From 498635f2b8e385d85fbfcdfa8127e26a4918ac89 Mon Sep 17 00:00:00 2001 From: Alan Protasio Date: Tue, 2 Apr 2024 17:23:12 -0700 Subject: [PATCH] Chore: Update Prometheus (#5841) * update prometheus Signed-off-by: alanprot * fix breaking changes Signed-off-by: alanprot * fix breaking changes Signed-off-by: alanprot * update doc Signed-off-by: alanprot * changelog Signed-off-by: alanprot * not allow to configure AM experimental features Signed-off-by: alanprot * remove v1 AM apis test Signed-off-by: alanprot * update changelog Signed-off-by: alanprot * Deprecate ruler.alertmanager-use-v2 flag Signed-off-by: alanprot * fixing more tests Signed-off-by: alanprot --------- Signed-off-by: alanprot --- CHANGELOG.md | 1 + cmd/cortex/main.go | 3 +- docs/configuration/config-file-reference.md | 4 - go.mod | 106 +- go.sum | 256 ++-- integration/alertmanager_test.go | 64 - integration/e2ecortex/client.go | 166 +-- pkg/alertmanager/alertmanager.go | 15 +- pkg/alertmanager/distributor.go | 9 - pkg/alertmanager/distributor_test.go | 30 - pkg/alertmanager/merger/v1_alerts.go | 72 - pkg/alertmanager/merger/v1_alerts_test.go | 158 -- pkg/alertmanager/merger/v1_silence_id.go | 51 - pkg/alertmanager/merger/v1_silence_id_test.go | 110 -- pkg/alertmanager/merger/v1_silences.go | 45 - pkg/alertmanager/merger/v1_silences_test.go | 128 -- pkg/alertmanager/multitenant.go | 1 + pkg/alertmanager/multitenant_test.go | 4 +- pkg/api/handlers.go | 3 +- pkg/cortex/cortex.go | 4 +- pkg/cortex/modules.go | 3 +- pkg/ingester/client/compat_test.go | 18 +- pkg/querier/blocks_store_queryable_test.go | 3 +- pkg/querier/chunk_store_queryable_test.go | 3 +- pkg/querier/error_translate_queryable_test.go | 2 +- pkg/querier/querier.go | 5 +- pkg/querier/querier_test.go | 9 +- pkg/ruler/compat.go | 5 +- pkg/ruler/notifier.go | 8 +- pkg/ruler/notifier_test.go | 18 +- pkg/ruler/ruler.go | 5 +- .../go/compute/internal/version.go | 2 +- vendor/cloud.google.com/go/iam/CHANGES.md | 7 + .../go/iam/apiv1/iampb/iam_policy.pb.go | 2 +- .../go/iam/apiv1/iampb/options.pb.go | 2 +- .../go/iam/apiv1/iampb/policy.pb.go | 74 +- .../go/internal/.repo-metadata-full.json | 80 + .../go/internal/trace/trace.go | 41 +- vendor/cloud.google.com/go/storage/CHANGES.md | 13 + vendor/cloud.google.com/go/storage/bucket.go | 51 +- vendor/cloud.google.com/go/storage/client.go | 13 +- .../go/storage/grpc_client.go | 86 +- .../go/storage/http_client.go | 31 +- .../go/storage/internal/version.go | 2 +- vendor/cloud.google.com/go/storage/storage.go | 154 +- .../azure-sdk-for-go/sdk/azcore/CHANGELOG.md | 17 + .../Azure/azure-sdk-for-go/sdk/azcore/core.go | 21 +- .../Azure/azure-sdk-for-go/sdk/azcore/etag.go | 9 + .../internal/exported/response_error.go | 32 +- .../sdk/azcore/internal/log/log.go | 20 +- .../sdk/azcore/internal/shared/constants.go | 2 +- .../azure-sdk-for-go/sdk/azcore/log/log.go | 5 + .../sdk/azcore/runtime/errors.go | 8 + .../sdk/azcore/runtime/request.go | 9 +- .../aws/aws-sdk-go/aws/endpoints/defaults.go | 210 +++ .../github.com/aws/aws-sdk-go/aws/version.go | 2 +- vendor/github.com/go-openapi/strfmt/format.go | 3 +- .../go-openapi/validate/BENCHMARK.md | 31 + .../go-openapi/validate/default_validator.go | 88 +- .../go-openapi/validate/example_validator.go | 48 +- .../github.com/go-openapi/validate/formats.go | 78 +- .../github.com/go-openapi/validate/helpers.go | 12 +- .../go-openapi/validate/object_validator.go | 448 ++++-- .../github.com/go-openapi/validate/options.go | 1 + .../github.com/go-openapi/validate/pools.go | 373 +++++ .../github.com/go-openapi/validate/result.go | 59 +- .../github.com/go-openapi/validate/schema.go | 253 ++-- .../go-openapi/validate/schema_option.go | 31 +- .../go-openapi/validate/schema_props.go | 163 ++- .../go-openapi/validate/slice_validator.go | 57 +- vendor/github.com/go-openapi/validate/spec.go | 101 +- .../go-openapi/validate/spec_messages.go | 5 + vendor/github.com/go-openapi/validate/type.go | 70 +- .../go-openapi/validate/validator.go | 909 ++++++++---- .../golang/protobuf/jsonpb/decode.go | 530 ------- .../golang/protobuf/jsonpb/encode.go | 559 ------- .../github.com/golang/protobuf/jsonpb/json.go | 69 - .../github.com/golang/protobuf/ptypes/any.go | 179 --- .../github.com/golang/protobuf/ptypes/doc.go | 10 - .../golang/protobuf/ptypes/duration.go | 76 - .../golang/protobuf/ptypes/timestamp.go | 112 -- .../gax-go/v2/.release-please-manifest.json | 2 +- .../googleapis/gax-go/v2/CHANGES.md | 14 + .../googleapis/gax-go/v2/callctx/callctx.go | 26 + .../github.com/googleapis/gax-go/v2/header.go | 11 +- .../googleapis/gax-go/v2/internal/version.go | 2 +- .../grpc-gateway/v2/{LICENSE.txt => LICENSE} | 0 .../v2/internal/httprule/BUILD.bazel | 2 +- .../grpc-gateway/v2/runtime/BUILD.bazel | 8 +- .../grpc-gateway/v2/runtime/errors.go | 4 +- .../grpc-gateway/v2/runtime/fieldmask.go | 2 +- .../grpc-gateway/v2/runtime/handler.go | 26 +- .../v2/runtime/marshal_httpbodyproto.go | 2 +- .../grpc-gateway/v2/runtime/mux.go | 32 +- vendor/github.com/hashicorp/consul/api/acl.go | 3 + .../consul/api/config_entry_discoverychain.go | 7 +- .../consul/api/config_entry_exports.go | 4 +- .../hashicorp/consul/api/exported_services.go | 49 + .../hashicorp/golang-lru/v2/.golangci.yml | 25 +- .../github.com/hashicorp/golang-lru/v2/2q.go | 46 +- .../hashicorp/golang-lru/v2/README.md | 72 +- .../github.com/hashicorp/golang-lru/v2/arc.go | 259 ---- .../github.com/hashicorp/golang-lru/v2/doc.go | 20 +- .../hashicorp/golang-lru/v2/internal/list.go | 142 ++ .../github.com/hashicorp/golang-lru/v2/lru.go | 8 + .../hashicorp/golang-lru/v2/simplelru/list.go | 128 -- .../hashicorp/golang-lru/v2/simplelru/lru.go | 67 +- .../golang-lru/v2/simplelru/lru_interface.go | 3 + .../hashicorp/golang-lru/v2/testing.go | 19 - .../github.com/klauspost/compress/README.md | 10 +- .../klauspost/compress/s2/encode_all.go | 22 +- .../klauspost/compress/s2/encodeblock_amd64.s | 108 ++ .../klauspost/compress/s2/writer.go | 21 +- .../prometheus/alertmanager/api/api.go | 26 +- .../alertmanager/api/metrics/metrics.go | 9 +- .../prometheus/alertmanager/api/v1/api.go | 808 ---------- .../alertmanager/api/v1_deprecation_router.go | 67 + .../prometheus/alertmanager/api/v2/api.go | 25 +- .../v2/client/alert/get_alerts_responses.go | 17 +- .../v2/client/alert/post_alerts_responses.go | 17 +- .../alertgroup/get_alert_groups_responses.go | 17 +- .../v2/client/general/get_status_responses.go | 7 +- .../receiver/get_receivers_responses.go | 7 +- .../silence/delete_silence_responses.go | 17 +- .../client/silence/get_silence_responses.go | 17 +- .../client/silence/get_silences_responses.go | 84 +- .../client/silence/post_silences_responses.go | 17 +- .../alertmanager/api/v2/models/alert_group.go | 6 + .../api/v2/models/alert_groups.go | 5 + .../api/v2/models/alertmanager_status.go | 3 + .../api/v2/models/cluster_status.go | 5 + .../api/v2/models/gettable_alert.go | 6 + .../api/v2/models/gettable_alerts.go | 5 + .../api/v2/models/gettable_silence.go | 1 + .../api/v2/models/gettable_silences.go | 5 + .../alertmanager/api/v2/models/matchers.go | 5 + .../api/v2/models/postable_alert.go | 4 + .../api/v2/models/postable_alerts.go | 5 + .../alertmanager/api/v2/openapi.yaml | 2 + .../api/v2/restapi/embedded_spec.go | 9 + .../v2/restapi/operations/alertmanager_api.go | 2 +- .../silence/get_silences_responses.go | 43 + .../alertmanager/asset/assets_vfsdata.go | 4 +- .../alertmanager/cluster/advertise.go | 13 +- .../alertmanager/cluster/cluster.go | 20 +- .../alertmanager/cluster/connection_pool.go | 4 +- .../alertmanager/cluster/tls_connection.go | 15 +- .../alertmanager/cluster/tls_transport.go | 20 +- .../prometheus/alertmanager/config/config.go | 15 +- .../alertmanager/config/notifiers.go | 59 +- .../alertmanager/dispatch/dispatch.go | 3 +- .../prometheus/alertmanager/dispatch/route.go | 23 + .../featurecontrol/featurecontrol.go | 123 ++ .../alertmanager/matchers/compat/parse.go | 205 +++ .../alertmanager/matchers/parse/lexer.go | 309 ++++ .../alertmanager/matchers/parse/parse.go | 304 ++++ .../alertmanager/matchers/parse/token.go | 108 ++ .../prometheus/alertmanager/nflog/nflog.go | 2 +- .../alertmanager/notify/discord/discord.go | 33 +- .../alertmanager/notify/email/email.go | 64 +- .../alertmanager/notify/msteams/msteams.go | 22 +- .../prometheus/alertmanager/notify/notify.go | 266 ++-- .../alertmanager/notify/opsgenie/opsgenie.go | 5 +- .../notify/pagerduty/pagerduty.go | 20 +- .../alertmanager/notify/pushover/pushover.go | 6 + .../alertmanager/notify/slack/slack.go | 9 +- .../prometheus/alertmanager/notify/sns/sns.go | 7 +- .../prometheus/alertmanager/notify/util.go | 16 +- .../notify/victorops/victorops.go | 9 +- .../alertmanager/notify/wechat/wechat.go | 6 +- .../alertmanager/pkg/labels/matcher.go | 15 + .../alertmanager/pkg/labels/parse.go | 11 +- .../alertmanager/silence/silence.go | 40 +- .../alertmanager/template/default.tmpl | 1 + .../alertmanager/timeinterval/timeinterval.go | 32 +- .../prometheus/alertmanager/types/types.go | 40 + .../prometheus/alertmanager/ui/web.go | 20 +- .../prometheus/collectors/version/version.go | 47 + .../client_golang/prometheus/push/push.go | 2 +- .../prometheus/testutil/promlint/promlint.go | 2 +- .../prometheus/testutil/testutil.go | 4 +- .../prometheus/client_model/go/metrics.pb.go | 195 +-- .../prometheus/common/config/http_config.go | 35 + .../prometheus/common/expfmt/decode.go | 14 +- .../prometheus/common/expfmt/encode.go | 34 +- .../prometheus/common/expfmt/expfmt.go | 41 +- .../common/expfmt/openmetrics_create.go | 93 +- .../prometheus/common/model/labelset.go | 29 +- .../prometheus/common/version/info.go | 2 + .../prometheus/prometheus/config/config.go | 8 + .../prometheus/model/labels/labels.go | 4 +- .../prometheus/model/labels/labels_common.go | 5 +- .../model/labels/labels_stringlabels.go | 10 +- .../prometheus/model/labels/matcher.go | 27 + .../prometheus/model/labels/regexp.go | 882 ++++++++++- .../prometheus/model/textparse/interface.go | 4 +- .../model/textparse/openmetricsparse.go | 4 +- .../prometheus/model/textparse/promparse.go | 4 +- .../prometheus/notifier/notifier.go | 40 +- .../prometheus/prometheus/promql/engine.go | 75 +- .../prometheus/prometheus/promql/functions.go | 48 +- .../prometheus/prometheus/promql/test.go | 446 ++++-- .../prometheus/promql/testdata/functions.test | 31 +- .../prometheus/prometheus/rules/group.go | 6 +- .../prometheus/prometheus/rules/manager.go | 2 +- .../prometheus/prometheus/scrape/scrape.go | 66 +- .../prometheus/prometheus/storage/buffer.go | 12 +- .../storage/remote/azuread/azuread.go | 48 +- .../prometheus/storage/remote/client.go | 13 +- .../prometheus/normalize_label.go | 2 +- .../prometheus/normalize_name.go | 2 +- .../otlptranslator/prometheus/unit_to_ucum.go | 2 +- .../storage/remote/queue_manager.go | 15 +- .../prometheus/storage/remote/read_handler.go | 53 +- .../prometheus/tsdb/chunks/chunks.go | 9 - .../prometheus/tsdb/chunks/head_chunks.go | 21 +- .../prometheus/prometheus/tsdb/compact.go | 9 +- .../prometheus/prometheus/tsdb/db.go | 52 +- .../prometheus/prometheus/tsdb/head.go | 35 +- .../prometheus/prometheus/tsdb/head_append.go | 10 +- .../prometheus/prometheus/tsdb/index/index.go | 2 +- .../prometheus/prometheus/tsdb/querier.go | 69 +- .../prometheus/prometheus/tsdb/wal.go | 1303 ----------------- .../prometheus/tsdb/wlog/checkpoint.go | 47 +- .../prometheus/util/teststorage/storage.go | 23 +- .../prometheus/prometheus/web/api/v1/api.go | 14 +- vendor/github.com/rs/cors/README.md | 23 +- vendor/github.com/rs/cors/cors.go | 203 ++- vendor/github.com/rs/cors/utils.go | 95 +- vendor/github.com/stretchr/objx/README.md | 8 +- vendor/github.com/stretchr/objx/Taskfile.yml | 5 +- vendor/github.com/stretchr/objx/accessors.go | 24 +- .../github.com/stretchr/objx/conversions.go | 4 +- vendor/github.com/stretchr/objx/doc.go | 44 +- vendor/github.com/stretchr/objx/map.go | 9 +- .../testify/assert/assertion_compare.go | 28 +- .../assert/assertion_compare_can_convert.go | 16 - .../assert/assertion_compare_legacy.go | 16 - .../testify/assert/assertion_format.go | 32 +- .../testify/assert/assertion_forward.go | 59 +- .../stretchr/testify/assert/assertions.go | 207 ++- .../testify/assert/http_assertions.go | 27 +- .../github.com/stretchr/testify/mock/mock.go | 129 +- .../stretchr/testify/require/require.go | 65 +- .../testify/require/require_forward.go | 59 +- .../thanos-io/promql-engine/api/remote.go | 8 +- .../promql-engine/engine/distributed.go | 39 +- .../thanos-io/promql-engine/engine/engine.go | 128 +- .../thanos-io/promql-engine/engine/explain.go | 6 +- .../execution/aggregate/hashaggregate.go | 25 +- .../execution/aggregate/khashaggregate.go | 35 +- .../promql-engine/execution/binary/scalar.go | 18 +- .../promql-engine/execution/binary/vector.go | 20 +- .../execution/exchange/coalesce.go | 16 +- .../execution/exchange/concurrent.go | 15 +- .../promql-engine/execution/exchange/dedup.go | 18 +- .../execution/exchange/duplicate_label.go | 16 +- .../promql-engine/execution/execution.go | 78 +- .../execution/function/absent.go | 27 +- .../execution/function/histogram.go | 31 +- .../promql-engine/execution/function/noarg.go | 14 +- .../execution/function/operator.go | 62 +- .../execution/function/relabel.go | 23 +- .../execution/function/scalar.go | 18 +- .../execution/function/timestamp.go | 16 +- .../promql-engine/execution/model/operator.go | 26 +- .../promql-engine/execution/noop/operator.go | 4 +- .../execution/remote/operator.go | 25 +- .../promql-engine/execution/scan/functions.go | 35 +- .../execution/scan/literal_selector.go | 15 +- .../promql-engine/execution/scan/subquery.go | 24 +- .../step_invariant/step_invariant.go | 16 +- .../promql-engine/execution/unary/unary.go | 12 +- .../promql-engine/logicalplan/codec.go | 183 +++ .../promql-engine/logicalplan/distribute.go | 128 +- .../logicalplan/distribute_avg.go | 16 +- .../promql-engine/logicalplan/exprutil.go | 18 +- .../logicalplan/logical_nodes.go | 402 ++++- .../logicalplan/merge_selects.go | 12 +- .../promql-engine/logicalplan/passthrough.go | 10 +- .../promql-engine/logicalplan/plan.go | 394 ++--- .../logicalplan/propagate_selectors.go | 8 +- .../logicalplan/set_batch_size.go | 10 +- .../logicalplan/sort_matchers.go | 5 +- .../promql-engine/logicalplan/user_defined.go | 4 +- .../thanos-io/promql-engine/query/options.go | 16 +- .../promql-engine/storage/interface.go | 3 +- .../storage/prometheus/matrix_selector.go | 19 +- .../storage/prometheus/scanners.go | 5 +- .../storage/prometheus/vector_selector.go | 12 +- .../thanos-io/thanos/pkg/store/bucket.go | 4 +- .../thanos-io/thanos/pkg/store/opts.go | 73 - .../bson/bsoncodec/array_codec.go | 7 +- .../bson/bsoncodec/byte_slice_codec.go | 25 +- .../bson/bsoncodec/default_value_decoders.go | 10 +- .../bson/bsoncodec/default_value_encoders.go | 12 +- .../bson/bsoncodec/empty_interface_codec.go | 24 +- .../mongo-driver/bson/bsoncodec/map_codec.go | 38 +- .../bson/bsoncodec/pointer_codec.go | 16 +- .../bson/bsoncodec/slice_codec.go | 27 +- .../bson/bsoncodec/string_codec.go | 16 +- .../bson/bsoncodec/struct_codec.go | 62 +- .../mongo-driver/bson/bsoncodec/time_codec.go | 24 +- .../mongo-driver/bson/bsoncodec/uint_codec.go | 24 +- .../mongo-driver/bson/bsonrw/copier.go | 5 +- .../bson/bsonrw/extjson_parser.go | 2 +- .../bson/bsonrw/extjson_reader.go | 5 +- .../mongo-driver/bson/bsonrw/json_scanner.go | 26 +- .../go.mongodb.org/mongo-driver/bson/doc.go | 89 +- .../mongo-driver/bson/primitive/decimal.go | 3 - .../mongo-driver/bson/primitive/objectid.go | 4 +- .../collector/featuregate/registry.go | 10 +- .../internal/data/protogen/logs/v1/logs.pb.go | 14 +- .../data/protogen/metrics/v1/metrics.pb.go | 8 +- .../data/protogen/trace/v1/trace.pb.go | 260 +++- .../collector/pdata/pcommon/map.go | 7 +- .../collector/pdata/pcommon/trace_state.go | 3 + .../collector/pdata/pmetric/json.go | 2 +- .../pdata/pmetric/pmetricotlp/response.go | 2 +- .../google.golang.org/grpc/otelgrpc/config.go | 16 + .../grpc/otelgrpc/stats_handler.go | 86 +- .../grpc/otelgrpc/version.go | 2 +- .../net/http/otelhttp/common.go | 14 +- .../net/http/otelhttp/handler.go | 16 +- .../otelhttp/internal/semconvutil/httpconv.go | 120 +- .../otelhttp/internal/semconvutil/netconv.go | 163 --- .../net/http/otelhttp/transport.go | 109 +- .../net/http/otelhttp/version.go | 2 +- .../instrumentation/net/http/otelhttp/wrap.go | 5 +- .../go.opentelemetry.io/otel/.codespellignore | 2 + vendor/go.opentelemetry.io/otel/CHANGELOG.md | 86 +- vendor/go.opentelemetry.io/otel/CODEOWNERS | 2 +- .../go.opentelemetry.io/otel/CONTRIBUTING.md | 2 +- vendor/go.opentelemetry.io/otel/Makefile | 4 +- vendor/go.opentelemetry.io/otel/README.md | 20 +- .../go.opentelemetry.io/otel/attribute/set.go | 2 +- .../otel/exporters/otlp/otlptrace/exporter.go | 2 +- .../otlp/otlptrace/otlptracegrpc/doc.go | 2 +- .../internal/otlpconfig/options.go | 20 + .../otlp/otlptrace/otlptracegrpc/options.go | 34 +- .../otel/exporters/otlp/otlptrace/version.go | 2 +- .../otel/internal/global/meter.go | 4 +- .../otel/internal/global/state.go | 6 +- .../otel/metric/noop/noop.go | 264 ++++ .../otel/sdk/resource/auto.go | 25 +- .../otel/sdk/resource/container.go | 2 +- .../otel/sdk/resource/resource.go | 79 +- .../otel/sdk/trace/batch_span_processor.go | 2 +- .../otel/sdk/trace/provider.go | 2 +- .../go.opentelemetry.io/otel/sdk/version.go | 2 +- vendor/go.opentelemetry.io/otel/version.go | 2 +- vendor/go.opentelemetry.io/otel/versions.yaml | 20 +- .../proto/otlp/trace/v1/trace.pb.go | 367 +++-- .../x/crypto/internal/poly1305/sum_ppc64le.s | 14 +- vendor/golang.org/x/net/http2/transport.go | 9 + vendor/golang.org/x/oauth2/google/default.go | 10 +- vendor/golang.org/x/oauth2/google/doc.go | 86 +- .../{internal => }/externalaccount/aws.go | 112 +- .../google/externalaccount/basecredentials.go | 484 ++++++ .../externalaccount/executablecredsource.go | 28 +- .../externalaccount/filecredsource.go | 14 +- .../{internal => }/externalaccount/header.go | 0 .../programmaticrefreshcredsource.go | 21 + .../externalaccount/urlcredsource.go | 18 +- vendor/golang.org/x/oauth2/google/google.go | 9 +- .../externalaccount/basecredentials.go | 254 ---- .../google/internal/externalaccount/err.go | 18 - .../impersonate.go | 2 +- vendor/golang.org/x/sys/unix/aliases.go | 2 +- .../x/sys/unix/syscall_darwin_libSystem.go | 2 +- .../golang.org/x/sys/unix/syscall_freebsd.go | 12 +- vendor/golang.org/x/sys/unix/syscall_linux.go | 99 ++ .../golang.org/x/sys/unix/zsyscall_linux.go | 10 + vendor/golang.org/x/sys/unix/ztypes_linux.go | 60 + .../x/tools/go/gcexportdata/gcexportdata.go | 2 +- vendor/golang.org/x/tools/go/packages/doc.go | 40 +- .../x/tools/go/packages/external.go | 77 +- .../golang.org/x/tools/go/packages/golist.go | 35 +- .../x/tools/go/packages/packages.go | 46 +- .../x/tools/go/types/objectpath/objectpath.go | 20 +- .../x/tools/internal/aliases/aliases.go | 28 + .../x/tools/internal/aliases/aliases_go121.go | 30 + .../x/tools/internal/aliases/aliases_go122.go | 72 + .../x/tools/internal/gcimporter/gcimporter.go | 7 - .../x/tools/internal/gcimporter/iexport.go | 9 +- .../x/tools/internal/gcimporter/iimport.go | 34 +- .../internal/gcimporter/support_go117.go | 16 - .../internal/gcimporter/support_go118.go | 3 - .../x/tools/internal/gcimporter/unified_no.go | 4 +- .../tools/internal/gcimporter/unified_yes.go | 4 +- .../x/tools/internal/gcimporter/ureader_no.go | 19 - .../tools/internal/gcimporter/ureader_yes.go | 6 +- .../internal/tokeninternal/tokeninternal.go | 28 +- .../x/tools/internal/typeparams/common.go | 37 +- .../x/tools/internal/typeparams/coretype.go | 17 +- .../x/tools/internal/typesinternal/recv.go | 43 + .../tools/internal/typesinternal/types_118.go | 3 - .../x/tools/internal/versions/features.go | 43 + .../x/tools/internal/versions/toolchain.go | 14 + .../internal/versions/toolchain_go119.go | 14 + .../internal/versions/toolchain_go120.go | 14 + .../internal/versions/toolchain_go121.go | 14 + .../x/tools/internal/versions/types_go121.go | 18 +- .../x/tools/internal/versions/types_go122.go | 25 +- .../x/tools/internal/versions/versions.go | 5 + vendor/google.golang.org/api/internal/cba.go | 72 +- .../google.golang.org/api/internal/creds.go | 62 +- .../api/internal/settings.go | 70 +- .../google.golang.org/api/internal/version.go | 2 +- .../api/storage/v1/storage-api.json | 24 +- .../api/storage/v1/storage-gen.go | 13 +- .../api/transport/grpc/dial.go | 11 + .../api/transport/http/dial.go | 11 + .../googleapis/api/annotations/client.pb.go | 139 +- .../api/annotations/field_behavior.pb.go | 24 +- .../genproto/googleapis/api/tidyfix.go | 23 - .../genproto/internal/doc.go | 17 - .../grpclb/grpc_lb_v1/load_balancer.pb.go | 4 +- .../grpc_lb_v1/load_balancer_grpc.pb.go | 2 +- .../grpc/balancer/grpclb/grpclb.go | 2 +- .../balancer/grpclb/grpclb_remote_balancer.go | 4 +- .../grpc_binarylog_v1/binarylog.pb.go | 4 +- vendor/google.golang.org/grpc/clientconn.go | 2 + .../internal/proto/grpc_gcp/altscontext.pb.go | 4 +- .../internal/proto/grpc_gcp/handshaker.pb.go | 4 +- .../proto/grpc_gcp/handshaker_grpc.pb.go | 2 +- .../grpc_gcp/transport_security_common.pb.go | 4 +- .../grpc/encoding/proto/proto.go | 24 +- .../grpc/health/grpc_health_v1/health.pb.go | 4 +- .../health/grpc_health_v1/health_grpc.pb.go | 2 +- .../grpc/internal/binarylog/method_logger.go | 9 +- .../grpc/internal/binarylog/sink.go | 2 +- .../grpc/internal/grpcrand/grpcrand.go | 5 + .../grpc/internal/grpcrand/grpcrand_go1.21.go | 73 + .../grpc/internal/pretty/pretty.go | 7 +- .../grpc/internal/status/status.go | 15 +- .../grpc/internal/transport/controlbuf.go | 5 +- .../grpc/internal/transport/handler_server.go | 2 +- .../grpc/internal/transport/http2_client.go | 8 +- .../grpc/internal/transport/http2_server.go | 29 +- .../grpc/internal/transport/transport.go | 9 +- .../grpc/resolver/resolver.go | 3 + .../grpc/resolver_wrapper.go | 1 + vendor/google.golang.org/grpc/rpc_util.go | 69 +- vendor/google.golang.org/grpc/server.go | 21 +- vendor/google.golang.org/grpc/stream.go | 5 +- vendor/google.golang.org/grpc/trace.go | 26 +- .../google.golang.org/grpc/trace_notrace.go | 52 + .../google.golang.org/grpc/trace_withtrace.go | 39 + vendor/google.golang.org/grpc/version.go | 2 +- vendor/google.golang.org/grpc/vet.sh | 2 +- .../protobuf/protoadapt/convert.go | 31 + vendor/gopkg.in/telebot.v3/admin.go | 84 +- vendor/gopkg.in/telebot.v3/bot.go | 100 +- vendor/gopkg.in/telebot.v3/chat.go | 70 +- vendor/gopkg.in/telebot.v3/context.go | 21 +- vendor/gopkg.in/telebot.v3/errors.go | 18 + vendor/gopkg.in/telebot.v3/inline.go | 4 +- vendor/gopkg.in/telebot.v3/markup.go | 101 +- vendor/gopkg.in/telebot.v3/media.go | 21 +- vendor/gopkg.in/telebot.v3/message.go | 38 +- vendor/gopkg.in/telebot.v3/middleware.go | 11 +- vendor/gopkg.in/telebot.v3/options.go | 19 +- vendor/gopkg.in/telebot.v3/sendable.go | 1 - vendor/gopkg.in/telebot.v3/telebot.go | 102 +- vendor/gopkg.in/telebot.v3/topic.go | 172 +++ vendor/gopkg.in/telebot.v3/update.go | 49 +- vendor/gopkg.in/telebot.v3/video_chat.go | 36 +- vendor/gopkg.in/telebot.v3/web_app.go | 6 + vendor/gopkg.in/telebot.v3/webhook.go | 2 +- vendor/modules.txt | 149 +- 471 files changed, 13686 insertions(+), 10212 deletions(-) delete mode 100644 pkg/alertmanager/merger/v1_alerts.go delete mode 100644 pkg/alertmanager/merger/v1_alerts_test.go delete mode 100644 pkg/alertmanager/merger/v1_silence_id.go delete mode 100644 pkg/alertmanager/merger/v1_silence_id_test.go delete mode 100644 pkg/alertmanager/merger/v1_silences.go delete mode 100644 pkg/alertmanager/merger/v1_silences_test.go create mode 100644 vendor/github.com/go-openapi/validate/BENCHMARK.md create mode 100644 vendor/github.com/go-openapi/validate/pools.go delete mode 100644 vendor/github.com/golang/protobuf/jsonpb/decode.go delete mode 100644 vendor/github.com/golang/protobuf/jsonpb/encode.go delete mode 100644 vendor/github.com/golang/protobuf/jsonpb/json.go delete mode 100644 vendor/github.com/golang/protobuf/ptypes/any.go delete mode 100644 vendor/github.com/golang/protobuf/ptypes/doc.go delete mode 100644 vendor/github.com/golang/protobuf/ptypes/duration.go delete mode 100644 vendor/github.com/golang/protobuf/ptypes/timestamp.go rename vendor/github.com/grpc-ecosystem/grpc-gateway/v2/{LICENSE.txt => LICENSE} (100%) create mode 100644 vendor/github.com/hashicorp/consul/api/exported_services.go delete mode 100644 vendor/github.com/hashicorp/golang-lru/v2/arc.go create mode 100644 vendor/github.com/hashicorp/golang-lru/v2/internal/list.go delete mode 100644 vendor/github.com/hashicorp/golang-lru/v2/simplelru/list.go delete mode 100644 vendor/github.com/hashicorp/golang-lru/v2/testing.go delete mode 100644 vendor/github.com/prometheus/alertmanager/api/v1/api.go create mode 100644 vendor/github.com/prometheus/alertmanager/api/v1_deprecation_router.go create mode 100644 vendor/github.com/prometheus/alertmanager/featurecontrol/featurecontrol.go create mode 100644 vendor/github.com/prometheus/alertmanager/matchers/compat/parse.go create mode 100644 vendor/github.com/prometheus/alertmanager/matchers/parse/lexer.go create mode 100644 vendor/github.com/prometheus/alertmanager/matchers/parse/parse.go create mode 100644 vendor/github.com/prometheus/alertmanager/matchers/parse/token.go create mode 100644 vendor/github.com/prometheus/client_golang/prometheus/collectors/version/version.go delete mode 100644 vendor/github.com/prometheus/prometheus/tsdb/wal.go delete mode 100644 vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go delete mode 100644 vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go create mode 100644 vendor/github.com/thanos-io/promql-engine/logicalplan/codec.go delete mode 100644 vendor/github.com/thanos-io/thanos/pkg/store/opts.go create mode 100644 vendor/go.opentelemetry.io/otel/metric/noop/noop.go rename vendor/golang.org/x/oauth2/google/{internal => }/externalaccount/aws.go (77%) create mode 100644 vendor/golang.org/x/oauth2/google/externalaccount/basecredentials.go rename vendor/golang.org/x/oauth2/google/{internal => }/externalaccount/executablecredsource.go (84%) rename vendor/golang.org/x/oauth2/google/{internal => }/externalaccount/filecredsource.go (62%) rename vendor/golang.org/x/oauth2/google/{internal => }/externalaccount/header.go (100%) create mode 100644 vendor/golang.org/x/oauth2/google/externalaccount/programmaticrefreshcredsource.go rename vendor/golang.org/x/oauth2/google/{internal => }/externalaccount/urlcredsource.go (61%) delete mode 100644 vendor/golang.org/x/oauth2/google/internal/externalaccount/basecredentials.go delete mode 100644 vendor/golang.org/x/oauth2/google/internal/externalaccount/err.go rename vendor/golang.org/x/oauth2/google/internal/{externalaccount => impersonate}/impersonate.go (99%) create mode 100644 vendor/golang.org/x/tools/internal/aliases/aliases.go create mode 100644 vendor/golang.org/x/tools/internal/aliases/aliases_go121.go create mode 100644 vendor/golang.org/x/tools/internal/aliases/aliases_go122.go delete mode 100644 vendor/golang.org/x/tools/internal/gcimporter/support_go117.go delete mode 100644 vendor/golang.org/x/tools/internal/gcimporter/ureader_no.go create mode 100644 vendor/golang.org/x/tools/internal/typesinternal/recv.go create mode 100644 vendor/golang.org/x/tools/internal/versions/features.go create mode 100644 vendor/golang.org/x/tools/internal/versions/toolchain.go create mode 100644 vendor/golang.org/x/tools/internal/versions/toolchain_go119.go create mode 100644 vendor/golang.org/x/tools/internal/versions/toolchain_go120.go create mode 100644 vendor/golang.org/x/tools/internal/versions/toolchain_go121.go delete mode 100644 vendor/google.golang.org/genproto/googleapis/api/tidyfix.go delete mode 100644 vendor/google.golang.org/genproto/internal/doc.go create mode 100644 vendor/google.golang.org/grpc/internal/grpcrand/grpcrand_go1.21.go create mode 100644 vendor/google.golang.org/grpc/trace_notrace.go create mode 100644 vendor/google.golang.org/grpc/trace_withtrace.go create mode 100644 vendor/google.golang.org/protobuf/protoadapt/convert.go create mode 100644 vendor/gopkg.in/telebot.v3/topic.go diff --git a/CHANGELOG.md b/CHANGELOG.md index f34a231c55..0ee8f3a290 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ * [CHANGE] Ruler: Remove `cortex_ruler_write_requests_total`, `cortex_ruler_write_requests_failed_total`, `cortex_ruler_queries_total`, `cortex_ruler_queries_failed_total`, and `cortex_ruler_query_seconds_total` metrics for the tenant when the ruler deletes the manager for the tenant. #5772 * [CHANGE] Main: Mark `mem-ballast-size-bytes` flag as deprecated. #5816 * [CHANGE] Querier: Mark `-querier.ingester-streaming` flag as deprecated. Now query ingester streaming is always enabled. #5817 +* [CHANGE] AlertManager API: Removal of all api/v1/ endpoints following [2970](https://github.com/prometheus/alertmanager/pull/2970). [5841] * [FEATURE] Ingester: Add per-tenant new metric `cortex_ingester_tsdb_data_replay_duration_seconds`. #5477 * [FEATURE] Query Frontend/Scheduler: Add query priority support. #5605 * [FEATURE] Tracing: Add `kuberesolver` to resolve endpoints address with `kubernetes://` prefix as Kubernetes service. #5731 diff --git a/cmd/cortex/main.go b/cmd/cortex/main.go index ad0ff0fa08..a5742d0f2e 100644 --- a/cmd/cortex/main.go +++ b/cmd/cortex/main.go @@ -16,6 +16,7 @@ import ( "github.com/go-kit/log/level" "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" + collectorversion "github.com/prometheus/client_golang/prometheus/collectors/version" "github.com/prometheus/common/version" "gopkg.in/yaml.v2" @@ -46,7 +47,7 @@ func init() { version.Version = Version version.Branch = Branch version.Revision = Revision - prometheus.MustRegister(version.NewCollector("cortex")) + prometheus.MustRegister(collectorversion.NewCollector("cortex")) prometheus.MustRegister(configHash) } diff --git a/docs/configuration/config-file-reference.md b/docs/configuration/config-file-reference.md index e0597f15b2..866adea2ed 100644 --- a/docs/configuration/config-file-reference.md +++ b/docs/configuration/config-file-reference.md @@ -4079,10 +4079,6 @@ ruler_client: # CLI flag: -ruler.alertmanager-refresh-interval [alertmanager_refresh_interval: | default = 1m] -# If enabled requests to Alertmanager will utilize the V2 API. -# CLI flag: -ruler.alertmanager-use-v2 -[enable_alertmanager_v2: | default = false] - # Capacity of the queue for notifications to be sent to the Alertmanager. # CLI flag: -ruler.notification-queue-capacity [notification_queue_capacity: | default = 10000] diff --git a/go.mod b/go.mod index 93da884405..f550023a5f 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 github.com/alicebob/miniredis/v2 v2.32.1 github.com/armon/go-metrics v0.4.1 - github.com/aws/aws-sdk-go v1.50.25 + github.com/aws/aws-sdk-go v1.50.32 github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 github.com/cespare/xxhash v1.1.0 github.com/cortexproject/promqlsmith v0.0.0-20240328172224-5e341f0dd08e @@ -16,23 +16,23 @@ require ( github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb github.com/felixge/fgprof v0.9.3 github.com/go-kit/log v0.2.1 - github.com/go-openapi/strfmt v0.22.0 + github.com/go-openapi/strfmt v0.22.2 github.com/go-openapi/swag v0.22.9 github.com/go-redis/redis/v8 v8.11.5 github.com/gogo/protobuf v1.3.2 github.com/gogo/status v1.1.1 github.com/golang-migrate/migrate/v4 v4.17.0 - github.com/golang/protobuf v1.5.3 + github.com/golang/protobuf v1.5.4 github.com/golang/snappy v0.0.4 github.com/gorilla/mux v1.8.1 github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 - github.com/hashicorp/consul/api v1.27.0 + github.com/hashicorp/consul/api v1.28.2 github.com/hashicorp/go-cleanhttp v0.5.2 github.com/hashicorp/go-sockaddr v1.0.6 github.com/hashicorp/memberlist v0.5.0 github.com/json-iterator/go v1.1.12 - github.com/klauspost/compress v1.17.6 + github.com/klauspost/compress v1.17.7 github.com/lib/pq v1.10.9 github.com/minio/minio-go/v7 v7.0.69 github.com/mitchellh/go-wordwrap v1.0.1 @@ -41,36 +41,36 @@ require ( github.com/opentracing-contrib/go-stdlib v1.0.0 github.com/opentracing/opentracing-go v1.2.0 github.com/pkg/errors v0.9.1 - github.com/prometheus/alertmanager v0.26.0 - github.com/prometheus/client_golang v1.18.0 - github.com/prometheus/client_model v0.5.0 - github.com/prometheus/common v0.47.0 + github.com/prometheus/alertmanager v0.27.0 + github.com/prometheus/client_golang v1.19.0 + github.com/prometheus/client_model v0.6.0 + github.com/prometheus/common v0.49.1-0.20240306132007-4199f18c3e92 // Prometheus maps version 2.x.y to tags v0.x.y. - github.com/prometheus/prometheus v0.50.2-0.20240229164915-d5f0a240faad + github.com/prometheus/prometheus v0.51.1-0.20240328124728-d81e41d58ec8 github.com/segmentio/fasthash v1.0.3 github.com/sony/gobreaker v0.5.0 github.com/spf13/afero v1.11.0 - github.com/stretchr/testify v1.8.4 + github.com/stretchr/testify v1.9.0 github.com/thanos-io/objstore v0.0.0-20240309075357-e8336a5fd5f3 - github.com/thanos-io/promql-engine v0.0.0-20240318110350-23714ea2522d - github.com/thanos-io/thanos v0.34.2-0.20240327180044-4d7a75f40ae1 + github.com/thanos-io/promql-engine v0.0.0-20240327143517-c5e4b2e6ef02 + github.com/thanos-io/thanos v0.34.2-0.20240328185924-943401f726ed github.com/uber/jaeger-client-go v2.30.0+incompatible github.com/weaveworks/common v0.0.0-20230728070032-dd9e68f319d5 go.etcd.io/etcd/api/v3 v3.5.12 go.etcd.io/etcd/client/pkg/v3 v3.5.12 go.etcd.io/etcd/client/v3 v3.5.12 go.opentelemetry.io/contrib/propagators/aws v1.22.0 - go.opentelemetry.io/otel v1.22.0 + go.opentelemetry.io/otel v1.24.0 go.opentelemetry.io/otel/bridge/opentracing v1.22.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 - go.opentelemetry.io/otel/sdk v1.22.0 - go.opentelemetry.io/otel/trace v1.22.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 + go.opentelemetry.io/otel/sdk v1.24.0 + go.opentelemetry.io/otel/trace v1.24.0 go.uber.org/atomic v1.11.0 - golang.org/x/net v0.21.0 + golang.org/x/net v0.22.0 golang.org/x/sync v0.6.0 golang.org/x/time v0.5.0 - google.golang.org/grpc v1.61.0 + google.golang.org/grpc v1.62.1 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -86,12 +86,12 @@ require ( ) require ( - cloud.google.com/go v0.111.0 // indirect - cloud.google.com/go/compute v1.23.3 // indirect + cloud.google.com/go v0.112.0 // indirect + cloud.google.com/go/compute v1.23.4 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v1.1.5 // indirect - cloud.google.com/go/storage v1.35.1 // indirect - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.2 // indirect + cloud.google.com/go/iam v1.1.6 // indirect + cloud.google.com/go/storage v1.36.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.10.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2 // indirect github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.0 // indirect @@ -131,25 +131,25 @@ require ( github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/analysis v0.22.2 // indirect - github.com/go-openapi/errors v0.21.0 // indirect + github.com/go-openapi/errors v0.21.1 // indirect github.com/go-openapi/jsonpointer v0.20.2 // indirect github.com/go-openapi/jsonreference v0.20.4 // indirect github.com/go-openapi/loads v0.21.5 // indirect github.com/go-openapi/runtime v0.27.1 // indirect github.com/go-openapi/spec v0.20.14 // indirect - github.com/go-openapi/validate v0.22.6 // indirect + github.com/go-openapi/validate v0.23.0 // indirect github.com/gofrs/uuid v4.4.0+incompatible // indirect github.com/gogo/googleapis v1.4.0 // indirect github.com/golang-jwt/jwt/v5 v5.2.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/google/btree v1.0.1 // indirect - github.com/google/pprof v0.0.0-20240117000934-35fc243c5815 // indirect + github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7 // indirect github.com/google/s2a-go v0.1.7 // indirect github.com/google/uuid v1.6.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect - github.com/googleapis/gax-go/v2 v2.12.0 // indirect + github.com/googleapis/gax-go/v2 v2.12.2 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.2.0.20201207153454-9f6bf00c00a7 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-hclog v1.5.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect @@ -158,7 +158,7 @@ require ( github.com/hashicorp/go-rootcerts v1.0.2 // indirect github.com/hashicorp/go-version v1.6.0 // indirect github.com/hashicorp/golang-lru v0.6.0 // indirect - github.com/hashicorp/golang-lru/v2 v2.0.2 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hashicorp/serf v0.10.1 // indirect github.com/jessevdk/go-flags v1.5.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect @@ -192,54 +192,54 @@ require ( github.com/prometheus/exporter-toolkit v0.11.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect github.com/redis/rueidis v1.0.14-go1.18 // indirect - github.com/rs/cors v1.9.0 // indirect + github.com/rs/cors v1.10.1 // indirect github.com/rs/xid v1.5.0 // indirect github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c // indirect github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/soheilhy/cmux v0.1.5 // indirect - github.com/stretchr/objx v0.5.0 // indirect + github.com/stretchr/objx v0.5.2 // indirect github.com/uber/jaeger-lib v2.4.1+incompatible // indirect github.com/vimeo/galaxycache v0.0.0-20210323154928-b7e5d71c067a // indirect github.com/weaveworks/promrus v1.2.0 // indirect github.com/yuin/gopher-lua v1.1.1 // indirect github.com/zhangyunhao116/umap v0.0.0-20221211160557-cb7705fafa39 // indirect - go.mongodb.org/mongo-driver v1.13.1 // indirect + go.mongodb.org/mongo-driver v1.14.0 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/collector/featuregate v1.0.1 // indirect - go.opentelemetry.io/collector/pdata v1.0.1 // indirect - go.opentelemetry.io/collector/semconv v0.93.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 // indirect + go.opentelemetry.io/collector/featuregate v1.3.0 // indirect + go.opentelemetry.io/collector/pdata v1.3.0 // indirect + go.opentelemetry.io/collector/semconv v0.96.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect go.opentelemetry.io/contrib/propagators/autoprop v0.38.0 // indirect go.opentelemetry.io/contrib/propagators/b3 v1.13.0 // indirect go.opentelemetry.io/contrib/propagators/jaeger v1.13.0 // indirect go.opentelemetry.io/contrib/propagators/ot v1.13.0 // indirect - go.opentelemetry.io/otel/metric v1.22.0 // indirect - go.opentelemetry.io/proto/otlp v1.0.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/proto/otlp v1.1.0 // indirect go.uber.org/goleak v1.3.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.21.0 // indirect go4.org/intern v0.0.0-20230525184215-6c62f75575cb // indirect go4.org/unsafe/assume-no-moving-gc v0.0.0-20230525183740-e7c30c78aeb2 // indirect - golang.org/x/crypto v0.19.0 // indirect - golang.org/x/mod v0.14.0 // indirect - golang.org/x/oauth2 v0.16.0 // indirect - golang.org/x/sys v0.17.0 // indirect + golang.org/x/crypto v0.21.0 // indirect + golang.org/x/mod v0.16.0 // indirect + golang.org/x/oauth2 v0.18.0 // indirect + golang.org/x/sys v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect - golang.org/x/tools v0.17.0 // indirect + golang.org/x/tools v0.19.0 // indirect gonum.org/v1/gonum v0.12.0 // indirect - google.golang.org/api v0.157.0 // indirect + google.golang.org/api v0.168.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240116215550-a9fa1716bcac // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac // indirect + google.golang.org/genproto v0.0.0-20240205150955-31a09d347014 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240304212257-790db918fca8 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240304161311-37d4d3c04a78 // indirect gopkg.in/alecthomas/kingpin.v2 v2.2.6 // indirect gopkg.in/ini.v1 v1.67.0 // indirect - gopkg.in/telebot.v3 v3.1.3 // indirect - k8s.io/apimachinery v0.29.2 // indirect - k8s.io/client-go v0.29.2 // indirect + gopkg.in/telebot.v3 v3.2.1 // indirect + k8s.io/apimachinery v0.29.3 // indirect + k8s.io/client-go v0.29.3 // indirect k8s.io/klog/v2 v2.120.1 // indirect k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect ) diff --git a/go.sum b/go.sum index 7e025c1859..a512d798be 100644 --- a/go.sum +++ b/go.sum @@ -36,8 +36,8 @@ cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRY cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= -cloud.google.com/go v0.111.0 h1:YHLKNupSD1KqjDbQ3+LVdQ81h/UJbJyZG203cEfnQgM= -cloud.google.com/go v0.111.0/go.mod h1:0mibmpKP1TyOOFYQY5izo0LnT+ecvOQ0Sg3OdmMiNRU= +cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM= +cloud.google.com/go v0.112.0/go.mod h1:3jEEVwZ/MHU4djK5t5RHuKOA/GbLddgTdVubX1qnPD4= cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= @@ -148,8 +148,8 @@ cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARy cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= -cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= -cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= +cloud.google.com/go/compute v1.23.4 h1:EBT9Nw4q3zyE7G45Wvv3MzolIrCJEuHys5muLY0wvAw= +cloud.google.com/go/compute v1.23.4/go.mod h1:/EJMj55asU6kAFnuZET8zqgwgJ9FvXWXOkkfQZa4ioI= cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= @@ -271,8 +271,8 @@ cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQE cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= cloud.google.com/go/iam v0.11.0/go.mod h1:9PiLDanza5D+oWFZiH1uG+RnRCfEGKoyl6yo4cgWZGY= cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= -cloud.google.com/go/iam v1.1.5 h1:1jTsCu4bcsNsE4iiqNT5SHwrDRCfRmIaaaVFhRveTJI= -cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8= +cloud.google.com/go/iam v1.1.6 h1:bEa06k05IO4f4uJonbB5iAgKTPpABy1ayxaIZV/GHVc= +cloud.google.com/go/iam v1.1.6/go.mod h1:O0zxdPeGBoFdWW3HWmBxJsk0pfvNM/p/qa82rWOGTwI= cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc= cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A= cloud.google.com/go/iap v1.6.0/go.mod h1:NSuvI9C/j7UdjGjIde7t7HBz+QTwBcapPE07+sSRcLk= @@ -461,8 +461,8 @@ cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y= -cloud.google.com/go/storage v1.35.1 h1:B59ahL//eDfx2IIKFBeT5Atm9wnNmj3+8xG/W4WB//w= -cloud.google.com/go/storage v1.35.1/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8= +cloud.google.com/go/storage v1.36.0 h1:P0mOkAcaJxhCTvAkMhxMfrTKiNcub4YmmPBtlhAyTr8= +cloud.google.com/go/storage v1.36.0/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8= cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w= cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I= cloud.google.com/go/storagetransfer v1.7.0/go.mod h1:8Giuj1QNb1kfLAiWM1bN6dHzfdlDAVC9rv9abHot2W4= @@ -521,14 +521,14 @@ cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcP dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.2 h1:c4k2FIYIh4xtwqrQwV0Ct1v5+ehlNXj5NI/MWVsiTkQ= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.2/go.mod h1:5FDJtLEO/GxwNgUxbwrY3LP0pEoThTQJtk2oysdXHxM= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.10.0 h1:n1DH8TPV4qqPTje2RcUBYwtrTWlabVp4n46+74X2pn4= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.10.0/go.mod h1:HDcZnuGbiyppErN6lB+idp4CKhjbc8gwjto6OPpyggM= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1 h1:sO0/P7g68FrryJzljemN+6GTssUXdANk6aJ7T1ZxnsQ= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1/go.mod h1:h8hyGFDsU5HMivxiS2iYFZsgDbU9OnnJ163x5UGVKYo= github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2 h1:LqbJ/WzJUwBf8UiaSzgX7aMclParm9/5Vgp+TY51uBQ= github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2/go.mod h1:yInRyqWXAuaPrgI7p70+lDDgh3mlBohis29jGMISnmc= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.4.0 h1:QfV5XZt6iNa2aWMAt96CZEbfJ7kgG/qYIpq465Shr5E= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.4.0/go.mod h1:uYt4CfhkJA9o0FN7jfE5minm/i4nUE4MjGUJkzB6Zs8= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.5.0 h1:MxA59PGoCFb+vCwRQi3PhQEwHj4+r2dhuv9HG+vM7iM= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.5.0/go.mod h1:uYt4CfhkJA9o0FN7jfE5minm/i4nUE4MjGUJkzB6Zs8= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0 h1:bXwSugBiSbgtz7rOtbfGf+woewp4f06orW9OP5BjHLA= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0/go.mod h1:Y/HgrePTmGy9HjdSGTqZNa+apUpTVIEVKXJyARP2lrk= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.5.0 h1:AifHbc4mg0x9zW52WOpKbsHaDKuRhlI7TVl47thgQ70= @@ -598,8 +598,8 @@ github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3d github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= -github.com/aws/aws-sdk-go v1.50.25 h1:vhiHtLYybv1Nhx3Kv18BBC6L0aPJHaG9aeEsr92W99c= -github.com/aws/aws-sdk-go v1.50.25/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= +github.com/aws/aws-sdk-go v1.50.32 h1:POt81DvegnpQKM4DMDLlHz1CO6OBnEoQ1gRhYFd7QRY= +github.com/aws/aws-sdk-go v1.50.32/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= github.com/aws/aws-sdk-go-v2 v1.16.0/go.mod h1:lJYcuZZEHWNIb6ugJjbQY1fykdoobWbOS7kJYb4APoI= github.com/aws/aws-sdk-go-v2 v1.16.16 h1:M1fj4FE2lB4NzRb9Y0xdWsn2P0+2UHVxwKyOa4YJNjk= github.com/aws/aws-sdk-go-v2 v1.16.16/go.mod h1:SwiyXi/1zTUZ6KIAmLK5V5ll8SiURNUYOqTerZPaF9k= @@ -683,8 +683,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101 h1:7To3pQ+pZo0i3dsWEbinPNFs5gPSBOsJtx3wTT94VBY= -github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -705,8 +705,8 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/r github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dhui/dktest v0.4.0 h1:z05UmuXZHO/bgj/ds2bGMBu8FI4WA+Ag/m3ghL+om7M= github.com/dhui/dktest v0.4.0/go.mod h1:v/Dbz1LgCBOi2Uki2nUqLBGa83hWBGFMu5MrgMDCc78= -github.com/digitalocean/godo v1.108.0 h1:fWyMENvtxpCpva1UbKzOFnyAS04N1FNuBWWfPeTGquQ= -github.com/digitalocean/godo v1.108.0/go.mod h1:R6EmmWI8CT1+fCtjWY9UCB+L5uufuZH13wk3YhxycCs= +github.com/digitalocean/godo v1.109.0 h1:4W97RJLJSUQ3veRZDNbp1Ol3Rbn6Lmt9bKGvfqYI5SU= +github.com/digitalocean/godo v1.109.0/go.mod h1:R6EmmWI8CT1+fCtjWY9UCB+L5uufuZH13wk3YhxycCs= github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= @@ -800,8 +800,8 @@ 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-openapi/analysis v0.22.2 h1:ZBmNoP2h5omLKr/srIC9bfqrUGzT6g6gNv03HE9Vpj0= github.com/go-openapi/analysis v0.22.2/go.mod h1:pDF4UbZsQTo/oNuRfAWWd4dAh4yuYf//LYorPTjrpvo= -github.com/go-openapi/errors v0.21.0 h1:FhChC/duCnfoLj1gZ0BgaBmzhJC2SL/sJr8a2vAobSY= -github.com/go-openapi/errors v0.21.0/go.mod h1:jxNTMUxRCKj65yb/okJGEtahVd7uvWnuWfj53bse4ho= +github.com/go-openapi/errors v0.21.1 h1:rVisxQPdETctjlYntm0Ek4dKf68nAQocCloCT50vWuI= +github.com/go-openapi/errors v0.21.1/go.mod h1:LyiY9bgc7AVVh6wtVvMYEyoj3KJYNoRw92mmvnMWgj8= 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.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q= @@ -815,14 +815,14 @@ github.com/go-openapi/runtime v0.27.1 h1:ae53yaOoh+fx/X5Eaq8cRmavHgDma65XPZuvBqv github.com/go-openapi/runtime v0.27.1/go.mod h1:fijeJEiEclyS8BRurYE1DE5TLb9/KZl6eAdbzjsrlLU= github.com/go-openapi/spec v0.20.6 h1:ich1RQ3WDbfoeTqTAb+5EIxNmpKVJZWBNah9RAT0jIQ= github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= -github.com/go-openapi/strfmt v0.22.0 h1:Ew9PnEYc246TwrEspvBdDHS4BVKXy/AOVsfqGDgAcaI= -github.com/go-openapi/strfmt v0.22.0/go.mod h1:HzJ9kokGIju3/K6ap8jL+OlGAbjpSv27135Yr9OivU4= +github.com/go-openapi/strfmt v0.22.2 h1:DPYOrm6gexCfZZfXUaXFS4+Jw6HAaIIG0SZ5630f8yw= +github.com/go-openapi/strfmt v0.22.2/go.mod h1:HB/b7TCm91rno75Dembc1dFW/0FPLk5CEXsoF9ReNc4= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-openapi/swag v0.22.9 h1:XX2DssF+mQKM2DHsbgZK74y/zj4mo9I99+89xUmuZCE= github.com/go-openapi/swag v0.22.9/go.mod h1:3/OXnFfnMAwBD099SwYRk7GD3xOrr1iL7d/XNLXVVwE= -github.com/go-openapi/validate v0.22.6 h1:+NhuwcEYpWdO5Nm4bmvhGLW0rt1Fcc532Mu3wpypXfo= -github.com/go-openapi/validate v0.22.6/go.mod h1:eaddXSqKeTg5XpSmj1dYyFTK/95n/XHwcOY+BMxKMyM= +github.com/go-openapi/validate v0.23.0 h1:2l7PJLzCis4YUGEoW6eoQw3WhyM65WSIcjX6SQnlfDw= +github.com/go-openapi/validate v0.23.0/go.mod h1:EeiAZ5bmpSIOJV1WLfyYF9qp/B1ZgSaEpHTJHtN5cbE= github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= @@ -864,8 +864,6 @@ github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGw github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= -github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= -github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -897,9 +895,9 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -955,8 +953,8 @@ github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= -github.com/google/pprof v0.0.0-20240117000934-35fc243c5815 h1:WzfWbQz/Ze8v6l++GGbGNFZnUShVpP/0xffCPLL+ax8= -github.com/google/pprof v0.0.0-20240117000934-35fc243c5815/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= +github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7 h1:y3N7Bm7Y9/CtpiVkw/ZWj6lSlDF3F74SfKwfTCer72Q= +github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= @@ -981,8 +979,8 @@ github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= -github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= -github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= +github.com/googleapis/gax-go/v2 v2.12.2 h1:mhN09QQW1jEWeMF74zGR81R30z4VJzjZsfkUhuHF+DA= +github.com/googleapis/gax-go/v2 v2.12.2/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gophercloud/gophercloud v1.8.0 h1:TM3Jawprb2NrdOnvcHhWJalmKmAmOGgfZElM/3oBYCk= @@ -1004,15 +1002,15 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw= github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0= -github.com/hashicorp/consul/api v1.27.0 h1:gmJ6DPKQog1426xsdmgk5iqDyoRiNc+ipBdJOqKQFjc= -github.com/hashicorp/consul/api v1.27.0/go.mod h1:JkekNRSou9lANFdt+4IKx3Za7XY0JzzpQjEb4Ivo1c8= +github.com/hashicorp/consul/api v1.28.2 h1:mXfkRHrpHN4YY3RqL09nXU1eHKLNiuAN4kHvDQ16k/8= +github.com/hashicorp/consul/api v1.28.2/go.mod h1:KyzqzgMEya+IZPcD65YFoOVAgPpbfERu4I/tzG6/ueE= github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= -github.com/hashicorp/consul/sdk v0.15.1 h1:kKIGxc7CZtflcF5DLfHeq7rOQmRq3vk7kwISN9bif8Q= -github.com/hashicorp/consul/sdk v0.15.1/go.mod h1:7pxqqhqoaPqnBnzXD1StKed62LqJeClzVsUEy85Zr0A= +github.com/hashicorp/consul/sdk v0.16.0 h1:SE9m0W6DEfgIVCJX7xU+iv/hUl4m/nxqMTnCdMxDpJ8= +github.com/hashicorp/consul/sdk v0.16.0/go.mod h1:7pxqqhqoaPqnBnzXD1StKed62LqJeClzVsUEy85Zr0A= github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A= github.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -1056,13 +1054,13 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru v0.6.0 h1:uL2shRDx7RTrOrTCUZEGP/wJUFiUI8QT6E7z5o8jga4= github.com/hashicorp/golang-lru v0.6.0/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hashicorp/golang-lru/v2 v2.0.2 h1:Dwmkdr5Nc/oBiXgJS3CDHNhJtIHkuZ3DZF5twqnfBdU= -github.com/hashicorp/golang-lru/v2 v2.0.2/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= -github.com/hashicorp/nomad/api v0.0.0-20230721134942-515895c7690c h1:Nc3Mt2BAnq0/VoLEntF/nipX+K1S7pG+RgwiitSv6v0= -github.com/hashicorp/nomad/api v0.0.0-20230721134942-515895c7690c/go.mod h1:O23qLAZuCx4htdY9zBaO4cJPXgleSFEdq6D/sezGgYE= +github.com/hashicorp/nomad/api v0.0.0-20240306004928-3e7191ccb702 h1:fI1LXuBaS1d9z1kmb++Og6YD8uMRwadXorCwE+xgOFA= +github.com/hashicorp/nomad/api v0.0.0-20240306004928-3e7191ccb702/go.mod h1:z71gkJdrkAt/Rl6C7Q79VE7AwJ5lUF+M+fzFTyIHYB0= github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= github.com/hashicorp/serf v0.9.7/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY= @@ -1109,10 +1107,9 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL 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/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= -github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI= -github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= @@ -1144,8 +1141,8 @@ github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2 github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/linode/linodego v1.29.0 h1:gDSQWAbKMAQX8db9FDCXHhodQPrJmLcmthjx6m+PyV4= -github.com/linode/linodego v1.29.0/go.mod h1:3k6WvCM10gillgYcnoLqIL23ST27BD9HhMsCJWb3Bpk= +github.com/linode/linodego v1.30.0 h1:6HJli+LX7NGu+Sne2G+ux790EkVOWOV/SR4mK3jcs6k= +github.com/linode/linodego v1.30.0/go.mod h1:/46h/XpmWi//oSA92GX2p3FIxb8HbX7grslPPQalR2o= github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o= @@ -1212,7 +1209,6 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mozillazg/go-httpheader v0.2.1 h1:geV7TrjbL8KXSyvghnFm+NyTux/hxwueTSrwhe88TQQ= @@ -1277,8 +1273,8 @@ github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndr github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/prometheus-community/prom-label-proxy v0.8.1-0.20240127162815-c1195f9aabc0 h1:owfYHh79h8Y5HvNMGyww+DaVwo10CKiRW1RQrrZzIwg= github.com/prometheus-community/prom-label-proxy v0.8.1-0.20240127162815-c1195f9aabc0/go.mod h1:rT989D4UtOcfd9tVqIZRVIM8rkg+9XbreBjFNEKXvVI= -github.com/prometheus/alertmanager v0.26.0 h1:uOMJWfIwJguc3NaM3appWNbbrh6G/OjvaHMk22aBBYc= -github.com/prometheus/alertmanager v0.26.0/go.mod h1:rVcnARltVjavgVaNnmevxK7kOn7IZavyf0KNgHkbEpU= +github.com/prometheus/alertmanager v0.27.0 h1:V6nTa2J5V4s8TG4C4HtrBP/WNSebCCTYGGv4qecA/+I= +github.com/prometheus/alertmanager v0.27.0/go.mod h1:8Ia/R3urPmbzJ8OsdvmZvIprDwvwmYCmUbwBL+jlPOE= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= @@ -1290,15 +1286,15 @@ github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrb github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= -github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= -github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= -github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= @@ -1307,8 +1303,8 @@ github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+ github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= -github.com/prometheus/common v0.47.0 h1:p5Cz0FNHo7SnWOmWmoRozVcjEp0bIVU8cV7OShpjL1k= -github.com/prometheus/common v0.47.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/common v0.49.1-0.20240306132007-4199f18c3e92 h1:nuwTDY/15McImfuXcUD6AA3alpUNEXfWws8K/8SXr68= +github.com/prometheus/common v0.49.1-0.20240306132007-4199f18c3e92/go.mod h1:Kxm+EULxRbUkjGU6WFsQqo3ORzB4tyKvlWFOE9mB2sE= github.com/prometheus/common/sigv4 v0.1.0 h1:qoVebwtwwEhS85Czm2dSROY5fTo2PAPEVdDeppTwGX4= github.com/prometheus/common/sigv4 v0.1.0/go.mod h1:2Jkxxk9yYvCkE5G1sQT7GuEXm57JrvHu9k5YwTjsNtI= github.com/prometheus/exporter-toolkit v0.8.2/go.mod h1:00shzmJL7KxcsabLWcONwpyNEuWhREOnFqZW7vadFS0= @@ -1324,8 +1320,8 @@ github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0ua github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/prometheus/prometheus v0.50.2-0.20240229164915-d5f0a240faad h1:1aalU6B61Tyxsp3HtvQ4cxtiQd3N5JbaGO7dYfwJ4bQ= -github.com/prometheus/prometheus v0.50.2-0.20240229164915-d5f0a240faad/go.mod h1:lD1Dr94ecu5J10uQWrHg9ZfDMDvlhV5KiLyja/UHolA= +github.com/prometheus/prometheus v0.51.1-0.20240328124728-d81e41d58ec8 h1:Y8WPduSuSD3ffPwKfSXqNoU+tLX9g2bBBK31qyvquLA= +github.com/prometheus/prometheus v0.51.1-0.20240328124728-d81e41d58ec8/go.mod h1:FguQG8pCICrSpHA2pwizwV5FxGNTUBSZED/wMoZwVfY= github.com/redis/rueidis v1.0.14-go1.18 h1:dGir5z8w8X1ex7JWO/Zx2FMBrZgQ8Yjm+lw9fPLSNGw= github.com/redis/rueidis v1.0.14-go1.18/go.mod h1:HGekzV3HbmzFmRK6j0xic8Z9119+ECoGMjeN1TV1NYU= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= @@ -1335,16 +1331,16 @@ github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTE github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= -github.com/rs/cors v1.9.0 h1:l9HGsTsHJcvW14Nk7J9KFz8bzeAWXn3CG6bgt7LsrAE= -github.com/rs/cors v1.9.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= +github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sagikazarmark/crypt v0.6.0/go.mod h1:U8+INwJo3nBv1m6A/8OBXAq7Jnpspk5AxSgDyEQcea8= -github.com/scaleway/scaleway-sdk-go v1.0.0-beta.22 h1:wJrcTdddKOI8TFxs8cemnhKP2EmKy3yfUKHj3ZdfzYo= -github.com/scaleway/scaleway-sdk-go v1.0.0-beta.22/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg= +github.com/scaleway/scaleway-sdk-go v1.0.0-beta.25 h1:/8rfZAdFfafRXOgz+ZpMZZWZ5pYggCY9t7e/BvjaBHM= +github.com/scaleway/scaleway-sdk-go v1.0.0-beta.25/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM= @@ -1381,8 +1377,9 @@ github.com/spf13/viper v1.13.0/go.mod h1:Icm2xNL3/8uyh/wFuB1jI7TiTNKp8632Nwegu+z github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -1394,8 +1391,8 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/tencentyun/cos-go-sdk-v5 v0.7.40 h1:W6vDGKCHe4wBACI1d2UgE6+50sJFhRWU4O8IB2ozzxM= github.com/tencentyun/cos-go-sdk-v5 v0.7.40/go.mod h1:4dCEtLHGh8QPxHEkgq+nFaky7yZxQuYwgSJM87icDaw= @@ -1403,10 +1400,10 @@ github.com/thanos-community/galaxycache v0.0.0-20211122094458-3a32041a1f1e h1:f1 github.com/thanos-community/galaxycache v0.0.0-20211122094458-3a32041a1f1e/go.mod h1:jXcofnrSln/cLI6/dhlBxPQZEEQHVPCcFaH75M+nSzM= github.com/thanos-io/objstore v0.0.0-20240309075357-e8336a5fd5f3 h1:Q0BjHI7FMe5KkKVXBFYto5VNASxiA/+AEhHup/IT7N0= github.com/thanos-io/objstore v0.0.0-20240309075357-e8336a5fd5f3/go.mod h1:ptMYNPgbyAR7a2Ab2t7zHA2/0be2ePyawVR7lp7fZtg= -github.com/thanos-io/promql-engine v0.0.0-20240318110350-23714ea2522d h1:/6Gy8ul/6iKHaAg3OhaoPmph2TRAlansv4z+VAbTOKk= -github.com/thanos-io/promql-engine v0.0.0-20240318110350-23714ea2522d/go.mod h1:YGk7VqhYDfhUyZjWK7ZU1JmBQKSvr5mT5Txut8oK1MA= -github.com/thanos-io/thanos v0.34.2-0.20240327180044-4d7a75f40ae1 h1:/SlnZTDenWF6UiSE1dUmE8fjyR1iZjatCzB8Ly3gFtU= -github.com/thanos-io/thanos v0.34.2-0.20240327180044-4d7a75f40ae1/go.mod h1:jSnVeqLU+lsrZYZ/wVDyh4HmrZY1YfG3s4onyBdCT34= +github.com/thanos-io/promql-engine v0.0.0-20240327143517-c5e4b2e6ef02 h1:lSzA+ZGblFAh18uI3ziBmWCASxQR4CqwO3UEstv99Kg= +github.com/thanos-io/promql-engine v0.0.0-20240327143517-c5e4b2e6ef02/go.mod h1:FEPnabuTql1bDA4OUM41mwcZOJ20R436k8vq+xtGEG0= +github.com/thanos-io/thanos v0.34.2-0.20240328185924-943401f726ed h1:WAGbjaUpZUdem8OY3jF0ReTtCXKmQKu+g4sWNkBA2JQ= +github.com/thanos-io/thanos v0.34.2-0.20240328185924-943401f726ed/go.mod h1:CVOISIxBlYk+wIzYayY1wlwFrsSpQsqAnPFTn61jAWU= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/uber/jaeger-client-go v2.28.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o= @@ -1420,11 +1417,7 @@ github.com/weaveworks/common v0.0.0-20230728070032-dd9e68f319d5 h1:nORobjToZAvi5 github.com/weaveworks/common v0.0.0-20230728070032-dd9e68f319d5/go.mod h1:rgbeLfJUtEr+G74cwFPR1k/4N0kDeaeSv/qhUNE4hm8= github.com/weaveworks/promrus v1.2.0 h1:jOLf6pe6/vss4qGHjXmGz4oDJQA+AOCqEL3FvvZGz7M= github.com/weaveworks/promrus v1.2.0/go.mod h1:SaE82+OJ91yqjrE1rsvBWVzNZKcHYFtMUyS1+Ogs/KA= -github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= -github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= -github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= github.com/xhit/go-str2duration v1.2.0/go.mod h1:3cPSlfZlUHVlneIVfePFWcJZsuwf+P1v2SRTV4cUmp4= -github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -1448,8 +1441,8 @@ go.etcd.io/etcd/client/v2 v2.305.4/go.mod h1:Ud+VUwIi9/uQHOMA+4ekToJ12lTxlv0zB/+ go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY= go.etcd.io/etcd/client/v3 v3.5.12 h1:v5lCPXn1pf1Uu3M4laUE2hp/geOTc5uPcYYsNe1lDxg= go.etcd.io/etcd/client/v3 v3.5.12/go.mod h1:tSbBCakoWmmddL+BKVAJHa9km+O/E+bumDe9mSbPiqw= -go.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/vk= -go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo= +go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80= +go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -1459,16 +1452,16 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/collector/featuregate v1.0.1 h1:ok//hLSXttBbyu4sSV1pTx1nKdr5udSmrWy5sFMIIbM= -go.opentelemetry.io/collector/featuregate v1.0.1/go.mod h1:QQXjP4etmJQhkQ20j4P/rapWuItYxoFozg/iIwuKnYg= -go.opentelemetry.io/collector/pdata v1.0.1 h1:dGX2h7maA6zHbl5D3AsMnF1c3Nn+3EUftbVCLzeyNvA= -go.opentelemetry.io/collector/pdata v1.0.1/go.mod h1:jutXeu0QOXYY8wcZ/hege+YAnSBP3+jpTqYU1+JTI5Y= -go.opentelemetry.io/collector/semconv v0.93.0 h1:eBlMcVNTwYYsVdAsCVDs4wvVYs75K1xcIDpqj16PG4c= -go.opentelemetry.io/collector/semconv v0.93.0/go.mod h1:gZ0uzkXsN+J5NpiRcdp9xOhNGQDDui8Y62p15sKrlzo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 h1:SpGay3w+nEwMpfVnbqOLH5gY52/foP8RE8UzTZ1pdSE= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 h1:sv9kVfal0MK0wBMCOGr+HeJm9v803BkJxGrk2au7j08= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0/go.mod h1:SK2UL73Zy1quvRPonmOmRDiWk1KBV3LyIeeIxcEApWw= +go.opentelemetry.io/collector/featuregate v1.3.0 h1:nrFSx+zfjdisjE9oCx25Aep3nJ9RaUjeE1qFL6eovoU= +go.opentelemetry.io/collector/featuregate v1.3.0/go.mod h1:mm8+xyQfgDmqhyegZRNIQmoKsNnDTwWKFLsdMoXAb7A= +go.opentelemetry.io/collector/pdata v1.3.0 h1:JRYN7tVHYFwmtQhIYbxWeiKSa2L1nCohyAs8sYqKFZo= +go.opentelemetry.io/collector/pdata v1.3.0/go.mod h1:t7W0Undtes53HODPdSujPLTnfSR5fzT+WpL+RTaaayo= +go.opentelemetry.io/collector/semconv v0.96.0 h1:DrZy8BpzJDnN2zFxXRj6BhfGYxNlqpFHBqyuS9fVHRY= +go.opentelemetry.io/collector/semconv v0.96.0/go.mod h1:zOm/U3pgMIWcvrcnPbR9Xx2HinoXj46ERMK8PUV9wrs= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= go.opentelemetry.io/contrib/propagators/autoprop v0.38.0 h1:WZwiLCwOL0XW/6TVT7LTtdRDveoHZ6q3wL+0iYsBcdE= go.opentelemetry.io/contrib/propagators/autoprop v0.38.0/go.mod h1:JBebP2d0HiffbfelbIEoBOCl4790g7Z8lD1scUd3Vd8= go.opentelemetry.io/contrib/propagators/aws v1.22.0 h1:SKtPYiel5TWrE9gib3F4/BUcrvVjKsA5CH9xnWvj6cQ= @@ -1479,25 +1472,25 @@ go.opentelemetry.io/contrib/propagators/jaeger v1.13.0 h1:+tVlvpiQMOCzi4EYCaBjbl go.opentelemetry.io/contrib/propagators/jaeger v1.13.0/go.mod h1:Qf7eVCLYawiNIB+A81kk8aFDFwYqXSqmt0N2RcvkLLI= go.opentelemetry.io/contrib/propagators/ot v1.13.0 h1:tHWNd0WRS6w9keZoZg9aF3zYohdaBacQfojPYZJgATQ= go.opentelemetry.io/contrib/propagators/ot v1.13.0/go.mod h1:R6Op9T6LxNaMRVlGD0wVwz40LSsAq296CXiEydKLQBU= -go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y= -go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= go.opentelemetry.io/otel/bridge/opentracing v1.22.0 h1:ZujpdLoATPdsyzp8hE5xW3jCNVZE46eMm42eu1JuxKk= go.opentelemetry.io/otel/bridge/opentracing v1.22.0/go.mod h1:tnna9idtdH9//GUou9KCMo9pmnU9G14zrosFeeaqFP0= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 h1:9M3+rhx7kZCIQQhQRYaZCdNu1V73tm4TvXs2ntl98C4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0/go.mod h1:noq80iT8rrHP1SfybmPiRGc9dc5M8RPmGvtwo7Oo7tc= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 h1:H2JFgRcGiyHg7H7bwcwaQJYrNFqCqrbTQ8K4p1OvDu8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0/go.mod h1:WfCWp1bGoYK8MeULtI15MmQVczfR+bFkk0DF3h06QmQ= -go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg= -go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= -go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw= -go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= -go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0= -go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 h1:t6wl9SPayj+c7lEIFgm4ooDBZVb01IhLB4InpomhRw8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0/go.mod h1:iSDOcsnSA5INXzZtwaBPrKp/lWu/V14Dd+llD0oI2EA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 h1:Mw5xcxMwlqoJd97vwPxA8isEaIoxsta9/Q51+TTJLGE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0/go.mod h1:CQNu9bj7o7mC6U7+CA/schKEYakYXWr79ucDHTMGhCM= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= -go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= +go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= go.uber.org/atomic v1.5.1/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= @@ -1529,10 +1522,9 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20221012134737-56aed061732a/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1592,8 +1584,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= +golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 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-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1659,8 +1651,8 @@ golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= +golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1690,8 +1682,8 @@ golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= -golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= -golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= +golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= +golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1811,8 +1803,8 @@ golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -1820,8 +1812,8 @@ golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1914,8 +1906,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= -golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= -golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= +golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw= +golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc= 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= @@ -1993,8 +1985,8 @@ google.golang.org/api v0.106.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/ google.golang.org/api v0.107.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= -google.golang.org/api v0.157.0 h1:ORAeqmbrrozeyw5NjnMxh7peHO0UzV4wWYSwZeCUb20= -google.golang.org/api v0.157.0/go.mod h1:+z4v4ufbZ1WEpld6yMGHyggs+PmAHiaLNj5ytP3N01g= +google.golang.org/api v0.168.0 h1:MBRe+Ki4mMN93jhDDbpuRLjRddooArz4FeSObvUMmjY= +google.golang.org/api v0.168.0/go.mod h1:gpNOiMA2tZ4mf5R9Iwf4rK/Dcz0fbdIgWYWVoxmsyLg= 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/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -2134,12 +2126,12 @@ google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44/go.mod h1:8B0gmkoRebU8ukX6HP+4wrVQUY1+6PkQ44BSyIlflHA= google.golang.org/genproto v0.0.0-20230222225845-10f96fb3dbec/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= -google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 h1:nz5NESFLZbJGPFxDT/HCn+V1mZ8JGNoY4nUpmW/Y2eg= -google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917/go.mod h1:pZqR+glSb11aJ+JQcczCvgf47+duRuzNSKqE8YAQnV0= -google.golang.org/genproto/googleapis/api v0.0.0-20240116215550-a9fa1716bcac h1:OZkkudMUu9LVQMCoRUbI/1p5VCo9BOrlvkqMvWtqa6s= -google.golang.org/genproto/googleapis/api v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:B5xPO//w8qmBDjGReYLpR6UJPnkldGkCSMoH/2vxJeg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac h1:nUQEQmH/csSvFECKYRv6HWEyypysidKl2I6Qpsglq/0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:daQN87bsDqDoe316QbbvX60nMoJQa4r6Ds0ZuoAe5yA= +google.golang.org/genproto v0.0.0-20240205150955-31a09d347014 h1:g/4bk7P6TPMkAUbUhquq98xey1slwvuVJPosdBqYJlU= +google.golang.org/genproto v0.0.0-20240205150955-31a09d347014/go.mod h1:xEgQu1e4stdSSsxPDK8Azkrk/ECl5HvdPf6nbZrTS5M= +google.golang.org/genproto/googleapis/api v0.0.0-20240304212257-790db918fca8 h1:8eadJkXbwDEMNwcB5O0s5Y5eCfyuCLdvaiOIaGTrWmQ= +google.golang.org/genproto/googleapis/api v0.0.0-20240304212257-790db918fca8/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240304161311-37d4d3c04a78 h1:Xs9lu+tLXxLIfuci70nG4cpwaRC+mRQPUL7LoIeDJC4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240304161311-37d4d3c04a78/go.mod h1:UCOku4NytXMJuLQE5VuqA5lX3PcHCBo8pxNyvkf4xBs= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -2182,8 +2174,8 @@ google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsA google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= -google.golang.org/grpc v1.61.0 h1:TOvOcuXn30kRao+gfcvsebNEa5iZIiLkisYEkf7R7o0= -google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= +google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk= +google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= 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= @@ -2214,8 +2206,8 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/telebot.v3 v3.1.3 h1:T+CTyOWpZMqp3ALHSweNgp1awQ9nMXdRAMpe/r6x9/s= -gopkg.in/telebot.v3 v3.1.3/go.mod h1:GJKwwWqp9nSkIVN51eRKU78aB5f5OnQuWdwiIZfPbko= +gopkg.in/telebot.v3 v3.2.1 h1:3I4LohaAyJBiivGmkfB+CiVu7QFOWkuZ4+KHgO/G3rs= +gopkg.in/telebot.v3 v3.2.1/go.mod h1:GJKwwWqp9nSkIVN51eRKU78aB5f5OnQuWdwiIZfPbko= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= 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= @@ -2240,12 +2232,12 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= -k8s.io/api v0.29.2 h1:hBC7B9+MU+ptchxEqTNW2DkUosJpp1P+Wn6YncZ474A= -k8s.io/api v0.29.2/go.mod h1:sdIaaKuU7P44aoyyLlikSLayT6Vb7bvJNCX105xZXY0= -k8s.io/apimachinery v0.29.2 h1:EWGpfJ856oj11C52NRCHuU7rFDwxev48z+6DSlGNsV8= -k8s.io/apimachinery v0.29.2/go.mod h1:6HVkd1FwxIagpYrHSwJlQqZI3G9LfYWRPAkUvLnXTKU= -k8s.io/client-go v0.29.2 h1:FEg85el1TeZp+/vYJM7hkDlSTFZ+c5nnK44DJ4FyoRg= -k8s.io/client-go v0.29.2/go.mod h1:knlvFZE58VpqbQpJNbCbctTVXcd35mMyAAwBdpt4jrA= +k8s.io/api v0.29.3 h1:2ORfZ7+bGC3YJqGpV0KSDDEVf8hdGQ6A03/50vj8pmw= +k8s.io/api v0.29.3/go.mod h1:y2yg2NTyHUUkIoTC+phinTnEa3KFM6RZ3szxt014a80= +k8s.io/apimachinery v0.29.3 h1:2tbx+5L7RNvqJjn7RIuIKu9XTsIZ9Z5wX2G22XAa5EU= +k8s.io/apimachinery v0.29.3/go.mod h1:hx/S4V2PNW4OMg3WizRrHutyB5la0iCUbZym+W0EQIU= +k8s.io/client-go v0.29.3 h1:R/zaZbEAxqComZ9FHeQwOh3Y1ZUs7FaHKZdQtIc2WZg= +k8s.io/client-go v0.29.3/go.mod h1:tkDisCvgPfiRpxGnOORfkljmS+UrW+WtXAy2fTvXJB0= k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780= diff --git a/integration/alertmanager_test.go b/integration/alertmanager_test.go index 2ceb5e0013..b50c65132a 100644 --- a/integration/alertmanager_test.go +++ b/integration/alertmanager_test.go @@ -7,7 +7,6 @@ import ( "bytes" "context" "fmt" - "net/http" "strings" "testing" "time" @@ -68,25 +67,6 @@ func TestAlertmanager(t *testing.T) { // Ensure no service-specific metrics prefix is used by the wrong service. assertServiceMetricsPrefixes(t, AlertManager, alertmanager) - - // Test compression by inspecting the response Headers - req, err := http.NewRequest("GET", fmt.Sprintf("http://%s/api/v1/alerts", alertmanager.HTTPEndpoint()), nil) - require.NoError(t, err) - - req.Header.Set("X-Scope-OrgID", "user-1") - req.Header.Set("Accept-Encoding", "gzip") - - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - - // Execute HTTP request - res, err := http.DefaultClient.Do(req.WithContext(ctx)) - require.NoError(t, err) - - defer res.Body.Close() - // We assert on the Vary header as the minimum response size for enabling compression is 1500 bytes. - // This is enough to know whenever the handler for compression is enabled or not. - require.Equal(t, "Accept-Encoding", res.Header.Get("Vary")) } func TestAlertmanagerStoreAPI(t *testing.T) { @@ -360,16 +340,6 @@ func TestAlertmanagerSharding(t *testing.T) { assert.Equal(t, comment(3), ids[id3].Comment) assert.Equal(t, s3, ids[id3].Status.State) } - - // Endpoint: GET /v1/silences - { - for _, c := range clients { - list, err := c.GetSilencesV1(context.Background()) - require.NoError(t, err) - assertSilences(list, types.SilenceStateActive, types.SilenceStateActive, types.SilenceStateActive) - } - } - // Endpoint: GET /v2/silences { for _, c := range clients { @@ -379,26 +349,6 @@ func TestAlertmanagerSharding(t *testing.T) { } } - // Endpoint: GET /v1/silence/{id} - { - for _, c := range clients { - sil1, err := c.GetSilenceV1(context.Background(), id1) - require.NoError(t, err) - assert.Equal(t, comment(1), sil1.Comment) - assert.Equal(t, types.SilenceStateActive, sil1.Status.State) - - sil2, err := c.GetSilenceV1(context.Background(), id2) - require.NoError(t, err) - assert.Equal(t, comment(2), sil2.Comment) - assert.Equal(t, types.SilenceStateActive, sil2.Status.State) - - sil3, err := c.GetSilenceV1(context.Background(), id3) - require.NoError(t, err) - assert.Equal(t, comment(3), sil3.Comment) - assert.Equal(t, types.SilenceStateActive, sil3.Status.State) - } - } - // Endpoint: GET /v2/silence/{id} { for _, c := range clients { @@ -517,18 +467,6 @@ func TestAlertmanagerSharding(t *testing.T) { e2e.SkipMissingMetrics)) } - // Endpoint: GET /v1/alerts - { - // Reads will query at least two replicas and merge the results. - // Therefore, the alerts we posted should always be visible. - - for _, c := range clients { - list, err := c.GetAlertsV1(context.Background()) - require.NoError(t, err) - assert.ElementsMatch(t, []string{"alert_1", "alert_2", "alert_3"}, alertNames(list)) - } - } - // Endpoint: GET /v2/alerts { for _, c := range clients { @@ -555,8 +493,6 @@ func TestAlertmanagerSharding(t *testing.T) { require.Contains(t, groups, "group_2") assert.ElementsMatch(t, []string{"alert_3"}, alertNames(groups["group_2"])) } - - // Note: /v1/alerts/groups does not exist. } // Check the alerts were eventually written to every replica. diff --git a/integration/e2ecortex/client.go b/integration/e2ecortex/client.go index 23a3948af2..81b3a0d77c 100644 --- a/integration/e2ecortex/client.go +++ b/integration/e2ecortex/client.go @@ -14,6 +14,7 @@ import ( "github.com/gogo/protobuf/proto" "github.com/golang/snappy" + open_api_models "github.com/prometheus/alertmanager/api/v2/models" alertConfig "github.com/prometheus/alertmanager/config" "github.com/prometheus/alertmanager/types" promapi "github.com/prometheus/client_golang/api" @@ -614,7 +615,7 @@ func (c *Client) getRawPage(ctx context.Context, url string) ([]byte, error) { // GetAlertmanagerConfig gets the status of an alertmanager instance func (c *Client) GetAlertmanagerConfig(ctx context.Context) (*alertConfig.Config, error) { - u := c.alertmanagerClient.URL("/api/prom/api/v1/status", nil) + u := c.alertmanagerClient.URL("/api/prom/api/v2/status", nil) req, err := http.NewRequest(http.MethodGet, u.String(), nil) if err != nil { @@ -634,16 +635,17 @@ func (c *Client) GetAlertmanagerConfig(ctx context.Context) (*alertConfig.Config return nil, fmt.Errorf("getting config failed with status %d and error %v", resp.StatusCode, string(body)) } - var ss *ServerStatus - err = json.Unmarshal(body, &ss) + cfg := &open_api_models.AlertmanagerStatus{} + err = yaml.Unmarshal(body, cfg) + if err != nil { return nil, err } - cfg := &alertConfig.Config{} - err = yaml.Unmarshal([]byte(ss.Data.ConfigYaml), cfg) + original := &alertConfig.Config{} + err = yaml.Unmarshal([]byte(*cfg.Config.Original), original) - return cfg, err + return original, err } // SetAlertmanagerConfig gets the status of an alertmanager instance @@ -705,7 +707,7 @@ func (c *Client) DeleteAlertmanagerConfig(ctx context.Context) error { // SendAlertToAlermanager sends alerts to the Alertmanager API func (c *Client) SendAlertToAlermanager(ctx context.Context, alert *model.Alert) error { - u := c.alertmanagerClient.URL("/api/prom/api/v1/alerts", nil) + u := c.alertmanagerClient.URL("/api/prom/api/v2/alerts", nil) data, err := json.Marshal([]types.Alert{{Alert: *alert}}) if err != nil { @@ -716,7 +718,7 @@ func (c *Client) SendAlertToAlermanager(ctx context.Context, alert *model.Alert) if err != nil { return fmt.Errorf("error creating request: %v", err) } - + req.Header.Set("Content-Type", "application/json") resp, body, err := c.alertmanagerClient.Do(ctx, req) if err != nil { return err @@ -729,44 +731,6 @@ func (c *Client) SendAlertToAlermanager(ctx context.Context, alert *model.Alert) return nil } -func (c *Client) GetAlertsV1(ctx context.Context) ([]model.Alert, error) { - u := c.alertmanagerClient.URL("api/prom/api/v1/alerts", nil) - - req, err := http.NewRequest(http.MethodGet, u.String(), nil) - if err != nil { - return nil, fmt.Errorf("error creating request: %v", err) - } - - resp, body, err := c.alertmanagerClient.Do(ctx, req) - if err != nil { - return nil, err - } - - if resp.StatusCode == http.StatusNotFound { - return nil, ErrNotFound - } - - if resp.StatusCode/100 != 2 { - return nil, fmt.Errorf("getting alerts failed with status %d and error %v", resp.StatusCode, string(body)) - } - - type response struct { - Status string `json:"status"` - Data []model.Alert `json:"data"` - } - - decoded := &response{} - if err := json.Unmarshal(body, decoded); err != nil { - return nil, err - } - - if decoded.Status != "success" { - return nil, fmt.Errorf("unexpected response status '%s'", decoded.Status) - } - - return decoded.Data, nil -} - func (c *Client) GetAlertsV2(ctx context.Context) ([]model.Alert, error) { u := c.alertmanagerClient.URL("api/prom/api/v2/alerts", nil) @@ -831,7 +795,7 @@ func (c *Client) GetAlertGroups(ctx context.Context) ([]AlertGroup, error) { // CreateSilence creates a new silence and returns the unique identifier of the silence. func (c *Client) CreateSilence(ctx context.Context, silence types.Silence) (string, error) { - u := c.alertmanagerClient.URL("api/prom/api/v1/silences", nil) + u := c.alertmanagerClient.URL("api/prom/api/v2/silences", nil) data, err := json.Marshal(silence) if err != nil { @@ -843,6 +807,8 @@ func (c *Client) CreateSilence(ctx context.Context, silence types.Silence) (stri return "", fmt.Errorf("error creating request: %v", err) } + req.Header.Set("Content-Type", "application/json") + resp, body, err := c.alertmanagerClient.Do(ctx, req) if err != nil { return "", err @@ -853,60 +819,14 @@ func (c *Client) CreateSilence(ctx context.Context, silence types.Silence) (stri } type response struct { - Status string `json:"status"` - Data struct { - SilenceID string `json:"silenceID"` - } `json:"data"` + SilenceID string `json:"silenceID"` } decoded := &response{} if err := json.Unmarshal(body, decoded); err != nil { return "", err } - - if decoded.Status != "success" { - return "", fmt.Errorf("unexpected response status '%s'", decoded.Status) - } - - return decoded.Data.SilenceID, nil -} - -func (c *Client) GetSilencesV1(ctx context.Context) ([]types.Silence, error) { - u := c.alertmanagerClient.URL("api/prom/api/v1/silences", nil) - - req, err := http.NewRequest(http.MethodGet, u.String(), nil) - if err != nil { - return nil, fmt.Errorf("error creating request: %v", err) - } - - resp, body, err := c.alertmanagerClient.Do(ctx, req) - if err != nil { - return nil, err - } - - if resp.StatusCode == http.StatusNotFound { - return nil, ErrNotFound - } - - if resp.StatusCode/100 != 2 { - return nil, fmt.Errorf("getting silences failed with status %d and error %v", resp.StatusCode, string(body)) - } - - type response struct { - Status string `json:"status"` - Data []types.Silence `json:"data"` - } - - decoded := &response{} - if err := json.Unmarshal(body, decoded); err != nil { - return nil, err - } - - if decoded.Status != "success" { - return nil, fmt.Errorf("unexpected response status '%s'", decoded.Status) - } - - return decoded.Data, nil + return decoded.SilenceID, nil } func (c *Client) GetSilencesV2(ctx context.Context) ([]types.Silence, error) { @@ -938,44 +858,6 @@ func (c *Client) GetSilencesV2(ctx context.Context) ([]types.Silence, error) { return decoded, nil } -func (c *Client) GetSilenceV1(ctx context.Context, id string) (types.Silence, error) { - u := c.alertmanagerClient.URL(fmt.Sprintf("api/prom/api/v1/silence/%s", url.PathEscape(id)), nil) - - req, err := http.NewRequest(http.MethodGet, u.String(), nil) - if err != nil { - return types.Silence{}, fmt.Errorf("error creating request: %v", err) - } - - resp, body, err := c.alertmanagerClient.Do(ctx, req) - if err != nil { - return types.Silence{}, err - } - - if resp.StatusCode == http.StatusNotFound { - return types.Silence{}, ErrNotFound - } - - if resp.StatusCode/100 != 2 { - return types.Silence{}, fmt.Errorf("getting silence failed with status %d and error %v", resp.StatusCode, string(body)) - } - - type response struct { - Status string `json:"status"` - Data types.Silence `json:"data"` - } - - decoded := &response{} - if err := json.Unmarshal(body, decoded); err != nil { - return types.Silence{}, err - } - - if decoded.Status != "success" { - return types.Silence{}, fmt.Errorf("unexpected response status '%s'", decoded.Status) - } - - return decoded.Data, nil -} - func (c *Client) GetSilenceV2(ctx context.Context, id string) (types.Silence, error) { u := c.alertmanagerClient.URL(fmt.Sprintf("api/prom/api/v2/silence/%s", url.PathEscape(id)), nil) @@ -1006,7 +888,7 @@ func (c *Client) GetSilenceV2(ctx context.Context, id string) (types.Silence, er } func (c *Client) DeleteSilence(ctx context.Context, id string) error { - u := c.alertmanagerClient.URL(fmt.Sprintf("api/prom/api/v1/silence/%s", url.PathEscape(id)), nil) + u := c.alertmanagerClient.URL(fmt.Sprintf("api/prom/api/v2/silence/%s", url.PathEscape(id)), nil) req, err := http.NewRequest(http.MethodDelete, u.String(), nil) if err != nil { @@ -1030,7 +912,7 @@ func (c *Client) DeleteSilence(ctx context.Context, id string) error { } func (c *Client) GetReceivers(ctx context.Context) ([]string, error) { - u := c.alertmanagerClient.URL("api/prom/api/v1/receivers", nil) + u := c.alertmanagerClient.URL("api/prom/api/v2/receivers", nil) req, err := http.NewRequest(http.MethodGet, u.String(), nil) if err != nil { @@ -1050,21 +932,21 @@ func (c *Client) GetReceivers(ctx context.Context) ([]string, error) { return nil, fmt.Errorf("getting receivers failed with status %d and error %v", resp.StatusCode, string(body)) } + r := []string{} type response struct { - Status string `json:"status"` - Data []string `json:"data"` + Name string `json:"name"` } - decoded := &response{} - if err := json.Unmarshal(body, decoded); err != nil { + decoded := []response{} + if err := json.Unmarshal(body, &decoded); err != nil { return nil, err } - if decoded.Status != "success" { - return nil, fmt.Errorf("unexpected response status '%s'", decoded.Status) + for _, d := range decoded { + r = append(r, d.Name) } - return decoded.Data, nil + return r, nil } func (c *Client) PostRequest(url string, body io.Reader) (*http.Response, error) { diff --git a/pkg/alertmanager/alertmanager.go b/pkg/alertmanager/alertmanager.go index b9c0b35f28..ec134c07f4 100644 --- a/pkg/alertmanager/alertmanager.go +++ b/pkg/alertmanager/alertmanager.go @@ -5,6 +5,7 @@ import ( "crypto/md5" "encoding/binary" "fmt" + "net/http" "net/url" "path" @@ -21,6 +22,7 @@ import ( "github.com/prometheus/alertmanager/cluster/clusterpb" "github.com/prometheus/alertmanager/config" "github.com/prometheus/alertmanager/dispatch" + "github.com/prometheus/alertmanager/featurecontrol" "github.com/prometheus/alertmanager/inhibit" "github.com/prometheus/alertmanager/nflog" "github.com/prometheus/alertmanager/notify" @@ -243,7 +245,14 @@ func New(cfg *Config, reg *prometheus.Registry) (*Alertmanager, error) { } } - am.pipelineBuilder = notify.NewPipelineBuilder(am.registry) + // Lets not enable any AM experimental feature for now. + featureConfig, err := featurecontrol.NewFlags(am.logger, "") + if err != nil { + level.Error(am.logger).Log("msg", "error parsing the feature flag list", "err", err) + return nil, errors.Wrap(err, "error parsing the feature flag list") + } + + am.pipelineBuilder = notify.NewPipelineBuilder(am.registry, featureConfig) am.wg.Add(1) go func() { @@ -390,7 +399,7 @@ func (am *Alertmanager) ApplyConfig(userID string, conf *config.Config, rawCfg s waitFunc, am.inhibitor, silence.NewSilencer(am.silences, am.marker, am.logger), - timeIntervals, + timeinterval.NewIntervener(timeIntervals), am.nflog, am.state, ) @@ -495,7 +504,7 @@ func buildReceiverIntegrations(nc config.Receiver, tmpl *template.Template, fire return } n = wrapper(name, n) - integrations = append(integrations, notify.NewIntegration(n, rs, name, i)) + integrations = append(integrations, notify.NewIntegration(n, rs, name, i, nc.Name)) } ) diff --git a/pkg/alertmanager/distributor.go b/pkg/alertmanager/distributor.go index 378971e843..d1a7781493 100644 --- a/pkg/alertmanager/distributor.go +++ b/pkg/alertmanager/distributor.go @@ -78,21 +78,12 @@ func (d *Distributor) isUnaryDeletePath(p string) bool { } func (d *Distributor) isQuorumReadPath(p string) (bool, merger.Merger) { - if strings.HasSuffix(p, "/v1/alerts") { - return true, merger.V1Alerts{} - } if strings.HasSuffix(p, "/v2/alerts") { return true, merger.V2Alerts{} } if strings.HasSuffix(p, "/v2/alerts/groups") { return true, merger.V2AlertGroups{} } - if strings.HasSuffix(p, "/v1/silences") { - return true, merger.V1Silences{} - } - if strings.HasSuffix(path.Dir(p), "/v1/silence") { - return true, merger.V1SilenceID{} - } if strings.HasSuffix(p, "/v2/silences") { return true, merger.V2Silences{} } diff --git a/pkg/alertmanager/distributor_test.go b/pkg/alertmanager/distributor_test.go index ddda42749f..beb2277e74 100644 --- a/pkg/alertmanager/distributor_test.go +++ b/pkg/alertmanager/distributor_test.go @@ -85,16 +85,6 @@ func TestDistributor_DistributeRequest(t *testing.T) { expStatusCode: http.StatusInternalServerError, expectedTotalCalls: 3, route: "/alerts", - }, { - name: "Read /v1/alerts is sent to 3 AMs", - numAM: 5, - numHappyAM: 5, - replicationFactor: 3, - isRead: true, - expStatusCode: http.StatusOK, - expectedTotalCalls: 3, - route: "/v1/alerts", - responseBody: []byte(`{"status":"success","data":[]}`), }, { name: "Read /v2/alerts is sent to 3 AMs", numAM: 5, @@ -133,16 +123,6 @@ func TestDistributor_DistributeRequest(t *testing.T) { expectedTotalCalls: 0, headersNotPreserved: true, route: "/alerts/groups", - }, { - name: "Read /v1/silences is sent to 3 AMs", - numAM: 5, - numHappyAM: 5, - replicationFactor: 3, - isRead: true, - expStatusCode: http.StatusOK, - expectedTotalCalls: 3, - route: "/v1/silences", - responseBody: []byte(`{"status":"success","data":[]}`), }, { name: "Read /v2/silences is sent to 3 AMs", numAM: 5, @@ -161,16 +141,6 @@ func TestDistributor_DistributeRequest(t *testing.T) { expStatusCode: http.StatusOK, expectedTotalCalls: 1, route: "/silences", - }, { - name: "Read /v1/silence/id is sent to 3 AMs", - numAM: 5, - numHappyAM: 5, - replicationFactor: 3, - isRead: true, - expStatusCode: http.StatusOK, - expectedTotalCalls: 3, - route: "/v1/silence/id", - responseBody: []byte(`{"status":"success","data":{"id":"aaa","updatedAt":"2020-01-01T00:00:00Z"}}`), }, { name: "Read /v2/silence/id is sent to 3 AMs", numAM: 5, diff --git a/pkg/alertmanager/merger/v1_alerts.go b/pkg/alertmanager/merger/v1_alerts.go deleted file mode 100644 index ae2f286891..0000000000 --- a/pkg/alertmanager/merger/v1_alerts.go +++ /dev/null @@ -1,72 +0,0 @@ -package merger - -import ( - "encoding/json" - "fmt" - "sort" - - v1 "github.com/prometheus/alertmanager/api/v1" -) - -const ( - statusSuccess = "success" -) - -// V1Alerts implements the Merger interface for GET /v1/alerts. It returns the union of alerts over -// all the responses. When the same alert exists in multiple responses, the alert instance in the -// earliest response is returned in the final response. We cannot use the UpdatedAt timestamp as -// for V2Alerts, because the v1 API does not provide it. -type V1Alerts struct{} - -func (V1Alerts) MergeResponses(in [][]byte) ([]byte, error) { - type bodyType struct { - Status string `json:"status"` - Data []*v1.Alert `json:"data"` - } - - alerts := make([]*v1.Alert, 0) - for _, body := range in { - parsed := bodyType{} - if err := json.Unmarshal(body, &parsed); err != nil { - return nil, err - } - if parsed.Status != statusSuccess { - return nil, fmt.Errorf("unable to merge response of status: %s", parsed.Status) - } - alerts = append(alerts, parsed.Data...) - } - - merged, err := mergeV1Alerts(alerts) - if err != nil { - return nil, err - } - body := bodyType{ - Status: statusSuccess, - Data: merged, - } - - return json.Marshal(body) -} - -func mergeV1Alerts(in []*v1.Alert) ([]*v1.Alert, error) { - // Select an arbitrary alert for each distinct alert. - alerts := make(map[string]*v1.Alert) - for _, alert := range in { - key := alert.Fingerprint - if _, ok := alerts[key]; !ok { - alerts[key] = alert - } - } - - result := make([]*v1.Alert, 0, len(alerts)) - for _, alert := range alerts { - result = append(result, alert) - } - - // Mimic Alertmanager which returns alerts ordered by fingerprint (as string). - sort.Slice(result, func(i, j int) bool { - return result[i].Fingerprint < result[j].Fingerprint - }) - - return result, nil -} diff --git a/pkg/alertmanager/merger/v1_alerts_test.go b/pkg/alertmanager/merger/v1_alerts_test.go deleted file mode 100644 index 83f4382442..0000000000 --- a/pkg/alertmanager/merger/v1_alerts_test.go +++ /dev/null @@ -1,158 +0,0 @@ -package merger - -import ( - "testing" - "time" - - v1 "github.com/prometheus/alertmanager/api/v1" - "github.com/prometheus/alertmanager/types" - prom_model "github.com/prometheus/common/model" - "github.com/stretchr/testify/require" -) - -func TestV1Alerts(t *testing.T) { - - // This test is to check the parsing round-trip is working as expected, the merging logic is - // tested in TestMergeV1Alerts. The test data is based on captures from an actual Alertmanager. - - in := [][]byte{ - []byte(`{"status":"success","data":[` + - `{"labels":{"group":"group_1","name":"alert_1"},` + - `"annotations":null,"startsAt":"2021-04-21T09:47:32.16145934+02:00",` + - `"endsAt":"2021-04-21T10:47:32.161462204+02:00","generatorURL":"",` + - `"status":{"state":"unprocessed","silencedBy":[],"inhibitedBy":[]},` + - `"receivers":["dummy"],"fingerprint":"c4b6b79a607b6ba0"},` + - `{"labels":{"group":"group_1","name":"alert_2"},` + - `"annotations":null,"startsAt":"2021-04-21T09:47:32.163797336+02:00",` + - `"endsAt":"2021-04-21T10:47:32.163800129+02:00","generatorURL":"",` + - `"status":{"state":"unprocessed","silencedBy":[],"inhibitedBy":[]},` + - `"receivers":["dummy"],"fingerprint":"c4b8b79a607bee77"}]}`), - []byte(`{"status":"success","data":[` + - `{"labels":{"group":"group_2","name":"alert_3"},` + - `"annotations":null,"startsAt":"2021-04-21T09:47:32.165939585+02:00",` + - `"endsAt":"2021-04-21T10:47:32.165942448+02:00","generatorURL":"",` + - `"status":{"state":"unprocessed","silencedBy":[],"inhibitedBy":[]},` + - `"receivers":["dummy"],"fingerprint":"465de60f606461c3"}]}`), - []byte(`{"status":"success","data":[]}`), - } - - expected := []byte(`{"status":"success","data":[` + - `{"labels":{"group":"group_2","name":"alert_3"},"annotations":null,` + - `"startsAt":"2021-04-21T09:47:32.165939585+02:00",` + - `"endsAt":"2021-04-21T10:47:32.165942448+02:00","generatorURL":"",` + - `"status":{"state":"unprocessed","silencedBy":[],"inhibitedBy":[]},` + - `"receivers":["dummy"],"fingerprint":"465de60f606461c3"},` + - `{"labels":{"group":"group_1","name":"alert_1"},"annotations":null,` + - `"startsAt":"2021-04-21T09:47:32.16145934+02:00",` + - `"endsAt":"2021-04-21T10:47:32.161462204+02:00","generatorURL":"",` + - `"status":{"state":"unprocessed","silencedBy":[],"inhibitedBy":[]},` + - `"receivers":["dummy"],"fingerprint":"c4b6b79a607b6ba0"},` + - `{"labels":{"group":"group_1","name":"alert_2"},"annotations":null,` + - `"startsAt":"2021-04-21T09:47:32.163797336+02:00",` + - `"endsAt":"2021-04-21T10:47:32.163800129+02:00","generatorURL":"",` + - `"status":{"state":"unprocessed","silencedBy":[],"inhibitedBy":[]},` + - `"receivers":["dummy"],"fingerprint":"c4b8b79a607bee77"}]}`) - - out, err := V1Alerts{}.MergeResponses(in) - require.NoError(t, err) - require.Equal(t, expected, out) -} - -func v1ParseTime(s string) time.Time { - t, _ := time.Parse(time.RFC3339, s) - return t -} - -// v1alert is a convenience function to create alert structures with certain important fields set -// and with sensible defaults for the remaining fields to test they are passed through. -func v1alert(fingerprint, annotation string) *v1.Alert { - return &v1.Alert{ - Alert: &prom_model.Alert{ - Labels: prom_model.LabelSet{ - "label1": "value1", - }, - Annotations: prom_model.LabelSet{ - "annotation1": prom_model.LabelValue(annotation), - }, - StartsAt: v1ParseTime("2020-01-01T12:00:00.000Z"), - EndsAt: v1ParseTime("2020-01-01T12:00:00.000Z"), - GeneratorURL: "something", - }, - Status: types.AlertStatus{}, - Receivers: []string{"dummy"}, - Fingerprint: fingerprint, - } -} - -func v1alerts(alerts ...*v1.Alert) []*v1.Alert { - return alerts -} - -func TestMergeV1Alerts(t *testing.T) { - var ( - alert1 = v1alert("1111111111111111", "a1") - alert1b = v1alert("1111111111111111", "a1b") - alert2 = v1alert("2222222222222222", "a2") - alert3 = v1alert("3333333333333333", "a3") - ) - cases := []struct { - name string - in []*v1.Alert - err error - out []*v1.Alert - }{ - { - name: "no alerts, should return an empty list", - in: v1alerts(), - out: []*v1.Alert{}, - }, - { - name: "one alert, should return the alert", - in: v1alerts(alert1), - out: v1alerts(alert1), - }, - { - name: "two alerts, should return two alerts", - in: v1alerts(alert1, alert2), - out: v1alerts(alert1, alert2), - }, - { - name: "three alerts, should return three alerts", - in: v1alerts(alert1, alert2, alert3), - out: v1alerts(alert1, alert2, alert3), - }, - { - name: "three alerts out of order, should return three alerts in fingerprint order", - in: v1alerts(alert3, alert2, alert1), - out: v1alerts(alert1, alert2, alert3), - }, - { - name: "two identical alerts, should return one alert", - in: v1alerts(alert1, alert1), - out: v1alerts(alert1), - }, - { - name: "two identical alerts plus another, should return two alerts", - in: v1alerts(alert1, alert1, alert2), - out: v1alerts(alert1, alert2), - }, - { - name: "two duplicates out of sync alerts, should return first seen alert", - in: v1alerts(alert1, alert1b), - out: v1alerts(alert1), - }, - { - name: "two duplicates plus others, should return first seen alert and others", - in: v1alerts(alert1b, alert3, alert1, alert2), - out: v1alerts(alert1b, alert2, alert3), - }, - } - - for _, c := range cases { - t.Run(c.name, func(t *testing.T) { - out, err := mergeV1Alerts(c.in) - require.Equal(t, c.err, err) - require.Equal(t, c.out, out) - }) - } -} diff --git a/pkg/alertmanager/merger/v1_silence_id.go b/pkg/alertmanager/merger/v1_silence_id.go deleted file mode 100644 index 4352634f4c..0000000000 --- a/pkg/alertmanager/merger/v1_silence_id.go +++ /dev/null @@ -1,51 +0,0 @@ -package merger - -import ( - "encoding/json" - "errors" - "fmt" - - v2_models "github.com/prometheus/alertmanager/api/v2/models" -) - -// V1Silences implements the Merger interface for GET /v1/silences. This re-uses the logic for -// merging /v2/silences, with additional handling for the enclosing status/data fields. Unlike for -// alerts, the API definitions for silences are almost identical between v1 and v2. The differences -// are that the fields in the JSON output are ordered differently, and the timestamps have more -// precision in v1, but these differences should not be problematic to clients. -type V1SilenceID struct{} - -func (V1SilenceID) MergeResponses(in [][]byte) ([]byte, error) { - type bodyType struct { - Status string `json:"status"` - Data *v2_models.GettableSilence `json:"data"` - } - - silences := make(v2_models.GettableSilences, 0) - for _, body := range in { - parsed := bodyType{} - if err := json.Unmarshal(body, &parsed); err != nil { - return nil, err - } - if parsed.Status != statusSuccess { - return nil, fmt.Errorf("unable to merge response of status: %s", parsed.Status) - } - silences = append(silences, parsed.Data) - } - - merged, err := mergeV2Silences(silences) - if err != nil { - return nil, err - } - - if len(merged) != 1 { - return nil, errors.New("unexpected mismatched silence ids") - } - - body := bodyType{ - Status: statusSuccess, - Data: merged[0], - } - - return json.Marshal(body) -} diff --git a/pkg/alertmanager/merger/v1_silence_id_test.go b/pkg/alertmanager/merger/v1_silence_id_test.go deleted file mode 100644 index 434bcfa227..0000000000 --- a/pkg/alertmanager/merger/v1_silence_id_test.go +++ /dev/null @@ -1,110 +0,0 @@ -package merger - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestV1SilenceID_ReturnsNewestSilence(t *testing.T) { - in := [][]byte{ - []byte(`{"status":"success","data":{` + - `"id":"77b580dd-1d9c-4b7e-9bba-13ac173cb4e5",` + - `"matchers":[` + - `{` + - `"name":"instance",` + - `"value":"prometheus-one",` + - `"isRegex":false,` + - `"isEqual":true` + - `}` + - `],` + - `"startsAt":"2021-04-28T17:31:01.725956017Z",` + - `"endsAt":"2021-04-28T20:31:01.722829007+02:00",` + - `"updatedAt":"2021-04-28T17:32:01.725956017Z",` + - `"createdBy":"",` + - `"comment":"The newer silence",` + - `"status":{"state":"active"}` + - `}}`), - []byte(`{"status":"success","data":{` + - `"id":"77b580dd-1d9c-4b7e-9bba-13ac173cb4e5",` + - `"matchers":[` + - `{` + - `"name":"instance",` + - `"value":"prometheus-one",` + - `"isRegex":false,` + - `"isEqual":true` + - `}` + - `],` + - `"startsAt":"2021-04-28T17:31:01.725956017Z",` + - `"endsAt":"2021-04-28T20:31:01.722829007+02:00",` + - `"updatedAt":"2021-04-28T17:31:01.725956017Z",` + - `"createdBy":"",` + - `"comment":"Silence Comment #1",` + - `"status":{"state":"active"}` + - `}}`), - } - - expected := []byte(`{"status":"success","data":{` + - `"id":"77b580dd-1d9c-4b7e-9bba-13ac173cb4e5",` + - `"status":{"state":"active"},` + - `"updatedAt":"2021-04-28T17:32:01.725Z",` + - `"comment":"The newer silence",` + - `"createdBy":"",` + - `"endsAt":"2021-04-28T20:31:01.722+02:00",` + - `"matchers":[` + - `{` + - `"isEqual":true,` + - `"isRegex":false,` + - `"name":"instance",` + - `"value":"prometheus-one"` + - `}` + - `],` + - `"startsAt":"2021-04-28T17:31:01.725Z"` + - `}}`) - - out, err := V1SilenceID{}.MergeResponses(in) - require.NoError(t, err) - require.Equal(t, string(expected), string(out)) -} - -func TestV1SilenceID_InvalidDifferentIDs(t *testing.T) { - in := [][]byte{ - []byte(`{"status":"success","data":{` + - `"id":"77b580dd-1d9c-4b7e-9bba-13ac173cb4e5",` + - `"matchers":[` + - `{` + - `"name":"instance",` + - `"value":"prometheus-one",` + - `"isRegex":false,` + - `"isEqual":true` + - `}` + - `],` + - `"startsAt":"2021-04-28T17:31:01.725956017Z",` + - `"endsAt":"2021-04-28T20:31:01.722829007+02:00",` + - `"updatedAt":"2021-04-28T17:32:01.725956017Z",` + - `"createdBy":"",` + - `"comment":"Silence Comment #1",` + - `"status":{"state":"active"}` + - `}}`), - []byte(`{"status":"success","data":{` + - `"id":"261248d1-4ff7-4cf1-9957-850c65f4e48b",` + - `"matchers":[` + - `{` + - `"name":"instance",` + - `"value":"prometheus-one",` + - `"isRegex":false,` + - `"isEqual":true` + - `}` + - `],` + - `"startsAt":"2021-04-28T17:31:01.725956017Z",` + - `"endsAt":"2021-04-28T20:31:01.722829007+02:00",` + - `"updatedAt":"2021-04-28T17:31:01.725956017Z",` + - `"createdBy":"",` + - `"comment":"Silence Comment #2",` + - `"status":{"state":"active"}` + - `}}`), - } - - _, err := V1SilenceID{}.MergeResponses(in) - require.Error(t, err) -} diff --git a/pkg/alertmanager/merger/v1_silences.go b/pkg/alertmanager/merger/v1_silences.go deleted file mode 100644 index 1e0bd08121..0000000000 --- a/pkg/alertmanager/merger/v1_silences.go +++ /dev/null @@ -1,45 +0,0 @@ -package merger - -import ( - "encoding/json" - "fmt" - - v2_models "github.com/prometheus/alertmanager/api/v2/models" -) - -// V1Silences implements the Merger interface for GET /v1/silences. Unlike for alerts, the API -// definitions for silences are almost identical between v1 and v2. The differences are that the -// fields in the JSON output are ordered differently, and the timestamps have more precision in v1, -// but these differences should not be problematic to clients. Therefore, the implementation -// re-uses the v2 types, with additional handling for the enclosing status/data fields. -type V1Silences struct{} - -func (V1Silences) MergeResponses(in [][]byte) ([]byte, error) { - type bodyType struct { - Status string `json:"status"` - Data v2_models.GettableSilences `json:"data"` - } - - silences := make(v2_models.GettableSilences, 0) - for _, body := range in { - parsed := bodyType{} - if err := json.Unmarshal(body, &parsed); err != nil { - return nil, err - } - if parsed.Status != statusSuccess { - return nil, fmt.Errorf("unable to merge response of status: %s", parsed.Status) - } - silences = append(silences, parsed.Data...) - } - - merged, err := mergeV2Silences(silences) - if err != nil { - return nil, err - } - body := bodyType{ - Status: statusSuccess, - Data: merged, - } - - return json.Marshal(body) -} diff --git a/pkg/alertmanager/merger/v1_silences_test.go b/pkg/alertmanager/merger/v1_silences_test.go deleted file mode 100644 index b44a4e2257..0000000000 --- a/pkg/alertmanager/merger/v1_silences_test.go +++ /dev/null @@ -1,128 +0,0 @@ -package merger - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestV1Silences(t *testing.T) { - - // This test is to check the parsing round-trip is working as expected, the merging logic is - // tested in TestMergeV2Silences. The test data is based on captures from an actual Alertmanager. - - in := [][]byte{ - []byte(`{"status":"success","data":[` + - `{` + - `"id":"77b580dd-1d9c-4b7e-9bba-13ac173cb4e5",` + - `"matchers":[` + - `{` + - `"name":"instance",` + - `"value":"prometheus-one",` + - `"isRegex":false,` + - `"isEqual":true` + - `}` + - `],` + - `"startsAt":"2021-04-28T17:31:01.725956017Z",` + - `"endsAt":"2021-04-28T20:31:01.722829007+02:00",` + - `"updatedAt":"2021-04-28T17:31:01.725956017Z",` + - `"createdBy":"",` + - `"comment":"Silence Comment #1",` + - `"status":{"state":"active"}` + - `},` + - `{` + - `"id":"17526003-c745-4464-a355-4f06de26a236",` + - `"matchers":[` + - `{` + - `"name":"instance",` + - `"value":"prometheus-one",` + - `"isRegex":false,` + - `"isEqual":true` + - `}` + - `],` + - `"startsAt":"2021-04-28T17:31:01.731140275Z",` + - `"endsAt":"2021-04-28T18:31:01.727579131Z",` + - `"updatedAt":"2021-04-28T17:31:01.731140275Z",` + - `"createdBy":"",` + - `"comment":"Silence Comment #2",` + - `"status":{"state":"active"}},` + - `{` + - `"id":"261248d1-4ff7-4cf1-9957-850c65f4e48b",` + - `"matchers":[` + - `{` + - `"name":"instance",` + - `"value":"prometheus-one",` + - `"isRegex":false,` + - `"isEqual":true` + - `}` + - `],` + - `"startsAt":"2021-04-28T17:31:01.73572697Z",` + - `"endsAt":"2021-04-28T18:31:01.732873879Z",` + - `"updatedAt":"2021-04-28T17:31:01.73572697Z",` + - `"createdBy":"",` + - `"comment":"Silence Comment #3",` + - `"status":{"state":"active"}}` + - `]}`), - []byte(`{"status":"success","data":[]}`), - } - - // Note that our implementation for v1 uses v2 code internally. This means the JSON fields - // come out in a slightly different order, and the timestamps lave less digits. - expected := []byte(`{"status":"success","data":[` + - `{` + - `"id":"77b580dd-1d9c-4b7e-9bba-13ac173cb4e5",` + - `"status":{"state":"active"},` + - `"updatedAt":"2021-04-28T17:31:01.725Z",` + - `"comment":"Silence Comment #1",` + - `"createdBy":"",` + - `"endsAt":"2021-04-28T20:31:01.722+02:00",` + - `"matchers":[` + - `{` + - `"isEqual":true,` + - `"isRegex":false,` + - `"name":"instance",` + - `"value":"prometheus-one"` + - `}` + - `],` + - `"startsAt":"2021-04-28T17:31:01.725Z"` + - `},` + - `{` + - `"id":"17526003-c745-4464-a355-4f06de26a236",` + - `"status":{"state":"active"},` + - `"updatedAt":"2021-04-28T17:31:01.731Z",` + - `"comment":"Silence Comment #2",` + - `"createdBy":"",` + - `"endsAt":"2021-04-28T18:31:01.727Z",` + - `"matchers":[` + - `{` + - `"isEqual":true,` + - `"isRegex":false,` + - `"name":"instance",` + - `"value":"prometheus-one"` + - `}` + - `],` + - `"startsAt":"2021-04-28T17:31:01.731Z"` + - `},` + - `{` + - `"id":"261248d1-4ff7-4cf1-9957-850c65f4e48b",` + - `"status":{"state":"active"},` + - `"updatedAt":"2021-04-28T17:31:01.735Z",` + - `"comment":"Silence Comment #3",` + - `"createdBy":"",` + - `"endsAt":"2021-04-28T18:31:01.732Z",` + - `"matchers":[` + - `{` + - `"isEqual":true,` + - `"isRegex":false,` + - `"name":"instance",` + - `"value":"prometheus-one"` + - `}` + - `],` + - `"startsAt":"2021-04-28T17:31:01.735Z"` + - `}` + - `]}`) - - out, err := V1Silences{}.MergeResponses(in) - require.NoError(t, err) - require.Equal(t, string(expected), string(out)) -} diff --git a/pkg/alertmanager/multitenant.go b/pkg/alertmanager/multitenant.go index 49a3e401ad..654487d15d 100644 --- a/pkg/alertmanager/multitenant.go +++ b/pkg/alertmanager/multitenant.go @@ -4,6 +4,7 @@ import ( "context" "flag" "fmt" + "net/http" "net/url" "os" diff --git a/pkg/alertmanager/multitenant_test.go b/pkg/alertmanager/multitenant_test.go index 38057bb144..5fa5635350 100644 --- a/pkg/alertmanager/multitenant_test.go +++ b/pkg/alertmanager/multitenant_test.go @@ -529,7 +529,7 @@ receivers: require.NoError(t, err) // Push an alert. - req := httptest.NewRequest(http.MethodPost, cfg.ExternalURL.String()+"/api/v1/alerts", bytes.NewReader(alertsPayload)) + req := httptest.NewRequest(http.MethodPost, cfg.ExternalURL.String()+"/api/v2/alerts", bytes.NewReader(alertsPayload)) req.Header.Set("content-type", "application/json") reqCtx := user.InjectOrgID(req.Context(), userID) { @@ -979,7 +979,7 @@ receivers: defer services.StopAndAwaitTerminated(ctx, am) //nolint:errcheck // Request when no user configuration is present. - req := httptest.NewRequest("GET", externalURL.String()+"/api/v1/status", nil) + req := httptest.NewRequest("GET", externalURL.String()+"/api/v2/status", nil) w := httptest.NewRecorder() am.ServeHTTP(w, req.WithContext(user.InjectOrgID(req.Context(), "user1"))) diff --git a/pkg/api/handlers.go b/pkg/api/handlers.go index a1b1afc200..17bd42d7c4 100644 --- a/pkg/api/handlers.go +++ b/pkg/api/handlers.go @@ -19,6 +19,7 @@ import ( "github.com/prometheus/common/route" "github.com/prometheus/common/version" "github.com/prometheus/prometheus/config" + "github.com/prometheus/prometheus/promql" "github.com/prometheus/prometheus/storage" v1 "github.com/prometheus/prometheus/web/api/v1" "github.com/weaveworks/common/instrument" @@ -159,7 +160,7 @@ func NewQuerierHandler( cfg Config, queryable storage.SampleAndChunkQueryable, exemplarQueryable storage.ExemplarQueryable, - engine v1.QueryEngine, + engine promql.QueryEngine, distributor Distributor, reg prometheus.Registerer, logger log.Logger, diff --git a/pkg/cortex/cortex.go b/pkg/cortex/cortex.go index 279bfcaece..b560baccf2 100644 --- a/pkg/cortex/cortex.go +++ b/pkg/cortex/cortex.go @@ -14,8 +14,8 @@ import ( "github.com/go-kit/log/level" "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/prometheus/promql" prom_storage "github.com/prometheus/prometheus/storage" - v1 "github.com/prometheus/prometheus/web/api/v1" "github.com/weaveworks/common/server" "github.com/weaveworks/common/signals" "google.golang.org/grpc/health/grpc_health_v1" @@ -303,7 +303,7 @@ type Cortex struct { RuntimeConfig *runtimeconfig.Manager QuerierQueryable prom_storage.SampleAndChunkQueryable ExemplarQueryable prom_storage.ExemplarQueryable - QuerierEngine v1.QueryEngine + QuerierEngine promql.QueryEngine QueryFrontendTripperware tripperware.Tripperware Ruler *ruler.Ruler diff --git a/pkg/cortex/modules.go b/pkg/cortex/modules.go index 3b39646310..8b10594f40 100644 --- a/pkg/cortex/modules.go +++ b/pkg/cortex/modules.go @@ -15,7 +15,6 @@ import ( "github.com/prometheus/prometheus/promql" "github.com/prometheus/prometheus/rules" prom_storage "github.com/prometheus/prometheus/storage" - v1 "github.com/prometheus/prometheus/web/api/v1" "github.com/thanos-io/objstore" "github.com/thanos-io/promql-engine/engine" "github.com/thanos-io/promql-engine/logicalplan" @@ -556,7 +555,7 @@ func (t *Cortex) initRuler() (serv services.Service, err error) { if t.Cfg.ExternalPusher != nil && t.Cfg.ExternalQueryable != nil { rulerRegisterer := prometheus.WrapRegistererWith(prometheus.Labels{"engine": "ruler"}, prometheus.DefaultRegisterer) - var queryEngine v1.QueryEngine + var queryEngine promql.QueryEngine opts := promql.EngineOpts{ Logger: util_log.Logger, Reg: rulerRegisterer, diff --git a/pkg/ingester/client/compat_test.go b/pkg/ingester/client/compat_test.go index 54ea26c9bb..56483abedd 100644 --- a/pkg/ingester/client/compat_test.go +++ b/pkg/ingester/client/compat_test.go @@ -54,11 +54,27 @@ func TestQueryRequest(t *testing.T) { if !reflect.DeepEqual(haveTo, to) { t.Fatalf("Bad to FromQueryRequest(ToQueryRequest) round trip") } - if !reflect.DeepEqual(haveMatchers, matchers) { + if !matchersEqual(haveMatchers, matchers) { t.Fatalf("Bad have FromQueryRequest(ToQueryRequest) round trip - %v != %v", haveMatchers, matchers) } } +func matchersEqual(expected, actual []*labels.Matcher) bool { + if len(expected) != len(actual) { + return false + } + + for i := 0; i < len(expected); i++ { + a := actual[i] + e := expected[i] + if a.Name != e.Name || a.Value != e.Value || a.Type != e.Type { + return false + } + } + + return true +} + func buildTestMatrix(numSeries int, samplesPerSeries int, offset int) model.Matrix { m := make(model.Matrix, 0, numSeries) for i := 0; i < numSeries; i++ { diff --git a/pkg/querier/blocks_store_queryable_test.go b/pkg/querier/blocks_store_queryable_test.go index f624644866..0ad8f3996e 100644 --- a/pkg/querier/blocks_store_queryable_test.go +++ b/pkg/querier/blocks_store_queryable_test.go @@ -19,7 +19,6 @@ import ( "github.com/prometheus/prometheus/promql" "github.com/prometheus/prometheus/storage" "github.com/prometheus/prometheus/tsdb/chunkenc" - v1 "github.com/prometheus/prometheus/web/api/v1" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -1512,7 +1511,7 @@ func TestBlocksStoreQuerier_PromQLExecution(t *testing.T) { } for _, thanosEngine := range []bool{false, true} { t.Run(fmt.Sprintf("thanos engine enabled=%t", thanosEngine), func(t *testing.T) { - var queryEngine v1.QueryEngine + var queryEngine promql.QueryEngine if thanosEngine { queryEngine = engine.New(engine.Opts{ EngineOpts: opts, diff --git a/pkg/querier/chunk_store_queryable_test.go b/pkg/querier/chunk_store_queryable_test.go index e9c361323c..5b3b7d9e4e 100644 --- a/pkg/querier/chunk_store_queryable_test.go +++ b/pkg/querier/chunk_store_queryable_test.go @@ -11,7 +11,6 @@ import ( "github.com/prometheus/common/model" "github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/promql" - v1 "github.com/prometheus/prometheus/web/api/v1" "github.com/stretchr/testify/require" "github.com/thanos-io/promql-engine/engine" "github.com/thanos-io/promql-engine/logicalplan" @@ -35,7 +34,7 @@ func TestChunkQueryable(t *testing.T) { for _, encoding := range encodings { for _, query := range queries { t.Run(fmt.Sprintf("%s/%s/%s/ thanos engine enabled = %t", testcase.name, encoding.name, query.query, thanosEngine), func(t *testing.T) { - var queryEngine v1.QueryEngine + var queryEngine promql.QueryEngine if thanosEngine { queryEngine = engine.New(engine.Opts{ EngineOpts: opts, diff --git a/pkg/querier/error_translate_queryable_test.go b/pkg/querier/error_translate_queryable_test.go index 43c560d4c1..e62cad6bb5 100644 --- a/pkg/querier/error_translate_queryable_test.go +++ b/pkg/querier/error_translate_queryable_test.go @@ -136,7 +136,7 @@ func TestApiStatusCodes(t *testing.T) { } } -func createPrometheusAPI(q storage.SampleAndChunkQueryable, engine v1.QueryEngine) *route.Router { +func createPrometheusAPI(q storage.SampleAndChunkQueryable, engine promql.QueryEngine) *route.Router { api := v1.NewAPI( engine, q, diff --git a/pkg/querier/querier.go b/pkg/querier/querier.go index 5938b976e6..1f24912691 100644 --- a/pkg/querier/querier.go +++ b/pkg/querier/querier.go @@ -18,7 +18,6 @@ import ( "github.com/prometheus/prometheus/promql" "github.com/prometheus/prometheus/storage" "github.com/prometheus/prometheus/util/annotations" - v1 "github.com/prometheus/prometheus/web/api/v1" "github.com/thanos-io/promql-engine/engine" "github.com/thanos-io/promql-engine/logicalplan" "github.com/thanos-io/thanos/pkg/strutil" @@ -162,7 +161,7 @@ func getChunksIteratorFunction(cfg Config) chunkIteratorFunc { } // New builds a queryable and promql engine. -func New(cfg Config, limits *validation.Overrides, distributor Distributor, stores []QueryableWithFilter, reg prometheus.Registerer, logger log.Logger) (storage.SampleAndChunkQueryable, storage.ExemplarQueryable, v1.QueryEngine) { +func New(cfg Config, limits *validation.Overrides, distributor Distributor, stores []QueryableWithFilter, reg prometheus.Registerer, logger log.Logger) (storage.SampleAndChunkQueryable, storage.ExemplarQueryable, promql.QueryEngine) { iteratorFunc := getChunksIteratorFunction(cfg) distributorQueryable := newDistributorQueryable(distributor, cfg.IngesterMetadataStreaming, iteratorFunc, cfg.QueryIngestersWithin, cfg.QueryStoreForLabels) @@ -193,7 +192,7 @@ func New(cfg Config, limits *validation.Overrides, distributor Distributor, stor }) maxConcurrentMetric.Set(float64(cfg.MaxConcurrent)) - var queryEngine v1.QueryEngine + var queryEngine promql.QueryEngine opts := promql.EngineOpts{ Logger: logger, Reg: reg, diff --git a/pkg/querier/querier_test.go b/pkg/querier/querier_test.go index fbb868d0e8..fbd15116c5 100644 --- a/pkg/querier/querier_test.go +++ b/pkg/querier/querier_test.go @@ -18,7 +18,6 @@ import ( "github.com/prometheus/prometheus/storage" "github.com/prometheus/prometheus/tsdb" "github.com/prometheus/prometheus/util/annotations" - v1 "github.com/prometheus/prometheus/web/api/v1" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -253,7 +252,7 @@ func TestShouldSortSeriesIfQueryingMultipleQueryables(t *testing.T) { MaxSamples: 1e6, Timeout: 1 * time.Minute, } - var queryEngine v1.QueryEngine + var queryEngine promql.QueryEngine if thanosEngine { queryEngine = engine.New(engine.Opts{ EngineOpts: opts, @@ -499,7 +498,7 @@ func TestQuerier(t *testing.T) { for _, iterators := range []bool{false, true} { iterators := iterators t.Run(fmt.Sprintf("%s/%s/iterators=%t", query.query, encoding.name, iterators), func(t *testing.T) { - var queryEngine v1.QueryEngine + var queryEngine promql.QueryEngine if thanosEngine { queryEngine = engine.New(engine.Opts{ EngineOpts: opts, @@ -648,7 +647,7 @@ func TestNoHistoricalQueryToIngester(t *testing.T) { for _, c := range testCases { cfg.QueryIngestersWithin = c.queryIngestersWithin t.Run(fmt.Sprintf("thanosEngine=%t,queryIngestersWithin=%v, test=%s", thanosEngine, c.queryIngestersWithin, c.name), func(t *testing.T) { - var queryEngine v1.QueryEngine + var queryEngine promql.QueryEngine if thanosEngine { queryEngine = engine.New(engine.Opts{ EngineOpts: opts, @@ -1223,7 +1222,7 @@ func mockDistibutorFor(t *testing.T, cs mockChunkStore, through model.Time) *Moc return result } -func testRangeQuery(t testing.TB, queryable storage.Queryable, queryEngine v1.QueryEngine, end model.Time, q query) *promql.Result { +func testRangeQuery(t testing.TB, queryable storage.Queryable, queryEngine promql.QueryEngine, end model.Time, q query) *promql.Result { from, through, step := time.Unix(0, 0), end.Time(), q.step ctx := user.InjectOrgID(context.Background(), "0") query, err := queryEngine.NewRangeQuery(ctx, queryable, nil, q.query, from, through, step) diff --git a/pkg/ruler/compat.go b/pkg/ruler/compat.go index e5a535cf69..4a02540ef6 100644 --- a/pkg/ruler/compat.go +++ b/pkg/ruler/compat.go @@ -19,7 +19,6 @@ import ( "github.com/prometheus/prometheus/promql/parser" "github.com/prometheus/prometheus/rules" "github.com/prometheus/prometheus/storage" - v1 "github.com/prometheus/prometheus/web/api/v1" "github.com/weaveworks/common/httpgrpc" "github.com/weaveworks/common/user" @@ -158,7 +157,7 @@ type RulesLimits interface { // EngineQueryFunc returns a new engine query function by passing an altered timestamp. // Modified from Prometheus rules.EngineQueryFunc // https://github.com/prometheus/prometheus/blob/v2.39.1/rules/manager.go#L189. -func EngineQueryFunc(engine v1.QueryEngine, q storage.Queryable, overrides RulesLimits, userID string, lookbackDelta time.Duration) rules.QueryFunc { +func EngineQueryFunc(engine promql.QueryEngine, q storage.Queryable, overrides RulesLimits, userID string, lookbackDelta time.Duration) rules.QueryFunc { return func(ctx context.Context, qs string, t time.Time) (promql.Vector, error) { // Enforce the max query length. maxQueryLength := overrides.MaxQueryLength(userID) @@ -299,7 +298,7 @@ type RulesManager interface { // ManagerFactory is a function that creates new RulesManager for given user and notifier.Manager. type ManagerFactory func(ctx context.Context, userID string, notifier *notifier.Manager, logger log.Logger, reg prometheus.Registerer) RulesManager -func DefaultTenantManagerFactory(cfg Config, p Pusher, q storage.Queryable, engine v1.QueryEngine, overrides RulesLimits, evalMetrics *RuleEvalMetrics, reg prometheus.Registerer) ManagerFactory { +func DefaultTenantManagerFactory(cfg Config, p Pusher, q storage.Queryable, engine promql.QueryEngine, overrides RulesLimits, evalMetrics *RuleEvalMetrics, reg prometheus.Registerer) ManagerFactory { // Wrap errors returned by Queryable to our wrapper, so that we can distinguish between those errors // and errors returned by PromQL engine. Errors from Queryable can be either caused by user (limits) or internal errors. // Errors from PromQL are always "user" errors. diff --git a/pkg/ruler/notifier.go b/pkg/ruler/notifier.go index 8f8b87f754..2665411ab3 100644 --- a/pkg/ruler/notifier.go +++ b/pkg/ruler/notifier.go @@ -117,15 +117,9 @@ func buildNotifierConfig(rulerConfig *Config) (*config.Config, error) { if len(validURLs) == 0 { return &config.Config{}, nil } - - apiVersion := config.AlertmanagerAPIVersionV1 - if rulerConfig.AlertmanangerEnableV2API { - apiVersion = config.AlertmanagerAPIVersionV2 - } - amConfigs := make([]*config.AlertmanagerConfig, 0, len(validURLs)) for _, url := range validURLs { - amConfigs = append(amConfigs, amConfigFromURL(rulerConfig, url, apiVersion)) + amConfigs = append(amConfigs, amConfigFromURL(rulerConfig, url, config.AlertmanagerAPIVersionV2)) } promConfig := &config.Config{ diff --git a/pkg/ruler/notifier_test.go b/pkg/ruler/notifier_test.go index 22789a235b..8d3c6ba2af 100644 --- a/pkg/ruler/notifier_test.go +++ b/pkg/ruler/notifier_test.go @@ -37,7 +37,7 @@ func TestBuildNotifierConfig(t *testing.T) { AlertingConfig: config.AlertingConfig{ AlertmanagerConfigs: []*config.AlertmanagerConfig{ { - APIVersion: "v1", + APIVersion: "v2", Scheme: "http", PathPrefix: "/alertmanager", ServiceDiscoveryConfigs: discovery.Configs{ @@ -63,7 +63,7 @@ func TestBuildNotifierConfig(t *testing.T) { AlertingConfig: config.AlertingConfig{ AlertmanagerConfigs: []*config.AlertmanagerConfig{ { - APIVersion: "v1", + APIVersion: "v2", Scheme: "http", PathPrefix: "/alertmanager", ServiceDiscoveryConfigs: discovery.Configs{ @@ -96,7 +96,7 @@ func TestBuildNotifierConfig(t *testing.T) { AlertingConfig: config.AlertingConfig{ AlertmanagerConfigs: []*config.AlertmanagerConfig{ { - APIVersion: "v1", + APIVersion: "v2", Scheme: "http", PathPrefix: "/alertmanager", ServiceDiscoveryConfigs: discovery.Configs{ @@ -107,7 +107,7 @@ func TestBuildNotifierConfig(t *testing.T) { }, }, { - APIVersion: "v1", + APIVersion: "v2", Scheme: "http", PathPrefix: "/alertmanager", ServiceDiscoveryConfigs: discovery.Configs{ @@ -132,7 +132,7 @@ func TestBuildNotifierConfig(t *testing.T) { AlertingConfig: config.AlertingConfig{ AlertmanagerConfigs: []*config.AlertmanagerConfig{ { - APIVersion: "v1", + APIVersion: "v2", Scheme: "http", PathPrefix: "/alertmanager", ServiceDiscoveryConfigs: discovery.Configs{ @@ -145,7 +145,7 @@ func TestBuildNotifierConfig(t *testing.T) { }, }, { - APIVersion: "v1", + APIVersion: "v2", Scheme: "http", PathPrefix: "/alertmanager", ServiceDiscoveryConfigs: discovery.Configs{ @@ -173,7 +173,7 @@ func TestBuildNotifierConfig(t *testing.T) { HTTPClientConfig: config_util.HTTPClientConfig{ BasicAuth: &config_util.BasicAuth{Username: "marco", Password: "hunter2"}, }, - APIVersion: "v1", + APIVersion: "v2", Scheme: "http", PathPrefix: "/alertmanager", ServiceDiscoveryConfigs: discovery.Configs{ @@ -206,7 +206,7 @@ func TestBuildNotifierConfig(t *testing.T) { HTTPClientConfig: config_util.HTTPClientConfig{ BasicAuth: &config_util.BasicAuth{Username: "jacob", Password: "test"}, }, - APIVersion: "v1", + APIVersion: "v2", Scheme: "http", PathPrefix: "/alertmanager", ServiceDiscoveryConfigs: discovery.Configs{ @@ -233,7 +233,7 @@ func TestBuildNotifierConfig(t *testing.T) { AlertingConfig: config.AlertingConfig{ AlertmanagerConfigs: []*config.AlertmanagerConfig{ { - APIVersion: "v1", + APIVersion: "v2", Scheme: "http", PathPrefix: "/alertmanager", ServiceDiscoveryConfigs: discovery.Configs{ diff --git a/pkg/ruler/ruler.go b/pkg/ruler/ruler.go index b0c46cb694..ba3c698e36 100644 --- a/pkg/ruler/ruler.go +++ b/pkg/ruler/ruler.go @@ -103,8 +103,6 @@ type Config struct { AlertmanagerDiscovery bool `yaml:"enable_alertmanager_discovery"` // How long to wait between refreshing the list of Alertmanager based on DNS service discovery. AlertmanagerRefreshInterval time.Duration `yaml:"alertmanager_refresh_interval"` - // Enables the ruler notifier to use the Alertmananger V2 API. - AlertmanangerEnableV2API bool `yaml:"enable_alertmanager_v2"` // Capacity of the queue for notifications to be sent to the Alertmanager. NotificationQueueCapacity int `yaml:"notification_queue_capacity"` // HTTP timeout duration when sending notifications to the Alertmanager. @@ -177,6 +175,8 @@ func (cfg *Config) RegisterFlags(f *flag.FlagSet) { flagext.DeprecatedFlag(f, "ruler.group-timeout", "This flag is no longer functional.", util_log.Logger) //lint:ignore faillint Need to pass the global logger like this for warning on deprecated methods flagext.DeprecatedFlag(f, "ruler.num-workers", "This flag is no longer functional. For increased concurrency horizontal sharding is recommended", util_log.Logger) + //lint:ignore faillint Need to pass the global logger like this for warning on deprecated methods + flagext.DeprecatedFlag(f, "ruler.alertmanager-use-v2", "This flag is no longer functional. V1 API is deprecated and removed", util_log.Logger) cfg.ExternalURL.URL, _ = url.Parse("") // Must be non-nil f.Var(&cfg.ExternalURL, "ruler.external.url", "URL of alerts return path.") @@ -186,7 +186,6 @@ func (cfg *Config) RegisterFlags(f *flag.FlagSet) { f.StringVar(&cfg.AlertmanagerURL, "ruler.alertmanager-url", "", "Comma-separated list of URL(s) of the Alertmanager(s) to send notifications to. Each Alertmanager URL is treated as a separate group in the configuration. Multiple Alertmanagers in HA per group can be supported by using DNS resolution via -ruler.alertmanager-discovery.") f.BoolVar(&cfg.AlertmanagerDiscovery, "ruler.alertmanager-discovery", false, "Use DNS SRV records to discover Alertmanager hosts.") f.DurationVar(&cfg.AlertmanagerRefreshInterval, "ruler.alertmanager-refresh-interval", 1*time.Minute, "How long to wait between refreshing DNS resolutions of Alertmanager hosts.") - f.BoolVar(&cfg.AlertmanangerEnableV2API, "ruler.alertmanager-use-v2", false, "If enabled requests to Alertmanager will utilize the V2 API.") f.IntVar(&cfg.NotificationQueueCapacity, "ruler.notification-queue-capacity", 10000, "Capacity of the queue for notifications to be sent to the Alertmanager.") f.DurationVar(&cfg.NotificationTimeout, "ruler.notification-timeout", 10*time.Second, "HTTP timeout duration when sending notifications to the Alertmanager.") diff --git a/vendor/cloud.google.com/go/compute/internal/version.go b/vendor/cloud.google.com/go/compute/internal/version.go index 540ad16ac4..27a1970b9d 100644 --- a/vendor/cloud.google.com/go/compute/internal/version.go +++ b/vendor/cloud.google.com/go/compute/internal/version.go @@ -15,4 +15,4 @@ package internal // Version is the current tagged release of the library. -const Version = "1.23.3" +const Version = "1.23.4" diff --git a/vendor/cloud.google.com/go/iam/CHANGES.md b/vendor/cloud.google.com/go/iam/CHANGES.md index c4cacb03f8..43a1793848 100644 --- a/vendor/cloud.google.com/go/iam/CHANGES.md +++ b/vendor/cloud.google.com/go/iam/CHANGES.md @@ -1,6 +1,13 @@ # Changes +## [1.1.6](https://github.com/googleapis/google-cloud-go/compare/iam/v1.1.5...iam/v1.1.6) (2024-01-30) + + +### Bug Fixes + +* **iam:** Enable universe domain resolution options ([fd1d569](https://github.com/googleapis/google-cloud-go/commit/fd1d56930fa8a747be35a224611f4797b8aeb698)) + ## [1.1.5](https://github.com/googleapis/google-cloud-go/compare/iam/v1.1.4...iam/v1.1.5) (2023-11-01) diff --git a/vendor/cloud.google.com/go/iam/apiv1/iampb/iam_policy.pb.go b/vendor/cloud.google.com/go/iam/apiv1/iampb/iam_policy.pb.go index 85346a891d..b5243e6129 100644 --- a/vendor/cloud.google.com/go/iam/apiv1/iampb/iam_policy.pb.go +++ b/vendor/cloud.google.com/go/iam/apiv1/iampb/iam_policy.pb.go @@ -14,7 +14,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 +// protoc-gen-go v1.32.0 // protoc v4.23.2 // source: google/iam/v1/iam_policy.proto diff --git a/vendor/cloud.google.com/go/iam/apiv1/iampb/options.pb.go b/vendor/cloud.google.com/go/iam/apiv1/iampb/options.pb.go index 68f8d761f7..3f854fe496 100644 --- a/vendor/cloud.google.com/go/iam/apiv1/iampb/options.pb.go +++ b/vendor/cloud.google.com/go/iam/apiv1/iampb/options.pb.go @@ -14,7 +14,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 +// protoc-gen-go v1.32.0 // protoc v4.23.2 // source: google/iam/v1/options.proto diff --git a/vendor/cloud.google.com/go/iam/apiv1/iampb/policy.pb.go b/vendor/cloud.google.com/go/iam/apiv1/iampb/policy.pb.go index eefd1d0e54..dfc60661a3 100644 --- a/vendor/cloud.google.com/go/iam/apiv1/iampb/policy.pb.go +++ b/vendor/cloud.google.com/go/iam/apiv1/iampb/policy.pb.go @@ -14,7 +14,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 +// protoc-gen-go v1.32.0 // protoc v4.23.2 // source: google/iam/v1/policy.proto @@ -289,11 +289,11 @@ type Policy struct { // Any operation that affects conditional role bindings must specify version // `3`. This requirement applies to the following operations: // - // * Getting a policy that includes a conditional role binding - // * Adding a conditional role binding to a policy - // * Changing a conditional role binding in a policy - // * Removing any role binding, with or without a condition, from a policy - // that includes conditions + // - Getting a policy that includes a conditional role binding + // - Adding a conditional role binding to a policy + // - Changing a conditional role binding in a policy + // - Removing any role binding, with or without a condition, from a policy + // that includes conditions // // **Important:** If you use IAM Conditions, you must include the `etag` field // whenever you call `setIamPolicy`. If you omit this field, then IAM allows @@ -407,47 +407,43 @@ type Binding struct { // Specifies the principals requesting access for a Google Cloud resource. // `members` can have the following values: // - // * `allUsers`: A special identifier that represents anyone who is - // on the internet; with or without a Google account. + // - `allUsers`: A special identifier that represents anyone who is + // on the internet; with or without a Google account. // - // * `allAuthenticatedUsers`: A special identifier that represents anyone - // who is authenticated with a Google account or a service account. + // - `allAuthenticatedUsers`: A special identifier that represents anyone + // who is authenticated with a Google account or a service account. // - // * `user:{emailid}`: An email address that represents a specific Google - // account. For example, `alice@example.com` . + // - `user:{emailid}`: An email address that represents a specific Google + // account. For example, `alice@example.com` . // + // - `serviceAccount:{emailid}`: An email address that represents a service + // account. For example, `my-other-app@appspot.gserviceaccount.com`. // - // * `serviceAccount:{emailid}`: An email address that represents a service - // account. For example, `my-other-app@appspot.gserviceaccount.com`. + // - `group:{emailid}`: An email address that represents a Google group. + // For example, `admins@example.com`. // - // * `group:{emailid}`: An email address that represents a Google group. - // For example, `admins@example.com`. + // - `deleted:user:{emailid}?uid={uniqueid}`: An email address (plus unique + // identifier) representing a user that has been recently deleted. For + // example, `alice@example.com?uid=123456789012345678901`. If the user is + // recovered, this value reverts to `user:{emailid}` and the recovered user + // retains the role in the binding. // - // * `deleted:user:{emailid}?uid={uniqueid}`: An email address (plus unique - // identifier) representing a user that has been recently deleted. For - // example, `alice@example.com?uid=123456789012345678901`. If the user is - // recovered, this value reverts to `user:{emailid}` and the recovered user - // retains the role in the binding. - // - // * `deleted:serviceAccount:{emailid}?uid={uniqueid}`: An email address (plus - // unique identifier) representing a service account that has been recently - // deleted. For example, - // `my-other-app@appspot.gserviceaccount.com?uid=123456789012345678901`. - // If the service account is undeleted, this value reverts to - // `serviceAccount:{emailid}` and the undeleted service account retains the - // role in the binding. - // - // * `deleted:group:{emailid}?uid={uniqueid}`: An email address (plus unique - // identifier) representing a Google group that has been recently - // deleted. For example, `admins@example.com?uid=123456789012345678901`. If - // the group is recovered, this value reverts to `group:{emailid}` and the - // recovered group retains the role in the binding. - // - // - // * `domain:{domain}`: The G Suite domain (primary) that represents all the - // users of that domain. For example, `google.com` or `example.com`. + // - `deleted:serviceAccount:{emailid}?uid={uniqueid}`: An email address (plus + // unique identifier) representing a service account that has been recently + // deleted. For example, + // `my-other-app@appspot.gserviceaccount.com?uid=123456789012345678901`. + // If the service account is undeleted, this value reverts to + // `serviceAccount:{emailid}` and the undeleted service account retains the + // role in the binding. // + // - `deleted:group:{emailid}?uid={uniqueid}`: An email address (plus unique + // identifier) representing a Google group that has been recently + // deleted. For example, `admins@example.com?uid=123456789012345678901`. If + // the group is recovered, this value reverts to `group:{emailid}` and the + // recovered group retains the role in the binding. // + // - `domain:{domain}`: The G Suite domain (primary) that represents all the + // users of that domain. For example, `google.com` or `example.com`. Members []string `protobuf:"bytes,2,rep,name=members,proto3" json:"members,omitempty"` // The condition that is associated with this binding. // diff --git a/vendor/cloud.google.com/go/internal/.repo-metadata-full.json b/vendor/cloud.google.com/go/internal/.repo-metadata-full.json index 46c4094d3b..ae8a1fc146 100644 --- a/vendor/cloud.google.com/go/internal/.repo-metadata-full.json +++ b/vendor/cloud.google.com/go/internal/.repo-metadata-full.json @@ -29,6 +29,26 @@ "release_level": "stable", "library_type": "GAPIC_AUTO" }, + "cloud.google.com/go/ai/generativelanguage/apiv1": { + "api_shortname": "generativelanguage", + "distribution_name": "cloud.google.com/go/ai/generativelanguage/apiv1", + "description": "Generative Language API", + "language": "go", + "client_library_type": "generated", + "client_documentation": "https://cloud.google.com/go/docs/reference/cloud.google.com/go/ai/latest/generativelanguage/apiv1", + "release_level": "preview", + "library_type": "GAPIC_AUTO" + }, + "cloud.google.com/go/ai/generativelanguage/apiv1beta": { + "api_shortname": "generativelanguage", + "distribution_name": "cloud.google.com/go/ai/generativelanguage/apiv1beta", + "description": "Generative Language API", + "language": "go", + "client_library_type": "generated", + "client_documentation": "https://cloud.google.com/go/docs/reference/cloud.google.com/go/ai/latest/generativelanguage/apiv1beta", + "release_level": "preview", + "library_type": "GAPIC_AUTO" + }, "cloud.google.com/go/ai/generativelanguage/apiv1beta2": { "api_shortname": "generativelanguage", "distribution_name": "cloud.google.com/go/ai/generativelanguage/apiv1beta2", @@ -179,6 +199,16 @@ "release_level": "stable", "library_type": "GAPIC_AUTO" }, + "cloud.google.com/go/apps/meet/apiv2beta": { + "api_shortname": "meet", + "distribution_name": "cloud.google.com/go/apps/meet/apiv2beta", + "description": "Google Meet API", + "language": "go", + "client_library_type": "generated", + "client_documentation": "https://cloud.google.com/go/docs/reference/cloud.google.com/go/apps/latest/meet/apiv2beta", + "release_level": "preview", + "library_type": "GAPIC_AUTO" + }, "cloud.google.com/go/area120/tables/apiv1alpha1": { "api_shortname": "area120tables", "distribution_name": "cloud.google.com/go/area120/tables/apiv1alpha1", @@ -629,6 +659,16 @@ "release_level": "preview", "library_type": "GAPIC_AUTO" }, + "cloud.google.com/go/cloudquotas/apiv1": { + "api_shortname": "cloudquotas", + "distribution_name": "cloud.google.com/go/cloudquotas/apiv1", + "description": "Cloud Quotas API", + "language": "go", + "client_library_type": "generated", + "client_documentation": "https://cloud.google.com/go/docs/reference/cloud.google.com/go/cloudquotas/latest/apiv1", + "release_level": "preview", + "library_type": "GAPIC_AUTO" + }, "cloud.google.com/go/cloudtasks/apiv2": { "api_shortname": "cloudtasks", "distribution_name": "cloud.google.com/go/cloudtasks/apiv2", @@ -969,6 +1009,16 @@ "release_level": "stable", "library_type": "GAPIC_AUTO" }, + "cloud.google.com/go/discoveryengine/apiv1alpha": { + "api_shortname": "discoveryengine", + "distribution_name": "cloud.google.com/go/discoveryengine/apiv1alpha", + "description": "Discovery Engine API", + "language": "go", + "client_library_type": "generated", + "client_documentation": "https://cloud.google.com/go/docs/reference/cloud.google.com/go/discoveryengine/latest/apiv1alpha", + "release_level": "preview", + "library_type": "GAPIC_AUTO" + }, "cloud.google.com/go/discoveryengine/apiv1beta": { "api_shortname": "discoveryengine", "distribution_name": "cloud.google.com/go/discoveryengine/apiv1beta", @@ -2099,6 +2149,16 @@ "release_level": "preview", "library_type": "GAPIC_AUTO" }, + "cloud.google.com/go/securitycentermanagement/apiv1": { + "api_shortname": "securitycentermanagement", + "distribution_name": "cloud.google.com/go/securitycentermanagement/apiv1", + "description": "Security Center Management API", + "language": "go", + "client_library_type": "generated", + "client_documentation": "https://cloud.google.com/go/docs/reference/cloud.google.com/go/securitycentermanagement/latest/apiv1", + "release_level": "preview", + "library_type": "GAPIC_AUTO" + }, "cloud.google.com/go/servicecontrol/apiv1": { "api_shortname": "servicecontrol", "distribution_name": "cloud.google.com/go/servicecontrol/apiv1", @@ -2159,6 +2219,16 @@ "release_level": "stable", "library_type": "GAPIC_AUTO" }, + "cloud.google.com/go/shopping/css/apiv1": { + "api_shortname": "css", + "distribution_name": "cloud.google.com/go/shopping/css/apiv1", + "description": "CSS API", + "language": "go", + "client_library_type": "generated", + "client_documentation": "https://cloud.google.com/go/docs/reference/cloud.google.com/go/shopping/latest/css/apiv1", + "release_level": "preview", + "library_type": "GAPIC_AUTO" + }, "cloud.google.com/go/shopping/merchant/inventories/apiv1beta": { "api_shortname": "merchantapi", "distribution_name": "cloud.google.com/go/shopping/merchant/inventories/apiv1beta", @@ -2209,6 +2279,16 @@ "release_level": "stable", "library_type": "GAPIC_AUTO" }, + "cloud.google.com/go/spanner/executor/apiv1": { + "api_shortname": "spanner-cloud-executor", + "distribution_name": "cloud.google.com/go/spanner/executor/apiv1", + "description": "Cloud Spanner Executor test API", + "language": "go", + "client_library_type": "generated", + "client_documentation": "https://cloud.google.com/go/docs/reference/cloud.google.com/go/spanner/latest/executor/apiv1", + "release_level": "preview", + "library_type": "GAPIC_AUTO" + }, "cloud.google.com/go/speech/apiv1": { "api_shortname": "speech", "distribution_name": "cloud.google.com/go/speech/apiv1", diff --git a/vendor/cloud.google.com/go/internal/trace/trace.go b/vendor/cloud.google.com/go/internal/trace/trace.go index f6b88253b4..eabed000f3 100644 --- a/vendor/cloud.google.com/go/internal/trace/trace.go +++ b/vendor/cloud.google.com/go/internal/trace/trace.go @@ -32,16 +32,33 @@ import ( ) const ( - telemetryPlatformTracingOpenCensus = "opencensus" - telemetryPlatformTracingOpenTelemetry = "opentelemetry" - telemetryPlatformTracingVar = "GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING" + // TelemetryPlatformTracingOpenCensus is the value to which the environment + // variable GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING should be + // set to enable OpenCensus tracing. + TelemetryPlatformTracingOpenCensus = "opencensus" + // TelemetryPlatformTracingOpenCensus is the value to which the environment + // variable GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING should be + // set to enable OpenTelemetry tracing. + TelemetryPlatformTracingOpenTelemetry = "opentelemetry" + // TelemetryPlatformTracingOpenCensus is the name of the environment + // variable that can be set to change the default tracing from OpenCensus + // to OpenTelemetry. + TelemetryPlatformTracingVar = "GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING" + // OpenTelemetryTracerName is the name given to the OpenTelemetry Tracer + // when it is obtained from the OpenTelemetry TracerProvider. + OpenTelemetryTracerName = "cloud.google.com/go" ) var ( - // TODO(chrisdsmith): Should the name of the OpenTelemetry tracer be public and mutable? - openTelemetryTracerName string = "cloud.google.com/go" - openTelemetryTracingEnabled bool = strings.EqualFold(strings.TrimSpace( - os.Getenv(telemetryPlatformTracingVar)), telemetryPlatformTracingOpenTelemetry) + // OpenTelemetryTracingEnabled is true if the environment variable + // GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING is set to the + // case-insensitive value "opentelemetry". + // + // Do not access directly. Use instead IsOpenTelemetryTracingEnabled or + // IsOpenCensusTracingEnabled. Intended for use only in unit tests. Restore + // original value after each test. + OpenTelemetryTracingEnabled bool = strings.EqualFold(strings.TrimSpace( + os.Getenv(TelemetryPlatformTracingVar)), TelemetryPlatformTracingOpenTelemetry) ) // IsOpenCensusTracingEnabled returns true if the environment variable @@ -55,7 +72,7 @@ func IsOpenCensusTracingEnabled() bool { // GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING is set to the // case-insensitive value "opentelemetry". func IsOpenTelemetryTracingEnabled() bool { - return openTelemetryTracingEnabled + return OpenTelemetryTracingEnabled } // StartSpan adds a span to the trace with the given name. If IsOpenCensusTracingEnabled @@ -63,12 +80,12 @@ func IsOpenTelemetryTracingEnabled() bool { // returns true, the span will be an OpenTelemetry span. Set the environment variable // GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING to the case-insensitive // value "opentelemetry" before loading the package to use OpenTelemetry tracing. -// The default will remain OpenCensus until [TBD], at which time the default will +// The default will remain OpenCensus until May 29, 2024, at which time the default will // switch to "opentelemetry" and explicitly setting the environment variable to // "opencensus" will be required to continue using OpenCensus tracing. func StartSpan(ctx context.Context, name string) context.Context { if IsOpenTelemetryTracingEnabled() { - ctx, _ = otel.GetTracerProvider().Tracer(openTelemetryTracerName).Start(ctx, name) + ctx, _ = otel.GetTracerProvider().Tracer(OpenTelemetryTracerName).Start(ctx, name) } else { ctx, _ = trace.StartSpan(ctx, name) } @@ -80,7 +97,7 @@ func StartSpan(ctx context.Context, name string) context.Context { // returns true, the span will be an OpenTelemetry span. Set the environment variable // GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING to the case-insensitive // value "opentelemetry" before loading the package to use OpenTelemetry tracing. -// The default will remain OpenCensus until [TBD], at which time the default will +// The default will remain OpenCensus until May 29, 2024, at which time the default will // switch to "opentelemetry" and explicitly setting the environment variable to // "opencensus" will be required to continue using OpenCensus tracing. func EndSpan(ctx context.Context, err error) { @@ -166,7 +183,7 @@ func httpStatusCodeToOCCode(httpStatusCode int) int32 { // span must be an OpenTelemetry span. Set the environment variable // GOOGLE_API_GO_EXPERIMENTAL_TELEMETRY_PLATFORM_TRACING to the case-insensitive // value "opentelemetry" before loading the package to use OpenTelemetry tracing. -// The default will remain OpenCensus until [TBD], at which time the default will +// The default will remain OpenCensus until May 29, 2024, at which time the default will // switch to "opentelemetry" and explicitly setting the environment variable to // "opencensus" will be required to continue using OpenCensus tracing. func TracePrintf(ctx context.Context, attrMap map[string]interface{}, format string, args ...interface{}) { diff --git a/vendor/cloud.google.com/go/storage/CHANGES.md b/vendor/cloud.google.com/go/storage/CHANGES.md index 30ee040f76..8b3fa6fc48 100644 --- a/vendor/cloud.google.com/go/storage/CHANGES.md +++ b/vendor/cloud.google.com/go/storage/CHANGES.md @@ -1,6 +1,19 @@ # Changes +## [1.36.0](https://github.com/googleapis/google-cloud-go/compare/storage/v1.35.1...storage/v1.36.0) (2023-12-14) + + +### Features + +* **storage:** Add object retention feature ([#9072](https://github.com/googleapis/google-cloud-go/issues/9072)) ([16ecfd1](https://github.com/googleapis/google-cloud-go/commit/16ecfd150ff1982f03d207a80a82e934d1013874)) + + +### Bug Fixes + +* **storage:** Do not inhibit the dead code elimination. ([#8543](https://github.com/googleapis/google-cloud-go/issues/8543)) ([ca2493f](https://github.com/googleapis/google-cloud-go/commit/ca2493f43c299bbaed5f7e5b70f66cc763ff9802)) +* **storage:** Set flush and get_state to false on the last write in gRPC ([#9013](https://github.com/googleapis/google-cloud-go/issues/9013)) ([c1e9fe5](https://github.com/googleapis/google-cloud-go/commit/c1e9fe5f4166a71e55814ccf126926ec0e0e7945)) + ## [1.35.1](https://github.com/googleapis/google-cloud-go/compare/storage/v1.35.0...storage/v1.35.1) (2023-11-09) diff --git a/vendor/cloud.google.com/go/storage/bucket.go b/vendor/cloud.google.com/go/storage/bucket.go index 3818c4498c..1059d4e8b7 100644 --- a/vendor/cloud.google.com/go/storage/bucket.go +++ b/vendor/cloud.google.com/go/storage/bucket.go @@ -41,13 +41,14 @@ import ( // BucketHandle provides operations on a Google Cloud Storage bucket. // Use Client.Bucket to get a handle. type BucketHandle struct { - c *Client - name string - acl ACLHandle - defaultObjectACL ACLHandle - conds *BucketConditions - userProject string // project for Requester Pays buckets - retry *retryConfig + c *Client + name string + acl ACLHandle + defaultObjectACL ACLHandle + conds *BucketConditions + userProject string // project for Requester Pays buckets + retry *retryConfig + enableObjectRetention *bool } // Bucket returns a BucketHandle, which provides operations on the named bucket. @@ -85,7 +86,8 @@ func (b *BucketHandle) Create(ctx context.Context, projectID string, attrs *Buck defer func() { trace.EndSpan(ctx, err) }() o := makeStorageOpts(true, b.retry, b.userProject) - if _, err := b.c.tc.CreateBucket(ctx, projectID, b.name, attrs, o...); err != nil { + + if _, err := b.c.tc.CreateBucket(ctx, projectID, b.name, attrs, b.enableObjectRetention, o...); err != nil { return err } return nil @@ -462,6 +464,15 @@ type BucketAttrs struct { // allows for the automatic selection of the best storage class // based on object access patterns. Autoclass *Autoclass + + // ObjectRetentionMode reports whether individual objects in the bucket can + // be configured with a retention policy. An empty value means that object + // retention is disabled. + // This field is read-only. Object retention can be enabled only by creating + // a bucket with SetObjectRetention set to true on the BucketHandle. It + // cannot be modified once the bucket is created. + // ObjectRetention cannot be configured or reported through the gRPC API. + ObjectRetentionMode string } // BucketPolicyOnly is an alias for UniformBucketLevelAccess. @@ -757,6 +768,7 @@ func newBucket(b *raw.Bucket) (*BucketAttrs, error) { if err != nil { return nil, err } + return &BucketAttrs{ Name: b.Name, Location: b.Location, @@ -771,6 +783,7 @@ func newBucket(b *raw.Bucket) (*BucketAttrs, error) { RequesterPays: b.Billing != nil && b.Billing.RequesterPays, Lifecycle: toLifecycle(b.Lifecycle), RetentionPolicy: rp, + ObjectRetentionMode: toBucketObjectRetention(b.ObjectRetention), CORS: toCORS(b.Cors), Encryption: toBucketEncryption(b.Encryption), Logging: toBucketLogging(b.Logging), @@ -1348,6 +1361,17 @@ func (b *BucketHandle) LockRetentionPolicy(ctx context.Context) error { return b.c.tc.LockBucketRetentionPolicy(ctx, b.name, b.conds, o...) } +// SetObjectRetention returns a new BucketHandle that will enable object retention +// on bucket creation. To enable object retention, you must use the returned +// handle to create the bucket. This has no effect on an already existing bucket. +// ObjectRetention is not enabled by default. +// ObjectRetention cannot be configured through the gRPC API. +func (b *BucketHandle) SetObjectRetention(enable bool) *BucketHandle { + b2 := *b + b2.enableObjectRetention = &enable + return &b2 +} + // applyBucketConds modifies the provided call using the conditions in conds. // call is something that quacks like a *raw.WhateverCall. func applyBucketConds(method string, conds *BucketConditions, call interface{}) error { @@ -1360,11 +1384,11 @@ func applyBucketConds(method string, conds *BucketConditions, call interface{}) cval := reflect.ValueOf(call) switch { case conds.MetagenerationMatch != 0: - if !setConditionField(cval, "IfMetagenerationMatch", conds.MetagenerationMatch) { + if !setIfMetagenerationMatch(cval, conds.MetagenerationMatch) { return fmt.Errorf("storage: %s: ifMetagenerationMatch not supported", method) } case conds.MetagenerationNotMatch != 0: - if !setConditionField(cval, "IfMetagenerationNotMatch", conds.MetagenerationNotMatch) { + if !setIfMetagenerationNotMatch(cval, conds.MetagenerationNotMatch) { return fmt.Errorf("storage: %s: ifMetagenerationNotMatch not supported", method) } } @@ -1447,6 +1471,13 @@ func toRetentionPolicyFromProto(rp *storagepb.Bucket_RetentionPolicy) *Retention } } +func toBucketObjectRetention(or *raw.BucketObjectRetention) string { + if or == nil { + return "" + } + return or.Mode +} + func toRawCORS(c []CORS) []*raw.BucketCors { var out []*raw.BucketCors for _, v := range c { diff --git a/vendor/cloud.google.com/go/storage/client.go b/vendor/cloud.google.com/go/storage/client.go index 3bed9b64c2..4906b1d1f7 100644 --- a/vendor/cloud.google.com/go/storage/client.go +++ b/vendor/cloud.google.com/go/storage/client.go @@ -44,7 +44,7 @@ type storageClient interface { // Top-level methods. GetServiceAccount(ctx context.Context, project string, opts ...storageOption) (string, error) - CreateBucket(ctx context.Context, project, bucket string, attrs *BucketAttrs, opts ...storageOption) (*BucketAttrs, error) + CreateBucket(ctx context.Context, project, bucket string, attrs *BucketAttrs, enableObjectRetention *bool, opts ...storageOption) (*BucketAttrs, error) ListBuckets(ctx context.Context, project string, opts ...storageOption) *BucketIterator Close() error @@ -60,7 +60,7 @@ type storageClient interface { DeleteObject(ctx context.Context, bucket, object string, gen int64, conds *Conditions, opts ...storageOption) error GetObject(ctx context.Context, bucket, object string, gen int64, encryptionKey []byte, conds *Conditions, opts ...storageOption) (*ObjectAttrs, error) - UpdateObject(ctx context.Context, bucket, object string, uattrs *ObjectAttrsToUpdate, gen int64, encryptionKey []byte, conds *Conditions, opts ...storageOption) (*ObjectAttrs, error) + UpdateObject(ctx context.Context, params *updateObjectParams, opts ...storageOption) (*ObjectAttrs, error) // Default Object ACL methods. @@ -291,6 +291,15 @@ type newRangeReaderParams struct { readCompressed bool // Use accept-encoding: gzip. Only works for HTTP currently. } +type updateObjectParams struct { + bucket, object string + uattrs *ObjectAttrsToUpdate + gen int64 + encryptionKey []byte + conds *Conditions + overrideRetention *bool +} + type composeObjectRequest struct { dstBucket string dstObject destinationObject diff --git a/vendor/cloud.google.com/go/storage/grpc_client.go b/vendor/cloud.google.com/go/storage/grpc_client.go index 99dfba4677..a51cf9c086 100644 --- a/vendor/cloud.google.com/go/storage/grpc_client.go +++ b/vendor/cloud.google.com/go/storage/grpc_client.go @@ -152,7 +152,12 @@ func (c *grpcStorageClient) GetServiceAccount(ctx context.Context, project strin return resp.EmailAddress, err } -func (c *grpcStorageClient) CreateBucket(ctx context.Context, project, bucket string, attrs *BucketAttrs, opts ...storageOption) (*BucketAttrs, error) { +func (c *grpcStorageClient) CreateBucket(ctx context.Context, project, bucket string, attrs *BucketAttrs, enableObjectRetention *bool, opts ...storageOption) (*BucketAttrs, error) { + if enableObjectRetention != nil { + // TO-DO: implement ObjectRetention once available - see b/308194853 + return nil, status.Errorf(codes.Unimplemented, "storage: object retention is not supported in gRPC") + } + s := callSettings(c.settings, opts...) b := attrs.toProtoBucket() b.Project = toProjectResource(project) @@ -507,25 +512,30 @@ func (c *grpcStorageClient) GetObject(ctx context.Context, bucket, object string return attrs, err } -func (c *grpcStorageClient) UpdateObject(ctx context.Context, bucket, object string, uattrs *ObjectAttrsToUpdate, gen int64, encryptionKey []byte, conds *Conditions, opts ...storageOption) (*ObjectAttrs, error) { +func (c *grpcStorageClient) UpdateObject(ctx context.Context, params *updateObjectParams, opts ...storageOption) (*ObjectAttrs, error) { + uattrs := params.uattrs + if params.overrideRetention != nil || uattrs.Retention != nil { + // TO-DO: implement ObjectRetention once available - see b/308194853 + return nil, status.Errorf(codes.Unimplemented, "storage: object retention is not supported in gRPC") + } s := callSettings(c.settings, opts...) - o := uattrs.toProtoObject(bucketResourceName(globalProjectAlias, bucket), object) + o := uattrs.toProtoObject(bucketResourceName(globalProjectAlias, params.bucket), params.object) // For Update, generation is passed via the object message rather than a field on the request. - if gen >= 0 { - o.Generation = gen + if params.gen >= 0 { + o.Generation = params.gen } req := &storagepb.UpdateObjectRequest{ Object: o, PredefinedAcl: uattrs.PredefinedACL, } - if err := applyCondsProto("grpcStorageClient.UpdateObject", defaultGen, conds, req); err != nil { + if err := applyCondsProto("grpcStorageClient.UpdateObject", defaultGen, params.conds, req); err != nil { return nil, err } if s.userProject != "" { ctx = setUserProjectMetadata(ctx, s.userProject) } - if encryptionKey != nil { - req.CommonObjectRequestParams = toProtoCommonObjectRequestParams(encryptionKey) + if params.encryptionKey != nil { + req.CommonObjectRequestParams = toProtoCommonObjectRequestParams(params.encryptionKey) } fieldMask := &fieldmaskpb.FieldMask{Paths: nil} @@ -739,7 +749,8 @@ func (c *grpcStorageClient) DeleteObjectACL(ctx context.Context, bucket, object } uattrs := &ObjectAttrsToUpdate{ACL: acl} // Call UpdateObject with the specified metageneration. - if _, err = c.UpdateObject(ctx, bucket, object, uattrs, defaultGen, nil, &Conditions{MetagenerationMatch: attrs.Metageneration}, opts...); err != nil { + params := &updateObjectParams{bucket: bucket, object: object, uattrs: uattrs, gen: defaultGen, conds: &Conditions{MetagenerationMatch: attrs.Metageneration}} + if _, err = c.UpdateObject(ctx, params, opts...); err != nil { return err } return nil @@ -769,7 +780,8 @@ func (c *grpcStorageClient) UpdateObjectACL(ctx context.Context, bucket, object acl = append(attrs.ACL, aclRule) uattrs := &ObjectAttrsToUpdate{ACL: acl} // Call UpdateObject with the specified metageneration. - if _, err = c.UpdateObject(ctx, bucket, object, uattrs, defaultGen, nil, &Conditions{MetagenerationMatch: attrs.Metageneration}, opts...); err != nil { + params := &updateObjectParams{bucket: bucket, object: object, uattrs: uattrs, gen: defaultGen, conds: &Conditions{MetagenerationMatch: attrs.Metageneration}} + if _, err = c.UpdateObject(ctx, params, opts...); err != nil { return err } return nil @@ -1049,6 +1061,13 @@ func (c *grpcStorageClient) OpenWriter(params *openWriterParams, opts ...storage return } + if params.attrs.Retention != nil { + // TO-DO: remove once ObjectRetention is available - see b/308194853 + err = status.Errorf(codes.Unimplemented, "storage: object retention is not supported in gRPC") + errorf(err) + pr.CloseWithError(err) + return + } // The chunk buffer is full, but there is no end in sight. This // means that either: // 1. A resumable upload will need to be used to send @@ -1629,8 +1648,8 @@ func (w *gRPCWriter) uploadBuffer(recvd int, start int64, doneReading bool) (*st }, WriteOffset: writeOffset, FinishWrite: lastWriteOfEntireObject, - Flush: remainingDataFitsInSingleReq, - StateLookup: remainingDataFitsInSingleReq, + Flush: remainingDataFitsInSingleReq && !lastWriteOfEntireObject, + StateLookup: remainingDataFitsInSingleReq && !lastWriteOfEntireObject, } // Open a new stream if necessary and set the first_message field on @@ -1723,32 +1742,33 @@ func (w *gRPCWriter) uploadBuffer(recvd int, start int64, doneReading bool) (*st return nil, writeOffset, nil } - // Done sending data (remainingDataFitsInSingleReq should == true if we - // reach this code). Receive from the stream to confirm the persisted data. - resp, err := w.stream.Recv() + // Done sending the data in the buffer (remainingDataFitsInSingleReq + // should == true if we reach this code). + // If we are done sending the whole object, close the stream and get the final + // object. Otherwise, receive from the stream to confirm the persisted data. + if !lastWriteOfEntireObject { + resp, err := w.stream.Recv() + + // Retriable errors mean we should start over and attempt to + // resend the entire buffer via a new stream. + // If not retriable, falling through will return the error received + // from closing the stream. + if shouldRetry(err) { + writeOffset, err = w.determineOffset(start) + if err != nil { + return nil, 0, err + } + sent = int(writeOffset) - int(start) + + // Drop the stream reference as a new one will need to be created. + w.stream = nil - // Retriable errors mean we should start over and attempt to - // resend the entire buffer via a new stream. - // If not retriable, falling through will return the error received - // from closing the stream. - if shouldRetry(err) { - writeOffset, err = w.determineOffset(start) + continue + } if err != nil { return nil, 0, err } - sent = int(writeOffset) - int(start) - - // Drop the stream reference as a new one will need to be created. - w.stream = nil - - continue - } - if err != nil { - return nil, 0, err - } - // Confirm the persisted data if we have not finished uploading the object. - if !lastWriteOfEntireObject { if resp.GetPersistedSize() != writeOffset { // Retry if not all bytes were persisted. writeOffset = resp.GetPersistedSize() diff --git a/vendor/cloud.google.com/go/storage/http_client.go b/vendor/cloud.google.com/go/storage/http_client.go index b62f009da1..0e157e4ba9 100644 --- a/vendor/cloud.google.com/go/storage/http_client.go +++ b/vendor/cloud.google.com/go/storage/http_client.go @@ -159,7 +159,7 @@ func (c *httpStorageClient) GetServiceAccount(ctx context.Context, project strin return res.EmailAddress, nil } -func (c *httpStorageClient) CreateBucket(ctx context.Context, project, bucket string, attrs *BucketAttrs, opts ...storageOption) (*BucketAttrs, error) { +func (c *httpStorageClient) CreateBucket(ctx context.Context, project, bucket string, attrs *BucketAttrs, enableObjectRetention *bool, opts ...storageOption) (*BucketAttrs, error) { s := callSettings(c.settings, opts...) var bkt *raw.Bucket if attrs != nil { @@ -181,6 +181,9 @@ func (c *httpStorageClient) CreateBucket(ctx context.Context, project, bucket st if attrs != nil && attrs.PredefinedDefaultObjectACL != "" { req.PredefinedDefaultObjectAcl(attrs.PredefinedDefaultObjectACL) } + if enableObjectRetention != nil { + req.EnableObjectRetention(*enableObjectRetention) + } var battrs *BucketAttrs err := run(ctx, func(ctx context.Context) error { b, err := req.Context(ctx).Do() @@ -431,7 +434,8 @@ func (c *httpStorageClient) GetObject(ctx context.Context, bucket, object string return newObject(obj), nil } -func (c *httpStorageClient) UpdateObject(ctx context.Context, bucket, object string, uattrs *ObjectAttrsToUpdate, gen int64, encryptionKey []byte, conds *Conditions, opts ...storageOption) (*ObjectAttrs, error) { +func (c *httpStorageClient) UpdateObject(ctx context.Context, params *updateObjectParams, opts ...storageOption) (*ObjectAttrs, error) { + uattrs := params.uattrs s := callSettings(c.settings, opts...) var attrs ObjectAttrs @@ -496,11 +500,21 @@ func (c *httpStorageClient) UpdateObject(ctx context.Context, bucket, object str // we don't append to nullFields here. forceSendFields = append(forceSendFields, "Acl") } - rawObj := attrs.toRawObject(bucket) + if uattrs.Retention != nil { + // For ObjectRetention it's an error to send empty fields. + // Instead we send a null as the user's intention is to remove. + if uattrs.Retention.Mode == "" && uattrs.Retention.RetainUntil.IsZero() { + nullFields = append(nullFields, "Retention") + } else { + attrs.Retention = uattrs.Retention + forceSendFields = append(forceSendFields, "Retention") + } + } + rawObj := attrs.toRawObject(params.bucket) rawObj.ForceSendFields = forceSendFields rawObj.NullFields = nullFields - call := c.raw.Objects.Patch(bucket, object, rawObj).Projection("full") - if err := applyConds("Update", gen, conds, call); err != nil { + call := c.raw.Objects.Patch(params.bucket, params.object, rawObj).Projection("full") + if err := applyConds("Update", params.gen, params.conds, call); err != nil { return nil, err } if s.userProject != "" { @@ -509,9 +523,14 @@ func (c *httpStorageClient) UpdateObject(ctx context.Context, bucket, object str if uattrs.PredefinedACL != "" { call.PredefinedAcl(uattrs.PredefinedACL) } - if err := setEncryptionHeaders(call.Header(), encryptionKey, false); err != nil { + if err := setEncryptionHeaders(call.Header(), params.encryptionKey, false); err != nil { return nil, err } + + if params.overrideRetention != nil { + call.OverrideUnlockedRetention(*params.overrideRetention) + } + var obj *raw.Object var err error err = run(ctx, func(ctx context.Context) error { obj, err = call.Context(ctx).Do(); return err }, s.retry, s.idempotent) diff --git a/vendor/cloud.google.com/go/storage/internal/version.go b/vendor/cloud.google.com/go/storage/internal/version.go index eca9b294aa..2d5cf890e0 100644 --- a/vendor/cloud.google.com/go/storage/internal/version.go +++ b/vendor/cloud.google.com/go/storage/internal/version.go @@ -15,4 +15,4 @@ package internal // Version is the current tagged release of the library. -const Version = "1.35.1" +const Version = "1.36.0" diff --git a/vendor/cloud.google.com/go/storage/storage.go b/vendor/cloud.google.com/go/storage/storage.go index a16e512f5e..78ecbf0e89 100644 --- a/vendor/cloud.google.com/go/storage/storage.go +++ b/vendor/cloud.google.com/go/storage/storage.go @@ -879,16 +879,17 @@ func signedURLV2(bucket, name string, opts *SignedURLOptions) (string, error) { // ObjectHandle provides operations on an object in a Google Cloud Storage bucket. // Use BucketHandle.Object to get a handle. type ObjectHandle struct { - c *Client - bucket string - object string - acl ACLHandle - gen int64 // a negative value indicates latest - conds *Conditions - encryptionKey []byte // AES-256 key - userProject string // for requester-pays buckets - readCompressed bool // Accept-Encoding: gzip - retry *retryConfig + c *Client + bucket string + object string + acl ACLHandle + gen int64 // a negative value indicates latest + conds *Conditions + encryptionKey []byte // AES-256 key + userProject string // for requester-pays buckets + readCompressed bool // Accept-Encoding: gzip + retry *retryConfig + overrideRetention *bool } // ACL provides access to the object's access control list. @@ -958,7 +959,15 @@ func (o *ObjectHandle) Update(ctx context.Context, uattrs ObjectAttrsToUpdate) ( } isIdempotent := o.conds != nil && o.conds.MetagenerationMatch != 0 opts := makeStorageOpts(isIdempotent, o.retry, o.userProject) - return o.c.tc.UpdateObject(ctx, o.bucket, o.object, &uattrs, o.gen, o.encryptionKey, o.conds, opts...) + return o.c.tc.UpdateObject(ctx, + &updateObjectParams{ + bucket: o.bucket, + object: o.object, + uattrs: &uattrs, + gen: o.gen, + encryptionKey: o.encryptionKey, + conds: o.conds, + overrideRetention: o.overrideRetention}, opts...) } // BucketName returns the name of the bucket. @@ -973,16 +982,19 @@ func (o *ObjectHandle) ObjectName() string { // ObjectAttrsToUpdate is used to update the attributes of an object. // Only fields set to non-nil values will be updated. -// For all fields except CustomTime, set the field to its zero value to delete -// it. CustomTime cannot be deleted or changed to an earlier time once set. +// For all fields except CustomTime and Retention, set the field to its zero +// value to delete it. CustomTime cannot be deleted or changed to an earlier +// time once set. Retention can be deleted (only if the Mode is Unlocked) by +// setting it to an empty value (not nil). // -// For example, to change ContentType and delete ContentEncoding and -// Metadata, use +// For example, to change ContentType and delete ContentEncoding, Metadata and +// Retention, use: // // ObjectAttrsToUpdate{ // ContentType: "text/html", // ContentEncoding: "", // Metadata: map[string]string{}, +// Retention: &ObjectRetention{}, // } type ObjectAttrsToUpdate struct { EventBasedHold optional.Bool @@ -999,6 +1011,12 @@ type ObjectAttrsToUpdate struct { // If not empty, applies a predefined set of access controls. ACL must be nil. // See https://cloud.google.com/storage/docs/json_api/v1/objects/patch. PredefinedACL string + + // Retention contains the retention configuration for this object. + // Operations other than setting the retention for the first time or + // extending the RetainUntil time on the object retention must be done + // on an ObjectHandle with OverrideUnlockedRetention set to true. + Retention *ObjectRetention } // Delete deletes the single specified object. @@ -1020,6 +1038,17 @@ func (o *ObjectHandle) ReadCompressed(compressed bool) *ObjectHandle { return &o2 } +// OverrideUnlockedRetention provides an option for overriding an Unlocked +// Retention policy. This must be set to true in order to change a policy +// from Unlocked to Locked, to set it to null, or to reduce its +// RetainUntil attribute. It is not required for setting the ObjectRetention for +// the first time nor for extending the RetainUntil time. +func (o *ObjectHandle) OverrideUnlockedRetention(override bool) *ObjectHandle { + o2 := *o + o2.overrideRetention = &override + return &o2 +} + // NewWriter returns a storage Writer that writes to the GCS object // associated with this ObjectHandle. // @@ -1109,6 +1138,7 @@ func (o *ObjectAttrs) toRawObject(bucket string) *raw.Object { Acl: toRawObjectACL(o.ACL), Metadata: o.Metadata, CustomTime: ct, + Retention: o.Retention.toRawObjectRetention(), } } @@ -1344,6 +1374,42 @@ type ObjectAttrs struct { // For non-composite objects, the value will be zero. // This field is read-only. ComponentCount int64 + + // Retention contains the retention configuration for this object. + // ObjectRetention cannot be configured or reported through the gRPC API. + Retention *ObjectRetention +} + +// ObjectRetention contains the retention configuration for this object. +type ObjectRetention struct { + // Mode is the retention policy's mode on this object. Valid values are + // "Locked" and "Unlocked". + // Locked retention policies cannot be changed. Unlocked policies require an + // override to change. + Mode string + + // RetainUntil is the time this object will be retained until. + RetainUntil time.Time +} + +func (r *ObjectRetention) toRawObjectRetention() *raw.ObjectRetention { + if r == nil { + return nil + } + return &raw.ObjectRetention{ + Mode: r.Mode, + RetainUntilTime: r.RetainUntil.Format(time.RFC3339), + } +} + +func toObjectRetention(r *raw.ObjectRetention) *ObjectRetention { + if r == nil { + return nil + } + return &ObjectRetention{ + Mode: r.Mode, + RetainUntil: convertTime(r.RetainUntilTime), + } } // convertTime converts a time in RFC3339 format to time.Time. @@ -1415,6 +1481,7 @@ func newObject(o *raw.Object) *ObjectAttrs { Etag: o.Etag, CustomTime: convertTime(o.CustomTime), ComponentCount: o.ComponentCount, + Retention: toObjectRetention(o.Retention), } } @@ -1587,6 +1654,7 @@ var attrToFieldMap = map[string]string{ "Etag": "etag", "CustomTime": "customTime", "ComponentCount": "componentCount", + "Retention": "retention", } // attrToProtoFieldMap maps the field names of ObjectAttrs to the underlying field @@ -1621,6 +1689,7 @@ var attrToProtoFieldMap = map[string]string{ "ComponentCount": "component_count", // MediaLink was explicitly excluded from the proto as it is an HTTP-ism. // "MediaLink": "mediaLink", + // TODO: add object retention - b/308194853 } // SetAttrSelection makes the query populate only specific attributes of @@ -1806,7 +1875,7 @@ func (c *Conditions) isMetagenerationValid() bool { func applyConds(method string, gen int64, conds *Conditions, call interface{}) error { cval := reflect.ValueOf(call) if gen >= 0 { - if !setConditionField(cval, "Generation", gen) { + if !setGeneration(cval, gen) { return fmt.Errorf("storage: %s: generation not supported", method) } } @@ -1818,25 +1887,25 @@ func applyConds(method string, gen int64, conds *Conditions, call interface{}) e } switch { case conds.GenerationMatch != 0: - if !setConditionField(cval, "IfGenerationMatch", conds.GenerationMatch) { + if !setIfGenerationMatch(cval, conds.GenerationMatch) { return fmt.Errorf("storage: %s: ifGenerationMatch not supported", method) } case conds.GenerationNotMatch != 0: - if !setConditionField(cval, "IfGenerationNotMatch", conds.GenerationNotMatch) { + if !setIfGenerationNotMatch(cval, conds.GenerationNotMatch) { return fmt.Errorf("storage: %s: ifGenerationNotMatch not supported", method) } case conds.DoesNotExist: - if !setConditionField(cval, "IfGenerationMatch", int64(0)) { + if !setIfGenerationMatch(cval, int64(0)) { return fmt.Errorf("storage: %s: DoesNotExist not supported", method) } } switch { case conds.MetagenerationMatch != 0: - if !setConditionField(cval, "IfMetagenerationMatch", conds.MetagenerationMatch) { + if !setIfMetagenerationMatch(cval, conds.MetagenerationMatch) { return fmt.Errorf("storage: %s: ifMetagenerationMatch not supported", method) } case conds.MetagenerationNotMatch != 0: - if !setConditionField(cval, "IfMetagenerationNotMatch", conds.MetagenerationNotMatch) { + if !setIfMetagenerationNotMatch(cval, conds.MetagenerationNotMatch) { return fmt.Errorf("storage: %s: ifMetagenerationNotMatch not supported", method) } } @@ -1897,16 +1966,45 @@ func applySourceCondsProto(gen int64, conds *Conditions, call *storagepb.Rewrite return nil } -// setConditionField sets a field on a *raw.WhateverCall. +// setGeneration sets Generation on a *raw.WhateverCall. // We can't use anonymous interfaces because the return type is // different, since the field setters are builders. -func setConditionField(call reflect.Value, name string, value interface{}) bool { - m := call.MethodByName(name) - if !m.IsValid() { - return false +// We also make sure to supply a compile-time constant to MethodByName; +// otherwise, the Go Linker will disable dead code elimination, leading +// to larger binaries for all packages that import storage. +func setGeneration(cval reflect.Value, value interface{}) bool { + return setCondition(cval.MethodByName("Generation"), value) +} + +// setIfGenerationMatch sets IfGenerationMatch on a *raw.WhateverCall. +// See also setGeneration. +func setIfGenerationMatch(cval reflect.Value, value interface{}) bool { + return setCondition(cval.MethodByName("IfGenerationMatch"), value) +} + +// setIfGenerationNotMatch sets IfGenerationNotMatch on a *raw.WhateverCall. +// See also setGeneration. +func setIfGenerationNotMatch(cval reflect.Value, value interface{}) bool { + return setCondition(cval.MethodByName("IfGenerationNotMatch"), value) +} + +// setIfMetagenerationMatch sets IfMetagenerationMatch on a *raw.WhateverCall. +// See also setGeneration. +func setIfMetagenerationMatch(cval reflect.Value, value interface{}) bool { + return setCondition(cval.MethodByName("IfMetagenerationMatch"), value) +} + +// setIfMetagenerationNotMatch sets IfMetagenerationNotMatch on a *raw.WhateverCall. +// See also setGeneration. +func setIfMetagenerationNotMatch(cval reflect.Value, value interface{}) bool { + return setCondition(cval.MethodByName("IfMetagenerationNotMatch"), value) +} + +func setCondition(setter reflect.Value, value interface{}) bool { + if setter.IsValid() { + setter.Call([]reflect.Value{reflect.ValueOf(value)}) } - m.Call([]reflect.Value{reflect.ValueOf(value)}) - return true + return setter.IsValid() } // Retryer returns an object handle that is configured with custom retry diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md index 7a0a524e33..bf0c3e1aac 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/CHANGELOG.md @@ -1,5 +1,22 @@ # Release History +## 1.10.0 (2024-02-29) + +### Features Added + +* Added logging event `log.EventResponseError` that will contain the contents of `ResponseError.Error()` whenever an `azcore.ResponseError` is created. +* Added `runtime.NewResponseErrorWithErrorCode` for creating an `azcore.ResponseError` with a caller-supplied error code. +* Added type `MatchConditions` for use in conditional requests. + +### Bugs Fixed + +* Fixed a potential race condition between `NullValue` and `IsNullValue`. +* `runtime.EncodeQueryParams` will escape semicolons before calling `url.ParseQuery`. + +### Other Changes + +* Update dependencies. + ## 1.9.2 (2024-02-06) ### Bugs Fixed diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/core.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/core.go index 8eef8633a7..9d1c2f0c05 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/core.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/core.go @@ -8,6 +8,7 @@ package azcore import ( "reflect" + "sync" "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported" "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared" @@ -41,13 +42,28 @@ func NewSASCredential(sas string) *SASCredential { } // holds sentinel values used to send nulls -var nullables map[reflect.Type]interface{} = map[reflect.Type]interface{}{} +var nullables map[reflect.Type]any = map[reflect.Type]any{} +var nullablesMu sync.RWMutex // NullValue is used to send an explicit 'null' within a request. // This is typically used in JSON-MERGE-PATCH operations to delete a value. func NullValue[T any]() T { t := shared.TypeOfT[T]() + + nullablesMu.RLock() v, found := nullables[t] + nullablesMu.RUnlock() + + if found { + // return the sentinel object + return v.(T) + } + + // promote to exclusive lock and check again (double-checked locking pattern) + nullablesMu.Lock() + defer nullablesMu.Unlock() + v, found = nullables[t] + if !found { var o reflect.Value if k := t.Kind(); k == reflect.Map { @@ -72,6 +88,9 @@ func NullValue[T any]() T { func IsNullValue[T any](v T) bool { // see if our map has a sentinel object for this *T t := reflect.TypeOf(v) + nullablesMu.RLock() + defer nullablesMu.RUnlock() + if o, found := nullables[t]; found { o1 := reflect.ValueOf(o) v1 := reflect.ValueOf(v) diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/etag.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/etag.go index 23ea7e7c8e..2b19d01f76 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/etag.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/etag.go @@ -46,3 +46,12 @@ func (e ETag) WeakEquals(other ETag) bool { func (e ETag) IsWeak() bool { return len(e) >= 4 && strings.HasPrefix(string(e), "W/\"") && strings.HasSuffix(string(e), "\"") } + +// MatchConditions specifies HTTP options for conditional requests. +type MatchConditions struct { + // Optionally limit requests to resources that have a matching ETag. + IfMatch *ETag + + // Optionally limit requests to resources that do not match the ETag. + IfNoneMatch *ETag +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/response_error.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/response_error.go index f243552885..bd348b868b 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/response_error.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported/response_error.go @@ -13,6 +13,7 @@ import ( "net/http" "regexp" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/log" "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared" "github.com/Azure/azure-sdk-for-go/sdk/internal/exported" ) @@ -20,31 +21,40 @@ import ( // NewResponseError creates a new *ResponseError from the provided HTTP response. // Exported as runtime.NewResponseError(). func NewResponseError(resp *http.Response) error { - respErr := &ResponseError{ - StatusCode: resp.StatusCode, - RawResponse: resp, - } - // prefer the error code in the response header if ec := resp.Header.Get(shared.HeaderXMSErrorCode); ec != "" { - respErr.ErrorCode = ec - return respErr + return NewResponseErrorWithErrorCode(resp, ec) } // if we didn't get x-ms-error-code, check in the response body body, err := exported.Payload(resp, nil) if err != nil { + // since we're not returning the ResponseError in this + // case we also don't want to write it to the log. return err } + var errorCode string if len(body) > 0 { - if code := extractErrorCodeJSON(body); code != "" { - respErr.ErrorCode = code - } else if code := extractErrorCodeXML(body); code != "" { - respErr.ErrorCode = code + if fromJSON := extractErrorCodeJSON(body); fromJSON != "" { + errorCode = fromJSON + } else if fromXML := extractErrorCodeXML(body); fromXML != "" { + errorCode = fromXML } } + return NewResponseErrorWithErrorCode(resp, errorCode) +} + +// NewResponseErrorWithErrorCode creates an *azcore.ResponseError from the provided HTTP response and errorCode. +// Exported as runtime.NewResponseErrorWithErrorCode(). +func NewResponseErrorWithErrorCode(resp *http.Response, errorCode string) error { + respErr := &ResponseError{ + ErrorCode: errorCode, + StatusCode: resp.StatusCode, + RawResponse: resp, + } + log.Write(log.EventResponseError, respErr.Error()) return respErr } diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/log/log.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/log/log.go index 0684cb3173..5cb87de2cb 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/log/log.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/log/log.go @@ -15,24 +15,36 @@ import ( type Event = log.Event const ( - EventRequest = azlog.EventRequest - EventResponse = azlog.EventResponse - EventRetryPolicy = azlog.EventRetryPolicy - EventLRO = azlog.EventLRO + EventRequest = azlog.EventRequest + EventResponse = azlog.EventResponse + EventResponseError = azlog.EventResponseError + EventRetryPolicy = azlog.EventRetryPolicy + EventLRO = azlog.EventLRO ) +// Write invokes the underlying listener with the specified event and message. +// If the event shouldn't be logged or there is no listener then Write does nothing. func Write(cls log.Event, msg string) { log.Write(cls, msg) } +// Writef invokes the underlying listener with the specified event and formatted message. +// If the event shouldn't be logged or there is no listener then Writef does nothing. func Writef(cls log.Event, format string, a ...interface{}) { log.Writef(cls, format, a...) } +// SetListener will set the Logger to write to the specified listener. func SetListener(lst func(Event, string)) { log.SetListener(lst) } +// Should returns true if the specified log event should be written to the log. +// By default all log events will be logged. Call SetEvents() to limit +// the log events for logging. +// If no listener has been set this will return false. +// Calling this method is useful when the message to log is computationally expensive +// and you want to avoid the overhead if its log event is not enabled. func Should(cls log.Event) bool { return log.Should(cls) } diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go index 8f749f48d9..330bf9a60b 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared/constants.go @@ -40,5 +40,5 @@ const ( Module = "azcore" // Version is the semantic version (see http://semver.org) of this module. - Version = "v1.9.2" + Version = "v1.10.0" ) diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/log/log.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/log/log.go index 7bde29d0a4..f260dac363 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/log/log.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/log/log.go @@ -23,6 +23,11 @@ const ( // This includes information like the HTTP status code, headers, and request URL. EventResponse Event = "Response" + // EventResponseError entries contain information about HTTP responses that returned + // an *azcore.ResponseError (i.e. responses with a non 2xx HTTP status code). + // This includes the contents of ResponseError.Error(). + EventResponseError Event = "ResponseError" + // EventRetryPolicy entries contain information specific to the retry policy in use. EventRetryPolicy Event = "Retry" diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/errors.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/errors.go index 6d03b291eb..c0d56158e2 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/errors.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/errors.go @@ -14,6 +14,14 @@ import ( // NewResponseError creates an *azcore.ResponseError from the provided HTTP response. // Call this when a service request returns a non-successful status code. +// The error code will be extracted from the *http.Response, either from the x-ms-error-code +// header (preferred) or attempted to be parsed from the response body. func NewResponseError(resp *http.Response) error { return exported.NewResponseError(resp) } + +// NewResponseErrorWithErrorCode creates an *azcore.ResponseError from the provided HTTP response and errorCode. +// Use this variant when the error code is in a non-standard location. +func NewResponseErrorWithErrorCode(resp *http.Response, errorCode string) error { + return exported.NewResponseErrorWithErrorCode(resp, errorCode) +} diff --git a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/request.go b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/request.go index 5d1569c8dd..bef05f2a3d 100644 --- a/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/request.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime/request.go @@ -42,12 +42,19 @@ func NewRequest(ctx context.Context, httpMethod string, endpoint string) (*polic } // EncodeQueryParams will parse and encode any query parameters in the specified URL. +// Any semicolons will automatically be escaped. func EncodeQueryParams(u string) (string, error) { before, after, found := strings.Cut(u, "?") if !found { return u, nil } - qp, err := url.ParseQuery(after) + // starting in Go 1.17, url.ParseQuery will reject semicolons in query params. + // so, we must escape them first. note that this assumes that semicolons aren't + // being used as query param separators which is per the current RFC. + // for more info: + // https://github.com/golang/go/issues/25192 + // https://github.com/golang/go/issues/50034 + qp, err := url.ParseQuery(strings.ReplaceAll(after, ";", "%3B")) if err != nil { return "", err } diff --git a/vendor/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go b/vendor/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go index a18c83304f..25055d6b81 100644 --- a/vendor/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go +++ b/vendor/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go @@ -12547,6 +12547,9 @@ var awsPartition = partition{ endpointKey{ Region: "eu-south-1", }: endpoint{}, + endpointKey{ + Region: "eu-south-2", + }: endpoint{}, endpointKey{ Region: "eu-west-1", }: endpoint{}, @@ -14554,6 +14557,9 @@ var awsPartition = partition{ endpointKey{ Region: "ca-central-1", }: endpoint{}, + endpointKey{ + Region: "ca-west-1", + }: endpoint{}, endpointKey{ Region: "eu-central-1", }: endpoint{}, @@ -19213,66 +19219,222 @@ var awsPartition = partition{ endpointKey{ Region: "af-south-1", }: endpoint{}, + endpointKey{ + Region: "af-south-1", + Variant: dualStackVariant, + }: endpoint{ + Hostname: "logs.af-south-1.api.aws", + }, endpointKey{ Region: "ap-east-1", }: endpoint{}, + endpointKey{ + Region: "ap-east-1", + Variant: dualStackVariant, + }: endpoint{ + Hostname: "logs.ap-east-1.api.aws", + }, endpointKey{ Region: "ap-northeast-1", }: endpoint{}, + endpointKey{ + Region: "ap-northeast-1", + Variant: dualStackVariant, + }: endpoint{ + Hostname: "logs.ap-northeast-1.api.aws", + }, endpointKey{ Region: "ap-northeast-2", }: endpoint{}, + endpointKey{ + Region: "ap-northeast-2", + Variant: dualStackVariant, + }: endpoint{ + Hostname: "logs.ap-northeast-2.api.aws", + }, endpointKey{ Region: "ap-northeast-3", }: endpoint{}, + endpointKey{ + Region: "ap-northeast-3", + Variant: dualStackVariant, + }: endpoint{ + Hostname: "logs.ap-northeast-3.api.aws", + }, endpointKey{ Region: "ap-south-1", }: endpoint{}, + endpointKey{ + Region: "ap-south-1", + Variant: dualStackVariant, + }: endpoint{ + Hostname: "logs.ap-south-1.api.aws", + }, endpointKey{ Region: "ap-south-2", }: endpoint{}, + endpointKey{ + Region: "ap-south-2", + Variant: dualStackVariant, + }: endpoint{ + Hostname: "logs.ap-south-2.api.aws", + }, endpointKey{ Region: "ap-southeast-1", }: endpoint{}, + endpointKey{ + Region: "ap-southeast-1", + Variant: dualStackVariant, + }: endpoint{ + Hostname: "logs.ap-southeast-1.api.aws", + }, endpointKey{ Region: "ap-southeast-2", }: endpoint{}, + endpointKey{ + Region: "ap-southeast-2", + Variant: dualStackVariant, + }: endpoint{ + Hostname: "logs.ap-southeast-2.api.aws", + }, endpointKey{ Region: "ap-southeast-3", }: endpoint{}, + endpointKey{ + Region: "ap-southeast-3", + Variant: dualStackVariant, + }: endpoint{ + Hostname: "logs.ap-southeast-3.api.aws", + }, endpointKey{ Region: "ap-southeast-4", }: endpoint{}, + endpointKey{ + Region: "ap-southeast-4", + Variant: dualStackVariant, + }: endpoint{ + Hostname: "logs.ap-southeast-4.api.aws", + }, endpointKey{ Region: "ca-central-1", }: endpoint{}, + endpointKey{ + Region: "ca-central-1", + Variant: dualStackVariant, + }: endpoint{ + Hostname: "logs.ca-central-1.api.aws", + }, + endpointKey{ + Region: "ca-central-1", + Variant: fipsVariant, + }: endpoint{ + Hostname: "logs-fips.ca-central-1.amazonaws.com", + }, endpointKey{ Region: "ca-west-1", }: endpoint{}, + endpointKey{ + Region: "ca-west-1", + Variant: dualStackVariant, + }: endpoint{ + Hostname: "logs.ca-west-1.api.aws", + }, + endpointKey{ + Region: "ca-west-1", + Variant: fipsVariant, + }: endpoint{ + Hostname: "logs-fips.ca-west-1.amazonaws.com", + }, endpointKey{ Region: "eu-central-1", }: endpoint{}, + endpointKey{ + Region: "eu-central-1", + Variant: dualStackVariant, + }: endpoint{ + Hostname: "logs.eu-central-1.api.aws", + }, endpointKey{ Region: "eu-central-2", }: endpoint{}, + endpointKey{ + Region: "eu-central-2", + Variant: dualStackVariant, + }: endpoint{ + Hostname: "logs.eu-central-2.api.aws", + }, endpointKey{ Region: "eu-north-1", }: endpoint{}, + endpointKey{ + Region: "eu-north-1", + Variant: dualStackVariant, + }: endpoint{ + Hostname: "logs.eu-north-1.api.aws", + }, endpointKey{ Region: "eu-south-1", }: endpoint{}, + endpointKey{ + Region: "eu-south-1", + Variant: dualStackVariant, + }: endpoint{ + Hostname: "logs.eu-south-1.api.aws", + }, endpointKey{ Region: "eu-south-2", }: endpoint{}, + endpointKey{ + Region: "eu-south-2", + Variant: dualStackVariant, + }: endpoint{ + Hostname: "logs.eu-south-2.api.aws", + }, endpointKey{ Region: "eu-west-1", }: endpoint{}, + endpointKey{ + Region: "eu-west-1", + Variant: dualStackVariant, + }: endpoint{ + Hostname: "logs.eu-west-1.api.aws", + }, endpointKey{ Region: "eu-west-2", }: endpoint{}, + endpointKey{ + Region: "eu-west-2", + Variant: dualStackVariant, + }: endpoint{ + Hostname: "logs.eu-west-2.api.aws", + }, endpointKey{ Region: "eu-west-3", }: endpoint{}, + endpointKey{ + Region: "eu-west-3", + Variant: dualStackVariant, + }: endpoint{ + Hostname: "logs.eu-west-3.api.aws", + }, + endpointKey{ + Region: "fips-ca-central-1", + }: endpoint{ + Hostname: "logs-fips.ca-central-1.amazonaws.com", + CredentialScope: credentialScope{ + Region: "ca-central-1", + }, + Deprecated: boxedTrue, + }, + endpointKey{ + Region: "fips-ca-west-1", + }: endpoint{ + Hostname: "logs-fips.ca-west-1.amazonaws.com", + CredentialScope: credentialScope{ + Region: "ca-west-1", + }, + Deprecated: boxedTrue, + }, endpointKey{ Region: "fips-us-east-1", }: endpoint{ @@ -19312,18 +19474,48 @@ var awsPartition = partition{ endpointKey{ Region: "il-central-1", }: endpoint{}, + endpointKey{ + Region: "il-central-1", + Variant: dualStackVariant, + }: endpoint{ + Hostname: "logs.il-central-1.api.aws", + }, endpointKey{ Region: "me-central-1", }: endpoint{}, + endpointKey{ + Region: "me-central-1", + Variant: dualStackVariant, + }: endpoint{ + Hostname: "logs.me-central-1.api.aws", + }, endpointKey{ Region: "me-south-1", }: endpoint{}, + endpointKey{ + Region: "me-south-1", + Variant: dualStackVariant, + }: endpoint{ + Hostname: "logs.me-south-1.api.aws", + }, endpointKey{ Region: "sa-east-1", }: endpoint{}, + endpointKey{ + Region: "sa-east-1", + Variant: dualStackVariant, + }: endpoint{ + Hostname: "logs.sa-east-1.api.aws", + }, endpointKey{ Region: "us-east-1", }: endpoint{}, + endpointKey{ + Region: "us-east-1", + Variant: dualStackVariant, + }: endpoint{ + Hostname: "logs.us-east-1.api.aws", + }, endpointKey{ Region: "us-east-1", Variant: fipsVariant, @@ -19333,6 +19525,12 @@ var awsPartition = partition{ endpointKey{ Region: "us-east-2", }: endpoint{}, + endpointKey{ + Region: "us-east-2", + Variant: dualStackVariant, + }: endpoint{ + Hostname: "logs.us-east-2.api.aws", + }, endpointKey{ Region: "us-east-2", Variant: fipsVariant, @@ -19342,6 +19540,12 @@ var awsPartition = partition{ endpointKey{ Region: "us-west-1", }: endpoint{}, + endpointKey{ + Region: "us-west-1", + Variant: dualStackVariant, + }: endpoint{ + Hostname: "logs.us-west-1.api.aws", + }, endpointKey{ Region: "us-west-1", Variant: fipsVariant, @@ -19351,6 +19555,12 @@ var awsPartition = partition{ endpointKey{ Region: "us-west-2", }: endpoint{}, + endpointKey{ + Region: "us-west-2", + Variant: dualStackVariant, + }: endpoint{ + Hostname: "logs.us-west-2.api.aws", + }, endpointKey{ Region: "us-west-2", Variant: fipsVariant, diff --git a/vendor/github.com/aws/aws-sdk-go/aws/version.go b/vendor/github.com/aws/aws-sdk-go/aws/version.go index e026795755..554b0ebde8 100644 --- a/vendor/github.com/aws/aws-sdk-go/aws/version.go +++ b/vendor/github.com/aws/aws-sdk-go/aws/version.go @@ -5,4 +5,4 @@ package aws const SDKName = "aws-sdk-go" // SDKVersion is the version of this SDK -const SDKVersion = "1.50.25" +const SDKVersion = "1.50.32" diff --git a/vendor/github.com/go-openapi/strfmt/format.go b/vendor/github.com/go-openapi/strfmt/format.go index ce99ce521b..888e107c38 100644 --- a/vendor/github.com/go-openapi/strfmt/format.go +++ b/vendor/github.com/go-openapi/strfmt/format.go @@ -16,6 +16,7 @@ package strfmt import ( "encoding" + stderrors "errors" "fmt" "reflect" "strings" @@ -117,7 +118,7 @@ func (f *defaultFormats) MapStructureHookFunc() mapstructure.DecodeHookFunc { case "datetime": input := data if len(input) == 0 { - return nil, fmt.Errorf("empty string is an invalid datetime format") + return nil, stderrors.New("empty string is an invalid datetime format") } return ParseDateTime(input) case "duration": diff --git a/vendor/github.com/go-openapi/validate/BENCHMARK.md b/vendor/github.com/go-openapi/validate/BENCHMARK.md new file mode 100644 index 0000000000..79cf6a077b --- /dev/null +++ b/vendor/github.com/go-openapi/validate/BENCHMARK.md @@ -0,0 +1,31 @@ +# Benchmark + +Validating the Kubernetes Swagger API + +## v0.22.6: 60,000,000 allocs +``` +goos: linux +goarch: amd64 +pkg: github.com/go-openapi/validate +cpu: AMD Ryzen 7 5800X 8-Core Processor +Benchmark_KubernetesSpec/validating_kubernetes_API-16 1 8549863982 ns/op 7067424936 B/op 59583275 allocs/op +``` + +## After refact PR: minor but noticable improvements: 25,000,000 allocs +``` +go test -bench Spec +goos: linux +goarch: amd64 +pkg: github.com/go-openapi/validate +cpu: AMD Ryzen 7 5800X 8-Core Processor +Benchmark_KubernetesSpec/validating_kubernetes_API-16 1 4064535557 ns/op 3379715592 B/op 25320330 allocs/op +``` + +## After reduce GC pressure PR: 17,000,000 allocs +``` +goos: linux +goarch: amd64 +pkg: github.com/go-openapi/validate +cpu: AMD Ryzen 7 5800X 8-Core Processor +Benchmark_KubernetesSpec/validating_kubernetes_API-16 1 3758414145 ns/op 2593881496 B/op 17111373 allocs/op +``` diff --git a/vendor/github.com/go-openapi/validate/default_validator.go b/vendor/github.com/go-openapi/validate/default_validator.go index 7f7fd0be9c..e30d1501f5 100644 --- a/vendor/github.com/go-openapi/validate/default_validator.go +++ b/vendor/github.com/go-openapi/validate/default_validator.go @@ -25,48 +25,55 @@ import ( // According to Swagger spec, default values MUST validate their schema. type defaultValidator struct { SpecValidator *SpecValidator - visitedSchemas map[string]bool + visitedSchemas map[string]struct{} + schemaOptions *SchemaValidatorOptions } // resetVisited resets the internal state of visited schemas func (d *defaultValidator) resetVisited() { - d.visitedSchemas = map[string]bool{} + if d.visitedSchemas == nil { + d.visitedSchemas = make(map[string]struct{}) + + return + } + + // TODO(go1.21): clear(ex.visitedSchemas) + for k := range d.visitedSchemas { + delete(d.visitedSchemas, k) + } } -func isVisited(path string, visitedSchemas map[string]bool) bool { - found := visitedSchemas[path] - if !found { - // search for overlapping paths - frags := strings.Split(path, ".") - if len(frags) < 2 { - // shortcut exit on smaller paths - return found +func isVisited(path string, visitedSchemas map[string]struct{}) bool { + _, found := visitedSchemas[path] + if found { + return true + } + + // search for overlapping paths + var ( + parent string + suffix string + ) + for i := len(path) - 2; i >= 0; i-- { + r := path[i] + if r != '.' { + continue } - last := len(frags) - 1 - var currentFragStr, parent string - for i := range frags { - if i == 0 { - currentFragStr = frags[last] - } else { - currentFragStr = strings.Join([]string{frags[last-i], currentFragStr}, ".") - } - if i < last { - parent = strings.Join(frags[0:last-i], ".") - } else { - parent = "" - } - if strings.HasSuffix(parent, currentFragStr) { - found = true - break - } + + parent = path[0:i] + suffix = path[i+1:] + + if strings.HasSuffix(parent, suffix) { + return true } } - return found + + return false } // beingVisited asserts a schema is being visited func (d *defaultValidator) beingVisited(path string) { - d.visitedSchemas[path] = true + d.visitedSchemas[path] = struct{}{} } // isVisited tells if a path has already been visited @@ -75,8 +82,9 @@ func (d *defaultValidator) isVisited(path string) bool { } // Validate validates the default values declared in the swagger spec -func (d *defaultValidator) Validate() (errs *Result) { - errs = new(Result) +func (d *defaultValidator) Validate() *Result { + errs := poolOfResults.BorrowResult() // will redeem when merged + if d == nil || d.SpecValidator == nil { return errs } @@ -89,7 +97,7 @@ func (d *defaultValidator) validateDefaultValueValidAgainstSchema() *Result { // every default value that is specified must validate against the schema for that property // headers, items, parameters, schema - res := new(Result) + res := poolOfResults.BorrowResult() // will redeem when merged s := d.SpecValidator for method, pathItem := range s.expandedAnalyzer().Operations() { @@ -107,7 +115,7 @@ func (d *defaultValidator) validateDefaultValueValidAgainstSchema() *Result { // default values provided must validate against their inline definition (no explicit schema) if param.Default != nil && param.Schema == nil { // check param default value is valid - red := NewParamValidator(¶m, s.KnownFormats).Validate(param.Default) //#nosec + red := newParamValidator(¶m, s.KnownFormats, d.schemaOptions).Validate(param.Default) //#nosec if red.HasErrorsOrWarnings() { res.AddErrors(defaultValueDoesNotValidateMsg(param.Name, param.In)) res.Merge(red) @@ -176,7 +184,7 @@ func (d *defaultValidator) validateDefaultInResponse(resp *spec.Response, respon d.resetVisited() if h.Default != nil { - red := NewHeaderValidator(nm, &h, s.KnownFormats).Validate(h.Default) //#nosec + red := newHeaderValidator(nm, &h, s.KnownFormats, d.schemaOptions).Validate(h.Default) //#nosec if red.HasErrorsOrWarnings() { res.AddErrors(defaultValueHeaderDoesNotValidateMsg(operationID, nm, responseName)) res.Merge(red) @@ -219,11 +227,13 @@ func (d *defaultValidator) validateDefaultValueSchemaAgainstSchema(path, in stri return nil } d.beingVisited(path) - res := new(Result) + res := poolOfResults.BorrowResult() s := d.SpecValidator if schema.Default != nil { - res.Merge(NewSchemaValidator(schema, s.spec.Spec(), path+".default", s.KnownFormats, SwaggerSchema(true)).Validate(schema.Default)) + res.Merge( + newSchemaValidator(schema, s.spec.Spec(), path+".default", s.KnownFormats, d.schemaOptions).Validate(schema.Default), + ) } if schema.Items != nil { if schema.Items.Schema != nil { @@ -263,11 +273,13 @@ func (d *defaultValidator) validateDefaultValueSchemaAgainstSchema(path, in stri // TODO: Temporary duplicated code. Need to refactor with examples func (d *defaultValidator) validateDefaultValueItemsAgainstSchema(path, in string, root interface{}, items *spec.Items) *Result { - res := new(Result) + res := poolOfResults.BorrowResult() s := d.SpecValidator if items != nil { if items.Default != nil { - res.Merge(newItemsValidator(path, in, items, root, s.KnownFormats).Validate(0, items.Default)) + res.Merge( + newItemsValidator(path, in, items, root, s.KnownFormats, d.schemaOptions).Validate(0, items.Default), + ) } if items.Items != nil { res.Merge(d.validateDefaultValueItemsAgainstSchema(path+"[0].default", in, root, items.Items)) diff --git a/vendor/github.com/go-openapi/validate/example_validator.go b/vendor/github.com/go-openapi/validate/example_validator.go index d5d4b88332..2e2cce1b89 100644 --- a/vendor/github.com/go-openapi/validate/example_validator.go +++ b/vendor/github.com/go-openapi/validate/example_validator.go @@ -23,17 +23,27 @@ import ( // ExampleValidator validates example values defined in a spec type exampleValidator struct { SpecValidator *SpecValidator - visitedSchemas map[string]bool + visitedSchemas map[string]struct{} + schemaOptions *SchemaValidatorOptions } // resetVisited resets the internal state of visited schemas func (ex *exampleValidator) resetVisited() { - ex.visitedSchemas = map[string]bool{} + if ex.visitedSchemas == nil { + ex.visitedSchemas = make(map[string]struct{}) + + return + } + + // TODO(go1.21): clear(ex.visitedSchemas) + for k := range ex.visitedSchemas { + delete(ex.visitedSchemas, k) + } } // beingVisited asserts a schema is being visited func (ex *exampleValidator) beingVisited(path string) { - ex.visitedSchemas[path] = true + ex.visitedSchemas[path] = struct{}{} } // isVisited tells if a path has already been visited @@ -48,8 +58,9 @@ func (ex *exampleValidator) isVisited(path string) bool { // - schemas // - individual property // - responses -func (ex *exampleValidator) Validate() (errs *Result) { - errs = new(Result) +func (ex *exampleValidator) Validate() *Result { + errs := poolOfResults.BorrowResult() + if ex == nil || ex.SpecValidator == nil { return errs } @@ -64,7 +75,7 @@ func (ex *exampleValidator) validateExampleValueValidAgainstSchema() *Result { // in: schemas, properties, object, items // not in: headers, parameters without schema - res := new(Result) + res := poolOfResults.BorrowResult() s := ex.SpecValidator for method, pathItem := range s.expandedAnalyzer().Operations() { @@ -82,7 +93,7 @@ func (ex *exampleValidator) validateExampleValueValidAgainstSchema() *Result { // default values provided must validate against their inline definition (no explicit schema) if param.Example != nil && param.Schema == nil { // check param default value is valid - red := NewParamValidator(¶m, s.KnownFormats).Validate(param.Example) //#nosec + red := newParamValidator(¶m, s.KnownFormats, ex.schemaOptions).Validate(param.Example) //#nosec if red.HasErrorsOrWarnings() { res.AddWarnings(exampleValueDoesNotValidateMsg(param.Name, param.In)) res.MergeAsWarnings(red) @@ -95,6 +106,8 @@ func (ex *exampleValidator) validateExampleValueValidAgainstSchema() *Result { if red.HasErrorsOrWarnings() { res.AddWarnings(exampleValueItemsDoesNotValidateMsg(param.Name, param.In)) res.Merge(red) + } else { + poolOfResults.RedeemResult(red) } } @@ -104,6 +117,8 @@ func (ex *exampleValidator) validateExampleValueValidAgainstSchema() *Result { if red.HasErrorsOrWarnings() { res.AddWarnings(exampleValueDoesNotValidateMsg(param.Name, param.In)) res.Merge(red) + } else { + poolOfResults.RedeemResult(red) } } } @@ -151,7 +166,7 @@ func (ex *exampleValidator) validateExampleInResponse(resp *spec.Response, respo ex.resetVisited() if h.Example != nil { - red := NewHeaderValidator(nm, &h, s.KnownFormats).Validate(h.Example) //#nosec + red := newHeaderValidator(nm, &h, s.KnownFormats, ex.schemaOptions).Validate(h.Example) //#nosec if red.HasErrorsOrWarnings() { res.AddWarnings(exampleValueHeaderDoesNotValidateMsg(operationID, nm, responseName)) res.MergeAsWarnings(red) @@ -189,7 +204,9 @@ func (ex *exampleValidator) validateExampleInResponse(resp *spec.Response, respo if response.Examples != nil { if response.Schema != nil { if example, ok := response.Examples["application/json"]; ok { - res.MergeAsWarnings(NewSchemaValidator(response.Schema, s.spec.Spec(), path+".examples", s.KnownFormats, SwaggerSchema(true)).Validate(example)) + res.MergeAsWarnings( + newSchemaValidator(response.Schema, s.spec.Spec(), path+".examples", s.KnownFormats, s.schemaOptions).Validate(example), + ) } else { // TODO: validate other media types too res.AddWarnings(examplesMimeNotSupportedMsg(operationID, responseName)) @@ -208,10 +225,12 @@ func (ex *exampleValidator) validateExampleValueSchemaAgainstSchema(path, in str } ex.beingVisited(path) s := ex.SpecValidator - res := new(Result) + res := poolOfResults.BorrowResult() if schema.Example != nil { - res.MergeAsWarnings(NewSchemaValidator(schema, s.spec.Spec(), path+".example", s.KnownFormats, SwaggerSchema(true)).Validate(schema.Example)) + res.MergeAsWarnings( + newSchemaValidator(schema, s.spec.Spec(), path+".example", s.KnownFormats, ex.schemaOptions).Validate(schema.Example), + ) } if schema.Items != nil { if schema.Items.Schema != nil { @@ -252,11 +271,13 @@ func (ex *exampleValidator) validateExampleValueSchemaAgainstSchema(path, in str // func (ex *exampleValidator) validateExampleValueItemsAgainstSchema(path, in string, root interface{}, items *spec.Items) *Result { - res := new(Result) + res := poolOfResults.BorrowResult() s := ex.SpecValidator if items != nil { if items.Example != nil { - res.MergeAsWarnings(newItemsValidator(path, in, items, root, s.KnownFormats).Validate(0, items.Example)) + res.MergeAsWarnings( + newItemsValidator(path, in, items, root, s.KnownFormats, ex.schemaOptions).Validate(0, items.Example), + ) } if items.Items != nil { res.Merge(ex.validateExampleValueItemsAgainstSchema(path+"[0].example", in, root, items.Items)) @@ -265,5 +286,6 @@ func (ex *exampleValidator) validateExampleValueItemsAgainstSchema(path, in stri res.AddErrors(invalidPatternInMsg(path, in, items.Pattern)) } } + return res } diff --git a/vendor/github.com/go-openapi/validate/formats.go b/vendor/github.com/go-openapi/validate/formats.go index 0ad996cbbc..9c66cabb2c 100644 --- a/vendor/github.com/go-openapi/validate/formats.go +++ b/vendor/github.com/go-openapi/validate/formats.go @@ -22,10 +22,32 @@ import ( ) type formatValidator struct { - Format string Path string In string + Format string KnownFormats strfmt.Registry + Options *SchemaValidatorOptions +} + +func newFormatValidator(path, in, format string, formats strfmt.Registry, opts *SchemaValidatorOptions) *formatValidator { + if opts == nil { + opts = new(SchemaValidatorOptions) + } + + var f *formatValidator + if opts.recycleValidators { + f = poolOfFormatValidators.BorrowValidator() + } else { + f = new(formatValidator) + } + + f.Path = path + f.In = in + f.Format = format + f.KnownFormats = formats + f.Options = opts + + return f } func (f *formatValidator) SetPath(path string) { @@ -33,37 +55,45 @@ func (f *formatValidator) SetPath(path string) { } func (f *formatValidator) Applies(source interface{}, kind reflect.Kind) bool { - doit := func() bool { - if source == nil { - return false - } - switch source := source.(type) { - case *spec.Items: - return kind == reflect.String && f.KnownFormats.ContainsName(source.Format) - case *spec.Parameter: - return kind == reflect.String && f.KnownFormats.ContainsName(source.Format) - case *spec.Schema: - return kind == reflect.String && f.KnownFormats.ContainsName(source.Format) - case *spec.Header: - return kind == reflect.String && f.KnownFormats.ContainsName(source.Format) - } + if source == nil || f.KnownFormats == nil { + return false + } + + switch source := source.(type) { + case *spec.Items: + return kind == reflect.String && f.KnownFormats.ContainsName(source.Format) + case *spec.Parameter: + return kind == reflect.String && f.KnownFormats.ContainsName(source.Format) + case *spec.Schema: + return kind == reflect.String && f.KnownFormats.ContainsName(source.Format) + case *spec.Header: + return kind == reflect.String && f.KnownFormats.ContainsName(source.Format) + default: return false } - r := doit() - debugLog("format validator for %q applies %t for %T (kind: %v)\n", f.Path, r, source, kind) - return r } func (f *formatValidator) Validate(val interface{}) *Result { - result := new(Result) - debugLog("validating \"%v\" against format: %s", val, f.Format) + if f.Options.recycleValidators { + defer func() { + f.redeem() + }() + } + + var result *Result + if f.Options.recycleResult { + result = poolOfResults.BorrowResult() + } else { + result = new(Result) + } if err := FormatOf(f.Path, f.In, f.Format, val.(string), f.KnownFormats); err != nil { result.AddErrors(err) } - if result.HasErrors() { - return result - } - return nil + return result +} + +func (f *formatValidator) redeem() { + poolOfFormatValidators.RedeemValidator(f) } diff --git a/vendor/github.com/go-openapi/validate/helpers.go b/vendor/github.com/go-openapi/validate/helpers.go index fc7500c844..e855994dfe 100644 --- a/vendor/github.com/go-openapi/validate/helpers.go +++ b/vendor/github.com/go-openapi/validate/helpers.go @@ -101,9 +101,17 @@ type errorHelper struct { // A collection of unexported helpers for error construction } -func (h *errorHelper) sErr(err errors.Error) *Result { +func (h *errorHelper) sErr(err errors.Error, recycle bool) *Result { // Builds a Result from standard errors.Error - return &Result{Errors: []error{err}} + var result *Result + if recycle { + result = poolOfResults.BorrowResult() + } else { + result = new(Result) + } + result.Errors = []error{err} + + return result } func (h *errorHelper) addPointerError(res *Result, err error, ref string, fromPath string) *Result { diff --git a/vendor/github.com/go-openapi/validate/object_validator.go b/vendor/github.com/go-openapi/validate/object_validator.go index 7bb12615d8..c556a9b61d 100644 --- a/vendor/github.com/go-openapi/validate/object_validator.go +++ b/vendor/github.com/go-openapi/validate/object_validator.go @@ -15,8 +15,8 @@ package validate import ( + "fmt" "reflect" - "regexp" "strings" "github.com/go-openapi/errors" @@ -35,62 +35,116 @@ type objectValidator struct { PatternProperties map[string]spec.Schema Root interface{} KnownFormats strfmt.Registry - Options SchemaValidatorOptions + Options *SchemaValidatorOptions + splitPath []string +} + +func newObjectValidator(path, in string, + maxProperties, minProperties *int64, required []string, properties spec.SchemaProperties, + additionalProperties *spec.SchemaOrBool, patternProperties spec.SchemaProperties, + root interface{}, formats strfmt.Registry, opts *SchemaValidatorOptions) *objectValidator { + if opts == nil { + opts = new(SchemaValidatorOptions) + } + + var v *objectValidator + if opts.recycleValidators { + v = poolOfObjectValidators.BorrowValidator() + } else { + v = new(objectValidator) + } + + v.Path = path + v.In = in + v.MaxProperties = maxProperties + v.MinProperties = minProperties + v.Required = required + v.Properties = properties + v.AdditionalProperties = additionalProperties + v.PatternProperties = patternProperties + v.Root = root + v.KnownFormats = formats + v.Options = opts + v.splitPath = strings.Split(v.Path, ".") + + return v } func (o *objectValidator) SetPath(path string) { o.Path = path + o.splitPath = strings.Split(path, ".") } func (o *objectValidator) Applies(source interface{}, kind reflect.Kind) bool { // TODO: this should also work for structs // there is a problem in the type validator where it will be unhappy about null values // so that requires more testing - r := reflect.TypeOf(source) == specSchemaType && (kind == reflect.Map || kind == reflect.Struct) - debugLog("object validator for %q applies %t for %T (kind: %v)\n", o.Path, r, source, kind) - return r + _, isSchema := source.(*spec.Schema) + return isSchema && (kind == reflect.Map || kind == reflect.Struct) } func (o *objectValidator) isProperties() bool { - p := strings.Split(o.Path, ".") + p := o.splitPath return len(p) > 1 && p[len(p)-1] == jsonProperties && p[len(p)-2] != jsonProperties } func (o *objectValidator) isDefault() bool { - p := strings.Split(o.Path, ".") + p := o.splitPath return len(p) > 1 && p[len(p)-1] == jsonDefault && p[len(p)-2] != jsonDefault } func (o *objectValidator) isExample() bool { - p := strings.Split(o.Path, ".") + p := o.splitPath return len(p) > 1 && (p[len(p)-1] == swaggerExample || p[len(p)-1] == swaggerExamples) && p[len(p)-2] != swaggerExample } func (o *objectValidator) checkArrayMustHaveItems(res *Result, val map[string]interface{}) { // for swagger 2.0 schemas, there is an additional constraint to have array items defined explicitly. // with pure jsonschema draft 4, one may have arrays with undefined items (i.e. any type). - if t, typeFound := val[jsonType]; typeFound { - if tpe, ok := t.(string); ok && tpe == arrayType { - if item, itemsKeyFound := val[jsonItems]; !itemsKeyFound { - res.AddErrors(errors.Required(jsonItems, o.Path, item)) - } - } + if val == nil { + return + } + + t, typeFound := val[jsonType] + if !typeFound { + return + } + + tpe, isString := t.(string) + if !isString || tpe != arrayType { + return + } + + item, itemsKeyFound := val[jsonItems] + if itemsKeyFound { + return } + + res.AddErrors(errors.Required(jsonItems, o.Path, item)) } func (o *objectValidator) checkItemsMustBeTypeArray(res *Result, val map[string]interface{}) { - if !o.isProperties() && !o.isDefault() && !o.isExample() { - if _, itemsKeyFound := val[jsonItems]; itemsKeyFound { - t, typeFound := val[jsonType] - if typeFound { - if tpe, ok := t.(string); !ok || tpe != arrayType { - res.AddErrors(errors.InvalidType(o.Path, o.In, arrayType, nil)) - } - } else { - // there is no type - res.AddErrors(errors.Required(jsonType, o.Path, t)) - } - } + if val == nil { + return + } + + if o.isProperties() || o.isDefault() || o.isExample() { + return + } + + _, itemsKeyFound := val[jsonItems] + if !itemsKeyFound { + return + } + + t, typeFound := val[jsonType] + if !typeFound { + // there is no type + res.AddErrors(errors.Required(jsonType, o.Path, t)) + } + + if tpe, isString := t.(string); !isString || tpe != arrayType { + res.AddErrors(errors.InvalidType(o.Path, o.In, arrayType, nil)) } } @@ -104,176 +158,274 @@ func (o *objectValidator) precheck(res *Result, val map[string]interface{}) { } func (o *objectValidator) Validate(data interface{}) *Result { - val := data.(map[string]interface{}) - // TODO: guard against nil data + if o.Options.recycleValidators { + defer func() { + o.redeem() + }() + } + + var val map[string]interface{} + if data != nil { + var ok bool + val, ok = data.(map[string]interface{}) + if !ok { + return errorHelp.sErr(invalidObjectMsg(o.Path, o.In), o.Options.recycleResult) + } + } numKeys := int64(len(val)) if o.MinProperties != nil && numKeys < *o.MinProperties { - return errorHelp.sErr(errors.TooFewProperties(o.Path, o.In, *o.MinProperties)) + return errorHelp.sErr(errors.TooFewProperties(o.Path, o.In, *o.MinProperties), o.Options.recycleResult) } if o.MaxProperties != nil && numKeys > *o.MaxProperties { - return errorHelp.sErr(errors.TooManyProperties(o.Path, o.In, *o.MaxProperties)) + return errorHelp.sErr(errors.TooManyProperties(o.Path, o.In, *o.MaxProperties), o.Options.recycleResult) } - res := new(Result) + var res *Result + if o.Options.recycleResult { + res = poolOfResults.BorrowResult() + } else { + res = new(Result) + } o.precheck(res, val) // check validity of field names if o.AdditionalProperties != nil && !o.AdditionalProperties.Allows { // Case: additionalProperties: false - for k := range val { - _, regularProperty := o.Properties[k] - matched := false - - for pk := range o.PatternProperties { - if matches, _ := regexp.MatchString(pk, k); matches { - matched = true - break - } + o.validateNoAdditionalProperties(val, res) + } else { + // Cases: empty additionalProperties (implying: true), or additionalProperties: true, or additionalProperties: { <> } + o.validateAdditionalProperties(val, res) + } + + o.validatePropertiesSchema(val, res) + + // Check patternProperties + // TODO: it looks like we have done that twice in many cases + for key, value := range val { + _, regularProperty := o.Properties[key] + matched, _, patterns := o.validatePatternProperty(key, value, res) // applies to regular properties as well + if regularProperty || !matched { + continue + } + + for _, pName := range patterns { + if v, ok := o.PatternProperties[pName]; ok { + r := newSchemaValidator(&v, o.Root, o.Path+"."+key, o.KnownFormats, o.Options).Validate(value) + res.mergeForField(data.(map[string]interface{}), key, r) } + } + } - if !regularProperty && k != "$schema" && k != "id" && !matched { - // Special properties "$schema" and "id" are ignored - res.AddErrors(errors.PropertyNotAllowed(o.Path, o.In, k)) - - // BUG(fredbi): This section should move to a part dedicated to spec validation as - // it will conflict with regular schemas where a property "headers" is defined. - - // - // Croaks a more explicit message on top of the standard one - // on some recognized cases. - // - // NOTE: edge cases with invalid type assertion are simply ignored here. - // NOTE: prefix your messages here by "IMPORTANT!" so there are not filtered - // by higher level callers (the IMPORTANT! tag will be eventually - // removed). - if k == "headers" && val[k] != nil { - // $ref is forbidden in header - if headers, mapOk := val[k].(map[string]interface{}); mapOk { - for headerKey, headerBody := range headers { - if headerBody != nil { - if headerSchema, mapOfMapOk := headerBody.(map[string]interface{}); mapOfMapOk { - if _, found := headerSchema["$ref"]; found { - var msg string - if refString, stringOk := headerSchema["$ref"].(string); stringOk { - msg = strings.Join([]string{", one may not use $ref=\":", refString, "\""}, "") - } - res.AddErrors(refNotAllowedInHeaderMsg(o.Path, headerKey, msg)) - } - } - } - } - } - /* - case "$ref": - if val[k] != nil { - // TODO: check context of that ref: warn about siblings, check against invalid context - } - */ - } + return res +} + +func (o *objectValidator) validateNoAdditionalProperties(val map[string]interface{}, res *Result) { + for k := range val { + if k == "$schema" || k == "id" { + // special properties "$schema" and "id" are ignored + continue + } + + _, regularProperty := o.Properties[k] + if regularProperty { + continue + } + + matched := false + for pk := range o.PatternProperties { + re, err := compileRegexp(pk) + if err != nil { + continue + } + if matches := re.MatchString(k); matches { + matched = true + break } } - } else { - // Cases: no additionalProperties (implying: true), or additionalProperties: true, or additionalProperties: { <> } - for key, value := range val { - _, regularProperty := o.Properties[key] - - // Validates property against "patternProperties" if applicable - // BUG(fredbi): succeededOnce is always false - - // NOTE: how about regular properties which do not match patternProperties? - matched, succeededOnce, _ := o.validatePatternProperty(key, value, res) - - if !(regularProperty || matched || succeededOnce) { - - // Cases: properties which are not regular properties and have not been matched by the PatternProperties validator - if o.AdditionalProperties != nil && o.AdditionalProperties.Schema != nil { - // AdditionalProperties as Schema - r := NewSchemaValidator(o.AdditionalProperties.Schema, o.Root, o.Path+"."+key, o.KnownFormats, o.Options.Options()...).Validate(value) - res.mergeForField(data.(map[string]interface{}), key, r) - } else if regularProperty && !(matched || succeededOnce) { - // TODO: this is dead code since regularProperty=false here - res.AddErrors(errors.FailedAllPatternProperties(o.Path, o.In, key)) - } + if matched { + continue + } + + res.AddErrors(errors.PropertyNotAllowed(o.Path, o.In, k)) + + // BUG(fredbi): This section should move to a part dedicated to spec validation as + // it will conflict with regular schemas where a property "headers" is defined. + + // + // Croaks a more explicit message on top of the standard one + // on some recognized cases. + // + // NOTE: edge cases with invalid type assertion are simply ignored here. + // NOTE: prefix your messages here by "IMPORTANT!" so there are not filtered + // by higher level callers (the IMPORTANT! tag will be eventually + // removed). + if k != "headers" || val[k] == nil { + continue + } + + // $ref is forbidden in header + headers, mapOk := val[k].(map[string]interface{}) + if !mapOk { + continue + } + + for headerKey, headerBody := range headers { + if headerBody == nil { + continue + } + + headerSchema, mapOfMapOk := headerBody.(map[string]interface{}) + if !mapOfMapOk { + continue + } + + _, found := headerSchema["$ref"] + if !found { + continue + } + + refString, stringOk := headerSchema["$ref"].(string) + if !stringOk { + continue } + + msg := strings.Join([]string{", one may not use $ref=\":", refString, "\""}, "") + res.AddErrors(refNotAllowedInHeaderMsg(o.Path, headerKey, msg)) + /* + case "$ref": + if val[k] != nil { + // TODO: check context of that ref: warn about siblings, check against invalid context + } + */ + } + } +} + +func (o *objectValidator) validateAdditionalProperties(val map[string]interface{}, res *Result) { + for key, value := range val { + _, regularProperty := o.Properties[key] + if regularProperty { + continue + } + + // Validates property against "patternProperties" if applicable + // BUG(fredbi): succeededOnce is always false + + // NOTE: how about regular properties which do not match patternProperties? + matched, succeededOnce, _ := o.validatePatternProperty(key, value, res) + if matched || succeededOnce { + continue + } + + if o.AdditionalProperties == nil || o.AdditionalProperties.Schema == nil { + continue } - // Valid cases: additionalProperties: true or undefined + + // Cases: properties which are not regular properties and have not been matched by the PatternProperties validator + // AdditionalProperties as Schema + r := newSchemaValidator(o.AdditionalProperties.Schema, o.Root, o.Path+"."+key, o.KnownFormats, o.Options).Validate(value) + res.mergeForField(val, key, r) } + // Valid cases: additionalProperties: true or undefined +} - createdFromDefaults := map[string]bool{} +func (o *objectValidator) validatePropertiesSchema(val map[string]interface{}, res *Result) { + createdFromDefaults := map[string]struct{}{} // Property types: // - regular Property + pSchema := poolOfSchemas.BorrowSchema() // recycle a spec.Schema object which lifespan extends only to the validation of properties + defer func() { + poolOfSchemas.RedeemSchema(pSchema) + }() + for pName := range o.Properties { - pSchema := o.Properties[pName] // one instance per iteration - rName := pName - if o.Path != "" { + *pSchema = o.Properties[pName] + var rName string + if o.Path == "" { + rName = pName + } else { rName = o.Path + "." + pName } // Recursively validates each property against its schema - if v, ok := val[pName]; ok { - r := NewSchemaValidator(&pSchema, o.Root, rName, o.KnownFormats, o.Options.Options()...).Validate(v) - res.mergeForField(data.(map[string]interface{}), pName, r) - } else if pSchema.Default != nil { - // If a default value is defined, creates the property from defaults - // NOTE: JSON schema does not enforce default values to be valid against schema. Swagger does. - createdFromDefaults[pName] = true - res.addPropertySchemata(data.(map[string]interface{}), pName, &pSchema) + v, ok := val[pName] + if ok { + r := newSchemaValidator(pSchema, o.Root, rName, o.KnownFormats, o.Options).Validate(v) + res.mergeForField(val, pName, r) + + continue } - } - // Check required properties - if len(o.Required) > 0 { - for _, k := range o.Required { - if v, ok := val[k]; !ok && !createdFromDefaults[k] { - res.AddErrors(errors.Required(o.Path+"."+k, o.In, v)) - continue + if pSchema.Default != nil { + // if a default value is defined, creates the property from defaults + // NOTE: JSON schema does not enforce default values to be valid against schema. Swagger does. + createdFromDefaults[pName] = struct{}{} + if !o.Options.skipSchemataResult { + res.addPropertySchemata(val, pName, pSchema) // this shallow-clones the content of the pSchema pointer } } } - // Check patternProperties - // TODO: it looks like we have done that twice in many cases - for key, value := range val { - _, regularProperty := o.Properties[key] - matched, _ /*succeededOnce*/, patterns := o.validatePatternProperty(key, value, res) - if !regularProperty && (matched /*|| succeededOnce*/) { - for _, pName := range patterns { - if v, ok := o.PatternProperties[pName]; ok { - r := NewSchemaValidator(&v, o.Root, o.Path+"."+key, o.KnownFormats, o.Options.Options()...).Validate(value) - res.mergeForField(data.(map[string]interface{}), key, r) - } - } + if len(o.Required) == 0 { + return + } + + // Check required properties + for _, k := range o.Required { + v, ok := val[k] + if ok { + continue + } + _, isCreatedFromDefaults := createdFromDefaults[k] + if isCreatedFromDefaults { + continue } + + res.AddErrors(errors.Required(fmt.Sprintf("%s.%s", o.Path, k), o.In, v)) } - return res } // TODO: succeededOnce is not used anywhere func (o *objectValidator) validatePatternProperty(key string, value interface{}, result *Result) (bool, bool, []string) { + if len(o.PatternProperties) == 0 { + return false, false, nil + } + matched := false succeededOnce := false - var patterns []string + patterns := make([]string, 0, len(o.PatternProperties)) - for k, schema := range o.PatternProperties { - sch := schema - if match, _ := regexp.MatchString(k, key); match { - patterns = append(patterns, k) - matched = true - validator := NewSchemaValidator(&sch, o.Root, o.Path+"."+key, o.KnownFormats, o.Options.Options()...) + schema := poolOfSchemas.BorrowSchema() + defer func() { + poolOfSchemas.RedeemSchema(schema) + }() - res := validator.Validate(value) - result.Merge(res) + for k := range o.PatternProperties { + re, err := compileRegexp(k) + if err != nil { + continue } - } - // BUG(fredbi): can't get to here. Should remove dead code (commented out). + match := re.MatchString(key) + if !match { + continue + } - // if succeededOnce { - // result.Inc() - // } + *schema = o.PatternProperties[k] + patterns = append(patterns, k) + matched = true + validator := newSchemaValidator(schema, o.Root, fmt.Sprintf("%s.%s", o.Path, key), o.KnownFormats, o.Options) + + res := validator.Validate(value) + result.Merge(res) + } return matched, succeededOnce, patterns } + +func (o *objectValidator) redeem() { + poolOfObjectValidators.RedeemValidator(o) +} diff --git a/vendor/github.com/go-openapi/validate/options.go b/vendor/github.com/go-openapi/validate/options.go index 8a22ce9911..cfe9b0660f 100644 --- a/vendor/github.com/go-openapi/validate/options.go +++ b/vendor/github.com/go-openapi/validate/options.go @@ -31,6 +31,7 @@ type Opts struct { // GET:/v1/{shelve} and GET:/v1/{book}, where the IDs are "shelve/*" and // /"shelve/*/book/*" respectively. StrictPathParamUniqueness bool + SkipSchemataResult bool } var ( diff --git a/vendor/github.com/go-openapi/validate/pools.go b/vendor/github.com/go-openapi/validate/pools.go new file mode 100644 index 0000000000..728ed0a569 --- /dev/null +++ b/vendor/github.com/go-openapi/validate/pools.go @@ -0,0 +1,373 @@ +package validate + +import ( + "sync" + + "github.com/go-openapi/spec" +) + +var ( + // memory pools for all validator objects. + // + // Each pool can be borrowed from and redeemed to. + poolOfSchemaValidators schemaValidatorsPool + poolOfObjectValidators objectValidatorsPool + poolOfSliceValidators sliceValidatorsPool + poolOfItemsValidators itemsValidatorsPool + poolOfBasicCommonValidators basicCommonValidatorsPool + poolOfHeaderValidators headerValidatorsPool + poolOfParamValidators paramValidatorsPool + poolOfBasicSliceValidators basicSliceValidatorsPool + poolOfNumberValidators numberValidatorsPool + poolOfStringValidators stringValidatorsPool + poolOfSchemaPropsValidators schemaPropsValidatorsPool + poolOfFormatValidators formatValidatorsPool + poolOfTypeValidators typeValidatorsPool + poolOfSchemas schemasPool + poolOfResults resultsPool +) + +func init() { + resetPools() +} + +func resetPools() { + // NOTE: for testing purpose, we might want to reset pools after calling Validate twice. + // The pool is corrupted in that case: calling Put twice inserts a duplicate in the pool + // and further calls to Get are mishandled. + poolOfSchemaValidators = schemaValidatorsPool{ + Pool: &sync.Pool{ + New: func() any { + s := &SchemaValidator{} + + return s + }, + }, + } + + poolOfObjectValidators = objectValidatorsPool{ + Pool: &sync.Pool{ + New: func() any { + s := &objectValidator{} + + return s + }, + }, + } + + poolOfSliceValidators = sliceValidatorsPool{ + Pool: &sync.Pool{ + New: func() any { + s := &schemaSliceValidator{} + + return s + }, + }, + } + + poolOfItemsValidators = itemsValidatorsPool{ + Pool: &sync.Pool{ + New: func() any { + s := &itemsValidator{} + + return s + }, + }, + } + + poolOfBasicCommonValidators = basicCommonValidatorsPool{ + Pool: &sync.Pool{ + New: func() any { + s := &basicCommonValidator{} + + return s + }, + }, + } + + poolOfHeaderValidators = headerValidatorsPool{ + Pool: &sync.Pool{ + New: func() any { + s := &HeaderValidator{} + + return s + }, + }, + } + + poolOfParamValidators = paramValidatorsPool{ + Pool: &sync.Pool{ + New: func() any { + s := &ParamValidator{} + + return s + }, + }, + } + + poolOfBasicSliceValidators = basicSliceValidatorsPool{ + Pool: &sync.Pool{ + New: func() any { + s := &basicSliceValidator{} + + return s + }, + }, + } + + poolOfNumberValidators = numberValidatorsPool{ + Pool: &sync.Pool{ + New: func() any { + s := &numberValidator{} + + return s + }, + }, + } + + poolOfStringValidators = stringValidatorsPool{ + Pool: &sync.Pool{ + New: func() any { + s := &stringValidator{} + + return s + }, + }, + } + + poolOfSchemaPropsValidators = schemaPropsValidatorsPool{ + Pool: &sync.Pool{ + New: func() any { + s := &schemaPropsValidator{} + + return s + }, + }, + } + + poolOfFormatValidators = formatValidatorsPool{ + Pool: &sync.Pool{ + New: func() any { + s := &formatValidator{} + + return s + }, + }, + } + + poolOfTypeValidators = typeValidatorsPool{ + Pool: &sync.Pool{ + New: func() any { + s := &typeValidator{} + + return s + }, + }, + } + + poolOfSchemas = schemasPool{ + Pool: &sync.Pool{ + New: func() any { + s := &spec.Schema{} + + return s + }, + }, + } + + poolOfResults = resultsPool{ + Pool: &sync.Pool{ + New: func() any { + s := &Result{} + + return s + }, + }, + } +} + +type ( + schemaValidatorsPool struct { + *sync.Pool + } + + objectValidatorsPool struct { + *sync.Pool + } + + sliceValidatorsPool struct { + *sync.Pool + } + + itemsValidatorsPool struct { + *sync.Pool + } + + basicCommonValidatorsPool struct { + *sync.Pool + } + + headerValidatorsPool struct { + *sync.Pool + } + + paramValidatorsPool struct { + *sync.Pool + } + + basicSliceValidatorsPool struct { + *sync.Pool + } + + numberValidatorsPool struct { + *sync.Pool + } + + stringValidatorsPool struct { + *sync.Pool + } + + schemaPropsValidatorsPool struct { + *sync.Pool + } + + formatValidatorsPool struct { + *sync.Pool + } + + typeValidatorsPool struct { + *sync.Pool + } + + schemasPool struct { + *sync.Pool + } + + resultsPool struct { + *sync.Pool + } +) + +func (p schemaValidatorsPool) BorrowValidator() *SchemaValidator { + return p.Get().(*SchemaValidator) +} + +func (p schemaValidatorsPool) RedeemValidator(s *SchemaValidator) { + // NOTE: s might be nil. In that case, Put is a noop. + p.Put(s) +} + +func (p objectValidatorsPool) BorrowValidator() *objectValidator { + return p.Get().(*objectValidator) +} + +func (p objectValidatorsPool) RedeemValidator(s *objectValidator) { + p.Put(s) +} + +func (p sliceValidatorsPool) BorrowValidator() *schemaSliceValidator { + return p.Get().(*schemaSliceValidator) +} + +func (p sliceValidatorsPool) RedeemValidator(s *schemaSliceValidator) { + p.Put(s) +} + +func (p itemsValidatorsPool) BorrowValidator() *itemsValidator { + return p.Get().(*itemsValidator) +} + +func (p itemsValidatorsPool) RedeemValidator(s *itemsValidator) { + p.Put(s) +} + +func (p basicCommonValidatorsPool) BorrowValidator() *basicCommonValidator { + return p.Get().(*basicCommonValidator) +} + +func (p basicCommonValidatorsPool) RedeemValidator(s *basicCommonValidator) { + p.Put(s) +} + +func (p headerValidatorsPool) BorrowValidator() *HeaderValidator { + return p.Get().(*HeaderValidator) +} + +func (p headerValidatorsPool) RedeemValidator(s *HeaderValidator) { + p.Put(s) +} + +func (p paramValidatorsPool) BorrowValidator() *ParamValidator { + return p.Get().(*ParamValidator) +} + +func (p paramValidatorsPool) RedeemValidator(s *ParamValidator) { + p.Put(s) +} + +func (p basicSliceValidatorsPool) BorrowValidator() *basicSliceValidator { + return p.Get().(*basicSliceValidator) +} + +func (p basicSliceValidatorsPool) RedeemValidator(s *basicSliceValidator) { + p.Put(s) +} + +func (p numberValidatorsPool) BorrowValidator() *numberValidator { + return p.Get().(*numberValidator) +} + +func (p numberValidatorsPool) RedeemValidator(s *numberValidator) { + p.Put(s) +} + +func (p stringValidatorsPool) BorrowValidator() *stringValidator { + return p.Get().(*stringValidator) +} + +func (p stringValidatorsPool) RedeemValidator(s *stringValidator) { + p.Put(s) +} + +func (p schemaPropsValidatorsPool) BorrowValidator() *schemaPropsValidator { + return p.Get().(*schemaPropsValidator) +} + +func (p schemaPropsValidatorsPool) RedeemValidator(s *schemaPropsValidator) { + p.Put(s) +} + +func (p formatValidatorsPool) BorrowValidator() *formatValidator { + return p.Get().(*formatValidator) +} + +func (p formatValidatorsPool) RedeemValidator(s *formatValidator) { + p.Put(s) +} + +func (p typeValidatorsPool) BorrowValidator() *typeValidator { + return p.Get().(*typeValidator) +} + +func (p typeValidatorsPool) RedeemValidator(s *typeValidator) { + p.Put(s) +} + +func (p schemasPool) BorrowSchema() *spec.Schema { + return p.Get().(*spec.Schema) +} + +func (p schemasPool) RedeemSchema(s *spec.Schema) { + p.Put(s) +} + +func (p resultsPool) BorrowResult() *Result { + return p.Get().(*Result).cleared() +} + +func (p resultsPool) RedeemResult(s *Result) { + if s == emptyResult { + return + } + p.Put(s) +} diff --git a/vendor/github.com/go-openapi/validate/result.go b/vendor/github.com/go-openapi/validate/result.go index 0fe934fe67..605ec39604 100644 --- a/vendor/github.com/go-openapi/validate/result.go +++ b/vendor/github.com/go-openapi/validate/result.go @@ -23,6 +23,8 @@ import ( "github.com/go-openapi/spec" ) +var emptyResult = &Result{MatchCount: 1} + // Result represents a validation result set, composed of // errors and warnings. // @@ -52,6 +54,8 @@ type Result struct { cachedFieldSchemta map[FieldKey][]*spec.Schema cachedItemSchemata map[ItemKey][]*spec.Schema + + wantsRedeemOnMerge bool } // FieldKey is a pair of an object and a field, usable as a key for a map. @@ -116,6 +120,9 @@ func (r *Result) Merge(others ...*Result) *Result { } r.mergeWithoutRootSchemata(other) r.rootObjectSchemata.Append(other.rootObjectSchemata) + if other.wantsRedeemOnMerge { + poolOfResults.RedeemResult(other) + } } return r } @@ -193,6 +200,9 @@ func (r *Result) mergeForField(obj map[string]interface{}, field string, other * schemata: other.rootObjectSchemata, }) } + if other.wantsRedeemOnMerge { + poolOfResults.RedeemResult(other) + } return r } @@ -216,23 +226,30 @@ func (r *Result) mergeForSlice(slice reflect.Value, i int, other *Result) *Resul schemata: other.rootObjectSchemata, }) } + if other.wantsRedeemOnMerge { + poolOfResults.RedeemResult(other) + } return r } // addRootObjectSchemata adds the given schemata for the root object of the result. -// The slice schemata might be reused. I.e. do not modify it after being added to a result. +// +// Since the slice schemata might be reused, it is shallow-cloned before saving it into the result. func (r *Result) addRootObjectSchemata(s *spec.Schema) { - r.rootObjectSchemata.Append(schemata{one: s}) + clone := *s + r.rootObjectSchemata.Append(schemata{one: &clone}) } // addPropertySchemata adds the given schemata for the object and field. -// The slice schemata might be reused. I.e. do not modify it after being added to a result. +// +// Since the slice schemata might be reused, it is shallow-cloned before saving it into the result. func (r *Result) addPropertySchemata(obj map[string]interface{}, fld string, schema *spec.Schema) { if r.fieldSchemata == nil { r.fieldSchemata = make([]fieldSchemata, 0, len(obj)) } - r.fieldSchemata = append(r.fieldSchemata, fieldSchemata{obj: obj, field: fld, schemata: schemata{one: schema}}) + clone := *schema + r.fieldSchemata = append(r.fieldSchemata, fieldSchemata{obj: obj, field: fld, schemata: schemata{one: &clone}}) } /* @@ -280,6 +297,9 @@ func (r *Result) MergeAsErrors(others ...*Result) *Result { r.AddErrors(other.Errors...) r.AddErrors(other.Warnings...) r.MatchCount += other.MatchCount + if other.wantsRedeemOnMerge { + poolOfResults.RedeemResult(other) + } } } return r @@ -295,6 +315,9 @@ func (r *Result) MergeAsWarnings(others ...*Result) *Result { r.AddWarnings(other.Errors...) r.AddWarnings(other.Warnings...) r.MatchCount += other.MatchCount + if other.wantsRedeemOnMerge { + poolOfResults.RedeemResult(other) + } } } return r @@ -365,7 +388,12 @@ func (r *Result) keepRelevantErrors() *Result { strippedWarnings = append(strippedWarnings, fmt.Errorf(strings.TrimPrefix(e.Error(), "IMPORTANT!"))) } } - strippedResult := new(Result) + var strippedResult *Result + if r.wantsRedeemOnMerge { + strippedResult = poolOfResults.BorrowResult() + } else { + strippedResult = new(Result) + } strippedResult.Errors = strippedErrors strippedResult.Warnings = strippedWarnings return strippedResult @@ -427,6 +455,27 @@ func (r *Result) AsError() error { return errors.CompositeValidationError(r.Errors...) } +func (r *Result) cleared() *Result { + // clear the Result to be reusable. Keep allocated capacity. + r.Errors = r.Errors[:0] + r.Warnings = r.Warnings[:0] + r.MatchCount = 0 + r.data = nil + r.rootObjectSchemata.one = nil + r.rootObjectSchemata.multiple = r.rootObjectSchemata.multiple[:0] + r.fieldSchemata = r.fieldSchemata[:0] + r.itemSchemata = r.itemSchemata[:0] + for k := range r.cachedFieldSchemta { + delete(r.cachedFieldSchemta, k) + } + for k := range r.cachedItemSchemata { + delete(r.cachedItemSchemata, k) + } + r.wantsRedeemOnMerge = true // mark this result as eligible for redeem when merged into another + + return r +} + // schemata is an arbitrary number of schemata. It does a distinction between zero, // one and many schemata to avoid slice allocations. type schemata struct { diff --git a/vendor/github.com/go-openapi/validate/schema.go b/vendor/github.com/go-openapi/validate/schema.go index 62b91dc5b0..a359331121 100644 --- a/vendor/github.com/go-openapi/validate/schema.go +++ b/vendor/github.com/go-openapi/validate/schema.go @@ -24,32 +24,32 @@ import ( "github.com/go-openapi/swag" ) -var ( - specSchemaType = reflect.TypeOf(&spec.Schema{}) - specParameterType = reflect.TypeOf(&spec.Parameter{}) - specHeaderType = reflect.TypeOf(&spec.Header{}) - // specItemsType = reflect.TypeOf(&spec.Items{}) -) - // SchemaValidator validates data against a JSON schema type SchemaValidator struct { Path string in string Schema *spec.Schema - validators []valueValidator + validators [8]valueValidator Root interface{} KnownFormats strfmt.Registry - Options SchemaValidatorOptions + Options *SchemaValidatorOptions } // AgainstSchema validates the specified data against the provided schema, using a registry of supported formats. // // When no pre-parsed *spec.Schema structure is provided, it uses a JSON schema as default. See example. func AgainstSchema(schema *spec.Schema, data interface{}, formats strfmt.Registry, options ...Option) error { - res := NewSchemaValidator(schema, nil, "", formats, options...).Validate(data) + res := NewSchemaValidator(schema, nil, "", formats, + append(options, WithRecycleValidators(true), withRecycleResults(true))..., + ).Validate(data) + defer func() { + poolOfResults.RedeemResult(res) + }() + if res.HasErrors() { return errors.CompositeValidationError(res.Errors...) } + return nil } @@ -57,6 +57,15 @@ func AgainstSchema(schema *spec.Schema, data interface{}, formats strfmt.Registr // // Panics if the provided schema is invalid. func NewSchemaValidator(schema *spec.Schema, rootSchema interface{}, root string, formats strfmt.Registry, options ...Option) *SchemaValidator { + opts := new(SchemaValidatorOptions) + for _, o := range options { + o(opts) + } + + return newSchemaValidator(schema, rootSchema, root, formats, opts) +} + +func newSchemaValidator(schema *spec.Schema, rootSchema interface{}, root string, formats strfmt.Registry, opts *SchemaValidatorOptions) *SchemaValidator { if schema == nil { return nil } @@ -72,17 +81,26 @@ func NewSchemaValidator(schema *spec.Schema, rootSchema interface{}, root string panic(msg) } } - s := SchemaValidator{ - Path: root, - in: "body", - Schema: schema, - Root: rootSchema, - KnownFormats: formats, - Options: SchemaValidatorOptions{}} - for _, o := range options { - o(&s.Options) + + if opts == nil { + opts = new(SchemaValidatorOptions) + } + + var s *SchemaValidator + if opts.recycleValidators { + s = poolOfSchemaValidators.BorrowValidator() + } else { + s = new(SchemaValidator) } - s.validators = []valueValidator{ + + s.Path = root + s.in = "body" + s.Schema = schema + s.Root = rootSchema + s.Options = opts + s.KnownFormats = formats + + s.validators = [8]valueValidator{ s.typeValidator(), s.schemaPropsValidator(), s.stringValidator(), @@ -92,7 +110,8 @@ func NewSchemaValidator(schema *spec.Schema, rootSchema interface{}, root string s.commonValidator(), s.objectValidator(), } - return &s + + return s } // SetPath sets the path for this schema valdiator @@ -108,17 +127,39 @@ func (s *SchemaValidator) Applies(source interface{}, _ reflect.Kind) bool { // Validate validates the data against the schema func (s *SchemaValidator) Validate(data interface{}) *Result { - result := &Result{data: data} if s == nil { - return result + return emptyResult + } + + if s.Options.recycleValidators { + defer func() { + s.redeem() // one-time use validator + }() + } + + var result *Result + if s.Options.recycleResult { + result = poolOfResults.BorrowResult() + result.data = data + } else { + result = &Result{data: data} } - if s.Schema != nil { + + if s.Schema != nil && !s.Options.skipSchemataResult { result.addRootObjectSchemata(s.Schema) } if data == nil { + // early exit with minimal validation result.Merge(s.validators[0].Validate(data)) // type validator result.Merge(s.validators[6].Validate(data)) // common validator + + if s.Options.recycleValidators { + s.validators[0] = nil + s.validators[6] = nil + s.redeemChildren() + } + return result } @@ -164,14 +205,23 @@ func (s *SchemaValidator) Validate(data interface{}) *Result { kind = tpe.Kind() } - for _, v := range s.validators { + for idx, v := range s.validators { if !v.Applies(s.Schema, kind) { - debugLog("%T does not apply for %v", v, kind) + if s.Options.recycleValidators { + // Validate won't be called, so relinquish this validator + if redeemableChildren, ok := v.(interface{ redeemChildren() }); ok { + redeemableChildren.redeemChildren() + } + if redeemable, ok := v.(interface{ redeem() }); ok { + redeemable.redeem() + } + s.validators[idx] = nil // prevents further (unsafe) usage + } + continue } - err := v.Validate(d) - result.Merge(err) + result.Merge(v.Validate(d)) result.Inc() } result.Inc() @@ -180,81 +230,120 @@ func (s *SchemaValidator) Validate(data interface{}) *Result { } func (s *SchemaValidator) typeValidator() valueValidator { - return &typeValidator{Type: s.Schema.Type, Nullable: s.Schema.Nullable, Format: s.Schema.Format, In: s.in, Path: s.Path} + return newTypeValidator( + s.Path, + s.in, + s.Schema.Type, + s.Schema.Nullable, + s.Schema.Format, + s.Options, + ) } func (s *SchemaValidator) commonValidator() valueValidator { - return &basicCommonValidator{ - Path: s.Path, - In: s.in, - Enum: s.Schema.Enum, - } + return newBasicCommonValidator( + s.Path, + s.in, + s.Schema.Default, + s.Schema.Enum, + s.Options, + ) } func (s *SchemaValidator) sliceValidator() valueValidator { - return &schemaSliceValidator{ - Path: s.Path, - In: s.in, - MaxItems: s.Schema.MaxItems, - MinItems: s.Schema.MinItems, - UniqueItems: s.Schema.UniqueItems, - AdditionalItems: s.Schema.AdditionalItems, - Items: s.Schema.Items, - Root: s.Root, - KnownFormats: s.KnownFormats, - Options: s.Options, - } + return newSliceValidator( + s.Path, + s.in, + s.Schema.MaxItems, + s.Schema.MinItems, + s.Schema.UniqueItems, + s.Schema.AdditionalItems, + s.Schema.Items, + s.Root, + s.KnownFormats, + s.Options, + ) } func (s *SchemaValidator) numberValidator() valueValidator { - return &numberValidator{ - Path: s.Path, - In: s.in, - Default: s.Schema.Default, - MultipleOf: s.Schema.MultipleOf, - Maximum: s.Schema.Maximum, - ExclusiveMaximum: s.Schema.ExclusiveMaximum, - Minimum: s.Schema.Minimum, - ExclusiveMinimum: s.Schema.ExclusiveMinimum, - } + return newNumberValidator( + s.Path, + s.in, + s.Schema.Default, + s.Schema.MultipleOf, + s.Schema.Maximum, + s.Schema.ExclusiveMaximum, + s.Schema.Minimum, + s.Schema.ExclusiveMinimum, + "", + "", + s.Options, + ) } func (s *SchemaValidator) stringValidator() valueValidator { - return &stringValidator{ - Path: s.Path, - In: s.in, - MaxLength: s.Schema.MaxLength, - MinLength: s.Schema.MinLength, - Pattern: s.Schema.Pattern, - } + return newStringValidator( + s.Path, + s.in, + nil, + false, + false, + s.Schema.MaxLength, + s.Schema.MinLength, + s.Schema.Pattern, + s.Options, + ) } func (s *SchemaValidator) formatValidator() valueValidator { - return &formatValidator{ - Path: s.Path, - In: s.in, - Format: s.Schema.Format, - KnownFormats: s.KnownFormats, - } + return newFormatValidator( + s.Path, + s.in, + s.Schema.Format, + s.KnownFormats, + s.Options, + ) } func (s *SchemaValidator) schemaPropsValidator() valueValidator { sch := s.Schema - return newSchemaPropsValidator(s.Path, s.in, sch.AllOf, sch.OneOf, sch.AnyOf, sch.Not, sch.Dependencies, s.Root, s.KnownFormats, s.Options.Options()...) + return newSchemaPropsValidator( + s.Path, s.in, sch.AllOf, sch.OneOf, sch.AnyOf, sch.Not, sch.Dependencies, s.Root, s.KnownFormats, + s.Options, + ) } func (s *SchemaValidator) objectValidator() valueValidator { - return &objectValidator{ - Path: s.Path, - In: s.in, - MaxProperties: s.Schema.MaxProperties, - MinProperties: s.Schema.MinProperties, - Required: s.Schema.Required, - Properties: s.Schema.Properties, - AdditionalProperties: s.Schema.AdditionalProperties, - PatternProperties: s.Schema.PatternProperties, - Root: s.Root, - KnownFormats: s.KnownFormats, - Options: s.Options, + return newObjectValidator( + s.Path, + s.in, + s.Schema.MaxProperties, + s.Schema.MinProperties, + s.Schema.Required, + s.Schema.Properties, + s.Schema.AdditionalProperties, + s.Schema.PatternProperties, + s.Root, + s.KnownFormats, + s.Options, + ) +} + +func (s *SchemaValidator) redeem() { + poolOfSchemaValidators.RedeemValidator(s) +} + +func (s *SchemaValidator) redeemChildren() { + for i, validator := range s.validators { + if validator == nil { + continue + } + if redeemableChildren, ok := validator.(interface{ redeemChildren() }); ok { + redeemableChildren.redeemChildren() + } + if redeemable, ok := validator.(interface{ redeem() }); ok { + redeemable.redeem() + } + s.validators[i] = nil // free up allocated children if not in pool } } diff --git a/vendor/github.com/go-openapi/validate/schema_option.go b/vendor/github.com/go-openapi/validate/schema_option.go index 4b4879de8b..65eeebeaab 100644 --- a/vendor/github.com/go-openapi/validate/schema_option.go +++ b/vendor/github.com/go-openapi/validate/schema_option.go @@ -18,6 +18,9 @@ package validate type SchemaValidatorOptions struct { EnableObjectArrayTypeCheck bool EnableArrayMustHaveItemsCheck bool + recycleValidators bool + recycleResult bool + skipSchemataResult bool } // Option sets optional rules for schema validation @@ -45,10 +48,36 @@ func SwaggerSchema(enable bool) Option { } } -// Options returns current options +// WithRecycleValidators saves memory allocations and makes validators +// available for a single use of Validate() only. +// +// When a validator is recycled, called MUST not call the Validate() method twice. +func WithRecycleValidators(enable bool) Option { + return func(svo *SchemaValidatorOptions) { + svo.recycleValidators = enable + } +} + +func withRecycleResults(enable bool) Option { + return func(svo *SchemaValidatorOptions) { + svo.recycleResult = enable + } +} + +// WithSkipSchemataResult skips the deep audit payload stored in validation Result +func WithSkipSchemataResult(enable bool) Option { + return func(svo *SchemaValidatorOptions) { + svo.skipSchemataResult = enable + } +} + +// Options returns the current set of options func (svo SchemaValidatorOptions) Options() []Option { return []Option{ EnableObjectArrayTypeCheck(svo.EnableObjectArrayTypeCheck), EnableArrayMustHaveItemsCheck(svo.EnableArrayMustHaveItemsCheck), + WithRecycleValidators(svo.recycleValidators), + withRecycleResults(svo.recycleResult), + WithSkipSchemataResult(svo.skipSchemataResult), } } diff --git a/vendor/github.com/go-openapi/validate/schema_props.go b/vendor/github.com/go-openapi/validate/schema_props.go index 9bac3d29fb..bbea4a37db 100644 --- a/vendor/github.com/go-openapi/validate/schema_props.go +++ b/vendor/github.com/go-openapi/validate/schema_props.go @@ -30,78 +30,96 @@ type schemaPropsValidator struct { AnyOf []spec.Schema Not *spec.Schema Dependencies spec.Dependencies - anyOfValidators []SchemaValidator - allOfValidators []SchemaValidator - oneOfValidators []SchemaValidator + anyOfValidators []*SchemaValidator + allOfValidators []*SchemaValidator + oneOfValidators []*SchemaValidator notValidator *SchemaValidator Root interface{} KnownFormats strfmt.Registry - Options SchemaValidatorOptions + Options *SchemaValidatorOptions } func (s *schemaPropsValidator) SetPath(path string) { s.Path = path } -func newSchemaPropsValidator(path string, in string, allOf, oneOf, anyOf []spec.Schema, not *spec.Schema, deps spec.Dependencies, root interface{}, formats strfmt.Registry, options ...Option) *schemaPropsValidator { - anyValidators := make([]SchemaValidator, 0, len(anyOf)) - for _, v := range anyOf { - v := v - anyValidators = append(anyValidators, *NewSchemaValidator(&v, root, path, formats, options...)) +func newSchemaPropsValidator( + path string, in string, allOf, oneOf, anyOf []spec.Schema, not *spec.Schema, deps spec.Dependencies, root interface{}, formats strfmt.Registry, + opts *SchemaValidatorOptions) *schemaPropsValidator { + if opts == nil { + opts = new(SchemaValidatorOptions) } - allValidators := make([]SchemaValidator, 0, len(allOf)) - for _, v := range allOf { - v := v - allValidators = append(allValidators, *NewSchemaValidator(&v, root, path, formats, options...)) + + anyValidators := make([]*SchemaValidator, 0, len(anyOf)) + for i := range anyOf { + anyValidators = append(anyValidators, newSchemaValidator(&anyOf[i], root, path, formats, opts)) + } + allValidators := make([]*SchemaValidator, 0, len(allOf)) + for i := range allOf { + allValidators = append(allValidators, newSchemaValidator(&allOf[i], root, path, formats, opts)) } - oneValidators := make([]SchemaValidator, 0, len(oneOf)) - for _, v := range oneOf { - v := v - oneValidators = append(oneValidators, *NewSchemaValidator(&v, root, path, formats, options...)) + oneValidators := make([]*SchemaValidator, 0, len(oneOf)) + for i := range oneOf { + oneValidators = append(oneValidators, newSchemaValidator(&oneOf[i], root, path, formats, opts)) } var notValidator *SchemaValidator if not != nil { - notValidator = NewSchemaValidator(not, root, path, formats, options...) - } - - schOptions := &SchemaValidatorOptions{} - for _, o := range options { - o(schOptions) - } - return &schemaPropsValidator{ - Path: path, - In: in, - AllOf: allOf, - OneOf: oneOf, - AnyOf: anyOf, - Not: not, - Dependencies: deps, - anyOfValidators: anyValidators, - allOfValidators: allValidators, - oneOfValidators: oneValidators, - notValidator: notValidator, - Root: root, - KnownFormats: formats, - Options: *schOptions, + notValidator = newSchemaValidator(not, root, path, formats, opts) + } + + var s *schemaPropsValidator + if opts.recycleValidators { + s = poolOfSchemaPropsValidators.BorrowValidator() + } else { + s = new(schemaPropsValidator) } + + s.Path = path + s.In = in + s.AllOf = allOf + s.OneOf = oneOf + s.AnyOf = anyOf + s.Not = not + s.Dependencies = deps + s.anyOfValidators = anyValidators + s.allOfValidators = allValidators + s.oneOfValidators = oneValidators + s.notValidator = notValidator + s.Root = root + s.KnownFormats = formats + s.Options = opts + + return s } -func (s *schemaPropsValidator) Applies(source interface{}, kind reflect.Kind) bool { - r := reflect.TypeOf(source) == specSchemaType - debugLog("schema props validator for %q applies %t for %T (kind: %v)\n", s.Path, r, source, kind) - return r +func (s *schemaPropsValidator) Applies(source interface{}, _ reflect.Kind) bool { + _, isSchema := source.(*spec.Schema) + return isSchema } func (s *schemaPropsValidator) Validate(data interface{}) *Result { - mainResult := new(Result) + var mainResult *Result + if s.Options.recycleValidators { + mainResult = poolOfResults.BorrowResult() + } else { + mainResult = new(Result) + } // Intermediary error results // IMPORTANT! messages from underlying validators - keepResultAnyOf := new(Result) - keepResultOneOf := new(Result) - keepResultAllOf := new(Result) + keepResultAnyOf := poolOfResults.BorrowResult() + keepResultOneOf := poolOfResults.BorrowResult() + keepResultAllOf := poolOfResults.BorrowResult() + + if s.Options.recycleValidators { + defer func() { + s.redeem() + + // results are redeemed when merged + }() + } // Validates at least one in anyOf schemas var firstSuccess *Result @@ -115,10 +133,9 @@ func (s *schemaPropsValidator) Validate(data interface{}) *Result { if result.IsValid() { bestFailures = nil succeededOnce = true - if firstSuccess == nil { - firstSuccess = result - } - keepResultAnyOf = new(Result) + firstSuccess = result + _ = keepResultAnyOf.cleared() + break } // MatchCount is used to select errors from the schema with most positive checks @@ -132,6 +149,9 @@ func (s *schemaPropsValidator) Validate(data interface{}) *Result { } if bestFailures != nil { mainResult.Merge(bestFailures) + if firstSuccess != nil && firstSuccess.wantsRedeemOnMerge { + poolOfResults.RedeemResult(firstSuccess) + } } else if firstSuccess != nil { mainResult.Merge(firstSuccess) } @@ -153,7 +173,7 @@ func (s *schemaPropsValidator) Validate(data interface{}) *Result { if firstSuccess == nil { firstSuccess = result } - keepResultOneOf = new(Result) + _ = keepResultOneOf.cleared() continue } // MatchCount is used to select errors from the schema with most positive checks @@ -174,8 +194,14 @@ func (s *schemaPropsValidator) Validate(data interface{}) *Result { if bestFailures != nil { mainResult.Merge(bestFailures) } + if firstSuccess != nil && firstSuccess.wantsRedeemOnMerge { + poolOfResults.RedeemResult(firstSuccess) + } } else if firstSuccess != nil { mainResult.Merge(firstSuccess) + if bestFailures != nil && bestFailures.wantsRedeemOnMerge { + poolOfResults.RedeemResult(bestFailures) + } } } @@ -187,7 +213,6 @@ func (s *schemaPropsValidator) Validate(data interface{}) *Result { result := allOfSchema.Validate(data) // We keep inner IMPORTANT! errors no matter what MatchCount tells us keepResultAllOf.Merge(result.keepRelevantErrors()) - // keepResultAllOf.Merge(result) if result.IsValid() { validated++ } @@ -218,7 +243,9 @@ func (s *schemaPropsValidator) Validate(data interface{}) *Result { if dep, ok := s.Dependencies[key]; ok { if dep.Schema != nil { - mainResult.Merge(NewSchemaValidator(dep.Schema, s.Root, s.Path+"."+key, s.KnownFormats, s.Options.Options()...).Validate(data)) + mainResult.Merge( + newSchemaValidator(dep.Schema, s.Root, s.Path+"."+key, s.KnownFormats, s.Options).Validate(data), + ) continue } @@ -238,3 +265,31 @@ func (s *schemaPropsValidator) Validate(data interface{}) *Result { // plus, if any, composite errors which may explain special cases (tagged as IMPORTANT!). return mainResult.Merge(keepResultAllOf, keepResultOneOf, keepResultAnyOf) } + +func (s *schemaPropsValidator) redeem() { + poolOfSchemaPropsValidators.RedeemValidator(s) +} + +func (s *schemaPropsValidator) redeemChildren() { + for _, v := range s.anyOfValidators { + v.redeemChildren() + v.redeem() + } + s.anyOfValidators = nil + for _, v := range s.allOfValidators { + v.redeemChildren() + v.redeem() + } + s.allOfValidators = nil + for _, v := range s.oneOfValidators { + v.redeemChildren() + v.redeem() + } + s.oneOfValidators = nil + + if s.notValidator != nil { + s.notValidator.redeemChildren() + s.notValidator.redeem() + s.notValidator = nil + } +} diff --git a/vendor/github.com/go-openapi/validate/slice_validator.go b/vendor/github.com/go-openapi/validate/slice_validator.go index aa429f5184..e974d3e052 100644 --- a/vendor/github.com/go-openapi/validate/slice_validator.go +++ b/vendor/github.com/go-openapi/validate/slice_validator.go @@ -32,7 +32,36 @@ type schemaSliceValidator struct { Items *spec.SchemaOrArray Root interface{} KnownFormats strfmt.Registry - Options SchemaValidatorOptions + Options *SchemaValidatorOptions +} + +func newSliceValidator(path, in string, + maxItems, minItems *int64, uniqueItems bool, + additionalItems *spec.SchemaOrBool, items *spec.SchemaOrArray, + root interface{}, formats strfmt.Registry, opts *SchemaValidatorOptions) *schemaSliceValidator { + if opts == nil { + opts = new(SchemaValidatorOptions) + } + + var v *schemaSliceValidator + if opts.recycleValidators { + v = poolOfSliceValidators.BorrowValidator() + } else { + v = new(schemaSliceValidator) + } + + v.Path = path + v.In = in + v.MaxItems = maxItems + v.MinItems = minItems + v.UniqueItems = uniqueItems + v.AdditionalItems = additionalItems + v.Items = items + v.Root = root + v.KnownFormats = formats + v.Options = opts + + return v } func (s *schemaSliceValidator) SetPath(path string) { @@ -46,7 +75,18 @@ func (s *schemaSliceValidator) Applies(source interface{}, kind reflect.Kind) bo } func (s *schemaSliceValidator) Validate(data interface{}) *Result { - result := new(Result) + if s.Options.recycleValidators { + defer func() { + s.redeem() + }() + } + + var result *Result + if s.Options.recycleResult { + result = poolOfResults.BorrowResult() + } else { + result = new(Result) + } if data == nil { return result } @@ -54,8 +94,8 @@ func (s *schemaSliceValidator) Validate(data interface{}) *Result { size := val.Len() if s.Items != nil && s.Items.Schema != nil { - validator := NewSchemaValidator(s.Items.Schema, s.Root, s.Path, s.KnownFormats, s.Options.Options()...) for i := 0; i < size; i++ { + validator := newSchemaValidator(s.Items.Schema, s.Root, s.Path, s.KnownFormats, s.Options) validator.SetPath(fmt.Sprintf("%s.%d", s.Path, i)) value := val.Index(i) result.mergeForSlice(val, i, validator.Validate(value.Interface())) @@ -66,10 +106,11 @@ func (s *schemaSliceValidator) Validate(data interface{}) *Result { if s.Items != nil && len(s.Items.Schemas) > 0 { itemsSize = len(s.Items.Schemas) for i := 0; i < itemsSize; i++ { - validator := NewSchemaValidator(&s.Items.Schemas[i], s.Root, fmt.Sprintf("%s.%d", s.Path, i), s.KnownFormats, s.Options.Options()...) - if val.Len() <= i { + if size <= i { break } + + validator := newSchemaValidator(&s.Items.Schemas[i], s.Root, fmt.Sprintf("%s.%d", s.Path, i), s.KnownFormats, s.Options) result.mergeForSlice(val, i, validator.Validate(val.Index(i).Interface())) } } @@ -79,7 +120,7 @@ func (s *schemaSliceValidator) Validate(data interface{}) *Result { } if s.AdditionalItems.Schema != nil { for i := itemsSize; i < size-itemsSize+1; i++ { - validator := NewSchemaValidator(s.AdditionalItems.Schema, s.Root, fmt.Sprintf("%s.%d", s.Path, i), s.KnownFormats, s.Options.Options()...) + validator := newSchemaValidator(s.AdditionalItems.Schema, s.Root, fmt.Sprintf("%s.%d", s.Path, i), s.KnownFormats, s.Options) result.mergeForSlice(val, i, validator.Validate(val.Index(i).Interface())) } } @@ -103,3 +144,7 @@ func (s *schemaSliceValidator) Validate(data interface{}) *Result { result.Inc() return result } + +func (s *schemaSliceValidator) redeem() { + poolOfSliceValidators.RedeemValidator(s) +} diff --git a/vendor/github.com/go-openapi/validate/spec.go b/vendor/github.com/go-openapi/validate/spec.go index 30168b7109..ee322a2df1 100644 --- a/vendor/github.com/go-openapi/validate/spec.go +++ b/vendor/github.com/go-openapi/validate/spec.go @@ -53,25 +53,38 @@ func Spec(doc *loads.Document, formats strfmt.Registry) error { // SpecValidator validates a swagger 2.0 spec type SpecValidator struct { - schema *spec.Schema // swagger 2.0 schema - spec *loads.Document - analyzer *analysis.Spec - expanded *loads.Document - KnownFormats strfmt.Registry - Options Opts // validation options + schema *spec.Schema // swagger 2.0 schema + spec *loads.Document + analyzer *analysis.Spec + expanded *loads.Document + KnownFormats strfmt.Registry + Options Opts // validation options + schemaOptions *SchemaValidatorOptions } // NewSpecValidator creates a new swagger spec validator instance func NewSpecValidator(schema *spec.Schema, formats strfmt.Registry) *SpecValidator { + // schema options that apply to all called validators + schemaOptions := new(SchemaValidatorOptions) + for _, o := range []Option{ + SwaggerSchema(true), + WithRecycleValidators(true), + withRecycleResults(true), + } { + o(schemaOptions) + } + return &SpecValidator{ - schema: schema, - KnownFormats: formats, - Options: defaultOpts, + schema: schema, + KnownFormats: formats, + Options: defaultOpts, + schemaOptions: schemaOptions, } } // Validate validates the swagger spec func (s *SpecValidator) Validate(data interface{}) (*Result, *Result) { + s.schemaOptions.skipSchemataResult = s.Options.SkipSchemataResult var sd *loads.Document errs, warnings := new(Result), new(Result) @@ -85,11 +98,8 @@ func (s *SpecValidator) Validate(data interface{}) (*Result, *Result) { s.spec = sd s.analyzer = analysis.New(sd.Spec()) - // Swagger schema validator - schv := NewSchemaValidator(s.schema, nil, "", s.KnownFormats, SwaggerSchema(true)) - var obj interface{} - // Raw spec unmarshalling errors + var obj interface{} if err := json.Unmarshal(sd.Raw(), &obj); err != nil { // NOTE: under normal conditions, the *load.Document has been already unmarshalled // So this one is just a paranoid check on the behavior of the spec package @@ -103,6 +113,8 @@ func (s *SpecValidator) Validate(data interface{}) (*Result, *Result) { warnings.AddErrors(errs.Warnings...) }() + // Swagger schema validator + schv := newSchemaValidator(s.schema, nil, "", s.KnownFormats, s.schemaOptions) errs.Merge(schv.Validate(obj)) // error - // There may be a point in continuing to try and determine more accurate errors if !s.Options.ContinueOnErrors && errs.HasErrors() { @@ -130,13 +142,13 @@ func (s *SpecValidator) Validate(data interface{}) (*Result, *Result) { } // Values provided as default MUST validate their schema - df := &defaultValidator{SpecValidator: s} + df := &defaultValidator{SpecValidator: s, schemaOptions: s.schemaOptions} errs.Merge(df.Validate()) // Values provided as examples MUST validate their schema // Value provided as examples in a response without schema generate a warning // Known limitations: examples in responses for mime type not application/json are ignored (warning) - ex := &exampleValidator{SpecValidator: s} + ex := &exampleValidator{SpecValidator: s, schemaOptions: s.schemaOptions} errs.Merge(ex.Validate()) errs.Merge(s.validateNonEmptyPathParamNames()) @@ -148,22 +160,27 @@ func (s *SpecValidator) Validate(data interface{}) (*Result, *Result) { } func (s *SpecValidator) validateNonEmptyPathParamNames() *Result { - res := new(Result) + res := poolOfResults.BorrowResult() if s.spec.Spec().Paths == nil { // There is no Paths object: error res.AddErrors(noValidPathMsg()) - } else { - if s.spec.Spec().Paths.Paths == nil { - // Paths may be empty: warning - res.AddWarnings(noValidPathMsg()) - } else { - for k := range s.spec.Spec().Paths.Paths { - if strings.Contains(k, "{}") { - res.AddErrors(emptyPathParameterMsg(k)) - } - } + + return res + } + + if s.spec.Spec().Paths.Paths == nil { + // Paths may be empty: warning + res.AddWarnings(noValidPathMsg()) + + return res + } + + for k := range s.spec.Spec().Paths.Paths { + if strings.Contains(k, "{}") { + res.AddErrors(emptyPathParameterMsg(k)) } } + return res } @@ -177,7 +194,7 @@ func (s *SpecValidator) validateDuplicateOperationIDs() *Result { // fallback on possible incomplete picture because of previous errors analyzer = s.analyzer } - res := new(Result) + res := poolOfResults.BorrowResult() known := make(map[string]int) for _, v := range analyzer.OperationIDs() { if v != "" { @@ -199,7 +216,7 @@ type dupProp struct { func (s *SpecValidator) validateDuplicatePropertyNames() *Result { // definition can't declare a property that's already defined by one of its ancestors - res := new(Result) + res := poolOfResults.BorrowResult() for k, sch := range s.spec.Spec().Definitions { if len(sch.AllOf) == 0 { continue @@ -248,7 +265,7 @@ func (s *SpecValidator) validateSchemaPropertyNames(nm string, sch spec.Schema, schn := nm schc := &sch - res := new(Result) + res := poolOfResults.BorrowResult() for schc.Ref.String() != "" { // gather property names @@ -285,7 +302,7 @@ func (s *SpecValidator) validateSchemaPropertyNames(nm string, sch spec.Schema, } func (s *SpecValidator) validateCircularAncestry(nm string, sch spec.Schema, knowns map[string]struct{}) ([]string, *Result) { - res := new(Result) + res := poolOfResults.BorrowResult() if sch.Ref.String() == "" && len(sch.AllOf) == 0 { // Safeguard. We should not be able to actually get there return nil, res @@ -335,7 +352,7 @@ func (s *SpecValidator) validateCircularAncestry(nm string, sch spec.Schema, kno func (s *SpecValidator) validateItems() *Result { // validate parameter, items, schema and response objects for presence of item if type is array - res := new(Result) + res := poolOfResults.BorrowResult() for method, pi := range s.analyzer.Operations() { for path, op := range pi { @@ -394,7 +411,7 @@ func (s *SpecValidator) validateItems() *Result { // Verifies constraints on array type func (s *SpecValidator) validateSchemaItems(schema spec.Schema, prefix, opID string) *Result { - res := new(Result) + res := poolOfResults.BorrowResult() if !schema.Type.Contains(arrayType) { return res } @@ -418,7 +435,7 @@ func (s *SpecValidator) validateSchemaItems(schema spec.Schema, prefix, opID str func (s *SpecValidator) validatePathParamPresence(path string, fromPath, fromOperation []string) *Result { // Each defined operation path parameters must correspond to a named element in the API's path pattern. // (For example, you cannot have a path parameter named id for the following path /pets/{petId} but you must have a path parameter named petId.) - res := new(Result) + res := poolOfResults.BorrowResult() for _, l := range fromPath { var matched bool for _, r := range fromOperation { @@ -474,7 +491,7 @@ func (s *SpecValidator) validateReferencedParameters() *Result { if len(expected) == 0 { return nil } - result := new(Result) + result := poolOfResults.BorrowResult() for k := range expected { result.AddWarnings(unusedParamMsg(k)) } @@ -499,7 +516,7 @@ func (s *SpecValidator) validateReferencedResponses() *Result { if len(expected) == 0 { return nil } - result := new(Result) + result := poolOfResults.BorrowResult() for k := range expected { result.AddWarnings(unusedResponseMsg(k)) } @@ -534,7 +551,7 @@ func (s *SpecValidator) validateReferencedDefinitions() *Result { func (s *SpecValidator) validateRequiredDefinitions() *Result { // Each property listed in the required array must be defined in the properties of the model - res := new(Result) + res := poolOfResults.BorrowResult() DEFINITIONS: for d, schema := range s.spec.Spec().Definitions { @@ -553,7 +570,7 @@ DEFINITIONS: func (s *SpecValidator) validateRequiredProperties(path, in string, v *spec.Schema) *Result { // Takes care of recursive property definitions, which may be nested in additionalProperties schemas - res := new(Result) + res := poolOfResults.BorrowResult() propertyMatch := false patternMatch := false additionalPropertiesMatch := false @@ -619,7 +636,7 @@ func (s *SpecValidator) validateParameters() *Result { // - parameters with pattern property must specify valid patterns // - $ref in parameters must resolve // - path param must be required - res := new(Result) + res := poolOfResults.BorrowResult() rexGarbledPathSegment := mustCompileRegexp(`.*[{}\s]+.*`) for method, pi := range s.expandedAnalyzer().Operations() { methodPaths := make(map[string]map[string]string) @@ -664,8 +681,8 @@ func (s *SpecValidator) validateParameters() *Result { } for _, pr := range paramHelp.safeExpandedParamsFor(path, method, op.ID, res, s) { - // An expanded parameter must validate its schema (an unexpanded $ref always pass high-level schema validation) - schv := NewSchemaValidator(¶mSchema, s.schema, fmt.Sprintf("%s.%s.parameters.%s", path, method, pr.Name), s.KnownFormats, SwaggerSchema(true)) + // An expanded parameter must validate its schema (an unexpanded $ref always passes high-level schema validation) + schv := newSchemaValidator(¶mSchema, s.schema, fmt.Sprintf("%s.%s.parameters.%s", path, method, pr.Name), s.KnownFormats, s.schemaOptions) obj := swag.ToDynamicJSON(pr) paramValidationResult := schv.Validate(obj) res.Merge(paramValidationResult) @@ -751,7 +768,7 @@ func (s *SpecValidator) validateParameters() *Result { func (s *SpecValidator) validateReferencesValid() *Result { // each reference must point to a valid object - res := new(Result) + res := poolOfResults.BorrowResult() for _, r := range s.analyzer.AllRefs() { if !r.IsValidURI(s.spec.SpecFilePath()) { // Safeguard - spec should always yield a valid URI res.AddErrors(invalidRefMsg(r.String())) @@ -777,7 +794,7 @@ func (s *SpecValidator) checkUniqueParams(path, method string, op *spec.Operatio // However, there are some issues with such a factorization: // - analysis does not seem to fully expand params // - param keys may be altered by x-go-name - res := new(Result) + res := poolOfResults.BorrowResult() pnames := make(map[string]struct{}) if op.Parameters != nil { // Safeguard diff --git a/vendor/github.com/go-openapi/validate/spec_messages.go b/vendor/github.com/go-openapi/validate/spec_messages.go index 5398679bff..6d1f0f819c 100644 --- a/vendor/github.com/go-openapi/validate/spec_messages.go +++ b/vendor/github.com/go-openapi/validate/spec_messages.go @@ -187,6 +187,8 @@ const ( // UnusedResponseWarning ... UnusedResponseWarning = "response %q is not used anywhere" + + InvalidObject = "expected an object in %q.%s" ) // Additional error codes @@ -347,6 +349,9 @@ func invalidParameterDefinitionAsSchemaMsg(path, method, operationID string) err func parameterValidationTypeMismatchMsg(param, path, typ string) errors.Error { return errors.New(errors.CompositeErrorCode, ParamValidationTypeMismatch, param, path, typ) } +func invalidObjectMsg(path, in string) errors.Error { + return errors.New(errors.CompositeErrorCode, InvalidObject, path, in) +} // disabled // diff --git a/vendor/github.com/go-openapi/validate/type.go b/vendor/github.com/go-openapi/validate/type.go index c7abf380b9..5647a4429e 100644 --- a/vendor/github.com/go-openapi/validate/type.go +++ b/vendor/github.com/go-openapi/validate/type.go @@ -25,11 +25,34 @@ import ( ) type typeValidator struct { + Path string + In string Type spec.StringOrArray Nullable bool Format string - In string - Path string + Options *SchemaValidatorOptions +} + +func newTypeValidator(path, in string, typ spec.StringOrArray, nullable bool, format string, opts *SchemaValidatorOptions) *typeValidator { + if opts == nil { + opts = new(SchemaValidatorOptions) + } + + var t *typeValidator + if opts.recycleValidators { + t = poolOfTypeValidators.BorrowValidator() + } else { + t = new(typeValidator) + } + + t.Path = path + t.In = in + t.Type = typ + t.Nullable = nullable + t.Format = format + t.Options = opts + + return t } func (t *typeValidator) schemaInfoForType(data interface{}) (string, string) { @@ -125,23 +148,33 @@ func (t *typeValidator) SetPath(path string) { t.Path = path } -func (t *typeValidator) Applies(source interface{}, kind reflect.Kind) bool { +func (t *typeValidator) Applies(source interface{}, _ reflect.Kind) bool { // typeValidator applies to Schema, Parameter and Header objects - stpe := reflect.TypeOf(source) - r := (len(t.Type) > 0 || t.Format != "") && (stpe == specSchemaType || stpe == specParameterType || stpe == specHeaderType) - debugLog("type validator for %q applies %t for %T (kind: %v)\n", t.Path, r, source, kind) - return r + switch source.(type) { + case *spec.Schema: + case *spec.Parameter: + case *spec.Header: + default: + return false + } + + return (len(t.Type) > 0 || t.Format != "") } func (t *typeValidator) Validate(data interface{}) *Result { - result := new(Result) - result.Inc() + if t.Options.recycleValidators { + defer func() { + t.redeem() + }() + } + if data == nil { // nil or zero value for the passed structure require Type: null if len(t.Type) > 0 && !t.Type.Contains(nullType) && !t.Nullable { // TODO: if a property is not required it also passes this - return errorHelp.sErr(errors.InvalidType(t.Path, t.In, strings.Join(t.Type, ","), nullType)) + return errorHelp.sErr(errors.InvalidType(t.Path, t.In, strings.Join(t.Type, ","), nullType), t.Options.recycleResult) } - return result + + return emptyResult } // check if the type matches, should be used in every validator chain as first item @@ -151,8 +184,6 @@ func (t *typeValidator) Validate(data interface{}) *Result { // infer schema type (JSON) and format from passed data type schType, format := t.schemaInfoForType(data) - debugLog("path: %s, schType: %s, format: %s, expType: %s, expFmt: %s, kind: %s", t.Path, schType, format, t.Type, t.Format, val.Kind().String()) - // check numerical types // TODO: check unsigned ints // TODO: check json.Number (see schema.go) @@ -163,15 +194,20 @@ func (t *typeValidator) Validate(data interface{}) *Result { if kind != reflect.String && kind != reflect.Slice && t.Format != "" && !(t.Type.Contains(schType) || format == t.Format || isFloatInt || isIntFloat || isLowerInt || isLowerFloat) { // TODO: test case - return errorHelp.sErr(errors.InvalidType(t.Path, t.In, t.Format, format)) + return errorHelp.sErr(errors.InvalidType(t.Path, t.In, t.Format, format), t.Options.recycleResult) } if !(t.Type.Contains(numberType) || t.Type.Contains(integerType)) && t.Format != "" && (kind == reflect.String || kind == reflect.Slice) { - return result + return emptyResult } if !(t.Type.Contains(schType) || isFloatInt || isIntFloat) { - return errorHelp.sErr(errors.InvalidType(t.Path, t.In, strings.Join(t.Type, ","), schType)) + return errorHelp.sErr(errors.InvalidType(t.Path, t.In, strings.Join(t.Type, ","), schType), t.Options.recycleResult) } - return result + + return emptyResult +} + +func (t *typeValidator) redeem() { + poolOfTypeValidators.RedeemValidator(t) } diff --git a/vendor/github.com/go-openapi/validate/validator.go b/vendor/github.com/go-openapi/validate/validator.go index ab4f718b5b..aa322643c3 100644 --- a/vendor/github.com/go-openapi/validate/validator.go +++ b/vendor/github.com/go-openapi/validate/validator.go @@ -39,20 +39,31 @@ type itemsValidator struct { root interface{} path string in string - validators []valueValidator + validators [6]valueValidator KnownFormats strfmt.Registry + Options *SchemaValidatorOptions } -func newItemsValidator(path, in string, items *spec.Items, root interface{}, formats strfmt.Registry) *itemsValidator { - iv := &itemsValidator{path: path, in: in, items: items, root: root, KnownFormats: formats} - iv.validators = []valueValidator{ - &typeValidator{ - Type: spec.StringOrArray([]string{items.Type}), - Nullable: items.Nullable, - Format: items.Format, - In: in, - Path: path, - }, +func newItemsValidator(path, in string, items *spec.Items, root interface{}, formats strfmt.Registry, opts *SchemaValidatorOptions) *itemsValidator { + if opts == nil { + opts = new(SchemaValidatorOptions) + } + + var iv *itemsValidator + if opts.recycleValidators { + iv = poolOfItemsValidators.BorrowValidator() + } else { + iv = new(itemsValidator) + } + + iv.path = path + iv.in = in + iv.items = items + iv.root = root + iv.KnownFormats = formats + iv.Options = opts + iv.validators = [6]valueValidator{ + iv.typeValidator(), iv.stringValidator(), iv.formatValidator(), iv.numberValidator(), @@ -63,77 +74,144 @@ func newItemsValidator(path, in string, items *spec.Items, root interface{}, for } func (i *itemsValidator) Validate(index int, data interface{}) *Result { + if i.Options.recycleValidators { + defer func() { + i.redeemChildren() + i.redeem() + }() + } + tpe := reflect.TypeOf(data) kind := tpe.Kind() - mainResult := new(Result) + var mainResult *Result + if i.Options.recycleResult { + mainResult = poolOfResults.BorrowResult() + } else { + mainResult = new(Result) + } + path := fmt.Sprintf("%s.%d", i.path, index) - for _, validator := range i.validators { - validator.SetPath(path) - if validator.Applies(i.root, kind) { - result := validator.Validate(data) - mainResult.Merge(result) - mainResult.Inc() - if result != nil && result.HasErrors() { - return mainResult + for idx, validator := range i.validators { + if !validator.Applies(i.root, kind) { + if i.Options.recycleValidators { + // Validate won't be called, so relinquish this validator + if redeemableChildren, ok := validator.(interface{ redeemChildren() }); ok { + redeemableChildren.redeemChildren() + } + if redeemable, ok := validator.(interface{ redeem() }); ok { + redeemable.redeem() + } + i.validators[idx] = nil // prevents further (unsafe) usage } + + continue + } + + validator.SetPath(path) + result := validator.Validate(data) + mainResult.Merge(result) + mainResult.Inc() + if result != nil && result.HasErrors() { + break } } + return mainResult } +func (i *itemsValidator) typeValidator() valueValidator { + return newTypeValidator( + i.path, + i.in, + spec.StringOrArray([]string{i.items.Type}), + i.items.Nullable, + i.items.Format, + i.Options, + ) +} + func (i *itemsValidator) commonValidator() valueValidator { - return &basicCommonValidator{ - In: i.in, - Default: i.items.Default, - Enum: i.items.Enum, - } + return newBasicCommonValidator( + "", + i.in, + i.items.Default, + i.items.Enum, + i.Options, + ) } func (i *itemsValidator) sliceValidator() valueValidator { - return &basicSliceValidator{ - In: i.in, - Default: i.items.Default, - MaxItems: i.items.MaxItems, - MinItems: i.items.MinItems, - UniqueItems: i.items.UniqueItems, - Source: i.root, - Items: i.items.Items, - KnownFormats: i.KnownFormats, - } + return newBasicSliceValidator( + "", + i.in, + i.items.Default, + i.items.MaxItems, + i.items.MinItems, + i.items.UniqueItems, + i.items.Items, + i.root, + i.KnownFormats, + i.Options, + ) } func (i *itemsValidator) numberValidator() valueValidator { - return &numberValidator{ - In: i.in, - Default: i.items.Default, - MultipleOf: i.items.MultipleOf, - Maximum: i.items.Maximum, - ExclusiveMaximum: i.items.ExclusiveMaximum, - Minimum: i.items.Minimum, - ExclusiveMinimum: i.items.ExclusiveMinimum, - Type: i.items.Type, - Format: i.items.Format, - } + return newNumberValidator( + "", + i.in, + i.items.Default, + i.items.MultipleOf, + i.items.Maximum, + i.items.ExclusiveMaximum, + i.items.Minimum, + i.items.ExclusiveMinimum, + i.items.Type, + i.items.Format, + i.Options, + ) } func (i *itemsValidator) stringValidator() valueValidator { - return &stringValidator{ - In: i.in, - Default: i.items.Default, - MaxLength: i.items.MaxLength, - MinLength: i.items.MinLength, - Pattern: i.items.Pattern, - AllowEmptyValue: false, - } + return newStringValidator( + "", + i.in, + i.items.Default, + false, // Required + false, // AllowEmpty + i.items.MaxLength, + i.items.MinLength, + i.items.Pattern, + i.Options, + ) } func (i *itemsValidator) formatValidator() valueValidator { - return &formatValidator{ - In: i.in, - //Default: i.items.Default, - Format: i.items.Format, - KnownFormats: i.KnownFormats, + return newFormatValidator( + "", + i.in, + i.items.Format, + i.KnownFormats, + i.Options, + ) +} + +func (i *itemsValidator) redeem() { + poolOfItemsValidators.RedeemValidator(i) +} + +func (i *itemsValidator) redeemChildren() { + for idx, validator := range i.validators { + if validator == nil { + continue + } + if redeemableChildren, ok := validator.(interface{ redeemChildren() }); ok { + redeemableChildren.redeemChildren() + } + if redeemable, ok := validator.(interface{ redeem() }); ok { + redeemable.redeem() + } + i.validators[idx] = nil // free up allocated children if not in pool } } @@ -142,6 +220,28 @@ type basicCommonValidator struct { In string Default interface{} Enum []interface{} + Options *SchemaValidatorOptions +} + +func newBasicCommonValidator(path, in string, def interface{}, enum []interface{}, opts *SchemaValidatorOptions) *basicCommonValidator { + if opts == nil { + opts = new(SchemaValidatorOptions) + } + + var b *basicCommonValidator + if opts.recycleValidators { + b = poolOfBasicCommonValidators.BorrowValidator() + } else { + b = new(basicCommonValidator) + } + + b.Path = path + b.In = in + b.Default = def + b.Enum = enum + b.Options = opts + + return b } func (b *basicCommonValidator) SetPath(path string) { @@ -152,255 +252,458 @@ func (b *basicCommonValidator) Applies(source interface{}, _ reflect.Kind) bool switch source.(type) { case *spec.Parameter, *spec.Schema, *spec.Header: return true + default: + return false } - return false } func (b *basicCommonValidator) Validate(data interface{}) (res *Result) { - if len(b.Enum) > 0 { - for _, enumValue := range b.Enum { - actualType := reflect.TypeOf(enumValue) - if actualType != nil { // Safeguard - expectedValue := reflect.ValueOf(data) - if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) { - if reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), enumValue) { - return nil - } - } - } + if b.Options.recycleValidators { + defer func() { + b.redeem() + }() + } + + if len(b.Enum) == 0 { + return nil + } + + for _, enumValue := range b.Enum { + actualType := reflect.TypeOf(enumValue) + if actualType == nil { // Safeguard + continue + } + + expectedValue := reflect.ValueOf(data) + if expectedValue.IsValid() && + expectedValue.Type().ConvertibleTo(actualType) && + reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), enumValue) { + return nil } - return errorHelp.sErr(errors.EnumFail(b.Path, b.In, data, b.Enum)) } - return nil + + return errorHelp.sErr(errors.EnumFail(b.Path, b.In, data, b.Enum), b.Options.recycleResult) +} + +func (b *basicCommonValidator) redeem() { + poolOfBasicCommonValidators.RedeemValidator(b) } // A HeaderValidator has very limited subset of validations to apply type HeaderValidator struct { name string header *spec.Header - validators []valueValidator + validators [6]valueValidator KnownFormats strfmt.Registry + Options *SchemaValidatorOptions } // NewHeaderValidator creates a new header validator object -func NewHeaderValidator(name string, header *spec.Header, formats strfmt.Registry) *HeaderValidator { - p := &HeaderValidator{name: name, header: header, KnownFormats: formats} - p.validators = []valueValidator{ - &typeValidator{ - Type: spec.StringOrArray([]string{header.Type}), - Nullable: header.Nullable, - Format: header.Format, - In: "header", - Path: name, - }, +func NewHeaderValidator(name string, header *spec.Header, formats strfmt.Registry, options ...Option) *HeaderValidator { + opts := new(SchemaValidatorOptions) + for _, o := range options { + o(opts) + } + + return newHeaderValidator(name, header, formats, opts) +} + +func newHeaderValidator(name string, header *spec.Header, formats strfmt.Registry, opts *SchemaValidatorOptions) *HeaderValidator { + if opts == nil { + opts = new(SchemaValidatorOptions) + } + + var p *HeaderValidator + if opts.recycleValidators { + p = poolOfHeaderValidators.BorrowValidator() + } else { + p = new(HeaderValidator) + } + + p.name = name + p.header = header + p.KnownFormats = formats + p.Options = opts + p.validators = [6]valueValidator{ + newTypeValidator( + name, + "header", + spec.StringOrArray([]string{header.Type}), + header.Nullable, + header.Format, + p.Options, + ), p.stringValidator(), p.formatValidator(), p.numberValidator(), p.sliceValidator(), p.commonValidator(), } + return p } // Validate the value of the header against its schema func (p *HeaderValidator) Validate(data interface{}) *Result { - result := new(Result) + if p.Options.recycleValidators { + defer func() { + p.redeemChildren() + p.redeem() + }() + } + + if data == nil { + return nil + } + + var result *Result + if p.Options.recycleResult { + result = poolOfResults.BorrowResult() + } else { + result = new(Result) + } + tpe := reflect.TypeOf(data) kind := tpe.Kind() - for _, validator := range p.validators { - if validator.Applies(p.header, kind) { - if err := validator.Validate(data); err != nil { - result.Merge(err) - if err.HasErrors() { - return result + for idx, validator := range p.validators { + if !validator.Applies(p.header, kind) { + if p.Options.recycleValidators { + // Validate won't be called, so relinquish this validator + if redeemableChildren, ok := validator.(interface{ redeemChildren() }); ok { + redeemableChildren.redeemChildren() + } + if redeemable, ok := validator.(interface{ redeem() }); ok { + redeemable.redeem() } + p.validators[idx] = nil // prevents further (unsafe) usage + } + + continue + } + + if err := validator.Validate(data); err != nil { + result.Merge(err) + if err.HasErrors() { + break } } } - return nil + return result } func (p *HeaderValidator) commonValidator() valueValidator { - return &basicCommonValidator{ - Path: p.name, - In: "response", - Default: p.header.Default, - Enum: p.header.Enum, - } + return newBasicCommonValidator( + p.name, + "response", + p.header.Default, + p.header.Enum, + p.Options, + ) } func (p *HeaderValidator) sliceValidator() valueValidator { - return &basicSliceValidator{ - Path: p.name, - In: "response", - Default: p.header.Default, - MaxItems: p.header.MaxItems, - MinItems: p.header.MinItems, - UniqueItems: p.header.UniqueItems, - Items: p.header.Items, - Source: p.header, - KnownFormats: p.KnownFormats, - } + return newBasicSliceValidator( + p.name, + "response", + p.header.Default, + p.header.MaxItems, + p.header.MinItems, + p.header.UniqueItems, + p.header.Items, + p.header, + p.KnownFormats, + p.Options, + ) } func (p *HeaderValidator) numberValidator() valueValidator { - return &numberValidator{ - Path: p.name, - In: "response", - Default: p.header.Default, - MultipleOf: p.header.MultipleOf, - Maximum: p.header.Maximum, - ExclusiveMaximum: p.header.ExclusiveMaximum, - Minimum: p.header.Minimum, - ExclusiveMinimum: p.header.ExclusiveMinimum, - Type: p.header.Type, - Format: p.header.Format, - } + return newNumberValidator( + p.name, + "response", + p.header.Default, + p.header.MultipleOf, + p.header.Maximum, + p.header.ExclusiveMaximum, + p.header.Minimum, + p.header.ExclusiveMinimum, + p.header.Type, + p.header.Format, + p.Options, + ) } func (p *HeaderValidator) stringValidator() valueValidator { - return &stringValidator{ - Path: p.name, - In: "response", - Default: p.header.Default, - Required: true, - MaxLength: p.header.MaxLength, - MinLength: p.header.MinLength, - Pattern: p.header.Pattern, - AllowEmptyValue: false, - } + return newStringValidator( + p.name, + "response", + p.header.Default, + true, + false, + p.header.MaxLength, + p.header.MinLength, + p.header.Pattern, + p.Options, + ) } func (p *HeaderValidator) formatValidator() valueValidator { - return &formatValidator{ - Path: p.name, - In: "response", - //Default: p.header.Default, - Format: p.header.Format, - KnownFormats: p.KnownFormats, + return newFormatValidator( + p.name, + "response", + p.header.Format, + p.KnownFormats, + p.Options, + ) +} + +func (p *HeaderValidator) redeem() { + poolOfHeaderValidators.RedeemValidator(p) +} + +func (p *HeaderValidator) redeemChildren() { + for idx, validator := range p.validators { + if validator == nil { + continue + } + if redeemableChildren, ok := validator.(interface{ redeemChildren() }); ok { + redeemableChildren.redeemChildren() + } + if redeemable, ok := validator.(interface{ redeem() }); ok { + redeemable.redeem() + } + p.validators[idx] = nil // free up allocated children if not in pool } } // A ParamValidator has very limited subset of validations to apply type ParamValidator struct { param *spec.Parameter - validators []valueValidator + validators [6]valueValidator KnownFormats strfmt.Registry + Options *SchemaValidatorOptions } // NewParamValidator creates a new param validator object -func NewParamValidator(param *spec.Parameter, formats strfmt.Registry) *ParamValidator { - p := &ParamValidator{param: param, KnownFormats: formats} - p.validators = []valueValidator{ - &typeValidator{ - Type: spec.StringOrArray([]string{param.Type}), - Nullable: param.Nullable, - Format: param.Format, - In: param.In, - Path: param.Name, - }, +func NewParamValidator(param *spec.Parameter, formats strfmt.Registry, options ...Option) *ParamValidator { + opts := new(SchemaValidatorOptions) + for _, o := range options { + o(opts) + } + + return newParamValidator(param, formats, opts) +} + +func newParamValidator(param *spec.Parameter, formats strfmt.Registry, opts *SchemaValidatorOptions) *ParamValidator { + if opts == nil { + opts = new(SchemaValidatorOptions) + } + + var p *ParamValidator + if opts.recycleValidators { + p = poolOfParamValidators.BorrowValidator() + } else { + p = new(ParamValidator) + } + + p.param = param + p.KnownFormats = formats + p.Options = opts + p.validators = [6]valueValidator{ + newTypeValidator( + param.Name, + param.In, + spec.StringOrArray([]string{param.Type}), + param.Nullable, + param.Format, + p.Options, + ), p.stringValidator(), p.formatValidator(), p.numberValidator(), p.sliceValidator(), p.commonValidator(), } + return p } // Validate the data against the description of the parameter func (p *ParamValidator) Validate(data interface{}) *Result { - result := new(Result) + if data == nil { + return nil + } + + var result *Result + if p.Options.recycleResult { + result = poolOfResults.BorrowResult() + } else { + result = new(Result) + } + tpe := reflect.TypeOf(data) kind := tpe.Kind() + if p.Options.recycleValidators { + defer func() { + p.redeemChildren() + p.redeem() + }() + } + // TODO: validate type - for _, validator := range p.validators { - if validator.Applies(p.param, kind) { - if err := validator.Validate(data); err != nil { - result.Merge(err) - if err.HasErrors() { - return result + for idx, validator := range p.validators { + if !validator.Applies(p.param, kind) { + if p.Options.recycleValidators { + // Validate won't be called, so relinquish this validator + if redeemableChildren, ok := validator.(interface{ redeemChildren() }); ok { + redeemableChildren.redeemChildren() + } + if redeemable, ok := validator.(interface{ redeem() }); ok { + redeemable.redeem() } + p.validators[idx] = nil // prevents further (unsafe) usage + } + + continue + } + + if err := validator.Validate(data); err != nil { + result.Merge(err) + if err.HasErrors() { + break } } } - return nil + + return result } func (p *ParamValidator) commonValidator() valueValidator { - return &basicCommonValidator{ - Path: p.param.Name, - In: p.param.In, - Default: p.param.Default, - Enum: p.param.Enum, - } + return newBasicCommonValidator( + p.param.Name, + p.param.In, + p.param.Default, + p.param.Enum, + p.Options, + ) } func (p *ParamValidator) sliceValidator() valueValidator { - return &basicSliceValidator{ - Path: p.param.Name, - In: p.param.In, - Default: p.param.Default, - MaxItems: p.param.MaxItems, - MinItems: p.param.MinItems, - UniqueItems: p.param.UniqueItems, - Items: p.param.Items, - Source: p.param, - KnownFormats: p.KnownFormats, - } + return newBasicSliceValidator( + p.param.Name, + p.param.In, + p.param.Default, + p.param.MaxItems, + p.param.MinItems, + p.param.UniqueItems, + p.param.Items, + p.param, + p.KnownFormats, + p.Options, + ) } func (p *ParamValidator) numberValidator() valueValidator { - return &numberValidator{ - Path: p.param.Name, - In: p.param.In, - Default: p.param.Default, - MultipleOf: p.param.MultipleOf, - Maximum: p.param.Maximum, - ExclusiveMaximum: p.param.ExclusiveMaximum, - Minimum: p.param.Minimum, - ExclusiveMinimum: p.param.ExclusiveMinimum, - Type: p.param.Type, - Format: p.param.Format, - } + return newNumberValidator( + p.param.Name, + p.param.In, + p.param.Default, + p.param.MultipleOf, + p.param.Maximum, + p.param.ExclusiveMaximum, + p.param.Minimum, + p.param.ExclusiveMinimum, + p.param.Type, + p.param.Format, + p.Options, + ) } func (p *ParamValidator) stringValidator() valueValidator { - return &stringValidator{ - Path: p.param.Name, - In: p.param.In, - Default: p.param.Default, - AllowEmptyValue: p.param.AllowEmptyValue, - Required: p.param.Required, - MaxLength: p.param.MaxLength, - MinLength: p.param.MinLength, - Pattern: p.param.Pattern, - } + return newStringValidator( + p.param.Name, + p.param.In, + p.param.Default, + p.param.Required, + p.param.AllowEmptyValue, + p.param.MaxLength, + p.param.MinLength, + p.param.Pattern, + p.Options, + ) } func (p *ParamValidator) formatValidator() valueValidator { - return &formatValidator{ - Path: p.param.Name, - In: p.param.In, - //Default: p.param.Default, - Format: p.param.Format, - KnownFormats: p.KnownFormats, + return newFormatValidator( + p.param.Name, + p.param.In, + p.param.Format, + p.KnownFormats, + p.Options, + ) +} + +func (p *ParamValidator) redeem() { + poolOfParamValidators.RedeemValidator(p) +} + +func (p *ParamValidator) redeemChildren() { + for idx, validator := range p.validators { + if validator == nil { + continue + } + if redeemableChildren, ok := validator.(interface{ redeemChildren() }); ok { + redeemableChildren.redeemChildren() + } + if redeemable, ok := validator.(interface{ redeem() }); ok { + redeemable.redeem() + } + p.validators[idx] = nil // free up allocated children if not in pool } } type basicSliceValidator struct { - Path string - In string - Default interface{} - MaxItems *int64 - MinItems *int64 - UniqueItems bool - Items *spec.Items - Source interface{} - itemsValidator *itemsValidator - KnownFormats strfmt.Registry + Path string + In string + Default interface{} + MaxItems *int64 + MinItems *int64 + UniqueItems bool + Items *spec.Items + Source interface{} + KnownFormats strfmt.Registry + Options *SchemaValidatorOptions +} + +func newBasicSliceValidator( + path, in string, + def interface{}, maxItems, minItems *int64, uniqueItems bool, items *spec.Items, + source interface{}, formats strfmt.Registry, + opts *SchemaValidatorOptions) *basicSliceValidator { + if opts == nil { + opts = new(SchemaValidatorOptions) + } + + var s *basicSliceValidator + if opts.recycleValidators { + s = poolOfBasicSliceValidators.BorrowValidator() + } else { + s = new(basicSliceValidator) + } + + s.Path = path + s.In = in + s.Default = def + s.MaxItems = maxItems + s.MinItems = minItems + s.UniqueItems = uniqueItems + s.Items = items + s.Source = source + s.KnownFormats = formats + s.Options = opts + + return s } func (s *basicSliceValidator) SetPath(path string) { @@ -411,60 +714,56 @@ func (s *basicSliceValidator) Applies(source interface{}, kind reflect.Kind) boo switch source.(type) { case *spec.Parameter, *spec.Items, *spec.Header: return kind == reflect.Slice + default: + return false } - return false } func (s *basicSliceValidator) Validate(data interface{}) *Result { + if s.Options.recycleValidators { + defer func() { + s.redeem() + }() + } val := reflect.ValueOf(data) size := int64(val.Len()) if s.MinItems != nil { if err := MinItems(s.Path, s.In, size, *s.MinItems); err != nil { - return errorHelp.sErr(err) + return errorHelp.sErr(err, s.Options.recycleResult) } } if s.MaxItems != nil { if err := MaxItems(s.Path, s.In, size, *s.MaxItems); err != nil { - return errorHelp.sErr(err) + return errorHelp.sErr(err, s.Options.recycleResult) } } if s.UniqueItems { if err := UniqueItems(s.Path, s.In, data); err != nil { - return errorHelp.sErr(err) + return errorHelp.sErr(err, s.Options.recycleResult) } } - if s.itemsValidator == nil && s.Items != nil { - s.itemsValidator = newItemsValidator(s.Path, s.In, s.Items, s.Source, s.KnownFormats) + if s.Items == nil { + return nil } - if s.itemsValidator != nil { - for i := 0; i < int(size); i++ { - ele := val.Index(i) - if err := s.itemsValidator.Validate(i, ele.Interface()); err != nil && err.HasErrors() { - return err - } + for i := 0; i < int(size); i++ { + itemsValidator := newItemsValidator(s.Path, s.In, s.Items, s.Source, s.KnownFormats, s.Options) + ele := val.Index(i) + if err := itemsValidator.Validate(i, ele.Interface()); err != nil && err.HasErrors() { + return err } } + return nil } -/* unused -func (s *basicSliceValidator) hasDuplicates(value reflect.Value, size int) bool { - dict := make(map[interface{}]struct{}) - for i := 0; i < size; i++ { - ele := value.Index(i) - if _, ok := dict[ele.Interface()]; ok { - return true - } - dict[ele.Interface()] = struct{}{} - } - return false +func (s *basicSliceValidator) redeem() { + poolOfBasicSliceValidators.RedeemValidator(s) } -*/ type numberValidator struct { Path string @@ -476,8 +775,40 @@ type numberValidator struct { Minimum *float64 ExclusiveMinimum bool // Allows for more accurate behavior regarding integers - Type string - Format string + Type string + Format string + Options *SchemaValidatorOptions +} + +func newNumberValidator( + path, in string, def interface{}, + multipleOf, maximum *float64, exclusiveMaximum bool, minimum *float64, exclusiveMinimum bool, + typ, format string, + opts *SchemaValidatorOptions) *numberValidator { + if opts == nil { + opts = new(SchemaValidatorOptions) + } + + var n *numberValidator + if opts.recycleValidators { + n = poolOfNumberValidators.BorrowValidator() + } else { + n = new(numberValidator) + } + + n.Path = path + n.In = in + n.Default = def + n.MultipleOf = multipleOf + n.Maximum = maximum + n.ExclusiveMaximum = exclusiveMaximum + n.Minimum = minimum + n.ExclusiveMinimum = exclusiveMinimum + n.Type = typ + n.Format = format + n.Options = opts + + return n } func (n *numberValidator) SetPath(path string) { @@ -489,12 +820,10 @@ func (n *numberValidator) Applies(source interface{}, kind reflect.Kind) bool { case *spec.Parameter, *spec.Schema, *spec.Items, *spec.Header: isInt := kind >= reflect.Int && kind <= reflect.Uint64 isFloat := kind == reflect.Float32 || kind == reflect.Float64 - r := isInt || isFloat - debugLog("schema props validator for %q applies %t for %T (kind: %v) isInt=%t, isFloat=%t\n", n.Path, r, source, kind, isInt, isFloat) - return r + return isInt || isFloat + default: + return false } - debugLog("schema props validator for %q applies %t for %T (kind: %v)\n", n.Path, false, source, kind) - return false } // Validate provides a validator for generic JSON numbers, @@ -519,11 +848,22 @@ func (n *numberValidator) Applies(source interface{}, kind reflect.Kind) bool { // // TODO: default boundaries with MAX_SAFE_INTEGER are not checked (specific to json.Number?) func (n *numberValidator) Validate(val interface{}) *Result { - res := new(Result) + if n.Options.recycleValidators { + defer func() { + n.redeem() + }() + } - resMultiple := new(Result) - resMinimum := new(Result) - resMaximum := new(Result) + var res *Result + if n.Options.recycleResult { + res = poolOfResults.BorrowResult() + } else { + res = new(Result) + } + + resMultiple := poolOfResults.BorrowResult() + resMinimum := poolOfResults.BorrowResult() + resMaximum := poolOfResults.BorrowResult() // Used only to attempt to validate constraint on value, // even though value or constraint specified do not match type and format @@ -538,12 +878,12 @@ func (n *numberValidator) Validate(val interface{}) *Result { if resMultiple.IsValid() { // Constraint validated with compatible types if err := MultipleOfNativeType(n.Path, n.In, val, *n.MultipleOf); err != nil { - resMultiple.Merge(errorHelp.sErr(err)) + resMultiple.Merge(errorHelp.sErr(err, n.Options.recycleResult)) } } else { // Constraint nevertheless validated, converted as general number if err := MultipleOf(n.Path, n.In, data, *n.MultipleOf); err != nil { - resMultiple.Merge(errorHelp.sErr(err)) + resMultiple.Merge(errorHelp.sErr(err, n.Options.recycleResult)) } } } @@ -554,12 +894,12 @@ func (n *numberValidator) Validate(val interface{}) *Result { if resMaximum.IsValid() { // Constraint validated with compatible types if err := MaximumNativeType(n.Path, n.In, val, *n.Maximum, n.ExclusiveMaximum); err != nil { - resMaximum.Merge(errorHelp.sErr(err)) + resMaximum.Merge(errorHelp.sErr(err, n.Options.recycleResult)) } } else { // Constraint nevertheless validated, converted as general number if err := Maximum(n.Path, n.In, data, *n.Maximum, n.ExclusiveMaximum); err != nil { - resMaximum.Merge(errorHelp.sErr(err)) + resMaximum.Merge(errorHelp.sErr(err, n.Options.recycleResult)) } } } @@ -570,12 +910,12 @@ func (n *numberValidator) Validate(val interface{}) *Result { if resMinimum.IsValid() { // Constraint validated with compatible types if err := MinimumNativeType(n.Path, n.In, val, *n.Minimum, n.ExclusiveMinimum); err != nil { - resMinimum.Merge(errorHelp.sErr(err)) + resMinimum.Merge(errorHelp.sErr(err, n.Options.recycleResult)) } } else { // Constraint nevertheless validated, converted as general number if err := Minimum(n.Path, n.In, data, *n.Minimum, n.ExclusiveMinimum); err != nil { - resMinimum.Merge(errorHelp.sErr(err)) + resMinimum.Merge(errorHelp.sErr(err, n.Options.recycleResult)) } } } @@ -584,15 +924,48 @@ func (n *numberValidator) Validate(val interface{}) *Result { return res } +func (n *numberValidator) redeem() { + poolOfNumberValidators.RedeemValidator(n) +} + type stringValidator struct { + Path string + In string Default interface{} Required bool AllowEmptyValue bool MaxLength *int64 MinLength *int64 Pattern string - Path string - In string + Options *SchemaValidatorOptions +} + +func newStringValidator( + path, in string, + def interface{}, required, allowEmpty bool, maxLength, minLength *int64, pattern string, + opts *SchemaValidatorOptions) *stringValidator { + if opts == nil { + opts = new(SchemaValidatorOptions) + } + + var s *stringValidator + if opts.recycleValidators { + s = poolOfStringValidators.BorrowValidator() + } else { + s = new(stringValidator) + } + + s.Path = path + s.In = in + s.Default = def + s.Required = required + s.AllowEmptyValue = allowEmpty + s.MaxLength = maxLength + s.MinLength = minLength + s.Pattern = pattern + s.Options = opts + + return s } func (s *stringValidator) SetPath(path string) { @@ -602,42 +975,50 @@ func (s *stringValidator) SetPath(path string) { func (s *stringValidator) Applies(source interface{}, kind reflect.Kind) bool { switch source.(type) { case *spec.Parameter, *spec.Schema, *spec.Items, *spec.Header: - r := kind == reflect.String - debugLog("string validator for %q applies %t for %T (kind: %v)\n", s.Path, r, source, kind) - return r + return kind == reflect.String + default: + return false } - debugLog("string validator for %q applies %t for %T (kind: %v)\n", s.Path, false, source, kind) - return false } func (s *stringValidator) Validate(val interface{}) *Result { + if s.Options.recycleValidators { + defer func() { + s.redeem() + }() + } + data, ok := val.(string) if !ok { - return errorHelp.sErr(errors.InvalidType(s.Path, s.In, stringType, val)) + return errorHelp.sErr(errors.InvalidType(s.Path, s.In, stringType, val), s.Options.recycleResult) } if s.Required && !s.AllowEmptyValue && (s.Default == nil || s.Default == "") { if err := RequiredString(s.Path, s.In, data); err != nil { - return errorHelp.sErr(err) + return errorHelp.sErr(err, s.Options.recycleResult) } } if s.MaxLength != nil { if err := MaxLength(s.Path, s.In, data, *s.MaxLength); err != nil { - return errorHelp.sErr(err) + return errorHelp.sErr(err, s.Options.recycleResult) } } if s.MinLength != nil { if err := MinLength(s.Path, s.In, data, *s.MinLength); err != nil { - return errorHelp.sErr(err) + return errorHelp.sErr(err, s.Options.recycleResult) } } if s.Pattern != "" { if err := Pattern(s.Path, s.In, data, s.Pattern); err != nil { - return errorHelp.sErr(err) + return errorHelp.sErr(err, s.Options.recycleResult) } } return nil } + +func (s *stringValidator) redeem() { + poolOfStringValidators.RedeemValidator(s) +} diff --git a/vendor/github.com/golang/protobuf/jsonpb/decode.go b/vendor/github.com/golang/protobuf/jsonpb/decode.go deleted file mode 100644 index 6c16c255ff..0000000000 --- a/vendor/github.com/golang/protobuf/jsonpb/decode.go +++ /dev/null @@ -1,530 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package jsonpb - -import ( - "encoding/json" - "errors" - "fmt" - "io" - "math" - "reflect" - "strconv" - "strings" - "time" - - "github.com/golang/protobuf/proto" - "google.golang.org/protobuf/encoding/protojson" - protoV2 "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/reflect/protoregistry" -) - -const wrapJSONUnmarshalV2 = false - -// UnmarshalNext unmarshals the next JSON object from d into m. -func UnmarshalNext(d *json.Decoder, m proto.Message) error { - return new(Unmarshaler).UnmarshalNext(d, m) -} - -// Unmarshal unmarshals a JSON object from r into m. -func Unmarshal(r io.Reader, m proto.Message) error { - return new(Unmarshaler).Unmarshal(r, m) -} - -// UnmarshalString unmarshals a JSON object from s into m. -func UnmarshalString(s string, m proto.Message) error { - return new(Unmarshaler).Unmarshal(strings.NewReader(s), m) -} - -// Unmarshaler is a configurable object for converting from a JSON -// representation to a protocol buffer object. -type Unmarshaler struct { - // AllowUnknownFields specifies whether to allow messages to contain - // unknown JSON fields, as opposed to failing to unmarshal. - AllowUnknownFields bool - - // AnyResolver is used to resolve the google.protobuf.Any well-known type. - // If unset, the global registry is used by default. - AnyResolver AnyResolver -} - -// JSONPBUnmarshaler is implemented by protobuf messages that customize the way -// they are unmarshaled from JSON. Messages that implement this should also -// implement JSONPBMarshaler so that the custom format can be produced. -// -// The JSON unmarshaling must follow the JSON to proto specification: -// https://developers.google.com/protocol-buffers/docs/proto3#json -// -// Deprecated: Custom types should implement protobuf reflection instead. -type JSONPBUnmarshaler interface { - UnmarshalJSONPB(*Unmarshaler, []byte) error -} - -// Unmarshal unmarshals a JSON object from r into m. -func (u *Unmarshaler) Unmarshal(r io.Reader, m proto.Message) error { - return u.UnmarshalNext(json.NewDecoder(r), m) -} - -// UnmarshalNext unmarshals the next JSON object from d into m. -func (u *Unmarshaler) UnmarshalNext(d *json.Decoder, m proto.Message) error { - if m == nil { - return errors.New("invalid nil message") - } - - // Parse the next JSON object from the stream. - raw := json.RawMessage{} - if err := d.Decode(&raw); err != nil { - return err - } - - // Check for custom unmarshalers first since they may not properly - // implement protobuf reflection that the logic below relies on. - if jsu, ok := m.(JSONPBUnmarshaler); ok { - return jsu.UnmarshalJSONPB(u, raw) - } - - mr := proto.MessageReflect(m) - - // NOTE: For historical reasons, a top-level null is treated as a noop. - // This is incorrect, but kept for compatibility. - if string(raw) == "null" && mr.Descriptor().FullName() != "google.protobuf.Value" { - return nil - } - - if wrapJSONUnmarshalV2 { - // NOTE: If input message is non-empty, we need to preserve merge semantics - // of the old jsonpb implementation. These semantics are not supported by - // the protobuf JSON specification. - isEmpty := true - mr.Range(func(protoreflect.FieldDescriptor, protoreflect.Value) bool { - isEmpty = false // at least one iteration implies non-empty - return false - }) - if !isEmpty { - // Perform unmarshaling into a newly allocated, empty message. - mr = mr.New() - - // Use a defer to copy all unmarshaled fields into the original message. - dst := proto.MessageReflect(m) - defer mr.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { - dst.Set(fd, v) - return true - }) - } - - // Unmarshal using the v2 JSON unmarshaler. - opts := protojson.UnmarshalOptions{ - DiscardUnknown: u.AllowUnknownFields, - } - if u.AnyResolver != nil { - opts.Resolver = anyResolver{u.AnyResolver} - } - return opts.Unmarshal(raw, mr.Interface()) - } else { - if err := u.unmarshalMessage(mr, raw); err != nil { - return err - } - return protoV2.CheckInitialized(mr.Interface()) - } -} - -func (u *Unmarshaler) unmarshalMessage(m protoreflect.Message, in []byte) error { - md := m.Descriptor() - fds := md.Fields() - - if jsu, ok := proto.MessageV1(m.Interface()).(JSONPBUnmarshaler); ok { - return jsu.UnmarshalJSONPB(u, in) - } - - if string(in) == "null" && md.FullName() != "google.protobuf.Value" { - return nil - } - - switch wellKnownType(md.FullName()) { - case "Any": - var jsonObject map[string]json.RawMessage - if err := json.Unmarshal(in, &jsonObject); err != nil { - return err - } - - rawTypeURL, ok := jsonObject["@type"] - if !ok { - return errors.New("Any JSON doesn't have '@type'") - } - typeURL, err := unquoteString(string(rawTypeURL)) - if err != nil { - return fmt.Errorf("can't unmarshal Any's '@type': %q", rawTypeURL) - } - m.Set(fds.ByNumber(1), protoreflect.ValueOfString(typeURL)) - - var m2 protoreflect.Message - if u.AnyResolver != nil { - mi, err := u.AnyResolver.Resolve(typeURL) - if err != nil { - return err - } - m2 = proto.MessageReflect(mi) - } else { - mt, err := protoregistry.GlobalTypes.FindMessageByURL(typeURL) - if err != nil { - if err == protoregistry.NotFound { - return fmt.Errorf("could not resolve Any message type: %v", typeURL) - } - return err - } - m2 = mt.New() - } - - if wellKnownType(m2.Descriptor().FullName()) != "" { - rawValue, ok := jsonObject["value"] - if !ok { - return errors.New("Any JSON doesn't have 'value'") - } - if err := u.unmarshalMessage(m2, rawValue); err != nil { - return fmt.Errorf("can't unmarshal Any nested proto %v: %v", typeURL, err) - } - } else { - delete(jsonObject, "@type") - rawJSON, err := json.Marshal(jsonObject) - if err != nil { - return fmt.Errorf("can't generate JSON for Any's nested proto to be unmarshaled: %v", err) - } - if err = u.unmarshalMessage(m2, rawJSON); err != nil { - return fmt.Errorf("can't unmarshal Any nested proto %v: %v", typeURL, err) - } - } - - rawWire, err := protoV2.Marshal(m2.Interface()) - if err != nil { - return fmt.Errorf("can't marshal proto %v into Any.Value: %v", typeURL, err) - } - m.Set(fds.ByNumber(2), protoreflect.ValueOfBytes(rawWire)) - return nil - case "BoolValue", "BytesValue", "StringValue", - "Int32Value", "UInt32Value", "FloatValue", - "Int64Value", "UInt64Value", "DoubleValue": - fd := fds.ByNumber(1) - v, err := u.unmarshalValue(m.NewField(fd), in, fd) - if err != nil { - return err - } - m.Set(fd, v) - return nil - case "Duration": - v, err := unquoteString(string(in)) - if err != nil { - return err - } - d, err := time.ParseDuration(v) - if err != nil { - return fmt.Errorf("bad Duration: %v", err) - } - - sec := d.Nanoseconds() / 1e9 - nsec := d.Nanoseconds() % 1e9 - m.Set(fds.ByNumber(1), protoreflect.ValueOfInt64(int64(sec))) - m.Set(fds.ByNumber(2), protoreflect.ValueOfInt32(int32(nsec))) - return nil - case "Timestamp": - v, err := unquoteString(string(in)) - if err != nil { - return err - } - t, err := time.Parse(time.RFC3339Nano, v) - if err != nil { - return fmt.Errorf("bad Timestamp: %v", err) - } - - sec := t.Unix() - nsec := t.Nanosecond() - m.Set(fds.ByNumber(1), protoreflect.ValueOfInt64(int64(sec))) - m.Set(fds.ByNumber(2), protoreflect.ValueOfInt32(int32(nsec))) - return nil - case "Value": - switch { - case string(in) == "null": - m.Set(fds.ByNumber(1), protoreflect.ValueOfEnum(0)) - case string(in) == "true": - m.Set(fds.ByNumber(4), protoreflect.ValueOfBool(true)) - case string(in) == "false": - m.Set(fds.ByNumber(4), protoreflect.ValueOfBool(false)) - case hasPrefixAndSuffix('"', in, '"'): - s, err := unquoteString(string(in)) - if err != nil { - return fmt.Errorf("unrecognized type for Value %q", in) - } - m.Set(fds.ByNumber(3), protoreflect.ValueOfString(s)) - case hasPrefixAndSuffix('[', in, ']'): - v := m.Mutable(fds.ByNumber(6)) - return u.unmarshalMessage(v.Message(), in) - case hasPrefixAndSuffix('{', in, '}'): - v := m.Mutable(fds.ByNumber(5)) - return u.unmarshalMessage(v.Message(), in) - default: - f, err := strconv.ParseFloat(string(in), 0) - if err != nil { - return fmt.Errorf("unrecognized type for Value %q", in) - } - m.Set(fds.ByNumber(2), protoreflect.ValueOfFloat64(f)) - } - return nil - case "ListValue": - var jsonArray []json.RawMessage - if err := json.Unmarshal(in, &jsonArray); err != nil { - return fmt.Errorf("bad ListValue: %v", err) - } - - lv := m.Mutable(fds.ByNumber(1)).List() - for _, raw := range jsonArray { - ve := lv.NewElement() - if err := u.unmarshalMessage(ve.Message(), raw); err != nil { - return err - } - lv.Append(ve) - } - return nil - case "Struct": - var jsonObject map[string]json.RawMessage - if err := json.Unmarshal(in, &jsonObject); err != nil { - return fmt.Errorf("bad StructValue: %v", err) - } - - mv := m.Mutable(fds.ByNumber(1)).Map() - for key, raw := range jsonObject { - kv := protoreflect.ValueOf(key).MapKey() - vv := mv.NewValue() - if err := u.unmarshalMessage(vv.Message(), raw); err != nil { - return fmt.Errorf("bad value in StructValue for key %q: %v", key, err) - } - mv.Set(kv, vv) - } - return nil - } - - var jsonObject map[string]json.RawMessage - if err := json.Unmarshal(in, &jsonObject); err != nil { - return err - } - - // Handle known fields. - for i := 0; i < fds.Len(); i++ { - fd := fds.Get(i) - if fd.IsWeak() && fd.Message().IsPlaceholder() { - continue // weak reference is not linked in - } - - // Search for any raw JSON value associated with this field. - var raw json.RawMessage - name := string(fd.Name()) - if fd.Kind() == protoreflect.GroupKind { - name = string(fd.Message().Name()) - } - if v, ok := jsonObject[name]; ok { - delete(jsonObject, name) - raw = v - } - name = string(fd.JSONName()) - if v, ok := jsonObject[name]; ok { - delete(jsonObject, name) - raw = v - } - - field := m.NewField(fd) - // Unmarshal the field value. - if raw == nil || (string(raw) == "null" && !isSingularWellKnownValue(fd) && !isSingularJSONPBUnmarshaler(field, fd)) { - continue - } - v, err := u.unmarshalValue(field, raw, fd) - if err != nil { - return err - } - m.Set(fd, v) - } - - // Handle extension fields. - for name, raw := range jsonObject { - if !strings.HasPrefix(name, "[") || !strings.HasSuffix(name, "]") { - continue - } - - // Resolve the extension field by name. - xname := protoreflect.FullName(name[len("[") : len(name)-len("]")]) - xt, _ := protoregistry.GlobalTypes.FindExtensionByName(xname) - if xt == nil && isMessageSet(md) { - xt, _ = protoregistry.GlobalTypes.FindExtensionByName(xname.Append("message_set_extension")) - } - if xt == nil { - continue - } - delete(jsonObject, name) - fd := xt.TypeDescriptor() - if fd.ContainingMessage().FullName() != m.Descriptor().FullName() { - return fmt.Errorf("extension field %q does not extend message %q", xname, m.Descriptor().FullName()) - } - - field := m.NewField(fd) - // Unmarshal the field value. - if raw == nil || (string(raw) == "null" && !isSingularWellKnownValue(fd) && !isSingularJSONPBUnmarshaler(field, fd)) { - continue - } - v, err := u.unmarshalValue(field, raw, fd) - if err != nil { - return err - } - m.Set(fd, v) - } - - if !u.AllowUnknownFields && len(jsonObject) > 0 { - for name := range jsonObject { - return fmt.Errorf("unknown field %q in %v", name, md.FullName()) - } - } - return nil -} - -func isSingularWellKnownValue(fd protoreflect.FieldDescriptor) bool { - if fd.Cardinality() == protoreflect.Repeated { - return false - } - if md := fd.Message(); md != nil { - return md.FullName() == "google.protobuf.Value" - } - if ed := fd.Enum(); ed != nil { - return ed.FullName() == "google.protobuf.NullValue" - } - return false -} - -func isSingularJSONPBUnmarshaler(v protoreflect.Value, fd protoreflect.FieldDescriptor) bool { - if fd.Message() != nil && fd.Cardinality() != protoreflect.Repeated { - _, ok := proto.MessageV1(v.Interface()).(JSONPBUnmarshaler) - return ok - } - return false -} - -func (u *Unmarshaler) unmarshalValue(v protoreflect.Value, in []byte, fd protoreflect.FieldDescriptor) (protoreflect.Value, error) { - switch { - case fd.IsList(): - var jsonArray []json.RawMessage - if err := json.Unmarshal(in, &jsonArray); err != nil { - return v, err - } - lv := v.List() - for _, raw := range jsonArray { - ve, err := u.unmarshalSingularValue(lv.NewElement(), raw, fd) - if err != nil { - return v, err - } - lv.Append(ve) - } - return v, nil - case fd.IsMap(): - var jsonObject map[string]json.RawMessage - if err := json.Unmarshal(in, &jsonObject); err != nil { - return v, err - } - kfd := fd.MapKey() - vfd := fd.MapValue() - mv := v.Map() - for key, raw := range jsonObject { - var kv protoreflect.MapKey - if kfd.Kind() == protoreflect.StringKind { - kv = protoreflect.ValueOf(key).MapKey() - } else { - v, err := u.unmarshalSingularValue(kfd.Default(), []byte(key), kfd) - if err != nil { - return v, err - } - kv = v.MapKey() - } - - vv, err := u.unmarshalSingularValue(mv.NewValue(), raw, vfd) - if err != nil { - return v, err - } - mv.Set(kv, vv) - } - return v, nil - default: - return u.unmarshalSingularValue(v, in, fd) - } -} - -var nonFinite = map[string]float64{ - `"NaN"`: math.NaN(), - `"Infinity"`: math.Inf(+1), - `"-Infinity"`: math.Inf(-1), -} - -func (u *Unmarshaler) unmarshalSingularValue(v protoreflect.Value, in []byte, fd protoreflect.FieldDescriptor) (protoreflect.Value, error) { - switch fd.Kind() { - case protoreflect.BoolKind: - return unmarshalValue(in, new(bool)) - case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind: - return unmarshalValue(trimQuote(in), new(int32)) - case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: - return unmarshalValue(trimQuote(in), new(int64)) - case protoreflect.Uint32Kind, protoreflect.Fixed32Kind: - return unmarshalValue(trimQuote(in), new(uint32)) - case protoreflect.Uint64Kind, protoreflect.Fixed64Kind: - return unmarshalValue(trimQuote(in), new(uint64)) - case protoreflect.FloatKind: - if f, ok := nonFinite[string(in)]; ok { - return protoreflect.ValueOfFloat32(float32(f)), nil - } - return unmarshalValue(trimQuote(in), new(float32)) - case protoreflect.DoubleKind: - if f, ok := nonFinite[string(in)]; ok { - return protoreflect.ValueOfFloat64(float64(f)), nil - } - return unmarshalValue(trimQuote(in), new(float64)) - case protoreflect.StringKind: - return unmarshalValue(in, new(string)) - case protoreflect.BytesKind: - return unmarshalValue(in, new([]byte)) - case protoreflect.EnumKind: - if hasPrefixAndSuffix('"', in, '"') { - vd := fd.Enum().Values().ByName(protoreflect.Name(trimQuote(in))) - if vd == nil { - return v, fmt.Errorf("unknown value %q for enum %s", in, fd.Enum().FullName()) - } - return protoreflect.ValueOfEnum(vd.Number()), nil - } - return unmarshalValue(in, new(protoreflect.EnumNumber)) - case protoreflect.MessageKind, protoreflect.GroupKind: - err := u.unmarshalMessage(v.Message(), in) - return v, err - default: - panic(fmt.Sprintf("invalid kind %v", fd.Kind())) - } -} - -func unmarshalValue(in []byte, v interface{}) (protoreflect.Value, error) { - err := json.Unmarshal(in, v) - return protoreflect.ValueOf(reflect.ValueOf(v).Elem().Interface()), err -} - -func unquoteString(in string) (out string, err error) { - err = json.Unmarshal([]byte(in), &out) - return out, err -} - -func hasPrefixAndSuffix(prefix byte, in []byte, suffix byte) bool { - if len(in) >= 2 && in[0] == prefix && in[len(in)-1] == suffix { - return true - } - return false -} - -// trimQuote is like unquoteString but simply strips surrounding quotes. -// This is incorrect, but is behavior done by the legacy implementation. -func trimQuote(in []byte) []byte { - if len(in) >= 2 && in[0] == '"' && in[len(in)-1] == '"' { - in = in[1 : len(in)-1] - } - return in -} diff --git a/vendor/github.com/golang/protobuf/jsonpb/encode.go b/vendor/github.com/golang/protobuf/jsonpb/encode.go deleted file mode 100644 index 685c80a62b..0000000000 --- a/vendor/github.com/golang/protobuf/jsonpb/encode.go +++ /dev/null @@ -1,559 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package jsonpb - -import ( - "encoding/json" - "errors" - "fmt" - "io" - "math" - "reflect" - "sort" - "strconv" - "strings" - "time" - - "github.com/golang/protobuf/proto" - "google.golang.org/protobuf/encoding/protojson" - protoV2 "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/reflect/protoregistry" -) - -const wrapJSONMarshalV2 = false - -// Marshaler is a configurable object for marshaling protocol buffer messages -// to the specified JSON representation. -type Marshaler struct { - // OrigName specifies whether to use the original protobuf name for fields. - OrigName bool - - // EnumsAsInts specifies whether to render enum values as integers, - // as opposed to string values. - EnumsAsInts bool - - // EmitDefaults specifies whether to render fields with zero values. - EmitDefaults bool - - // Indent controls whether the output is compact or not. - // If empty, the output is compact JSON. Otherwise, every JSON object - // entry and JSON array value will be on its own line. - // Each line will be preceded by repeated copies of Indent, where the - // number of copies is the current indentation depth. - Indent string - - // AnyResolver is used to resolve the google.protobuf.Any well-known type. - // If unset, the global registry is used by default. - AnyResolver AnyResolver -} - -// JSONPBMarshaler is implemented by protobuf messages that customize the -// way they are marshaled to JSON. Messages that implement this should also -// implement JSONPBUnmarshaler so that the custom format can be parsed. -// -// The JSON marshaling must follow the proto to JSON specification: -// https://developers.google.com/protocol-buffers/docs/proto3#json -// -// Deprecated: Custom types should implement protobuf reflection instead. -type JSONPBMarshaler interface { - MarshalJSONPB(*Marshaler) ([]byte, error) -} - -// Marshal serializes a protobuf message as JSON into w. -func (jm *Marshaler) Marshal(w io.Writer, m proto.Message) error { - b, err := jm.marshal(m) - if len(b) > 0 { - if _, err := w.Write(b); err != nil { - return err - } - } - return err -} - -// MarshalToString serializes a protobuf message as JSON in string form. -func (jm *Marshaler) MarshalToString(m proto.Message) (string, error) { - b, err := jm.marshal(m) - if err != nil { - return "", err - } - return string(b), nil -} - -func (jm *Marshaler) marshal(m proto.Message) ([]byte, error) { - v := reflect.ValueOf(m) - if m == nil || (v.Kind() == reflect.Ptr && v.IsNil()) { - return nil, errors.New("Marshal called with nil") - } - - // Check for custom marshalers first since they may not properly - // implement protobuf reflection that the logic below relies on. - if jsm, ok := m.(JSONPBMarshaler); ok { - return jsm.MarshalJSONPB(jm) - } - - if wrapJSONMarshalV2 { - opts := protojson.MarshalOptions{ - UseProtoNames: jm.OrigName, - UseEnumNumbers: jm.EnumsAsInts, - EmitUnpopulated: jm.EmitDefaults, - Indent: jm.Indent, - } - if jm.AnyResolver != nil { - opts.Resolver = anyResolver{jm.AnyResolver} - } - return opts.Marshal(proto.MessageReflect(m).Interface()) - } else { - // Check for unpopulated required fields first. - m2 := proto.MessageReflect(m) - if err := protoV2.CheckInitialized(m2.Interface()); err != nil { - return nil, err - } - - w := jsonWriter{Marshaler: jm} - err := w.marshalMessage(m2, "", "") - return w.buf, err - } -} - -type jsonWriter struct { - *Marshaler - buf []byte -} - -func (w *jsonWriter) write(s string) { - w.buf = append(w.buf, s...) -} - -func (w *jsonWriter) marshalMessage(m protoreflect.Message, indent, typeURL string) error { - if jsm, ok := proto.MessageV1(m.Interface()).(JSONPBMarshaler); ok { - b, err := jsm.MarshalJSONPB(w.Marshaler) - if err != nil { - return err - } - if typeURL != "" { - // we are marshaling this object to an Any type - var js map[string]*json.RawMessage - if err = json.Unmarshal(b, &js); err != nil { - return fmt.Errorf("type %T produced invalid JSON: %v", m.Interface(), err) - } - turl, err := json.Marshal(typeURL) - if err != nil { - return fmt.Errorf("failed to marshal type URL %q to JSON: %v", typeURL, err) - } - js["@type"] = (*json.RawMessage)(&turl) - if b, err = json.Marshal(js); err != nil { - return err - } - } - w.write(string(b)) - return nil - } - - md := m.Descriptor() - fds := md.Fields() - - // Handle well-known types. - const secondInNanos = int64(time.Second / time.Nanosecond) - switch wellKnownType(md.FullName()) { - case "Any": - return w.marshalAny(m, indent) - case "BoolValue", "BytesValue", "StringValue", - "Int32Value", "UInt32Value", "FloatValue", - "Int64Value", "UInt64Value", "DoubleValue": - fd := fds.ByNumber(1) - return w.marshalValue(fd, m.Get(fd), indent) - case "Duration": - const maxSecondsInDuration = 315576000000 - // "Generated output always contains 0, 3, 6, or 9 fractional digits, - // depending on required precision." - s := m.Get(fds.ByNumber(1)).Int() - ns := m.Get(fds.ByNumber(2)).Int() - if s < -maxSecondsInDuration || s > maxSecondsInDuration { - return fmt.Errorf("seconds out of range %v", s) - } - if ns <= -secondInNanos || ns >= secondInNanos { - return fmt.Errorf("ns out of range (%v, %v)", -secondInNanos, secondInNanos) - } - if (s > 0 && ns < 0) || (s < 0 && ns > 0) { - return errors.New("signs of seconds and nanos do not match") - } - var sign string - if s < 0 || ns < 0 { - sign, s, ns = "-", -1*s, -1*ns - } - x := fmt.Sprintf("%s%d.%09d", sign, s, ns) - x = strings.TrimSuffix(x, "000") - x = strings.TrimSuffix(x, "000") - x = strings.TrimSuffix(x, ".000") - w.write(fmt.Sprintf(`"%vs"`, x)) - return nil - case "Timestamp": - // "RFC 3339, where generated output will always be Z-normalized - // and uses 0, 3, 6 or 9 fractional digits." - s := m.Get(fds.ByNumber(1)).Int() - ns := m.Get(fds.ByNumber(2)).Int() - if ns < 0 || ns >= secondInNanos { - return fmt.Errorf("ns out of range [0, %v)", secondInNanos) - } - t := time.Unix(s, ns).UTC() - // time.RFC3339Nano isn't exactly right (we need to get 3/6/9 fractional digits). - x := t.Format("2006-01-02T15:04:05.000000000") - x = strings.TrimSuffix(x, "000") - x = strings.TrimSuffix(x, "000") - x = strings.TrimSuffix(x, ".000") - w.write(fmt.Sprintf(`"%vZ"`, x)) - return nil - case "Value": - // JSON value; which is a null, number, string, bool, object, or array. - od := md.Oneofs().Get(0) - fd := m.WhichOneof(od) - if fd == nil { - return errors.New("nil Value") - } - return w.marshalValue(fd, m.Get(fd), indent) - case "Struct", "ListValue": - // JSON object or array. - fd := fds.ByNumber(1) - return w.marshalValue(fd, m.Get(fd), indent) - } - - w.write("{") - if w.Indent != "" { - w.write("\n") - } - - firstField := true - if typeURL != "" { - if err := w.marshalTypeURL(indent, typeURL); err != nil { - return err - } - firstField = false - } - - for i := 0; i < fds.Len(); { - fd := fds.Get(i) - if od := fd.ContainingOneof(); od != nil { - fd = m.WhichOneof(od) - i += od.Fields().Len() - if fd == nil { - continue - } - } else { - i++ - } - - v := m.Get(fd) - - if !m.Has(fd) { - if !w.EmitDefaults || fd.ContainingOneof() != nil { - continue - } - if fd.Cardinality() != protoreflect.Repeated && (fd.Message() != nil || fd.Syntax() == protoreflect.Proto2) { - v = protoreflect.Value{} // use "null" for singular messages or proto2 scalars - } - } - - if !firstField { - w.writeComma() - } - if err := w.marshalField(fd, v, indent); err != nil { - return err - } - firstField = false - } - - // Handle proto2 extensions. - if md.ExtensionRanges().Len() > 0 { - // Collect a sorted list of all extension descriptor and values. - type ext struct { - desc protoreflect.FieldDescriptor - val protoreflect.Value - } - var exts []ext - m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { - if fd.IsExtension() { - exts = append(exts, ext{fd, v}) - } - return true - }) - sort.Slice(exts, func(i, j int) bool { - return exts[i].desc.Number() < exts[j].desc.Number() - }) - - for _, ext := range exts { - if !firstField { - w.writeComma() - } - if err := w.marshalField(ext.desc, ext.val, indent); err != nil { - return err - } - firstField = false - } - } - - if w.Indent != "" { - w.write("\n") - w.write(indent) - } - w.write("}") - return nil -} - -func (w *jsonWriter) writeComma() { - if w.Indent != "" { - w.write(",\n") - } else { - w.write(",") - } -} - -func (w *jsonWriter) marshalAny(m protoreflect.Message, indent string) error { - // "If the Any contains a value that has a special JSON mapping, - // it will be converted as follows: {"@type": xxx, "value": yyy}. - // Otherwise, the value will be converted into a JSON object, - // and the "@type" field will be inserted to indicate the actual data type." - md := m.Descriptor() - typeURL := m.Get(md.Fields().ByNumber(1)).String() - rawVal := m.Get(md.Fields().ByNumber(2)).Bytes() - - var m2 protoreflect.Message - if w.AnyResolver != nil { - mi, err := w.AnyResolver.Resolve(typeURL) - if err != nil { - return err - } - m2 = proto.MessageReflect(mi) - } else { - mt, err := protoregistry.GlobalTypes.FindMessageByURL(typeURL) - if err != nil { - return err - } - m2 = mt.New() - } - - if err := protoV2.Unmarshal(rawVal, m2.Interface()); err != nil { - return err - } - - if wellKnownType(m2.Descriptor().FullName()) == "" { - return w.marshalMessage(m2, indent, typeURL) - } - - w.write("{") - if w.Indent != "" { - w.write("\n") - } - if err := w.marshalTypeURL(indent, typeURL); err != nil { - return err - } - w.writeComma() - if w.Indent != "" { - w.write(indent) - w.write(w.Indent) - w.write(`"value": `) - } else { - w.write(`"value":`) - } - if err := w.marshalMessage(m2, indent+w.Indent, ""); err != nil { - return err - } - if w.Indent != "" { - w.write("\n") - w.write(indent) - } - w.write("}") - return nil -} - -func (w *jsonWriter) marshalTypeURL(indent, typeURL string) error { - if w.Indent != "" { - w.write(indent) - w.write(w.Indent) - } - w.write(`"@type":`) - if w.Indent != "" { - w.write(" ") - } - b, err := json.Marshal(typeURL) - if err != nil { - return err - } - w.write(string(b)) - return nil -} - -// marshalField writes field description and value to the Writer. -func (w *jsonWriter) marshalField(fd protoreflect.FieldDescriptor, v protoreflect.Value, indent string) error { - if w.Indent != "" { - w.write(indent) - w.write(w.Indent) - } - w.write(`"`) - switch { - case fd.IsExtension(): - // For message set, use the fname of the message as the extension name. - name := string(fd.FullName()) - if isMessageSet(fd.ContainingMessage()) { - name = strings.TrimSuffix(name, ".message_set_extension") - } - - w.write("[" + name + "]") - case w.OrigName: - name := string(fd.Name()) - if fd.Kind() == protoreflect.GroupKind { - name = string(fd.Message().Name()) - } - w.write(name) - default: - w.write(string(fd.JSONName())) - } - w.write(`":`) - if w.Indent != "" { - w.write(" ") - } - return w.marshalValue(fd, v, indent) -} - -func (w *jsonWriter) marshalValue(fd protoreflect.FieldDescriptor, v protoreflect.Value, indent string) error { - switch { - case fd.IsList(): - w.write("[") - comma := "" - lv := v.List() - for i := 0; i < lv.Len(); i++ { - w.write(comma) - if w.Indent != "" { - w.write("\n") - w.write(indent) - w.write(w.Indent) - w.write(w.Indent) - } - if err := w.marshalSingularValue(fd, lv.Get(i), indent+w.Indent); err != nil { - return err - } - comma = "," - } - if w.Indent != "" { - w.write("\n") - w.write(indent) - w.write(w.Indent) - } - w.write("]") - return nil - case fd.IsMap(): - kfd := fd.MapKey() - vfd := fd.MapValue() - mv := v.Map() - - // Collect a sorted list of all map keys and values. - type entry struct{ key, val protoreflect.Value } - var entries []entry - mv.Range(func(k protoreflect.MapKey, v protoreflect.Value) bool { - entries = append(entries, entry{k.Value(), v}) - return true - }) - sort.Slice(entries, func(i, j int) bool { - switch kfd.Kind() { - case protoreflect.BoolKind: - return !entries[i].key.Bool() && entries[j].key.Bool() - case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind, protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: - return entries[i].key.Int() < entries[j].key.Int() - case protoreflect.Uint32Kind, protoreflect.Fixed32Kind, protoreflect.Uint64Kind, protoreflect.Fixed64Kind: - return entries[i].key.Uint() < entries[j].key.Uint() - case protoreflect.StringKind: - return entries[i].key.String() < entries[j].key.String() - default: - panic("invalid kind") - } - }) - - w.write(`{`) - comma := "" - for _, entry := range entries { - w.write(comma) - if w.Indent != "" { - w.write("\n") - w.write(indent) - w.write(w.Indent) - w.write(w.Indent) - } - - s := fmt.Sprint(entry.key.Interface()) - b, err := json.Marshal(s) - if err != nil { - return err - } - w.write(string(b)) - - w.write(`:`) - if w.Indent != "" { - w.write(` `) - } - - if err := w.marshalSingularValue(vfd, entry.val, indent+w.Indent); err != nil { - return err - } - comma = "," - } - if w.Indent != "" { - w.write("\n") - w.write(indent) - w.write(w.Indent) - } - w.write(`}`) - return nil - default: - return w.marshalSingularValue(fd, v, indent) - } -} - -func (w *jsonWriter) marshalSingularValue(fd protoreflect.FieldDescriptor, v protoreflect.Value, indent string) error { - switch { - case !v.IsValid(): - w.write("null") - return nil - case fd.Message() != nil: - return w.marshalMessage(v.Message(), indent+w.Indent, "") - case fd.Enum() != nil: - if fd.Enum().FullName() == "google.protobuf.NullValue" { - w.write("null") - return nil - } - - vd := fd.Enum().Values().ByNumber(v.Enum()) - if vd == nil || w.EnumsAsInts { - w.write(strconv.Itoa(int(v.Enum()))) - } else { - w.write(`"` + string(vd.Name()) + `"`) - } - return nil - default: - switch v.Interface().(type) { - case float32, float64: - switch { - case math.IsInf(v.Float(), +1): - w.write(`"Infinity"`) - return nil - case math.IsInf(v.Float(), -1): - w.write(`"-Infinity"`) - return nil - case math.IsNaN(v.Float()): - w.write(`"NaN"`) - return nil - } - case int64, uint64: - w.write(fmt.Sprintf(`"%d"`, v.Interface())) - return nil - } - - b, err := json.Marshal(v.Interface()) - if err != nil { - return err - } - w.write(string(b)) - return nil - } -} diff --git a/vendor/github.com/golang/protobuf/jsonpb/json.go b/vendor/github.com/golang/protobuf/jsonpb/json.go deleted file mode 100644 index 480e2448de..0000000000 --- a/vendor/github.com/golang/protobuf/jsonpb/json.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package jsonpb provides functionality to marshal and unmarshal between a -// protocol buffer message and JSON. It follows the specification at -// https://developers.google.com/protocol-buffers/docs/proto3#json. -// -// Do not rely on the default behavior of the standard encoding/json package -// when called on generated message types as it does not operate correctly. -// -// Deprecated: Use the "google.golang.org/protobuf/encoding/protojson" -// package instead. -package jsonpb - -import ( - "github.com/golang/protobuf/proto" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/reflect/protoregistry" - "google.golang.org/protobuf/runtime/protoimpl" -) - -// AnyResolver takes a type URL, present in an Any message, -// and resolves it into an instance of the associated message. -type AnyResolver interface { - Resolve(typeURL string) (proto.Message, error) -} - -type anyResolver struct{ AnyResolver } - -func (r anyResolver) FindMessageByName(message protoreflect.FullName) (protoreflect.MessageType, error) { - return r.FindMessageByURL(string(message)) -} - -func (r anyResolver) FindMessageByURL(url string) (protoreflect.MessageType, error) { - m, err := r.Resolve(url) - if err != nil { - return nil, err - } - return protoimpl.X.MessageTypeOf(m), nil -} - -func (r anyResolver) FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) { - return protoregistry.GlobalTypes.FindExtensionByName(field) -} - -func (r anyResolver) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) { - return protoregistry.GlobalTypes.FindExtensionByNumber(message, field) -} - -func wellKnownType(s protoreflect.FullName) string { - if s.Parent() == "google.protobuf" { - switch s.Name() { - case "Empty", "Any", - "BoolValue", "BytesValue", "StringValue", - "Int32Value", "UInt32Value", "FloatValue", - "Int64Value", "UInt64Value", "DoubleValue", - "Duration", "Timestamp", - "NullValue", "Struct", "Value", "ListValue": - return string(s.Name()) - } - } - return "" -} - -func isMessageSet(md protoreflect.MessageDescriptor) bool { - ms, ok := md.(interface{ IsMessageSet() bool }) - return ok && ms.IsMessageSet() -} diff --git a/vendor/github.com/golang/protobuf/ptypes/any.go b/vendor/github.com/golang/protobuf/ptypes/any.go deleted file mode 100644 index 85f9f57365..0000000000 --- a/vendor/github.com/golang/protobuf/ptypes/any.go +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ptypes - -import ( - "fmt" - "strings" - - "github.com/golang/protobuf/proto" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/reflect/protoregistry" - - anypb "github.com/golang/protobuf/ptypes/any" -) - -const urlPrefix = "type.googleapis.com/" - -// AnyMessageName returns the message name contained in an anypb.Any message. -// Most type assertions should use the Is function instead. -// -// Deprecated: Call the any.MessageName method instead. -func AnyMessageName(any *anypb.Any) (string, error) { - name, err := anyMessageName(any) - return string(name), err -} -func anyMessageName(any *anypb.Any) (protoreflect.FullName, error) { - if any == nil { - return "", fmt.Errorf("message is nil") - } - name := protoreflect.FullName(any.TypeUrl) - if i := strings.LastIndex(any.TypeUrl, "/"); i >= 0 { - name = name[i+len("/"):] - } - if !name.IsValid() { - return "", fmt.Errorf("message type url %q is invalid", any.TypeUrl) - } - return name, nil -} - -// MarshalAny marshals the given message m into an anypb.Any message. -// -// Deprecated: Call the anypb.New function instead. -func MarshalAny(m proto.Message) (*anypb.Any, error) { - switch dm := m.(type) { - case DynamicAny: - m = dm.Message - case *DynamicAny: - if dm == nil { - return nil, proto.ErrNil - } - m = dm.Message - } - b, err := proto.Marshal(m) - if err != nil { - return nil, err - } - return &anypb.Any{TypeUrl: urlPrefix + proto.MessageName(m), Value: b}, nil -} - -// Empty returns a new message of the type specified in an anypb.Any message. -// It returns protoregistry.NotFound if the corresponding message type could not -// be resolved in the global registry. -// -// Deprecated: Use protoregistry.GlobalTypes.FindMessageByName instead -// to resolve the message name and create a new instance of it. -func Empty(any *anypb.Any) (proto.Message, error) { - name, err := anyMessageName(any) - if err != nil { - return nil, err - } - mt, err := protoregistry.GlobalTypes.FindMessageByName(name) - if err != nil { - return nil, err - } - return proto.MessageV1(mt.New().Interface()), nil -} - -// UnmarshalAny unmarshals the encoded value contained in the anypb.Any message -// into the provided message m. It returns an error if the target message -// does not match the type in the Any message or if an unmarshal error occurs. -// -// The target message m may be a *DynamicAny message. If the underlying message -// type could not be resolved, then this returns protoregistry.NotFound. -// -// Deprecated: Call the any.UnmarshalTo method instead. -func UnmarshalAny(any *anypb.Any, m proto.Message) error { - if dm, ok := m.(*DynamicAny); ok { - if dm.Message == nil { - var err error - dm.Message, err = Empty(any) - if err != nil { - return err - } - } - m = dm.Message - } - - anyName, err := AnyMessageName(any) - if err != nil { - return err - } - msgName := proto.MessageName(m) - if anyName != msgName { - return fmt.Errorf("mismatched message type: got %q want %q", anyName, msgName) - } - return proto.Unmarshal(any.Value, m) -} - -// Is reports whether the Any message contains a message of the specified type. -// -// Deprecated: Call the any.MessageIs method instead. -func Is(any *anypb.Any, m proto.Message) bool { - if any == nil || m == nil { - return false - } - name := proto.MessageName(m) - if !strings.HasSuffix(any.TypeUrl, name) { - return false - } - return len(any.TypeUrl) == len(name) || any.TypeUrl[len(any.TypeUrl)-len(name)-1] == '/' -} - -// DynamicAny is a value that can be passed to UnmarshalAny to automatically -// allocate a proto.Message for the type specified in an anypb.Any message. -// The allocated message is stored in the embedded proto.Message. -// -// Example: -// var x ptypes.DynamicAny -// if err := ptypes.UnmarshalAny(a, &x); err != nil { ... } -// fmt.Printf("unmarshaled message: %v", x.Message) -// -// Deprecated: Use the any.UnmarshalNew method instead to unmarshal -// the any message contents into a new instance of the underlying message. -type DynamicAny struct{ proto.Message } - -func (m DynamicAny) String() string { - if m.Message == nil { - return "" - } - return m.Message.String() -} -func (m DynamicAny) Reset() { - if m.Message == nil { - return - } - m.Message.Reset() -} -func (m DynamicAny) ProtoMessage() { - return -} -func (m DynamicAny) ProtoReflect() protoreflect.Message { - if m.Message == nil { - return nil - } - return dynamicAny{proto.MessageReflect(m.Message)} -} - -type dynamicAny struct{ protoreflect.Message } - -func (m dynamicAny) Type() protoreflect.MessageType { - return dynamicAnyType{m.Message.Type()} -} -func (m dynamicAny) New() protoreflect.Message { - return dynamicAnyType{m.Message.Type()}.New() -} -func (m dynamicAny) Interface() protoreflect.ProtoMessage { - return DynamicAny{proto.MessageV1(m.Message.Interface())} -} - -type dynamicAnyType struct{ protoreflect.MessageType } - -func (t dynamicAnyType) New() protoreflect.Message { - return dynamicAny{t.MessageType.New()} -} -func (t dynamicAnyType) Zero() protoreflect.Message { - return dynamicAny{t.MessageType.Zero()} -} diff --git a/vendor/github.com/golang/protobuf/ptypes/doc.go b/vendor/github.com/golang/protobuf/ptypes/doc.go deleted file mode 100644 index d3c33259d2..0000000000 --- a/vendor/github.com/golang/protobuf/ptypes/doc.go +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package ptypes provides functionality for interacting with well-known types. -// -// Deprecated: Well-known types have specialized functionality directly -// injected into the generated packages for each message type. -// See the deprecation notice for each function for the suggested alternative. -package ptypes diff --git a/vendor/github.com/golang/protobuf/ptypes/duration.go b/vendor/github.com/golang/protobuf/ptypes/duration.go deleted file mode 100644 index b2b55dd851..0000000000 --- a/vendor/github.com/golang/protobuf/ptypes/duration.go +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ptypes - -import ( - "errors" - "fmt" - "time" - - durationpb "github.com/golang/protobuf/ptypes/duration" -) - -// Range of google.protobuf.Duration as specified in duration.proto. -// This is about 10,000 years in seconds. -const ( - maxSeconds = int64(10000 * 365.25 * 24 * 60 * 60) - minSeconds = -maxSeconds -) - -// Duration converts a durationpb.Duration to a time.Duration. -// Duration returns an error if dur is invalid or overflows a time.Duration. -// -// Deprecated: Call the dur.AsDuration and dur.CheckValid methods instead. -func Duration(dur *durationpb.Duration) (time.Duration, error) { - if err := validateDuration(dur); err != nil { - return 0, err - } - d := time.Duration(dur.Seconds) * time.Second - if int64(d/time.Second) != dur.Seconds { - return 0, fmt.Errorf("duration: %v is out of range for time.Duration", dur) - } - if dur.Nanos != 0 { - d += time.Duration(dur.Nanos) * time.Nanosecond - if (d < 0) != (dur.Nanos < 0) { - return 0, fmt.Errorf("duration: %v is out of range for time.Duration", dur) - } - } - return d, nil -} - -// DurationProto converts a time.Duration to a durationpb.Duration. -// -// Deprecated: Call the durationpb.New function instead. -func DurationProto(d time.Duration) *durationpb.Duration { - nanos := d.Nanoseconds() - secs := nanos / 1e9 - nanos -= secs * 1e9 - return &durationpb.Duration{ - Seconds: int64(secs), - Nanos: int32(nanos), - } -} - -// validateDuration determines whether the durationpb.Duration is valid -// according to the definition in google/protobuf/duration.proto. -// A valid durpb.Duration may still be too large to fit into a time.Duration -// Note that the range of durationpb.Duration is about 10,000 years, -// while the range of time.Duration is about 290 years. -func validateDuration(dur *durationpb.Duration) error { - if dur == nil { - return errors.New("duration: nil Duration") - } - if dur.Seconds < minSeconds || dur.Seconds > maxSeconds { - return fmt.Errorf("duration: %v: seconds out of range", dur) - } - if dur.Nanos <= -1e9 || dur.Nanos >= 1e9 { - return fmt.Errorf("duration: %v: nanos out of range", dur) - } - // Seconds and Nanos must have the same sign, unless d.Nanos is zero. - if (dur.Seconds < 0 && dur.Nanos > 0) || (dur.Seconds > 0 && dur.Nanos < 0) { - return fmt.Errorf("duration: %v: seconds and nanos have different signs", dur) - } - return nil -} diff --git a/vendor/github.com/golang/protobuf/ptypes/timestamp.go b/vendor/github.com/golang/protobuf/ptypes/timestamp.go deleted file mode 100644 index 8368a3f70d..0000000000 --- a/vendor/github.com/golang/protobuf/ptypes/timestamp.go +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ptypes - -import ( - "errors" - "fmt" - "time" - - timestamppb "github.com/golang/protobuf/ptypes/timestamp" -) - -// Range of google.protobuf.Duration as specified in timestamp.proto. -const ( - // Seconds field of the earliest valid Timestamp. - // This is time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC).Unix(). - minValidSeconds = -62135596800 - // Seconds field just after the latest valid Timestamp. - // This is time.Date(10000, 1, 1, 0, 0, 0, 0, time.UTC).Unix(). - maxValidSeconds = 253402300800 -) - -// Timestamp converts a timestamppb.Timestamp to a time.Time. -// It returns an error if the argument is invalid. -// -// Unlike most Go functions, if Timestamp returns an error, the first return -// value is not the zero time.Time. Instead, it is the value obtained from the -// time.Unix function when passed the contents of the Timestamp, in the UTC -// locale. This may or may not be a meaningful time; many invalid Timestamps -// do map to valid time.Times. -// -// A nil Timestamp returns an error. The first return value in that case is -// undefined. -// -// Deprecated: Call the ts.AsTime and ts.CheckValid methods instead. -func Timestamp(ts *timestamppb.Timestamp) (time.Time, error) { - // Don't return the zero value on error, because corresponds to a valid - // timestamp. Instead return whatever time.Unix gives us. - var t time.Time - if ts == nil { - t = time.Unix(0, 0).UTC() // treat nil like the empty Timestamp - } else { - t = time.Unix(ts.Seconds, int64(ts.Nanos)).UTC() - } - return t, validateTimestamp(ts) -} - -// TimestampNow returns a google.protobuf.Timestamp for the current time. -// -// Deprecated: Call the timestamppb.Now function instead. -func TimestampNow() *timestamppb.Timestamp { - ts, err := TimestampProto(time.Now()) - if err != nil { - panic("ptypes: time.Now() out of Timestamp range") - } - return ts -} - -// TimestampProto converts the time.Time to a google.protobuf.Timestamp proto. -// It returns an error if the resulting Timestamp is invalid. -// -// Deprecated: Call the timestamppb.New function instead. -func TimestampProto(t time.Time) (*timestamppb.Timestamp, error) { - ts := ×tamppb.Timestamp{ - Seconds: t.Unix(), - Nanos: int32(t.Nanosecond()), - } - if err := validateTimestamp(ts); err != nil { - return nil, err - } - return ts, nil -} - -// TimestampString returns the RFC 3339 string for valid Timestamps. -// For invalid Timestamps, it returns an error message in parentheses. -// -// Deprecated: Call the ts.AsTime method instead, -// followed by a call to the Format method on the time.Time value. -func TimestampString(ts *timestamppb.Timestamp) string { - t, err := Timestamp(ts) - if err != nil { - return fmt.Sprintf("(%v)", err) - } - return t.Format(time.RFC3339Nano) -} - -// validateTimestamp determines whether a Timestamp is valid. -// A valid timestamp represents a time in the range [0001-01-01, 10000-01-01) -// and has a Nanos field in the range [0, 1e9). -// -// If the Timestamp is valid, validateTimestamp returns nil. -// Otherwise, it returns an error that describes the problem. -// -// Every valid Timestamp can be represented by a time.Time, -// but the converse is not true. -func validateTimestamp(ts *timestamppb.Timestamp) error { - if ts == nil { - return errors.New("timestamp: nil Timestamp") - } - if ts.Seconds < minValidSeconds { - return fmt.Errorf("timestamp: %v before 0001-01-01", ts) - } - if ts.Seconds >= maxValidSeconds { - return fmt.Errorf("timestamp: %v after 10000-01-01", ts) - } - if ts.Nanos < 0 || ts.Nanos >= 1e9 { - return fmt.Errorf("timestamp: %v: nanos not in range [0, 1e9)", ts) - } - return nil -} diff --git a/vendor/github.com/googleapis/gax-go/v2/.release-please-manifest.json b/vendor/github.com/googleapis/gax-go/v2/.release-please-manifest.json index ef508417b3..b2a67c0a22 100644 --- a/vendor/github.com/googleapis/gax-go/v2/.release-please-manifest.json +++ b/vendor/github.com/googleapis/gax-go/v2/.release-please-manifest.json @@ -1,3 +1,3 @@ { - "v2": "2.12.0" + "v2": "2.12.2" } diff --git a/vendor/github.com/googleapis/gax-go/v2/CHANGES.md b/vendor/github.com/googleapis/gax-go/v2/CHANGES.md index ae71149470..5f0908e689 100644 --- a/vendor/github.com/googleapis/gax-go/v2/CHANGES.md +++ b/vendor/github.com/googleapis/gax-go/v2/CHANGES.md @@ -1,5 +1,19 @@ # Changelog +## [2.12.2](https://github.com/googleapis/gax-go/compare/v2.12.1...v2.12.2) (2024-02-23) + + +### Bug Fixes + +* **v2/callctx:** fix SetHeader race by cloning header map ([#326](https://github.com/googleapis/gax-go/issues/326)) ([534311f](https://github.com/googleapis/gax-go/commit/534311f0f163d101f30657736c0e6f860e9c39dc)) + +## [2.12.1](https://github.com/googleapis/gax-go/compare/v2.12.0...v2.12.1) (2024-02-13) + + +### Bug Fixes + +* add XGoogFieldMaskHeader constant ([#321](https://github.com/googleapis/gax-go/issues/321)) ([666ee08](https://github.com/googleapis/gax-go/commit/666ee08931041b7fed56bed7132649785b2d3dfe)) + ## [2.12.0](https://github.com/googleapis/gax-go/compare/v2.11.0...v2.12.0) (2023-06-26) diff --git a/vendor/github.com/googleapis/gax-go/v2/callctx/callctx.go b/vendor/github.com/googleapis/gax-go/v2/callctx/callctx.go index af15fb5827..f5af5c990f 100644 --- a/vendor/github.com/googleapis/gax-go/v2/callctx/callctx.go +++ b/vendor/github.com/googleapis/gax-go/v2/callctx/callctx.go @@ -38,6 +38,14 @@ import ( ) const ( + // XGoogFieldMaskHeader is the canonical header key for the [System Parameter] + // that specifies the response read mask. The value(s) for this header + // must adhere to format described in [fieldmaskpb]. + // + // [System Parameter]: https://cloud.google.com/apis/docs/system-parameters + // [fieldmaskpb]: https://google.golang.org/protobuf/types/known/fieldmaskpb + XGoogFieldMaskHeader = "x-goog-fieldmask" + headerKey = contextKey("header") ) @@ -66,9 +74,27 @@ func SetHeaders(ctx context.Context, keyvals ...string) context.Context { h, ok := ctx.Value(headerKey).(map[string][]string) if !ok { h = make(map[string][]string) + } else { + h = cloneHeaders(h) } + for i := 0; i < len(keyvals); i = i + 2 { h[keyvals[i]] = append(h[keyvals[i]], keyvals[i+1]) } return context.WithValue(ctx, headerKey, h) } + +// cloneHeaders makes a new key-value map while reusing the value slices. +// As such, new values should be appended to the value slice, and modifying +// indexed values is not thread safe. +// +// TODO: Replace this with maps.Clone when Go 1.21 is the minimum version. +func cloneHeaders(h map[string][]string) map[string][]string { + c := make(map[string][]string, len(h)) + for k, v := range h { + vc := make([]string, len(v)) + copy(vc, v) + c[k] = vc + } + return c +} diff --git a/vendor/github.com/googleapis/gax-go/v2/header.go b/vendor/github.com/googleapis/gax-go/v2/header.go index 453fab7ecc..3e53729e5f 100644 --- a/vendor/github.com/googleapis/gax-go/v2/header.go +++ b/vendor/github.com/googleapis/gax-go/v2/header.go @@ -103,7 +103,9 @@ func goVersion() string { return "UNKNOWN" } -// XGoogHeader is for use by the Google Cloud Libraries only. +// XGoogHeader is for use by the Google Cloud Libraries only. See package +// [github.com/googleapis/gax-go/v2/callctx] for help setting/retrieving +// request/response headers. // // XGoogHeader formats key-value pairs. // The resulting string is suitable for x-goog-api-client header. @@ -125,7 +127,8 @@ func XGoogHeader(keyval ...string) string { } // InsertMetadataIntoOutgoingContext is for use by the Google Cloud Libraries -// only. +// only. See package [github.com/googleapis/gax-go/v2/callctx] for help +// setting/retrieving request/response headers. // // InsertMetadataIntoOutgoingContext returns a new context that merges the // provided keyvals metadata pairs with any existing metadata/headers in the @@ -137,7 +140,9 @@ func InsertMetadataIntoOutgoingContext(ctx context.Context, keyvals ...string) c return metadata.NewOutgoingContext(ctx, insertMetadata(ctx, keyvals...)) } -// BuildHeaders is for use by the Google Cloud Libraries only. +// BuildHeaders is for use by the Google Cloud Libraries only. See package +// [github.com/googleapis/gax-go/v2/callctx] for help setting/retrieving +// request/response headers. // // BuildHeaders returns a new http.Header that merges the provided // keyvals header pairs with any existing metadata/headers in the provided diff --git a/vendor/github.com/googleapis/gax-go/v2/internal/version.go b/vendor/github.com/googleapis/gax-go/v2/internal/version.go index 7425b5ffbb..53c04d4d45 100644 --- a/vendor/github.com/googleapis/gax-go/v2/internal/version.go +++ b/vendor/github.com/googleapis/gax-go/v2/internal/version.go @@ -30,4 +30,4 @@ package internal // Version is the current tagged release of the library. -const Version = "2.12.0" +const Version = "2.12.2" diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/LICENSE.txt b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/LICENSE similarity index 100% rename from vendor/github.com/grpc-ecosystem/grpc-gateway/v2/LICENSE.txt rename to vendor/github.com/grpc-ecosystem/grpc-gateway/v2/LICENSE diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule/BUILD.bazel b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule/BUILD.bazel index f694f3c0d0..b8fbb2b77c 100644 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule/BUILD.bazel +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule/BUILD.bazel @@ -24,7 +24,7 @@ go_test( embed = [":httprule"], deps = [ "//utilities", - "@com_github_golang_glog//:glog", + "@org_golang_google_grpc//grpclog", ], ) diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/BUILD.bazel b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/BUILD.bazel index a8789f1702..78d7c9f5c8 100644 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/BUILD.bazel +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/BUILD.bazel @@ -26,7 +26,7 @@ go_library( deps = [ "//internal/httprule", "//utilities", - "@go_googleapis//google/api:httpbody_go_proto", + "@org_golang_google_genproto_googleapis_api//httpbody", "@org_golang_google_grpc//codes", "@org_golang_google_grpc//grpclog", "@org_golang_google_grpc//health/grpc_health_v1", @@ -70,9 +70,9 @@ go_test( "//utilities", "@com_github_google_go_cmp//cmp", "@com_github_google_go_cmp//cmp/cmpopts", - "@go_googleapis//google/api:httpbody_go_proto", - "@go_googleapis//google/rpc:errdetails_go_proto", - "@go_googleapis//google/rpc:status_go_proto", + "@org_golang_google_genproto_googleapis_api//httpbody", + "@org_golang_google_genproto_googleapis_rpc//errdetails", + "@org_golang_google_genproto_googleapis_rpc//status", "@org_golang_google_grpc//:go_default_library", "@org_golang_google_grpc//codes", "@org_golang_google_grpc//health/grpc_health_v1", diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/errors.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/errors.go index d2bcbb7d2a..230cac7b86 100644 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/errors.go +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/errors.go @@ -137,7 +137,7 @@ func DefaultHTTPErrorHandler(ctx context.Context, mux *ServeMux, marshaler Marsh doForwardTrailers := requestAcceptsTrailers(r) if doForwardTrailers { - handleForwardResponseTrailerHeader(w, md) + handleForwardResponseTrailerHeader(w, mux, md) w.Header().Set("Transfer-Encoding", "chunked") } @@ -152,7 +152,7 @@ func DefaultHTTPErrorHandler(ctx context.Context, mux *ServeMux, marshaler Marsh } if doForwardTrailers { - handleForwardResponseTrailer(w, md) + handleForwardResponseTrailer(w, mux, md) } } diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/fieldmask.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/fieldmask.go index a03dd166bd..19d9d37fff 100644 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/fieldmask.go +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/fieldmask.go @@ -27,7 +27,7 @@ func FieldMaskFromRequestBody(r io.Reader, msg proto.Message) (*field_mask.Field var root interface{} if err := json.NewDecoder(r).Decode(&root); err != nil { - if err == io.EOF { + if errors.Is(err, io.EOF) { return fm, nil } return nil, err diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/handler.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/handler.go index 945f3a5ebf..5e14cf8b0e 100644 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/handler.go +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/handler.go @@ -2,7 +2,7 @@ package runtime import ( "context" - "fmt" + "errors" "io" "net/http" "net/textproto" @@ -48,7 +48,7 @@ func ForwardResponseStream(ctx context.Context, mux *ServeMux, marshaler Marshal var wroteHeader bool for { resp, err := recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { return } if err != nil { @@ -108,18 +108,20 @@ func handleForwardResponseServerMetadata(w http.ResponseWriter, mux *ServeMux, m } } -func handleForwardResponseTrailerHeader(w http.ResponseWriter, md ServerMetadata) { +func handleForwardResponseTrailerHeader(w http.ResponseWriter, mux *ServeMux, md ServerMetadata) { for k := range md.TrailerMD { - tKey := textproto.CanonicalMIMEHeaderKey(fmt.Sprintf("%s%s", MetadataTrailerPrefix, k)) - w.Header().Add("Trailer", tKey) + if h, ok := mux.outgoingTrailerMatcher(k); ok { + w.Header().Add("Trailer", textproto.CanonicalMIMEHeaderKey(h)) + } } } -func handleForwardResponseTrailer(w http.ResponseWriter, md ServerMetadata) { +func handleForwardResponseTrailer(w http.ResponseWriter, mux *ServeMux, md ServerMetadata) { for k, vs := range md.TrailerMD { - tKey := fmt.Sprintf("%s%s", MetadataTrailerPrefix, k) - for _, v := range vs { - w.Header().Add(tKey, v) + if h, ok := mux.outgoingTrailerMatcher(k); ok { + for _, v := range vs { + w.Header().Add(h, v) + } } } } @@ -147,12 +149,10 @@ func ForwardResponseMessage(ctx context.Context, mux *ServeMux, marshaler Marsha doForwardTrailers := requestAcceptsTrailers(req) if doForwardTrailers { - handleForwardResponseTrailerHeader(w, md) + handleForwardResponseTrailerHeader(w, mux, md) w.Header().Set("Transfer-Encoding", "chunked") } - handleForwardResponseTrailerHeader(w, md) - contentType := marshaler.ContentType(resp) w.Header().Set("Content-Type", contentType) @@ -178,7 +178,7 @@ func ForwardResponseMessage(ctx context.Context, mux *ServeMux, marshaler Marsha } if doForwardTrailers { - handleForwardResponseTrailer(w, md) + handleForwardResponseTrailer(w, mux, md) } } diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_httpbodyproto.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_httpbodyproto.go index b86135c889..6de2e220c7 100644 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_httpbodyproto.go +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_httpbodyproto.go @@ -26,7 +26,7 @@ func (h *HTTPBodyMarshaler) ContentType(v interface{}) string { // google.api.HttpBody message, otherwise it falls back to the default Marshaler. func (h *HTTPBodyMarshaler) Marshal(v interface{}) ([]byte, error) { if httpBody, ok := v.(*httpbody.HttpBody); ok { - return httpBody.Data, nil + return httpBody.GetData(), nil } return h.Marshaler.Marshal(v) } diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/mux.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/mux.go index f451cb441f..628e1fde1c 100644 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/mux.go +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/mux.go @@ -57,6 +57,7 @@ type ServeMux struct { marshalers marshalerRegistry incomingHeaderMatcher HeaderMatcherFunc outgoingHeaderMatcher HeaderMatcherFunc + outgoingTrailerMatcher HeaderMatcherFunc metadataAnnotators []func(context.Context, *http.Request) metadata.MD errorHandler ErrorHandlerFunc streamErrorHandler StreamErrorHandlerFunc @@ -114,10 +115,18 @@ func DefaultHeaderMatcher(key string) (string, bool) { return "", false } +func defaultOutgoingHeaderMatcher(key string) (string, bool) { + return fmt.Sprintf("%s%s", MetadataHeaderPrefix, key), true +} + +func defaultOutgoingTrailerMatcher(key string) (string, bool) { + return fmt.Sprintf("%s%s", MetadataTrailerPrefix, key), true +} + // WithIncomingHeaderMatcher returns a ServeMuxOption representing a headerMatcher for incoming request to gateway. // // This matcher will be called with each header in http.Request. If matcher returns true, that header will be -// passed to gRPC context. To transform the header before passing to gRPC context, matcher should return modified header. +// passed to gRPC context. To transform the header before passing to gRPC context, matcher should return the modified header. func WithIncomingHeaderMatcher(fn HeaderMatcherFunc) ServeMuxOption { for _, header := range fn.matchedMalformedHeaders() { grpclog.Warningf("The configured forwarding filter would allow %q to be sent to the gRPC server, which will likely cause errors. See https://github.com/grpc/grpc-go/pull/4803#issuecomment-986093310 for more information.", header) @@ -147,13 +156,24 @@ func (fn HeaderMatcherFunc) matchedMalformedHeaders() []string { // // This matcher will be called with each header in response header metadata. If matcher returns true, that header will be // passed to http response returned from gateway. To transform the header before passing to response, -// matcher should return modified header. +// matcher should return the modified header. func WithOutgoingHeaderMatcher(fn HeaderMatcherFunc) ServeMuxOption { return func(mux *ServeMux) { mux.outgoingHeaderMatcher = fn } } +// WithOutgoingTrailerMatcher returns a ServeMuxOption representing a headerMatcher for outgoing response from gateway. +// +// This matcher will be called with each header in response trailer metadata. If matcher returns true, that header will be +// passed to http response returned from gateway. To transform the header before passing to response, +// matcher should return the modified header. +func WithOutgoingTrailerMatcher(fn HeaderMatcherFunc) ServeMuxOption { + return func(mux *ServeMux) { + mux.outgoingTrailerMatcher = fn + } +} + // WithMetadata returns a ServeMuxOption for passing metadata to a gRPC context. // // This can be used by services that need to read from http.Request and modify gRPC context. A common use case @@ -273,11 +293,11 @@ func NewServeMux(opts ...ServeMuxOption) *ServeMux { if serveMux.incomingHeaderMatcher == nil { serveMux.incomingHeaderMatcher = DefaultHeaderMatcher } - if serveMux.outgoingHeaderMatcher == nil { - serveMux.outgoingHeaderMatcher = func(key string) (string, bool) { - return fmt.Sprintf("%s%s", MetadataHeaderPrefix, key), true - } + serveMux.outgoingHeaderMatcher = defaultOutgoingHeaderMatcher + } + if serveMux.outgoingTrailerMatcher == nil { + serveMux.outgoingTrailerMatcher = defaultOutgoingTrailerMatcher } return serveMux diff --git a/vendor/github.com/hashicorp/consul/api/acl.go b/vendor/github.com/hashicorp/consul/api/acl.go index f95e597af4..fcea0fdde0 100644 --- a/vendor/github.com/hashicorp/consul/api/acl.go +++ b/vendor/github.com/hashicorp/consul/api/acl.go @@ -256,6 +256,9 @@ const ( // BindingRuleBindTypeNode binds to a node identity with given name. BindingRuleBindTypeNode BindingRuleBindType = "node" + // BindingRuleBindTypePolicy binds to a specific policy with given name. + BindingRuleBindTypePolicy BindingRuleBindType = "policy" + // BindingRuleBindTypeTemplatedPolicy binds to a templated policy with given template name and variables. BindingRuleBindTypeTemplatedPolicy BindingRuleBindType = "templated-policy" ) diff --git a/vendor/github.com/hashicorp/consul/api/config_entry_discoverychain.go b/vendor/github.com/hashicorp/consul/api/config_entry_discoverychain.go index eeb3a1074c..572d9d2d5e 100644 --- a/vendor/github.com/hashicorp/consul/api/config_entry_discoverychain.go +++ b/vendor/github.com/hashicorp/consul/api/config_entry_discoverychain.go @@ -41,9 +41,10 @@ type ServiceRouteMatch struct { } type ServiceRouteHTTPMatch struct { - PathExact string `json:",omitempty" alias:"path_exact"` - PathPrefix string `json:",omitempty" alias:"path_prefix"` - PathRegex string `json:",omitempty" alias:"path_regex"` + PathExact string `json:",omitempty" alias:"path_exact"` + PathPrefix string `json:",omitempty" alias:"path_prefix"` + PathRegex string `json:",omitempty" alias:"path_regex"` + CaseInsensitive bool `json:",omitempty" alias:"case_insensitive"` Header []ServiceRouteHTTPMatchHeader `json:",omitempty"` QueryParam []ServiceRouteHTTPMatchQueryParam `json:",omitempty" alias:"query_param"` diff --git a/vendor/github.com/hashicorp/consul/api/config_entry_exports.go b/vendor/github.com/hashicorp/consul/api/config_entry_exports.go index 97920e40dd..b8e9830e65 100644 --- a/vendor/github.com/hashicorp/consul/api/config_entry_exports.go +++ b/vendor/github.com/hashicorp/consul/api/config_entry_exports.go @@ -3,7 +3,9 @@ package api -import "encoding/json" +import ( + "encoding/json" +) // ExportedServicesConfigEntry manages the exported services for a single admin partition. // Admin Partitions are a Consul Enterprise feature. diff --git a/vendor/github.com/hashicorp/consul/api/exported_services.go b/vendor/github.com/hashicorp/consul/api/exported_services.go new file mode 100644 index 0000000000..50483e9c8d --- /dev/null +++ b/vendor/github.com/hashicorp/consul/api/exported_services.go @@ -0,0 +1,49 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package api + +type ResolvedExportedService struct { + // Service is the name of the service which is exported. + Service string + + // Partition of the service + Partition string `json:",omitempty"` + + // Namespace of the service + Namespace string `json:",omitempty"` + + // Consumers is a list of downstream consumers of the service. + Consumers ResolvedConsumers +} + +type ResolvedConsumers struct { + Peers []string `json:",omitempty"` + Partitions []string `json:",omitempty"` +} + +func (c *Client) ExportedServices(q *QueryOptions) ([]ResolvedExportedService, *QueryMeta, error) { + + r := c.newRequest("GET", "/v1/exported-services") + r.setQueryOptions(q) + rtt, resp, err := c.doRequest(r) + if err != nil { + return nil, nil, err + } + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, nil, err + } + + qm := &QueryMeta{} + parseQueryMeta(resp, qm) + qm.RequestTime = rtt + + var expSvcs []ResolvedExportedService + + if err := decodeBody(resp, &expSvcs); err != nil { + return nil, nil, err + } + + return expSvcs, qm, nil +} diff --git a/vendor/github.com/hashicorp/golang-lru/v2/.golangci.yml b/vendor/github.com/hashicorp/golang-lru/v2/.golangci.yml index 95700902d9..7e7b8a9627 100644 --- a/vendor/github.com/hashicorp/golang-lru/v2/.golangci.yml +++ b/vendor/github.com/hashicorp/golang-lru/v2/.golangci.yml @@ -2,12 +2,13 @@ # SPDX-License-Identifier: MPL-2.0 linters: + fast: false + disable-all: true enable: - - megacheck - revive + - megacheck - govet - unconvert - - megacheck - gas - gocyclo - dupl @@ -16,18 +17,30 @@ linters: - unused - typecheck - ineffassign - - stylecheck + # - stylecheck - exportloopref - gocritic - nakedret - gosimple - prealloc - fast: false - disable-all: true + +# golangci-lint configuration file +linters-settings: + revive: + ignore-generated-header: true + severity: warning + rules: + - name: package-comments + severity: warning + disabled: true + - name: exported + severity: warning + disabled: false + arguments: ["checkPrivateReceivers", "disableStutteringCheck"] issues: + exclude-use-default: false exclude-rules: - path: _test\.go linters: - dupl - exclude-use-default: false diff --git a/vendor/github.com/hashicorp/golang-lru/v2/2q.go b/vendor/github.com/hashicorp/golang-lru/v2/2q.go index 1f0055b7b5..8c95252b6f 100644 --- a/vendor/github.com/hashicorp/golang-lru/v2/2q.go +++ b/vendor/github.com/hashicorp/golang-lru/v2/2q.go @@ -30,8 +30,10 @@ const ( // head. The ARCCache is similar, but does not require setting any // parameters. type TwoQueueCache[K comparable, V any] struct { - size int - recentSize int + size int + recentSize int + recentRatio float64 + ghostRatio float64 recent simplelru.LRUCache[K, V] frequent simplelru.LRUCache[K, V] @@ -80,6 +82,8 @@ func New2QParams[K comparable, V any](size int, recentRatio, ghostRatio float64) c := &TwoQueueCache[K, V]{ size: size, recentSize: recentSize, + recentRatio: recentRatio, + ghostRatio: ghostRatio, recent: recent, frequent: frequent, recentEvict: recentEvict, @@ -171,6 +175,34 @@ func (c *TwoQueueCache[K, V]) Len() int { return c.recent.Len() + c.frequent.Len() } +// Resize changes the cache size. +func (c *TwoQueueCache[K, V]) Resize(size int) (evicted int) { + c.lock.Lock() + defer c.lock.Unlock() + + // Recalculate the sub-sizes + recentSize := int(float64(size) * c.recentRatio) + evictSize := int(float64(size) * c.ghostRatio) + c.size = size + c.recentSize = recentSize + + // ensureSpace + diff := c.recent.Len() + c.frequent.Len() - size + if diff < 0 { + diff = 0 + } + for i := 0; i < diff; i++ { + c.ensureSpace(true) + } + + // Reallocate the LRUs + c.recent.Resize(size) + c.frequent.Resize(size) + c.recentEvict.Resize(evictSize) + + return diff +} + // Keys returns a slice of the keys in the cache. // The frequently used keys are first in the returned slice. func (c *TwoQueueCache[K, V]) Keys() []K { @@ -181,6 +213,16 @@ func (c *TwoQueueCache[K, V]) Keys() []K { return append(k1, k2...) } +// Values returns a slice of the values in the cache. +// The frequently used values are first in the returned slice. +func (c *TwoQueueCache[K, V]) Values() []V { + c.lock.RLock() + defer c.lock.RUnlock() + v1 := c.frequent.Values() + v2 := c.recent.Values() + return append(v1, v2...) +} + // Remove removes the provided key from the cache. func (c *TwoQueueCache[K, V]) Remove(key K) { c.lock.Lock() diff --git a/vendor/github.com/hashicorp/golang-lru/v2/README.md b/vendor/github.com/hashicorp/golang-lru/v2/README.md index 4c08cc46ff..a942eb5397 100644 --- a/vendor/github.com/hashicorp/golang-lru/v2/README.md +++ b/vendor/github.com/hashicorp/golang-lru/v2/README.md @@ -9,17 +9,71 @@ Documentation Full docs are available on [Go Packages](https://pkg.go.dev/github.com/hashicorp/golang-lru/v2) -Example -======= - -Using the LRU is very simple: +LRU cache example +================= ```go -l, _ := New[int, interface{}](128) -for i := 0; i < 256; i++ { - l.Add(i, nil) +package main + +import ( + "fmt" + "github.com/hashicorp/golang-lru/v2" +) + +func main() { + l, _ := lru.New[int, any](128) + for i := 0; i < 256; i++ { + l.Add(i, nil) + } + if l.Len() != 128 { + panic(fmt.Sprintf("bad len: %v", l.Len())) + } } -if l.Len() != 128 { - panic(fmt.Sprintf("bad len: %v", l.Len())) +``` + +Expirable LRU cache example +=========================== + +```go +package main + +import ( + "fmt" + "time" + + "github.com/hashicorp/golang-lru/v2/expirable" +) + +func main() { + // make cache with 10ms TTL and 5 max keys + cache := expirable.NewLRU[string, string](5, nil, time.Millisecond*10) + + + // set value under key1. + cache.Add("key1", "val1") + + // get value under key1 + r, ok := cache.Get("key1") + + // check for OK value + if ok { + fmt.Printf("value before expiration is found: %v, value: %q\n", ok, r) + } + + // wait for cache to expire + time.Sleep(time.Millisecond * 12) + + // get value under key1 after key expiration + r, ok = cache.Get("key1") + fmt.Printf("value after expiration is found: %v, value: %q\n", ok, r) + + // set value under key2, would evict old entry because it is already expired. + cache.Add("key2", "val2") + + fmt.Printf("Cache len: %d\n", cache.Len()) + // Output: + // value before expiration is found: true, value: "val1" + // value after expiration is found: false, value: "" + // Cache len: 1 } ``` diff --git a/vendor/github.com/hashicorp/golang-lru/v2/arc.go b/vendor/github.com/hashicorp/golang-lru/v2/arc.go deleted file mode 100644 index a255aae219..0000000000 --- a/vendor/github.com/hashicorp/golang-lru/v2/arc.go +++ /dev/null @@ -1,259 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package lru - -import ( - "sync" - - "github.com/hashicorp/golang-lru/v2/simplelru" -) - -// ARCCache is a thread-safe fixed size Adaptive Replacement Cache (ARC). -// ARC is an enhancement over the standard LRU cache in that tracks both -// frequency and recency of use. This avoids a burst in access to new -// entries from evicting the frequently used older entries. It adds some -// additional tracking overhead to a standard LRU cache, computationally -// it is roughly 2x the cost, and the extra memory overhead is linear -// with the size of the cache. ARC has been patented by IBM, but is -// similar to the TwoQueueCache (2Q) which requires setting parameters. -type ARCCache[K comparable, V any] struct { - size int // Size is the total capacity of the cache - p int // P is the dynamic preference towards T1 or T2 - - t1 simplelru.LRUCache[K, V] // T1 is the LRU for recently accessed items - b1 simplelru.LRUCache[K, struct{}] // B1 is the LRU for evictions from t1 - - t2 simplelru.LRUCache[K, V] // T2 is the LRU for frequently accessed items - b2 simplelru.LRUCache[K, struct{}] // B2 is the LRU for evictions from t2 - - lock sync.RWMutex -} - -// NewARC creates an ARC of the given size -func NewARC[K comparable, V any](size int) (*ARCCache[K, V], error) { - // Create the sub LRUs - b1, err := simplelru.NewLRU[K, struct{}](size, nil) - if err != nil { - return nil, err - } - b2, err := simplelru.NewLRU[K, struct{}](size, nil) - if err != nil { - return nil, err - } - t1, err := simplelru.NewLRU[K, V](size, nil) - if err != nil { - return nil, err - } - t2, err := simplelru.NewLRU[K, V](size, nil) - if err != nil { - return nil, err - } - - // Initialize the ARC - c := &ARCCache[K, V]{ - size: size, - p: 0, - t1: t1, - b1: b1, - t2: t2, - b2: b2, - } - return c, nil -} - -// Get looks up a key's value from the cache. -func (c *ARCCache[K, V]) Get(key K) (value V, ok bool) { - c.lock.Lock() - defer c.lock.Unlock() - - // If the value is contained in T1 (recent), then - // promote it to T2 (frequent) - if val, ok := c.t1.Peek(key); ok { - c.t1.Remove(key) - c.t2.Add(key, val) - return val, ok - } - - // Check if the value is contained in T2 (frequent) - if val, ok := c.t2.Get(key); ok { - return val, ok - } - - // No hit - return -} - -// Add adds a value to the cache. -func (c *ARCCache[K, V]) Add(key K, value V) { - c.lock.Lock() - defer c.lock.Unlock() - - // Check if the value is contained in T1 (recent), and potentially - // promote it to frequent T2 - if c.t1.Contains(key) { - c.t1.Remove(key) - c.t2.Add(key, value) - return - } - - // Check if the value is already in T2 (frequent) and update it - if c.t2.Contains(key) { - c.t2.Add(key, value) - return - } - - // Check if this value was recently evicted as part of the - // recently used list - if c.b1.Contains(key) { - // T1 set is too small, increase P appropriately - delta := 1 - b1Len := c.b1.Len() - b2Len := c.b2.Len() - if b2Len > b1Len { - delta = b2Len / b1Len - } - if c.p+delta >= c.size { - c.p = c.size - } else { - c.p += delta - } - - // Potentially need to make room in the cache - if c.t1.Len()+c.t2.Len() >= c.size { - c.replace(false) - } - - // Remove from B1 - c.b1.Remove(key) - - // Add the key to the frequently used list - c.t2.Add(key, value) - return - } - - // Check if this value was recently evicted as part of the - // frequently used list - if c.b2.Contains(key) { - // T2 set is too small, decrease P appropriately - delta := 1 - b1Len := c.b1.Len() - b2Len := c.b2.Len() - if b1Len > b2Len { - delta = b1Len / b2Len - } - if delta >= c.p { - c.p = 0 - } else { - c.p -= delta - } - - // Potentially need to make room in the cache - if c.t1.Len()+c.t2.Len() >= c.size { - c.replace(true) - } - - // Remove from B2 - c.b2.Remove(key) - - // Add the key to the frequently used list - c.t2.Add(key, value) - return - } - - // Potentially need to make room in the cache - if c.t1.Len()+c.t2.Len() >= c.size { - c.replace(false) - } - - // Keep the size of the ghost buffers trim - if c.b1.Len() > c.size-c.p { - c.b1.RemoveOldest() - } - if c.b2.Len() > c.p { - c.b2.RemoveOldest() - } - - // Add to the recently seen list - c.t1.Add(key, value) -} - -// replace is used to adaptively evict from either T1 or T2 -// based on the current learned value of P -func (c *ARCCache[K, V]) replace(b2ContainsKey bool) { - t1Len := c.t1.Len() - if t1Len > 0 && (t1Len > c.p || (t1Len == c.p && b2ContainsKey)) { - k, _, ok := c.t1.RemoveOldest() - if ok { - c.b1.Add(k, struct{}{}) - } - } else { - k, _, ok := c.t2.RemoveOldest() - if ok { - c.b2.Add(k, struct{}{}) - } - } -} - -// Len returns the number of cached entries -func (c *ARCCache[K, V]) Len() int { - c.lock.RLock() - defer c.lock.RUnlock() - return c.t1.Len() + c.t2.Len() -} - -// Keys returns all the cached keys -func (c *ARCCache[K, V]) Keys() []K { - c.lock.RLock() - defer c.lock.RUnlock() - k1 := c.t1.Keys() - k2 := c.t2.Keys() - return append(k1, k2...) -} - -// Remove is used to purge a key from the cache -func (c *ARCCache[K, V]) Remove(key K) { - c.lock.Lock() - defer c.lock.Unlock() - if c.t1.Remove(key) { - return - } - if c.t2.Remove(key) { - return - } - if c.b1.Remove(key) { - return - } - if c.b2.Remove(key) { - return - } -} - -// Purge is used to clear the cache -func (c *ARCCache[K, V]) Purge() { - c.lock.Lock() - defer c.lock.Unlock() - c.t1.Purge() - c.t2.Purge() - c.b1.Purge() - c.b2.Purge() -} - -// Contains is used to check if the cache contains a key -// without updating recency or frequency. -func (c *ARCCache[K, V]) Contains(key K) bool { - c.lock.RLock() - defer c.lock.RUnlock() - return c.t1.Contains(key) || c.t2.Contains(key) -} - -// Peek is used to inspect the cache value of a key -// without updating recency or frequency. -func (c *ARCCache[K, V]) Peek(key K) (value V, ok bool) { - c.lock.RLock() - defer c.lock.RUnlock() - if val, ok := c.t1.Peek(key); ok { - return val, ok - } - return c.t2.Peek(key) -} diff --git a/vendor/github.com/hashicorp/golang-lru/v2/doc.go b/vendor/github.com/hashicorp/golang-lru/v2/doc.go index 2474929f7d..24107ee0ed 100644 --- a/vendor/github.com/hashicorp/golang-lru/v2/doc.go +++ b/vendor/github.com/hashicorp/golang-lru/v2/doc.go @@ -3,21 +3,21 @@ // Package lru provides three different LRU caches of varying sophistication. // -// Cache is a simple LRU cache. It is based on the -// LRU implementation in groupcache: -// https://github.com/golang/groupcache/tree/master/lru +// Cache is a simple LRU cache. It is based on the LRU implementation in +// groupcache: https://github.com/golang/groupcache/tree/master/lru // // TwoQueueCache tracks frequently used and recently used entries separately. -// This avoids a burst of accesses from taking out frequently used entries, -// at the cost of about 2x computational overhead and some extra bookkeeping. +// This avoids a burst of accesses from taking out frequently used entries, at +// the cost of about 2x computational overhead and some extra bookkeeping. // -// ARCCache is an adaptive replacement cache. It tracks recent evictions as -// well as recent usage in both the frequent and recent caches. Its -// computational overhead is comparable to TwoQueueCache, but the memory -// overhead is linear with the size of the cache. +// ARCCache is an adaptive replacement cache. It tracks recent evictions as well +// as recent usage in both the frequent and recent caches. Its computational +// overhead is comparable to TwoQueueCache, but the memory overhead is linear +// with the size of the cache. // // ARC has been patented by IBM, so do not use it if that is problematic for -// your program. +// your program. For this reason, it is in a separate go module contained within +// this repository. // // All caches in this package take locks while operating, and are therefore // thread-safe for consumers. diff --git a/vendor/github.com/hashicorp/golang-lru/v2/internal/list.go b/vendor/github.com/hashicorp/golang-lru/v2/internal/list.go new file mode 100644 index 0000000000..5cd74a0343 --- /dev/null +++ b/vendor/github.com/hashicorp/golang-lru/v2/internal/list.go @@ -0,0 +1,142 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE_list file. + +package internal + +import "time" + +// Entry is an LRU Entry +type Entry[K comparable, V any] struct { + // Next and previous pointers in the doubly-linked list of elements. + // To simplify the implementation, internally a list l is implemented + // as a ring, such that &l.root is both the next element of the last + // list element (l.Back()) and the previous element of the first list + // element (l.Front()). + next, prev *Entry[K, V] + + // The list to which this element belongs. + list *LruList[K, V] + + // The LRU Key of this element. + Key K + + // The Value stored with this element. + Value V + + // The time this element would be cleaned up, optional + ExpiresAt time.Time + + // The expiry bucket item was put in, optional + ExpireBucket uint8 +} + +// PrevEntry returns the previous list element or nil. +func (e *Entry[K, V]) PrevEntry() *Entry[K, V] { + if p := e.prev; e.list != nil && p != &e.list.root { + return p + } + return nil +} + +// LruList represents a doubly linked list. +// The zero Value for LruList is an empty list ready to use. +type LruList[K comparable, V any] struct { + root Entry[K, V] // sentinel list element, only &root, root.prev, and root.next are used + len int // current list Length excluding (this) sentinel element +} + +// Init initializes or clears list l. +func (l *LruList[K, V]) Init() *LruList[K, V] { + l.root.next = &l.root + l.root.prev = &l.root + l.len = 0 + return l +} + +// NewList returns an initialized list. +func NewList[K comparable, V any]() *LruList[K, V] { return new(LruList[K, V]).Init() } + +// Length returns the number of elements of list l. +// The complexity is O(1). +func (l *LruList[K, V]) Length() int { return l.len } + +// Back returns the last element of list l or nil if the list is empty. +func (l *LruList[K, V]) Back() *Entry[K, V] { + if l.len == 0 { + return nil + } + return l.root.prev +} + +// lazyInit lazily initializes a zero List Value. +func (l *LruList[K, V]) lazyInit() { + if l.root.next == nil { + l.Init() + } +} + +// insert inserts e after at, increments l.len, and returns e. +func (l *LruList[K, V]) insert(e, at *Entry[K, V]) *Entry[K, V] { + e.prev = at + e.next = at.next + e.prev.next = e + e.next.prev = e + e.list = l + l.len++ + return e +} + +// insertValue is a convenience wrapper for insert(&Entry{Value: v, ExpiresAt: ExpiresAt}, at). +func (l *LruList[K, V]) insertValue(k K, v V, expiresAt time.Time, at *Entry[K, V]) *Entry[K, V] { + return l.insert(&Entry[K, V]{Value: v, Key: k, ExpiresAt: expiresAt}, at) +} + +// Remove removes e from its list, decrements l.len +func (l *LruList[K, V]) Remove(e *Entry[K, V]) V { + e.prev.next = e.next + e.next.prev = e.prev + e.next = nil // avoid memory leaks + e.prev = nil // avoid memory leaks + e.list = nil + l.len-- + + return e.Value +} + +// move moves e to next to at. +func (l *LruList[K, V]) move(e, at *Entry[K, V]) { + if e == at { + return + } + e.prev.next = e.next + e.next.prev = e.prev + + e.prev = at + e.next = at.next + e.prev.next = e + e.next.prev = e +} + +// PushFront inserts a new element e with value v at the front of list l and returns e. +func (l *LruList[K, V]) PushFront(k K, v V) *Entry[K, V] { + l.lazyInit() + return l.insertValue(k, v, time.Time{}, &l.root) +} + +// PushFrontExpirable inserts a new expirable element e with Value v at the front of list l and returns e. +func (l *LruList[K, V]) PushFrontExpirable(k K, v V, expiresAt time.Time) *Entry[K, V] { + l.lazyInit() + return l.insertValue(k, v, expiresAt, &l.root) +} + +// MoveToFront moves element e to the front of list l. +// If e is not an element of l, the list is not modified. +// The element must not be nil. +func (l *LruList[K, V]) MoveToFront(e *Entry[K, V]) { + if e.list != l || l.root.next == e { + return + } + // see comment in List.Remove about initialization of l + l.move(e, &l.root) +} diff --git a/vendor/github.com/hashicorp/golang-lru/v2/lru.go b/vendor/github.com/hashicorp/golang-lru/v2/lru.go index 32d04170d5..a2655f1f31 100644 --- a/vendor/github.com/hashicorp/golang-lru/v2/lru.go +++ b/vendor/github.com/hashicorp/golang-lru/v2/lru.go @@ -233,6 +233,14 @@ func (c *Cache[K, V]) Keys() []K { return keys } +// Values returns a slice of the values in the cache, from oldest to newest. +func (c *Cache[K, V]) Values() []V { + c.lock.RLock() + values := c.lru.Values() + c.lock.RUnlock() + return values +} + // Len returns the number of items in the cache. func (c *Cache[K, V]) Len() int { c.lock.RLock() diff --git a/vendor/github.com/hashicorp/golang-lru/v2/simplelru/list.go b/vendor/github.com/hashicorp/golang-lru/v2/simplelru/list.go deleted file mode 100644 index c39da3c12d..0000000000 --- a/vendor/github.com/hashicorp/golang-lru/v2/simplelru/list.go +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE_list file. - -package simplelru - -// entry is an LRU entry -type entry[K comparable, V any] struct { - // Next and previous pointers in the doubly-linked list of elements. - // To simplify the implementation, internally a list l is implemented - // as a ring, such that &l.root is both the next element of the last - // list element (l.Back()) and the previous element of the first list - // element (l.Front()). - next, prev *entry[K, V] - - // The list to which this element belongs. - list *lruList[K, V] - - // The LRU key of this element. - key K - - // The value stored with this element. - value V -} - -// prevEntry returns the previous list element or nil. -func (e *entry[K, V]) prevEntry() *entry[K, V] { - if p := e.prev; e.list != nil && p != &e.list.root { - return p - } - return nil -} - -// lruList represents a doubly linked list. -// The zero value for lruList is an empty list ready to use. -type lruList[K comparable, V any] struct { - root entry[K, V] // sentinel list element, only &root, root.prev, and root.next are used - len int // current list length excluding (this) sentinel element -} - -// init initializes or clears list l. -func (l *lruList[K, V]) init() *lruList[K, V] { - l.root.next = &l.root - l.root.prev = &l.root - l.len = 0 - return l -} - -// newList returns an initialized list. -func newList[K comparable, V any]() *lruList[K, V] { return new(lruList[K, V]).init() } - -// length returns the number of elements of list l. -// The complexity is O(1). -func (l *lruList[K, V]) length() int { return l.len } - -// back returns the last element of list l or nil if the list is empty. -func (l *lruList[K, V]) back() *entry[K, V] { - if l.len == 0 { - return nil - } - return l.root.prev -} - -// lazyInit lazily initializes a zero List value. -func (l *lruList[K, V]) lazyInit() { - if l.root.next == nil { - l.init() - } -} - -// insert inserts e after at, increments l.len, and returns e. -func (l *lruList[K, V]) insert(e, at *entry[K, V]) *entry[K, V] { - e.prev = at - e.next = at.next - e.prev.next = e - e.next.prev = e - e.list = l - l.len++ - return e -} - -// insertValue is a convenience wrapper for insert(&Element{Value: v}, at). -func (l *lruList[K, V]) insertValue(k K, v V, at *entry[K, V]) *entry[K, V] { - return l.insert(&entry[K, V]{value: v, key: k}, at) -} - -// remove removes e from its list, decrements l.len -func (l *lruList[K, V]) remove(e *entry[K, V]) V { - e.prev.next = e.next - e.next.prev = e.prev - e.next = nil // avoid memory leaks - e.prev = nil // avoid memory leaks - e.list = nil - l.len-- - - return e.value -} - -// move moves e to next to at. -func (l *lruList[K, V]) move(e, at *entry[K, V]) { - if e == at { - return - } - e.prev.next = e.next - e.next.prev = e.prev - - e.prev = at - e.next = at.next - e.prev.next = e - e.next.prev = e -} - -// pushFront inserts a new element e with value v at the front of list l and returns e. -func (l *lruList[K, V]) pushFront(k K, v V) *entry[K, V] { - l.lazyInit() - return l.insertValue(k, v, &l.root) -} - -// moveToFront moves element e to the front of list l. -// If e is not an element of l, the list is not modified. -// The element must not be nil. -func (l *lruList[K, V]) moveToFront(e *entry[K, V]) { - if e.list != l || l.root.next == e { - return - } - // see comment in List.Remove about initialization of l - l.move(e, &l.root) -} diff --git a/vendor/github.com/hashicorp/golang-lru/v2/simplelru/lru.go b/vendor/github.com/hashicorp/golang-lru/v2/simplelru/lru.go index b6731afdd0..f69792388c 100644 --- a/vendor/github.com/hashicorp/golang-lru/v2/simplelru/lru.go +++ b/vendor/github.com/hashicorp/golang-lru/v2/simplelru/lru.go @@ -5,6 +5,8 @@ package simplelru import ( "errors" + + "github.com/hashicorp/golang-lru/v2/internal" ) // EvictCallback is used to get a callback when a cache entry is evicted @@ -13,8 +15,8 @@ type EvictCallback[K comparable, V any] func(key K, value V) // LRU implements a non-thread safe fixed size LRU cache type LRU[K comparable, V any] struct { size int - evictList *lruList[K, V] - items map[K]*entry[K, V] + evictList *internal.LruList[K, V] + items map[K]*internal.Entry[K, V] onEvict EvictCallback[K, V] } @@ -26,8 +28,8 @@ func NewLRU[K comparable, V any](size int, onEvict EvictCallback[K, V]) (*LRU[K, c := &LRU[K, V]{ size: size, - evictList: newList[K, V](), - items: make(map[K]*entry[K, V]), + evictList: internal.NewList[K, V](), + items: make(map[K]*internal.Entry[K, V]), onEvict: onEvict, } return c, nil @@ -37,27 +39,27 @@ func NewLRU[K comparable, V any](size int, onEvict EvictCallback[K, V]) (*LRU[K, func (c *LRU[K, V]) Purge() { for k, v := range c.items { if c.onEvict != nil { - c.onEvict(k, v.value) + c.onEvict(k, v.Value) } delete(c.items, k) } - c.evictList.init() + c.evictList.Init() } // Add adds a value to the cache. Returns true if an eviction occurred. func (c *LRU[K, V]) Add(key K, value V) (evicted bool) { // Check for existing item if ent, ok := c.items[key]; ok { - c.evictList.moveToFront(ent) - ent.value = value + c.evictList.MoveToFront(ent) + ent.Value = value return false } // Add new item - ent := c.evictList.pushFront(key, value) + ent := c.evictList.PushFront(key, value) c.items[key] = ent - evict := c.evictList.length() > c.size + evict := c.evictList.Length() > c.size // Verify size not exceeded if evict { c.removeOldest() @@ -68,8 +70,8 @@ func (c *LRU[K, V]) Add(key K, value V) (evicted bool) { // Get looks up a key's value from the cache. func (c *LRU[K, V]) Get(key K) (value V, ok bool) { if ent, ok := c.items[key]; ok { - c.evictList.moveToFront(ent) - return ent.value, true + c.evictList.MoveToFront(ent) + return ent.Value, true } return } @@ -84,9 +86,9 @@ func (c *LRU[K, V]) Contains(key K) (ok bool) { // Peek returns the key value (or undefined if not found) without updating // the "recently used"-ness of the key. func (c *LRU[K, V]) Peek(key K) (value V, ok bool) { - var ent *entry[K, V] + var ent *internal.Entry[K, V] if ent, ok = c.items[key]; ok { - return ent.value, true + return ent.Value, true } return } @@ -103,35 +105,46 @@ func (c *LRU[K, V]) Remove(key K) (present bool) { // RemoveOldest removes the oldest item from the cache. func (c *LRU[K, V]) RemoveOldest() (key K, value V, ok bool) { - if ent := c.evictList.back(); ent != nil { + if ent := c.evictList.Back(); ent != nil { c.removeElement(ent) - return ent.key, ent.value, true + return ent.Key, ent.Value, true } return } // GetOldest returns the oldest entry func (c *LRU[K, V]) GetOldest() (key K, value V, ok bool) { - if ent := c.evictList.back(); ent != nil { - return ent.key, ent.value, true + if ent := c.evictList.Back(); ent != nil { + return ent.Key, ent.Value, true } return } // Keys returns a slice of the keys in the cache, from oldest to newest. func (c *LRU[K, V]) Keys() []K { - keys := make([]K, c.evictList.length()) + keys := make([]K, c.evictList.Length()) i := 0 - for ent := c.evictList.back(); ent != nil; ent = ent.prevEntry() { - keys[i] = ent.key + for ent := c.evictList.Back(); ent != nil; ent = ent.PrevEntry() { + keys[i] = ent.Key i++ } return keys } +// Values returns a slice of the values in the cache, from oldest to newest. +func (c *LRU[K, V]) Values() []V { + values := make([]V, len(c.items)) + i := 0 + for ent := c.evictList.Back(); ent != nil; ent = ent.PrevEntry() { + values[i] = ent.Value + i++ + } + return values +} + // Len returns the number of items in the cache. func (c *LRU[K, V]) Len() int { - return c.evictList.length() + return c.evictList.Length() } // Resize changes the cache size. @@ -149,16 +162,16 @@ func (c *LRU[K, V]) Resize(size int) (evicted int) { // removeOldest removes the oldest item from the cache. func (c *LRU[K, V]) removeOldest() { - if ent := c.evictList.back(); ent != nil { + if ent := c.evictList.Back(); ent != nil { c.removeElement(ent) } } // removeElement is used to remove a given list element from the cache -func (c *LRU[K, V]) removeElement(e *entry[K, V]) { - c.evictList.remove(e) - delete(c.items, e.key) +func (c *LRU[K, V]) removeElement(e *internal.Entry[K, V]) { + c.evictList.Remove(e) + delete(c.items, e.Key) if c.onEvict != nil { - c.onEvict(e.key, e.value) + c.onEvict(e.Key, e.Value) } } diff --git a/vendor/github.com/hashicorp/golang-lru/v2/simplelru/lru_interface.go b/vendor/github.com/hashicorp/golang-lru/v2/simplelru/lru_interface.go index 3cbf02bc7b..043b8bcc3f 100644 --- a/vendor/github.com/hashicorp/golang-lru/v2/simplelru/lru_interface.go +++ b/vendor/github.com/hashicorp/golang-lru/v2/simplelru/lru_interface.go @@ -32,6 +32,9 @@ type LRUCache[K comparable, V any] interface { // Returns a slice of the keys in the cache, from oldest to newest. Keys() []K + // Values returns a slice of the values in the cache, from oldest to newest. + Values() []V + // Returns the number of items in the cache. Len() int diff --git a/vendor/github.com/hashicorp/golang-lru/v2/testing.go b/vendor/github.com/hashicorp/golang-lru/v2/testing.go deleted file mode 100644 index 3277c2186a..0000000000 --- a/vendor/github.com/hashicorp/golang-lru/v2/testing.go +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package lru - -import ( - "crypto/rand" - "math" - "math/big" - "testing" -) - -func getRand(tb testing.TB) int64 { - out, err := rand.Int(rand.Reader, big.NewInt(math.MaxInt64)) - if err != nil { - tb.Fatal(err) - } - return out.Int64() -} diff --git a/vendor/github.com/klauspost/compress/README.md b/vendor/github.com/klauspost/compress/README.md index ac281fb720..1f72cdde18 100644 --- a/vendor/github.com/klauspost/compress/README.md +++ b/vendor/github.com/klauspost/compress/README.md @@ -16,10 +16,14 @@ This package provides various compression algorithms. # changelog +* Feb 5th, 2024 - [1.17.6](https://github.com/klauspost/compress/releases/tag/v1.17.6) + * zstd: Fix incorrect repeat coding in best mode https://github.com/klauspost/compress/pull/923 + * s2: Fix DecodeConcurrent deadlock on errors https://github.com/klauspost/compress/pull/925 + * Jan 26th, 2024 - [v1.17.5](https://github.com/klauspost/compress/releases/tag/v1.17.5) - * flate: Fix reset with dictionary on custom window encodes by @klauspost in https://github.com/klauspost/compress/pull/912 - * zstd: Add Frame header encoding and stripping by @klauspost in https://github.com/klauspost/compress/pull/908 - * zstd: Limit better/best default window to 8MB by @klauspost in https://github.com/klauspost/compress/pull/913 + * flate: Fix reset with dictionary on custom window encodes https://github.com/klauspost/compress/pull/912 + * zstd: Add Frame header encoding and stripping https://github.com/klauspost/compress/pull/908 + * zstd: Limit better/best default window to 8MB https://github.com/klauspost/compress/pull/913 * zstd: Speed improvements by @greatroar in https://github.com/klauspost/compress/pull/896 https://github.com/klauspost/compress/pull/910 * s2: Fix callbacks for skippable blocks and disallow 0xfe (Padding) by @Jille in https://github.com/klauspost/compress/pull/916 https://github.com/klauspost/compress/pull/917 https://github.com/klauspost/compress/pull/919 https://github.com/klauspost/compress/pull/918 diff --git a/vendor/github.com/klauspost/compress/s2/encode_all.go b/vendor/github.com/klauspost/compress/s2/encode_all.go index 5e57995d48..9977045696 100644 --- a/vendor/github.com/klauspost/compress/s2/encode_all.go +++ b/vendor/github.com/klauspost/compress/s2/encode_all.go @@ -117,6 +117,12 @@ func encodeBlockGo(dst, src []byte) (d int) { i-- base-- } + + // Bail if we exceed the maximum size. + if d+(base-nextEmit) > dstLimit { + return 0 + } + d += emitLiteral(dst[d:], src[nextEmit:base]) // Extend forward @@ -152,7 +158,6 @@ func encodeBlockGo(dst, src []byte) (d int) { if s >= sLimit { goto emitRemainder } - cv = load64(src, s) continue } @@ -325,6 +330,11 @@ func encodeBlockSnappyGo(dst, src []byte) (d int) { i-- base-- } + // Bail if we exceed the maximum size. + if d+(base-nextEmit) > dstLimit { + return 0 + } + d += emitLiteral(dst[d:], src[nextEmit:base]) // Extend forward @@ -532,6 +542,11 @@ searchDict: i-- base-- } + // Bail if we exceed the maximum size. + if d+(base-nextEmit) > dstLimit { + return 0 + } + d += emitLiteral(dst[d:], src[nextEmit:base]) if debug && nextEmit != base { fmt.Println("emitted ", base-nextEmit, "literals") @@ -880,6 +895,11 @@ searchDict: i-- base-- } + // Bail if we exceed the maximum size. + if d+(base-nextEmit) > dstLimit { + return 0 + } + d += emitLiteral(dst[d:], src[nextEmit:base]) if debug && nextEmit != base { fmt.Println("emitted ", base-nextEmit, "literals") diff --git a/vendor/github.com/klauspost/compress/s2/encodeblock_amd64.s b/vendor/github.com/klauspost/compress/s2/encodeblock_amd64.s index 5f110d1940..2ff5b33401 100644 --- a/vendor/github.com/klauspost/compress/s2/encodeblock_amd64.s +++ b/vendor/github.com/klauspost/compress/s2/encodeblock_amd64.s @@ -100,6 +100,15 @@ repeat_extend_back_loop_encodeBlockAsm: JNZ repeat_extend_back_loop_encodeBlockAsm repeat_extend_back_end_encodeBlockAsm: + MOVL SI, BX + SUBL 12(SP), BX + LEAQ 5(AX)(BX*1), BX + CMPQ BX, (SP) + JB repeat_dst_size_check_encodeBlockAsm + MOVQ $0x00000000, ret+48(FP) + RET + +repeat_dst_size_check_encodeBlockAsm: MOVL 12(SP), BX CMPL BX, SI JEQ emit_literal_done_repeat_emit_encodeBlockAsm @@ -1513,6 +1522,15 @@ repeat_extend_back_loop_encodeBlockAsm4MB: JNZ repeat_extend_back_loop_encodeBlockAsm4MB repeat_extend_back_end_encodeBlockAsm4MB: + MOVL SI, BX + SUBL 12(SP), BX + LEAQ 4(AX)(BX*1), BX + CMPQ BX, (SP) + JB repeat_dst_size_check_encodeBlockAsm4MB + MOVQ $0x00000000, ret+48(FP) + RET + +repeat_dst_size_check_encodeBlockAsm4MB: MOVL 12(SP), BX CMPL BX, SI JEQ emit_literal_done_repeat_emit_encodeBlockAsm4MB @@ -2828,6 +2846,15 @@ repeat_extend_back_loop_encodeBlockAsm12B: JNZ repeat_extend_back_loop_encodeBlockAsm12B repeat_extend_back_end_encodeBlockAsm12B: + MOVL SI, BX + SUBL 12(SP), BX + LEAQ 3(AX)(BX*1), BX + CMPQ BX, (SP) + JB repeat_dst_size_check_encodeBlockAsm12B + MOVQ $0x00000000, ret+48(FP) + RET + +repeat_dst_size_check_encodeBlockAsm12B: MOVL 12(SP), BX CMPL BX, SI JEQ emit_literal_done_repeat_emit_encodeBlockAsm12B @@ -3903,6 +3930,15 @@ repeat_extend_back_loop_encodeBlockAsm10B: JNZ repeat_extend_back_loop_encodeBlockAsm10B repeat_extend_back_end_encodeBlockAsm10B: + MOVL SI, BX + SUBL 12(SP), BX + LEAQ 3(AX)(BX*1), BX + CMPQ BX, (SP) + JB repeat_dst_size_check_encodeBlockAsm10B + MOVQ $0x00000000, ret+48(FP) + RET + +repeat_dst_size_check_encodeBlockAsm10B: MOVL 12(SP), BX CMPL BX, SI JEQ emit_literal_done_repeat_emit_encodeBlockAsm10B @@ -4978,6 +5014,15 @@ repeat_extend_back_loop_encodeBlockAsm8B: JNZ repeat_extend_back_loop_encodeBlockAsm8B repeat_extend_back_end_encodeBlockAsm8B: + MOVL SI, BX + SUBL 12(SP), BX + LEAQ 3(AX)(BX*1), BX + CMPQ BX, (SP) + JB repeat_dst_size_check_encodeBlockAsm8B + MOVQ $0x00000000, ret+48(FP) + RET + +repeat_dst_size_check_encodeBlockAsm8B: MOVL 12(SP), BX CMPL BX, SI JEQ emit_literal_done_repeat_emit_encodeBlockAsm8B @@ -10756,6 +10801,15 @@ repeat_extend_back_loop_encodeSnappyBlockAsm: JNZ repeat_extend_back_loop_encodeSnappyBlockAsm repeat_extend_back_end_encodeSnappyBlockAsm: + MOVL SI, BX + SUBL 12(SP), BX + LEAQ 5(AX)(BX*1), BX + CMPQ BX, (SP) + JB repeat_dst_size_check_encodeSnappyBlockAsm + MOVQ $0x00000000, ret+48(FP) + RET + +repeat_dst_size_check_encodeSnappyBlockAsm: MOVL 12(SP), BX CMPL BX, SI JEQ emit_literal_done_repeat_emit_encodeSnappyBlockAsm @@ -11678,6 +11732,15 @@ repeat_extend_back_loop_encodeSnappyBlockAsm64K: JNZ repeat_extend_back_loop_encodeSnappyBlockAsm64K repeat_extend_back_end_encodeSnappyBlockAsm64K: + MOVL SI, BX + SUBL 12(SP), BX + LEAQ 3(AX)(BX*1), BX + CMPQ BX, (SP) + JB repeat_dst_size_check_encodeSnappyBlockAsm64K + MOVQ $0x00000000, ret+48(FP) + RET + +repeat_dst_size_check_encodeSnappyBlockAsm64K: MOVL 12(SP), BX CMPL BX, SI JEQ emit_literal_done_repeat_emit_encodeSnappyBlockAsm64K @@ -12504,6 +12567,15 @@ repeat_extend_back_loop_encodeSnappyBlockAsm12B: JNZ repeat_extend_back_loop_encodeSnappyBlockAsm12B repeat_extend_back_end_encodeSnappyBlockAsm12B: + MOVL SI, BX + SUBL 12(SP), BX + LEAQ 3(AX)(BX*1), BX + CMPQ BX, (SP) + JB repeat_dst_size_check_encodeSnappyBlockAsm12B + MOVQ $0x00000000, ret+48(FP) + RET + +repeat_dst_size_check_encodeSnappyBlockAsm12B: MOVL 12(SP), BX CMPL BX, SI JEQ emit_literal_done_repeat_emit_encodeSnappyBlockAsm12B @@ -13330,6 +13402,15 @@ repeat_extend_back_loop_encodeSnappyBlockAsm10B: JNZ repeat_extend_back_loop_encodeSnappyBlockAsm10B repeat_extend_back_end_encodeSnappyBlockAsm10B: + MOVL SI, BX + SUBL 12(SP), BX + LEAQ 3(AX)(BX*1), BX + CMPQ BX, (SP) + JB repeat_dst_size_check_encodeSnappyBlockAsm10B + MOVQ $0x00000000, ret+48(FP) + RET + +repeat_dst_size_check_encodeSnappyBlockAsm10B: MOVL 12(SP), BX CMPL BX, SI JEQ emit_literal_done_repeat_emit_encodeSnappyBlockAsm10B @@ -14156,6 +14237,15 @@ repeat_extend_back_loop_encodeSnappyBlockAsm8B: JNZ repeat_extend_back_loop_encodeSnappyBlockAsm8B repeat_extend_back_end_encodeSnappyBlockAsm8B: + MOVL SI, BX + SUBL 12(SP), BX + LEAQ 3(AX)(BX*1), BX + CMPQ BX, (SP) + JB repeat_dst_size_check_encodeSnappyBlockAsm8B + MOVQ $0x00000000, ret+48(FP) + RET + +repeat_dst_size_check_encodeSnappyBlockAsm8B: MOVL 12(SP), BX CMPL BX, SI JEQ emit_literal_done_repeat_emit_encodeSnappyBlockAsm8B @@ -17949,6 +18039,15 @@ repeat_extend_back_loop_calcBlockSize: JNZ repeat_extend_back_loop_calcBlockSize repeat_extend_back_end_calcBlockSize: + MOVL SI, BX + SUBL 12(SP), BX + LEAQ 5(AX)(BX*1), BX + CMPQ BX, (SP) + JB repeat_dst_size_check_calcBlockSize + MOVQ $0x00000000, ret+24(FP) + RET + +repeat_dst_size_check_calcBlockSize: MOVL 12(SP), BX CMPL BX, SI JEQ emit_literal_done_repeat_emit_calcBlockSize @@ -18531,6 +18630,15 @@ repeat_extend_back_loop_calcBlockSizeSmall: JNZ repeat_extend_back_loop_calcBlockSizeSmall repeat_extend_back_end_calcBlockSizeSmall: + MOVL SI, BX + SUBL 12(SP), BX + LEAQ 3(AX)(BX*1), BX + CMPQ BX, (SP) + JB repeat_dst_size_check_calcBlockSizeSmall + MOVQ $0x00000000, ret+24(FP) + RET + +repeat_dst_size_check_calcBlockSizeSmall: MOVL 12(SP), BX CMPL BX, SI JEQ emit_literal_done_repeat_emit_calcBlockSizeSmall diff --git a/vendor/github.com/klauspost/compress/s2/writer.go b/vendor/github.com/klauspost/compress/s2/writer.go index bba66a8766..1253ea675c 100644 --- a/vendor/github.com/klauspost/compress/s2/writer.go +++ b/vendor/github.com/klauspost/compress/s2/writer.go @@ -215,7 +215,7 @@ func (w *Writer) ReadFrom(r io.Reader) (n int64, err error) { return 0, err } if len(w.ibuf) > 0 { - err := w.Flush() + err := w.AsyncFlush() if err != nil { return 0, err } @@ -225,7 +225,7 @@ func (w *Writer) ReadFrom(r io.Reader) (n int64, err error) { if err := w.EncodeBuffer(buf); err != nil { return 0, err } - return int64(len(buf)), w.Flush() + return int64(len(buf)), w.AsyncFlush() } for { inbuf := w.buffers.Get().([]byte)[:w.blockSize+obufHeaderLen] @@ -354,7 +354,7 @@ func (w *Writer) EncodeBuffer(buf []byte) (err error) { } // Flush queued data first. if len(w.ibuf) > 0 { - err := w.Flush() + err := w.AsyncFlush() if err != nil { return err } @@ -716,9 +716,9 @@ func (w *Writer) writeSync(p []byte) (nRet int, errRet error) { return nRet, nil } -// Flush flushes the Writer to its underlying io.Writer. -// This does not apply padding. -func (w *Writer) Flush() error { +// AsyncFlush writes any buffered bytes to a block and starts compressing it. +// It does not wait for the output has been written as Flush() does. +func (w *Writer) AsyncFlush() error { if err := w.err(nil); err != nil { return err } @@ -738,6 +738,15 @@ func (w *Writer) Flush() error { } } } + return w.err(nil) +} + +// Flush flushes the Writer to its underlying io.Writer. +// This does not apply padding. +func (w *Writer) Flush() error { + if err := w.AsyncFlush(); err != nil { + return err + } if w.output == nil { return w.err(nil) } diff --git a/vendor/github.com/prometheus/alertmanager/api/api.go b/vendor/github.com/prometheus/alertmanager/api/api.go index 59bfb76da6..2e1e1ea425 100644 --- a/vendor/github.com/prometheus/alertmanager/api/api.go +++ b/vendor/github.com/prometheus/alertmanager/api/api.go @@ -25,7 +25,6 @@ import ( "github.com/prometheus/common/model" "github.com/prometheus/common/route" - apiv1 "github.com/prometheus/alertmanager/api/v1" apiv2 "github.com/prometheus/alertmanager/api/v2" "github.com/prometheus/alertmanager/cluster" "github.com/prometheus/alertmanager/config" @@ -37,8 +36,9 @@ import ( // API represents all APIs of Alertmanager. type API struct { - v1 *apiv1.API - v2 *apiv2.API + v2 *apiv2.API + deprecationRouter *V1DeprecationRouter + requestsInFlight prometheus.Gauge concurrencyLimitExceeded prometheus.Counter timeout time.Duration @@ -96,7 +96,7 @@ func (o Options) validate() error { // call is also needed to get the APIs into an operational state. func New(opts Options) (*API, error) { if err := opts.validate(); err != nil { - return nil, fmt.Errorf("invalid API options: %s", err) + return nil, fmt.Errorf("invalid API options: %w", err) } l := opts.Logger if l == nil { @@ -110,15 +110,6 @@ func New(opts Options) (*API, error) { } } - v1 := apiv1.New( - opts.Alerts, - opts.Silences, - opts.StatusFunc, - opts.Peer, - log.With(l, "version", "v1"), - opts.Registry, - ) - v2, err := apiv2.NewAPI( opts.Alerts, opts.GroupFunc, @@ -154,7 +145,7 @@ func New(opts Options) (*API, error) { } return &API{ - v1: v1, + deprecationRouter: NewV1DeprecationRouter(log.With(l, "version", "v1")), v2: v2, requestsInFlight: requestsInFlight, concurrencyLimitExceeded: concurrencyLimitExceeded, @@ -163,8 +154,7 @@ func New(opts Options) (*API, error) { }, nil } -// Register all APIs. It registers APIv1 with the provided router directly. As -// APIv2 works on the http.Handler level, this method also creates a new +// Register API. As APIv2 works on the http.Handler level, this method also creates a new // http.ServeMux and then uses it to register both the provided router (to // handle "/") and APIv2 (to handle "/api/v2"). The method returns // the newly created http.ServeMux. If a timeout has been set on construction of @@ -172,7 +162,8 @@ func New(opts Options) (*API, error) { // true for the concurrency limit, with the exception that it is only applied to // GET requests. func (api *API) Register(r *route.Router, routePrefix string) *http.ServeMux { - api.v1.Register(r.WithPrefix("/api/v1")) + // TODO(gotjosh) API V1 was removed as of version 0.28, when we reach 1.0.0 we should removed these deprecation warnings. + api.deprecationRouter.Register(r.WithPrefix("/api/v1")) mux := http.NewServeMux() mux.Handle("/", api.limitHandler(r)) @@ -196,7 +187,6 @@ func (api *API) Register(r *route.Router, routePrefix string) *http.ServeMux { // Update config and resolve timeout of each API. APIv2 also needs // setAlertStatus to be updated. func (api *API) Update(cfg *config.Config, setAlertStatus func(model.LabelSet)) { - api.v1.Update(cfg) api.v2.Update(cfg, setAlertStatus) } diff --git a/vendor/github.com/prometheus/alertmanager/api/metrics/metrics.go b/vendor/github.com/prometheus/alertmanager/api/metrics/metrics.go index 483569ab9d..ea45acc2ee 100644 --- a/vendor/github.com/prometheus/alertmanager/api/metrics/metrics.go +++ b/vendor/github.com/prometheus/alertmanager/api/metrics/metrics.go @@ -15,7 +15,7 @@ package metrics import "github.com/prometheus/client_golang/prometheus" -// Alerts stores metrics for alerts which are common across all API versions. +// Alerts stores metrics for alerts. type Alerts struct { firing prometheus.Counter resolved prometheus.Counter @@ -23,16 +23,17 @@ type Alerts struct { } // NewAlerts returns an *Alerts struct for the given API version. -func NewAlerts(version string, r prometheus.Registerer) *Alerts { +// Since v1 was deprecated in 0.28, v2 is now hardcoded. +func NewAlerts(r prometheus.Registerer) *Alerts { numReceivedAlerts := prometheus.NewCounterVec(prometheus.CounterOpts{ Name: "alertmanager_alerts_received_total", Help: "The total number of received alerts.", - ConstLabels: prometheus.Labels{"version": version}, + ConstLabels: prometheus.Labels{"version": "v2"}, }, []string{"status"}) numInvalidAlerts := prometheus.NewCounter(prometheus.CounterOpts{ Name: "alertmanager_alerts_invalid_total", Help: "The total number of received alerts that were invalid.", - ConstLabels: prometheus.Labels{"version": version}, + ConstLabels: prometheus.Labels{"version": "v2"}, }) if r != nil { r.MustRegister(numReceivedAlerts, numInvalidAlerts) diff --git a/vendor/github.com/prometheus/alertmanager/api/v1/api.go b/vendor/github.com/prometheus/alertmanager/api/v1/api.go deleted file mode 100644 index 39018a7589..0000000000 --- a/vendor/github.com/prometheus/alertmanager/api/v1/api.go +++ /dev/null @@ -1,808 +0,0 @@ -// Copyright 2015 Prometheus Team -// 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 ( - "encoding/json" - "errors" - "fmt" - "net/http" - "regexp" - "sort" - "sync" - "time" - - "github.com/go-kit/log" - "github.com/go-kit/log/level" - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/common/model" - "github.com/prometheus/common/route" - "github.com/prometheus/common/version" - - "github.com/prometheus/alertmanager/api/metrics" - "github.com/prometheus/alertmanager/cluster" - "github.com/prometheus/alertmanager/config" - "github.com/prometheus/alertmanager/dispatch" - "github.com/prometheus/alertmanager/pkg/labels" - "github.com/prometheus/alertmanager/provider" - "github.com/prometheus/alertmanager/silence" - "github.com/prometheus/alertmanager/silence/silencepb" - "github.com/prometheus/alertmanager/types" -) - -var corsHeaders = map[string]string{ - "Access-Control-Allow-Headers": "Accept, Authorization, Content-Type, Origin", - "Access-Control-Allow-Methods": "GET, POST, DELETE, OPTIONS", - "Access-Control-Allow-Origin": "*", - "Access-Control-Expose-Headers": "Date", - "Cache-Control": "no-cache, no-store, must-revalidate", -} - -// Alert is the API representation of an alert, which is a regular alert -// annotated with silencing and inhibition info. -type Alert struct { - *model.Alert - Status types.AlertStatus `json:"status"` - Receivers []string `json:"receivers"` - Fingerprint string `json:"fingerprint"` -} - -// Enables cross-site script calls. -func setCORS(w http.ResponseWriter) { - for h, v := range corsHeaders { - w.Header().Set(h, v) - } -} - -// API provides registration of handlers for API routes. -type API struct { - alerts provider.Alerts - silences *silence.Silences - config *config.Config - route *dispatch.Route - uptime time.Time - peer cluster.ClusterPeer - logger log.Logger - m *metrics.Alerts - - getAlertStatus getAlertStatusFn - - mtx sync.RWMutex -} - -type getAlertStatusFn func(model.Fingerprint) types.AlertStatus - -// New returns a new API. -func New( - alerts provider.Alerts, - silences *silence.Silences, - sf getAlertStatusFn, - peer cluster.ClusterPeer, - l log.Logger, - r prometheus.Registerer, -) *API { - if l == nil { - l = log.NewNopLogger() - } - - return &API{ - alerts: alerts, - silences: silences, - getAlertStatus: sf, - uptime: time.Now(), - peer: peer, - logger: l, - m: metrics.NewAlerts("v1", r), - } -} - -// Register registers the API handlers under their correct routes -// in the given router. -func (api *API) Register(r *route.Router) { - wrap := func(f http.HandlerFunc) http.HandlerFunc { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - setCORS(w) - f(w, r) - }) - } - - r.Options("/*path", wrap(func(w http.ResponseWriter, r *http.Request) {})) - - r.Get("/status", wrap(api.status)) - r.Get("/receivers", wrap(api.receivers)) - - r.Get("/alerts", wrap(api.listAlerts)) - r.Post("/alerts", wrap(api.addAlerts)) - - r.Get("/silences", wrap(api.listSilences)) - r.Post("/silences", wrap(api.setSilence)) - r.Get("/silence/:sid", wrap(api.getSilence)) - r.Del("/silence/:sid", wrap(api.delSilence)) -} - -// Update sets the configuration string to a new value. -func (api *API) Update(cfg *config.Config) { - api.mtx.Lock() - defer api.mtx.Unlock() - - api.config = cfg - api.route = dispatch.NewRoute(cfg.Route, nil) -} - -type errorType string - -const ( - errorInternal errorType = "server_error" - errorBadData errorType = "bad_data" -) - -type apiError struct { - typ errorType - err error -} - -func (e *apiError) Error() string { - return fmt.Sprintf("%s: %s", e.typ, e.err) -} - -func (api *API) receivers(w http.ResponseWriter, req *http.Request) { - api.mtx.RLock() - defer api.mtx.RUnlock() - - receivers := make([]string, 0, len(api.config.Receivers)) - for _, r := range api.config.Receivers { - receivers = append(receivers, r.Name) - } - - api.respond(w, receivers) -} - -func (api *API) status(w http.ResponseWriter, req *http.Request) { - api.mtx.RLock() - - status := struct { - ConfigYAML string `json:"configYAML"` - ConfigJSON *config.Config `json:"configJSON"` - VersionInfo map[string]string `json:"versionInfo"` - Uptime time.Time `json:"uptime"` - ClusterStatus *clusterStatus `json:"clusterStatus"` - }{ - ConfigYAML: api.config.String(), - ConfigJSON: api.config, - VersionInfo: map[string]string{ - "version": version.Version, - "revision": version.Revision, - "branch": version.Branch, - "buildUser": version.BuildUser, - "buildDate": version.BuildDate, - "goVersion": version.GoVersion, - }, - Uptime: api.uptime, - ClusterStatus: getClusterStatus(api.peer), - } - - api.mtx.RUnlock() - - api.respond(w, status) -} - -type peerStatus struct { - Name string `json:"name"` - Address string `json:"address"` -} - -type clusterStatus struct { - Name string `json:"name"` - Status string `json:"status"` - Peers []peerStatus `json:"peers"` -} - -func getClusterStatus(p cluster.ClusterPeer) *clusterStatus { - if p == nil { - return nil - } - s := &clusterStatus{Name: p.Name(), Status: p.Status()} - - for _, n := range p.Peers() { - s.Peers = append(s.Peers, peerStatus{ - Name: n.Name(), - Address: n.Address(), - }) - } - return s -} - -func (api *API) listAlerts(w http.ResponseWriter, r *http.Request) { - var ( - err error - receiverFilter *regexp.Regexp - // Initialize result slice to prevent api returning `null` when there - // are no alerts present - res = []*Alert{} - matchers = []*labels.Matcher{} - ctx = r.Context() - - showActive, showInhibited bool - showSilenced, showUnprocessed bool - ) - - getBoolParam := func(name string) (bool, error) { - v := r.FormValue(name) - if v == "" { - return true, nil - } - if v == "false" { - return false, nil - } - if v != "true" { - err := fmt.Errorf("parameter %q can either be 'true' or 'false', not %q", name, v) - api.respondError(w, apiError{ - typ: errorBadData, - err: err, - }, nil) - return false, err - } - return true, nil - } - - if filter := r.FormValue("filter"); filter != "" { - matchers, err = labels.ParseMatchers(filter) - if err != nil { - api.respondError(w, apiError{ - typ: errorBadData, - err: err, - }, nil) - return - } - } - - showActive, err = getBoolParam("active") - if err != nil { - return - } - - showSilenced, err = getBoolParam("silenced") - if err != nil { - return - } - - showInhibited, err = getBoolParam("inhibited") - if err != nil { - return - } - - showUnprocessed, err = getBoolParam("unprocessed") - if err != nil { - return - } - - if receiverParam := r.FormValue("receiver"); receiverParam != "" { - receiverFilter, err = regexp.Compile("^(?:" + receiverParam + ")$") - if err != nil { - api.respondError(w, apiError{ - typ: errorBadData, - err: fmt.Errorf( - "failed to parse receiver param: %s", - receiverParam, - ), - }, nil) - return - } - } - - alerts := api.alerts.GetPending() - defer alerts.Close() - - api.mtx.RLock() - for a := range alerts.Next() { - if err = alerts.Err(); err != nil { - break - } - if err = ctx.Err(); err != nil { - break - } - - routes := api.route.Match(a.Labels) - receivers := make([]string, 0, len(routes)) - for _, r := range routes { - receivers = append(receivers, r.RouteOpts.Receiver) - } - - if receiverFilter != nil && !receiversMatchFilter(receivers, receiverFilter) { - continue - } - - if !alertMatchesFilterLabels(&a.Alert, matchers) { - continue - } - - // Continue if the alert is resolved. - if !a.Alert.EndsAt.IsZero() && a.Alert.EndsAt.Before(time.Now()) { - continue - } - - status := api.getAlertStatus(a.Fingerprint()) - - if !showActive && status.State == types.AlertStateActive { - continue - } - - if !showUnprocessed && status.State == types.AlertStateUnprocessed { - continue - } - - if !showSilenced && len(status.SilencedBy) != 0 { - continue - } - - if !showInhibited && len(status.InhibitedBy) != 0 { - continue - } - - alert := &Alert{ - Alert: &a.Alert, - Status: status, - Receivers: receivers, - Fingerprint: a.Fingerprint().String(), - } - - res = append(res, alert) - } - api.mtx.RUnlock() - - if err != nil { - api.respondError(w, apiError{ - typ: errorInternal, - err: err, - }, nil) - return - } - sort.Slice(res, func(i, j int) bool { - return res[i].Fingerprint < res[j].Fingerprint - }) - api.respond(w, res) -} - -func receiversMatchFilter(receivers []string, filter *regexp.Regexp) bool { - for _, r := range receivers { - if filter.MatchString(r) { - return true - } - } - - return false -} - -func alertMatchesFilterLabels(a *model.Alert, matchers []*labels.Matcher) bool { - sms := make(map[string]string) - for name, value := range a.Labels { - sms[string(name)] = string(value) - } - return matchFilterLabels(matchers, sms) -} - -func (api *API) addAlerts(w http.ResponseWriter, r *http.Request) { - var alerts []*types.Alert - if err := api.receive(r, &alerts); err != nil { - api.respondError(w, apiError{ - typ: errorBadData, - err: err, - }, nil) - return - } - - api.insertAlerts(w, r, alerts...) -} - -func (api *API) insertAlerts(w http.ResponseWriter, r *http.Request, alerts ...*types.Alert) { - now := time.Now() - - api.mtx.RLock() - resolveTimeout := time.Duration(api.config.Global.ResolveTimeout) - api.mtx.RUnlock() - - for _, alert := range alerts { - alert.UpdatedAt = now - - // Ensure StartsAt is set. - if alert.StartsAt.IsZero() { - if alert.EndsAt.IsZero() { - alert.StartsAt = now - } else { - alert.StartsAt = alert.EndsAt - } - } - // If no end time is defined, set a timeout after which an alert - // is marked resolved if it is not updated. - if alert.EndsAt.IsZero() { - alert.Timeout = true - alert.EndsAt = now.Add(resolveTimeout) - } - if alert.EndsAt.After(time.Now()) { - api.m.Firing().Inc() - } else { - api.m.Resolved().Inc() - } - } - - // Make a best effort to insert all alerts that are valid. - var ( - validAlerts = make([]*types.Alert, 0, len(alerts)) - validationErrs = &types.MultiError{} - ) - for _, a := range alerts { - removeEmptyLabels(a.Labels) - - if err := a.Validate(); err != nil { - validationErrs.Add(err) - api.m.Invalid().Inc() - continue - } - validAlerts = append(validAlerts, a) - } - if err := api.alerts.Put(validAlerts...); err != nil { - api.respondError(w, apiError{ - typ: errorInternal, - err: err, - }, nil) - return - } - - if validationErrs.Len() > 0 { - api.respondError(w, apiError{ - typ: errorBadData, - err: validationErrs, - }, nil) - return - } - - api.respond(w, nil) -} - -func removeEmptyLabels(ls model.LabelSet) { - for k, v := range ls { - if string(v) == "" { - delete(ls, k) - } - } -} - -func (api *API) setSilence(w http.ResponseWriter, r *http.Request) { - var sil types.Silence - if err := api.receive(r, &sil); err != nil { - api.respondError(w, apiError{ - typ: errorBadData, - err: err, - }, nil) - return - } - - // This is an API only validation, it cannot be done internally - // because the expired silence is semantically important. - // But one should not be able to create expired silences, that - // won't have any use. - if sil.Expired() { - api.respondError(w, apiError{ - typ: errorBadData, - err: errors.New("start time must not be equal to end time"), - }, nil) - return - } - - if sil.EndsAt.Before(time.Now()) { - api.respondError(w, apiError{ - typ: errorBadData, - err: errors.New("end time can't be in the past"), - }, nil) - return - } - - psil, err := silenceToProto(&sil) - if err != nil { - api.respondError(w, apiError{ - typ: errorBadData, - err: err, - }, nil) - return - } - - sid, err := api.silences.Set(psil) - if err != nil { - api.respondError(w, apiError{ - typ: errorBadData, - err: err, - }, nil) - return - } - - api.respond(w, struct { - SilenceID string `json:"silenceId"` - }{ - SilenceID: sid, - }) -} - -func (api *API) getSilence(w http.ResponseWriter, r *http.Request) { - sid := route.Param(r.Context(), "sid") - - sils, _, err := api.silences.Query(silence.QIDs(sid)) - if err != nil || len(sils) == 0 { - http.Error(w, fmt.Sprint("Error getting silence: ", err), http.StatusNotFound) - return - } - sil, err := silenceFromProto(sils[0]) - if err != nil { - api.respondError(w, apiError{ - typ: errorInternal, - err: err, - }, nil) - return - } - - api.respond(w, sil) -} - -func (api *API) delSilence(w http.ResponseWriter, r *http.Request) { - sid := route.Param(r.Context(), "sid") - - if err := api.silences.Expire(sid); err != nil { - api.respondError(w, apiError{ - typ: errorBadData, - err: err, - }, nil) - return - } - api.respond(w, nil) -} - -func (api *API) listSilences(w http.ResponseWriter, r *http.Request) { - psils, _, err := api.silences.Query() - if err != nil { - api.respondError(w, apiError{ - typ: errorInternal, - err: err, - }, nil) - return - } - - matchers := []*labels.Matcher{} - if filter := r.FormValue("filter"); filter != "" { - matchers, err = labels.ParseMatchers(filter) - if err != nil { - api.respondError(w, apiError{ - typ: errorBadData, - err: err, - }, nil) - return - } - } - - sils := []*types.Silence{} - for _, ps := range psils { - s, err := silenceFromProto(ps) - if err != nil { - api.respondError(w, apiError{ - typ: errorInternal, - err: err, - }, nil) - return - } - - if !silenceMatchesFilterLabels(s, matchers) { - continue - } - sils = append(sils, s) - } - - var active, pending, expired []*types.Silence - - for _, s := range sils { - switch s.Status.State { - case types.SilenceStateActive: - active = append(active, s) - case types.SilenceStatePending: - pending = append(pending, s) - case types.SilenceStateExpired: - expired = append(expired, s) - } - } - - sort.Slice(active, func(i, j int) bool { - return active[i].EndsAt.Before(active[j].EndsAt) - }) - sort.Slice(pending, func(i, j int) bool { - return pending[i].StartsAt.Before(pending[j].EndsAt) - }) - sort.Slice(expired, func(i, j int) bool { - return expired[i].EndsAt.After(expired[j].EndsAt) - }) - - // Initialize silences explicitly to an empty list (instead of nil) - // So that it does not get converted to "null" in JSON. - silences := []*types.Silence{} - silences = append(silences, active...) - silences = append(silences, pending...) - silences = append(silences, expired...) - - api.respond(w, silences) -} - -func silenceMatchesFilterLabels(s *types.Silence, matchers []*labels.Matcher) bool { - sms := make(map[string]string) - for _, m := range s.Matchers { - sms[m.Name] = m.Value - } - - return matchFilterLabels(matchers, sms) -} - -func matchFilterLabels(matchers []*labels.Matcher, sms map[string]string) bool { - for _, m := range matchers { - v, prs := sms[m.Name] - switch m.Type { - case labels.MatchNotRegexp, labels.MatchNotEqual: - if string(m.Value) == "" && prs { - continue - } - if !m.Matches(string(v)) { - return false - } - default: - if string(m.Value) == "" && !prs { - continue - } - if !m.Matches(string(v)) { - return false - } - } - } - - return true -} - -func silenceToProto(s *types.Silence) (*silencepb.Silence, error) { - sil := &silencepb.Silence{ - Id: s.ID, - StartsAt: s.StartsAt, - EndsAt: s.EndsAt, - UpdatedAt: s.UpdatedAt, - Comment: s.Comment, - CreatedBy: s.CreatedBy, - } - for _, m := range s.Matchers { - matcher := &silencepb.Matcher{ - Name: m.Name, - Pattern: m.Value, - } - switch m.Type { - case labels.MatchEqual: - matcher.Type = silencepb.Matcher_EQUAL - case labels.MatchNotEqual: - matcher.Type = silencepb.Matcher_NOT_EQUAL - case labels.MatchRegexp: - matcher.Type = silencepb.Matcher_REGEXP - case labels.MatchNotRegexp: - matcher.Type = silencepb.Matcher_NOT_REGEXP - } - sil.Matchers = append(sil.Matchers, matcher) - } - return sil, nil -} - -func silenceFromProto(s *silencepb.Silence) (*types.Silence, error) { - sil := &types.Silence{ - ID: s.Id, - StartsAt: s.StartsAt, - EndsAt: s.EndsAt, - UpdatedAt: s.UpdatedAt, - Status: types.SilenceStatus{ - State: types.CalcSilenceState(s.StartsAt, s.EndsAt), - }, - Comment: s.Comment, - CreatedBy: s.CreatedBy, - } - for _, m := range s.Matchers { - var t labels.MatchType - switch m.Type { - case silencepb.Matcher_EQUAL: - t = labels.MatchEqual - case silencepb.Matcher_NOT_EQUAL: - t = labels.MatchNotEqual - case silencepb.Matcher_REGEXP: - t = labels.MatchRegexp - case silencepb.Matcher_NOT_REGEXP: - t = labels.MatchNotRegexp - } - matcher, err := labels.NewMatcher(t, m.Name, m.Pattern) - if err != nil { - return nil, err - } - - sil.Matchers = append(sil.Matchers, matcher) - } - - return sil, nil -} - -type status string - -const ( - statusSuccess status = "success" - statusError status = "error" -) - -type response struct { - Status status `json:"status"` - Data interface{} `json:"data,omitempty"` - ErrorType errorType `json:"errorType,omitempty"` - Error string `json:"error,omitempty"` -} - -func (api *API) respond(w http.ResponseWriter, data interface{}) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(200) - - b, err := json.Marshal(&response{ - Status: statusSuccess, - Data: data, - }) - if err != nil { - level.Error(api.logger).Log("msg", "Error marshaling JSON", "err", err) - return - } - - if _, err := w.Write(b); err != nil { - level.Error(api.logger).Log("msg", "failed to write data to connection", "err", err) - } -} - -func (api *API) respondError(w http.ResponseWriter, apiErr apiError, data interface{}) { - w.Header().Set("Content-Type", "application/json") - - switch apiErr.typ { - case errorBadData: - w.WriteHeader(http.StatusBadRequest) - case errorInternal: - w.WriteHeader(http.StatusInternalServerError) - default: - panic(fmt.Sprintf("unknown error type %q", apiErr.Error())) - } - - b, err := json.Marshal(&response{ - Status: statusError, - ErrorType: apiErr.typ, - Error: apiErr.err.Error(), - Data: data, - }) - if err != nil { - return - } - level.Error(api.logger).Log("msg", "API error", "err", apiErr.Error()) - - if _, err := w.Write(b); err != nil { - level.Error(api.logger).Log("msg", "failed to write data to connection", "err", err) - } -} - -func (api *API) receive(r *http.Request, v interface{}) error { - dec := json.NewDecoder(r.Body) - defer r.Body.Close() - - err := dec.Decode(v) - if err != nil { - level.Debug(api.logger).Log("msg", "Decoding request failed", "err", err) - return err - } - return nil -} diff --git a/vendor/github.com/prometheus/alertmanager/api/v1_deprecation_router.go b/vendor/github.com/prometheus/alertmanager/api/v1_deprecation_router.go new file mode 100644 index 0000000000..3ebbbd076f --- /dev/null +++ b/vendor/github.com/prometheus/alertmanager/api/v1_deprecation_router.go @@ -0,0 +1,67 @@ +// Copyright 2023 Prometheus Team +// 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 l + +package api + +import ( + "encoding/json" + "net/http" + + "github.com/go-kit/log" + "github.com/go-kit/log/level" + "github.com/prometheus/common/route" +) + +// V1DeprecationRouter is the router to signal v1 users that the API v1 is now removed. +type V1DeprecationRouter struct { + logger log.Logger +} + +// NewV1DeprecationRouter returns a new V1DeprecationRouter. +func NewV1DeprecationRouter(l log.Logger) *V1DeprecationRouter { + return &V1DeprecationRouter{ + logger: l, + } +} + +// Register registers all the API v1 routes with an endpoint that returns a JSON deprecation notice and a logs a warning. +func (dr *V1DeprecationRouter) Register(r *route.Router) { + r.Get("/status", dr.deprecationHandler) + r.Get("/receivers", dr.deprecationHandler) + + r.Get("/alerts", dr.deprecationHandler) + r.Post("/alerts", dr.deprecationHandler) + + r.Get("/silences", dr.deprecationHandler) + r.Post("/silences", dr.deprecationHandler) + r.Get("/silence/:sid", dr.deprecationHandler) + r.Del("/silence/:sid", dr.deprecationHandler) +} + +func (dr *V1DeprecationRouter) deprecationHandler(w http.ResponseWriter, req *http.Request) { + level.Warn(dr.logger).Log("msg", "v1 API received a request on a removed endpoint", "path", req.URL.Path, "method", req.Method) + + resp := struct { + Status string `json:"status"` + Error string `json:"error"` + }{ + "deprecated", + "The Alertmanager v1 API was deprecated in version 0.16.0 and is removed as of version 0.28.0 - please use the equivalent route in the v2 API", + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(410) + + if err := json.NewEncoder(w).Encode(resp); err != nil { + level.Error(dr.logger).Log("msg", "failed to write response", "err", err) + } +} diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/api.go b/vendor/github.com/prometheus/alertmanager/api/v2/api.go index 1ddb2bcbae..b4f57e75e2 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/api.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/api.go @@ -14,6 +14,7 @@ package v2 import ( + "errors" "fmt" "net/http" "regexp" @@ -44,6 +45,7 @@ import ( "github.com/prometheus/alertmanager/cluster" "github.com/prometheus/alertmanager/config" "github.com/prometheus/alertmanager/dispatch" + "github.com/prometheus/alertmanager/matchers/compat" "github.com/prometheus/alertmanager/pkg/labels" "github.com/prometheus/alertmanager/provider" "github.com/prometheus/alertmanager/silence" @@ -97,7 +99,7 @@ func NewAPI( peer: peer, silences: silences, logger: l, - m: metrics.NewAlerts("v2", r), + m: metrics.NewAlerts(r), uptime: time.Now(), } @@ -505,17 +507,10 @@ func matchFilterLabels(matchers []*labels.Matcher, sms map[string]string) bool { func (api *API) getSilencesHandler(params silence_ops.GetSilencesParams) middleware.Responder { logger := api.requestLogger(params.HTTPRequest) - matchers := []*labels.Matcher{} - if params.Filter != nil { - for _, matcherString := range params.Filter { - matcher, err := labels.ParseMatcher(matcherString) - if err != nil { - level.Debug(logger).Log("msg", "Failed to parse matchers", "err", err) - return alert_ops.NewGetAlertsBadRequest().WithPayload(err.Error()) - } - - matchers = append(matchers, matcher) - } + matchers, err := parseFilter(params.Filter) + if err != nil { + level.Debug(logger).Log("msg", "Failed to parse matchers", "err", err) + return silence_ops.NewGetSilencesBadRequest().WithPayload(err.Error()) } psils, _, err := api.silences.Query() @@ -634,7 +629,7 @@ func (api *API) deleteSilenceHandler(params silence_ops.DeleteSilenceParams) mid sid := params.SilenceID.String() if err := api.silences.Expire(sid); err != nil { level.Error(logger).Log("msg", "Failed to expire silence", "err", err) - if err == silence.ErrNotFound { + if errors.Is(err, silence.ErrNotFound) { return silence_ops.NewDeleteSilenceNotFound() } return silence_ops.NewDeleteSilenceInternalServerError().WithPayload(err.Error()) @@ -668,7 +663,7 @@ func (api *API) postSilencesHandler(params silence_ops.PostSilencesParams) middl sid, err := api.silences.Set(sil) if err != nil { level.Error(logger).Log("msg", "Failed to create silence", "err", err) - if err == silence.ErrNotFound { + if errors.Is(err, silence.ErrNotFound) { return silence_ops.NewPostSilencesNotFound().WithPayload(err.Error()) } return silence_ops.NewPostSilencesBadRequest().WithPayload(err.Error()) @@ -682,7 +677,7 @@ func (api *API) postSilencesHandler(params silence_ops.PostSilencesParams) middl func parseFilter(filter []string) ([]*labels.Matcher, error) { matchers := make([]*labels.Matcher, 0, len(filter)) for _, matcherString := range filter { - matcher, err := labels.ParseMatcher(matcherString) + matcher, err := compat.Matcher(matcherString, "api") if err != nil { return nil, err } diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/client/alert/get_alerts_responses.go b/vendor/github.com/prometheus/alertmanager/api/v2/client/alert/get_alerts_responses.go index 516dbc31d9..54fcb9c355 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/client/alert/get_alerts_responses.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/client/alert/get_alerts_responses.go @@ -56,7 +56,7 @@ func (o *GetAlertsReader) ReadResponse(response runtime.ClientResponse, consumer } return nil, result default: - return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code()) + return nil, runtime.NewAPIError("[GET /alerts] getAlerts", response, response.Code()) } } @@ -99,6 +99,11 @@ func (o *GetAlertsOK) IsCode(code int) bool { return code == 200 } +// Code gets the status code for the get alerts o k response +func (o *GetAlertsOK) Code() int { + return 200 +} + func (o *GetAlertsOK) Error() string { return fmt.Sprintf("[GET /alerts][%d] getAlertsOK %+v", 200, o.Payload) } @@ -160,6 +165,11 @@ func (o *GetAlertsBadRequest) IsCode(code int) bool { return code == 400 } +// Code gets the status code for the get alerts bad request response +func (o *GetAlertsBadRequest) Code() int { + return 400 +} + func (o *GetAlertsBadRequest) Error() string { return fmt.Sprintf("[GET /alerts][%d] getAlertsBadRequest %+v", 400, o.Payload) } @@ -221,6 +231,11 @@ func (o *GetAlertsInternalServerError) IsCode(code int) bool { return code == 500 } +// Code gets the status code for the get alerts internal server error response +func (o *GetAlertsInternalServerError) Code() int { + return 500 +} + func (o *GetAlertsInternalServerError) Error() string { return fmt.Sprintf("[GET /alerts][%d] getAlertsInternalServerError %+v", 500, o.Payload) } diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/client/alert/post_alerts_responses.go b/vendor/github.com/prometheus/alertmanager/api/v2/client/alert/post_alerts_responses.go index 67be66c6af..7a7955ce79 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/client/alert/post_alerts_responses.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/client/alert/post_alerts_responses.go @@ -54,7 +54,7 @@ func (o *PostAlertsReader) ReadResponse(response runtime.ClientResponse, consume } return nil, result default: - return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code()) + return nil, runtime.NewAPIError("[POST /alerts] postAlerts", response, response.Code()) } } @@ -96,6 +96,11 @@ func (o *PostAlertsOK) IsCode(code int) bool { return code == 200 } +// Code gets the status code for the post alerts o k response +func (o *PostAlertsOK) Code() int { + return 200 +} + func (o *PostAlertsOK) Error() string { return fmt.Sprintf("[POST /alerts][%d] postAlertsOK ", 200) } @@ -148,6 +153,11 @@ func (o *PostAlertsBadRequest) IsCode(code int) bool { return code == 400 } +// Code gets the status code for the post alerts bad request response +func (o *PostAlertsBadRequest) Code() int { + return 400 +} + func (o *PostAlertsBadRequest) Error() string { return fmt.Sprintf("[POST /alerts][%d] postAlertsBadRequest %+v", 400, o.Payload) } @@ -209,6 +219,11 @@ func (o *PostAlertsInternalServerError) IsCode(code int) bool { return code == 500 } +// Code gets the status code for the post alerts internal server error response +func (o *PostAlertsInternalServerError) Code() int { + return 500 +} + func (o *PostAlertsInternalServerError) Error() string { return fmt.Sprintf("[POST /alerts][%d] postAlertsInternalServerError %+v", 500, o.Payload) } diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/client/alertgroup/get_alert_groups_responses.go b/vendor/github.com/prometheus/alertmanager/api/v2/client/alertgroup/get_alert_groups_responses.go index f348da944e..2cd5a18eb7 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/client/alertgroup/get_alert_groups_responses.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/client/alertgroup/get_alert_groups_responses.go @@ -56,7 +56,7 @@ func (o *GetAlertGroupsReader) ReadResponse(response runtime.ClientResponse, con } return nil, result default: - return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code()) + return nil, runtime.NewAPIError("[GET /alerts/groups] getAlertGroups", response, response.Code()) } } @@ -99,6 +99,11 @@ func (o *GetAlertGroupsOK) IsCode(code int) bool { return code == 200 } +// Code gets the status code for the get alert groups o k response +func (o *GetAlertGroupsOK) Code() int { + return 200 +} + func (o *GetAlertGroupsOK) Error() string { return fmt.Sprintf("[GET /alerts/groups][%d] getAlertGroupsOK %+v", 200, o.Payload) } @@ -160,6 +165,11 @@ func (o *GetAlertGroupsBadRequest) IsCode(code int) bool { return code == 400 } +// Code gets the status code for the get alert groups bad request response +func (o *GetAlertGroupsBadRequest) Code() int { + return 400 +} + func (o *GetAlertGroupsBadRequest) Error() string { return fmt.Sprintf("[GET /alerts/groups][%d] getAlertGroupsBadRequest %+v", 400, o.Payload) } @@ -221,6 +231,11 @@ func (o *GetAlertGroupsInternalServerError) IsCode(code int) bool { return code == 500 } +// Code gets the status code for the get alert groups internal server error response +func (o *GetAlertGroupsInternalServerError) Code() int { + return 500 +} + func (o *GetAlertGroupsInternalServerError) Error() string { return fmt.Sprintf("[GET /alerts/groups][%d] getAlertGroupsInternalServerError %+v", 500, o.Payload) } diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/client/general/get_status_responses.go b/vendor/github.com/prometheus/alertmanager/api/v2/client/general/get_status_responses.go index ddd6b2a2d7..0cb6f36af3 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/client/general/get_status_responses.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/client/general/get_status_responses.go @@ -44,7 +44,7 @@ func (o *GetStatusReader) ReadResponse(response runtime.ClientResponse, consumer } return result, nil default: - return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code()) + return nil, runtime.NewAPIError("[GET /status] getStatus", response, response.Code()) } } @@ -87,6 +87,11 @@ func (o *GetStatusOK) IsCode(code int) bool { return code == 200 } +// Code gets the status code for the get status o k response +func (o *GetStatusOK) Code() int { + return 200 +} + func (o *GetStatusOK) Error() string { return fmt.Sprintf("[GET /status][%d] getStatusOK %+v", 200, o.Payload) } diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/client/receiver/get_receivers_responses.go b/vendor/github.com/prometheus/alertmanager/api/v2/client/receiver/get_receivers_responses.go index c8fe599913..ef97632773 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/client/receiver/get_receivers_responses.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/client/receiver/get_receivers_responses.go @@ -44,7 +44,7 @@ func (o *GetReceiversReader) ReadResponse(response runtime.ClientResponse, consu } return result, nil default: - return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code()) + return nil, runtime.NewAPIError("[GET /receivers] getReceivers", response, response.Code()) } } @@ -87,6 +87,11 @@ func (o *GetReceiversOK) IsCode(code int) bool { return code == 200 } +// Code gets the status code for the get receivers o k response +func (o *GetReceiversOK) Code() int { + return 200 +} + func (o *GetReceiversOK) Error() string { return fmt.Sprintf("[GET /receivers][%d] getReceiversOK %+v", 200, o.Payload) } diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/client/silence/delete_silence_responses.go b/vendor/github.com/prometheus/alertmanager/api/v2/client/silence/delete_silence_responses.go index c8b2bba1c7..40c87fc9bf 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/client/silence/delete_silence_responses.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/client/silence/delete_silence_responses.go @@ -54,7 +54,7 @@ func (o *DeleteSilenceReader) ReadResponse(response runtime.ClientResponse, cons } return nil, result default: - return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code()) + return nil, runtime.NewAPIError("[DELETE /silence/{silenceID}] deleteSilence", response, response.Code()) } } @@ -96,6 +96,11 @@ func (o *DeleteSilenceOK) IsCode(code int) bool { return code == 200 } +// Code gets the status code for the delete silence o k response +func (o *DeleteSilenceOK) Code() int { + return 200 +} + func (o *DeleteSilenceOK) Error() string { return fmt.Sprintf("[DELETE /silence/{silenceID}][%d] deleteSilenceOK ", 200) } @@ -147,6 +152,11 @@ func (o *DeleteSilenceNotFound) IsCode(code int) bool { return code == 404 } +// Code gets the status code for the delete silence not found response +func (o *DeleteSilenceNotFound) Code() int { + return 404 +} + func (o *DeleteSilenceNotFound) Error() string { return fmt.Sprintf("[DELETE /silence/{silenceID}][%d] deleteSilenceNotFound ", 404) } @@ -199,6 +209,11 @@ func (o *DeleteSilenceInternalServerError) IsCode(code int) bool { return code == 500 } +// Code gets the status code for the delete silence internal server error response +func (o *DeleteSilenceInternalServerError) Code() int { + return 500 +} + func (o *DeleteSilenceInternalServerError) Error() string { return fmt.Sprintf("[DELETE /silence/{silenceID}][%d] deleteSilenceInternalServerError %+v", 500, o.Payload) } diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/client/silence/get_silence_responses.go b/vendor/github.com/prometheus/alertmanager/api/v2/client/silence/get_silence_responses.go index 6cfdb73bf2..b11ded0429 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/client/silence/get_silence_responses.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/client/silence/get_silence_responses.go @@ -56,7 +56,7 @@ func (o *GetSilenceReader) ReadResponse(response runtime.ClientResponse, consume } return nil, result default: - return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code()) + return nil, runtime.NewAPIError("[GET /silence/{silenceID}] getSilence", response, response.Code()) } } @@ -99,6 +99,11 @@ func (o *GetSilenceOK) IsCode(code int) bool { return code == 200 } +// Code gets the status code for the get silence o k response +func (o *GetSilenceOK) Code() int { + return 200 +} + func (o *GetSilenceOK) Error() string { return fmt.Sprintf("[GET /silence/{silenceID}][%d] getSilenceOK %+v", 200, o.Payload) } @@ -161,6 +166,11 @@ func (o *GetSilenceNotFound) IsCode(code int) bool { return code == 404 } +// Code gets the status code for the get silence not found response +func (o *GetSilenceNotFound) Code() int { + return 404 +} + func (o *GetSilenceNotFound) Error() string { return fmt.Sprintf("[GET /silence/{silenceID}][%d] getSilenceNotFound ", 404) } @@ -213,6 +223,11 @@ func (o *GetSilenceInternalServerError) IsCode(code int) bool { return code == 500 } +// Code gets the status code for the get silence internal server error response +func (o *GetSilenceInternalServerError) Code() int { + return 500 +} + func (o *GetSilenceInternalServerError) Error() string { return fmt.Sprintf("[GET /silence/{silenceID}][%d] getSilenceInternalServerError %+v", 500, o.Payload) } diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/client/silence/get_silences_responses.go b/vendor/github.com/prometheus/alertmanager/api/v2/client/silence/get_silences_responses.go index 6578dd399e..501449faba 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/client/silence/get_silences_responses.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/client/silence/get_silences_responses.go @@ -43,6 +43,12 @@ func (o *GetSilencesReader) ReadResponse(response runtime.ClientResponse, consum return nil, err } return result, nil + case 400: + result := NewGetSilencesBadRequest() + if err := result.readResponse(response, consumer, o.formats); err != nil { + return nil, err + } + return nil, result case 500: result := NewGetSilencesInternalServerError() if err := result.readResponse(response, consumer, o.formats); err != nil { @@ -50,7 +56,7 @@ func (o *GetSilencesReader) ReadResponse(response runtime.ClientResponse, consum } return nil, result default: - return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code()) + return nil, runtime.NewAPIError("[GET /silences] getSilences", response, response.Code()) } } @@ -93,6 +99,11 @@ func (o *GetSilencesOK) IsCode(code int) bool { return code == 200 } +// Code gets the status code for the get silences o k response +func (o *GetSilencesOK) Code() int { + return 200 +} + func (o *GetSilencesOK) Error() string { return fmt.Sprintf("[GET /silences][%d] getSilencesOK %+v", 200, o.Payload) } @@ -115,6 +126,72 @@ func (o *GetSilencesOK) readResponse(response runtime.ClientResponse, consumer r return nil } +// NewGetSilencesBadRequest creates a GetSilencesBadRequest with default headers values +func NewGetSilencesBadRequest() *GetSilencesBadRequest { + return &GetSilencesBadRequest{} +} + +/* +GetSilencesBadRequest describes a response with status code 400, with default header values. + +Bad request +*/ +type GetSilencesBadRequest struct { + Payload string +} + +// IsSuccess returns true when this get silences bad request response has a 2xx status code +func (o *GetSilencesBadRequest) IsSuccess() bool { + return false +} + +// IsRedirect returns true when this get silences bad request response has a 3xx status code +func (o *GetSilencesBadRequest) IsRedirect() bool { + return false +} + +// IsClientError returns true when this get silences bad request response has a 4xx status code +func (o *GetSilencesBadRequest) IsClientError() bool { + return true +} + +// IsServerError returns true when this get silences bad request response has a 5xx status code +func (o *GetSilencesBadRequest) IsServerError() bool { + return false +} + +// IsCode returns true when this get silences bad request response a status code equal to that given +func (o *GetSilencesBadRequest) IsCode(code int) bool { + return code == 400 +} + +// Code gets the status code for the get silences bad request response +func (o *GetSilencesBadRequest) Code() int { + return 400 +} + +func (o *GetSilencesBadRequest) Error() string { + return fmt.Sprintf("[GET /silences][%d] getSilencesBadRequest %+v", 400, o.Payload) +} + +func (o *GetSilencesBadRequest) String() string { + return fmt.Sprintf("[GET /silences][%d] getSilencesBadRequest %+v", 400, o.Payload) +} + +func (o *GetSilencesBadRequest) GetPayload() string { + return o.Payload +} + +func (o *GetSilencesBadRequest) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { + + // response payload + if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF { + return err + } + + return nil +} + // NewGetSilencesInternalServerError creates a GetSilencesInternalServerError with default headers values func NewGetSilencesInternalServerError() *GetSilencesInternalServerError { return &GetSilencesInternalServerError{} @@ -154,6 +231,11 @@ func (o *GetSilencesInternalServerError) IsCode(code int) bool { return code == 500 } +// Code gets the status code for the get silences internal server error response +func (o *GetSilencesInternalServerError) Code() int { + return 500 +} + func (o *GetSilencesInternalServerError) Error() string { return fmt.Sprintf("[GET /silences][%d] getSilencesInternalServerError %+v", 500, o.Payload) } diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/client/silence/post_silences_responses.go b/vendor/github.com/prometheus/alertmanager/api/v2/client/silence/post_silences_responses.go index 9cf1f2e500..7d14642978 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/client/silence/post_silences_responses.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/client/silence/post_silences_responses.go @@ -56,7 +56,7 @@ func (o *PostSilencesReader) ReadResponse(response runtime.ClientResponse, consu } return nil, result default: - return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code()) + return nil, runtime.NewAPIError("[POST /silences] postSilences", response, response.Code()) } } @@ -99,6 +99,11 @@ func (o *PostSilencesOK) IsCode(code int) bool { return code == 200 } +// Code gets the status code for the post silences o k response +func (o *PostSilencesOK) Code() int { + return 200 +} + func (o *PostSilencesOK) Error() string { return fmt.Sprintf("[POST /silences][%d] postSilencesOK %+v", 200, o.Payload) } @@ -162,6 +167,11 @@ func (o *PostSilencesBadRequest) IsCode(code int) bool { return code == 400 } +// Code gets the status code for the post silences bad request response +func (o *PostSilencesBadRequest) Code() int { + return 400 +} + func (o *PostSilencesBadRequest) Error() string { return fmt.Sprintf("[POST /silences][%d] postSilencesBadRequest %+v", 400, o.Payload) } @@ -223,6 +233,11 @@ func (o *PostSilencesNotFound) IsCode(code int) bool { return code == 404 } +// Code gets the status code for the post silences not found response +func (o *PostSilencesNotFound) Code() int { + return 404 +} + func (o *PostSilencesNotFound) Error() string { return fmt.Sprintf("[POST /silences][%d] postSilencesNotFound %+v", 404, o.Payload) } diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/models/alert_group.go b/vendor/github.com/prometheus/alertmanager/api/v2/models/alert_group.go index c943e68330..fbb5e283b1 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/models/alert_group.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/models/alert_group.go @@ -163,6 +163,11 @@ func (m *AlertGroup) contextValidateAlerts(ctx context.Context, formats strfmt.R for i := 0; i < len(m.Alerts); i++ { if m.Alerts[i] != nil { + + if swag.IsZero(m.Alerts[i]) { // not required + return nil + } + if err := m.Alerts[i].ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("alerts" + "." + strconv.Itoa(i)) @@ -195,6 +200,7 @@ func (m *AlertGroup) contextValidateLabels(ctx context.Context, formats strfmt.R func (m *AlertGroup) contextValidateReceiver(ctx context.Context, formats strfmt.Registry) error { if m.Receiver != nil { + if err := m.Receiver.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("receiver") diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/models/alert_groups.go b/vendor/github.com/prometheus/alertmanager/api/v2/models/alert_groups.go index 31ccb2172b..338b22127a 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/models/alert_groups.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/models/alert_groups.go @@ -68,6 +68,11 @@ func (m AlertGroups) ContextValidate(ctx context.Context, formats strfmt.Registr for i := 0; i < len(m); i++ { if m[i] != nil { + + if swag.IsZero(m[i]) { // not required + return nil + } + if err := m[i].ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName(strconv.Itoa(i)) diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/models/alertmanager_status.go b/vendor/github.com/prometheus/alertmanager/api/v2/models/alertmanager_status.go index 0d5370edfb..2ab11ec461 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/models/alertmanager_status.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/models/alertmanager_status.go @@ -175,6 +175,7 @@ func (m *AlertmanagerStatus) ContextValidate(ctx context.Context, formats strfmt func (m *AlertmanagerStatus) contextValidateCluster(ctx context.Context, formats strfmt.Registry) error { if m.Cluster != nil { + if err := m.Cluster.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("cluster") @@ -191,6 +192,7 @@ func (m *AlertmanagerStatus) contextValidateCluster(ctx context.Context, formats func (m *AlertmanagerStatus) contextValidateConfig(ctx context.Context, formats strfmt.Registry) error { if m.Config != nil { + if err := m.Config.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("config") @@ -207,6 +209,7 @@ func (m *AlertmanagerStatus) contextValidateConfig(ctx context.Context, formats func (m *AlertmanagerStatus) contextValidateVersionInfo(ctx context.Context, formats strfmt.Registry) error { if m.VersionInfo != nil { + if err := m.VersionInfo.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("versionInfo") diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/models/cluster_status.go b/vendor/github.com/prometheus/alertmanager/api/v2/models/cluster_status.go index 0078320f15..f470bc010f 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/models/cluster_status.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/models/cluster_status.go @@ -156,6 +156,11 @@ func (m *ClusterStatus) contextValidatePeers(ctx context.Context, formats strfmt for i := 0; i < len(m.Peers); i++ { if m.Peers[i] != nil { + + if swag.IsZero(m.Peers[i]) { // not required + return nil + } + if err := m.Peers[i].ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("peers" + "." + strconv.Itoa(i)) diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/models/gettable_alert.go b/vendor/github.com/prometheus/alertmanager/api/v2/models/gettable_alert.go index f7db3321c1..195bb53764 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/models/gettable_alert.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/models/gettable_alert.go @@ -366,6 +366,11 @@ func (m *GettableAlert) contextValidateReceivers(ctx context.Context, formats st for i := 0; i < len(m.Receivers); i++ { if m.Receivers[i] != nil { + + if swag.IsZero(m.Receivers[i]) { // not required + return nil + } + if err := m.Receivers[i].ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("receivers" + "." + strconv.Itoa(i)) @@ -384,6 +389,7 @@ func (m *GettableAlert) contextValidateReceivers(ctx context.Context, formats st func (m *GettableAlert) contextValidateStatus(ctx context.Context, formats strfmt.Registry) error { if m.Status != nil { + if err := m.Status.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("status") diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/models/gettable_alerts.go b/vendor/github.com/prometheus/alertmanager/api/v2/models/gettable_alerts.go index 4efe8cd5ec..db78dcc471 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/models/gettable_alerts.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/models/gettable_alerts.go @@ -68,6 +68,11 @@ func (m GettableAlerts) ContextValidate(ctx context.Context, formats strfmt.Regi for i := 0; i < len(m); i++ { if m[i] != nil { + + if swag.IsZero(m[i]) { // not required + return nil + } + if err := m[i].ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName(strconv.Itoa(i)) diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/models/gettable_silence.go b/vendor/github.com/prometheus/alertmanager/api/v2/models/gettable_silence.go index fe9d178d7f..9d60f6cad0 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/models/gettable_silence.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/models/gettable_silence.go @@ -202,6 +202,7 @@ func (m *GettableSilence) ContextValidate(ctx context.Context, formats strfmt.Re func (m *GettableSilence) contextValidateStatus(ctx context.Context, formats strfmt.Registry) error { if m.Status != nil { + if err := m.Status.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("status") diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/models/gettable_silences.go b/vendor/github.com/prometheus/alertmanager/api/v2/models/gettable_silences.go index cda5ef6497..fed9d0b886 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/models/gettable_silences.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/models/gettable_silences.go @@ -68,6 +68,11 @@ func (m GettableSilences) ContextValidate(ctx context.Context, formats strfmt.Re for i := 0; i < len(m); i++ { if m[i] != nil { + + if swag.IsZero(m[i]) { // not required + return nil + } + if err := m[i].ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName(strconv.Itoa(i)) diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/models/matchers.go b/vendor/github.com/prometheus/alertmanager/api/v2/models/matchers.go index 4e2061872e..fbff9875eb 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/models/matchers.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/models/matchers.go @@ -75,6 +75,11 @@ func (m Matchers) ContextValidate(ctx context.Context, formats strfmt.Registry) for i := 0; i < len(m); i++ { if m[i] != nil { + + if swag.IsZero(m[i]) { // not required + return nil + } + if err := m[i].ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName(strconv.Itoa(i)) diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/models/postable_alert.go b/vendor/github.com/prometheus/alertmanager/api/v2/models/postable_alert.go index dcec7f0a19..105b8b30cd 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/models/postable_alert.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/models/postable_alert.go @@ -203,6 +203,10 @@ func (m *PostableAlert) ContextValidate(ctx context.Context, formats strfmt.Regi func (m *PostableAlert) contextValidateAnnotations(ctx context.Context, formats strfmt.Registry) error { + if swag.IsZero(m.Annotations) { // not required + return nil + } + if err := m.Annotations.ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName("annotations") diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/models/postable_alerts.go b/vendor/github.com/prometheus/alertmanager/api/v2/models/postable_alerts.go index ed4d7fb9ba..3df968820d 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/models/postable_alerts.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/models/postable_alerts.go @@ -68,6 +68,11 @@ func (m PostableAlerts) ContextValidate(ctx context.Context, formats strfmt.Regi for i := 0; i < len(m); i++ { if m[i] != nil { + + if swag.IsZero(m[i]) { // not required + return nil + } + if err := m[i].ContextValidate(ctx, formats); err != nil { if ve, ok := err.(*errors.Validation); ok { return ve.ValidateName(strconv.Itoa(i)) diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/openapi.yaml b/vendor/github.com/prometheus/alertmanager/api/v2/openapi.yaml index 801edf00bb..549cc33e7f 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/openapi.yaml +++ b/vendor/github.com/prometheus/alertmanager/api/v2/openapi.yaml @@ -53,6 +53,8 @@ paths: description: Get silences response schema: $ref: '#/definitions/gettableSilences' + '400': + $ref: '#/responses/BadRequest' '500': $ref: '#/responses/InternalServerError' parameters: diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/restapi/embedded_spec.go b/vendor/github.com/prometheus/alertmanager/api/v2/restapi/embedded_spec.go index caf371d884..0e23efd060 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/restapi/embedded_spec.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/restapi/embedded_spec.go @@ -317,6 +317,9 @@ func init() { "$ref": "#/definitions/gettableSilences" } }, + "400": { + "$ref": "#/responses/BadRequest" + }, "500": { "$ref": "#/responses/InternalServerError" } @@ -1128,6 +1131,12 @@ func init() { "$ref": "#/definitions/gettableSilences" } }, + "400": { + "description": "Bad request", + "schema": { + "type": "string" + } + }, "500": { "description": "Internal server error", "schema": { diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/restapi/operations/alertmanager_api.go b/vendor/github.com/prometheus/alertmanager/api/v2/restapi/operations/alertmanager_api.go index 8cbd9a6efb..e28c76b32e 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/restapi/operations/alertmanager_api.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/restapi/operations/alertmanager_api.go @@ -412,6 +412,6 @@ func (o *AlertmanagerAPI) AddMiddlewareFor(method, path string, builder middlewa } o.Init() if h, ok := o.handlers[um][path]; ok { - o.handlers[method][path] = builder(h) + o.handlers[um][path] = builder(h) } } diff --git a/vendor/github.com/prometheus/alertmanager/api/v2/restapi/operations/silence/get_silences_responses.go b/vendor/github.com/prometheus/alertmanager/api/v2/restapi/operations/silence/get_silences_responses.go index f2f7b88f74..b09c772aa2 100644 --- a/vendor/github.com/prometheus/alertmanager/api/v2/restapi/operations/silence/get_silences_responses.go +++ b/vendor/github.com/prometheus/alertmanager/api/v2/restapi/operations/silence/get_silences_responses.go @@ -75,6 +75,49 @@ func (o *GetSilencesOK) WriteResponse(rw http.ResponseWriter, producer runtime.P } } +// GetSilencesBadRequestCode is the HTTP code returned for type GetSilencesBadRequest +const GetSilencesBadRequestCode int = 400 + +/* +GetSilencesBadRequest Bad request + +swagger:response getSilencesBadRequest +*/ +type GetSilencesBadRequest struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetSilencesBadRequest creates GetSilencesBadRequest with default headers values +func NewGetSilencesBadRequest() *GetSilencesBadRequest { + + return &GetSilencesBadRequest{} +} + +// WithPayload adds the payload to the get silences bad request response +func (o *GetSilencesBadRequest) WithPayload(payload string) *GetSilencesBadRequest { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get silences bad request response +func (o *GetSilencesBadRequest) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetSilencesBadRequest) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(400) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + // GetSilencesInternalServerErrorCode is the HTTP code returned for type GetSilencesInternalServerError const GetSilencesInternalServerErrorCode int = 500 diff --git a/vendor/github.com/prometheus/alertmanager/asset/assets_vfsdata.go b/vendor/github.com/prometheus/alertmanager/asset/assets_vfsdata.go index fe0d3ce719..f74112ad01 100644 --- a/vendor/github.com/prometheus/alertmanager/asset/assets_vfsdata.go +++ b/vendor/github.com/prometheus/alertmanager/asset/assets_vfsdata.go @@ -163,9 +163,9 @@ var Assets = func() http.FileSystem { "/templates/default.tmpl": &vfsgen۰CompressedFileInfo{ name: "default.tmpl", modTime: time.Date(1970, 1, 1, 0, 0, 1, 0, time.UTC), - uncompressedSize: 5875, + uncompressedSize: 5951, - compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x02\xff\xec\x58\x41\x6f\xa3\x3a\x10\xbe\xf3\x2b\xac\xf4\xd2\x1c\x42\xdf\xb9\x52\xf5\x54\x3d\xbd\xdd\x4b\xb5\x5a\xa5\xca\x5e\x56\x2b\xe4\xc0\x84\xba\x31\x36\xb5\x87\xb4\x11\xe1\xbf\xaf\x0c\x94\x40\x0c\xa9\x49\xb3\xa7\xcd\xad\xb8\x33\xdf\x8c\xbf\xf9\x98\x19\x92\xe7\x24\x82\x15\x13\x40\x26\x41\x40\x39\x28\x4c\xa8\xa0\x31\xa8\x09\x29\x8a\xfb\xd6\x73\x9e\x13\x10\x11\x29\x0a\x6f\xd0\x65\x31\x7f\x30\x5e\x79\x4e\xfc\xff\xdf\x10\x94\xa0\x7c\x31\x7f\x20\x45\x71\x73\x75\x53\xda\xe9\x7f\x15\x84\xc0\x36\xa0\xee\x8c\xd1\xbc\x7e\x20\x3b\x92\x29\xfe\x92\x81\xda\x56\xee\x75\xa0\x6e\x24\x9d\x2d\x9f\x21\x44\x13\xe1\xa7\xf1\x7e\x44\x8a\x99\x26\x3b\x82\x72\x91\xa6\xa0\x2a\x57\xb6\x22\xf0\xd2\xfc\x73\xb2\x62\x8a\x89\xd8\xf8\xdc\x1a\x9f\xf2\x42\xda\xff\x52\x9e\x92\x1d\xe1\x20\xda\x11\x7f\x11\x63\xf4\x55\xc9\x2c\x7d\xa0\x4b\xe0\xda\x7f\x94\x0a\x21\xfa\x4e\x99\xd2\xfe\x0f\xca\x33\x30\x01\x9f\x25\x13\x64\x42\x0c\x2a\xa9\x42\xc6\x48\xae\x0d\x96\xff\x9f\x4c\x12\x29\x2a\xe7\x69\x7d\xd6\xc2\x9b\x92\xa2\xb8\xce\x73\xf2\xca\xf0\xa9\x6b\xec\xcf\x21\x91\x1b\xe8\x46\xff\x46\x13\xd0\x35\xa3\x7d\xd1\x9b\xc4\xa7\xcd\x5f\x03\x65\x8a\x40\x87\x8a\xa5\xc8\xa4\x98\x1c\xe1\x18\xe1\x0d\xab\x92\x06\x9c\x69\xac\x4d\x15\x15\x31\x10\x9f\x14\x45\x95\xd7\xad\xb7\x3f\xb4\x79\x32\xac\xcc\x4a\x22\x4d\xfa\xe6\xe9\x8e\x34\x17\xa8\x13\xab\x82\xdf\x0b\x21\x91\x9a\x9c\x3a\x90\xad\xe3\xd3\x70\x1f\x65\xa6\x42\xb8\xad\x8a\x09\x02\x14\x45\xa9\x2a\x25\x7a\x3d\x44\x1d\xa5\x20\x48\xa8\x5a\x47\xf2\x55\x58\x5c\x78\xae\x64\x38\x66\xed\x8d\xa7\xc3\x15\xd9\x89\x10\xaf\x9f\x11\xcd\x69\xb8\xf6\x23\x58\xd1\x8c\xa3\x8f\x0c\x39\xd4\x54\x20\x24\x29\xa7\xd8\x7d\x39\xfd\x21\x0d\x76\x71\x32\x6d\xda\x43\xd2\x07\xd5\x6d\x42\x8e\x78\x2b\xca\xf9\x92\x86\x6b\x0b\xaf\x37\x7d\x03\x4a\x76\xe4\x23\x43\xce\xc4\xda\x39\x83\xb0\xce\x80\x45\x13\x37\x87\x54\x81\xd1\x9a\xa3\x75\x2b\xa1\xa3\x8c\x95\x3d\xd8\x31\x65\x16\x4a\x01\x89\x7c\x66\x13\x77\xfb\x4c\x71\xd7\x8c\xdd\x2f\xb7\x92\x12\xab\x89\xd3\xd2\x60\xdb\x3c\x35\x57\x8b\x32\xdc\x36\x2e\x76\x43\x1b\x27\x47\x1b\x31\xe4\x0c\x04\x9e\x2e\xc8\x21\xc4\xfd\x54\x3c\xad\x66\x36\x2e\x13\x1a\xa9\x08\x41\xf7\xe0\x5a\x1d\xdc\x1f\x66\x55\xa6\x3a\x06\xc1\xa0\x01\x4e\x40\x6b\x1a\x9f\xf6\x7e\x5b\x60\x76\x85\xea\x81\x37\xd0\xd0\x7a\x27\x9c\x77\x30\x5f\x3b\x03\x7c\x4a\xfe\x21\x33\xd3\x38\xcb\x43\x52\x1d\x96\xad\xf3\x38\x23\xdd\x2d\xa0\x0c\x32\x6b\xdd\xa8\x27\xde\x1c\xb4\xe4\x1b\x88\x0e\x22\xbe\x1f\xbb\xc7\x7c\xf7\xb0\xa2\xce\x5c\x28\xd5\x65\x1f\x1f\xaf\xa6\x4e\xd5\x5f\x21\x7c\xa2\x38\xb6\xe6\xde\xa5\x7e\x47\xea\xd7\x5e\x94\x17\x8a\x5b\x78\xbd\xf5\x19\xa8\xfa\x41\x7d\x50\x06\x66\x58\x0e\x76\x52\xdb\x3c\xa5\x0a\xb7\x23\xec\x91\xc6\xae\xd6\x34\x06\x81\xc1\xe1\x88\xeb\xea\x6b\xc3\x42\x94\x4a\xa6\x7a\x2f\x5b\xa4\x08\x41\x57\x68\x17\x2d\x8d\xeb\x05\x36\xab\x20\x90\xe1\x36\x88\x98\x4e\x39\xdd\x06\x03\xdb\xd4\xc7\x8d\xdb\x46\x4e\xa4\x60\x28\x0d\x21\x01\x4a\xc9\x47\x8e\xc4\xce\xec\xca\xf4\x93\xdc\x80\x3a\xc3\xfe\x68\x41\xfd\x79\x3d\x9d\x47\x4e\xee\x6a\x3a\x9f\x98\xec\x95\xfe\x18\x93\xfb\x9d\x6e\xcc\x4c\x69\x6f\x73\xa2\xf5\xb2\xef\x3f\xd3\xc7\x7f\x23\xb4\x70\x2e\xe5\x1d\x53\xde\x36\x8b\x08\x1c\x62\x45\x93\x3e\x2a\xff\x5a\x52\x22\xa6\x43\xa9\xa2\x33\x34\xa2\x43\xa4\x0b\xbb\x66\x4d\x58\xc2\xdb\xe5\xd5\xfd\x34\x8f\x89\x46\xa0\x89\x3e\x83\x4a\x2d\xa4\xfa\x6b\xdc\x85\xda\x2b\x32\x8a\xdc\xd6\x4f\x64\x9f\x66\xb9\x09\xed\xca\x73\x4f\xf0\x8f\x08\xff\x1d\x00\x00\xff\xff\xc6\x76\xea\x54\xf3\x16\x00\x00"), + compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x02\xff\xec\x58\x4f\x6f\xbb\x46\x10\xbd\xf3\x29\x56\xce\x25\x3e\x98\xf4\x1c\x29\xaa\xa2\xaa\xed\x25\xaa\x2a\x47\xee\xa5\xaa\xd0\x1a\xc6\x64\xe3\xfd\x43\x76\x07\x27\x16\xe6\xbb\x57\x0b\xc4\x06\x2f\x38\x8b\xe3\xdf\xe9\xe7\x5b\xd8\xcc\xbc\x99\x7d\x6f\x98\x19\x5c\x14\x24\x81\x15\x93\x40\x26\x51\x44\x39\x68\x14\x54\xd2\x14\xf4\x84\x94\xe5\x63\xeb\xb9\x28\x08\xc8\x84\x94\x65\x30\xe8\xb2\x98\x3f\x59\xaf\xa2\x20\xe1\xef\x1f\x08\x5a\x52\xbe\x98\x3f\x91\xb2\xbc\xbb\xb9\xab\xec\xcc\xaf\x1a\x62\x60\x1b\xd0\x0f\xd6\x68\xde\x3c\x90\x1d\xc9\x35\x7f\xcb\x41\x6f\x6b\xf7\x26\x50\x37\x92\xc9\x97\xaf\x10\xa3\x8d\xf0\xaf\xf5\x7e\x46\x8a\xb9\x21\x3b\x82\x6a\x91\x65\xa0\x6b\x57\xb6\x22\xf0\xb6\xff\xe7\x64\xc5\x34\x93\xa9\xf5\xb9\xb7\x3e\xd5\x85\x4c\xf8\x47\x75\x4a\x76\x84\x83\x6c\x47\xfc\x8f\x58\xa3\x3f\xb5\xca\xb3\x27\xba\x04\x6e\xc2\x67\xa5\x11\x92\xbf\x29\xd3\x26\xfc\x87\xf2\x1c\x6c\xc0\x57\xc5\x24\x99\x10\x8b\x4a\xea\x90\x29\x92\x5b\x8b\x15\xfe\xa6\x84\x50\xb2\x76\x9e\x36\x67\x2d\xbc\x29\x29\xcb\xdb\xa2\x20\xef\x0c\x5f\xba\xc6\xe1\x1c\x84\xda\x40\x37\xfa\x5f\x54\x80\x69\x18\xed\x8b\xbe\x4f\x7c\xba\xff\x6b\x40\xa6\x04\x4c\xac\x59\x86\x4c\xc9\xc9\x09\x8e\x11\x3e\xb0\x96\x34\xe2\xcc\x60\x63\xaa\xa9\x4c\x81\x84\xa4\x2c\xeb\xbc\xee\x83\xc3\xa1\xcb\x93\x65\x65\x56\x11\x69\xd3\xb7\x4f\x0f\x64\x7f\x81\x26\xb1\x3a\xf8\xa3\x94\x0a\xa9\xcd\xa9\x03\xd9\x3a\x3e\x0f\xf7\x59\xe5\x3a\x86\xfb\x5a\x4c\x90\xa0\x29\x2a\x5d\x57\x62\xd0\x43\xd4\x49\x0a\x22\x41\xf5\x3a\x51\xef\xd2\xe1\x22\xf0\x25\xc3\x33\xeb\x60\x3c\x1d\xbe\xc8\x5e\x84\x04\xfd\x8c\x18\x4e\xe3\x75\x98\xc0\x8a\xe6\x1c\x43\x64\xc8\xa1\xa1\x02\x41\x64\x9c\x62\xf7\xe5\x0c\x87\x6a\xb0\x8b\x93\x1b\xdb\x1e\x44\x1f\x54\xb7\x09\x79\xe2\xad\x28\xe7\x4b\x1a\xaf\x1d\xbc\xde\xf4\x2d\x28\xd9\x91\xaf\x0c\x39\x93\x6b\xef\x0c\xe2\x26\x03\x96\x4c\xfc\x1c\x32\x0d\xb6\xd6\x3c\xad\x5b\x09\x9d\x64\xac\xea\xc1\x9e\x29\xb3\x58\x49\x10\xea\x95\x4d\xfc\xed\x73\xcd\x7d\x33\xf6\xbf\xdc\x4a\x29\xac\x27\x4e\xab\x06\xdb\xe6\x99\xbd\x5a\x92\xe3\x76\xef\xe2\x36\xb4\x71\xe5\xe8\x22\xc6\x9c\x81\xc4\xf3\x0b\x72\x08\xf1\x30\x15\xcf\xd3\xcc\xc5\x65\xd2\x20\x95\x31\x98\x1e\x5c\xa7\x83\x87\xc3\xac\xaa\xcc\xa4\x20\x19\xec\x81\x05\x18\x43\xd3\xf3\xde\x6f\x07\xcc\x55\xa8\x19\x78\x03\x0d\xad\x77\xc2\x05\x47\xf3\xb5\x33\xc0\xa7\xe4\x17\x32\xb3\x8d\xb3\x3a\x24\xf5\x61\xd5\x3a\x4f\x33\xd2\xdd\x02\xaa\x20\xb3\xd6\x8d\x7a\xe2\xcd\xc1\x28\xbe\x81\xe4\x28\xe2\xe7\xb1\x7f\xcc\x4f\x0f\x27\xea\xcc\x87\x52\x53\xf5\xf1\xf1\xd5\xd4\x51\xfd\x1d\xe2\x17\x8a\x63\x35\x0f\xae\xfa\x9d\xd0\xaf\xbd\x28\x2f\x34\x77\xf0\x7a\xf5\x19\x50\xfd\x48\x1f\x54\x91\x1d\x96\x83\x9d\xd4\x35\xcf\xa8\xc6\xed\x08\x7b\xa4\xa9\xaf\x35\x4d\x41\x62\x74\x3c\xe2\xba\xf5\xb5\x61\x31\x2a\xad\x32\x73\x28\x5b\xa4\x08\x51\xb7\xd0\xae\xb5\x34\xae\x17\xb8\xac\x82\x44\x86\xdb\x28\x61\x26\xe3\x74\x1b\x0d\x6c\x53\x5f\x37\x6e\x17\x59\x28\xc9\x50\x59\x42\x22\x54\x8a\x8f\x1c\x89\x9d\xd9\x95\x9b\x17\xb5\x01\x7d\x81\xfd\xd1\x81\xfa\xf1\xf5\x74\x99\x72\xf2\xaf\xa6\xcb\x15\x93\xbb\xd2\x9f\x62\xf2\xb0\xd3\x8d\x99\x29\xed\x6d\x4e\xb6\x5e\xf6\xc3\x67\xfa\xf8\x6f\x84\x16\xce\x55\xde\x31\xf2\xb6\x59\x44\xe0\x90\x6a\x2a\xfa\xa8\xfc\x69\x49\x49\x98\x89\x95\x4e\x2e\xd0\x88\x8e\x91\xae\xec\xda\x35\x61\x09\x1f\xd7\x57\xf7\xdb\x3c\x0a\x83\x40\x45\xbb\x99\x0a\x41\xf5\xf6\xac\x3a\x3d\xc6\x3a\xbf\xe2\x1d\xa4\xe6\xcb\xde\x47\xa6\x1b\x32\x4a\xa8\xd6\xcf\x6d\xdf\x56\x6c\x1f\xda\x57\xb3\x9e\xe0\x5f\x89\xf7\x7f\x00\x00\x00\xff\xff\xf6\x0e\x88\xb1\x3f\x17\x00\x00"), }, "/templates/email.tmpl": &vfsgen۰CompressedFileInfo{ name: "email.tmpl", diff --git a/vendor/github.com/prometheus/alertmanager/cluster/advertise.go b/vendor/github.com/prometheus/alertmanager/cluster/advertise.go index b1b8fe949c..ac734649d1 100644 --- a/vendor/github.com/prometheus/alertmanager/cluster/advertise.go +++ b/vendor/github.com/prometheus/alertmanager/cluster/advertise.go @@ -14,10 +14,11 @@ package cluster import ( + "errors" + "fmt" "net" "github.com/hashicorp/go-sockaddr" - "github.com/pkg/errors" ) type getIPFunc func() (string, error) @@ -38,7 +39,7 @@ func calculateAdvertiseAddress(bindAddr, advertiseAddr string, allowInsecureAdve if advertiseAddr != "" { ip := net.ParseIP(advertiseAddr) if ip == nil { - return nil, errors.Errorf("failed to parse advertise addr '%s'", advertiseAddr) + return nil, fmt.Errorf("failed to parse advertise addr '%s'", advertiseAddr) } if ip4 := ip.To4(); ip4 != nil { ip = ip4 @@ -52,7 +53,7 @@ func calculateAdvertiseAddress(bindAddr, advertiseAddr string, allowInsecureAdve ip := net.ParseIP(bindAddr) if ip == nil { - return nil, errors.Errorf("failed to parse bind addr '%s'", bindAddr) + return nil, fmt.Errorf("failed to parse bind addr '%s'", bindAddr) } return ip, nil } @@ -64,7 +65,7 @@ func calculateAdvertiseAddress(bindAddr, advertiseAddr string, allowInsecureAdve func discoverAdvertiseAddress(allowInsecureAdvertise bool) (net.IP, error) { addr, err := getPrivateAddress() if err != nil { - return nil, errors.Wrap(err, "failed to get private IP") + return nil, fmt.Errorf("failed to get private IP: %w", err) } if addr == "" && !allowInsecureAdvertise { return nil, errors.New("no private IP found, explicit advertise addr not provided") @@ -73,7 +74,7 @@ func discoverAdvertiseAddress(allowInsecureAdvertise bool) (net.IP, error) { if addr == "" { addr, err = getPublicAddress() if err != nil { - return nil, errors.Wrap(err, "failed to get public IP") + return nil, fmt.Errorf("failed to get public IP: %w", err) } if addr == "" { return nil, errors.New("no private/public IP found, explicit advertise addr not provided") @@ -82,7 +83,7 @@ func discoverAdvertiseAddress(allowInsecureAdvertise bool) (net.IP, error) { ip := net.ParseIP(addr) if ip == nil { - return nil, errors.Errorf("failed to parse discovered IP '%s'", addr) + return nil, fmt.Errorf("failed to parse discovered IP '%s'", addr) } return ip, nil } diff --git a/vendor/github.com/prometheus/alertmanager/cluster/cluster.go b/vendor/github.com/prometheus/alertmanager/cluster/cluster.go index 2c7ee945e6..d85ee7f533 100644 --- a/vendor/github.com/prometheus/alertmanager/cluster/cluster.go +++ b/vendor/github.com/prometheus/alertmanager/cluster/cluster.go @@ -15,6 +15,7 @@ package cluster import ( "context" + "errors" "fmt" "math/rand" "net" @@ -28,7 +29,6 @@ import ( "github.com/go-kit/log/level" "github.com/hashicorp/memberlist" "github.com/oklog/ulid" - "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" ) @@ -146,11 +146,11 @@ func Create( ) (*Peer, error) { bindHost, bindPortStr, err := net.SplitHostPort(bindAddr) if err != nil { - return nil, errors.Wrap(err, "invalid listen address") + return nil, fmt.Errorf("invalid listen address: %w", err) } bindPort, err := strconv.Atoi(bindPortStr) if err != nil { - return nil, errors.Wrapf(err, "address %s: invalid port", bindAddr) + return nil, fmt.Errorf("address %s: invalid port: %w", bindAddr, err) } var advertiseHost string @@ -159,17 +159,17 @@ func Create( var advertisePortStr string advertiseHost, advertisePortStr, err = net.SplitHostPort(advertiseAddr) if err != nil { - return nil, errors.Wrap(err, "invalid advertise address") + return nil, fmt.Errorf("invalid advertise address: %w", err) } advertisePort, err = strconv.Atoi(advertisePortStr) if err != nil { - return nil, errors.Wrapf(err, "address %s: invalid port", advertiseAddr) + return nil, fmt.Errorf("address %s: invalid port: %w", advertiseAddr, err) } } resolvedPeers, err := resolvePeers(context.Background(), knownPeers, advertiseAddr, &net.Resolver{}, waitIfEmpty) if err != nil { - return nil, errors.Wrap(err, "resolve peers") + return nil, fmt.Errorf("resolve peers: %w", err) } level.Debug(l).Log("msg", "resolved peers to following addresses", "peers", strings.Join(resolvedPeers, ",")) @@ -242,13 +242,13 @@ func Create( level.Info(l).Log("msg", "using TLS for gossip") cfg.Transport, err = NewTLSTransport(context.Background(), l, reg, cfg.BindAddr, cfg.BindPort, tlsTransportConfig) if err != nil { - return nil, errors.Wrap(err, "tls transport") + return nil, fmt.Errorf("tls transport: %w", err) } } ml, err := memberlist.Create(cfg) if err != nil { - return nil, errors.Wrap(err, "create memberlist") + return nil, fmt.Errorf("create memberlist: %w", err) } p.mlist = ml return p, nil @@ -736,7 +736,7 @@ func resolvePeers(ctx context.Context, peers []string, myAddress string, res *ne for _, peer := range peers { host, port, err := net.SplitHostPort(peer) if err != nil { - return nil, errors.Wrapf(err, "split host/port for peer %s", peer) + return nil, fmt.Errorf("split host/port for peer %s: %w", peer, err) } retryCtx, cancel := context.WithCancel(ctx) @@ -761,7 +761,7 @@ func resolvePeers(ctx context.Context, peers []string, myAddress string, res *ne ips, err = res.LookupIPAddr(retryCtx, host) if err != nil { lookupErrSpotted = true - return errors.Wrapf(err, "IP Addr lookup for peer %s", peer) + return fmt.Errorf("IP Addr lookup for peer %s: %w", peer, err) } ips = removeMyAddr(ips, port, myAddress) diff --git a/vendor/github.com/prometheus/alertmanager/cluster/connection_pool.go b/vendor/github.com/prometheus/alertmanager/cluster/connection_pool.go index 4d8085dd81..b9bda3a82a 100644 --- a/vendor/github.com/prometheus/alertmanager/cluster/connection_pool.go +++ b/vendor/github.com/prometheus/alertmanager/cluster/connection_pool.go @@ -15,12 +15,12 @@ package cluster import ( "crypto/tls" + "errors" "fmt" "sync" "time" lru "github.com/hashicorp/golang-lru/v2" - "github.com/pkg/errors" ) const capacity = 1024 @@ -38,7 +38,7 @@ func newConnectionPool(tlsClientCfg *tls.Config) (*connectionPool, error) { }, ) if err != nil { - return nil, errors.Wrap(err, "failed to create new LRU") + return nil, fmt.Errorf("failed to create new LRU: %w", err) } return &connectionPool{ cache: cache, diff --git a/vendor/github.com/prometheus/alertmanager/cluster/tls_connection.go b/vendor/github.com/prometheus/alertmanager/cluster/tls_connection.go index 21ffc95970..5d6416fd1b 100644 --- a/vendor/github.com/prometheus/alertmanager/cluster/tls_connection.go +++ b/vendor/github.com/prometheus/alertmanager/cluster/tls_connection.go @@ -17,6 +17,8 @@ import ( "bufio" "crypto/tls" "encoding/binary" + "errors" + "fmt" "io" "net" "sync" @@ -24,7 +26,6 @@ import ( "github.com/gogo/protobuf/proto" "github.com/hashicorp/memberlist" - "github.com/pkg/errors" "github.com/prometheus/alertmanager/cluster/clusterpb" ) @@ -99,7 +100,7 @@ func (conn *tlsConn) writePacket(fromAddr string, b []byte) error { }, ) if err != nil { - return errors.Wrap(err, "unable to marshal memeberlist packet message") + return fmt.Errorf("unable to marshal memeberlist packet message: %w", err) } buf := make([]byte, uint32length, uint32length+len(msg)) binary.LittleEndian.PutUint32(buf, uint32(len(msg))) @@ -116,7 +117,7 @@ func (conn *tlsConn) writeStream() error { }, ) if err != nil { - return errors.Wrap(err, "unable to marshal memeberlist stream message") + return fmt.Errorf("unable to marshal memeberlist stream message: %w", err) } buf := make([]byte, uint32length, uint32length+len(msg)) binary.LittleEndian.PutUint32(buf, uint32(len(msg))) @@ -136,7 +137,7 @@ func (conn *tlsConn) read() (*memberlist.Packet, error) { lenBuf := make([]byte, uint32length) _, err := io.ReadFull(reader, lenBuf) if err != nil { - return nil, errors.Wrap(err, "error reading message length") + return nil, fmt.Errorf("error reading message length: %w", err) } msgLen := binary.LittleEndian.Uint32(lenBuf) msgBuf := make([]byte, msgLen) @@ -144,12 +145,12 @@ func (conn *tlsConn) read() (*memberlist.Packet, error) { conn.mtx.Unlock() if err != nil { - return nil, errors.Wrap(err, "error reading message") + return nil, fmt.Errorf("error reading message: %w", err) } pb := clusterpb.MemberlistMessage{} err = proto.Unmarshal(msgBuf, &pb) if err != nil { - return nil, errors.Wrap(err, "error parsing message") + return nil, fmt.Errorf("error parsing message: %w", err) } if pb.Version != version { return nil, errors.New("tls memberlist message version incompatible") @@ -167,7 +168,7 @@ func (conn *tlsConn) read() (*memberlist.Packet, error) { func toPacket(pb clusterpb.MemberlistMessage) (*memberlist.Packet, error) { addr, err := net.ResolveTCPAddr(network, pb.FromAddr) if err != nil { - return nil, errors.Wrap(err, "error parsing packet sender address") + return nil, fmt.Errorf("error parsing packet sender address: %w", err) } return &memberlist.Packet{ Buf: pb.Msg, diff --git a/vendor/github.com/prometheus/alertmanager/cluster/tls_transport.go b/vendor/github.com/prometheus/alertmanager/cluster/tls_transport.go index eb521e049d..7e39d6fed8 100644 --- a/vendor/github.com/prometheus/alertmanager/cluster/tls_transport.go +++ b/vendor/github.com/prometheus/alertmanager/cluster/tls_transport.go @@ -20,6 +20,7 @@ package cluster import ( "context" "crypto/tls" + "errors" "fmt" "net" "strings" @@ -29,7 +30,6 @@ import ( "github.com/go-kit/log/level" "github.com/hashicorp/go-sockaddr" "github.com/hashicorp/memberlist" - "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" common "github.com/prometheus/common/config" "github.com/prometheus/exporter-toolkit/web" @@ -83,12 +83,12 @@ func NewTLSTransport( tlsServerCfg, err := web.ConfigToTLSConfig(cfg.TLSServerConfig) if err != nil { - return nil, errors.Wrap(err, "invalid TLS server config") + return nil, fmt.Errorf("invalid TLS server config: %w", err) } tlsClientCfg, err := common.NewTLSConfig(cfg.TLSClientConfig) if err != nil { - return nil, errors.Wrap(err, "invalid TLS client config") + return nil, fmt.Errorf("invalid TLS client config: %w", err) } ip := net.ParseIP(bindAddr) @@ -99,12 +99,12 @@ func NewTLSTransport( addr := &net.TCPAddr{IP: ip, Port: bindPort} listener, err := tls.Listen(network, addr.String(), tlsServerCfg) if err != nil { - return nil, errors.Wrap(err, fmt.Sprintf("failed to start TLS listener on %q port %d", bindAddr, bindPort)) + return nil, fmt.Errorf("failed to start TLS listener on %q port %d: %w", bindAddr, bindPort, err) } connPool, err := newConnectionPool(tlsClientCfg) if err != nil { - return nil, errors.Wrap(err, "failed to initialize tls transport connection pool") + return nil, fmt.Errorf("failed to initialize tls transport connection pool: %w", err) } ctx, cancel := context.WithCancel(ctx) @@ -155,7 +155,7 @@ func (t *TLSTransport) FinalAdvertiseAddr(ip string, port int) (net.IP, int, err var err error ip, err = sockaddr.GetPrivateIP() if err != nil { - return nil, 0, fmt.Errorf("failed to get interface addresses: %v", err) + return nil, 0, fmt.Errorf("failed to get interface addresses: %w", err) } if ip == "" { return nil, 0, fmt.Errorf("no private IP address found, and explicit IP not provided") @@ -203,13 +203,13 @@ func (t *TLSTransport) WriteTo(b []byte, addr string) (time.Time, error) { conn, err := t.connPool.borrowConnection(addr, DefaultTCPTimeout) if err != nil { t.writeErrs.WithLabelValues("packet").Inc() - return time.Now(), errors.Wrap(err, "failed to dial") + return time.Now(), fmt.Errorf("failed to dial: %w", err) } fromAddr := t.listener.Addr().String() err = conn.writePacket(fromAddr, b) if err != nil { t.writeErrs.WithLabelValues("packet").Inc() - return time.Now(), errors.Wrap(err, "failed to write packet") + return time.Now(), fmt.Errorf("failed to write packet: %w", err) } t.packetsSent.Add(float64(len(b))) return time.Now(), nil @@ -221,13 +221,13 @@ func (t *TLSTransport) DialTimeout(addr string, timeout time.Duration) (net.Conn conn, err := dialTLSConn(addr, timeout, t.tlsClientCfg) if err != nil { t.writeErrs.WithLabelValues("stream").Inc() - return nil, errors.Wrap(err, "failed to dial") + return nil, fmt.Errorf("failed to dial: %w", err) } err = conn.writeStream() netConn := conn.getRawConn() if err != nil { t.writeErrs.WithLabelValues("stream").Inc() - return netConn, errors.Wrap(err, "failed to create stream connection") + return netConn, fmt.Errorf("failed to create stream connection: %w", err) } t.streamsSent.Inc() return netConn, nil diff --git a/vendor/github.com/prometheus/alertmanager/config/config.go b/vendor/github.com/prometheus/alertmanager/config/config.go index ae5f786ee8..7f3602e066 100644 --- a/vendor/github.com/prometheus/alertmanager/config/config.go +++ b/vendor/github.com/prometheus/alertmanager/config/config.go @@ -15,6 +15,7 @@ package config import ( "encoding/json" + "errors" "fmt" "net" "net/url" @@ -25,11 +26,11 @@ import ( "strings" "time" - "github.com/pkg/errors" commoncfg "github.com/prometheus/common/config" "github.com/prometheus/common/model" "gopkg.in/yaml.v2" + "github.com/prometheus/alertmanager/matchers/compat" "github.com/prometheus/alertmanager/pkg/labels" "github.com/prometheus/alertmanager/timeinterval" ) @@ -688,7 +689,7 @@ func (hp *HostPort) UnmarshalYAML(unmarshal func(interface{}) error) error { return err } if hp.Port == "" { - return errors.Errorf("address %q: port cannot be empty", s) + return fmt.Errorf("address %q: port cannot be empty", s) } return nil } @@ -710,7 +711,7 @@ func (hp *HostPort) UnmarshalJSON(data []byte) error { return err } if hp.Port == "" { - return errors.Errorf("address %q: port cannot be empty", s) + return fmt.Errorf("address %q: port cannot be empty", s) } return nil } @@ -813,7 +814,7 @@ func (r *Route) UnmarshalYAML(unmarshal func(interface{}) error) error { r.GroupByAll = true } else { labelName := model.LabelName(l) - if !labelName.IsValid() { + if !compat.IsValidLabelName(labelName) { return fmt.Errorf("invalid label name %q in group_by list", l) } r.GroupBy = append(r.GroupBy, labelName) @@ -907,7 +908,7 @@ type Receiver struct { SNSConfigs []*SNSConfig `yaml:"sns_configs,omitempty" json:"sns_configs,omitempty"` TelegramConfigs []*TelegramConfig `yaml:"telegram_configs,omitempty" json:"telegram_configs,omitempty"` WebexConfigs []*WebexConfig `yaml:"webex_configs,omitempty" json:"webex_configs,omitempty"` - MSTeamsConfigs []*MSTeamsConfig `yaml:"msteams_configs,omitempty" json:"teams_configs,omitempty"` + MSTeamsConfigs []*MSTeamsConfig `yaml:"msteams_configs,omitempty" json:"msteams_configs,omitempty"` } // UnmarshalYAML implements the yaml.Unmarshaler interface for Receiver. @@ -1005,7 +1006,7 @@ func (m *Matchers) UnmarshalYAML(unmarshal func(interface{}) error) error { return err } for _, line := range lines { - pm, err := labels.ParseMatchers(line) + pm, err := compat.Matchers(line, "config") if err != nil { return err } @@ -1031,7 +1032,7 @@ func (m *Matchers) UnmarshalJSON(data []byte) error { return err } for _, line := range lines { - pm, err := labels.ParseMatchers(line) + pm, err := compat.Matchers(line, "config") if err != nil { return err } diff --git a/vendor/github.com/prometheus/alertmanager/config/notifiers.go b/vendor/github.com/prometheus/alertmanager/config/notifiers.go index 0da9e27ba2..d79c8b5057 100644 --- a/vendor/github.com/prometheus/alertmanager/config/notifiers.go +++ b/vendor/github.com/prometheus/alertmanager/config/notifiers.go @@ -21,7 +21,6 @@ import ( "text/template" "time" - "github.com/pkg/errors" commoncfg "github.com/prometheus/common/config" "github.com/prometheus/common/sigv4" ) @@ -169,8 +168,9 @@ var ( NotifierConfig: NotifierConfig{ VSendResolved: true, }, - Title: `{{ template "msteams.default.title" . }}`, - Text: `{{ template "msteams.default.text" . }}`, + Title: `{{ template "msteams.default.title" . }}`, + Summary: `{{ template "msteams.default.summary" . }}`, + Text: `{{ template "msteams.default.text" . }}`, } ) @@ -216,8 +216,9 @@ func (c *WebexConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { type DiscordConfig struct { NotifierConfig `yaml:",inline" json:",inline"` - HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"` - WebhookURL *SecretURL `yaml:"webhook_url,omitempty" json:"webhook_url,omitempty"` + HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"` + WebhookURL *SecretURL `yaml:"webhook_url,omitempty" json:"webhook_url,omitempty"` + WebhookURLFile string `yaml:"webhook_url_file,omitempty" json:"webhook_url_file,omitempty"` Title string `yaml:"title,omitempty" json:"title,omitempty"` Message string `yaml:"message,omitempty" json:"message,omitempty"` @@ -227,7 +228,19 @@ type DiscordConfig struct { func (c *DiscordConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { *c = DefaultDiscordConfig type plain DiscordConfig - return unmarshal((*plain)(c)) + if err := unmarshal((*plain)(c)); err != nil { + return err + } + + if c.WebhookURL == nil && c.WebhookURLFile == "" { + return fmt.Errorf("one of webhook_url or webhook_url_file must be configured") + } + + if c.WebhookURL != nil && len(c.WebhookURLFile) > 0 { + return fmt.Errorf("at most one of webhook_url & webhook_url_file must be configured") + } + + return nil } // EmailConfig configures notifications via mail. @@ -503,11 +516,6 @@ func (c *WebhookConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { if c.URL != nil && c.URLFile != "" { return fmt.Errorf("at most one of url & url_file must be configured") } - if c.URL != nil { - if c.URL.Scheme != "https" && c.URL.Scheme != "http" { - return fmt.Errorf("scheme required for webhook url") - } - } return nil } @@ -545,7 +553,7 @@ func (c *WechatConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { } if !wechatTypeMatcher.MatchString(c.MessageType) { - return errors.Errorf("weChat message type %q does not match valid options %s", c.MessageType, wechatValidTypesRe) + return fmt.Errorf("weChat message type %q does not match valid options %s", c.MessageType, wechatValidTypesRe) } return nil @@ -591,18 +599,18 @@ func (c *OpsGenieConfig) UnmarshalYAML(unmarshal func(interface{}) error) error for _, r := range c.Responders { if r.ID == "" && r.Username == "" && r.Name == "" { - return errors.Errorf("opsGenieConfig responder %v has to have at least one of id, username or name specified", r) + return fmt.Errorf("opsGenieConfig responder %v has to have at least one of id, username or name specified", r) } if strings.Contains(r.Type, "{{") { _, err := template.New("").Parse(r.Type) if err != nil { - return errors.Errorf("opsGenieConfig responder %v type is not a valid template: %v", r, err) + return fmt.Errorf("opsGenieConfig responder %v type is not a valid template: %w", r, err) } } else { r.Type = strings.ToLower(r.Type) if !opsgenieTypeMatcher.MatchString(r.Type) { - return errors.Errorf("opsGenieConfig responder %v type does not match valid options %s", r, opsgenieValidTypesRe) + return fmt.Errorf("opsGenieConfig responder %v type does not match valid options %s", r, opsgenieValidTypesRe) } } } @@ -694,6 +702,7 @@ type PushoverConfig struct { Priority string `yaml:"priority,omitempty" json:"priority,omitempty"` Retry duration `yaml:"retry,omitempty" json:"retry,omitempty"` Expire duration `yaml:"expire,omitempty" json:"expire,omitempty"` + TTL duration `yaml:"ttl,omitempty" json:"ttl,omitempty"` HTML bool `yaml:"html" json:"html,omitempty"` } @@ -791,13 +800,27 @@ type MSTeamsConfig struct { NotifierConfig `yaml:",inline" json:",inline"` HTTPConfig *commoncfg.HTTPClientConfig `yaml:"http_config,omitempty" json:"http_config,omitempty"` WebhookURL *SecretURL `yaml:"webhook_url,omitempty" json:"webhook_url,omitempty"` + WebhookURLFile string `yaml:"webhook_url_file,omitempty" json:"webhook_url_file,omitempty"` - Title string `yaml:"title,omitempty" json:"title,omitempty"` - Text string `yaml:"text,omitempty" json:"text,omitempty"` + Title string `yaml:"title,omitempty" json:"title,omitempty"` + Summary string `yaml:"summary,omitempty" json:"summary,omitempty"` + Text string `yaml:"text,omitempty" json:"text,omitempty"` } func (c *MSTeamsConfig) UnmarshalYAML(unmarshal func(interface{}) error) error { *c = DefaultMSTeamsConfig type plain MSTeamsConfig - return unmarshal((*plain)(c)) + if err := unmarshal((*plain)(c)); err != nil { + return err + } + + if c.WebhookURL == nil && c.WebhookURLFile == "" { + return fmt.Errorf("one of webhook_url or webhook_url_file must be configured") + } + + if c.WebhookURL != nil && len(c.WebhookURLFile) > 0 { + return fmt.Errorf("at most one of webhook_url & webhook_url_file must be configured") + } + + return nil } diff --git a/vendor/github.com/prometheus/alertmanager/dispatch/dispatch.go b/vendor/github.com/prometheus/alertmanager/dispatch/dispatch.go index 853d849688..640b22abe2 100644 --- a/vendor/github.com/prometheus/alertmanager/dispatch/dispatch.go +++ b/vendor/github.com/prometheus/alertmanager/dispatch/dispatch.go @@ -15,6 +15,7 @@ package dispatch import ( "context" + "errors" "fmt" "sort" "sync" @@ -343,7 +344,7 @@ func (d *Dispatcher) processAlert(alert *types.Alert, route *Route) { _, _, err := d.stage.Exec(ctx, d.logger, alerts...) if err != nil { lvl := level.Error(d.logger) - if ctx.Err() == context.Canceled { + if errors.Is(ctx.Err(), context.Canceled) { // It is expected for the context to be canceled on // configuration reload or shutdown. In this case, the // message should only be logged at the debug level. diff --git a/vendor/github.com/prometheus/alertmanager/dispatch/route.go b/vendor/github.com/prometheus/alertmanager/dispatch/route.go index 4b3673c531..5ada178dab 100644 --- a/vendor/github.com/prometheus/alertmanager/dispatch/route.go +++ b/vendor/github.com/prometheus/alertmanager/dispatch/route.go @@ -180,6 +180,29 @@ func (r *Route) Key() string { return b.String() } +// ID returns a unique identifier for the route. +func (r *Route) ID() string { + b := strings.Builder{} + + position := -1 + if r.parent != nil { + // Find the position in the same level leaf. + for i, cr := range r.parent.Routes { + if cr == r { + position = i + break + } + } + } + b.WriteString(r.Key()) + + if position > -1 { + b.WriteRune('/') + b.WriteString(fmt.Sprint(position)) + } + return b.String() +} + // Walk traverses the route tree in depth-first order. func (r *Route) Walk(visit func(*Route)) { visit(r) diff --git a/vendor/github.com/prometheus/alertmanager/featurecontrol/featurecontrol.go b/vendor/github.com/prometheus/alertmanager/featurecontrol/featurecontrol.go new file mode 100644 index 0000000000..9ff7a2d8fd --- /dev/null +++ b/vendor/github.com/prometheus/alertmanager/featurecontrol/featurecontrol.go @@ -0,0 +1,123 @@ +// Copyright 2023 Prometheus Team +// 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 featurecontrol + +import ( + "errors" + "fmt" + "strings" + + "github.com/go-kit/log" + "github.com/go-kit/log/level" +) + +const ( + FeatureReceiverNameInMetrics = "receiver-name-in-metrics" + FeatureClassicMode = "classic-mode" + FeatureUTF8StrictMode = "utf8-strict-mode" +) + +var AllowedFlags = []string{ + FeatureReceiverNameInMetrics, + FeatureClassicMode, + FeatureUTF8StrictMode, +} + +type Flagger interface { + EnableReceiverNamesInMetrics() bool + ClassicMode() bool + UTF8StrictMode() bool +} + +type Flags struct { + logger log.Logger + enableReceiverNamesInMetrics bool + classicMode bool + utf8StrictMode bool +} + +func (f *Flags) EnableReceiverNamesInMetrics() bool { + return f.enableReceiverNamesInMetrics +} + +func (f *Flags) ClassicMode() bool { + return f.classicMode +} + +func (f *Flags) UTF8StrictMode() bool { + return f.utf8StrictMode +} + +type flagOption func(flags *Flags) + +func enableReceiverNameInMetrics() flagOption { + return func(configs *Flags) { + configs.enableReceiverNamesInMetrics = true + } +} + +func enableClassicMode() flagOption { + return func(configs *Flags) { + configs.classicMode = true + } +} + +func enableUTF8StrictMode() flagOption { + return func(configs *Flags) { + configs.utf8StrictMode = true + } +} + +func NewFlags(logger log.Logger, features string) (Flagger, error) { + fc := &Flags{logger: logger} + opts := []flagOption{} + + if len(features) == 0 { + return NoopFlags{}, nil + } + + for _, feature := range strings.Split(features, ",") { + switch feature { + case FeatureReceiverNameInMetrics: + opts = append(opts, enableReceiverNameInMetrics()) + level.Warn(logger).Log("msg", "Experimental receiver name in metrics enabled") + case FeatureClassicMode: + opts = append(opts, enableClassicMode()) + level.Warn(logger).Log("msg", "Classic mode enabled") + case FeatureUTF8StrictMode: + opts = append(opts, enableUTF8StrictMode()) + level.Warn(logger).Log("msg", "UTF-8 strict mode enabled") + default: + return nil, fmt.Errorf("Unknown option '%s' for --enable-feature", feature) + } + } + + for _, opt := range opts { + opt(fc) + } + + if fc.classicMode && fc.utf8StrictMode { + return nil, errors.New("cannot have both classic and UTF-8 modes enabled") + } + + return fc, nil +} + +type NoopFlags struct{} + +func (n NoopFlags) EnableReceiverNamesInMetrics() bool { return false } + +func (n NoopFlags) ClassicMode() bool { return false } + +func (n NoopFlags) UTF8StrictMode() bool { return false } diff --git a/vendor/github.com/prometheus/alertmanager/matchers/compat/parse.go b/vendor/github.com/prometheus/alertmanager/matchers/compat/parse.go new file mode 100644 index 0000000000..0c0dfffb1f --- /dev/null +++ b/vendor/github.com/prometheus/alertmanager/matchers/compat/parse.go @@ -0,0 +1,205 @@ +// Copyright 2023 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 compat + +import ( + "fmt" + "reflect" + "strings" + "unicode/utf8" + + "github.com/go-kit/log" + "github.com/go-kit/log/level" + "github.com/prometheus/common/model" + + "github.com/prometheus/alertmanager/featurecontrol" + "github.com/prometheus/alertmanager/matchers/parse" + "github.com/prometheus/alertmanager/pkg/labels" +) + +var ( + isValidLabelName = isValidClassicLabelName(log.NewNopLogger()) + parseMatcher = ClassicMatcherParser(log.NewNopLogger()) + parseMatchers = ClassicMatchersParser(log.NewNopLogger()) +) + +// IsValidLabelName returns true if the string is a valid label name. +func IsValidLabelName(name model.LabelName) bool { + return isValidLabelName(name) +} + +type ParseMatcher func(input, origin string) (*labels.Matcher, error) + +type ParseMatchers func(input, origin string) (labels.Matchers, error) + +// Matcher parses the matcher in the input string. It returns an error +// if the input is invalid or contains two or more matchers. +func Matcher(input, origin string) (*labels.Matcher, error) { + return parseMatcher(input, origin) +} + +// Matchers parses one or more matchers in the input string. It returns +// an error if the input is invalid. +func Matchers(input, origin string) (labels.Matchers, error) { + return parseMatchers(input, origin) +} + +// InitFromFlags initializes the compat package from the flagger. +func InitFromFlags(l log.Logger, f featurecontrol.Flagger) { + if f.ClassicMode() { + isValidLabelName = isValidClassicLabelName(l) + parseMatcher = ClassicMatcherParser(l) + parseMatchers = ClassicMatchersParser(l) + } else if f.UTF8StrictMode() { + isValidLabelName = isValidUTF8LabelName(l) + parseMatcher = UTF8MatcherParser(l) + parseMatchers = UTF8MatchersParser(l) + } else { + isValidLabelName = isValidUTF8LabelName(l) + parseMatcher = FallbackMatcherParser(l) + parseMatchers = FallbackMatchersParser(l) + } +} + +// ClassicMatcherParser uses the pkg/labels parser to parse the matcher in +// the input string. +func ClassicMatcherParser(l log.Logger) ParseMatcher { + return func(input, origin string) (matcher *labels.Matcher, err error) { + level.Debug(l).Log("msg", "Parsing with classic matchers parser", "input", input, "origin", origin) + return labels.ParseMatcher(input) + } +} + +// ClassicMatchersParser uses the pkg/labels parser to parse zero or more +// matchers in the input string. It returns an error if the input is invalid. +func ClassicMatchersParser(l log.Logger) ParseMatchers { + return func(input, origin string) (matchers labels.Matchers, err error) { + level.Debug(l).Log("msg", "Parsing with classic matchers parser", "input", input, "origin", origin) + return labels.ParseMatchers(input) + } +} + +// UTF8MatcherParser uses the new matchers/parse parser to parse the matcher +// in the input string. If this fails it does not revert to the pkg/labels parser. +func UTF8MatcherParser(l log.Logger) ParseMatcher { + return func(input, origin string) (matcher *labels.Matcher, err error) { + level.Debug(l).Log("msg", "Parsing with UTF-8 matchers parser", "input", input, "origin", origin) + if strings.HasPrefix(input, "{") || strings.HasSuffix(input, "}") { + return nil, fmt.Errorf("unexpected open or close brace: %s", input) + } + return parse.Matcher(input) + } +} + +// UTF8MatchersParser uses the new matchers/parse parser to parse zero or more +// matchers in the input string. If this fails it does not revert to the +// pkg/labels parser. +func UTF8MatchersParser(l log.Logger) ParseMatchers { + return func(input, origin string) (matchers labels.Matchers, err error) { + level.Debug(l).Log("msg", "Parsing with UTF-8 matchers parser", "input", input, "origin", origin) + return parse.Matchers(input) + } +} + +// FallbackMatcherParser uses the new matchers/parse parser to parse zero or more +// matchers in the string. If this fails it reverts to the pkg/labels parser and +// emits a warning log line. +func FallbackMatcherParser(l log.Logger) ParseMatcher { + return func(input, origin string) (matcher *labels.Matcher, err error) { + level.Debug(l).Log("msg", "Parsing with UTF-8 matchers parser, with fallback to classic matchers parser", "input", input, "origin", origin) + if strings.HasPrefix(input, "{") || strings.HasSuffix(input, "}") { + return nil, fmt.Errorf("unexpected open or close brace: %s", input) + } + // Parse the input in both parsers to look for disagreement and incompatible + // inputs. + nMatcher, nErr := parse.Matcher(input) + cMatcher, cErr := labels.ParseMatcher(input) + if nErr != nil { + // If the input is invalid in both parsers, return the error. + if cErr != nil { + return nil, cErr + } + // The input is valid in the pkg/labels parser, but not the matchers/parse + // parser. This means the input is not forwards compatible. + suggestion := cMatcher.String() + level.Warn(l).Log("msg", "Alertmanager is moving to a new parser for labels and matchers, and this input is incompatible. Alertmanager has instead parsed the input using the classic matchers parser as a fallback. To make this input compatible with the UTF-8 matchers parser please make sure all regular expressions and values are double-quoted. If you are still seeing this message please open an issue.", "input", input, "origin", origin, "err", nErr, "suggestion", suggestion) + return cMatcher, nil + } + // If the input is valid in both parsers, but produces different results, + // then there is disagreement. + if nErr == nil && cErr == nil && !reflect.DeepEqual(nMatcher, cMatcher) { + level.Warn(l).Log("msg", "Matchers input has disagreement", "input", input, "origin", origin) + return cMatcher, nil + } + return nMatcher, nil + } +} + +// FallbackMatchersParser uses the new matchers/parse parser to parse the +// matcher in the input string. If this fails it falls back to the pkg/labels +// parser and emits a warning log line. +func FallbackMatchersParser(l log.Logger) ParseMatchers { + return func(input, origin string) (matchers labels.Matchers, err error) { + level.Debug(l).Log("msg", "Parsing with UTF-8 matchers parser, with fallback to classic matchers parser", "input", input, "origin", origin) + // Parse the input in both parsers to look for disagreement and incompatible + // inputs. + nMatchers, nErr := parse.Matchers(input) + cMatchers, cErr := labels.ParseMatchers(input) + if nErr != nil { + // If the input is invalid in both parsers, return the error. + if cErr != nil { + return nil, cErr + } + // The input is valid in the pkg/labels parser, but not the matchers/parse + // parser. This means the input is not forwards compatible. + var sb strings.Builder + for i, n := range cMatchers { + sb.WriteString(n.String()) + if i < len(cMatchers)-1 { + sb.WriteRune(',') + } + } + suggestion := sb.String() + // The input is valid in the pkg/labels parser, but not the + // new matchers/parse parser. + level.Warn(l).Log("msg", "Alertmanager is moving to a new parser for labels and matchers, and this input is incompatible. Alertmanager has instead parsed the input using the classic matchers parser as a fallback. To make this input compatible with the UTF-8 matchers parser please make sure all regular expressions and values are double-quoted. If you are still seeing this message please open an issue.", "input", input, "origin", origin, "err", nErr, "suggestion", suggestion) + return cMatchers, nil + } + // If the input is valid in both parsers, but produces different results, + // then there is disagreement. We need to compare to labels.Matchers(cMatchers) + // as cMatchers is a []*labels.Matcher not labels.Matchers. + if nErr == nil && cErr == nil && !reflect.DeepEqual(nMatchers, labels.Matchers(cMatchers)) { + level.Warn(l).Log("msg", "Matchers input has disagreement", "input", input, "origin", origin) + return cMatchers, nil + } + return nMatchers, nil + } +} + +// isValidClassicLabelName returns true if the string is a valid classic label name. +func isValidClassicLabelName(_ log.Logger) func(model.LabelName) bool { + return func(name model.LabelName) bool { + return name.IsValid() + } +} + +// isValidUTF8LabelName returns true if the string is a valid UTF-8 label name. +func isValidUTF8LabelName(_ log.Logger) func(model.LabelName) bool { + return func(name model.LabelName) bool { + if len(name) == 0 { + return false + } + return utf8.ValidString(string(name)) + } +} diff --git a/vendor/github.com/prometheus/alertmanager/matchers/parse/lexer.go b/vendor/github.com/prometheus/alertmanager/matchers/parse/lexer.go new file mode 100644 index 0000000000..d6daa6a9e8 --- /dev/null +++ b/vendor/github.com/prometheus/alertmanager/matchers/parse/lexer.go @@ -0,0 +1,309 @@ +// Copyright 2023 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 parse + +import ( + "fmt" + "strings" + "unicode" + "unicode/utf8" +) + +const ( + eof rune = -1 +) + +func isReserved(r rune) bool { + return unicode.IsSpace(r) || strings.ContainsRune("{}!=~,\\\"'`", r) +} + +// expectedError is returned when the next rune does not match what is expected. +type expectedError struct { + position + input string + expected string +} + +func (e expectedError) Error() string { + if e.offsetEnd >= len(e.input) { + return fmt.Sprintf("%d:%d: unexpected end of input, expected one of '%s'", + e.columnStart, + e.columnEnd, + e.expected, + ) + } + return fmt.Sprintf("%d:%d: %s: expected one of '%s'", + e.columnStart, + e.columnEnd, + e.input[e.offsetStart:e.offsetEnd], + e.expected, + ) +} + +// invalidInputError is returned when the next rune in the input does not match +// the grammar of Prometheus-like matchers. +type invalidInputError struct { + position + input string +} + +func (e invalidInputError) Error() string { + return fmt.Sprintf("%d:%d: %s: invalid input", + e.columnStart, + e.columnEnd, + e.input[e.offsetStart:e.offsetEnd], + ) +} + +// unterminatedError is returned when text in quotes does not have a closing quote. +type unterminatedError struct { + position + input string + quote rune +} + +func (e unterminatedError) Error() string { + return fmt.Sprintf("%d:%d: %s: missing end %c", + e.columnStart, + e.columnEnd, + e.input[e.offsetStart:e.offsetEnd], + e.quote, + ) +} + +// lexer scans a sequence of tokens that match the grammar of Prometheus-like +// matchers. A token is emitted for each call to scan() which returns the +// next token in the input or an error if the input does not conform to the +// grammar. A token can be one of a number of kinds and corresponds to a +// subslice of the input. Once the input has been consumed successive calls to +// scan() return a tokenEOF token. +type lexer struct { + input string + err error + start int // The offset of the current token. + pos int // The position of the cursor in the input. + width int // The width of the last rune. + column int // The column offset of the current token. + cols int // The number of columns (runes) decoded from the input. +} + +// Scans the next token in the input or an error if the input does not +// conform to the grammar. Once the input has been consumed successive +// calls scan() return a tokenEOF token. +func (l *lexer) scan() (token, error) { + t := token{} + // Do not attempt to emit more tokens if the input is invalid. + if l.err != nil { + return t, l.err + } + // Iterate over each rune in the input and either emit a token or an error. + for r := l.next(); r != eof; r = l.next() { + switch { + case r == '{': + t = l.emit(tokenOpenBrace) + return t, l.err + case r == '}': + t = l.emit(tokenCloseBrace) + return t, l.err + case r == ',': + t = l.emit(tokenComma) + return t, l.err + case r == '=' || r == '!': + l.rewind() + t, l.err = l.scanOperator() + return t, l.err + case r == '"': + l.rewind() + t, l.err = l.scanQuoted() + return t, l.err + case !isReserved(r): + l.rewind() + t, l.err = l.scanUnquoted() + return t, l.err + case unicode.IsSpace(r): + l.skip() + default: + l.err = invalidInputError{ + position: l.position(), + input: l.input, + } + return t, l.err + } + } + return t, l.err +} + +func (l *lexer) scanOperator() (token, error) { + // If the first rune is an '!' then it must be followed with either an + // '=' or '~' to not match a string or regex. + if l.accept("!") { + if l.accept("=") { + return l.emit(tokenNotEquals), nil + } + if l.accept("~") { + return l.emit(tokenNotMatches), nil + } + return token{}, expectedError{ + position: l.position(), + input: l.input, + expected: "=~", + } + } + // If the first rune is an '=' then it can be followed with an optional + // '~' to match a regex. + if l.accept("=") { + if l.accept("~") { + return l.emit(tokenMatches), nil + } + return l.emit(tokenEquals), nil + } + return token{}, expectedError{ + position: l.position(), + input: l.input, + expected: "!=", + } +} + +func (l *lexer) scanQuoted() (token, error) { + if err := l.expect("\""); err != nil { + return token{}, err + } + var isEscaped bool + for r := l.next(); r != eof; r = l.next() { + if isEscaped { + isEscaped = false + } else if r == '\\' { + isEscaped = true + } else if r == '"' { + l.rewind() + break + } + } + if err := l.expect("\""); err != nil { + return token{}, unterminatedError{ + position: l.position(), + input: l.input, + quote: '"', + } + } + return l.emit(tokenQuoted), nil +} + +func (l *lexer) scanUnquoted() (token, error) { + for r := l.next(); r != eof; r = l.next() { + if isReserved(r) { + l.rewind() + break + } + } + return l.emit(tokenUnquoted), nil +} + +// peek the next token in the input or an error if the input does not +// conform to the grammar. Once the input has been consumed successive +// calls peek() return a tokenEOF token. +func (l *lexer) peek() (token, error) { + start := l.start + pos := l.pos + width := l.width + column := l.column + cols := l.cols + // Do not reset l.err because we can return it on the next call to scan(). + defer func() { + l.start = start + l.pos = pos + l.width = width + l.column = column + l.cols = cols + }() + return l.scan() +} + +// position returns the position of the last emitted token. +func (l *lexer) position() position { + return position{ + offsetStart: l.start, + offsetEnd: l.pos, + columnStart: l.column, + columnEnd: l.cols, + } +} + +// accept consumes the next if its one of the valid runes. +// It returns true if the next rune was accepted, otherwise false. +func (l *lexer) accept(valid string) bool { + if strings.ContainsRune(valid, l.next()) { + return true + } + l.rewind() + return false +} + +// expect consumes the next rune if its one of the valid runes. +// it returns nil if the next rune is valid, otherwise an expectedError +// error. +func (l *lexer) expect(valid string) error { + if strings.ContainsRune(valid, l.next()) { + return nil + } + l.rewind() + return expectedError{ + position: l.position(), + input: l.input, + expected: valid, + } +} + +// emits returns the scanned input as a token. +func (l *lexer) emit(kind tokenKind) token { + t := token{ + kind: kind, + value: l.input[l.start:l.pos], + position: l.position(), + } + l.start = l.pos + l.column = l.cols + return t +} + +// next returns the next rune in the input or eof. +func (l *lexer) next() rune { + if l.pos >= len(l.input) { + l.width = 0 + return eof + } + r, width := utf8.DecodeRuneInString(l.input[l.pos:]) + l.width = width + l.pos += width + l.cols++ + return r +} + +// rewind the last rune in the input. It should not be called more than once +// between consecutive calls of next. +func (l *lexer) rewind() { + l.pos -= l.width + // When the next rune in the input is eof the width is zero. This check + // prevents cols from being decremented when the next rune being accepted + // is instead eof. + if l.width > 0 { + l.cols-- + } +} + +// skip the scanned input between start and pos. +func (l *lexer) skip() { + l.start = l.pos + l.column = l.cols +} diff --git a/vendor/github.com/prometheus/alertmanager/matchers/parse/parse.go b/vendor/github.com/prometheus/alertmanager/matchers/parse/parse.go new file mode 100644 index 0000000000..30a95b2554 --- /dev/null +++ b/vendor/github.com/prometheus/alertmanager/matchers/parse/parse.go @@ -0,0 +1,304 @@ +// Copyright 2023 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 parse + +import ( + "errors" + "fmt" + "os" + "runtime/debug" + + "github.com/prometheus/alertmanager/pkg/labels" +) + +var ( + errEOF = errors.New("end of input") + errExpectedEOF = errors.New("expected end of input") + errNoOpenBrace = errors.New("expected opening brace") + errNoCloseBrace = errors.New("expected close brace") + errNoLabelName = errors.New("expected label name") + errNoLabelValue = errors.New("expected label value") + errNoOperator = errors.New("expected an operator such as '=', '!=', '=~' or '!~'") + errExpectedComma = errors.New("expected a comma") + errExpectedCommaOrCloseBrace = errors.New("expected a comma or close brace") + errExpectedMatcherOrCloseBrace = errors.New("expected a matcher or close brace after comma") +) + +// Matchers parses one or more matchers in the input string. It returns an error +// if the input is invalid. +func Matchers(input string) (matchers labels.Matchers, err error) { + defer func() { + if r := recover(); r != nil { + fmt.Fprintf(os.Stderr, "parser panic: %s, %s", r, debug.Stack()) + err = errors.New("parser panic: this should never happen, check stderr for the stack trace") + } + }() + p := parser{lexer: lexer{input: input}} + return p.parse() +} + +// Matcher parses the matcher in the input string. It returns an error +// if the input is invalid or contains two or more matchers. +func Matcher(input string) (*labels.Matcher, error) { + m, err := Matchers(input) + if err != nil { + return nil, err + } + switch len(m) { + case 1: + return m[0], nil + case 0: + return nil, fmt.Errorf("no matchers") + default: + return nil, fmt.Errorf("expected 1 matcher, found %d", len(m)) + } +} + +// parseFunc is state in the finite state automata. +type parseFunc func(l *lexer) (parseFunc, error) + +// parser reads the sequence of tokens from the lexer and returns either a +// series of matchers or an error. It works as a finite state automata, where +// each state in the automata is a parseFunc. The finite state automata can move +// from one state to another by returning the next parseFunc. It terminates when +// a parseFunc returns nil as the next parseFunc, if the lexer attempts to scan +// input that does not match the expected grammar, or if the tokens returned from +// the lexer cannot be parsed into a complete series of matchers. +type parser struct { + matchers labels.Matchers + // Tracks if the input starts with an open brace and if we should expect to + // parse a close brace at the end of the input. + hasOpenBrace bool + lexer lexer +} + +func (p *parser) parse() (labels.Matchers, error) { + var ( + err error + fn = p.parseOpenBrace + l = &p.lexer + ) + for { + if fn, err = fn(l); err != nil { + return nil, err + } else if fn == nil { + break + } + } + return p.matchers, nil +} + +func (p *parser) parseOpenBrace(l *lexer) (parseFunc, error) { + var ( + hasCloseBrace bool + err error + ) + // Can start with an optional open brace. + p.hasOpenBrace, err = p.accept(l, tokenOpenBrace) + if err != nil { + if errors.Is(err, errEOF) { + return p.parseEOF, nil + } + return nil, err + } + // If the next token is a close brace there are no matchers in the input. + hasCloseBrace, err = p.acceptPeek(l, tokenCloseBrace) + if err != nil { + // If there is no more input after the open brace then parse the close brace + // so the error message contains ErrNoCloseBrace. + if errors.Is(err, errEOF) { + return p.parseCloseBrace, nil + } + return nil, err + } + if hasCloseBrace { + return p.parseCloseBrace, nil + } + return p.parseMatcher, nil +} + +func (p *parser) parseCloseBrace(l *lexer) (parseFunc, error) { + if p.hasOpenBrace { + // If there was an open brace there must be a matching close brace. + if _, err := p.expect(l, tokenCloseBrace); err != nil { + return nil, fmt.Errorf("0:%d: %w: %w", l.position().columnEnd, err, errNoCloseBrace) + } + } else { + // If there was no open brace there must not be a close brace either. + if _, err := p.expect(l, tokenCloseBrace); err == nil { + return nil, fmt.Errorf("0:%d: }: %w", l.position().columnEnd, errNoOpenBrace) + } + } + return p.parseEOF, nil +} + +func (p *parser) parseMatcher(l *lexer) (parseFunc, error) { + var ( + err error + t token + matchName, matchValue string + matchTy labels.MatchType + ) + // The first token should be the label name. + if t, err = p.expect(l, tokenQuoted, tokenUnquoted); err != nil { + return nil, fmt.Errorf("%w: %w", err, errNoLabelName) + } + matchName, err = t.unquote() + if err != nil { + return nil, fmt.Errorf("%d:%d: %s: invalid input", t.columnStart, t.columnEnd, t.value) + } + // The next token should be the operator. + if t, err = p.expect(l, tokenEquals, tokenNotEquals, tokenMatches, tokenNotMatches); err != nil { + return nil, fmt.Errorf("%w: %w", err, errNoOperator) + } + switch t.kind { + case tokenEquals: + matchTy = labels.MatchEqual + case tokenNotEquals: + matchTy = labels.MatchNotEqual + case tokenMatches: + matchTy = labels.MatchRegexp + case tokenNotMatches: + matchTy = labels.MatchNotRegexp + default: + panic(fmt.Sprintf("bad operator %s", t)) + } + // The next token should be the match value. Like the match name, this too + // can be either double-quoted UTF-8 or unquoted UTF-8 without reserved characters. + if t, err = p.expect(l, tokenUnquoted, tokenQuoted); err != nil { + return nil, fmt.Errorf("%w: %w", err, errNoLabelValue) + } + matchValue, err = t.unquote() + if err != nil { + return nil, fmt.Errorf("%d:%d: %s: invalid input", t.columnStart, t.columnEnd, t.value) + } + m, err := labels.NewMatcher(matchTy, matchName, matchValue) + if err != nil { + return nil, fmt.Errorf("failed to create matcher: %w", err) + } + p.matchers = append(p.matchers, m) + return p.parseEndOfMatcher, nil +} + +func (p *parser) parseEndOfMatcher(l *lexer) (parseFunc, error) { + t, err := p.expectPeek(l, tokenComma, tokenCloseBrace) + if err != nil { + if errors.Is(err, errEOF) { + // If this is the end of input we still need to check if the optional + // open brace has a matching close brace + return p.parseCloseBrace, nil + } + return nil, fmt.Errorf("%w: %w", err, errExpectedCommaOrCloseBrace) + } + switch t.kind { + case tokenComma: + return p.parseComma, nil + case tokenCloseBrace: + return p.parseCloseBrace, nil + default: + panic(fmt.Sprintf("bad token %s", t)) + } +} + +func (p *parser) parseComma(l *lexer) (parseFunc, error) { + if _, err := p.expect(l, tokenComma); err != nil { + return nil, fmt.Errorf("%w: %w", err, errExpectedComma) + } + // The token after the comma can be another matcher, a close brace or end of input. + t, err := p.expectPeek(l, tokenCloseBrace, tokenUnquoted, tokenQuoted) + if err != nil { + if errors.Is(err, errEOF) { + // If this is the end of input we still need to check if the optional + // open brace has a matching close brace + return p.parseCloseBrace, nil + } + return nil, fmt.Errorf("%w: %w", err, errExpectedMatcherOrCloseBrace) + } + if t.kind == tokenCloseBrace { + return p.parseCloseBrace, nil + } + return p.parseMatcher, nil +} + +func (p *parser) parseEOF(l *lexer) (parseFunc, error) { + t, err := l.scan() + if err != nil { + return nil, fmt.Errorf("%w: %w", err, errExpectedEOF) + } + if !t.isEOF() { + return nil, fmt.Errorf("%d:%d: %s: %w", t.columnStart, t.columnEnd, t.value, errExpectedEOF) + } + return nil, nil +} + +// accept returns true if the next token is one of the specified kinds, +// otherwise false. If the token is accepted it is consumed. tokenEOF is +// not an accepted kind and instead accept returns ErrEOF if there is no +// more input. +func (p *parser) accept(l *lexer, kinds ...tokenKind) (ok bool, err error) { + ok, err = p.acceptPeek(l, kinds...) + if ok { + if _, err = l.scan(); err != nil { + panic("failed to scan peeked token") + } + } + return ok, err +} + +// acceptPeek returns true if the next token is one of the specified kinds, +// otherwise false. However, unlike accept, acceptPeek does not consume accepted +// tokens. tokenEOF is not an accepted kind and instead accept returns ErrEOF +// if there is no more input. +func (p *parser) acceptPeek(l *lexer, kinds ...tokenKind) (bool, error) { + t, err := l.peek() + if err != nil { + return false, err + } + if t.isEOF() { + return false, errEOF + } + return t.isOneOf(kinds...), nil +} + +// expect returns the next token if it is one of the specified kinds, otherwise +// it returns an error. If the token is expected it is consumed. tokenEOF is not +// an accepted kind and instead expect returns ErrEOF if there is no more input. +func (p *parser) expect(l *lexer, kind ...tokenKind) (token, error) { + t, err := p.expectPeek(l, kind...) + if err != nil { + return t, err + } + if _, err = l.scan(); err != nil { + panic("failed to scan peeked token") + } + return t, nil +} + +// expect returns the next token if it is one of the specified kinds, otherwise +// it returns an error. However, unlike expect, expectPeek does not consume tokens. +// tokenEOF is not an accepted kind and instead expect returns ErrEOF if there is no +// more input. +func (p *parser) expectPeek(l *lexer, kind ...tokenKind) (token, error) { + t, err := l.peek() + if err != nil { + return t, err + } + if t.isEOF() { + return t, errEOF + } + if !t.isOneOf(kind...) { + return t, fmt.Errorf("%d:%d: unexpected %s", t.columnStart, t.columnEnd, t.value) + } + return t, nil +} diff --git a/vendor/github.com/prometheus/alertmanager/matchers/parse/token.go b/vendor/github.com/prometheus/alertmanager/matchers/parse/token.go new file mode 100644 index 0000000000..96baeeef43 --- /dev/null +++ b/vendor/github.com/prometheus/alertmanager/matchers/parse/token.go @@ -0,0 +1,108 @@ +// Copyright 2023 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 parse + +import ( + "errors" + "fmt" + "strconv" + "unicode/utf8" +) + +type tokenKind int + +const ( + tokenEOF tokenKind = iota + tokenOpenBrace + tokenCloseBrace + tokenComma + tokenEquals + tokenNotEquals + tokenMatches + tokenNotMatches + tokenQuoted + tokenUnquoted +) + +func (k tokenKind) String() string { + switch k { + case tokenOpenBrace: + return "OpenBrace" + case tokenCloseBrace: + return "CloseBrace" + case tokenComma: + return "Comma" + case tokenEquals: + return "Equals" + case tokenNotEquals: + return "NotEquals" + case tokenMatches: + return "Matches" + case tokenNotMatches: + return "NotMatches" + case tokenQuoted: + return "Quoted" + case tokenUnquoted: + return "Unquoted" + default: + return "EOF" + } +} + +type token struct { + kind tokenKind + value string + position +} + +// isEOF returns true if the token is an end of file token. +func (t token) isEOF() bool { + return t.kind == tokenEOF +} + +// isOneOf returns true if the token is one of the specified kinds. +func (t token) isOneOf(kinds ...tokenKind) bool { + for _, k := range kinds { + if k == t.kind { + return true + } + } + return false +} + +// unquote the value in token. If unquoted returns it unmodified. +func (t token) unquote() (string, error) { + if t.kind == tokenQuoted { + unquoted, err := strconv.Unquote(t.value) + if err != nil { + return "", err + } + if !utf8.ValidString(unquoted) { + return "", errors.New("quoted string contains invalid UTF-8 code points") + } + return unquoted, nil + } + return t.value, nil +} + +func (t token) String() string { + return fmt.Sprintf("(%s) '%s'", t.kind, t.value) +} + +type position struct { + offsetStart int // The start position in the input. + offsetEnd int // The end position in the input. + columnStart int // The column number. + columnEnd int // The end of the column. +} diff --git a/vendor/github.com/prometheus/alertmanager/nflog/nflog.go b/vendor/github.com/prometheus/alertmanager/nflog/nflog.go index c318cede80..c533dd0e66 100644 --- a/vendor/github.com/prometheus/alertmanager/nflog/nflog.go +++ b/vendor/github.com/prometheus/alertmanager/nflog/nflog.go @@ -212,7 +212,7 @@ func decodeState(r io.Reader) (state, error) { st[stateKey(string(e.Entry.GroupKey), e.Entry.Receiver)] = &e continue } - if err == io.EOF { + if errors.Is(err, io.EOF) { break } return nil, err diff --git a/vendor/github.com/prometheus/alertmanager/notify/discord/discord.go b/vendor/github.com/prometheus/alertmanager/notify/discord/discord.go index 31a0a7cfe7..69aff39957 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/discord/discord.go +++ b/vendor/github.com/prometheus/alertmanager/notify/discord/discord.go @@ -17,7 +17,10 @@ import ( "bytes" "context" "encoding/json" + "fmt" "net/http" + "os" + "strings" "github.com/go-kit/log" "github.com/go-kit/log/level" @@ -30,6 +33,13 @@ import ( "github.com/prometheus/alertmanager/types" ) +const ( + // https://discord.com/developers/docs/resources/channel#embed-object-embed-limits - 256 characters or runes. + maxTitleLenRunes = 256 + // https://discord.com/developers/docs/resources/channel#embed-object-embed-limits - 4096 characters or runes. + maxDescriptionLenRunes = 4096 +) + const ( colorRed = 0x992D22 colorGreen = 0x2ECC71 @@ -90,14 +100,20 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) return false, err } - title := tmpl(n.conf.Title) + title, truncated := notify.TruncateInRunes(tmpl(n.conf.Title), maxTitleLenRunes) if err != nil { return false, err } - description := tmpl(n.conf.Message) + if truncated { + level.Warn(n.logger).Log("msg", "Truncated title", "key", key, "max_runes", maxTitleLenRunes) + } + description, truncated := notify.TruncateInRunes(tmpl(n.conf.Message), maxDescriptionLenRunes) if err != nil { return false, err } + if truncated { + level.Warn(n.logger).Log("msg", "Truncated message", "key", key, "max_runes", maxDescriptionLenRunes) + } color := colorGrey if alerts.Status() == model.AlertFiring { @@ -107,6 +123,17 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) color = colorGreen } + var url string + if n.conf.WebhookURL != nil { + url = n.conf.WebhookURL.String() + } else { + content, err := os.ReadFile(n.conf.WebhookURLFile) + if err != nil { + return false, fmt.Errorf("read webhook_url_file: %w", err) + } + url = strings.TrimSpace(string(content)) + } + w := webhook{ Embeds: []webhookEmbed{{ Title: title, @@ -120,7 +147,7 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) return false, err } - resp, err := notify.PostJSON(ctx, n.client, n.webhookURL.String(), &payload) + resp, err := notify.PostJSON(ctx, n.client, url, &payload) if err != nil { return true, notify.RedactURL(err) } diff --git a/vendor/github.com/prometheus/alertmanager/notify/email/email.go b/vendor/github.com/prometheus/alertmanager/notify/email/email.go index 944aabdf85..d7e5be7bdc 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/email/email.go +++ b/vendor/github.com/prometheus/alertmanager/notify/email/email.go @@ -17,6 +17,7 @@ import ( "bytes" "context" "crypto/tls" + "errors" "fmt" "math/rand" "mime" @@ -32,7 +33,6 @@ import ( "github.com/go-kit/log" "github.com/go-kit/log/level" - "github.com/pkg/errors" commoncfg "github.com/prometheus/common/config" "github.com/prometheus/alertmanager/config" @@ -133,7 +133,7 @@ func (n *Email) Notify(ctx context.Context, as ...*types.Alert) (bool, error) { if n.conf.Smarthost.Port == "465" { tlsConfig, err := commoncfg.NewTLSConfig(&n.conf.TLSConfig) if err != nil { - return false, errors.Wrap(err, "parse TLS configuration") + return false, fmt.Errorf("parse TLS configuration: %w", err) } if tlsConfig.ServerName == "" { tlsConfig.ServerName = n.conf.Smarthost.Host @@ -141,7 +141,7 @@ func (n *Email) Notify(ctx context.Context, as ...*types.Alert) (bool, error) { conn, err = tls.Dial("tcp", n.conf.Smarthost.String(), tlsConfig) if err != nil { - return true, errors.Wrap(err, "establish TLS connection to server") + return true, fmt.Errorf("establish TLS connection to server: %w", err) } } else { var ( @@ -150,13 +150,13 @@ func (n *Email) Notify(ctx context.Context, as ...*types.Alert) (bool, error) { ) conn, err = d.DialContext(ctx, "tcp", n.conf.Smarthost.String()) if err != nil { - return true, errors.Wrap(err, "establish connection to server") + return true, fmt.Errorf("establish connection to server: %w", err) } } c, err = smtp.NewClient(conn, n.conf.Smarthost.Host) if err != nil { conn.Close() - return true, errors.Wrap(err, "create SMTP client") + return true, fmt.Errorf("create SMTP client: %w", err) } defer func() { // Try to clean up after ourselves but don't log anything if something has failed. @@ -168,37 +168,37 @@ func (n *Email) Notify(ctx context.Context, as ...*types.Alert) (bool, error) { if n.conf.Hello != "" { err = c.Hello(n.conf.Hello) if err != nil { - return true, errors.Wrap(err, "send EHLO command") + return true, fmt.Errorf("send EHLO command: %w", err) } } // Global Config guarantees RequireTLS is not nil. if *n.conf.RequireTLS { if ok, _ := c.Extension("STARTTLS"); !ok { - return true, errors.Errorf("'require_tls' is true (default) but %q does not advertise the STARTTLS extension", n.conf.Smarthost) + return true, fmt.Errorf("'require_tls' is true (default) but %q does not advertise the STARTTLS extension", n.conf.Smarthost) } tlsConf, err := commoncfg.NewTLSConfig(&n.conf.TLSConfig) if err != nil { - return false, errors.Wrap(err, "parse TLS configuration") + return false, fmt.Errorf("parse TLS configuration: %w", err) } if tlsConf.ServerName == "" { tlsConf.ServerName = n.conf.Smarthost.Host } if err := c.StartTLS(tlsConf); err != nil { - return true, errors.Wrap(err, "send STARTTLS command") + return true, fmt.Errorf("send STARTTLS command: %w", err) } } if ok, mech := c.Extension("AUTH"); ok { auth, err := n.auth(mech) if err != nil { - return true, errors.Wrap(err, "find auth mechanism") + return true, fmt.Errorf("find auth mechanism: %w", err) } if auth != nil { if err := c.Auth(auth); err != nil { - return true, errors.Wrapf(err, "%T auth", auth) + return true, fmt.Errorf("%T auth: %w", auth, err) } } } @@ -210,37 +210,37 @@ func (n *Email) Notify(ctx context.Context, as ...*types.Alert) (bool, error) { ) from := tmpl(n.conf.From) if tmplErr != nil { - return false, errors.Wrap(tmplErr, "execute 'from' template") + return false, fmt.Errorf("execute 'from' template: %w", tmplErr) } to := tmpl(n.conf.To) if tmplErr != nil { - return false, errors.Wrap(tmplErr, "execute 'to' template") + return false, fmt.Errorf("execute 'to' template: %w", tmplErr) } addrs, err := mail.ParseAddressList(from) if err != nil { - return false, errors.Wrap(err, "parse 'from' addresses") + return false, fmt.Errorf("parse 'from' addresses: %w", err) } if len(addrs) != 1 { - return false, errors.Errorf("must be exactly one 'from' address (got: %d)", len(addrs)) + return false, fmt.Errorf("must be exactly one 'from' address (got: %d)", len(addrs)) } if err = c.Mail(addrs[0].Address); err != nil { - return true, errors.Wrap(err, "send MAIL command") + return true, fmt.Errorf("send MAIL command: %w", err) } addrs, err = mail.ParseAddressList(to) if err != nil { - return false, errors.Wrapf(err, "parse 'to' addresses") + return false, fmt.Errorf("parse 'to' addresses: %w", err) } for _, addr := range addrs { if err = c.Rcpt(addr.Address); err != nil { - return true, errors.Wrapf(err, "send RCPT command") + return true, fmt.Errorf("send RCPT command: %w", err) } } // Send the email headers and body. message, err := c.Data() if err != nil { - return true, errors.Wrapf(err, "send DATA command") + return true, fmt.Errorf("send DATA command: %w", err) } defer message.Close() @@ -248,7 +248,7 @@ func (n *Email) Notify(ctx context.Context, as ...*types.Alert) (bool, error) { for header, t := range n.conf.Headers { value, err := n.tmpl.ExecuteTextString(t, data) if err != nil { - return false, errors.Wrapf(err, "execute %q header template", header) + return false, fmt.Errorf("execute %q header template: %w", header, err) } fmt.Fprintf(buffer, "%s: %s\r\n", header, mime.QEncoding.Encode("utf-8", value)) } @@ -268,7 +268,7 @@ func (n *Email) Notify(ctx context.Context, as ...*types.Alert) (bool, error) { // and active/resolved. _, err = message.Write(buffer.Bytes()) if err != nil { - return false, errors.Wrap(err, "write headers") + return false, fmt.Errorf("write headers: %w", err) } if len(n.conf.Text) > 0 { @@ -278,20 +278,20 @@ func (n *Email) Notify(ctx context.Context, as ...*types.Alert) (bool, error) { "Content-Type": {"text/plain; charset=UTF-8"}, }) if err != nil { - return false, errors.Wrap(err, "create part for text template") + return false, fmt.Errorf("create part for text template: %w", err) } body, err := n.tmpl.ExecuteTextString(n.conf.Text, data) if err != nil { - return false, errors.Wrap(err, "execute text template") + return false, fmt.Errorf("execute text template: %w", err) } qw := quotedprintable.NewWriter(w) _, err = qw.Write([]byte(body)) if err != nil { - return true, errors.Wrap(err, "write text part") + return true, fmt.Errorf("write text part: %w", err) } err = qw.Close() if err != nil { - return true, errors.Wrap(err, "close text part") + return true, fmt.Errorf("close text part: %w", err) } } @@ -304,31 +304,31 @@ func (n *Email) Notify(ctx context.Context, as ...*types.Alert) (bool, error) { "Content-Type": {"text/html; charset=UTF-8"}, }) if err != nil { - return false, errors.Wrap(err, "create part for html template") + return false, fmt.Errorf("create part for html template: %w", err) } body, err := n.tmpl.ExecuteHTMLString(n.conf.HTML, data) if err != nil { - return false, errors.Wrap(err, "execute html template") + return false, fmt.Errorf("execute html template: %w", err) } qw := quotedprintable.NewWriter(w) _, err = qw.Write([]byte(body)) if err != nil { - return true, errors.Wrap(err, "write HTML part") + return true, fmt.Errorf("write HTML part: %w", err) } err = qw.Close() if err != nil { - return true, errors.Wrap(err, "close HTML part") + return true, fmt.Errorf("close HTML part: %w", err) } } err = multipartWriter.Close() if err != nil { - return false, errors.Wrap(err, "close multipartWriter") + return false, fmt.Errorf("close multipartWriter: %w", err) } _, err = message.Write(multipartBuffer.Bytes()) if err != nil { - return false, errors.Wrap(err, "write body buffer") + return false, fmt.Errorf("write body buffer: %w", err) } success = true @@ -368,7 +368,7 @@ func (n *Email) getPassword() (string, error) { if err != nil { return "", fmt.Errorf("could not read %s: %w", n.conf.AuthPasswordFile, err) } - return string(content), nil + return strings.TrimSpace(string(content)), nil } return string(n.conf.AuthPassword), nil } diff --git a/vendor/github.com/prometheus/alertmanager/notify/msteams/msteams.go b/vendor/github.com/prometheus/alertmanager/notify/msteams/msteams.go index 8675d7b6da..d71e108144 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/msteams/msteams.go +++ b/vendor/github.com/prometheus/alertmanager/notify/msteams/msteams.go @@ -17,8 +17,11 @@ import ( "bytes" "context" "encoding/json" + "fmt" "io" "net/http" + "os" + "strings" "github.com/go-kit/log" "github.com/go-kit/log/level" @@ -52,6 +55,7 @@ type teamsMessage struct { Context string `json:"@context"` Type string `json:"type"` Title string `json:"title"` + Summary string `json:"summary"` Text string `json:"text"` ThemeColor string `json:"themeColor"` } @@ -98,6 +102,10 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) if err != nil { return false, err } + summary := tmpl(n.conf.Summary) + if err != nil { + return false, err + } alerts := types.Alerts(as...) color := colorGrey @@ -108,10 +116,22 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) color = colorGreen } + var url string + if n.conf.WebhookURL != nil { + url = n.conf.WebhookURL.String() + } else { + content, err := os.ReadFile(n.conf.WebhookURLFile) + if err != nil { + return false, fmt.Errorf("read webhook_url_file: %w", err) + } + url = strings.TrimSpace(string(content)) + } + t := teamsMessage{ Context: "http://schema.org/extensions", Type: "MessageCard", Title: title, + Summary: summary, Text: text, ThemeColor: color, } @@ -121,7 +141,7 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) return false, err } - resp, err := n.postJSONFunc(ctx, n.client, n.webhookURL.String(), &payload) + resp, err := n.postJSONFunc(ctx, n.client, url, &payload) if err != nil { return true, notify.RedactURL(err) } diff --git a/vendor/github.com/prometheus/alertmanager/notify/notify.go b/vendor/github.com/prometheus/alertmanager/notify/notify.go index 0364a04909..30861a3027 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/notify.go +++ b/vendor/github.com/prometheus/alertmanager/notify/notify.go @@ -15,6 +15,7 @@ package notify import ( "context" + "errors" "fmt" "sort" "sync" @@ -24,10 +25,10 @@ import ( "github.com/cespare/xxhash/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" - "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/common/model" + "github.com/prometheus/alertmanager/featurecontrol" "github.com/prometheus/alertmanager/inhibit" "github.com/prometheus/alertmanager/nflog" "github.com/prometheus/alertmanager/nflog/nflogpb" @@ -61,19 +62,21 @@ type Notifier interface { // Integration wraps a notifier and its configuration to be uniquely identified // by name and index from its origin in the configuration. type Integration struct { - notifier Notifier - rs ResolvedSender - name string - idx int + notifier Notifier + rs ResolvedSender + name string + idx int + receiverName string } // NewIntegration returns a new integration. -func NewIntegration(notifier Notifier, rs ResolvedSender, name string, idx int) Integration { +func NewIntegration(notifier Notifier, rs ResolvedSender, name string, idx int, receiverName string) Integration { return Integration{ - notifier: notifier, - rs: rs, - name: name, - idx: idx, + notifier: notifier, + rs: rs, + name: name, + idx: idx, + receiverName: receiverName, } } @@ -248,41 +251,93 @@ type Metrics struct { numTotalFailedNotifications *prometheus.CounterVec numNotificationRequestsTotal *prometheus.CounterVec numNotificationRequestsFailedTotal *prometheus.CounterVec + numNotificationSuppressedTotal *prometheus.CounterVec notificationLatencySeconds *prometheus.HistogramVec + + ff featurecontrol.Flagger } -func NewMetrics(r prometheus.Registerer) *Metrics { +func NewMetrics(r prometheus.Registerer, ff featurecontrol.Flagger) *Metrics { + labels := []string{"integration"} + + if ff.EnableReceiverNamesInMetrics() { + labels = append(labels, "receiver_name") + } + m := &Metrics{ numNotifications: prometheus.NewCounterVec(prometheus.CounterOpts{ Namespace: "alertmanager", Name: "notifications_total", Help: "The total number of attempted notifications.", - }, []string{"integration"}), + }, labels), numTotalFailedNotifications: prometheus.NewCounterVec(prometheus.CounterOpts{ Namespace: "alertmanager", Name: "notifications_failed_total", Help: "The total number of failed notifications.", - }, []string{"integration", "reason"}), + }, append(labels, "reason")), numNotificationRequestsTotal: prometheus.NewCounterVec(prometheus.CounterOpts{ Namespace: "alertmanager", Name: "notification_requests_total", Help: "The total number of attempted notification requests.", - }, []string{"integration"}), + }, labels), numNotificationRequestsFailedTotal: prometheus.NewCounterVec(prometheus.CounterOpts{ Namespace: "alertmanager", Name: "notification_requests_failed_total", Help: "The total number of failed notification requests.", - }, []string{"integration"}), + }, labels), + numNotificationSuppressedTotal: prometheus.NewCounterVec(prometheus.CounterOpts{ + Namespace: "alertmanager", + Name: "notifications_suppressed_total", + Help: "The total number of notifications suppressed for being outside of active time intervals or within muted time intervals.", + }, []string{"reason"}), notificationLatencySeconds: prometheus.NewHistogramVec(prometheus.HistogramOpts{ Namespace: "alertmanager", Name: "notification_latency_seconds", Help: "The latency of notifications in seconds.", Buckets: []float64{1, 5, 10, 15, 20}, - }, []string{"integration"}), + }, labels), + ff: ff, + } + + r.MustRegister( + m.numNotifications, m.numTotalFailedNotifications, + m.numNotificationRequestsTotal, m.numNotificationRequestsFailedTotal, + m.numNotificationSuppressedTotal, m.notificationLatencySeconds, + ) + + return m +} + +func (m *Metrics) InitializeFor(receiver map[string][]Integration) { + if m.ff.EnableReceiverNamesInMetrics() { + + // Reset the vectors to take into account receiver names changing after hot reloads. + m.numNotifications.Reset() + m.numNotificationRequestsTotal.Reset() + m.numNotificationRequestsFailedTotal.Reset() + m.notificationLatencySeconds.Reset() + m.numTotalFailedNotifications.Reset() + + for name, integrations := range receiver { + for _, integration := range integrations { + + m.numNotifications.WithLabelValues(integration.Name(), name) + m.numNotificationRequestsTotal.WithLabelValues(integration.Name(), name) + m.numNotificationRequestsFailedTotal.WithLabelValues(integration.Name(), name) + m.notificationLatencySeconds.WithLabelValues(integration.Name(), name) + + for _, reason := range possibleFailureReasonCategory { + m.numTotalFailedNotifications.WithLabelValues(integration.Name(), name, reason) + } + } + } + + return } + + // When the feature flag is not enabled, we just carry on registering _all_ the integrations. for _, integration := range []string{ "email", - "msteams", "pagerduty", "wechat", "pushover", @@ -292,6 +347,9 @@ func NewMetrics(r prometheus.Registerer) *Metrics { "victorops", "sns", "telegram", + "discord", + "webex", + "msteams", } { m.numNotifications.WithLabelValues(integration) m.numNotificationRequestsTotal.WithLabelValues(integration) @@ -302,21 +360,17 @@ func NewMetrics(r prometheus.Registerer) *Metrics { m.numTotalFailedNotifications.WithLabelValues(integration, reason) } } - r.MustRegister( - m.numNotifications, m.numTotalFailedNotifications, - m.numNotificationRequestsTotal, m.numNotificationRequestsFailedTotal, - m.notificationLatencySeconds, - ) - return m } type PipelineBuilder struct { metrics *Metrics + ff featurecontrol.Flagger } -func NewPipelineBuilder(r prometheus.Registerer) *PipelineBuilder { +func NewPipelineBuilder(r prometheus.Registerer, ff featurecontrol.Flagger) *PipelineBuilder { return &PipelineBuilder{ - metrics: NewMetrics(r), + metrics: NewMetrics(r, ff), + ff: ff, } } @@ -326,22 +380,25 @@ func (pb *PipelineBuilder) New( wait func() time.Duration, inhibitor *inhibit.Inhibitor, silencer *silence.Silencer, - times map[string][]timeinterval.TimeInterval, + intervener *timeinterval.Intervener, notificationLog NotificationLog, peer Peer, ) RoutingStage { rs := make(RoutingStage, len(receivers)) ms := NewGossipSettleStage(peer) - is := NewMuteStage(inhibitor) - tas := NewTimeActiveStage(times) - tms := NewTimeMuteStage(times) - ss := NewMuteStage(silencer) + is := NewMuteStage(inhibitor, pb.metrics) + tas := NewTimeActiveStage(intervener, pb.metrics) + tms := NewTimeMuteStage(intervener, pb.metrics) + ss := NewMuteStage(silencer, pb.metrics) for name := range receivers { st := createReceiverStage(name, receivers[name], wait, notificationLog, pb.metrics) rs[name] = MultiStage{ms, is, tas, tms, ss, st} } + + pb.metrics.InitializeFor(receivers) + return rs } @@ -456,27 +513,54 @@ func (n *GossipSettleStage) Exec(ctx context.Context, _ log.Logger, alerts ...*t return ctx, alerts, nil } +const ( + suppressedReasonSilence = "silence" + suppressedReasonInhibition = "inhibition" + suppressedReasonMuteTimeInterval = "mute_time_interval" + suppressedReasonActiveTimeInterval = "active_time_interval" +) + // MuteStage filters alerts through a Muter. type MuteStage struct { - muter types.Muter + muter types.Muter + metrics *Metrics } // NewMuteStage return a new MuteStage. -func NewMuteStage(m types.Muter) *MuteStage { - return &MuteStage{muter: m} +func NewMuteStage(m types.Muter, metrics *Metrics) *MuteStage { + return &MuteStage{muter: m, metrics: metrics} } // Exec implements the Stage interface. -func (n *MuteStage) Exec(ctx context.Context, _ log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) { - var filtered []*types.Alert +func (n *MuteStage) Exec(ctx context.Context, logger log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) { + var ( + filtered []*types.Alert + muted []*types.Alert + ) for _, a := range alerts { // TODO(fabxc): increment total alerts counter. // Do not send the alert if muted. - if !n.muter.Mutes(a.Labels) { + if n.muter.Mutes(a.Labels) { + muted = append(muted, a) + } else { filtered = append(filtered, a) } // TODO(fabxc): increment muted alerts counter if muted. } + if len(muted) > 0 { + level.Debug(logger).Log("msg", "Notifications will not be sent for muted alerts", "alerts", fmt.Sprintf("%v", muted)) + + var reason string + switch n.muter.(type) { + case *silence.Silencer: + reason = suppressedReasonSilence + case *inhibit.Inhibitor: + reason = suppressedReasonInhibition + default: + } + n.metrics.numNotificationSuppressedTotal.WithLabelValues(reason).Add(float64(len(muted))) + } + return ctx, filtered, nil } @@ -627,7 +711,7 @@ func (n *DedupStage) Exec(ctx context.Context, _ log.Logger, alerts ...*types.Al ctx = WithResolvedAlerts(ctx, resolved) entries, err := n.nflog.Query(nflog.QGroupKey(gkey), nflog.QReceiver(n.recv)) - if err != nil && err != nflog.ErrNotFound { + if err != nil && !errors.Is(err, nflog.ErrNotFound) { return ctx, nil, err } @@ -637,7 +721,7 @@ func (n *DedupStage) Exec(ctx context.Context, _ log.Logger, alerts ...*types.Al case 1: entry = entries[0] default: - return ctx, nil, errors.Errorf("unexpected entry result size %d", len(entries)) + return ctx, nil, fmt.Errorf("unexpected entry result size %d", len(entries)) } if n.needsUpdate(entry, firingSet, resolvedSet, repeatInterval) { @@ -652,27 +736,36 @@ type RetryStage struct { integration Integration groupName string metrics *Metrics + labelValues []string } // NewRetryStage returns a new instance of a RetryStage. func NewRetryStage(i Integration, groupName string, metrics *Metrics) *RetryStage { + labelValues := []string{i.Name()} + + if metrics.ff.EnableReceiverNamesInMetrics() { + labelValues = append(labelValues, i.receiverName) + } + return &RetryStage{ integration: i, groupName: groupName, metrics: metrics, + labelValues: labelValues, } } func (r RetryStage) Exec(ctx context.Context, l log.Logger, alerts ...*types.Alert) (context.Context, []*types.Alert, error) { - r.metrics.numNotifications.WithLabelValues(r.integration.Name()).Inc() + r.metrics.numNotifications.WithLabelValues(r.labelValues...).Inc() ctx, alerts, err := r.exec(ctx, l, alerts...) failureReason := DefaultReason.String() if err != nil { - if e, ok := errors.Cause(err).(*ErrorWithReason); ok { + var e *ErrorWithReason + if errors.As(err, &e) { failureReason = e.Reason.String() } - r.metrics.numTotalFailedNotifications.WithLabelValues(r.integration.Name(), failureReason).Inc() + r.metrics.numTotalFailedNotifications.WithLabelValues(append(r.labelValues, failureReason)...).Inc() } return ctx, alerts, err } @@ -723,9 +816,17 @@ func (r RetryStage) exec(ctx context.Context, l log.Logger, alerts ...*types.Ale case <-ctx.Done(): if iErr == nil { iErr = ctx.Err() + if errors.Is(iErr, context.Canceled) { + iErr = NewErrorWithReason(ContextCanceledReason, iErr) + } else if errors.Is(iErr, context.DeadlineExceeded) { + iErr = NewErrorWithReason(ContextDeadlineExceededReason, iErr) + } } - return ctx, nil, errors.Wrapf(iErr, "%s/%s: notify retry canceled after %d attempts", r.groupName, r.integration.String(), i) + if iErr != nil { + return ctx, nil, fmt.Errorf("%s/%s: notify retry canceled after %d attempts: %w", r.groupName, r.integration.String(), i, iErr) + } + return ctx, nil, nil default: } @@ -733,36 +834,45 @@ func (r RetryStage) exec(ctx context.Context, l log.Logger, alerts ...*types.Ale case <-tick.C: now := time.Now() retry, err := r.integration.Notify(ctx, sent...) - r.metrics.notificationLatencySeconds.WithLabelValues(r.integration.Name()).Observe(time.Since(now).Seconds()) - r.metrics.numNotificationRequestsTotal.WithLabelValues(r.integration.Name()).Inc() + dur := time.Since(now) + r.metrics.notificationLatencySeconds.WithLabelValues(r.labelValues...).Observe(dur.Seconds()) + r.metrics.numNotificationRequestsTotal.WithLabelValues(r.labelValues...).Inc() if err != nil { - r.metrics.numNotificationRequestsFailedTotal.WithLabelValues(r.integration.Name()).Inc() + r.metrics.numNotificationRequestsFailedTotal.WithLabelValues(r.labelValues...).Inc() if !retry { - return ctx, alerts, errors.Wrapf(err, "%s/%s: notify retry canceled due to unrecoverable error after %d attempts", r.groupName, r.integration.String(), i) + return ctx, alerts, fmt.Errorf("%s/%s: notify retry canceled due to unrecoverable error after %d attempts: %w", r.groupName, r.integration.String(), i, err) } - if ctx.Err() == nil && (iErr == nil || err.Error() != iErr.Error()) { - // Log the error if the context isn't done and the error isn't the same as before. - level.Warn(l).Log("msg", "Notify attempt failed, will retry later", "attempts", i, "err", err) + if ctx.Err() == nil { + if iErr == nil || err.Error() != iErr.Error() { + // Log the error if the context isn't done and the error isn't the same as before. + level.Warn(l).Log("msg", "Notify attempt failed, will retry later", "attempts", i, "err", err) + } + // Save this error to be able to return the last seen error by an + // integration upon context timeout. + iErr = err } - - // Save this error to be able to return the last seen error by an - // integration upon context timeout. - iErr = err } else { lvl := level.Info(l) if i <= 1 { lvl = level.Debug(log.With(l, "alerts", fmt.Sprintf("%v", alerts))) } - lvl.Log("msg", "Notify success", "attempts", i) + lvl.Log("msg", "Notify success", "attempts", i, "duration", dur) return ctx, alerts, nil } case <-ctx.Done(): if iErr == nil { iErr = ctx.Err() + if errors.Is(iErr, context.Canceled) { + iErr = NewErrorWithReason(ContextCanceledReason, iErr) + } else if errors.Is(iErr, context.DeadlineExceeded) { + iErr = NewErrorWithReason(ContextDeadlineExceededReason, iErr) + } } - - return ctx, nil, errors.Wrapf(iErr, "%s/%s: notify retry canceled after %d attempts", r.groupName, r.integration.String(), i) + if iErr != nil { + return ctx, nil, fmt.Errorf("%s/%s: notify retry canceled after %d attempts: %w", r.groupName, r.integration.String(), i, iErr) + } + return ctx, nil, nil } } } @@ -809,13 +919,14 @@ func (n SetNotifiesStage) Exec(ctx context.Context, l log.Logger, alerts ...*typ } type timeStage struct { - Times map[string][]timeinterval.TimeInterval + muter types.TimeMuter + metrics *Metrics } type TimeMuteStage timeStage -func NewTimeMuteStage(ti map[string][]timeinterval.TimeInterval) *TimeMuteStage { - return &TimeMuteStage{ti} +func NewTimeMuteStage(m types.TimeMuter, metrics *Metrics) *TimeMuteStage { + return &TimeMuteStage{m, metrics} } // Exec implements the stage interface for TimeMuteStage. @@ -830,14 +941,20 @@ func (tms TimeMuteStage) Exec(ctx context.Context, l log.Logger, alerts ...*type return ctx, alerts, errors.New("missing now timestamp") } - muted, err := inTimeIntervals(now, tms.Times, muteTimeIntervalNames) + // Skip this stage if there are no mute timings. + if len(muteTimeIntervalNames) == 0 { + return ctx, alerts, nil + } + + muted, err := tms.muter.Mutes(muteTimeIntervalNames, now) if err != nil { return ctx, alerts, err } // If the current time is inside a mute time, all alerts are removed from the pipeline. if muted { - level.Debug(l).Log("msg", "Notifications not sent, route is within mute time") + tms.metrics.numNotificationSuppressedTotal.WithLabelValues(suppressedReasonMuteTimeInterval).Add(float64(len(alerts))) + level.Debug(l).Log("msg", "Notifications not sent, route is within mute time", "alerts", len(alerts)) return ctx, nil, nil } return ctx, alerts, nil @@ -845,8 +962,8 @@ func (tms TimeMuteStage) Exec(ctx context.Context, l log.Logger, alerts ...*type type TimeActiveStage timeStage -func NewTimeActiveStage(ti map[string][]timeinterval.TimeInterval) *TimeActiveStage { - return &TimeActiveStage{ti} +func NewTimeActiveStage(m types.TimeMuter, metrics *Metrics) *TimeActiveStage { + return &TimeActiveStage{m, metrics} } // Exec implements the stage interface for TimeActiveStage. @@ -867,32 +984,17 @@ func (tas TimeActiveStage) Exec(ctx context.Context, l log.Logger, alerts ...*ty return ctx, alerts, errors.New("missing now timestamp") } - active, err := inTimeIntervals(now, tas.Times, activeTimeIntervalNames) + muted, err := tas.muter.Mutes(activeTimeIntervalNames, now) if err != nil { return ctx, alerts, err } // If the current time is not inside an active time, all alerts are removed from the pipeline - if !active { - level.Debug(l).Log("msg", "Notifications not sent, route is not within active time") + if !muted { + tas.metrics.numNotificationSuppressedTotal.WithLabelValues(suppressedReasonActiveTimeInterval).Add(float64(len(alerts))) + level.Debug(l).Log("msg", "Notifications not sent, route is not within active time", "alerts", len(alerts)) return ctx, nil, nil } return ctx, alerts, nil } - -// inTimeIntervals returns true if the current time is contained in one of the given time intervals. -func inTimeIntervals(now time.Time, intervals map[string][]timeinterval.TimeInterval, intervalNames []string) (bool, error) { - for _, name := range intervalNames { - interval, ok := intervals[name] - if !ok { - return false, errors.Errorf("time interval %s doesn't exist in config", name) - } - for _, ti := range interval { - if ti.ContainsTime(now.UTC()) { - return true, nil - } - } - } - return false, nil -} diff --git a/vendor/github.com/prometheus/alertmanager/notify/opsgenie/opsgenie.go b/vendor/github.com/prometheus/alertmanager/notify/opsgenie/opsgenie.go index 0a5e218f3a..4421cd6545 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/opsgenie/opsgenie.go +++ b/vendor/github.com/prometheus/alertmanager/notify/opsgenie/opsgenie.go @@ -24,7 +24,6 @@ import ( "github.com/go-kit/log" "github.com/go-kit/log/level" - "github.com/pkg/errors" commoncfg "github.com/prometheus/common/config" "github.com/prometheus/common/model" @@ -281,13 +280,13 @@ func (n *Notifier) createRequests(ctx context.Context, as ...*types.Alert) ([]*h } else { content, err := os.ReadFile(n.conf.APIKeyFile) if err != nil { - return nil, false, errors.Wrap(err, "read key_file error") + return nil, false, fmt.Errorf("read key_file error: %w", err) } apiKey = tmpl(string(content)) } if err != nil { - return nil, false, errors.Wrap(err, "templating error") + return nil, false, fmt.Errorf("templating error: %w", err) } for _, req := range requests { diff --git a/vendor/github.com/prometheus/alertmanager/notify/pagerduty/pagerduty.go b/vendor/github.com/prometheus/alertmanager/notify/pagerduty/pagerduty.go index 39ec84d919..6f6e1a20a8 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/pagerduty/pagerduty.go +++ b/vendor/github.com/prometheus/alertmanager/notify/pagerduty/pagerduty.go @@ -17,6 +17,7 @@ import ( "bytes" "context" "encoding/json" + "errors" "fmt" "io" "net/http" @@ -26,7 +27,6 @@ import ( "github.com/alecthomas/units" "github.com/go-kit/log" "github.com/go-kit/log/level" - "github.com/pkg/errors" commoncfg "github.com/prometheus/common/config" "github.com/prometheus/common/model" @@ -120,7 +120,7 @@ type pagerDutyPayload struct { func (n *Notifier) encodeMessage(msg *pagerDutyMessage) (bytes.Buffer, error) { var buf bytes.Buffer if err := json.NewEncoder(&buf).Encode(msg); err != nil { - return buf, errors.Wrap(err, "failed to encode PagerDuty message") + return buf, fmt.Errorf("failed to encode PagerDuty message: %w", err) } if buf.Len() > maxEventSize { @@ -137,7 +137,7 @@ func (n *Notifier) encodeMessage(msg *pagerDutyMessage) (bytes.Buffer, error) { buf.Reset() if err := json.NewEncoder(&buf).Encode(msg); err != nil { - return buf, errors.Wrap(err, "failed to encode PagerDuty message") + return buf, fmt.Errorf("failed to encode PagerDuty message: %w", err) } } @@ -164,7 +164,7 @@ func (n *Notifier) notifyV1( if serviceKey == "" { content, fileErr := os.ReadFile(n.conf.ServiceKeyFile) if fileErr != nil { - return false, errors.Wrap(fileErr, "failed to read service key from file") + return false, fmt.Errorf("failed to read service key from file: %w", fileErr) } serviceKey = strings.TrimSpace(string(content)) } @@ -183,7 +183,7 @@ func (n *Notifier) notifyV1( } if tmplErr != nil { - return false, errors.Wrap(tmplErr, "failed to template PagerDuty v1 message") + return false, fmt.Errorf("failed to template PagerDuty v1 message: %w", tmplErr) } // Ensure that the service key isn't empty after templating. @@ -198,7 +198,7 @@ func (n *Notifier) notifyV1( resp, err := notify.PostJSON(ctx, n.client, n.apiV1, &encodedMsg) if err != nil { - return true, errors.Wrap(err, "failed to post message to PagerDuty v1") + return true, fmt.Errorf("failed to post message to PagerDuty v1: %w", err) } defer notify.Drain(resp) @@ -229,7 +229,7 @@ func (n *Notifier) notifyV2( if routingKey == "" { content, fileErr := os.ReadFile(n.conf.RoutingKeyFile) if fileErr != nil { - return false, errors.Wrap(fileErr, "failed to read routing key from file") + return false, fmt.Errorf("failed to read routing key from file: %w", fileErr) } routingKey = strings.TrimSpace(string(content)) } @@ -277,7 +277,7 @@ func (n *Notifier) notifyV2( } if tmplErr != nil { - return false, errors.Wrap(tmplErr, "failed to template PagerDuty v2 message") + return false, fmt.Errorf("failed to template PagerDuty v2 message: %w", tmplErr) } // Ensure that the routing key isn't empty after templating. @@ -292,7 +292,7 @@ func (n *Notifier) notifyV2( resp, err := notify.PostJSON(ctx, n.client, n.conf.URL.String(), &encodedMsg) if err != nil { - return true, errors.Wrap(err, "failed to post message to PagerDuty") + return true, fmt.Errorf("failed to post message to PagerDuty: %w", err) } defer notify.Drain(resp) @@ -325,7 +325,7 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) for k, v := range n.conf.Details { detail, err := n.tmpl.ExecuteTextString(v, data) if err != nil { - return false, errors.Wrapf(err, "%q: failed to template %q", k, v) + return false, fmt.Errorf("%q: failed to template %q: %w", k, v, err) } details[k] = detail } diff --git a/vendor/github.com/prometheus/alertmanager/notify/pushover/pushover.go b/vendor/github.com/prometheus/alertmanager/notify/pushover/pushover.go index 9964270a5e..a8f4644f65 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/pushover/pushover.go +++ b/vendor/github.com/prometheus/alertmanager/notify/pushover/pushover.go @@ -147,6 +147,12 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) parameters.Add("expire", fmt.Sprintf("%d", int64(time.Duration(n.conf.Expire).Seconds()))) parameters.Add("device", tmpl(n.conf.Device)) parameters.Add("sound", tmpl(n.conf.Sound)) + + newttl := int64(time.Duration(n.conf.TTL).Seconds()) + if newttl > 0 { + parameters.Add("ttl", fmt.Sprintf("%d", newttl)) + } + if err != nil { return false, err } diff --git a/vendor/github.com/prometheus/alertmanager/notify/slack/slack.go b/vendor/github.com/prometheus/alertmanager/notify/slack/slack.go index 79097b7a7e..b4b5a195e9 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/slack/slack.go +++ b/vendor/github.com/prometheus/alertmanager/notify/slack/slack.go @@ -25,7 +25,6 @@ import ( "github.com/go-kit/log" "github.com/go-kit/log/level" - "github.com/pkg/errors" commoncfg "github.com/prometheus/common/config" "github.com/prometheus/alertmanager/config" @@ -216,7 +215,7 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) // classify them as retriable or not. retry, err := n.retrier.Check(resp.StatusCode, resp.Body) if err != nil { - err = errors.Wrap(err, fmt.Sprintf("channel %q", req.Channel)) + err = fmt.Errorf("channel %q: %w", req.Channel, err) return retry, notify.NewErrorWithReason(notify.GetFailureReasonFromStatusCode(resp.StatusCode), err) } @@ -224,7 +223,7 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) // https://slack.dev/node-slack-sdk/web-api#handle-errors retry, err = checkResponseError(resp) if err != nil { - err = errors.Wrap(err, fmt.Sprintf("channel %q", req.Channel)) + err = fmt.Errorf("channel %q: %w", req.Channel, err) return retry, notify.NewErrorWithReason(notify.ClientErrorReason, err) } @@ -235,7 +234,7 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) func checkResponseError(resp *http.Response) (bool, error) { body, err := io.ReadAll(resp.Body) if err != nil { - return true, errors.Wrap(err, "could not read response body") + return true, fmt.Errorf("could not read response body: %w", err) } if strings.HasPrefix(resp.Header.Get("Content-Type"), "application/json") { @@ -265,7 +264,7 @@ func checkJSONResponseError(body []byte) (bool, error) { var data response if err := json.Unmarshal(body, &data); err != nil { - return true, errors.Wrapf(err, "could not unmarshal JSON response %q", string(body)) + return true, fmt.Errorf("could not unmarshal JSON response %q: %w", string(body), err) } if !data.OK { return false, fmt.Errorf("error response from Slack: %s", data.Error) diff --git a/vendor/github.com/prometheus/alertmanager/notify/sns/sns.go b/vendor/github.com/prometheus/alertmanager/notify/sns/sns.go index b9881b0175..996566c726 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/sns/sns.go +++ b/vendor/github.com/prometheus/alertmanager/notify/sns/sns.go @@ -15,6 +15,7 @@ package sns import ( "context" + "errors" "fmt" "net/http" "strings" @@ -69,7 +70,8 @@ func (n *Notifier) Notify(ctx context.Context, alert ...*types.Alert) (bool, err client, err := n.createSNSClient(tmpl) if err != nil { - if e, ok := err.(awserr.RequestFailure); ok { + var e awserr.RequestFailure + if errors.As(err, &e) { return n.retrier.Check(e.StatusCode(), strings.NewReader(e.Message())) } return true, err @@ -82,7 +84,8 @@ func (n *Notifier) Notify(ctx context.Context, alert ...*types.Alert) (bool, err publishOutput, err := client.Publish(publishInput) if err != nil { - if e, ok := err.(awserr.RequestFailure); ok { + var e awserr.RequestFailure + if errors.As(err, &e) { retryable, error := n.retrier.Check(e.StatusCode(), strings.NewReader(e.Message())) reasonErr := notify.NewErrorWithReason(notify.GetFailureReasonFromStatusCode(e.StatusCode()), error) diff --git a/vendor/github.com/prometheus/alertmanager/notify/util.go b/vendor/github.com/prometheus/alertmanager/notify/util.go index 706856c160..bd54e2b47d 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/util.go +++ b/vendor/github.com/prometheus/alertmanager/notify/util.go @@ -16,6 +16,7 @@ package notify import ( "context" "crypto/sha256" + "errors" "fmt" "io" "net/http" @@ -24,7 +25,6 @@ import ( "github.com/go-kit/log" "github.com/go-kit/log/level" - "github.com/pkg/errors" "github.com/prometheus/common/version" "github.com/prometheus/alertmanager/template" @@ -39,8 +39,8 @@ var UserAgentHeader = fmt.Sprintf("Alertmanager/%s", version.Version) // RedactURL removes the URL part from an error of *url.Error type. func RedactURL(err error) error { - e, ok := err.(*url.Error) - if !ok { + var e *url.Error + if !errors.As(err, &e) { return err } e.URL = "" @@ -160,7 +160,7 @@ type Key string func ExtractGroupKey(ctx context.Context) (Key, error) { key, ok := GroupKey(ctx) if !ok { - return "", errors.Errorf("group key missing") + return "", fmt.Errorf("group key missing") } return Key(key), nil } @@ -270,6 +270,8 @@ const ( DefaultReason Reason = iota ClientErrorReason ServerErrorReason + ContextCanceledReason + ContextDeadlineExceededReason ) func (s Reason) String() string { @@ -280,13 +282,17 @@ func (s Reason) String() string { return "clientError" case ServerErrorReason: return "serverError" + case ContextCanceledReason: + return "contextCanceled" + case ContextDeadlineExceededReason: + return "contextDeadlineExceeded" default: panic(fmt.Sprintf("unknown Reason: %d", s)) } } // possibleFailureReasonCategory is a list of possible failure reason. -var possibleFailureReasonCategory = []string{DefaultReason.String(), ClientErrorReason.String(), ServerErrorReason.String()} +var possibleFailureReasonCategory = []string{DefaultReason.String(), ClientErrorReason.String(), ServerErrorReason.String(), ContextCanceledReason.String(), ContextDeadlineExceededReason.String()} // GetFailureReasonFromStatusCode returns the reason for the failure based on the status code provided. func GetFailureReasonFromStatusCode(statusCode int) Reason { diff --git a/vendor/github.com/prometheus/alertmanager/notify/victorops/victorops.go b/vendor/github.com/prometheus/alertmanager/notify/victorops/victorops.go index 780f7a8d1d..44088b4eb3 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/victorops/victorops.go +++ b/vendor/github.com/prometheus/alertmanager/notify/victorops/victorops.go @@ -24,7 +24,6 @@ import ( "github.com/go-kit/log" "github.com/go-kit/log/level" - "github.com/pkg/errors" commoncfg "github.com/prometheus/common/config" "github.com/prometheus/common/model" @@ -83,14 +82,14 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) } else { content, fileErr := os.ReadFile(n.conf.APIKeyFile) if fileErr != nil { - return false, errors.Wrap(fileErr, "failed to read API key from file") + return false, fmt.Errorf("failed to read API key from file: %w", fileErr) } apiKey = strings.TrimSpace(string(content)) } apiURL.Path += fmt.Sprintf("%s/%s", apiKey, tmpl(n.conf.RoutingKey)) if err != nil { - return false, fmt.Errorf("templating error: %s", err) + return false, fmt.Errorf("templating error: %w", err) } buf, err := n.createVictorOpsPayload(ctx, as...) @@ -155,14 +154,14 @@ func (n *Notifier) createVictorOpsPayload(ctx context.Context, as ...*types.Aler } if err != nil { - return nil, fmt.Errorf("templating error: %s", err) + return nil, fmt.Errorf("templating error: %w", err) } // Add custom fields to the payload. for k, v := range n.conf.CustomFields { msg[k] = tmpl(v) if err != nil { - return nil, fmt.Errorf("templating error: %s", err) + return nil, fmt.Errorf("templating error: %w", err) } } diff --git a/vendor/github.com/prometheus/alertmanager/notify/wechat/wechat.go b/vendor/github.com/prometheus/alertmanager/notify/wechat/wechat.go index 2e3b2c29ec..9eb77b66a5 100644 --- a/vendor/github.com/prometheus/alertmanager/notify/wechat/wechat.go +++ b/vendor/github.com/prometheus/alertmanager/notify/wechat/wechat.go @@ -17,6 +17,7 @@ import ( "bytes" "context" "encoding/json" + "errors" "fmt" "io" "net/http" @@ -25,7 +26,6 @@ import ( "github.com/go-kit/log" "github.com/go-kit/log/level" - "github.com/pkg/errors" commoncfg "github.com/prometheus/common/config" "github.com/prometheus/alertmanager/config" @@ -101,7 +101,7 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) parameters.Add("corpsecret", tmpl(string(n.conf.APISecret))) parameters.Add("corpid", tmpl(string(n.conf.CorpID))) if err != nil { - return false, fmt.Errorf("templating error: %s", err) + return false, fmt.Errorf("templating error: %w", err) } u := n.conf.APIURL.Copy() @@ -147,7 +147,7 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error) } } if err != nil { - return false, fmt.Errorf("templating error: %s", err) + return false, fmt.Errorf("templating error: %w", err) } var buf bytes.Buffer diff --git a/vendor/github.com/prometheus/alertmanager/pkg/labels/matcher.go b/vendor/github.com/prometheus/alertmanager/pkg/labels/matcher.go index 445c905651..f37fcb2173 100644 --- a/vendor/github.com/prometheus/alertmanager/pkg/labels/matcher.go +++ b/vendor/github.com/prometheus/alertmanager/pkg/labels/matcher.go @@ -18,7 +18,9 @@ import ( "encoding/json" "fmt" "regexp" + "strconv" "strings" + "unicode" "github.com/prometheus/common/model" ) @@ -74,6 +76,9 @@ func NewMatcher(t MatchType, n, v string) (*Matcher, error) { } func (m *Matcher) String() string { + if strings.ContainsFunc(m.Name, isReserved) { + return fmt.Sprintf(`%s%s%s`, strconv.Quote(m.Name), m.Type, strconv.Quote(m.Value)) + } return fmt.Sprintf(`%s%s"%s"`, m.Name, m.Type, openMetricsEscape(m.Value)) } @@ -199,3 +204,13 @@ func (ms Matchers) String() string { return buf.String() } + +// This is copied from matchers/parse/lexer.go. It will be removed when +// the transition window from classic matchers to UTF-8 matchers is complete, +// as then we can use double quotes when printing the label name for all +// matchers. Until then, the classic parser does not understand double quotes +// around the label name, so we use this function as a heuristic to tell if +// the matcher was parsed with the UTF-8 parser or the classic parser. +func isReserved(r rune) bool { + return unicode.IsSpace(r) || strings.ContainsRune("{}!=~,\\\"'`", r) +} diff --git a/vendor/github.com/prometheus/alertmanager/pkg/labels/parse.go b/vendor/github.com/prometheus/alertmanager/pkg/labels/parse.go index a125d59d8a..5138716e0a 100644 --- a/vendor/github.com/prometheus/alertmanager/pkg/labels/parse.go +++ b/vendor/github.com/prometheus/alertmanager/pkg/labels/parse.go @@ -14,11 +14,10 @@ package labels import ( + "fmt" "regexp" "strings" "unicode/utf8" - - "github.com/pkg/errors" ) var ( @@ -118,7 +117,7 @@ func ParseMatchers(s string) ([]*Matcher, error) { func ParseMatcher(s string) (_ *Matcher, err error) { ms := re.FindStringSubmatch(s) if len(ms) == 0 { - return nil, errors.Errorf("bad matcher format: %s", s) + return nil, fmt.Errorf("bad matcher format: %s", s) } var ( @@ -134,7 +133,7 @@ func ParseMatcher(s string) (_ *Matcher, err error) { } if !utf8.ValidString(rawValue) { - return nil, errors.Errorf("matcher value not valid UTF-8: %s", ms[3]) + return nil, fmt.Errorf("matcher value not valid UTF-8: %s", ms[3]) } // Unescape the rawValue: @@ -163,7 +162,7 @@ func ParseMatcher(s string) (_ *Matcher, err error) { value.WriteByte('\\') case '"': if !expectTrailingQuote || i < len(rawValue)-1 { - return nil, errors.Errorf("matcher value contains unescaped double quote: %s", ms[3]) + return nil, fmt.Errorf("matcher value contains unescaped double quote: %s", ms[3]) } expectTrailingQuote = false default: @@ -172,7 +171,7 @@ func ParseMatcher(s string) (_ *Matcher, err error) { } if expectTrailingQuote { - return nil, errors.Errorf("matcher value contains unescaped double quote: %s", ms[3]) + return nil, fmt.Errorf("matcher value contains unescaped double quote: %s", ms[3]) } return NewMatcher(typeMap[ms[2]], ms[1], value.String()) diff --git a/vendor/github.com/prometheus/alertmanager/silence/silence.go b/vendor/github.com/prometheus/alertmanager/silence/silence.go index 68844d38b0..710323f747 100644 --- a/vendor/github.com/prometheus/alertmanager/silence/silence.go +++ b/vendor/github.com/prometheus/alertmanager/silence/silence.go @@ -17,6 +17,7 @@ package silence import ( "bytes" + "errors" "fmt" "io" "math/rand" @@ -32,11 +33,11 @@ import ( "github.com/go-kit/log/level" uuid "github.com/gofrs/uuid" "github.com/matttproud/golang_protobuf_extensions/pbutil" - "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/common/model" "github.com/prometheus/alertmanager/cluster" + "github.com/prometheus/alertmanager/matchers/compat" "github.com/prometheus/alertmanager/pkg/labels" pb "github.com/prometheus/alertmanager/silence/silencepb" "github.com/prometheus/alertmanager/types" @@ -77,7 +78,7 @@ func (c matcherCache) add(s *pb.Silence) (labels.Matchers, error) { case pb.Matcher_NOT_REGEXP: mt = labels.MatchNotRegexp default: - return nil, errors.Errorf("unknown matcher type %q", m.Type) + return nil, fmt.Errorf("unknown matcher type %q", m.Type) } matcher, err := labels.NewMatcher(mt, m.Name, m.Pattern) if err != nil { @@ -331,6 +332,7 @@ func New(o Options) (*Silences, error) { if err := o.validate(); err != nil { return nil, err } + s := &Silences{ clock: clock.New(), mc: matcherCache{}, @@ -467,9 +469,8 @@ func (s *Silences) GC() (int, error) { return n, nil } -// ValidateMatcher runs validation on the matcher name, type, and pattern. -var ValidateMatcher = func(m *pb.Matcher) error { - if !model.LabelName(m.Name).IsValid() { +func validateMatcher(m *pb.Matcher) error { + if !compat.IsValidLabelName(model.LabelName(m.Name)) { return fmt.Errorf("invalid label name %q", m.Name) } switch m.Type { @@ -479,7 +480,7 @@ var ValidateMatcher = func(m *pb.Matcher) error { } case pb.Matcher_REGEXP, pb.Matcher_NOT_REGEXP: if _, err := regexp.Compile(m.Pattern); err != nil { - return fmt.Errorf("invalid regular expression %q: %s", m.Pattern, err) + return fmt.Errorf("invalid regular expression %q: %w", m.Pattern, err) } default: return fmt.Errorf("unknown matcher type %q", m.Type) @@ -507,9 +508,10 @@ func validateSilence(s *pb.Silence) error { return errors.New("at least one matcher required") } allMatchEmpty := true + for i, m := range s.Matchers { - if err := ValidateMatcher(m); err != nil { - return fmt.Errorf("invalid label matcher %d: %s", i, err) + if err := validateMatcher(m); err != nil { + return fmt.Errorf("invalid label matcher %d: %w", i, err) } allMatchEmpty = allMatchEmpty && matchesEmpty(m) } @@ -545,11 +547,13 @@ func (s *Silences) getSilence(id string) (*pb.Silence, bool) { return msil.Silence, true } -func (s *Silences) setSilence(sil *pb.Silence, now time.Time) error { +func (s *Silences) setSilence(sil *pb.Silence, now time.Time, skipValidate bool) error { sil.UpdatedAt = now - if err := validateSilence(sil); err != nil { - return errors.Wrap(err, "silence invalid") + if !skipValidate { + if err := validateSilence(sil); err != nil { + return fmt.Errorf("silence invalid: %w", err) + } } msil := &pb.MeshSilence{ @@ -583,19 +587,19 @@ func (s *Silences) Set(sil *pb.Silence) (string, error) { } if ok { if canUpdate(prev, sil, now) { - return sil.Id, s.setSilence(sil, now) + return sil.Id, s.setSilence(sil, now, false) } if getState(prev, s.nowUTC()) != types.SilenceStateExpired { // We cannot update the silence, expire the old one. if err := s.expire(prev.Id); err != nil { - return "", errors.Wrap(err, "expire previous silence") + return "", fmt.Errorf("expire previous silence: %w", err) } } } // If we got here it's either a new silence or a replacing one. uid, err := uuid.NewV4() if err != nil { - return "", errors.Wrap(err, "generate uuid") + return "", fmt.Errorf("generate uuid: %w", err) } sil.Id = uid.String() @@ -603,7 +607,7 @@ func (s *Silences) Set(sil *pb.Silence) (string, error) { sil.StartsAt = now } - return sil.Id, s.setSilence(sil, now) + return sil.Id, s.setSilence(sil, now, false) } // canUpdate returns true if silence a can be updated to b without @@ -662,7 +666,9 @@ func (s *Silences) expire(id string) error { sil.EndsAt = now } - return s.setSilence(sil, now) + // Skip validation of the silence when expiring it. Without this, silences created + // with valid UTF-8 matchers cannot be expired when Alertmanager is run in classic mode. + return s.setSilence(sil, now, true) } // QueryParam expresses parameters along which silences are queried. @@ -951,7 +957,7 @@ func decodeState(r io.Reader) (state, error) { st[s.Silence.Id] = &s continue } - if err == io.EOF { + if errors.Is(err, io.EOF) { break } return nil, err diff --git a/vendor/github.com/prometheus/alertmanager/template/default.tmpl b/vendor/github.com/prometheus/alertmanager/template/default.tmpl index a1bbfe96fc..8b2bb7470e 100644 --- a/vendor/github.com/prometheus/alertmanager/template/default.tmpl +++ b/vendor/github.com/prometheus/alertmanager/template/default.tmpl @@ -146,6 +146,7 @@ Alerts Resolved: {{ end }} {{ end }} +{{ define "msteams.default.summary" }}{{ template "__subject" . }}{{ end }} {{ define "msteams.default.title" }}{{ template "__subject" . }}{{ end }} {{ define "msteams.default.text" }} {{ if gt (len .Alerts.Firing) 0 }} diff --git a/vendor/github.com/prometheus/alertmanager/timeinterval/timeinterval.go b/vendor/github.com/prometheus/alertmanager/timeinterval/timeinterval.go index a5018aaef9..fe8c97d729 100644 --- a/vendor/github.com/prometheus/alertmanager/timeinterval/timeinterval.go +++ b/vendor/github.com/prometheus/alertmanager/timeinterval/timeinterval.go @@ -27,6 +27,35 @@ import ( "gopkg.in/yaml.v2" ) +// Intervener determines whether a given time and active route time interval should mute outgoing notifications. +// It implements the TimeMuter interface. +type Intervener struct { + intervals map[string][]TimeInterval +} + +func (i *Intervener) Mutes(names []string, now time.Time) (bool, error) { + for _, name := range names { + interval, ok := i.intervals[name] + if !ok { + return false, fmt.Errorf("time interval %s doesn't exist in config", name) + } + + for _, ti := range interval { + if ti.ContainsTime(now.UTC()) { + return true, nil + } + } + } + + return false, nil +} + +func NewIntervener(ti map[string][]TimeInterval) *Intervener { + return &Intervener{ + intervals: ti, + } +} + // TimeInterval describes intervals of time. ContainsTime will tell you if a golang time is contained // within the interval. type TimeInterval struct { @@ -436,9 +465,6 @@ func (ir InclusiveRange) MarshalYAML() (interface{}, error) { return string(bytes), err } -// TimeLayout specifies the layout to be used in time.Parse() calls for time intervals. -const TimeLayout = "15:04" - var ( validTime = "^((([01][0-9])|(2[0-3])):[0-5][0-9])$|(^24:00$)" validTimeRE = regexp.MustCompile(validTime) diff --git a/vendor/github.com/prometheus/alertmanager/types/types.go b/vendor/github.com/prometheus/alertmanager/types/types.go index f3101f8234..54a889ab9c 100644 --- a/vendor/github.com/prometheus/alertmanager/types/types.go +++ b/vendor/github.com/prometheus/alertmanager/types/types.go @@ -14,6 +14,7 @@ package types import ( + "fmt" "strings" "sync" "time" @@ -21,6 +22,7 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/common/model" + "github.com/prometheus/alertmanager/matchers/compat" "github.com/prometheus/alertmanager/pkg/labels" ) @@ -302,6 +304,39 @@ type Alert struct { Timeout bool } +func validateLs(ls model.LabelSet) error { + for ln, lv := range ls { + if !compat.IsValidLabelName(ln) { + return fmt.Errorf("invalid name %q", ln) + } + if !lv.IsValid() { + return fmt.Errorf("invalid value %q", lv) + } + } + return nil +} + +// Validate overrides the same method in model.Alert to allow UTF-8 labels. +// This can be removed once prometheus/common has support for UTF-8. +func (a *Alert) Validate() error { + if a.StartsAt.IsZero() { + return fmt.Errorf("start time missing") + } + if !a.EndsAt.IsZero() && a.EndsAt.Before(a.StartsAt) { + return fmt.Errorf("start time must be before end time") + } + if len(a.Labels) == 0 { + return fmt.Errorf("at least one label pair required") + } + if err := validateLs(a.Labels); err != nil { + return fmt.Errorf("invalid label set: %w", err) + } + if err := validateLs(a.Annotations); err != nil { + return fmt.Errorf("invalid annotations: %w", err) + } + return nil +} + // AlertSlice is a sortable slice of Alerts. type AlertSlice []*Alert @@ -381,6 +416,11 @@ type Muter interface { Mutes(model.LabelSet) bool } +// TimeMuter determines if alerts should be muted based on the specified current time and active time interval on the route. +type TimeMuter interface { + Mutes(timeIntervalName []string, now time.Time) (bool, error) +} + // A MuteFunc is a function that implements the Muter interface. type MuteFunc func(model.LabelSet) bool diff --git a/vendor/github.com/prometheus/alertmanager/ui/web.go b/vendor/github.com/prometheus/alertmanager/ui/web.go index 4d41a30732..3820625925 100644 --- a/vendor/github.com/prometheus/alertmanager/ui/web.go +++ b/vendor/github.com/prometheus/alertmanager/ui/web.go @@ -62,7 +62,7 @@ func Register(r *route.Router, reloadCh chan<- chan error, logger log.Logger) { fs.ServeHTTP(w, req) }) - r.Post("/-/reload", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + r.Post("/-/reload", func(w http.ResponseWriter, req *http.Request) { errc := make(chan error) defer close(errc) @@ -70,22 +70,22 @@ func Register(r *route.Router, reloadCh chan<- chan error, logger log.Logger) { if err := <-errc; err != nil { http.Error(w, fmt.Sprintf("failed to reload config: %s", err), http.StatusInternalServerError) } - })) + }) - r.Get("/-/healthy", http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + r.Get("/-/healthy", func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) fmt.Fprintf(w, "OK") - })) - r.Head("/-/healthy", http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + }) + r.Head("/-/healthy", func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) - })) - r.Get("/-/ready", http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + }) + r.Get("/-/ready", func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) fmt.Fprintf(w, "OK") - })) - r.Head("/-/ready", http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + }) + r.Head("/-/ready", func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) - })) + }) r.Get("/debug/*subpath", http.DefaultServeMux.ServeHTTP) r.Post("/debug/*subpath", http.DefaultServeMux.ServeHTTP) diff --git a/vendor/github.com/prometheus/client_golang/prometheus/collectors/version/version.go b/vendor/github.com/prometheus/client_golang/prometheus/collectors/version/version.go new file mode 100644 index 0000000000..c96e187126 --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/collectors/version/version.go @@ -0,0 +1,47 @@ +// Copyright 2016 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 version + +import ( + "fmt" + + "github.com/prometheus/common/version" + + "github.com/prometheus/client_golang/prometheus" +) + +// NewCollector returns a collector that exports metrics about current version +// information. +func NewCollector(program string) prometheus.Collector { + return prometheus.NewGaugeFunc( + prometheus.GaugeOpts{ + Namespace: program, + Name: "build_info", + Help: fmt.Sprintf( + "A metric with a constant '1' value labeled by version, revision, branch, goversion from which %s was built, and the goos and goarch for the build.", + program, + ), + ConstLabels: prometheus.Labels{ + "version": version.Version, + "revision": version.GetRevision(), + "branch": version.Branch, + "goversion": version.GoVersion, + "goos": version.GoOS, + "goarch": version.GoArch, + "tags": version.GetTags(), + }, + }, + func() float64 { return 1 }, + ) +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/push/push.go b/vendor/github.com/prometheus/client_golang/prometheus/push/push.go index b2c32f4294..e524aa1303 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/push/push.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/push/push.go @@ -109,7 +109,7 @@ func New(url, job string) *Pusher { gatherers: prometheus.Gatherers{reg}, registerer: reg, client: &http.Client{}, - expfmt: expfmt.FmtProtoDelim, + expfmt: expfmt.NewFormat(expfmt.TypeProtoDelim), } } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/testutil/promlint/promlint.go b/vendor/github.com/prometheus/client_golang/prometheus/testutil/promlint/promlint.go index dd29cccc30..ea46f38ecf 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/testutil/promlint/promlint.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/testutil/promlint/promlint.go @@ -68,7 +68,7 @@ func (l *Linter) Lint() ([]Problem, error) { var problems []Problem if l.r != nil { - d := expfmt.NewDecoder(l.r, expfmt.FmtText) + d := expfmt.NewDecoder(l.r, expfmt.NewFormat(expfmt.TypeTextPlain)) mf := &dto.MetricFamily{} for { diff --git a/vendor/github.com/prometheus/client_golang/prometheus/testutil/testutil.go b/vendor/github.com/prometheus/client_golang/prometheus/testutil/testutil.go index 269f56435b..9dce15eafa 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/testutil/testutil.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/testutil/testutil.go @@ -265,13 +265,13 @@ func compareMetricFamilies(got, expected []*dto.MetricFamily, metricNames ...str // result. func compare(got, want []*dto.MetricFamily) error { var gotBuf, wantBuf bytes.Buffer - enc := expfmt.NewEncoder(&gotBuf, expfmt.FmtText) + enc := expfmt.NewEncoder(&gotBuf, expfmt.NewFormat(expfmt.TypeTextPlain)) for _, mf := range got { if err := enc.Encode(mf); err != nil { return fmt.Errorf("encoding gathered metrics failed: %w", err) } } - enc = expfmt.NewEncoder(&wantBuf, expfmt.FmtText) + enc = expfmt.NewEncoder(&wantBuf, expfmt.NewFormat(expfmt.TypeTextPlain)) for _, mf := range want { if err := enc.Encode(mf); err != nil { return fmt.Errorf("encoding expected metrics failed: %w", err) diff --git a/vendor/github.com/prometheus/client_model/go/metrics.pb.go b/vendor/github.com/prometheus/client_model/go/metrics.pb.go index cee360db7f..2f15490758 100644 --- a/vendor/github.com/prometheus/client_model/go/metrics.pb.go +++ b/vendor/github.com/prometheus/client_model/go/metrics.pb.go @@ -483,6 +483,8 @@ type Histogram struct { // histograms. PositiveDelta []int64 `protobuf:"zigzag64,13,rep,name=positive_delta,json=positiveDelta" json:"positive_delta,omitempty"` // Count delta of each bucket compared to previous one (or to zero for 1st bucket). PositiveCount []float64 `protobuf:"fixed64,14,rep,name=positive_count,json=positiveCount" json:"positive_count,omitempty"` // Absolute count of each bucket. + // Only used for native histograms. These exemplars MUST have a timestamp. + Exemplars []*Exemplar `protobuf:"bytes,16,rep,name=exemplars" json:"exemplars,omitempty"` } func (x *Histogram) Reset() { @@ -622,6 +624,13 @@ func (x *Histogram) GetPositiveCount() []float64 { return nil } +func (x *Histogram) GetExemplars() []*Exemplar { + if x != nil { + return x.Exemplars + } + return nil +} + // A Bucket of a conventional histogram, each of which is treated as // an individual counter-like time series by Prometheus. type Bucket struct { @@ -923,6 +932,7 @@ type MetricFamily struct { Help *string `protobuf:"bytes,2,opt,name=help" json:"help,omitempty"` Type *MetricType `protobuf:"varint,3,opt,name=type,enum=io.prometheus.client.MetricType" json:"type,omitempty"` Metric []*Metric `protobuf:"bytes,4,rep,name=metric" json:"metric,omitempty"` + Unit *string `protobuf:"bytes,5,opt,name=unit" json:"unit,omitempty"` } func (x *MetricFamily) Reset() { @@ -985,6 +995,13 @@ func (x *MetricFamily) GetMetric() []*Metric { return nil } +func (x *MetricFamily) GetUnit() string { + if x != nil && x.Unit != nil { + return *x.Unit + } + return "" +} + var File_io_prometheus_client_metrics_proto protoreflect.FileDescriptor var file_io_prometheus_client_metrics_proto_rawDesc = []byte{ @@ -1028,7 +1045,7 @@ var file_io_prometheus_client_metrics_proto_rawDesc = []byte{ 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x10, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x1f, 0x0a, 0x07, 0x55, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xac, 0x05, 0x0a, 0x09, 0x48, + 0x01, 0x28, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xea, 0x05, 0x0a, 0x09, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x73, @@ -1071,79 +1088,84 @@ var file_io_prometheus_client_metrics_proto_rawDesc = []byte{ 0x03, 0x28, 0x12, 0x52, 0x0d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x01, 0x52, 0x0d, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xc6, 0x01, 0x0a, 0x06, 0x42, 0x75, - 0x63, 0x6b, 0x65, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, - 0x76, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, - 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, - 0x34, 0x0a, 0x16, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, - 0x14, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, - 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x75, 0x70, 0x70, 0x65, 0x72, 0x5f, 0x62, - 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0a, 0x75, 0x70, 0x70, 0x65, - 0x72, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x3a, 0x0a, 0x08, 0x65, 0x78, 0x65, 0x6d, 0x70, 0x6c, - 0x61, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, - 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, - 0x45, 0x78, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x52, 0x08, 0x65, 0x78, 0x65, 0x6d, 0x70, 0x6c, - 0x61, 0x72, 0x22, 0x3c, 0x0a, 0x0a, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x70, 0x61, 0x6e, - 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x11, - 0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x65, 0x6e, 0x67, - 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, - 0x22, 0x91, 0x01, 0x0a, 0x08, 0x45, 0x78, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x12, 0x35, 0x0a, + 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x3c, 0x0a, 0x09, 0x65, 0x78, 0x65, + 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x73, 0x18, 0x10, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x69, + 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x78, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x52, 0x09, 0x65, 0x78, + 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x73, 0x22, 0xc6, 0x01, 0x0a, 0x06, 0x42, 0x75, 0x63, 0x6b, + 0x65, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, + 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x63, 0x75, + 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x34, 0x0a, + 0x16, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x14, 0x63, + 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x46, 0x6c, + 0x6f, 0x61, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x75, 0x70, 0x70, 0x65, 0x72, 0x5f, 0x62, 0x6f, 0x75, + 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0a, 0x75, 0x70, 0x70, 0x65, 0x72, 0x42, + 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x3a, 0x0a, 0x08, 0x65, 0x78, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, + 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x78, + 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x52, 0x08, 0x65, 0x78, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, + 0x22, 0x3c, 0x0a, 0x0a, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x70, 0x61, 0x6e, 0x12, 0x16, + 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x11, 0x52, 0x06, + 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x91, + 0x01, 0x0a, 0x08, 0x45, 0x78, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x12, 0x35, 0x0a, 0x05, 0x6c, + 0x61, 0x62, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x69, 0x6f, 0x2e, + 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x52, 0x05, 0x6c, 0x61, 0x62, + 0x65, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x22, 0xff, 0x02, 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x35, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x52, 0x05, 0x6c, - 0x61, 0x62, 0x65, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x22, 0xff, 0x02, 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, - 0x35, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, - 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, - 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x52, - 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x31, 0x0a, 0x05, 0x67, 0x61, 0x75, 0x67, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, - 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x47, 0x61, 0x75, - 0x67, 0x65, 0x52, 0x05, 0x67, 0x61, 0x75, 0x67, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x69, 0x6f, 0x2e, + 0x61, 0x62, 0x65, 0x6c, 0x12, 0x31, 0x0a, 0x05, 0x67, 0x61, 0x75, 0x67, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, + 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x47, 0x61, 0x75, 0x67, 0x65, + 0x52, 0x05, 0x67, 0x61, 0x75, 0x67, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, + 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, + 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x52, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, + 0x12, 0x37, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1d, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, + 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, + 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x37, 0x0a, 0x07, 0x75, 0x6e, 0x74, + 0x79, 0x70, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, - 0x74, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x52, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x65, 0x72, 0x12, 0x37, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, - 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x75, 0x6d, 0x6d, 0x61, - 0x72, 0x79, 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x37, 0x0a, 0x07, 0x75, - 0x6e, 0x74, 0x79, 0x70, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x69, - 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x2e, 0x55, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x64, 0x52, 0x07, 0x75, 0x6e, 0x74, - 0x79, 0x70, 0x65, 0x64, 0x12, 0x3d, 0x0a, 0x09, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, - 0x6d, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, - 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x48, - 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x52, 0x09, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, - 0x72, 0x61, 0x6d, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x4d, 0x73, 0x22, 0xa2, 0x01, 0x0a, 0x0c, 0x4d, 0x65, 0x74, 0x72, 0x69, - 0x63, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, - 0x65, 0x6c, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x65, 0x6c, 0x70, 0x12, - 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, - 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, - 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x54, 0x79, 0x70, 0x65, 0x52, - 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x18, - 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, - 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x4d, 0x65, 0x74, - 0x72, 0x69, 0x63, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2a, 0x62, 0x0a, 0x0a, 0x4d, - 0x65, 0x74, 0x72, 0x69, 0x63, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x4f, 0x55, - 0x4e, 0x54, 0x45, 0x52, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x47, 0x41, 0x55, 0x47, 0x45, 0x10, - 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x55, 0x4d, 0x4d, 0x41, 0x52, 0x59, 0x10, 0x02, 0x12, 0x0b, - 0x0a, 0x07, 0x55, 0x4e, 0x54, 0x59, 0x50, 0x45, 0x44, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x48, - 0x49, 0x53, 0x54, 0x4f, 0x47, 0x52, 0x41, 0x4d, 0x10, 0x04, 0x12, 0x13, 0x0a, 0x0f, 0x47, 0x41, - 0x55, 0x47, 0x45, 0x5f, 0x48, 0x49, 0x53, 0x54, 0x4f, 0x47, 0x52, 0x41, 0x4d, 0x10, 0x05, 0x42, - 0x52, 0x0a, 0x14, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, - 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2f, 0x63, - 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x67, 0x6f, 0x3b, 0x69, - 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x5f, 0x63, 0x6c, 0x69, - 0x65, 0x6e, 0x74, + 0x74, 0x2e, 0x55, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x64, 0x52, 0x07, 0x75, 0x6e, 0x74, 0x79, 0x70, + 0x65, 0x64, 0x12, 0x3d, 0x0a, 0x09, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, + 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x48, 0x69, 0x73, + 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x52, 0x09, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, + 0x6d, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x5f, 0x6d, + 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x4d, 0x73, 0x22, 0xb6, 0x01, 0x0a, 0x0c, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x46, + 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x65, 0x6c, + 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x65, 0x6c, 0x70, 0x12, 0x34, 0x0a, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x69, 0x6f, + 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x18, 0x04, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, + 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, + 0x63, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x6e, 0x69, + 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x6e, 0x69, 0x74, 0x2a, 0x62, 0x0a, + 0x0a, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x43, + 0x4f, 0x55, 0x4e, 0x54, 0x45, 0x52, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x47, 0x41, 0x55, 0x47, + 0x45, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x55, 0x4d, 0x4d, 0x41, 0x52, 0x59, 0x10, 0x02, + 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x54, 0x59, 0x50, 0x45, 0x44, 0x10, 0x03, 0x12, 0x0d, 0x0a, + 0x09, 0x48, 0x49, 0x53, 0x54, 0x4f, 0x47, 0x52, 0x41, 0x4d, 0x10, 0x04, 0x12, 0x13, 0x0a, 0x0f, + 0x47, 0x41, 0x55, 0x47, 0x45, 0x5f, 0x48, 0x49, 0x53, 0x54, 0x4f, 0x47, 0x52, 0x41, 0x4d, 0x10, + 0x05, 0x42, 0x52, 0x0a, 0x14, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, + 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, + 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, 0x67, 0x6f, + 0x3b, 0x69, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x5f, 0x63, + 0x6c, 0x69, 0x65, 0x6e, 0x74, } var ( @@ -1185,22 +1207,23 @@ var file_io_prometheus_client_metrics_proto_depIdxs = []int32{ 13, // 5: io.prometheus.client.Histogram.created_timestamp:type_name -> google.protobuf.Timestamp 9, // 6: io.prometheus.client.Histogram.negative_span:type_name -> io.prometheus.client.BucketSpan 9, // 7: io.prometheus.client.Histogram.positive_span:type_name -> io.prometheus.client.BucketSpan - 10, // 8: io.prometheus.client.Bucket.exemplar:type_name -> io.prometheus.client.Exemplar - 1, // 9: io.prometheus.client.Exemplar.label:type_name -> io.prometheus.client.LabelPair - 13, // 10: io.prometheus.client.Exemplar.timestamp:type_name -> google.protobuf.Timestamp - 1, // 11: io.prometheus.client.Metric.label:type_name -> io.prometheus.client.LabelPair - 2, // 12: io.prometheus.client.Metric.gauge:type_name -> io.prometheus.client.Gauge - 3, // 13: io.prometheus.client.Metric.counter:type_name -> io.prometheus.client.Counter - 5, // 14: io.prometheus.client.Metric.summary:type_name -> io.prometheus.client.Summary - 6, // 15: io.prometheus.client.Metric.untyped:type_name -> io.prometheus.client.Untyped - 7, // 16: io.prometheus.client.Metric.histogram:type_name -> io.prometheus.client.Histogram - 0, // 17: io.prometheus.client.MetricFamily.type:type_name -> io.prometheus.client.MetricType - 11, // 18: io.prometheus.client.MetricFamily.metric:type_name -> io.prometheus.client.Metric - 19, // [19:19] is the sub-list for method output_type - 19, // [19:19] is the sub-list for method input_type - 19, // [19:19] is the sub-list for extension type_name - 19, // [19:19] is the sub-list for extension extendee - 0, // [0:19] is the sub-list for field type_name + 10, // 8: io.prometheus.client.Histogram.exemplars:type_name -> io.prometheus.client.Exemplar + 10, // 9: io.prometheus.client.Bucket.exemplar:type_name -> io.prometheus.client.Exemplar + 1, // 10: io.prometheus.client.Exemplar.label:type_name -> io.prometheus.client.LabelPair + 13, // 11: io.prometheus.client.Exemplar.timestamp:type_name -> google.protobuf.Timestamp + 1, // 12: io.prometheus.client.Metric.label:type_name -> io.prometheus.client.LabelPair + 2, // 13: io.prometheus.client.Metric.gauge:type_name -> io.prometheus.client.Gauge + 3, // 14: io.prometheus.client.Metric.counter:type_name -> io.prometheus.client.Counter + 5, // 15: io.prometheus.client.Metric.summary:type_name -> io.prometheus.client.Summary + 6, // 16: io.prometheus.client.Metric.untyped:type_name -> io.prometheus.client.Untyped + 7, // 17: io.prometheus.client.Metric.histogram:type_name -> io.prometheus.client.Histogram + 0, // 18: io.prometheus.client.MetricFamily.type:type_name -> io.prometheus.client.MetricType + 11, // 19: io.prometheus.client.MetricFamily.metric:type_name -> io.prometheus.client.Metric + 20, // [20:20] is the sub-list for method output_type + 20, // [20:20] is the sub-list for method input_type + 20, // [20:20] is the sub-list for extension type_name + 20, // [20:20] is the sub-list for extension extendee + 0, // [0:20] is the sub-list for field type_name } func init() { file_io_prometheus_client_metrics_proto_init() } diff --git a/vendor/github.com/prometheus/common/config/http_config.go b/vendor/github.com/prometheus/common/config/http_config.go index f295e917a9..2044181840 100644 --- a/vendor/github.com/prometheus/common/config/http_config.go +++ b/vendor/github.com/prometheus/common/config/http_config.go @@ -427,6 +427,7 @@ type httpClientOptions struct { http2Enabled bool idleConnTimeout time.Duration userAgent string + host string } // HTTPClientOption defines an option that can be applied to the HTTP client. @@ -467,6 +468,13 @@ func WithUserAgent(ua string) HTTPClientOption { } } +// WithHost allows setting the host header. +func WithHost(host string) HTTPClientOption { + return func(opts *httpClientOptions) { + opts.host = host + } +} + // NewClient returns a http.Client using the specified http.RoundTripper. func newClient(rt http.RoundTripper) *http.Client { return &http.Client{Transport: rt} @@ -568,6 +576,10 @@ func NewRoundTripperFromConfig(cfg HTTPClientConfig, name string, optFuncs ...HT rt = NewUserAgentRoundTripper(opts.userAgent, rt) } + if opts.host != "" { + rt = NewHostRoundTripper(opts.host, rt) + } + // Return a new configured RoundTripper. return rt, nil } @@ -1164,11 +1176,21 @@ type userAgentRoundTripper struct { rt http.RoundTripper } +type hostRoundTripper struct { + host string + rt http.RoundTripper +} + // NewUserAgentRoundTripper adds the user agent every request header. func NewUserAgentRoundTripper(userAgent string, rt http.RoundTripper) http.RoundTripper { return &userAgentRoundTripper{userAgent, rt} } +// NewHostRoundTripper sets the [http.Request.Host] of every request. +func NewHostRoundTripper(host string, rt http.RoundTripper) http.RoundTripper { + return &hostRoundTripper{host, rt} +} + func (rt *userAgentRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { req = cloneRequest(req) req.Header.Set("User-Agent", rt.userAgent) @@ -1181,6 +1203,19 @@ func (rt *userAgentRoundTripper) CloseIdleConnections() { } } +func (rt *hostRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { + req = cloneRequest(req) + req.Host = rt.host + req.Header.Set("Host", rt.host) + return rt.rt.RoundTrip(req) +} + +func (rt *hostRoundTripper) CloseIdleConnections() { + if ci, ok := rt.rt.(closeIdler); ok { + ci.CloseIdleConnections() + } +} + func (c HTTPClientConfig) String() string { b, err := yaml.Marshal(c) if err != nil { diff --git a/vendor/github.com/prometheus/common/expfmt/decode.go b/vendor/github.com/prometheus/common/expfmt/decode.go index 3597bfd93e..b2b89b017e 100644 --- a/vendor/github.com/prometheus/common/expfmt/decode.go +++ b/vendor/github.com/prometheus/common/expfmt/decode.go @@ -45,7 +45,7 @@ func ResponseFormat(h http.Header) Format { mediatype, params, err := mime.ParseMediaType(ct) if err != nil { - return FmtUnknown + return fmtUnknown } const textType = "text/plain" @@ -53,21 +53,21 @@ func ResponseFormat(h http.Header) Format { switch mediatype { case ProtoType: if p, ok := params["proto"]; ok && p != ProtoProtocol { - return FmtUnknown + return fmtUnknown } if e, ok := params["encoding"]; ok && e != "delimited" { - return FmtUnknown + return fmtUnknown } - return FmtProtoDelim + return fmtProtoDelim case textType: if v, ok := params["version"]; ok && v != TextVersion { - return FmtUnknown + return fmtUnknown } - return FmtText + return fmtText } - return FmtUnknown + return fmtUnknown } // NewDecoder returns a new decoder based on the given input format. diff --git a/vendor/github.com/prometheus/common/expfmt/encode.go b/vendor/github.com/prometheus/common/expfmt/encode.go index 97ee673d94..7f6cbe7d29 100644 --- a/vendor/github.com/prometheus/common/expfmt/encode.go +++ b/vendor/github.com/prometheus/common/expfmt/encode.go @@ -76,18 +76,18 @@ func Negotiate(h http.Header) Format { if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol { switch ac.Params["encoding"] { case "delimited": - return FmtProtoDelim + escapingScheme + return fmtProtoDelim + escapingScheme case "text": - return FmtProtoText + escapingScheme + return fmtProtoText + escapingScheme case "compact-text": - return FmtProtoCompact + escapingScheme + return fmtProtoCompact + escapingScheme } } if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") { - return FmtText + escapingScheme + return fmtText + escapingScheme } } - return FmtText + escapingScheme + return fmtText + escapingScheme } // NegotiateIncludingOpenMetrics works like Negotiate but includes @@ -109,26 +109,26 @@ func NegotiateIncludingOpenMetrics(h http.Header) Format { if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol { switch ac.Params["encoding"] { case "delimited": - return FmtProtoDelim + escapingScheme + return fmtProtoDelim + escapingScheme case "text": - return FmtProtoText + escapingScheme + return fmtProtoText + escapingScheme case "compact-text": - return FmtProtoCompact + escapingScheme + return fmtProtoCompact + escapingScheme } } if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") { - return FmtText + escapingScheme + return fmtText + escapingScheme } if ac.Type+"/"+ac.SubType == OpenMetricsType && (ver == OpenMetricsVersion_0_0_1 || ver == OpenMetricsVersion_1_0_0 || ver == "") { switch ver { case OpenMetricsVersion_1_0_0: - return FmtOpenMetrics_1_0_0 + escapingScheme + return fmtOpenMetrics_1_0_0 + escapingScheme default: - return FmtOpenMetrics_0_0_1 + escapingScheme + return fmtOpenMetrics_0_0_1 + escapingScheme } } } - return FmtText + escapingScheme + return fmtText + escapingScheme } // NewEncoder returns a new encoder based on content type negotiation. All @@ -139,7 +139,13 @@ func NegotiateIncludingOpenMetrics(h http.Header) Format { // interface is kept for backwards compatibility. // In cases where the Format does not allow for UTF-8 names, the global // NameEscapingScheme will be applied. -func NewEncoder(w io.Writer, format Format) Encoder { +// +// NewEncoder can be called with additional options to customize the OpenMetrics text output. +// For example: +// NewEncoder(w, FmtOpenMetrics_1_0_0, WithCreatedLines()) +// +// Extra options are ignored for all other formats. +func NewEncoder(w io.Writer, format Format, options ...EncoderOption) Encoder { escapingScheme := format.ToEscapingScheme() switch format.FormatType() { @@ -178,7 +184,7 @@ func NewEncoder(w io.Writer, format Format) Encoder { case TypeOpenMetrics: return encoderCloser{ encode: func(v *dto.MetricFamily) error { - _, err := MetricFamilyToOpenMetrics(w, model.EscapeMetricFamily(v, escapingScheme)) + _, err := MetricFamilyToOpenMetrics(w, model.EscapeMetricFamily(v, escapingScheme), options...) return err }, close: func() error { diff --git a/vendor/github.com/prometheus/common/expfmt/expfmt.go b/vendor/github.com/prometheus/common/expfmt/expfmt.go index f9b6f70fe8..6fc9555e3f 100644 --- a/vendor/github.com/prometheus/common/expfmt/expfmt.go +++ b/vendor/github.com/prometheus/common/expfmt/expfmt.go @@ -34,20 +34,21 @@ const ( TextVersion = "0.0.4" ProtoType = `application/vnd.google.protobuf` ProtoProtocol = `io.prometheus.client.MetricFamily` - ProtoFmt = ProtoType + "; proto=" + ProtoProtocol + ";" + protoFmt = ProtoType + "; proto=" + ProtoProtocol + ";" OpenMetricsType = `application/openmetrics-text` OpenMetricsVersion_0_0_1 = "0.0.1" OpenMetricsVersion_1_0_0 = "1.0.0" - // The Content-Type values for the different wire protocols. Do not do direct - // comparisons to these constants, instead use the comparison functions. - FmtUnknown Format = `` - FmtText Format = `text/plain; version=` + TextVersion + `; charset=utf-8` - FmtProtoDelim Format = ProtoFmt + ` encoding=delimited` - FmtProtoText Format = ProtoFmt + ` encoding=text` - FmtProtoCompact Format = ProtoFmt + ` encoding=compact-text` - FmtOpenMetrics_1_0_0 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_1_0_0 + `; charset=utf-8` - FmtOpenMetrics_0_0_1 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_0_0_1 + `; charset=utf-8` + // The Content-Type values for the different wire protocols. Note that these + // values are now unexported. If code was relying on comparisons to these + // constants, instead use FormatType(). + fmtUnknown Format = `` + fmtText Format = `text/plain; version=` + TextVersion + `; charset=utf-8` + fmtProtoDelim Format = protoFmt + ` encoding=delimited` + fmtProtoText Format = protoFmt + ` encoding=text` + fmtProtoCompact Format = protoFmt + ` encoding=compact-text` + fmtOpenMetrics_1_0_0 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_1_0_0 + `; charset=utf-8` + fmtOpenMetrics_0_0_1 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_0_0_1 + `; charset=utf-8` ) const ( @@ -70,6 +71,26 @@ const ( TypeOpenMetrics ) +// NewFormat generates a new Format from the type provided. Mostly used for +// tests, most Formats should be generated as part of content negotiation in +// encode.go. +func NewFormat(t FormatType) Format { + switch t { + case TypeProtoCompact: + return fmtProtoCompact + case TypeProtoDelim: + return fmtProtoDelim + case TypeProtoText: + return fmtProtoText + case TypeTextPlain: + return fmtText + case TypeOpenMetrics: + return fmtOpenMetrics_1_0_0 + default: + return fmtUnknown + } +} + // FormatType deduces an overall FormatType for the given format. func (f Format) FormatType() FormatType { toks := strings.Split(string(f), ";") diff --git a/vendor/github.com/prometheus/common/expfmt/openmetrics_create.go b/vendor/github.com/prometheus/common/expfmt/openmetrics_create.go index 5622578ed6..63fc1f4d16 100644 --- a/vendor/github.com/prometheus/common/expfmt/openmetrics_create.go +++ b/vendor/github.com/prometheus/common/expfmt/openmetrics_create.go @@ -22,11 +22,35 @@ import ( "strconv" "strings" + "google.golang.org/protobuf/types/known/timestamppb" + "github.com/prometheus/common/model" dto "github.com/prometheus/client_model/go" ) +type encoderOption struct { + withCreatedLines bool +} + +type EncoderOption func(*encoderOption) + +// WithCreatedLines is an EncoderOption that configures the OpenMetrics encoder +// to include _created lines (See +// https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#counter-1). +// Created timestamps can improve the accuracy of series reset detection, but +// come with a bandwidth cost. +// +// At the time of writing, created timestamp ingestion is still experimental in +// Prometheus and need to be enabled with the feature-flag +// `--feature-flag=created-timestamp-zero-ingestion`, and breaking changes are +// still possible. Therefore, it is recommended to use this feature with caution. +func WithCreatedLines() EncoderOption { + return func(t *encoderOption) { + t.withCreatedLines = true + } +} + // MetricFamilyToOpenMetrics converts a MetricFamily proto message into the // OpenMetrics text format and writes the resulting lines to 'out'. It returns // the number of bytes written and any error encountered. The output will have @@ -64,15 +88,20 @@ import ( // its type will be set to `unknown` in that case to avoid invalid OpenMetrics // output. // -// - No support for the following (optional) features: `# UNIT` line, `_created` -// line, info type, stateset type, gaugehistogram type. +// - No support for the following (optional) features: `# UNIT` line, info type, +// stateset type, gaugehistogram type. // // - The size of exemplar labels is not checked (i.e. it's possible to create // exemplars that are larger than allowed by the OpenMetrics specification). // // - The value of Counters is not checked. (OpenMetrics doesn't allow counters // with a `NaN` value.) -func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily) (written int, err error) { +func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily, options ...EncoderOption) (written int, err error) { + toOM := encoderOption{} + for _, option := range options { + option(&toOM) + } + name := in.GetName() if name == "" { return 0, fmt.Errorf("MetricFamily has no name: %s", in) @@ -164,6 +193,7 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily) (written int return } + var createdTsBytesWritten int // Finally the samples, one line for each. for _, metric := range in.Metric { switch metricType { @@ -181,6 +211,10 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily) (written int metric.Counter.GetValue(), 0, false, metric.Counter.Exemplar, ) + if toOM.withCreatedLines && metric.Counter.CreatedTimestamp != nil { + createdTsBytesWritten, err = writeOpenMetricsCreated(w, name, "_total", metric, "", 0, metric.Counter.GetCreatedTimestamp()) + n += createdTsBytesWritten + } case dto.MetricType_GAUGE: if metric.Gauge == nil { return written, fmt.Errorf( @@ -235,6 +269,10 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily) (written int 0, metric.Summary.GetSampleCount(), true, nil, ) + if toOM.withCreatedLines && metric.Summary.CreatedTimestamp != nil { + createdTsBytesWritten, err = writeOpenMetricsCreated(w, name, "", metric, "", 0, metric.Summary.GetCreatedTimestamp()) + n += createdTsBytesWritten + } case dto.MetricType_HISTOGRAM: if metric.Histogram == nil { return written, fmt.Errorf( @@ -283,6 +321,10 @@ func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily) (written int 0, metric.Histogram.GetSampleCount(), true, nil, ) + if toOM.withCreatedLines && metric.Histogram.CreatedTimestamp != nil { + createdTsBytesWritten, err = writeOpenMetricsCreated(w, name, "", metric, "", 0, metric.Histogram.GetCreatedTimestamp()) + n += createdTsBytesWritten + } default: return written, fmt.Errorf( "unexpected type in metric %s %s", name, metric, @@ -350,7 +392,7 @@ func writeOpenMetricsSample( return written, err } } - if exemplar != nil { + if exemplar != nil && len(exemplar.Label) > 0 { n, err = writeExemplar(w, exemplar) written += n if err != nil { @@ -473,6 +515,49 @@ func writeOpenMetricsNameAndLabelPairs( return written, nil } +// writeOpenMetricsCreated writes the created timestamp for a single time series +// following OpenMetrics text format to w, given the metric name, the metric proto +// message itself, optionally a suffix to be removed, e.g. '_total' for counters, +// an additional label name with a float64 value (use empty string as label name if +// not required) and the timestamp that represents the created timestamp. +// The function returns the number of bytes written and any error encountered. +func writeOpenMetricsCreated(w enhancedWriter, + name, suffixToTrim string, metric *dto.Metric, + additionalLabelName string, additionalLabelValue float64, + createdTimestamp *timestamppb.Timestamp, +) (int, error) { + written := 0 + n, err := writeOpenMetricsNameAndLabelPairs( + w, strings.TrimSuffix(name, suffixToTrim)+"_created", metric.Label, additionalLabelName, additionalLabelValue, + ) + written += n + if err != nil { + return written, err + } + + err = w.WriteByte(' ') + written++ + if err != nil { + return written, err + } + + // TODO(beorn7): Format this directly from components of ts to + // avoid overflow/underflow and precision issues of the float + // conversion. + n, err = writeOpenMetricsFloat(w, float64(createdTimestamp.AsTime().UnixNano())/1e9) + written += n + if err != nil { + return written, err + } + + err = w.WriteByte('\n') + written++ + if err != nil { + return written, err + } + return written, nil +} + // writeExemplar writes the provided exemplar in OpenMetrics format to w. The // function returns the number of bytes written and any error encountered. func writeExemplar(w enhancedWriter, e *dto.Exemplar) (int, error) { diff --git a/vendor/github.com/prometheus/common/model/labelset.go b/vendor/github.com/prometheus/common/model/labelset.go index 6eda08a739..ec738e6245 100644 --- a/vendor/github.com/prometheus/common/model/labelset.go +++ b/vendor/github.com/prometheus/common/model/labelset.go @@ -14,10 +14,12 @@ package model import ( + "bytes" "encoding/json" "fmt" + "slices" "sort" - "strings" + "strconv" ) // A LabelSet is a collection of LabelName and LabelValue pairs. The LabelSet @@ -129,14 +131,27 @@ func (l LabelSet) Merge(other LabelSet) LabelSet { return result } +// String will look like `{foo="bar", more="less"}`. Names are sorted alphabetically. func (l LabelSet) String() string { - lstrs := make([]string, 0, len(l)) - for l, v := range l { - lstrs = append(lstrs, fmt.Sprintf("%s=%q", l, v)) + var lna [32]LabelName // On stack to avoid memory allocation for sorting names. + labelNames := lna[:0] + for name := range l { + labelNames = append(labelNames, name) } - - sort.Strings(lstrs) - return fmt.Sprintf("{%s}", strings.Join(lstrs, ", ")) + slices.Sort(labelNames) + var bytea [1024]byte // On stack to avoid memory allocation while building the output. + b := bytes.NewBuffer(bytea[:0]) + b.WriteByte('{') + for i, name := range labelNames { + if i > 0 { + b.WriteString(", ") + } + b.WriteString(string(name)) + b.WriteByte('=') + b.Write(strconv.AppendQuote(b.AvailableBuffer(), string(l[name]))) + } + b.WriteByte('}') + return b.String() } // Fingerprint returns the LabelSet's fingerprint. diff --git a/vendor/github.com/prometheus/common/version/info.go b/vendor/github.com/prometheus/common/version/info.go index 28884dbc39..6b526d975f 100644 --- a/vendor/github.com/prometheus/common/version/info.go +++ b/vendor/github.com/prometheus/common/version/info.go @@ -35,6 +35,8 @@ var ( GoArch = runtime.GOARCH ) +// Deprecated: Use github.com/prometheus/client_golang/prometheus/collectors/version.NewCollector instead. +// // NewCollector returns a collector that exports metrics about current version // information. func NewCollector(program string) prometheus.Collector { diff --git a/vendor/github.com/prometheus/prometheus/config/config.go b/vendor/github.com/prometheus/prometheus/config/config.go index e81ee8dd0b..1cfd588643 100644 --- a/vendor/github.com/prometheus/prometheus/config/config.go +++ b/vendor/github.com/prometheus/prometheus/config/config.go @@ -941,6 +941,8 @@ type AlertmanagerConfig struct { // List of Alertmanager relabel configurations. RelabelConfigs []*relabel.Config `yaml:"relabel_configs,omitempty"` + // Relabel alerts before sending to the specific alertmanager. + AlertRelabelConfigs []*relabel.Config `yaml:"alert_relabel_configs,omitempty"` } // SetDirectory joins any relative file paths with dir. @@ -983,6 +985,12 @@ func (c *AlertmanagerConfig) UnmarshalYAML(unmarshal func(interface{}) error) er } } + for _, rlcfg := range c.AlertRelabelConfigs { + if rlcfg == nil { + return errors.New("empty or null Alertmanager alert relabeling rule") + } + } + return nil } diff --git a/vendor/github.com/prometheus/prometheus/model/labels/labels.go b/vendor/github.com/prometheus/prometheus/model/labels/labels.go index e998248269..01514abf38 100644 --- a/vendor/github.com/prometheus/prometheus/model/labels/labels.go +++ b/vendor/github.com/prometheus/prometheus/model/labels/labels.go @@ -349,7 +349,9 @@ func (ls Labels) DropMetricName() Labels { if i == 0 { // Make common case fast with no allocations. return ls[1:] } - return append(ls[:i], ls[i+1:]...) + // Avoid modifying original Labels - use [:i:i] so that left slice would not + // have any spare capacity and append would have to allocate a new slice for the result. + return append(ls[:i:i], ls[i+1:]...) } } return ls diff --git a/vendor/github.com/prometheus/prometheus/model/labels/labels_common.go b/vendor/github.com/prometheus/prometheus/model/labels/labels_common.go index 4c4a87e872..f46321c97e 100644 --- a/vendor/github.com/prometheus/prometheus/model/labels/labels_common.go +++ b/vendor/github.com/prometheus/prometheus/model/labels/labels_common.go @@ -39,7 +39,8 @@ type Label struct { } func (ls Labels) String() string { - var b bytes.Buffer + var bytea [1024]byte // On stack to avoid memory allocation while building the output. + b := bytes.NewBuffer(bytea[:0]) b.WriteByte('{') i := 0 @@ -50,7 +51,7 @@ func (ls Labels) String() string { } b.WriteString(l.Name) b.WriteByte('=') - b.WriteString(strconv.Quote(l.Value)) + b.Write(strconv.AppendQuote(b.AvailableBuffer(), l.Value)) i++ }) b.WriteByte('}') diff --git a/vendor/github.com/prometheus/prometheus/model/labels/labels_stringlabels.go b/vendor/github.com/prometheus/prometheus/model/labels/labels_stringlabels.go index 2e718c2b1f..9ef764daec 100644 --- a/vendor/github.com/prometheus/prometheus/model/labels/labels_stringlabels.go +++ b/vendor/github.com/prometheus/prometheus/model/labels/labels_stringlabels.go @@ -363,13 +363,11 @@ func Compare(a, b Labels) int { // Now we know that there is some difference before the end of a and b. // Go back through the fields and find which field that difference is in. - firstCharDifferent := i - for i = 0; ; { - size, nextI := decodeSize(a.data, i) - if nextI+size > firstCharDifferent { - break - } + firstCharDifferent, i := i, 0 + size, nextI := decodeSize(a.data, i) + for nextI+size <= firstCharDifferent { i = nextI + size + size, nextI = decodeSize(a.data, i) } // Difference is inside this entry. aStr, _ := decodeString(a.data, i) diff --git a/vendor/github.com/prometheus/prometheus/model/labels/matcher.go b/vendor/github.com/prometheus/prometheus/model/labels/matcher.go index f299c40f64..1282f80d63 100644 --- a/vendor/github.com/prometheus/prometheus/model/labels/matcher.go +++ b/vendor/github.com/prometheus/prometheus/model/labels/matcher.go @@ -118,3 +118,30 @@ func (m *Matcher) GetRegexString() string { } return m.re.GetRegexString() } + +// SetMatches returns a set of equality matchers for the current regex matchers if possible. +// For examples the regexp `a(b|f)` will returns "ab" and "af". +// Returns nil if we can't replace the regexp by only equality matchers. +func (m *Matcher) SetMatches() []string { + if m.re == nil { + return nil + } + return m.re.SetMatches() +} + +// Prefix returns the required prefix of the value to match, if possible. +// It will be empty if it's an equality matcher or if the prefix can't be determined. +func (m *Matcher) Prefix() string { + if m.re == nil { + return "" + } + return m.re.prefix +} + +// IsRegexOptimized returns whether regex is optimized. +func (m *Matcher) IsRegexOptimized() bool { + if m.re == nil { + return false + } + return m.re.IsOptimized() +} diff --git a/vendor/github.com/prometheus/prometheus/model/labels/regexp.go b/vendor/github.com/prometheus/prometheus/model/labels/regexp.go index 14319c7f7a..f35dc76f60 100644 --- a/vendor/github.com/prometheus/prometheus/model/labels/regexp.go +++ b/vendor/github.com/prometheus/prometheus/model/labels/regexp.go @@ -14,73 +14,348 @@ package labels import ( + "slices" "strings" "github.com/grafana/regexp" "github.com/grafana/regexp/syntax" ) +const ( + maxSetMatches = 256 + + // The minimum number of alternate values a regex should have to trigger + // the optimization done by optimizeEqualStringMatchers() and so use a map + // to match values instead of iterating over a list. This value has + // been computed running BenchmarkOptimizeEqualStringMatchers. + minEqualMultiStringMatcherMapThreshold = 16 +) + type FastRegexMatcher struct { + // Under some conditions, re is nil because the expression is never parsed. + // We store the original string to be able to return it in GetRegexString(). + reString string re *regexp.Regexp - prefix string - suffix string - contains string - // shortcut for literals - literal bool - value string + setMatches []string + stringMatcher StringMatcher + prefix string + suffix string + contains string + + // matchString is the "compiled" function to run by MatchString(). + matchString func(string) bool } func NewFastRegexMatcher(v string) (*FastRegexMatcher, error) { - if isLiteral(v) { - return &FastRegexMatcher{literal: true, value: v}, nil + m := &FastRegexMatcher{ + reString: v, } - re, err := regexp.Compile("^(?:" + v + ")$") - if err != nil { - return nil, err + + m.stringMatcher, m.setMatches = optimizeAlternatingLiterals(v) + if m.stringMatcher != nil { + // If we already have a string matcher, we don't need to parse the regex + // or compile the matchString function. This also avoids the behavior in + // compileMatchStringFunction where it prefers to use setMatches when + // available, even if the string matcher is faster. + m.matchString = m.stringMatcher.Matches + } else { + parsed, err := syntax.Parse(v, syntax.Perl) + if err != nil { + return nil, err + } + // Simplify the syntax tree to run faster. + parsed = parsed.Simplify() + m.re, err = regexp.Compile("^(?:" + parsed.String() + ")$") + if err != nil { + return nil, err + } + if parsed.Op == syntax.OpConcat { + m.prefix, m.suffix, m.contains = optimizeConcatRegex(parsed) + } + if matches, caseSensitive := findSetMatches(parsed); caseSensitive { + m.setMatches = matches + } + m.stringMatcher = stringMatcherFromRegexp(parsed) + m.matchString = m.compileMatchStringFunction() } - parsed, err := syntax.Parse(v, syntax.Perl) - if err != nil { - return nil, err + return m, nil +} + +// compileMatchStringFunction returns the function to run by MatchString(). +func (m *FastRegexMatcher) compileMatchStringFunction() func(string) bool { + // If the only optimization available is the string matcher, then we can just run it. + if len(m.setMatches) == 0 && m.prefix == "" && m.suffix == "" && m.contains == "" && m.stringMatcher != nil { + return m.stringMatcher.Matches } - m := &FastRegexMatcher{ - re: re, + return func(s string) bool { + if len(m.setMatches) != 0 { + for _, match := range m.setMatches { + if match == s { + return true + } + } + return false + } + if m.prefix != "" && !strings.HasPrefix(s, m.prefix) { + return false + } + if m.suffix != "" && !strings.HasSuffix(s, m.suffix) { + return false + } + if m.contains != "" && !strings.Contains(s, m.contains) { + return false + } + if m.stringMatcher != nil { + return m.stringMatcher.Matches(s) + } + return m.re.MatchString(s) } +} + +// IsOptimized returns true if any fast-path optimization is applied to the +// regex matcher. +func (m *FastRegexMatcher) IsOptimized() bool { + return len(m.setMatches) > 0 || m.stringMatcher != nil || m.prefix != "" || m.suffix != "" || m.contains != "" +} + +// findSetMatches extract equality matches from a regexp. +// Returns nil if we can't replace the regexp by only equality matchers or the regexp contains +// a mix of case sensitive and case insensitive matchers. +func findSetMatches(re *syntax.Regexp) (matches []string, caseSensitive bool) { + clearBeginEndText(re) + + return findSetMatchesInternal(re, "") +} - if parsed.Op == syntax.OpConcat { - m.prefix, m.suffix, m.contains = optimizeConcatRegex(parsed) +func findSetMatchesInternal(re *syntax.Regexp, base string) (matches []string, caseSensitive bool) { + switch re.Op { + case syntax.OpBeginText: + // Correctly handling the begin text operator inside a regex is tricky, + // so in this case we fallback to the regex engine. + return nil, false + case syntax.OpEndText: + // Correctly handling the end text operator inside a regex is tricky, + // so in this case we fallback to the regex engine. + return nil, false + case syntax.OpLiteral: + return []string{base + string(re.Rune)}, isCaseSensitive(re) + case syntax.OpEmptyMatch: + if base != "" { + return []string{base}, isCaseSensitive(re) + } + case syntax.OpAlternate: + return findSetMatchesFromAlternate(re, base) + case syntax.OpCapture: + clearCapture(re) + return findSetMatchesInternal(re, base) + case syntax.OpConcat: + return findSetMatchesFromConcat(re, base) + case syntax.OpCharClass: + if len(re.Rune)%2 != 0 { + return nil, false + } + var matches []string + var totalSet int + for i := 0; i+1 < len(re.Rune); i += 2 { + totalSet += int(re.Rune[i+1]-re.Rune[i]) + 1 + } + // limits the total characters that can be used to create matches. + // In some case like negation [^0-9] a lot of possibilities exists and that + // can create thousands of possible matches at which points we're better off using regexp. + if totalSet > maxSetMatches { + return nil, false + } + for i := 0; i+1 < len(re.Rune); i += 2 { + lo, hi := re.Rune[i], re.Rune[i+1] + for c := lo; c <= hi; c++ { + matches = append(matches, base+string(c)) + } + } + return matches, isCaseSensitive(re) + default: + return nil, false } + return nil, false +} - return m, nil +func findSetMatchesFromConcat(re *syntax.Regexp, base string) (matches []string, matchesCaseSensitive bool) { + if len(re.Sub) == 0 { + return nil, false + } + clearCapture(re.Sub...) + + matches = []string{base} + + for i := 0; i < len(re.Sub); i++ { + var newMatches []string + for j, b := range matches { + m, caseSensitive := findSetMatchesInternal(re.Sub[i], b) + if m == nil { + return nil, false + } + if tooManyMatches(newMatches, m...) { + return nil, false + } + + // All matches must have the same case sensitivity. If it's the first set of matches + // returned, we store its sensitivity as the expected case, and then we'll check all + // other ones. + if i == 0 && j == 0 { + matchesCaseSensitive = caseSensitive + } + if matchesCaseSensitive != caseSensitive { + return nil, false + } + + newMatches = append(newMatches, m...) + } + matches = newMatches + } + + return matches, matchesCaseSensitive } -func (m *FastRegexMatcher) MatchString(s string) bool { - if m.literal { - return s == m.value +func findSetMatchesFromAlternate(re *syntax.Regexp, base string) (matches []string, matchesCaseSensitive bool) { + for i, sub := range re.Sub { + found, caseSensitive := findSetMatchesInternal(sub, base) + if found == nil { + return nil, false + } + if tooManyMatches(matches, found...) { + return nil, false + } + + // All matches must have the same case sensitivity. If it's the first set of matches + // returned, we store its sensitivity as the expected case, and then we'll check all + // other ones. + if i == 0 { + matchesCaseSensitive = caseSensitive + } + if matchesCaseSensitive != caseSensitive { + return nil, false + } + + matches = append(matches, found...) } - if m.prefix != "" && !strings.HasPrefix(s, m.prefix) { - return false + + return matches, matchesCaseSensitive +} + +// clearCapture removes capture operation as they are not used for matching. +func clearCapture(regs ...*syntax.Regexp) { + for _, r := range regs { + // Iterate on the regexp because capture groups could be nested. + for r.Op == syntax.OpCapture { + *r = *r.Sub[0] + } } - if m.suffix != "" && !strings.HasSuffix(s, m.suffix) { - return false +} + +// clearBeginEndText removes the begin and end text from the regexp. Prometheus regexp are anchored to the beginning and end of the string. +func clearBeginEndText(re *syntax.Regexp) { + // Do not clear begin/end text from an alternate operator because it could + // change the actual regexp properties. + if re.Op == syntax.OpAlternate { + return } - if m.contains != "" && !strings.Contains(s, m.contains) { - return false + + if len(re.Sub) == 0 { + return + } + if len(re.Sub) == 1 { + if re.Sub[0].Op == syntax.OpBeginText || re.Sub[0].Op == syntax.OpEndText { + // We need to remove this element. Since it's the only one, we convert into a matcher of an empty string. + // OpEmptyMatch is regexp's nop operator. + re.Op = syntax.OpEmptyMatch + re.Sub = nil + return + } } - return m.re.MatchString(s) + if re.Sub[0].Op == syntax.OpBeginText { + re.Sub = re.Sub[1:] + } + if re.Sub[len(re.Sub)-1].Op == syntax.OpEndText { + re.Sub = re.Sub[:len(re.Sub)-1] + } +} + +// isCaseInsensitive tells if a regexp is case insensitive. +// The flag should be check at each level of the syntax tree. +func isCaseInsensitive(reg *syntax.Regexp) bool { + return (reg.Flags & syntax.FoldCase) != 0 +} + +// isCaseSensitive tells if a regexp is case sensitive. +// The flag should be check at each level of the syntax tree. +func isCaseSensitive(reg *syntax.Regexp) bool { + return !isCaseInsensitive(reg) +} + +// tooManyMatches guards against creating too many set matches. +func tooManyMatches(matches []string, added ...string) bool { + return len(matches)+len(added) > maxSetMatches +} + +func (m *FastRegexMatcher) MatchString(s string) bool { + return m.matchString(s) +} + +func (m *FastRegexMatcher) SetMatches() []string { + // IMPORTANT: always return a copy, otherwise if the caller manipulate this slice it will + // also get manipulated in the cached FastRegexMatcher instance. + return slices.Clone(m.setMatches) } func (m *FastRegexMatcher) GetRegexString() string { - if m.literal { - return m.value - } - return m.re.String() + return m.reString } -func isLiteral(re string) bool { - return regexp.QuoteMeta(re) == re +// optimizeAlternatingLiterals optimizes a regex of the form +// +// `literal1|literal2|literal3|...` +// +// this function returns an optimized StringMatcher or nil if the regex +// cannot be optimized in this way, and a list of setMatches up to maxSetMatches. +func optimizeAlternatingLiterals(s string) (StringMatcher, []string) { + if len(s) == 0 { + return emptyStringMatcher{}, nil + } + + estimatedAlternates := strings.Count(s, "|") + 1 + + // If there are no alternates, check if the string is a literal + if estimatedAlternates == 1 { + if regexp.QuoteMeta(s) == s { + return &equalStringMatcher{s: s, caseSensitive: true}, []string{s} + } + return nil, nil + } + + multiMatcher := newEqualMultiStringMatcher(true, estimatedAlternates) + + for end := strings.IndexByte(s, '|'); end > -1; end = strings.IndexByte(s, '|') { + // Split the string into the next literal and the remainder + subMatch := s[:end] + s = s[end+1:] + + // break if any of the submatches are not literals + if regexp.QuoteMeta(subMatch) != subMatch { + return nil, nil + } + + multiMatcher.add(subMatch) + } + + // break if the remainder is not a literal + if regexp.QuoteMeta(s) != s { + return nil, nil + } + multiMatcher.add(s) + + return multiMatcher, multiMatcher.setMatches() } // optimizeConcatRegex returns literal prefix/suffix text that can be safely @@ -123,3 +398,540 @@ func optimizeConcatRegex(r *syntax.Regexp) (prefix, suffix, contains string) { return } + +// StringMatcher is a matcher that matches a string in place of a regular expression. +type StringMatcher interface { + Matches(s string) bool +} + +// stringMatcherFromRegexp attempts to replace a common regexp with a string matcher. +// It returns nil if the regexp is not supported. +func stringMatcherFromRegexp(re *syntax.Regexp) StringMatcher { + clearBeginEndText(re) + + m := stringMatcherFromRegexpInternal(re) + m = optimizeEqualStringMatchers(m, minEqualMultiStringMatcherMapThreshold) + + return m +} + +func stringMatcherFromRegexpInternal(re *syntax.Regexp) StringMatcher { + clearCapture(re) + + switch re.Op { + case syntax.OpBeginText: + // Correctly handling the begin text operator inside a regex is tricky, + // so in this case we fallback to the regex engine. + return nil + case syntax.OpEndText: + // Correctly handling the end text operator inside a regex is tricky, + // so in this case we fallback to the regex engine. + return nil + case syntax.OpPlus: + if re.Sub[0].Op != syntax.OpAnyChar && re.Sub[0].Op != syntax.OpAnyCharNotNL { + return nil + } + return &anyNonEmptyStringMatcher{ + matchNL: re.Sub[0].Op == syntax.OpAnyChar, + } + case syntax.OpStar: + if re.Sub[0].Op != syntax.OpAnyChar && re.Sub[0].Op != syntax.OpAnyCharNotNL { + return nil + } + + // If the newline is valid, than this matcher literally match any string (even empty). + if re.Sub[0].Op == syntax.OpAnyChar { + return trueMatcher{} + } + + // Any string is fine (including an empty one), as far as it doesn't contain any newline. + return anyStringWithoutNewlineMatcher{} + case syntax.OpQuest: + // Only optimize for ".?". + if len(re.Sub) != 1 || (re.Sub[0].Op != syntax.OpAnyChar && re.Sub[0].Op != syntax.OpAnyCharNotNL) { + return nil + } + + return &zeroOrOneCharacterStringMatcher{ + matchNL: re.Sub[0].Op == syntax.OpAnyChar, + } + case syntax.OpEmptyMatch: + return emptyStringMatcher{} + + case syntax.OpLiteral: + return &equalStringMatcher{ + s: string(re.Rune), + caseSensitive: !isCaseInsensitive(re), + } + case syntax.OpAlternate: + or := make([]StringMatcher, 0, len(re.Sub)) + for _, sub := range re.Sub { + m := stringMatcherFromRegexpInternal(sub) + if m == nil { + return nil + } + or = append(or, m) + } + return orStringMatcher(or) + case syntax.OpConcat: + clearCapture(re.Sub...) + + if len(re.Sub) == 0 { + return emptyStringMatcher{} + } + if len(re.Sub) == 1 { + return stringMatcherFromRegexpInternal(re.Sub[0]) + } + + var left, right StringMatcher + + // Let's try to find if there's a first and last any matchers. + if re.Sub[0].Op == syntax.OpPlus || re.Sub[0].Op == syntax.OpStar || re.Sub[0].Op == syntax.OpQuest { + left = stringMatcherFromRegexpInternal(re.Sub[0]) + if left == nil { + return nil + } + re.Sub = re.Sub[1:] + } + if re.Sub[len(re.Sub)-1].Op == syntax.OpPlus || re.Sub[len(re.Sub)-1].Op == syntax.OpStar || re.Sub[len(re.Sub)-1].Op == syntax.OpQuest { + right = stringMatcherFromRegexpInternal(re.Sub[len(re.Sub)-1]) + if right == nil { + return nil + } + re.Sub = re.Sub[:len(re.Sub)-1] + } + + matches, matchesCaseSensitive := findSetMatchesInternal(re, "") + + if len(matches) == 0 && len(re.Sub) == 2 { + // We have not find fixed set matches. We look for other known cases that + // we can optimize. + switch { + // Prefix is literal. + case right == nil && re.Sub[0].Op == syntax.OpLiteral: + right = stringMatcherFromRegexpInternal(re.Sub[1]) + if right != nil { + matches = []string{string(re.Sub[0].Rune)} + matchesCaseSensitive = !isCaseInsensitive(re.Sub[0]) + } + + // Suffix is literal. + case left == nil && re.Sub[1].Op == syntax.OpLiteral: + left = stringMatcherFromRegexpInternal(re.Sub[0]) + if left != nil { + matches = []string{string(re.Sub[1].Rune)} + matchesCaseSensitive = !isCaseInsensitive(re.Sub[1]) + } + } + } + + // Ensure we've found some literals to match (optionally with a left and/or right matcher). + // If not, then this optimization doesn't trigger. + if len(matches) == 0 { + return nil + } + + // Use the right (and best) matcher based on what we've found. + switch { + // No left and right matchers (only fixed set matches). + case left == nil && right == nil: + // if there's no any matchers on both side it's a concat of literals + or := make([]StringMatcher, 0, len(matches)) + for _, match := range matches { + or = append(or, &equalStringMatcher{ + s: match, + caseSensitive: matchesCaseSensitive, + }) + } + return orStringMatcher(or) + + // Right matcher with 1 fixed set match. + case left == nil && len(matches) == 1: + return &literalPrefixStringMatcher{ + prefix: matches[0], + prefixCaseSensitive: matchesCaseSensitive, + right: right, + } + + // Left matcher with 1 fixed set match. + case right == nil && len(matches) == 1: + return &literalSuffixStringMatcher{ + left: left, + suffix: matches[0], + suffixCaseSensitive: matchesCaseSensitive, + } + + // We found literals in the middle. We can trigger the fast path only if + // the matches are case sensitive because containsStringMatcher doesn't + // support case insensitive. + case matchesCaseSensitive: + return &containsStringMatcher{ + substrings: matches, + left: left, + right: right, + } + } + } + return nil +} + +// containsStringMatcher matches a string if it contains any of the substrings. +// If left and right are not nil, it's a contains operation where left and right must match. +// If left is nil, it's a hasPrefix operation and right must match. +// Finally, if right is nil it's a hasSuffix operation and left must match. +type containsStringMatcher struct { + // The matcher that must match the left side. Can be nil. + left StringMatcher + + // At least one of these strings must match in the "middle", between left and right matchers. + substrings []string + + // The matcher that must match the right side. Can be nil. + right StringMatcher +} + +func (m *containsStringMatcher) Matches(s string) bool { + for _, substr := range m.substrings { + switch { + case m.right != nil && m.left != nil: + searchStartPos := 0 + + for { + pos := strings.Index(s[searchStartPos:], substr) + if pos < 0 { + break + } + + // Since we started searching from searchStartPos, we have to add that offset + // to get the actual position of the substring inside the text. + pos += searchStartPos + + // If both the left and right matchers match, then we can stop searching because + // we've found a match. + if m.left.Matches(s[:pos]) && m.right.Matches(s[pos+len(substr):]) { + return true + } + + // Continue searching for another occurrence of the substring inside the text. + searchStartPos = pos + 1 + } + case m.left != nil: + // If we have to check for characters on the left then we need to match a suffix. + if strings.HasSuffix(s, substr) && m.left.Matches(s[:len(s)-len(substr)]) { + return true + } + case m.right != nil: + if strings.HasPrefix(s, substr) && m.right.Matches(s[len(substr):]) { + return true + } + } + } + return false +} + +// literalPrefixStringMatcher matches a string with the given literal prefix and right side matcher. +type literalPrefixStringMatcher struct { + prefix string + prefixCaseSensitive bool + + // The matcher that must match the right side. Can be nil. + right StringMatcher +} + +func (m *literalPrefixStringMatcher) Matches(s string) bool { + // Ensure the prefix matches. + if m.prefixCaseSensitive && !strings.HasPrefix(s, m.prefix) { + return false + } + if !m.prefixCaseSensitive && !hasPrefixCaseInsensitive(s, m.prefix) { + return false + } + + // Ensure the right side matches. + return m.right.Matches(s[len(m.prefix):]) +} + +// literalSuffixStringMatcher matches a string with the given literal suffix and left side matcher. +type literalSuffixStringMatcher struct { + // The matcher that must match the left side. Can be nil. + left StringMatcher + + suffix string + suffixCaseSensitive bool +} + +func (m *literalSuffixStringMatcher) Matches(s string) bool { + // Ensure the suffix matches. + if m.suffixCaseSensitive && !strings.HasSuffix(s, m.suffix) { + return false + } + if !m.suffixCaseSensitive && !hasSuffixCaseInsensitive(s, m.suffix) { + return false + } + + // Ensure the left side matches. + return m.left.Matches(s[:len(s)-len(m.suffix)]) +} + +// emptyStringMatcher matches an empty string. +type emptyStringMatcher struct{} + +func (m emptyStringMatcher) Matches(s string) bool { + return len(s) == 0 +} + +// orStringMatcher matches any of the sub-matchers. +type orStringMatcher []StringMatcher + +func (m orStringMatcher) Matches(s string) bool { + for _, matcher := range m { + if matcher.Matches(s) { + return true + } + } + return false +} + +// equalStringMatcher matches a string exactly and support case insensitive. +type equalStringMatcher struct { + s string + caseSensitive bool +} + +func (m *equalStringMatcher) Matches(s string) bool { + if m.caseSensitive { + return m.s == s + } + return strings.EqualFold(m.s, s) +} + +type multiStringMatcherBuilder interface { + StringMatcher + add(s string) + setMatches() []string +} + +func newEqualMultiStringMatcher(caseSensitive bool, estimatedSize int) multiStringMatcherBuilder { + // If the estimated size is low enough, it's faster to use a slice instead of a map. + if estimatedSize < minEqualMultiStringMatcherMapThreshold { + return &equalMultiStringSliceMatcher{caseSensitive: caseSensitive, values: make([]string, 0, estimatedSize)} + } + + return &equalMultiStringMapMatcher{ + values: make(map[string]struct{}, estimatedSize), + caseSensitive: caseSensitive, + } +} + +// equalMultiStringSliceMatcher matches a string exactly against a slice of valid values. +type equalMultiStringSliceMatcher struct { + values []string + + caseSensitive bool +} + +func (m *equalMultiStringSliceMatcher) add(s string) { + m.values = append(m.values, s) +} + +func (m *equalMultiStringSliceMatcher) setMatches() []string { + return m.values +} + +func (m *equalMultiStringSliceMatcher) Matches(s string) bool { + if m.caseSensitive { + for _, v := range m.values { + if s == v { + return true + } + } + } else { + for _, v := range m.values { + if strings.EqualFold(s, v) { + return true + } + } + } + return false +} + +// equalMultiStringMapMatcher matches a string exactly against a map of valid values. +type equalMultiStringMapMatcher struct { + // values contains values to match a string against. If the matching is case insensitive, + // the values here must be lowercase. + values map[string]struct{} + + caseSensitive bool +} + +func (m *equalMultiStringMapMatcher) add(s string) { + if !m.caseSensitive { + s = strings.ToLower(s) + } + + m.values[s] = struct{}{} +} + +func (m *equalMultiStringMapMatcher) setMatches() []string { + if len(m.values) >= maxSetMatches { + return nil + } + + matches := make([]string, 0, len(m.values)) + for s := range m.values { + matches = append(matches, s) + } + return matches +} + +func (m *equalMultiStringMapMatcher) Matches(s string) bool { + if !m.caseSensitive { + s = strings.ToLower(s) + } + + _, ok := m.values[s] + return ok +} + +// anyStringWithoutNewlineMatcher is a stringMatcher which matches any string +// (including an empty one) as far as it doesn't contain any newline character. +type anyStringWithoutNewlineMatcher struct{} + +func (m anyStringWithoutNewlineMatcher) Matches(s string) bool { + // We need to make sure it doesn't contain a newline. Since the newline is + // an ASCII character, we can use strings.IndexByte(). + return strings.IndexByte(s, '\n') == -1 +} + +// anyNonEmptyStringMatcher is a stringMatcher which matches any non-empty string. +type anyNonEmptyStringMatcher struct { + matchNL bool +} + +func (m *anyNonEmptyStringMatcher) Matches(s string) bool { + if m.matchNL { + // It's OK if the string contains a newline so we just need to make + // sure it's non-empty. + return len(s) > 0 + } + + // We need to make sure it non-empty and doesn't contain a newline. + // Since the newline is an ASCII character, we can use strings.IndexByte(). + return len(s) > 0 && strings.IndexByte(s, '\n') == -1 +} + +// zeroOrOneCharacterStringMatcher is a StringMatcher which matches zero or one occurrence +// of any character. The newline character is matches only if matchNL is set to true. +type zeroOrOneCharacterStringMatcher struct { + matchNL bool +} + +func (m *zeroOrOneCharacterStringMatcher) Matches(s string) bool { + // Zero or one. + if len(s) > 1 { + return false + } + + // No need to check for the newline if the string is empty or matching a newline is OK. + if m.matchNL || len(s) == 0 { + return true + } + + return s[0] != '\n' +} + +// trueMatcher is a stringMatcher which matches any string (always returns true). +type trueMatcher struct{} + +func (m trueMatcher) Matches(_ string) bool { + return true +} + +// optimizeEqualStringMatchers optimize a specific case where all matchers are made by an +// alternation (orStringMatcher) of strings checked for equality (equalStringMatcher). In +// this specific case, when we have many strings to match against we can use a map instead +// of iterating over the list of strings. +func optimizeEqualStringMatchers(input StringMatcher, threshold int) StringMatcher { + var ( + caseSensitive bool + caseSensitiveSet bool + numValues int + ) + + // Analyse the input StringMatcher to count the number of occurrences + // and ensure all of them have the same case sensitivity. + analyseCallback := func(matcher *equalStringMatcher) bool { + // Ensure we don't have mixed case sensitivity. + if caseSensitiveSet && caseSensitive != matcher.caseSensitive { + return false + } else if !caseSensitiveSet { + caseSensitive = matcher.caseSensitive + caseSensitiveSet = true + } + + numValues++ + return true + } + + if !findEqualStringMatchers(input, analyseCallback) { + return input + } + + // If the number of values found is less than the threshold, then we should skip the optimization. + if numValues < threshold { + return input + } + + // Parse again the input StringMatcher to extract all values and storing them. + // We can skip the case sensitivity check because we've already checked it and + // if the code reach this point then it means all matchers have the same case sensitivity. + multiMatcher := newEqualMultiStringMatcher(caseSensitive, numValues) + + // Ignore the return value because we already iterated over the input StringMatcher + // and it was all good. + findEqualStringMatchers(input, func(matcher *equalStringMatcher) bool { + multiMatcher.add(matcher.s) + return true + }) + + return multiMatcher +} + +// findEqualStringMatchers analyze the input StringMatcher and calls the callback for each +// equalStringMatcher found. Returns true if and only if the input StringMatcher is *only* +// composed by an alternation of equalStringMatcher. +func findEqualStringMatchers(input StringMatcher, callback func(matcher *equalStringMatcher) bool) bool { + orInput, ok := input.(orStringMatcher) + if !ok { + return false + } + + for _, m := range orInput { + switch casted := m.(type) { + case orStringMatcher: + if !findEqualStringMatchers(m, callback) { + return false + } + + case *equalStringMatcher: + if !callback(casted) { + return false + } + + default: + // It's not an equal string matcher, so we have to stop searching + // cause this optimization can't be applied. + return false + } + } + + return true +} + +func hasPrefixCaseInsensitive(s, prefix string) bool { + return len(s) >= len(prefix) && strings.EqualFold(s[0:len(prefix)], prefix) +} + +func hasSuffixCaseInsensitive(s, suffix string) bool { + return len(s) >= len(suffix) && strings.EqualFold(s[len(s)-len(suffix):], suffix) +} diff --git a/vendor/github.com/prometheus/prometheus/model/textparse/interface.go b/vendor/github.com/prometheus/prometheus/model/textparse/interface.go index 2e8c40e72f..df01dbc34f 100644 --- a/vendor/github.com/prometheus/prometheus/model/textparse/interface.go +++ b/vendor/github.com/prometheus/prometheus/model/textparse/interface.go @@ -71,8 +71,8 @@ type Parser interface { // if the scrape protocol or metric type does not support created timestamps. CreatedTimestamp() *int64 - // Next advances the parser to the next sample. It returns false if no - // more samples were read or an error occurred. + // Next advances the parser to the next sample. + // It returns (EntryInvalid, io.EOF) if no samples were read. Next() (Entry, error) } diff --git a/vendor/github.com/prometheus/prometheus/model/textparse/openmetricsparse.go b/vendor/github.com/prometheus/prometheus/model/textparse/openmetricsparse.go index ea92bc55f4..b7ad1dd85c 100644 --- a/vendor/github.com/prometheus/prometheus/model/textparse/openmetricsparse.go +++ b/vendor/github.com/prometheus/prometheus/model/textparse/openmetricsparse.go @@ -239,8 +239,8 @@ func (p *OpenMetricsParser) parseError(exp string, got token) error { return fmt.Errorf("%s, got %q (%q) while parsing: %q", exp, p.l.b[p.l.start:e], got, p.l.b[p.start:e]) } -// Next advances the parser to the next sample. It returns false if no -// more samples were read or an error occurred. +// Next advances the parser to the next sample. +// It returns (EntryInvalid, io.EOF) if no samples were read. func (p *OpenMetricsParser) Next() (Entry, error) { var err error diff --git a/vendor/github.com/prometheus/prometheus/model/textparse/promparse.go b/vendor/github.com/prometheus/prometheus/model/textparse/promparse.go index 54b5306e6a..a611f3aea7 100644 --- a/vendor/github.com/prometheus/prometheus/model/textparse/promparse.go +++ b/vendor/github.com/prometheus/prometheus/model/textparse/promparse.go @@ -280,8 +280,8 @@ func (p *PromParser) parseError(exp string, got token) error { return fmt.Errorf("%s, got %q (%q) while parsing: %q", exp, p.l.b[p.l.start:e], got, p.l.b[p.start:e]) } -// Next advances the parser to the next sample. It returns false if no -// more samples were read or an error occurred. +// Next advances the parser to the next sample. +// It returns (EntryInvalid, io.EOF) if no samples were read. func (p *PromParser) Next() (Entry, error) { var err error diff --git a/vendor/github.com/prometheus/prometheus/notifier/notifier.go b/vendor/github.com/prometheus/prometheus/notifier/notifier.go index af55799337..d1832402f7 100644 --- a/vendor/github.com/prometheus/prometheus/notifier/notifier.go +++ b/vendor/github.com/prometheus/prometheus/notifier/notifier.go @@ -350,7 +350,7 @@ func (n *Manager) Send(alerts ...*Alert) { n.mtx.Lock() defer n.mtx.Unlock() - alerts = n.relabelAlerts(alerts) + alerts = relabelAlerts(n.opts.RelabelConfigs, n.opts.ExternalLabels, alerts) if len(alerts) == 0 { return } @@ -378,20 +378,19 @@ func (n *Manager) Send(alerts ...*Alert) { n.setMore() } -// Attach external labels and process relabelling rules. -func (n *Manager) relabelAlerts(alerts []*Alert) []*Alert { +func relabelAlerts(relabelConfigs []*relabel.Config, externalLabels labels.Labels, alerts []*Alert) []*Alert { lb := labels.NewBuilder(labels.EmptyLabels()) var relabeledAlerts []*Alert for _, a := range alerts { lb.Reset(a.Labels) - n.opts.ExternalLabels.Range(func(l labels.Label) { + externalLabels.Range(func(l labels.Label) { if a.Labels.Get(l.Name) == "" { lb.Set(l.Name, l.Value) } }) - keep := relabel.ProcessBuilder(lb, n.opts.RelabelConfigs...) + keep := relabel.ProcessBuilder(lb, relabelConfigs...) if !keep { continue } @@ -473,17 +472,27 @@ func (n *Manager) sendAll(alerts ...*Alert) bool { ) for _, ams := range amSets { var ( - payload []byte - err error + payload []byte + err error + amAlerts = alerts ) ams.mtx.RLock() + if len(ams.cfg.AlertRelabelConfigs) > 0 { + amAlerts = relabelAlerts(ams.cfg.AlertRelabelConfigs, labels.Labels{}, alerts) + if len(amAlerts) == 0 { + continue + } + // We can't use the cached values from previous iteration. + v1Payload, v2Payload = nil, nil + } + switch ams.cfg.APIVersion { case config.AlertmanagerAPIVersionV1: { if v1Payload == nil { - v1Payload, err = json.Marshal(alerts) + v1Payload, err = json.Marshal(amAlerts) if err != nil { level.Error(n.logger).Log("msg", "Encoding alerts for Alertmanager API v1 failed", "err", err) ams.mtx.RUnlock() @@ -496,7 +505,7 @@ func (n *Manager) sendAll(alerts ...*Alert) bool { case config.AlertmanagerAPIVersionV2: { if v2Payload == nil { - openAPIAlerts := alertsToOpenAPIAlerts(alerts) + openAPIAlerts := alertsToOpenAPIAlerts(amAlerts) v2Payload, err = json.Marshal(openAPIAlerts) if err != nil { @@ -519,24 +528,29 @@ func (n *Manager) sendAll(alerts ...*Alert) bool { } } + if len(ams.cfg.AlertRelabelConfigs) > 0 { + // We can't use the cached values on the next iteration. + v1Payload, v2Payload = nil, nil + } + for _, am := range ams.ams { wg.Add(1) ctx, cancel := context.WithTimeout(n.ctx, time.Duration(ams.cfg.Timeout)) defer cancel() - go func(client *http.Client, url string) { + go func(ctx context.Context, client *http.Client, url string, payload []byte, count int) { if err := n.sendOne(ctx, client, url, payload); err != nil { - level.Error(n.logger).Log("alertmanager", url, "count", len(alerts), "msg", "Error sending alert", "err", err) + level.Error(n.logger).Log("alertmanager", url, "count", count, "msg", "Error sending alert", "err", err) n.metrics.errors.WithLabelValues(url).Inc() } else { numSuccess.Inc() } n.metrics.latency.WithLabelValues(url).Observe(time.Since(begin).Seconds()) - n.metrics.sent.WithLabelValues(url).Add(float64(len(alerts))) + n.metrics.sent.WithLabelValues(url).Add(float64(len(amAlerts))) wg.Done() - }(ams.client, am.url().String()) + }(ctx, ams.client, am.url().String(), payload, len(amAlerts)) } ams.mtx.RUnlock() diff --git a/vendor/github.com/prometheus/prometheus/promql/engine.go b/vendor/github.com/prometheus/prometheus/promql/engine.go index 68e0502907..cf60f477af 100644 --- a/vendor/github.com/prometheus/prometheus/promql/engine.go +++ b/vendor/github.com/prometheus/prometheus/promql/engine.go @@ -115,6 +115,12 @@ func (e ErrStorage) Error() string { return e.Err.Error() } +// QueryEngine defines the interface for the *promql.Engine, so it can be replaced, wrapped or mocked. +type QueryEngine interface { + NewInstantQuery(ctx context.Context, q storage.Queryable, opts QueryOpts, qs string, ts time.Time) (Query, error) + NewRangeQuery(ctx context.Context, q storage.Queryable, opts QueryOpts, qs string, start, end time.Time, interval time.Duration) (Query, error) +} + // QueryLogger is an interface that can be used to log all the queries logged // by the engine. type QueryLogger interface { @@ -1196,6 +1202,9 @@ func (ev *evaluator) rangeEval(prepSeries func(labels.Labels, *EvalSeriesHelper) if prepSeries != nil { bufHelpers[i] = append(bufHelpers[i], seriesHelpers[i][si]) } + // Don't add histogram size here because we only + // copy the pointer above, not the whole + // histogram. ev.currentSamples++ if ev.currentSamples > ev.maxSamples { ev.error(ErrTooManySamples(env)) @@ -1221,7 +1230,6 @@ func (ev *evaluator) rangeEval(prepSeries func(labels.Labels, *EvalSeriesHelper) if ev.currentSamples > ev.maxSamples { ev.error(ErrTooManySamples(env)) } - ev.samplesStats.UpdatePeak(ev.currentSamples) // If this could be an instant query, shortcut so as not to change sort order. if ev.endTimestamp == ev.startTimestamp { @@ -1540,13 +1548,12 @@ func (ev *evaluator) eval(expr parser.Expr) (parser.Value, annotations.Annotatio histSamples := totalHPointSize(ss.Histograms) if len(ss.Floats)+histSamples > 0 { - if ev.currentSamples+len(ss.Floats)+histSamples <= ev.maxSamples { - mat = append(mat, ss) - prevSS = &mat[len(mat)-1] - ev.currentSamples += len(ss.Floats) + histSamples - } else { + if ev.currentSamples+len(ss.Floats)+histSamples > ev.maxSamples { ev.error(ErrTooManySamples(env)) } + mat = append(mat, ss) + prevSS = &mat[len(mat)-1] + ev.currentSamples += len(ss.Floats) + histSamples } ev.samplesStats.UpdatePeak(ev.currentSamples) @@ -1709,26 +1716,28 @@ func (ev *evaluator) eval(expr parser.Expr) (parser.Value, annotations.Annotatio step++ _, f, h, ok := ev.vectorSelectorSingle(it, e, ts) if ok { - if ev.currentSamples < ev.maxSamples { - if h == nil { - if ss.Floats == nil { - ss.Floats = reuseOrGetFPointSlices(prevSS, numSteps) - } - ss.Floats = append(ss.Floats, FPoint{F: f, T: ts}) - ev.currentSamples++ - ev.samplesStats.IncrementSamplesAtStep(step, 1) - } else { - if ss.Histograms == nil { - ss.Histograms = reuseOrGetHPointSlices(prevSS, numSteps) - } - point := HPoint{H: h, T: ts} - ss.Histograms = append(ss.Histograms, point) - histSize := point.size() - ev.currentSamples += histSize - ev.samplesStats.IncrementSamplesAtStep(step, int64(histSize)) + if h == nil { + ev.currentSamples++ + ev.samplesStats.IncrementSamplesAtStep(step, 1) + if ev.currentSamples > ev.maxSamples { + ev.error(ErrTooManySamples(env)) } + if ss.Floats == nil { + ss.Floats = reuseOrGetFPointSlices(prevSS, numSteps) + } + ss.Floats = append(ss.Floats, FPoint{F: f, T: ts}) } else { - ev.error(ErrTooManySamples(env)) + point := HPoint{H: h, T: ts} + histSize := point.size() + ev.currentSamples += histSize + ev.samplesStats.IncrementSamplesAtStep(step, int64(histSize)) + if ev.currentSamples > ev.maxSamples { + ev.error(ErrTooManySamples(env)) + } + if ss.Histograms == nil { + ss.Histograms = reuseOrGetHPointSlices(prevSS, numSteps) + } + ss.Histograms = append(ss.Histograms, point) } } } @@ -1856,7 +1865,7 @@ func (ev *evaluator) eval(expr parser.Expr) (parser.Value, annotations.Annotatio panic(fmt.Errorf("unhandled expression of type: %T", expr)) } -// reuseOrGetFPointSlices reuses the space from previous slice to create new slice if the former has lots of room. +// reuseOrGetHPointSlices reuses the space from previous slice to create new slice if the former has lots of room. // The previous slices capacity is adjusted so when it is re-used from the pool it doesn't overflow into the new one. func reuseOrGetHPointSlices(prevSS *Series, numSteps int) (r []HPoint) { if prevSS != nil && cap(prevSS.Histograms)-2*len(prevSS.Histograms) > 0 { @@ -2168,10 +2177,10 @@ loop: histograms = histograms[:n] continue loop } - if ev.currentSamples >= ev.maxSamples { + ev.currentSamples += histograms[n].size() + if ev.currentSamples > ev.maxSamples { ev.error(ErrTooManySamples(env)) } - ev.currentSamples += histograms[n].size() } case chunkenc.ValFloat: t, f := buf.At() @@ -2180,10 +2189,10 @@ loop: } // Values in the buffer are guaranteed to be smaller than maxt. if t >= mintFloats { - if ev.currentSamples >= ev.maxSamples { + ev.currentSamples++ + if ev.currentSamples > ev.maxSamples { ev.error(ErrTooManySamples(env)) } - ev.currentSamples++ if floats == nil { floats = getFPointSlice(16) } @@ -2211,22 +2220,22 @@ loop: histograms = histograms[:n] break } - if ev.currentSamples >= ev.maxSamples { + ev.currentSamples += histograms[n].size() + if ev.currentSamples > ev.maxSamples { ev.error(ErrTooManySamples(env)) } - ev.currentSamples += histograms[n].size() case chunkenc.ValFloat: t, f := it.At() if t == maxt && !value.IsStaleNaN(f) { - if ev.currentSamples >= ev.maxSamples { + ev.currentSamples++ + if ev.currentSamples > ev.maxSamples { ev.error(ErrTooManySamples(env)) } if floats == nil { floats = getFPointSlice(16) } floats = append(floats, FPoint{T: t, F: f}) - ev.currentSamples++ } } ev.samplesStats.UpdatePeak(ev.currentSamples) diff --git a/vendor/github.com/prometheus/prometheus/promql/functions.go b/vendor/github.com/prometheus/prometheus/promql/functions.go index ae044d5961..0cfbcc3452 100644 --- a/vendor/github.com/prometheus/prometheus/promql/functions.go +++ b/vendor/github.com/prometheus/prometheus/promql/functions.go @@ -128,7 +128,16 @@ func extrapolatedRate(vals []parser.Value, args parser.Expressions, enh *EvalNod sampledInterval := float64(lastT-firstT) / 1000 averageDurationBetweenSamples := sampledInterval / float64(numSamplesMinusOne) - // TODO(beorn7): Do this for histograms, too. + // If the first/last samples are close to the boundaries of the range, + // extrapolate the result. This is as we expect that another sample + // will exist given the spacing between samples we've seen thus far, + // with an allowance for noise. + extrapolationThreshold := averageDurationBetweenSamples * 1.1 + extrapolateToInterval := sampledInterval + + if durationToStart >= extrapolationThreshold { + durationToStart = averageDurationBetweenSamples / 2 + } if isCounter && resultFloat > 0 && len(samples.Floats) > 0 && samples.Floats[0].F >= 0 { // Counters cannot be negative. If we have any slope at all // (i.e. resultFloat went up), we can extrapolate the zero point @@ -136,29 +145,19 @@ func extrapolatedRate(vals []parser.Value, args parser.Expressions, enh *EvalNod // than the durationToStart, we take the zero point as the start // of the series, thereby avoiding extrapolation to negative // counter values. + // TODO(beorn7): Do this for histograms, too. durationToZero := sampledInterval * (samples.Floats[0].F / resultFloat) if durationToZero < durationToStart { durationToStart = durationToZero } } + extrapolateToInterval += durationToStart - // If the first/last samples are close to the boundaries of the range, - // extrapolate the result. This is as we expect that another sample - // will exist given the spacing between samples we've seen thus far, - // with an allowance for noise. - extrapolationThreshold := averageDurationBetweenSamples * 1.1 - extrapolateToInterval := sampledInterval - - if durationToStart < extrapolationThreshold { - extrapolateToInterval += durationToStart - } else { - extrapolateToInterval += averageDurationBetweenSamples / 2 - } - if durationToEnd < extrapolationThreshold { - extrapolateToInterval += durationToEnd - } else { - extrapolateToInterval += averageDurationBetweenSamples / 2 + if durationToEnd >= extrapolationThreshold { + durationToEnd = averageDurationBetweenSamples / 2 } + extrapolateToInterval += durationToEnd + factor := extrapolateToInterval / sampledInterval if isRate { factor /= ms.Range.Seconds() @@ -1112,11 +1111,17 @@ func funcHistogramStdDev(vals []parser.Value, args parser.Expressions, enh *Eval it := sample.H.AllBucketIterator() for it.Next() { bucket := it.At() + if bucket.Count == 0 { + continue + } var val float64 if bucket.Lower <= 0 && 0 <= bucket.Upper { val = 0 } else { val = math.Sqrt(bucket.Upper * bucket.Lower) + if bucket.Upper < 0 { + val = -val + } } delta := val - mean variance, cVariance = kahanSumInc(bucket.Count*delta*delta, variance, cVariance) @@ -1145,11 +1150,17 @@ func funcHistogramStdVar(vals []parser.Value, args parser.Expressions, enh *Eval it := sample.H.AllBucketIterator() for it.Next() { bucket := it.At() + if bucket.Count == 0 { + continue + } var val float64 if bucket.Lower <= 0 && 0 <= bucket.Upper { val = 0 } else { val = math.Sqrt(bucket.Upper * bucket.Lower) + if bucket.Upper < 0 { + val = -val + } } delta := val - mean variance, cVariance = kahanSumInc(bucket.Count*delta*delta, variance, cVariance) @@ -1387,6 +1398,9 @@ func (ev *evaluator) evalLabelJoin(args parser.Expressions) (parser.Value, annot } srcLabels[i-3] = src } + if !model.LabelName(dst).IsValid() { + panic(fmt.Errorf("invalid destination label name in label_join(): %s", dst)) + } val, ws := ev.eval(args[0]) matrix := val.(Matrix) diff --git a/vendor/github.com/prometheus/prometheus/promql/test.go b/vendor/github.com/prometheus/prometheus/promql/test.go index 589b1e5b6b..ba716d1eea 100644 --- a/vendor/github.com/prometheus/prometheus/promql/test.go +++ b/vendor/github.com/prometheus/prometheus/promql/test.go @@ -46,6 +46,7 @@ var ( patSpace = regexp.MustCompile("[\t ]+") patLoad = regexp.MustCompile(`^load\s+(.+?)$`) patEvalInstant = regexp.MustCompile(`^eval(?:_(fail|ordered))?\s+instant\s+(?:at\s+(.+?))?\s+(.+)$`) + patEvalRange = regexp.MustCompile(`^eval(?:_(fail))?\s+range\s+from\s+(.+)\s+to\s+(.+)\s+step\s+(.+?)\s+(.+)$`) ) const ( @@ -72,7 +73,7 @@ func LoadedStorage(t testutil.T, input string) *teststorage.TestStorage { } // RunBuiltinTests runs an acceptance test suite against the provided engine. -func RunBuiltinTests(t *testing.T, engine engineQuerier) { +func RunBuiltinTests(t *testing.T, engine QueryEngine) { t.Cleanup(func() { parser.EnableExperimentalFunctions = false }) parser.EnableExperimentalFunctions = true @@ -89,11 +90,19 @@ func RunBuiltinTests(t *testing.T, engine engineQuerier) { } // RunTest parses and runs the test against the provided engine. -func RunTest(t testutil.T, input string, engine engineQuerier) { +func RunTest(t testutil.T, input string, engine QueryEngine) { + require.NoError(t, runTest(t, input, engine)) +} + +func runTest(t testutil.T, input string, engine QueryEngine) error { test, err := newTest(t, input) - require.NoError(t, err) + // Why do this before checking err? newTest() can create the test storage and then return an error, + // and we want to make sure to clean that up to avoid leaking goroutines. defer func() { + if test == nil { + return + } if test.storage != nil { test.storage.Close() } @@ -102,11 +111,19 @@ func RunTest(t testutil.T, input string, engine engineQuerier) { } }() + if err != nil { + return err + } + for _, cmd := range test.cmds { - // TODO(fabxc): aggregate command errors, yield diffs for result - // comparison errors. - require.NoError(t, test.exec(cmd, engine)) + if err := test.exec(cmd, engine); err != nil { + // TODO(fabxc): aggregate command errors, yield diffs for result + // comparison errors. + return err + } } + + return nil } // test is a sequence of read and write commands that are run @@ -137,11 +154,6 @@ func newTest(t testutil.T, input string) (*test, error) { //go:embed testdata var testsFs embed.FS -type engineQuerier interface { - NewRangeQuery(ctx context.Context, q storage.Queryable, opts QueryOpts, qs string, start, end time.Time, interval time.Duration) (Query, error) - NewInstantQuery(ctx context.Context, q storage.Queryable, opts QueryOpts, qs string, ts time.Time) (Query, error) -} - func raise(line int, format string, v ...interface{}) error { return &parser.ParseErr{ LineOffset: line, @@ -188,15 +200,26 @@ func parseSeries(defLine string, line int) (labels.Labels, []parser.SequenceValu } func (t *test) parseEval(lines []string, i int) (int, *evalCmd, error) { - if !patEvalInstant.MatchString(lines[i]) { - return i, nil, raise(i, "invalid evaluation command. (eval[_fail|_ordered] instant [at ] ") - } - parts := patEvalInstant.FindStringSubmatch(lines[i]) - var ( - mod = parts[1] - at = parts[2] - expr = parts[3] - ) + instantParts := patEvalInstant.FindStringSubmatch(lines[i]) + rangeParts := patEvalRange.FindStringSubmatch(lines[i]) + + if instantParts == nil && rangeParts == nil { + return i, nil, raise(i, "invalid evaluation command. Must be either 'eval[_fail|_ordered] instant [at ] ' or 'eval[_fail] range from to step '") + } + + isInstant := instantParts != nil + + var mod string + var expr string + + if isInstant { + mod = instantParts[1] + expr = instantParts[3] + } else { + mod = rangeParts[1] + expr = rangeParts[5] + } + _, err := parser.ParseExpr(expr) if err != nil { parser.EnrichParseError(err, func(parseErr *parser.ParseErr) { @@ -209,15 +232,54 @@ func (t *test) parseEval(lines []string, i int) (int, *evalCmd, error) { return i, nil, err } - offset, err := model.ParseDuration(at) - if err != nil { - return i, nil, raise(i, "invalid step definition %q: %s", parts[1], err) + formatErr := func(format string, args ...any) error { + combinedArgs := []any{expr, i + 1} + + combinedArgs = append(combinedArgs, args...) + return fmt.Errorf("error in eval %s (line %v): "+format, combinedArgs...) + } + + var cmd *evalCmd + + if isInstant { + at := instantParts[2] + offset, err := model.ParseDuration(at) + if err != nil { + return i, nil, formatErr("invalid timestamp definition %q: %s", at, err) + } + ts := testStartTime.Add(time.Duration(offset)) + cmd = newInstantEvalCmd(expr, ts, i+1) + } else { + from := rangeParts[2] + to := rangeParts[3] + step := rangeParts[4] + + parsedFrom, err := model.ParseDuration(from) + if err != nil { + return i, nil, formatErr("invalid start timestamp definition %q: %s", from, err) + } + + parsedTo, err := model.ParseDuration(to) + if err != nil { + return i, nil, formatErr("invalid end timestamp definition %q: %s", to, err) + } + + if parsedTo < parsedFrom { + return i, nil, formatErr("invalid test definition, end timestamp (%s) is before start timestamp (%s)", to, from) + } + + parsedStep, err := model.ParseDuration(step) + if err != nil { + return i, nil, formatErr("invalid step definition %q: %s", step, err) + } + + cmd = newRangeEvalCmd(expr, testStartTime.Add(time.Duration(parsedFrom)), testStartTime.Add(time.Duration(parsedTo)), time.Duration(parsedStep), i+1) } - ts := testStartTime.Add(time.Duration(offset)) - cmd := newEvalCmd(expr, ts, i+1) switch mod { case "ordered": + // Ordered results are not supported for range queries, but the regex for range query commands does not allow + // asserting an ordered result, so we don't need to do any error checking here. cmd.ordered = true case "fail": cmd.fail = true @@ -240,8 +302,8 @@ func (t *test) parseEval(lines []string, i int) (int, *evalCmd, error) { } // Currently, we are not expecting any matrices. - if len(vals) > 1 { - return i, nil, raise(i, "expecting multiple values in instant evaluation not allowed") + if len(vals) > 1 && isInstant { + return i, nil, formatErr("expecting multiple values in instant evaluation not allowed") } cmd.expectMetric(j, metric, vals...) } @@ -375,8 +437,11 @@ func appendSample(a storage.Appender, s Sample, m labels.Labels) error { type evalCmd struct { expr string start time.Time + end time.Time + step time.Duration line int + isRange bool // if false, instant query fail, ordered bool metrics map[uint64]labels.Labels @@ -392,7 +457,7 @@ func (e entry) String() string { return fmt.Sprintf("%d: %s", e.pos, e.vals) } -func newEvalCmd(expr string, start time.Time, line int) *evalCmd { +func newInstantEvalCmd(expr string, start time.Time, line int) *evalCmd { return &evalCmd{ expr: expr, start: start, @@ -403,6 +468,20 @@ func newEvalCmd(expr string, start time.Time, line int) *evalCmd { } } +func newRangeEvalCmd(expr string, start, end time.Time, step time.Duration, line int) *evalCmd { + return &evalCmd{ + expr: expr, + start: start, + end: end, + step: step, + line: line, + isRange: true, + + metrics: map[uint64]labels.Labels{}, + expected: map[uint64]entry{}, + } +} + func (ev *evalCmd) String() string { return "eval" } @@ -425,7 +504,77 @@ func (ev *evalCmd) expectMetric(pos int, m labels.Labels, vals ...parser.Sequenc func (ev *evalCmd) compareResult(result parser.Value) error { switch val := result.(type) { case Matrix: - return errors.New("received range result on instant evaluation") + if ev.ordered { + return fmt.Errorf("expected ordered result, but query returned a matrix") + } + + if err := assertMatrixSorted(val); err != nil { + return err + } + + seen := map[uint64]bool{} + for _, s := range val { + hash := s.Metric.Hash() + if _, ok := ev.metrics[hash]; !ok { + return fmt.Errorf("unexpected metric %s in result", s.Metric) + } + seen[hash] = true + exp := ev.expected[hash] + + var expectedFloats []FPoint + var expectedHistograms []HPoint + + for i, e := range exp.vals { + ts := ev.start.Add(time.Duration(i) * ev.step) + + if ts.After(ev.end) { + return fmt.Errorf("expected %v points for %s, but query time range cannot return this many points", len(exp.vals), ev.metrics[hash]) + } + + t := ts.UnixNano() / int64(time.Millisecond/time.Nanosecond) + + if e.Histogram != nil { + expectedHistograms = append(expectedHistograms, HPoint{T: t, H: e.Histogram}) + } else if !e.Omitted { + expectedFloats = append(expectedFloats, FPoint{T: t, F: e.Value}) + } + } + + if len(expectedFloats) != len(s.Floats) || len(expectedHistograms) != len(s.Histograms) { + return fmt.Errorf("expected %v float points and %v histogram points for %s, but got %s", len(expectedFloats), len(expectedHistograms), ev.metrics[hash], formatSeriesResult(s)) + } + + for i, expected := range expectedFloats { + actual := s.Floats[i] + + if expected.T != actual.T { + return fmt.Errorf("expected float value at index %v for %s to have timestamp %v, but it had timestamp %v (result has %s)", i, ev.metrics[hash], expected.T, actual.T, formatSeriesResult(s)) + } + + if !almostEqual(actual.F, expected.F, defaultEpsilon) { + return fmt.Errorf("expected float value at index %v (t=%v) for %s to be %v, but got %v (result has %s)", i, actual.T, ev.metrics[hash], expected.F, actual.F, formatSeriesResult(s)) + } + } + + for i, expected := range expectedHistograms { + actual := s.Histograms[i] + + if expected.T != actual.T { + return fmt.Errorf("expected histogram value at index %v for %s to have timestamp %v, but it had timestamp %v (result has %s)", i, ev.metrics[hash], expected.T, actual.T, formatSeriesResult(s)) + } + + if !actual.H.Equals(expected.H.Compact(0)) { + return fmt.Errorf("expected histogram value at index %v (t=%v) for %s to be %v, but got %v (result has %s)", i, actual.T, ev.metrics[hash], expected.H, actual.H, formatSeriesResult(s)) + } + } + + } + + for hash := range ev.expected { + if !seen[hash] { + return fmt.Errorf("expected metric %s not found", ev.metrics[hash]) + } + } case Vector: seen := map[uint64]bool{} @@ -440,7 +589,13 @@ func (ev *evalCmd) compareResult(result parser.Value) error { } exp0 := exp.vals[0] expH := exp0.Histogram - if (expH == nil) != (v.H == nil) || (expH != nil && !expH.Equals(v.H)) { + if expH == nil && v.H != nil { + return fmt.Errorf("expected float value %v for %s but got histogram %s", exp0, v.Metric, HistogramTestExpression(v.H)) + } + if expH != nil && v.H == nil { + return fmt.Errorf("expected histogram %s for %s but got float value %v", HistogramTestExpression(expH), v.Metric, v.F) + } + if expH != nil && !expH.Compact(0).Equals(v.H) { return fmt.Errorf("expected %v for %s but got %s", HistogramTestExpression(expH), v.Metric, HistogramTestExpression(v.H)) } if !almostEqual(exp0.Value, v.F, defaultEpsilon) { @@ -451,10 +606,6 @@ func (ev *evalCmd) compareResult(result parser.Value) error { } for fp, expVals := range ev.expected { if !seen[fp] { - fmt.Println("vector result", len(val), ev.expr) - for _, ss := range val { - fmt.Println(" ", ss.Metric, ss.T, ss.F) - } return fmt.Errorf("expected metric %s with %v not found", ev.metrics[fp], expVals) } } @@ -477,6 +628,21 @@ func (ev *evalCmd) compareResult(result parser.Value) error { return nil } +func formatSeriesResult(s Series) string { + floatPlural := "s" + histogramPlural := "s" + + if len(s.Floats) == 1 { + floatPlural = "" + } + + if len(s.Histograms) == 1 { + histogramPlural = "" + } + + return fmt.Sprintf("%v float point%s %v and %v histogram point%s %v", len(s.Floats), floatPlural, s.Floats, len(s.Histograms), histogramPlural, s.Histograms) +} + // HistogramTestExpression returns TestExpression() for the given histogram or "" if the histogram is nil. func HistogramTestExpression(h *histogram.FloatHistogram) string { if h != nil { @@ -561,7 +727,7 @@ func atModifierTestCases(exprStr string, evalTime time.Time) ([]atModifierTestCa } // exec processes a single step of the test. -func (t *test) exec(tc testCommand, engine engineQuerier) error { +func (t *test) exec(tc testCommand, engine QueryEngine) error { switch cmd := tc.(type) { case *clearCmd: t.clear() @@ -578,78 +744,137 @@ func (t *test) exec(tc testCommand, engine engineQuerier) error { } case *evalCmd: - queries, err := atModifierTestCases(cmd.expr, cmd.start) + return t.execEval(cmd, engine) + + default: + panic("promql.Test.exec: unknown test command type") + } + return nil +} + +func (t *test) execEval(cmd *evalCmd, engine QueryEngine) error { + if cmd.isRange { + return t.execRangeEval(cmd, engine) + } + + return t.execInstantEval(cmd, engine) +} + +func (t *test) execRangeEval(cmd *evalCmd, engine QueryEngine) error { + q, err := engine.NewRangeQuery(t.context, t.storage, nil, cmd.expr, cmd.start, cmd.end, cmd.step) + if err != nil { + return err + } + res := q.Exec(t.context) + if res.Err != nil { + if cmd.fail { + return nil + } + + return fmt.Errorf("error evaluating query %q (line %d): %w", cmd.expr, cmd.line, res.Err) + } + if res.Err == nil && cmd.fail { + return fmt.Errorf("expected error evaluating query %q (line %d) but got none", cmd.expr, cmd.line) + } + defer q.Close() + + if err := cmd.compareResult(res.Value); err != nil { + return fmt.Errorf("error in %s %s (line %d): %w", cmd, cmd.expr, cmd.line, err) + } + + return nil +} + +func (t *test) execInstantEval(cmd *evalCmd, engine QueryEngine) error { + queries, err := atModifierTestCases(cmd.expr, cmd.start) + if err != nil { + return err + } + queries = append([]atModifierTestCase{{expr: cmd.expr, evalTime: cmd.start}}, queries...) + for _, iq := range queries { + q, err := engine.NewInstantQuery(t.context, t.storage, nil, iq.expr, iq.evalTime) if err != nil { return err } - queries = append([]atModifierTestCase{{expr: cmd.expr, evalTime: cmd.start}}, queries...) - for _, iq := range queries { - q, err := engine.NewInstantQuery(t.context, t.storage, nil, iq.expr, iq.evalTime) - if err != nil { - return err - } - defer q.Close() - res := q.Exec(t.context) - if res.Err != nil { - if cmd.fail { - continue - } - return fmt.Errorf("error evaluating query %q (line %d): %w", iq.expr, cmd.line, res.Err) - } - if res.Err == nil && cmd.fail { - return fmt.Errorf("expected error evaluating query %q (line %d) but got none", iq.expr, cmd.line) - } - err = cmd.compareResult(res.Value) - if err != nil { - return fmt.Errorf("error in %s %s (line %d): %w", cmd, iq.expr, cmd.line, err) - } - - // Check query returns same result in range mode, - // by checking against the middle step. - q, err = engine.NewRangeQuery(t.context, t.storage, nil, iq.expr, iq.evalTime.Add(-time.Minute), iq.evalTime.Add(time.Minute), time.Minute) - if err != nil { - return err - } - rangeRes := q.Exec(t.context) - if rangeRes.Err != nil { - return fmt.Errorf("error evaluating query %q (line %d) in range mode: %w", iq.expr, cmd.line, rangeRes.Err) - } - defer q.Close() - if cmd.ordered { - // Ordering isn't defined for range queries. + defer q.Close() + res := q.Exec(t.context) + if res.Err != nil { + if cmd.fail { continue } - mat := rangeRes.Value.(Matrix) - vec := make(Vector, 0, len(mat)) - for _, series := range mat { - // We expect either Floats or Histograms. - for _, point := range series.Floats { - if point.T == timeMilliseconds(iq.evalTime) { - vec = append(vec, Sample{Metric: series.Metric, T: point.T, F: point.F}) - break - } - } - for _, point := range series.Histograms { - if point.T == timeMilliseconds(iq.evalTime) { - vec = append(vec, Sample{Metric: series.Metric, T: point.T, H: point.H}) - break - } + return fmt.Errorf("error evaluating query %q (line %d): %w", iq.expr, cmd.line, res.Err) + } + if res.Err == nil && cmd.fail { + return fmt.Errorf("expected error evaluating query %q (line %d) but got none", iq.expr, cmd.line) + } + err = cmd.compareResult(res.Value) + if err != nil { + return fmt.Errorf("error in %s %s (line %d): %w", cmd, iq.expr, cmd.line, err) + } + + // Check query returns same result in range mode, + // by checking against the middle step. + q, err = engine.NewRangeQuery(t.context, t.storage, nil, iq.expr, iq.evalTime.Add(-time.Minute), iq.evalTime.Add(time.Minute), time.Minute) + if err != nil { + return err + } + rangeRes := q.Exec(t.context) + if rangeRes.Err != nil { + return fmt.Errorf("error evaluating query %q (line %d) in range mode: %w", iq.expr, cmd.line, rangeRes.Err) + } + defer q.Close() + if cmd.ordered { + // Range queries are always sorted by labels, so skip this test case that expects results in a particular order. + continue + } + mat := rangeRes.Value.(Matrix) + if err := assertMatrixSorted(mat); err != nil { + return err + } + + vec := make(Vector, 0, len(mat)) + for _, series := range mat { + // We expect either Floats or Histograms. + for _, point := range series.Floats { + if point.T == timeMilliseconds(iq.evalTime) { + vec = append(vec, Sample{Metric: series.Metric, T: point.T, F: point.F}) + break } } - if _, ok := res.Value.(Scalar); ok { - err = cmd.compareResult(Scalar{V: vec[0].F}) - } else { - err = cmd.compareResult(vec) - } - if err != nil { - return fmt.Errorf("error in %s %s (line %d) range mode: %w", cmd, iq.expr, cmd.line, err) + for _, point := range series.Histograms { + if point.T == timeMilliseconds(iq.evalTime) { + vec = append(vec, Sample{Metric: series.Metric, T: point.T, H: point.H}) + break + } } - } + if _, ok := res.Value.(Scalar); ok { + err = cmd.compareResult(Scalar{V: vec[0].F}) + } else { + err = cmd.compareResult(vec) + } + if err != nil { + return fmt.Errorf("error in %s %s (line %d) range mode: %w", cmd, iq.expr, cmd.line, err) + } + } - default: - panic("promql.Test.exec: unknown test command type") + return nil +} + +func assertMatrixSorted(m Matrix) error { + if len(m) <= 1 { + return nil } + + for i, s := range m[:len(m)-1] { + nextIndex := i + 1 + nextMetric := m[nextIndex].Metric + + if labels.Compare(s.Metric, nextMetric) > 0 { + return fmt.Errorf("matrix results should always be sorted by labels, but matrix is not sorted: series at index %v with labels %s sorts before series at index %v with labels %s", nextIndex, nextMetric, i, s.Metric) + } + } + return nil } @@ -704,8 +929,6 @@ func parseNumber(s string) (float64, error) { // LazyLoader lazily loads samples into storage. // This is specifically implemented for unit testing of rules. type LazyLoader struct { - testutil.T - loadCmd *loadCmd storage storage.Storage @@ -727,13 +950,15 @@ type LazyLoaderOpts struct { } // NewLazyLoader returns an initialized empty LazyLoader. -func NewLazyLoader(t testutil.T, input string, opts LazyLoaderOpts) (*LazyLoader, error) { +func NewLazyLoader(input string, opts LazyLoaderOpts) (*LazyLoader, error) { ll := &LazyLoader{ - T: t, opts: opts, } err := ll.parse(input) - ll.clear() + if err != nil { + return nil, err + } + err = ll.clear() return ll, err } @@ -761,15 +986,20 @@ func (ll *LazyLoader) parse(input string) error { } // clear the current test storage of all inserted samples. -func (ll *LazyLoader) clear() { +func (ll *LazyLoader) clear() error { if ll.storage != nil { - err := ll.storage.Close() - require.NoError(ll.T, err, "Unexpected error while closing test storage.") + if err := ll.storage.Close(); err != nil { + return fmt.Errorf("closing test storage: %w", err) + } } if ll.cancelCtx != nil { ll.cancelCtx() } - ll.storage = teststorage.New(ll) + var err error + ll.storage, err = teststorage.NewWithError() + if err != nil { + return err + } opts := EngineOpts{ Logger: nil, @@ -783,6 +1013,7 @@ func (ll *LazyLoader) clear() { ll.queryEngine = NewEngine(opts) ll.context, ll.cancelCtx = context.WithCancel(context.Background()) + return nil } // appendTill appends the defined time series to the storage till the given timestamp (in milliseconds). @@ -836,8 +1067,7 @@ func (ll *LazyLoader) Storage() storage.Storage { } // Close closes resources associated with the LazyLoader. -func (ll *LazyLoader) Close() { +func (ll *LazyLoader) Close() error { ll.cancelCtx() - err := ll.storage.Close() - require.NoError(ll.T, err, "Unexpected error while closing test storage.") + return ll.storage.Close() } diff --git a/vendor/github.com/prometheus/prometheus/promql/testdata/functions.test b/vendor/github.com/prometheus/prometheus/promql/testdata/functions.test index 4e104e406e..e01c75a7f6 100644 --- a/vendor/github.com/prometheus/prometheus/promql/testdata/functions.test +++ b/vendor/github.com/prometheus/prometheus/promql/testdata/functions.test @@ -71,15 +71,28 @@ clear load 5m http_requests{path="/foo"} 0+10x10 http_requests{path="/bar"} 0+10x5 0+10x5 + http_requests{path="/dings"} 10+10x10 + http_requests{path="/bumms"} 1+10x10 # Tests for increase(). eval instant at 50m increase(http_requests[50m]) - {path="/foo"} 100 - {path="/bar"} 90 - + {path="/foo"} 100 + {path="/bar"} 90 + {path="/dings"} 100 + {path="/bumms"} 100 + +# "foo" and "bar" are already at value 0 at t=0, so no extrapolation +# happens. "dings" has value 10 at t=0 and would reach 0 at t=-5m. The +# normal extrapolation by half a sample interval only goes to +# t=-2m30s, so that's not yet reaching a negative value and therefore +# chosen. However, "bumms" has value 1 at t=0 and would reach 0 at +# t=-30s. Here the extrapolation to t=-2m30s would reach a negative +# value, and therefore the extrapolation happens only by 30s. eval instant at 50m increase(http_requests[100m]) - {path="/foo"} 100 - {path="/bar"} 90 + {path="/foo"} 100 + {path="/bar"} 90 + {path="/dings"} 105 + {path="/bumms"} 101 clear @@ -133,13 +146,15 @@ load 4m testcounter_zero_cutoff{start="4m"} 240+240x10 testcounter_zero_cutoff{start="5m"} 300+240x10 -# Zero cutoff for left-side extrapolation. +# Zero cutoff for left-side extrapolation happens until we +# reach half a sampling interval (2m). Beyond that, we only +# extrapolate by half a sampling interval. eval instant at 10m rate(testcounter_zero_cutoff[20m]) {start="0m"} 0.5 {start="1m"} 0.55 {start="2m"} 0.6 - {start="3m"} 0.65 - {start="4m"} 0.7 + {start="3m"} 0.6 + {start="4m"} 0.6 {start="5m"} 0.6 # Normal half-interval cutoff for left-side extrapolation. diff --git a/vendor/github.com/prometheus/prometheus/rules/group.go b/vendor/github.com/prometheus/prometheus/rules/group.go index b8694a255e..c268d2df7d 100644 --- a/vendor/github.com/prometheus/prometheus/rules/group.go +++ b/vendor/github.com/prometheus/prometheus/rules/group.go @@ -546,13 +546,13 @@ func (g *Group) Eval(ctx context.Context, ts time.Time) { } } if numOutOfOrder > 0 { - level.Warn(logger).Log("msg", "Error on ingesting out-of-order result from rule evaluation", "numDropped", numOutOfOrder) + level.Warn(logger).Log("msg", "Error on ingesting out-of-order result from rule evaluation", "num_dropped", numOutOfOrder) } if numTooOld > 0 { - level.Warn(logger).Log("msg", "Error on ingesting too old result from rule evaluation", "numDropped", numTooOld) + level.Warn(logger).Log("msg", "Error on ingesting too old result from rule evaluation", "num_dropped", numTooOld) } if numDuplicates > 0 { - level.Warn(logger).Log("msg", "Error on ingesting results from rule evaluation with different value but same timestamp", "numDropped", numDuplicates) + level.Warn(logger).Log("msg", "Error on ingesting results from rule evaluation with different value but same timestamp", "num_dropped", numDuplicates) } for metric, lset := range g.seriesInPreviousEval[i] { diff --git a/vendor/github.com/prometheus/prometheus/rules/manager.go b/vendor/github.com/prometheus/prometheus/rules/manager.go index e87d55b1e1..165dca144e 100644 --- a/vendor/github.com/prometheus/prometheus/rules/manager.go +++ b/vendor/github.com/prometheus/prometheus/rules/manager.go @@ -43,7 +43,7 @@ type QueryFunc func(ctx context.Context, q string, t time.Time) (promql.Vector, // EngineQueryFunc returns a new query function that executes instant queries against // the given engine. // It converts scalar into vector results. -func EngineQueryFunc(engine *promql.Engine, q storage.Queryable) QueryFunc { +func EngineQueryFunc(engine promql.QueryEngine, q storage.Queryable) QueryFunc { return func(ctx context.Context, qs string, t time.Time) (promql.Vector, error) { q, err := engine.NewInstantQuery(ctx, q, nil, qs, t) if err != nil { diff --git a/vendor/github.com/prometheus/prometheus/scrape/scrape.go b/vendor/github.com/prometheus/prometheus/scrape/scrape.go index 6ac3c551c1..734c248130 100644 --- a/vendor/github.com/prometheus/prometheus/scrape/scrape.go +++ b/vendor/github.com/prometheus/prometheus/scrape/scrape.go @@ -427,6 +427,7 @@ func (sp *scrapePool) sync(targets []*Target) { bodySizeLimit = int64(sp.config.BodySizeLimit) sampleLimit = int(sp.config.SampleLimit) bucketLimit = int(sp.config.NativeHistogramBucketLimit) + maxSchema = pickSchema(sp.config.NativeHistogramMinBucketFactor) labelLimits = &labelLimits{ labelLimit: int(sp.config.LabelLimit), labelNameLengthLimit: int(sp.config.LabelNameLengthLimit), @@ -464,6 +465,7 @@ func (sp *scrapePool) sync(targets []*Target) { scraper: s, sampleLimit: sampleLimit, bucketLimit: bucketLimit, + maxSchema: maxSchema, labelLimits: labelLimits, honorLabels: honorLabels, honorTimestamps: honorTimestamps, @@ -954,13 +956,14 @@ func (c *scrapeCache) iterDone(flushCache bool) { } } -func (c *scrapeCache) get(met []byte) (*cacheEntry, bool) { +func (c *scrapeCache) get(met []byte) (*cacheEntry, bool, bool) { e, ok := c.series[string(met)] if !ok { - return nil, false + return nil, false, false } + alreadyScraped := e.lastIter == c.iter e.lastIter = c.iter - return e, true + return e, true, alreadyScraped } func (c *scrapeCache) addRef(met []byte, ref storage.SeriesRef, lset labels.Labels, hash uint64) { @@ -1217,14 +1220,16 @@ mainLoop: // Calling Round ensures the time used is the wall clock, as otherwise .Sub // and .Add on time.Time behave differently (see time package docs). scrapeTime := time.Now().Round(0) - if AlignScrapeTimestamps && sl.interval > 100*ScrapeTimestampTolerance { + if AlignScrapeTimestamps { + // Tolerance is clamped to maximum 1% of the scrape interval. + tolerance := min(sl.interval/100, ScrapeTimestampTolerance) // For some reason, a tick might have been skipped, in which case we // would call alignedScrapeTime.Add(interval) multiple times. for scrapeTime.Sub(alignedScrapeTime) >= sl.interval { alignedScrapeTime = alignedScrapeTime.Add(sl.interval) } // Align the scrape time if we are in the tolerance boundaries. - if scrapeTime.Sub(alignedScrapeTime) <= ScrapeTimestampTolerance { + if scrapeTime.Sub(alignedScrapeTime) <= tolerance { scrapeTime = alignedScrapeTime } } @@ -1564,7 +1569,7 @@ loop: if sl.cache.getDropped(met) { continue } - ce, ok := sl.cache.get(met) + ce, ok, seriesAlreadyScraped := sl.cache.get(met) var ( ref storage.SeriesRef hash uint64 @@ -1573,6 +1578,7 @@ loop: if ok { ref = ce.ref lset = ce.lset + hash = ce.hash // Update metadata only if it changed in the current iteration. updateMetadata(lset, false) @@ -1609,25 +1615,36 @@ loop: updateMetadata(lset, true) } - if ctMs := p.CreatedTimestamp(); sl.enableCTZeroIngestion && ctMs != nil { - ref, err = app.AppendCTZeroSample(ref, lset, t, *ctMs) - if err != nil && !errors.Is(err, storage.ErrOutOfOrderCT) { // OOO is a common case, ignoring completely for now. - // CT is an experimental feature. For now, we don't need to fail the - // scrape on errors updating the created timestamp, log debug. - level.Debug(sl.l).Log("msg", "Error when appending CT in scrape loop", "series", string(met), "ct", *ctMs, "t", t, "err", err) + if seriesAlreadyScraped { + err = storage.ErrDuplicateSampleForTimestamp + } else { + if ctMs := p.CreatedTimestamp(); sl.enableCTZeroIngestion && ctMs != nil { + ref, err = app.AppendCTZeroSample(ref, lset, t, *ctMs) + if err != nil && !errors.Is(err, storage.ErrOutOfOrderCT) { // OOO is a common case, ignoring completely for now. + // CT is an experimental feature. For now, we don't need to fail the + // scrape on errors updating the created timestamp, log debug. + level.Debug(sl.l).Log("msg", "Error when appending CT in scrape loop", "series", string(met), "ct", *ctMs, "t", t, "err", err) + } } - } - if isHistogram { - if h != nil { - ref, err = app.AppendHistogram(ref, lset, t, h, nil) + if isHistogram { + if h != nil { + ref, err = app.AppendHistogram(ref, lset, t, h, nil) + } else { + ref, err = app.AppendHistogram(ref, lset, t, nil, fh) + } } else { - ref, err = app.AppendHistogram(ref, lset, t, nil, fh) + ref, err = app.Append(ref, lset, t, val) } - } else { - ref, err = app.Append(ref, lset, t, val) } - sampleAdded, err = sl.checkAddError(ce, met, parsedTimestamp, err, &sampleLimitErr, &bucketLimitErr, &appErrs) + + if err == nil { + if (parsedTimestamp == nil || sl.trackTimestampsStaleness) && ce != nil { + sl.cache.trackStaleness(ce.hash, ce.lset) + } + } + + sampleAdded, err = sl.checkAddError(met, err, &sampleLimitErr, &bucketLimitErr, &appErrs) if err != nil { if !errors.Is(err, storage.ErrNotFound) { level.Debug(sl.l).Log("msg", "Unexpected error", "series", string(met), "err", err) @@ -1648,6 +1665,8 @@ loop: // Increment added even if there's an error so we correctly report the // number of samples remaining after relabeling. + // We still report duplicated samples here since this number should be the exact number + // of time series exposed on a scrape after relabelling. added++ exemplars = exemplars[:0] // Reset and reuse the exemplar slice. for hasExemplar := p.Exemplar(&e); hasExemplar; hasExemplar = p.Exemplar(&e) { @@ -1742,12 +1761,9 @@ loop: // Adds samples to the appender, checking the error, and then returns the # of samples added, // whether the caller should continue to process more samples, and any sample or bucket limit errors. -func (sl *scrapeLoop) checkAddError(ce *cacheEntry, met []byte, tp *int64, err error, sampleLimitErr, bucketLimitErr *error, appErrs *appendErrors) (bool, error) { +func (sl *scrapeLoop) checkAddError(met []byte, err error, sampleLimitErr, bucketLimitErr *error, appErrs *appendErrors) (bool, error) { switch { case err == nil: - if (tp == nil || sl.trackTimestampsStaleness) && ce != nil { - sl.cache.trackStaleness(ce.hash, ce.lset) - } return true, nil case errors.Is(err, storage.ErrNotFound): return false, storage.ErrNotFound @@ -1870,7 +1886,7 @@ func (sl *scrapeLoop) reportStale(app storage.Appender, start time.Time) (err er } func (sl *scrapeLoop) addReportSample(app storage.Appender, s []byte, t int64, v float64, b *labels.Builder) error { - ce, ok := sl.cache.get(s) + ce, ok, _ := sl.cache.get(s) var ref storage.SeriesRef var lset labels.Labels if ok { diff --git a/vendor/github.com/prometheus/prometheus/storage/buffer.go b/vendor/github.com/prometheus/prometheus/storage/buffer.go index b3c789e97d..651e5c83e8 100644 --- a/vendor/github.com/prometheus/prometheus/storage/buffer.go +++ b/vendor/github.com/prometheus/prometheus/storage/buffer.go @@ -306,10 +306,9 @@ func (r *sampleRing) reset() { r.iBuf = r.iBuf[:0] } -// Returns the current iterator. Invalidates previously returned iterators. +// Resets and returns the iterator. Invalidates previously returned iterators. func (r *sampleRing) iterator() *SampleRingIterator { - r.it.r = r - r.it.i = -1 + r.it.reset(r) return &r.it } @@ -324,6 +323,13 @@ type SampleRingIterator struct { fh *histogram.FloatHistogram } +func (it *SampleRingIterator) reset(r *sampleRing) { + it.r = r + it.i = -1 + it.h = nil + it.fh = nil +} + func (it *SampleRingIterator) Next() chunkenc.ValueType { it.i++ if it.i >= it.r.l { diff --git a/vendor/github.com/prometheus/prometheus/storage/remote/azuread/azuread.go b/vendor/github.com/prometheus/prometheus/storage/remote/azuread/azuread.go index 20d48d0087..e2058fb54d 100644 --- a/vendor/github.com/prometheus/prometheus/storage/remote/azuread/azuread.go +++ b/vendor/github.com/prometheus/prometheus/storage/remote/azuread/azuread.go @@ -61,6 +61,12 @@ type OAuthConfig struct { TenantID string `yaml:"tenant_id,omitempty"` } +// SDKConfig is used to store azure SDK config values. +type SDKConfig struct { + // TenantID is the tenantId of the azure active directory application that is being used to authenticate. + TenantID string `yaml:"tenant_id,omitempty"` +} + // AzureADConfig is used to store the config values. type AzureADConfig struct { //nolint:revive // exported. // ManagedIdentity is the managed identity that is being used to authenticate. @@ -69,6 +75,9 @@ type AzureADConfig struct { //nolint:revive // exported. // OAuth is the oauth config that is being used to authenticate. OAuth *OAuthConfig `yaml:"oauth,omitempty"` + // OAuth is the oauth config that is being used to authenticate. + SDK *SDKConfig `yaml:"sdk,omitempty"` + // Cloud is the Azure cloud in which the service is running. Example: AzurePublic/AzureGovernment/AzureChina. Cloud string `yaml:"cloud,omitempty"` } @@ -102,14 +111,22 @@ func (c *AzureADConfig) Validate() error { return fmt.Errorf("must provide a cloud in the Azure AD config") } - if c.ManagedIdentity == nil && c.OAuth == nil { - return fmt.Errorf("must provide an Azure Managed Identity or Azure OAuth in the Azure AD config") + if c.ManagedIdentity == nil && c.OAuth == nil && c.SDK == nil { + return fmt.Errorf("must provide an Azure Managed Identity, Azure OAuth or Azure SDK in the Azure AD config") } if c.ManagedIdentity != nil && c.OAuth != nil { return fmt.Errorf("cannot provide both Azure Managed Identity and Azure OAuth in the Azure AD config") } + if c.ManagedIdentity != nil && c.SDK != nil { + return fmt.Errorf("cannot provide both Azure Managed Identity and Azure SDK in the Azure AD config") + } + + if c.OAuth != nil && c.SDK != nil { + return fmt.Errorf("cannot provide both Azure OAuth and Azure SDK in the Azure AD config") + } + if c.ManagedIdentity != nil { if c.ManagedIdentity.ClientID == "" { return fmt.Errorf("must provide an Azure Managed Identity client_id in the Azure AD config") @@ -143,6 +160,17 @@ func (c *AzureADConfig) Validate() error { } } + if c.SDK != nil { + var err error + + if c.SDK.TenantID != "" { + _, err = regexp.MatchString("^[0-9a-zA-Z-.]+$", c.SDK.TenantID) + if err != nil { + return fmt.Errorf("the provided Azure OAuth tenant_id is invalid") + } + } + } + return nil } @@ -225,6 +253,16 @@ func newTokenCredential(cfg *AzureADConfig) (azcore.TokenCredential, error) { } } + if cfg.SDK != nil { + sdkConfig := &SDKConfig{ + TenantID: cfg.SDK.TenantID, + } + cred, err = newSDKTokenCredential(clientOpts, sdkConfig) + if err != nil { + return nil, err + } + } + return cred, nil } @@ -241,6 +279,12 @@ func newOAuthTokenCredential(clientOpts *azcore.ClientOptions, oAuthConfig *OAut return azidentity.NewClientSecretCredential(oAuthConfig.TenantID, oAuthConfig.ClientID, oAuthConfig.ClientSecret, opts) } +// newSDKTokenCredential returns new SDK token credential. +func newSDKTokenCredential(clientOpts *azcore.ClientOptions, sdkConfig *SDKConfig) (azcore.TokenCredential, error) { + opts := &azidentity.DefaultAzureCredentialOptions{ClientOptions: *clientOpts, TenantID: sdkConfig.TenantID} + return azidentity.NewDefaultAzureCredential(opts) +} + // newTokenProvider helps to fetch accessToken for different types of credential. This also takes care of // refreshing the accessToken before expiry. This accessToken is attached to the Authorization header while making requests. func newTokenProvider(cfg *AzureADConfig, cred azcore.TokenCredential) (*tokenProvider, error) { diff --git a/vendor/github.com/prometheus/prometheus/storage/remote/client.go b/vendor/github.com/prometheus/prometheus/storage/remote/client.go index e765b47c3e..5ba0f7117f 100644 --- a/vendor/github.com/prometheus/prometheus/storage/remote/client.go +++ b/vendor/github.com/prometheus/prometheus/storage/remote/client.go @@ -64,11 +64,14 @@ var ( ) remoteReadQueryDuration = prometheus.NewHistogramVec( prometheus.HistogramOpts{ - Namespace: namespace, - Subsystem: subsystem, - Name: "read_request_duration_seconds", - Help: "Histogram of the latency for remote read requests.", - Buckets: append(prometheus.DefBuckets, 25, 60), + Namespace: namespace, + Subsystem: subsystem, + Name: "read_request_duration_seconds", + Help: "Histogram of the latency for remote read requests.", + Buckets: append(prometheus.DefBuckets, 25, 60), + NativeHistogramBucketFactor: 1.1, + NativeHistogramMaxBucketNumber: 100, + NativeHistogramMinResetDuration: 1 * time.Hour, }, []string{remoteName, endpoint}, ) diff --git a/vendor/github.com/prometheus/prometheus/storage/remote/otlptranslator/prometheus/normalize_label.go b/vendor/github.com/prometheus/prometheus/storage/remote/otlptranslator/prometheus/normalize_label.go index c02800c8bc..a6b41d1c37 100644 --- a/vendor/github.com/prometheus/prometheus/storage/remote/otlptranslator/prometheus/normalize_label.go +++ b/vendor/github.com/prometheus/prometheus/storage/remote/otlptranslator/prometheus/normalize_label.go @@ -3,7 +3,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -package prometheus // import "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/prometheus" +package prometheus // import "github.com/prometheus/prometheus/storage/remote/otlptranslator/prometheus" import ( "strings" diff --git a/vendor/github.com/prometheus/prometheus/storage/remote/otlptranslator/prometheus/normalize_name.go b/vendor/github.com/prometheus/prometheus/storage/remote/otlptranslator/prometheus/normalize_name.go index 7ae233a187..a976dfb485 100644 --- a/vendor/github.com/prometheus/prometheus/storage/remote/otlptranslator/prometheus/normalize_name.go +++ b/vendor/github.com/prometheus/prometheus/storage/remote/otlptranslator/prometheus/normalize_name.go @@ -3,7 +3,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -package prometheus // import "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/prometheus" +package prometheus // import "github.com/prometheus/prometheus/storage/remote/otlptranslator/prometheus" import ( "strings" diff --git a/vendor/github.com/prometheus/prometheus/storage/remote/otlptranslator/prometheus/unit_to_ucum.go b/vendor/github.com/prometheus/prometheus/storage/remote/otlptranslator/prometheus/unit_to_ucum.go index 4a72e683bb..718a520675 100644 --- a/vendor/github.com/prometheus/prometheus/storage/remote/otlptranslator/prometheus/unit_to_ucum.go +++ b/vendor/github.com/prometheus/prometheus/storage/remote/otlptranslator/prometheus/unit_to_ucum.go @@ -3,7 +3,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -package prometheus // import "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/prometheus" +package prometheus // import "github.com/prometheus/prometheus/storage/remote/otlptranslator/prometheus" import "strings" diff --git a/vendor/github.com/prometheus/prometheus/storage/remote/queue_manager.go b/vendor/github.com/prometheus/prometheus/storage/remote/queue_manager.go index 98e4aa54c1..01d2db06a5 100644 --- a/vendor/github.com/prometheus/prometheus/storage/remote/queue_manager.go +++ b/vendor/github.com/prometheus/prometheus/storage/remote/queue_manager.go @@ -214,12 +214,15 @@ func newQueueManagerMetrics(r prometheus.Registerer, rn, e string) *queueManager ConstLabels: constLabels, }) m.sentBatchDuration = prometheus.NewHistogram(prometheus.HistogramOpts{ - Namespace: namespace, - Subsystem: subsystem, - Name: "sent_batch_duration_seconds", - Help: "Duration of send calls to the remote storage.", - Buckets: append(prometheus.DefBuckets, 25, 60, 120, 300), - ConstLabels: constLabels, + Namespace: namespace, + Subsystem: subsystem, + Name: "sent_batch_duration_seconds", + Help: "Duration of send calls to the remote storage.", + Buckets: append(prometheus.DefBuckets, 25, 60, 120, 300), + ConstLabels: constLabels, + NativeHistogramBucketFactor: 1.1, + NativeHistogramMaxBucketNumber: 100, + NativeHistogramMinResetDuration: 1 * time.Hour, }) m.highestSentTimestamp = &maxTimestamp{ Gauge: prometheus.NewGauge(prometheus.GaugeOpts{ diff --git a/vendor/github.com/prometheus/prometheus/storage/remote/read_handler.go b/vendor/github.com/prometheus/prometheus/storage/remote/read_handler.go index ffc64c9c3f..2a00ce897f 100644 --- a/vendor/github.com/prometheus/prometheus/storage/remote/read_handler.go +++ b/vendor/github.com/prometheus/prometheus/storage/remote/read_handler.go @@ -202,34 +202,16 @@ func (h *readHandler) remoteReadStreamedXORChunks(ctx context.Context, w http.Re return err } - querier, err := h.queryable.ChunkQuerier(query.StartTimestampMs, query.EndTimestampMs) - if err != nil { + chunks := h.getChunkSeriesSet(ctx, query, filteredMatchers) + if err := chunks.Err(); err != nil { return err } - defer func() { - if err := querier.Close(); err != nil { - level.Warn(h.logger).Log("msg", "Error on chunk querier close", "err", err.Error()) - } - }() - - var hints *storage.SelectHints - if query.Hints != nil { - hints = &storage.SelectHints{ - Start: query.Hints.StartMs, - End: query.Hints.EndMs, - Step: query.Hints.StepMs, - Func: query.Hints.Func, - Grouping: query.Hints.Grouping, - Range: query.Hints.RangeMs, - By: query.Hints.By, - } - } ws, err := StreamChunkedReadResponses( NewChunkedWriter(w, f), int64(i), // The streaming API has to provide the series sorted. - querier.Select(ctx, true, hints, filteredMatchers...), + chunks, sortedExternalLabels, h.remoteReadMaxBytesInFrame, h.marshalPool, @@ -254,6 +236,35 @@ func (h *readHandler) remoteReadStreamedXORChunks(ctx context.Context, w http.Re } } +// getChunkSeriesSet executes a query to retrieve a ChunkSeriesSet, +// encapsulating the operation in its own function to ensure timely release of +// the querier resources. +func (h *readHandler) getChunkSeriesSet(ctx context.Context, query *prompb.Query, filteredMatchers []*labels.Matcher) storage.ChunkSeriesSet { + querier, err := h.queryable.ChunkQuerier(query.StartTimestampMs, query.EndTimestampMs) + if err != nil { + return storage.ErrChunkSeriesSet(err) + } + defer func() { + if err := querier.Close(); err != nil { + level.Warn(h.logger).Log("msg", "Error on chunk querier close", "err", err.Error()) + } + }() + + var hints *storage.SelectHints + if query.Hints != nil { + hints = &storage.SelectHints{ + Start: query.Hints.StartMs, + End: query.Hints.EndMs, + Step: query.Hints.StepMs, + Func: query.Hints.Func, + Grouping: query.Hints.Grouping, + Range: query.Hints.RangeMs, + By: query.Hints.By, + } + } + return querier.Select(ctx, true, hints, filteredMatchers...) +} + // filterExtLabelsFromMatchers change equality matchers which match external labels // to a matcher that looks for an empty label, // as that label should not be present in the storage. diff --git a/vendor/github.com/prometheus/prometheus/tsdb/chunks/chunks.go b/vendor/github.com/prometheus/prometheus/tsdb/chunks/chunks.go index 543b98c289..0826f69670 100644 --- a/vendor/github.com/prometheus/prometheus/tsdb/chunks/chunks.go +++ b/vendor/github.com/prometheus/prometheus/tsdb/chunks/chunks.go @@ -202,15 +202,6 @@ func ChunkFromSamplesGeneric(s Samples) (Meta, error) { }, nil } -// PopulatedChunk creates a chunk populated with samples every second starting at minTime. -func PopulatedChunk(numSamples int, minTime int64) (Meta, error) { - samples := make([]Sample, numSamples) - for i := 0; i < numSamples; i++ { - samples[i] = sample{t: minTime + int64(i*1000), f: 1.0} - } - return ChunkFromSamples(samples) -} - // ChunkMetasToSamples converts a slice of chunk meta data to a slice of samples. // Used in tests to compare the content of chunks. func ChunkMetasToSamples(chunks []Meta) (result []Sample) { diff --git a/vendor/github.com/prometheus/prometheus/tsdb/chunks/head_chunks.go b/vendor/github.com/prometheus/prometheus/tsdb/chunks/head_chunks.go index 5ba5381320..087f25fbb3 100644 --- a/vendor/github.com/prometheus/prometheus/tsdb/chunks/head_chunks.go +++ b/vendor/github.com/prometheus/prometheus/tsdb/chunks/head_chunks.go @@ -15,7 +15,6 @@ package chunks import ( "bufio" - "bytes" "encoding/binary" "errors" "fmt" @@ -690,7 +689,6 @@ func (cdm *ChunkDiskMapper) Chunk(ref ChunkDiskMapperRef) (chunkenc.Chunk, error sgmIndex, chkStart := ref.Unpack() // We skip the series ref and the mint/maxt beforehand. chkStart += SeriesRefSize + (2 * MintMaxtSize) - chkCRC32 := newCRC32() // If it is the current open file, then the chunks can be in the buffer too. if sgmIndex == cdm.curFileSequence { @@ -755,20 +753,13 @@ func (cdm *ChunkDiskMapper) Chunk(ref ChunkDiskMapperRef) (chunkenc.Chunk, error // Check the CRC. sum := mmapFile.byteSlice.Range(chkDataEnd, chkDataEnd+CRCSize) - if _, err := chkCRC32.Write(mmapFile.byteSlice.Range(chkStart-(SeriesRefSize+2*MintMaxtSize), chkDataEnd)); err != nil { + if err := checkCRC32(mmapFile.byteSlice.Range(chkStart-(SeriesRefSize+2*MintMaxtSize), chkDataEnd), sum); err != nil { return nil, &CorruptionErr{ Dir: cdm.dir.Name(), FileIndex: sgmIndex, Err: err, } } - if act := chkCRC32.Sum(nil); !bytes.Equal(act, sum) { - return nil, &CorruptionErr{ - Dir: cdm.dir.Name(), - FileIndex: sgmIndex, - Err: fmt.Errorf("checksum mismatch expected:%x, actual:%x", sum, act), - } - } // The chunk data itself. chkData := mmapFile.byteSlice.Range(chkDataEnd-int(chkDataLen), chkDataEnd) @@ -802,8 +793,6 @@ func (cdm *ChunkDiskMapper) IterateAllChunks(f func(seriesRef HeadSeriesRef, chu cdm.fileMaxtSet = true }() - chkCRC32 := newCRC32() - // Iterate files in ascending order. segIDs := make([]int, 0, len(cdm.mmappedChunkFiles)) for seg := range cdm.mmappedChunkFiles { @@ -838,7 +827,6 @@ func (cdm *ChunkDiskMapper) IterateAllChunks(f func(seriesRef HeadSeriesRef, chu " - required:%v, available:%v, file:%d", idx+MaxHeadChunkMetaSize, fileEnd, segID), } } - chkCRC32.Reset() chunkRef := newChunkDiskMapperRef(uint64(segID), uint64(idx)) startIdx := idx @@ -877,14 +865,11 @@ func (cdm *ChunkDiskMapper) IterateAllChunks(f func(seriesRef HeadSeriesRef, chu // Check CRC. sum := mmapFile.byteSlice.Range(idx, idx+CRCSize) - if _, err := chkCRC32.Write(mmapFile.byteSlice.Range(startIdx, idx)); err != nil { - return err - } - if act := chkCRC32.Sum(nil); !bytes.Equal(act, sum) { + if err := checkCRC32(mmapFile.byteSlice.Range(startIdx, idx), sum); err != nil { return &CorruptionErr{ Dir: cdm.dir.Name(), FileIndex: segID, - Err: fmt.Errorf("checksum mismatch expected:%x, actual:%x", sum, act), + Err: err, } } idx += CRCSize diff --git a/vendor/github.com/prometheus/prometheus/tsdb/compact.go b/vendor/github.com/prometheus/prometheus/tsdb/compact.go index b21ac4d317..3d8d9130c4 100644 --- a/vendor/github.com/prometheus/prometheus/tsdb/compact.go +++ b/vendor/github.com/prometheus/prometheus/tsdb/compact.go @@ -112,9 +112,12 @@ func newCompactorMetrics(r prometheus.Registerer) *CompactorMetrics { Help: "Total number of compactions done on overlapping blocks.", }) m.Duration = prometheus.NewHistogram(prometheus.HistogramOpts{ - Name: "prometheus_tsdb_compaction_duration_seconds", - Help: "Duration of compaction runs", - Buckets: prometheus.ExponentialBuckets(1, 2, 14), + Name: "prometheus_tsdb_compaction_duration_seconds", + Help: "Duration of compaction runs", + Buckets: prometheus.ExponentialBuckets(1, 2, 14), + NativeHistogramBucketFactor: 1.1, + NativeHistogramMaxBucketNumber: 100, + NativeHistogramMinResetDuration: 1 * time.Hour, }) m.ChunkSize = prometheus.NewHistogram(prometheus.HistogramOpts{ Name: "prometheus_tsdb_compaction_chunk_size_bytes", diff --git a/vendor/github.com/prometheus/prometheus/tsdb/db.go b/vendor/github.com/prometheus/prometheus/tsdb/db.go index f29315517b..856a9a68a3 100644 --- a/vendor/github.com/prometheus/prometheus/tsdb/db.go +++ b/vendor/github.com/prometheus/prometheus/tsdb/db.go @@ -24,7 +24,6 @@ import ( "os" "path/filepath" "slices" - "strconv" "strings" "sync" "time" @@ -319,8 +318,11 @@ func newDBMetrics(db *DB, r prometheus.Registerer) *dbMetrics { return float64(db.blocks[0].meta.MinTime) }) m.tombCleanTimer = prometheus.NewHistogram(prometheus.HistogramOpts{ - Name: "prometheus_tsdb_tombstone_cleanup_seconds", - Help: "The time taken to recompact blocks to remove tombstones.", + Name: "prometheus_tsdb_tombstone_cleanup_seconds", + Help: "The time taken to recompact blocks to remove tombstones.", + NativeHistogramBucketFactor: 1.1, + NativeHistogramMaxBucketNumber: 100, + NativeHistogramMinResetDuration: 1 * time.Hour, }) m.blocksBytes = prometheus.NewGauge(prometheus.GaugeOpts{ Name: "prometheus_tsdb_storage_blocks_bytes", @@ -527,9 +529,10 @@ func (db *DBReadOnly) loadDataAsQueryable(maxt int64) (storage.SampleAndChunkQue if err := head.Init(maxBlockTime); err != nil { return nil, fmt.Errorf("read WAL: %w", err) } - // Set the wal to nil to disable all wal operations. + // Set the wal and the wbl to nil to disable related operations. // This is mainly to avoid blocking when closing the head. head.wal = nil + head.wbl = nil } db.closers = append(db.closers, head) @@ -776,10 +779,6 @@ func open(dir string, l log.Logger, r prometheus.Registerer, opts *Options, rngs walDir := filepath.Join(dir, "wal") wblDir := filepath.Join(dir, wlog.WblDirName) - // Migrate old WAL if one exists. - if err := MigrateWAL(l, walDir); err != nil { - return nil, fmt.Errorf("migrate WAL: %w", err) - } for _, tmpDir := range []string{walDir, dir} { // Remove tmp dirs. if err := removeBestEffortTmpDirs(l, tmpDir); err != nil { @@ -1610,9 +1609,9 @@ func BeyondTimeRetention(db *DB, blocks []*Block) (deletable map[ulid.ULID]struc deletable = make(map[ulid.ULID]struct{}) for i, block := range blocks { - // The difference between the first block and this block is larger than + // The difference between the first block and this block is greater than or equal to // the retention period so any blocks after that are added as deletable. - if i > 0 && blocks[0].Meta().MaxTime-block.Meta().MaxTime > db.opts.RetentionDuration { + if i > 0 && blocks[0].Meta().MaxTime-block.Meta().MaxTime >= db.opts.RetentionDuration { for _, b := range blocks[i:] { deletable[b.meta.ULID] = struct{}{} } @@ -2210,39 +2209,6 @@ func blockDirs(dir string) ([]string, error) { return dirs, nil } -func sequenceFiles(dir string) ([]string, error) { - files, err := os.ReadDir(dir) - if err != nil { - return nil, err - } - var res []string - - for _, fi := range files { - if _, err := strconv.ParseUint(fi.Name(), 10, 64); err != nil { - continue - } - res = append(res, filepath.Join(dir, fi.Name())) - } - return res, nil -} - -func nextSequenceFile(dir string) (string, int, error) { - files, err := os.ReadDir(dir) - if err != nil { - return "", 0, err - } - - i := uint64(0) - for _, f := range files { - j, err := strconv.ParseUint(f.Name(), 10, 64) - if err != nil { - continue - } - i = j - } - return filepath.Join(dir, fmt.Sprintf("%0.6d", i+1)), int(i + 1), nil -} - func exponential(d, min, max time.Duration) time.Duration { d *= 2 if d < min { diff --git a/vendor/github.com/prometheus/prometheus/tsdb/head.go b/vendor/github.com/prometheus/prometheus/tsdb/head.go index dd2142e528..8b3d9787ca 100644 --- a/vendor/github.com/prometheus/prometheus/tsdb/head.go +++ b/vendor/github.com/prometheus/prometheus/tsdb/head.go @@ -480,6 +480,9 @@ func newHeadMetrics(h *Head, r prometheus.Registerer) *headMetrics { 60 * 60 * 6, // 6h 60 * 60 * 12, // 12h }, + NativeHistogramBucketFactor: 1.1, + NativeHistogramMaxBucketNumber: 100, + NativeHistogramMinResetDuration: 1 * time.Hour, }), mmapChunksTotal: prometheus.NewCounter(prometheus.CounterOpts{ Name: "prometheus_tsdb_mmap_chunks_total", @@ -617,6 +620,7 @@ func (h *Head) Init(minValidTime int64) error { refSeries := make(map[chunks.HeadSeriesRef]*memSeries) snapshotLoaded := false + var chunkSnapshotLoadDuration time.Duration if h.opts.EnableMemorySnapshotOnShutdown { level.Info(h.logger).Log("msg", "Chunk snapshot is enabled, replaying from the snapshot") // If there are any WAL files, there should be at least one WAL file with an index that is current or newer @@ -647,7 +651,8 @@ func (h *Head) Init(minValidTime int64) error { snapIdx, snapOffset, refSeries, err = h.loadChunkSnapshot() if err == nil { snapshotLoaded = true - level.Info(h.logger).Log("msg", "Chunk snapshot loading time", "duration", time.Since(start).String()) + chunkSnapshotLoadDuration = time.Since(start) + level.Info(h.logger).Log("msg", "Chunk snapshot loading time", "duration", chunkSnapshotLoadDuration.String()) } if err != nil { snapIdx, snapOffset = -1, 0 @@ -669,6 +674,8 @@ func (h *Head) Init(minValidTime int64) error { oooMmappedChunks map[chunks.HeadSeriesRef][]*mmappedChunk lastMmapRef chunks.ChunkDiskMapperRef err error + + mmapChunkReplayDuration time.Duration ) if snapshotLoaded || h.wal != nil { // If snapshot was not loaded and if there is no WAL, then m-map chunks will be discarded @@ -692,7 +699,8 @@ func (h *Head) Init(minValidTime int64) error { return err } } - level.Info(h.logger).Log("msg", "On-disk memory mappable chunks replay completed", "duration", time.Since(mmapChunkReplayStart).String()) + mmapChunkReplayDuration = time.Since(mmapChunkReplayStart) + level.Info(h.logger).Log("msg", "On-disk memory mappable chunks replay completed", "duration", mmapChunkReplayDuration.String()) } if h.wal == nil { @@ -814,6 +822,8 @@ func (h *Head) Init(minValidTime int64) error { "checkpoint_replay_duration", checkpointReplayDuration.String(), "wal_replay_duration", walReplayDuration.String(), "wbl_replay_duration", wblReplayDuration.String(), + "chunk_snapshot_load_duration", chunkSnapshotLoadDuration.String(), + "mmap_chunk_replay_duration", mmapChunkReplayDuration.String(), "total_replay_duration", totalReplayDuration.String(), ) @@ -1071,11 +1081,11 @@ func (h *Head) SetMinValidTime(minValidTime int64) { // Truncate removes old data before mint from the head and WAL. func (h *Head) Truncate(mint int64) (err error) { - initialize := h.MinTime() == math.MaxInt64 + initialized := h.initialized() if err := h.truncateMemory(mint); err != nil { return err } - if initialize { + if !initialized { return nil } return h.truncateWAL(mint) @@ -1097,9 +1107,9 @@ func (h *Head) truncateMemory(mint int64) (err error) { } }() - initialize := h.MinTime() == math.MaxInt64 + initialized := h.initialized() - if h.MinTime() >= mint && !initialize { + if h.MinTime() >= mint && initialized { return nil } @@ -1110,7 +1120,7 @@ func (h *Head) truncateMemory(mint int64) (err error) { defer h.memTruncationInProcess.Store(false) // We wait for pending queries to end that overlap with this truncation. - if !initialize { + if initialized { h.WaitForPendingReadersInTimeRange(h.MinTime(), mint) } @@ -1124,7 +1134,7 @@ func (h *Head) truncateMemory(mint int64) (err error) { // This was an initial call to Truncate after loading blocks on startup. // We haven't read back the WAL yet, so do not attempt to truncate it. - if initialize { + if !initialized { return nil } @@ -1612,10 +1622,19 @@ func (h *Head) MaxOOOTime() int64 { return h.maxOOOTime.Load() } +// initialized returns true if the head has a MinTime set, false otherwise. +func (h *Head) initialized() bool { + return h.MinTime() != math.MaxInt64 +} + // compactable returns whether the head has a compactable range. // The head has a compactable range when the head time range is 1.5 times the chunk range. // The 0.5 acts as a buffer of the appendable window. func (h *Head) compactable() bool { + if !h.initialized() { + return false + } + return h.MaxTime()-h.MinTime() > h.chunkRange.Load()/2*3 } diff --git a/vendor/github.com/prometheus/prometheus/tsdb/head_append.go b/vendor/github.com/prometheus/prometheus/tsdb/head_append.go index a0bf987160..58d24ceb94 100644 --- a/vendor/github.com/prometheus/prometheus/tsdb/head_append.go +++ b/vendor/github.com/prometheus/prometheus/tsdb/head_append.go @@ -138,7 +138,7 @@ func (h *Head) Appender(_ context.Context) storage.Appender { // The head cache might not have a starting point yet. The init appender // picks up the first appended timestamp as the base. - if h.MinTime() == math.MaxInt64 { + if !h.initialized() { return &initAppender{ head: h, } @@ -191,7 +191,7 @@ func (h *Head) appendableMinValidTime() int64 { // AppendableMinValidTime returns the minimum valid time for samples to be appended to the Head. // Returns false if Head hasn't been initialized yet and the minimum time isn't known yet. func (h *Head) AppendableMinValidTime() (int64, bool) { - if h.MinTime() == math.MaxInt64 { + if !h.initialized() { return 0, false } @@ -229,6 +229,9 @@ func (h *Head) putExemplarBuffer(b []exemplarWithSeriesRef) { if b == nil { return } + for i := range b { // Zero out to avoid retaining label data. + b[i].exemplar.Labels = labels.EmptyLabels() + } h.exemplarsPool.Put(b[:0]) } @@ -278,6 +281,9 @@ func (h *Head) getSeriesBuffer() []*memSeries { } func (h *Head) putSeriesBuffer(b []*memSeries) { + for i := range b { // Zero out to avoid retaining data. + b[i] = nil + } h.seriesPool.Put(b[:0]) } diff --git a/vendor/github.com/prometheus/prometheus/tsdb/index/index.go b/vendor/github.com/prometheus/prometheus/tsdb/index/index.go index 7aae4c2645..7ab890b99e 100644 --- a/vendor/github.com/prometheus/prometheus/tsdb/index/index.go +++ b/vendor/github.com/prometheus/prometheus/tsdb/index/index.go @@ -1829,7 +1829,7 @@ func NewStringListIter(s []string) StringIter { return &stringListIter{l: s} } -// symbolsIter implements StringIter. +// stringListIter implements StringIter. type stringListIter struct { l []string cur string diff --git a/vendor/github.com/prometheus/prometheus/tsdb/querier.go b/vendor/github.com/prometheus/prometheus/tsdb/querier.go index 6fc2758dbe..2ee7f5153b 100644 --- a/vendor/github.com/prometheus/prometheus/tsdb/querier.go +++ b/vendor/github.com/prometheus/prometheus/tsdb/querier.go @@ -19,8 +19,6 @@ import ( "fmt" "math" "slices" - "strings" - "unicode/utf8" "github.com/oklog/ulid" @@ -35,20 +33,6 @@ import ( "github.com/prometheus/prometheus/util/annotations" ) -// Bitmap used by func isRegexMetaCharacter to check whether a character needs to be escaped. -var regexMetaCharacterBytes [16]byte - -// isRegexMetaCharacter reports whether byte b needs to be escaped. -func isRegexMetaCharacter(b byte) bool { - return b < utf8.RuneSelf && regexMetaCharacterBytes[b%16]&(1<<(b/16)) != 0 -} - -func init() { - for _, b := range []byte(`.+*?()|[]{}^$`) { - regexMetaCharacterBytes[b%16] |= 1 << (b / 16) - } -} - type blockBaseQuerier struct { blockID ulid.ULID index IndexReader @@ -195,55 +179,6 @@ func (q *blockChunkQuerier) Select(ctx context.Context, sortSeries bool, hints * return NewBlockChunkSeriesSet(q.blockID, q.index, q.chunks, q.tombstones, p, mint, maxt, disableTrimming) } -func findSetMatches(pattern string) []string { - // Return empty matches if the wrapper from Prometheus is missing. - if len(pattern) < 6 || pattern[:4] != "^(?:" || pattern[len(pattern)-2:] != ")$" { - return nil - } - escaped := false - sets := []*strings.Builder{{}} - init := 4 - end := len(pattern) - 2 - // If the regex is wrapped in a group we can remove the first and last parentheses - if pattern[init] == '(' && pattern[end-1] == ')' { - init++ - end-- - } - for i := init; i < end; i++ { - if escaped { - switch { - case isRegexMetaCharacter(pattern[i]): - sets[len(sets)-1].WriteByte(pattern[i]) - case pattern[i] == '\\': - sets[len(sets)-1].WriteByte('\\') - default: - return nil - } - escaped = false - } else { - switch { - case isRegexMetaCharacter(pattern[i]): - if pattern[i] == '|' { - sets = append(sets, &strings.Builder{}) - } else { - return nil - } - case pattern[i] == '\\': - escaped = true - default: - sets[len(sets)-1].WriteByte(pattern[i]) - } - } - } - matches := make([]string, 0, len(sets)) - for _, s := range sets { - if s.Len() > 0 { - matches = append(matches, s.String()) - } - } - return matches -} - // PostingsForMatchers assembles a single postings iterator against the index reader // based on the given matchers. The resulting postings are not ordered by series. func PostingsForMatchers(ctx context.Context, ix IndexReader, ms ...*labels.Matcher) (index.Postings, error) { @@ -385,7 +320,7 @@ func postingsForMatcher(ctx context.Context, ix IndexReader, m *labels.Matcher) // Fast-path for set matching. if m.Type == labels.MatchRegexp { - setMatches := findSetMatches(m.GetRegexString()) + setMatches := m.SetMatches() if len(setMatches) > 0 { return ix.Postings(ctx, m.Name, setMatches...) } @@ -416,7 +351,7 @@ func inversePostingsForMatcher(ctx context.Context, ix IndexReader, m *labels.Ma // Inverse of a MatchNotRegexp is MatchRegexp (double negation). // Fast-path for set matching. if m.Type == labels.MatchNotRegexp { - setMatches := findSetMatches(m.GetRegexString()) + setMatches := m.SetMatches() if len(setMatches) > 0 { return ix.Postings(ctx, m.Name, setMatches...) } diff --git a/vendor/github.com/prometheus/prometheus/tsdb/wal.go b/vendor/github.com/prometheus/prometheus/tsdb/wal.go deleted file mode 100644 index e06a8aea53..0000000000 --- a/vendor/github.com/prometheus/prometheus/tsdb/wal.go +++ /dev/null @@ -1,1303 +0,0 @@ -// Copyright 2017 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package tsdb - -import ( - "bufio" - "encoding/binary" - "errors" - "fmt" - "hash" - "hash/crc32" - "io" - "math" - "os" - "path/filepath" - "sync" - "time" - - "github.com/go-kit/log" - "github.com/go-kit/log/level" - "github.com/prometheus/client_golang/prometheus" - - "github.com/prometheus/prometheus/model/labels" - "github.com/prometheus/prometheus/storage" - "github.com/prometheus/prometheus/tsdb/chunks" - "github.com/prometheus/prometheus/tsdb/encoding" - "github.com/prometheus/prometheus/tsdb/fileutil" - "github.com/prometheus/prometheus/tsdb/record" - "github.com/prometheus/prometheus/tsdb/tombstones" - "github.com/prometheus/prometheus/tsdb/wlog" - "github.com/prometheus/prometheus/util/zeropool" -) - -// WALEntryType indicates what data a WAL entry contains. -type WALEntryType uint8 - -const ( - // WALMagic is a 4 byte number every WAL segment file starts with. - WALMagic = uint32(0x43AF00EF) - - // WALFormatDefault is the version flag for the default outer segment file format. - WALFormatDefault = byte(1) -) - -// Entry types in a segment file. -const ( - WALEntrySymbols WALEntryType = 1 - WALEntrySeries WALEntryType = 2 - WALEntrySamples WALEntryType = 3 - WALEntryDeletes WALEntryType = 4 -) - -type walMetrics struct { - fsyncDuration prometheus.Summary - corruptions prometheus.Counter -} - -func newWalMetrics(r prometheus.Registerer) *walMetrics { - m := &walMetrics{} - - m.fsyncDuration = prometheus.NewSummary(prometheus.SummaryOpts{ - Name: "prometheus_tsdb_wal_fsync_duration_seconds", - Help: "Duration of WAL fsync.", - Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, - }) - m.corruptions = prometheus.NewCounter(prometheus.CounterOpts{ - Name: "prometheus_tsdb_wal_corruptions_total", - Help: "Total number of WAL corruptions.", - }) - - if r != nil { - r.MustRegister( - m.fsyncDuration, - m.corruptions, - ) - } - return m -} - -// WAL is a write ahead log that can log new series labels and samples. -// It must be completely read before new entries are logged. -// -// Deprecated: use wlog pkg combined with the record codex instead. -type WAL interface { - Reader() WALReader - LogSeries([]record.RefSeries) error - LogSamples([]record.RefSample) error - LogDeletes([]tombstones.Stone) error - Truncate(mint int64, keep func(uint64) bool) error - Close() error -} - -// WALReader reads entries from a WAL. -type WALReader interface { - Read( - seriesf func([]record.RefSeries), - samplesf func([]record.RefSample), - deletesf func([]tombstones.Stone), - ) error -} - -// segmentFile wraps a file object of a segment and tracks the highest timestamp -// it contains. During WAL truncating, all segments with no higher timestamp than -// the truncation threshold can be compacted. -type segmentFile struct { - *os.File - maxTime int64 // highest tombstone or sample timestamp in segment - minSeries chunks.HeadSeriesRef // lowerst series ID in segment -} - -func newSegmentFile(f *os.File) *segmentFile { - return &segmentFile{ - File: f, - maxTime: math.MinInt64, - minSeries: math.MaxUint64, - } -} - -const ( - walSegmentSizeBytes = 256 * 1024 * 1024 // 256 MB -) - -// The table gets initialized with sync.Once but may still cause a race -// with any other use of the crc32 package anywhere. Thus we initialize it -// before. -var castagnoliTable *crc32.Table - -func init() { - castagnoliTable = crc32.MakeTable(crc32.Castagnoli) -} - -// newCRC32 initializes a CRC32 hash with a preconfigured polynomial, so the -// polynomial may be easily changed in one location at a later time, if necessary. -func newCRC32() hash.Hash32 { - return crc32.New(castagnoliTable) -} - -// SegmentWAL is a write ahead log for series data. -// -// Deprecated: use wlog pkg combined with the record coders instead. -type SegmentWAL struct { - mtx sync.Mutex - metrics *walMetrics - - dirFile *os.File - files []*segmentFile - - logger log.Logger - flushInterval time.Duration - segmentSize int64 - - crc32 hash.Hash32 - cur *bufio.Writer - curN int64 - - stopc chan struct{} - donec chan struct{} - actorc chan func() error // sequentialized background operations - buffers sync.Pool -} - -// OpenSegmentWAL opens or creates a write ahead log in the given directory. -// The WAL must be read completely before new data is written. -func OpenSegmentWAL(dir string, logger log.Logger, flushInterval time.Duration, r prometheus.Registerer) (*SegmentWAL, error) { - if err := os.MkdirAll(dir, 0o777); err != nil { - return nil, err - } - df, err := fileutil.OpenDir(dir) - if err != nil { - return nil, err - } - if logger == nil { - logger = log.NewNopLogger() - } - - w := &SegmentWAL{ - dirFile: df, - logger: logger, - flushInterval: flushInterval, - donec: make(chan struct{}), - stopc: make(chan struct{}), - actorc: make(chan func() error, 2), - segmentSize: walSegmentSizeBytes, - crc32: newCRC32(), - } - w.metrics = newWalMetrics(r) - - fns, err := sequenceFiles(w.dirFile.Name()) - if err != nil { - return nil, err - } - - for i, fn := range fns { - f, err := w.openSegmentFile(fn) - if err == nil { - w.files = append(w.files, newSegmentFile(f)) - continue - } - level.Warn(logger).Log("msg", "Invalid segment file detected, truncating WAL", "err", err, "file", fn) - - for _, fn := range fns[i:] { - if err := os.Remove(fn); err != nil { - return w, fmt.Errorf("removing segment failed: %w", err) - } - } - break - } - - go w.run(flushInterval) - - return w, nil -} - -// repairingWALReader wraps a WAL reader and truncates its underlying SegmentWAL after the last -// valid entry if it encounters corruption. -type repairingWALReader struct { - wal *SegmentWAL - r WALReader -} - -func (r *repairingWALReader) Read( - seriesf func([]record.RefSeries), - samplesf func([]record.RefSample), - deletesf func([]tombstones.Stone), -) error { - err := r.r.Read(seriesf, samplesf, deletesf) - if err == nil { - return nil - } - var cerr *walCorruptionErr - if !errors.As(err, &cerr) { - return err - } - r.wal.metrics.corruptions.Inc() - return r.wal.truncate(cerr.err, cerr.file, cerr.lastOffset) -} - -// truncate the WAL after the last valid entry. -func (w *SegmentWAL) truncate(err error, file int, lastOffset int64) error { - level.Error(w.logger).Log("msg", "WAL corruption detected; truncating", - "err", err, "file", w.files[file].Name(), "pos", lastOffset) - - // Close and delete all files after the current one. - for _, f := range w.files[file+1:] { - if err := f.Close(); err != nil { - return err - } - if err := os.Remove(f.Name()); err != nil { - return err - } - } - w.mtx.Lock() - defer w.mtx.Unlock() - - w.files = w.files[:file+1] - - // Seek the current file to the last valid offset where we continue writing from. - _, err = w.files[file].Seek(lastOffset, io.SeekStart) - return err -} - -// Reader returns a new reader over the write ahead log data. -// It must be completely consumed before writing to the WAL. -func (w *SegmentWAL) Reader() WALReader { - return &repairingWALReader{ - wal: w, - r: newWALReader(w.files, w.logger), - } -} - -func (w *SegmentWAL) getBuffer() *encoding.Encbuf { - b := w.buffers.Get() - if b == nil { - return &encoding.Encbuf{B: make([]byte, 0, 64*1024)} - } - return b.(*encoding.Encbuf) -} - -func (w *SegmentWAL) putBuffer(b *encoding.Encbuf) { - b.Reset() - w.buffers.Put(b) -} - -// Truncate deletes the values prior to mint and the series which the keep function -// does not indicate to preserve. -func (w *SegmentWAL) Truncate(mint int64, keep func(chunks.HeadSeriesRef) bool) error { - // The last segment is always active. - if len(w.files) < 2 { - return nil - } - var candidates []*segmentFile - - // All files have to be traversed as there could be two segments for a block - // with first block having times (10000, 20000) and SECOND one having (0, 10000). - for _, sf := range w.files[:len(w.files)-1] { - if sf.maxTime >= mint { - break - } - // Past WAL files are closed. We have to reopen them for another read. - f, err := w.openSegmentFile(sf.Name()) - if err != nil { - return fmt.Errorf("open old WAL segment for read: %w", err) - } - candidates = append(candidates, &segmentFile{ - File: f, - minSeries: sf.minSeries, - maxTime: sf.maxTime, - }) - } - if len(candidates) == 0 { - return nil - } - - r := newWALReader(candidates, w.logger) - - // Create a new tmp file. - f, err := w.createSegmentFile(filepath.Join(w.dirFile.Name(), "compact.tmp")) - if err != nil { - return fmt.Errorf("create compaction segment: %w", err) - } - defer func() { - if err := os.RemoveAll(f.Name()); err != nil { - level.Error(w.logger).Log("msg", "remove tmp file", "err", err.Error()) - } - }() - - var ( - csf = newSegmentFile(f) - crc32 = newCRC32() - decSeries = []record.RefSeries{} - activeSeries = []record.RefSeries{} - ) - - for r.next() { - rt, flag, byt := r.at() - - if rt != WALEntrySeries { - continue - } - decSeries = decSeries[:0] - activeSeries = activeSeries[:0] - - err := r.decodeSeries(flag, byt, &decSeries) - if err != nil { - return fmt.Errorf("decode samples while truncating: %w", err) - } - for _, s := range decSeries { - if keep(s.Ref) { - activeSeries = append(activeSeries, s) - } - } - - buf := w.getBuffer() - flag = w.encodeSeries(buf, activeSeries) - - _, err = w.writeTo(csf, crc32, WALEntrySeries, flag, buf.Get()) - w.putBuffer(buf) - - if err != nil { - return fmt.Errorf("write to compaction segment: %w", err) - } - } - if err := r.Err(); err != nil { - return fmt.Errorf("read candidate WAL files: %w", err) - } - - off, err := csf.Seek(0, io.SeekCurrent) - if err != nil { - return err - } - if err := csf.Truncate(off); err != nil { - return err - } - if err := csf.Sync(); err != nil { - return nil - } - if err := csf.Close(); err != nil { - return nil - } - - _ = candidates[0].Close() // need close before remove on platform windows - if err := fileutil.Replace(csf.Name(), candidates[0].Name()); err != nil { - return fmt.Errorf("rename compaction segment: %w", err) - } - for _, f := range candidates[1:] { - f.Close() // need close before remove on platform windows - if err := os.RemoveAll(f.Name()); err != nil { - return fmt.Errorf("delete WAL segment file: %w", err) - } - } - if err := w.dirFile.Sync(); err != nil { - return err - } - - // The file object of csf still holds the name before rename. Recreate it so - // subsequent truncations do not look at a non-existent file name. - csf.File, err = w.openSegmentFile(candidates[0].Name()) - if err != nil { - return err - } - // We don't need it to be open. - if err := csf.Close(); err != nil { - return err - } - - w.mtx.Lock() - w.files = append([]*segmentFile{csf}, w.files[len(candidates):]...) - w.mtx.Unlock() - - return nil -} - -// LogSeries writes a batch of new series labels to the log. -// The series have to be ordered. -func (w *SegmentWAL) LogSeries(series []record.RefSeries) error { - buf := w.getBuffer() - - flag := w.encodeSeries(buf, series) - - w.mtx.Lock() - defer w.mtx.Unlock() - - err := w.write(WALEntrySeries, flag, buf.Get()) - - w.putBuffer(buf) - - if err != nil { - return fmt.Errorf("log series: %w", err) - } - - tf := w.head() - - for _, s := range series { - if tf.minSeries > s.Ref { - tf.minSeries = s.Ref - } - } - return nil -} - -// LogSamples writes a batch of new samples to the log. -func (w *SegmentWAL) LogSamples(samples []record.RefSample) error { - buf := w.getBuffer() - - flag := w.encodeSamples(buf, samples) - - w.mtx.Lock() - defer w.mtx.Unlock() - - err := w.write(WALEntrySamples, flag, buf.Get()) - - w.putBuffer(buf) - - if err != nil { - return fmt.Errorf("log series: %w", err) - } - tf := w.head() - - for _, s := range samples { - if tf.maxTime < s.T { - tf.maxTime = s.T - } - } - return nil -} - -// LogDeletes write a batch of new deletes to the log. -func (w *SegmentWAL) LogDeletes(stones []tombstones.Stone) error { - buf := w.getBuffer() - - flag := w.encodeDeletes(buf, stones) - - w.mtx.Lock() - defer w.mtx.Unlock() - - err := w.write(WALEntryDeletes, flag, buf.Get()) - - w.putBuffer(buf) - - if err != nil { - return fmt.Errorf("log series: %w", err) - } - tf := w.head() - - for _, s := range stones { - for _, iv := range s.Intervals { - if tf.maxTime < iv.Maxt { - tf.maxTime = iv.Maxt - } - } - } - return nil -} - -// openSegmentFile opens the given segment file and consumes and validates header. -func (w *SegmentWAL) openSegmentFile(name string) (*os.File, error) { - // We must open all files in read/write mode as we may have to truncate along - // the way and any file may become the head. - f, err := os.OpenFile(name, os.O_RDWR, 0o666) - if err != nil { - return nil, err - } - metab := make([]byte, 8) - - // If there is an error, we need close f for platform windows before gc. - // Otherwise, file op may fail. - hasError := true - defer func() { - if hasError { - f.Close() - } - }() - - switch n, err := f.Read(metab); { - case err != nil: - return nil, fmt.Errorf("validate meta %q: %w", f.Name(), err) - case n != 8: - return nil, fmt.Errorf("invalid header size %d in %q", n, f.Name()) - } - - if m := binary.BigEndian.Uint32(metab[:4]); m != WALMagic { - return nil, fmt.Errorf("invalid magic header %x in %q", m, f.Name()) - } - if metab[4] != WALFormatDefault { - return nil, fmt.Errorf("unknown WAL segment format %d in %q", metab[4], f.Name()) - } - hasError = false - return f, nil -} - -// createSegmentFile creates a new segment file with the given name. It preallocates -// the standard segment size if possible and writes the header. -func (w *SegmentWAL) createSegmentFile(name string) (*os.File, error) { - f, err := os.Create(name) - if err != nil { - return nil, err - } - if err = fileutil.Preallocate(f, w.segmentSize, true); err != nil { - return nil, err - } - // Write header metadata for new file. - metab := make([]byte, 8) - binary.BigEndian.PutUint32(metab[:4], WALMagic) - metab[4] = WALFormatDefault - - if _, err := f.Write(metab); err != nil { - return nil, err - } - return f, err -} - -// cut finishes the currently active segments and opens the next one. -// The encoder is reset to point to the new segment. -func (w *SegmentWAL) cut() error { - // Sync current head to disk and close. - if hf := w.head(); hf != nil { - if err := w.flush(); err != nil { - return err - } - // Finish last segment asynchronously to not block the WAL moving along - // in the new segment. - go func() { - w.actorc <- func() error { - off, err := hf.Seek(0, io.SeekCurrent) - if err != nil { - return fmt.Errorf("finish old segment %s: %w", hf.Name(), err) - } - if err := hf.Truncate(off); err != nil { - return fmt.Errorf("finish old segment %s: %w", hf.Name(), err) - } - if err := hf.Sync(); err != nil { - return fmt.Errorf("finish old segment %s: %w", hf.Name(), err) - } - if err := hf.Close(); err != nil { - return fmt.Errorf("finish old segment %s: %w", hf.Name(), err) - } - return nil - } - }() - } - - p, _, err := nextSequenceFile(w.dirFile.Name()) - if err != nil { - return err - } - f, err := w.createSegmentFile(p) - if err != nil { - return err - } - - go func() { - w.actorc <- func() error { - if err := w.dirFile.Sync(); err != nil { - return fmt.Errorf("sync WAL directory: %w", err) - } - return nil - } - }() - - w.files = append(w.files, newSegmentFile(f)) - - // TODO(gouthamve): make the buffer size a constant. - w.cur = bufio.NewWriterSize(f, 8*1024*1024) - w.curN = 8 - - return nil -} - -func (w *SegmentWAL) head() *segmentFile { - if len(w.files) == 0 { - return nil - } - return w.files[len(w.files)-1] -} - -// Sync flushes the changes to disk. -func (w *SegmentWAL) Sync() error { - var head *segmentFile - var err error - - // Flush the writer and retrieve the reference to the head segment under mutex lock. - func() { - w.mtx.Lock() - defer w.mtx.Unlock() - if err = w.flush(); err != nil { - return - } - head = w.head() - }() - if err != nil { - return fmt.Errorf("flush buffer: %w", err) - } - if head != nil { - // But only fsync the head segment after releasing the mutex as it will block on disk I/O. - start := time.Now() - err := fileutil.Fdatasync(head.File) - w.metrics.fsyncDuration.Observe(time.Since(start).Seconds()) - return err - } - return nil -} - -func (w *SegmentWAL) sync() error { - if err := w.flush(); err != nil { - return err - } - if w.head() == nil { - return nil - } - - start := time.Now() - err := fileutil.Fdatasync(w.head().File) - w.metrics.fsyncDuration.Observe(time.Since(start).Seconds()) - return err -} - -func (w *SegmentWAL) flush() error { - if w.cur == nil { - return nil - } - return w.cur.Flush() -} - -func (w *SegmentWAL) run(interval time.Duration) { - var tick <-chan time.Time - - if interval > 0 { - ticker := time.NewTicker(interval) - defer ticker.Stop() - tick = ticker.C - } - defer close(w.donec) - - for { - // Processing all enqueued operations has precedence over shutdown and - // background syncs. - select { - case f := <-w.actorc: - if err := f(); err != nil { - level.Error(w.logger).Log("msg", "operation failed", "err", err) - } - continue - default: - } - select { - case <-w.stopc: - return - case f := <-w.actorc: - if err := f(); err != nil { - level.Error(w.logger).Log("msg", "operation failed", "err", err) - } - case <-tick: - if err := w.Sync(); err != nil { - level.Error(w.logger).Log("msg", "sync failed", "err", err) - } - } - } -} - -// Close syncs all data and closes the underlying resources. -func (w *SegmentWAL) Close() error { - // Make sure you can call Close() multiple times. - select { - case <-w.stopc: - return nil // Already closed. - default: - } - - close(w.stopc) - <-w.donec - - w.mtx.Lock() - defer w.mtx.Unlock() - - if err := w.sync(); err != nil { - return err - } - // On opening, a WAL must be fully consumed once. Afterwards - // only the current segment will still be open. - if hf := w.head(); hf != nil { - if err := hf.Close(); err != nil { - return fmt.Errorf("closing WAL head %s: %w", hf.Name(), err) - } - } - if err := w.dirFile.Close(); err != nil { - return fmt.Errorf("closing WAL dir %s: %w", w.dirFile.Name(), err) - } - return nil -} - -func (w *SegmentWAL) write(t WALEntryType, flag uint8, buf []byte) error { - // Cut to the next segment if the entry exceeds the file size unless it would also - // exceed the size of a new segment. - // TODO(gouthamve): Add a test for this case where the commit is greater than segmentSize. - var ( - sz = int64(len(buf)) + 6 - newsz = w.curN + sz - ) - // XXX(fabxc): this currently cuts a new file whenever the WAL was newly opened. - // Probably fine in general but may yield a lot of short files in some cases. - if w.cur == nil || w.curN > w.segmentSize || newsz > w.segmentSize && sz <= w.segmentSize { - if err := w.cut(); err != nil { - return err - } - } - n, err := w.writeTo(w.cur, w.crc32, t, flag, buf) - - w.curN += int64(n) - - return err -} - -func (w *SegmentWAL) writeTo(wr io.Writer, crc32 hash.Hash, t WALEntryType, flag uint8, buf []byte) (int, error) { - if len(buf) == 0 { - return 0, nil - } - crc32.Reset() - wr = io.MultiWriter(crc32, wr) - - var b [6]byte - b[0] = byte(t) - b[1] = flag - - binary.BigEndian.PutUint32(b[2:], uint32(len(buf))) - - n1, err := wr.Write(b[:]) - if err != nil { - return n1, err - } - n2, err := wr.Write(buf) - if err != nil { - return n1 + n2, err - } - n3, err := wr.Write(crc32.Sum(b[:0])) - - return n1 + n2 + n3, err -} - -const ( - walSeriesSimple = 1 - walSamplesSimple = 1 - walDeletesSimple = 1 -) - -func (w *SegmentWAL) encodeSeries(buf *encoding.Encbuf, series []record.RefSeries) uint8 { - for _, s := range series { - buf.PutBE64(uint64(s.Ref)) - record.EncodeLabels(buf, s.Labels) - } - return walSeriesSimple -} - -func (w *SegmentWAL) encodeSamples(buf *encoding.Encbuf, samples []record.RefSample) uint8 { - if len(samples) == 0 { - return walSamplesSimple - } - // Store base timestamp and base reference number of first sample. - // All samples encode their timestamp and ref as delta to those. - // - // TODO(fabxc): optimize for all samples having the same timestamp. - first := samples[0] - - buf.PutBE64(uint64(first.Ref)) - buf.PutBE64int64(first.T) - - for _, s := range samples { - buf.PutVarint64(int64(s.Ref) - int64(first.Ref)) - buf.PutVarint64(s.T - first.T) - buf.PutBE64(math.Float64bits(s.V)) - } - return walSamplesSimple -} - -func (w *SegmentWAL) encodeDeletes(buf *encoding.Encbuf, stones []tombstones.Stone) uint8 { - for _, s := range stones { - for _, iv := range s.Intervals { - buf.PutBE64(uint64(s.Ref)) - buf.PutVarint64(iv.Mint) - buf.PutVarint64(iv.Maxt) - } - } - return walDeletesSimple -} - -// walReader decodes and emits write ahead log entries. -type walReader struct { - logger log.Logger - - files []*segmentFile - cur int - buf []byte - crc32 hash.Hash32 - dec record.Decoder - - curType WALEntryType - curFlag byte - curBuf []byte - lastOffset int64 // offset after last successfully read entry - - err error -} - -func newWALReader(files []*segmentFile, l log.Logger) *walReader { - if l == nil { - l = log.NewNopLogger() - } - return &walReader{ - logger: l, - files: files, - buf: make([]byte, 0, 128*4096), - crc32: newCRC32(), - dec: record.NewDecoder(labels.NewSymbolTable()), - } -} - -// Err returns the last error the reader encountered. -func (r *walReader) Err() error { - return r.err -} - -func (r *walReader) Read( - seriesf func([]record.RefSeries), - samplesf func([]record.RefSample), - deletesf func([]tombstones.Stone), -) error { - // Concurrency for replaying the WAL is very limited. We at least split out decoding and - // processing into separate threads. - // Historically, the processing is the bottleneck with reading and decoding using only - // 15% of the CPU. - var ( - seriesPool zeropool.Pool[[]record.RefSeries] - samplePool zeropool.Pool[[]record.RefSample] - deletePool zeropool.Pool[[]tombstones.Stone] - ) - donec := make(chan struct{}) - datac := make(chan interface{}, 100) - - go func() { - defer close(donec) - - for x := range datac { - switch v := x.(type) { - case []record.RefSeries: - if seriesf != nil { - seriesf(v) - } - seriesPool.Put(v[:0]) - case []record.RefSample: - if samplesf != nil { - samplesf(v) - } - samplePool.Put(v[:0]) - case []tombstones.Stone: - if deletesf != nil { - deletesf(v) - } - deletePool.Put(v[:0]) - default: - level.Error(r.logger).Log("msg", "unexpected data type") - } - } - }() - - var err error - - for r.next() { - et, flag, b := r.at() - - // In decoding below we never return a walCorruptionErr for now. - // Those should generally be caught by entry decoding before. - switch et { - case WALEntrySeries: - series := seriesPool.Get() - if series == nil { - series = make([]record.RefSeries, 0, 512) - } - - err = r.decodeSeries(flag, b, &series) - if err != nil { - err = fmt.Errorf("decode series entry: %w", err) - break - } - datac <- series - - cf := r.current() - for _, s := range series { - if cf.minSeries > s.Ref { - cf.minSeries = s.Ref - } - } - case WALEntrySamples: - samples := samplePool.Get() - if samples == nil { - samples = make([]record.RefSample, 0, 512) - } - - err = r.decodeSamples(flag, b, &samples) - if err != nil { - err = fmt.Errorf("decode samples entry: %w", err) - break - } - datac <- samples - - // Update the times for the WAL segment file. - cf := r.current() - for _, s := range samples { - if cf.maxTime < s.T { - cf.maxTime = s.T - } - } - case WALEntryDeletes: - deletes := deletePool.Get() - if deletes == nil { - deletes = make([]tombstones.Stone, 0, 512) - } - - err = r.decodeDeletes(flag, b, &deletes) - if err != nil { - err = fmt.Errorf("decode delete entry: %w", err) - break - } - datac <- deletes - - // Update the times for the WAL segment file. - cf := r.current() - for _, s := range deletes { - for _, iv := range s.Intervals { - if cf.maxTime < iv.Maxt { - cf.maxTime = iv.Maxt - } - } - } - } - } - close(datac) - <-donec - - if err != nil { - return err - } - if err := r.Err(); err != nil { - return fmt.Errorf("read entry: %w", err) - } - return nil -} - -func (r *walReader) at() (WALEntryType, byte, []byte) { - return r.curType, r.curFlag, r.curBuf -} - -// next returns decodes the next entry pair and returns true -// if it was successful. -func (r *walReader) next() bool { - if r.cur >= len(r.files) { - return false - } - cf := r.files[r.cur] - - // Remember the offset after the last correctly read entry. If the next one - // is corrupted, this is where we can safely truncate. - r.lastOffset, r.err = cf.Seek(0, io.SeekCurrent) - if r.err != nil { - return false - } - - et, flag, b, err := r.entry(cf) - // If we reached the end of the reader, advance to the next one - // and close. - // Do not close on the last one as it will still be appended to. - if errors.Is(err, io.EOF) { - if r.cur == len(r.files)-1 { - return false - } - // Current reader completed, close and move to the next one. - if err := cf.Close(); err != nil { - r.err = err - return false - } - r.cur++ - return r.next() - } - if err != nil { - r.err = err - return false - } - - r.curType = et - r.curFlag = flag - r.curBuf = b - return r.err == nil -} - -func (r *walReader) current() *segmentFile { - return r.files[r.cur] -} - -// walCorruptionErr is a type wrapper for errors that indicate WAL corruption -// and trigger a truncation. -type walCorruptionErr struct { - err error - file int - lastOffset int64 -} - -func (e *walCorruptionErr) Error() string { - return fmt.Sprintf("%s ", e.err, e.file, e.lastOffset) -} - -func (e *walCorruptionErr) Unwrap() error { - return e.err -} - -func (r *walReader) corruptionErr(s string, args ...interface{}) error { - return &walCorruptionErr{ - err: fmt.Errorf(s, args...), - file: r.cur, - lastOffset: r.lastOffset, - } -} - -func (r *walReader) entry(cr io.Reader) (WALEntryType, byte, []byte, error) { - r.crc32.Reset() - tr := io.TeeReader(cr, r.crc32) - - b := make([]byte, 6) - switch n, err := tr.Read(b); { - case err != nil: - return 0, 0, nil, err - case n != 6: - return 0, 0, nil, r.corruptionErr("invalid entry header size %d", n) - } - - var ( - etype = WALEntryType(b[0]) - flag = b[1] - length = int(binary.BigEndian.Uint32(b[2:])) - ) - // Exit if we reached pre-allocated space. - if etype == 0 { - return 0, 0, nil, io.EOF - } - if etype != WALEntrySeries && etype != WALEntrySamples && etype != WALEntryDeletes { - return 0, 0, nil, r.corruptionErr("invalid entry type %d", etype) - } - - if length > len(r.buf) { - r.buf = make([]byte, length) - } - buf := r.buf[:length] - - switch n, err := tr.Read(buf); { - case err != nil: - return 0, 0, nil, err - case n != length: - return 0, 0, nil, r.corruptionErr("invalid entry body size %d", n) - } - - switch n, err := cr.Read(b[:4]); { - case err != nil: - return 0, 0, nil, err - case n != 4: - return 0, 0, nil, r.corruptionErr("invalid checksum length %d", n) - } - if exp, has := binary.BigEndian.Uint32(b[:4]), r.crc32.Sum32(); has != exp { - return 0, 0, nil, r.corruptionErr("unexpected CRC32 checksum %x, want %x", has, exp) - } - - return etype, flag, buf, nil -} - -func (r *walReader) decodeSeries(flag byte, b []byte, res *[]record.RefSeries) error { - dec := encoding.Decbuf{B: b} - - for len(dec.B) > 0 && dec.Err() == nil { - ref := chunks.HeadSeriesRef(dec.Be64()) - lset := r.dec.DecodeLabels(&dec) - - *res = append(*res, record.RefSeries{ - Ref: ref, - Labels: lset, - }) - } - if dec.Err() != nil { - return dec.Err() - } - if len(dec.B) > 0 { - return fmt.Errorf("unexpected %d bytes left in entry", len(dec.B)) - } - return nil -} - -func (r *walReader) decodeSamples(flag byte, b []byte, res *[]record.RefSample) error { - if len(b) == 0 { - return nil - } - dec := encoding.Decbuf{B: b} - - var ( - baseRef = dec.Be64() - baseTime = dec.Be64int64() - ) - - for len(dec.B) > 0 && dec.Err() == nil { - dref := dec.Varint64() - dtime := dec.Varint64() - val := dec.Be64() - - *res = append(*res, record.RefSample{ - Ref: chunks.HeadSeriesRef(int64(baseRef) + dref), - T: baseTime + dtime, - V: math.Float64frombits(val), - }) - } - - if err := dec.Err(); err != nil { - return fmt.Errorf("decode error after %d samples: %w", len(*res), err) - } - if len(dec.B) > 0 { - return fmt.Errorf("unexpected %d bytes left in entry", len(dec.B)) - } - return nil -} - -func (r *walReader) decodeDeletes(flag byte, b []byte, res *[]tombstones.Stone) error { - dec := &encoding.Decbuf{B: b} - - for dec.Len() > 0 && dec.Err() == nil { - *res = append(*res, tombstones.Stone{ - Ref: storage.SeriesRef(dec.Be64()), - Intervals: tombstones.Intervals{ - {Mint: dec.Varint64(), Maxt: dec.Varint64()}, - }, - }) - } - if dec.Err() != nil { - return dec.Err() - } - if len(dec.B) > 0 { - return fmt.Errorf("unexpected %d bytes left in entry", len(dec.B)) - } - return nil -} - -func deprecatedWALExists(logger log.Logger, dir string) (bool, error) { - // Detect whether we still have the old WAL. - fns, err := sequenceFiles(dir) - if err != nil && !os.IsNotExist(err) { - return false, fmt.Errorf("list sequence files: %w", err) - } - if len(fns) == 0 { - return false, nil // No WAL at all yet. - } - // Check header of first segment to see whether we are still dealing with an - // old WAL. - f, err := os.Open(fns[0]) - if err != nil { - return false, fmt.Errorf("check first existing segment: %w", err) - } - defer f.Close() - - var hdr [4]byte - if _, err := f.Read(hdr[:]); err != nil && !errors.Is(err, io.EOF) { - return false, fmt.Errorf("read header from first segment: %w", err) - } - // If we cannot read the magic header for segments of the old WAL, abort. - // Either it's migrated already or there's a corruption issue with which - // we cannot deal here anyway. Subsequent attempts to open the WAL will error in that case. - if binary.BigEndian.Uint32(hdr[:]) != WALMagic { - return false, nil - } - return true, nil -} - -// MigrateWAL rewrites the deprecated write ahead log into the new format. -func MigrateWAL(logger log.Logger, dir string) (err error) { - if logger == nil { - logger = log.NewNopLogger() - } - if exists, err := deprecatedWALExists(logger, dir); err != nil || !exists { - return err - } - level.Info(logger).Log("msg", "Migrating WAL format") - - tmpdir := dir + ".tmp" - if err := os.RemoveAll(tmpdir); err != nil { - return fmt.Errorf("cleanup replacement dir: %w", err) - } - repl, err := wlog.New(logger, nil, tmpdir, wlog.CompressionNone) - if err != nil { - return fmt.Errorf("open new WAL: %w", err) - } - - // It should've already been closed as part of the previous finalization. - // Do it once again in case of prior errors. - defer func() { - if err != nil { - repl.Close() - } - }() - - w, err := OpenSegmentWAL(dir, logger, time.Minute, nil) - if err != nil { - return fmt.Errorf("open old WAL: %w", err) - } - defer w.Close() - - rdr := w.Reader() - - var ( - enc record.Encoder - b []byte - ) - decErr := rdr.Read( - func(s []record.RefSeries) { - if err != nil { - return - } - err = repl.Log(enc.Series(s, b[:0])) - }, - func(s []record.RefSample) { - if err != nil { - return - } - err = repl.Log(enc.Samples(s, b[:0])) - }, - func(s []tombstones.Stone) { - if err != nil { - return - } - err = repl.Log(enc.Tombstones(s, b[:0])) - }, - ) - if decErr != nil { - return fmt.Errorf("decode old entries: %w", err) - } - if err != nil { - return fmt.Errorf("write new entries: %w", err) - } - // We explicitly close even when there is a defer for Windows to be - // able to delete it. The defer is in place to close it in-case there - // are errors above. - if err := w.Close(); err != nil { - return fmt.Errorf("close old WAL: %w", err) - } - if err := repl.Close(); err != nil { - return fmt.Errorf("close new WAL: %w", err) - } - if err := fileutil.Replace(tmpdir, dir); err != nil { - return fmt.Errorf("replace old WAL: %w", err) - } - return nil -} diff --git a/vendor/github.com/prometheus/prometheus/tsdb/wlog/checkpoint.go b/vendor/github.com/prometheus/prometheus/tsdb/wlog/checkpoint.go index 4ad1bb2365..a16cd5fc74 100644 --- a/vendor/github.com/prometheus/prometheus/tsdb/wlog/checkpoint.go +++ b/vendor/github.com/prometheus/prometheus/tsdb/wlog/checkpoint.go @@ -149,22 +149,23 @@ func Checkpoint(logger log.Logger, w *WL, from, to int, keep func(id chunks.Head r := NewReader(sgmReader) var ( - series []record.RefSeries - samples []record.RefSample - histogramSamples []record.RefHistogramSample - tstones []tombstones.Stone - exemplars []record.RefExemplar - metadata []record.RefMetadata - st = labels.NewSymbolTable() // Needed for decoding; labels do not outlive this function. - dec = record.NewDecoder(st) - enc record.Encoder - buf []byte - recs [][]byte + series []record.RefSeries + samples []record.RefSample + histogramSamples []record.RefHistogramSample + floatHistogramSamples []record.RefFloatHistogramSample + tstones []tombstones.Stone + exemplars []record.RefExemplar + metadata []record.RefMetadata + st = labels.NewSymbolTable() // Needed for decoding; labels do not outlive this function. + dec = record.NewDecoder(st) + enc record.Encoder + buf []byte + recs [][]byte latestMetadataMap = make(map[chunks.HeadSeriesRef]record.RefMetadata) ) for r.Next() { - series, samples, histogramSamples, tstones, exemplars, metadata = series[:0], samples[:0], histogramSamples[:0], tstones[:0], exemplars[:0], metadata[:0] + series, samples, histogramSamples, floatHistogramSamples, tstones, exemplars, metadata = series[:0], samples[:0], histogramSamples[:0], floatHistogramSamples[:0], tstones[:0], exemplars[:0], metadata[:0] // We don't reset the buffer since we batch up multiple records // before writing them to the checkpoint. @@ -224,8 +225,26 @@ func Checkpoint(logger log.Logger, w *WL, from, to int, keep func(id chunks.Head if len(repl) > 0 { buf = enc.HistogramSamples(repl, buf) } - stats.TotalSamples += len(samples) - stats.DroppedSamples += len(samples) - len(repl) + stats.TotalSamples += len(histogramSamples) + stats.DroppedSamples += len(histogramSamples) - len(repl) + + case record.FloatHistogramSamples: + floatHistogramSamples, err = dec.FloatHistogramSamples(rec, floatHistogramSamples) + if err != nil { + return nil, fmt.Errorf("decode float histogram samples: %w", err) + } + // Drop irrelevant floatHistogramSamples in place. + repl := floatHistogramSamples[:0] + for _, fh := range floatHistogramSamples { + if fh.T >= mint { + repl = append(repl, fh) + } + } + if len(repl) > 0 { + buf = enc.FloatHistogramSamples(repl, buf) + } + stats.TotalSamples += len(floatHistogramSamples) + stats.DroppedSamples += len(floatHistogramSamples) - len(repl) case record.Tombstones: tstones, err = dec.Tombstones(rec, tstones) diff --git a/vendor/github.com/prometheus/prometheus/util/teststorage/storage.go b/vendor/github.com/prometheus/prometheus/util/teststorage/storage.go index 5d95437e99..7d1f9dda24 100644 --- a/vendor/github.com/prometheus/prometheus/util/teststorage/storage.go +++ b/vendor/github.com/prometheus/prometheus/util/teststorage/storage.go @@ -14,6 +14,7 @@ package teststorage import ( + "fmt" "os" "time" @@ -30,8 +31,18 @@ import ( // New returns a new TestStorage for testing purposes // that removes all associated files on closing. func New(t testutil.T) *TestStorage { + stor, err := NewWithError() + require.NoError(t, err) + return stor +} + +// NewWithError returns a new TestStorage for user facing tests, which reports +// errors directly. +func NewWithError() (*TestStorage, error) { dir, err := os.MkdirTemp("", "test_storage") - require.NoError(t, err, "unexpected error while opening test directory") + if err != nil { + return nil, fmt.Errorf("opening test directory: %w", err) + } // Tests just load data for a series sequentially. Thus we // need a long appendable window. @@ -41,13 +52,17 @@ func New(t testutil.T) *TestStorage { opts.RetentionDuration = 0 opts.EnableNativeHistograms = true db, err := tsdb.Open(dir, nil, nil, opts, tsdb.NewDBStats()) - require.NoError(t, err, "unexpected error while opening test storage") + if err != nil { + return nil, fmt.Errorf("opening test storage: %w", err) + } reg := prometheus.NewRegistry() eMetrics := tsdb.NewExemplarMetrics(reg) es, err := tsdb.NewCircularExemplarStorage(10, eMetrics) - require.NoError(t, err, "unexpected error while opening test exemplar storage") - return &TestStorage{DB: db, exemplarStorage: es, dir: dir} + if err != nil { + return nil, fmt.Errorf("opening test exemplar storage: %w", err) + } + return &TestStorage{DB: db, exemplarStorage: es, dir: dir}, nil } type TestStorage struct { diff --git a/vendor/github.com/prometheus/prometheus/web/api/v1/api.go b/vendor/github.com/prometheus/prometheus/web/api/v1/api.go index 48938fce12..dc22365073 100644 --- a/vendor/github.com/prometheus/prometheus/web/api/v1/api.go +++ b/vendor/github.com/prometheus/prometheus/web/api/v1/api.go @@ -177,13 +177,6 @@ type TSDBAdminStats interface { WALReplayStatus() (tsdb.WALReplayStatus, error) } -// QueryEngine defines the interface for the *promql.Engine, so it can be replaced, wrapped or mocked. -type QueryEngine interface { - SetQueryLogger(l promql.QueryLogger) - NewInstantQuery(ctx context.Context, q storage.Queryable, opts promql.QueryOpts, qs string, ts time.Time) (promql.Query, error) - NewRangeQuery(ctx context.Context, q storage.Queryable, opts promql.QueryOpts, qs string, start, end time.Time, interval time.Duration) (promql.Query, error) -} - type QueryOpts interface { EnablePerStepStats() bool LookbackDelta() time.Duration @@ -193,7 +186,7 @@ type QueryOpts interface { // them using the provided storage and query engine. type API struct { Queryable storage.SampleAndChunkQueryable - QueryEngine QueryEngine + QueryEngine promql.QueryEngine ExemplarQueryable storage.ExemplarQueryable scrapePoolsRetriever func(context.Context) ScrapePoolsRetriever @@ -226,7 +219,7 @@ type API struct { // NewAPI returns an initialized API type. func NewAPI( - qe QueryEngine, + qe promql.QueryEngine, q storage.SampleAndChunkQueryable, ap storage.Appendable, eq storage.ExemplarQueryable, @@ -889,6 +882,9 @@ func (api *API) series(r *http.Request) (result apiFuncResult) { warnings := set.Warnings() for set.Next() { + if err := ctx.Err(); err != nil { + return apiFuncResult{nil, returnAPIError(err), warnings, closer} + } metrics = append(metrics, set.At().Labels()) if len(metrics) >= limit { diff --git a/vendor/github.com/rs/cors/README.md b/vendor/github.com/rs/cors/README.md index 0ad3e94e1b..fe12fa671d 100644 --- a/vendor/github.com/rs/cors/README.md +++ b/vendor/github.com/rs/cors/README.md @@ -1,4 +1,4 @@ -# Go CORS handler [![godoc](http://img.shields.io/badge/godoc-reference-blue.svg?style=flat)](https://godoc.org/github.com/rs/cors) [![license](http://img.shields.io/badge/license-MIT-red.svg?style=flat)](https://raw.githubusercontent.com/rs/cors/master/LICENSE) [![build](https://img.shields.io/travis/rs/cors.svg?style=flat)](https://travis-ci.org/rs/cors) [![Coverage](http://gocover.io/_badge/github.com/rs/cors)](http://gocover.io/github.com/rs/cors) +# Go CORS handler [![godoc](http://img.shields.io/badge/godoc-reference-blue.svg?style=flat)](https://godoc.org/github.com/rs/cors) [![license](http://img.shields.io/badge/license-MIT-red.svg?style=flat)](https://raw.githubusercontent.com/rs/cors/master/LICENSE) [![Go Coverage](https://github.com/rs/cors/wiki/coverage.svg)](https://raw.githack.com/wiki/rs/cors/coverage.html) CORS is a `net/http` handler implementing [Cross Origin Resource Sharing W3 specification](http://www.w3.org/TR/cors/) in Golang. @@ -102,15 +102,18 @@ See [API documentation](http://godoc.org/github.com/rs/cors) for more info. ## Benchmarks - BenchmarkWithout 20000000 64.6 ns/op 8 B/op 1 allocs/op - BenchmarkDefault 3000000 469 ns/op 114 B/op 2 allocs/op - BenchmarkAllowedOrigin 3000000 608 ns/op 114 B/op 2 allocs/op - BenchmarkPreflight 20000000 73.2 ns/op 0 B/op 0 allocs/op - BenchmarkPreflightHeader 20000000 73.6 ns/op 0 B/op 0 allocs/op - BenchmarkParseHeaderList 2000000 847 ns/op 184 B/op 6 allocs/op - BenchmarkParse…Single 5000000 290 ns/op 32 B/op 3 allocs/op - BenchmarkParse…Normalized 2000000 776 ns/op 160 B/op 6 allocs/op - +goos: darwin +goarch: arm64 +pkg: github.com/rs/cors +BenchmarkWithout-10 352671961 3.317 ns/op 0 B/op 0 allocs/op +BenchmarkDefault-10 18261723 65.63 ns/op 0 B/op 0 allocs/op +BenchmarkAllowedOrigin-10 13309591 90.21 ns/op 0 B/op 0 allocs/op +BenchmarkPreflight-10 7247728 166.9 ns/op 0 B/op 0 allocs/op +BenchmarkPreflightHeader-10 5915437 202.9 ns/op 0 B/op 0 allocs/op +BenchmarkWildcard/match-10 250336476 4.784 ns/op 0 B/op 0 allocs/op +BenchmarkWildcard/too_short-10 1000000000 0.6354 ns/op 0 B/op 0 allocs/op +PASS +ok github.com/rs/cors 9.613s ## Licenses All source code is licensed under the [MIT License](https://raw.github.com/rs/cors/master/LICENSE). diff --git a/vendor/github.com/rs/cors/cors.go b/vendor/github.com/rs/cors/cors.go index 5669a67f89..69f89d8f94 100644 --- a/vendor/github.com/rs/cors/cors.go +++ b/vendor/github.com/rs/cors/cors.go @@ -4,15 +4,15 @@ as defined by http://www.w3.org/TR/cors/ You can configure it by passing an option struct to cors.New: - c := cors.New(cors.Options{ - AllowedOrigins: []string{"foo.com"}, - AllowedMethods: []string{http.MethodGet, http.MethodPost, http.MethodDelete}, - AllowCredentials: true, - }) + c := cors.New(cors.Options{ + AllowedOrigins: []string{"foo.com"}, + AllowedMethods: []string{http.MethodGet, http.MethodPost, http.MethodDelete}, + AllowCredentials: true, + }) Then insert the handler in the chain: - handler = c.Handler(handler) + handler = c.Handler(handler) See Options documentation for more options. @@ -28,6 +28,10 @@ import ( "strings" ) +var headerVaryOrigin = []string{"Origin"} +var headerOriginAll = []string{"*"} +var headerTrue = []string{"true"} + // Options is a configuration container to setup the CORS middleware. type Options struct { // AllowedOrigins is a list of origins a cross-domain request can be executed from. @@ -37,27 +41,39 @@ type Options struct { // Only one wildcard can be used per origin. // Default value is ["*"] AllowedOrigins []string - // AllowOriginFunc is a custom function to validate the origin. It take the origin - // as argument and returns true if allowed or false otherwise. If this option is - // set, the content of AllowedOrigins is ignored. + // AllowOriginFunc is a custom function to validate the origin. It take the + // origin as argument and returns true if allowed or false otherwise. If + // this option is set, the content of `AllowedOrigins` is ignored. AllowOriginFunc func(origin string) bool - // AllowOriginRequestFunc is a custom function to validate the origin. It takes the HTTP Request object and the origin as - // argument and returns true if allowed or false otherwise. If this option is set, the content of `AllowedOrigins` - // and `AllowOriginFunc` is ignored. + // AllowOriginRequestFunc is a custom function to validate the origin. It + // takes the HTTP Request object and the origin as argument and returns true + // if allowed or false otherwise. If headers are used take the decision, + // consider using AllowOriginVaryRequestFunc instead. If this option is set, + // the content of `AllowedOrigins`, `AllowOriginFunc` are ignored. AllowOriginRequestFunc func(r *http.Request, origin string) bool + // AllowOriginVaryRequestFunc is a custom function to validate the origin. + // It takes the HTTP Request object and the origin as argument and returns + // true if allowed or false otherwise with a list of headers used to take + // that decision if any so they can be added to the Vary header. If this + // option is set, the content of `AllowedOrigins`, `AllowOriginFunc` and + // `AllowOriginRequestFunc` are ignored. + AllowOriginVaryRequestFunc func(r *http.Request, origin string) (bool, []string) // AllowedMethods is a list of methods the client is allowed to use with // cross-domain requests. Default value is simple methods (HEAD, GET and POST). AllowedMethods []string // AllowedHeaders is list of non simple headers the client is allowed to use with // cross-domain requests. // If the special "*" value is present in the list, all headers will be allowed. - // Default value is [] but "Origin" is always appended to the list. + // Default value is []. AllowedHeaders []string // ExposedHeaders indicates which headers are safe to expose to the API of a CORS // API specification ExposedHeaders []string // MaxAge indicates how long (in seconds) the results of a preflight request - // can be cached + // can be cached. Default value is 0, which stands for no + // Access-Control-Max-Age header to be sent back, resulting in browsers + // using their default value (5s by spec). If you need to force a 0 max-age, + // set `MaxAge` to a negative value (ie: -1). MaxAge int // AllowCredentials indicates whether the request can include user credentials like // cookies, HTTP authentication or client side SSL certificates. @@ -73,6 +89,8 @@ type Options struct { OptionsSuccessStatus int // Debugging flag adds additional output to debug server side CORS issues Debug bool + // Adds a custom logger, implies Debug is true + Logger Logger } // Logger generic interface for logger @@ -89,16 +107,15 @@ type Cors struct { // List of allowed origins containing wildcards allowedWOrigins []wildcard // Optional origin validator function - allowOriginFunc func(origin string) bool - // Optional origin validator (with request) function - allowOriginRequestFunc func(r *http.Request, origin string) bool + allowOriginFunc func(r *http.Request, origin string) (bool, []string) // Normalized list of allowed headers allowedHeaders []string // Normalized list of allowed methods allowedMethods []string - // Normalized list of exposed headers + // Pre-computed normalized list of exposed headers exposedHeaders []string - maxAge int + // Pre-computed maxAge header value + maxAge []string // Set to true when allowed origins contains a "*" allowedOriginsAll bool // Set to true when allowed headers contains a "*" @@ -108,30 +125,40 @@ type Cors struct { allowCredentials bool allowPrivateNetwork bool optionPassthrough bool + preflightVary []string } // New creates a new Cors handler with the provided options. func New(options Options) *Cors { c := &Cors{ - exposedHeaders: convert(options.ExposedHeaders, http.CanonicalHeaderKey), - allowOriginFunc: options.AllowOriginFunc, - allowOriginRequestFunc: options.AllowOriginRequestFunc, - allowCredentials: options.AllowCredentials, - allowPrivateNetwork: options.AllowPrivateNetwork, - maxAge: options.MaxAge, - optionPassthrough: options.OptionsPassthrough, + allowCredentials: options.AllowCredentials, + allowPrivateNetwork: options.AllowPrivateNetwork, + optionPassthrough: options.OptionsPassthrough, + Log: options.Logger, } if options.Debug && c.Log == nil { c.Log = log.New(os.Stdout, "[cors] ", log.LstdFlags) } + if options.AllowOriginVaryRequestFunc != nil { + c.allowOriginFunc = options.AllowOriginVaryRequestFunc + } else if options.AllowOriginRequestFunc != nil { + c.allowOriginFunc = func(r *http.Request, origin string) (bool, []string) { + return options.AllowOriginRequestFunc(r, origin), nil + } + } else if options.AllowOriginFunc != nil { + c.allowOriginFunc = func(r *http.Request, origin string) (bool, []string) { + return options.AllowOriginFunc(origin), nil + } + } + // Normalize options - // Note: for origins and methods matching, the spec requires a case-sensitive matching. + // Note: for origins matching, the spec requires a case-sensitive matching. // As it may error prone, we chose to ignore the spec here. // Allowed Origins if len(options.AllowedOrigins) == 0 { - if options.AllowOriginFunc == nil && options.AllowOriginRequestFunc == nil { + if c.allowOriginFunc == nil { // Default is all origins c.allowedOriginsAll = true } @@ -160,10 +187,9 @@ func New(options Options) *Cors { // Allowed Headers if len(options.AllowedHeaders) == 0 { // Use sensible defaults - c.allowedHeaders = []string{"Origin", "Accept", "Content-Type", "X-Requested-With"} + c.allowedHeaders = []string{"Accept", "Content-Type", "X-Requested-With"} } else { - // Origin is always appended as some browsers will always request for this header at preflight - c.allowedHeaders = convert(append(options.AllowedHeaders, "Origin"), http.CanonicalHeaderKey) + c.allowedHeaders = convert(options.AllowedHeaders, http.CanonicalHeaderKey) for _, h := range options.AllowedHeaders { if h == "*" { c.allowedHeadersAll = true @@ -178,7 +204,7 @@ func New(options Options) *Cors { // Default is spec's "simple" methods c.allowedMethods = []string{http.MethodGet, http.MethodPost, http.MethodHead} } else { - c.allowedMethods = convert(options.AllowedMethods, strings.ToUpper) + c.allowedMethods = options.AllowedMethods } // Options Success Status Code @@ -188,6 +214,25 @@ func New(options Options) *Cors { c.optionsSuccessStatus = options.OptionsSuccessStatus } + // Pre-compute exposed headers header value + if len(options.ExposedHeaders) > 0 { + c.exposedHeaders = []string{strings.Join(convert(options.ExposedHeaders, http.CanonicalHeaderKey), ", ")} + } + + // Pre-compute prefight Vary header to save allocations + if c.allowPrivateNetwork { + c.preflightVary = []string{"Origin, Access-Control-Request-Method, Access-Control-Request-Headers, Access-Control-Request-Private-Network"} + } else { + c.preflightVary = []string{"Origin, Access-Control-Request-Method, Access-Control-Request-Headers"} + } + + // Precompute max-age + if options.MaxAge > 0 { + c.maxAge = []string{strconv.Itoa(options.MaxAge)} + } else if options.MaxAge < 0 { + c.maxAge = []string{"0"} + } + return c } @@ -284,18 +329,21 @@ func (c *Cors) handlePreflight(w http.ResponseWriter, r *http.Request) { // Always set Vary headers // see https://github.com/rs/cors/issues/10, // https://github.com/rs/cors/commit/dbdca4d95feaa7511a46e6f1efb3b3aa505bc43f#commitcomment-12352001 - headers.Add("Vary", "Origin") - headers.Add("Vary", "Access-Control-Request-Method") - headers.Add("Vary", "Access-Control-Request-Headers") - if c.allowPrivateNetwork { - headers.Add("Vary", "Access-Control-Request-Private-Network") + if vary, found := headers["Vary"]; found { + headers["Vary"] = append(vary, c.preflightVary[0]) + } else { + headers["Vary"] = c.preflightVary + } + allowed, additionalVaryHeaders := c.isOriginAllowed(r, origin) + if len(additionalVaryHeaders) > 0 { + headers.Add("Vary", strings.Join(convert(additionalVaryHeaders, http.CanonicalHeaderKey), ", ")) } if origin == "" { c.logf(" Preflight aborted: empty origin") return } - if !c.isOriginAllowed(r, origin) { + if !allowed { c.logf(" Preflight aborted: origin '%s' not allowed", origin) return } @@ -305,40 +353,41 @@ func (c *Cors) handlePreflight(w http.ResponseWriter, r *http.Request) { c.logf(" Preflight aborted: method '%s' not allowed", reqMethod) return } - // Amazon API Gateway is sometimes feeding multiple values for - // Access-Control-Request-Headers in a way where r.Header.Values() picks - // them all up, but r.Header.Get() does not. - // I suspect it is something like this: https://stackoverflow.com/a/4371395 - reqHeaderList := strings.Join(r.Header.Values("Access-Control-Request-Headers"), ",") - reqHeaders := parseHeaderList(reqHeaderList) + reqHeadersRaw := r.Header["Access-Control-Request-Headers"] + reqHeaders, reqHeadersEdited := convertDidCopy(splitHeaderValues(reqHeadersRaw), http.CanonicalHeaderKey) if !c.areHeadersAllowed(reqHeaders) { c.logf(" Preflight aborted: headers '%v' not allowed", reqHeaders) return } if c.allowedOriginsAll { - headers.Set("Access-Control-Allow-Origin", "*") + headers["Access-Control-Allow-Origin"] = headerOriginAll } else { - headers.Set("Access-Control-Allow-Origin", origin) + headers["Access-Control-Allow-Origin"] = r.Header["Origin"] } // Spec says: Since the list of methods can be unbounded, simply returning the method indicated // by Access-Control-Request-Method (if supported) can be enough - headers.Set("Access-Control-Allow-Methods", strings.ToUpper(reqMethod)) + headers["Access-Control-Allow-Methods"] = r.Header["Access-Control-Request-Method"] if len(reqHeaders) > 0 { - // Spec says: Since the list of headers can be unbounded, simply returning supported headers // from Access-Control-Request-Headers can be enough - headers.Set("Access-Control-Allow-Headers", strings.Join(reqHeaders, ", ")) + if reqHeadersEdited || len(reqHeaders) != len(reqHeadersRaw) { + headers.Set("Access-Control-Allow-Headers", strings.Join(reqHeaders, ", ")) + } else { + headers["Access-Control-Allow-Headers"] = reqHeadersRaw + } } if c.allowCredentials { - headers.Set("Access-Control-Allow-Credentials", "true") + headers["Access-Control-Allow-Credentials"] = headerTrue } if c.allowPrivateNetwork && r.Header.Get("Access-Control-Request-Private-Network") == "true" { - headers.Set("Access-Control-Allow-Private-Network", "true") + headers["Access-Control-Allow-Private-Network"] = headerTrue } - if c.maxAge > 0 { - headers.Set("Access-Control-Max-Age", strconv.Itoa(c.maxAge)) + if len(c.maxAge) > 0 { + headers["Access-Control-Max-Age"] = c.maxAge + } + if c.Log != nil { + c.logf(" Preflight response headers: %v", headers) } - c.logf(" Preflight response headers: %v", headers) } // handleActualRequest handles simple cross-origin requests, actual request or redirects @@ -346,13 +395,22 @@ func (c *Cors) handleActualRequest(w http.ResponseWriter, r *http.Request) { headers := w.Header() origin := r.Header.Get("Origin") + allowed, additionalVaryHeaders := c.isOriginAllowed(r, origin) + // Always set Vary, see https://github.com/rs/cors/issues/10 - headers.Add("Vary", "Origin") + if vary, found := headers["Vary"]; found { + headers["Vary"] = append(vary, headerVaryOrigin[0]) + } else { + headers["Vary"] = headerVaryOrigin + } + if len(additionalVaryHeaders) > 0 { + headers.Add("Vary", strings.Join(convert(additionalVaryHeaders, http.CanonicalHeaderKey), ", ")) + } if origin == "" { c.logf(" Actual request no headers added: missing origin") return } - if !c.isOriginAllowed(r, origin) { + if !allowed { c.logf(" Actual request no headers added: origin '%s' not allowed", origin) return } @@ -363,21 +421,22 @@ func (c *Cors) handleActualRequest(w http.ResponseWriter, r *http.Request) { // We think it's a nice feature to be able to have control on those methods though. if !c.isMethodAllowed(r.Method) { c.logf(" Actual request no headers added: method '%s' not allowed", r.Method) - return } if c.allowedOriginsAll { - headers.Set("Access-Control-Allow-Origin", "*") + headers["Access-Control-Allow-Origin"] = headerOriginAll } else { - headers.Set("Access-Control-Allow-Origin", origin) + headers["Access-Control-Allow-Origin"] = r.Header["Origin"] } if len(c.exposedHeaders) > 0 { - headers.Set("Access-Control-Expose-Headers", strings.Join(c.exposedHeaders, ", ")) + headers["Access-Control-Expose-Headers"] = c.exposedHeaders } if c.allowCredentials { - headers.Set("Access-Control-Allow-Credentials", "true") + headers["Access-Control-Allow-Credentials"] = headerTrue + } + if c.Log != nil { + c.logf(" Actual response added headers: %v", headers) } - c.logf(" Actual response added headers: %v", headers) } // convenience method. checks if a logger is set. @@ -390,33 +449,31 @@ func (c *Cors) logf(format string, a ...interface{}) { // check the Origin of a request. No origin at all is also allowed. func (c *Cors) OriginAllowed(r *http.Request) bool { origin := r.Header.Get("Origin") - return c.isOriginAllowed(r, origin) + allowed, _ := c.isOriginAllowed(r, origin) + return allowed } // isOriginAllowed checks if a given origin is allowed to perform cross-domain requests // on the endpoint -func (c *Cors) isOriginAllowed(r *http.Request, origin string) bool { - if c.allowOriginRequestFunc != nil { - return c.allowOriginRequestFunc(r, origin) - } +func (c *Cors) isOriginAllowed(r *http.Request, origin string) (allowed bool, varyHeaders []string) { if c.allowOriginFunc != nil { - return c.allowOriginFunc(origin) + return c.allowOriginFunc(r, origin) } if c.allowedOriginsAll { - return true + return true, nil } origin = strings.ToLower(origin) for _, o := range c.allowedOrigins { if o == origin { - return true + return true, nil } } for _, w := range c.allowedWOrigins { if w.match(origin) { - return true + return true, nil } } - return false + return false, nil } // isMethodAllowed checks if a given method can be used as part of a cross-domain request @@ -426,7 +483,6 @@ func (c *Cors) isMethodAllowed(method string) bool { // If no method allowed, always return false, even for preflight request return false } - method = strings.ToUpper(method) if method == http.MethodOptions { // Always allow preflight requests return true @@ -446,7 +502,6 @@ func (c *Cors) areHeadersAllowed(requestedHeaders []string) bool { return true } for _, header := range requestedHeaders { - header = http.CanonicalHeaderKey(header) found := false for _, h := range c.allowedHeaders { if h == header { diff --git a/vendor/github.com/rs/cors/utils.go b/vendor/github.com/rs/cors/utils.go index 6bb120caed..ca9983d3f7 100644 --- a/vendor/github.com/rs/cors/utils.go +++ b/vendor/github.com/rs/cors/utils.go @@ -1,8 +1,8 @@ package cors -import "strings" - -const toLower = 'a' - 'A' +import ( + "strings" +) type converter func(string) string @@ -15,57 +15,58 @@ func (w wildcard) match(s string) bool { return len(s) >= len(w.prefix)+len(w.suffix) && strings.HasPrefix(s, w.prefix) && strings.HasSuffix(s, w.suffix) } -// convert converts a list of string using the passed converter function -func convert(s []string, c converter) []string { - out := []string{} - for _, i := range s { - out = append(out, c(i)) - } - return out -} - -// parseHeaderList tokenize + normalize a string containing a list of headers -func parseHeaderList(headerList string) []string { - l := len(headerList) - h := make([]byte, 0, l) - upper := true - // Estimate the number headers in order to allocate the right splice size - t := 0 - for i := 0; i < l; i++ { - if headerList[i] == ',' { - t++ - } - } - headers := make([]string, 0, t) - for i := 0; i < l; i++ { - b := headerList[i] - switch { - case b >= 'a' && b <= 'z': - if upper { - h = append(h, b-toLower) - } else { - h = append(h, b) +// split compounded header values ["foo, bar", "baz"] -> ["foo", "bar", "baz"] +func splitHeaderValues(values []string) []string { + out := values + copied := false + for i, v := range values { + needsSplit := strings.IndexByte(v, ',') != -1 + if !copied { + if needsSplit { + split := strings.Split(v, ",") + out = make([]string, i, len(values)+len(split)-1) + copy(out, values[:i]) + for _, s := range split { + out = append(out, strings.TrimSpace(s)) + } + copied = true } - case b >= 'A' && b <= 'Z': - if !upper { - h = append(h, b+toLower) + } else { + if needsSplit { + split := strings.Split(v, ",") + for _, s := range split { + out = append(out, strings.TrimSpace(s)) + } } else { - h = append(h, b) + out = append(out, v) } - case b == '-' || b == '_' || b == '.' || (b >= '0' && b <= '9'): - h = append(h, b) } + } + return out +} + +// convert converts a list of string using the passed converter function +func convert(s []string, c converter) []string { + out, _ := convertDidCopy(s, c) + return out +} - if b == ' ' || b == ',' || i == l-1 { - if len(h) > 0 { - // Flush the found header - headers = append(headers, string(h)) - h = h[:0] - upper = true +// convertDidCopy is same as convert but returns true if it copied the slice +func convertDidCopy(s []string, c converter) ([]string, bool) { + out := s + copied := false + for i, v := range s { + if !copied { + v2 := c(v) + if v2 != v { + out = make([]string, len(s)) + copy(out, s[:i]) + out[i] = v2 + copied = true } } else { - upper = b == '-' || b == '_' + out[i] = c(v) } } - return headers + return out, copied } diff --git a/vendor/github.com/stretchr/objx/README.md b/vendor/github.com/stretchr/objx/README.md index 246660b21a..78dc1f8b03 100644 --- a/vendor/github.com/stretchr/objx/README.md +++ b/vendor/github.com/stretchr/objx/README.md @@ -4,20 +4,20 @@ [![Maintainability](https://api.codeclimate.com/v1/badges/1d64bc6c8474c2074f2b/maintainability)](https://codeclimate.com/github/stretchr/objx/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/1d64bc6c8474c2074f2b/test_coverage)](https://codeclimate.com/github/stretchr/objx/test_coverage) [![Sourcegraph](https://sourcegraph.com/github.com/stretchr/objx/-/badge.svg)](https://sourcegraph.com/github.com/stretchr/objx) -[![GoDoc](https://godoc.org/github.com/stretchr/objx?status.svg)](https://godoc.org/github.com/stretchr/objx) +[![GoDoc](https://pkg.go.dev/badge/github.com/stretchr/objx?utm_source=godoc)](https://pkg.go.dev/github.com/stretchr/objx) Objx - Go package for dealing with maps, slices, JSON and other data. Get started: - Install Objx with [one line of code](#installation), or [update it with another](#staying-up-to-date) -- Check out the API Documentation http://godoc.org/github.com/stretchr/objx +- Check out the API Documentation http://pkg.go.dev/github.com/stretchr/objx ## Overview Objx provides the `objx.Map` type, which is a `map[string]interface{}` that exposes a powerful `Get` method (among others) that allows you to easily and quickly get access to data within the map, without having to worry too much about type assertions, missing data, default values etc. ### Pattern -Objx uses a preditable pattern to make access data from within `map[string]interface{}` easy. Call one of the `objx.` functions to create your `objx.Map` to get going: +Objx uses a predictable pattern to make access data from within `map[string]interface{}` easy. Call one of the `objx.` functions to create your `objx.Map` to get going: m, err := objx.FromJSON(json) @@ -74,7 +74,7 @@ To update Objx to the latest version, run: go get -u github.com/stretchr/objx ### Supported go versions -We support the lastest three major Go versions, which are 1.10, 1.11 and 1.12 at the moment. +We currently support the three recent major Go versions. ## Contributing Please feel free to submit issues, fork the repository and send pull requests! diff --git a/vendor/github.com/stretchr/objx/Taskfile.yml b/vendor/github.com/stretchr/objx/Taskfile.yml index 7746f516da..8a79e8d674 100644 --- a/vendor/github.com/stretchr/objx/Taskfile.yml +++ b/vendor/github.com/stretchr/objx/Taskfile.yml @@ -1,7 +1,4 @@ -version: '2' - -env: - GOFLAGS: -mod=vendor +version: '3' tasks: default: diff --git a/vendor/github.com/stretchr/objx/accessors.go b/vendor/github.com/stretchr/objx/accessors.go index 4c60455886..72f1d1c1ce 100644 --- a/vendor/github.com/stretchr/objx/accessors.go +++ b/vendor/github.com/stretchr/objx/accessors.go @@ -14,17 +14,17 @@ const ( // For example, `location.address.city` PathSeparator string = "." - // arrayAccesRegexString is the regex used to extract the array number + // arrayAccessRegexString is the regex used to extract the array number // from the access path - arrayAccesRegexString = `^(.+)\[([0-9]+)\]$` + arrayAccessRegexString = `^(.+)\[([0-9]+)\]$` // mapAccessRegexString is the regex used to extract the map key // from the access path mapAccessRegexString = `^([^\[]*)\[([^\]]+)\](.*)$` ) -// arrayAccesRegex is the compiled arrayAccesRegexString -var arrayAccesRegex = regexp.MustCompile(arrayAccesRegexString) +// arrayAccessRegex is the compiled arrayAccessRegexString +var arrayAccessRegex = regexp.MustCompile(arrayAccessRegexString) // mapAccessRegex is the compiled mapAccessRegexString var mapAccessRegex = regexp.MustCompile(mapAccessRegexString) @@ -37,11 +37,11 @@ var mapAccessRegex = regexp.MustCompile(mapAccessRegexString) // // Get can only operate directly on map[string]interface{} and []interface. // -// Example +// # Example // // To access the title of the third chapter of the second book, do: // -// o.Get("books[1].chapters[2].title") +// o.Get("books[1].chapters[2].title") func (m Map) Get(selector string) *Value { rawObj := access(m, selector, nil, false) return &Value{data: rawObj} @@ -52,26 +52,26 @@ func (m Map) Get(selector string) *Value { // // Set can only operate directly on map[string]interface{} and []interface // -// Example +// # Example // // To set the title of the third chapter of the second book, do: // -// o.Set("books[1].chapters[2].title","Time to Go") +// o.Set("books[1].chapters[2].title","Time to Go") func (m Map) Set(selector string, value interface{}) Map { access(m, selector, value, true) return m } -// getIndex returns the index, which is hold in s by two braches. -// It also returns s withour the index part, e.g. name[1] will return (1, name). +// getIndex returns the index, which is hold in s by two branches. +// It also returns s without the index part, e.g. name[1] will return (1, name). // If no index is found, -1 is returned func getIndex(s string) (int, string) { - arrayMatches := arrayAccesRegex.FindStringSubmatch(s) + arrayMatches := arrayAccessRegex.FindStringSubmatch(s) if len(arrayMatches) > 0 { // Get the key into the map selector := arrayMatches[1] // Get the index into the array at the key - // We know this cannt fail because arrayMatches[2] is an int for sure + // We know this can't fail because arrayMatches[2] is an int for sure index, _ := strconv.Atoi(arrayMatches[2]) return index, selector } diff --git a/vendor/github.com/stretchr/objx/conversions.go b/vendor/github.com/stretchr/objx/conversions.go index 080aa46e47..01c63d7d3b 100644 --- a/vendor/github.com/stretchr/objx/conversions.go +++ b/vendor/github.com/stretchr/objx/conversions.go @@ -15,7 +15,7 @@ import ( const SignatureSeparator = "_" // URLValuesSliceKeySuffix is the character that is used to -// specify a suffic for slices parsed by URLValues. +// specify a suffix for slices parsed by URLValues. // If the suffix is set to "[i]", then the index of the slice // is used in place of i // Ex: Suffix "[]" would have the form a[]=b&a[]=c @@ -30,7 +30,7 @@ const ( ) // SetURLValuesSliceKeySuffix sets the character that is used to -// specify a suffic for slices parsed by URLValues. +// specify a suffix for slices parsed by URLValues. // If the suffix is set to "[i]", then the index of the slice // is used in place of i // Ex: Suffix "[]" would have the form a[]=b&a[]=c diff --git a/vendor/github.com/stretchr/objx/doc.go b/vendor/github.com/stretchr/objx/doc.go index 6d6af1a83a..b170af74b3 100644 --- a/vendor/github.com/stretchr/objx/doc.go +++ b/vendor/github.com/stretchr/objx/doc.go @@ -1,19 +1,19 @@ /* -Objx - Go package for dealing with maps, slices, JSON and other data. +Package objx provides utilities for dealing with maps, slices, JSON and other data. -Overview +# Overview Objx provides the `objx.Map` type, which is a `map[string]interface{}` that exposes a powerful `Get` method (among others) that allows you to easily and quickly get access to data within the map, without having to worry too much about type assertions, missing data, default values etc. -Pattern +# Pattern -Objx uses a preditable pattern to make access data from within `map[string]interface{}` easy. +Objx uses a predictable pattern to make access data from within `map[string]interface{}` easy. Call one of the `objx.` functions to create your `objx.Map` to get going: - m, err := objx.FromJSON(json) + m, err := objx.FromJSON(json) NOTE: Any methods or functions with the `Must` prefix will panic if something goes wrong, the rest will be optimistic and try to figure things out without panicking. @@ -21,46 +21,46 @@ the rest will be optimistic and try to figure things out without panicking. Use `Get` to access the value you're interested in. You can use dot and array notation too: - m.Get("places[0].latlng") + m.Get("places[0].latlng") Once you have sought the `Value` you're interested in, you can use the `Is*` methods to determine its type. - if m.Get("code").IsStr() { // Your code... } + if m.Get("code").IsStr() { // Your code... } Or you can just assume the type, and use one of the strong type methods to extract the real value: - m.Get("code").Int() + m.Get("code").Int() If there's no value there (or if it's the wrong type) then a default value will be returned, or you can be explicit about the default value. - Get("code").Int(-1) + Get("code").Int(-1) If you're dealing with a slice of data as a value, Objx provides many useful methods for iterating, manipulating and selecting that data. You can find out more by exploring the index below. -Reading data +# Reading data A simple example of how to use Objx: - // Use MustFromJSON to make an objx.Map from some JSON - m := objx.MustFromJSON(`{"name": "Mat", "age": 30}`) + // Use MustFromJSON to make an objx.Map from some JSON + m := objx.MustFromJSON(`{"name": "Mat", "age": 30}`) - // Get the details - name := m.Get("name").Str() - age := m.Get("age").Int() + // Get the details + name := m.Get("name").Str() + age := m.Get("age").Int() - // Get their nickname (or use their name if they don't have one) - nickname := m.Get("nickname").Str(name) + // Get their nickname (or use their name if they don't have one) + nickname := m.Get("nickname").Str(name) -Ranging +# Ranging Since `objx.Map` is a `map[string]interface{}` you can treat it as such. For example, to `range` the data, do what you would expect: - m := objx.MustFromJSON(json) - for key, value := range m { - // Your code... - } + m := objx.MustFromJSON(json) + for key, value := range m { + // Your code... + } */ package objx diff --git a/vendor/github.com/stretchr/objx/map.go b/vendor/github.com/stretchr/objx/map.go index a64712a08b..ab9f9ae67c 100644 --- a/vendor/github.com/stretchr/objx/map.go +++ b/vendor/github.com/stretchr/objx/map.go @@ -47,17 +47,16 @@ func New(data interface{}) Map { // // The arguments follow a key, value pattern. // -// // Returns nil if any key argument is non-string or if there are an odd number of arguments. // -// Example +// # Example // // To easily create Maps: // -// m := objx.MSI("name", "Mat", "age", 29, "subobj", objx.MSI("active", true)) +// m := objx.MSI("name", "Mat", "age", 29, "subobj", objx.MSI("active", true)) // -// // creates an Map equivalent to -// m := objx.Map{"name": "Mat", "age": 29, "subobj": objx.Map{"active": true}} +// // creates an Map equivalent to +// m := objx.Map{"name": "Mat", "age": 29, "subobj": objx.Map{"active": true}} func MSI(keyAndValuePairs ...interface{}) Map { newMap := Map{} keyAndValuePairsLen := len(keyAndValuePairs) diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare.go b/vendor/github.com/stretchr/testify/assert/assertion_compare.go index b774da88d8..4d4b4aad6f 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_compare.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_compare.go @@ -28,6 +28,8 @@ var ( uint32Type = reflect.TypeOf(uint32(1)) uint64Type = reflect.TypeOf(uint64(1)) + uintptrType = reflect.TypeOf(uintptr(1)) + float32Type = reflect.TypeOf(float32(1)) float64Type = reflect.TypeOf(float64(1)) @@ -308,11 +310,11 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { case reflect.Struct: { // All structs enter here. We're not interested in most types. - if !canConvert(obj1Value, timeType) { + if !obj1Value.CanConvert(timeType) { break } - // time.Time can compared! + // time.Time can be compared! timeObj1, ok := obj1.(time.Time) if !ok { timeObj1 = obj1Value.Convert(timeType).Interface().(time.Time) @@ -328,7 +330,7 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { case reflect.Slice: { // We only care about the []byte type. - if !canConvert(obj1Value, bytesType) { + if !obj1Value.CanConvert(bytesType) { break } @@ -345,6 +347,26 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { return CompareType(bytes.Compare(bytesObj1, bytesObj2)), true } + case reflect.Uintptr: + { + uintptrObj1, ok := obj1.(uintptr) + if !ok { + uintptrObj1 = obj1Value.Convert(uintptrType).Interface().(uintptr) + } + uintptrObj2, ok := obj2.(uintptr) + if !ok { + uintptrObj2 = obj2Value.Convert(uintptrType).Interface().(uintptr) + } + if uintptrObj1 > uintptrObj2 { + return compareGreater, true + } + if uintptrObj1 == uintptrObj2 { + return compareEqual, true + } + if uintptrObj1 < uintptrObj2 { + return compareLess, true + } + } } return compareEqual, false diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go b/vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go deleted file mode 100644 index da867903e2..0000000000 --- a/vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build go1.17 -// +build go1.17 - -// TODO: once support for Go 1.16 is dropped, this file can be -// merged/removed with assertion_compare_go1.17_test.go and -// assertion_compare_legacy.go - -package assert - -import "reflect" - -// Wrapper around reflect.Value.CanConvert, for compatibility -// reasons. -func canConvert(value reflect.Value, to reflect.Type) bool { - return value.CanConvert(to) -} diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go b/vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go deleted file mode 100644 index 1701af2a3c..0000000000 --- a/vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build !go1.17 -// +build !go1.17 - -// TODO: once support for Go 1.16 is dropped, this file can be -// merged/removed with assertion_compare_go1.17_test.go and -// assertion_compare_can_convert.go - -package assert - -import "reflect" - -// Older versions of Go does not have the reflect.Value.CanConvert -// method. -func canConvert(value reflect.Value, to reflect.Type) bool { - return false -} diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go b/vendor/github.com/stretchr/testify/assert/assertion_format.go index 84dbd6c790..3ddab109ad 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_format.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go @@ -1,7 +1,4 @@ -/* -* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen -* THIS FILE MUST NOT BE EDITED BY HAND - */ +// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT. package assert @@ -107,7 +104,7 @@ func EqualExportedValuesf(t TestingT, expected interface{}, actual interface{}, return EqualExportedValues(t, expected, actual, append([]interface{}{msg}, args...)...) } -// EqualValuesf asserts that two objects are equal or convertable to the same types +// EqualValuesf asserts that two objects are equal or convertible to the same types // and equal. // // assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted") @@ -616,6 +613,16 @@ func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interf return NotErrorIs(t, err, target, append([]interface{}{msg}, args...)...) } +// NotImplementsf asserts that an object does not implement the specified interface. +// +// assert.NotImplementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted") +func NotImplementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotImplements(t, interfaceObject, object, append([]interface{}{msg}, args...)...) +} + // NotNilf asserts that the specified object is not nil. // // assert.NotNilf(t, err, "error message %s", "formatted") @@ -660,10 +667,12 @@ func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string, return NotSame(t, expected, actual, append([]interface{}{msg}, args...)...) } -// NotSubsetf asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubsetf asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") +// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "error message %s", "formatted") +// assert.NotSubsetf(t, {"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -747,10 +756,11 @@ func Samef(t TestingT, expected interface{}, actual interface{}, msg string, arg return Same(t, expected, actual, append([]interface{}{msg}, args...)...) } -// Subsetf asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subsetf asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") +// assert.Subsetf(t, [1, 2, 3], [1, 2], "error message %s", "formatted") +// assert.Subsetf(t, {"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go b/vendor/github.com/stretchr/testify/assert/assertion_forward.go index b1d94aec53..a84e09bd40 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_forward.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go @@ -1,7 +1,4 @@ -/* -* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen -* THIS FILE MUST NOT BE EDITED BY HAND - */ +// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT. package assert @@ -189,7 +186,7 @@ func (a *Assertions) EqualExportedValuesf(expected interface{}, actual interface return EqualExportedValuesf(a.t, expected, actual, msg, args...) } -// EqualValues asserts that two objects are equal or convertable to the same types +// EqualValues asserts that two objects are equal or convertible to the same types // and equal. // // a.EqualValues(uint32(123), int32(123)) @@ -200,7 +197,7 @@ func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAn return EqualValues(a.t, expected, actual, msgAndArgs...) } -// EqualValuesf asserts that two objects are equal or convertable to the same types +// EqualValuesf asserts that two objects are equal or convertible to the same types // and equal. // // a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted") @@ -1221,6 +1218,26 @@ func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...in return NotErrorIsf(a.t, err, target, msg, args...) } +// NotImplements asserts that an object does not implement the specified interface. +// +// a.NotImplements((*MyInterface)(nil), new(MyObject)) +func (a *Assertions) NotImplements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotImplements(a.t, interfaceObject, object, msgAndArgs...) +} + +// NotImplementsf asserts that an object does not implement the specified interface. +// +// a.NotImplementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted") +func (a *Assertions) NotImplementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotImplementsf(a.t, interfaceObject, object, msg, args...) +} + // NotNil asserts that the specified object is not nil. // // a.NotNil(err) @@ -1309,10 +1326,12 @@ func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg stri return NotSamef(a.t, expected, actual, msg, args...) } -// NotSubset asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubset asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") +// a.NotSubset([1, 3, 4], [1, 2]) +// a.NotSubset({"x": 1, "y": 2}, {"z": 3}) func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1320,10 +1339,12 @@ func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs return NotSubset(a.t, list, subset, msgAndArgs...) } -// NotSubsetf asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubsetf asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") +// a.NotSubsetf([1, 3, 4], [1, 2], "error message %s", "formatted") +// a.NotSubsetf({"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1483,10 +1504,11 @@ func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string, return Samef(a.t, expected, actual, msg, args...) } -// Subset asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subset asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") +// a.Subset([1, 2, 3], [1, 2]) +// a.Subset({"x": 1, "y": 2}, {"x": 1}) func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1494,10 +1516,11 @@ func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ... return Subset(a.t, list, subset, msgAndArgs...) } -// Subsetf asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subsetf asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") +// a.Subsetf([1, 2, 3], [1, 2], "error message %s", "formatted") +// a.Subsetf({"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() diff --git a/vendor/github.com/stretchr/testify/assert/assertions.go b/vendor/github.com/stretchr/testify/assert/assertions.go index a55d1bba92..0b7570f21c 100644 --- a/vendor/github.com/stretchr/testify/assert/assertions.go +++ b/vendor/github.com/stretchr/testify/assert/assertions.go @@ -19,7 +19,7 @@ import ( "github.com/davecgh/go-spew/spew" "github.com/pmezard/go-difflib/difflib" - yaml "gopkg.in/yaml.v3" + "gopkg.in/yaml.v3" ) //go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_format.go.tmpl" @@ -110,7 +110,12 @@ func copyExportedFields(expected interface{}) interface{} { return result.Interface() case reflect.Array, reflect.Slice: - result := reflect.MakeSlice(expectedType, expectedValue.Len(), expectedValue.Len()) + var result reflect.Value + if expectedKind == reflect.Array { + result = reflect.New(reflect.ArrayOf(expectedValue.Len(), expectedType.Elem())).Elem() + } else { + result = reflect.MakeSlice(expectedType, expectedValue.Len(), expectedValue.Len()) + } for i := 0; i < expectedValue.Len(); i++ { index := expectedValue.Index(i) if isNil(index) { @@ -140,6 +145,8 @@ func copyExportedFields(expected interface{}) interface{} { // structures. // // This function does no assertion of any kind. +// +// Deprecated: Use [EqualExportedValues] instead. func ObjectsExportedFieldsAreEqual(expected, actual interface{}) bool { expectedCleaned := copyExportedFields(expected) actualCleaned := copyExportedFields(actual) @@ -153,17 +160,40 @@ func ObjectsAreEqualValues(expected, actual interface{}) bool { return true } - actualType := reflect.TypeOf(actual) - if actualType == nil { + expectedValue := reflect.ValueOf(expected) + actualValue := reflect.ValueOf(actual) + if !expectedValue.IsValid() || !actualValue.IsValid() { return false } - expectedValue := reflect.ValueOf(expected) - if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) { + + expectedType := expectedValue.Type() + actualType := actualValue.Type() + if !expectedType.ConvertibleTo(actualType) { + return false + } + + if !isNumericType(expectedType) || !isNumericType(actualType) { // Attempt comparison after type conversion - return reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual) + return reflect.DeepEqual( + expectedValue.Convert(actualType).Interface(), actual, + ) } - return false + // If BOTH values are numeric, there are chances of false positives due + // to overflow or underflow. So, we need to make sure to always convert + // the smaller type to a larger type before comparing. + if expectedType.Size() >= actualType.Size() { + return actualValue.Convert(expectedType).Interface() == expected + } + + return expectedValue.Convert(actualType).Interface() == actual +} + +// isNumericType returns true if the type is one of: +// int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, +// float32, float64, complex64, complex128 +func isNumericType(t reflect.Type) bool { + return t.Kind() >= reflect.Int && t.Kind() <= reflect.Complex128 } /* CallerInfo is necessary because the assert functions use the testing object @@ -266,7 +296,7 @@ func messageFromMsgAndArgs(msgAndArgs ...interface{}) string { // Aligns the provided message so that all lines after the first line start at the same location as the first line. // Assumes that the first line starts at the correct location (after carriage return, tab, label, spacer and tab). -// The longestLabelLen parameter specifies the length of the longest label in the output (required becaues this is the +// The longestLabelLen parameter specifies the length of the longest label in the output (required because this is the // basis on which the alignment occurs). func indentMessageLines(message string, longestLabelLen int) string { outBuf := new(bytes.Buffer) @@ -382,6 +412,25 @@ func Implements(t TestingT, interfaceObject interface{}, object interface{}, msg return true } +// NotImplements asserts that an object does not implement the specified interface. +// +// assert.NotImplements(t, (*MyInterface)(nil), new(MyObject)) +func NotImplements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + interfaceType := reflect.TypeOf(interfaceObject).Elem() + + if object == nil { + return Fail(t, fmt.Sprintf("Cannot check if nil does not implement %v", interfaceType), msgAndArgs...) + } + if reflect.TypeOf(object).Implements(interfaceType) { + return Fail(t, fmt.Sprintf("%T implements %v", object, interfaceType), msgAndArgs...) + } + + return true +} + // IsType asserts that the specified objects are of the same type. func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { @@ -496,7 +545,7 @@ func samePointers(first, second interface{}) bool { // representations appropriate to be presented to the user. // // If the values are not of like type, the returned strings will be prefixed -// with the type name, and the value will be enclosed in parenthesis similar +// with the type name, and the value will be enclosed in parentheses similar // to a type conversion in the Go grammar. func formatUnequalValues(expected, actual interface{}) (e string, a string) { if reflect.TypeOf(expected) != reflect.TypeOf(actual) { @@ -523,7 +572,7 @@ func truncatingFormat(data interface{}) string { return value } -// EqualValues asserts that two objects are equal or convertable to the same types +// EqualValues asserts that two objects are equal or convertible to the same types // and equal. // // assert.EqualValues(t, uint32(123), int32(123)) @@ -566,12 +615,19 @@ func EqualExportedValues(t TestingT, expected, actual interface{}, msgAndArgs .. return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...) } + if aType.Kind() == reflect.Ptr { + aType = aType.Elem() + } + if bType.Kind() == reflect.Ptr { + bType = bType.Elem() + } + if aType.Kind() != reflect.Struct { - return Fail(t, fmt.Sprintf("Types expected to both be struct \n\t%v != %v", aType.Kind(), reflect.Struct), msgAndArgs...) + return Fail(t, fmt.Sprintf("Types expected to both be struct or pointer to struct \n\t%v != %v", aType.Kind(), reflect.Struct), msgAndArgs...) } if bType.Kind() != reflect.Struct { - return Fail(t, fmt.Sprintf("Types expected to both be struct \n\t%v != %v", bType.Kind(), reflect.Struct), msgAndArgs...) + return Fail(t, fmt.Sprintf("Types expected to both be struct or pointer to struct \n\t%v != %v", bType.Kind(), reflect.Struct), msgAndArgs...) } expected = copyExportedFields(expected) @@ -620,17 +676,6 @@ func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { return Fail(t, "Expected value not to be nil.", msgAndArgs...) } -// containsKind checks if a specified kind in the slice of kinds. -func containsKind(kinds []reflect.Kind, kind reflect.Kind) bool { - for i := 0; i < len(kinds); i++ { - if kind == kinds[i] { - return true - } - } - - return false -} - // isNil checks if a specified object is nil or not, without Failing. func isNil(object interface{}) bool { if object == nil { @@ -638,16 +683,13 @@ func isNil(object interface{}) bool { } value := reflect.ValueOf(object) - kind := value.Kind() - isNilableKind := containsKind( - []reflect.Kind{ - reflect.Chan, reflect.Func, - reflect.Interface, reflect.Map, - reflect.Ptr, reflect.Slice, reflect.UnsafePointer}, - kind) - - if isNilableKind && value.IsNil() { - return true + switch value.Kind() { + case + reflect.Chan, reflect.Func, + reflect.Interface, reflect.Map, + reflect.Ptr, reflect.Slice, reflect.UnsafePointer: + + return value.IsNil() } return false @@ -731,16 +773,14 @@ func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { } -// getLen try to get length of object. -// return (false, 0) if impossible. -func getLen(x interface{}) (ok bool, length int) { +// getLen tries to get the length of an object. +// It returns (0, false) if impossible. +func getLen(x interface{}) (length int, ok bool) { v := reflect.ValueOf(x) defer func() { - if e := recover(); e != nil { - ok = false - } + ok = recover() == nil }() - return true, v.Len() + return v.Len(), true } // Len asserts that the specified object has specific length. @@ -751,13 +791,13 @@ func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) if h, ok := t.(tHelper); ok { h.Helper() } - ok, l := getLen(object) + l, ok := getLen(object) if !ok { - return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", object), msgAndArgs...) + return Fail(t, fmt.Sprintf("\"%v\" could not be applied builtin len()", object), msgAndArgs...) } if l != length { - return Fail(t, fmt.Sprintf("\"%s\" should have %d item(s), but has %d", object, length, l), msgAndArgs...) + return Fail(t, fmt.Sprintf("\"%v\" should have %d item(s), but has %d", object, length, l), msgAndArgs...) } return true } @@ -919,10 +959,11 @@ func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) } -// Subset asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subset asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") +// assert.Subset(t, [1, 2, 3], [1, 2]) +// assert.Subset(t, {"x": 1, "y": 2}, {"x": 1}) func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { if h, ok := t.(tHelper); ok { h.Helper() @@ -975,10 +1016,12 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok return true } -// NotSubset asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubset asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") +// assert.NotSubset(t, [1, 3, 4], [1, 2]) +// assert.NotSubset(t, {"x": 1, "y": 2}, {"z": 3}) func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1439,7 +1482,7 @@ func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAnd h.Helper() } if math.IsNaN(epsilon) { - return Fail(t, "epsilon must not be NaN") + return Fail(t, "epsilon must not be NaN", msgAndArgs...) } actualEpsilon, err := calcRelativeError(expected, actual) if err != nil { @@ -1458,19 +1501,26 @@ func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, m if h, ok := t.(tHelper); ok { h.Helper() } - if expected == nil || actual == nil || - reflect.TypeOf(actual).Kind() != reflect.Slice || - reflect.TypeOf(expected).Kind() != reflect.Slice { + + if expected == nil || actual == nil { return Fail(t, "Parameters must be slice", msgAndArgs...) } - actualSlice := reflect.ValueOf(actual) expectedSlice := reflect.ValueOf(expected) + actualSlice := reflect.ValueOf(actual) - for i := 0; i < actualSlice.Len(); i++ { - result := InEpsilon(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), epsilon) - if !result { - return result + if expectedSlice.Type().Kind() != reflect.Slice { + return Fail(t, "Expected value must be slice", msgAndArgs...) + } + + expectedLen := expectedSlice.Len() + if !IsType(t, expected, actual) || !Len(t, actual, expectedLen) { + return false + } + + for i := 0; i < expectedLen; i++ { + if !InEpsilon(t, expectedSlice.Index(i).Interface(), actualSlice.Index(i).Interface(), epsilon, "at index %d", i) { + return false } } @@ -1870,23 +1920,18 @@ func (c *CollectT) Errorf(format string, args ...interface{}) { } // FailNow panics. -func (c *CollectT) FailNow() { +func (*CollectT) FailNow() { panic("Assertion failed") } -// Reset clears the collected errors. -func (c *CollectT) Reset() { - c.errors = nil +// Deprecated: That was a method for internal usage that should not have been published. Now just panics. +func (*CollectT) Reset() { + panic("Reset() is deprecated") } -// Copy copies the collected errors to the supplied t. -func (c *CollectT) Copy(t TestingT) { - if tt, ok := t.(tHelper); ok { - tt.Helper() - } - for _, err := range c.errors { - t.Errorf("%v", err) - } +// Deprecated: That was a method for internal usage that should not have been published. Now just panics. +func (*CollectT) Copy(TestingT) { + panic("Copy() is deprecated") } // EventuallyWithT asserts that given condition will be met in waitFor time, @@ -1912,8 +1957,8 @@ func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time h.Helper() } - collect := new(CollectT) - ch := make(chan bool, 1) + var lastFinishedTickErrs []error + ch := make(chan []error, 1) timer := time.NewTimer(waitFor) defer timer.Stop() @@ -1924,19 +1969,25 @@ func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time for tick := ticker.C; ; { select { case <-timer.C: - collect.Copy(t) + for _, err := range lastFinishedTickErrs { + t.Errorf("%v", err) + } return Fail(t, "Condition never satisfied", msgAndArgs...) case <-tick: tick = nil - collect.Reset() go func() { + collect := new(CollectT) + defer func() { + ch <- collect.errors + }() condition(collect) - ch <- len(collect.errors) == 0 }() - case v := <-ch: - if v { + case errs := <-ch: + if len(errs) == 0 { return true } + // Keep the errors from the last ended condition, so that they can be copied to t if timeout is reached. + lastFinishedTickErrs = errs tick = ticker.C } } diff --git a/vendor/github.com/stretchr/testify/assert/http_assertions.go b/vendor/github.com/stretchr/testify/assert/http_assertions.go index d8038c28a7..861ed4b7ce 100644 --- a/vendor/github.com/stretchr/testify/assert/http_assertions.go +++ b/vendor/github.com/stretchr/testify/assert/http_assertions.go @@ -12,7 +12,7 @@ import ( // an error if building a new request fails. func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) { w := httptest.NewRecorder() - req, err := http.NewRequest(method, url, nil) + req, err := http.NewRequest(method, url, http.NoBody) if err != nil { return -1, err } @@ -32,12 +32,12 @@ func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, value } code, err := httpCode(handler, method, url, values) if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) } isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent if !isSuccessCode { - Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code)) + Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...) } return isSuccessCode @@ -54,12 +54,12 @@ func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, valu } code, err := httpCode(handler, method, url, values) if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) } isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect if !isRedirectCode { - Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code)) + Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...) } return isRedirectCode @@ -76,12 +76,12 @@ func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values } code, err := httpCode(handler, method, url, values) if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) } isErrorCode := code >= http.StatusBadRequest if !isErrorCode { - Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code)) + Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...) } return isErrorCode @@ -98,12 +98,12 @@ func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url string, va } code, err := httpCode(handler, method, url, values) if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) } successful := code == statuscode if !successful { - Fail(t, fmt.Sprintf("Expected HTTP status code %d for %q but received %d", statuscode, url+"?"+values.Encode(), code)) + Fail(t, fmt.Sprintf("Expected HTTP status code %d for %q but received %d", statuscode, url+"?"+values.Encode(), code), msgAndArgs...) } return successful @@ -113,7 +113,10 @@ func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url string, va // empty string if building a new request fails. func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string { w := httptest.NewRecorder() - req, err := http.NewRequest(method, url+"?"+values.Encode(), nil) + if len(values) > 0 { + url += "?" + values.Encode() + } + req, err := http.NewRequest(method, url, http.NoBody) if err != nil { return "" } @@ -135,7 +138,7 @@ func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, contains := strings.Contains(body, fmt.Sprint(str)) if !contains { - Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) + Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body), msgAndArgs...) } return contains @@ -155,7 +158,7 @@ func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url strin contains := strings.Contains(body, fmt.Sprint(str)) if contains { - Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) + Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body), msgAndArgs...) } return !contains diff --git a/vendor/github.com/stretchr/testify/mock/mock.go b/vendor/github.com/stretchr/testify/mock/mock.go index f4b42e44ff..213bde2ea6 100644 --- a/vendor/github.com/stretchr/testify/mock/mock.go +++ b/vendor/github.com/stretchr/testify/mock/mock.go @@ -18,6 +18,9 @@ import ( "github.com/stretchr/testify/assert" ) +// regex for GCCGO functions +var gccgoRE = regexp.MustCompile(`\.pN\d+_`) + // TestingT is an interface wrapper around *testing.T type TestingT interface { Logf(format string, args ...interface{}) @@ -111,7 +114,7 @@ func (c *Call) Return(returnArguments ...interface{}) *Call { return c } -// Panic specifies if the functon call should fail and the panic message +// Panic specifies if the function call should fail and the panic message // // Mock.On("DoSomething").Panic("test panic") func (c *Call) Panic(msg string) *Call { @@ -123,21 +126,21 @@ func (c *Call) Panic(msg string) *Call { return c } -// Once indicates that that the mock should only return the value once. +// Once indicates that the mock should only return the value once. // // Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Once() func (c *Call) Once() *Call { return c.Times(1) } -// Twice indicates that that the mock should only return the value twice. +// Twice indicates that the mock should only return the value twice. // // Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Twice() func (c *Call) Twice() *Call { return c.Times(2) } -// Times indicates that that the mock should only return the indicated number +// Times indicates that the mock should only return the indicated number // of times. // // Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Times(5) @@ -455,9 +458,8 @@ func (m *Mock) Called(arguments ...interface{}) Arguments { // For Ex: github_com_docker_libkv_store_mock.WatchTree.pN39_github_com_docker_libkv_store_mock.Mock // uses interface information unlike golang github.com/docker/libkv/store/mock.(*Mock).WatchTree // With GCCGO we need to remove interface information starting from pN
. - re := regexp.MustCompile("\\.pN\\d+_") - if re.MatchString(functionPath) { - functionPath = re.Split(functionPath, -1)[0] + if gccgoRE.MatchString(functionPath) { + functionPath = gccgoRE.Split(functionPath, -1)[0] } parts := strings.Split(functionPath, ".") functionName := parts[len(parts)-1] @@ -474,7 +476,7 @@ func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Argumen found, call := m.findExpectedCall(methodName, arguments...) if found < 0 { - // expected call found but it has already been called with repeatable times + // expected call found, but it has already been called with repeatable times if call != nil { m.mutex.Unlock() m.fail("\nassert: mock: The method has been called over %d times.\n\tEither do one more Mock.On(\"%s\").Return(...), or remove extra call.\n\tThis call was unexpected:\n\t\t%s\n\tat: %s", call.totalCalls, methodName, callString(methodName, arguments, true), assert.CallerInfo()) @@ -563,7 +565,7 @@ func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Argumen Assertions */ -type assertExpectationser interface { +type assertExpectationiser interface { AssertExpectations(TestingT) bool } @@ -580,7 +582,7 @@ func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool { t.Logf("Deprecated mock.AssertExpectationsForObjects(myMock.Mock) use mock.AssertExpectationsForObjects(myMock)") obj = m } - m := obj.(assertExpectationser) + m := obj.(assertExpectationiser) if !m.AssertExpectations(t) { t.Logf("Expectations didn't match for Mock: %+v", reflect.TypeOf(m)) return false @@ -592,6 +594,9 @@ func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool { // AssertExpectations asserts that everything specified with On and Return was // in fact called as expected. Calls may have occurred in any order. func (m *Mock) AssertExpectations(t TestingT) bool { + if s, ok := t.(interface{ Skipped() bool }); ok && s.Skipped() { + return true + } if h, ok := t.(tHelper); ok { h.Helper() } @@ -606,8 +611,8 @@ func (m *Mock) AssertExpectations(t TestingT) bool { satisfied, reason := m.checkExpectation(expectedCall) if !satisfied { failedExpectations++ + t.Logf(reason) } - t.Logf(reason) } if failedExpectations != 0 { @@ -758,25 +763,33 @@ const ( Anything = "mock.Anything" ) -// AnythingOfTypeArgument is a string that contains the type of an argument +// AnythingOfTypeArgument contains the type of an argument +// for use when type checking. Used in Diff and Assert. +// +// Deprecated: this is an implementation detail that must not be used. Use [AnythingOfType] instead. +type AnythingOfTypeArgument = anythingOfTypeArgument + +// anythingOfTypeArgument is a string that contains the type of an argument // for use when type checking. Used in Diff and Assert. -type AnythingOfTypeArgument string +type anythingOfTypeArgument string -// AnythingOfType returns an AnythingOfTypeArgument object containing the -// name of the type to check for. Used in Diff and Assert. +// AnythingOfType returns a special value containing the +// name of the type to check for. The type name will be matched against the type name returned by [reflect.Type.String]. +// +// Used in Diff and Assert. // // For example: // // Assert(t, AnythingOfType("string"), AnythingOfType("int")) func AnythingOfType(t string) AnythingOfTypeArgument { - return AnythingOfTypeArgument(t) + return anythingOfTypeArgument(t) } // IsTypeArgument is a struct that contains the type of an argument // for use when type checking. This is an alternative to AnythingOfType. // Used in Diff and Assert. type IsTypeArgument struct { - t interface{} + t reflect.Type } // IsType returns an IsTypeArgument object containing the type to check for. @@ -786,7 +799,7 @@ type IsTypeArgument struct { // For example: // Assert(t, IsType(""), IsType(0)) func IsType(t interface{}) *IsTypeArgument { - return &IsTypeArgument{t: t} + return &IsTypeArgument{t: reflect.TypeOf(t)} } // FunctionalOptionsArgument is a struct that contains the type and value of an functional option argument @@ -950,53 +963,55 @@ func (args Arguments) Diff(objects []interface{}) (string, int) { differences++ output = fmt.Sprintf("%s\t%d: FAIL: %s not matched by %s\n", output, i, actualFmt, matcher) } - } else if reflect.TypeOf(expected) == reflect.TypeOf((*AnythingOfTypeArgument)(nil)).Elem() { - // type checking - if reflect.TypeOf(actual).Name() != string(expected.(AnythingOfTypeArgument)) && reflect.TypeOf(actual).String() != string(expected.(AnythingOfTypeArgument)) { - // not match - differences++ - output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, expected, reflect.TypeOf(actual).Name(), actualFmt) - } - } else if reflect.TypeOf(expected) == reflect.TypeOf((*IsTypeArgument)(nil)) { - t := expected.(*IsTypeArgument).t - if reflect.TypeOf(t) != reflect.TypeOf(actual) { - differences++ - output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, reflect.TypeOf(t).Name(), reflect.TypeOf(actual).Name(), actualFmt) - } - } else if reflect.TypeOf(expected) == reflect.TypeOf((*FunctionalOptionsArgument)(nil)) { - t := expected.(*FunctionalOptionsArgument).value + } else { + switch expected := expected.(type) { + case anythingOfTypeArgument: + // type checking + if reflect.TypeOf(actual).Name() != string(expected) && reflect.TypeOf(actual).String() != string(expected) { + // not match + differences++ + output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, expected, reflect.TypeOf(actual).Name(), actualFmt) + } + case *IsTypeArgument: + actualT := reflect.TypeOf(actual) + if actualT != expected.t { + differences++ + output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, expected.t.Name(), actualT.Name(), actualFmt) + } + case *FunctionalOptionsArgument: + t := expected.value - var name string - tValue := reflect.ValueOf(t) - if tValue.Len() > 0 { - name = "[]" + reflect.TypeOf(tValue.Index(0).Interface()).String() - } + var name string + tValue := reflect.ValueOf(t) + if tValue.Len() > 0 { + name = "[]" + reflect.TypeOf(tValue.Index(0).Interface()).String() + } - tName := reflect.TypeOf(t).Name() - if name != reflect.TypeOf(actual).String() && tValue.Len() != 0 { - differences++ - output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, tName, reflect.TypeOf(actual).Name(), actualFmt) - } else { - if ef, af := assertOpts(t, actual); ef == "" && af == "" { + tName := reflect.TypeOf(t).Name() + if name != reflect.TypeOf(actual).String() && tValue.Len() != 0 { + differences++ + output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, tName, reflect.TypeOf(actual).Name(), actualFmt) + } else { + if ef, af := assertOpts(t, actual); ef == "" && af == "" { + // match + output = fmt.Sprintf("%s\t%d: PASS: %s == %s\n", output, i, tName, tName) + } else { + // not match + differences++ + output = fmt.Sprintf("%s\t%d: FAIL: %s != %s\n", output, i, af, ef) + } + } + + default: + if assert.ObjectsAreEqual(expected, Anything) || assert.ObjectsAreEqual(actual, Anything) || assert.ObjectsAreEqual(actual, expected) { // match - output = fmt.Sprintf("%s\t%d: PASS: %s == %s\n", output, i, tName, tName) + output = fmt.Sprintf("%s\t%d: PASS: %s == %s\n", output, i, actualFmt, expectedFmt) } else { // not match differences++ - output = fmt.Sprintf("%s\t%d: FAIL: %s != %s\n", output, i, af, ef) + output = fmt.Sprintf("%s\t%d: FAIL: %s != %s\n", output, i, actualFmt, expectedFmt) } } - } else { - // normal checking - - if assert.ObjectsAreEqual(expected, Anything) || assert.ObjectsAreEqual(actual, Anything) || assert.ObjectsAreEqual(actual, expected) { - // match - output = fmt.Sprintf("%s\t%d: PASS: %s == %s\n", output, i, actualFmt, expectedFmt) - } else { - // not match - differences++ - output = fmt.Sprintf("%s\t%d: FAIL: %s != %s\n", output, i, actualFmt, expectedFmt) - } } } diff --git a/vendor/github.com/stretchr/testify/require/require.go b/vendor/github.com/stretchr/testify/require/require.go index 63f8521476..506a82f807 100644 --- a/vendor/github.com/stretchr/testify/require/require.go +++ b/vendor/github.com/stretchr/testify/require/require.go @@ -1,7 +1,4 @@ -/* -* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen -* THIS FILE MUST NOT BE EDITED BY HAND - */ +// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT. package require @@ -235,7 +232,7 @@ func EqualExportedValuesf(t TestingT, expected interface{}, actual interface{}, t.FailNow() } -// EqualValues asserts that two objects are equal or convertable to the same types +// EqualValues asserts that two objects are equal or convertible to the same types // and equal. // // assert.EqualValues(t, uint32(123), int32(123)) @@ -249,7 +246,7 @@ func EqualValues(t TestingT, expected interface{}, actual interface{}, msgAndArg t.FailNow() } -// EqualValuesf asserts that two objects are equal or convertable to the same types +// EqualValuesf asserts that two objects are equal or convertible to the same types // and equal. // // assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted") @@ -1546,6 +1543,32 @@ func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interf t.FailNow() } +// NotImplements asserts that an object does not implement the specified interface. +// +// assert.NotImplements(t, (*MyInterface)(nil), new(MyObject)) +func NotImplements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NotImplements(t, interfaceObject, object, msgAndArgs...) { + return + } + t.FailNow() +} + +// NotImplementsf asserts that an object does not implement the specified interface. +// +// assert.NotImplementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted") +func NotImplementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NotImplementsf(t, interfaceObject, object, msg, args...) { + return + } + t.FailNow() +} + // NotNil asserts that the specified object is not nil. // // assert.NotNil(t, err) @@ -1658,10 +1681,12 @@ func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string, t.FailNow() } -// NotSubset asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubset asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") +// assert.NotSubset(t, [1, 3, 4], [1, 2]) +// assert.NotSubset(t, {"x": 1, "y": 2}, {"z": 3}) func NotSubset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1672,10 +1697,12 @@ func NotSubset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...i t.FailNow() } -// NotSubsetf asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubsetf asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") +// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "error message %s", "formatted") +// assert.NotSubsetf(t, {"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1880,10 +1907,11 @@ func Samef(t TestingT, expected interface{}, actual interface{}, msg string, arg t.FailNow() } -// Subset asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subset asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") +// assert.Subset(t, [1, 2, 3], [1, 2]) +// assert.Subset(t, {"x": 1, "y": 2}, {"x": 1}) func Subset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1894,10 +1922,11 @@ func Subset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...inte t.FailNow() } -// Subsetf asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subsetf asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") +// assert.Subsetf(t, [1, 2, 3], [1, 2], "error message %s", "formatted") +// assert.Subsetf(t, {"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() diff --git a/vendor/github.com/stretchr/testify/require/require_forward.go b/vendor/github.com/stretchr/testify/require/require_forward.go index 3b5b09330a..eee8310a5f 100644 --- a/vendor/github.com/stretchr/testify/require/require_forward.go +++ b/vendor/github.com/stretchr/testify/require/require_forward.go @@ -1,7 +1,4 @@ -/* -* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen -* THIS FILE MUST NOT BE EDITED BY HAND - */ +// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT. package require @@ -190,7 +187,7 @@ func (a *Assertions) EqualExportedValuesf(expected interface{}, actual interface EqualExportedValuesf(a.t, expected, actual, msg, args...) } -// EqualValues asserts that two objects are equal or convertable to the same types +// EqualValues asserts that two objects are equal or convertible to the same types // and equal. // // a.EqualValues(uint32(123), int32(123)) @@ -201,7 +198,7 @@ func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAn EqualValues(a.t, expected, actual, msgAndArgs...) } -// EqualValuesf asserts that two objects are equal or convertable to the same types +// EqualValuesf asserts that two objects are equal or convertible to the same types // and equal. // // a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted") @@ -1222,6 +1219,26 @@ func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...in NotErrorIsf(a.t, err, target, msg, args...) } +// NotImplements asserts that an object does not implement the specified interface. +// +// a.NotImplements((*MyInterface)(nil), new(MyObject)) +func (a *Assertions) NotImplements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotImplements(a.t, interfaceObject, object, msgAndArgs...) +} + +// NotImplementsf asserts that an object does not implement the specified interface. +// +// a.NotImplementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted") +func (a *Assertions) NotImplementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotImplementsf(a.t, interfaceObject, object, msg, args...) +} + // NotNil asserts that the specified object is not nil. // // a.NotNil(err) @@ -1310,10 +1327,12 @@ func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg stri NotSamef(a.t, expected, actual, msg, args...) } -// NotSubset asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubset asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") +// a.NotSubset([1, 3, 4], [1, 2]) +// a.NotSubset({"x": 1, "y": 2}, {"z": 3}) func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1321,10 +1340,12 @@ func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs NotSubset(a.t, list, subset, msgAndArgs...) } -// NotSubsetf asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubsetf asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") +// a.NotSubsetf([1, 3, 4], [1, 2], "error message %s", "formatted") +// a.NotSubsetf({"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1484,10 +1505,11 @@ func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string, Samef(a.t, expected, actual, msg, args...) } -// Subset asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subset asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") +// a.Subset([1, 2, 3], [1, 2]) +// a.Subset({"x": 1, "y": 2}, {"x": 1}) func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1495,10 +1517,11 @@ func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ... Subset(a.t, list, subset, msgAndArgs...) } -// Subsetf asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subsetf asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") +// a.Subsetf([1, 2, 3], [1, 2], "error message %s", "formatted") +// a.Subsetf({"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() diff --git a/vendor/github.com/thanos-io/promql-engine/api/remote.go b/vendor/github.com/thanos-io/promql-engine/api/remote.go index 2149ed2624..6dcb882d42 100644 --- a/vendor/github.com/thanos-io/promql-engine/api/remote.go +++ b/vendor/github.com/thanos-io/promql-engine/api/remote.go @@ -5,13 +5,17 @@ package api import ( "context" + "fmt" "time" "github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/promql" - "github.com/prometheus/prometheus/promql/parser" ) +type RemoteQuery interface { + fmt.Stringer +} + type RemoteEndpoints interface { Engines() []RemoteEngine } @@ -20,7 +24,7 @@ type RemoteEngine interface { MaxT() int64 MinT() int64 LabelSets() []labels.Labels - NewRangeQuery(ctx context.Context, opts promql.QueryOpts, plan parser.Expr, start, end time.Time, interval time.Duration) (promql.Query, error) + NewRangeQuery(ctx context.Context, opts promql.QueryOpts, plan RemoteQuery, start, end time.Time, interval time.Duration) (promql.Query, error) } type staticEndpoints struct { diff --git a/vendor/github.com/thanos-io/promql-engine/engine/distributed.go b/vendor/github.com/thanos-io/promql-engine/engine/distributed.go index 658202dab9..c61357d8da 100644 --- a/vendor/github.com/thanos-io/promql-engine/engine/distributed.go +++ b/vendor/github.com/thanos-io/promql-engine/engine/distributed.go @@ -7,20 +7,17 @@ import ( "context" "time" - "github.com/prometheus/prometheus/promql/parser" - "github.com/thanos-io/promql-engine/api" "github.com/thanos-io/promql-engine/logicalplan" "github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/promql" "github.com/prometheus/prometheus/storage" - v1 "github.com/prometheus/prometheus/web/api/v1" ) type remoteEngine struct { q storage.Queryable - engine *compatibilityEngine + engine *Engine labelSets []labels.Labels maxt int64 mint int64 @@ -48,31 +45,31 @@ func (l remoteEngine) LabelSets() []labels.Labels { return l.labelSets } -func (l remoteEngine) NewRangeQuery(ctx context.Context, opts promql.QueryOpts, plan parser.Expr, start, end time.Time, interval time.Duration) (promql.Query, error) { +func (l remoteEngine) NewRangeQuery(ctx context.Context, opts promql.QueryOpts, plan api.RemoteQuery, start, end time.Time, interval time.Duration) (promql.Query, error) { return l.engine.NewRangeQuery(ctx, l.q, opts, plan.String(), start, end, interval) } -type distributedEngine struct { +type DistributedEngine struct { endpoints api.RemoteEndpoints - remoteEngine *compatibilityEngine + remoteEngine *Engine } -func NewDistributedEngine(opts Opts, endpoints api.RemoteEndpoints) v1.QueryEngine { +func NewDistributedEngine(opts Opts, endpoints api.RemoteEndpoints) *DistributedEngine { opts.LogicalOptimizers = []logicalplan.Optimizer{ logicalplan.PassthroughOptimizer{Endpoints: endpoints}, logicalplan.DistributeAvgOptimizer{}, logicalplan.DistributedExecutionOptimizer{Endpoints: endpoints}, } - return &distributedEngine{ + return &DistributedEngine{ endpoints: endpoints, remoteEngine: New(opts), } } -func (l distributedEngine) SetQueryLogger(log promql.QueryLogger) {} +func (l DistributedEngine) SetQueryLogger(log promql.QueryLogger) {} -func (l distributedEngine) NewInstantQuery(ctx context.Context, q storage.Queryable, opts promql.QueryOpts, qs string, ts time.Time) (promql.Query, error) { +func (l DistributedEngine) NewInstantQuery(ctx context.Context, q storage.Queryable, opts promql.QueryOpts, qs string, ts time.Time) (promql.Query, error) { // Truncate milliseconds to avoid mismatch in timestamps between remote and local engines. // Some clients might only support second precision when executing queries. ts = ts.Truncate(time.Second) @@ -80,7 +77,7 @@ func (l distributedEngine) NewInstantQuery(ctx context.Context, q storage.Querya return l.remoteEngine.NewInstantQuery(ctx, q, opts, qs, ts) } -func (l distributedEngine) NewRangeQuery(ctx context.Context, q storage.Queryable, opts promql.QueryOpts, qs string, start, end time.Time, interval time.Duration) (promql.Query, error) { +func (l DistributedEngine) NewRangeQuery(ctx context.Context, q storage.Queryable, opts promql.QueryOpts, qs string, start, end time.Time, interval time.Duration) (promql.Query, error) { // Truncate milliseconds to avoid mismatch in timestamps between remote and local engines. // Some clients might only support second precision when executing queries. start = start.Truncate(time.Second) @@ -89,3 +86,21 @@ func (l distributedEngine) NewRangeQuery(ctx context.Context, q storage.Queryabl return l.remoteEngine.NewRangeQuery(ctx, q, opts, qs, start, end, interval) } + +func (l DistributedEngine) NewRangeQueryFromPlan(ctx context.Context, q storage.Queryable, opts promql.QueryOpts, plan logicalplan.Node, start, end time.Time, interval time.Duration) (promql.Query, error) { + // Truncate milliseconds to avoid mismatch in timestamps between remote and local engines. + // Some clients might only support second precision when executing queries. + start = start.Truncate(time.Second) + end = end.Truncate(time.Second) + interval = interval.Truncate(time.Second) + + return l.remoteEngine.NewRangeQueryFromPlan(ctx, q, opts, plan, start, end, interval) +} + +func (l DistributedEngine) NewInstantQueryFromPlan(ctx context.Context, q storage.Queryable, opts promql.QueryOpts, plan logicalplan.Node, ts time.Time) (promql.Query, error) { + // Truncate milliseconds to avoid mismatch in timestamps between remote and local engines. + // Some clients might only support second precision when executing queries. + ts = ts.Truncate(time.Second) + + return l.remoteEngine.NewInstantQueryFromPlan(ctx, q, opts, plan, ts) +} diff --git a/vendor/github.com/thanos-io/promql-engine/engine/engine.go b/vendor/github.com/thanos-io/promql-engine/engine/engine.go index 2797160695..823ee08749 100644 --- a/vendor/github.com/thanos-io/promql-engine/engine/engine.go +++ b/vendor/github.com/thanos-io/promql-engine/engine/engine.go @@ -20,10 +20,6 @@ import ( "github.com/prometheus/prometheus/storage" "github.com/prometheus/prometheus/util/annotations" "github.com/prometheus/prometheus/util/stats" - v1 "github.com/prometheus/prometheus/web/api/v1" - - engstorage "github.com/thanos-io/promql-engine/storage" - promstorage "github.com/thanos-io/promql-engine/storage/prometheus" "github.com/thanos-io/promql-engine/execution" "github.com/thanos-io/promql-engine/execution/function" @@ -33,6 +29,8 @@ import ( "github.com/thanos-io/promql-engine/extlabels" "github.com/thanos-io/promql-engine/logicalplan" "github.com/thanos-io/promql-engine/query" + engstorage "github.com/thanos-io/promql-engine/storage" + promstorage "github.com/thanos-io/promql-engine/storage/prometheus" ) type QueryType int @@ -69,7 +67,7 @@ type Opts struct { EnableXFunctions bool // FallbackEngine - Engine v1.QueryEngine + Engine promql.QueryEngine // EnableAnalysis enables query analysis. EnableAnalysis bool @@ -98,7 +96,7 @@ func (o Opts) getLogicalOptimizers() []logicalplan.Optimizer { // New creates a new query engine with the given options. The query engine will // use the storage passed in NewInstantQuery and NewRangeQuery for retrieving // data when executing queries. -func New(opts Opts) *compatibilityEngine { +func New(opts Opts) *Engine { return NewWithScanners(opts, nil) } @@ -106,7 +104,7 @@ func New(opts Opts) *compatibilityEngine { // When executing queries, the engine will create scanner operators using the storage.Scanners and will ignore the // Prometheus storage passed in NewInstantQuery and NewRangeQuery. // This method is useful when the data being queried does not easily fit into the Prometheus storage model. -func NewWithScanners(opts Opts, scanners engstorage.Scanners) *compatibilityEngine { +func NewWithScanners(opts Opts, scanners engstorage.Scanners) *Engine { if opts.Logger == nil { opts.Logger = log.NewNopLogger() } @@ -154,14 +152,14 @@ func NewWithScanners(opts Opts, scanners engstorage.Scanners) *compatibilityEngi ), } - var engine v1.QueryEngine + var engine promql.QueryEngine if opts.Engine == nil { engine = promql.NewEngine(opts.EngineOpts) } else { engine = opts.Engine } - return &compatibilityEngine{ + return &Engine{ prom: engine, functions: functions, scanners: scanners, @@ -189,8 +187,8 @@ var ( ErrStepsBatchTooLarge = errors.New("'StepsBatch' must be less than 64") ) -type compatibilityEngine struct { - prom v1.QueryEngine +type Engine struct { + prom promql.QueryEngine functions map[string]*parser.Function scanners engstorage.Scanners @@ -208,11 +206,7 @@ type compatibilityEngine struct { noStepSubqueryIntervalFn func(time.Duration) time.Duration } -func (e *compatibilityEngine) SetQueryLogger(l promql.QueryLogger) { - e.prom.SetQueryLogger(l) -} - -func (e *compatibilityEngine) NewInstantQuery(ctx context.Context, q storage.Queryable, opts promql.QueryOpts, qs string, ts time.Time) (promql.Query, error) { +func (e *Engine) NewInstantQuery(ctx context.Context, q storage.Queryable, opts promql.QueryOpts, qs string, ts time.Time) (promql.Query, error) { expr, err := parser.NewParser(qs, parser.WithFunctions(e.functions)).ParseExpr() if err != nil { return nil, err @@ -248,8 +242,8 @@ func (e *compatibilityEngine) NewInstantQuery(ctx context.Context, q storage.Que planOpts := logicalplan.PlanOptions{ DisableDuplicateLabelCheck: e.disableDuplicateLabelChecks, } - lplan, warns := logicalplan.New(expr, qOpts, planOpts).Optimize(e.logicalOptimizers) - exec, err := execution.New(lplan.Expr(), e.storageScanners(q), qOpts) + lplan, warns := logicalplan.NewFromAST(expr, qOpts, planOpts).Optimize(e.logicalOptimizers) + exec, err := execution.New(lplan.Root(), e.storageScanners(q), qOpts) if e.triggerFallback(err) { e.metrics.queries.WithLabelValues("true").Inc() return e.prom.NewInstantQuery(ctx, q, opts, qs, ts) @@ -262,7 +256,7 @@ func (e *compatibilityEngine) NewInstantQuery(ctx context.Context, q storage.Que return &compatibilityQuery{ Query: &Query{exec: exec, opts: opts}, engine: e, - expr: expr, + plan: lplan, ts: ts, warns: warns, t: InstantQuery, @@ -270,7 +264,7 @@ func (e *compatibilityEngine) NewInstantQuery(ctx context.Context, q storage.Que }, nil } -func (e *compatibilityEngine) NewRangeQuery(ctx context.Context, q storage.Queryable, opts promql.QueryOpts, qs string, start, end time.Time, step time.Duration) (promql.Query, error) { +func (e *Engine) NewRangeQuery(ctx context.Context, q storage.Queryable, opts promql.QueryOpts, qs string, start, end time.Time, step time.Duration) (promql.Query, error) { expr, err := parser.NewParser(qs, parser.WithFunctions(e.functions)).ParseExpr() if err != nil { return nil, err @@ -280,37 +274,58 @@ func (e *compatibilityEngine) NewRangeQuery(ctx context.Context, q storage.Query if expr.Type() != parser.ValueTypeVector && expr.Type() != parser.ValueTypeScalar { return nil, errors.Newf("invalid expression type %q for range query, must be Scalar or instant Vector", parser.DocumentedType(expr.Type())) } - if opts == nil { opts = promql.NewPrometheusQueryOpts(false, e.lookbackDelta) } if opts.LookbackDelta() <= 0 { opts = promql.NewPrometheusQueryOpts(opts.EnablePerStepStats(), e.lookbackDelta) } + qOpts := e.makeQueryOpts(ctx, start, end, step, opts) + if qOpts.StepsBatch > 64 { + return nil, ErrStepsBatchTooLarge + } + planOpts := logicalplan.PlanOptions{ + DisableDuplicateLabelCheck: e.disableDuplicateLabelChecks, + } + lplan, warns := logicalplan.NewFromAST(expr, qOpts, planOpts).Optimize(e.logicalOptimizers) + exec, err := execution.New(lplan.Root(), e.storageScanners(q), qOpts) + if e.triggerFallback(err) { + e.metrics.queries.WithLabelValues("true").Inc() + return e.prom.NewRangeQuery(ctx, q, opts, qs, start, end, step) + } + e.metrics.queries.WithLabelValues("false").Inc() + if err != nil { + return nil, err + } - qOpts := &query.Options{ - Context: ctx, - Start: start, - End: end, - Step: step, - StepsBatch: stepsBatch, - LookbackDelta: opts.LookbackDelta(), - ExtLookbackDelta: e.extLookbackDelta, - EnableAnalysis: e.enableAnalysis, - NoStepSubqueryIntervalFn: e.noStepSubqueryIntervalFn, + return &compatibilityQuery{ + Query: &Query{exec: exec, opts: opts}, + engine: e, + plan: lplan, + warns: warns, + t: RangeQuery, + }, nil +} + +func (e *Engine) NewRangeQueryFromPlan(ctx context.Context, q storage.Queryable, opts promql.QueryOpts, root logicalplan.Node, start, end time.Time, step time.Duration) (promql.Query, error) { + if opts == nil { + opts = promql.NewPrometheusQueryOpts(false, e.lookbackDelta) + } + if opts.LookbackDelta() <= 0 { + opts = promql.NewPrometheusQueryOpts(opts.EnablePerStepStats(), e.lookbackDelta) } + qOpts := e.makeQueryOpts(ctx, start, end, step, opts) if qOpts.StepsBatch > 64 { return nil, ErrStepsBatchTooLarge } - planOpts := logicalplan.PlanOptions{ DisableDuplicateLabelCheck: e.disableDuplicateLabelChecks, } - lplan, warns := logicalplan.New(expr, qOpts, planOpts).Optimize(e.logicalOptimizers) - exec, err := execution.New(lplan.Expr(), e.storageScanners(q), qOpts) + lplan, warns := logicalplan.New(root, qOpts, planOpts).Optimize(e.logicalOptimizers) + exec, err := execution.New(lplan.Root(), e.storageScanners(q), qOpts) if e.triggerFallback(err) { e.metrics.queries.WithLabelValues("true").Inc() - return e.prom.NewRangeQuery(ctx, q, opts, qs, start, end, step) + return e.prom.NewRangeQuery(ctx, q, opts, lplan.Root().String(), start, end, step) } e.metrics.queries.WithLabelValues("false").Inc() if err != nil { @@ -320,13 +335,32 @@ func (e *compatibilityEngine) NewRangeQuery(ctx context.Context, q storage.Query return &compatibilityQuery{ Query: &Query{exec: exec, opts: opts}, engine: e, - expr: expr, + plan: lplan, warns: warns, t: RangeQuery, }, nil } -func (e *compatibilityEngine) storageScanners(queryable storage.Queryable) engstorage.Scanners { +func (e *Engine) NewInstantQueryFromPlan(ctx context.Context, q storage.Queryable, opts promql.QueryOpts, plan logicalplan.Node, ts time.Time) (promql.Query, error) { + return e.NewRangeQueryFromPlan(ctx, q, opts, plan, ts, ts, 0) +} + +func (e *Engine) makeQueryOpts(ctx context.Context, start time.Time, end time.Time, step time.Duration, opts promql.QueryOpts) *query.Options { + qOpts := &query.Options{ + Context: ctx, + Start: start, + End: end, + Step: step, + StepsBatch: stepsBatch, + LookbackDelta: opts.LookbackDelta(), + ExtLookbackDelta: e.extLookbackDelta, + EnableAnalysis: e.enableAnalysis, + NoStepSubqueryIntervalFn: e.noStepSubqueryIntervalFn, + } + return qOpts +} + +func (e *Engine) storageScanners(queryable storage.Queryable) engstorage.Scanners { if e.scanners == nil { return promstorage.NewPrometheusScanners(queryable) } @@ -353,8 +387,8 @@ func (q *Query) Analyze() *AnalyzeOutputNode { type compatibilityQuery struct { *Query - engine *compatibilityEngine - expr parser.Expr + engine *Engine + plan logicalplan.Plan ts time.Time // Empty for range queries. warns annotations.Annotations @@ -370,7 +404,7 @@ func (q *compatibilityQuery) Exec(ctx context.Context) (ret *promql.Result) { }() // Handle case with strings early on as this does not need us to process samples. - switch e := q.expr.(type) { + switch e := q.plan.Root().(type) { case *logicalplan.StringLiteral: return &promql.Result{Value: promql.String{V: e.Val, T: q.ts.UnixMilli()}} } @@ -378,7 +412,7 @@ func (q *compatibilityQuery) Exec(ctx context.Context) (ret *promql.Result) { Value: promql.Vector{}, Warnings: q.warns, } - defer recoverEngine(q.engine.logger, q.expr, &ret.Err) + defer recoverEngine(q.engine.logger, q.plan, &ret.Err) q.engine.metrics.currentQueries.Inc() defer q.engine.metrics.currentQueries.Dec() @@ -459,7 +493,7 @@ loop: } var result parser.Value - switch q.expr.Type() { + switch q.plan.Root().ReturnType() { case parser.ValueTypeMatrix: result = promql.Matrix(series) case parser.ValueTypeVector: @@ -494,7 +528,7 @@ loop: } result = promql.Scalar{V: v, T: q.ts.UnixMilli()} default: - panic(errors.Newf("new.Engine.exec: unexpected expression type %q", q.expr.Type())) + panic(errors.Newf("new.Engine.exec: unexpected expression type %q", q.plan.Root().Type())) } ret.Value = result @@ -524,7 +558,7 @@ func (q *compatibilityQuery) Stats() *stats.Statistics { func (q *compatibilityQuery) Close() { q.Cancel() } -func (q *compatibilityQuery) String() string { return q.expr.String() } +func (q *compatibilityQuery) String() string { return q.plan.Root().String() } func (q *compatibilityQuery) Cancel() { if q.cancel != nil { @@ -533,7 +567,7 @@ func (q *compatibilityQuery) Cancel() { } } -func (e *compatibilityEngine) triggerFallback(err error) bool { +func (e *Engine) triggerFallback(err error) bool { if e.disableFallback { return false } @@ -541,7 +575,7 @@ func (e *compatibilityEngine) triggerFallback(err error) bool { return errors.Is(err, parse.ErrNotSupportedExpr) || errors.Is(err, parse.ErrNotImplemented) } -func recoverEngine(logger log.Logger, expr parser.Expr, errp *error) { +func recoverEngine(logger log.Logger, plan logicalplan.Plan, errp *error) { e := recover() if e == nil { return @@ -553,7 +587,7 @@ func recoverEngine(logger log.Logger, expr parser.Expr, errp *error) { buf := make([]byte, 64<<10) buf = buf[:runtime.Stack(buf, false)] - level.Error(logger).Log("msg", "runtime panic in engine", "expr", expr.String(), "err", e, "stacktrace", string(buf)) + level.Error(logger).Log("msg", "runtime panic in engine", "expr", plan.Root().String(), "err", e, "stacktrace", string(buf)) *errp = errors.Wrap(err, "unexpected error") } } diff --git a/vendor/github.com/thanos-io/promql-engine/engine/explain.go b/vendor/github.com/thanos-io/promql-engine/engine/explain.go index 61630b9b2b..48f61208ce 100644 --- a/vendor/github.com/thanos-io/promql-engine/engine/explain.go +++ b/vendor/github.com/thanos-io/promql-engine/engine/explain.go @@ -29,7 +29,7 @@ type ExplainOutputNode struct { var _ ExplainableQuery = &compatibilityQuery{} func analyzeQuery(obsv model.ObservableVectorOperator) *AnalyzeOutputNode { - _, children := obsv.Explain() + children := obsv.Explain() var childTelemetry []AnalyzeOutputNode for _, child := range children { if obsChild, ok := child.(model.ObservableVectorOperator); ok { @@ -44,7 +44,7 @@ func analyzeQuery(obsv model.ObservableVectorOperator) *AnalyzeOutputNode { } func explainVector(v model.VectorOperator) *ExplainOutputNode { - name, vectors := v.Explain() + vectors := v.Explain() var children []ExplainOutputNode for _, vector := range vectors { @@ -52,7 +52,7 @@ func explainVector(v model.VectorOperator) *ExplainOutputNode { } return &ExplainOutputNode{ - OperatorName: name, + OperatorName: v.String(), Children: children, } } diff --git a/vendor/github.com/thanos-io/promql-engine/execution/aggregate/hashaggregate.go b/vendor/github.com/thanos-io/promql-engine/execution/aggregate/hashaggregate.go index 89627e08a5..a34ebc4f61 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/aggregate/hashaggregate.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/aggregate/hashaggregate.go @@ -59,8 +59,7 @@ func NewHashAggregate( // Grouping labels need to be sorted in order for metric hashing to work. // https://github.com/prometheus/prometheus/blob/8ed39fdab1ead382a354e45ded999eb3610f8d5f/model/labels/labels.go#L162-L181 slices.Sort(labels) - return &aggregate{ - OperatorTelemetry: model.NewTelemetry("[aggregate]", opts.EnableAnalysis), + a := &aggregate{ next: next, paramOp: paramOp, @@ -70,19 +69,27 @@ func NewHashAggregate( aggregation: aggregation, labels: labels, stepsBatch: opts.StepsBatch, - }, nil + } + + a.OperatorTelemetry = model.NewTelemetry(a, opts.EnableAnalysis) + + return a, nil } -func (a *aggregate) Explain() (me string, next []model.VectorOperator) { +func (a *aggregate) String() string { + if a.by { + return fmt.Sprintf("[aggregate] %v by (%v)", a.aggregation.String(), a.labels) + } + return fmt.Sprintf("[aggregate] %v without (%v)", a.aggregation.String(), a.labels) +} + +func (a *aggregate) Explain() (next []model.VectorOperator) { var ops []model.VectorOperator + ops = append(ops, a.next) if a.paramOp != nil { ops = append(ops, a.paramOp) } - ops = append(ops, a.next) - if a.by { - return fmt.Sprintf("[aggregate] %v by (%v)", a.aggregation.String(), a.labels), ops - } - return fmt.Sprintf("[aggregate] %v without (%v)", a.aggregation.String(), a.labels), ops + return ops } func (a *aggregate) Series(ctx context.Context) ([]labels.Labels, error) { diff --git a/vendor/github.com/thanos-io/promql-engine/execution/aggregate/khashaggregate.go b/vendor/github.com/thanos-io/promql-engine/execution/aggregate/khashaggregate.go index 6b63edd50d..1e7c9dbffc 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/aggregate/khashaggregate.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/aggregate/khashaggregate.go @@ -67,17 +67,20 @@ func NewKHashAggregate( // https://github.com/prometheus/prometheus/blob/8ed39fdab1ead382a354e45ded999eb3610f8d5f/model/labels/labels.go#L162-L181 slices.Sort(labels) - return &kAggregate{ - OperatorTelemetry: model.NewTelemetry("[kaggregate]", opts.EnableAnalysis), - next: next, - vectorPool: points, - by: by, - aggregation: aggregation, - labels: labels, - paramOp: paramOp, - compare: compare, - params: make([]float64, opts.StepsBatch), - }, nil + op := &kAggregate{ + next: next, + vectorPool: points, + by: by, + aggregation: aggregation, + labels: labels, + paramOp: paramOp, + compare: compare, + params: make([]float64, opts.StepsBatch), + } + + op.OperatorTelemetry = model.NewTelemetry(op, opts.EnableAnalysis) + + return op, nil } func (a *kAggregate) Next(ctx context.Context) ([]model.StepVector, error) { @@ -155,11 +158,15 @@ func (a *kAggregate) GetPool() *model.VectorPool { return a.vectorPool } -func (a *kAggregate) Explain() (me string, next []model.VectorOperator) { +func (a *kAggregate) String() string { if a.by { - return fmt.Sprintf("[kaggregate] %v by (%v)", a.aggregation.String(), a.labels), []model.VectorOperator{a.paramOp, a.next} + return fmt.Sprintf("[kaggregate] %v by (%v)", a.aggregation.String(), a.labels) } - return fmt.Sprintf("[kaggregate] %v without (%v)", a.aggregation.String(), a.labels), []model.VectorOperator{a.paramOp, a.next} + return fmt.Sprintf("[kaggregate] %v without (%v)", a.aggregation.String(), a.labels) +} + +func (a *kAggregate) Explain() (next []model.VectorOperator) { + return []model.VectorOperator{a.paramOp, a.next} } func (a *kAggregate) init(ctx context.Context) error { diff --git a/vendor/github.com/thanos-io/promql-engine/execution/binary/scalar.go b/vendor/github.com/thanos-io/promql-engine/execution/binary/scalar.go index 7b5caf5818..e66683d48a 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/binary/scalar.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/binary/scalar.go @@ -71,9 +71,7 @@ func NewScalar( operandValIdx = 1 } - return &scalarOperator{ - OperatorTelemetry: model.NewTelemetry("[vectorScalarBinary]", opts.EnableAnalysis), - + oper := &scalarOperator{ pool: pool, next: next, scalar: scalar, @@ -84,12 +82,16 @@ func NewScalar( operandValIdx: operandValIdx, returnBool: returnBool, bothScalars: scalarSide == ScalarSideBoth, - }, nil + } + + oper.OperatorTelemetry = model.NewTelemetry(op, opts.EnableAnalysis) + + return oper, nil } -func (o *scalarOperator) Explain() (me string, next []model.VectorOperator) { - return fmt.Sprintf("[vectorScalarBinary] %s", parser.ItemTypeStr[o.opType]), []model.VectorOperator{o.next, o.scalar} +func (o *scalarOperator) Explain() (next []model.VectorOperator) { + return []model.VectorOperator{o.next, o.scalar} } func (o *scalarOperator) Series(ctx context.Context) ([]labels.Labels, error) { @@ -104,6 +106,10 @@ func (o *scalarOperator) Series(ctx context.Context) ([]labels.Labels, error) { return o.series, nil } +func (o *scalarOperator) String() string { + return fmt.Sprintf("[vectorScalarBinary] %s", parser.ItemTypeStr[o.opType]) +} + func (o *scalarOperator) Next(ctx context.Context) ([]model.StepVector, error) { start := time.Now() defer func() { o.AddExecutionTimeTaken(time.Since(start)) }() diff --git a/vendor/github.com/thanos-io/promql-engine/execution/binary/vector.go b/vendor/github.com/thanos-io/promql-engine/execution/binary/vector.go index f8ae8a6208..f284bd2e49 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/binary/vector.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/binary/vector.go @@ -67,9 +67,7 @@ func NewVectorOperator( returnBool bool, opts *query.Options, ) (model.VectorOperator, error) { - return &vectorOperator{ - OperatorTelemetry: model.NewTelemetry("[vectorBinary]", opts.EnableAnalysis), - + oper := &vectorOperator{ pool: pool, lhs: lhs, rhs: rhs, @@ -77,14 +75,22 @@ func NewVectorOperator( opType: opType, returnBool: returnBool, sigFunc: signatureFunc(matching.On, matching.MatchingLabels...), - }, nil + } + + oper.OperatorTelemetry = model.NewTelemetry(oper, opts.EnableAnalysis) + + return oper, nil } -func (o *vectorOperator) Explain() (me string, next []model.VectorOperator) { +func (o *vectorOperator) String() string { if o.matching.On { - return fmt.Sprintf("[vectorBinary] %s - %v, on: %v, group: %v", parser.ItemTypeStr[o.opType], o.matching.Card.String(), o.matching.MatchingLabels, o.matching.Include), []model.VectorOperator{o.lhs, o.rhs} + return fmt.Sprintf("[vectorBinary] %s - %v, on: %v, group: %v", parser.ItemTypeStr[o.opType], o.matching.Card.String(), o.matching.MatchingLabels, o.matching.Include) } - return fmt.Sprintf("[vectorBinary] %s - %v, ignoring: %v, group: %v", parser.ItemTypeStr[o.opType], o.matching.Card.String(), o.matching.On, o.matching.Include), []model.VectorOperator{o.lhs, o.rhs} + return fmt.Sprintf("[vectorBinary] %s - %v, ignoring: %v, group: %v", parser.ItemTypeStr[o.opType], o.matching.Card.String(), o.matching.On, o.matching.Include) +} + +func (o *vectorOperator) Explain() (next []model.VectorOperator) { + return []model.VectorOperator{o.lhs, o.rhs} } func (o *vectorOperator) Series(ctx context.Context) ([]labels.Labels, error) { diff --git a/vendor/github.com/thanos-io/promql-engine/execution/exchange/coalesce.go b/vendor/github.com/thanos-io/promql-engine/execution/exchange/coalesce.go index 8c64e0ba23..558a76a64b 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/exchange/coalesce.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/exchange/coalesce.go @@ -51,19 +51,25 @@ type coalesce struct { } func NewCoalesce(pool *model.VectorPool, opts *query.Options, batchSize int64, operators ...model.VectorOperator) model.VectorOperator { - return &coalesce{ - OperatorTelemetry: model.NewTelemetry("[coalesce]", opts.EnableAnalysis), - + oper := &coalesce{ pool: pool, sampleOffsets: make([]uint64, len(operators)), operators: operators, inVectors: make([][]model.StepVector, len(operators)), batchSize: batchSize, } + + oper.OperatorTelemetry = model.NewTelemetry(oper, opts.EnableAnalysis) + + return oper +} + +func (c *coalesce) Explain() (next []model.VectorOperator) { + return c.operators } -func (c *coalesce) Explain() (me string, next []model.VectorOperator) { - return "[coalesce]", c.operators +func (c *coalesce) String() string { + return "[coalesce]" } func (c *coalesce) GetPool() *model.VectorPool { diff --git a/vendor/github.com/thanos-io/promql-engine/execution/exchange/concurrent.go b/vendor/github.com/thanos-io/promql-engine/execution/exchange/concurrent.go index f41bb86dac..3e8af4cff9 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/exchange/concurrent.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/exchange/concurrent.go @@ -29,17 +29,22 @@ type concurrencyOperator struct { } func NewConcurrent(next model.VectorOperator, bufferSize int, opts *query.Options) model.VectorOperator { - return &concurrencyOperator{ - OperatorTelemetry: model.NewTelemetry("[concurrent]", opts.EnableAnalysis), - + oper := &concurrencyOperator{ next: next, buffer: make(chan maybeStepVector, bufferSize), bufferSize: bufferSize, } + + oper.OperatorTelemetry = model.NewTelemetry(oper, opts.EnableAnalysis) + return oper +} + +func (c *concurrencyOperator) Explain() (next []model.VectorOperator) { + return []model.VectorOperator{c.next} } -func (c *concurrencyOperator) Explain() (me string, next []model.VectorOperator) { - return fmt.Sprintf("[concurrent(buff=%v)]", c.bufferSize), []model.VectorOperator{c.next} +func (c *concurrencyOperator) String() string { + return fmt.Sprintf("[concurrent(buff=%v)]", c.bufferSize) } func (c *concurrencyOperator) Series(ctx context.Context) ([]labels.Labels, error) { diff --git a/vendor/github.com/thanos-io/promql-engine/execution/exchange/dedup.go b/vendor/github.com/thanos-io/promql-engine/execution/exchange/dedup.go index 36b2d4b3c9..344d801703 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/exchange/dedup.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/exchange/dedup.go @@ -44,11 +44,13 @@ type dedupOperator struct { } func NewDedupOperator(pool *model.VectorPool, next model.VectorOperator, opts *query.Options) model.VectorOperator { - return &dedupOperator{ - OperatorTelemetry: model.NewTelemetry("[dedup]", opts.EnableAnalysis), - next: next, - pool: pool, + oper := &dedupOperator{ + next: next, + pool: pool, } + oper.OperatorTelemetry = model.NewTelemetry(oper, opts.EnableAnalysis) + + return oper } func (d *dedupOperator) Next(ctx context.Context) ([]model.StepVector, error) { @@ -119,8 +121,12 @@ func (d *dedupOperator) GetPool() *model.VectorPool { return d.pool } -func (d *dedupOperator) Explain() (me string, next []model.VectorOperator) { - return "[dedup]", []model.VectorOperator{d.next} +func (d *dedupOperator) Explain() (next []model.VectorOperator) { + return []model.VectorOperator{d.next} +} + +func (d *dedupOperator) String() string { + return "[dedup]" } func (d *dedupOperator) loadSeries(ctx context.Context) error { diff --git a/vendor/github.com/thanos-io/promql-engine/execution/exchange/duplicate_label.go b/vendor/github.com/thanos-io/promql-engine/execution/exchange/duplicate_label.go index e96845c3b5..fb1c1d4429 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/exchange/duplicate_label.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/exchange/duplicate_label.go @@ -28,10 +28,12 @@ type duplicateLabelCheckOperator struct { } func NewDuplicateLabelCheck(next model.VectorOperator, opts *query.Options) model.VectorOperator { - return &duplicateLabelCheckOperator{ - OperatorTelemetry: model.NewTelemetry("[duplicateLabelCheck]", opts.EnableAnalysis), - next: next, + oper := &duplicateLabelCheckOperator{ + next: next, } + oper.OperatorTelemetry = model.NewTelemetry(oper, opts.EnableAnalysis) + + return oper } func (d *duplicateLabelCheckOperator) Next(ctx context.Context) ([]model.StepVector, error) { @@ -94,8 +96,12 @@ func (d *duplicateLabelCheckOperator) GetPool() *model.VectorPool { return d.next.GetPool() } -func (d *duplicateLabelCheckOperator) Explain() (me string, next []model.VectorOperator) { - return d.next.Explain() +func (d *duplicateLabelCheckOperator) Explain() (next []model.VectorOperator) { + return []model.VectorOperator{d.next} +} + +func (d *duplicateLabelCheckOperator) String() string { + return "[duplicateLabelCheck]" } func (d *duplicateLabelCheckOperator) init(ctx context.Context) error { diff --git a/vendor/github.com/thanos-io/promql-engine/execution/execution.go b/vendor/github.com/thanos-io/promql-engine/execution/execution.go index e0ea8d47ad..be201134bd 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/execution.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/execution.go @@ -43,7 +43,7 @@ import ( // New creates new physical query execution for a given query expression which represents logical plan. // TODO(bwplotka): Add definition (could be parameters for each execution operator) we can optimize - it would represent physical plan. -func New(expr parser.Expr, storage storage.Scanners, opts *query.Options) (model.VectorOperator, error) { +func New(expr logicalplan.Node, storage storage.Scanners, opts *query.Options) (model.VectorOperator, error) { hints := promstorage.SelectHints{ Start: opts.Start.UnixMilli(), End: opts.End.UnixMilli(), @@ -52,21 +52,21 @@ func New(expr parser.Expr, storage storage.Scanners, opts *query.Options) (model return newOperator(expr, storage, opts, hints) } -func newOperator(expr parser.Expr, storage storage.Scanners, opts *query.Options, hints promstorage.SelectHints) (model.VectorOperator, error) { +func newOperator(expr logicalplan.Node, storage storage.Scanners, opts *query.Options, hints promstorage.SelectHints) (model.VectorOperator, error) { switch e := expr.(type) { case *logicalplan.NumberLiteral: return scan.NewNumberLiteralSelector(model.NewVectorPool(opts.StepsBatch), opts, e.Val), nil case *logicalplan.VectorSelector: return newVectorSelector(e, storage, opts, hints) - case *parser.Call: + case *logicalplan.FunctionCall: return newCall(e, storage, opts, hints) - case *parser.AggregateExpr: + case *logicalplan.Aggregation: return newAggregateExpression(e, storage, opts, hints) - case *parser.BinaryExpr: + case *logicalplan.Binary: return newBinaryExpression(e, storage, opts, hints) - case *parser.ParenExpr: + case *logicalplan.Parens: return newOperator(e.Expr, storage, opts, hints) - case *parser.UnaryExpr: + case *logicalplan.Unary: return newUnaryExpression(e, storage, opts, hints) case *logicalplan.StepInvariantExpr: return newStepInvariantExpression(e, storage, opts, hints) @@ -74,7 +74,7 @@ func newOperator(expr parser.Expr, storage storage.Scanners, opts *query.Options return newDeduplication(e, storage, opts, hints) case logicalplan.RemoteExecution: return newRemoteExecution(e, opts, hints) - case logicalplan.CheckDuplicateLabels: + case *logicalplan.CheckDuplicateLabels: return newDuplicateLabelCheck(e, storage, opts, hints) case logicalplan.Noop: return noop.NewOperator(), nil @@ -92,7 +92,7 @@ func newVectorSelector(e *logicalplan.VectorSelector, scanners storage.Scanners, return scanners.NewVectorSelector(opts, hints, *e) } -func newCall(e *parser.Call, scanners storage.Scanners, opts *query.Options, hints promstorage.SelectHints) (model.VectorOperator, error) { +func newCall(e *logicalplan.FunctionCall, scanners storage.Scanners, opts *query.Options, hints promstorage.SelectHints) (model.VectorOperator, error) { hints.Func = e.Func.Name hints.Grouping = nil hints.By = false @@ -105,7 +105,7 @@ func newCall(e *parser.Call, scanners storage.Scanners, opts *query.Options, hin case *logicalplan.VectorSelector: arg.SelectTimestamp = true return newVectorSelector(arg, scanners, opts, hints) - case *parser.StepInvariantExpr: + case *logicalplan.StepInvariantExpr: // Step invariant expressions on vector selectors need to be unwrapped so that we // can return the original timestamp rather than the step invariant one. switch vs := arg.Expr.(type) { @@ -126,7 +126,7 @@ func newCall(e *parser.Call, scanners storage.Scanners, opts *query.Options, hin // before it can be non-nested. https://github.com/thanos-io/promql-engine/issues/39 for i := range e.Args { switch t := e.Args[i].(type) { - case *parser.SubqueryExpr: + case *logicalplan.Subquery: return newSubqueryFunction(e, t, scanners, opts, hints) case *logicalplan.MatrixSelector: return newRangeVectorFunction(e, t, scanners, opts, hints) @@ -135,33 +135,33 @@ func newCall(e *parser.Call, scanners storage.Scanners, opts *query.Options, hin return newInstantVectorFunction(e, scanners, opts, hints) } -func newAbsentOverTimeOperator(call *parser.Call, scanners storage.Scanners, opts *query.Options, hints promstorage.SelectHints) (model.VectorOperator, error) { +func newAbsentOverTimeOperator(call *logicalplan.FunctionCall, scanners storage.Scanners, opts *query.Options, hints promstorage.SelectHints) (model.VectorOperator, error) { switch arg := call.Args[0].(type) { - case *parser.SubqueryExpr: - matrixCall := &parser.Call{ - Func: &parser.Function{Name: "last_over_time"}, + case *logicalplan.Subquery: + matrixCall := &logicalplan.FunctionCall{ + Func: parser.Function{Name: "last_over_time"}, } argOp, err := newSubqueryFunction(matrixCall, arg, scanners, opts, hints) if err != nil { return nil, err } - f := &parser.Call{ - Func: &parser.Function{Name: "absent"}, - Args: []parser.Expr{matrixCall}, + f := &logicalplan.FunctionCall{ + Func: parser.Function{Name: "absent"}, + Args: []logicalplan.Node{matrixCall}, } return function.NewFunctionOperator(f, []model.VectorOperator{argOp}, opts.StepsBatch, opts) case *logicalplan.MatrixSelector: - matrixCall := &parser.Call{ - Func: &parser.Function{Name: "last_over_time"}, + matrixCall := &logicalplan.FunctionCall{ + Func: parser.Function{Name: "last_over_time"}, Args: call.Args, } argOp, err := newRangeVectorFunction(matrixCall, arg, scanners, opts, hints) if err != nil { return nil, err } - f := &parser.Call{ - Func: &parser.Function{Name: "absent"}, - Args: []parser.Expr{&logicalplan.MatrixSelector{ + f := &logicalplan.FunctionCall{ + Func: parser.Function{Name: "absent"}, + Args: []logicalplan.Node{&logicalplan.MatrixSelector{ VectorSelector: arg.VectorSelector, Range: arg.Range, OriginalString: arg.String(), @@ -173,7 +173,7 @@ func newAbsentOverTimeOperator(call *parser.Call, scanners storage.Scanners, opt } } -func newRangeVectorFunction(e *parser.Call, t *logicalplan.MatrixSelector, scanners storage.Scanners, opts *query.Options, hints promstorage.SelectHints) (model.VectorOperator, error) { +func newRangeVectorFunction(e *logicalplan.FunctionCall, t *logicalplan.MatrixSelector, scanners storage.Scanners, opts *query.Options, hints promstorage.SelectHints) (model.VectorOperator, error) { // TODO(saswatamcode): Range vector result might need new operator // before it can be non-nested. https://github.com/thanos-io/promql-engine/issues/39 milliSecondRange := t.Range.Milliseconds() @@ -181,20 +181,20 @@ func newRangeVectorFunction(e *parser.Call, t *logicalplan.MatrixSelector, scann milliSecondRange += opts.ExtLookbackDelta.Milliseconds() } - start, end := getTimeRangesForVectorSelector(t.VectorSelector.(*logicalplan.VectorSelector), opts, milliSecondRange) + start, end := getTimeRangesForVectorSelector(t.VectorSelector, opts, milliSecondRange) hints.Start = start hints.End = end hints.Range = milliSecondRange return scanners.NewMatrixSelector(opts, hints, *t, *e) } -func newSubqueryFunction(e *parser.Call, t *parser.SubqueryExpr, storage storage.Scanners, opts *query.Options, hints promstorage.SelectHints) (model.VectorOperator, error) { +func newSubqueryFunction(e *logicalplan.FunctionCall, t *logicalplan.Subquery, storage storage.Scanners, opts *query.Options, hints promstorage.SelectHints) (model.VectorOperator, error) { // TODO: We dont implement ext functions if parse.IsExtFunction(e.Func.Name) { return nil, parse.ErrNotImplemented } - nOpts := query.NestedOptionsForSubquery(opts, t) + nOpts := query.NestedOptionsForSubquery(opts, t.Step, t.Range, t.Offset) hints.Start = nOpts.Start.UnixMilli() hints.End = nOpts.End.UnixMilli() @@ -213,11 +213,11 @@ func newSubqueryFunction(e *parser.Call, t *parser.SubqueryExpr, storage storage return scan.NewSubqueryOperator(model.NewVectorPool(opts.StepsBatch), inner, &outerOpts, e, t) } -func newInstantVectorFunction(e *parser.Call, storage storage.Scanners, opts *query.Options, hints promstorage.SelectHints) (model.VectorOperator, error) { +func newInstantVectorFunction(e *logicalplan.FunctionCall, storage storage.Scanners, opts *query.Options, hints promstorage.SelectHints) (model.VectorOperator, error) { nextOperators := make([]model.VectorOperator, 0, len(e.Args)) for i := range e.Args { // Strings don't need an operator - if e.Args[i].Type() == parser.ValueTypeString { + if e.Args[i].ReturnType() == parser.ValueTypeString { continue } next, err := newOperator(e.Args[i], storage, opts, hints) @@ -230,7 +230,7 @@ func newInstantVectorFunction(e *parser.Call, storage storage.Scanners, opts *qu return function.NewFunctionOperator(e, nextOperators, opts.StepsBatch, opts) } -func newAggregateExpression(e *parser.AggregateExpr, scanners storage.Scanners, opts *query.Options, hints promstorage.SelectHints) (model.VectorOperator, error) { +func newAggregateExpression(e *logicalplan.Aggregation, scanners storage.Scanners, opts *query.Options, hints promstorage.SelectHints) (model.VectorOperator, error) { hints.Func = e.Op.String() hints.Grouping = e.Grouping hints.By = !e.Without @@ -241,7 +241,7 @@ func newAggregateExpression(e *parser.AggregateExpr, scanners storage.Scanners, return nil, err } - if e.Param != nil && e.Param.Type() != parser.ValueTypeString { + if e.Param != nil && e.Param.ReturnType() != parser.ValueTypeString { paramOp, err = newOperator(e.Param, scanners, opts, hints) if err != nil { return nil, err @@ -262,14 +262,14 @@ func newAggregateExpression(e *parser.AggregateExpr, scanners storage.Scanners, } -func newBinaryExpression(e *parser.BinaryExpr, scanners storage.Scanners, opts *query.Options, hints promstorage.SelectHints) (model.VectorOperator, error) { - if e.LHS.Type() == parser.ValueTypeScalar || e.RHS.Type() == parser.ValueTypeScalar { +func newBinaryExpression(e *logicalplan.Binary, scanners storage.Scanners, opts *query.Options, hints promstorage.SelectHints) (model.VectorOperator, error) { + if e.LHS.ReturnType() == parser.ValueTypeScalar || e.RHS.ReturnType() == parser.ValueTypeScalar { return newScalarBinaryOperator(e, scanners, opts, hints) } return newVectorBinaryOperator(e, scanners, opts, hints) } -func newVectorBinaryOperator(e *parser.BinaryExpr, storage storage.Scanners, opts *query.Options, hints promstorage.SelectHints) (model.VectorOperator, error) { +func newVectorBinaryOperator(e *logicalplan.Binary, storage storage.Scanners, opts *query.Options, hints promstorage.SelectHints) (model.VectorOperator, error) { leftOperator, err := newOperator(e.LHS, storage, opts, hints) if err != nil { return nil, err @@ -281,7 +281,7 @@ func newVectorBinaryOperator(e *parser.BinaryExpr, storage storage.Scanners, opt return binary.NewVectorOperator(model.NewVectorPool(opts.StepsBatch), leftOperator, rightOperator, e.VectorMatching, e.Op, e.ReturnBool, opts) } -func newScalarBinaryOperator(e *parser.BinaryExpr, storage storage.Scanners, opts *query.Options, hints promstorage.SelectHints) (model.VectorOperator, error) { +func newScalarBinaryOperator(e *logicalplan.Binary, storage storage.Scanners, opts *query.Options, hints promstorage.SelectHints) (model.VectorOperator, error) { lhs, err := newOperator(e.LHS, storage, opts, hints) if err != nil { return nil, err @@ -292,9 +292,9 @@ func newScalarBinaryOperator(e *parser.BinaryExpr, storage storage.Scanners, opt } scalarSide := binary.ScalarSideRight - if e.LHS.Type() == parser.ValueTypeScalar && e.RHS.Type() == parser.ValueTypeScalar { + if e.LHS.ReturnType() == parser.ValueTypeScalar && e.RHS.ReturnType() == parser.ValueTypeScalar { scalarSide = binary.ScalarSideBoth - } else if e.LHS.Type() == parser.ValueTypeScalar { + } else if e.LHS.ReturnType() == parser.ValueTypeScalar { rhs, lhs = lhs, rhs scalarSide = binary.ScalarSideLeft } @@ -302,7 +302,7 @@ func newScalarBinaryOperator(e *parser.BinaryExpr, storage storage.Scanners, opt return binary.NewScalar(model.NewVectorPoolWithSize(opts.StepsBatch, 1), lhs, rhs, e.Op, scalarSide, e.ReturnBool, opts) } -func newUnaryExpression(e *parser.UnaryExpr, scanners storage.Scanners, opts *query.Options, hints promstorage.SelectHints) (model.VectorOperator, error) { +func newUnaryExpression(e *logicalplan.Unary, scanners storage.Scanners, opts *query.Options, hints promstorage.SelectHints) (model.VectorOperator, error) { next, err := newOperator(e.Expr, scanners, opts, hints) if err != nil { return nil, err @@ -369,7 +369,7 @@ func newRemoteExecution(e logicalplan.RemoteExecution, opts *query.Options, hint return exchange.NewConcurrent(remoteExec, 2, opts), nil } -func newDuplicateLabelCheck(e logicalplan.CheckDuplicateLabels, storage storage.Scanners, opts *query.Options, hints promstorage.SelectHints) (model.VectorOperator, error) { +func newDuplicateLabelCheck(e *logicalplan.CheckDuplicateLabels, storage storage.Scanners, opts *query.Options, hints promstorage.SelectHints) (model.VectorOperator, error) { op, err := newOperator(e.Expr, storage, opts, hints) if err != nil { return nil, err diff --git a/vendor/github.com/thanos-io/promql-engine/execution/function/absent.go b/vendor/github.com/thanos-io/promql-engine/execution/function/absent.go index f2286f54ed..28c1cf359f 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/function/absent.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/function/absent.go @@ -9,7 +9,6 @@ import ( "time" "github.com/prometheus/prometheus/model/labels" - "github.com/prometheus/prometheus/promql/parser" "github.com/thanos-io/promql-engine/execution/model" "github.com/thanos-io/promql-engine/logicalplan" @@ -20,28 +19,34 @@ type absentOperator struct { model.OperatorTelemetry once sync.Once - funcExpr *parser.Call + funcExpr *logicalplan.FunctionCall series []labels.Labels pool *model.VectorPool next model.VectorOperator } func newAbsentOperator( - funcExpr *parser.Call, + funcExpr *logicalplan.FunctionCall, pool *model.VectorPool, next model.VectorOperator, opts *query.Options, ) *absentOperator { - return &absentOperator{ - OperatorTelemetry: model.NewTelemetry(absentOperatorName, opts.EnableAnalysis), - funcExpr: funcExpr, - pool: pool, - next: next, + oper := &absentOperator{ + funcExpr: funcExpr, + pool: pool, + next: next, } + oper.OperatorTelemetry = model.NewTelemetry(oper, opts.EnableAnalysis) + + return oper +} + +func (o *absentOperator) String() string { + return "[absent]" } -func (o *absentOperator) Explain() (me string, next []model.VectorOperator) { - return absentOperatorName, []model.VectorOperator{o.next} +func (o *absentOperator) Explain() (next []model.VectorOperator) { + return []model.VectorOperator{o.next} } func (o *absentOperator) Series(_ context.Context) ([]labels.Labels, error) { @@ -63,7 +68,7 @@ func (o *absentOperator) loadSeries() { case *logicalplan.VectorSelector: lm = append(n.LabelMatchers, n.Filters...) case *logicalplan.MatrixSelector: - v := n.VectorSelector.(*logicalplan.VectorSelector) + v := n.VectorSelector lm = append(v.LabelMatchers, v.Filters...) default: o.series = []labels.Labels{labels.EmptyLabels()} diff --git a/vendor/github.com/thanos-io/promql-engine/execution/function/histogram.go b/vendor/github.com/thanos-io/promql-engine/execution/function/histogram.go index 3050badcd8..1f89e00380 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/function/histogram.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/function/histogram.go @@ -13,10 +13,10 @@ import ( "github.com/cespare/xxhash/v2" "github.com/prometheus/prometheus/model/labels" - "github.com/prometheus/prometheus/promql/parser" "github.com/thanos-io/promql-engine/execution/model" "github.com/thanos-io/promql-engine/extlabels" + "github.com/thanos-io/promql-engine/logicalplan" "github.com/thanos-io/promql-engine/query" ) @@ -33,7 +33,7 @@ type histogramOperator struct { series []labels.Labels pool *model.VectorPool - funcArgs parser.Expressions + funcArgs logicalplan.Nodes scalarOp model.VectorOperator vectorOp model.VectorOperator @@ -51,24 +51,29 @@ type histogramOperator struct { func newHistogramOperator( pool *model.VectorPool, - funcArgs parser.Expressions, + funcArgs logicalplan.Nodes, scalarOp model.VectorOperator, vectorOp model.VectorOperator, opts *query.Options, ) *histogramOperator { - return &histogramOperator{ - pool: pool, - funcArgs: funcArgs, - scalarOp: scalarOp, - vectorOp: vectorOp, - scalarPoints: make([]float64, opts.StepsBatch), - OperatorTelemetry: model.NewTelemetry(histogramOperatorName, opts.EnableAnalysis), + oper := &histogramOperator{ + pool: pool, + funcArgs: funcArgs, + scalarOp: scalarOp, + vectorOp: vectorOp, + scalarPoints: make([]float64, opts.StepsBatch), } + oper.OperatorTelemetry = model.NewTelemetry(oper, opts.EnableAnalysis) + + return oper +} + +func (o *histogramOperator) String() string { + return fmt.Sprintf("[histogram_quantile](%v)", o.funcArgs) } -func (o *histogramOperator) Explain() (me string, next []model.VectorOperator) { - next = []model.VectorOperator{o.scalarOp, o.vectorOp} - return fmt.Sprintf("%s(%v)", histogramOperatorName, o.funcArgs), next +func (o *histogramOperator) Explain() (next []model.VectorOperator) { + return []model.VectorOperator{o.scalarOp, o.vectorOp} } func (o *histogramOperator) Series(ctx context.Context) ([]labels.Labels, error) { diff --git a/vendor/github.com/thanos-io/promql-engine/execution/function/noarg.go b/vendor/github.com/thanos-io/promql-engine/execution/function/noarg.go index 2eba119445..79fcc86340 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/function/noarg.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/function/noarg.go @@ -5,14 +5,12 @@ package function import ( "context" - "fmt" "time" "github.com/prometheus/prometheus/model/labels" - "github.com/prometheus/prometheus/promql/parser" - "github.com/thanos-io/promql-engine/execution/model" + "github.com/thanos-io/promql-engine/logicalplan" ) type noArgFunctionOperator struct { @@ -23,15 +21,19 @@ type noArgFunctionOperator struct { step int64 currentStep int64 stepsBatch int - funcExpr *parser.Call + funcExpr *logicalplan.FunctionCall call noArgFunctionCall vectorPool *model.VectorPool series []labels.Labels sampleIDs []uint64 } -func (o *noArgFunctionOperator) Explain() (me string, next []model.VectorOperator) { - return fmt.Sprintf("%s %s()", noArgFunctionOperatorName, o.funcExpr.Func.Name), []model.VectorOperator{} +func (o *noArgFunctionOperator) Explain() (next []model.VectorOperator) { + return nil +} + +func (o *noArgFunctionOperator) String() string { + return "[noArgFunction]" } func (o *noArgFunctionOperator) Series(_ context.Context) ([]labels.Labels, error) { diff --git a/vendor/github.com/thanos-io/promql-engine/execution/function/operator.go b/vendor/github.com/thanos-io/promql-engine/execution/function/operator.go index 42333d1894..02a0001663 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/function/operator.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/function/operator.go @@ -17,20 +17,11 @@ import ( "github.com/thanos-io/promql-engine/execution/model" "github.com/thanos-io/promql-engine/execution/parse" "github.com/thanos-io/promql-engine/extlabels" + "github.com/thanos-io/promql-engine/logicalplan" "github.com/thanos-io/promql-engine/query" ) -const ( - absentOperatorName = "[absent]" - functionOperatorName = "[function]" - histogramOperatorName = "[histogram_quantile]" - relabelOperatorName = "[relabel]" - scalarOperatorName = "[scalar]" - timestampOperatorName = "[timestamp]" - noArgFunctionOperatorName = "[noArgFunction]" -) - -func NewFunctionOperator(funcExpr *parser.Call, nextOps []model.VectorOperator, stepsBatch int, opts *query.Options) (model.VectorOperator, error) { +func NewFunctionOperator(funcExpr *logicalplan.FunctionCall, nextOps []model.VectorOperator, stepsBatch int, opts *query.Options) (model.VectorOperator, error) { // Some functions need to be handled in special operators switch funcExpr.Func.Name { case "scalar": @@ -53,7 +44,7 @@ func NewFunctionOperator(funcExpr *parser.Call, nextOps []model.VectorOperator, return newInstantVectorFunctionOperator(funcExpr, nextOps, stepsBatch, opts) } -func newNoArgsFunctionOperator(funcExpr *parser.Call, stepsBatch int, opts *query.Options) (model.VectorOperator, error) { +func newNoArgsFunctionOperator(funcExpr *logicalplan.FunctionCall, stepsBatch int, opts *query.Options) (model.VectorOperator, error) { call, ok := noArgFuncs[funcExpr.Func.Name] if !ok { return nil, UnknownFunctionError(funcExpr.Func.Name) @@ -66,16 +57,17 @@ func newNoArgsFunctionOperator(funcExpr *parser.Call, stepsBatch int, opts *quer } op := &noArgFunctionOperator{ - OperatorTelemetry: model.NewTelemetry(noArgFunctionOperatorName, opts.EnableAnalysis), - currentStep: opts.Start.UnixMilli(), - mint: opts.Start.UnixMilli(), - maxt: opts.End.UnixMilli(), - step: interval, - stepsBatch: stepsBatch, - funcExpr: funcExpr, - call: call, - vectorPool: model.NewVectorPool(stepsBatch), + currentStep: opts.Start.UnixMilli(), + mint: opts.Start.UnixMilli(), + maxt: opts.End.UnixMilli(), + step: interval, + stepsBatch: stepsBatch, + funcExpr: funcExpr, + call: call, + vectorPool: model.NewVectorPool(stepsBatch), } + op.OperatorTelemetry = model.NewTelemetry(op, opts.EnableAnalysis) + switch funcExpr.Func.Name { case "pi", "time": op.sampleIDs = []uint64{0} @@ -92,7 +84,7 @@ func newNoArgsFunctionOperator(funcExpr *parser.Call, stepsBatch int, opts *quer type functionOperator struct { model.OperatorTelemetry - funcExpr *parser.Call + funcExpr *logicalplan.FunctionCall series []labels.Labels once sync.Once @@ -103,7 +95,7 @@ type functionOperator struct { scalarPoints [][]float64 } -func newInstantVectorFunctionOperator(funcExpr *parser.Call, nextOps []model.VectorOperator, stepsBatch int, opts *query.Options) (model.VectorOperator, error) { +func newInstantVectorFunctionOperator(funcExpr *logicalplan.FunctionCall, nextOps []model.VectorOperator, stepsBatch int, opts *query.Options) (model.VectorOperator, error) { call, ok := instantVectorFuncs[funcExpr.Func.Name] if !ok { return nil, UnknownFunctionError(funcExpr.Func.Name) @@ -114,23 +106,23 @@ func newInstantVectorFunctionOperator(funcExpr *parser.Call, nextOps []model.Vec scalarPoints[i] = make([]float64, len(nextOps)-1) } f := &functionOperator{ - OperatorTelemetry: model.NewTelemetry(functionOperatorName, opts.EnableAnalysis), - nextOps: nextOps, - call: call, - funcExpr: funcExpr, - vectorIndex: 0, - scalarPoints: scalarPoints, + nextOps: nextOps, + call: call, + funcExpr: funcExpr, + vectorIndex: 0, + scalarPoints: scalarPoints, } + f.OperatorTelemetry = model.NewTelemetry(f, opts.EnableAnalysis) for i := range funcExpr.Args { - if funcExpr.Args[i].Type() == parser.ValueTypeVector { + if funcExpr.Args[i].ReturnType() == parser.ValueTypeVector { f.vectorIndex = i break } } // Check selector type. - switch funcExpr.Args[f.vectorIndex].Type() { + switch funcExpr.Args[f.vectorIndex].ReturnType() { case parser.ValueTypeVector, parser.ValueTypeScalar: return f, nil default: @@ -138,8 +130,12 @@ func newInstantVectorFunctionOperator(funcExpr *parser.Call, nextOps []model.Vec } } -func (o *functionOperator) Explain() (me string, next []model.VectorOperator) { - return fmt.Sprintf("%s %v(%v)", functionOperatorName, o.funcExpr.Func.Name, o.funcExpr.Args), o.nextOps +func (o *functionOperator) Explain() (next []model.VectorOperator) { + return o.nextOps +} + +func (o *functionOperator) String() string { + return fmt.Sprintf("[function] %v(%v)", o.funcExpr.Func.Name, o.funcExpr.Args) } func (o *functionOperator) Series(ctx context.Context) ([]labels.Labels, error) { diff --git a/vendor/github.com/thanos-io/promql-engine/execution/function/relabel.go b/vendor/github.com/thanos-io/promql-engine/execution/function/relabel.go index 252bab155a..fe78d704d5 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/function/relabel.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/function/relabel.go @@ -13,7 +13,6 @@ import ( "github.com/efficientgo/core/errors" prommodel "github.com/prometheus/common/model" "github.com/prometheus/prometheus/model/labels" - "github.com/prometheus/prometheus/promql/parser" "github.com/thanos-io/promql-engine/execution/model" "github.com/thanos-io/promql-engine/logicalplan" @@ -24,25 +23,31 @@ type relabelOperator struct { model.OperatorTelemetry next model.VectorOperator - funcExpr *parser.Call + funcExpr *logicalplan.FunctionCall once sync.Once series []labels.Labels } func newRelabelOperator( next model.VectorOperator, - funcExpr *parser.Call, + funcExpr *logicalplan.FunctionCall, opts *query.Options, ) *relabelOperator { - return &relabelOperator{ - OperatorTelemetry: model.NewTelemetry(relabelOperatorName, opts.EnableAnalysis), - next: next, - funcExpr: funcExpr, + oper := &relabelOperator{ + next: next, + funcExpr: funcExpr, } + oper.OperatorTelemetry = model.NewTelemetry(oper, opts.EnableAnalysis) + + return oper +} + +func (o *relabelOperator) String() string { + return "[relabel]" } -func (o *relabelOperator) Explain() (me string, next []model.VectorOperator) { - return relabelOperatorName, []model.VectorOperator{} +func (o *relabelOperator) Explain() (next []model.VectorOperator) { + return []model.VectorOperator{} } func (o *relabelOperator) Series(ctx context.Context) ([]labels.Labels, error) { diff --git a/vendor/github.com/thanos-io/promql-engine/execution/function/scalar.go b/vendor/github.com/thanos-io/promql-engine/execution/function/scalar.go index fc1a77b070..b9a6003f3c 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/function/scalar.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/function/scalar.go @@ -21,15 +21,21 @@ type scalarOperator struct { } func newScalarOperator(pool *model.VectorPool, next model.VectorOperator, opts *query.Options) *scalarOperator { - return &scalarOperator{ - pool: pool, - next: next, - OperatorTelemetry: model.NewTelemetry(scalarOperatorName, opts.EnableAnalysis), + oper := &scalarOperator{ + pool: pool, + next: next, } + + oper.OperatorTelemetry = model.NewTelemetry(oper, opts.EnableAnalysis) + return oper +} + +func (o *scalarOperator) String() string { + return "[scalar]" } -func (o *scalarOperator) Explain() (me string, next []model.VectorOperator) { - return scalarOperatorName, []model.VectorOperator{o.next} +func (o *scalarOperator) Explain() (next []model.VectorOperator) { + return []model.VectorOperator{o.next} } func (o *scalarOperator) Series(ctx context.Context) ([]labels.Labels, error) { diff --git a/vendor/github.com/thanos-io/promql-engine/execution/function/timestamp.go b/vendor/github.com/thanos-io/promql-engine/execution/function/timestamp.go index 471f367fda..735c32d0a7 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/function/timestamp.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/function/timestamp.go @@ -24,14 +24,16 @@ type timestampOperator struct { } func newTimestampOperator(next model.VectorOperator, opts *query.Options) *timestampOperator { - return ×tampOperator{ - next: next, - OperatorTelemetry: model.NewTelemetry(timestampOperatorName, opts.EnableAnalysis), + oper := ×tampOperator{ + next: next, } + oper.OperatorTelemetry = model.NewTelemetry(oper, opts.EnableAnalysis) + + return oper } -func (o *timestampOperator) Explain() (me string, next []model.VectorOperator) { - return timestampOperatorName, []model.VectorOperator{o.next} +func (o *timestampOperator) Explain() (next []model.VectorOperator) { + return []model.VectorOperator{o.next} } func (o *timestampOperator) Series(ctx context.Context) ([]labels.Labels, error) { @@ -44,6 +46,10 @@ func (o *timestampOperator) Series(ctx context.Context) ([]labels.Labels, error) return o.series, nil } +func (o *timestampOperator) String() string { + return "[timestamp]" +} + func (o *timestampOperator) loadSeries(ctx context.Context) error { var err error o.once.Do(func() { diff --git a/vendor/github.com/thanos-io/promql-engine/execution/model/operator.go b/vendor/github.com/thanos-io/promql-engine/execution/model/operator.go index 176377dc95..cadf876e3d 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/model/operator.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/model/operator.go @@ -5,6 +5,7 @@ package model import ( "context" + "fmt" "time" "github.com/prometheus/prometheus/model/labels" @@ -13,27 +14,25 @@ import ( type OperatorTelemetry interface { AddExecutionTimeTaken(time.Duration) ExecutionTimeTaken() time.Duration - Name() string + fmt.Stringer } -func NewTelemetry(name string, enabled bool) OperatorTelemetry { +func NewTelemetry(operator fmt.Stringer, enabled bool) OperatorTelemetry { if enabled { - return NewTrackedTelemetry(name) + return NewTrackedTelemetry(operator) } - return NewNoopTelemetry(name) + return NewNoopTelemetry(operator) } type NoopTelemetry struct { - name string + fmt.Stringer } -func NewNoopTelemetry(name string) *NoopTelemetry { - return &NoopTelemetry{name: name} +func NewNoopTelemetry(operator fmt.Stringer) *NoopTelemetry { + return &NoopTelemetry{Stringer: operator} } -func (tm *NoopTelemetry) Name() string { return tm.name } - func (tm *NoopTelemetry) AddExecutionTimeTaken(t time.Duration) {} func (tm *NoopTelemetry) ExecutionTimeTaken() time.Duration { @@ -43,10 +42,11 @@ func (tm *NoopTelemetry) ExecutionTimeTaken() time.Duration { type TrackedTelemetry struct { name string ExecutionTime time.Duration + fmt.Stringer } -func NewTrackedTelemetry(name string) *TrackedTelemetry { - return &TrackedTelemetry{name: name} +func NewTrackedTelemetry(operator fmt.Stringer) *TrackedTelemetry { + return &TrackedTelemetry{Stringer: operator} } func (ti *TrackedTelemetry) Name() string { @@ -78,5 +78,7 @@ type VectorOperator interface { GetPool() *VectorPool // Explain returns human-readable explanation of the current operator and optional nested operators. - Explain() (me string, next []VectorOperator) + Explain() (next []VectorOperator) + + fmt.Stringer } diff --git a/vendor/github.com/thanos-io/promql-engine/execution/noop/operator.go b/vendor/github.com/thanos-io/promql-engine/execution/noop/operator.go index 7e192b95ad..2736f261ce 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/noop/operator.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/noop/operator.go @@ -15,10 +15,12 @@ type operator struct{} func NewOperator() model.VectorOperator { return &operator{} } +func (o operator) String() string { return "noop" } + func (o operator) Next(ctx context.Context) ([]model.StepVector, error) { return nil, nil } func (o operator) Series(ctx context.Context) ([]labels.Labels, error) { return nil, nil } func (o operator) GetPool() *model.VectorPool { return nil } -func (o operator) Explain() (me string, next []model.VectorOperator) { return "noop", nil } +func (o operator) Explain() (next []model.VectorOperator) { return nil } diff --git a/vendor/github.com/thanos-io/promql-engine/execution/remote/operator.go b/vendor/github.com/thanos-io/promql-engine/execution/remote/operator.go index a7556542c0..0872e8bfcb 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/remote/operator.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/remote/operator.go @@ -30,14 +30,17 @@ type Execution struct { func NewExecution(query promql.Query, pool *model.VectorPool, queryRangeStart time.Time, opts *query.Options, hints storage.SelectHints) *Execution { storage := newStorageFromQuery(query, opts) - return &Execution{ - storage: storage, - query: query, - opts: opts, - queryRangeStart: queryRangeStart, - vectorSelector: promstorage.NewVectorSelector(pool, storage, opts, 0, 0, false, 0, 1), - OperatorTelemetry: model.NewTelemetry("[remoteExec]", opts.EnableAnalysis), + oper := &Execution{ + storage: storage, + query: query, + opts: opts, + queryRangeStart: queryRangeStart, + vectorSelector: promstorage.NewVectorSelector(pool, storage, opts, 0, 0, false, 0, 1), } + + oper.OperatorTelemetry = model.NewTelemetry(oper, opts.EnableAnalysis) + + return oper } func (e *Execution) Series(ctx context.Context) ([]labels.Labels, error) { @@ -47,6 +50,10 @@ func (e *Execution) Series(ctx context.Context) ([]labels.Labels, error) { return e.vectorSelector.Series(ctx) } +func (e *Execution) String() string { + return fmt.Sprintf("[remoteExec] %s (%d, %d)", e.query, e.queryRangeStart.Unix(), e.opts.End.Unix()) +} + func (e *Execution) Next(ctx context.Context) ([]model.StepVector, error) { start := time.Now() defer func() { e.AddExecutionTimeTaken(time.Since(start)) }() @@ -65,8 +72,8 @@ func (e *Execution) GetPool() *model.VectorPool { return e.vectorSelector.GetPool() } -func (e *Execution) Explain() (me string, next []model.VectorOperator) { - return fmt.Sprintf("[remoteExec] %s (%d, %d)", e.query, e.queryRangeStart.Unix(), e.opts.End.Unix()), nil +func (e *Execution) Explain() (next []model.VectorOperator) { + return nil } type storageAdapter struct { diff --git a/vendor/github.com/thanos-io/promql-engine/execution/scan/functions.go b/vendor/github.com/thanos-io/promql-engine/execution/scan/functions.go index 548a656b3e..110cd082f7 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/scan/functions.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/scan/functions.go @@ -105,6 +105,9 @@ var rangeVectorFuncs = map[string]FunctionCall{ if len(f.Samples) == 0 { return 0., nil, false } + if f.Samples[0].V.H != nil { + return 0, f.Samples[len(f.Samples)-1].V.H.Copy(), true + } return f.Samples[len(f.Samples)-1].V.F, nil, true }, "present_over_time": func(f FunctionArgs) (float64, *histogram.FloatHistogram, bool) { @@ -258,6 +261,16 @@ func extrapolatedRate(samples []ringbuffer.Sample[Value], isCounter, isRate bool sampledInterval := float64(samples[len(samples)-1].T-samples[0].T) / 1000 averageDurationBetweenSamples := sampledInterval / float64(len(samples)-1) + // If the first/last samples are close to the boundaries of the range, + // extrapolate the result. This is as we expect that another sample + // will exist given the spacing between samples we've seen thus far, + // with an allowance for noise. + extrapolationThreshold := averageDurationBetweenSamples * 1.1 + extrapolateToInterval := sampledInterval + + if durationToStart >= extrapolationThreshold { + durationToStart = averageDurationBetweenSamples / 2 + } if isCounter && resultValue > 0 && samples[0].V.F >= 0 { // Counters cannot be negative. If we have any slope at // all (i.e. resultValue went up), we can extrapolate @@ -266,29 +279,19 @@ func extrapolatedRate(samples []ringbuffer.Sample[Value], isCounter, isRate bool // take the zero point as the start of the series, // thereby avoiding extrapolation to negative counter // values. + // TODO(beorn7): Do this for histograms, too. durationToZero := sampledInterval * (samples[0].V.F / resultValue) if durationToZero < durationToStart { durationToStart = durationToZero } } + extrapolateToInterval += durationToStart - // If the first/last Samples are close to the boundaries of the range, - // extrapolate the result. This is as we expect that another sample - // will exist given the spacing between Samples we've seen thus far, - // with an allowance for noise. - extrapolationThreshold := averageDurationBetweenSamples * 1.1 - extrapolateToInterval := sampledInterval - - if durationToStart < extrapolationThreshold { - extrapolateToInterval += durationToStart - } else { - extrapolateToInterval += averageDurationBetweenSamples / 2 - } - if durationToEnd < extrapolationThreshold { - extrapolateToInterval += durationToEnd - } else { - extrapolateToInterval += averageDurationBetweenSamples / 2 + if durationToEnd >= extrapolationThreshold { + durationToEnd = averageDurationBetweenSamples / 2 } + extrapolateToInterval += durationToEnd + factor := extrapolateToInterval / sampledInterval if isRate { factor /= float64(selectRange / 1000) diff --git a/vendor/github.com/thanos-io/promql-engine/execution/scan/literal_selector.go b/vendor/github.com/thanos-io/promql-engine/execution/scan/literal_selector.go index 382e5dd3f3..7ae8ba5751 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/scan/literal_selector.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/scan/literal_selector.go @@ -32,9 +32,7 @@ type numberLiteralSelector struct { } func NewNumberLiteralSelector(pool *model.VectorPool, opts *query.Options, val float64) *numberLiteralSelector { - return &numberLiteralSelector{ - OperatorTelemetry: model.NewTelemetry("[numberLiteral]", opts.EnableAnalysis), - + oper := &numberLiteralSelector{ vectorPool: pool, numSteps: opts.NumSteps(), mint: opts.Start.UnixMilli(), @@ -43,10 +41,17 @@ func NewNumberLiteralSelector(pool *model.VectorPool, opts *query.Options, val f currentStep: opts.Start.UnixMilli(), val: val, } + + oper.OperatorTelemetry = model.NewTelemetry(oper, opts.EnableAnalysis) + return oper +} + +func (o *numberLiteralSelector) Explain() (next []model.VectorOperator) { + return nil } -func (o *numberLiteralSelector) Explain() (me string, next []model.VectorOperator) { - return fmt.Sprintf("[numberLiteral] %v", o.val), nil +func (o *numberLiteralSelector) String() string { + return fmt.Sprintf("[numberLiteral] %v", o.val) } func (o *numberLiteralSelector) Series(context.Context) ([]labels.Labels, error) { diff --git a/vendor/github.com/thanos-io/promql-engine/execution/scan/subquery.go b/vendor/github.com/thanos-io/promql-engine/execution/scan/subquery.go index dee4ca9971..26a2dfb933 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/scan/subquery.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/scan/subquery.go @@ -11,7 +11,6 @@ import ( "github.com/efficientgo/core/errors" "github.com/prometheus/prometheus/model/labels" - "github.com/prometheus/prometheus/promql/parser" "github.com/thanos-io/promql-engine/execution/model" "github.com/thanos-io/promql-engine/execution/parse" @@ -34,8 +33,8 @@ type subqueryOperator struct { stepsBatch int scalarArgs []float64 - funcExpr *parser.Call - subQuery *parser.SubqueryExpr + funcExpr *logicalplan.FunctionCall + subQuery *logicalplan.Subquery onceSeries sync.Once series []labels.Labels @@ -45,7 +44,7 @@ type subqueryOperator struct { buffers []*ringbuffer.RingBuffer[Value] } -func NewSubqueryOperator(pool *model.VectorPool, next model.VectorOperator, opts *query.Options, funcExpr *parser.Call, subQuery *parser.SubqueryExpr) (model.VectorOperator, error) { +func NewSubqueryOperator(pool *model.VectorPool, next model.VectorOperator, opts *query.Options, funcExpr *logicalplan.FunctionCall, subQuery *logicalplan.Subquery) (model.VectorOperator, error) { call, err := NewRangeVectorFunc(funcExpr.Func.Name) if err != nil { return nil, err @@ -64,9 +63,7 @@ func NewSubqueryOperator(pool *model.VectorPool, next model.VectorOperator, opts arg = unwrap } - return &subqueryOperator{ - OperatorTelemetry: model.NewTelemetry("[subquery]", opts.EnableAnalysis), - + oper := &subqueryOperator{ next: next, call: call, pool: pool, @@ -79,11 +76,18 @@ func NewSubqueryOperator(pool *model.VectorPool, next model.VectorOperator, opts step: step, stepsBatch: opts.StepsBatch, lastCollected: -1, - }, nil + } + oper.OperatorTelemetry = model.NewTelemetry(oper, opts.EnableAnalysis) + + return oper, nil +} + +func (o *subqueryOperator) String() string { + return fmt.Sprintf("[subquery] %v()", o.funcExpr.Func.Name) } -func (o *subqueryOperator) Explain() (me string, next []model.VectorOperator) { - return fmt.Sprintf("[subquery] %v()", o.funcExpr.Func.Name), []model.VectorOperator{o.next} +func (o *subqueryOperator) Explain() (next []model.VectorOperator) { + return []model.VectorOperator{o.next} } func (o *subqueryOperator) GetPool() *model.VectorPool { return o.pool } diff --git a/vendor/github.com/thanos-io/promql-engine/execution/step_invariant/step_invariant.go b/vendor/github.com/thanos-io/promql-engine/execution/step_invariant/step_invariant.go index e4126148b8..9dbeff5357 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/step_invariant/step_invariant.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/step_invariant/step_invariant.go @@ -10,7 +10,6 @@ import ( "github.com/efficientgo/core/errors" "github.com/prometheus/prometheus/model/labels" - "github.com/prometheus/prometheus/promql/parser" "github.com/thanos-io/promql-engine/execution/model" "github.com/thanos-io/promql-engine/logicalplan" @@ -35,20 +34,22 @@ type stepInvariantOperator struct { model.OperatorTelemetry } -func (u *stepInvariantOperator) Explain() (me string, next []model.VectorOperator) { - return "[stepInvariant]", []model.VectorOperator{u.next} +func (u *stepInvariantOperator) Explain() (next []model.VectorOperator) { + return []model.VectorOperator{u.next} +} + +func (u *stepInvariantOperator) String() string { + return "[stepInvariant]" } func NewStepInvariantOperator( pool *model.VectorPool, next model.VectorOperator, - expr parser.Expr, + expr logicalplan.Node, opts *query.Options, ) (model.VectorOperator, error) { // We set interval to be at least 1. u := &stepInvariantOperator{ - OperatorTelemetry: model.NewTelemetry("[stepInvariant]", opts.EnableAnalysis), - vectorPool: pool, next: next, currentStep: opts.Start.UnixMilli(), @@ -58,13 +59,14 @@ func NewStepInvariantOperator( stepsBatch: opts.StepsBatch, cacheResult: true, } + u.OperatorTelemetry = model.NewTelemetry(u, opts.EnableAnalysis) if u.step == 0 { u.step = 1 } // We do not duplicate results for range selectors since result is a matrix // with their unique timestamps which does not depend on the step. switch expr.(type) { - case *logicalplan.MatrixSelector, *parser.SubqueryExpr: + case *logicalplan.MatrixSelector, *logicalplan.Subquery: u.cacheResult = false } diff --git a/vendor/github.com/thanos-io/promql-engine/execution/unary/unary.go b/vendor/github.com/thanos-io/promql-engine/execution/unary/unary.go index 4200752a9e..73b0513841 100644 --- a/vendor/github.com/thanos-io/promql-engine/execution/unary/unary.go +++ b/vendor/github.com/thanos-io/promql-engine/execution/unary/unary.go @@ -25,15 +25,19 @@ type unaryNegation struct { func NewUnaryNegation(next model.VectorOperator, opts *query.Options) (model.VectorOperator, error) { u := &unaryNegation{ - next: next, - OperatorTelemetry: model.NewTelemetry("[unaryNegation]", opts.EnableAnalysis), + next: next, } + u.OperatorTelemetry = model.NewTelemetry(u, opts.EnableAnalysis) return u, nil } -func (u *unaryNegation) Explain() (me string, next []model.VectorOperator) { - return "[unaryNegation]", []model.VectorOperator{u.next} +func (u *unaryNegation) Explain() (next []model.VectorOperator) { + return []model.VectorOperator{u.next} +} + +func (u *unaryNegation) String() string { + return "[unaryNegation]" } func (u *unaryNegation) Series(ctx context.Context) ([]labels.Labels, error) { diff --git a/vendor/github.com/thanos-io/promql-engine/logicalplan/codec.go b/vendor/github.com/thanos-io/promql-engine/logicalplan/codec.go new file mode 100644 index 0000000000..5bd69367d1 --- /dev/null +++ b/vendor/github.com/thanos-io/promql-engine/logicalplan/codec.go @@ -0,0 +1,183 @@ +// Copyright (c) The Thanos Community Authors. +// Licensed under the Apache License 2.0. + +package logicalplan + +import ( + "encoding/json" +) + +type jsonNode struct { + Type NodeType `json:"type"` + Data json.RawMessage `json:"data"` + Children []json.RawMessage `json:"children,omitempty"` +} + +func Marshal(node Node) ([]byte, error) { + clone := node.Clone() + return marshalNode(clone) +} + +func marshalNode(node Node) ([]byte, error) { + children := make([]json.RawMessage, 0, len(node.Children())) + for _, c := range node.Children() { + childData, err := marshalNode(*c) + if err != nil { + return nil, err + } + children = append(children, childData) + } + data, err := json.Marshal(node) + if err != nil { + return nil, err + } + return json.Marshal(jsonNode{ + Type: node.Type(), + Data: data, + Children: children, + }) +} + +func Unmarshal(data []byte) (Node, error) { + return unmarshalNode(data) +} + +func unmarshalNode(data []byte) (Node, error) { + t := jsonNode{} + if err := json.Unmarshal(data, &t); err != nil { + return nil, err + } + + switch t.Type { + case VectorSelectorNode: + v := &VectorSelector{} + if err := json.Unmarshal(t.Data, v); err != nil { + return nil, err + } + return v, nil + case MatrixSelectorNode: + m := &MatrixSelector{} + if err := json.Unmarshal(t.Data, m); err != nil { + return nil, err + } + vs, err := unmarshalNode(t.Children[0]) + if err != nil { + return nil, err + } + m.VectorSelector = vs.(*VectorSelector) + return m, nil + case AggregationNode: + a := &Aggregation{} + if err := json.Unmarshal(t.Data, a); err != nil { + return nil, err + } + var err error + a.Expr, err = unmarshalNode(t.Children[0]) + if err != nil { + return nil, err + } + if len(t.Children) > 1 { + a.Param, err = unmarshalNode(t.Children[1]) + if err != nil { + return nil, err + } + } + return a, nil + case BinaryNode: + b := &Binary{} + if err := json.Unmarshal(t.Data, b); err != nil { + return nil, err + } + var err error + b.LHS, err = unmarshalNode(t.Children[0]) + if err != nil { + return nil, err + } + b.RHS, err = unmarshalNode(t.Children[1]) + if err != nil { + return nil, err + } + return b, nil + case FunctionNode: + f := &FunctionCall{} + if err := json.Unmarshal(t.Data, f); err != nil { + return nil, err + } + for _, c := range t.Children { + child, err := unmarshalNode(c) + if err != nil { + return nil, err + } + f.Args = append(f.Args, child) + } + return f, nil + case NumberLiteralNode: + n := &NumberLiteral{} + if err := json.Unmarshal(t.Data, n); err != nil { + return nil, err + } + return n, nil + case StringLiteralNode: + s := &StringLiteral{} + if err := json.Unmarshal(t.Data, s); err != nil { + return nil, err + } + return s, nil + case SubqueryNode: + s := &Subquery{} + if err := json.Unmarshal(t.Data, s); err != nil { + return nil, err + } + var err error + s.Expr, err = unmarshalNode(t.Children[0]) + if err != nil { + return nil, err + } + return s, nil + case CheckDuplicateNode: + c := &CheckDuplicateLabels{} + if err := json.Unmarshal(t.Data, c); err != nil { + return nil, err + } + var err error + c.Expr, err = unmarshalNode(t.Children[0]) + if err != nil { + return nil, err + } + return c, nil + case StepInvariantNode: + s := &StepInvariantExpr{} + if err := json.Unmarshal(t.Data, s); err != nil { + return nil, err + } + var err error + s.Expr, err = unmarshalNode(t.Children[0]) + if err != nil { + return nil, err + } + return s, nil + case ParensNode: + p := &Parens{} + if err := json.Unmarshal(t.Data, p); err != nil { + return nil, err + } + var err error + p.Expr, err = unmarshalNode(t.Children[0]) + if err != nil { + return nil, err + } + return p, nil + case UnaryNode: + u := &Unary{} + if err := json.Unmarshal(t.Data, u); err != nil { + return nil, err + } + var err error + u.Expr, err = unmarshalNode(t.Children[0]) + if err != nil { + return nil, err + } + return u, nil + } + return nil, nil +} diff --git a/vendor/github.com/thanos-io/promql-engine/logicalplan/distribute.go b/vendor/github.com/thanos-io/promql-engine/logicalplan/distribute.go index ad7f9f3b10..ce81275448 100644 --- a/vendor/github.com/thanos-io/promql-engine/logicalplan/distribute.go +++ b/vendor/github.com/thanos-io/promql-engine/logicalplan/distribute.go @@ -15,7 +15,6 @@ import ( "github.com/prometheus/prometheus/util/annotations" "github.com/prometheus/prometheus/promql/parser" - "github.com/prometheus/prometheus/promql/parser/posrange" "github.com/thanos-io/promql-engine/api" "github.com/thanos-io/promql-engine/query" @@ -80,13 +79,20 @@ func (rs RemoteExecutions) String() string { // RemoteExecution is a logical plan that describes a // remote execution of a Query against the given PromQL Engine. type RemoteExecution struct { + LeafNode Engine api.RemoteEngine - Query parser.Expr + Query Node QueryRangeStart time.Time valueType parser.ValueType } +func (r RemoteExecution) Clone() Node { + clone := r + clone.Query = r.Query.Clone() + return clone +} + func (r RemoteExecution) String() string { if r.QueryRangeStart.UnixMilli() == 0 { return fmt.Sprintf("remote(%s)", r.Query) @@ -94,42 +100,44 @@ func (r RemoteExecution) String() string { return fmt.Sprintf("remote(%s) [%s]", r.Query, r.QueryRangeStart.UTC().String()) } -func (r RemoteExecution) Pretty(level int) string { return r.String() } - -func (r RemoteExecution) PositionRange() posrange.PositionRange { return posrange.PositionRange{} } - -func (r RemoteExecution) Type() parser.ValueType { return r.valueType } +func (r RemoteExecution) Type() NodeType { return RemoteExecutionNode } -func (r RemoteExecution) PromQLExpr() {} +func (r RemoteExecution) ReturnType() parser.ValueType { return r.valueType } // Deduplicate is a logical plan which deduplicates samples from multiple RemoteExecutions. type Deduplicate struct { + LeafNode Expressions RemoteExecutions } +func (r Deduplicate) Clone() Node { + clone := r + clone.Expressions = make(RemoteExecutions, len(r.Expressions)) + for i, e := range r.Expressions { + clone.Expressions[i] = e.Clone().(RemoteExecution) + } + return clone +} + func (r Deduplicate) String() string { return fmt.Sprintf("dedup(%s)", r.Expressions.String()) } -func (r Deduplicate) Pretty(level int) string { return r.String() } +func (r Deduplicate) ReturnType() parser.ValueType { return r.Expressions[0].ReturnType() } -func (r Deduplicate) PositionRange() posrange.PositionRange { return posrange.PositionRange{} } +func (r Deduplicate) Type() NodeType { return DeduplicateNode } -func (r Deduplicate) Type() parser.ValueType { return r.Expressions[0].Type() } - -func (r Deduplicate) PromQLExpr() {} +type Noop struct { + LeafNode +} -type Noop struct{} +func (r Noop) Clone() Node { return r } func (r Noop) String() string { return "noop" } -func (r Noop) Pretty(level int) string { return r.String() } - -func (r Noop) PositionRange() posrange.PositionRange { return posrange.PositionRange{} } +func (r Noop) ReturnType() parser.ValueType { return parser.ValueTypeVector } -func (r Noop) Type() parser.ValueType { return parser.ValueTypeVector } - -func (r Noop) PromQLExpr() {} +func (r Noop) Type() NodeType { return NoopNode } // distributiveAggregations are all PromQL aggregations which support // distributed execution. @@ -150,7 +158,7 @@ type DistributedExecutionOptimizer struct { SkipBinaryPushdown bool } -func (m DistributedExecutionOptimizer) Optimize(plan parser.Expr, opts *query.Options) (parser.Expr, annotations.Annotations) { +func (m DistributedExecutionOptimizer) Optimize(plan Node, opts *query.Options) (Node, annotations.Annotations) { engines := m.Endpoints.Engines() sort.Slice(engines, func(i, j int) bool { return engines[i].MinT() < engines[j].MinT() @@ -176,12 +184,12 @@ func (m DistributedExecutionOptimizer) Optimize(plan parser.Expr, opts *query.Op } // TODO(fpetkovski): Consider changing TraverseBottomUp to pass in a list of parents in the transform function. - parents := make(map[*parser.Expr]*parser.Expr) - TraverseBottomUp(nil, &plan, func(parent, current *parser.Expr) (stop bool) { + parents := make(map[*Node]*Node) + TraverseBottomUp(nil, &plan, func(parent, current *Node) (stop bool) { parents[current] = parent return false }) - TraverseBottomUp(nil, &plan, func(parent, current *parser.Expr) (stop bool) { + TraverseBottomUp(nil, &plan, func(parent, current *Node) (stop bool) { // If the current operation is not distributive, stop the traversal. if !isDistributive(current, m.SkipBinaryPushdown) { return true @@ -189,7 +197,7 @@ func (m DistributedExecutionOptimizer) Optimize(plan parser.Expr, opts *query.Op // If the current node is an aggregation, distribute the operation and // stop the traversal. - if aggr, ok := (*current).(*parser.AggregateExpr); ok { + if aggr, ok := (*current).(*Aggregation); ok { localAggregation := aggr.Op if aggr.Op == parser.COUNT { localAggregation = parser.SUM @@ -197,13 +205,12 @@ func (m DistributedExecutionOptimizer) Optimize(plan parser.Expr, opts *query.Op remoteAggregation := newRemoteAggregation(aggr, engines) subQueries := m.distributeQuery(&remoteAggregation, engines, m.subqueryOpts(parents, current, opts), minEngineOverlap) - *current = &parser.AggregateExpr{ + *current = &Aggregation{ Op: localAggregation, Expr: subQueries, Param: aggr.Param, Grouping: aggr.Grouping, Without: aggr.Without, - PosRange: aggr.PosRange, } return true } @@ -224,20 +231,25 @@ func (m DistributedExecutionOptimizer) Optimize(plan parser.Expr, opts *query.Op return plan, nil } -func (m DistributedExecutionOptimizer) subqueryOpts(parents map[*parser.Expr]*parser.Expr, current *parser.Expr, opts *query.Options) *query.Options { - subqueryParents := make([]*parser.SubqueryExpr, 0, len(parents)) +func (m DistributedExecutionOptimizer) subqueryOpts(parents map[*Node]*Node, current *Node, opts *query.Options) *query.Options { + subqueryParents := make([]*Subquery, 0, len(parents)) for p := parents[current]; p != nil; p = parents[p] { - if subquery, ok := (*p).(*parser.SubqueryExpr); ok { + if subquery, ok := (*p).(*Subquery); ok { subqueryParents = append(subqueryParents, subquery) } } for i := len(subqueryParents) - 1; i >= 0; i-- { - opts = query.NestedOptionsForSubquery(opts, subqueryParents[i]) + opts = query.NestedOptionsForSubquery( + opts, + subqueryParents[i].Step, + subqueryParents[i].Range, + subqueryParents[i].Offset, + ) } return opts } -func newRemoteAggregation(rootAggregation *parser.AggregateExpr, engines []api.RemoteEngine) parser.Expr { +func newRemoteAggregation(rootAggregation *Aggregation, engines []api.RemoteEngine) Node { groupingSet := make(map[string]struct{}) for _, lbl := range rootAggregation.Grouping { groupingSet[lbl] = struct{}{} @@ -269,7 +281,7 @@ func newRemoteAggregation(rootAggregation *parser.AggregateExpr, engines []api.R // distributeQuery takes a PromQL expression in the form of *parser.Expr and a set of remote engines. // For each engine which matches the time range of the query, it creates a RemoteExecution scoped to the range of the engine. // All remote executions are wrapped in a Deduplicate logical node to make sure that results from overlapping engines are deduplicated. -func (m DistributedExecutionOptimizer) distributeQuery(expr *parser.Expr, engines []api.RemoteEngine, opts *query.Options, allowedStartOffset time.Duration) parser.Expr { +func (m DistributedExecutionOptimizer) distributeQuery(expr *Node, engines []api.RemoteEngine, opts *query.Options, allowedStartOffset time.Duration) Node { startOffset := calculateStartOffset(expr, opts.LookbackDelta) if allowedStartOffset < startOffset { return *expr @@ -304,9 +316,9 @@ func (m DistributedExecutionOptimizer) distributeQuery(expr *parser.Expr, engine remoteQueries = append(remoteQueries, RemoteExecution{ Engine: e, - Query: *expr, + Query: (*expr).Clone(), QueryRangeStart: start, - valueType: (*expr).Type(), + valueType: (*expr).ReturnType(), }) } @@ -319,7 +331,7 @@ func (m DistributedExecutionOptimizer) distributeQuery(expr *parser.Expr, engine } } -func (m DistributedExecutionOptimizer) distributeAbsent(expr parser.Expr, engines []api.RemoteEngine, startOffset time.Duration, opts *query.Options) parser.Expr { +func (m DistributedExecutionOptimizer) distributeAbsent(expr Node, engines []api.RemoteEngine, startOffset time.Duration, opts *query.Options) Node { queries := make(RemoteExecutions, 0, len(engines)) for i, e := range engines { if e.MaxT() < opts.Start.UnixMilli()-startOffset.Milliseconds() { @@ -330,9 +342,9 @@ func (m DistributedExecutionOptimizer) distributeAbsent(expr parser.Expr, engine } queries = append(queries, RemoteExecution{ Engine: engines[i], - Query: expr, + Query: expr.Clone(), QueryRangeStart: opts.Start, - valueType: expr.Type(), + valueType: expr.ReturnType(), }) } // We need to make sure that absent is at least evaluated against one engine. @@ -344,13 +356,13 @@ func (m DistributedExecutionOptimizer) distributeAbsent(expr parser.Expr, engine Engine: engines[len(engines)-1], Query: expr, QueryRangeStart: opts.Start, - valueType: expr.Type(), + valueType: expr.ReturnType(), } } - var rootExpr parser.Expr = queries[0] + var rootExpr Node = queries[0] for i := 1; i < len(queries); i++ { - rootExpr = &parser.BinaryExpr{ + rootExpr = &Binary{ Op: parser.MUL, LHS: rootExpr, RHS: queries[i], @@ -361,8 +373,8 @@ func (m DistributedExecutionOptimizer) distributeAbsent(expr parser.Expr, engine return rootExpr } -func isAbsent(expr parser.Expr) bool { - call, ok := expr.(*parser.Call) +func isAbsent(expr Node) bool { + call, ok := expr.(*FunctionCall) if !ok { return false } @@ -424,16 +436,16 @@ func calculateStepAlignedStart(opts *query.Options, engineMinTime time.Time) tim // 6h can correctly evaluate only the last 5h of the range. // The first 1 hour of data cannot be correctly calculated since the range selector in the engine // will not be able to gather enough points. -func calculateStartOffset(expr *parser.Expr, lookbackDelta time.Duration) time.Duration { +func calculateStartOffset(expr *Node, lookbackDelta time.Duration) time.Duration { if expr == nil { return lookbackDelta } var selectRange time.Duration var offset time.Duration - Traverse(expr, func(node *parser.Expr) { + Traverse(expr, func(node *Node) { switch n := (*node).(type) { - case *parser.SubqueryExpr: + case *Subquery: selectRange += n.Range case *MatrixSelector: selectRange += n.Range @@ -448,15 +460,17 @@ func numSteps(start, end time.Time, step time.Duration) int64 { return (end.UnixMilli()-start.UnixMilli())/step.Milliseconds() + 1 } -func isDistributive(expr *parser.Expr, skipBinaryPushdown bool) bool { +func isDistributive(expr *Node, skipBinaryPushdown bool) bool { if expr == nil { return false } switch e := (*expr).(type) { - case *parser.BinaryExpr: + case Deduplicate, RemoteExecution: + return false + case *Binary: return isBinaryExpressionWithOneConstantSide(e) || (!skipBinaryPushdown && isBinaryExpressionWithDistributableMatching(e)) - case *parser.AggregateExpr: + case *Aggregation: // Certain aggregations are currently not supported. if _, ok := distributiveAggregations[e.Op]; !ok { return false @@ -466,13 +480,13 @@ func isDistributive(expr *parser.Expr, skipBinaryPushdown bool) bool { return true } -func isBinaryExpressionWithOneConstantSide(expr *parser.BinaryExpr) bool { +func isBinaryExpressionWithOneConstantSide(expr *Binary) bool { lhsConstant := IsConstantExpr(expr.LHS) rhsConstant := IsConstantExpr(expr.RHS) - return (lhsConstant || rhsConstant) + return lhsConstant || rhsConstant } -func isBinaryExpressionWithDistributableMatching(expr *parser.BinaryExpr) bool { +func isBinaryExpressionWithDistributableMatching(expr *Binary) bool { if expr.VectorMatching == nil { return false } @@ -483,12 +497,12 @@ func isBinaryExpressionWithDistributableMatching(expr *parser.BinaryExpr) bool { } // matchesExternalLabels returns false if given matchers are not matching external labels. -func matchesExternalLabelSet(expr parser.Expr, externalLabelSet []labels.Labels) bool { +func matchesExternalLabelSet(expr Node, externalLabelSet []labels.Labels) bool { if len(externalLabelSet) == 0 { return true } var selectorSet [][]*labels.Matcher - Traverse(&expr, func(current *parser.Expr) { + Traverse(&expr, func(current *Node) { vs, ok := (*current).(*VectorSelector) if ok { selectorSet = append(selectorSet, vs.LabelMatchers) @@ -523,10 +537,10 @@ func matchesExternalLabels(ms []*labels.Matcher, externalLabels labels.Labels) b return true } -func rewritesEngineLabels(e parser.Expr, engineLabels map[string]struct{}) bool { +func rewritesEngineLabels(e Node, engineLabels map[string]struct{}) bool { var result bool - TraverseBottomUp(nil, &e, func(parent *parser.Expr, node *parser.Expr) bool { - call, ok := (*node).(*parser.Call) + TraverseBottomUp(nil, &e, func(parent *Node, node *Node) bool { + call, ok := (*node).(*FunctionCall) if !ok || call.Func.Name != "label_replace" { return false } diff --git a/vendor/github.com/thanos-io/promql-engine/logicalplan/distribute_avg.go b/vendor/github.com/thanos-io/promql-engine/logicalplan/distribute_avg.go index a98f5284ff..4c9f7c6afc 100644 --- a/vendor/github.com/thanos-io/promql-engine/logicalplan/distribute_avg.go +++ b/vendor/github.com/thanos-io/promql-engine/logicalplan/distribute_avg.go @@ -16,23 +16,23 @@ type DistributeAvgOptimizer struct { SkipBinaryPushdown bool } -func (r DistributeAvgOptimizer) Optimize(plan parser.Expr, _ *query.Options) (parser.Expr, annotations.Annotations) { - TraverseBottomUp(nil, &plan, func(parent, current *parser.Expr) (stop bool) { +func (r DistributeAvgOptimizer) Optimize(plan Node, _ *query.Options) (Node, annotations.Annotations) { + TraverseBottomUp(nil, &plan, func(parent, current *Node) (stop bool) { if !isDistributiveOrAverage(current, r.SkipBinaryPushdown) { return true } // If the current node is avg(), distribute the operation and // stop the traversal. - if aggr, ok := (*current).(*parser.AggregateExpr); ok { + if aggr, ok := (*current).(*Aggregation); ok { if aggr.Op != parser.AVG { return true } - sum := *(*current).(*parser.AggregateExpr) + sum := *(*current).(*Aggregation) sum.Op = parser.SUM - count := *(*current).(*parser.AggregateExpr) + count := *(*current).(*Aggregation) count.Op = parser.COUNT - *current = &parser.BinaryExpr{ + *current = &Binary{ Op: parser.DIV, LHS: &sum, RHS: &count, @@ -49,12 +49,12 @@ func (r DistributeAvgOptimizer) Optimize(plan parser.Expr, _ *query.Options) (pa return plan, nil } -func isDistributiveOrAverage(expr *parser.Expr, skipBinaryPushdown bool) bool { +func isDistributiveOrAverage(expr *Node, skipBinaryPushdown bool) bool { if expr == nil { return false } var isAvg bool - if aggr, ok := (*expr).(*parser.AggregateExpr); ok { + if aggr, ok := (*expr).(*Aggregation); ok { isAvg = aggr.Op == parser.AVG } return isDistributive(expr, skipBinaryPushdown) || isAvg diff --git a/vendor/github.com/thanos-io/promql-engine/logicalplan/exprutil.go b/vendor/github.com/thanos-io/promql-engine/logicalplan/exprutil.go index a86feabaf3..4cd3f1b73b 100644 --- a/vendor/github.com/thanos-io/promql-engine/logicalplan/exprutil.go +++ b/vendor/github.com/thanos-io/promql-engine/logicalplan/exprutil.go @@ -9,11 +9,11 @@ import ( ) // UnwrapString recursively unwraps a parser.Expr until it reaches an StringLiteral. -func UnwrapString(expr parser.Expr) (string, error) { +func UnwrapString(expr Node) (string, error) { switch texpr := expr.(type) { case *StringLiteral: return texpr.Val, nil - case *parser.ParenExpr: + case *Parens: return UnwrapString(texpr.Expr) case *StepInvariantExpr: return UnwrapString(texpr.Expr) @@ -24,17 +24,17 @@ func UnwrapString(expr parser.Expr) (string, error) { // UnsafeUnwrapString is like UnwrapString but should only be used in cases where the parser // guarantees success by already only allowing strings wrapped in parentheses. -func UnsafeUnwrapString(expr parser.Expr) string { +func UnsafeUnwrapString(expr Node) string { v, _ := UnwrapString(expr) return v } // UnwrapFloat recursively unwraps a parser.Expr until it reaches an NumberLiteral. -func UnwrapFloat(expr parser.Expr) (float64, error) { +func UnwrapFloat(expr Node) (float64, error) { switch texpr := expr.(type) { case *NumberLiteral: return texpr.Val, nil - case *parser.ParenExpr: + case *Parens: return UnwrapFloat(texpr.Expr) case *StepInvariantExpr: return UnwrapFloat(texpr.Expr) @@ -54,22 +54,22 @@ func UnwrapParens(expr parser.Expr) parser.Expr { } // IsConstantExpr reports if the expression evaluates to a constant. -func IsConstantExpr(expr parser.Expr) bool { +func IsConstantExpr(expr Node) bool { // TODO: there are more possibilities for constant expressions switch texpr := expr.(type) { case *NumberLiteral, *StringLiteral: return true case *StepInvariantExpr: return IsConstantExpr(texpr.Expr) - case *parser.ParenExpr: + case *Parens: return IsConstantExpr(texpr.Expr) - case *parser.Call: + case *FunctionCall: constArgs := true for _, arg := range texpr.Args { constArgs = constArgs && IsConstantExpr(arg) } return constArgs - case *parser.BinaryExpr: + case *Binary: return IsConstantExpr(texpr.LHS) && IsConstantExpr(texpr.RHS) default: return false diff --git a/vendor/github.com/thanos-io/promql-engine/logicalplan/logical_nodes.go b/vendor/github.com/thanos-io/promql-engine/logicalplan/logical_nodes.go index b8f8884c4d..40acd97610 100644 --- a/vendor/github.com/thanos-io/promql-engine/logicalplan/logical_nodes.go +++ b/vendor/github.com/thanos-io/promql-engine/logicalplan/logical_nodes.go @@ -5,13 +5,57 @@ package logicalplan import ( "fmt" + "strings" "time" + "github.com/prometheus/common/model" "github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/promql/parser" - "github.com/prometheus/prometheus/promql/parser/posrange" ) +type NodeType string + +const ( + VectorSelectorNode = "vector_selector" + MatrixSelectorNode = "matrix_selector" + AggregationNode = "aggregation" + BinaryNode = "binary" + FunctionNode = "function" + NumberLiteralNode = "number_literal" + StringLiteralNode = "string_literal" + SubqueryNode = "subquery" + CheckDuplicateNode = "check_duplicate" + StepInvariantNode = "step_invariant" + ParensNode = "parens" + UnaryNode = "unary" + + RemoteExecutionNode = "remote_exec" + DeduplicateNode = "dedup" + NoopNode = "noop" +) + +type Cloneable interface { + Clone() Node +} + +type Traversable interface { + Children() []*Node +} + +type LeafNode struct{} + +func (l LeafNode) Children() []*Node { return nil } + +type Node interface { + fmt.Stringer + Cloneable + Traversable + Type() NodeType + ReturnType() parser.ValueType +} + +type Nodes []Node + // Projection has information on which series labels should be selected from storage. type Projection struct { // Labels is a list of labels to be included or excluded from the selection result, depending on the value of Include. @@ -24,13 +68,33 @@ type Projection struct { // VectorSelector is vector selector with additional configuration set by optimizers. type VectorSelector struct { *parser.VectorSelector + LeafNode Filters []*labels.Matcher BatchSize int64 SelectTimestamp bool Projection Projection } -func (f VectorSelector) String() string { +func (f *VectorSelector) Clone() Node { + clone := *f + vsClone := *f.VectorSelector + clone.VectorSelector = &vsClone + + clone.Filters = shallowCloneSlice(f.Filters) + clone.LabelMatchers = shallowCloneSlice(f.LabelMatchers) + clone.Projection.Labels = shallowCloneSlice(f.Projection.Labels) + + if f.VectorSelector.Timestamp != nil { + ts := *f.VectorSelector.Timestamp + clone.Timestamp = &ts + } + + return &clone +} + +func (f *VectorSelector) Type() NodeType { return VectorSelectorNode } + +func (f *VectorSelector) String() string { if f.SelectTimestamp { // If we pushed down timestamp into the vector selector we need to render the proper // PromQL again. @@ -39,101 +103,337 @@ func (f VectorSelector) String() string { return f.VectorSelector.String() } -func (f VectorSelector) Pretty(level int) string { return f.String() } - -func (f VectorSelector) PositionRange() posrange.PositionRange { return posrange.PositionRange{} } - -func (f VectorSelector) Type() parser.ValueType { return parser.ValueTypeVector } - -func (f VectorSelector) PromQLExpr() {} +func (f *VectorSelector) ReturnType() parser.ValueType { return parser.ValueTypeVector } // MatrixSelector is matrix selector with additional configuration set by optimizers. // It is used so we can get rid of VectorSelector in distributed mode too. type MatrixSelector struct { - VectorSelector parser.Expr + VectorSelector *VectorSelector `json:"-"` Range time.Duration // Needed because this operator is used in the distributed mode OriginalString string } -func (f MatrixSelector) String() string { - return f.OriginalString +func (f *MatrixSelector) Clone() Node { + clone := *f + clone.VectorSelector = f.VectorSelector.Clone().(*VectorSelector) + return &clone } -func (f MatrixSelector) Pretty(level int) string { return f.String() } +func (f *MatrixSelector) Children() []*Node { + var vs Node = f.VectorSelector + return []*Node{&vs} +} -func (f MatrixSelector) PositionRange() posrange.PositionRange { return posrange.PositionRange{} } +func (f *MatrixSelector) String() string { + return f.OriginalString +} -func (f MatrixSelector) Type() parser.ValueType { return parser.ValueTypeVector } +func (f *MatrixSelector) ReturnType() parser.ValueType { return parser.ValueTypeVector } -func (f MatrixSelector) PromQLExpr() {} +func (f *MatrixSelector) Type() NodeType { return MatrixSelectorNode } // CheckDuplicateLabels is a logical node that checks for duplicate labels in the same timestamp. type CheckDuplicateLabels struct { - Expr parser.Expr + Expr Node `json:"-"` } -func (c CheckDuplicateLabels) String() string { - return c.Expr.String() +func (c *CheckDuplicateLabels) Clone() Node { + clone := *c + clone.Expr = c.Expr.Clone() + return &clone } -func (c CheckDuplicateLabels) Pretty(level int) string { return c.Expr.Pretty(level) } - -func (c CheckDuplicateLabels) PositionRange() posrange.PositionRange { return c.Expr.PositionRange() } - -func (c CheckDuplicateLabels) Type() parser.ValueType { return c.Expr.Type() } - -func (c CheckDuplicateLabels) PromQLExpr() {} +func (c *CheckDuplicateLabels) Children() []*Node { return []*Node{&c.Expr} } +func (c *CheckDuplicateLabels) String() string { return c.Expr.String() } +func (c *CheckDuplicateLabels) ReturnType() parser.ValueType { return c.Expr.ReturnType() } +func (c *CheckDuplicateLabels) Type() NodeType { return CheckDuplicateNode } // StringLiteral is a logical node representing a literal string. type StringLiteral struct { + LeafNode Val string } -func (c StringLiteral) String() string { - return fmt.Sprintf("%q", c.Val) +func (c *StringLiteral) Clone() Node { return &StringLiteral{Val: c.Val} } +func (c *StringLiteral) String() string { return fmt.Sprintf("%q", c.Val) } +func (c *StringLiteral) ReturnType() parser.ValueType { return parser.ValueTypeString } +func (c *StringLiteral) Type() NodeType { return StringLiteralNode } + +// NumberLiteral is a logical node representing a literal number. +type NumberLiteral struct { + LeafNode + Val float64 } -func (c StringLiteral) Pretty(level int) string { return c.String() } +func (c *NumberLiteral) Clone() Node { return &NumberLiteral{Val: c.Val} } +func (c *NumberLiteral) String() string { return fmt.Sprint(c.Val) } +func (c *NumberLiteral) ReturnType() parser.ValueType { return parser.ValueTypeScalar } +func (c *NumberLiteral) Type() NodeType { return NumberLiteralNode } -func (c StringLiteral) PositionRange() posrange.PositionRange { return posrange.PositionRange{} } +// StepInvariantExpr is a logical node that expresses that the child expression +// returns the same value at every step in the evaluation. +type StepInvariantExpr struct { + Expr Node `json:"-"` +} -func (c StringLiteral) Type() parser.ValueType { return parser.ValueTypeString } +func (c *StepInvariantExpr) Clone() Node { + clone := *c + clone.Expr = c.Expr.Clone() + return &clone +} -func (c StringLiteral) PromQLExpr() {} +func (c *StepInvariantExpr) Children() []*Node { return []*Node{&c.Expr} } +func (c *StepInvariantExpr) String() string { return c.Expr.String() } +func (c *StepInvariantExpr) ReturnType() parser.ValueType { return c.Expr.ReturnType() } +func (c *StepInvariantExpr) Type() NodeType { return StepInvariantNode } + +// FunctionCall represents a PromQL function. +type FunctionCall struct { + // The function that was called. + Func parser.Function + // Arguments passed into the function. + Args []Node `json:"-"` +} -// NumberLiteral is a logical node representing a literal number. -type NumberLiteral struct { - Val float64 +func (f *FunctionCall) Clone() Node { + clone := *f + clone.Args = make([]Node, 0, len(f.Args)) + for _, arg := range f.Args { + clone.Args = append(clone.Args, arg.Clone()) + } + return &clone } -func (c NumberLiteral) String() string { - return fmt.Sprint(c.Val) +func (f *FunctionCall) Children() []*Node { + args := make([]*Node, 0, len(f.Args)) + for i := range f.Args { + args = append(args, &f.Args[i]) + } + return args } -func (c NumberLiteral) Pretty(level int) string { return c.String() } +func (f *FunctionCall) String() string { + args := make([]string, 0, len(f.Args)) + for _, arg := range f.Args { + args = append(args, arg.String()) + } + return fmt.Sprintf("%s(%s)", f.Func.Name, strings.Join(args, ", ")) +} -func (c NumberLiteral) PositionRange() posrange.PositionRange { return posrange.PositionRange{} } +func (f *FunctionCall) ReturnType() parser.ValueType { return f.Func.ReturnType } +func (f *FunctionCall) Type() NodeType { return FunctionNode } -func (c NumberLiteral) Type() parser.ValueType { return parser.ValueTypeScalar } +type Parens struct { + Expr Node `json:"-"` +} -func (c NumberLiteral) PromQLExpr() {} +func (p *Parens) Clone() Node { return &Parens{Expr: p.Expr.Clone()} } +func (p *Parens) Children() []*Node { return []*Node{&p.Expr} } +func (p *Parens) String() string { return fmt.Sprintf("(%s)", p.Expr.String()) } +func (p *Parens) ReturnType() parser.ValueType { return p.Expr.ReturnType() } +func (p *Parens) Type() NodeType { return ParensNode } -// StepInvariantExpr is a logical node that expresses that the child expression -// returns the same value at every step in the evaluation. -type StepInvariantExpr struct { - Expr parser.Expr +type Unary struct { + Op parser.ItemType + Expr Node `json:"-"` } -func (c StepInvariantExpr) String() string { return c.Expr.String() } +func (p *Unary) Clone() Node { return &Unary{Op: p.Op, Expr: p.Expr.Clone()} } +func (p *Unary) Children() []*Node { return []*Node{&p.Expr} } +func (p *Unary) String() string { return fmt.Sprintf("%s%s", p.Op.String(), p.Expr.String()) } +func (p *Unary) ReturnType() parser.ValueType { return p.Expr.ReturnType() } +func (p *Unary) Type() NodeType { return UnaryNode } + +// Aggregation represents a PromQL aggregation. +type Aggregation struct { + Op parser.ItemType + Expr Node `json:"-"` + Param Node `json:"-"` + Grouping []string + Without bool +} -func (c StepInvariantExpr) Pretty(level int) string { return c.String() } +func (f *Aggregation) Clone() Node { + clone := *f + clone.Expr = f.Expr.Clone() + if clone.Param != nil { + clone.Param = f.Param.Clone() + } + clone.Grouping = shallowCloneSlice(f.Grouping) + return &clone +} + +func (f *Aggregation) Children() []*Node { + children := []*Node{&f.Expr} + if f.Param != nil { + children = append(children, &f.Param) + } + return children +} + +func (f *Aggregation) String() string { + aggrString := f.getAggOpStr() + aggrString += "(" + if f.Op.IsAggregatorWithParam() { + aggrString += fmt.Sprintf("%s, ", f.Param) + } + aggrString += fmt.Sprintf("%s)", f.Expr) + + return aggrString +} + +func (f *Aggregation) ReturnType() parser.ValueType { return parser.ValueTypeVector } +func (f *Aggregation) Type() NodeType { return AggregationNode } + +func (f *Aggregation) getAggOpStr() string { + aggrString := f.Op.String() + + switch { + case f.Without: + aggrString += fmt.Sprintf(" without (%s) ", strings.Join(f.Grouping, ", ")) + case len(f.Grouping) > 0: + aggrString += fmt.Sprintf(" by (%s) ", strings.Join(f.Grouping, ", ")) + } + + return aggrString +} + +type Binary struct { + Op parser.ItemType // The operation of the expression. + LHS, RHS Node `json:"-"` // The operands on the respective sides of the operator. + + // The matching behavior for the operation if both operands are Vectors. + // If they are not this field is nil. + VectorMatching *parser.VectorMatching + + // If a comparison operator, return 0/1 rather than filtering. + ReturnBool bool + + ValueType parser.ValueType +} + +func (b *Binary) Clone() Node { + clone := *b + clone.LHS = b.LHS.Clone() + clone.RHS = b.RHS.Clone() + if b.VectorMatching != nil { + vm := *b.VectorMatching + clone.VectorMatching = &vm + } + return &clone +} + +func (b *Binary) Children() []*Node { return []*Node{&b.LHS, &b.RHS} } + +func (b *Binary) ReturnType() parser.ValueType { + if b.LHS.ReturnType() == parser.ValueTypeScalar && b.RHS.ReturnType() == parser.ValueTypeScalar { + return parser.ValueTypeScalar + } + return parser.ValueTypeVector +} + +func (b *Binary) Type() NodeType { return BinaryNode } + +func (b *Binary) String() string { + returnBool := "" + if b.ReturnBool { + returnBool = " bool" + } -func (c StepInvariantExpr) PositionRange() posrange.PositionRange { - return c.Expr.PositionRange() + matching := b.getMatchingStr() + return fmt.Sprintf("%s %s%s%s %s", b.LHS, b.Op, returnBool, matching, b.RHS) +} + +func (b *Binary) getMatchingStr() string { + matching := "" + vm := b.VectorMatching + if vm != nil && (len(vm.MatchingLabels) > 0 || vm.On) { + vmTag := "ignoring" + if vm.On { + vmTag = "on" + } + matching = fmt.Sprintf(" %s (%s)", vmTag, strings.Join(vm.MatchingLabels, ", ")) + + if vm.Card == parser.CardManyToOne || vm.Card == parser.CardOneToMany { + vmCard := "right" + if vm.Card == parser.CardManyToOne { + vmCard = "left" + } + matching += fmt.Sprintf(" group_%s (%s)", vmCard, strings.Join(vm.Include, ", ")) + } + } + return matching } -func (c StepInvariantExpr) Type() parser.ValueType { return c.Expr.Type() } +type Subquery struct { + Expr Node `json:"-"` + Range time.Duration + // OriginalOffset is the actual offset that was set in the query. + // This never changes. + OriginalOffset time.Duration + // Offset is the offset used during the query execution + // which is calculated using the original offset, at modifier time, + // eval time, and subquery offsets in the AST tree. + Offset time.Duration + Timestamp *int64 + Step time.Duration + + StartOrEnd parser.ItemType +} + +func (s *Subquery) Clone() Node { + clone := *s + clone.Expr = s.Expr.Clone() + + if s.Timestamp != nil { + ts := *s.Timestamp + clone.Timestamp = &ts + } + + return &clone +} -func (c StepInvariantExpr) PromQLExpr() {} +func (s *Subquery) Children() []*Node { return []*Node{&s.Expr} } + +func (s *Subquery) String() string { + return fmt.Sprintf("%s%s", s.Expr.String(), s.getSubqueryTimeSuffix()) +} + +func (s *Subquery) ReturnType() parser.ValueType { return s.Expr.ReturnType() } + +func (s *Subquery) Type() NodeType { return SubqueryNode } + +func (s *Subquery) getSubqueryTimeSuffix() any { + step := "" + if s.Step != 0 { + step = model.Duration(s.Step).String() + } + offset := "" + switch { + case s.OriginalOffset > time.Duration(0): + offset = fmt.Sprintf(" offset %s", model.Duration(s.OriginalOffset)) + case s.OriginalOffset < time.Duration(0): + offset = fmt.Sprintf(" offset -%s", model.Duration(-s.OriginalOffset)) + } + at := "" + switch { + case s.Timestamp != nil: + at = fmt.Sprintf(" @ %.3f", float64(*s.Timestamp)/1000.0) + case s.StartOrEnd == parser.START: + at = " @ start()" + case s.StartOrEnd == parser.END: + at = " @ end()" + } + return fmt.Sprintf("[%s:%s]%s%s", model.Duration(s.Range), step, at, offset) +} + +func shallowCloneSlice[T any](s []T) []T { + if s == nil { + return nil + } + clone := make([]T, len(s)) + copy(clone, s) + return clone +} diff --git a/vendor/github.com/thanos-io/promql-engine/logicalplan/merge_selects.go b/vendor/github.com/thanos-io/promql-engine/logicalplan/merge_selects.go index 72105343a0..1db8148bbc 100644 --- a/vendor/github.com/thanos-io/promql-engine/logicalplan/merge_selects.go +++ b/vendor/github.com/thanos-io/promql-engine/logicalplan/merge_selects.go @@ -7,8 +7,6 @@ import ( "github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/util/annotations" - "github.com/prometheus/prometheus/promql/parser" - "github.com/thanos-io/promql-engine/query" ) @@ -23,7 +21,7 @@ import ( // and apply an additional filter for {c="d"}. type MergeSelectsOptimizer struct{} -func (m MergeSelectsOptimizer) Optimize(plan parser.Expr, _ *query.Options) (parser.Expr, annotations.Annotations) { +func (m MergeSelectsOptimizer) Optimize(plan Node, _ *query.Options) (Node, annotations.Annotations) { heap := make(matcherHeap) extractSelectors(heap, plan) replaceMatchers(heap, &plan) @@ -31,8 +29,8 @@ func (m MergeSelectsOptimizer) Optimize(plan parser.Expr, _ *query.Options) (par return plan, nil } -func extractSelectors(selectors matcherHeap, expr parser.Expr) { - Traverse(&expr, func(node *parser.Expr) { +func extractSelectors(selectors matcherHeap, expr Node) { + Traverse(&expr, func(node *Node) { e, ok := (*node).(*VectorSelector) if !ok { return @@ -45,8 +43,8 @@ func extractSelectors(selectors matcherHeap, expr parser.Expr) { }) } -func replaceMatchers(selectors matcherHeap, expr *parser.Expr) { - Traverse(expr, func(node *parser.Expr) { +func replaceMatchers(selectors matcherHeap, expr *Node) { + Traverse(expr, func(node *Node) { var matchers []*labels.Matcher switch e := (*node).(type) { case *VectorSelector: diff --git a/vendor/github.com/thanos-io/promql-engine/logicalplan/passthrough.go b/vendor/github.com/thanos-io/promql-engine/logicalplan/passthrough.go index 195dec271c..489092dde7 100644 --- a/vendor/github.com/thanos-io/promql-engine/logicalplan/passthrough.go +++ b/vendor/github.com/thanos-io/promql-engine/logicalplan/passthrough.go @@ -7,8 +7,6 @@ import ( "github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/util/annotations" - "github.com/prometheus/prometheus/promql/parser" - "github.com/thanos-io/promql-engine/api" "github.com/thanos-io/promql-engine/query" ) @@ -44,7 +42,7 @@ func matchingEngineTime(e api.RemoteEngine, opts *query.Options) bool { return !(opts.Start.UnixMilli() > e.MaxT() || opts.End.UnixMilli() < e.MinT()) } -func (m PassthroughOptimizer) Optimize(plan parser.Expr, opts *query.Options) (parser.Expr, annotations.Annotations) { +func (m PassthroughOptimizer) Optimize(plan Node, opts *query.Options) (Node, annotations.Annotations) { engines := m.Endpoints.Engines() if len(engines) == 1 { if !matchingEngineTime(engines[0], opts) { @@ -52,7 +50,7 @@ func (m PassthroughOptimizer) Optimize(plan parser.Expr, opts *query.Options) (p } return RemoteExecution{ Engine: engines[0], - Query: plan, + Query: plan.Clone(), QueryRangeStart: opts.Start, }, nil } @@ -62,7 +60,7 @@ func (m PassthroughOptimizer) Optimize(plan parser.Expr, opts *query.Options) (p } matchingLabelsEngines := make([]api.RemoteEngine, 0, len(engines)) - TraverseBottomUp(nil, &plan, func(parent, current *parser.Expr) (stop bool) { + TraverseBottomUp(nil, &plan, func(parent, current *Node) (stop bool) { if vs, ok := (*current).(*VectorSelector); ok { for _, e := range engines { if !labelSetsMatch(vs.LabelMatchers, e.LabelSets()...) { @@ -78,7 +76,7 @@ func (m PassthroughOptimizer) Optimize(plan parser.Expr, opts *query.Options) (p if len(matchingLabelsEngines) == 1 && matchingEngineTime(matchingLabelsEngines[0], opts) { return RemoteExecution{ Engine: matchingLabelsEngines[0], - Query: plan, + Query: plan.Clone(), QueryRangeStart: opts.Start, }, nil } diff --git a/vendor/github.com/thanos-io/promql-engine/logicalplan/plan.go b/vendor/github.com/thanos-io/promql-engine/logicalplan/plan.go index a610f12a36..5b15924db4 100644 --- a/vendor/github.com/thanos-io/promql-engine/logicalplan/plan.go +++ b/vendor/github.com/thanos-io/promql-engine/logicalplan/plan.go @@ -4,12 +4,10 @@ package logicalplan import ( - "fmt" "math" "strings" "time" - "github.com/prometheus/prometheus/model/timestamp" "github.com/prometheus/prometheus/promql" "github.com/prometheus/prometheus/promql/parser" "github.com/prometheus/prometheus/util/annotations" @@ -29,15 +27,15 @@ var DefaultOptimizers = []Optimizer{ type Plan interface { Optimize([]Optimizer) (Plan, annotations.Annotations) - Expr() parser.Expr + Root() Node } type Optimizer interface { - Optimize(plan parser.Expr, opts *query.Options) (parser.Expr, annotations.Annotations) + Optimize(plan Node, opts *query.Options) (Node, annotations.Annotations) } type plan struct { - expr parser.Expr + expr Node opts *query.Options planOpts PlanOptions } @@ -46,16 +44,25 @@ type PlanOptions struct { DisableDuplicateLabelCheck bool } -func New(expr parser.Expr, queryOpts *query.Options, planOpts PlanOptions) Plan { - expr = preprocessExpr(expr, queryOpts.Start, queryOpts.End) - setOffsetForAtModifier(queryOpts.Start.UnixMilli(), expr) - setOffsetForInnerSubqueries(expr, queryOpts) +// New creates a new logical plan from logical node. +func New(root Node, queryOpts *query.Options, planOpts PlanOptions) Plan { + return &plan{ + expr: root, + opts: queryOpts, + planOpts: planOpts, + } +} - // the engine handles sorting at the presentation layer - expr = trimSorts(expr) +func NewFromAST(ast parser.Expr, queryOpts *query.Options, planOpts PlanOptions) Plan { + ast = promql.PreprocessExpr(ast, queryOpts.Start, queryOpts.End) + setOffsetForAtModifier(queryOpts.Start.UnixMilli(), ast) + setOffsetForInnerSubqueries(ast, queryOpts) // replace scanners by our logical nodes - expr = replacePrometheusNodes(expr) + expr := replacePrometheusNodes(ast) + + // the engine handles sorting at the presentation layer + expr = trimSorts(expr) return &plan{ expr: expr, @@ -64,6 +71,23 @@ func New(expr parser.Expr, queryOpts *query.Options, planOpts PlanOptions) Plan } } +// NewFromBytes creates a new logical plan from a byte slice created with Marshal. +// This method is used to deserialize a logical plan which has been sent over the wire. +func NewFromBytes(bytes []byte, queryOpts *query.Options, planOpts PlanOptions) (Plan, error) { + root, err := Unmarshal(bytes) + if err != nil { + return nil, err + } + // the engine handles sorting at the presentation layer + root = trimSorts(root) + + return &plan{ + expr: root, + opts: queryOpts, + planOpts: planOpts, + }, nil +} + func (p *plan) Optimize(optimizers []Optimizer) (Plan, annotations.Annotations) { annos := annotations.New() for _, o := range optimizers { @@ -83,134 +107,30 @@ func (p *plan) Optimize(optimizers []Optimizer) (Plan, annotations.Annotations) return &plan{expr: expr, opts: p.opts}, *annos } -func (p *plan) Expr() parser.Expr { +func (p *plan) Root() Node { return p.expr } -func Traverse(expr *parser.Expr, transform func(*parser.Expr)) { - switch node := (*expr).(type) { - case *parser.StringLiteral, *parser.NumberLiteral: - transform(expr) - case *parser.StepInvariantExpr: - transform(expr) - Traverse(&node.Expr, transform) - case *StepInvariantExpr: - transform(expr) - Traverse(&node.Expr, transform) - case *parser.VectorSelector: - transform(expr) - case *VectorSelector: - var x parser.Expr = node.VectorSelector - transform(expr) - Traverse(&x, transform) - case *MatrixSelector: - var x parser.Expr = node.VectorSelector - transform(expr) - Traverse(&x, transform) - case *parser.MatrixSelector: - transform(expr) - Traverse(&node.VectorSelector, transform) - case *parser.AggregateExpr: - transform(expr) - Traverse(&node.Param, transform) - Traverse(&node.Expr, transform) - case *parser.Call: - transform(expr) - for i := range node.Args { - Traverse(&(node.Args[i]), transform) - } - case *parser.BinaryExpr: - transform(expr) - Traverse(&node.LHS, transform) - Traverse(&node.RHS, transform) - case *parser.UnaryExpr: - transform(expr) - Traverse(&node.Expr, transform) - case *parser.ParenExpr: - transform(expr) - Traverse(&node.Expr, transform) - case *parser.SubqueryExpr: - transform(expr) - Traverse(&node.Expr, transform) - case CheckDuplicateLabels: - transform(expr) - Traverse(&node.Expr, transform) +func Traverse(expr *Node, transform func(*Node)) { + children := (*expr).Children() + transform(expr) + for _, c := range children { + Traverse(c, transform) } } -func TraverseBottomUp(parent *parser.Expr, current *parser.Expr, transform func(parent *parser.Expr, node *parser.Expr) bool) bool { - switch node := (*current).(type) { - case *parser.StringLiteral, *StringLiteral: - return transform(parent, current) - case *parser.NumberLiteral, *NumberLiteral: - return transform(parent, current) - case *parser.StepInvariantExpr: - if stop := TraverseBottomUp(current, &node.Expr, transform); stop { - return stop - } - return transform(parent, current) - case *StepInvariantExpr: - if stop := TraverseBottomUp(current, &node.Expr, transform); stop { - return stop - } - return transform(parent, current) - case *parser.VectorSelector: - return transform(parent, current) - case *VectorSelector: - if stop := transform(parent, current); stop { - return stop - } - var x parser.Expr = node.VectorSelector - return TraverseBottomUp(current, &x, transform) - case *MatrixSelector: - if stop := transform(parent, current); stop { - return stop - } - var x parser.Expr = node.VectorSelector - return TraverseBottomUp(current, &x, transform) - case *parser.MatrixSelector: - return transform(current, &node.VectorSelector) - case *parser.AggregateExpr: - if stop := TraverseBottomUp(current, &node.Expr, transform); stop { - return stop - } - return transform(parent, current) - case *parser.Call: - for i := range node.Args { - if stop := TraverseBottomUp(current, &node.Args[i], transform); stop { - return stop - } - } - return transform(parent, current) - case *parser.BinaryExpr: - lstop := TraverseBottomUp(current, &node.LHS, transform) - rstop := TraverseBottomUp(current, &node.RHS, transform) - if lstop || rstop { - return true - } - return transform(parent, current) - case *parser.UnaryExpr: - return TraverseBottomUp(current, &node.Expr, transform) - case *parser.ParenExpr: - if stop := TraverseBottomUp(current, &node.Expr, transform); stop { - return stop - } - return transform(parent, current) - case *parser.SubqueryExpr: - if stop := TraverseBottomUp(current, &node.Expr, transform); stop { - return stop - } - return transform(parent, current) - case CheckDuplicateLabels: - if stop := TraverseBottomUp(current, &node.Expr, transform); stop { - return stop - } - return transform(parent, current) +func TraverseBottomUp(parent *Node, current *Node, transform func(parent *Node, node *Node) bool) bool { + var stop bool + for _, c := range (*current).Children() { + stop = TraverseBottomUp(current, c, transform) || stop + } + if stop { + return stop } - return true + return transform(parent, current) } -func replacePrometheusNodes(plan parser.Expr) parser.Expr { +func replacePrometheusNodes(plan parser.Expr) Node { switch t := (plan).(type) { case *parser.StringLiteral: return &StringLiteral{Val: t.Val} @@ -219,11 +139,17 @@ func replacePrometheusNodes(plan parser.Expr) parser.Expr { case *parser.StepInvariantExpr: return &StepInvariantExpr{Expr: replacePrometheusNodes(t.Expr)} case *parser.MatrixSelector: - return &MatrixSelector{VectorSelector: replacePrometheusNodes(t.VectorSelector), Range: t.Range, OriginalString: t.String()} + return &MatrixSelector{ + VectorSelector: &VectorSelector{ + VectorSelector: t.VectorSelector.(*parser.VectorSelector), + }, + Range: t.Range, + OriginalString: t.String(), + } case *parser.VectorSelector: return &VectorSelector{VectorSelector: t} - //TODO: we dont yet have logical nodes for these, keep traversing here but set fields in-place + // TODO: we dont yet have logical nodes for these, keep traversing here but set fields in-place case *parser.Call: if t.Func.Name == "timestamp" { // pushed-down timestamp function @@ -237,47 +163,73 @@ func replacePrometheusNodes(plan parser.Expr) parser.Expr { if vs.Timestamp != nil { vs.OriginalOffset = 0 } - return &VectorSelector{VectorSelector: vs, SelectTimestamp: true} + return &StepInvariantExpr{ + Expr: &VectorSelector{VectorSelector: vs, SelectTimestamp: true}, + } } } } + args := make([]Node, len(t.Args)) // nested timestamp functions for i, arg := range t.Args { - t.Args[i] = replacePrometheusNodes(arg) + args[i] = replacePrometheusNodes(arg) + } + return &FunctionCall{ + Func: *t.Func, + Args: args, } - return t case *parser.ParenExpr: - t.Expr = replacePrometheusNodes(t.Expr) - return t + return &Parens{ + Expr: replacePrometheusNodes(t.Expr), + } case *parser.UnaryExpr: - t.Expr = replacePrometheusNodes(t.Expr) - return t + return &Unary{ + Op: t.Op, + Expr: replacePrometheusNodes(t.Expr), + } case *parser.AggregateExpr: - t.Expr = replacePrometheusNodes(t.Expr) - t.Param = replacePrometheusNodes(t.Param) - return t + return &Aggregation{ + Op: t.Op, + Expr: replacePrometheusNodes(t.Expr), + Param: replacePrometheusNodes(t.Param), + Grouping: t.Grouping, + Without: t.Without, + } case *parser.BinaryExpr: - t.LHS = replacePrometheusNodes(t.LHS) - t.RHS = replacePrometheusNodes(t.RHS) - return t + return &Binary{ + Op: t.Op, + LHS: replacePrometheusNodes(t.LHS), + RHS: replacePrometheusNodes(t.RHS), + VectorMatching: t.VectorMatching, + ReturnBool: t.ReturnBool, + } case *parser.SubqueryExpr: - t.Expr = replacePrometheusNodes(t.Expr) - return t + return &Subquery{ + Expr: replacePrometheusNodes(t.Expr), + Range: t.Range, + OriginalOffset: t.OriginalOffset, + Offset: t.Offset, + Timestamp: t.Timestamp, + Step: t.Step, + StartOrEnd: t.StartOrEnd, + } + case nil: + return nil } - return plan + panic("Unrecognized AST node") } -func trimSorts(expr parser.Expr) parser.Expr { +func trimSorts(expr Node) Node { canTrimSorts := true // We cannot trim inner sort if its an argument to a timestamp function. // If we would do it we could transform "timestamp(sort(X))" into "timestamp(X)" // Which might return actual timestamps of samples instead of query execution timestamp. - TraverseBottomUp(nil, &expr, func(parent, current *parser.Expr) bool { + TraverseBottomUp(nil, &expr, func(parent, current *Node) bool { if current == nil || parent == nil { return true } - e, pok := (*parent).(*parser.Call) - f, cok := (*current).(*parser.Call) + e, pok := (*parent).(*FunctionCall) + f, cok := (*current).(*FunctionCall) if pok && cok { if e.Func.Name == "timestamp" && strings.HasPrefix(f.Func.Name, "sort") { @@ -290,12 +242,12 @@ func trimSorts(expr parser.Expr) parser.Expr { if !canTrimSorts { return expr } - TraverseBottomUp(nil, &expr, func(parent, current *parser.Expr) bool { + TraverseBottomUp(nil, &expr, func(parent, current *Node) bool { if current == nil || parent == nil { return true } switch e := (*parent).(type) { - case *parser.Call: + case *FunctionCall: switch e.Func.Name { case "sort", "sort_desc": *parent = *current @@ -306,13 +258,13 @@ func trimSorts(expr parser.Expr) parser.Expr { return expr } -func trimParens(expr parser.Expr) parser.Expr { - TraverseBottomUp(nil, &expr, func(parent, current *parser.Expr) bool { +func trimParens(expr Node) Node { + TraverseBottomUp(nil, &expr, func(parent, current *Node) bool { if current == nil || parent == nil { return true } switch (*parent).(type) { - case *parser.ParenExpr: + case *Parens: *parent = *current } return false @@ -320,132 +272,22 @@ func trimParens(expr parser.Expr) parser.Expr { return expr } -func insertDuplicateLabelChecks(expr parser.Expr) parser.Expr { - Traverse(&expr, func(node *parser.Expr) { +func insertDuplicateLabelChecks(expr Node) Node { + Traverse(&expr, func(node *Node) { switch t := (*node).(type) { - case *parser.AggregateExpr, *parser.UnaryExpr, *parser.BinaryExpr, *parser.Call: - *node = CheckDuplicateLabels{Expr: t} + case *CheckDuplicateLabels: + return + case *Aggregation, *Unary, *Binary, *FunctionCall: + *node = &CheckDuplicateLabels{Expr: t} case *VectorSelector: if t.SelectTimestamp { - *node = CheckDuplicateLabels{Expr: t} + *node = &CheckDuplicateLabels{Expr: t} } } }) return expr } -// preprocessExpr wraps all possible step invariant parts of the given expression with -// StepInvariantExpr. It also resolves the preprocessors. -// Copied from Prometheus and adjusted to work with the vendored parser: -// https://github.com/prometheus/prometheus/blob/3ac49d4ae210869043e6c33e3a82f13f2f849361/promql/engine.go#L2676-L2684 -func preprocessExpr(expr parser.Expr, start, end time.Time) parser.Expr { - isStepInvariant := preprocessExprHelper(expr, start, end) - if isStepInvariant { - return newStepInvariantExpr(expr) - } - return expr -} - -// preprocessExprHelper wraps the child nodes of the expression -// with a StepInvariantExpr wherever it's step invariant. The returned boolean is true if the -// passed expression qualifies to be wrapped by StepInvariantExpr. -// It also resolves the preprocessors. -func preprocessExprHelper(expr parser.Expr, start, end time.Time) bool { - switch n := expr.(type) { - case *parser.VectorSelector: - if n.StartOrEnd == parser.START { - n.Timestamp = makeInt64Pointer(timestamp.FromTime(start)) - } else if n.StartOrEnd == parser.END { - n.Timestamp = makeInt64Pointer(timestamp.FromTime(end)) - } - return n.Timestamp != nil - - case *parser.AggregateExpr: - return preprocessExprHelper(n.Expr, start, end) - - case *parser.BinaryExpr: - isInvariant1, isInvariant2 := preprocessExprHelper(n.LHS, start, end), preprocessExprHelper(n.RHS, start, end) - if isInvariant1 && isInvariant2 { - return true - } - - if isInvariant1 { - n.LHS = newStepInvariantExpr(n.LHS) - } - if isInvariant2 { - n.RHS = newStepInvariantExpr(n.RHS) - } - - return false - - case *parser.Call: - _, ok := promql.AtModifierUnsafeFunctions[n.Func.Name] - isStepInvariant := !ok - isStepInvariantSlice := make([]bool, len(n.Args)) - for i := range n.Args { - isStepInvariantSlice[i] = preprocessExprHelper(n.Args[i], start, end) - isStepInvariant = isStepInvariant && isStepInvariantSlice[i] - } - - if isStepInvariant { - // The function and all arguments are step invariant. - return true - } - - for i, isi := range isStepInvariantSlice { - if isi { - n.Args[i] = newStepInvariantExpr(n.Args[i]) - } - } - return false - - case *parser.MatrixSelector: - return preprocessExprHelper(n.VectorSelector, start, end) - - case *parser.SubqueryExpr: - // Since we adjust offset for the @ modifier evaluation, - // it gets tricky to adjust it for every subquery step. - // Hence we wrap the inside of subquery irrespective of - // @ on subquery (given it is also step invariant) so that - // it is evaluated only once w.r.t. the start time of subquery. - isInvariant := preprocessExprHelper(n.Expr, start, end) - if isInvariant { - n.Expr = newStepInvariantExpr(n.Expr) - } - if n.StartOrEnd == parser.START { - n.Timestamp = makeInt64Pointer(timestamp.FromTime(start)) - } else if n.StartOrEnd == parser.END { - n.Timestamp = makeInt64Pointer(timestamp.FromTime(end)) - } - return n.Timestamp != nil - - case *parser.ParenExpr: - return preprocessExprHelper(n.Expr, start, end) - - case *parser.UnaryExpr: - return preprocessExprHelper(n.Expr, start, end) - - case *parser.NumberLiteral: - return true - case *parser.StringLiteral: - // strings should be used as fixed strings; no need - // to wrap under stepInvariantExpr - return false - } - - panic(fmt.Sprintf("found unexpected node %#v", expr)) -} - -func makeInt64Pointer(val int64) *int64 { - valp := new(int64) - *valp = val - return valp -} - -func newStepInvariantExpr(expr parser.Expr) parser.Expr { - return &parser.StepInvariantExpr{Expr: expr} -} - // Copy from https://github.com/prometheus/prometheus/blob/v2.39.1/promql/engine.go#L2658. func setOffsetForAtModifier(evalTime int64, expr parser.Expr) { getOffset := func(ts *int64, originalOffset time.Duration, path []parser.Node) time.Duration { @@ -511,7 +353,7 @@ func subqueryTimes(path []parser.Node) (time.Duration, time.Duration, *int64) { func setOffsetForInnerSubqueries(expr parser.Expr, opts *query.Options) { switch n := expr.(type) { case *parser.SubqueryExpr: - nOpts := query.NestedOptionsForSubquery(opts, n) + nOpts := query.NestedOptionsForSubquery(opts, n.Step, n.Range, n.Offset) setOffsetForAtModifier(nOpts.Start.UnixMilli(), n.Expr) setOffsetForInnerSubqueries(n.Expr, nOpts) default: diff --git a/vendor/github.com/thanos-io/promql-engine/logicalplan/propagate_selectors.go b/vendor/github.com/thanos-io/promql-engine/logicalplan/propagate_selectors.go index 6d7b48eb31..9c8b175dcd 100644 --- a/vendor/github.com/thanos-io/promql-engine/logicalplan/propagate_selectors.go +++ b/vendor/github.com/thanos-io/promql-engine/logicalplan/propagate_selectors.go @@ -18,9 +18,9 @@ import ( // two vector selectors in a binary expression. type PropagateMatchersOptimizer struct{} -func (m PropagateMatchersOptimizer) Optimize(plan parser.Expr, _ *query.Options) (parser.Expr, annotations.Annotations) { - Traverse(&plan, func(expr *parser.Expr) { - binOp, ok := (*expr).(*parser.BinaryExpr) +func (m PropagateMatchersOptimizer) Optimize(plan Node, _ *query.Options) (Node, annotations.Annotations) { + Traverse(&plan, func(expr *Node) { + binOp, ok := (*expr).(*Binary) if !ok { return } @@ -46,7 +46,7 @@ func (m PropagateMatchersOptimizer) Optimize(plan parser.Expr, _ *query.Options) return plan, nil } -func propagateMatchers(binOp *parser.BinaryExpr) { +func propagateMatchers(binOp *Binary) { lhSelector, ok := binOp.LHS.(*VectorSelector) if !ok { return diff --git a/vendor/github.com/thanos-io/promql-engine/logicalplan/set_batch_size.go b/vendor/github.com/thanos-io/promql-engine/logicalplan/set_batch_size.go index 3c783b9a1e..6ebf1942c3 100644 --- a/vendor/github.com/thanos-io/promql-engine/logicalplan/set_batch_size.go +++ b/vendor/github.com/thanos-io/promql-engine/logicalplan/set_batch_size.go @@ -20,18 +20,18 @@ type SelectorBatchSize struct { // If any aggregate is present in the plan, the batch size is set to the configured value. // The two exceptions where this cannot be done is if the aggregate is quantile, or // when a binary expression precedes the aggregate. -func (m SelectorBatchSize) Optimize(plan parser.Expr, _ *query.Options) (parser.Expr, annotations.Annotations) { +func (m SelectorBatchSize) Optimize(plan Node, _ *query.Options) (Node, annotations.Annotations) { canBatch := false - Traverse(&plan, func(current *parser.Expr) { + Traverse(&plan, func(current *Node) { switch e := (*current).(type) { - case *parser.Call: + case *FunctionCall: //TODO: calls can reduce the labelset of the input; think histogram_quantile reducing // multiple "le" labels into one output. We cannot handle this in batching. Revisit // what is safe here. canBatch = false - case *parser.BinaryExpr: + case *Binary: canBatch = false - case *parser.AggregateExpr: + case *Aggregation: if e.Op == parser.QUANTILE || e.Op == parser.TOPK || e.Op == parser.BOTTOMK { canBatch = false return diff --git a/vendor/github.com/thanos-io/promql-engine/logicalplan/sort_matchers.go b/vendor/github.com/thanos-io/promql-engine/logicalplan/sort_matchers.go index 890e9a02c3..acb976b1f6 100644 --- a/vendor/github.com/thanos-io/promql-engine/logicalplan/sort_matchers.go +++ b/vendor/github.com/thanos-io/promql-engine/logicalplan/sort_matchers.go @@ -6,7 +6,6 @@ package logicalplan import ( "sort" - "github.com/prometheus/prometheus/promql/parser" "github.com/prometheus/prometheus/util/annotations" "github.com/thanos-io/promql-engine/query" @@ -17,8 +16,8 @@ import ( // can rely on this property. type SortMatchers struct{} -func (m SortMatchers) Optimize(plan parser.Expr, _ *query.Options) (parser.Expr, annotations.Annotations) { - Traverse(&plan, func(node *parser.Expr) { +func (m SortMatchers) Optimize(plan Node, _ *query.Options) (Node, annotations.Annotations) { + Traverse(&plan, func(node *Node) { e, ok := (*node).(*VectorSelector) if !ok { return diff --git a/vendor/github.com/thanos-io/promql-engine/logicalplan/user_defined.go b/vendor/github.com/thanos-io/promql-engine/logicalplan/user_defined.go index 7885fad9a4..7a684fc204 100644 --- a/vendor/github.com/thanos-io/promql-engine/logicalplan/user_defined.go +++ b/vendor/github.com/thanos-io/promql-engine/logicalplan/user_defined.go @@ -6,15 +6,13 @@ package logicalplan import ( "github.com/prometheus/prometheus/storage" - "github.com/prometheus/prometheus/promql/parser" - "github.com/thanos-io/promql-engine/execution/model" "github.com/thanos-io/promql-engine/query" ) // UserDefinedExpr is an extension point which allows users to define their execution operators. type UserDefinedExpr interface { - parser.Expr + Node MakeExecutionOperator( vectors *model.VectorPool, opts *query.Options, diff --git a/vendor/github.com/thanos-io/promql-engine/query/options.go b/vendor/github.com/thanos-io/promql-engine/query/options.go index 3381c054d0..369fb832ca 100644 --- a/vendor/github.com/thanos-io/promql-engine/query/options.go +++ b/vendor/github.com/thanos-io/promql-engine/query/options.go @@ -6,8 +6,6 @@ package query import ( "context" "time" - - "github.com/prometheus/prometheus/promql/parser" ) type Options struct { @@ -45,23 +43,23 @@ func (o *Options) WithEndTime(end time.Time) *Options { return &result } -func NestedOptionsForSubquery(opts *Options, t *parser.SubqueryExpr) *Options { +func NestedOptionsForSubquery(opts *Options, step, queryRange, offset time.Duration) *Options { nOpts := &Options{ Context: opts.Context, - End: opts.End.Add(-t.Offset), + End: opts.End.Add(-offset), LookbackDelta: opts.LookbackDelta, StepsBatch: opts.StepsBatch, ExtLookbackDelta: opts.ExtLookbackDelta, NoStepSubqueryIntervalFn: opts.NoStepSubqueryIntervalFn, EnableAnalysis: opts.EnableAnalysis, } - if t.Step != 0 { - nOpts.Step = t.Step + if step != 0 { + nOpts.Step = step } else { - nOpts.Step = opts.NoStepSubqueryIntervalFn(t.Range) + nOpts.Step = opts.NoStepSubqueryIntervalFn(queryRange) } - nOpts.Start = time.UnixMilli(nOpts.Step.Milliseconds() * (opts.Start.Add(-t.Offset-t.Range).UnixMilli() / nOpts.Step.Milliseconds())) - if nOpts.Start.Before(opts.Start.Add(-t.Offset - t.Range)) { + nOpts.Start = time.UnixMilli(nOpts.Step.Milliseconds() * (opts.Start.Add(-offset-queryRange).UnixMilli() / nOpts.Step.Milliseconds())) + if nOpts.Start.Before(opts.Start.Add(-offset - queryRange)) { nOpts.Start = nOpts.Start.Add(nOpts.Step) } return nOpts diff --git a/vendor/github.com/thanos-io/promql-engine/storage/interface.go b/vendor/github.com/thanos-io/promql-engine/storage/interface.go index 6d3b419ab6..1ebbadc371 100644 --- a/vendor/github.com/thanos-io/promql-engine/storage/interface.go +++ b/vendor/github.com/thanos-io/promql-engine/storage/interface.go @@ -4,7 +4,6 @@ package storage import ( - "github.com/prometheus/prometheus/promql/parser" "github.com/prometheus/prometheus/storage" "github.com/thanos-io/promql-engine/execution/model" @@ -14,5 +13,5 @@ import ( type Scanners interface { NewVectorSelector(opts *query.Options, hints storage.SelectHints, selector logicalplan.VectorSelector) (model.VectorOperator, error) - NewMatrixSelector(opts *query.Options, hints storage.SelectHints, selector logicalplan.MatrixSelector, call parser.Call) (model.VectorOperator, error) + NewMatrixSelector(opts *query.Options, hints storage.SelectHints, selector logicalplan.MatrixSelector, call logicalplan.FunctionCall) (model.VectorOperator, error) } diff --git a/vendor/github.com/thanos-io/promql-engine/storage/prometheus/matrix_selector.go b/vendor/github.com/thanos-io/promql-engine/storage/prometheus/matrix_selector.go index f2efc51dab..c29c50b910 100644 --- a/vendor/github.com/thanos-io/promql-engine/storage/prometheus/matrix_selector.go +++ b/vendor/github.com/thanos-io/promql-engine/storage/prometheus/matrix_selector.go @@ -85,8 +85,6 @@ func NewMatrixSelector( } isExtFunction := function.IsExtFunction(functionName) m := &matrixSelector{ - OperatorTelemetry: model.NewTelemetry("matrixSelector", opts.EnableAnalysis), - storage: selector, call: call, functionName: functionName, @@ -110,6 +108,7 @@ func NewMatrixSelector( extLookbackDelta: opts.ExtLookbackDelta.Milliseconds(), } + m.OperatorTelemetry = model.NewTelemetry(m, opts.EnableAnalysis) // For instant queries, set the step to a positive value // so that the operator can terminate. @@ -120,12 +119,8 @@ func NewMatrixSelector( return m, nil } -func (o *matrixSelector) Explain() (me string, next []model.VectorOperator) { - r := time.Duration(o.selectRange) * time.Millisecond - if o.call != nil { - return fmt.Sprintf("[matrixSelector] %v({%v}[%s] %v mod %v)", o.functionName, o.storage.Matchers(), r, o.shard, o.numShards), nil - } - return fmt.Sprintf("[matrixSelector] {%v}[%s] %v mod %v", o.storage.Matchers(), r, o.shard, o.numShards), nil +func (o *matrixSelector) Explain() []model.VectorOperator { + return nil } func (o *matrixSelector) Series(ctx context.Context) ([]labels.Labels, error) { @@ -261,6 +256,14 @@ func (o *matrixSelector) loadSeries(ctx context.Context) error { return err } +func (o *matrixSelector) String() string { + r := time.Duration(o.selectRange) * time.Millisecond + if o.call != nil { + return fmt.Sprintf("[matrixSelector] %v({%v}[%s] %v mod %v)", o.functionName, o.storage.Matchers(), r, o.shard, o.numShards) + } + return fmt.Sprintf("[matrixSelector] {%v}[%s] %v mod %v", o.storage.Matchers(), r, o.shard, o.numShards) +} + // matrixIterSlice populates a matrix vector covering the requested range for a // single time series, with points retrieved from an iterator. // diff --git a/vendor/github.com/thanos-io/promql-engine/storage/prometheus/scanners.go b/vendor/github.com/thanos-io/promql-engine/storage/prometheus/scanners.go index c65d796e95..4b51f92bad 100644 --- a/vendor/github.com/thanos-io/promql-engine/storage/prometheus/scanners.go +++ b/vendor/github.com/thanos-io/promql-engine/storage/prometheus/scanners.go @@ -7,7 +7,6 @@ import ( "runtime" "github.com/efficientgo/core/errors" - "github.com/prometheus/prometheus/promql/parser" "github.com/prometheus/prometheus/storage" "github.com/thanos-io/promql-engine/execution/exchange" @@ -59,7 +58,7 @@ func (p prometheusScanners) NewMatrixSelector( opts *query.Options, hints storage.SelectHints, logicalNode logicalplan.MatrixSelector, - call parser.Call, + call logicalplan.FunctionCall, ) (model.VectorOperator, error) { numShards := runtime.GOMAXPROCS(0) / 2 if numShards < 1 { @@ -75,7 +74,7 @@ func (p prometheusScanners) NewMatrixSelector( arg = unwrap } - vs := logicalNode.VectorSelector.(*logicalplan.VectorSelector) + vs := logicalNode.VectorSelector filter := p.selectors.GetFilteredSelector(hints.Start, hints.End, opts.Step.Milliseconds(), vs.LabelMatchers, vs.Filters, hints) operators := make([]model.VectorOperator, 0, numShards) diff --git a/vendor/github.com/thanos-io/promql-engine/storage/prometheus/vector_selector.go b/vendor/github.com/thanos-io/promql-engine/storage/prometheus/vector_selector.go index 0872a8619b..898276dc36 100644 --- a/vendor/github.com/thanos-io/promql-engine/storage/prometheus/vector_selector.go +++ b/vendor/github.com/thanos-io/promql-engine/storage/prometheus/vector_selector.go @@ -65,8 +65,6 @@ func NewVectorSelector( shard, numShards int, ) model.VectorOperator { o := &vectorSelector{ - OperatorTelemetry: model.NewTelemetry("[vectorSelector]", queryOpts.EnableAnalysis), - storage: selector, vectorPool: pool, @@ -84,6 +82,8 @@ func NewVectorSelector( selectTimestamp: selectTimestamp, } + o.OperatorTelemetry = model.NewTelemetry(o, queryOpts.EnableAnalysis) + // For instant queries, set the step to a positive value // so that the operator can terminate. if o.step == 0 { @@ -93,8 +93,12 @@ func NewVectorSelector( return o } -func (o *vectorSelector) Explain() (me string, next []model.VectorOperator) { - return fmt.Sprintf("[vectorSelector] {%v} %v mod %v", o.storage.Matchers(), o.shard, o.numShards), nil +func (o *vectorSelector) String() string { + return fmt.Sprintf("[vectorSelector] {%v} %v mod %v", o.storage.Matchers(), o.shard, o.numShards) +} + +func (o *vectorSelector) Explain() (next []model.VectorOperator) { + return nil } func (o *vectorSelector) Series(ctx context.Context) ([]labels.Labels, error) { diff --git a/vendor/github.com/thanos-io/thanos/pkg/store/bucket.go b/vendor/github.com/thanos-io/thanos/pkg/store/bucket.go index a45150681f..1951c217bf 100644 --- a/vendor/github.com/thanos-io/thanos/pkg/store/bucket.go +++ b/vendor/github.com/thanos-io/thanos/pkg/store/bucket.go @@ -2751,7 +2751,7 @@ func toPostingGroup(ctx context.Context, lvalsFn func(name string) ([]string, er // Inverse of a MatchNotRegexp is MatchRegexp (double negation). // Fast-path for set matching. if m.Type == labels.MatchNotRegexp { - if vals := findSetMatches(m.Value); len(vals) > 0 { + if vals := m.SetMatches(); len(vals) > 0 { sort.Strings(vals) return newPostingGroup(true, m.Name, nil, vals), nil, nil } @@ -2780,7 +2780,7 @@ func toPostingGroup(ctx context.Context, lvalsFn func(name string) ([]string, er return newPostingGroup(true, m.Name, nil, toRemove), vals, nil } if m.Type == labels.MatchRegexp { - if vals := findSetMatches(m.Value); len(vals) > 0 { + if vals := m.SetMatches(); len(vals) > 0 { sort.Strings(vals) return newPostingGroup(false, m.Name, vals, nil), nil, nil } diff --git a/vendor/github.com/thanos-io/thanos/pkg/store/opts.go b/vendor/github.com/thanos-io/thanos/pkg/store/opts.go deleted file mode 100644 index 0a739a482a..0000000000 --- a/vendor/github.com/thanos-io/thanos/pkg/store/opts.go +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) The Thanos Authors. -// Licensed under the Apache License 2.0. - -package store - -import ( - "strings" - "unicode/utf8" -) - -// Bitmap used by func isRegexMetaCharacter to check whether a character needs to be escaped. -var regexMetaCharacterBytes [16]byte - -// isRegexMetaCharacter reports whether byte b needs to be escaped. -func isRegexMetaCharacter(b byte) bool { - return b < utf8.RuneSelf && regexMetaCharacterBytes[b%16]&(1<<(b/16)) != 0 -} - -func init() { - for _, b := range []byte(`.+*?()|[]{}^$`) { - regexMetaCharacterBytes[b%16] |= 1 << (b / 16) - } -} - -// Copied from Prometheus querier.go, removed check for Prometheus wrapper. -// Returns list of values that can regex matches. -func findSetMatches(pattern string) []string { - if len(pattern) == 0 { - return nil - } - escaped := false - sets := []*strings.Builder{{}} - init := 0 - end := len(pattern) - // If the regex is wrapped in a group we can remove the first and last parentheses - if pattern[init] == '(' && pattern[end-1] == ')' { - init++ - end-- - } - for i := init; i < end; i++ { - if escaped { - switch { - case isRegexMetaCharacter(pattern[i]): - sets[len(sets)-1].WriteByte(pattern[i]) - case pattern[i] == '\\': - sets[len(sets)-1].WriteByte('\\') - default: - return nil - } - escaped = false - } else { - switch { - case isRegexMetaCharacter(pattern[i]): - if pattern[i] == '|' { - sets = append(sets, &strings.Builder{}) - } else { - return nil - } - case pattern[i] == '\\': - escaped = true - default: - sets[len(sets)-1].WriteByte(pattern[i]) - } - } - } - matches := make([]string, 0, len(sets)) - for _, s := range sets { - if s.Len() > 0 { - matches = append(matches, s.String()) - } - } - return matches -} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/array_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/array_codec.go index 6ca8d9ad6c..652aa48b85 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/array_codec.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/array_codec.go @@ -15,16 +15,15 @@ import ( // ArrayCodec is the Codec used for bsoncore.Array values. // -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// ArrayCodec registered. +// Deprecated: ArrayCodec will not be directly accessible in Go Driver 2.0. type ArrayCodec struct{} var defaultArrayCodec = NewArrayCodec() // NewArrayCodec returns an ArrayCodec. // -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// ArrayCodec registered. +// Deprecated: NewArrayCodec will not be available in Go Driver 2.0. See +// [ArrayCodec] for more details. func NewArrayCodec() *ArrayCodec { return &ArrayCodec{} } diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/byte_slice_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/byte_slice_codec.go index dde3e76815..0134b5a94b 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/byte_slice_codec.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/byte_slice_codec.go @@ -17,13 +17,28 @@ import ( // ByteSliceCodec is the Codec used for []byte values. // -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// ByteSliceCodec registered. +// Deprecated: ByteSliceCodec will not be directly configurable in Go Driver +// 2.0. To configure the byte slice encode and decode behavior, use the +// configuration methods on a [go.mongodb.org/mongo-driver/bson.Encoder] or +// [go.mongodb.org/mongo-driver/bson.Decoder]. To configure the byte slice +// encode and decode behavior for a mongo.Client, use +// [go.mongodb.org/mongo-driver/mongo/options.ClientOptions.SetBSONOptions]. +// +// For example, to configure a mongo.Client to encode nil byte slices as empty +// BSON binary values, use: +// +// opt := options.Client().SetBSONOptions(&options.BSONOptions{ +// NilByteSliceAsEmpty: true, +// }) +// +// See the deprecation notice for each field in ByteSliceCodec for the +// corresponding settings. type ByteSliceCodec struct { // EncodeNilAsEmpty causes EncodeValue to marshal nil Go byte slices as empty BSON binary values // instead of BSON null. // - // Deprecated: Use bson.Encoder.NilByteSliceAsEmpty instead. + // Deprecated: Use bson.Encoder.NilByteSliceAsEmpty or options.BSONOptions.NilByteSliceAsEmpty + // instead. EncodeNilAsEmpty bool } @@ -38,8 +53,8 @@ var ( // NewByteSliceCodec returns a ByteSliceCodec with options opts. // -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// ByteSliceCodec registered. +// Deprecated: NewByteSliceCodec will not be available in Go Driver 2.0. See +// [ByteSliceCodec] for more details. func NewByteSliceCodec(opts ...*bsonoptions.ByteSliceCodecOptions) *ByteSliceCodec { byteSliceOpt := bsonoptions.MergeByteSliceCodecOptions(opts...) codec := ByteSliceCodec{} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_decoders.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_decoders.go index 2ce119731b..7e08aab35e 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_decoders.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_decoders.go @@ -41,7 +41,7 @@ func newDefaultStructCodec() *StructCodec { if err != nil { // This function is called from the codec registration path, so errors can't be propagated. If there's an error // constructing the StructCodec, we panic to avoid losing it. - panic(fmt.Errorf("error creating default StructCodec: %v", err)) + panic(fmt.Errorf("error creating default StructCodec: %w", err)) } return codec } @@ -178,7 +178,7 @@ func (dvd DefaultValueDecoders) DDecodeValue(dc DecodeContext, vr bsonrw.ValueRe for { key, elemVr, err := dr.ReadElement() - if err == bsonrw.ErrEOD { + if errors.Is(err, bsonrw.ErrEOD) { break } else if err != nil { return err @@ -1379,7 +1379,7 @@ func (dvd DefaultValueDecoders) MapDecodeValue(dc DecodeContext, vr bsonrw.Value keyType := val.Type().Key() for { key, vr, err := dr.ReadElement() - if err == bsonrw.ErrEOD { + if errors.Is(err, bsonrw.ErrEOD) { break } if err != nil { @@ -1675,7 +1675,7 @@ func (dvd DefaultValueDecoders) decodeDefault(dc DecodeContext, vr bsonrw.ValueR idx := 0 for { vr, err := ar.ReadValue() - if err == bsonrw.ErrEOA { + if errors.Is(err, bsonrw.ErrEOA) { break } if err != nil { @@ -1787,7 +1787,7 @@ func (DefaultValueDecoders) decodeElemsFromDocumentReader(dc DecodeContext, dr b elems := make([]reflect.Value, 0) for { key, vr, err := dr.ReadElement() - if err == bsonrw.ErrEOD { + if errors.Is(err, bsonrw.ErrEOD) { break } if err != nil { diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_encoders.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_encoders.go index 4ab14a668c..4751ae995e 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_encoders.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/default_value_encoders.go @@ -343,7 +343,7 @@ func (dve DefaultValueEncoders) mapEncodeValue(ec EncodeContext, dw bsonrw.Docum } currEncoder, currVal, lookupErr := dve.lookupElementEncoder(ec, encoder, val.MapIndex(key)) - if lookupErr != nil && lookupErr != errInvalidValue { + if lookupErr != nil && !errors.Is(lookupErr, errInvalidValue) { return lookupErr } @@ -352,7 +352,7 @@ func (dve DefaultValueEncoders) mapEncodeValue(ec EncodeContext, dw bsonrw.Docum return err } - if lookupErr == errInvalidValue { + if errors.Is(lookupErr, errInvalidValue) { err = vw.WriteNull() if err != nil { return err @@ -418,7 +418,7 @@ func (dve DefaultValueEncoders) ArrayEncodeValue(ec EncodeContext, vw bsonrw.Val for idx := 0; idx < val.Len(); idx++ { currEncoder, currVal, lookupErr := dve.lookupElementEncoder(ec, encoder, val.Index(idx)) - if lookupErr != nil && lookupErr != errInvalidValue { + if lookupErr != nil && !errors.Is(lookupErr, errInvalidValue) { return lookupErr } @@ -427,7 +427,7 @@ func (dve DefaultValueEncoders) ArrayEncodeValue(ec EncodeContext, vw bsonrw.Val return err } - if lookupErr == errInvalidValue { + if errors.Is(lookupErr, errInvalidValue) { err = vw.WriteNull() if err != nil { return err @@ -487,7 +487,7 @@ func (dve DefaultValueEncoders) SliceEncodeValue(ec EncodeContext, vw bsonrw.Val for idx := 0; idx < val.Len(); idx++ { currEncoder, currVal, lookupErr := dve.lookupElementEncoder(ec, encoder, val.Index(idx)) - if lookupErr != nil && lookupErr != errInvalidValue { + if lookupErr != nil && !errors.Is(lookupErr, errInvalidValue) { return lookupErr } @@ -496,7 +496,7 @@ func (dve DefaultValueEncoders) SliceEncodeValue(ec EncodeContext, vw bsonrw.Val return err } - if lookupErr == errInvalidValue { + if errors.Is(lookupErr, errInvalidValue) { err = vw.WriteNull() if err != nil { return err diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/empty_interface_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/empty_interface_codec.go index 94f7dcf1eb..098368f071 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/empty_interface_codec.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/empty_interface_codec.go @@ -17,13 +17,27 @@ import ( // EmptyInterfaceCodec is the Codec used for interface{} values. // -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// EmptyInterfaceCodec registered. +// Deprecated: EmptyInterfaceCodec will not be directly configurable in Go +// Driver 2.0. To configure the empty interface encode and decode behavior, use +// the configuration methods on a [go.mongodb.org/mongo-driver/bson.Encoder] or +// [go.mongodb.org/mongo-driver/bson.Decoder]. To configure the empty interface +// encode and decode behavior for a mongo.Client, use +// [go.mongodb.org/mongo-driver/mongo/options.ClientOptions.SetBSONOptions]. +// +// For example, to configure a mongo.Client to unmarshal BSON binary field +// values as a Go byte slice, use: +// +// opt := options.Client().SetBSONOptions(&options.BSONOptions{ +// BinaryAsSlice: true, +// }) +// +// See the deprecation notice for each field in EmptyInterfaceCodec for the +// corresponding settings. type EmptyInterfaceCodec struct { // DecodeBinaryAsSlice causes DecodeValue to unmarshal BSON binary field values that are the // "Generic" or "Old" BSON binary subtype as a Go byte slice instead of a primitive.Binary. // - // Deprecated: Use bson.Decoder.BinaryAsSlice instead. + // Deprecated: Use bson.Decoder.BinaryAsSlice or options.BSONOptions.BinaryAsSlice instead. DecodeBinaryAsSlice bool } @@ -38,8 +52,8 @@ var ( // NewEmptyInterfaceCodec returns a EmptyInterfaceCodec with options opts. // -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// EmptyInterfaceCodec registered. +// Deprecated: NewEmptyInterfaceCodec will not be available in Go Driver 2.0. See +// [EmptyInterfaceCodec] for more details. func NewEmptyInterfaceCodec(opts ...*bsonoptions.EmptyInterfaceCodecOptions) *EmptyInterfaceCodec { interfaceOpt := bsonoptions.MergeEmptyInterfaceCodecOptions(opts...) diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/map_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/map_codec.go index 325c1738ab..d7e00ffa8d 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/map_codec.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/map_codec.go @@ -8,6 +8,7 @@ package bsoncodec import ( "encoding" + "errors" "fmt" "reflect" "strconv" @@ -21,25 +22,40 @@ var defaultMapCodec = NewMapCodec() // MapCodec is the Codec used for map values. // -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// MapCodec registered. +// Deprecated: MapCodec will not be directly configurable in Go Driver 2.0. To +// configure the map encode and decode behavior, use the configuration methods +// on a [go.mongodb.org/mongo-driver/bson.Encoder] or +// [go.mongodb.org/mongo-driver/bson.Decoder]. To configure the map encode and +// decode behavior for a mongo.Client, use +// [go.mongodb.org/mongo-driver/mongo/options.ClientOptions.SetBSONOptions]. +// +// For example, to configure a mongo.Client to marshal nil Go maps as empty BSON +// documents, use: +// +// opt := options.Client().SetBSONOptions(&options.BSONOptions{ +// NilMapAsEmpty: true, +// }) +// +// See the deprecation notice for each field in MapCodec for the corresponding +// settings. type MapCodec struct { // DecodeZerosMap causes DecodeValue to delete any existing values from Go maps in the destination // value passed to Decode before unmarshaling BSON documents into them. // - // Deprecated: Use bson.Decoder.ZeroMaps instead. + // Deprecated: Use bson.Decoder.ZeroMaps or options.BSONOptions.ZeroMaps instead. DecodeZerosMap bool // EncodeNilAsEmpty causes EncodeValue to marshal nil Go maps as empty BSON documents instead of // BSON null. // - // Deprecated: Use bson.Encoder.NilMapAsEmpty instead. + // Deprecated: Use bson.Encoder.NilMapAsEmpty or options.BSONOptions.NilMapAsEmpty instead. EncodeNilAsEmpty bool // EncodeKeysWithStringer causes the Encoder to convert Go map keys to BSON document field name // strings using fmt.Sprintf() instead of the default string conversion logic. // - // Deprecated: Use bson.Encoder.StringifyMapKeysWithFmt instead. + // Deprecated: Use bson.Encoder.StringifyMapKeysWithFmt or + // options.BSONOptions.StringifyMapKeysWithFmt instead. EncodeKeysWithStringer bool } @@ -61,8 +77,8 @@ type KeyUnmarshaler interface { // NewMapCodec returns a MapCodec with options opts. // -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// MapCodec registered. +// Deprecated: NewMapCodec will not be available in Go Driver 2.0. See +// [MapCodec] for more details. func NewMapCodec(opts ...*bsonoptions.MapCodecOptions) *MapCodec { mapOpt := bsonoptions.MergeMapCodecOptions(opts...) @@ -128,7 +144,7 @@ func (mc *MapCodec) mapEncodeValue(ec EncodeContext, dw bsonrw.DocumentWriter, v } currEncoder, currVal, lookupErr := defaultValueEncoders.lookupElementEncoder(ec, encoder, val.MapIndex(key)) - if lookupErr != nil && lookupErr != errInvalidValue { + if lookupErr != nil && !errors.Is(lookupErr, errInvalidValue) { return lookupErr } @@ -137,7 +153,7 @@ func (mc *MapCodec) mapEncodeValue(ec EncodeContext, dw bsonrw.DocumentWriter, v return err } - if lookupErr == errInvalidValue { + if errors.Is(lookupErr, errInvalidValue) { err = vw.WriteNull() if err != nil { return err @@ -200,7 +216,7 @@ func (mc *MapCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val ref for { key, vr, err := dr.ReadElement() - if err == bsonrw.ErrEOD { + if errors.Is(err, bsonrw.ErrEOD) { break } if err != nil { @@ -313,7 +329,7 @@ func (mc *MapCodec) decodeKey(key string, keyType reflect.Type) (reflect.Value, if mc.EncodeKeysWithStringer { parsed, err := strconv.ParseFloat(key, 64) if err != nil { - return keyVal, fmt.Errorf("Map key is defined to be a decimal type (%v) but got error %v", keyType.Kind(), err) + return keyVal, fmt.Errorf("Map key is defined to be a decimal type (%v) but got error %w", keyType.Kind(), err) } keyVal = reflect.ValueOf(parsed) break diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/pointer_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/pointer_codec.go index e5923230b0..ddfa4a33e1 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/pointer_codec.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/pointer_codec.go @@ -18,8 +18,16 @@ var _ ValueDecoder = &PointerCodec{} // PointerCodec is the Codec used for pointers. // -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// PointerCodec registered. +// Deprecated: PointerCodec will not be directly accessible in Go Driver 2.0. To +// override the default pointer encode and decode behavior, create a new registry +// with [go.mongodb.org/mongo-driver/bson.NewRegistry] and register a new +// encoder and decoder for pointers. +// +// For example, +// +// reg := bson.NewRegistry() +// reg.RegisterKindEncoder(reflect.Ptr, myPointerEncoder) +// reg.RegisterKindDecoder(reflect.Ptr, myPointerDecoder) type PointerCodec struct { ecache typeEncoderCache dcache typeDecoderCache @@ -27,8 +35,8 @@ type PointerCodec struct { // NewPointerCodec returns a PointerCodec that has been initialized. // -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// PointerCodec registered. +// Deprecated: NewPointerCodec will not be available in Go Driver 2.0. See +// [PointerCodec] for more details. func NewPointerCodec() *PointerCodec { return &PointerCodec{} } diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/slice_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/slice_codec.go index a43daf005f..14c9fd2564 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/slice_codec.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/slice_codec.go @@ -7,6 +7,7 @@ package bsoncodec import ( + "errors" "fmt" "reflect" @@ -20,8 +21,22 @@ var defaultSliceCodec = NewSliceCodec() // SliceCodec is the Codec used for slice values. // -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// SliceCodec registered. +// Deprecated: SliceCodec will not be directly configurable in Go Driver 2.0. To +// configure the slice encode and decode behavior, use the configuration methods +// on a [go.mongodb.org/mongo-driver/bson.Encoder] or +// [go.mongodb.org/mongo-driver/bson.Decoder]. To configure the slice encode and +// decode behavior for a mongo.Client, use +// [go.mongodb.org/mongo-driver/mongo/options.ClientOptions.SetBSONOptions]. +// +// For example, to configure a mongo.Client to marshal nil Go slices as empty +// BSON arrays, use: +// +// opt := options.Client().SetBSONOptions(&options.BSONOptions{ +// NilSliceAsEmpty: true, +// }) +// +// See the deprecation notice for each field in SliceCodec for the corresponding +// settings. type SliceCodec struct { // EncodeNilAsEmpty causes EncodeValue to marshal nil Go slices as empty BSON arrays instead of // BSON null. @@ -32,8 +47,8 @@ type SliceCodec struct { // NewSliceCodec returns a MapCodec with options opts. // -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// SliceCodec registered. +// Deprecated: NewSliceCodec will not be available in Go Driver 2.0. See +// [SliceCodec] for more details. func NewSliceCodec(opts ...*bsonoptions.SliceCodecOptions) *SliceCodec { sliceOpt := bsonoptions.MergeSliceCodecOptions(opts...) @@ -93,7 +108,7 @@ func (sc SliceCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val re for idx := 0; idx < val.Len(); idx++ { currEncoder, currVal, lookupErr := defaultValueEncoders.lookupElementEncoder(ec, encoder, val.Index(idx)) - if lookupErr != nil && lookupErr != errInvalidValue { + if lookupErr != nil && !errors.Is(lookupErr, errInvalidValue) { return lookupErr } @@ -102,7 +117,7 @@ func (sc SliceCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val re return err } - if lookupErr == errInvalidValue { + if errors.Is(lookupErr, errInvalidValue) { err = vw.WriteNull() if err != nil { return err diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/string_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/string_codec.go index ff931b7253..a8f885a854 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/string_codec.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/string_codec.go @@ -17,8 +17,16 @@ import ( // StringCodec is the Codec used for string values. // -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// StringCodec registered. +// Deprecated: StringCodec will not be directly accessible in Go Driver 2.0. To +// override the default string encode and decode behavior, create a new registry +// with [go.mongodb.org/mongo-driver/bson.NewRegistry] and register a new +// encoder and decoder for strings. +// +// For example, +// +// reg := bson.NewRegistry() +// reg.RegisterKindEncoder(reflect.String, myStringEncoder) +// reg.RegisterKindDecoder(reflect.String, myStringDecoder) type StringCodec struct { // DecodeObjectIDAsHex specifies if object IDs should be decoded as their hex representation. // If false, a string made from the raw object ID bytes will be used. Defaults to true. @@ -38,8 +46,8 @@ var ( // NewStringCodec returns a StringCodec with options opts. // -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// StringCodec registered. +// Deprecated: NewStringCodec will not be available in Go Driver 2.0. See +// [StringCodec] for more details. func NewStringCodec(opts ...*bsonoptions.StringCodecOptions) *StringCodec { stringOpt := bsonoptions.MergeStringCodecOptions(opts...) return &StringCodec{*stringOpt.DecodeObjectIDAsHex} diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_codec.go index 4cde0a4d6b..f8d9690c13 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_codec.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/struct_codec.go @@ -60,8 +60,22 @@ type Zeroer interface { // StructCodec is the Codec used for struct values. // -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// StructCodec registered. +// Deprecated: StructCodec will not be directly configurable in Go Driver 2.0. +// To configure the struct encode and decode behavior, use the configuration +// methods on a [go.mongodb.org/mongo-driver/bson.Encoder] or +// [go.mongodb.org/mongo-driver/bson.Decoder]. To configure the struct encode +// and decode behavior for a mongo.Client, use +// [go.mongodb.org/mongo-driver/mongo/options.ClientOptions.SetBSONOptions]. +// +// For example, to configure a mongo.Client to omit zero-value structs when +// using the "omitempty" struct tag, use: +// +// opt := options.Client().SetBSONOptions(&options.BSONOptions{ +// OmitZeroStruct: true, +// }) +// +// See the deprecation notice for each field in StructCodec for the corresponding +// settings. type StructCodec struct { cache sync.Map // map[reflect.Type]*structDescription parser StructTagParser @@ -69,7 +83,7 @@ type StructCodec struct { // DecodeZeroStruct causes DecodeValue to delete any existing values from Go structs in the // destination value passed to Decode before unmarshaling BSON documents into them. // - // Deprecated: Use bson.Decoder.ZeroStructs instead. + // Deprecated: Use bson.Decoder.ZeroStructs or options.BSONOptions.ZeroStructs instead. DecodeZeroStruct bool // DecodeDeepZeroInline causes DecodeValue to delete any existing values from Go structs in the @@ -82,7 +96,7 @@ type StructCodec struct { // MyStruct{}) as empty and omit it from the marshaled BSON when the "omitempty" struct tag // option is set. // - // Deprecated: Use bson.Encoder.OmitZeroStruct instead. + // Deprecated: Use bson.Encoder.OmitZeroStruct or options.BSONOptions.OmitZeroStruct instead. EncodeOmitDefaultStruct bool // AllowUnexportedFields allows encoding and decoding values from un-exported struct fields. @@ -95,7 +109,8 @@ type StructCodec struct { // a duplicate field in the marshaled BSON when the "inline" struct tag option is set. The // default value is true. // - // Deprecated: Use bson.Encoder.ErrorOnInlineDuplicates instead. + // Deprecated: Use bson.Encoder.ErrorOnInlineDuplicates or + // options.BSONOptions.ErrorOnInlineDuplicates instead. OverwriteDuplicatedInlinedFields bool } @@ -104,8 +119,8 @@ var _ ValueDecoder = &StructCodec{} // NewStructCodec returns a StructCodec that uses p for struct tag parsing. // -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// StructCodec registered. +// Deprecated: NewStructCodec will not be available in Go Driver 2.0. See +// [StructCodec] for more details. func NewStructCodec(p StructTagParser, opts ...*bsonoptions.StructCodecOptions) (*StructCodec, error) { if p == nil { return nil, errors.New("a StructTagParser must be provided to NewStructCodec") @@ -164,11 +179,11 @@ func (sc *StructCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val desc.encoder, rv, err = defaultValueEncoders.lookupElementEncoder(ec, desc.encoder, rv) - if err != nil && err != errInvalidValue { + if err != nil && !errors.Is(err, errInvalidValue) { return err } - if err == errInvalidValue { + if errors.Is(err, errInvalidValue) { if desc.omitEmpty { continue } @@ -189,17 +204,17 @@ func (sc *StructCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val encoder := desc.encoder - var zero bool + var empty bool if cz, ok := encoder.(CodecZeroer); ok { - zero = cz.IsTypeZero(rv.Interface()) + empty = cz.IsTypeZero(rv.Interface()) } else if rv.Kind() == reflect.Interface { - // isZero will not treat an interface rv as an interface, so we need to check for the - // zero interface separately. - zero = rv.IsNil() + // isEmpty will not treat an interface rv as an interface, so we need to check for the + // nil interface separately. + empty = rv.IsNil() } else { - zero = isZero(rv, sc.EncodeOmitDefaultStruct || ec.omitZeroStruct) + empty = isEmpty(rv, sc.EncodeOmitDefaultStruct || ec.omitZeroStruct) } - if desc.omitEmpty && zero { + if desc.omitEmpty && empty { continue } @@ -239,8 +254,8 @@ func (sc *StructCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val } func newDecodeError(key string, original error) error { - de, ok := original.(*DecodeError) - if !ok { + var de *DecodeError + if !errors.As(original, &de) { return &DecodeError{ keys: []string{key}, wrapped: original, @@ -308,7 +323,7 @@ func (sc *StructCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val for { name, vr, err := dr.ReadElement() - if err == bsonrw.ErrEOD { + if errors.Is(err, bsonrw.ErrEOD) { break } if err != nil { @@ -391,12 +406,15 @@ func (sc *StructCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val return nil } -func isZero(v reflect.Value, omitZeroStruct bool) bool { +func isEmpty(v reflect.Value, omitZeroStruct bool) bool { kind := v.Kind() if (kind != reflect.Ptr || !v.IsNil()) && v.Type().Implements(tZeroer) { return v.Interface().(Zeroer).IsZero() } - if kind == reflect.Struct { + switch kind { + case reflect.Array, reflect.Map, reflect.Slice, reflect.String: + return v.Len() == 0 + case reflect.Struct: if !omitZeroStruct { return false } @@ -410,7 +428,7 @@ func isZero(v reflect.Value, omitZeroStruct bool) bool { if ff.PkgPath != "" && !ff.Anonymous { continue // Private field } - if !isZero(v.Field(i), omitZeroStruct) { + if !isEmpty(v.Field(i), omitZeroStruct) { return false } } diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/time_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/time_codec.go index 7b005a9958..22fb762c41 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/time_codec.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/time_codec.go @@ -23,12 +23,26 @@ const ( // TimeCodec is the Codec used for time.Time values. // -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// TimeCodec registered. +// Deprecated: TimeCodec will not be directly configurable in Go Driver 2.0. +// To configure the time.Time encode and decode behavior, use the configuration +// methods on a [go.mongodb.org/mongo-driver/bson.Encoder] or +// [go.mongodb.org/mongo-driver/bson.Decoder]. To configure the time.Time encode +// and decode behavior for a mongo.Client, use +// [go.mongodb.org/mongo-driver/mongo/options.ClientOptions.SetBSONOptions]. +// +// For example, to configure a mongo.Client to ..., use: +// +// opt := options.Client().SetBSONOptions(&options.BSONOptions{ +// UseLocalTimeZone: true, +// }) +// +// See the deprecation notice for each field in TimeCodec for the corresponding +// settings. type TimeCodec struct { // UseLocalTimeZone specifies if we should decode into the local time zone. Defaults to false. // - // Deprecated: Use bson.Decoder.UseLocalTimeZone instead. + // Deprecated: Use bson.Decoder.UseLocalTimeZone or options.BSONOptions.UseLocalTimeZone + // instead. UseLocalTimeZone bool } @@ -42,8 +56,8 @@ var ( // NewTimeCodec returns a TimeCodec with options opts. // -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// TimeCodec registered. +// Deprecated: NewTimeCodec will not be available in Go Driver 2.0. See +// [TimeCodec] for more details. func NewTimeCodec(opts ...*bsonoptions.TimeCodecOptions) *TimeCodec { timeOpt := bsonoptions.MergeTimeCodecOptions(opts...) diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/uint_codec.go b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/uint_codec.go index 7eb1069050..8525472769 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/uint_codec.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsoncodec/uint_codec.go @@ -18,13 +18,27 @@ import ( // UIntCodec is the Codec used for uint values. // -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// UIntCodec registered. +// Deprecated: UIntCodec will not be directly configurable in Go Driver 2.0. To +// configure the uint encode and decode behavior, use the configuration methods +// on a [go.mongodb.org/mongo-driver/bson.Encoder] or +// [go.mongodb.org/mongo-driver/bson.Decoder]. To configure the uint encode and +// decode behavior for a mongo.Client, use +// [go.mongodb.org/mongo-driver/mongo/options.ClientOptions.SetBSONOptions]. +// +// For example, to configure a mongo.Client to marshal Go uint values as the +// minimum BSON int size that can represent the value, use: +// +// opt := options.Client().SetBSONOptions(&options.BSONOptions{ +// IntMinSize: true, +// }) +// +// See the deprecation notice for each field in UIntCodec for the corresponding +// settings. type UIntCodec struct { // EncodeToMinSize causes EncodeValue to marshal Go uint values (excluding uint64) as the // minimum BSON int size (either 32-bit or 64-bit) that can represent the integer value. // - // Deprecated: Use bson.Encoder.IntMinSize instead. + // Deprecated: Use bson.Encoder.IntMinSize or options.BSONOptions.IntMinSize instead. EncodeToMinSize bool } @@ -38,8 +52,8 @@ var ( // NewUIntCodec returns a UIntCodec with options opts. // -// Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the -// UIntCodec registered. +// Deprecated: NewUIntCodec will not be available in Go Driver 2.0. See +// [UIntCodec] for more details. func NewUIntCodec(opts ...*bsonoptions.UIntCodecOptions) *UIntCodec { uintOpt := bsonoptions.MergeUIntCodecOptions(opts...) diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/copier.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/copier.go index 4d279b7fee..1e25570b85 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/copier.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/copier.go @@ -7,6 +7,7 @@ package bsonrw import ( + "errors" "fmt" "io" @@ -442,7 +443,7 @@ func (c Copier) copyArray(dst ValueWriter, src ValueReader) error { for { vr, err := ar.ReadValue() - if err == ErrEOA { + if errors.Is(err, ErrEOA) { break } if err != nil { @@ -466,7 +467,7 @@ func (c Copier) copyArray(dst ValueWriter, src ValueReader) error { func (c Copier) copyDocumentCore(dw DocumentWriter, dr DocumentReader) error { for { key, vr, err := dr.ReadElement() - if err == ErrEOD { + if errors.Is(err, ErrEOD) { break } if err != nil { diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_parser.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_parser.go index 54c76bf746..bb52a0ec3d 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_parser.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_parser.go @@ -313,7 +313,7 @@ func (ejp *extJSONParser) readValue(t bsontype.Type) (*extJSONValue, error) { // convert hex to bytes bytes, err := hex.DecodeString(uuidNoHyphens) if err != nil { - return nil, fmt.Errorf("$uuid value does not follow RFC 4122 format regarding hex bytes: %v", err) + return nil, fmt.Errorf("$uuid value does not follow RFC 4122 format regarding hex bytes: %w", err) } ejp.advanceState() diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_reader.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_reader.go index 2aca37a91f..59ddfc4485 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_reader.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/extjson_reader.go @@ -7,6 +7,7 @@ package bsonrw import ( + "errors" "fmt" "io" "sync" @@ -613,7 +614,7 @@ func (ejvr *extJSONValueReader) ReadElement() (string, ValueReader, error) { name, t, err := ejvr.p.readKey() if err != nil { - if err == ErrEOD { + if errors.Is(err, ErrEOD) { if ejvr.stack[ejvr.frame].mode == mCodeWithScope { _, err := ejvr.p.peekType() if err != nil { @@ -640,7 +641,7 @@ func (ejvr *extJSONValueReader) ReadValue() (ValueReader, error) { t, err := ejvr.p.peekType() if err != nil { - if err == ErrEOA { + if errors.Is(err, ErrEOA) { ejvr.pop() } diff --git a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/json_scanner.go b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/json_scanner.go index cd4843a3a4..43f3e4f383 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/json_scanner.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/bsonrw/json_scanner.go @@ -58,7 +58,7 @@ func (js *jsonScanner) nextToken() (*jsonToken, error) { c, err = js.readNextByte() } - if err == io.EOF { + if errors.Is(err, io.EOF) { return &jsonToken{t: jttEOF}, nil } else if err != nil { return nil, err @@ -198,7 +198,7 @@ func (js *jsonScanner) scanString() (*jsonToken, error) { for { c, err = js.readNextByte() if err != nil { - if err == io.EOF { + if errors.Is(err, io.EOF) { return nil, errors.New("end of input in JSON string") } return nil, err @@ -209,7 +209,7 @@ func (js *jsonScanner) scanString() (*jsonToken, error) { case '\\': c, err = js.readNextByte() if err != nil { - if err == io.EOF { + if errors.Is(err, io.EOF) { return nil, errors.New("end of input in JSON string") } return nil, err @@ -248,7 +248,7 @@ func (js *jsonScanner) scanString() (*jsonToken, error) { if utf16.IsSurrogate(rn) { c, err = js.readNextByte() if err != nil { - if err == io.EOF { + if errors.Is(err, io.EOF) { return nil, errors.New("end of input in JSON string") } return nil, err @@ -264,7 +264,7 @@ func (js *jsonScanner) scanString() (*jsonToken, error) { c, err = js.readNextByte() if err != nil { - if err == io.EOF { + if errors.Is(err, io.EOF) { return nil, errors.New("end of input in JSON string") } return nil, err @@ -325,17 +325,17 @@ func (js *jsonScanner) scanLiteral(first byte) (*jsonToken, error) { c5, err := js.readNextByte() - if bytes.Equal([]byte("true"), lit) && (isValueTerminator(c5) || err == io.EOF) { + if bytes.Equal([]byte("true"), lit) && (isValueTerminator(c5) || errors.Is(err, io.EOF)) { js.pos = int(math.Max(0, float64(js.pos-1))) return &jsonToken{t: jttBool, v: true, p: p}, nil - } else if bytes.Equal([]byte("null"), lit) && (isValueTerminator(c5) || err == io.EOF) { + } else if bytes.Equal([]byte("null"), lit) && (isValueTerminator(c5) || errors.Is(err, io.EOF)) { js.pos = int(math.Max(0, float64(js.pos-1))) return &jsonToken{t: jttNull, v: nil, p: p}, nil } else if bytes.Equal([]byte("fals"), lit) { if c5 == 'e' { c5, err = js.readNextByte() - if isValueTerminator(c5) || err == io.EOF { + if isValueTerminator(c5) || errors.Is(err, io.EOF) { js.pos = int(math.Max(0, float64(js.pos-1))) return &jsonToken{t: jttBool, v: false, p: p}, nil } @@ -384,7 +384,7 @@ func (js *jsonScanner) scanNumber(first byte) (*jsonToken, error) { for { c, err = js.readNextByte() - if err != nil && err != io.EOF { + if err != nil && !errors.Is(err, io.EOF) { return nil, err } @@ -413,7 +413,7 @@ func (js *jsonScanner) scanNumber(first byte) (*jsonToken, error) { case '}', ']', ',': s = nssDone default: - if isWhiteSpace(c) || err == io.EOF { + if isWhiteSpace(c) || errors.Is(err, io.EOF) { s = nssDone } else { s = nssInvalid @@ -430,7 +430,7 @@ func (js *jsonScanner) scanNumber(first byte) (*jsonToken, error) { case '}', ']', ',': s = nssDone default: - if isWhiteSpace(c) || err == io.EOF { + if isWhiteSpace(c) || errors.Is(err, io.EOF) { s = nssDone } else if isDigit(c) { s = nssSawIntegerDigits @@ -455,7 +455,7 @@ func (js *jsonScanner) scanNumber(first byte) (*jsonToken, error) { case '}', ']', ',': s = nssDone default: - if isWhiteSpace(c) || err == io.EOF { + if isWhiteSpace(c) || errors.Is(err, io.EOF) { s = nssDone } else if isDigit(c) { s = nssSawFractionDigits @@ -490,7 +490,7 @@ func (js *jsonScanner) scanNumber(first byte) (*jsonToken, error) { case '}', ']', ',': s = nssDone default: - if isWhiteSpace(c) || err == io.EOF { + if isWhiteSpace(c) || errors.Is(err, io.EOF) { s = nssDone } else if isDigit(c) { s = nssSawExponentDigits diff --git a/vendor/go.mongodb.org/mongo-driver/bson/doc.go b/vendor/go.mongodb.org/mongo-driver/bson/doc.go index 048b5eb998..af6098475e 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/doc.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/doc.go @@ -6,9 +6,9 @@ // Package bson is a library for reading, writing, and manipulating BSON. BSON is a binary serialization format used to // store documents and make remote procedure calls in MongoDB. The BSON specification is located at https://bsonspec.org. -// The BSON library handles marshalling and unmarshalling of values through a configurable codec system. For a description -// of the codec system and examples of registering custom codecs, see the bsoncodec package. For additional information and -// usage examples, check out the [Work with BSON] page in the Go Driver docs site. +// The BSON library handles marshaling and unmarshaling of values through a configurable codec system. For a description +// of the codec system and examples of registering custom codecs, see the bsoncodec package. For additional information +// and usage examples, check out the [Work with BSON] page in the Go Driver docs site. // // # Raw BSON // @@ -38,7 +38,7 @@ // bson.D{{"foo", "bar"}, {"hello", "world"}, {"pi", 3.14159}} // bson.M{"foo": "bar", "hello": "world", "pi": 3.14159} // -// When decoding BSON to a D or M, the following type mappings apply when unmarshalling: +// When decoding BSON to a D or M, the following type mappings apply when unmarshaling: // // 1. BSON int32 unmarshals to an int32. // 2. BSON int64 unmarshals to an int64. @@ -62,83 +62,78 @@ // 20. BSON DBPointer unmarshals to a primitive.DBPointer. // 21. BSON symbol unmarshals to a primitive.Symbol. // -// The above mappings also apply when marshalling a D or M to BSON. Some other useful marshalling mappings are: +// The above mappings also apply when marshaling a D or M to BSON. Some other useful marshaling mappings are: // // 1. time.Time marshals to a BSON datetime. // 2. int8, int16, and int32 marshal to a BSON int32. // 3. int marshals to a BSON int32 if the value is between math.MinInt32 and math.MaxInt32, inclusive, and a BSON int64 // otherwise. -// 4. int64 marshals to BSON int64. +// 4. int64 marshals to BSON int64 (unless [Encoder.IntMinSize] is set). // 5. uint8 and uint16 marshal to a BSON int32. -// 6. uint, uint32, and uint64 marshal to a BSON int32 if the value is between math.MinInt32 and math.MaxInt32, -// inclusive, and BSON int64 otherwise. -// 7. BSON null and undefined values will unmarshal into the zero value of a field (e.g. unmarshalling a BSON null or +// 6. uint, uint32, and uint64 marshal to a BSON int64 (unless [Encoder.IntMinSize] is set). +// 7. BSON null and undefined values will unmarshal into the zero value of a field (e.g. unmarshaling a BSON null or // undefined value into a string will yield the empty string.). // // # Structs // -// Structs can be marshalled/unmarshalled to/from BSON or Extended JSON. When transforming structs to/from BSON or Extended +// Structs can be marshaled/unmarshaled to/from BSON or Extended JSON. When transforming structs to/from BSON or Extended // JSON, the following rules apply: // -// 1. Only exported fields in structs will be marshalled or unmarshalled. +// 1. Only exported fields in structs will be marshaled or unmarshaled. // -// 2. When marshalling a struct, each field will be lowercased to generate the key for the corresponding BSON element. +// 2. When marshaling a struct, each field will be lowercased to generate the key for the corresponding BSON element. // For example, a struct field named "Foo" will generate key "foo". This can be overridden via a struct tag (e.g. // `bson:"fooField"` to generate key "fooField" instead). // -// 3. An embedded struct field is marshalled as a subdocument. The key will be the lowercased name of the field's type. +// 3. An embedded struct field is marshaled as a subdocument. The key will be the lowercased name of the field's type. // -// 4. A pointer field is marshalled as the underlying type if the pointer is non-nil. If the pointer is nil, it is -// marshalled as a BSON null value. +// 4. A pointer field is marshaled as the underlying type if the pointer is non-nil. If the pointer is nil, it is +// marshaled as a BSON null value. // -// 5. When unmarshalling, a field of type interface{} will follow the D/M type mappings listed above. BSON documents -// unmarshalled into an interface{} field will be unmarshalled as a D. +// 5. When unmarshaling, a field of type interface{} will follow the D/M type mappings listed above. BSON documents +// unmarshaled into an interface{} field will be unmarshaled as a D. // // The encoding of each struct field can be customized by the "bson" struct tag. // // This tag behavior is configurable, and different struct tag behavior can be configured by initializing a new -// bsoncodec.StructCodec with the desired tag parser and registering that StructCodec onto the Registry. By default, JSON tags -// are not honored, but that can be enabled by creating a StructCodec with JSONFallbackStructTagParser, like below: +// bsoncodec.StructCodec with the desired tag parser and registering that StructCodec onto the Registry. By default, JSON +// tags are not honored, but that can be enabled by creating a StructCodec with JSONFallbackStructTagParser, like below: // // Example: // // structcodec, _ := bsoncodec.NewStructCodec(bsoncodec.JSONFallbackStructTagParser) // // The bson tag gives the name of the field, possibly followed by a comma-separated list of options. -// The name may be empty in order to specify options without overriding the default field name. The following options can be used -// to configure behavior: -// -// 1. omitempty: If the omitempty struct tag is specified on a field, the field will not be marshalled if it is set to -// the zero value. Fields with language primitive types such as integers, booleans, and strings are considered empty if -// their value is equal to the zero value for the type (i.e. 0 for integers, false for booleans, and "" for strings). -// Slices, maps, and arrays are considered empty if they are of length zero. Interfaces and pointers are considered -// empty if their value is nil. By default, structs are only considered empty if the struct type implements the -// bsoncodec.Zeroer interface and the IsZero method returns true. Struct fields whose types do not implement Zeroer are -// never considered empty and will be marshalled as embedded documents. +// The name may be empty in order to specify options without overriding the default field name. The following options can +// be used to configure behavior: +// +// 1. omitempty: If the omitempty struct tag is specified on a field, the field will be omitted from the marshaling if +// the field has an empty value, defined as false, 0, a nil pointer, a nil interface value, and any empty array, +// slice, map, or string. // NOTE: It is recommended that this tag be used for all slice and map fields. // // 2. minsize: If the minsize struct tag is specified on a field of type int64, uint, uint32, or uint64 and the value of -// the field can fit in a signed int32, the field will be serialized as a BSON int32 rather than a BSON int64. For other -// types, this tag is ignored. +// the field can fit in a signed int32, the field will be serialized as a BSON int32 rather than a BSON int64. For +// other types, this tag is ignored. // -// 3. truncate: If the truncate struct tag is specified on a field with a non-float numeric type, BSON doubles unmarshalled -// into that field will be truncated at the decimal point. For example, if 3.14 is unmarshalled into a field of type int, -// it will be unmarshalled as 3. If this tag is not specified, the decoder will throw an error if the value cannot be -// decoded without losing precision. For float64 or non-numeric types, this tag is ignored. +// 3. truncate: If the truncate struct tag is specified on a field with a non-float numeric type, BSON doubles +// unmarshaled into that field will be truncated at the decimal point. For example, if 3.14 is unmarshaled into a +// field of type int, it will be unmarshaled as 3. If this tag is not specified, the decoder will throw an error if +// the value cannot be decoded without losing precision. For float64 or non-numeric types, this tag is ignored. // // 4. inline: If the inline struct tag is specified for a struct or map field, the field will be "flattened" when -// marshalling and "un-flattened" when unmarshalling. This means that all of the fields in that struct/map will be -// pulled up one level and will become top-level fields rather than being fields in a nested document. For example, if a -// map field named "Map" with value map[string]interface{}{"foo": "bar"} is inlined, the resulting document will be -// {"foo": "bar"} instead of {"map": {"foo": "bar"}}. There can only be one inlined map field in a struct. If there are -// duplicated fields in the resulting document when an inlined struct is marshalled, the inlined field will be overwritten. -// If there are duplicated fields in the resulting document when an inlined map is marshalled, an error will be returned. -// This tag can be used with fields that are pointers to structs. If an inlined pointer field is nil, it will not be -// marshalled. For fields that are not maps or structs, this tag is ignored. -// -// # Marshalling and Unmarshalling -// -// Manually marshalling and unmarshalling can be done with the Marshal and Unmarshal family of functions. +// marshaling and "un-flattened" when unmarshaling. This means that all of the fields in that struct/map will be +// pulled up one level and will become top-level fields rather than being fields in a nested document. For example, +// if a map field named "Map" with value map[string]interface{}{"foo": "bar"} is inlined, the resulting document will +// be {"foo": "bar"} instead of {"map": {"foo": "bar"}}. There can only be one inlined map field in a struct. If +// there are duplicated fields in the resulting document when an inlined struct is marshaled, the inlined field will +// be overwritten. If there are duplicated fields in the resulting document when an inlined map is marshaled, an +// error will be returned. This tag can be used with fields that are pointers to structs. If an inlined pointer field +// is nil, it will not be marshaled. For fields that are not maps or structs, this tag is ignored. +// +// # Marshaling and Unmarshaling +// +// Manually marshaling and unmarshaling can be done with the Marshal and Unmarshal family of functions. // // [Work with BSON]: https://www.mongodb.com/docs/drivers/go/current/fundamentals/bson/ package bson diff --git a/vendor/go.mongodb.org/mongo-driver/bson/primitive/decimal.go b/vendor/go.mongodb.org/mongo-driver/bson/primitive/decimal.go index 24ab58fc49..08c39514be 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/primitive/decimal.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/primitive/decimal.go @@ -164,9 +164,6 @@ func (d Decimal128) BigInt() (*big.Int, int, error) { // Would be handled by the logic below, but that's trivial and common. if high == 0 && low == 0 && exp == 0 { - if posSign { - return new(big.Int), 0, nil - } return new(big.Int), 0, nil } diff --git a/vendor/go.mongodb.org/mongo-driver/bson/primitive/objectid.go b/vendor/go.mongodb.org/mongo-driver/bson/primitive/objectid.go index 9bbaffac26..c130e3ff19 100644 --- a/vendor/go.mongodb.org/mongo-driver/bson/primitive/objectid.go +++ b/vendor/go.mongodb.org/mongo-driver/bson/primitive/objectid.go @@ -183,7 +183,7 @@ func processUniqueBytes() [5]byte { var b [5]byte _, err := io.ReadFull(rand.Reader, b[:]) if err != nil { - panic(fmt.Errorf("cannot initialize objectid package with crypto.rand.Reader: %v", err)) + panic(fmt.Errorf("cannot initialize objectid package with crypto.rand.Reader: %w", err)) } return b @@ -193,7 +193,7 @@ func readRandomUint32() uint32 { var b [4]byte _, err := io.ReadFull(rand.Reader, b[:]) if err != nil { - panic(fmt.Errorf("cannot initialize objectid package with crypto.rand.Reader: %v", err)) + panic(fmt.Errorf("cannot initialize objectid package with crypto.rand.Reader: %w", err)) } return (uint32(b[0]) << 0) | (uint32(b[1]) << 8) | (uint32(b[2]) << 16) | (uint32(b[3]) << 24) diff --git a/vendor/go.opentelemetry.io/collector/featuregate/registry.go b/vendor/go.opentelemetry.io/collector/featuregate/registry.go index b43a33e446..69486d623e 100644 --- a/vendor/go.opentelemetry.io/collector/featuregate/registry.go +++ b/vendor/go.opentelemetry.io/collector/featuregate/registry.go @@ -4,6 +4,7 @@ package featuregate // import "go.opentelemetry.io/collector/featuregate" import ( + "errors" "fmt" "net/url" "regexp" @@ -22,6 +23,11 @@ var ( idRegexp = regexp.MustCompile(`^[0-9a-zA-Z\.]*$`) ) +var ( + // ErrAlreadyRegistered is returned when adding a Gate that is already registered. + ErrAlreadyRegistered = errors.New("gate is already registered") +) + // GlobalRegistry returns the global Registry. func GlobalRegistry() *Registry { return globalRegistry @@ -157,7 +163,7 @@ func (r *Registry) Register(id string, stage Stage, opts ...RegisterOption) (*Ga } if _, loaded := r.gates.LoadOrStore(id, g); loaded { - return nil, fmt.Errorf("attempted to add pre-existing gate %q", id) + return nil, fmt.Errorf("failed to register %q: %w", id, ErrAlreadyRegistered) } return g, nil } @@ -194,7 +200,7 @@ func (r *Registry) Set(id string, enabled bool) error { // VisitAll visits all the gates in lexicographical order, calling fn for each. func (r *Registry) VisitAll(fn func(*Gate)) { var gates []*Gate - r.gates.Range(func(key, value any) bool { + r.gates.Range(func(_, value any) bool { gates = append(gates, value.(*Gate)) return true }) diff --git a/vendor/go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1/logs.pb.go b/vendor/go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1/logs.pb.go index 240a4d1905..65b11fbe28 100644 --- a/vendor/go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1/logs.pb.go +++ b/vendor/go.opentelemetry.io/collector/pdata/internal/data/protogen/logs/v1/logs.pb.go @@ -125,9 +125,11 @@ func (SeverityNumber) EnumDescriptor() ([]byte, []int) { return fileDescriptor_d1c030a3ec7e961e, []int{0} } -// LogRecordFlags is defined as a protobuf 'uint32' type and is to be used as -// bit-fields. Each non-zero value defined in this enum is a bit-mask. -// To extract the bit-field, for example, use an expression like: +// LogRecordFlags represents constants used to interpret the +// LogRecord.flags field, which is protobuf 'fixed32' type and is to +// be used as bit-fields. Each non-zero value defined in this enum is +// a bit-mask. To extract the bit-field, for example, use an +// expression like: // // (logRecord.flags & LOG_RECORD_FLAGS_TRACE_FLAGS_MASK) type LogRecordFlags int32 @@ -225,6 +227,9 @@ type ResourceLogs struct { Resource v1.Resource `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource"` // A list of ScopeLogs that originate from a resource. ScopeLogs []*ScopeLogs `protobuf:"bytes,2,rep,name=scope_logs,json=scopeLogs,proto3" json:"scope_logs,omitempty"` + // The Schema URL, if known. This is the identifier of the Schema that the resource data + // is recorded in. To learn more about Schema URL see + // https://opentelemetry.io/docs/specs/otel/schemas/#schema-url // This schema_url applies to the data in the "resource" field. It does not apply // to the data in the "scope_logs" field which have their own schema_url field. SchemaUrl string `protobuf:"bytes,3,opt,name=schema_url,json=schemaUrl,proto3" json:"schema_url,omitempty"` @@ -299,6 +304,9 @@ type ScopeLogs struct { Scope v11.InstrumentationScope `protobuf:"bytes,1,opt,name=scope,proto3" json:"scope"` // A list of log records. LogRecords []*LogRecord `protobuf:"bytes,2,rep,name=log_records,json=logRecords,proto3" json:"log_records,omitempty"` + // The Schema URL, if known. This is the identifier of the Schema that the log data + // is recorded in. To learn more about Schema URL see + // https://opentelemetry.io/docs/specs/otel/schemas/#schema-url // This schema_url applies to all logs in the "logs" field. SchemaUrl string `protobuf:"bytes,3,opt,name=schema_url,json=schemaUrl,proto3" json:"schema_url,omitempty"` } diff --git a/vendor/go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1/metrics.pb.go b/vendor/go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1/metrics.pb.go index 09cd8e712e..4ef4f4d5f6 100644 --- a/vendor/go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1/metrics.pb.go +++ b/vendor/go.opentelemetry.io/collector/pdata/internal/data/protogen/metrics/v1/metrics.pb.go @@ -223,6 +223,9 @@ type ResourceMetrics struct { Resource v1.Resource `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource"` // A list of metrics that originate from a resource. ScopeMetrics []*ScopeMetrics `protobuf:"bytes,2,rep,name=scope_metrics,json=scopeMetrics,proto3" json:"scope_metrics,omitempty"` + // The Schema URL, if known. This is the identifier of the Schema that the resource data + // is recorded in. To learn more about Schema URL see + // https://opentelemetry.io/docs/specs/otel/schemas/#schema-url // This schema_url applies to the data in the "resource" field. It does not apply // to the data in the "scope_metrics" field which have their own schema_url field. SchemaUrl string `protobuf:"bytes,3,opt,name=schema_url,json=schemaUrl,proto3" json:"schema_url,omitempty"` @@ -297,6 +300,9 @@ type ScopeMetrics struct { Scope v11.InstrumentationScope `protobuf:"bytes,1,opt,name=scope,proto3" json:"scope"` // A list of metrics that originate from an instrumentation library. Metrics []*Metric `protobuf:"bytes,2,rep,name=metrics,proto3" json:"metrics,omitempty"` + // The Schema URL, if known. This is the identifier of the Schema that the metric data + // is recorded in. To learn more about Schema URL see + // https://opentelemetry.io/docs/specs/otel/schemas/#schema-url // This schema_url applies to all metrics in the "metrics" field. SchemaUrl string `protobuf:"bytes,3,opt,name=schema_url,json=schemaUrl,proto3" json:"schema_url,omitempty"` } @@ -443,7 +449,7 @@ func (m *ScopeMetrics) GetSchemaUrl() string { // when the start time is truly unknown, setting StartTimeUnixNano is // strongly encouraged. type Metric struct { - // name of the metric, including its DNS name prefix. It must be unique. + // name of the metric. Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // description of the metric, which can be used in documentation. Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` diff --git a/vendor/go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1/trace.pb.go b/vendor/go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1/trace.pb.go index b48ce22602..71f32df0f7 100644 --- a/vendor/go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1/trace.pb.go +++ b/vendor/go.opentelemetry.io/collector/pdata/internal/data/protogen/trace/v1/trace.pb.go @@ -29,6 +29,48 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package +// SpanFlags represents constants used to interpret the +// Span.flags field, which is protobuf 'fixed32' type and is to +// be used as bit-fields. Each non-zero value defined in this enum is +// a bit-mask. To extract the bit-field, for example, use an +// expression like: +// +// (span.flags & SPAN_FLAGS_TRACE_FLAGS_MASK) +// +// See https://www.w3.org/TR/trace-context-2/#trace-flags for the flag definitions. +// +// Note that Span flags were introduced in version 1.1 of the +// OpenTelemetry protocol. Older Span producers do not set this +// field, consequently consumers should not rely on the absence of a +// particular flag bit to indicate the presence of a particular feature. +type SpanFlags int32 + +const ( + // The zero value for the enum. Should not be used for comparisons. + // Instead use bitwise "and" with the appropriate mask as shown above. + SpanFlags_SPAN_FLAGS_DO_NOT_USE SpanFlags = 0 + // Bits 0-7 are used for trace flags. + SpanFlags_SPAN_FLAGS_TRACE_FLAGS_MASK SpanFlags = 255 +) + +var SpanFlags_name = map[int32]string{ + 0: "SPAN_FLAGS_DO_NOT_USE", + 255: "SPAN_FLAGS_TRACE_FLAGS_MASK", +} + +var SpanFlags_value = map[string]int32{ + "SPAN_FLAGS_DO_NOT_USE": 0, + "SPAN_FLAGS_TRACE_FLAGS_MASK": 255, +} + +func (x SpanFlags) String() string { + return proto.EnumName(SpanFlags_name, int32(x)) +} + +func (SpanFlags) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_5c407ac9c675a601, []int{0} +} + // SpanKind is the type of span. Can be used to specify additional relationships between spans // in addition to a parent/child relationship. type Span_SpanKind int32 @@ -183,6 +225,9 @@ type ResourceSpans struct { Resource v1.Resource `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource"` // A list of ScopeSpans that originate from a resource. ScopeSpans []*ScopeSpans `protobuf:"bytes,2,rep,name=scope_spans,json=scopeSpans,proto3" json:"scope_spans,omitempty"` + // The Schema URL, if known. This is the identifier of the Schema that the resource data + // is recorded in. To learn more about Schema URL see + // https://opentelemetry.io/docs/specs/otel/schemas/#schema-url // This schema_url applies to the data in the "resource" field. It does not apply // to the data in the "scope_spans" field which have their own schema_url field. SchemaUrl string `protobuf:"bytes,3,opt,name=schema_url,json=schemaUrl,proto3" json:"schema_url,omitempty"` @@ -257,6 +302,9 @@ type ScopeSpans struct { Scope v11.InstrumentationScope `protobuf:"bytes,1,opt,name=scope,proto3" json:"scope"` // A list of Spans that originate from an instrumentation scope. Spans []*Span `protobuf:"bytes,2,rep,name=spans,proto3" json:"spans,omitempty"` + // The Schema URL, if known. This is the identifier of the Schema that the span data + // is recorded in. To learn more about Schema URL see + // https://opentelemetry.io/docs/specs/otel/schemas/#schema-url // This schema_url applies to all spans and span events in the "spans" field. SchemaUrl string `protobuf:"bytes,3,opt,name=schema_url,json=schemaUrl,proto3" json:"schema_url,omitempty"` } @@ -340,6 +388,21 @@ type Span struct { // The `span_id` of this span's parent span. If this is a root span, then this // field must be empty. The ID is an 8-byte array. ParentSpanId go_opentelemetry_io_collector_pdata_internal_data.SpanID `protobuf:"bytes,4,opt,name=parent_span_id,json=parentSpanId,proto3,customtype=go.opentelemetry.io/collector/pdata/internal/data.SpanID" json:"parent_span_id"` + // Flags, a bit field. 8 least significant bits are the trace + // flags as defined in W3C Trace Context specification. Readers + // MUST not assume that 24 most significant bits will be zero. + // To read the 8-bit W3C trace flag, use `flags & SPAN_FLAGS_TRACE_FLAGS_MASK`. + // + // When creating span messages, if the message is logically forwarded from another source + // with an equivalent flags fields (i.e., usually another OTLP span message), the field SHOULD + // be copied as-is. If creating from a source that does not have an equivalent flags field + // (such as a runtime representation of an OpenTelemetry span), the high 24 bits MUST + // be set to zero. + // + // [Optional]. + // + // See https://www.w3.org/TR/trace-context-2/#trace-flags for the flag definitions. + Flags uint32 `protobuf:"fixed32,16,opt,name=flags,proto3" json:"flags,omitempty"` // A description of the span's operation. // // For example, the name can be a qualified method name or a file name @@ -443,6 +506,13 @@ func (m *Span) GetTraceState() string { return "" } +func (m *Span) GetFlags() uint32 { + if m != nil { + return m.Flags + } + return 0 +} + func (m *Span) GetName() string { if m != nil { return m.Name @@ -617,6 +687,15 @@ type Span_Link struct { // dropped_attributes_count is the number of dropped attributes. If the value is 0, // then no attributes were dropped. DroppedAttributesCount uint32 `protobuf:"varint,5,opt,name=dropped_attributes_count,json=droppedAttributesCount,proto3" json:"dropped_attributes_count,omitempty"` + // Flags, a bit field. 8 least significant bits are the trace + // flags as defined in W3C Trace Context specification. Readers + // MUST not assume that 24 most significant bits will be zero. + // When creating new spans, the most-significant 24-bits MUST be + // zero. To read the 8-bit W3C trace flag (use flags & + // SPAN_FLAGS_TRACE_FLAGS_MASK). [Optional]. + // + // See https://www.w3.org/TR/trace-context-2/#trace-flags for the flag definitions. + Flags uint32 `protobuf:"fixed32,6,opt,name=flags,proto3" json:"flags,omitempty"` } func (m *Span_Link) Reset() { *m = Span_Link{} } @@ -673,6 +752,13 @@ func (m *Span_Link) GetDroppedAttributesCount() uint32 { return 0 } +func (m *Span_Link) GetFlags() uint32 { + if m != nil { + return m.Flags + } + return 0 +} + // The Status type defines a logical error model that is suitable for different // programming environments, including REST APIs and RPC APIs. type Status struct { @@ -730,6 +816,7 @@ func (m *Status) GetCode() Status_StatusCode { } func init() { + proto.RegisterEnum("opentelemetry.proto.trace.v1.SpanFlags", SpanFlags_name, SpanFlags_value) proto.RegisterEnum("opentelemetry.proto.trace.v1.Span_SpanKind", Span_SpanKind_name, Span_SpanKind_value) proto.RegisterEnum("opentelemetry.proto.trace.v1.Status_StatusCode", Status_StatusCode_name, Status_StatusCode_value) proto.RegisterType((*TracesData)(nil), "opentelemetry.proto.trace.v1.TracesData") @@ -746,70 +833,75 @@ func init() { } var fileDescriptor_5c407ac9c675a601 = []byte{ - // 1007 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x56, 0x4f, 0x6f, 0xe3, 0x44, - 0x14, 0xcf, 0xa4, 0x4e, 0xda, 0xbe, 0xb6, 0x59, 0x77, 0xe8, 0x56, 0xa6, 0x5a, 0xd2, 0x28, 0x5a, - 0x89, 0xc0, 0x4a, 0x09, 0xed, 0x5e, 0xca, 0x01, 0xb1, 0x6d, 0x62, 0x24, 0xd3, 0x6e, 0x52, 0x8d, - 0x93, 0x4a, 0x20, 0x24, 0x33, 0x1b, 0x0f, 0xc5, 0x6a, 0x32, 0xb6, 0xec, 0x49, 0xb5, 0x7b, 0xe3, - 0x23, 0x70, 0xe5, 0x13, 0x20, 0xc1, 0x9d, 0x1b, 0xf7, 0x15, 0xa7, 0x3d, 0x22, 0x0e, 0x2b, 0xd4, - 0x5e, 0xe0, 0x5b, 0xa0, 0x99, 0xb1, 0xf3, 0xa7, 0xaa, 0x92, 0xad, 0xc4, 0x5e, 0xf6, 0xd2, 0x4e, - 0xde, 0x7b, 0xbf, 0x3f, 0xef, 0xcd, 0xb3, 0x65, 0xa8, 0x85, 0x11, 0xe3, 0x82, 0x0d, 0xd8, 0x90, - 0x89, 0xf8, 0x45, 0x23, 0x8a, 0x43, 0x11, 0x36, 0x44, 0x4c, 0xfb, 0xac, 0x71, 0xb9, 0xa7, 0x0f, - 0x75, 0x15, 0xc4, 0x0f, 0x66, 0x2a, 0x75, 0xb0, 0xae, 0x0b, 0x2e, 0xf7, 0x76, 0xb6, 0xce, 0xc3, - 0xf3, 0x50, 0xa3, 0xe5, 0x49, 0xa7, 0x77, 0x3e, 0xbe, 0x8d, 0xbd, 0x1f, 0x0e, 0x87, 0x21, 0x97, - 0xf4, 0xfa, 0x94, 0xd6, 0xd6, 0x6f, 0xab, 0x8d, 0x59, 0x12, 0x8e, 0x62, 0x6d, 0x26, 0x3b, 0xeb, - 0xfa, 0xea, 0xb7, 0x00, 0x5d, 0xa9, 0x9e, 0xb4, 0xa8, 0xa0, 0x98, 0x40, 0x29, 0xcb, 0x7b, 0x49, - 0x44, 0x79, 0x62, 0xa1, 0xca, 0x52, 0x6d, 0x6d, 0xff, 0x51, 0x7d, 0x9e, 0xed, 0x3a, 0x49, 0x31, - 0xae, 0x84, 0x90, 0x8d, 0x78, 0xfa, 0x67, 0xf5, 0xe7, 0x3c, 0x6c, 0xcc, 0x14, 0x60, 0x0f, 0xb6, - 0x7d, 0x16, 0xc5, 0xac, 0x4f, 0x05, 0xf3, 0xbd, 0xa4, 0x1f, 0x46, 0x99, 0xda, 0x3f, 0xcb, 0x4a, - 0xae, 0x36, 0x5f, 0xce, 0x95, 0x08, 0xad, 0xb5, 0x35, 0x21, 0x9a, 0x44, 0xf1, 0x31, 0xac, 0x64, - 0x1e, 0x2c, 0x54, 0x41, 0xb5, 0xb5, 0xfd, 0x8f, 0x6e, 0x65, 0x1c, 0xcf, 0x62, 0xaa, 0x87, 0x23, - 0xe3, 0xe5, 0xeb, 0xdd, 0x1c, 0x19, 0x13, 0x60, 0x07, 0xd6, 0xa6, 0x2d, 0xe6, 0xef, 0xe8, 0x10, - 0x92, 0x89, 0xaf, 0x0f, 0x00, 0x92, 0xfe, 0xf7, 0x6c, 0x48, 0xbd, 0x51, 0x3c, 0xb0, 0x96, 0x2a, - 0xa8, 0xb6, 0x4a, 0x56, 0x75, 0xa4, 0x17, 0x0f, 0xaa, 0xbf, 0x21, 0x80, 0xa9, 0x2e, 0x3a, 0x50, - 0x50, 0xd8, 0xb4, 0x85, 0xc7, 0xb7, 0x4a, 0xa6, 0x97, 0x7f, 0xb9, 0x57, 0x77, 0x78, 0x22, 0xe2, - 0xd1, 0x90, 0x71, 0x41, 0x45, 0x10, 0x72, 0x45, 0x94, 0x36, 0xa3, 0x79, 0xf0, 0x01, 0x14, 0xa6, - 0x7b, 0xa8, 0x2e, 0xe8, 0x21, 0xa2, 0x9c, 0x68, 0xc0, 0x22, 0xe3, 0x3f, 0x6c, 0x80, 0x21, 0xcb, - 0xf1, 0x37, 0xb0, 0xa2, 0xf0, 0x5e, 0xe0, 0x2b, 0xd7, 0xeb, 0x47, 0x87, 0xd2, 0xc0, 0x5f, 0xaf, - 0x77, 0x3f, 0x3d, 0x0f, 0x6f, 0xc8, 0x05, 0x72, 0x87, 0x07, 0x03, 0xd6, 0x17, 0x61, 0xdc, 0x88, - 0x7c, 0x2a, 0x68, 0x23, 0xe0, 0x82, 0xc5, 0x9c, 0x0e, 0x1a, 0xf2, 0x57, 0x5d, 0xed, 0xa5, 0xd3, - 0x22, 0xcb, 0x8a, 0xd2, 0xf1, 0xf1, 0x57, 0xb0, 0x2c, 0xed, 0x48, 0xf2, 0xbc, 0x22, 0x7f, 0x92, - 0x92, 0x1f, 0xdc, 0x9d, 0x5c, 0xda, 0x75, 0x5a, 0xa4, 0x28, 0x09, 0x1d, 0x1f, 0xef, 0xc2, 0x9a, - 0x36, 0x9e, 0x08, 0x2a, 0x58, 0xda, 0x21, 0xa8, 0x90, 0x2b, 0x23, 0xf8, 0x3b, 0x28, 0x45, 0x34, - 0x66, 0x5c, 0x78, 0x99, 0x05, 0xe3, 0x7f, 0xb2, 0xb0, 0xae, 0x79, 0x5d, 0x6d, 0x04, 0x83, 0xc1, - 0xe9, 0x90, 0x59, 0x05, 0xe5, 0x40, 0x9d, 0xf1, 0xe7, 0x60, 0x5c, 0x04, 0xdc, 0xb7, 0x8a, 0x15, - 0x54, 0x2b, 0x2d, 0x7a, 0x16, 0x25, 0x8f, 0xfa, 0x73, 0x1c, 0x70, 0x9f, 0x28, 0x20, 0x6e, 0xc0, - 0x56, 0x22, 0x68, 0x2c, 0x3c, 0x11, 0x0c, 0x99, 0x37, 0xe2, 0xc1, 0x73, 0x8f, 0x53, 0x1e, 0x5a, - 0xcb, 0x15, 0x54, 0x2b, 0x92, 0x4d, 0x95, 0xeb, 0x06, 0x43, 0xd6, 0xe3, 0xc1, 0xf3, 0x36, 0xe5, - 0x21, 0x7e, 0x04, 0x98, 0x71, 0xff, 0x66, 0xf9, 0x8a, 0x2a, 0xbf, 0xc7, 0xb8, 0x3f, 0x53, 0xfc, - 0x14, 0x80, 0x0a, 0x11, 0x07, 0xcf, 0x46, 0x82, 0x25, 0xd6, 0xaa, 0xda, 0xad, 0x0f, 0x17, 0x2c, - 0xeb, 0x31, 0x7b, 0x71, 0x46, 0x07, 0xa3, 0x6c, 0x41, 0xa7, 0x08, 0xf0, 0x01, 0x58, 0x7e, 0x1c, - 0x46, 0x11, 0xf3, 0xbd, 0x49, 0xd4, 0xeb, 0x87, 0x23, 0x2e, 0x2c, 0xa8, 0xa0, 0xda, 0x06, 0xd9, - 0x4e, 0xf3, 0x87, 0xe3, 0x74, 0x53, 0x66, 0xf1, 0x13, 0x28, 0xb2, 0x4b, 0xc6, 0x45, 0x62, 0xad, - 0xbd, 0xd1, 0x43, 0x2a, 0x27, 0x65, 0x4b, 0x00, 0x49, 0x71, 0xf8, 0x13, 0xd8, 0xca, 0xb4, 0x75, - 0x24, 0xd5, 0x5d, 0x57, 0xba, 0x38, 0xcd, 0x29, 0x4c, 0xaa, 0xf9, 0x19, 0x14, 0x06, 0x01, 0xbf, - 0x48, 0xac, 0x8d, 0x39, 0x7d, 0xcf, 0x4a, 0x9e, 0x04, 0xfc, 0x82, 0x68, 0x14, 0xae, 0xc3, 0x7b, - 0x99, 0xa0, 0x0a, 0xa4, 0x7a, 0x25, 0xa5, 0xb7, 0x99, 0xa6, 0x24, 0x20, 0x95, 0x3b, 0x82, 0xa2, - 0xdc, 0xd0, 0x51, 0x62, 0xdd, 0x53, 0x2f, 0x85, 0x87, 0x0b, 0xf4, 0x54, 0x6d, 0x3a, 0xe4, 0x14, - 0xb9, 0xf3, 0x07, 0x82, 0x82, 0x6a, 0x01, 0x3f, 0x84, 0xd2, 0x8d, 0x2b, 0x46, 0xea, 0x8a, 0xd7, - 0xc5, 0xf4, 0xfd, 0x66, 0x2b, 0x99, 0x9f, 0x5a, 0xc9, 0xd9, 0x3b, 0x5f, 0x7a, 0x9b, 0x77, 0x6e, - 0xcc, 0xbb, 0xf3, 0x9d, 0x7f, 0xf3, 0x60, 0xc8, 0xf9, 0xbc, 0xc3, 0xaf, 0x9e, 0xd9, 0x59, 0x1b, - 0x6f, 0x73, 0xd6, 0x85, 0x79, 0xb3, 0xae, 0xfe, 0x84, 0x60, 0x25, 0x7b, 0xb3, 0xe0, 0xf7, 0xe1, - 0xbe, 0x7b, 0x7a, 0xd8, 0xf6, 0x8e, 0x9d, 0x76, 0xcb, 0xeb, 0xb5, 0xdd, 0x53, 0xbb, 0xe9, 0x7c, - 0xe1, 0xd8, 0x2d, 0x33, 0x87, 0xb7, 0x01, 0x4f, 0x52, 0x4e, 0xbb, 0x6b, 0x93, 0xf6, 0xe1, 0x89, - 0x89, 0xf0, 0x16, 0x98, 0x93, 0xb8, 0x6b, 0x93, 0x33, 0x9b, 0x98, 0xf9, 0xd9, 0x68, 0xf3, 0xc4, - 0xb1, 0xdb, 0x5d, 0x73, 0x69, 0x96, 0xe3, 0x94, 0x74, 0x5a, 0xbd, 0xa6, 0x4d, 0x4c, 0x63, 0x36, - 0xde, 0xec, 0xb4, 0xdd, 0xde, 0x53, 0x9b, 0x98, 0x85, 0xea, 0xef, 0x08, 0x8a, 0x7a, 0xdb, 0xb1, - 0x05, 0xcb, 0x43, 0x96, 0x24, 0xf4, 0x3c, 0x5b, 0xd9, 0xec, 0x27, 0x6e, 0x82, 0xd1, 0x0f, 0x7d, - 0x3d, 0xe3, 0xd2, 0x7e, 0xe3, 0x4d, 0x9e, 0x9d, 0xf4, 0x5f, 0x33, 0xf4, 0x19, 0x51, 0xe0, 0x6a, - 0x1b, 0x60, 0x12, 0xc3, 0xf7, 0x61, 0xd3, 0xed, 0x1e, 0x76, 0x7b, 0xae, 0xd7, 0xec, 0xb4, 0x6c, - 0x39, 0x08, 0xbb, 0x6b, 0xe6, 0x30, 0x86, 0xd2, 0x74, 0xb8, 0x73, 0x6c, 0xa2, 0x9b, 0xa5, 0x36, - 0x21, 0x1d, 0x62, 0xe6, 0xbf, 0x34, 0x56, 0x90, 0x99, 0x3f, 0xfa, 0x15, 0xbd, 0xbc, 0x2a, 0xa3, - 0x57, 0x57, 0x65, 0xf4, 0xf7, 0x55, 0x19, 0xfd, 0x78, 0x5d, 0xce, 0xbd, 0xba, 0x2e, 0xe7, 0xfe, - 0xbc, 0x2e, 0xe7, 0x60, 0x37, 0x08, 0xe7, 0x3a, 0x3d, 0xd2, 0x5f, 0x70, 0xa7, 0x32, 0x78, 0x8a, - 0xbe, 0x6e, 0xde, 0x79, 0x23, 0xf5, 0x57, 0xe2, 0x39, 0xe3, 0xe3, 0x4f, 0xd6, 0x5f, 0xf2, 0x0f, - 0x3a, 0x11, 0xe3, 0xdd, 0x31, 0x85, 0x22, 0xd7, 0x8f, 0x45, 0xfd, 0x6c, 0xef, 0x59, 0x51, 0x21, - 0x1e, 0xff, 0x17, 0x00, 0x00, 0xff, 0xff, 0xbb, 0xe9, 0x90, 0xbc, 0xf8, 0x0a, 0x00, 0x00, + // 1073 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x56, 0x4f, 0x6f, 0x1b, 0x45, + 0x14, 0xf7, 0x38, 0xfe, 0x93, 0xbc, 0x24, 0xee, 0x76, 0x70, 0xa3, 0x25, 0x14, 0xc7, 0xb2, 0x2a, + 0x61, 0x5a, 0xc9, 0x26, 0xe9, 0x25, 0x1c, 0x10, 0x75, 0xec, 0x0d, 0x18, 0x27, 0x76, 0x34, 0x6b, + 0x47, 0x02, 0x21, 0x2d, 0x5b, 0xef, 0xd4, 0xac, 0x62, 0xcf, 0xae, 0x76, 0xc7, 0x51, 0xfb, 0x2d, + 0xb8, 0xf2, 0x09, 0x90, 0x80, 0x33, 0x37, 0xee, 0x15, 0xa7, 0x1e, 0x11, 0x87, 0x0a, 0x25, 0x17, + 0xbe, 0x45, 0xd1, 0xcc, 0xec, 0xda, 0xeb, 0x28, 0x72, 0x1a, 0x89, 0x5e, 0xb8, 0x24, 0x33, 0xef, + 0xcf, 0xef, 0xf7, 0x7b, 0x6f, 0xde, 0x8c, 0x17, 0xaa, 0x9e, 0x4f, 0x19, 0xa7, 0x63, 0x3a, 0xa1, + 0x3c, 0x78, 0x51, 0xf7, 0x03, 0x8f, 0x7b, 0x75, 0x1e, 0xd8, 0x43, 0x5a, 0x3f, 0xdf, 0x55, 0x8b, + 0x9a, 0x34, 0xe2, 0xfb, 0x0b, 0x91, 0xca, 0x58, 0x53, 0x01, 0xe7, 0xbb, 0xdb, 0xc5, 0x91, 0x37, + 0xf2, 0x54, 0xb6, 0x58, 0x29, 0xf7, 0xf6, 0xc3, 0xeb, 0xd0, 0x87, 0xde, 0x64, 0xe2, 0x31, 0x01, + 0xaf, 0x56, 0x51, 0x6c, 0xed, 0xba, 0xd8, 0x80, 0x86, 0xde, 0x34, 0x50, 0x62, 0xe2, 0xb5, 0x8a, + 0xaf, 0x7c, 0x07, 0xd0, 0x17, 0xec, 0x61, 0xcb, 0xe6, 0x36, 0x26, 0x50, 0x88, 0xfd, 0x56, 0xe8, + 0xdb, 0x2c, 0xd4, 0x51, 0x79, 0xa5, 0xba, 0xbe, 0xf7, 0xa8, 0xb6, 0x4c, 0x76, 0x8d, 0x44, 0x39, + 0xa6, 0x48, 0x21, 0x9b, 0x41, 0x72, 0x5b, 0xf9, 0x29, 0x0d, 0x9b, 0x0b, 0x01, 0xd8, 0x82, 0x2d, + 0x87, 0xfa, 0x01, 0x1d, 0xda, 0x9c, 0x3a, 0x56, 0x38, 0xf4, 0xfc, 0x98, 0xed, 0x9f, 0xbc, 0xa4, + 0xab, 0x2e, 0xa7, 0x33, 0x45, 0x86, 0xe2, 0x2a, 0xce, 0x81, 0xe6, 0x56, 0xdc, 0x81, 0xd5, 0x58, + 0x83, 0x8e, 0xca, 0xa8, 0xba, 0xbe, 0xf7, 0xf1, 0xb5, 0x88, 0xb3, 0x5e, 0x24, 0x6a, 0x38, 0xc8, + 0xbc, 0x7c, 0xbd, 0x93, 0x22, 0x33, 0x00, 0xdc, 0x86, 0xf5, 0xa4, 0xc4, 0xf4, 0x2d, 0x15, 0x42, + 0x38, 0xd7, 0xf5, 0x21, 0x40, 0x38, 0xfc, 0x9e, 0x4e, 0x6c, 0x6b, 0x1a, 0x8c, 0xf5, 0x95, 0x32, + 0xaa, 0xae, 0x91, 0x35, 0x65, 0x19, 0x04, 0xe3, 0xca, 0x6f, 0x08, 0x20, 0x51, 0x45, 0x0f, 0xb2, + 0x32, 0x37, 0x2a, 0xe1, 0xf1, 0xb5, 0x94, 0xd1, 0xe1, 0x9f, 0xef, 0xd6, 0xda, 0x2c, 0xe4, 0xc1, + 0x74, 0x42, 0x19, 0xb7, 0xb9, 0xeb, 0x31, 0x09, 0x14, 0x15, 0xa3, 0x70, 0xf0, 0x3e, 0x64, 0x93, + 0x35, 0x54, 0x6e, 0xa8, 0xc1, 0xb7, 0x19, 0x51, 0x09, 0x37, 0x09, 0xff, 0x75, 0x13, 0x32, 0x22, + 0x1c, 0x7f, 0x0b, 0xab, 0x32, 0xdf, 0x72, 0x1d, 0xa9, 0x7a, 0xe3, 0xa0, 0x21, 0x04, 0xfc, 0xf5, + 0x7a, 0xe7, 0xd3, 0x91, 0x77, 0x85, 0xce, 0x15, 0x33, 0x3c, 0x1e, 0xd3, 0x21, 0xf7, 0x82, 0xba, + 0xef, 0xd8, 0xdc, 0xae, 0xbb, 0x8c, 0xd3, 0x80, 0xd9, 0xe3, 0xba, 0xd8, 0xd5, 0xe4, 0x5c, 0xb6, + 0x5b, 0x24, 0x2f, 0x21, 0xdb, 0x0e, 0xfe, 0x1a, 0xf2, 0x42, 0x8e, 0x00, 0x4f, 0x4b, 0xf0, 0x27, + 0x11, 0xf8, 0xfe, 0xed, 0xc1, 0x85, 0xdc, 0x76, 0x8b, 0xe4, 0x04, 0x60, 0xdb, 0xc1, 0x3b, 0xb0, + 0xae, 0x84, 0x87, 0xdc, 0xe6, 0x34, 0xaa, 0x10, 0xa4, 0xc9, 0x14, 0x16, 0xfc, 0x0c, 0x0a, 0xbe, + 0x1d, 0x50, 0xc6, 0xad, 0x58, 0x42, 0xe6, 0x3f, 0x92, 0xb0, 0xa1, 0x70, 0x4d, 0x25, 0xa4, 0x08, + 0xd9, 0x67, 0x63, 0x7b, 0x14, 0xea, 0x5a, 0x19, 0x55, 0xf3, 0x44, 0x6d, 0x30, 0x86, 0x0c, 0xb3, + 0x27, 0x54, 0xcf, 0x4a, 0x5d, 0x72, 0x8d, 0x3f, 0x87, 0xcc, 0x99, 0xcb, 0x1c, 0x3d, 0x57, 0x46, + 0xd5, 0xc2, 0x4d, 0x37, 0x54, 0xa0, 0xcb, 0x3f, 0x1d, 0x97, 0x39, 0x44, 0x26, 0xe2, 0x3a, 0x14, + 0x43, 0x6e, 0x07, 0xdc, 0xe2, 0xee, 0x84, 0x5a, 0x53, 0xe6, 0x3e, 0xb7, 0x98, 0xcd, 0x3c, 0x3d, + 0x5f, 0x46, 0xd5, 0x1c, 0xb9, 0x2b, 0x7d, 0x7d, 0x77, 0x42, 0x07, 0xcc, 0x7d, 0xde, 0xb5, 0x99, + 0x87, 0x1f, 0x01, 0xa6, 0xcc, 0xb9, 0x1a, 0xbe, 0x2a, 0xc3, 0xef, 0x50, 0xe6, 0x2c, 0x04, 0x1f, + 0x03, 0xd8, 0x9c, 0x07, 0xee, 0xd3, 0x29, 0xa7, 0xa1, 0xbe, 0x26, 0x27, 0xee, 0xa3, 0x1b, 0x46, + 0xb8, 0x43, 0x5f, 0x9c, 0xda, 0xe3, 0x69, 0x3c, 0xb6, 0x09, 0x00, 0xbc, 0x0f, 0xba, 0x13, 0x78, + 0xbe, 0x4f, 0x1d, 0x6b, 0x6e, 0xb5, 0x86, 0xde, 0x94, 0x71, 0x1d, 0xca, 0xa8, 0xba, 0x49, 0xb6, + 0x22, 0x7f, 0x63, 0xe6, 0x6e, 0x0a, 0x2f, 0x7e, 0x02, 0x39, 0x7a, 0x4e, 0x19, 0x0f, 0xf5, 0xf5, + 0xb7, 0xba, 0xba, 0xa2, 0x53, 0x86, 0x48, 0x20, 0x51, 0x1e, 0xfe, 0x04, 0x8a, 0x31, 0xb7, 0xb2, + 0x44, 0xbc, 0x1b, 0x92, 0x17, 0x47, 0x3e, 0x99, 0x13, 0x71, 0x7e, 0x06, 0xd9, 0xb1, 0xcb, 0xce, + 0x42, 0x7d, 0x73, 0x49, 0xdd, 0x8b, 0x94, 0x47, 0x2e, 0x3b, 0x23, 0x2a, 0x0b, 0xd7, 0xe0, 0xbd, + 0x98, 0x50, 0x1a, 0x22, 0xbe, 0x82, 0xe4, 0xbb, 0x1b, 0xb9, 0x44, 0x42, 0x44, 0x77, 0x00, 0x39, + 0x31, 0xb7, 0xd3, 0x50, 0xbf, 0x23, 0x9f, 0x8a, 0x07, 0x37, 0xf0, 0xc9, 0xd8, 0xa8, 0xc9, 0x51, + 0xe6, 0xf6, 0x1f, 0x08, 0xb2, 0xb2, 0x04, 0xfc, 0x00, 0x0a, 0x57, 0x8e, 0x18, 0xc9, 0x23, 0xde, + 0xe0, 0xc9, 0xf3, 0x8d, 0x47, 0x32, 0x9d, 0x18, 0xc9, 0xc5, 0x33, 0x5f, 0x79, 0x97, 0x67, 0x9e, + 0x59, 0x76, 0xe6, 0xdb, 0x6f, 0xd2, 0x90, 0x11, 0xfd, 0xf9, 0x1f, 0x3f, 0x48, 0x8b, 0xbd, 0xce, + 0xbc, 0xcb, 0x5e, 0x67, 0x97, 0xde, 0xaf, 0xd9, 0x8b, 0x95, 0x4b, 0xbc, 0x58, 0x95, 0x1f, 0x11, + 0xac, 0xc6, 0xef, 0x0d, 0x7e, 0x1f, 0xee, 0x99, 0x27, 0x8d, 0xae, 0xd5, 0x69, 0x77, 0x5b, 0xd6, + 0xa0, 0x6b, 0x9e, 0x18, 0xcd, 0xf6, 0x61, 0xdb, 0x68, 0x69, 0x29, 0xbc, 0x05, 0x78, 0xee, 0x6a, + 0x77, 0xfb, 0x06, 0xe9, 0x36, 0x8e, 0x34, 0x84, 0x8b, 0xa0, 0xcd, 0xed, 0xa6, 0x41, 0x4e, 0x0d, + 0xa2, 0xa5, 0x17, 0xad, 0xcd, 0xa3, 0xb6, 0xd1, 0xed, 0x6b, 0x2b, 0x8b, 0x18, 0x27, 0xa4, 0xd7, + 0x1a, 0x34, 0x0d, 0xa2, 0x65, 0x16, 0xed, 0xcd, 0x5e, 0xd7, 0x1c, 0x1c, 0x1b, 0x44, 0xcb, 0x56, + 0x7e, 0x47, 0x90, 0x53, 0x77, 0x00, 0xeb, 0x90, 0x9f, 0xd0, 0x30, 0xb4, 0x47, 0xf1, 0x20, 0xc7, + 0x5b, 0xdc, 0x84, 0xcc, 0xd0, 0x73, 0x54, 0xe7, 0x0b, 0x7b, 0xf5, 0xb7, 0xb9, 0x51, 0xd1, 0xbf, + 0xa6, 0xe7, 0x50, 0x22, 0x93, 0x2b, 0x5d, 0x80, 0xb9, 0x0d, 0xdf, 0x83, 0xbb, 0x66, 0xbf, 0xd1, + 0x1f, 0x98, 0x56, 0xb3, 0xd7, 0x32, 0x44, 0x23, 0x8c, 0xbe, 0x96, 0xc2, 0x18, 0x0a, 0x49, 0x73, + 0xaf, 0xa3, 0xa1, 0xab, 0xa1, 0x06, 0x21, 0x3d, 0xa2, 0xa5, 0xbf, 0xca, 0xac, 0x22, 0x2d, 0xfd, + 0xf0, 0x4b, 0x58, 0x13, 0xad, 0x3d, 0x94, 0x3f, 0x0d, 0x71, 0x6f, 0x0f, 0x8f, 0x1a, 0x5f, 0x98, + 0x56, 0xab, 0x67, 0x75, 0x7b, 0x7d, 0x6b, 0x60, 0x1a, 0x5a, 0x0a, 0x97, 0xe1, 0x83, 0x84, 0xab, + 0x4f, 0x1a, 0x4d, 0x23, 0x5a, 0x1f, 0x37, 0xcc, 0x8e, 0xf6, 0x06, 0x1d, 0xfc, 0x82, 0x5e, 0x5e, + 0x94, 0xd0, 0xab, 0x8b, 0x12, 0xfa, 0xfb, 0xa2, 0x84, 0x7e, 0xb8, 0x2c, 0xa5, 0x5e, 0x5d, 0x96, + 0x52, 0x7f, 0x5e, 0x96, 0x52, 0xb0, 0xe3, 0x7a, 0x4b, 0x6b, 0x3e, 0x50, 0xdf, 0x8d, 0x27, 0xc2, + 0x78, 0x82, 0xbe, 0x69, 0xde, 0x7a, 0xe2, 0xd5, 0xb7, 0xe9, 0x88, 0xb2, 0xd9, 0x87, 0xf2, 0xcf, + 0xe9, 0xfb, 0x3d, 0x9f, 0xb2, 0xfe, 0x0c, 0x42, 0x82, 0xab, 0x6b, 0x57, 0x3b, 0xdd, 0x7d, 0x9a, + 0x93, 0x19, 0x8f, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xc0, 0xd4, 0x18, 0xf8, 0x6e, 0x0b, 0x00, + 0x00, } func (m *TracesData) Marshal() (dAtA []byte, err error) { @@ -993,6 +1085,14 @@ func (m *Span) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Flags != 0 { + i -= 4 + encoding_binary.LittleEndian.PutUint32(dAtA[i:], uint32(m.Flags)) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x85 + } { size, err := m.Status.MarshalToSizedBuffer(dAtA[:i]) if err != nil { @@ -1199,6 +1299,12 @@ func (m *Span_Link) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Flags != 0 { + i -= 4 + encoding_binary.LittleEndian.PutUint32(dAtA[i:], uint32(m.Flags)) + i-- + dAtA[i] = 0x35 + } if m.DroppedAttributesCount != 0 { i = encodeVarintTrace(dAtA, i, uint64(m.DroppedAttributesCount)) i-- @@ -1415,6 +1521,9 @@ func (m *Span) Size() (n int) { } l = m.Status.Size() n += 1 + l + sovTrace(uint64(l)) + if m.Flags != 0 { + n += 6 + } return n } @@ -1466,6 +1575,9 @@ func (m *Span_Link) Size() (n int) { if m.DroppedAttributesCount != 0 { n += 1 + sovTrace(uint64(m.DroppedAttributesCount)) } + if m.Flags != 0 { + n += 5 + } return n } @@ -2330,6 +2442,16 @@ func (m *Span) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 16: + if wireType != 5 { + return fmt.Errorf("proto: wrong wireType = %d for field Flags", wireType) + } + m.Flags = 0 + if (iNdEx + 4) > l { + return io.ErrUnexpectedEOF + } + m.Flags = uint32(encoding_binary.LittleEndian.Uint32(dAtA[iNdEx:])) + iNdEx += 4 default: iNdEx = preIndex skippy, err := skipTrace(dAtA[iNdEx:]) @@ -2676,6 +2798,16 @@ func (m *Span_Link) Unmarshal(dAtA []byte) error { break } } + case 6: + if wireType != 5 { + return fmt.Errorf("proto: wrong wireType = %d for field Flags", wireType) + } + m.Flags = 0 + if (iNdEx + 4) > l { + return io.ErrUnexpectedEOF + } + m.Flags = uint32(encoding_binary.LittleEndian.Uint32(dAtA[iNdEx:])) + iNdEx += 4 default: iNdEx = preIndex skippy, err := skipTrace(dAtA[iNdEx:]) diff --git a/vendor/go.opentelemetry.io/collector/pdata/pcommon/map.go b/vendor/go.opentelemetry.io/collector/pdata/pcommon/map.go index c41aa9175a..5bbfab962b 100644 --- a/vendor/go.opentelemetry.io/collector/pdata/pcommon/map.go +++ b/vendor/go.opentelemetry.io/collector/pdata/pcommon/map.go @@ -11,6 +11,9 @@ import ( ) // Map stores a map of string keys to elements of Value type. +// +// Must use NewMap function to create new instances. +// Important: zero-initialized instance is not valid for use. type Map internal.Map // NewMap creates a Map with 0 elements. @@ -55,8 +58,8 @@ func (m Map) EnsureCapacity(capacity int) { // It is allowed to modify the returned value using Value.Set* functions. // Such modification will be applied to the value stored in this map. // -// If the key does not exist returns an invalid instance of the KeyValue and false. -// Calling any functions on the returned invalid instance will cause a panic. +// If the key does not exist returns a zero-initialized KeyValue and false. +// Calling any functions on the returned invalid instance may cause a panic. func (m Map) Get(key string) (Value, bool) { for i := range *m.getOrig() { akv := &(*m.getOrig())[i] diff --git a/vendor/go.opentelemetry.io/collector/pdata/pcommon/trace_state.go b/vendor/go.opentelemetry.io/collector/pdata/pcommon/trace_state.go index dd163629cb..c8f84217e0 100644 --- a/vendor/go.opentelemetry.io/collector/pdata/pcommon/trace_state.go +++ b/vendor/go.opentelemetry.io/collector/pdata/pcommon/trace_state.go @@ -8,6 +8,9 @@ import ( ) // TraceState represents the trace state from the w3c-trace-context. +// +// Must use NewTraceState function to create new instances. +// Important: zero-initialized instance is not valid for use. type TraceState internal.TraceState func NewTraceState() TraceState { diff --git a/vendor/go.opentelemetry.io/collector/pdata/pmetric/json.go b/vendor/go.opentelemetry.io/collector/pdata/pmetric/json.go index 3944bb0270..c8b76b0e6e 100644 --- a/vendor/go.opentelemetry.io/collector/pdata/pmetric/json.go +++ b/vendor/go.opentelemetry.io/collector/pdata/pmetric/json.go @@ -48,7 +48,7 @@ func (ms Metrics) unmarshalJsoniter(iter *jsoniter.Iterator) { iter.ReadObjectCB(func(iter *jsoniter.Iterator, f string) bool { switch f { case "resource_metrics", "resourceMetrics": - iter.ReadArrayCB(func(iterator *jsoniter.Iterator) bool { + iter.ReadArrayCB(func(*jsoniter.Iterator) bool { ms.ResourceMetrics().AppendEmpty().unmarshalJsoniter(iter) return true }) diff --git a/vendor/go.opentelemetry.io/collector/pdata/pmetric/pmetricotlp/response.go b/vendor/go.opentelemetry.io/collector/pdata/pmetric/pmetricotlp/response.go index e928400f31..5942568ddb 100644 --- a/vendor/go.opentelemetry.io/collector/pdata/pmetric/pmetricotlp/response.go +++ b/vendor/go.opentelemetry.io/collector/pdata/pmetric/pmetricotlp/response.go @@ -73,7 +73,7 @@ func (ms ExportResponse) unmarshalJsoniter(iter *jsoniter.Iterator) { } func (ms ExportPartialSuccess) unmarshalJsoniter(iter *jsoniter.Iterator) { - iter.ReadObjectCB(func(iterator *jsoniter.Iterator, f string) bool { + iter.ReadObjectCB(func(_ *jsoniter.Iterator, f string) bool { switch f { case "rejected_data_points", "rejectedDataPoints": ms.orig.RejectedDataPoints = json.ReadInt64(iter) diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/config.go b/vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/config.go index 67f8d73399..06282ce79c 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/config.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/config.go @@ -18,6 +18,7 @@ import ( "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/metric/noop" "go.opentelemetry.io/otel/propagation" semconv "go.opentelemetry.io/otel/semconv/v1.17.0" "go.opentelemetry.io/otel/trace" @@ -89,6 +90,9 @@ func newConfig(opts []Option, role string) *config { metric.WithUnit("ms")) if err != nil { otel.Handle(err) + if c.rpcDuration == nil { + c.rpcDuration = noop.Float64Histogram{} + } } c.rpcRequestSize, err = c.meter.Int64Histogram("rpc."+role+".request.size", @@ -96,6 +100,9 @@ func newConfig(opts []Option, role string) *config { metric.WithUnit("By")) if err != nil { otel.Handle(err) + if c.rpcRequestSize == nil { + c.rpcRequestSize = noop.Int64Histogram{} + } } c.rpcResponseSize, err = c.meter.Int64Histogram("rpc."+role+".response.size", @@ -103,6 +110,9 @@ func newConfig(opts []Option, role string) *config { metric.WithUnit("By")) if err != nil { otel.Handle(err) + if c.rpcResponseSize == nil { + c.rpcResponseSize = noop.Int64Histogram{} + } } c.rpcRequestsPerRPC, err = c.meter.Int64Histogram("rpc."+role+".requests_per_rpc", @@ -110,6 +120,9 @@ func newConfig(opts []Option, role string) *config { metric.WithUnit("{count}")) if err != nil { otel.Handle(err) + if c.rpcRequestsPerRPC == nil { + c.rpcRequestsPerRPC = noop.Int64Histogram{} + } } c.rpcResponsesPerRPC, err = c.meter.Int64Histogram("rpc."+role+".responses_per_rpc", @@ -117,6 +130,9 @@ func newConfig(opts []Option, role string) *config { metric.WithUnit("{count}")) if err != nil { otel.Handle(err) + if c.rpcResponsesPerRPC == nil { + c.rpcResponsesPerRPC = noop.Int64Histogram{} + } } return c diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/stats_handler.go b/vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/stats_handler.go index e41e6df618..73d2b8b6b2 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/stats_handler.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/stats_handler.go @@ -20,6 +20,7 @@ import ( "time" grpc_codes "google.golang.org/grpc/codes" + "google.golang.org/grpc/peer" "google.golang.org/grpc/stats" "google.golang.org/grpc/status" @@ -43,7 +44,7 @@ type serverHandler struct { *config } -// NewServerHandler creates a stats.Handler for gRPC server. +// NewServerHandler creates a stats.Handler for a gRPC server. func NewServerHandler(opts ...Option) stats.Handler { h := &serverHandler{ config: newConfig(opts, "server"), @@ -54,9 +55,6 @@ func NewServerHandler(opts ...Option) stats.Handler { // TagConn can attach some information to the given context. func (h *serverHandler) TagConn(ctx context.Context, info *stats.ConnTagInfo) context.Context { - span := trace.SpanFromContext(ctx) - attrs := peerAttr(peerFromCtx(ctx)) - span.SetAttributes(attrs...) return ctx } @@ -85,14 +83,15 @@ func (h *serverHandler) TagRPC(ctx context.Context, info *stats.RPCTagInfo) cont // HandleRPC processes the RPC stats. func (h *serverHandler) HandleRPC(ctx context.Context, rs stats.RPCStats) { - h.handleRPC(ctx, rs) + isServer := true + h.handleRPC(ctx, rs, isServer) } type clientHandler struct { *config } -// NewClientHandler creates a stats.Handler for gRPC client. +// NewClientHandler creates a stats.Handler for a gRPC client. func NewClientHandler(opts ...Option) stats.Handler { h := &clientHandler{ config: newConfig(opts, "client"), @@ -121,14 +120,12 @@ func (h *clientHandler) TagRPC(ctx context.Context, info *stats.RPCTagInfo) cont // HandleRPC processes the RPC stats. func (h *clientHandler) HandleRPC(ctx context.Context, rs stats.RPCStats) { - h.handleRPC(ctx, rs) + isServer := false + h.handleRPC(ctx, rs, isServer) } // TagConn can attach some information to the given context. -func (h *clientHandler) TagConn(ctx context.Context, cti *stats.ConnTagInfo) context.Context { - span := trace.SpanFromContext(ctx) - attrs := peerAttr(cti.RemoteAddr.String()) - span.SetAttributes(attrs...) +func (h *clientHandler) TagConn(ctx context.Context, info *stats.ConnTagInfo) context.Context { return ctx } @@ -137,20 +134,23 @@ func (h *clientHandler) HandleConn(context.Context, stats.ConnStats) { // no-op } -func (c *config) handleRPC(ctx context.Context, rs stats.RPCStats) { +func (c *config) handleRPC(ctx context.Context, rs stats.RPCStats, isServer bool) { // nolint: revive // isServer is not a control flag. span := trace.SpanFromContext(ctx) - gctx, _ := ctx.Value(gRPCContextKey{}).(*gRPCContext) + var metricAttrs []attribute.KeyValue var messageId int64 - metricAttrs := make([]attribute.KeyValue, 0, len(gctx.metricAttrs)+1) - metricAttrs = append(metricAttrs, gctx.metricAttrs...) - wctx := withoutCancel(ctx) + + gctx, _ := ctx.Value(gRPCContextKey{}).(*gRPCContext) + if gctx != nil { + metricAttrs = make([]attribute.KeyValue, 0, len(gctx.metricAttrs)+1) + metricAttrs = append(metricAttrs, gctx.metricAttrs...) + } switch rs := rs.(type) { case *stats.Begin: case *stats.InPayload: if gctx != nil { messageId = atomic.AddInt64(&gctx.messagesReceived, 1) - c.rpcRequestSize.Record(wctx, int64(rs.Length), metric.WithAttributes(metricAttrs...)) + c.rpcRequestSize.Record(ctx, int64(rs.Length), metric.WithAttributes(metricAttrs...)) } if c.ReceivedEvent { @@ -166,7 +166,7 @@ func (c *config) handleRPC(ctx context.Context, rs stats.RPCStats) { case *stats.OutPayload: if gctx != nil { messageId = atomic.AddInt64(&gctx.messagesSent, 1) - c.rpcResponseSize.Record(wctx, int64(rs.Length), metric.WithAttributes(metricAttrs...)) + c.rpcResponseSize.Record(ctx, int64(rs.Length), metric.WithAttributes(metricAttrs...)) } if c.SentEvent { @@ -180,12 +180,21 @@ func (c *config) handleRPC(ctx context.Context, rs stats.RPCStats) { ) } case *stats.OutTrailer: + case *stats.OutHeader: + if p, ok := peer.FromContext(ctx); ok { + span.SetAttributes(peerAttr(p.Addr.String())...) + } case *stats.End: var rpcStatusAttr attribute.KeyValue if rs.Error != nil { s, _ := status.FromError(rs.Error) - span.SetStatus(codes.Error, s.Message()) + if isServer { + statusCode, msg := serverStatus(s) + span.SetStatus(statusCode, msg) + } else { + span.SetStatus(codes.Error, s.Message()) + } rpcStatusAttr = semconv.RPCGRPCStatusCodeKey.Int(int(s.Code())) } else { rpcStatusAttr = semconv.RPCGRPCStatusCodeKey.Int(int(grpc_codes.OK)) @@ -198,41 +207,12 @@ func (c *config) handleRPC(ctx context.Context, rs stats.RPCStats) { // Use floating point division here for higher precision (instead of Millisecond method). elapsedTime := float64(rs.EndTime.Sub(rs.BeginTime)) / float64(time.Millisecond) - c.rpcDuration.Record(wctx, elapsedTime, metric.WithAttributes(metricAttrs...)) - c.rpcRequestsPerRPC.Record(wctx, atomic.LoadInt64(&gctx.messagesReceived), metric.WithAttributes(metricAttrs...)) - c.rpcResponsesPerRPC.Record(wctx, atomic.LoadInt64(&gctx.messagesSent), metric.WithAttributes(metricAttrs...)) + c.rpcDuration.Record(ctx, elapsedTime, metric.WithAttributes(metricAttrs...)) + if gctx != nil { + c.rpcRequestsPerRPC.Record(ctx, atomic.LoadInt64(&gctx.messagesReceived), metric.WithAttributes(metricAttrs...)) + c.rpcResponsesPerRPC.Record(ctx, atomic.LoadInt64(&gctx.messagesSent), metric.WithAttributes(metricAttrs...)) + } default: return } } - -func withoutCancel(parent context.Context) context.Context { - if parent == nil { - panic("cannot create context from nil parent") - } - return withoutCancelCtx{parent} -} - -type withoutCancelCtx struct { - c context.Context -} - -func (withoutCancelCtx) Deadline() (deadline time.Time, ok bool) { - return -} - -func (withoutCancelCtx) Done() <-chan struct{} { - return nil -} - -func (withoutCancelCtx) Err() error { - return nil -} - -func (w withoutCancelCtx) Value(key any) any { - return w.c.Value(key) -} - -func (w withoutCancelCtx) String() string { - return "withoutCancel" -} diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/version.go b/vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/version.go index f47c8a6751..d633c4bef0 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/version.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/version.go @@ -16,7 +16,7 @@ package otelgrpc // import "go.opentelemetry.io/contrib/instrumentation/google.g // Version is the current release version of the gRPC instrumentation. func Version() string { - return "0.46.1" + return "0.49.0" // This string is updated by the pre_release.sh script during release } diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/common.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/common.go index 9509014e87..cabf645a5b 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/common.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/common.go @@ -31,10 +31,16 @@ const ( // Server HTTP metrics. const ( - RequestCount = "http.server.request_count" // Incoming request count total - RequestContentLength = "http.server.request_content_length" // Incoming request bytes total - ResponseContentLength = "http.server.response_content_length" // Incoming response bytes total - ServerLatency = "http.server.duration" // Incoming end to end duration, milliseconds + serverRequestSize = "http.server.request.size" // Incoming request bytes total + serverResponseSize = "http.server.response.size" // Incoming response bytes total + serverDuration = "http.server.duration" // Incoming end to end duration, milliseconds +) + +// Client HTTP metrics. +const ( + clientRequestSize = "http.client.request.size" // Outgoing request bytes total + clientResponseSize = "http.client.response.size" // Outgoing response bytes total + clientDuration = "http.client.duration" // Outgoing end to end duration, milliseconds ) // Filter is a predicate used to determine whether a given http.request should diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go index af84f0e4bb..1fc15019e6 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go @@ -108,23 +108,23 @@ func handleErr(err error) { func (h *middleware) createMeasures() { var err error h.requestBytesCounter, err = h.meter.Int64Counter( - RequestContentLength, + serverRequestSize, metric.WithUnit("By"), - metric.WithDescription("Measures the size of HTTP request content length (uncompressed)"), + metric.WithDescription("Measures the size of HTTP request messages."), ) handleErr(err) h.responseBytesCounter, err = h.meter.Int64Counter( - ResponseContentLength, + serverResponseSize, metric.WithUnit("By"), - metric.WithDescription("Measures the size of HTTP response content length (uncompressed)"), + metric.WithDescription("Measures the size of HTTP response messages."), ) handleErr(err) h.serverLatencyMeasure, err = h.meter.Float64Histogram( - ServerLatency, + serverDuration, metric.WithUnit("ms"), - metric.WithDescription("Measures the duration of HTTP request handling"), + metric.WithDescription("Measures the duration of inbound HTTP requests."), ) handleErr(err) } @@ -224,7 +224,7 @@ func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http next.ServeHTTP(w, r.WithContext(ctx)) - setAfterServeAttributes(span, bw.read, rww.written, rww.statusCode, bw.err, rww.err) + setAfterServeAttributes(span, bw.read.Load(), rww.written, rww.statusCode, bw.err, rww.err) // Add metrics attributes := append(labeler.Get(), semconvutil.HTTPServerRequestMetrics(h.server, r)...) @@ -232,7 +232,7 @@ func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http attributes = append(attributes, semconv.HTTPStatusCode(rww.statusCode)) } o := metric.WithAttributes(attributes...) - h.requestBytesCounter.Add(ctx, bw.read, o) + h.requestBytesCounter.Add(ctx, bw.read.Load(), o) h.responseBytesCounter.Add(ctx, rww.written, o) // Use floating point division here for higher precision (instead of Millisecond method). diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/httpconv.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/httpconv.go index 794d4c26a4..0efd5261f6 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/httpconv.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/httpconv.go @@ -43,14 +43,22 @@ func HTTPClientResponse(resp *http.Response) []attribute.KeyValue { } // HTTPClientRequest returns trace attributes for an HTTP request made by a client. -// The following attributes are always returned: "http.url", "http.flavor", -// "http.method", "net.peer.name". The following attributes are returned if the -// related values are defined in req: "net.peer.port", "http.user_agent", -// "http.request_content_length", "enduser.id". +// The following attributes are always returned: "http.url", "http.method", +// "net.peer.name". The following attributes are returned if the related values +// are defined in req: "net.peer.port", "user_agent.original", +// "http.request_content_length". func HTTPClientRequest(req *http.Request) []attribute.KeyValue { return hc.ClientRequest(req) } +// HTTPClientRequestMetrics returns metric attributes for an HTTP request made by a client. +// The following attributes are always returned: "http.method", "net.peer.name". +// The following attributes are returned if the +// related values are defined in req: "net.peer.port". +func HTTPClientRequestMetrics(req *http.Request) []attribute.KeyValue { + return hc.ClientRequestMetrics(req) +} + // HTTPClientStatus returns a span status code and message for an HTTP status code // value received by a client. func HTTPClientStatus(code int) (codes.Code, string) { @@ -75,10 +83,9 @@ func HTTPClientStatus(code int) (codes.Code, string) { // The req Host will be used to determine the server instead. // // The following attributes are always returned: "http.method", "http.scheme", -// "http.flavor", "http.target", "net.host.name". The following attributes are -// returned if they related values are defined in req: "net.host.port", -// "net.sock.peer.addr", "net.sock.peer.port", "http.user_agent", "enduser.id", -// "http.client_ip". +// "http.target", "net.host.name". The following attributes are returned if +// they related values are defined in req: "net.host.port", "net.sock.peer.addr", +// "net.sock.peer.port", "user_agent.original", "http.client_ip". func HTTPServerRequest(server string, req *http.Request) []attribute.KeyValue { return hc.ServerRequest(server, req) } @@ -101,8 +108,8 @@ func HTTPServerRequest(server string, req *http.Request) []attribute.KeyValue { // The req Host will be used to determine the server instead. // // The following attributes are always returned: "http.method", "http.scheme", -// "http.flavor", "net.host.name". The following attributes are -// returned if they related values are defined in req: "net.host.port". +// "net.host.name". The following attributes are returned if they related +// values are defined in req: "net.host.port". func HTTPServerRequestMetrics(server string, req *http.Request) []attribute.KeyValue { return hc.ServerRequestMetrics(server, req) } @@ -114,36 +121,6 @@ func HTTPServerStatus(code int) (codes.Code, string) { return hc.ServerStatus(code) } -// HTTPRequestHeader returns the contents of h as attributes. -// -// Instrumentation should require an explicit configuration of which headers to -// captured and then prune what they pass here. Including all headers can be a -// security risk - explicit configuration helps avoid leaking sensitive -// information. -// -// The User-Agent header is already captured in the http.user_agent attribute -// from ClientRequest and ServerRequest. Instrumentation may provide an option -// to capture that header here even though it is not recommended. Otherwise, -// instrumentation should filter that out of what is passed. -func HTTPRequestHeader(h http.Header) []attribute.KeyValue { - return hc.RequestHeader(h) -} - -// HTTPResponseHeader returns the contents of h as attributes. -// -// Instrumentation should require an explicit configuration of which headers to -// captured and then prune what they pass here. Including all headers can be a -// security risk - explicit configuration helps avoid leaking sensitive -// information. -// -// The User-Agent header is already captured in the http.user_agent attribute -// from ClientRequest and ServerRequest. Instrumentation may provide an option -// to capture that header here even though it is not recommended. Otherwise, -// instrumentation should filter that out of what is passed. -func HTTPResponseHeader(h http.Header) []attribute.KeyValue { - return hc.ResponseHeader(h) -} - // httpConv are the HTTP semantic convention attributes defined for a version // of the OpenTelemetry specification. type httpConv struct { @@ -214,7 +191,7 @@ func (c *httpConv) ClientResponse(resp *http.Response) []attribute.KeyValue { // ClientRequest returns attributes for an HTTP request made by a client. The // following attributes are always returned: "http.url", "http.method", // "net.peer.name". The following attributes are returned if the related values -// are defined in req: "net.peer.port", "http.user_agent", +// are defined in req: "net.peer.port", "user_agent.original", // "http.request_content_length", "user_agent.original". func (c *httpConv) ClientRequest(req *http.Request) []attribute.KeyValue { /* The following semantic conventions are returned if present: @@ -286,6 +263,38 @@ func (c *httpConv) ClientRequest(req *http.Request) []attribute.KeyValue { return attrs } +// ClientRequestMetrics returns metric attributes for an HTTP request made by a client. The +// following attributes are always returned: "http.method", "net.peer.name". +// The following attributes are returned if the related values +// are defined in req: "net.peer.port". +func (c *httpConv) ClientRequestMetrics(req *http.Request) []attribute.KeyValue { + /* The following semantic conventions are returned if present: + http.method string + net.peer.name string + net.peer.port int + */ + + n := 2 // method, peer name. + var h string + if req.URL != nil { + h = req.URL.Host + } + peer, p := firstHostPort(h, req.Header.Get("Host")) + port := requiredHTTPPort(req.URL != nil && req.URL.Scheme == "https", p) + if port > 0 { + n++ + } + + attrs := make([]attribute.KeyValue, 0, n) + attrs = append(attrs, c.method(req.Method), c.NetConv.PeerName(peer)) + + if port > 0 { + attrs = append(attrs, c.NetConv.PeerPort(port)) + } + + return attrs +} + // ServerRequest returns attributes for an HTTP request received by a server. // // The server must be the primary server name if it is known. For example this @@ -439,8 +448,8 @@ func (c *httpConv) ServerRequest(server string, req *http.Request) []attribute.K // The req Host will be used to determine the server instead. // // The following attributes are always returned: "http.method", "http.scheme", -// "http.flavor", "net.host.name". The following attributes are -// returned if they related values are defined in req: "net.host.port". +// "net.host.name". The following attributes are returned if they related +// values are defined in req: "net.host.port". func (c *httpConv) ServerRequestMetrics(server string, req *http.Request) []attribute.KeyValue { /* The following semantic conventions are returned if present: http.scheme string @@ -551,31 +560,6 @@ func firstHostPort(source ...string) (host string, port int) { return } -// RequestHeader returns the contents of h as OpenTelemetry attributes. -func (c *httpConv) RequestHeader(h http.Header) []attribute.KeyValue { - return c.header("http.request.header", h) -} - -// ResponseHeader returns the contents of h as OpenTelemetry attributes. -func (c *httpConv) ResponseHeader(h http.Header) []attribute.KeyValue { - return c.header("http.response.header", h) -} - -func (c *httpConv) header(prefix string, h http.Header) []attribute.KeyValue { - key := func(k string) attribute.Key { - k = strings.ToLower(k) - k = strings.ReplaceAll(k, "-", "_") - k = fmt.Sprintf("%s.%s", prefix, k) - return attribute.Key(k) - } - - attrs := make([]attribute.KeyValue, 0, len(h)) - for k, v := range h { - attrs = append(attrs, key(k).StringSlice(v)) - } - return attrs -} - // ClientStatus returns a span status code and message for an HTTP status code // value received by a client. func (c *httpConv) ClientStatus(code int) (codes.Code, string) { diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/netconv.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/netconv.go index cb4cb9355d..d3a06e0cad 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/netconv.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/netconv.go @@ -32,24 +32,6 @@ func NetTransport(network string) attribute.KeyValue { return nc.Transport(network) } -// NetClient returns trace attributes for a client network connection to address. -// See net.Dial for information about acceptable address values, address should -// be the same as the one used to create conn. If conn is nil, only network -// peer attributes will be returned that describe address. Otherwise, the -// socket level information about conn will also be included. -func NetClient(address string, conn net.Conn) []attribute.KeyValue { - return nc.Client(address, conn) -} - -// NetServer returns trace attributes for a network listener listening at address. -// See net.Listen for information about acceptable address values, address -// should be the same as the one used to create ln. If ln is nil, only network -// host attributes will be returned that describe address. Otherwise, the -// socket level information about ln will also be included. -func NetServer(address string, ln net.Listener) []attribute.KeyValue { - return nc.Server(address, ln) -} - // netConv are the network semantic convention attributes defined for a version // of the OpenTelemetry specification. type netConv struct { @@ -125,52 +107,6 @@ func (c *netConv) Host(address string) []attribute.KeyValue { return attrs } -// Server returns attributes for a network listener listening at address. See -// net.Listen for information about acceptable address values, address should -// be the same as the one used to create ln. If ln is nil, only network host -// attributes will be returned that describe address. Otherwise, the socket -// level information about ln will also be included. -func (c *netConv) Server(address string, ln net.Listener) []attribute.KeyValue { - if ln == nil { - return c.Host(address) - } - - lAddr := ln.Addr() - if lAddr == nil { - return c.Host(address) - } - - hostName, hostPort := splitHostPort(address) - sockHostAddr, sockHostPort := splitHostPort(lAddr.String()) - network := lAddr.Network() - sockFamily := family(network, sockHostAddr) - - n := nonZeroStr(hostName, network, sockHostAddr, sockFamily) - n += positiveInt(hostPort, sockHostPort) - attr := make([]attribute.KeyValue, 0, n) - if hostName != "" { - attr = append(attr, c.HostName(hostName)) - if hostPort > 0 { - // Only if net.host.name is set should net.host.port be. - attr = append(attr, c.HostPort(hostPort)) - } - } - if network != "" { - attr = append(attr, c.Transport(network)) - } - if sockFamily != "" { - attr = append(attr, c.NetSockFamilyKey.String(sockFamily)) - } - if sockHostAddr != "" { - attr = append(attr, c.NetSockHostAddrKey.String(sockHostAddr)) - if sockHostPort > 0 { - // Only if net.sock.host.addr is set should net.sock.host.port be. - attr = append(attr, c.NetSockHostPortKey.Int(sockHostPort)) - } - } - return attr -} - func (c *netConv) HostName(name string) attribute.KeyValue { return c.NetHostNameKey.String(name) } @@ -179,85 +115,6 @@ func (c *netConv) HostPort(port int) attribute.KeyValue { return c.NetHostPortKey.Int(port) } -// Client returns attributes for a client network connection to address. See -// net.Dial for information about acceptable address values, address should be -// the same as the one used to create conn. If conn is nil, only network peer -// attributes will be returned that describe address. Otherwise, the socket -// level information about conn will also be included. -func (c *netConv) Client(address string, conn net.Conn) []attribute.KeyValue { - if conn == nil { - return c.Peer(address) - } - - lAddr, rAddr := conn.LocalAddr(), conn.RemoteAddr() - - var network string - switch { - case lAddr != nil: - network = lAddr.Network() - case rAddr != nil: - network = rAddr.Network() - default: - return c.Peer(address) - } - - peerName, peerPort := splitHostPort(address) - var ( - sockFamily string - sockPeerAddr string - sockPeerPort int - sockHostAddr string - sockHostPort int - ) - - if lAddr != nil { - sockHostAddr, sockHostPort = splitHostPort(lAddr.String()) - } - - if rAddr != nil { - sockPeerAddr, sockPeerPort = splitHostPort(rAddr.String()) - } - - switch { - case sockHostAddr != "": - sockFamily = family(network, sockHostAddr) - case sockPeerAddr != "": - sockFamily = family(network, sockPeerAddr) - } - - n := nonZeroStr(peerName, network, sockPeerAddr, sockHostAddr, sockFamily) - n += positiveInt(peerPort, sockPeerPort, sockHostPort) - attr := make([]attribute.KeyValue, 0, n) - if peerName != "" { - attr = append(attr, c.PeerName(peerName)) - if peerPort > 0 { - // Only if net.peer.name is set should net.peer.port be. - attr = append(attr, c.PeerPort(peerPort)) - } - } - if network != "" { - attr = append(attr, c.Transport(network)) - } - if sockFamily != "" { - attr = append(attr, c.NetSockFamilyKey.String(sockFamily)) - } - if sockPeerAddr != "" { - attr = append(attr, c.NetSockPeerAddrKey.String(sockPeerAddr)) - if sockPeerPort > 0 { - // Only if net.sock.peer.addr is set should net.sock.peer.port be. - attr = append(attr, c.NetSockPeerPortKey.Int(sockPeerPort)) - } - } - if sockHostAddr != "" { - attr = append(attr, c.NetSockHostAddrKey.String(sockHostAddr)) - if sockHostPort > 0 { - // Only if net.sock.host.addr is set should net.sock.host.port be. - attr = append(attr, c.NetSockHostPortKey.Int(sockHostPort)) - } - } - return attr -} - func family(network, address string) string { switch network { case "unix", "unixgram", "unixpacket": @@ -273,26 +130,6 @@ func family(network, address string) string { return "" } -func nonZeroStr(strs ...string) int { - var n int - for _, str := range strs { - if str != "" { - n++ - } - } - return n -} - -func positiveInt(ints ...int) int { - var n int - for _, i := range ints { - if i > 0 { - n++ - } - } - return n -} - // Peer returns attributes for a network peer address. func (c *netConv) Peer(address string) []attribute.KeyValue { h, p := splitHostPort(address) diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/transport.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/transport.go index e835cac12e..43e937a67a 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/transport.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/transport.go @@ -19,31 +19,43 @@ import ( "io" "net/http" "net/http/httptrace" + "sync/atomic" + "time" + + "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/codes" "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/trace" + + semconv "go.opentelemetry.io/otel/semconv/v1.20.0" ) // Transport implements the http.RoundTripper interface and wraps -// outbound HTTP(S) requests with a span. +// outbound HTTP(S) requests with a span and enriches it with metrics. type Transport struct { rt http.RoundTripper tracer trace.Tracer + meter metric.Meter propagators propagation.TextMapPropagator spanStartOptions []trace.SpanStartOption filters []Filter spanNameFormatter func(string, *http.Request) string clientTrace func(context.Context) *httptrace.ClientTrace + + requestBytesCounter metric.Int64Counter + responseBytesCounter metric.Int64Counter + latencyMeasure metric.Float64Histogram } var _ http.RoundTripper = &Transport{} // NewTransport wraps the provided http.RoundTripper with one that -// starts a span and injects the span context into the outbound request headers. +// starts a span, injects the span context into the outbound request headers, +// and enriches it with metrics. // // If the provided http.RoundTripper is nil, http.DefaultTransport will be used // as the base http.RoundTripper. @@ -63,12 +75,14 @@ func NewTransport(base http.RoundTripper, opts ...Option) *Transport { c := newConfig(append(defaultOpts, opts...)...) t.applyConfig(c) + t.createMeasures() return &t } func (t *Transport) applyConfig(c *config) { t.tracer = c.Tracer + t.meter = c.Meter t.propagators = c.Propagators t.spanStartOptions = c.SpanStartOptions t.filters = c.Filters @@ -76,6 +90,30 @@ func (t *Transport) applyConfig(c *config) { t.clientTrace = c.ClientTrace } +func (t *Transport) createMeasures() { + var err error + t.requestBytesCounter, err = t.meter.Int64Counter( + clientRequestSize, + metric.WithUnit("By"), + metric.WithDescription("Measures the size of HTTP request messages."), + ) + handleErr(err) + + t.responseBytesCounter, err = t.meter.Int64Counter( + clientResponseSize, + metric.WithUnit("By"), + metric.WithDescription("Measures the size of HTTP response messages."), + ) + handleErr(err) + + t.latencyMeasure, err = t.meter.Float64Histogram( + clientDuration, + metric.WithUnit("ms"), + metric.WithDescription("Measures the duration of outbound HTTP requests."), + ) + handleErr(err) +} + func defaultTransportFormatter(_ string, r *http.Request) string { return "HTTP " + r.Method } @@ -84,6 +122,7 @@ func defaultTransportFormatter(_ string, r *http.Request) string { // before handing the request to the configured base RoundTripper. The created span will // end when the response body is closed or when a read from the body returns io.EOF. func (t *Transport) RoundTrip(r *http.Request) (*http.Response, error) { + requestStartTime := time.Now() for _, f := range t.filters { if !f(r) { // Simply pass through to the base RoundTripper if a filter rejects the request @@ -109,7 +148,23 @@ func (t *Transport) RoundTrip(r *http.Request) (*http.Response, error) { ctx = httptrace.WithClientTrace(ctx, t.clientTrace(ctx)) } + labeler := &Labeler{} + ctx = injectLabeler(ctx, labeler) + r = r.Clone(ctx) // According to RoundTripper spec, we shouldn't modify the origin request. + + // use a body wrapper to determine the request size + var bw bodyWrapper + // if request body is nil or NoBody, we don't want to mutate the body as it + // will affect the identity of it in an unforeseeable way because we assert + // ReadCloser fulfills a certain interface and it is indeed nil or NoBody. + if r.Body != nil && r.Body != http.NoBody { + bw.ReadCloser = r.Body + // noop to prevent nil panic. not using this record fun yet. + bw.record = func(int64) {} + r.Body = &bw + } + span.SetAttributes(semconvutil.HTTPClientRequest(r)...) t.propagators.Inject(ctx, propagation.HeaderCarrier(r.Header)) @@ -121,9 +176,28 @@ func (t *Transport) RoundTrip(r *http.Request) (*http.Response, error) { return res, err } + // metrics + metricAttrs := append(labeler.Get(), semconvutil.HTTPClientRequestMetrics(r)...) + if res.StatusCode > 0 { + metricAttrs = append(metricAttrs, semconv.HTTPStatusCode(res.StatusCode)) + } + o := metric.WithAttributes(metricAttrs...) + t.requestBytesCounter.Add(ctx, bw.read.Load(), o) + // For handling response bytes we leverage a callback when the client reads the http response + readRecordFunc := func(n int64) { + t.responseBytesCounter.Add(ctx, n, o) + } + + // traces span.SetAttributes(semconvutil.HTTPClientResponse(res)...) span.SetStatus(semconvutil.HTTPClientStatus(res.StatusCode)) - res.Body = newWrappedBody(span, res.Body) + + res.Body = newWrappedBody(span, readRecordFunc, res.Body) + + // Use floating point division here for higher precision (instead of Millisecond method). + elapsedTime := float64(time.Since(requestStartTime)) / float64(time.Millisecond) + + t.latencyMeasure.Record(ctx, elapsedTime, o) return res, err } @@ -131,17 +205,17 @@ func (t *Transport) RoundTrip(r *http.Request) (*http.Response, error) { // newWrappedBody returns a new and appropriately scoped *wrappedBody as an // io.ReadCloser. If the passed body implements io.Writer, the returned value // will implement io.ReadWriteCloser. -func newWrappedBody(span trace.Span, body io.ReadCloser) io.ReadCloser { +func newWrappedBody(span trace.Span, record func(n int64), body io.ReadCloser) io.ReadCloser { // The successful protocol switch responses will have a body that // implement an io.ReadWriteCloser. Ensure this interface type continues // to be satisfied if that is the case. if _, ok := body.(io.ReadWriteCloser); ok { - return &wrappedBody{span: span, body: body} + return &wrappedBody{span: span, record: record, body: body} } // Remove the implementation of the io.ReadWriteCloser and only implement // the io.ReadCloser. - return struct{ io.ReadCloser }{&wrappedBody{span: span, body: body}} + return struct{ io.ReadCloser }{&wrappedBody{span: span, record: record, body: body}} } // wrappedBody is the response body type returned by the transport @@ -153,8 +227,11 @@ func newWrappedBody(span trace.Span, body io.ReadCloser) io.ReadCloser { // If the response body implements the io.Writer interface (i.e. for // successful protocol switches), the wrapped body also will. type wrappedBody struct { - span trace.Span - body io.ReadCloser + span trace.Span + recorded atomic.Bool + record func(n int64) + body io.ReadCloser + read atomic.Int64 } var _ io.ReadWriteCloser = &wrappedBody{} @@ -171,11 +248,14 @@ func (wb *wrappedBody) Write(p []byte) (int, error) { func (wb *wrappedBody) Read(b []byte) (int, error) { n, err := wb.body.Read(b) + // Record the number of bytes read + wb.read.Add(int64(n)) switch err { case nil: // nothing to do here but fall through to the return case io.EOF: + wb.recordBytesRead() wb.span.End() default: wb.span.RecordError(err) @@ -184,7 +264,20 @@ func (wb *wrappedBody) Read(b []byte) (int, error) { return n, err } +// recordBytesRead is a function that ensures the number of bytes read is recorded once and only once. +func (wb *wrappedBody) recordBytesRead() { + // note: it is more performant (and equally correct) to use atomic.Bool over sync.Once here. In the event that + // two goroutines are racing to call this method, the number of bytes read will no longer increase. Using + // CompareAndSwap allows later goroutines to return quickly and not block waiting for the race winner to finish + // calling wb.record(wb.read.Load()). + if wb.recorded.CompareAndSwap(false, true) { + // Record the total number of bytes read + wb.record(wb.read.Load()) + } +} + func (wb *wrappedBody) Close() error { + wb.recordBytesRead() wb.span.End() if wb.body != nil { return wb.body.Close() diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go index 9a4a02143d..35254e888f 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go @@ -16,7 +16,7 @@ package otelhttp // import "go.opentelemetry.io/contrib/instrumentation/net/http // Version is the current release version of the otelhttp instrumentation. func Version() string { - return "0.47.0" + return "0.49.0" // This string is updated by the pre_release.sh script during release } diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/wrap.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/wrap.go index 11a35ed167..2852ec9717 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/wrap.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/wrap.go @@ -18,6 +18,7 @@ import ( "context" "io" "net/http" + "sync/atomic" "go.opentelemetry.io/otel/propagation" ) @@ -30,14 +31,14 @@ type bodyWrapper struct { io.ReadCloser record func(n int64) // must not be nil - read int64 + read atomic.Int64 err error } func (w *bodyWrapper) Read(b []byte) (int, error) { n, err := w.ReadCloser.Read(b) n1 := int64(n) - w.read += n1 + w.read.Add(n1) w.err = err w.record(n1) return n, err diff --git a/vendor/go.opentelemetry.io/otel/.codespellignore b/vendor/go.opentelemetry.io/otel/.codespellignore index ae6a3bcf12..120b63a9c7 100644 --- a/vendor/go.opentelemetry.io/otel/.codespellignore +++ b/vendor/go.opentelemetry.io/otel/.codespellignore @@ -3,3 +3,5 @@ fo te collison consequentially +ans +nam diff --git a/vendor/go.opentelemetry.io/otel/CHANGELOG.md b/vendor/go.opentelemetry.io/otel/CHANGELOG.md index fe670d79cc..98f2d20438 100644 --- a/vendor/go.opentelemetry.io/otel/CHANGELOG.md +++ b/vendor/go.opentelemetry.io/otel/CHANGELOG.md @@ -8,6 +8,80 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [Unreleased] +## [1.24.0/0.46.0/0.0.1-alpha] 2024-02-23 + +This release is the last to support [Go 1.20]. +The next release will require at least [Go 1.21]. + +### Added + +- Support [Go 1.22]. (#4890) +- Add exemplar support to `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc`. (#4900) +- Add exemplar support to `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp`. (#4900) +- The `go.opentelemetry.io/otel/log` module is added. + This module includes OpenTelemetry Go's implementation of the Logs Bridge API. + This module is in an alpha state, it is subject to breaking changes. + See our [versioning policy](./VERSIONING.md) for more info. (#4961) + +### Fixed + +- Fix registration of multiple callbacks when using the global meter provider from `go.opentelemetry.io/otel`. (#4945) +- Fix negative buckets in output of exponential histograms. (#4956) + +## [1.23.1] 2024-02-07 + +### Fixed + +- Register all callbacks passed during observable instrument creation instead of just the last one multiple times in `go.opentelemetry.io/otel/sdk/metric`. (#4888) + +## [1.23.0] 2024-02-06 + +This release contains the first stable, `v1`, release of the following modules: + +- `go.opentelemetry.io/otel/bridge/opencensus` +- `go.opentelemetry.io/otel/bridge/opencensus/test` +- `go.opentelemetry.io/otel/example/opencensus` +- `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc` +- `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp` +- `go.opentelemetry.io/otel/exporters/stdout/stdoutmetric` + +See our [versioning policy](VERSIONING.md) for more information about these stability guarantees. + +### Added + +- Add `WithEndpointURL` option to the `exporters/otlp/otlpmetric/otlpmetricgrpc`, `exporters/otlp/otlpmetric/otlpmetrichttp`, `exporters/otlp/otlptrace/otlptracegrpc` and `exporters/otlp/otlptrace/otlptracehttp` packages. (#4808) +- Experimental exemplar exporting is added to the metric SDK. + See [metric documentation](./sdk/metric/internal/x/README.md#exemplars) for more information about this feature and how to enable it. (#4871) +- `ErrSchemaURLConflict` is added to `go.opentelemetry.io/otel/sdk/resource`. + This error is returned when a merge of two `Resource`s with different (non-empty) schema URL is attempted. (#4876) + +### Changed + +- The `Merge` and `New` functions in `go.opentelemetry.io/otel/sdk/resource` now returns a partial result if there is a schema URL merge conflict. + Instead of returning `nil` when two `Resource`s with different (non-empty) schema URLs are merged the merged `Resource`, along with the new `ErrSchemaURLConflict` error, is returned. + It is up to the user to decide if they want to use the returned `Resource` or not. + It may have desired attributes overwritten or include stale semantic conventions. (#4876) + +### Fixed + +- Fix `ContainerID` resource detection on systemd when cgroup path has a colon. (#4449) +- Fix `go.opentelemetry.io/otel/sdk/metric` to cache instruments to avoid leaking memory when the same instrument is created multiple times. (#4820) +- Fix missing `Mix` and `Max` values for `go.opentelemetry.io/otel/exporters/stdout/stdoutmetric` by introducing `MarshalText` and `MarshalJSON` for the `Extrema` type in `go.opentelemetry.io/sdk/metric/metricdata`. (#4827) + +## [1.23.0-rc.1] 2024-01-18 + +This is a release candidate for the v1.23.0 release. +That release is expected to include the `v1` release of the following modules: + +- `go.opentelemetry.io/otel/bridge/opencensus` +- `go.opentelemetry.io/otel/bridge/opencensus/test` +- `go.opentelemetry.io/otel/example/opencensus` +- `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc` +- `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp` +- `go.opentelemetry.io/otel/exporters/stdout/stdoutmetric` + +See our [versioning policy](VERSIONING.md) for more information about these stability guarantees. + ## [1.22.0/0.45.0] 2024-01-17 ### Added @@ -22,13 +96,13 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm The package contains semantic conventions from the `v1.24.0` version of the OpenTelemetry Semantic Conventions. (#4770) - Add `WithResourceAsConstantLabels` option to apply resource attributes for every metric emitted by the Prometheus exporter. (#4733) - Experimental cardinality limiting is added to the metric SDK. - See [metric documentation](./sdk/metric/EXPERIMENTAL.md#cardinality-limit) for more information about this feature and how to enable it. (#4457) + See [metric documentation](./sdk/metric/internal/x/README.md#cardinality-limit) for more information about this feature and how to enable it. (#4457) - Add `NewMemberRaw` and `NewKeyValuePropertyRaw` in `go.opentelemetry.io/otel/baggage`. (#4804) ### Changed - Upgrade all use of `go.opentelemetry.io/otel/semconv` to use `v1.24.0`. (#4754) -- Update transformations in `go.opentelemetry.io/otel/exporters/zipkin` to follow `v1.19.0` version of the OpenTelemetry specification. (#4754) +- Update transformations in `go.opentelemetry.io/otel/exporters/zipkin` to follow `v1.24.0` version of the OpenTelemetry specification. (#4754) - Record synchronous measurements when the passed context is canceled instead of dropping in `go.opentelemetry.io/otel/sdk/metric`. If you do not want to make a measurement when the context is cancelled, you need to handle it yourself (e.g `if ctx.Err() != nil`). (#4671) - Improve `go.opentelemetry.io/otel/trace.TraceState`'s performance. (#4722) @@ -2775,7 +2849,11 @@ It contains api and sdk for trace and meter. - CircleCI build CI manifest files. - CODEOWNERS file to track owners of this project. -[Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.22.0...HEAD +[Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.24.0...HEAD +[1.24.0/0.46.0/0.0.1-alpha]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.24.0 +[1.23.1]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.23.1 +[1.23.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.23.0 +[1.23.0-rc.1]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.23.0-rc.1 [1.22.0/0.45.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.22.0 [1.21.0/0.44.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.21.0 [1.20.0/0.43.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.20.0 @@ -2850,6 +2928,8 @@ It contains api and sdk for trace and meter. [0.1.1]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v0.1.1 [0.1.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v0.1.0 +[Go 1.22]: https://go.dev/doc/go1.22 +[Go 1.21]: https://go.dev/doc/go1.21 [Go 1.20]: https://go.dev/doc/go1.20 [Go 1.19]: https://go.dev/doc/go1.19 [Go 1.18]: https://go.dev/doc/go1.18 diff --git a/vendor/go.opentelemetry.io/otel/CODEOWNERS b/vendor/go.opentelemetry.io/otel/CODEOWNERS index 623740007d..31d336d922 100644 --- a/vendor/go.opentelemetry.io/otel/CODEOWNERS +++ b/vendor/go.opentelemetry.io/otel/CODEOWNERS @@ -14,4 +14,4 @@ * @MrAlias @Aneurysm9 @evantorrie @XSAM @dashpole @MadVikingGod @pellared @hanyuancheung @dmathieu -CODEOWNERS @MrAlias @MadVikingGod @pellared \ No newline at end of file +CODEOWNERS @MrAlias @MadVikingGod @pellared @dashpole \ No newline at end of file diff --git a/vendor/go.opentelemetry.io/otel/CONTRIBUTING.md b/vendor/go.opentelemetry.io/otel/CONTRIBUTING.md index 31857a6173..c9f2bac55b 100644 --- a/vendor/go.opentelemetry.io/otel/CONTRIBUTING.md +++ b/vendor/go.opentelemetry.io/otel/CONTRIBUTING.md @@ -617,13 +617,13 @@ should be canceled. - [Evan Torrie](https://github.com/evantorrie), Verizon Media - [Sam Xie](https://github.com/XSAM), Cisco/AppDynamics -- [David Ashpole](https://github.com/dashpole), Google - [Chester Cheung](https://github.com/hanyuancheung), Tencent - [Damien Mathieu](https://github.com/dmathieu), Elastic - [Anthony Mirabella](https://github.com/Aneurysm9), AWS ### Maintainers +- [David Ashpole](https://github.com/dashpole), Google - [Aaron Clawson](https://github.com/MadVikingGod), LightStep - [Robert Pająk](https://github.com/pellared), Splunk - [Tyler Yahn](https://github.com/MrAlias), Splunk diff --git a/vendor/go.opentelemetry.io/otel/Makefile b/vendor/go.opentelemetry.io/otel/Makefile index 35fc189961..6de95219be 100644 --- a/vendor/go.opentelemetry.io/otel/Makefile +++ b/vendor/go.opentelemetry.io/otel/Makefile @@ -192,7 +192,7 @@ test-coverage: | $(GOCOVMERGE) done; \ $(GOCOVMERGE) $$(find . -name coverage.out) > coverage.txt -# Adding a directory will include all benchmarks in that direcotry if a filter is not specified. +# Adding a directory will include all benchmarks in that directory if a filter is not specified. BENCHMARK_TARGETS := sdk/trace .PHONY: benchmark benchmark: $(BENCHMARK_TARGETS:%=benchmark/%) @@ -315,4 +315,4 @@ add-tags: | $(MULTIMOD) .PHONY: lint-markdown lint-markdown: - docker run -v "$(CURDIR):$(WORKDIR)" docker://avtodev/markdown-lint:v1 -c $(WORKDIR)/.markdownlint.yaml $(WORKDIR)/**/*.md + docker run -v "$(CURDIR):$(WORKDIR)" avtodev/markdown-lint:v1 -c $(WORKDIR)/.markdownlint.yaml $(WORKDIR)/**/*.md diff --git a/vendor/go.opentelemetry.io/otel/README.md b/vendor/go.opentelemetry.io/otel/README.md index 44e1bfc9b5..7766259a5c 100644 --- a/vendor/go.opentelemetry.io/otel/README.md +++ b/vendor/go.opentelemetry.io/otel/README.md @@ -11,14 +11,11 @@ It provides a set of APIs to directly measure performance and behavior of your s ## Project Status -| Signal | Status | -|---------|------------| -| Traces | Stable | -| Metrics | Stable | -| Logs | Design [1] | - -- [1]: Currently the logs signal development is in a design phase ([#4696](https://github.com/open-telemetry/opentelemetry-go/issues/4696)). - No Logs Pull Requests are currently being accepted. +| Signal | Status | +|---------|--------------------| +| Traces | Stable | +| Metrics | Stable | +| Logs | In development[^1] | Progress and status specific to this repository is tracked in our [project boards](https://github.com/open-telemetry/opentelemetry-go/projects) @@ -28,6 +25,8 @@ and Project versioning information and stability guarantees can be found in the [versioning documentation](VERSIONING.md). +[^1]: https://github.com/orgs/open-telemetry/projects/43 + ### Compatibility OpenTelemetry-Go ensures compatibility with the current supported versions of @@ -50,14 +49,19 @@ Currently, this project supports the following environments. | OS | Go Version | Architecture | |---------|------------|--------------| +| Ubuntu | 1.22 | amd64 | | Ubuntu | 1.21 | amd64 | | Ubuntu | 1.20 | amd64 | +| Ubuntu | 1.22 | 386 | | Ubuntu | 1.21 | 386 | | Ubuntu | 1.20 | 386 | +| MacOS | 1.22 | amd64 | | MacOS | 1.21 | amd64 | | MacOS | 1.20 | amd64 | +| Windows | 1.22 | amd64 | | Windows | 1.21 | amd64 | | Windows | 1.20 | amd64 | +| Windows | 1.22 | 386 | | Windows | 1.21 | 386 | | Windows | 1.20 | 386 | diff --git a/vendor/go.opentelemetry.io/otel/attribute/set.go b/vendor/go.opentelemetry.io/otel/attribute/set.go index 7e6765b06b..fb6da51450 100644 --- a/vendor/go.opentelemetry.io/otel/attribute/set.go +++ b/vendor/go.opentelemetry.io/otel/attribute/set.go @@ -427,7 +427,7 @@ func (l *Set) MarshalJSON() ([]byte, error) { return json.Marshal(l.equivalent.iface) } -// MarshalLog is the marshaling function used by the logging system to represent this exporter. +// MarshalLog is the marshaling function used by the logging system to represent this Set. func (l Set) MarshalLog() interface{} { kvs := make(map[string]string) for _, kv := range l.ToSlice() { diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/exporter.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/exporter.go index b46a38d60a..cb41c7d58f 100644 --- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/exporter.go +++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/exporter.go @@ -104,7 +104,7 @@ func NewUnstarted(client Client) *Exporter { } } -// MarshalLog is the marshaling function used by the logging system to represent this exporter. +// MarshalLog is the marshaling function used by the logging system to represent this Exporter. func (e *Exporter) MarshalLog() interface{} { return struct { Type string diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/doc.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/doc.go index 1f514ef9ea..a3c2690c5d 100644 --- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/doc.go +++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/doc.go @@ -28,7 +28,7 @@ The value may additionally a port, a scheme, and a path. The value accepts "http" and "https" scheme. The value should not contain a query string or fragment. OTEL_EXPORTER_OTLP_TRACES_ENDPOINT takes precedence over OTEL_EXPORTER_OTLP_ENDPOINT. -The configuration can be overridden by [WithEndpoint], [WithInsecure], [WithGRPCConn] options. +The configuration can be overridden by [WithEndpoint], [WithEndpointURL], [WithInsecure], and [WithGRPCConn] options. OTEL_EXPORTER_OTLP_INSECURE, OTEL_EXPORTER_OTLP_TRACES_INSECURE (default: "false") - setting "true" disables client transport security for the exporter's gRPC connection. diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig/options.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig/options.go index dddb1f334d..f0203cbe72 100644 --- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig/options.go +++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig/options.go @@ -20,6 +20,7 @@ package otlpconfig // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/ import ( "crypto/tls" "fmt" + "net/url" "path" "strings" "time" @@ -32,6 +33,7 @@ import ( "go.opentelemetry.io/otel/exporters/otlp/otlptrace" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/retry" + "go.opentelemetry.io/otel/internal/global" ) const ( @@ -265,6 +267,24 @@ func WithEndpoint(endpoint string) GenericOption { }) } +func WithEndpointURL(v string) GenericOption { + return newGenericOption(func(cfg Config) Config { + u, err := url.Parse(v) + if err != nil { + global.Error(err, "otlptrace: parse endpoint url", "url", v) + return cfg + } + + cfg.Traces.Endpoint = u.Host + cfg.Traces.URLPath = u.Path + if u.Scheme != "https" { + cfg.Traces.Insecure = true + } + + return cfg + }) +} + func WithCompression(compression Compression) GenericOption { return newGenericOption(func(cfg Config) Config { cfg.Traces.Compression = compression diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/options.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/options.go index 17ffeaf6ef..461610c6b9 100644 --- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/options.go +++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/options.go @@ -64,14 +64,44 @@ func WithInsecure() Option { return wrappedOption{otlpconfig.WithInsecure()} } -// WithEndpoint sets the target endpoint the exporter will connect to. If -// unset, localhost:4317 will be used as a default. +// WithEndpoint sets the target endpoint the Exporter will connect to. +// +// If the OTEL_EXPORTER_OTLP_ENDPOINT or OTEL_EXPORTER_OTLP_METRICS_ENDPOINT +// environment variable is set, and this option is not passed, that variable +// value will be used. If both are set, OTEL_EXPORTER_OTLP_TRACES_ENDPOINT +// will take precedence. +// +// If both this option and WithEndpointURL are used, the last used option will +// take precedence. +// +// By default, if an environment variable is not set, and this option is not +// passed, "localhost:4317" will be used. // // This option has no effect if WithGRPCConn is used. func WithEndpoint(endpoint string) Option { return wrappedOption{otlpconfig.WithEndpoint(endpoint)} } +// WithEndpointURL sets the target endpoint URL the Exporter will connect to. +// +// If the OTEL_EXPORTER_OTLP_ENDPOINT or OTEL_EXPORTER_OTLP_METRICS_ENDPOINT +// environment variable is set, and this option is not passed, that variable +// value will be used. If both are set, OTEL_EXPORTER_OTLP_TRACES_ENDPOINT +// will take precedence. +// +// If both this option and WithEndpoint are used, the last used option will +// take precedence. +// +// If an invalid URL is provided, the default value will be kept. +// +// By default, if an environment variable is not set, and this option is not +// passed, "localhost:4317" will be used. +// +// This option has no effect if WithGRPCConn is used. +func WithEndpointURL(u string) Option { + return wrappedOption{otlpconfig.WithEndpointURL(u)} +} + // WithReconnectionPeriod set the minimum amount of time between connection // attempts to the target endpoint. // diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/version.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/version.go index 3b3bc35911..afc89644e6 100644 --- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/version.go +++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/version.go @@ -16,5 +16,5 @@ package otlptrace // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace" // Version is the current release version of the OpenTelemetry OTLP trace exporter in use. func Version() string { - return "1.22.0" + return "1.24.0" } diff --git a/vendor/go.opentelemetry.io/otel/internal/global/meter.go b/vendor/go.opentelemetry.io/otel/internal/global/meter.go index 0097db478c..7ed61c0e25 100644 --- a/vendor/go.opentelemetry.io/otel/internal/global/meter.go +++ b/vendor/go.opentelemetry.io/otel/internal/global/meter.go @@ -130,9 +130,11 @@ func (m *meter) setDelegate(provider metric.MeterProvider) { inst.setDelegate(meter) } - for e := m.registry.Front(); e != nil; e = e.Next() { + var n *list.Element + for e := m.registry.Front(); e != nil; e = n { r := e.Value.(*registration) r.setDelegate(meter) + n = e.Next() m.registry.Remove(e) } diff --git a/vendor/go.opentelemetry.io/otel/internal/global/state.go b/vendor/go.opentelemetry.io/otel/internal/global/state.go index 7985005bcb..386c8bfdc0 100644 --- a/vendor/go.opentelemetry.io/otel/internal/global/state.go +++ b/vendor/go.opentelemetry.io/otel/internal/global/state.go @@ -63,7 +63,7 @@ func SetTracerProvider(tp trace.TracerProvider) { // to itself. Error( errors.New("no delegate configured in tracer provider"), - "Setting tracer provider to it's current value. No delegate will be configured", + "Setting tracer provider to its current value. No delegate will be configured", ) return } @@ -92,7 +92,7 @@ func SetTextMapPropagator(p propagation.TextMapPropagator) { // delegate to itself. Error( errors.New("no delegate configured in text map propagator"), - "Setting text map propagator to it's current value. No delegate will be configured", + "Setting text map propagator to its current value. No delegate will be configured", ) return } @@ -123,7 +123,7 @@ func SetMeterProvider(mp metric.MeterProvider) { // to itself. Error( errors.New("no delegate configured in meter provider"), - "Setting meter provider to it's current value. No delegate will be configured", + "Setting meter provider to its current value. No delegate will be configured", ) return } diff --git a/vendor/go.opentelemetry.io/otel/metric/noop/noop.go b/vendor/go.opentelemetry.io/otel/metric/noop/noop.go new file mode 100644 index 0000000000..acc9a670b2 --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/metric/noop/noop.go @@ -0,0 +1,264 @@ +// Copyright The OpenTelemetry 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 noop provides an implementation of the OpenTelemetry metric API that +// produces no telemetry and minimizes used computation resources. +// +// Using this package to implement the OpenTelemetry metric API will +// effectively disable OpenTelemetry. +// +// This implementation can be embedded in other implementations of the +// OpenTelemetry metric API. Doing so will mean the implementation defaults to +// no operation for methods it does not implement. +package noop // import "go.opentelemetry.io/otel/metric/noop" + +import ( + "context" + + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/metric/embedded" +) + +var ( + // Compile-time check this implements the OpenTelemetry API. + + _ metric.MeterProvider = MeterProvider{} + _ metric.Meter = Meter{} + _ metric.Observer = Observer{} + _ metric.Registration = Registration{} + _ metric.Int64Counter = Int64Counter{} + _ metric.Float64Counter = Float64Counter{} + _ metric.Int64UpDownCounter = Int64UpDownCounter{} + _ metric.Float64UpDownCounter = Float64UpDownCounter{} + _ metric.Int64Histogram = Int64Histogram{} + _ metric.Float64Histogram = Float64Histogram{} + _ metric.Int64ObservableCounter = Int64ObservableCounter{} + _ metric.Float64ObservableCounter = Float64ObservableCounter{} + _ metric.Int64ObservableGauge = Int64ObservableGauge{} + _ metric.Float64ObservableGauge = Float64ObservableGauge{} + _ metric.Int64ObservableUpDownCounter = Int64ObservableUpDownCounter{} + _ metric.Float64ObservableUpDownCounter = Float64ObservableUpDownCounter{} + _ metric.Int64Observer = Int64Observer{} + _ metric.Float64Observer = Float64Observer{} +) + +// MeterProvider is an OpenTelemetry No-Op MeterProvider. +type MeterProvider struct{ embedded.MeterProvider } + +// NewMeterProvider returns a MeterProvider that does not record any telemetry. +func NewMeterProvider() MeterProvider { + return MeterProvider{} +} + +// Meter returns an OpenTelemetry Meter that does not record any telemetry. +func (MeterProvider) Meter(string, ...metric.MeterOption) metric.Meter { + return Meter{} +} + +// Meter is an OpenTelemetry No-Op Meter. +type Meter struct{ embedded.Meter } + +// Int64Counter returns a Counter used to record int64 measurements that +// produces no telemetry. +func (Meter) Int64Counter(string, ...metric.Int64CounterOption) (metric.Int64Counter, error) { + return Int64Counter{}, nil +} + +// Int64UpDownCounter returns an UpDownCounter used to record int64 +// measurements that produces no telemetry. +func (Meter) Int64UpDownCounter(string, ...metric.Int64UpDownCounterOption) (metric.Int64UpDownCounter, error) { + return Int64UpDownCounter{}, nil +} + +// Int64Histogram returns a Histogram used to record int64 measurements that +// produces no telemetry. +func (Meter) Int64Histogram(string, ...metric.Int64HistogramOption) (metric.Int64Histogram, error) { + return Int64Histogram{}, nil +} + +// Int64ObservableCounter returns an ObservableCounter used to record int64 +// measurements that produces no telemetry. +func (Meter) Int64ObservableCounter(string, ...metric.Int64ObservableCounterOption) (metric.Int64ObservableCounter, error) { + return Int64ObservableCounter{}, nil +} + +// Int64ObservableUpDownCounter returns an ObservableUpDownCounter used to +// record int64 measurements that produces no telemetry. +func (Meter) Int64ObservableUpDownCounter(string, ...metric.Int64ObservableUpDownCounterOption) (metric.Int64ObservableUpDownCounter, error) { + return Int64ObservableUpDownCounter{}, nil +} + +// Int64ObservableGauge returns an ObservableGauge used to record int64 +// measurements that produces no telemetry. +func (Meter) Int64ObservableGauge(string, ...metric.Int64ObservableGaugeOption) (metric.Int64ObservableGauge, error) { + return Int64ObservableGauge{}, nil +} + +// Float64Counter returns a Counter used to record int64 measurements that +// produces no telemetry. +func (Meter) Float64Counter(string, ...metric.Float64CounterOption) (metric.Float64Counter, error) { + return Float64Counter{}, nil +} + +// Float64UpDownCounter returns an UpDownCounter used to record int64 +// measurements that produces no telemetry. +func (Meter) Float64UpDownCounter(string, ...metric.Float64UpDownCounterOption) (metric.Float64UpDownCounter, error) { + return Float64UpDownCounter{}, nil +} + +// Float64Histogram returns a Histogram used to record int64 measurements that +// produces no telemetry. +func (Meter) Float64Histogram(string, ...metric.Float64HistogramOption) (metric.Float64Histogram, error) { + return Float64Histogram{}, nil +} + +// Float64ObservableCounter returns an ObservableCounter used to record int64 +// measurements that produces no telemetry. +func (Meter) Float64ObservableCounter(string, ...metric.Float64ObservableCounterOption) (metric.Float64ObservableCounter, error) { + return Float64ObservableCounter{}, nil +} + +// Float64ObservableUpDownCounter returns an ObservableUpDownCounter used to +// record int64 measurements that produces no telemetry. +func (Meter) Float64ObservableUpDownCounter(string, ...metric.Float64ObservableUpDownCounterOption) (metric.Float64ObservableUpDownCounter, error) { + return Float64ObservableUpDownCounter{}, nil +} + +// Float64ObservableGauge returns an ObservableGauge used to record int64 +// measurements that produces no telemetry. +func (Meter) Float64ObservableGauge(string, ...metric.Float64ObservableGaugeOption) (metric.Float64ObservableGauge, error) { + return Float64ObservableGauge{}, nil +} + +// RegisterCallback performs no operation. +func (Meter) RegisterCallback(metric.Callback, ...metric.Observable) (metric.Registration, error) { + return Registration{}, nil +} + +// Observer acts as a recorder of measurements for multiple instruments in a +// Callback, it performing no operation. +type Observer struct{ embedded.Observer } + +// ObserveFloat64 performs no operation. +func (Observer) ObserveFloat64(metric.Float64Observable, float64, ...metric.ObserveOption) { +} + +// ObserveInt64 performs no operation. +func (Observer) ObserveInt64(metric.Int64Observable, int64, ...metric.ObserveOption) { +} + +// Registration is the registration of a Callback with a No-Op Meter. +type Registration struct{ embedded.Registration } + +// Unregister unregisters the Callback the Registration represents with the +// No-Op Meter. This will always return nil because the No-Op Meter performs no +// operation, including hold any record of registrations. +func (Registration) Unregister() error { return nil } + +// Int64Counter is an OpenTelemetry Counter used to record int64 measurements. +// It produces no telemetry. +type Int64Counter struct{ embedded.Int64Counter } + +// Add performs no operation. +func (Int64Counter) Add(context.Context, int64, ...metric.AddOption) {} + +// Float64Counter is an OpenTelemetry Counter used to record float64 +// measurements. It produces no telemetry. +type Float64Counter struct{ embedded.Float64Counter } + +// Add performs no operation. +func (Float64Counter) Add(context.Context, float64, ...metric.AddOption) {} + +// Int64UpDownCounter is an OpenTelemetry UpDownCounter used to record int64 +// measurements. It produces no telemetry. +type Int64UpDownCounter struct{ embedded.Int64UpDownCounter } + +// Add performs no operation. +func (Int64UpDownCounter) Add(context.Context, int64, ...metric.AddOption) {} + +// Float64UpDownCounter is an OpenTelemetry UpDownCounter used to record +// float64 measurements. It produces no telemetry. +type Float64UpDownCounter struct{ embedded.Float64UpDownCounter } + +// Add performs no operation. +func (Float64UpDownCounter) Add(context.Context, float64, ...metric.AddOption) {} + +// Int64Histogram is an OpenTelemetry Histogram used to record int64 +// measurements. It produces no telemetry. +type Int64Histogram struct{ embedded.Int64Histogram } + +// Record performs no operation. +func (Int64Histogram) Record(context.Context, int64, ...metric.RecordOption) {} + +// Float64Histogram is an OpenTelemetry Histogram used to record float64 +// measurements. It produces no telemetry. +type Float64Histogram struct{ embedded.Float64Histogram } + +// Record performs no operation. +func (Float64Histogram) Record(context.Context, float64, ...metric.RecordOption) {} + +// Int64ObservableCounter is an OpenTelemetry ObservableCounter used to record +// int64 measurements. It produces no telemetry. +type Int64ObservableCounter struct { + metric.Int64Observable + embedded.Int64ObservableCounter +} + +// Float64ObservableCounter is an OpenTelemetry ObservableCounter used to record +// float64 measurements. It produces no telemetry. +type Float64ObservableCounter struct { + metric.Float64Observable + embedded.Float64ObservableCounter +} + +// Int64ObservableGauge is an OpenTelemetry ObservableGauge used to record +// int64 measurements. It produces no telemetry. +type Int64ObservableGauge struct { + metric.Int64Observable + embedded.Int64ObservableGauge +} + +// Float64ObservableGauge is an OpenTelemetry ObservableGauge used to record +// float64 measurements. It produces no telemetry. +type Float64ObservableGauge struct { + metric.Float64Observable + embedded.Float64ObservableGauge +} + +// Int64ObservableUpDownCounter is an OpenTelemetry ObservableUpDownCounter +// used to record int64 measurements. It produces no telemetry. +type Int64ObservableUpDownCounter struct { + metric.Int64Observable + embedded.Int64ObservableUpDownCounter +} + +// Float64ObservableUpDownCounter is an OpenTelemetry ObservableUpDownCounter +// used to record float64 measurements. It produces no telemetry. +type Float64ObservableUpDownCounter struct { + metric.Float64Observable + embedded.Float64ObservableUpDownCounter +} + +// Int64Observer is a recorder of int64 measurements that performs no operation. +type Int64Observer struct{ embedded.Int64Observer } + +// Observe performs no operation. +func (Int64Observer) Observe(int64, ...metric.ObserveOption) {} + +// Float64Observer is a recorder of float64 measurements that performs no +// operation. +type Float64Observer struct{ embedded.Float64Observer } + +// Observe performs no operation. +func (Float64Observer) Observe(float64, ...metric.ObserveOption) {} diff --git a/vendor/go.opentelemetry.io/otel/sdk/resource/auto.go b/vendor/go.opentelemetry.io/otel/sdk/resource/auto.go index 4279013be8..aed756c5e7 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/resource/auto.go +++ b/vendor/go.opentelemetry.io/otel/sdk/resource/auto.go @@ -41,8 +41,20 @@ type Detector interface { // must never be done outside of a new major release. } -// Detect calls all input detectors sequentially and merges each result with the previous one. -// It returns the merged error too. +// Detect returns a new [Resource] merged from all the Resources each of the +// detectors produces. Each of the detectors are called sequentially, in the +// order they are passed, merging the produced resource into the previous. +// +// This may return a partial Resource along with an error containing +// [ErrPartialResource] if that error is returned from a detector. It may also +// return a merge-conflicting Resource along with an error containing +// [ErrSchemaURLConflict] if merging Resources from different detectors results +// in a schema URL conflict. It is up to the caller to determine if this +// returned Resource should be used or not. +// +// If one of the detectors returns an error that is not [ErrPartialResource], +// the resource produced by the detector will not be merged and the returned +// error will wrap that detector's error. func Detect(ctx context.Context, detectors ...Detector) (*Resource, error) { r := new(Resource) return r, detect(ctx, r, detectors) @@ -50,6 +62,10 @@ func Detect(ctx context.Context, detectors ...Detector) (*Resource, error) { // detect runs all detectors using ctx and merges the result into res. This // assumes res is allocated and not nil, it will panic otherwise. +// +// If the detectors or merging resources produces any errors (i.e. +// [ErrPartialResource] [ErrSchemaURLConflict]), a single error wrapping all of +// these errors will be returned. Otherwise, nil is returned. func detect(ctx context.Context, res *Resource, detectors []Detector) error { var ( r *Resource @@ -78,6 +94,11 @@ func detect(ctx context.Context, res *Resource, detectors []Detector) error { if len(errs) == 0 { return nil } + if errors.Is(errs, ErrSchemaURLConflict) { + // If there has been a merge conflict, ensure the resource has no + // schema URL. + res.schemaURL = "" + } return errs } diff --git a/vendor/go.opentelemetry.io/otel/sdk/resource/container.go b/vendor/go.opentelemetry.io/otel/sdk/resource/container.go index c881b2895b..c1b47193fe 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/resource/container.go +++ b/vendor/go.opentelemetry.io/otel/sdk/resource/container.go @@ -29,7 +29,7 @@ type containerIDProvider func() (string, error) var ( containerID containerIDProvider = getContainerIDFromCGroup - cgroupContainerIDRe = regexp.MustCompile(`^.*/(?:.*-)?([0-9a-f]+)(?:\.|\s*$)`) + cgroupContainerIDRe = regexp.MustCompile(`^.*/(?:.*[-:])?([0-9a-f]+)(?:\.|\s*$)`) ) type cgroupContainerIDDetector struct{} diff --git a/vendor/go.opentelemetry.io/otel/sdk/resource/resource.go b/vendor/go.opentelemetry.io/otel/sdk/resource/resource.go index 176ff10666..cb1ee0a9ce 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/resource/resource.go +++ b/vendor/go.opentelemetry.io/otel/sdk/resource/resource.go @@ -17,6 +17,7 @@ package resource // import "go.opentelemetry.io/otel/sdk/resource" import ( "context" "errors" + "fmt" "sync" "go.opentelemetry.io/otel" @@ -40,9 +41,20 @@ var ( defaultResourceOnce sync.Once ) -var errMergeConflictSchemaURL = errors.New("cannot merge resource due to conflicting Schema URL") +// ErrSchemaURLConflict is an error returned when two Resources are merged +// together that contain different, non-empty, schema URLs. +var ErrSchemaURLConflict = errors.New("conflicting Schema URL") -// New returns a Resource combined from the user-provided detectors. +// New returns a [Resource] built using opts. +// +// This may return a partial Resource along with an error containing +// [ErrPartialResource] if options that provide a [Detector] are used and that +// error is returned from one or more of the Detectors. It may also return a +// merge-conflict Resource along with an error containing +// [ErrSchemaURLConflict] if merging Resources from the opts results in a +// schema URL conflict (see [Resource.Merge] for more information). It is up to +// the caller to determine if this returned Resource should be used or not +// based on these errors. func New(ctx context.Context, opts ...Option) (*Resource, error) { cfg := config{} for _, opt := range opts { @@ -98,7 +110,7 @@ func (r *Resource) String() string { return r.attrs.Encoded(attribute.DefaultEncoder()) } -// MarshalLog is the marshaling function used by the logging system to represent this exporter. +// MarshalLog is the marshaling function used by the logging system to represent this Resource. func (r *Resource) MarshalLog() interface{} { return struct { Attributes attribute.Set @@ -146,16 +158,29 @@ func (r *Resource) Equal(eq *Resource) bool { return r.Equivalent() == eq.Equivalent() } -// Merge creates a new resource by combining resource a and b. +// Merge creates a new [Resource] by merging a and b. +// +// If there are common keys between a and b, then the value from b will +// overwrite the value from a, even if b's value is empty. // -// If there are common keys between resource a and b, then the value -// from resource b will overwrite the value from resource a, even -// if resource b's value is empty. +// The SchemaURL of the resources will be merged according to the +// [OpenTelemetry specification rules]: // -// The SchemaURL of the resources will be merged according to the spec rules: -// https://github.com/open-telemetry/opentelemetry-specification/blob/v1.20.0/specification/resource/sdk.md#merge -// If the resources have different non-empty schemaURL an empty resource and an error -// will be returned. +// - If a's schema URL is empty then the returned Resource's schema URL will +// be set to the schema URL of b, +// - Else if b's schema URL is empty then the returned Resource's schema URL +// will be set to the schema URL of a, +// - Else if the schema URLs of a and b are the same then that will be the +// schema URL of the returned Resource, +// - Else this is a merging error. If the resources have different, +// non-empty, schema URLs an error containing [ErrSchemaURLConflict] will +// be returned with the merged Resource. The merged Resource will have an +// empty schema URL. It may be the case that some unintended attributes +// have been overwritten or old semantic conventions persisted in the +// returned Resource. It is up to the caller to determine if this returned +// Resource should be used or not. +// +// [OpenTelemetry specification rules]: https://github.com/open-telemetry/opentelemetry-specification/blob/v1.20.0/specification/resource/sdk.md#merge func Merge(a, b *Resource) (*Resource, error) { if a == nil && b == nil { return Empty(), nil @@ -167,19 +192,6 @@ func Merge(a, b *Resource) (*Resource, error) { return a, nil } - // Merge the schema URL. - var schemaURL string - switch true { - case a.schemaURL == "": - schemaURL = b.schemaURL - case b.schemaURL == "": - schemaURL = a.schemaURL - case a.schemaURL == b.schemaURL: - schemaURL = a.schemaURL - default: - return Empty(), errMergeConflictSchemaURL - } - // Note: 'b' attributes will overwrite 'a' with last-value-wins in attribute.Key() // Meaning this is equivalent to: append(a.Attributes(), b.Attributes()...) mi := attribute.NewMergeIterator(b.Set(), a.Set()) @@ -187,8 +199,23 @@ func Merge(a, b *Resource) (*Resource, error) { for mi.Next() { combine = append(combine, mi.Attribute()) } - merged := NewWithAttributes(schemaURL, combine...) - return merged, nil + + switch { + case a.schemaURL == "": + return NewWithAttributes(b.schemaURL, combine...), nil + case b.schemaURL == "": + return NewWithAttributes(a.schemaURL, combine...), nil + case a.schemaURL == b.schemaURL: + return NewWithAttributes(a.schemaURL, combine...), nil + } + // Return the merged resource with an appropriate error. It is up to + // the user to decide if the returned resource can be used or not. + return NewSchemaless(combine...), fmt.Errorf( + "%w: %s and %s", + ErrSchemaURLConflict, + a.schemaURL, + b.schemaURL, + ) } // Empty returns an instance of Resource with no attributes. It is diff --git a/vendor/go.opentelemetry.io/otel/sdk/trace/batch_span_processor.go b/vendor/go.opentelemetry.io/otel/sdk/trace/batch_span_processor.go index c9c7effbf3..fca26f2e70 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/trace/batch_span_processor.go +++ b/vendor/go.opentelemetry.io/otel/sdk/trace/batch_span_processor.go @@ -406,7 +406,7 @@ func (bsp *batchSpanProcessor) enqueueDrop(ctx context.Context, sd ReadOnlySpan) return false } -// MarshalLog is the marshaling function used by the logging system to represent this exporter. +// MarshalLog is the marshaling function used by the logging system to represent this Span Processor. func (bsp *batchSpanProcessor) MarshalLog() interface{} { return struct { Type string diff --git a/vendor/go.opentelemetry.io/otel/sdk/trace/provider.go b/vendor/go.opentelemetry.io/otel/sdk/trace/provider.go index 7d46c4b48e..b1ac608464 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/trace/provider.go +++ b/vendor/go.opentelemetry.io/otel/sdk/trace/provider.go @@ -55,7 +55,7 @@ type tracerProviderConfig struct { resource *resource.Resource } -// MarshalLog is the marshaling function used by the logging system to represent this exporter. +// MarshalLog is the marshaling function used by the logging system to represent this Provider. func (cfg tracerProviderConfig) MarshalLog() interface{} { return struct { SpanProcessors []SpanProcessor diff --git a/vendor/go.opentelemetry.io/otel/sdk/version.go b/vendor/go.opentelemetry.io/otel/sdk/version.go index 17b16cc796..42de0b9a7c 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/version.go +++ b/vendor/go.opentelemetry.io/otel/sdk/version.go @@ -16,5 +16,5 @@ package sdk // import "go.opentelemetry.io/otel/sdk" // Version is the current release version of the OpenTelemetry SDK in use. func Version() string { - return "1.22.0" + return "1.24.0" } diff --git a/vendor/go.opentelemetry.io/otel/version.go b/vendor/go.opentelemetry.io/otel/version.go index c7aba1c3f4..7b2993a1fe 100644 --- a/vendor/go.opentelemetry.io/otel/version.go +++ b/vendor/go.opentelemetry.io/otel/version.go @@ -16,5 +16,5 @@ package otel // import "go.opentelemetry.io/otel" // Version is the current release version of OpenTelemetry in use. func Version() string { - return "1.22.0" + return "1.24.0" } diff --git a/vendor/go.opentelemetry.io/otel/versions.yaml b/vendor/go.opentelemetry.io/otel/versions.yaml index a9cfb80ae5..1b556e6782 100644 --- a/vendor/go.opentelemetry.io/otel/versions.yaml +++ b/vendor/go.opentelemetry.io/otel/versions.yaml @@ -14,19 +14,25 @@ module-sets: stable-v1: - version: v1.22.0 + version: v1.24.0 modules: - go.opentelemetry.io/otel + - go.opentelemetry.io/otel/bridge/opencensus + - go.opentelemetry.io/otel/bridge/opencensus/test - go.opentelemetry.io/otel/bridge/opentracing - go.opentelemetry.io/otel/bridge/opentracing/test - go.opentelemetry.io/otel/example/dice - go.opentelemetry.io/otel/example/namedtracer + - go.opentelemetry.io/otel/example/opencensus - go.opentelemetry.io/otel/example/otel-collector - go.opentelemetry.io/otel/example/passthrough - go.opentelemetry.io/otel/example/zipkin + - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc + - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp - go.opentelemetry.io/otel/exporters/otlp/otlptrace - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp + - go.opentelemetry.io/otel/exporters/stdout/stdoutmetric - go.opentelemetry.io/otel/exporters/stdout/stdouttrace - go.opentelemetry.io/otel/exporters/zipkin - go.opentelemetry.io/otel/metric @@ -34,16 +40,14 @@ module-sets: - go.opentelemetry.io/otel/sdk/metric - go.opentelemetry.io/otel/trace experimental-metrics: - version: v0.45.0 + version: v0.46.0 modules: - - go.opentelemetry.io/otel/bridge/opencensus - - go.opentelemetry.io/otel/bridge/opencensus/test - - go.opentelemetry.io/otel/example/opencensus - go.opentelemetry.io/otel/example/prometheus - - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc - - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp - go.opentelemetry.io/otel/exporters/prometheus - - go.opentelemetry.io/otel/exporters/stdout/stdoutmetric + experimental-logs: + version: v0.0.1-alpha + modules: + - go.opentelemetry.io/otel/log experimental-schema: version: v0.0.7 modules: diff --git a/vendor/go.opentelemetry.io/proto/otlp/trace/v1/trace.pb.go b/vendor/go.opentelemetry.io/proto/otlp/trace/v1/trace.pb.go index 51a499816a..7109088370 100644 --- a/vendor/go.opentelemetry.io/proto/otlp/trace/v1/trace.pb.go +++ b/vendor/go.opentelemetry.io/proto/otlp/trace/v1/trace.pb.go @@ -36,6 +36,69 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +// SpanFlags represents constants used to interpret the +// Span.flags field, which is protobuf 'fixed32' type and is to +// be used as bit-fields. Each non-zero value defined in this enum is +// a bit-mask. To extract the bit-field, for example, use an +// expression like: +// +// (span.flags & SPAN_FLAGS_TRACE_FLAGS_MASK) +// +// See https://www.w3.org/TR/trace-context-2/#trace-flags for the flag definitions. +// +// Note that Span flags were introduced in version 1.1 of the +// OpenTelemetry protocol. Older Span producers do not set this +// field, consequently consumers should not rely on the absence of a +// particular flag bit to indicate the presence of a particular feature. +type SpanFlags int32 + +const ( + // The zero value for the enum. Should not be used for comparisons. + // Instead use bitwise "and" with the appropriate mask as shown above. + SpanFlags_SPAN_FLAGS_DO_NOT_USE SpanFlags = 0 + // Bits 0-7 are used for trace flags. + SpanFlags_SPAN_FLAGS_TRACE_FLAGS_MASK SpanFlags = 255 +) + +// Enum value maps for SpanFlags. +var ( + SpanFlags_name = map[int32]string{ + 0: "SPAN_FLAGS_DO_NOT_USE", + 255: "SPAN_FLAGS_TRACE_FLAGS_MASK", + } + SpanFlags_value = map[string]int32{ + "SPAN_FLAGS_DO_NOT_USE": 0, + "SPAN_FLAGS_TRACE_FLAGS_MASK": 255, + } +) + +func (x SpanFlags) Enum() *SpanFlags { + p := new(SpanFlags) + *p = x + return p +} + +func (x SpanFlags) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (SpanFlags) Descriptor() protoreflect.EnumDescriptor { + return file_opentelemetry_proto_trace_v1_trace_proto_enumTypes[0].Descriptor() +} + +func (SpanFlags) Type() protoreflect.EnumType { + return &file_opentelemetry_proto_trace_v1_trace_proto_enumTypes[0] +} + +func (x SpanFlags) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use SpanFlags.Descriptor instead. +func (SpanFlags) EnumDescriptor() ([]byte, []int) { + return file_opentelemetry_proto_trace_v1_trace_proto_rawDescGZIP(), []int{0} +} + // SpanKind is the type of span. Can be used to specify additional relationships between spans // in addition to a parent/child relationship. type Span_SpanKind int32 @@ -94,11 +157,11 @@ func (x Span_SpanKind) String() string { } func (Span_SpanKind) Descriptor() protoreflect.EnumDescriptor { - return file_opentelemetry_proto_trace_v1_trace_proto_enumTypes[0].Descriptor() + return file_opentelemetry_proto_trace_v1_trace_proto_enumTypes[1].Descriptor() } func (Span_SpanKind) Type() protoreflect.EnumType { - return &file_opentelemetry_proto_trace_v1_trace_proto_enumTypes[0] + return &file_opentelemetry_proto_trace_v1_trace_proto_enumTypes[1] } func (x Span_SpanKind) Number() protoreflect.EnumNumber { @@ -149,11 +212,11 @@ func (x Status_StatusCode) String() string { } func (Status_StatusCode) Descriptor() protoreflect.EnumDescriptor { - return file_opentelemetry_proto_trace_v1_trace_proto_enumTypes[1].Descriptor() + return file_opentelemetry_proto_trace_v1_trace_proto_enumTypes[2].Descriptor() } func (Status_StatusCode) Type() protoreflect.EnumType { - return &file_opentelemetry_proto_trace_v1_trace_proto_enumTypes[1] + return &file_opentelemetry_proto_trace_v1_trace_proto_enumTypes[2] } func (x Status_StatusCode) Number() protoreflect.EnumNumber { @@ -238,6 +301,9 @@ type ResourceSpans struct { Resource *v1.Resource `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource,omitempty"` // A list of ScopeSpans that originate from a resource. ScopeSpans []*ScopeSpans `protobuf:"bytes,2,rep,name=scope_spans,json=scopeSpans,proto3" json:"scope_spans,omitempty"` + // The Schema URL, if known. This is the identifier of the Schema that the resource data + // is recorded in. To learn more about Schema URL see + // https://opentelemetry.io/docs/specs/otel/schemas/#schema-url // This schema_url applies to the data in the "resource" field. It does not apply // to the data in the "scope_spans" field which have their own schema_url field. SchemaUrl string `protobuf:"bytes,3,opt,name=schema_url,json=schemaUrl,proto3" json:"schema_url,omitempty"` @@ -308,6 +374,9 @@ type ScopeSpans struct { Scope *v11.InstrumentationScope `protobuf:"bytes,1,opt,name=scope,proto3" json:"scope,omitempty"` // A list of Spans that originate from an instrumentation scope. Spans []*Span `protobuf:"bytes,2,rep,name=spans,proto3" json:"spans,omitempty"` + // The Schema URL, if known. This is the identifier of the Schema that the span data + // is recorded in. To learn more about Schema URL see + // https://opentelemetry.io/docs/specs/otel/schemas/#schema-url // This schema_url applies to all spans and span events in the "spans" field. SchemaUrl string `protobuf:"bytes,3,opt,name=schema_url,json=schemaUrl,proto3" json:"schema_url,omitempty"` } @@ -394,6 +463,21 @@ type Span struct { // The `span_id` of this span's parent span. If this is a root span, then this // field must be empty. The ID is an 8-byte array. ParentSpanId []byte `protobuf:"bytes,4,opt,name=parent_span_id,json=parentSpanId,proto3" json:"parent_span_id,omitempty"` + // Flags, a bit field. 8 least significant bits are the trace + // flags as defined in W3C Trace Context specification. Readers + // MUST not assume that 24 most significant bits will be zero. + // To read the 8-bit W3C trace flag, use `flags & SPAN_FLAGS_TRACE_FLAGS_MASK`. + // + // When creating span messages, if the message is logically forwarded from another source + // with an equivalent flags fields (i.e., usually another OTLP span message), the field SHOULD + // be copied as-is. If creating from a source that does not have an equivalent flags field + // (such as a runtime representation of an OpenTelemetry span), the high 24 bits MUST + // be set to zero. + // + // [Optional]. + // + // See https://www.w3.org/TR/trace-context-2/#trace-flags for the flag definitions. + Flags uint32 `protobuf:"fixed32,16,opt,name=flags,proto3" json:"flags,omitempty"` // A description of the span's operation. // // For example, the name can be a qualified method name or a file name @@ -517,6 +601,13 @@ func (x *Span) GetParentSpanId() []byte { return nil } +func (x *Span) GetFlags() uint32 { + if x != nil { + return x.Flags + } + return 0 +} + func (x *Span) GetName() string { if x != nil { return x.Name @@ -757,6 +848,15 @@ type Span_Link struct { // dropped_attributes_count is the number of dropped attributes. If the value is 0, // then no attributes were dropped. DroppedAttributesCount uint32 `protobuf:"varint,5,opt,name=dropped_attributes_count,json=droppedAttributesCount,proto3" json:"dropped_attributes_count,omitempty"` + // Flags, a bit field. 8 least significant bits are the trace + // flags as defined in W3C Trace Context specification. Readers + // MUST not assume that 24 most significant bits will be zero. + // When creating new spans, the most-significant 24-bits MUST be + // zero. To read the 8-bit W3C trace flag (use flags & + // SPAN_FLAGS_TRACE_FLAGS_MASK). [Optional]. + // + // See https://www.w3.org/TR/trace-context-2/#trace-flags for the flag definitions. + Flags uint32 `protobuf:"fixed32,6,opt,name=flags,proto3" json:"flags,omitempty"` } func (x *Span_Link) Reset() { @@ -826,6 +926,13 @@ func (x *Span_Link) GetDroppedAttributesCount() uint32 { return 0 } +func (x *Span_Link) GetFlags() uint32 { + if x != nil { + return x.Flags + } + return 0 +} + var File_opentelemetry_proto_trace_v1_trace_proto protoreflect.FileDescriptor var file_opentelemetry_proto_trace_v1_trace_proto_rawDesc = []byte{ @@ -869,7 +976,7 @@ var file_opentelemetry_proto_trace_v1_trace_proto_rawDesc = []byte{ 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, 0x6e, 0x52, 0x05, 0x73, 0x70, 0x61, 0x6e, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x63, 0x68, 0x65, 0x6d, - 0x61, 0x55, 0x72, 0x6c, 0x22, 0x9c, 0x0a, 0x0a, 0x04, 0x53, 0x70, 0x61, 0x6e, 0x12, 0x19, 0x0a, + 0x61, 0x55, 0x72, 0x6c, 0x22, 0xc8, 0x0a, 0x0a, 0x04, 0x53, 0x70, 0x61, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x74, 0x72, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x70, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x70, 0x61, 0x6e, 0x49, @@ -877,101 +984,108 @@ var file_opentelemetry_proto_trace_v1_trace_proto_rawDesc = []byte{ 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x72, 0x61, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x70, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x70, 0x61, 0x72, 0x65, - 0x6e, 0x74, 0x53, 0x70, 0x61, 0x6e, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3f, 0x0a, 0x04, - 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x6f, 0x70, 0x65, - 0x6e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, 0x6e, 0x2e, 0x53, - 0x70, 0x61, 0x6e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x2f, 0x0a, - 0x14, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x75, 0x6e, 0x69, 0x78, - 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x18, 0x07, 0x20, 0x01, 0x28, 0x06, 0x52, 0x11, 0x73, 0x74, 0x61, - 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x78, 0x4e, 0x61, 0x6e, 0x6f, 0x12, 0x2b, - 0x0a, 0x12, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x75, 0x6e, 0x69, 0x78, 0x5f, - 0x6e, 0x61, 0x6e, 0x6f, 0x18, 0x08, 0x20, 0x01, 0x28, 0x06, 0x52, 0x0f, 0x65, 0x6e, 0x64, 0x54, - 0x69, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x78, 0x4e, 0x61, 0x6e, 0x6f, 0x12, 0x47, 0x0a, 0x0a, 0x61, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x27, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, - 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x73, 0x12, 0x38, 0x0a, 0x18, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x5f, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x16, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x41, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x40, - 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, - 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, - 0x61, 0x6e, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, - 0x12, 0x30, 0x0a, 0x14, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, - 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x43, 0x6f, 0x75, - 0x6e, 0x74, 0x12, 0x3d, 0x0a, 0x05, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x27, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, - 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x70, 0x61, 0x6e, 0x2e, 0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x05, 0x6c, 0x69, 0x6e, 0x6b, - 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x6c, 0x69, 0x6e, - 0x6b, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, - 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x4c, 0x69, 0x6e, 0x6b, 0x73, 0x43, 0x6f, 0x75, 0x6e, - 0x74, 0x12, 0x3c, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x24, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, - 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x1a, - 0xc4, 0x01, 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x69, 0x6d, - 0x65, 0x5f, 0x75, 0x6e, 0x69, 0x78, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x06, 0x52, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x78, 0x4e, 0x61, 0x6e, 0x6f, 0x12, - 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x12, 0x47, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x65, - 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, - 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x38, 0x0a, 0x18, - 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x16, - 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x1a, 0xde, 0x01, 0x0a, 0x04, 0x4c, 0x69, 0x6e, 0x6b, 0x12, - 0x19, 0x0a, 0x08, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x07, 0x74, 0x72, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x70, - 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x70, 0x61, - 0x6e, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x72, 0x61, 0x63, 0x65, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x12, 0x47, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x74, - 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, - 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x38, 0x0a, - 0x18, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, - 0x16, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x99, 0x01, 0x0a, 0x08, 0x53, 0x70, 0x61, 0x6e, - 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x19, 0x0a, 0x15, 0x53, 0x50, 0x41, 0x4e, 0x5f, 0x4b, 0x49, 0x4e, - 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, - 0x16, 0x0a, 0x12, 0x53, 0x50, 0x41, 0x4e, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x49, 0x4e, 0x54, - 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x50, 0x41, 0x4e, 0x5f, - 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x10, 0x02, 0x12, 0x14, 0x0a, - 0x10, 0x53, 0x50, 0x41, 0x4e, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x43, 0x4c, 0x49, 0x45, 0x4e, - 0x54, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x50, 0x41, 0x4e, 0x5f, 0x4b, 0x49, 0x4e, 0x44, - 0x5f, 0x50, 0x52, 0x4f, 0x44, 0x55, 0x43, 0x45, 0x52, 0x10, 0x04, 0x12, 0x16, 0x0a, 0x12, 0x53, - 0x50, 0x41, 0x4e, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x43, 0x4f, 0x4e, 0x53, 0x55, 0x4d, 0x45, - 0x52, 0x10, 0x05, 0x22, 0xbd, 0x01, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, - 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x43, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x65, 0x6c, - 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x74, 0x72, 0x61, - 0x63, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x22, 0x4e, 0x0a, - 0x0a, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x15, 0x0a, 0x11, 0x53, - 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x45, 0x54, - 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x4f, 0x44, - 0x45, 0x5f, 0x4f, 0x4b, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, - 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x4a, 0x04, 0x08, - 0x01, 0x10, 0x02, 0x42, 0x77, 0x0a, 0x1f, 0x69, 0x6f, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x53, 0x70, 0x61, 0x6e, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6c, 0x61, 0x67, + 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x07, 0x52, 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x12, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x2b, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x53, 0x70, 0x61, 0x6e, 0x2e, 0x53, 0x70, 0x61, 0x6e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x6b, + 0x69, 0x6e, 0x64, 0x12, 0x2f, 0x0a, 0x14, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, + 0x65, 0x5f, 0x75, 0x6e, 0x69, 0x78, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x06, 0x52, 0x11, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x78, + 0x4e, 0x61, 0x6e, 0x6f, 0x12, 0x2b, 0x0a, 0x12, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, + 0x5f, 0x75, 0x6e, 0x69, 0x78, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x18, 0x08, 0x20, 0x01, 0x28, 0x06, + 0x52, 0x0f, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x55, 0x6e, 0x69, 0x78, 0x4e, 0x61, 0x6e, + 0x6f, 0x12, 0x47, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, + 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x65, 0x6c, 0x65, + 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, + 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0a, + 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x38, 0x0a, 0x18, 0x64, 0x72, + 0x6f, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, + 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x16, 0x64, 0x72, + 0x6f, 0x70, 0x70, 0x65, 0x64, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x43, + 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x40, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x0b, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x65, 0x6c, 0x65, 0x6d, + 0x65, 0x74, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, 0x6e, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x06, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, + 0x64, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0c, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x3d, 0x0a, 0x05, 0x6c, 0x69, 0x6e, 0x6b, + 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x65, + 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x74, 0x72, + 0x61, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x70, 0x61, 0x6e, 0x2e, 0x4c, 0x69, 0x6e, 0x6b, + 0x52, 0x05, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x64, 0x72, 0x6f, 0x70, 0x70, + 0x65, 0x64, 0x5f, 0x6c, 0x69, 0x6e, 0x6b, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0e, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x4c, 0x69, 0x6e, + 0x6b, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x3c, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x74, 0x72, - 0x61, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x42, 0x0a, 0x54, 0x72, 0x61, 0x63, 0x65, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x27, 0x67, 0x6f, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x65, 0x6c, - 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x69, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, - 0x6f, 0x74, 0x6c, 0x70, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2f, 0x76, 0x31, 0xaa, 0x02, 0x1c, - 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x50, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x2e, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x61, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x1a, 0xc4, 0x01, 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, + 0x24, 0x0a, 0x0e, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x75, 0x6e, 0x69, 0x78, 0x5f, 0x6e, 0x61, 0x6e, + 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x06, 0x52, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x55, 0x6e, 0x69, + 0x78, 0x4e, 0x61, 0x6e, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x47, 0x0a, 0x0a, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, + 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x65, + 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x12, 0x38, 0x0a, 0x18, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x16, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x1a, 0xf4, 0x01, 0x0a, + 0x04, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x74, 0x72, 0x61, 0x63, 0x65, 0x49, 0x64, + 0x12, 0x17, 0x0a, 0x07, 0x73, 0x70, 0x61, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x06, 0x73, 0x70, 0x61, 0x6e, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x72, 0x61, + 0x63, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x74, 0x72, 0x61, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x47, 0x0a, 0x0a, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, + 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4b, + 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x12, 0x38, 0x0a, 0x18, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x61, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x16, 0x64, 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x41, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x14, 0x0a, + 0x05, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x07, 0x52, 0x05, 0x66, 0x6c, + 0x61, 0x67, 0x73, 0x22, 0x99, 0x01, 0x0a, 0x08, 0x53, 0x70, 0x61, 0x6e, 0x4b, 0x69, 0x6e, 0x64, + 0x12, 0x19, 0x0a, 0x15, 0x53, 0x50, 0x41, 0x4e, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x55, 0x4e, + 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x53, + 0x50, 0x41, 0x4e, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, + 0x4c, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x50, 0x41, 0x4e, 0x5f, 0x4b, 0x49, 0x4e, 0x44, + 0x5f, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x10, 0x02, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x50, 0x41, + 0x4e, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x10, 0x03, 0x12, + 0x16, 0x0a, 0x12, 0x53, 0x50, 0x41, 0x4e, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x50, 0x52, 0x4f, + 0x44, 0x55, 0x43, 0x45, 0x52, 0x10, 0x04, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x50, 0x41, 0x4e, 0x5f, + 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x43, 0x4f, 0x4e, 0x53, 0x55, 0x4d, 0x45, 0x52, 0x10, 0x05, 0x22, + 0xbd, 0x01, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x12, 0x43, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, + 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, + 0x6f, 0x64, 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x22, 0x4e, 0x0a, 0x0a, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x54, 0x41, 0x54, 0x55, + 0x53, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x45, 0x54, 0x10, 0x00, 0x12, 0x12, + 0x0a, 0x0e, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x4f, 0x4b, + 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x4f, 0x44, + 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x2a, + 0x48, 0x0a, 0x09, 0x53, 0x70, 0x61, 0x6e, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x12, 0x19, 0x0a, 0x15, + 0x53, 0x50, 0x41, 0x4e, 0x5f, 0x46, 0x4c, 0x41, 0x47, 0x53, 0x5f, 0x44, 0x4f, 0x5f, 0x4e, 0x4f, + 0x54, 0x5f, 0x55, 0x53, 0x45, 0x10, 0x00, 0x12, 0x20, 0x0a, 0x1b, 0x53, 0x50, 0x41, 0x4e, 0x5f, + 0x46, 0x4c, 0x41, 0x47, 0x53, 0x5f, 0x54, 0x52, 0x41, 0x43, 0x45, 0x5f, 0x46, 0x4c, 0x41, 0x47, + 0x53, 0x5f, 0x4d, 0x41, 0x53, 0x4b, 0x10, 0xff, 0x01, 0x42, 0x77, 0x0a, 0x1f, 0x69, 0x6f, 0x2e, + 0x6f, 0x70, 0x65, 0x6e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x2e, 0x76, 0x31, 0x42, 0x0a, 0x54, 0x72, + 0x61, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x27, 0x67, 0x6f, 0x2e, 0x6f, + 0x70, 0x65, 0x6e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x2e, 0x69, 0x6f, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6f, 0x74, 0x6c, 0x70, 0x2f, 0x74, 0x72, 0x61, 0x63, 0x65, + 0x2f, 0x76, 0x31, 0xaa, 0x02, 0x1c, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, + 0x74, 0x72, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x2e, + 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -986,36 +1100,37 @@ func file_opentelemetry_proto_trace_v1_trace_proto_rawDescGZIP() []byte { return file_opentelemetry_proto_trace_v1_trace_proto_rawDescData } -var file_opentelemetry_proto_trace_v1_trace_proto_enumTypes = make([]protoimpl.EnumInfo, 2) +var file_opentelemetry_proto_trace_v1_trace_proto_enumTypes = make([]protoimpl.EnumInfo, 3) var file_opentelemetry_proto_trace_v1_trace_proto_msgTypes = make([]protoimpl.MessageInfo, 7) var file_opentelemetry_proto_trace_v1_trace_proto_goTypes = []interface{}{ - (Span_SpanKind)(0), // 0: opentelemetry.proto.trace.v1.Span.SpanKind - (Status_StatusCode)(0), // 1: opentelemetry.proto.trace.v1.Status.StatusCode - (*TracesData)(nil), // 2: opentelemetry.proto.trace.v1.TracesData - (*ResourceSpans)(nil), // 3: opentelemetry.proto.trace.v1.ResourceSpans - (*ScopeSpans)(nil), // 4: opentelemetry.proto.trace.v1.ScopeSpans - (*Span)(nil), // 5: opentelemetry.proto.trace.v1.Span - (*Status)(nil), // 6: opentelemetry.proto.trace.v1.Status - (*Span_Event)(nil), // 7: opentelemetry.proto.trace.v1.Span.Event - (*Span_Link)(nil), // 8: opentelemetry.proto.trace.v1.Span.Link - (*v1.Resource)(nil), // 9: opentelemetry.proto.resource.v1.Resource - (*v11.InstrumentationScope)(nil), // 10: opentelemetry.proto.common.v1.InstrumentationScope - (*v11.KeyValue)(nil), // 11: opentelemetry.proto.common.v1.KeyValue + (SpanFlags)(0), // 0: opentelemetry.proto.trace.v1.SpanFlags + (Span_SpanKind)(0), // 1: opentelemetry.proto.trace.v1.Span.SpanKind + (Status_StatusCode)(0), // 2: opentelemetry.proto.trace.v1.Status.StatusCode + (*TracesData)(nil), // 3: opentelemetry.proto.trace.v1.TracesData + (*ResourceSpans)(nil), // 4: opentelemetry.proto.trace.v1.ResourceSpans + (*ScopeSpans)(nil), // 5: opentelemetry.proto.trace.v1.ScopeSpans + (*Span)(nil), // 6: opentelemetry.proto.trace.v1.Span + (*Status)(nil), // 7: opentelemetry.proto.trace.v1.Status + (*Span_Event)(nil), // 8: opentelemetry.proto.trace.v1.Span.Event + (*Span_Link)(nil), // 9: opentelemetry.proto.trace.v1.Span.Link + (*v1.Resource)(nil), // 10: opentelemetry.proto.resource.v1.Resource + (*v11.InstrumentationScope)(nil), // 11: opentelemetry.proto.common.v1.InstrumentationScope + (*v11.KeyValue)(nil), // 12: opentelemetry.proto.common.v1.KeyValue } var file_opentelemetry_proto_trace_v1_trace_proto_depIdxs = []int32{ - 3, // 0: opentelemetry.proto.trace.v1.TracesData.resource_spans:type_name -> opentelemetry.proto.trace.v1.ResourceSpans - 9, // 1: opentelemetry.proto.trace.v1.ResourceSpans.resource:type_name -> opentelemetry.proto.resource.v1.Resource - 4, // 2: opentelemetry.proto.trace.v1.ResourceSpans.scope_spans:type_name -> opentelemetry.proto.trace.v1.ScopeSpans - 10, // 3: opentelemetry.proto.trace.v1.ScopeSpans.scope:type_name -> opentelemetry.proto.common.v1.InstrumentationScope - 5, // 4: opentelemetry.proto.trace.v1.ScopeSpans.spans:type_name -> opentelemetry.proto.trace.v1.Span - 0, // 5: opentelemetry.proto.trace.v1.Span.kind:type_name -> opentelemetry.proto.trace.v1.Span.SpanKind - 11, // 6: opentelemetry.proto.trace.v1.Span.attributes:type_name -> opentelemetry.proto.common.v1.KeyValue - 7, // 7: opentelemetry.proto.trace.v1.Span.events:type_name -> opentelemetry.proto.trace.v1.Span.Event - 8, // 8: opentelemetry.proto.trace.v1.Span.links:type_name -> opentelemetry.proto.trace.v1.Span.Link - 6, // 9: opentelemetry.proto.trace.v1.Span.status:type_name -> opentelemetry.proto.trace.v1.Status - 1, // 10: opentelemetry.proto.trace.v1.Status.code:type_name -> opentelemetry.proto.trace.v1.Status.StatusCode - 11, // 11: opentelemetry.proto.trace.v1.Span.Event.attributes:type_name -> opentelemetry.proto.common.v1.KeyValue - 11, // 12: opentelemetry.proto.trace.v1.Span.Link.attributes:type_name -> opentelemetry.proto.common.v1.KeyValue + 4, // 0: opentelemetry.proto.trace.v1.TracesData.resource_spans:type_name -> opentelemetry.proto.trace.v1.ResourceSpans + 10, // 1: opentelemetry.proto.trace.v1.ResourceSpans.resource:type_name -> opentelemetry.proto.resource.v1.Resource + 5, // 2: opentelemetry.proto.trace.v1.ResourceSpans.scope_spans:type_name -> opentelemetry.proto.trace.v1.ScopeSpans + 11, // 3: opentelemetry.proto.trace.v1.ScopeSpans.scope:type_name -> opentelemetry.proto.common.v1.InstrumentationScope + 6, // 4: opentelemetry.proto.trace.v1.ScopeSpans.spans:type_name -> opentelemetry.proto.trace.v1.Span + 1, // 5: opentelemetry.proto.trace.v1.Span.kind:type_name -> opentelemetry.proto.trace.v1.Span.SpanKind + 12, // 6: opentelemetry.proto.trace.v1.Span.attributes:type_name -> opentelemetry.proto.common.v1.KeyValue + 8, // 7: opentelemetry.proto.trace.v1.Span.events:type_name -> opentelemetry.proto.trace.v1.Span.Event + 9, // 8: opentelemetry.proto.trace.v1.Span.links:type_name -> opentelemetry.proto.trace.v1.Span.Link + 7, // 9: opentelemetry.proto.trace.v1.Span.status:type_name -> opentelemetry.proto.trace.v1.Status + 2, // 10: opentelemetry.proto.trace.v1.Status.code:type_name -> opentelemetry.proto.trace.v1.Status.StatusCode + 12, // 11: opentelemetry.proto.trace.v1.Span.Event.attributes:type_name -> opentelemetry.proto.common.v1.KeyValue + 12, // 12: opentelemetry.proto.trace.v1.Span.Link.attributes:type_name -> opentelemetry.proto.common.v1.KeyValue 13, // [13:13] is the sub-list for method output_type 13, // [13:13] is the sub-list for method input_type 13, // [13:13] is the sub-list for extension type_name @@ -1119,7 +1234,7 @@ func file_opentelemetry_proto_trace_v1_trace_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_opentelemetry_proto_trace_v1_trace_proto_rawDesc, - NumEnums: 2, + NumEnums: 3, NumMessages: 7, NumExtensions: 0, NumServices: 0, diff --git a/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s b/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s index d2ca5deeb9..b3c1699bff 100644 --- a/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s +++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64le.s @@ -19,15 +19,14 @@ #define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3, t4, t5) \ MULLD r0, h0, t0; \ - MULLD r0, h1, t4; \ MULHDU r0, h0, t1; \ + MULLD r0, h1, t4; \ MULHDU r0, h1, t5; \ ADDC t4, t1, t1; \ MULLD r0, h2, t2; \ - ADDZE t5; \ MULHDU r1, h0, t4; \ MULLD r1, h0, h0; \ - ADD t5, t2, t2; \ + ADDE t5, t2, t2; \ ADDC h0, t1, t1; \ MULLD h2, r1, t3; \ ADDZE t4, h0; \ @@ -37,13 +36,11 @@ ADDE t5, t3, t3; \ ADDC h0, t2, t2; \ MOVD $-4, t4; \ - MOVD t0, h0; \ - MOVD t1, h1; \ ADDZE t3; \ - ANDCC $3, t2, h2; \ - AND t2, t4, t0; \ + RLDICL $0, t2, $62, h2; \ + AND t2, t4, h0; \ ADDC t0, h0, h0; \ - ADDE t3, h1, h1; \ + ADDE t3, t1, h1; \ SLD $62, t3, t4; \ SRD $2, t2; \ ADDZE h2; \ @@ -75,6 +72,7 @@ TEXT ·update(SB), $0-32 loop: POLY1305_ADD(R4, R8, R9, R10, R20, R21, R22) + PCALIGN $16 multiply: POLY1305_MUL(R8, R9, R10, R11, R12, R16, R17, R18, R14, R20, R21) ADD $-16, R5 diff --git a/vendor/golang.org/x/net/http2/transport.go b/vendor/golang.org/x/net/http2/transport.go index df578b86c6..c2a5b44b3d 100644 --- a/vendor/golang.org/x/net/http2/transport.go +++ b/vendor/golang.org/x/net/http2/transport.go @@ -2911,6 +2911,15 @@ func (rl *clientConnReadLoop) processWindowUpdate(f *WindowUpdateFrame) error { fl = &cs.flow } if !fl.add(int32(f.Increment)) { + // For stream, the sender sends RST_STREAM with an error code of FLOW_CONTROL_ERROR + if cs != nil { + rl.endStreamError(cs, StreamError{ + StreamID: f.StreamID, + Code: ErrCodeFlowControl, + }) + return nil + } + return ConnectionError(ErrCodeFlowControl) } cc.cond.Broadcast() diff --git a/vendor/golang.org/x/oauth2/google/default.go b/vendor/golang.org/x/oauth2/google/default.go index 02ccd08a77..18f369851b 100644 --- a/vendor/golang.org/x/oauth2/google/default.go +++ b/vendor/golang.org/x/oauth2/google/default.go @@ -22,7 +22,7 @@ import ( const ( adcSetupURL = "https://cloud.google.com/docs/authentication/external/set-up-adc" - universeDomainDefault = "googleapis.com" + defaultUniverseDomain = "googleapis.com" ) // Credentials holds Google credentials, including "Application Default Credentials". @@ -58,7 +58,7 @@ type Credentials struct { // See also [The attached service account](https://cloud.google.com/docs/authentication/application-default-credentials#attached-sa). func (c *Credentials) UniverseDomain() string { if c.universeDomain == "" { - return universeDomainDefault + return defaultUniverseDomain } return c.universeDomain } @@ -89,7 +89,7 @@ func (c *Credentials) GetUniverseDomain() (string, error) { // computeUniverseDomain that did not set universeDomain, set the default // universe domain. if c.universeDomain == "" { - c.universeDomain = universeDomainDefault + c.universeDomain = defaultUniverseDomain } return c.universeDomain, nil } @@ -103,7 +103,7 @@ func (c *Credentials) computeUniverseDomain() error { if err != nil { if _, ok := err.(metadata.NotDefinedError); ok { // http.StatusNotFound (404) - c.universeDomain = universeDomainDefault + c.universeDomain = defaultUniverseDomain return nil } else { return err @@ -287,7 +287,7 @@ func CredentialsFromJSONWithParams(ctx context.Context, jsonData []byte, params } // Authorized user credentials are only supported in the googleapis.com universe. if f.Type == userCredentialsKey { - universeDomain = universeDomainDefault + universeDomain = defaultUniverseDomain } ts, err := f.tokenSource(ctx, params) diff --git a/vendor/golang.org/x/oauth2/google/doc.go b/vendor/golang.org/x/oauth2/google/doc.go index 03c42c6f87..830d268c1e 100644 --- a/vendor/golang.org/x/oauth2/google/doc.go +++ b/vendor/golang.org/x/oauth2/google/doc.go @@ -22,91 +22,9 @@ // the other by JWTConfigFromJSON. The returned Config can be used to obtain a TokenSource or // create an http.Client. // -// # Workload Identity Federation +// # Workload and Workforce Identity Federation // -// Using workload identity federation, your application can access Google Cloud -// resources from Amazon Web Services (AWS), Microsoft Azure or any identity -// provider that supports OpenID Connect (OIDC) or SAML 2.0. -// Traditionally, applications running outside Google Cloud have used service -// account keys to access Google Cloud resources. Using identity federation, -// you can allow your workload to impersonate a service account. -// This lets you access Google Cloud resources directly, eliminating the -// maintenance and security burden associated with service account keys. -// -// Follow the detailed instructions on how to configure Workload Identity Federation -// in various platforms: -// -// Amazon Web Services (AWS): https://cloud.google.com/iam/docs/workload-identity-federation-with-other-clouds#aws -// Microsoft Azure: https://cloud.google.com/iam/docs/workload-identity-federation-with-other-clouds#azure -// OIDC identity provider: https://cloud.google.com/iam/docs/workload-identity-federation-with-other-providers#oidc -// SAML 2.0 identity provider: https://cloud.google.com/iam/docs/workload-identity-federation-with-other-providers#saml -// -// For OIDC and SAML providers, the library can retrieve tokens in three ways: -// from a local file location (file-sourced credentials), from a server -// (URL-sourced credentials), or from a local executable (executable-sourced -// credentials). -// For file-sourced credentials, a background process needs to be continuously -// refreshing the file location with a new OIDC/SAML token prior to expiration. -// For tokens with one hour lifetimes, the token needs to be updated in the file -// every hour. The token can be stored directly as plain text or in JSON format. -// For URL-sourced credentials, a local server needs to host a GET endpoint to -// return the OIDC/SAML token. The response can be in plain text or JSON. -// Additional required request headers can also be specified. -// For executable-sourced credentials, an application needs to be available to -// output the OIDC/SAML token and other information in a JSON format. -// For more information on how these work (and how to implement -// executable-sourced credentials), please check out: -// https://cloud.google.com/iam/docs/workload-identity-federation-with-other-providers#create_a_credential_configuration -// -// Note that this library does not perform any validation on the token_url, token_info_url, -// or service_account_impersonation_url fields of the credential configuration. -// It is not recommended to use a credential configuration that you did not generate with -// the gcloud CLI unless you verify that the URL fields point to a googleapis.com domain. -// -// # Workforce Identity Federation -// -// Workforce identity federation lets you use an external identity provider (IdP) to -// authenticate and authorize a workforce—a group of users, such as employees, partners, -// and contractors—using IAM, so that the users can access Google Cloud services. -// Workforce identity federation extends Google Cloud's identity capabilities to support -// syncless, attribute-based single sign on. -// -// With workforce identity federation, your workforce can access Google Cloud resources -// using an external identity provider (IdP) that supports OpenID Connect (OIDC) or -// SAML 2.0 such as Azure Active Directory (Azure AD), Active Directory Federation -// Services (AD FS), Okta, and others. -// -// Follow the detailed instructions on how to configure Workload Identity Federation -// in various platforms: -// -// Azure AD: https://cloud.google.com/iam/docs/workforce-sign-in-azure-ad -// Okta: https://cloud.google.com/iam/docs/workforce-sign-in-okta -// OIDC identity provider: https://cloud.google.com/iam/docs/configuring-workforce-identity-federation#oidc -// SAML 2.0 identity provider: https://cloud.google.com/iam/docs/configuring-workforce-identity-federation#saml -// -// For workforce identity federation, the library can retrieve tokens in three ways: -// from a local file location (file-sourced credentials), from a server -// (URL-sourced credentials), or from a local executable (executable-sourced -// credentials). -// For file-sourced credentials, a background process needs to be continuously -// refreshing the file location with a new OIDC/SAML token prior to expiration. -// For tokens with one hour lifetimes, the token needs to be updated in the file -// every hour. The token can be stored directly as plain text or in JSON format. -// For URL-sourced credentials, a local server needs to host a GET endpoint to -// return the OIDC/SAML token. The response can be in plain text or JSON. -// Additional required request headers can also be specified. -// For executable-sourced credentials, an application needs to be available to -// output the OIDC/SAML token and other information in a JSON format. -// For more information on how these work (and how to implement -// executable-sourced credentials), please check out: -// https://cloud.google.com/iam/docs/workforce-obtaining-short-lived-credentials#generate_a_configuration_file_for_non-interactive_sign-in -// -// # Security considerations -// -// Note that this library does not perform any validation on the token_url, token_info_url, -// or service_account_impersonation_url fields of the credential configuration. -// It is not recommended to use a credential configuration that you did not generate with -// the gcloud CLI unless you verify that the URL fields point to a googleapis.com domain. +// For information on how to use Workload and Workforce Identity Federation, see [golang.org/x/oauth2/google/externalaccount]. // // # Credentials // diff --git a/vendor/golang.org/x/oauth2/google/internal/externalaccount/aws.go b/vendor/golang.org/x/oauth2/google/externalaccount/aws.go similarity index 77% rename from vendor/golang.org/x/oauth2/google/internal/externalaccount/aws.go rename to vendor/golang.org/x/oauth2/google/externalaccount/aws.go index bd4efd19ba..da61d0c0e8 100644 --- a/vendor/golang.org/x/oauth2/google/internal/externalaccount/aws.go +++ b/vendor/golang.org/x/oauth2/google/externalaccount/aws.go @@ -26,22 +26,28 @@ import ( "golang.org/x/oauth2" ) -type awsSecurityCredentials struct { - AccessKeyID string `json:"AccessKeyID"` +// AwsSecurityCredentials models AWS security credentials. +type AwsSecurityCredentials struct { + // AccessKeyId is the AWS Access Key ID - Required. + AccessKeyID string `json:"AccessKeyID"` + // SecretAccessKey is the AWS Secret Access Key - Required. SecretAccessKey string `json:"SecretAccessKey"` - SecurityToken string `json:"Token"` + // SessionToken is the AWS Session token. This should be provided for temporary AWS security credentials - Optional. + SessionToken string `json:"Token"` } // awsRequestSigner is a utility class to sign http requests using a AWS V4 signature. type awsRequestSigner struct { RegionName string - AwsSecurityCredentials awsSecurityCredentials + AwsSecurityCredentials *AwsSecurityCredentials } // getenv aliases os.Getenv for testing var getenv = os.Getenv const ( + defaultRegionalCredentialVerificationUrl = "https://sts.{region}.amazonaws.com?Action=GetCallerIdentity&Version=2011-06-15" + // AWS Signature Version 4 signing algorithm identifier. awsAlgorithm = "AWS4-HMAC-SHA256" @@ -197,8 +203,8 @@ func (rs *awsRequestSigner) SignRequest(req *http.Request) error { signedRequest.Header.Add("host", requestHost(req)) - if rs.AwsSecurityCredentials.SecurityToken != "" { - signedRequest.Header.Add(awsSecurityTokenHeader, rs.AwsSecurityCredentials.SecurityToken) + if rs.AwsSecurityCredentials.SessionToken != "" { + signedRequest.Header.Add(awsSecurityTokenHeader, rs.AwsSecurityCredentials.SessionToken) } if signedRequest.Header.Get("date") == "" { @@ -251,16 +257,18 @@ func (rs *awsRequestSigner) generateAuthentication(req *http.Request, timestamp } type awsCredentialSource struct { - EnvironmentID string - RegionURL string - RegionalCredVerificationURL string - CredVerificationURL string - IMDSv2SessionTokenURL string - TargetResource string - requestSigner *awsRequestSigner - region string - ctx context.Context - client *http.Client + environmentID string + regionURL string + regionalCredVerificationURL string + credVerificationURL string + imdsv2SessionTokenURL string + targetResource string + requestSigner *awsRequestSigner + region string + ctx context.Context + client *http.Client + awsSecurityCredentialsSupplier AwsSecurityCredentialsSupplier + supplierOptions SupplierOptions } type awsRequestHeader struct { @@ -292,18 +300,25 @@ func canRetrieveSecurityCredentialFromEnvironment() bool { return getenv(awsAccessKeyId) != "" && getenv(awsSecretAccessKey) != "" } -func shouldUseMetadataServer() bool { - return !canRetrieveRegionFromEnvironment() || !canRetrieveSecurityCredentialFromEnvironment() +func (cs awsCredentialSource) shouldUseMetadataServer() bool { + return cs.awsSecurityCredentialsSupplier == nil && (!canRetrieveRegionFromEnvironment() || !canRetrieveSecurityCredentialFromEnvironment()) } func (cs awsCredentialSource) credentialSourceType() string { + if cs.awsSecurityCredentialsSupplier != nil { + return "programmatic" + } return "aws" } func (cs awsCredentialSource) subjectToken() (string, error) { + // Set Defaults + if cs.regionalCredVerificationURL == "" { + cs.regionalCredVerificationURL = defaultRegionalCredentialVerificationUrl + } if cs.requestSigner == nil { headers := make(map[string]string) - if shouldUseMetadataServer() { + if cs.shouldUseMetadataServer() { awsSessionToken, err := cs.getAWSSessionToken() if err != nil { return "", err @@ -318,8 +333,8 @@ func (cs awsCredentialSource) subjectToken() (string, error) { if err != nil { return "", err } - - if cs.region, err = cs.getRegion(headers); err != nil { + cs.region, err = cs.getRegion(headers) + if err != nil { return "", err } @@ -331,7 +346,7 @@ func (cs awsCredentialSource) subjectToken() (string, error) { // Generate the signed request to AWS STS GetCallerIdentity API. // Use the required regional endpoint. Otherwise, the request will fail. - req, err := http.NewRequest("POST", strings.Replace(cs.RegionalCredVerificationURL, "{region}", cs.region, 1), nil) + req, err := http.NewRequest("POST", strings.Replace(cs.regionalCredVerificationURL, "{region}", cs.region, 1), nil) if err != nil { return "", err } @@ -339,8 +354,8 @@ func (cs awsCredentialSource) subjectToken() (string, error) { // provider, with or without the HTTPS prefix. // Including this header as part of the signature is recommended to // ensure data integrity. - if cs.TargetResource != "" { - req.Header.Add("x-goog-cloud-target-resource", cs.TargetResource) + if cs.targetResource != "" { + req.Header.Add("x-goog-cloud-target-resource", cs.targetResource) } cs.requestSigner.SignRequest(req) @@ -387,11 +402,11 @@ func (cs awsCredentialSource) subjectToken() (string, error) { } func (cs *awsCredentialSource) getAWSSessionToken() (string, error) { - if cs.IMDSv2SessionTokenURL == "" { + if cs.imdsv2SessionTokenURL == "" { return "", nil } - req, err := http.NewRequest("PUT", cs.IMDSv2SessionTokenURL, nil) + req, err := http.NewRequest("PUT", cs.imdsv2SessionTokenURL, nil) if err != nil { return "", err } @@ -410,25 +425,29 @@ func (cs *awsCredentialSource) getAWSSessionToken() (string, error) { } if resp.StatusCode != 200 { - return "", fmt.Errorf("oauth2/google: unable to retrieve AWS session token - %s", string(respBody)) + return "", fmt.Errorf("oauth2/google/externalaccount: unable to retrieve AWS session token - %s", string(respBody)) } return string(respBody), nil } func (cs *awsCredentialSource) getRegion(headers map[string]string) (string, error) { + if cs.awsSecurityCredentialsSupplier != nil { + return cs.awsSecurityCredentialsSupplier.AwsRegion(cs.ctx, cs.supplierOptions) + } if canRetrieveRegionFromEnvironment() { if envAwsRegion := getenv(awsRegion); envAwsRegion != "" { + cs.region = envAwsRegion return envAwsRegion, nil } return getenv("AWS_DEFAULT_REGION"), nil } - if cs.RegionURL == "" { - return "", errors.New("oauth2/google: unable to determine AWS region") + if cs.regionURL == "" { + return "", errors.New("oauth2/google/externalaccount: unable to determine AWS region") } - req, err := http.NewRequest("GET", cs.RegionURL, nil) + req, err := http.NewRequest("GET", cs.regionURL, nil) if err != nil { return "", err } @@ -449,7 +468,7 @@ func (cs *awsCredentialSource) getRegion(headers map[string]string) (string, err } if resp.StatusCode != 200 { - return "", fmt.Errorf("oauth2/google: unable to retrieve AWS region - %s", string(respBody)) + return "", fmt.Errorf("oauth2/google/externalaccount: unable to retrieve AWS region - %s", string(respBody)) } // This endpoint will return the region in format: us-east-2b. @@ -461,12 +480,15 @@ func (cs *awsCredentialSource) getRegion(headers map[string]string) (string, err return string(respBody[:respBodyEnd]), nil } -func (cs *awsCredentialSource) getSecurityCredentials(headers map[string]string) (result awsSecurityCredentials, err error) { +func (cs *awsCredentialSource) getSecurityCredentials(headers map[string]string) (result *AwsSecurityCredentials, err error) { + if cs.awsSecurityCredentialsSupplier != nil { + return cs.awsSecurityCredentialsSupplier.AwsSecurityCredentials(cs.ctx, cs.supplierOptions) + } if canRetrieveSecurityCredentialFromEnvironment() { - return awsSecurityCredentials{ + return &AwsSecurityCredentials{ AccessKeyID: getenv(awsAccessKeyId), SecretAccessKey: getenv(awsSecretAccessKey), - SecurityToken: getenv(awsSessionToken), + SessionToken: getenv(awsSessionToken), }, nil } @@ -481,20 +503,20 @@ func (cs *awsCredentialSource) getSecurityCredentials(headers map[string]string) } if credentials.AccessKeyID == "" { - return result, errors.New("oauth2/google: missing AccessKeyId credential") + return result, errors.New("oauth2/google/externalaccount: missing AccessKeyId credential") } if credentials.SecretAccessKey == "" { - return result, errors.New("oauth2/google: missing SecretAccessKey credential") + return result, errors.New("oauth2/google/externalaccount: missing SecretAccessKey credential") } - return credentials, nil + return &credentials, nil } -func (cs *awsCredentialSource) getMetadataSecurityCredentials(roleName string, headers map[string]string) (awsSecurityCredentials, error) { - var result awsSecurityCredentials +func (cs *awsCredentialSource) getMetadataSecurityCredentials(roleName string, headers map[string]string) (AwsSecurityCredentials, error) { + var result AwsSecurityCredentials - req, err := http.NewRequest("GET", fmt.Sprintf("%s/%s", cs.CredVerificationURL, roleName), nil) + req, err := http.NewRequest("GET", fmt.Sprintf("%s/%s", cs.credVerificationURL, roleName), nil) if err != nil { return result, err } @@ -516,7 +538,7 @@ func (cs *awsCredentialSource) getMetadataSecurityCredentials(roleName string, h } if resp.StatusCode != 200 { - return result, fmt.Errorf("oauth2/google: unable to retrieve AWS security credentials - %s", string(respBody)) + return result, fmt.Errorf("oauth2/google/externalaccount: unable to retrieve AWS security credentials - %s", string(respBody)) } err = json.Unmarshal(respBody, &result) @@ -524,11 +546,11 @@ func (cs *awsCredentialSource) getMetadataSecurityCredentials(roleName string, h } func (cs *awsCredentialSource) getMetadataRoleName(headers map[string]string) (string, error) { - if cs.CredVerificationURL == "" { - return "", errors.New("oauth2/google: unable to determine the AWS metadata server security credentials endpoint") + if cs.credVerificationURL == "" { + return "", errors.New("oauth2/google/externalaccount: unable to determine the AWS metadata server security credentials endpoint") } - req, err := http.NewRequest("GET", cs.CredVerificationURL, nil) + req, err := http.NewRequest("GET", cs.credVerificationURL, nil) if err != nil { return "", err } @@ -549,7 +571,7 @@ func (cs *awsCredentialSource) getMetadataRoleName(headers map[string]string) (s } if resp.StatusCode != 200 { - return "", fmt.Errorf("oauth2/google: unable to retrieve AWS role name - %s", string(respBody)) + return "", fmt.Errorf("oauth2/google/externalaccount: unable to retrieve AWS role name - %s", string(respBody)) } return string(respBody), nil diff --git a/vendor/golang.org/x/oauth2/google/externalaccount/basecredentials.go b/vendor/golang.org/x/oauth2/google/externalaccount/basecredentials.go new file mode 100644 index 0000000000..400aa0a072 --- /dev/null +++ b/vendor/golang.org/x/oauth2/google/externalaccount/basecredentials.go @@ -0,0 +1,484 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package externalaccount provides support for creating workload identity +federation and workforce identity federation token sources that can be +used to access Google Cloud resources from external identity providers. + +# Workload Identity Federation + +Using workload identity federation, your application can access Google Cloud +resources from Amazon Web Services (AWS), Microsoft Azure or any identity +provider that supports OpenID Connect (OIDC) or SAML 2.0. +Traditionally, applications running outside Google Cloud have used service +account keys to access Google Cloud resources. Using identity federation, +you can allow your workload to impersonate a service account. +This lets you access Google Cloud resources directly, eliminating the +maintenance and security burden associated with service account keys. + +Follow the detailed instructions on how to configure Workload Identity Federation +in various platforms: + +Amazon Web Services (AWS): https://cloud.google.com/iam/docs/workload-identity-federation-with-other-clouds#aws +Microsoft Azure: https://cloud.google.com/iam/docs/workload-identity-federation-with-other-clouds#azure +OIDC identity provider: https://cloud.google.com/iam/docs/workload-identity-federation-with-other-providers#oidc +SAML 2.0 identity provider: https://cloud.google.com/iam/docs/workload-identity-federation-with-other-providers#saml + +For OIDC and SAML providers, the library can retrieve tokens in fours ways: +from a local file location (file-sourced credentials), from a server +(URL-sourced credentials), from a local executable (executable-sourced +credentials), or from a user defined function that returns an OIDC or SAML token. +For file-sourced credentials, a background process needs to be continuously +refreshing the file location with a new OIDC/SAML token prior to expiration. +For tokens with one hour lifetimes, the token needs to be updated in the file +every hour. The token can be stored directly as plain text or in JSON format. +For URL-sourced credentials, a local server needs to host a GET endpoint to +return the OIDC/SAML token. The response can be in plain text or JSON. +Additional required request headers can also be specified. +For executable-sourced credentials, an application needs to be available to +output the OIDC/SAML token and other information in a JSON format. +For more information on how these work (and how to implement +executable-sourced credentials), please check out: +https://cloud.google.com/iam/docs/workload-identity-federation-with-other-providers#create_a_credential_configuration + +To use a custom function to supply the token, define a struct that implements the [SubjectTokenSupplier] interface for OIDC/SAML providers, +or one that implements [AwsSecurityCredentialsSupplier] for AWS providers. This can then be used when building a [Config]. +The [golang.org/x/oauth2.TokenSource] created from the config using [NewTokenSource] can then be used to access Google +Cloud resources. For instance, you can create a new client from the +[cloud.google.com/go/storage] package and pass in option.WithTokenSource(yourTokenSource)) + +Note that this library does not perform any validation on the token_url, token_info_url, +or service_account_impersonation_url fields of the credential configuration. +It is not recommended to use a credential configuration that you did not generate with +the gcloud CLI unless you verify that the URL fields point to a googleapis.com domain. + +# Workforce Identity Federation + +Workforce identity federation lets you use an external identity provider (IdP) to +authenticate and authorize a workforce—a group of users, such as employees, partners, +and contractors—using IAM, so that the users can access Google Cloud services. +Workforce identity federation extends Google Cloud's identity capabilities to support +syncless, attribute-based single sign on. + +With workforce identity federation, your workforce can access Google Cloud resources +using an external identity provider (IdP) that supports OpenID Connect (OIDC) or +SAML 2.0 such as Azure Active Directory (Azure AD), Active Directory Federation +Services (AD FS), Okta, and others. + +Follow the detailed instructions on how to configure Workload Identity Federation +in various platforms: + +Azure AD: https://cloud.google.com/iam/docs/workforce-sign-in-azure-ad +Okta: https://cloud.google.com/iam/docs/workforce-sign-in-okta +OIDC identity provider: https://cloud.google.com/iam/docs/configuring-workforce-identity-federation#oidc +SAML 2.0 identity provider: https://cloud.google.com/iam/docs/configuring-workforce-identity-federation#saml + +For workforce identity federation, the library can retrieve tokens in four ways: +from a local file location (file-sourced credentials), from a server +(URL-sourced credentials), from a local executable (executable-sourced +credentials), or from a user supplied function that returns an OIDC or SAML token. +For file-sourced credentials, a background process needs to be continuously +refreshing the file location with a new OIDC/SAML token prior to expiration. +For tokens with one hour lifetimes, the token needs to be updated in the file +every hour. The token can be stored directly as plain text or in JSON format. +For URL-sourced credentials, a local server needs to host a GET endpoint to +return the OIDC/SAML token. The response can be in plain text or JSON. +Additional required request headers can also be specified. +For executable-sourced credentials, an application needs to be available to +output the OIDC/SAML token and other information in a JSON format. +For more information on how these work (and how to implement +executable-sourced credentials), please check out: +https://cloud.google.com/iam/docs/workforce-obtaining-short-lived-credentials#generate_a_configuration_file_for_non-interactive_sign-in + +To use a custom function to supply the token, define a struct that implements the [SubjectTokenSupplier] interface for OIDC/SAML providers. +This can then be used when building a [Config]. +The [golang.org/x/oauth2.TokenSource] created from the config using [NewTokenSource] can then be used access Google +Cloud resources. For instance, you can create a new client from the +[cloud.google.com/go/storage] package and pass in option.WithTokenSource(yourTokenSource)) + +# Security considerations + +Note that this library does not perform any validation on the token_url, token_info_url, +or service_account_impersonation_url fields of the credential configuration. +It is not recommended to use a credential configuration that you did not generate with +the gcloud CLI unless you verify that the URL fields point to a googleapis.com domain. +*/ +package externalaccount + +import ( + "context" + "fmt" + "net/http" + "regexp" + "strconv" + "strings" + "time" + + "golang.org/x/oauth2" + "golang.org/x/oauth2/google/internal/impersonate" + "golang.org/x/oauth2/google/internal/stsexchange" +) + +const ( + universeDomainPlaceholder = "UNIVERSE_DOMAIN" + defaultTokenURL = "https://sts.UNIVERSE_DOMAIN/v1/token" + defaultUniverseDomain = "googleapis.com" +) + +// now aliases time.Now for testing +var now = func() time.Time { + return time.Now().UTC() +} + +// Config stores the configuration for fetching tokens with external credentials. +type Config struct { + // Audience is the Secure Token Service (STS) audience which contains the resource name for the workload + // identity pool or the workforce pool and the provider identifier in that pool. Required. + Audience string + // SubjectTokenType is the STS token type based on the Oauth2.0 token exchange spec. + // Expected values include: + // “urn:ietf:params:oauth:token-type:jwt” + // “urn:ietf:params:oauth:token-type:id-token” + // “urn:ietf:params:oauth:token-type:saml2” + // “urn:ietf:params:aws:token-type:aws4_request” + // Required. + SubjectTokenType string + // TokenURL is the STS token exchange endpoint. If not provided, will default to + // https://sts.UNIVERSE_DOMAIN/v1/token, with UNIVERSE_DOMAIN set to the + // default service domain googleapis.com unless UniverseDomain is set. + // Optional. + TokenURL string + // TokenInfoURL is the token_info endpoint used to retrieve the account related information ( + // user attributes like account identifier, eg. email, username, uid, etc). This is + // needed for gCloud session account identification. Optional. + TokenInfoURL string + // ServiceAccountImpersonationURL is the URL for the service account impersonation request. This is only + // required for workload identity pools when APIs to be accessed have not integrated with UberMint. Optional. + ServiceAccountImpersonationURL string + // ServiceAccountImpersonationLifetimeSeconds is the number of seconds the service account impersonation + // token will be valid for. If not provided, it will default to 3600. Optional. + ServiceAccountImpersonationLifetimeSeconds int + // ClientSecret is currently only required if token_info endpoint also + // needs to be called with the generated GCP access token. When provided, STS will be + // called with additional basic authentication using ClientId as username and ClientSecret as password. Optional. + ClientSecret string + // ClientID is only required in conjunction with ClientSecret, as described above. Optional. + ClientID string + // CredentialSource contains the necessary information to retrieve the token itself, as well + // as some environmental information. One of SubjectTokenSupplier, AWSSecurityCredentialSupplier or + // CredentialSource must be provided. Optional. + CredentialSource *CredentialSource + // QuotaProjectID is injected by gCloud. If the value is non-empty, the Auth libraries + // will set the x-goog-user-project header which overrides the project associated with the credentials. Optional. + QuotaProjectID string + // Scopes contains the desired scopes for the returned access token. Optional. + Scopes []string + // WorkforcePoolUserProject is the workforce pool user project number when the credential + // corresponds to a workforce pool and not a workload identity pool. + // The underlying principal must still have serviceusage.services.use IAM + // permission to use the project for billing/quota. Optional. + WorkforcePoolUserProject string + // SubjectTokenSupplier is an optional token supplier for OIDC/SAML credentials. + // One of SubjectTokenSupplier, AWSSecurityCredentialSupplier or CredentialSource must be provided. Optional. + SubjectTokenSupplier SubjectTokenSupplier + // AwsSecurityCredentialsSupplier is an AWS Security Credential supplier for AWS credentials. + // One of SubjectTokenSupplier, AWSSecurityCredentialSupplier or CredentialSource must be provided. Optional. + AwsSecurityCredentialsSupplier AwsSecurityCredentialsSupplier + // UniverseDomain is the default service domain for a given Cloud universe. + // This value will be used in the default STS token URL. The default value + // is "googleapis.com". It will not be used if TokenURL is set. Optional. + UniverseDomain string +} + +var ( + validWorkforceAudiencePattern *regexp.Regexp = regexp.MustCompile(`//iam\.googleapis\.com/locations/[^/]+/workforcePools/`) +) + +func validateWorkforceAudience(input string) bool { + return validWorkforceAudiencePattern.MatchString(input) +} + +// NewTokenSource Returns an external account TokenSource using the provided external account config. +func NewTokenSource(ctx context.Context, conf Config) (oauth2.TokenSource, error) { + if conf.Audience == "" { + return nil, fmt.Errorf("oauth2/google/externalaccount: Audience must be set") + } + if conf.SubjectTokenType == "" { + return nil, fmt.Errorf("oauth2/google/externalaccount: Subject token type must be set") + } + if conf.WorkforcePoolUserProject != "" { + valid := validateWorkforceAudience(conf.Audience) + if !valid { + return nil, fmt.Errorf("oauth2/google/externalaccount: Workforce pool user project should not be set for non-workforce pool credentials") + } + } + count := 0 + if conf.CredentialSource != nil { + count++ + } + if conf.SubjectTokenSupplier != nil { + count++ + } + if conf.AwsSecurityCredentialsSupplier != nil { + count++ + } + if count == 0 { + return nil, fmt.Errorf("oauth2/google/externalaccount: One of CredentialSource, SubjectTokenSupplier, or AwsSecurityCredentialsSupplier must be set") + } + if count > 1 { + return nil, fmt.Errorf("oauth2/google/externalaccount: Only one of CredentialSource, SubjectTokenSupplier, or AwsSecurityCredentialsSupplier must be set") + } + return conf.tokenSource(ctx, "https") +} + +// tokenSource is a private function that's directly called by some of the tests, +// because the unit test URLs are mocked, and would otherwise fail the +// validity check. +func (c *Config) tokenSource(ctx context.Context, scheme string) (oauth2.TokenSource, error) { + + ts := tokenSource{ + ctx: ctx, + conf: c, + } + if c.ServiceAccountImpersonationURL == "" { + return oauth2.ReuseTokenSource(nil, ts), nil + } + scopes := c.Scopes + ts.conf.Scopes = []string{"https://www.googleapis.com/auth/cloud-platform"} + imp := impersonate.ImpersonateTokenSource{ + Ctx: ctx, + URL: c.ServiceAccountImpersonationURL, + Scopes: scopes, + Ts: oauth2.ReuseTokenSource(nil, ts), + TokenLifetimeSeconds: c.ServiceAccountImpersonationLifetimeSeconds, + } + return oauth2.ReuseTokenSource(nil, imp), nil +} + +// Subject token file types. +const ( + fileTypeText = "text" + fileTypeJSON = "json" +) + +// Format contains information needed to retireve a subject token for URL or File sourced credentials. +type Format struct { + // Type should be either "text" or "json". This determines whether the file or URL sourced credentials + // expect a simple text subject token or if the subject token will be contained in a JSON object. + // When not provided "text" type is assumed. + Type string `json:"type"` + // SubjectTokenFieldName is only required for JSON format. This is the field name that the credentials will check + // for the subject token in the file or URL response. This would be "access_token" for azure. + SubjectTokenFieldName string `json:"subject_token_field_name"` +} + +// CredentialSource stores the information necessary to retrieve the credentials for the STS exchange. +type CredentialSource struct { + // File is the location for file sourced credentials. + // One field amongst File, URL, Executable, or EnvironmentID should be provided, depending on the kind of credential in question. + File string `json:"file"` + + // Url is the URL to call for URL sourced credentials. + // One field amongst File, URL, Executable, or EnvironmentID should be provided, depending on the kind of credential in question. + URL string `json:"url"` + // Headers are the headers to attach to the request for URL sourced credentials. + Headers map[string]string `json:"headers"` + + // Executable is the configuration object for executable sourced credentials. + // One field amongst File, URL, Executable, or EnvironmentID should be provided, depending on the kind of credential in question. + Executable *ExecutableConfig `json:"executable"` + + // EnvironmentID is the EnvironmentID used for AWS sourced credentials. This should start with "AWS". + // One field amongst File, URL, Executable, or EnvironmentID should be provided, depending on the kind of credential in question. + EnvironmentID string `json:"environment_id"` + // RegionURL is the metadata URL to retrieve the region from for EC2 AWS credentials. + RegionURL string `json:"region_url"` + // RegionalCredVerificationURL is the AWS regional credential verification URL, will default to + // "https://sts.{region}.amazonaws.com?Action=GetCallerIdentity&Version=2011-06-15" if not provided." + RegionalCredVerificationURL string `json:"regional_cred_verification_url"` + // IMDSv2SessionTokenURL is the URL to retrieve the session token when using IMDSv2 in AWS. + IMDSv2SessionTokenURL string `json:"imdsv2_session_token_url"` + // Format is the format type for the subject token. Used for File and URL sourced credentials. Expected values are "text" or "json". + Format Format `json:"format"` +} + +// ExecutableConfig contains information needed for executable sourced credentials. +type ExecutableConfig struct { + // Command is the the full command to run to retrieve the subject token. + // This can include arguments. Must be an absolute path for the program. Required. + Command string `json:"command"` + // TimeoutMillis is the timeout duration, in milliseconds. Defaults to 30000 milliseconds when not provided. Optional. + TimeoutMillis *int `json:"timeout_millis"` + // OutputFile is the absolute path to the output file where the executable will cache the response. + // If specified the auth libraries will first check this location before running the executable. Optional. + OutputFile string `json:"output_file"` +} + +// SubjectTokenSupplier can be used to supply a subject token to exchange for a GCP access token. +type SubjectTokenSupplier interface { + // SubjectToken should return a valid subject token or an error. + // The external account token source does not cache the returned subject token, so caching + // logic should be implemented in the supplier to prevent multiple requests for the same subject token. + SubjectToken(ctx context.Context, options SupplierOptions) (string, error) +} + +// AWSSecurityCredentialsSupplier can be used to supply AwsSecurityCredentials and an AWS Region to +// exchange for a GCP access token. +type AwsSecurityCredentialsSupplier interface { + // AwsRegion should return the AWS region or an error. + AwsRegion(ctx context.Context, options SupplierOptions) (string, error) + // GetAwsSecurityCredentials should return a valid set of AwsSecurityCredentials or an error. + // The external account token source does not cache the returned security credentials, so caching + // logic should be implemented in the supplier to prevent multiple requests for the same security credentials. + AwsSecurityCredentials(ctx context.Context, options SupplierOptions) (*AwsSecurityCredentials, error) +} + +// SupplierOptions contains information about the requested subject token or AWS security credentials from the +// Google external account credential. +type SupplierOptions struct { + // Audience is the requested audience for the external account credential. + Audience string + // Subject token type is the requested subject token type for the external account credential. Expected values include: + // “urn:ietf:params:oauth:token-type:jwt” + // “urn:ietf:params:oauth:token-type:id-token” + // “urn:ietf:params:oauth:token-type:saml2” + // “urn:ietf:params:aws:token-type:aws4_request” + SubjectTokenType string +} + +// tokenURL returns the default STS token endpoint with the configured universe +// domain. +func (c *Config) tokenURL() string { + if c.UniverseDomain == "" { + return strings.Replace(defaultTokenURL, universeDomainPlaceholder, defaultUniverseDomain, 1) + } + return strings.Replace(defaultTokenURL, universeDomainPlaceholder, c.UniverseDomain, 1) +} + +// parse determines the type of CredentialSource needed. +func (c *Config) parse(ctx context.Context) (baseCredentialSource, error) { + //set Defaults + if c.TokenURL == "" { + c.TokenURL = c.tokenURL() + } + supplierOptions := SupplierOptions{Audience: c.Audience, SubjectTokenType: c.SubjectTokenType} + + if c.AwsSecurityCredentialsSupplier != nil { + awsCredSource := awsCredentialSource{ + awsSecurityCredentialsSupplier: c.AwsSecurityCredentialsSupplier, + targetResource: c.Audience, + supplierOptions: supplierOptions, + ctx: ctx, + } + return awsCredSource, nil + } else if c.SubjectTokenSupplier != nil { + return programmaticRefreshCredentialSource{subjectTokenSupplier: c.SubjectTokenSupplier, supplierOptions: supplierOptions, ctx: ctx}, nil + } else if len(c.CredentialSource.EnvironmentID) > 3 && c.CredentialSource.EnvironmentID[:3] == "aws" { + if awsVersion, err := strconv.Atoi(c.CredentialSource.EnvironmentID[3:]); err == nil { + if awsVersion != 1 { + return nil, fmt.Errorf("oauth2/google/externalaccount: aws version '%d' is not supported in the current build", awsVersion) + } + + awsCredSource := awsCredentialSource{ + environmentID: c.CredentialSource.EnvironmentID, + regionURL: c.CredentialSource.RegionURL, + regionalCredVerificationURL: c.CredentialSource.RegionalCredVerificationURL, + credVerificationURL: c.CredentialSource.URL, + targetResource: c.Audience, + ctx: ctx, + } + if c.CredentialSource.IMDSv2SessionTokenURL != "" { + awsCredSource.imdsv2SessionTokenURL = c.CredentialSource.IMDSv2SessionTokenURL + } + + return awsCredSource, nil + } + } else if c.CredentialSource.File != "" { + return fileCredentialSource{File: c.CredentialSource.File, Format: c.CredentialSource.Format}, nil + } else if c.CredentialSource.URL != "" { + return urlCredentialSource{URL: c.CredentialSource.URL, Headers: c.CredentialSource.Headers, Format: c.CredentialSource.Format, ctx: ctx}, nil + } else if c.CredentialSource.Executable != nil { + return createExecutableCredential(ctx, c.CredentialSource.Executable, c) + } + return nil, fmt.Errorf("oauth2/google/externalaccount: unable to parse credential source") +} + +type baseCredentialSource interface { + credentialSourceType() string + subjectToken() (string, error) +} + +// tokenSource is the source that handles external credentials. It is used to retrieve Tokens. +type tokenSource struct { + ctx context.Context + conf *Config +} + +func getMetricsHeaderValue(conf *Config, credSource baseCredentialSource) string { + return fmt.Sprintf("gl-go/%s auth/%s google-byoid-sdk source/%s sa-impersonation/%t config-lifetime/%t", + goVersion(), + "unknown", + credSource.credentialSourceType(), + conf.ServiceAccountImpersonationURL != "", + conf.ServiceAccountImpersonationLifetimeSeconds != 0) +} + +// Token allows tokenSource to conform to the oauth2.TokenSource interface. +func (ts tokenSource) Token() (*oauth2.Token, error) { + conf := ts.conf + + credSource, err := conf.parse(ts.ctx) + if err != nil { + return nil, err + } + subjectToken, err := credSource.subjectToken() + + if err != nil { + return nil, err + } + stsRequest := stsexchange.TokenExchangeRequest{ + GrantType: "urn:ietf:params:oauth:grant-type:token-exchange", + Audience: conf.Audience, + Scope: conf.Scopes, + RequestedTokenType: "urn:ietf:params:oauth:token-type:access_token", + SubjectToken: subjectToken, + SubjectTokenType: conf.SubjectTokenType, + } + header := make(http.Header) + header.Add("Content-Type", "application/x-www-form-urlencoded") + header.Add("x-goog-api-client", getMetricsHeaderValue(conf, credSource)) + clientAuth := stsexchange.ClientAuthentication{ + AuthStyle: oauth2.AuthStyleInHeader, + ClientID: conf.ClientID, + ClientSecret: conf.ClientSecret, + } + var options map[string]interface{} + // Do not pass workforce_pool_user_project when client authentication is used. + // The client ID is sufficient for determining the user project. + if conf.WorkforcePoolUserProject != "" && conf.ClientID == "" { + options = map[string]interface{}{ + "userProject": conf.WorkforcePoolUserProject, + } + } + stsResp, err := stsexchange.ExchangeToken(ts.ctx, conf.TokenURL, &stsRequest, clientAuth, header, options) + if err != nil { + return nil, err + } + + accessToken := &oauth2.Token{ + AccessToken: stsResp.AccessToken, + TokenType: stsResp.TokenType, + } + if stsResp.ExpiresIn < 0 { + return nil, fmt.Errorf("oauth2/google/externalaccount: got invalid expiry from security token service") + } else if stsResp.ExpiresIn >= 0 { + accessToken.Expiry = now().Add(time.Duration(stsResp.ExpiresIn) * time.Second) + } + + if stsResp.RefreshToken != "" { + accessToken.RefreshToken = stsResp.RefreshToken + } + return accessToken, nil +} diff --git a/vendor/golang.org/x/oauth2/google/internal/externalaccount/executablecredsource.go b/vendor/golang.org/x/oauth2/google/externalaccount/executablecredsource.go similarity index 84% rename from vendor/golang.org/x/oauth2/google/internal/externalaccount/executablecredsource.go rename to vendor/golang.org/x/oauth2/google/externalaccount/executablecredsource.go index 6497dc022e..dca5681a46 100644 --- a/vendor/golang.org/x/oauth2/google/internal/externalaccount/executablecredsource.go +++ b/vendor/golang.org/x/oauth2/google/externalaccount/executablecredsource.go @@ -19,7 +19,7 @@ import ( "time" ) -var serviceAccountImpersonationRE = regexp.MustCompile("https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/(.*@.*):generateAccessToken") +var serviceAccountImpersonationRE = regexp.MustCompile("https://iamcredentials\\..+/v1/projects/-/serviceAccounts/(.*@.*):generateAccessToken") const ( executableSupportedMaxVersion = 1 @@ -39,51 +39,51 @@ func (nce nonCacheableError) Error() string { } func missingFieldError(source, field string) error { - return fmt.Errorf("oauth2/google: %v missing `%q` field", source, field) + return fmt.Errorf("oauth2/google/externalaccount: %v missing `%q` field", source, field) } func jsonParsingError(source, data string) error { - return fmt.Errorf("oauth2/google: unable to parse %v\nResponse: %v", source, data) + return fmt.Errorf("oauth2/google/externalaccount: unable to parse %v\nResponse: %v", source, data) } func malformedFailureError() error { - return nonCacheableError{"oauth2/google: response must include `error` and `message` fields when unsuccessful"} + return nonCacheableError{"oauth2/google/externalaccount: response must include `error` and `message` fields when unsuccessful"} } func userDefinedError(code, message string) error { - return nonCacheableError{fmt.Sprintf("oauth2/google: response contains unsuccessful response: (%v) %v", code, message)} + return nonCacheableError{fmt.Sprintf("oauth2/google/externalaccount: response contains unsuccessful response: (%v) %v", code, message)} } func unsupportedVersionError(source string, version int) error { - return fmt.Errorf("oauth2/google: %v contains unsupported version: %v", source, version) + return fmt.Errorf("oauth2/google/externalaccount: %v contains unsupported version: %v", source, version) } func tokenExpiredError() error { - return nonCacheableError{"oauth2/google: the token returned by the executable is expired"} + return nonCacheableError{"oauth2/google/externalaccount: the token returned by the executable is expired"} } func tokenTypeError(source string) error { - return fmt.Errorf("oauth2/google: %v contains unsupported token type", source) + return fmt.Errorf("oauth2/google/externalaccount: %v contains unsupported token type", source) } func exitCodeError(exitCode int) error { - return fmt.Errorf("oauth2/google: executable command failed with exit code %v", exitCode) + return fmt.Errorf("oauth2/google/externalaccount: executable command failed with exit code %v", exitCode) } func executableError(err error) error { - return fmt.Errorf("oauth2/google: executable command failed: %v", err) + return fmt.Errorf("oauth2/google/externalaccount: executable command failed: %v", err) } func executablesDisallowedError() error { - return errors.New("oauth2/google: executables need to be explicitly allowed (set GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES to '1') to run") + return errors.New("oauth2/google/externalaccount: executables need to be explicitly allowed (set GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES to '1') to run") } func timeoutRangeError() error { - return errors.New("oauth2/google: invalid `timeout_millis` field — executable timeout must be between 5 and 120 seconds") + return errors.New("oauth2/google/externalaccount: invalid `timeout_millis` field — executable timeout must be between 5 and 120 seconds") } func commandMissingError() error { - return errors.New("oauth2/google: missing `command` field — executable command must be provided") + return errors.New("oauth2/google/externalaccount: missing `command` field — executable command must be provided") } type environment interface { @@ -146,7 +146,7 @@ type executableCredentialSource struct { // CreateExecutableCredential creates an executableCredentialSource given an ExecutableConfig. // It also performs defaulting and type conversions. -func CreateExecutableCredential(ctx context.Context, ec *ExecutableConfig, config *Config) (executableCredentialSource, error) { +func createExecutableCredential(ctx context.Context, ec *ExecutableConfig, config *Config) (executableCredentialSource, error) { if ec.Command == "" { return executableCredentialSource{}, commandMissingError() } diff --git a/vendor/golang.org/x/oauth2/google/internal/externalaccount/filecredsource.go b/vendor/golang.org/x/oauth2/google/externalaccount/filecredsource.go similarity index 62% rename from vendor/golang.org/x/oauth2/google/internal/externalaccount/filecredsource.go rename to vendor/golang.org/x/oauth2/google/externalaccount/filecredsource.go index f35f73c5cb..33766b9722 100644 --- a/vendor/golang.org/x/oauth2/google/internal/externalaccount/filecredsource.go +++ b/vendor/golang.org/x/oauth2/google/externalaccount/filecredsource.go @@ -16,7 +16,7 @@ import ( type fileCredentialSource struct { File string - Format format + Format Format } func (cs fileCredentialSource) credentialSourceType() string { @@ -26,12 +26,12 @@ func (cs fileCredentialSource) credentialSourceType() string { func (cs fileCredentialSource) subjectToken() (string, error) { tokenFile, err := os.Open(cs.File) if err != nil { - return "", fmt.Errorf("oauth2/google: failed to open credential file %q", cs.File) + return "", fmt.Errorf("oauth2/google/externalaccount: failed to open credential file %q", cs.File) } defer tokenFile.Close() tokenBytes, err := ioutil.ReadAll(io.LimitReader(tokenFile, 1<<20)) if err != nil { - return "", fmt.Errorf("oauth2/google: failed to read credential file: %v", err) + return "", fmt.Errorf("oauth2/google/externalaccount: failed to read credential file: %v", err) } tokenBytes = bytes.TrimSpace(tokenBytes) switch cs.Format.Type { @@ -39,15 +39,15 @@ func (cs fileCredentialSource) subjectToken() (string, error) { jsonData := make(map[string]interface{}) err = json.Unmarshal(tokenBytes, &jsonData) if err != nil { - return "", fmt.Errorf("oauth2/google: failed to unmarshal subject token file: %v", err) + return "", fmt.Errorf("oauth2/google/externalaccount: failed to unmarshal subject token file: %v", err) } val, ok := jsonData[cs.Format.SubjectTokenFieldName] if !ok { - return "", errors.New("oauth2/google: provided subject_token_field_name not found in credentials") + return "", errors.New("oauth2/google/externalaccount: provided subject_token_field_name not found in credentials") } token, ok := val.(string) if !ok { - return "", errors.New("oauth2/google: improperly formatted subject token") + return "", errors.New("oauth2/google/externalaccount: improperly formatted subject token") } return token, nil case "text": @@ -55,7 +55,7 @@ func (cs fileCredentialSource) subjectToken() (string, error) { case "": return string(tokenBytes), nil default: - return "", errors.New("oauth2/google: invalid credential_source file format type") + return "", errors.New("oauth2/google/externalaccount: invalid credential_source file format type") } } diff --git a/vendor/golang.org/x/oauth2/google/internal/externalaccount/header.go b/vendor/golang.org/x/oauth2/google/externalaccount/header.go similarity index 100% rename from vendor/golang.org/x/oauth2/google/internal/externalaccount/header.go rename to vendor/golang.org/x/oauth2/google/externalaccount/header.go diff --git a/vendor/golang.org/x/oauth2/google/externalaccount/programmaticrefreshcredsource.go b/vendor/golang.org/x/oauth2/google/externalaccount/programmaticrefreshcredsource.go new file mode 100644 index 0000000000..6c1abdf2da --- /dev/null +++ b/vendor/golang.org/x/oauth2/google/externalaccount/programmaticrefreshcredsource.go @@ -0,0 +1,21 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package externalaccount + +import "context" + +type programmaticRefreshCredentialSource struct { + supplierOptions SupplierOptions + subjectTokenSupplier SubjectTokenSupplier + ctx context.Context +} + +func (cs programmaticRefreshCredentialSource) credentialSourceType() string { + return "programmatic" +} + +func (cs programmaticRefreshCredentialSource) subjectToken() (string, error) { + return cs.subjectTokenSupplier.SubjectToken(cs.ctx, cs.supplierOptions) +} diff --git a/vendor/golang.org/x/oauth2/google/internal/externalaccount/urlcredsource.go b/vendor/golang.org/x/oauth2/google/externalaccount/urlcredsource.go similarity index 61% rename from vendor/golang.org/x/oauth2/google/internal/externalaccount/urlcredsource.go rename to vendor/golang.org/x/oauth2/google/externalaccount/urlcredsource.go index 606bb4e800..71a7184e01 100644 --- a/vendor/golang.org/x/oauth2/google/internal/externalaccount/urlcredsource.go +++ b/vendor/golang.org/x/oauth2/google/externalaccount/urlcredsource.go @@ -19,7 +19,7 @@ import ( type urlCredentialSource struct { URL string Headers map[string]string - Format format + Format Format ctx context.Context } @@ -31,7 +31,7 @@ func (cs urlCredentialSource) subjectToken() (string, error) { client := oauth2.NewClient(cs.ctx, nil) req, err := http.NewRequest("GET", cs.URL, nil) if err != nil { - return "", fmt.Errorf("oauth2/google: HTTP request for URL-sourced credential failed: %v", err) + return "", fmt.Errorf("oauth2/google/externalaccount: HTTP request for URL-sourced credential failed: %v", err) } req = req.WithContext(cs.ctx) @@ -40,16 +40,16 @@ func (cs urlCredentialSource) subjectToken() (string, error) { } resp, err := client.Do(req) if err != nil { - return "", fmt.Errorf("oauth2/google: invalid response when retrieving subject token: %v", err) + return "", fmt.Errorf("oauth2/google/externalaccount: invalid response when retrieving subject token: %v", err) } defer resp.Body.Close() respBody, err := ioutil.ReadAll(io.LimitReader(resp.Body, 1<<20)) if err != nil { - return "", fmt.Errorf("oauth2/google: invalid body in subject token URL query: %v", err) + return "", fmt.Errorf("oauth2/google/externalaccount: invalid body in subject token URL query: %v", err) } if c := resp.StatusCode; c < 200 || c > 299 { - return "", fmt.Errorf("oauth2/google: status code %d: %s", c, respBody) + return "", fmt.Errorf("oauth2/google/externalaccount: status code %d: %s", c, respBody) } switch cs.Format.Type { @@ -57,15 +57,15 @@ func (cs urlCredentialSource) subjectToken() (string, error) { jsonData := make(map[string]interface{}) err = json.Unmarshal(respBody, &jsonData) if err != nil { - return "", fmt.Errorf("oauth2/google: failed to unmarshal subject token file: %v", err) + return "", fmt.Errorf("oauth2/google/externalaccount: failed to unmarshal subject token file: %v", err) } val, ok := jsonData[cs.Format.SubjectTokenFieldName] if !ok { - return "", errors.New("oauth2/google: provided subject_token_field_name not found in credentials") + return "", errors.New("oauth2/google/externalaccount: provided subject_token_field_name not found in credentials") } token, ok := val.(string) if !ok { - return "", errors.New("oauth2/google: improperly formatted subject token") + return "", errors.New("oauth2/google/externalaccount: improperly formatted subject token") } return token, nil case "text": @@ -73,7 +73,7 @@ func (cs urlCredentialSource) subjectToken() (string, error) { case "": return string(respBody), nil default: - return "", errors.New("oauth2/google: invalid credential_source file format type") + return "", errors.New("oauth2/google/externalaccount: invalid credential_source file format type") } } diff --git a/vendor/golang.org/x/oauth2/google/google.go b/vendor/golang.org/x/oauth2/google/google.go index c66c53527d..ba931c2c3d 100644 --- a/vendor/golang.org/x/oauth2/google/google.go +++ b/vendor/golang.org/x/oauth2/google/google.go @@ -15,8 +15,9 @@ import ( "cloud.google.com/go/compute/metadata" "golang.org/x/oauth2" - "golang.org/x/oauth2/google/internal/externalaccount" + "golang.org/x/oauth2/google/externalaccount" "golang.org/x/oauth2/google/internal/externalaccountauthorizeduser" + "golang.org/x/oauth2/google/internal/impersonate" "golang.org/x/oauth2/jwt" ) @@ -200,12 +201,12 @@ func (f *credentialsFile) tokenSource(ctx context.Context, params CredentialsPar ServiceAccountImpersonationLifetimeSeconds: f.ServiceAccountImpersonation.TokenLifetimeSeconds, ClientSecret: f.ClientSecret, ClientID: f.ClientID, - CredentialSource: f.CredentialSource, + CredentialSource: &f.CredentialSource, QuotaProjectID: f.QuotaProjectID, Scopes: params.Scopes, WorkforcePoolUserProject: f.WorkforcePoolUserProject, } - return cfg.TokenSource(ctx) + return externalaccount.NewTokenSource(ctx, *cfg) case externalAccountAuthorizedUserKey: cfg := &externalaccountauthorizeduser.Config{ Audience: f.Audience, @@ -228,7 +229,7 @@ func (f *credentialsFile) tokenSource(ctx context.Context, params CredentialsPar if err != nil { return nil, err } - imp := externalaccount.ImpersonateTokenSource{ + imp := impersonate.ImpersonateTokenSource{ Ctx: ctx, URL: f.ServiceAccountImpersonationURL, Scopes: params.Scopes, diff --git a/vendor/golang.org/x/oauth2/google/internal/externalaccount/basecredentials.go b/vendor/golang.org/x/oauth2/google/internal/externalaccount/basecredentials.go deleted file mode 100644 index 33288d3677..0000000000 --- a/vendor/golang.org/x/oauth2/google/internal/externalaccount/basecredentials.go +++ /dev/null @@ -1,254 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package externalaccount - -import ( - "context" - "fmt" - "net/http" - "regexp" - "strconv" - "time" - - "golang.org/x/oauth2" - "golang.org/x/oauth2/google/internal/stsexchange" -) - -// now aliases time.Now for testing -var now = func() time.Time { - return time.Now().UTC() -} - -// Config stores the configuration for fetching tokens with external credentials. -type Config struct { - // Audience is the Secure Token Service (STS) audience which contains the resource name for the workload - // identity pool or the workforce pool and the provider identifier in that pool. - Audience string - // SubjectTokenType is the STS token type based on the Oauth2.0 token exchange spec - // e.g. `urn:ietf:params:oauth:token-type:jwt`. - SubjectTokenType string - // TokenURL is the STS token exchange endpoint. - TokenURL string - // TokenInfoURL is the token_info endpoint used to retrieve the account related information ( - // user attributes like account identifier, eg. email, username, uid, etc). This is - // needed for gCloud session account identification. - TokenInfoURL string - // ServiceAccountImpersonationURL is the URL for the service account impersonation request. This is only - // required for workload identity pools when APIs to be accessed have not integrated with UberMint. - ServiceAccountImpersonationURL string - // ServiceAccountImpersonationLifetimeSeconds is the number of seconds the service account impersonation - // token will be valid for. - ServiceAccountImpersonationLifetimeSeconds int - // ClientSecret is currently only required if token_info endpoint also - // needs to be called with the generated GCP access token. When provided, STS will be - // called with additional basic authentication using client_id as username and client_secret as password. - ClientSecret string - // ClientID is only required in conjunction with ClientSecret, as described above. - ClientID string - // CredentialSource contains the necessary information to retrieve the token itself, as well - // as some environmental information. - CredentialSource CredentialSource - // QuotaProjectID is injected by gCloud. If the value is non-empty, the Auth libraries - // will set the x-goog-user-project which overrides the project associated with the credentials. - QuotaProjectID string - // Scopes contains the desired scopes for the returned access token. - Scopes []string - // The optional workforce pool user project number when the credential - // corresponds to a workforce pool and not a workload identity pool. - // The underlying principal must still have serviceusage.services.use IAM - // permission to use the project for billing/quota. - WorkforcePoolUserProject string -} - -var ( - validWorkforceAudiencePattern *regexp.Regexp = regexp.MustCompile(`//iam\.googleapis\.com/locations/[^/]+/workforcePools/`) -) - -func validateWorkforceAudience(input string) bool { - return validWorkforceAudiencePattern.MatchString(input) -} - -// TokenSource Returns an external account TokenSource struct. This is to be called by package google to construct a google.Credentials. -func (c *Config) TokenSource(ctx context.Context) (oauth2.TokenSource, error) { - return c.tokenSource(ctx, "https") -} - -// tokenSource is a private function that's directly called by some of the tests, -// because the unit test URLs are mocked, and would otherwise fail the -// validity check. -func (c *Config) tokenSource(ctx context.Context, scheme string) (oauth2.TokenSource, error) { - if c.WorkforcePoolUserProject != "" { - valid := validateWorkforceAudience(c.Audience) - if !valid { - return nil, fmt.Errorf("oauth2/google: workforce_pool_user_project should not be set for non-workforce pool credentials") - } - } - - ts := tokenSource{ - ctx: ctx, - conf: c, - } - if c.ServiceAccountImpersonationURL == "" { - return oauth2.ReuseTokenSource(nil, ts), nil - } - scopes := c.Scopes - ts.conf.Scopes = []string{"https://www.googleapis.com/auth/cloud-platform"} - imp := ImpersonateTokenSource{ - Ctx: ctx, - URL: c.ServiceAccountImpersonationURL, - Scopes: scopes, - Ts: oauth2.ReuseTokenSource(nil, ts), - TokenLifetimeSeconds: c.ServiceAccountImpersonationLifetimeSeconds, - } - return oauth2.ReuseTokenSource(nil, imp), nil -} - -// Subject token file types. -const ( - fileTypeText = "text" - fileTypeJSON = "json" -) - -type format struct { - // Type is either "text" or "json". When not provided "text" type is assumed. - Type string `json:"type"` - // SubjectTokenFieldName is only required for JSON format. This would be "access_token" for azure. - SubjectTokenFieldName string `json:"subject_token_field_name"` -} - -// CredentialSource stores the information necessary to retrieve the credentials for the STS exchange. -// One field amongst File, URL, and Executable should be filled, depending on the kind of credential in question. -// The EnvironmentID should start with AWS if being used for an AWS credential. -type CredentialSource struct { - File string `json:"file"` - - URL string `json:"url"` - Headers map[string]string `json:"headers"` - - Executable *ExecutableConfig `json:"executable"` - - EnvironmentID string `json:"environment_id"` - RegionURL string `json:"region_url"` - RegionalCredVerificationURL string `json:"regional_cred_verification_url"` - CredVerificationURL string `json:"cred_verification_url"` - IMDSv2SessionTokenURL string `json:"imdsv2_session_token_url"` - Format format `json:"format"` -} - -type ExecutableConfig struct { - Command string `json:"command"` - TimeoutMillis *int `json:"timeout_millis"` - OutputFile string `json:"output_file"` -} - -// parse determines the type of CredentialSource needed. -func (c *Config) parse(ctx context.Context) (baseCredentialSource, error) { - if len(c.CredentialSource.EnvironmentID) > 3 && c.CredentialSource.EnvironmentID[:3] == "aws" { - if awsVersion, err := strconv.Atoi(c.CredentialSource.EnvironmentID[3:]); err == nil { - if awsVersion != 1 { - return nil, fmt.Errorf("oauth2/google: aws version '%d' is not supported in the current build", awsVersion) - } - - awsCredSource := awsCredentialSource{ - EnvironmentID: c.CredentialSource.EnvironmentID, - RegionURL: c.CredentialSource.RegionURL, - RegionalCredVerificationURL: c.CredentialSource.RegionalCredVerificationURL, - CredVerificationURL: c.CredentialSource.URL, - TargetResource: c.Audience, - ctx: ctx, - } - if c.CredentialSource.IMDSv2SessionTokenURL != "" { - awsCredSource.IMDSv2SessionTokenURL = c.CredentialSource.IMDSv2SessionTokenURL - } - - return awsCredSource, nil - } - } else if c.CredentialSource.File != "" { - return fileCredentialSource{File: c.CredentialSource.File, Format: c.CredentialSource.Format}, nil - } else if c.CredentialSource.URL != "" { - return urlCredentialSource{URL: c.CredentialSource.URL, Headers: c.CredentialSource.Headers, Format: c.CredentialSource.Format, ctx: ctx}, nil - } else if c.CredentialSource.Executable != nil { - return CreateExecutableCredential(ctx, c.CredentialSource.Executable, c) - } - return nil, fmt.Errorf("oauth2/google: unable to parse credential source") -} - -type baseCredentialSource interface { - credentialSourceType() string - subjectToken() (string, error) -} - -// tokenSource is the source that handles external credentials. It is used to retrieve Tokens. -type tokenSource struct { - ctx context.Context - conf *Config -} - -func getMetricsHeaderValue(conf *Config, credSource baseCredentialSource) string { - return fmt.Sprintf("gl-go/%s auth/%s google-byoid-sdk source/%s sa-impersonation/%t config-lifetime/%t", - goVersion(), - "unknown", - credSource.credentialSourceType(), - conf.ServiceAccountImpersonationURL != "", - conf.ServiceAccountImpersonationLifetimeSeconds != 0) -} - -// Token allows tokenSource to conform to the oauth2.TokenSource interface. -func (ts tokenSource) Token() (*oauth2.Token, error) { - conf := ts.conf - - credSource, err := conf.parse(ts.ctx) - if err != nil { - return nil, err - } - subjectToken, err := credSource.subjectToken() - - if err != nil { - return nil, err - } - stsRequest := stsexchange.TokenExchangeRequest{ - GrantType: "urn:ietf:params:oauth:grant-type:token-exchange", - Audience: conf.Audience, - Scope: conf.Scopes, - RequestedTokenType: "urn:ietf:params:oauth:token-type:access_token", - SubjectToken: subjectToken, - SubjectTokenType: conf.SubjectTokenType, - } - header := make(http.Header) - header.Add("Content-Type", "application/x-www-form-urlencoded") - header.Add("x-goog-api-client", getMetricsHeaderValue(conf, credSource)) - clientAuth := stsexchange.ClientAuthentication{ - AuthStyle: oauth2.AuthStyleInHeader, - ClientID: conf.ClientID, - ClientSecret: conf.ClientSecret, - } - var options map[string]interface{} - // Do not pass workforce_pool_user_project when client authentication is used. - // The client ID is sufficient for determining the user project. - if conf.WorkforcePoolUserProject != "" && conf.ClientID == "" { - options = map[string]interface{}{ - "userProject": conf.WorkforcePoolUserProject, - } - } - stsResp, err := stsexchange.ExchangeToken(ts.ctx, conf.TokenURL, &stsRequest, clientAuth, header, options) - if err != nil { - return nil, err - } - - accessToken := &oauth2.Token{ - AccessToken: stsResp.AccessToken, - TokenType: stsResp.TokenType, - } - if stsResp.ExpiresIn < 0 { - return nil, fmt.Errorf("oauth2/google: got invalid expiry from security token service") - } else if stsResp.ExpiresIn >= 0 { - accessToken.Expiry = now().Add(time.Duration(stsResp.ExpiresIn) * time.Second) - } - - if stsResp.RefreshToken != "" { - accessToken.RefreshToken = stsResp.RefreshToken - } - return accessToken, nil -} diff --git a/vendor/golang.org/x/oauth2/google/internal/externalaccount/err.go b/vendor/golang.org/x/oauth2/google/internal/externalaccount/err.go deleted file mode 100644 index 233a78cef2..0000000000 --- a/vendor/golang.org/x/oauth2/google/internal/externalaccount/err.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package externalaccount - -import "fmt" - -// Error for handling OAuth related error responses as stated in rfc6749#5.2. -type Error struct { - Code string - URI string - Description string -} - -func (err *Error) Error() string { - return fmt.Sprintf("got error code %s from %s: %s", err.Code, err.URI, err.Description) -} diff --git a/vendor/golang.org/x/oauth2/google/internal/externalaccount/impersonate.go b/vendor/golang.org/x/oauth2/google/internal/impersonate/impersonate.go similarity index 99% rename from vendor/golang.org/x/oauth2/google/internal/externalaccount/impersonate.go rename to vendor/golang.org/x/oauth2/google/internal/impersonate/impersonate.go index 54c8f209f3..6bc3af1103 100644 --- a/vendor/golang.org/x/oauth2/google/internal/externalaccount/impersonate.go +++ b/vendor/golang.org/x/oauth2/google/internal/impersonate/impersonate.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package externalaccount +package impersonate import ( "bytes" diff --git a/vendor/golang.org/x/sys/unix/aliases.go b/vendor/golang.org/x/sys/unix/aliases.go index e7d3df4bd3..b0e4198575 100644 --- a/vendor/golang.org/x/sys/unix/aliases.go +++ b/vendor/golang.org/x/sys/unix/aliases.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos) && go1.9 +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin_libSystem.go b/vendor/golang.org/x/sys/unix/syscall_darwin_libSystem.go index 16dc699379..2f0fa76e4f 100644 --- a/vendor/golang.org/x/sys/unix/syscall_darwin_libSystem.go +++ b/vendor/golang.org/x/sys/unix/syscall_darwin_libSystem.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build darwin && go1.12 +//go:build darwin package unix diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd.go b/vendor/golang.org/x/sys/unix/syscall_freebsd.go index 64d1bb4dba..2b57e0f73b 100644 --- a/vendor/golang.org/x/sys/unix/syscall_freebsd.go +++ b/vendor/golang.org/x/sys/unix/syscall_freebsd.go @@ -13,6 +13,7 @@ package unix import ( + "errors" "sync" "unsafe" ) @@ -169,25 +170,26 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) { func Uname(uname *Utsname) error { mib := []_C_int{CTL_KERN, KERN_OSTYPE} n := unsafe.Sizeof(uname.Sysname) - if err := sysctl(mib, &uname.Sysname[0], &n, nil, 0); err != nil { + // Suppress ENOMEM errors to be compatible with the C library __xuname() implementation. + if err := sysctl(mib, &uname.Sysname[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) { return err } mib = []_C_int{CTL_KERN, KERN_HOSTNAME} n = unsafe.Sizeof(uname.Nodename) - if err := sysctl(mib, &uname.Nodename[0], &n, nil, 0); err != nil { + if err := sysctl(mib, &uname.Nodename[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) { return err } mib = []_C_int{CTL_KERN, KERN_OSRELEASE} n = unsafe.Sizeof(uname.Release) - if err := sysctl(mib, &uname.Release[0], &n, nil, 0); err != nil { + if err := sysctl(mib, &uname.Release[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) { return err } mib = []_C_int{CTL_KERN, KERN_VERSION} n = unsafe.Sizeof(uname.Version) - if err := sysctl(mib, &uname.Version[0], &n, nil, 0); err != nil { + if err := sysctl(mib, &uname.Version[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) { return err } @@ -205,7 +207,7 @@ func Uname(uname *Utsname) error { mib = []_C_int{CTL_HW, HW_MACHINE} n = unsafe.Sizeof(uname.Machine) - if err := sysctl(mib, &uname.Machine[0], &n, nil, 0); err != nil { + if err := sysctl(mib, &uname.Machine[0], &n, nil, 0); err != nil && !errors.Is(err, ENOMEM) { return err } diff --git a/vendor/golang.org/x/sys/unix/syscall_linux.go b/vendor/golang.org/x/sys/unix/syscall_linux.go index 0f85e29e62..5682e2628a 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux.go @@ -1849,6 +1849,105 @@ func Dup2(oldfd, newfd int) error { //sys Fsmount(fd int, flags int, mountAttrs int) (fsfd int, err error) //sys Fsopen(fsName string, flags int) (fd int, err error) //sys Fspick(dirfd int, pathName string, flags int) (fd int, err error) + +//sys fsconfig(fd int, cmd uint, key *byte, value *byte, aux int) (err error) + +func fsconfigCommon(fd int, cmd uint, key string, value *byte, aux int) (err error) { + var keyp *byte + if keyp, err = BytePtrFromString(key); err != nil { + return + } + return fsconfig(fd, cmd, keyp, value, aux) +} + +// FsconfigSetFlag is equivalent to fsconfig(2) called +// with cmd == FSCONFIG_SET_FLAG. +// +// fd is the filesystem context to act upon. +// key the parameter key to set. +func FsconfigSetFlag(fd int, key string) (err error) { + return fsconfigCommon(fd, FSCONFIG_SET_FLAG, key, nil, 0) +} + +// FsconfigSetString is equivalent to fsconfig(2) called +// with cmd == FSCONFIG_SET_STRING. +// +// fd is the filesystem context to act upon. +// key the parameter key to set. +// value is the parameter value to set. +func FsconfigSetString(fd int, key string, value string) (err error) { + var valuep *byte + if valuep, err = BytePtrFromString(value); err != nil { + return + } + return fsconfigCommon(fd, FSCONFIG_SET_STRING, key, valuep, 0) +} + +// FsconfigSetBinary is equivalent to fsconfig(2) called +// with cmd == FSCONFIG_SET_BINARY. +// +// fd is the filesystem context to act upon. +// key the parameter key to set. +// value is the parameter value to set. +func FsconfigSetBinary(fd int, key string, value []byte) (err error) { + if len(value) == 0 { + return EINVAL + } + return fsconfigCommon(fd, FSCONFIG_SET_BINARY, key, &value[0], len(value)) +} + +// FsconfigSetPath is equivalent to fsconfig(2) called +// with cmd == FSCONFIG_SET_PATH. +// +// fd is the filesystem context to act upon. +// key the parameter key to set. +// path is a non-empty path for specified key. +// atfd is a file descriptor at which to start lookup from or AT_FDCWD. +func FsconfigSetPath(fd int, key string, path string, atfd int) (err error) { + var valuep *byte + if valuep, err = BytePtrFromString(path); err != nil { + return + } + return fsconfigCommon(fd, FSCONFIG_SET_PATH, key, valuep, atfd) +} + +// FsconfigSetPathEmpty is equivalent to fsconfig(2) called +// with cmd == FSCONFIG_SET_PATH_EMPTY. The same as +// FconfigSetPath but with AT_PATH_EMPTY implied. +func FsconfigSetPathEmpty(fd int, key string, path string, atfd int) (err error) { + var valuep *byte + if valuep, err = BytePtrFromString(path); err != nil { + return + } + return fsconfigCommon(fd, FSCONFIG_SET_PATH_EMPTY, key, valuep, atfd) +} + +// FsconfigSetFd is equivalent to fsconfig(2) called +// with cmd == FSCONFIG_SET_FD. +// +// fd is the filesystem context to act upon. +// key the parameter key to set. +// value is a file descriptor to be assigned to specified key. +func FsconfigSetFd(fd int, key string, value int) (err error) { + return fsconfigCommon(fd, FSCONFIG_SET_FD, key, nil, value) +} + +// FsconfigCreate is equivalent to fsconfig(2) called +// with cmd == FSCONFIG_CMD_CREATE. +// +// fd is the filesystem context to act upon. +func FsconfigCreate(fd int) (err error) { + return fsconfig(fd, FSCONFIG_CMD_CREATE, nil, nil, 0) +} + +// FsconfigReconfigure is equivalent to fsconfig(2) called +// with cmd == FSCONFIG_CMD_RECONFIGURE. +// +// fd is the filesystem context to act upon. +func FsconfigReconfigure(fd int) (err error) { + return fsconfig(fd, FSCONFIG_CMD_RECONFIGURE, nil, nil, 0) +} + //sys Getdents(fd int, buf []byte) (n int, err error) = SYS_GETDENTS64 //sysnb Getpgid(pid int) (pgid int, err error) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux.go b/vendor/golang.org/x/sys/unix/zsyscall_linux.go index 1488d27128..87d8612a1d 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux.go @@ -906,6 +906,16 @@ func Fspick(dirfd int, pathName string, flags int) (fd int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fsconfig(fd int, cmd uint, key *byte, value *byte, aux int) (err error) { + _, _, e1 := Syscall6(SYS_FSCONFIG, uintptr(fd), uintptr(cmd), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(value)), uintptr(aux), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Getdents(fd int, buf []byte) (n int, err error) { var _p0 unsafe.Pointer if len(buf) > 0 { diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux.go b/vendor/golang.org/x/sys/unix/ztypes_linux.go index dc0c955eec..eff6bcdef8 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux.go @@ -836,6 +836,15 @@ const ( FSPICK_EMPTY_PATH = 0x8 FSMOUNT_CLOEXEC = 0x1 + + FSCONFIG_SET_FLAG = 0x0 + FSCONFIG_SET_STRING = 0x1 + FSCONFIG_SET_BINARY = 0x2 + FSCONFIG_SET_PATH = 0x3 + FSCONFIG_SET_PATH_EMPTY = 0x4 + FSCONFIG_SET_FD = 0x5 + FSCONFIG_CMD_CREATE = 0x6 + FSCONFIG_CMD_RECONFIGURE = 0x7 ) type OpenHow struct { @@ -1550,6 +1559,7 @@ const ( IFLA_DEVLINK_PORT = 0x3e IFLA_GSO_IPV4_MAX_SIZE = 0x3f IFLA_GRO_IPV4_MAX_SIZE = 0x40 + IFLA_DPLL_PIN = 0x41 IFLA_PROTO_DOWN_REASON_UNSPEC = 0x0 IFLA_PROTO_DOWN_REASON_MASK = 0x1 IFLA_PROTO_DOWN_REASON_VALUE = 0x2 @@ -1565,6 +1575,7 @@ const ( IFLA_INET6_ICMP6STATS = 0x6 IFLA_INET6_TOKEN = 0x7 IFLA_INET6_ADDR_GEN_MODE = 0x8 + IFLA_INET6_RA_MTU = 0x9 IFLA_BR_UNSPEC = 0x0 IFLA_BR_FORWARD_DELAY = 0x1 IFLA_BR_HELLO_TIME = 0x2 @@ -1612,6 +1623,9 @@ const ( IFLA_BR_MCAST_MLD_VERSION = 0x2c IFLA_BR_VLAN_STATS_PER_PORT = 0x2d IFLA_BR_MULTI_BOOLOPT = 0x2e + IFLA_BR_MCAST_QUERIER_STATE = 0x2f + IFLA_BR_FDB_N_LEARNED = 0x30 + IFLA_BR_FDB_MAX_LEARNED = 0x31 IFLA_BRPORT_UNSPEC = 0x0 IFLA_BRPORT_STATE = 0x1 IFLA_BRPORT_PRIORITY = 0x2 @@ -1649,6 +1663,14 @@ const ( IFLA_BRPORT_BACKUP_PORT = 0x22 IFLA_BRPORT_MRP_RING_OPEN = 0x23 IFLA_BRPORT_MRP_IN_OPEN = 0x24 + IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT = 0x25 + IFLA_BRPORT_MCAST_EHT_HOSTS_CNT = 0x26 + IFLA_BRPORT_LOCKED = 0x27 + IFLA_BRPORT_MAB = 0x28 + IFLA_BRPORT_MCAST_N_GROUPS = 0x29 + IFLA_BRPORT_MCAST_MAX_GROUPS = 0x2a + IFLA_BRPORT_NEIGH_VLAN_SUPPRESS = 0x2b + IFLA_BRPORT_BACKUP_NHID = 0x2c IFLA_INFO_UNSPEC = 0x0 IFLA_INFO_KIND = 0x1 IFLA_INFO_DATA = 0x2 @@ -1670,6 +1692,9 @@ const ( IFLA_MACVLAN_MACADDR = 0x4 IFLA_MACVLAN_MACADDR_DATA = 0x5 IFLA_MACVLAN_MACADDR_COUNT = 0x6 + IFLA_MACVLAN_BC_QUEUE_LEN = 0x7 + IFLA_MACVLAN_BC_QUEUE_LEN_USED = 0x8 + IFLA_MACVLAN_BC_CUTOFF = 0x9 IFLA_VRF_UNSPEC = 0x0 IFLA_VRF_TABLE = 0x1 IFLA_VRF_PORT_UNSPEC = 0x0 @@ -1693,9 +1718,22 @@ const ( IFLA_XFRM_UNSPEC = 0x0 IFLA_XFRM_LINK = 0x1 IFLA_XFRM_IF_ID = 0x2 + IFLA_XFRM_COLLECT_METADATA = 0x3 IFLA_IPVLAN_UNSPEC = 0x0 IFLA_IPVLAN_MODE = 0x1 IFLA_IPVLAN_FLAGS = 0x2 + NETKIT_NEXT = -0x1 + NETKIT_PASS = 0x0 + NETKIT_DROP = 0x2 + NETKIT_REDIRECT = 0x7 + NETKIT_L2 = 0x0 + NETKIT_L3 = 0x1 + IFLA_NETKIT_UNSPEC = 0x0 + IFLA_NETKIT_PEER_INFO = 0x1 + IFLA_NETKIT_PRIMARY = 0x2 + IFLA_NETKIT_POLICY = 0x3 + IFLA_NETKIT_PEER_POLICY = 0x4 + IFLA_NETKIT_MODE = 0x5 IFLA_VXLAN_UNSPEC = 0x0 IFLA_VXLAN_ID = 0x1 IFLA_VXLAN_GROUP = 0x2 @@ -1726,6 +1764,8 @@ const ( IFLA_VXLAN_GPE = 0x1b IFLA_VXLAN_TTL_INHERIT = 0x1c IFLA_VXLAN_DF = 0x1d + IFLA_VXLAN_VNIFILTER = 0x1e + IFLA_VXLAN_LOCALBYPASS = 0x1f IFLA_GENEVE_UNSPEC = 0x0 IFLA_GENEVE_ID = 0x1 IFLA_GENEVE_REMOTE = 0x2 @@ -1740,6 +1780,7 @@ const ( IFLA_GENEVE_LABEL = 0xb IFLA_GENEVE_TTL_INHERIT = 0xc IFLA_GENEVE_DF = 0xd + IFLA_GENEVE_INNER_PROTO_INHERIT = 0xe IFLA_BAREUDP_UNSPEC = 0x0 IFLA_BAREUDP_PORT = 0x1 IFLA_BAREUDP_ETHERTYPE = 0x2 @@ -1752,6 +1793,8 @@ const ( IFLA_GTP_FD1 = 0x2 IFLA_GTP_PDP_HASHSIZE = 0x3 IFLA_GTP_ROLE = 0x4 + IFLA_GTP_CREATE_SOCKETS = 0x5 + IFLA_GTP_RESTART_COUNT = 0x6 IFLA_BOND_UNSPEC = 0x0 IFLA_BOND_MODE = 0x1 IFLA_BOND_ACTIVE_SLAVE = 0x2 @@ -1781,6 +1824,9 @@ const ( IFLA_BOND_AD_ACTOR_SYSTEM = 0x1a IFLA_BOND_TLB_DYNAMIC_LB = 0x1b IFLA_BOND_PEER_NOTIF_DELAY = 0x1c + IFLA_BOND_AD_LACP_ACTIVE = 0x1d + IFLA_BOND_MISSED_MAX = 0x1e + IFLA_BOND_NS_IP6_TARGET = 0x1f IFLA_BOND_AD_INFO_UNSPEC = 0x0 IFLA_BOND_AD_INFO_AGGREGATOR = 0x1 IFLA_BOND_AD_INFO_NUM_PORTS = 0x2 @@ -1796,6 +1842,7 @@ const ( IFLA_BOND_SLAVE_AD_AGGREGATOR_ID = 0x6 IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE = 0x7 IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE = 0x8 + IFLA_BOND_SLAVE_PRIO = 0x9 IFLA_VF_INFO_UNSPEC = 0x0 IFLA_VF_INFO = 0x1 IFLA_VF_UNSPEC = 0x0 @@ -1854,8 +1901,16 @@ const ( IFLA_STATS_LINK_XSTATS_SLAVE = 0x3 IFLA_STATS_LINK_OFFLOAD_XSTATS = 0x4 IFLA_STATS_AF_SPEC = 0x5 + IFLA_STATS_GETSET_UNSPEC = 0x0 + IFLA_STATS_GET_FILTERS = 0x1 + IFLA_STATS_SET_OFFLOAD_XSTATS_L3_STATS = 0x2 IFLA_OFFLOAD_XSTATS_UNSPEC = 0x0 IFLA_OFFLOAD_XSTATS_CPU_HIT = 0x1 + IFLA_OFFLOAD_XSTATS_HW_S_INFO = 0x2 + IFLA_OFFLOAD_XSTATS_L3_STATS = 0x3 + IFLA_OFFLOAD_XSTATS_HW_S_INFO_UNSPEC = 0x0 + IFLA_OFFLOAD_XSTATS_HW_S_INFO_REQUEST = 0x1 + IFLA_OFFLOAD_XSTATS_HW_S_INFO_USED = 0x2 IFLA_XDP_UNSPEC = 0x0 IFLA_XDP_FD = 0x1 IFLA_XDP_ATTACHED = 0x2 @@ -1885,6 +1940,11 @@ const ( IFLA_RMNET_UNSPEC = 0x0 IFLA_RMNET_MUX_ID = 0x1 IFLA_RMNET_FLAGS = 0x2 + IFLA_MCTP_UNSPEC = 0x0 + IFLA_MCTP_NET = 0x1 + IFLA_DSA_UNSPEC = 0x0 + IFLA_DSA_CONDUIT = 0x1 + IFLA_DSA_MASTER = 0x1 ) const ( diff --git a/vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go b/vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go index 03543bd4bb..137cc8df1d 100644 --- a/vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go +++ b/vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go @@ -47,7 +47,7 @@ import ( func Find(importPath, srcDir string) (filename, path string) { cmd := exec.Command("go", "list", "-json", "-export", "--", importPath) cmd.Dir = srcDir - out, err := cmd.CombinedOutput() + out, err := cmd.Output() if err != nil { return "", "" } diff --git a/vendor/golang.org/x/tools/go/packages/doc.go b/vendor/golang.org/x/tools/go/packages/doc.go index b2a0b7c6a6..a8d7b06ac0 100644 --- a/vendor/golang.org/x/tools/go/packages/doc.go +++ b/vendor/golang.org/x/tools/go/packages/doc.go @@ -15,22 +15,10 @@ Load passes most patterns directly to the underlying build tool. The default build tool is the go command. Its supported patterns are described at https://pkg.go.dev/cmd/go#hdr-Package_lists_and_patterns. +Other build systems may be supported by providing a "driver"; +see [The driver protocol]. -Load may be used in Go projects that use alternative build systems, by -installing an appropriate "driver" program for the build system and -specifying its location in the GOPACKAGESDRIVER environment variable. -For example, -https://github.com/bazelbuild/rules_go/wiki/Editor-and-tool-integration -explains how to use the driver for Bazel. -The driver program is responsible for interpreting patterns in its -preferred notation and reporting information about the packages that -they identify. -(See driverRequest and driverResponse types for the JSON -schema used by the protocol. -Though the protocol is supported, these types are currently unexported; -see #64608 for a proposal to publish them.) - -Regardless of driver, all patterns with the prefix "query=", where query is a +All patterns with the prefix "query=", where query is a non-empty string of letters from [a-z], are reserved and may be interpreted as query operators. @@ -86,7 +74,29 @@ for details. Most tools should pass their command-line arguments (after any flags) uninterpreted to [Load], so that it can interpret them according to the conventions of the underlying build system. + See the Example function for typical usage. + +# The driver protocol + +[Load] may be used to load Go packages even in Go projects that use +alternative build systems, by installing an appropriate "driver" +program for the build system and specifying its location in the +GOPACKAGESDRIVER environment variable. +For example, +https://github.com/bazelbuild/rules_go/wiki/Editor-and-tool-integration +explains how to use the driver for Bazel. + +The driver program is responsible for interpreting patterns in its +preferred notation and reporting information about the packages that +those patterns identify. Drivers must also support the special "file=" +and "pattern=" patterns described above. + +The patterns are provided as positional command-line arguments. A +JSON-encoded [DriverRequest] message providing additional information +is written to the driver's standard input. The driver must write a +JSON-encoded [DriverResponse] message to its standard output. (This +message differs from the JSON schema produced by 'go list'.) */ package packages // import "golang.org/x/tools/go/packages" diff --git a/vendor/golang.org/x/tools/go/packages/external.go b/vendor/golang.org/x/tools/go/packages/external.go index 7db1d1293a..4335c1eb14 100644 --- a/vendor/golang.org/x/tools/go/packages/external.go +++ b/vendor/golang.org/x/tools/go/packages/external.go @@ -2,12 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// This file enables an external tool to intercept package requests. -// If the tool is present then its results are used in preference to -// the go list command. - package packages +// This file defines the protocol that enables an external "driver" +// tool to supply package metadata in place of 'go list'. + import ( "bytes" "encoding/json" @@ -17,31 +16,71 @@ import ( "strings" ) -// The Driver Protocol +// DriverRequest defines the schema of a request for package metadata +// from an external driver program. The JSON-encoded DriverRequest +// message is provided to the driver program's standard input. The +// query patterns are provided as command-line arguments. // -// The driver, given the inputs to a call to Load, returns metadata about the packages specified. -// This allows for different build systems to support go/packages by telling go/packages how the -// packages' source is organized. -// The driver is a binary, either specified by the GOPACKAGESDRIVER environment variable or in -// the path as gopackagesdriver. It's given the inputs to load in its argv. See the package -// documentation in doc.go for the full description of the patterns that need to be supported. -// A driver receives as a JSON-serialized driverRequest struct in standard input and will -// produce a JSON-serialized driverResponse (see definition in packages.go) in its standard output. - -// driverRequest is used to provide the portion of Load's Config that is needed by a driver. -type driverRequest struct { +// See the package documentation for an overview. +type DriverRequest struct { Mode LoadMode `json:"mode"` + // Env specifies the environment the underlying build system should be run in. Env []string `json:"env"` + // BuildFlags are flags that should be passed to the underlying build system. BuildFlags []string `json:"build_flags"` + // Tests specifies whether the patterns should also return test packages. Tests bool `json:"tests"` + // Overlay maps file paths (relative to the driver's working directory) to the byte contents // of overlay files. Overlay map[string][]byte `json:"overlay"` } +// DriverResponse defines the schema of a response from an external +// driver program, providing the results of a query for package +// metadata. The driver program must write a JSON-encoded +// DriverResponse message to its standard output. +// +// See the package documentation for an overview. +type DriverResponse struct { + // NotHandled is returned if the request can't be handled by the current + // driver. If an external driver returns a response with NotHandled, the + // rest of the DriverResponse is ignored, and go/packages will fallback + // to the next driver. If go/packages is extended in the future to support + // lists of multiple drivers, go/packages will fall back to the next driver. + NotHandled bool + + // Compiler and Arch are the arguments pass of types.SizesFor + // to get a types.Sizes to use when type checking. + Compiler string + Arch string + + // Roots is the set of package IDs that make up the root packages. + // We have to encode this separately because when we encode a single package + // we cannot know if it is one of the roots as that requires knowledge of the + // graph it is part of. + Roots []string `json:",omitempty"` + + // Packages is the full set of packages in the graph. + // The packages are not connected into a graph. + // The Imports if populated will be stubs that only have their ID set. + // Imports will be connected and then type and syntax information added in a + // later pass (see refine). + Packages []*Package + + // GoVersion is the minor version number used by the driver + // (e.g. the go command on the PATH) when selecting .go files. + // Zero means unknown. + GoVersion int +} + +// driver is the type for functions that query the build system for the +// packages named by the patterns. +type driver func(cfg *Config, patterns ...string) (*DriverResponse, error) + // findExternalDriver returns the file path of a tool that supplies // the build system package structure, or "" if not found." // If GOPACKAGESDRIVER is set in the environment findExternalTool returns its @@ -64,8 +103,8 @@ func findExternalDriver(cfg *Config) driver { return nil } } - return func(cfg *Config, words ...string) (*driverResponse, error) { - req, err := json.Marshal(driverRequest{ + return func(cfg *Config, words ...string) (*DriverResponse, error) { + req, err := json.Marshal(DriverRequest{ Mode: cfg.Mode, Env: cfg.Env, BuildFlags: cfg.BuildFlags, @@ -92,7 +131,7 @@ func findExternalDriver(cfg *Config) driver { fmt.Fprintf(os.Stderr, "%s stderr: <<%s>>\n", cmdDebugStr(cmd), stderr) } - var response driverResponse + var response DriverResponse if err := json.Unmarshal(buf.Bytes(), &response); err != nil { return nil, err } diff --git a/vendor/golang.org/x/tools/go/packages/golist.go b/vendor/golang.org/x/tools/go/packages/golist.go index cd375fbc3c..22305d9c90 100644 --- a/vendor/golang.org/x/tools/go/packages/golist.go +++ b/vendor/golang.org/x/tools/go/packages/golist.go @@ -35,23 +35,23 @@ type goTooOldError struct { error } -// responseDeduper wraps a driverResponse, deduplicating its contents. +// responseDeduper wraps a DriverResponse, deduplicating its contents. type responseDeduper struct { seenRoots map[string]bool seenPackages map[string]*Package - dr *driverResponse + dr *DriverResponse } func newDeduper() *responseDeduper { return &responseDeduper{ - dr: &driverResponse{}, + dr: &DriverResponse{}, seenRoots: map[string]bool{}, seenPackages: map[string]*Package{}, } } -// addAll fills in r with a driverResponse. -func (r *responseDeduper) addAll(dr *driverResponse) { +// addAll fills in r with a DriverResponse. +func (r *responseDeduper) addAll(dr *DriverResponse) { for _, pkg := range dr.Packages { r.addPackage(pkg) } @@ -128,7 +128,7 @@ func (state *golistState) mustGetEnv() map[string]string { // goListDriver uses the go list command to interpret the patterns and produce // the build system package structure. // See driver for more details. -func goListDriver(cfg *Config, patterns ...string) (*driverResponse, error) { +func goListDriver(cfg *Config, patterns ...string) (_ *DriverResponse, err error) { // Make sure that any asynchronous go commands are killed when we return. parentCtx := cfg.Context if parentCtx == nil { @@ -146,16 +146,18 @@ func goListDriver(cfg *Config, patterns ...string) (*driverResponse, error) { } // Fill in response.Sizes asynchronously if necessary. - var sizeserr error - var sizeswg sync.WaitGroup if cfg.Mode&NeedTypesSizes != 0 || cfg.Mode&NeedTypes != 0 { - sizeswg.Add(1) + errCh := make(chan error) go func() { compiler, arch, err := packagesdriver.GetSizesForArgsGolist(ctx, state.cfgInvocation(), cfg.gocmdRunner) - sizeserr = err response.dr.Compiler = compiler response.dr.Arch = arch - sizeswg.Done() + errCh <- err + }() + defer func() { + if sizesErr := <-errCh; sizesErr != nil { + err = sizesErr + } }() } @@ -208,10 +210,7 @@ extractQueries: } } - sizeswg.Wait() - if sizeserr != nil { - return nil, sizeserr - } + // (We may yet return an error due to defer.) return response.dr, nil } @@ -266,7 +265,7 @@ func (state *golistState) runContainsQueries(response *responseDeduper, queries // adhocPackage attempts to load or construct an ad-hoc package for a given // query, if the original call to the driver produced inadequate results. -func (state *golistState) adhocPackage(pattern, query string) (*driverResponse, error) { +func (state *golistState) adhocPackage(pattern, query string) (*DriverResponse, error) { response, err := state.createDriverResponse(query) if err != nil { return nil, err @@ -357,7 +356,7 @@ func otherFiles(p *jsonPackage) [][]string { // createDriverResponse uses the "go list" command to expand the pattern // words and return a response for the specified packages. -func (state *golistState) createDriverResponse(words ...string) (*driverResponse, error) { +func (state *golistState) createDriverResponse(words ...string) (*DriverResponse, error) { // go list uses the following identifiers in ImportPath and Imports: // // "p" -- importable package or main (command) @@ -384,7 +383,7 @@ func (state *golistState) createDriverResponse(words ...string) (*driverResponse pkgs := make(map[string]*Package) additionalErrors := make(map[string][]Error) // Decode the JSON and convert it to Package form. - response := &driverResponse{ + response := &DriverResponse{ GoVersion: goVersion, } for dec := json.NewDecoder(buf); dec.More(); { diff --git a/vendor/golang.org/x/tools/go/packages/packages.go b/vendor/golang.org/x/tools/go/packages/packages.go index 81e9e6a727..f33b0afc22 100644 --- a/vendor/golang.org/x/tools/go/packages/packages.go +++ b/vendor/golang.org/x/tools/go/packages/packages.go @@ -206,43 +206,6 @@ type Config struct { Overlay map[string][]byte } -// driver is the type for functions that query the build system for the -// packages named by the patterns. -type driver func(cfg *Config, patterns ...string) (*driverResponse, error) - -// driverResponse contains the results for a driver query. -type driverResponse struct { - // NotHandled is returned if the request can't be handled by the current - // driver. If an external driver returns a response with NotHandled, the - // rest of the driverResponse is ignored, and go/packages will fallback - // to the next driver. If go/packages is extended in the future to support - // lists of multiple drivers, go/packages will fall back to the next driver. - NotHandled bool - - // Compiler and Arch are the arguments pass of types.SizesFor - // to get a types.Sizes to use when type checking. - Compiler string - Arch string - - // Roots is the set of package IDs that make up the root packages. - // We have to encode this separately because when we encode a single package - // we cannot know if it is one of the roots as that requires knowledge of the - // graph it is part of. - Roots []string `json:",omitempty"` - - // Packages is the full set of packages in the graph. - // The packages are not connected into a graph. - // The Imports if populated will be stubs that only have their ID set. - // Imports will be connected and then type and syntax information added in a - // later pass (see refine). - Packages []*Package - - // GoVersion is the minor version number used by the driver - // (e.g. the go command on the PATH) when selecting .go files. - // Zero means unknown. - GoVersion int -} - // Load loads and returns the Go packages named by the given patterns. // // Config specifies loading options; @@ -291,7 +254,7 @@ func Load(cfg *Config, patterns ...string) ([]*Package, error) { // no external driver, or the driver returns a response with NotHandled set, // defaultDriver will fall back to the go list driver. // The boolean result indicates that an external driver handled the request. -func defaultDriver(cfg *Config, patterns ...string) (*driverResponse, bool, error) { +func defaultDriver(cfg *Config, patterns ...string) (*DriverResponse, bool, error) { if driver := findExternalDriver(cfg); driver != nil { response, err := driver(cfg, patterns...) if err != nil { @@ -303,7 +266,10 @@ func defaultDriver(cfg *Config, patterns ...string) (*driverResponse, bool, erro } response, err := goListDriver(cfg, patterns...) - return response, false, err + if err != nil { + return nil, false, err + } + return response, false, nil } // A Package describes a loaded Go package. @@ -648,7 +614,7 @@ func newLoader(cfg *Config) *loader { // refine connects the supplied packages into a graph and then adds type // and syntax information as requested by the LoadMode. -func (ld *loader) refine(response *driverResponse) ([]*Package, error) { +func (ld *loader) refine(response *DriverResponse) ([]*Package, error) { roots := response.Roots rootMap := make(map[string]int, len(roots)) for i, root := range roots { diff --git a/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go b/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go index 11d5c8c3ad..6a57ce3b13 100644 --- a/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go +++ b/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go @@ -29,9 +29,13 @@ import ( "strconv" "strings" + "golang.org/x/tools/internal/aliases" "golang.org/x/tools/internal/typeparams" + "golang.org/x/tools/internal/typesinternal" ) +// TODO(adonovan): think about generic aliases. + // A Path is an opaque name that identifies a types.Object // relative to its package. Conceptually, the name consists of a // sequence of destructuring operations applied to the package scope @@ -223,7 +227,7 @@ func (enc *Encoder) For(obj types.Object) (Path, error) { // Reject obviously non-viable cases. switch obj := obj.(type) { case *types.TypeName: - if _, ok := obj.Type().(*types.TypeParam); !ok { + if _, ok := aliases.Unalias(obj.Type()).(*types.TypeParam); !ok { // With the exception of type parameters, only package-level type names // have a path. return "", fmt.Errorf("no path for %v", obj) @@ -310,7 +314,7 @@ func (enc *Encoder) For(obj types.Object) (Path, error) { } // Inspect declared methods of defined types. - if T, ok := o.Type().(*types.Named); ok { + if T, ok := aliases.Unalias(o.Type()).(*types.Named); ok { path = append(path, opType) // The method index here is always with respect // to the underlying go/types data structures, @@ -395,13 +399,8 @@ func (enc *Encoder) concreteMethod(meth *types.Func) (Path, bool) { return "", false } - recvT := meth.Type().(*types.Signature).Recv().Type() - if ptr, ok := recvT.(*types.Pointer); ok { - recvT = ptr.Elem() - } - - named, ok := recvT.(*types.Named) - if !ok { + _, named := typesinternal.ReceiverNamed(meth.Type().(*types.Signature).Recv()) + if named == nil { return "", false } @@ -444,6 +443,8 @@ func (enc *Encoder) concreteMethod(meth *types.Func) (Path, bool) { // nil, it will be allocated as necessary. func find(obj types.Object, T types.Type, path []byte, seen map[*types.TypeName]bool) []byte { switch T := T.(type) { + case *aliases.Alias: + return find(obj, aliases.Unalias(T), path, seen) case *types.Basic, *types.Named: // Named types belonging to pkg were handled already, // so T must belong to another package. No path. @@ -616,6 +617,7 @@ func Object(pkg *types.Package, p Path) (types.Object, error) { // Inv: t != nil, obj == nil + t = aliases.Unalias(t) switch code { case opElem: hasElem, ok := t.(hasElem) // Pointer, Slice, Array, Chan, Map diff --git a/vendor/golang.org/x/tools/internal/aliases/aliases.go b/vendor/golang.org/x/tools/internal/aliases/aliases.go new file mode 100644 index 0000000000..f89112c8ee --- /dev/null +++ b/vendor/golang.org/x/tools/internal/aliases/aliases.go @@ -0,0 +1,28 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package aliases + +import ( + "go/token" + "go/types" +) + +// Package aliases defines backward compatible shims +// for the types.Alias type representation added in 1.22. +// This defines placeholders for x/tools until 1.26. + +// NewAlias creates a new TypeName in Package pkg that +// is an alias for the type rhs. +// +// When GoVersion>=1.22 and GODEBUG=gotypesalias=1, +// the Type() of the return value is a *types.Alias. +func NewAlias(pos token.Pos, pkg *types.Package, name string, rhs types.Type) *types.TypeName { + if enabled() { + tname := types.NewTypeName(pos, pkg, name, nil) + newAlias(tname, rhs) + return tname + } + return types.NewTypeName(pos, pkg, name, rhs) +} diff --git a/vendor/golang.org/x/tools/internal/aliases/aliases_go121.go b/vendor/golang.org/x/tools/internal/aliases/aliases_go121.go new file mode 100644 index 0000000000..1872b56ff8 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/aliases/aliases_go121.go @@ -0,0 +1,30 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !go1.22 +// +build !go1.22 + +package aliases + +import ( + "go/types" +) + +// Alias is a placeholder for a go/types.Alias for <=1.21. +// It will never be created by go/types. +type Alias struct{} + +func (*Alias) String() string { panic("unreachable") } + +func (*Alias) Underlying() types.Type { panic("unreachable") } + +func (*Alias) Obj() *types.TypeName { panic("unreachable") } + +// Unalias returns the type t for go <=1.21. +func Unalias(t types.Type) types.Type { return t } + +// Always false for go <=1.21. Ignores GODEBUG. +func enabled() bool { return false } + +func newAlias(name *types.TypeName, rhs types.Type) *Alias { panic("unreachable") } diff --git a/vendor/golang.org/x/tools/internal/aliases/aliases_go122.go b/vendor/golang.org/x/tools/internal/aliases/aliases_go122.go new file mode 100644 index 0000000000..8b92116284 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/aliases/aliases_go122.go @@ -0,0 +1,72 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.22 +// +build go1.22 + +package aliases + +import ( + "go/ast" + "go/parser" + "go/token" + "go/types" + "os" + "strings" + "sync" +) + +// Alias is an alias of types.Alias. +type Alias = types.Alias + +// Unalias is a wrapper of types.Unalias. +func Unalias(t types.Type) types.Type { return types.Unalias(t) } + +// newAlias is an internal alias around types.NewAlias. +// Direct usage is discouraged as the moment. +// Try to use NewAlias instead. +func newAlias(tname *types.TypeName, rhs types.Type) *Alias { + a := types.NewAlias(tname, rhs) + // TODO(go.dev/issue/65455): Remove kludgy workaround to set a.actual as a side-effect. + Unalias(a) + return a +} + +// enabled returns true when types.Aliases are enabled. +func enabled() bool { + // Use the gotypesalias value in GODEBUG if set. + godebug := os.Getenv("GODEBUG") + value := -1 // last set value. + for _, f := range strings.Split(godebug, ",") { + switch f { + case "gotypesalias=1": + value = 1 + case "gotypesalias=0": + value = 0 + } + } + switch value { + case 0: + return false + case 1: + return true + default: + return aliasesDefault() + } +} + +// aliasesDefault reports if aliases are enabled by default. +func aliasesDefault() bool { + // Dynamically check if Aliases will be produced from go/types. + aliasesDefaultOnce.Do(func() { + fset := token.NewFileSet() + f, _ := parser.ParseFile(fset, "a.go", "package p; type A = int", 0) + pkg, _ := new(types.Config).Check("p", fset, []*ast.File{f}, nil) + _, gotypesaliasDefault = pkg.Scope().Lookup("A").Type().(*types.Alias) + }) + return gotypesaliasDefault +} + +var gotypesaliasDefault bool +var aliasesDefaultOnce sync.Once diff --git a/vendor/golang.org/x/tools/internal/gcimporter/gcimporter.go b/vendor/golang.org/x/tools/internal/gcimporter/gcimporter.go index 2d078ccb19..39df91124a 100644 --- a/vendor/golang.org/x/tools/internal/gcimporter/gcimporter.go +++ b/vendor/golang.org/x/tools/internal/gcimporter/gcimporter.go @@ -259,13 +259,6 @@ func Import(packages map[string]*types.Package, path, srcDir string, lookup func return } -func deref(typ types.Type) types.Type { - if p, _ := typ.(*types.Pointer); p != nil { - return p.Elem() - } - return typ -} - type byPath []*types.Package func (a byPath) Len() int { return len(a) } diff --git a/vendor/golang.org/x/tools/internal/gcimporter/iexport.go b/vendor/golang.org/x/tools/internal/gcimporter/iexport.go index 2ee8c70164..638fc1d3b8 100644 --- a/vendor/golang.org/x/tools/internal/gcimporter/iexport.go +++ b/vendor/golang.org/x/tools/internal/gcimporter/iexport.go @@ -23,6 +23,7 @@ import ( "strings" "golang.org/x/tools/go/types/objectpath" + "golang.org/x/tools/internal/aliases" "golang.org/x/tools/internal/tokeninternal" ) @@ -506,13 +507,13 @@ func (p *iexporter) doDecl(obj types.Object) { case *types.TypeName: t := obj.Type() - if tparam, ok := t.(*types.TypeParam); ok { + if tparam, ok := aliases.Unalias(t).(*types.TypeParam); ok { w.tag('P') w.pos(obj.Pos()) constraint := tparam.Constraint() if p.version >= iexportVersionGo1_18 { implicit := false - if iface, _ := constraint.(*types.Interface); iface != nil { + if iface, _ := aliases.Unalias(constraint).(*types.Interface); iface != nil { implicit = iface.IsImplicit() } w.bool(implicit) @@ -738,6 +739,8 @@ func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) { }() } switch t := t.(type) { + // TODO(adonovan): support types.Alias. + case *types.Named: if targs := t.TypeArgs(); targs.Len() > 0 { w.startType(instanceType) @@ -843,7 +846,7 @@ func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) { for i := 0; i < n; i++ { ft := t.EmbeddedType(i) tPkg := pkg - if named, _ := ft.(*types.Named); named != nil { + if named, _ := aliases.Unalias(ft).(*types.Named); named != nil { w.pos(named.Obj().Pos()) } else { w.pos(token.NoPos) diff --git a/vendor/golang.org/x/tools/internal/gcimporter/iimport.go b/vendor/golang.org/x/tools/internal/gcimporter/iimport.go index 9bde15e3bc..4d50eb8e58 100644 --- a/vendor/golang.org/x/tools/internal/gcimporter/iimport.go +++ b/vendor/golang.org/x/tools/internal/gcimporter/iimport.go @@ -22,6 +22,8 @@ import ( "strings" "golang.org/x/tools/go/types/objectpath" + "golang.org/x/tools/internal/aliases" + "golang.org/x/tools/internal/typesinternal" ) type intReader struct { @@ -224,6 +226,7 @@ func iimportCommon(fset *token.FileSet, getPackages GetPackagesFunc, data []byte // Gather the relevant packages from the manifest. items := make([]GetPackagesItem, r.uint64()) + uniquePkgPaths := make(map[string]bool) for i := range items { pkgPathOff := r.uint64() pkgPath := p.stringAt(pkgPathOff) @@ -248,6 +251,12 @@ func iimportCommon(fset *token.FileSet, getPackages GetPackagesFunc, data []byte } items[i].nameIndex = nameIndex + + uniquePkgPaths[pkgPath] = true + } + // Debugging #63822; hypothesis: there are duplicate PkgPaths. + if len(uniquePkgPaths) != len(items) { + reportf("found duplicate PkgPaths while reading export data manifest: %v", items) } // Request packages all at once from the client, @@ -515,7 +524,7 @@ func canReuse(def *types.Named, rhs types.Type) bool { if def == nil { return true } - iface, _ := rhs.(*types.Interface) + iface, _ := aliases.Unalias(rhs).(*types.Interface) if iface == nil { return true } @@ -580,14 +589,13 @@ func (r *importReader) obj(name string) { // If the receiver has any targs, set those as the // rparams of the method (since those are the // typeparams being used in the method sig/body). - base := baseType(recv.Type()) - assert(base != nil) - targs := base.TypeArgs() + _, recvNamed := typesinternal.ReceiverNamed(recv) + targs := recvNamed.TypeArgs() var rparams []*types.TypeParam if targs.Len() > 0 { rparams = make([]*types.TypeParam, targs.Len()) for i := range rparams { - rparams[i] = targs.At(i).(*types.TypeParam) + rparams[i] = aliases.Unalias(targs.At(i)).(*types.TypeParam) } } msig := r.signature(recv, rparams, nil) @@ -617,7 +625,7 @@ func (r *importReader) obj(name string) { } constraint := r.typ() if implicit { - iface, _ := constraint.(*types.Interface) + iface, _ := aliases.Unalias(constraint).(*types.Interface) if iface == nil { errorf("non-interface constraint marked implicit") } @@ -824,7 +832,7 @@ func (r *importReader) typ() types.Type { } func isInterface(t types.Type) bool { - _, ok := t.(*types.Interface) + _, ok := aliases.Unalias(t).(*types.Interface) return ok } @@ -1023,7 +1031,7 @@ func (r *importReader) tparamList() []*types.TypeParam { for i := range xs { // Note: the standard library importer is tolerant of nil types here, // though would panic in SetTypeParams. - xs[i] = r.typ().(*types.TypeParam) + xs[i] = aliases.Unalias(r.typ()).(*types.TypeParam) } return xs } @@ -1070,13 +1078,3 @@ func (r *importReader) byte() byte { } return x } - -func baseType(typ types.Type) *types.Named { - // pointer receivers are never types.Named types - if p, _ := typ.(*types.Pointer); p != nil { - typ = p.Elem() - } - // receiver base types are always (possibly generic) types.Named types - n, _ := typ.(*types.Named) - return n -} diff --git a/vendor/golang.org/x/tools/internal/gcimporter/support_go117.go b/vendor/golang.org/x/tools/internal/gcimporter/support_go117.go deleted file mode 100644 index d892273efb..0000000000 --- a/vendor/golang.org/x/tools/internal/gcimporter/support_go117.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.18 -// +build !go1.18 - -package gcimporter - -import "go/types" - -const iexportVersion = iexportVersionGo1_11 - -func additionalPredeclared() []types.Type { - return nil -} diff --git a/vendor/golang.org/x/tools/internal/gcimporter/support_go118.go b/vendor/golang.org/x/tools/internal/gcimporter/support_go118.go index edbe6ea704..0cd3b91b65 100644 --- a/vendor/golang.org/x/tools/internal/gcimporter/support_go118.go +++ b/vendor/golang.org/x/tools/internal/gcimporter/support_go118.go @@ -2,9 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.18 -// +build go1.18 - package gcimporter import "go/types" diff --git a/vendor/golang.org/x/tools/internal/gcimporter/unified_no.go b/vendor/golang.org/x/tools/internal/gcimporter/unified_no.go index 286bf44548..38b624cada 100644 --- a/vendor/golang.org/x/tools/internal/gcimporter/unified_no.go +++ b/vendor/golang.org/x/tools/internal/gcimporter/unified_no.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build !(go1.18 && goexperiment.unified) -// +build !go1.18 !goexperiment.unified +//go:build !goexperiment.unified +// +build !goexperiment.unified package gcimporter diff --git a/vendor/golang.org/x/tools/internal/gcimporter/unified_yes.go b/vendor/golang.org/x/tools/internal/gcimporter/unified_yes.go index b5d69ffbe6..b5118d0b3a 100644 --- a/vendor/golang.org/x/tools/internal/gcimporter/unified_yes.go +++ b/vendor/golang.org/x/tools/internal/gcimporter/unified_yes.go @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.18 && goexperiment.unified -// +build go1.18,goexperiment.unified +//go:build goexperiment.unified +// +build goexperiment.unified package gcimporter diff --git a/vendor/golang.org/x/tools/internal/gcimporter/ureader_no.go b/vendor/golang.org/x/tools/internal/gcimporter/ureader_no.go deleted file mode 100644 index 8eb20729c2..0000000000 --- a/vendor/golang.org/x/tools/internal/gcimporter/ureader_no.go +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.18 -// +build !go1.18 - -package gcimporter - -import ( - "fmt" - "go/token" - "go/types" -) - -func UImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) { - err = fmt.Errorf("go/tools compiled with a Go version earlier than 1.18 cannot read unified IR export data") - return -} diff --git a/vendor/golang.org/x/tools/internal/gcimporter/ureader_yes.go b/vendor/golang.org/x/tools/internal/gcimporter/ureader_yes.go index b977435f62..f4edc46ab7 100644 --- a/vendor/golang.org/x/tools/internal/gcimporter/ureader_yes.go +++ b/vendor/golang.org/x/tools/internal/gcimporter/ureader_yes.go @@ -4,9 +4,6 @@ // Derived from go/internal/gcimporter/ureader.go -//go:build go1.18 -// +build go1.18 - package gcimporter import ( @@ -16,6 +13,7 @@ import ( "sort" "strings" + "golang.org/x/tools/internal/aliases" "golang.org/x/tools/internal/pkgbits" ) @@ -553,7 +551,7 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) { // If the underlying type is an interface, we need to // duplicate its methods so we can replace the receiver // parameter's type (#49906). - if iface, ok := underlying.(*types.Interface); ok && iface.NumExplicitMethods() != 0 { + if iface, ok := aliases.Unalias(underlying).(*types.Interface); ok && iface.NumExplicitMethods() != 0 { methods := make([]*types.Func, iface.NumExplicitMethods()) for i := range methods { fn := iface.ExplicitMethod(i) diff --git a/vendor/golang.org/x/tools/internal/tokeninternal/tokeninternal.go b/vendor/golang.org/x/tools/internal/tokeninternal/tokeninternal.go index 7e638ec24f..ff9437a36c 100644 --- a/vendor/golang.org/x/tools/internal/tokeninternal/tokeninternal.go +++ b/vendor/golang.org/x/tools/internal/tokeninternal/tokeninternal.go @@ -34,30 +34,16 @@ func GetLines(file *token.File) []int { lines []int _ []struct{} } - type tokenFile118 struct { - _ *token.FileSet // deleted in go1.19 - tokenFile119 - } - - type uP = unsafe.Pointer - switch unsafe.Sizeof(*file) { - case unsafe.Sizeof(tokenFile118{}): - var ptr *tokenFile118 - *(*uP)(uP(&ptr)) = uP(file) - ptr.mu.Lock() - defer ptr.mu.Unlock() - return ptr.lines - case unsafe.Sizeof(tokenFile119{}): - var ptr *tokenFile119 - *(*uP)(uP(&ptr)) = uP(file) - ptr.mu.Lock() - defer ptr.mu.Unlock() - return ptr.lines - - default: + if unsafe.Sizeof(*file) != unsafe.Sizeof(tokenFile119{}) { panic("unexpected token.File size") } + var ptr *tokenFile119 + type uP = unsafe.Pointer + *(*uP)(uP(&ptr)) = uP(file) + ptr.mu.Lock() + defer ptr.mu.Unlock() + return ptr.lines } // AddExistingFiles adds the specified files to the FileSet if they diff --git a/vendor/golang.org/x/tools/internal/typeparams/common.go b/vendor/golang.org/x/tools/internal/typeparams/common.go index cdab988531..8c3a42dc31 100644 --- a/vendor/golang.org/x/tools/internal/typeparams/common.go +++ b/vendor/golang.org/x/tools/internal/typeparams/common.go @@ -2,20 +2,10 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package typeparams contains common utilities for writing tools that interact -// with generic Go code, as introduced with Go 1.18. -// -// Many of the types and functions in this package are proxies for the new APIs -// introduced in the standard library with Go 1.18. For example, the -// typeparams.Union type is an alias for go/types.Union, and the ForTypeSpec -// function returns the value of the go/ast.TypeSpec.TypeParams field. At Go -// versions older than 1.18 these helpers are implemented as stubs, allowing -// users of this package to write code that handles generic constructs inline, -// even if the Go version being used to compile does not support generics. -// -// Additionally, this package contains common utilities for working with the -// new generic constructs, to supplement the standard library APIs. Notably, -// the StructuralTerms API computes a minimal representation of the structural +// Package typeparams contains common utilities for writing tools that +// interact with generic Go code, as introduced with Go 1.18. It +// supplements the standard library APIs. Notably, the StructuralTerms +// API computes a minimal representation of the structural // restrictions on a type parameter. // // An external version of these APIs is available in the @@ -27,6 +17,9 @@ import ( "go/ast" "go/token" "go/types" + + "golang.org/x/tools/internal/aliases" + "golang.org/x/tools/internal/typesinternal" ) // UnpackIndexExpr extracts data from AST nodes that represent index @@ -72,9 +65,9 @@ func PackIndexExpr(x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack toke } } -// IsTypeParam reports whether t is a type parameter. +// IsTypeParam reports whether t is a type parameter (or an alias of one). func IsTypeParam(t types.Type) bool { - _, ok := t.(*types.TypeParam) + _, ok := aliases.Unalias(t).(*types.TypeParam) return ok } @@ -90,13 +83,8 @@ func OriginMethod(fn *types.Func) *types.Func { if recv == nil { return fn } - base := recv.Type() - p, isPtr := base.(*types.Pointer) - if isPtr { - base = p.Elem() - } - named, isNamed := base.(*types.Named) - if !isNamed { + _, named := typesinternal.ReceiverNamed(recv) + if named == nil { // Receiver is a *types.Interface. return fn } @@ -158,6 +146,9 @@ func OriginMethod(fn *types.Func) *types.Func { // In this case, GenericAssignableTo reports that instantiations of Container // are assignable to the corresponding instantiation of Interface. func GenericAssignableTo(ctxt *types.Context, V, T types.Type) bool { + V = aliases.Unalias(V) + T = aliases.Unalias(T) + // If V and T are not both named, or do not have matching non-empty type // parameter lists, fall back on types.AssignableTo. diff --git a/vendor/golang.org/x/tools/internal/typeparams/coretype.go b/vendor/golang.org/x/tools/internal/typeparams/coretype.go index 7ea8840eab..e66e9d0f48 100644 --- a/vendor/golang.org/x/tools/internal/typeparams/coretype.go +++ b/vendor/golang.org/x/tools/internal/typeparams/coretype.go @@ -5,7 +5,10 @@ package typeparams import ( + "fmt" "go/types" + + "golang.org/x/tools/internal/aliases" ) // CoreType returns the core type of T or nil if T does not have a core type. @@ -109,7 +112,7 @@ func CoreType(T types.Type) types.Type { // _NormalTerms makes no guarantees about the order of terms, except that it // is deterministic. func _NormalTerms(typ types.Type) ([]*types.Term, error) { - switch typ := typ.(type) { + switch typ := aliases.Unalias(typ).(type) { case *types.TypeParam: return StructuralTerms(typ) case *types.Union: @@ -120,3 +123,15 @@ func _NormalTerms(typ types.Type) ([]*types.Term, error) { return []*types.Term{types.NewTerm(false, typ)}, nil } } + +// MustDeref returns the type of the variable pointed to by t. +// It panics if t's core type is not a pointer. +// +// TODO(adonovan): ideally this would live in typesinternal, but that +// creates an import cycle. Move there when we melt this package down. +func MustDeref(t types.Type) types.Type { + if ptr, ok := CoreType(t).(*types.Pointer); ok { + return ptr.Elem() + } + panic(fmt.Sprintf("%v is not a pointer", t)) +} diff --git a/vendor/golang.org/x/tools/internal/typesinternal/recv.go b/vendor/golang.org/x/tools/internal/typesinternal/recv.go new file mode 100644 index 0000000000..fea7c8b75e --- /dev/null +++ b/vendor/golang.org/x/tools/internal/typesinternal/recv.go @@ -0,0 +1,43 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package typesinternal + +import ( + "go/types" + + "golang.org/x/tools/internal/aliases" +) + +// ReceiverNamed returns the named type (if any) associated with the +// type of recv, which may be of the form N or *N, or aliases thereof. +// It also reports whether a Pointer was present. +func ReceiverNamed(recv *types.Var) (isPtr bool, named *types.Named) { + t := recv.Type() + if ptr, ok := aliases.Unalias(t).(*types.Pointer); ok { + isPtr = true + t = ptr.Elem() + } + named, _ = aliases.Unalias(t).(*types.Named) + return +} + +// Unpointer returns T given *T or an alias thereof. +// For all other types it is the identity function. +// It does not look at underlying types. +// The result may be an alias. +// +// Use this function to strip off the optional pointer on a receiver +// in a field or method selection, without losing the named type +// (which is needed to compute the method set). +// +// See also [typeparams.MustDeref], which removes one level of +// indirection from the type, regardless of named types (analogous to +// a LOAD instruction). +func Unpointer(t types.Type) types.Type { + if ptr, ok := aliases.Unalias(t).(*types.Pointer); ok { + return ptr.Elem() + } + return t +} diff --git a/vendor/golang.org/x/tools/internal/typesinternal/types_118.go b/vendor/golang.org/x/tools/internal/typesinternal/types_118.go index a42b072a67..ef7ea290c0 100644 --- a/vendor/golang.org/x/tools/internal/typesinternal/types_118.go +++ b/vendor/golang.org/x/tools/internal/typesinternal/types_118.go @@ -2,9 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.18 -// +build go1.18 - package typesinternal import ( diff --git a/vendor/golang.org/x/tools/internal/versions/features.go b/vendor/golang.org/x/tools/internal/versions/features.go new file mode 100644 index 0000000000..b53f178616 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/versions/features.go @@ -0,0 +1,43 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package versions + +// This file contains predicates for working with file versions to +// decide when a tool should consider a language feature enabled. + +// GoVersions that features in x/tools can be gated to. +const ( + Go1_18 = "go1.18" + Go1_19 = "go1.19" + Go1_20 = "go1.20" + Go1_21 = "go1.21" + Go1_22 = "go1.22" +) + +// Future is an invalid unknown Go version sometime in the future. +// Do not use directly with Compare. +const Future = "" + +// AtLeast reports whether the file version v comes after a Go release. +// +// Use this predicate to enable a behavior once a certain Go release +// has happened (and stays enabled in the future). +func AtLeast(v, release string) bool { + if v == Future { + return true // an unknown future version is always after y. + } + return Compare(Lang(v), Lang(release)) >= 0 +} + +// Before reports whether the file version v is strictly before a Go release. +// +// Use this predicate to disable a behavior once a certain Go release +// has happened (and stays enabled in the future). +func Before(v, release string) bool { + if v == Future { + return false // an unknown future version happens after y. + } + return Compare(Lang(v), Lang(release)) < 0 +} diff --git a/vendor/golang.org/x/tools/internal/versions/toolchain.go b/vendor/golang.org/x/tools/internal/versions/toolchain.go new file mode 100644 index 0000000000..377bf7a53b --- /dev/null +++ b/vendor/golang.org/x/tools/internal/versions/toolchain.go @@ -0,0 +1,14 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package versions + +// toolchain is maximum version (<1.22) that the go toolchain used +// to build the current tool is known to support. +// +// When a tool is built with >=1.22, the value of toolchain is unused. +// +// x/tools does not support building with go <1.18. So we take this +// as the minimum possible maximum. +var toolchain string = Go1_18 diff --git a/vendor/golang.org/x/tools/internal/versions/toolchain_go119.go b/vendor/golang.org/x/tools/internal/versions/toolchain_go119.go new file mode 100644 index 0000000000..f65beed9d8 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/versions/toolchain_go119.go @@ -0,0 +1,14 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.19 +// +build go1.19 + +package versions + +func init() { + if Compare(toolchain, Go1_19) < 0 { + toolchain = Go1_19 + } +} diff --git a/vendor/golang.org/x/tools/internal/versions/toolchain_go120.go b/vendor/golang.org/x/tools/internal/versions/toolchain_go120.go new file mode 100644 index 0000000000..1a9efa126c --- /dev/null +++ b/vendor/golang.org/x/tools/internal/versions/toolchain_go120.go @@ -0,0 +1,14 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.20 +// +build go1.20 + +package versions + +func init() { + if Compare(toolchain, Go1_20) < 0 { + toolchain = Go1_20 + } +} diff --git a/vendor/golang.org/x/tools/internal/versions/toolchain_go121.go b/vendor/golang.org/x/tools/internal/versions/toolchain_go121.go new file mode 100644 index 0000000000..b7ef216dfe --- /dev/null +++ b/vendor/golang.org/x/tools/internal/versions/toolchain_go121.go @@ -0,0 +1,14 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.21 +// +build go1.21 + +package versions + +func init() { + if Compare(toolchain, Go1_21) < 0 { + toolchain = Go1_21 + } +} diff --git a/vendor/golang.org/x/tools/internal/versions/types_go121.go b/vendor/golang.org/x/tools/internal/versions/types_go121.go index a7b79207ae..b4345d3349 100644 --- a/vendor/golang.org/x/tools/internal/versions/types_go121.go +++ b/vendor/golang.org/x/tools/internal/versions/types_go121.go @@ -12,9 +12,19 @@ import ( "go/types" ) -// FileVersions always reports the a file's Go version as the -// zero version at this Go version. -func FileVersions(info *types.Info, file *ast.File) string { return "" } +// FileVersion returns a language version (<=1.21) derived from runtime.Version() +// or an unknown future version. +func FileVersion(info *types.Info, file *ast.File) string { + // In x/tools built with Go <= 1.21, we do not have Info.FileVersions + // available. We use a go version derived from the toolchain used to + // compile the tool by default. + // This will be <= go1.21. We take this as the maximum version that + // this tool can support. + // + // There are no features currently in x/tools that need to tell fine grained + // differences for versions <1.22. + return toolchain +} -// InitFileVersions is a noop at this Go version. +// InitFileVersions is a noop when compiled with this Go version. func InitFileVersions(*types.Info) {} diff --git a/vendor/golang.org/x/tools/internal/versions/types_go122.go b/vendor/golang.org/x/tools/internal/versions/types_go122.go index 7b9ba89a82..e8180632a5 100644 --- a/vendor/golang.org/x/tools/internal/versions/types_go122.go +++ b/vendor/golang.org/x/tools/internal/versions/types_go122.go @@ -12,10 +12,27 @@ import ( "go/types" ) -// FileVersions maps a file to the file's semantic Go version. -// The reported version is the zero version if a version cannot be determined. -func FileVersions(info *types.Info, file *ast.File) string { - return info.FileVersions[file] +// FileVersions returns a file's Go version. +// The reported version is an unknown Future version if a +// version cannot be determined. +func FileVersion(info *types.Info, file *ast.File) string { + // In tools built with Go >= 1.22, the Go version of a file + // follow a cascades of sources: + // 1) types.Info.FileVersion, which follows the cascade: + // 1.a) file version (ast.File.GoVersion), + // 1.b) the package version (types.Config.GoVersion), or + // 2) is some unknown Future version. + // + // File versions require a valid package version to be provided to types + // in Config.GoVersion. Config.GoVersion is either from the package's module + // or the toolchain (go run). This value should be provided by go/packages + // or unitchecker.Config.GoVersion. + if v := info.FileVersions[file]; IsValid(v) { + return v + } + // Note: we could instead return runtime.Version() [if valid]. + // This would act as a max version on what a tool can support. + return Future } // InitFileVersions initializes info to record Go versions for Go files. diff --git a/vendor/golang.org/x/tools/internal/versions/versions.go b/vendor/golang.org/x/tools/internal/versions/versions.go index e16f6c33a5..8d1f7453db 100644 --- a/vendor/golang.org/x/tools/internal/versions/versions.go +++ b/vendor/golang.org/x/tools/internal/versions/versions.go @@ -4,6 +4,10 @@ package versions +import ( + "strings" +) + // Note: If we use build tags to use go/versions when go >=1.22, // we run into go.dev/issue/53737. Under some operations users would see an // import of "go/versions" even if they would not compile the file. @@ -45,6 +49,7 @@ func IsValid(x string) bool { return isValid(stripGo(x)) } // stripGo converts from a "go1.21" version to a "1.21" version. // If v does not start with "go", stripGo returns the empty string (a known invalid version). func stripGo(v string) string { + v, _, _ = strings.Cut(v, "-") // strip -bigcorp suffix. if len(v) < 2 || v[:2] != "go" { return "" } diff --git a/vendor/google.golang.org/api/internal/cba.go b/vendor/google.golang.org/api/internal/cba.go index 829383f55b..fbf4ef1c6e 100644 --- a/vendor/google.golang.org/api/internal/cba.go +++ b/vendor/google.golang.org/api/internal/cba.go @@ -35,6 +35,7 @@ package internal import ( "context" "crypto/tls" + "errors" "net" "net/url" "os" @@ -53,6 +54,12 @@ const ( // Experimental: if true, the code will try MTLS with S2A as the default for transport security. Default value is false. googleAPIUseS2AEnv = "EXPERIMENTAL_GOOGLE_API_USE_S2A" + + universeDomainPlaceholder = "UNIVERSE_DOMAIN" +) + +var ( + errUniverseNotSupportedMTLS = errors.New("mTLS is not supported in any universe other than googleapis.com") ) // getClientCertificateSourceAndEndpoint is a convenience function that invokes @@ -67,6 +74,14 @@ func getClientCertificateSourceAndEndpoint(settings *DialSettings) (cert.Source, if err != nil { return nil, "", err } + // TODO(chrisdsmith): https://github.com/googleapis/google-api-go-client/issues/2359 + if settings.Endpoint == "" && !settings.IsUniverseDomainGDU() && settings.DefaultEndpointTemplate != "" { + // TODO(chrisdsmith): https://github.com/googleapis/google-api-go-client/issues/2359 + // if settings.DefaultEndpointTemplate == "" { + // return nil, "", errors.New("internaloption.WithDefaultEndpointTemplate is required if option.WithUniverseDomain is not googleapis.com") + // } + endpoint = resolvedDefaultEndpoint(settings) + } return clientCertSource, endpoint, nil } @@ -80,9 +95,7 @@ type transportConfig struct { func getTransportConfig(settings *DialSettings) (*transportConfig, error) { clientCertSource, endpoint, err := getClientCertificateSourceAndEndpoint(settings) if err != nil { - return &transportConfig{ - clientCertSource: nil, endpoint: "", s2aAddress: "", s2aMTLSEndpoint: "", - }, err + return nil, err } defaultTransportConfig := transportConfig{ clientCertSource: clientCertSource, @@ -94,12 +107,10 @@ func getTransportConfig(settings *DialSettings) (*transportConfig, error) { if !shouldUseS2A(clientCertSource, settings) { return &defaultTransportConfig, nil } - - s2aMTLSEndpoint := settings.DefaultMTLSEndpoint - // If there is endpoint override, honor it. - if settings.Endpoint != "" { - s2aMTLSEndpoint = endpoint + if !settings.IsUniverseDomainGDU() { + return nil, errUniverseNotSupportedMTLS } + s2aAddress := GetS2AAddress() if s2aAddress == "" { return &defaultTransportConfig, nil @@ -108,7 +119,7 @@ func getTransportConfig(settings *DialSettings) (*transportConfig, error) { clientCertSource: clientCertSource, endpoint: endpoint, s2aAddress: s2aAddress, - s2aMTLSEndpoint: s2aMTLSEndpoint, + s2aMTLSEndpoint: settings.DefaultMTLSEndpoint, }, nil } @@ -153,24 +164,41 @@ func isClientCertificateEnabled() bool { // WithDefaultEndpoint("https://foo.com/bar/baz") will return "https://myhost:8080/bar/baz" func getEndpoint(settings *DialSettings, clientCertSource cert.Source) (string, error) { if settings.Endpoint == "" { - mtlsMode := getMTLSMode() - if mtlsMode == mTLSModeAlways || (clientCertSource != nil && mtlsMode == mTLSModeAuto) { + if isMTLS(clientCertSource) { + if !settings.IsUniverseDomainGDU() { + return "", errUniverseNotSupportedMTLS + } return settings.DefaultMTLSEndpoint, nil } - return settings.DefaultEndpoint, nil + return resolvedDefaultEndpoint(settings), nil } if strings.Contains(settings.Endpoint, "://") { // User passed in a full URL path, use it verbatim. return settings.Endpoint, nil } - if settings.DefaultEndpoint == "" { + if resolvedDefaultEndpoint(settings) == "" { // If DefaultEndpoint is not configured, use the user provided endpoint verbatim. // This allows a naked "host[:port]" URL to be used with GRPC Direct Path. return settings.Endpoint, nil } // Assume user-provided endpoint is host[:port], merge it with the default endpoint. - return mergeEndpoints(settings.DefaultEndpoint, settings.Endpoint) + return mergeEndpoints(resolvedDefaultEndpoint(settings), settings.Endpoint) +} + +func isMTLS(clientCertSource cert.Source) bool { + mtlsMode := getMTLSMode() + return mtlsMode == mTLSModeAlways || (clientCertSource != nil && mtlsMode == mTLSModeAuto) +} + +// resolvedDefaultEndpoint returns the DefaultEndpointTemplate merged with the +// Universe Domain if the DefaultEndpointTemplate is set, otherwise returns the +// deprecated DefaultEndpoint value. +func resolvedDefaultEndpoint(settings *DialSettings) string { + if settings.DefaultEndpointTemplate == "" { + return settings.DefaultEndpoint + } + return strings.Replace(settings.DefaultEndpointTemplate, universeDomainPlaceholder, settings.GetUniverseDomain(), 1) } func getMTLSMode() string { @@ -274,25 +302,15 @@ func shouldUseS2A(clientCertSource cert.Source, settings *DialSettings) bool { if !isGoogleS2AEnabled() { return false } - // If DefaultMTLSEndpoint is not set and no endpoint override, skip S2A. - if settings.DefaultMTLSEndpoint == "" && settings.Endpoint == "" { - return false - } - // If MTLS is not enabled for this endpoint, skip S2A. - if !mtlsEndpointEnabledForS2A() { + // If DefaultMTLSEndpoint is not set or has endpoint override, skip S2A. + if settings.DefaultMTLSEndpoint == "" || settings.Endpoint != "" { return false } // If custom HTTP client is provided, skip S2A. if settings.HTTPClient != nil { return false } - return true -} - -// mtlsEndpointEnabledForS2A checks if the endpoint is indeed MTLS-enabled, so that we can use S2A for MTLS connection. -var mtlsEndpointEnabledForS2A = func() bool { - // TODO(xmenxk): determine this via discovery config. - return true + return !settings.EnableDirectPath && !settings.EnableDirectPathXds } func isGoogleS2AEnabled() bool { diff --git a/vendor/google.golang.org/api/internal/creds.go b/vendor/google.golang.org/api/internal/creds.go index 05165f333b..b648930985 100644 --- a/vendor/google.golang.org/api/internal/creds.go +++ b/vendor/google.golang.org/api/internal/creds.go @@ -16,6 +16,7 @@ import ( "time" "golang.org/x/oauth2" + "google.golang.org/api/internal/cert" "google.golang.org/api/internal/impersonate" "golang.org/x/oauth2/google" @@ -90,11 +91,11 @@ func credentialsFromJSON(ctx context.Context, data []byte, ds *DialSettings) (*g // Determine configurations for the OAuth2 transport, which is separate from the API transport. // The OAuth2 transport and endpoint will be configured for mTLS if applicable. - clientCertSource, oauth2Endpoint, err := getClientCertificateSourceAndEndpoint(oauth2DialSettings(ds)) + clientCertSource, err := getClientCertificateSource(ds) if err != nil { return nil, err } - params.TokenURL = oauth2Endpoint + params.TokenURL = oAuth2Endpoint(clientCertSource) if clientCertSource != nil { tlsConfig := &tls.Config{ GetClientCertificate: clientCertSource, @@ -124,22 +125,37 @@ func credentialsFromJSON(ctx context.Context, data []byte, ds *DialSettings) (*g return cred, err } +func oAuth2Endpoint(clientCertSource cert.Source) string { + if isMTLS(clientCertSource) { + return google.MTLSTokenURL + } + return google.Endpoint.TokenURL +} + func isSelfSignedJWTFlow(data []byte, ds *DialSettings) (bool, error) { - if (ds.EnableJwtWithScope || ds.HasCustomAudience()) && - ds.ImpersonationConfig == nil { - // Check if JSON is a service account and if so create a self-signed JWT. - var f struct { - Type string `json:"type"` - // The rest JSON fields are omitted because they are not used. - } - if err := json.Unmarshal(data, &f); err != nil { - return false, err - } - return f.Type == serviceAccountKey, nil + // For non-GDU universe domains, token exchange is impossible and services + // must support self-signed JWTs with scopes. + if !ds.IsUniverseDomainGDU() { + return typeServiceAccount(data) + } + if (ds.EnableJwtWithScope || ds.HasCustomAudience()) && ds.ImpersonationConfig == nil { + return typeServiceAccount(data) } return false, nil } +// typeServiceAccount checks if JSON data is for a service account. +func typeServiceAccount(data []byte) (bool, error) { + var f struct { + Type string `json:"type"` + // The remaining JSON fields are omitted because they are not used. + } + if err := json.Unmarshal(data, &f); err != nil { + return false, err + } + return f.Type == serviceAccountKey, nil +} + func selfSignedJWTTokenSource(data []byte, ds *DialSettings) (oauth2.TokenSource, error) { if len(ds.GetScopes()) > 0 && !ds.HasCustomAudience() { // Scopes are preferred in self-signed JWT unless the scope is not available @@ -188,15 +204,6 @@ func impersonateCredentials(ctx context.Context, creds *google.Credentials, ds * }, nil } -// oauth2DialSettings returns the settings to be used by the OAuth2 transport, which is separate from the API transport. -func oauth2DialSettings(ds *DialSettings) *DialSettings { - var ods DialSettings - ods.DefaultEndpoint = google.Endpoint.TokenURL - ods.DefaultMTLSEndpoint = google.MTLSTokenURL - ods.ClientCertSource = ds.ClientCertSource - return &ods -} - // customHTTPClient constructs an HTTPClient using the provided tlsConfig, to support mTLS. func customHTTPClient(tlsConfig *tls.Config) *http.Client { trans := baseTransport() @@ -219,3 +226,14 @@ func baseTransport() *http.Transport { ExpectContinueTimeout: 1 * time.Second, } } + +// ErrUniverseNotMatch composes an error string from the provided universe +// domain sources (DialSettings and Credentials, respectively). +func ErrUniverseNotMatch(settingsUD, credsUD string) error { + return fmt.Errorf( + "the configured universe domain (%q) does not match the universe "+ + "domain found in the credentials (%q). If you haven't configured "+ + "WithUniverseDomain explicitly, \"googleapis.com\" is the default", + settingsUD, + credsUD) +} diff --git a/vendor/google.golang.org/api/internal/settings.go b/vendor/google.golang.org/api/internal/settings.go index 285e6e04d3..6b709da707 100644 --- a/vendor/google.golang.org/api/internal/settings.go +++ b/vendor/google.golang.org/api/internal/settings.go @@ -11,6 +11,7 @@ import ( "net/http" "os" "strconv" + "time" "golang.org/x/oauth2" "golang.org/x/oauth2/google" @@ -19,7 +20,8 @@ import ( ) const ( - newAuthLibEnVar = "GOOGLE_API_GO_EXPERIMENTAL_USE_NEW_AUTH_LIB" + newAuthLibEnVar = "GOOGLE_API_GO_EXPERIMENTAL_USE_NEW_AUTH_LIB" + universeDomainDefault = "googleapis.com" ) // DialSettings holds information needed to establish a connection with a @@ -87,6 +89,7 @@ func (ds *DialSettings) HasCustomAudience() bool { return len(ds.Audiences) > 0 } +// IsNewAuthLibraryEnabled returns true if the new auth library should be used. func (ds *DialSettings) IsNewAuthLibraryEnabled() bool { if ds.EnableNewAuthLibrary { return true @@ -161,3 +164,68 @@ func (ds *DialSettings) Validate() error { } return nil } + +// GetDefaultUniverseDomain returns the default service domain for a given Cloud +// universe, as configured with internaloption.WithDefaultUniverseDomain. +// The default value is "googleapis.com". +func (ds *DialSettings) GetDefaultUniverseDomain() string { + if ds.DefaultUniverseDomain == "" { + return universeDomainDefault + } + return ds.DefaultUniverseDomain +} + +// GetUniverseDomain returns the default service domain for a given Cloud +// universe, as configured with option.WithUniverseDomain. +// The default value is the value of GetDefaultUniverseDomain, as configured +// with internaloption.WithDefaultUniverseDomain. +func (ds *DialSettings) GetUniverseDomain() string { + if ds.UniverseDomain == "" { + return ds.GetDefaultUniverseDomain() + } + return ds.UniverseDomain +} + +// IsUniverseDomainGDU returns true if the universe domain is the default Google +// universe. +func (ds *DialSettings) IsUniverseDomainGDU() bool { + return ds.GetUniverseDomain() == ds.GetDefaultUniverseDomain() +} + +// GetUniverseDomain returns the default service domain for a given Cloud +// universe, from google.Credentials, for comparison with the value returned by +// (*DialSettings).GetUniverseDomain. This wrapper function should be removed +// to close [TODO(chrisdsmith): issue link here]. See details below. +func GetUniverseDomain(creds *google.Credentials) (string, error) { + timer := time.NewTimer(time.Second) + defer timer.Stop() + errors := make(chan error) + results := make(chan string) + + go func() { + result, err := creds.GetUniverseDomain() + if err != nil { + errors <- err + return + } + results <- result + }() + + select { + case err := <-errors: + // An error that is returned before the timer expires is legitimate. + return "", err + case res := <-results: + return res, nil + case <-timer.C: // Timer is expired. + // If err or res was not returned, it means that creds.GetUniverseDomain() + // did not complete in 1s. Assume that MDS is likely never responding to + // the endpoint and will timeout. This is the source of issues such as + // https://github.com/googleapis/google-cloud-go/issues/9350. + // Temporarily (2024-02-02) return the GDU domain. Restore the original + // calls to creds.GetUniverseDomain() in grpc/dial.go and http/dial.go + // and remove this method to close + // https://github.com/googleapis/google-api-go-client/issues/2399. + return universeDomainDefault, nil + } +} diff --git a/vendor/google.golang.org/api/internal/version.go b/vendor/google.golang.org/api/internal/version.go index 88c15fa93e..a9458b00f8 100644 --- a/vendor/google.golang.org/api/internal/version.go +++ b/vendor/google.golang.org/api/internal/version.go @@ -5,4 +5,4 @@ package internal // Version is the current tagged release of the library. -const Version = "0.157.0" +const Version = "0.168.0" diff --git a/vendor/google.golang.org/api/storage/v1/storage-api.json b/vendor/google.golang.org/api/storage/v1/storage-api.json index 2500369220..cb34638d2b 100644 --- a/vendor/google.golang.org/api/storage/v1/storage-api.json +++ b/vendor/google.golang.org/api/storage/v1/storage-api.json @@ -33,7 +33,7 @@ "location": "me-central2" } ], - "etag": "\"3136323232353032373039383637313835303036\"", + "etag": "\"3135323132313733303039343736303631393739\"", "icons": { "x16": "https://www.google.com/images/icons/product/cloud_storage-16.png", "x32": "https://www.google.com/images/icons/product/cloud_storage-32.png" @@ -4040,7 +4040,7 @@ } } }, - "revision": "20240105", + "revision": "20240209", "rootUrl": "https://storage.googleapis.com/", "schemas": { "AnywhereCache": { @@ -4853,6 +4853,11 @@ "description": "The name of the bucket containing this folder.", "type": "string" }, + "createTime": { + "description": "The creation time of the folder in RFC 3339 format.", + "format": "date-time", + "type": "string" + }, "id": { "description": "The ID of the folder, including the bucket name, folder name.", "type": "string" @@ -4862,14 +4867,6 @@ "description": "The kind of item this is. For folders, this is always storage#folder.", "type": "string" }, - "metadata": { - "additionalProperties": { - "description": "An individual metadata entry.", - "type": "string" - }, - "description": "User-provided metadata, in key/value pairs.", - "type": "object" - }, "metageneration": { "description": "The version of the metadata for this folder. Used for preconditions and for detecting changes in metadata.", "format": "int64", @@ -4893,12 +4890,7 @@ "description": "The link to this folder.", "type": "string" }, - "timeCreated": { - "description": "The creation time of the folder in RFC 3339 format.", - "format": "date-time", - "type": "string" - }, - "updated": { + "updateTime": { "description": "The modification time of the folder metadata in RFC 3339 format.", "format": "date-time", "type": "string" diff --git a/vendor/google.golang.org/api/storage/v1/storage-gen.go b/vendor/google.golang.org/api/storage/v1/storage-gen.go index c34ca98c4d..6f01795faa 100644 --- a/vendor/google.golang.org/api/storage/v1/storage-gen.go +++ b/vendor/google.golang.org/api/storage/v1/storage-gen.go @@ -1853,6 +1853,9 @@ type Folder struct { // Bucket: The name of the bucket containing this folder. Bucket string `json:"bucket,omitempty"` + // CreateTime: The creation time of the folder in RFC 3339 format. + CreateTime string `json:"createTime,omitempty"` + // Id: The ID of the folder, including the bucket name, folder name. Id string `json:"id,omitempty"` @@ -1860,9 +1863,6 @@ type Folder struct { // storage#folder. Kind string `json:"kind,omitempty"` - // Metadata: User-provided metadata, in key/value pairs. - Metadata map[string]string `json:"metadata,omitempty"` - // Metageneration: The version of the metadata for this folder. Used for // preconditions and for detecting changes in metadata. Metageneration int64 `json:"metageneration,omitempty,string"` @@ -1879,12 +1879,9 @@ type Folder struct { // SelfLink: The link to this folder. SelfLink string `json:"selfLink,omitempty"` - // TimeCreated: The creation time of the folder in RFC 3339 format. - TimeCreated string `json:"timeCreated,omitempty"` - - // Updated: The modification time of the folder metadata in RFC 3339 + // UpdateTime: The modification time of the folder metadata in RFC 3339 // format. - Updated string `json:"updated,omitempty"` + UpdateTime string `json:"updateTime,omitempty"` // ServerResponse contains the HTTP response code and headers from the // server. diff --git a/vendor/google.golang.org/api/transport/grpc/dial.go b/vendor/google.golang.org/api/transport/grpc/dial.go index 10830f0164..bfc55594ef 100644 --- a/vendor/google.golang.org/api/transport/grpc/dial.go +++ b/vendor/google.golang.org/api/transport/grpc/dial.go @@ -177,6 +177,17 @@ func dial(ctx context.Context, insecure bool, o *internal.DialSettings) (*grpc.C if err != nil { return nil, err } + if o.TokenSource == nil { + // We only validate non-tokensource creds, as TokenSource-based credentials + // don't propagate universe. + credsUniverseDomain, err := internal.GetUniverseDomain(creds) + if err != nil { + return nil, err + } + if o.GetUniverseDomain() != credsUniverseDomain { + return nil, internal.ErrUniverseNotMatch(o.GetUniverseDomain(), credsUniverseDomain) + } + } grpcOpts = append(grpcOpts, grpc.WithPerRPCCredentials(grpcTokenSource{ TokenSource: oauth.TokenSource{TokenSource: creds.TokenSource}, quotaProject: internal.GetQuotaProject(creds, o.QuotaProject), diff --git a/vendor/google.golang.org/api/transport/http/dial.go b/vendor/google.golang.org/api/transport/http/dial.go index 7e322a17c6..c4f5e0b138 100644 --- a/vendor/google.golang.org/api/transport/http/dial.go +++ b/vendor/google.golang.org/api/transport/http/dial.go @@ -88,6 +88,17 @@ func newTransport(ctx context.Context, base http.RoundTripper, settings *interna if err != nil { return nil, err } + if settings.TokenSource == nil { + // We only validate non-tokensource creds, as TokenSource-based credentials + // don't propagate universe. + credsUniverseDomain, err := internal.GetUniverseDomain(creds) + if err != nil { + return nil, err + } + if settings.GetUniverseDomain() != credsUniverseDomain { + return nil, internal.ErrUniverseNotMatch(settings.GetUniverseDomain(), credsUniverseDomain) + } + } paramTransport.quotaProject = internal.GetQuotaProject(creds, settings.QuotaProject) ts := creds.TokenSource if settings.ImpersonationConfig == nil && settings.TokenSource != nil { diff --git a/vendor/google.golang.org/genproto/googleapis/api/annotations/client.pb.go b/vendor/google.golang.org/genproto/googleapis/api/annotations/client.pb.go index 83774fbcbe..d5dccb9337 100644 --- a/vendor/google.golang.org/genproto/googleapis/api/annotations/client.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/api/annotations/client.pb.go @@ -15,7 +15,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0 -// protoc v3.21.12 +// protoc v4.24.4 // source: google/api/client.proto package annotations @@ -1033,6 +1033,18 @@ type MethodSettings struct { // total_poll_timeout: // seconds: 54000 # 90 minutes LongRunning *MethodSettings_LongRunning `protobuf:"bytes,2,opt,name=long_running,json=longRunning,proto3" json:"long_running,omitempty"` + // List of top-level fields of the request message, that should be + // automatically populated by the client libraries based on their + // (google.api.field_info).format. Currently supported format: UUID4. + // + // Example of a YAML configuration: + // + // publishing: + // method_settings: + // - selector: google.example.v1.ExampleService.CreateExample + // auto_populated_fields: + // - request_id + AutoPopulatedFields []string `protobuf:"bytes,3,rep,name=auto_populated_fields,json=autoPopulatedFields,proto3" json:"auto_populated_fields,omitempty"` } func (x *MethodSettings) Reset() { @@ -1081,6 +1093,13 @@ func (x *MethodSettings) GetLongRunning() *MethodSettings_LongRunning { return nil } +func (x *MethodSettings) GetAutoPopulatedFields() []string { + if x != nil { + return x.AutoPopulatedFields + } + return nil +} + // Describes settings to use when generating API methods that use the // long-running operation pattern. // All default values below are from those used in the client library @@ -1452,69 +1471,73 @@ var file_google_api_client_proto_rawDesc = []byte{ 0x6d, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x06, 0x63, - 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x22, 0x8e, 0x03, 0x0a, 0x0e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, + 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x22, 0xc2, 0x03, 0x0a, 0x0e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x49, 0x0a, 0x0c, 0x6c, 0x6f, 0x6e, 0x67, 0x5f, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x4c, 0x6f, 0x6e, 0x67, 0x52, 0x75, 0x6e, 0x6e, 0x69, - 0x6e, 0x67, 0x52, 0x0b, 0x6c, 0x6f, 0x6e, 0x67, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x1a, - 0x94, 0x02, 0x0a, 0x0b, 0x4c, 0x6f, 0x6e, 0x67, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x12, - 0x47, 0x0a, 0x12, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x70, 0x6f, 0x6c, 0x6c, 0x5f, - 0x64, 0x65, 0x6c, 0x61, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x50, - 0x6f, 0x6c, 0x6c, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x32, 0x0a, 0x15, 0x70, 0x6f, 0x6c, 0x6c, - 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, 0x65, - 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x13, 0x70, 0x6f, 0x6c, 0x6c, 0x44, 0x65, 0x6c, - 0x61, 0x79, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x12, 0x3f, 0x0a, 0x0e, - 0x6d, 0x61, 0x78, 0x5f, 0x70, 0x6f, 0x6c, 0x6c, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x0c, 0x6d, 0x61, 0x78, 0x50, 0x6f, 0x6c, 0x6c, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x47, 0x0a, - 0x12, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x70, 0x6f, 0x6c, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, - 0x6f, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x50, 0x6f, 0x6c, 0x6c, 0x54, - 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x2a, 0xa3, 0x01, 0x0a, 0x19, 0x43, 0x6c, 0x69, 0x65, 0x6e, - 0x74, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2b, 0x0a, 0x27, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x5f, 0x4c, - 0x49, 0x42, 0x52, 0x41, 0x52, 0x59, 0x5f, 0x4f, 0x52, 0x47, 0x41, 0x4e, 0x49, 0x5a, 0x41, 0x54, - 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, - 0x00, 0x12, 0x09, 0x0a, 0x05, 0x43, 0x4c, 0x4f, 0x55, 0x44, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, - 0x41, 0x44, 0x53, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x50, 0x48, 0x4f, 0x54, 0x4f, 0x53, 0x10, - 0x03, 0x12, 0x0f, 0x0a, 0x0b, 0x53, 0x54, 0x52, 0x45, 0x45, 0x54, 0x5f, 0x56, 0x49, 0x45, 0x57, - 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x48, 0x4f, 0x50, 0x50, 0x49, 0x4e, 0x47, 0x10, 0x05, - 0x12, 0x07, 0x0a, 0x03, 0x47, 0x45, 0x4f, 0x10, 0x06, 0x12, 0x11, 0x0a, 0x0d, 0x47, 0x45, 0x4e, - 0x45, 0x52, 0x41, 0x54, 0x49, 0x56, 0x45, 0x5f, 0x41, 0x49, 0x10, 0x07, 0x2a, 0x67, 0x0a, 0x18, - 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x44, 0x65, 0x73, - 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x26, 0x43, 0x4c, 0x49, 0x45, - 0x4e, 0x54, 0x5f, 0x4c, 0x49, 0x42, 0x52, 0x41, 0x52, 0x59, 0x5f, 0x44, 0x45, 0x53, 0x54, 0x49, - 0x4e, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, - 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x47, 0x49, 0x54, 0x48, 0x55, 0x42, 0x10, 0x0a, - 0x12, 0x13, 0x0a, 0x0f, 0x50, 0x41, 0x43, 0x4b, 0x41, 0x47, 0x45, 0x5f, 0x4d, 0x41, 0x4e, 0x41, - 0x47, 0x45, 0x52, 0x10, 0x14, 0x3a, 0x4a, 0x0a, 0x10, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68, - 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x9b, 0x08, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x0f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x3a, 0x43, 0x0a, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x68, 0x6f, 0x73, - 0x74, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x18, 0x99, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x66, 0x61, 0x75, - 0x6c, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x43, 0x0a, 0x0c, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x5f, - 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x9a, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, - 0x6f, 0x61, 0x75, 0x74, 0x68, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x42, 0x69, 0x0a, 0x0e, 0x63, - 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x42, 0x0b, 0x43, - 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x41, 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, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x3b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0xa2, - 0x02, 0x04, 0x47, 0x41, 0x50, 0x49, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6e, 0x67, 0x52, 0x0b, 0x6c, 0x6f, 0x6e, 0x67, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x12, + 0x32, 0x0a, 0x15, 0x61, 0x75, 0x74, 0x6f, 0x5f, 0x70, 0x6f, 0x70, 0x75, 0x6c, 0x61, 0x74, 0x65, + 0x64, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x13, + 0x61, 0x75, 0x74, 0x6f, 0x50, 0x6f, 0x70, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x46, 0x69, 0x65, + 0x6c, 0x64, 0x73, 0x1a, 0x94, 0x02, 0x0a, 0x0b, 0x4c, 0x6f, 0x6e, 0x67, 0x52, 0x75, 0x6e, 0x6e, + 0x69, 0x6e, 0x67, 0x12, 0x47, 0x0a, 0x12, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x70, + 0x6f, 0x6c, 0x6c, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x69, 0x6e, 0x69, 0x74, + 0x69, 0x61, 0x6c, 0x50, 0x6f, 0x6c, 0x6c, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x32, 0x0a, 0x15, + 0x70, 0x6f, 0x6c, 0x6c, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, + 0x70, 0x6c, 0x69, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x13, 0x70, 0x6f, 0x6c, + 0x6c, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, 0x65, 0x72, + 0x12, 0x3f, 0x0a, 0x0e, 0x6d, 0x61, 0x78, 0x5f, 0x70, 0x6f, 0x6c, 0x6c, 0x5f, 0x64, 0x65, 0x6c, + 0x61, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x6d, 0x61, 0x78, 0x50, 0x6f, 0x6c, 0x6c, 0x44, 0x65, 0x6c, 0x61, + 0x79, 0x12, 0x47, 0x0a, 0x12, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x70, 0x6f, 0x6c, 0x6c, 0x5f, + 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x50, + 0x6f, 0x6c, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x2a, 0xa3, 0x01, 0x0a, 0x19, 0x43, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x4f, 0x72, 0x67, 0x61, + 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2b, 0x0a, 0x27, 0x43, 0x4c, 0x49, 0x45, + 0x4e, 0x54, 0x5f, 0x4c, 0x49, 0x42, 0x52, 0x41, 0x52, 0x59, 0x5f, 0x4f, 0x52, 0x47, 0x41, 0x4e, + 0x49, 0x5a, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, + 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x43, 0x4c, 0x4f, 0x55, 0x44, 0x10, 0x01, + 0x12, 0x07, 0x0a, 0x03, 0x41, 0x44, 0x53, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x50, 0x48, 0x4f, + 0x54, 0x4f, 0x53, 0x10, 0x03, 0x12, 0x0f, 0x0a, 0x0b, 0x53, 0x54, 0x52, 0x45, 0x45, 0x54, 0x5f, + 0x56, 0x49, 0x45, 0x57, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x48, 0x4f, 0x50, 0x50, 0x49, + 0x4e, 0x47, 0x10, 0x05, 0x12, 0x07, 0x0a, 0x03, 0x47, 0x45, 0x4f, 0x10, 0x06, 0x12, 0x11, 0x0a, + 0x0d, 0x47, 0x45, 0x4e, 0x45, 0x52, 0x41, 0x54, 0x49, 0x56, 0x45, 0x5f, 0x41, 0x49, 0x10, 0x07, + 0x2a, 0x67, 0x0a, 0x18, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, + 0x79, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x26, + 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x5f, 0x4c, 0x49, 0x42, 0x52, 0x41, 0x52, 0x59, 0x5f, 0x44, + 0x45, 0x53, 0x54, 0x49, 0x4e, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, + 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x47, 0x49, 0x54, 0x48, + 0x55, 0x42, 0x10, 0x0a, 0x12, 0x13, 0x0a, 0x0f, 0x50, 0x41, 0x43, 0x4b, 0x41, 0x47, 0x45, 0x5f, + 0x4d, 0x41, 0x4e, 0x41, 0x47, 0x45, 0x52, 0x10, 0x14, 0x3a, 0x4a, 0x0a, 0x10, 0x6d, 0x65, 0x74, + 0x68, 0x6f, 0x64, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x1e, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x9b, 0x08, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x53, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x3a, 0x43, 0x0a, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, + 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x99, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, + 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x3a, 0x43, 0x0a, 0x0c, 0x6f, 0x61, + 0x75, 0x74, 0x68, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x9a, 0x08, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x42, + 0x69, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, + 0x69, 0x42, 0x0b, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, + 0x5a, 0x41, 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, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0xa2, 0x02, 0x04, 0x47, 0x41, 0x50, 0x49, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( diff --git a/vendor/google.golang.org/genproto/googleapis/api/annotations/field_behavior.pb.go b/vendor/google.golang.org/genproto/googleapis/api/annotations/field_behavior.pb.go index 6ce01ac9a6..312d7eb49a 100644 --- a/vendor/google.golang.org/genproto/googleapis/api/annotations/field_behavior.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/api/annotations/field_behavior.pb.go @@ -15,7 +15,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0 -// protoc v3.21.12 +// protoc v4.24.4 // source: google/api/field_behavior.proto package annotations @@ -195,21 +195,21 @@ var file_google_api_field_behavior_proto_rawDesc = []byte{ 0x0e, 0x55, 0x4e, 0x4f, 0x52, 0x44, 0x45, 0x52, 0x45, 0x44, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x10, 0x06, 0x12, 0x15, 0x0a, 0x11, 0x4e, 0x4f, 0x4e, 0x5f, 0x45, 0x4d, 0x50, 0x54, 0x59, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x07, 0x12, 0x0e, 0x0a, 0x0a, 0x49, 0x44, 0x45, 0x4e, - 0x54, 0x49, 0x46, 0x49, 0x45, 0x52, 0x10, 0x08, 0x3a, 0x60, 0x0a, 0x0e, 0x66, 0x69, 0x65, 0x6c, + 0x54, 0x49, 0x46, 0x49, 0x45, 0x52, 0x10, 0x08, 0x3a, 0x64, 0x0a, 0x0e, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x12, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x9c, 0x08, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x46, 0x69, - 0x65, 0x6c, 0x64, 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x52, 0x0d, 0x66, 0x69, 0x65, - 0x6c, 0x64, 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x42, 0x70, 0x0a, 0x0e, 0x63, 0x6f, - 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x42, 0x12, 0x46, 0x69, - 0x65, 0x6c, 0x64, 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x50, 0x01, 0x5a, 0x41, 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, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, - 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0xa2, 0x02, 0x04, 0x47, 0x41, 0x50, 0x49, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x6c, 0x64, 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x42, 0x02, 0x10, 0x00, 0x52, + 0x0d, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x42, 0x70, + 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, + 0x42, 0x12, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x42, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x50, + 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x41, 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, 0x61, 0x70, + 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3b, 0x61, 0x6e, + 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0xa2, 0x02, 0x04, 0x47, 0x41, 0x50, 0x49, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/vendor/google.golang.org/genproto/googleapis/api/tidyfix.go b/vendor/google.golang.org/genproto/googleapis/api/tidyfix.go deleted file mode 100644 index 1d3f1b5b7e..0000000000 --- a/vendor/google.golang.org/genproto/googleapis/api/tidyfix.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2023 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// This file, and the {{.RootMod}} import, won't actually become part of -// the resultant binary. -//go:build modhack -// +build modhack - -package api - -// Necessary for safely adding multi-module repo. See: https://github.com/golang/go/wiki/Modules#is-it-possible-to-add-a-module-to-a-multi-module-repository -import _ "google.golang.org/genproto/internal" diff --git a/vendor/google.golang.org/genproto/internal/doc.go b/vendor/google.golang.org/genproto/internal/doc.go deleted file mode 100644 index 90e89b4aa3..0000000000 --- a/vendor/google.golang.org/genproto/internal/doc.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2023 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// This file makes internal an importable go package -// for use with backreferences from submodules. -package internal diff --git a/vendor/google.golang.org/grpc/balancer/grpclb/grpc_lb_v1/load_balancer.pb.go b/vendor/google.golang.org/grpc/balancer/grpclb/grpc_lb_v1/load_balancer.pb.go index f354530289..32989b3abb 100644 --- a/vendor/google.golang.org/grpc/balancer/grpclb/grpc_lb_v1/load_balancer.pb.go +++ b/vendor/google.golang.org/grpc/balancer/grpclb/grpc_lb_v1/load_balancer.pb.go @@ -19,8 +19,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.22.0 +// protoc-gen-go v1.32.0 +// protoc v4.25.2 // source: grpc/lb/v1/load_balancer.proto package grpc_lb_v1 diff --git a/vendor/google.golang.org/grpc/balancer/grpclb/grpc_lb_v1/load_balancer_grpc.pb.go b/vendor/google.golang.org/grpc/balancer/grpclb/grpc_lb_v1/load_balancer_grpc.pb.go index 00d0954b38..d8ec6539d2 100644 --- a/vendor/google.golang.org/grpc/balancer/grpclb/grpc_lb_v1/load_balancer_grpc.pb.go +++ b/vendor/google.golang.org/grpc/balancer/grpclb/grpc_lb_v1/load_balancer_grpc.pb.go @@ -20,7 +20,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.3.0 -// - protoc v4.22.0 +// - protoc v4.25.2 // source: grpc/lb/v1/load_balancer.proto package grpc_lb_v1 diff --git a/vendor/google.golang.org/grpc/balancer/grpclb/grpclb.go b/vendor/google.golang.org/grpc/balancer/grpclb/grpclb.go index 86ba65be4c..47a3e938dc 100644 --- a/vendor/google.golang.org/grpc/balancer/grpclb/grpclb.go +++ b/vendor/google.golang.org/grpc/balancer/grpclb/grpclb.go @@ -44,8 +44,8 @@ import ( "google.golang.org/grpc/internal/resolver/dns" "google.golang.org/grpc/resolver" "google.golang.org/grpc/resolver/manual" + "google.golang.org/protobuf/types/known/durationpb" - durationpb "github.com/golang/protobuf/ptypes/duration" lbpb "google.golang.org/grpc/balancer/grpclb/grpc_lb_v1" ) diff --git a/vendor/google.golang.org/grpc/balancer/grpclb/grpclb_remote_balancer.go b/vendor/google.golang.org/grpc/balancer/grpclb/grpclb_remote_balancer.go index c8fe1edd8e..f8b5229c35 100644 --- a/vendor/google.golang.org/grpc/balancer/grpclb/grpclb_remote_balancer.go +++ b/vendor/google.golang.org/grpc/balancer/grpclb/grpclb_remote_balancer.go @@ -26,7 +26,6 @@ import ( "sync" "time" - "github.com/golang/protobuf/proto" "google.golang.org/grpc" "google.golang.org/grpc/balancer" "google.golang.org/grpc/connectivity" @@ -36,8 +35,9 @@ import ( "google.golang.org/grpc/keepalive" "google.golang.org/grpc/metadata" "google.golang.org/grpc/resolver" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/timestamppb" - timestamppb "github.com/golang/protobuf/ptypes/timestamp" lbpb "google.golang.org/grpc/balancer/grpclb/grpc_lb_v1" ) 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 e9e97d4511..856c75dd4e 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,8 +18,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.22.0 +// protoc-gen-go v1.32.0 +// protoc v4.25.2 // source: grpc/binlog/v1/binarylog.proto package grpc_binarylog_v1 diff --git a/vendor/google.golang.org/grpc/clientconn.go b/vendor/google.golang.org/grpc/clientconn.go index f6e815e6bf..f0b7f3200f 100644 --- a/vendor/google.golang.org/grpc/clientconn.go +++ b/vendor/google.golang.org/grpc/clientconn.go @@ -1772,6 +1772,8 @@ func parseTarget(target string) (resolver.Target, error) { return resolver.Target{URL: *u}, nil } +// encodeAuthority escapes the authority string based on valid chars defined in +// https://datatracker.ietf.org/doc/html/rfc3986#section-3.2. func encodeAuthority(authority string) string { const upperhex = "0123456789ABCDEF" diff --git a/vendor/google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp/altscontext.pb.go b/vendor/google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp/altscontext.pb.go index c7cf1810a1..ca4d033154 100644 --- a/vendor/google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp/altscontext.pb.go +++ b/vendor/google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp/altscontext.pb.go @@ -17,8 +17,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.22.0 +// protoc-gen-go v1.32.0 +// protoc v4.25.2 // source: grpc/gcp/altscontext.proto package grpc_gcp diff --git a/vendor/google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp/handshaker.pb.go b/vendor/google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp/handshaker.pb.go index 00407de755..4a4074958e 100644 --- a/vendor/google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp/handshaker.pb.go +++ b/vendor/google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp/handshaker.pb.go @@ -17,8 +17,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.22.0 +// protoc-gen-go v1.32.0 +// protoc v4.25.2 // source: grpc/gcp/handshaker.proto package grpc_gcp diff --git a/vendor/google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp/handshaker_grpc.pb.go b/vendor/google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp/handshaker_grpc.pb.go index 39ecccf878..ba1c46f64b 100644 --- a/vendor/google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp/handshaker_grpc.pb.go +++ b/vendor/google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp/handshaker_grpc.pb.go @@ -18,7 +18,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.3.0 -// - protoc v4.22.0 +// - protoc v4.25.2 // source: grpc/gcp/handshaker.proto package grpc_gcp diff --git a/vendor/google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp/transport_security_common.pb.go b/vendor/google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp/transport_security_common.pb.go index 69f0947582..3e53b2b13b 100644 --- a/vendor/google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp/transport_security_common.pb.go +++ b/vendor/google.golang.org/grpc/credentials/alts/internal/proto/grpc_gcp/transport_security_common.pb.go @@ -17,8 +17,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.22.0 +// protoc-gen-go v1.32.0 +// protoc v4.25.2 // source: grpc/gcp/transport_security_common.proto package grpc_gcp diff --git a/vendor/google.golang.org/grpc/encoding/proto/proto.go b/vendor/google.golang.org/grpc/encoding/proto/proto.go index 0ee3d3bae9..66d5cdf03e 100644 --- a/vendor/google.golang.org/grpc/encoding/proto/proto.go +++ b/vendor/google.golang.org/grpc/encoding/proto/proto.go @@ -23,8 +23,9 @@ package proto import ( "fmt" - "github.com/golang/protobuf/proto" "google.golang.org/grpc/encoding" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/protoadapt" ) // Name is the name registered for the proto compressor. @@ -38,21 +39,34 @@ func init() { type codec struct{} func (codec) Marshal(v any) ([]byte, error) { - vv, ok := v.(proto.Message) - if !ok { + vv := messageV2Of(v) + if vv == nil { return nil, fmt.Errorf("failed to marshal, message is %T, want proto.Message", v) } + return proto.Marshal(vv) } func (codec) Unmarshal(data []byte, v any) error { - vv, ok := v.(proto.Message) - if !ok { + vv := messageV2Of(v) + if vv == nil { return fmt.Errorf("failed to unmarshal, message is %T, want proto.Message", v) } + return proto.Unmarshal(data, vv) } +func messageV2Of(v any) proto.Message { + switch v := v.(type) { + case protoadapt.MessageV1: + return protoadapt.MessageV2Of(v) + case protoadapt.MessageV2: + return v + } + + return nil +} + func (codec) Name() string { return Name } 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 24299efd63..5bf880d419 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,8 +17,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.22.0 +// protoc-gen-go v1.32.0 +// protoc v4.25.2 // source: grpc/health/v1/health.proto package grpc_health_v1 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 4439cda0f3..4c46c098dc 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 @@ -18,7 +18,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.3.0 -// - protoc v4.22.0 +// - protoc v4.25.2 // source: grpc/health/v1/health.proto package grpc_health_v1 diff --git a/vendor/google.golang.org/grpc/internal/binarylog/method_logger.go b/vendor/google.golang.org/grpc/internal/binarylog/method_logger.go index 0f31274a3c..e8456a77c2 100644 --- a/vendor/google.golang.org/grpc/internal/binarylog/method_logger.go +++ b/vendor/google.golang.org/grpc/internal/binarylog/method_logger.go @@ -25,11 +25,12 @@ import ( "sync/atomic" "time" - "github.com/golang/protobuf/proto" - "github.com/golang/protobuf/ptypes" binlogpb "google.golang.org/grpc/binarylog/grpc_binarylog_v1" "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/durationpb" + "google.golang.org/protobuf/types/known/timestamppb" ) type callIDGenerator struct { @@ -88,7 +89,7 @@ func NewTruncatingMethodLogger(h, m uint64) *TruncatingMethodLogger { // in TruncatingMethodLogger as possible. func (ml *TruncatingMethodLogger) Build(c LogEntryConfig) *binlogpb.GrpcLogEntry { m := c.toProto() - timestamp, _ := ptypes.TimestampProto(time.Now()) + timestamp := timestamppb.Now() m.Timestamp = timestamp m.CallId = ml.callID m.SequenceIdWithinCall = ml.idWithinCallGen.next() @@ -178,7 +179,7 @@ func (c *ClientHeader) toProto() *binlogpb.GrpcLogEntry { Authority: c.Authority, } if c.Timeout > 0 { - clientHeader.Timeout = ptypes.DurationProto(c.Timeout) + clientHeader.Timeout = durationpb.New(c.Timeout) } ret := &binlogpb.GrpcLogEntry{ Type: binlogpb.GrpcLogEntry_EVENT_TYPE_CLIENT_HEADER, diff --git a/vendor/google.golang.org/grpc/internal/binarylog/sink.go b/vendor/google.golang.org/grpc/internal/binarylog/sink.go index 264de387c2..9ea598b14c 100644 --- a/vendor/google.golang.org/grpc/internal/binarylog/sink.go +++ b/vendor/google.golang.org/grpc/internal/binarylog/sink.go @@ -25,8 +25,8 @@ import ( "sync" "time" - "github.com/golang/protobuf/proto" binlogpb "google.golang.org/grpc/binarylog/grpc_binarylog_v1" + "google.golang.org/protobuf/proto" ) var ( diff --git a/vendor/google.golang.org/grpc/internal/grpcrand/grpcrand.go b/vendor/google.golang.org/grpc/internal/grpcrand/grpcrand.go index aa97273e7d..0126d6b510 100644 --- a/vendor/google.golang.org/grpc/internal/grpcrand/grpcrand.go +++ b/vendor/google.golang.org/grpc/internal/grpcrand/grpcrand.go @@ -1,3 +1,8 @@ +//go:build !go1.21 + +// TODO: when this file is deleted (after Go 1.20 support is dropped), delete +// all of grpcrand and call the rand package directly. + /* * * Copyright 2018 gRPC authors. diff --git a/vendor/google.golang.org/grpc/internal/grpcrand/grpcrand_go1.21.go b/vendor/google.golang.org/grpc/internal/grpcrand/grpcrand_go1.21.go new file mode 100644 index 0000000000..c37299af1e --- /dev/null +++ b/vendor/google.golang.org/grpc/internal/grpcrand/grpcrand_go1.21.go @@ -0,0 +1,73 @@ +//go:build go1.21 + +/* + * + * Copyright 2024 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// Package grpcrand implements math/rand functions in a concurrent-safe way +// with a global random source, independent of math/rand's global source. +package grpcrand + +import "math/rand" + +// This implementation will be used for Go version 1.21 or newer. +// For older versions, the original implementation with mutex will be used. + +// Int implements rand.Int on the grpcrand global source. +func Int() int { + return rand.Int() +} + +// Int63n implements rand.Int63n on the grpcrand global source. +func Int63n(n int64) int64 { + return rand.Int63n(n) +} + +// Intn implements rand.Intn on the grpcrand global source. +func Intn(n int) int { + return rand.Intn(n) +} + +// Int31n implements rand.Int31n on the grpcrand global source. +func Int31n(n int32) int32 { + return rand.Int31n(n) +} + +// Float64 implements rand.Float64 on the grpcrand global source. +func Float64() float64 { + return rand.Float64() +} + +// Uint64 implements rand.Uint64 on the grpcrand global source. +func Uint64() uint64 { + return rand.Uint64() +} + +// Uint32 implements rand.Uint32 on the grpcrand global source. +func Uint32() uint32 { + return rand.Uint32() +} + +// ExpFloat64 implements rand.ExpFloat64 on the grpcrand global source. +func ExpFloat64() float64 { + return rand.ExpFloat64() +} + +// Shuffle implements rand.Shuffle on the grpcrand global source. +var Shuffle = func(n int, f func(int, int)) { + rand.Shuffle(n, f) +} diff --git a/vendor/google.golang.org/grpc/internal/pretty/pretty.go b/vendor/google.golang.org/grpc/internal/pretty/pretty.go index 7033191375..52cfab1b93 100644 --- a/vendor/google.golang.org/grpc/internal/pretty/pretty.go +++ b/vendor/google.golang.org/grpc/internal/pretty/pretty.go @@ -24,7 +24,6 @@ import ( "encoding/json" "fmt" - "github.com/golang/protobuf/jsonpb" protov1 "github.com/golang/protobuf/proto" "google.golang.org/protobuf/encoding/protojson" protov2 "google.golang.org/protobuf/proto" @@ -38,15 +37,15 @@ const jsonIndent = " " func ToJSON(e any) string { switch ee := e.(type) { case protov1.Message: - mm := jsonpb.Marshaler{Indent: jsonIndent} - ret, err := mm.MarshalToString(ee) + mm := protojson.MarshalOptions{Indent: jsonIndent} + ret, err := mm.Marshal(protov1.MessageV2(ee)) if err != nil { // This may fail for proto.Anys, e.g. for xDS v2, LDS, the v2 // messages are not imported, and this will fail because the message // is not found. return fmt.Sprintf("%+v", ee) } - return ret + return string(ret) case protov2.Message: mm := protojson.MarshalOptions{ Multiline: true, diff --git a/vendor/google.golang.org/grpc/internal/status/status.go b/vendor/google.golang.org/grpc/internal/status/status.go index 03ef2fedd5..c7dbc82059 100644 --- a/vendor/google.golang.org/grpc/internal/status/status.go +++ b/vendor/google.golang.org/grpc/internal/status/status.go @@ -31,10 +31,11 @@ import ( "errors" "fmt" - "github.com/golang/protobuf/proto" - "github.com/golang/protobuf/ptypes" spb "google.golang.org/genproto/googleapis/rpc/status" "google.golang.org/grpc/codes" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/protoadapt" + "google.golang.org/protobuf/types/known/anypb" ) // Status represents an RPC status code, message, and details. It is immutable @@ -130,14 +131,14 @@ func (s *Status) Err() error { // WithDetails returns a new status with the provided details messages appended to the status. // If any errors are encountered, it returns nil and the first error encountered. -func (s *Status) WithDetails(details ...proto.Message) (*Status, error) { +func (s *Status) WithDetails(details ...protoadapt.MessageV1) (*Status, error) { if s.Code() == codes.OK { return nil, errors.New("no error details for status with code OK") } // s.Code() != OK implies that s.Proto() != nil. p := s.Proto() for _, detail := range details { - any, err := ptypes.MarshalAny(detail) + any, err := anypb.New(protoadapt.MessageV2Of(detail)) if err != nil { return nil, err } @@ -154,12 +155,12 @@ func (s *Status) Details() []any { } details := make([]any, 0, len(s.s.Details)) for _, any := range s.s.Details { - detail := &ptypes.DynamicAny{} - if err := ptypes.UnmarshalAny(any, detail); err != nil { + detail, err := any.UnmarshalNew() + if err != nil { details = append(details, err) continue } - details = append(details, detail.Message) + details = append(details, detail) } return details } diff --git a/vendor/google.golang.org/grpc/internal/transport/controlbuf.go b/vendor/google.golang.org/grpc/internal/transport/controlbuf.go index b330ccedc8..83c3829826 100644 --- a/vendor/google.golang.org/grpc/internal/transport/controlbuf.go +++ b/vendor/google.golang.org/grpc/internal/transport/controlbuf.go @@ -535,8 +535,8 @@ const minBatchSize = 1000 // size is too low to give stream goroutines a chance to fill it up. // // Upon exiting, if the error causing the exit is not an I/O error, run() -// flushes and closes the underlying connection. Otherwise, the connection is -// left open to allow the I/O error to be encountered by the reader instead. +// flushes the underlying connection. The connection is always left open to +// allow different closing behavior on the client and server. func (l *loopyWriter) run() (err error) { defer func() { if l.logger.V(logLevel) { @@ -544,7 +544,6 @@ func (l *loopyWriter) run() (err error) { } if !isIOError(err) { l.framer.writer.Flush() - l.conn.Close() } l.cbuf.finish() }() diff --git a/vendor/google.golang.org/grpc/internal/transport/handler_server.go b/vendor/google.golang.org/grpc/internal/transport/handler_server.go index a9d70e2a16..bd39ff9a22 100644 --- a/vendor/google.golang.org/grpc/internal/transport/handler_server.go +++ b/vendor/google.golang.org/grpc/internal/transport/handler_server.go @@ -35,7 +35,6 @@ import ( "sync" "time" - "github.com/golang/protobuf/proto" "golang.org/x/net/http2" "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials" @@ -45,6 +44,7 @@ import ( "google.golang.org/grpc/peer" "google.golang.org/grpc/stats" "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" ) // NewServerHandlerTransport returns a ServerTransport handling gRPC from 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 c33ac5961b..eff8799640 100644 --- a/vendor/google.golang.org/grpc/internal/transport/http2_client.go +++ b/vendor/google.golang.org/grpc/internal/transport/http2_client.go @@ -451,7 +451,13 @@ func newHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts } go func() { t.loopy = newLoopyWriter(clientSide, t.framer, t.controlBuf, t.bdpEst, t.conn, t.logger) - t.loopy.run() + if err := t.loopy.run(); !isIOError(err) { + // Immediately close the connection, as the loopy writer returns + // when there are no more active streams and we were draining (the + // server sent a GOAWAY). For I/O errors, the reader will hit it + // after draining any remaining incoming data. + t.conn.Close() + } close(t.writerDone) }() return t, nil 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 f6bac0e8a0..3839c1ade2 100644 --- a/vendor/google.golang.org/grpc/internal/transport/http2_server.go +++ b/vendor/google.golang.org/grpc/internal/transport/http2_server.go @@ -32,13 +32,13 @@ import ( "sync/atomic" "time" - "github.com/golang/protobuf/proto" "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/internal/pretty" "google.golang.org/grpc/internal/syscall" + "google.golang.org/protobuf/proto" "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials" @@ -322,8 +322,24 @@ func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport, go func() { t.loopy = newLoopyWriter(serverSide, t.framer, t.controlBuf, t.bdpEst, t.conn, t.logger) t.loopy.ssGoAwayHandler = t.outgoingGoAwayHandler - t.loopy.run() + err := t.loopy.run() close(t.loopyWriterDone) + if !isIOError(err) { + // Close the connection if a non-I/O error occurs (for I/O errors + // the reader will also encounter the error and close). Wait 1 + // second before closing the connection, or when the reader is done + // (i.e. the client already closed the connection or a connection + // error occurred). This avoids the potential problem where there + // is unread data on the receive side of the connection, which, if + // closed, would lead to a TCP RST instead of FIN, and the client + // encountering errors. For more info: + // https://github.com/grpc/grpc-go/issues/5358 + select { + case <-t.readerDone: + case <-time.After(time.Second): + } + t.conn.Close() + } }() go t.keepalive() return t, nil @@ -609,8 +625,8 @@ func (t *http2Server) operateHeaders(ctx context.Context, frame *http2.MetaHeade // traceCtx attaches trace to ctx and returns the new context. func (t *http2Server) HandleStreams(ctx context.Context, handle func(*Stream)) { defer func() { - <-t.loopyWriterDone close(t.readerDone) + <-t.loopyWriterDone }() for { t.controlBuf.throttle() @@ -636,10 +652,6 @@ func (t *http2Server) HandleStreams(ctx context.Context, handle func(*Stream)) { } continue } - if err == io.EOF || err == io.ErrUnexpectedEOF { - t.Close(err) - return - } t.Close(err) return } @@ -1329,6 +1341,7 @@ func (t *http2Server) outgoingGoAwayHandler(g *goAway) (bool, error) { if err := t.framer.fr.WriteGoAway(sid, g.code, g.debugData); err != nil { return false, err } + t.framer.writer.Flush() if retErr != nil { return false, retErr } @@ -1349,7 +1362,7 @@ func (t *http2Server) outgoingGoAwayHandler(g *goAway) (bool, error) { return false, err } go func() { - timer := time.NewTimer(time.Minute) + timer := time.NewTimer(5 * time.Second) defer timer.Stop() select { case <-t.drainEvent.Done(): diff --git a/vendor/google.golang.org/grpc/internal/transport/transport.go b/vendor/google.golang.org/grpc/internal/transport/transport.go index b7b8fec180..d3796c256e 100644 --- a/vendor/google.golang.org/grpc/internal/transport/transport.go +++ b/vendor/google.golang.org/grpc/internal/transport/transport.go @@ -28,6 +28,7 @@ import ( "fmt" "io" "net" + "strings" "sync" "sync/atomic" "time" @@ -362,8 +363,12 @@ func (s *Stream) SendCompress() string { // ClientAdvertisedCompressors returns the compressor names advertised by the // client via grpc-accept-encoding header. -func (s *Stream) ClientAdvertisedCompressors() string { - return s.clientAdvertisedCompressors +func (s *Stream) ClientAdvertisedCompressors() []string { + values := strings.Split(s.clientAdvertisedCompressors, ",") + for i, v := range values { + values[i] = strings.TrimSpace(v) + } + return values } // Done returns a channel which is closed when it receives the final status diff --git a/vendor/google.golang.org/grpc/resolver/resolver.go b/vendor/google.golang.org/grpc/resolver/resolver.go index adf89dd9cf..d72f21c1b3 100644 --- a/vendor/google.golang.org/grpc/resolver/resolver.go +++ b/vendor/google.golang.org/grpc/resolver/resolver.go @@ -168,6 +168,9 @@ type BuildOptions struct { // field. In most cases though, it is not appropriate, and this field may // be ignored. Dialer func(context.Context, string) (net.Conn, error) + // Authority is the effective authority of the clientconn for which the + // resolver is built. + Authority string } // An Endpoint is one network endpoint, or server, which may have multiple diff --git a/vendor/google.golang.org/grpc/resolver_wrapper.go b/vendor/google.golang.org/grpc/resolver_wrapper.go index c79bab1214..f845ac9589 100644 --- a/vendor/google.golang.org/grpc/resolver_wrapper.go +++ b/vendor/google.golang.org/grpc/resolver_wrapper.go @@ -75,6 +75,7 @@ func (ccr *ccResolverWrapper) start() error { DialCreds: ccr.cc.dopts.copts.TransportCredentials, CredsBundle: ccr.cc.dopts.copts.CredsBundle, Dialer: ccr.cc.dopts.copts.Dialer, + Authority: ccr.cc.authority, } var err error ccr.resolver, err = ccr.cc.resolverBuilder.Build(ccr.cc.parsedTarget, ccr, opts) diff --git a/vendor/google.golang.org/grpc/rpc_util.go b/vendor/google.golang.org/grpc/rpc_util.go index a4b6bc6873..82493d237b 100644 --- a/vendor/google.golang.org/grpc/rpc_util.go +++ b/vendor/google.golang.org/grpc/rpc_util.go @@ -189,6 +189,20 @@ type EmptyCallOption struct{} func (EmptyCallOption) before(*callInfo) error { return nil } func (EmptyCallOption) after(*callInfo, *csAttempt) {} +// StaticMethod returns a CallOption which specifies that a call is being made +// to a method that is static, which means the method is known at compile time +// and doesn't change at runtime. This can be used as a signal to stats plugins +// that this method is safe to include as a key to a measurement. +func StaticMethod() CallOption { + return StaticMethodCallOption{} +} + +// StaticMethodCallOption is a CallOption that specifies that a call comes +// from a static method. +type StaticMethodCallOption struct { + EmptyCallOption +} + // Header returns a CallOptions that retrieves the header metadata // for a unary RPC. func Header(md *metadata.MD) CallOption { @@ -730,17 +744,19 @@ type payloadInfo struct { uncompressedBytes []byte } -func recvAndDecompress(p *parser, s *transport.Stream, dc Decompressor, maxReceiveMessageSize int, payInfo *payloadInfo, compressor encoding.Compressor) ([]byte, error) { - pf, buf, err := p.recvMsg(maxReceiveMessageSize) +// recvAndDecompress reads a message from the stream, decompressing it if necessary. +// +// Cancelling the returned cancel function releases the buffer back to the pool. So the caller should cancel as soon as +// the buffer is no longer needed. +func recvAndDecompress(p *parser, s *transport.Stream, dc Decompressor, maxReceiveMessageSize int, payInfo *payloadInfo, compressor encoding.Compressor, +) (uncompressedBuf []byte, cancel func(), err error) { + pf, compressedBuf, err := p.recvMsg(maxReceiveMessageSize) if err != nil { - return nil, err - } - if payInfo != nil { - payInfo.compressedLength = len(buf) + return nil, nil, err } if st := checkRecvPayload(pf, s.RecvCompress(), compressor != nil || dc != nil); st != nil { - return nil, st.Err() + return nil, nil, st.Err() } var size int @@ -748,21 +764,35 @@ func recvAndDecompress(p *parser, s *transport.Stream, dc Decompressor, maxRecei // To match legacy behavior, if the decompressor is set by WithDecompressor or RPCDecompressor, // use this decompressor as the default. if dc != nil { - buf, err = dc.Do(bytes.NewReader(buf)) - size = len(buf) + uncompressedBuf, err = dc.Do(bytes.NewReader(compressedBuf)) + size = len(uncompressedBuf) } else { - buf, size, err = decompress(compressor, buf, maxReceiveMessageSize) + uncompressedBuf, size, err = decompress(compressor, compressedBuf, maxReceiveMessageSize) } if err != nil { - return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the received message: %v", err) + return nil, nil, status.Errorf(codes.Internal, "grpc: failed to decompress the received message: %v", err) } if size > maxReceiveMessageSize { // TODO: Revisit the error code. Currently keep it consistent with java // implementation. - return nil, status.Errorf(codes.ResourceExhausted, "grpc: received message after decompression larger than max (%d vs. %d)", size, maxReceiveMessageSize) + return nil, nil, status.Errorf(codes.ResourceExhausted, "grpc: received message after decompression larger than max (%d vs. %d)", size, maxReceiveMessageSize) } + } else { + uncompressedBuf = compressedBuf } - return buf, nil + + if payInfo != nil { + payInfo.compressedLength = len(compressedBuf) + payInfo.uncompressedBytes = uncompressedBuf + + cancel = func() {} + } else { + cancel = func() { + p.recvBufferPool.Put(&compressedBuf) + } + } + + return uncompressedBuf, cancel, nil } // Using compressor, decompress d, returning data and size. @@ -782,6 +812,9 @@ func decompress(compressor encoding.Compressor, d []byte, maxReceiveMessageSize // size is used as an estimate to size the buffer, but we // will read more data if available. // +MinRead so ReadFrom will not reallocate if size is correct. + // + // TODO: If we ensure that the buffer size is the same as the DecompressedSize, + // we can also utilize the recv buffer pool here. buf := bytes.NewBuffer(make([]byte, 0, size+bytes.MinRead)) bytesRead, err := buf.ReadFrom(io.LimitReader(dcReader, int64(maxReceiveMessageSize)+1)) return buf.Bytes(), int(bytesRead), err @@ -797,18 +830,15 @@ func decompress(compressor encoding.Compressor, d []byte, maxReceiveMessageSize // dc takes precedence over compressor. // TODO(dfawley): wrap the old compressor/decompressor using the new API? func recv(p *parser, c baseCodec, s *transport.Stream, dc Decompressor, m any, maxReceiveMessageSize int, payInfo *payloadInfo, compressor encoding.Compressor) error { - buf, err := recvAndDecompress(p, s, dc, maxReceiveMessageSize, payInfo, compressor) + buf, cancel, err := recvAndDecompress(p, s, dc, maxReceiveMessageSize, payInfo, compressor) if err != nil { return err } + defer cancel() + if err := c.Unmarshal(buf, m); err != nil { return status.Errorf(codes.Internal, "grpc: failed to unmarshal the received message: %v", err) } - if payInfo != nil { - payInfo.uncompressedBytes = buf - } else { - p.recvBufferPool.Put(&buf) - } return nil } @@ -958,6 +988,7 @@ const ( SupportPackageIsVersion5 = true SupportPackageIsVersion6 = true SupportPackageIsVersion7 = true + SupportPackageIsVersion8 = true ) const grpcUA = "grpc-go/" + Version diff --git a/vendor/google.golang.org/grpc/server.go b/vendor/google.golang.org/grpc/server.go index e89c5ac613..a6a11704b3 100644 --- a/vendor/google.golang.org/grpc/server.go +++ b/vendor/google.golang.org/grpc/server.go @@ -33,8 +33,6 @@ import ( "sync/atomic" "time" - "golang.org/x/net/trace" - "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials" "google.golang.org/grpc/encoding" @@ -131,7 +129,7 @@ type Server struct { drain bool cv *sync.Cond // signaled when connections close for GracefulStop services map[string]*serviceInfo // service name -> service info - events trace.EventLog + events traceEventLog quit *grpcsync.Event done *grpcsync.Event @@ -670,7 +668,7 @@ func NewServer(opt ...ServerOption) *Server { s.cv = sync.NewCond(&s.mu) if EnableTracing { _, file, line, _ := runtime.Caller(1) - s.events = trace.NewEventLog("grpc.Server", fmt.Sprintf("%s:%d", file, line)) + s.events = newTraceEventLog("grpc.Server", fmt.Sprintf("%s:%d", file, line)) } if s.opts.numServerWorkers > 0 { @@ -1344,7 +1342,8 @@ func (s *Server) processUnaryRPC(ctx context.Context, t transport.ServerTranspor if len(shs) != 0 || len(binlogs) != 0 { payInfo = &payloadInfo{} } - d, err := recvAndDecompress(&parser{r: stream, recvBufferPool: s.opts.recvBufferPool}, stream, dc, s.opts.maxReceiveMessageSize, payInfo, decomp) + + d, cancel, err := recvAndDecompress(&parser{r: stream, recvBufferPool: s.opts.recvBufferPool}, stream, dc, s.opts.maxReceiveMessageSize, payInfo, decomp) if err != nil { if e := t.WriteStatus(stream, status.Convert(err)); e != nil { channelz.Warningf(logger, s.channelzID, "grpc: Server.processUnaryRPC failed to write status: %v", e) @@ -1355,6 +1354,8 @@ func (s *Server) processUnaryRPC(ctx context.Context, t transport.ServerTranspor t.IncrMsgRecv() } df := func(v any) error { + defer cancel() + if err := s.getCodec(stream.ContentSubtype()).Unmarshal(d, v); err != nil { return status.Errorf(codes.Internal, "grpc: error unmarshalling request: %v", err) } @@ -1734,8 +1735,8 @@ func (s *Server) handleStream(t transport.ServerTransport, stream *transport.Str ctx = contextWithServer(ctx, s) var ti *traceInfo if EnableTracing { - tr := trace.New("grpc.Recv."+methodFamily(stream.Method()), stream.Method()) - ctx = trace.NewContext(ctx, tr) + tr := newTrace("grpc.Recv."+methodFamily(stream.Method()), stream.Method()) + ctx = newTraceContext(ctx, tr) ti = &traceInfo{ tr: tr, firstLine: firstLine{ @@ -2119,7 +2120,7 @@ func ClientSupportedCompressors(ctx context.Context) ([]string, error) { return nil, fmt.Errorf("failed to fetch the stream from the given context %v", ctx) } - return strings.Split(stream.ClientAdvertisedCompressors(), ","), nil + return stream.ClientAdvertisedCompressors(), nil } // SetTrailer sets the trailer metadata that will be sent when an RPC returns. @@ -2159,7 +2160,7 @@ func (c *channelzServer) ChannelzMetric() *channelz.ServerInternalMetric { // validateSendCompressor returns an error when given compressor name cannot be // handled by the server or the client based on the advertised compressors. -func validateSendCompressor(name, clientCompressors string) error { +func validateSendCompressor(name string, clientCompressors []string) error { if name == encoding.Identity { return nil } @@ -2168,7 +2169,7 @@ func validateSendCompressor(name, clientCompressors string) error { return fmt.Errorf("compressor not registered %q", name) } - for _, c := range strings.Split(clientCompressors, ",") { + for _, c := range clientCompressors { if c == name { return nil // found match } diff --git a/vendor/google.golang.org/grpc/stream.go b/vendor/google.golang.org/grpc/stream.go index d621f52b1a..814e998354 100644 --- a/vendor/google.golang.org/grpc/stream.go +++ b/vendor/google.golang.org/grpc/stream.go @@ -27,7 +27,6 @@ import ( "sync" "time" - "golang.org/x/net/trace" "google.golang.org/grpc/balancer" "google.golang.org/grpc/codes" "google.golang.org/grpc/encoding" @@ -431,7 +430,7 @@ func (cs *clientStream) newAttemptLocked(isTransparent bool) (*csAttempt, error) var trInfo *traceInfo if EnableTracing { trInfo = &traceInfo{ - tr: trace.New("grpc.Sent."+methodFamily(method), method), + tr: newTrace("grpc.Sent."+methodFamily(method), method), firstLine: firstLine{ client: true, }, @@ -440,7 +439,7 @@ func (cs *clientStream) newAttemptLocked(isTransparent bool) (*csAttempt, error) trInfo.firstLine.deadline = time.Until(deadline) } trInfo.tr.LazyLog(&trInfo.firstLine, false) - ctx = trace.NewContext(ctx, trInfo.tr) + ctx = newTraceContext(ctx, trInfo.tr) } if cs.cc.parsedTarget.URL.Scheme == internal.GRPCResolverSchemeExtraMetadata { diff --git a/vendor/google.golang.org/grpc/trace.go b/vendor/google.golang.org/grpc/trace.go index 9ded79321b..10f4f798f5 100644 --- a/vendor/google.golang.org/grpc/trace.go +++ b/vendor/google.golang.org/grpc/trace.go @@ -26,8 +26,6 @@ import ( "strings" "sync" "time" - - "golang.org/x/net/trace" ) // EnableTracing controls whether to trace RPCs using the golang.org/x/net/trace package. @@ -44,9 +42,31 @@ func methodFamily(m string) string { return m } +// traceEventLog mirrors golang.org/x/net/trace.EventLog. +// +// It exists in order to avoid importing x/net/trace on grpcnotrace builds. +type traceEventLog interface { + Printf(format string, a ...any) + Errorf(format string, a ...any) + Finish() +} + +// traceLog mirrors golang.org/x/net/trace.Trace. +// +// It exists in order to avoid importing x/net/trace on grpcnotrace builds. +type traceLog interface { + LazyLog(x fmt.Stringer, sensitive bool) + LazyPrintf(format string, a ...any) + SetError() + SetRecycler(f func(any)) + SetTraceInfo(traceID, spanID uint64) + SetMaxEvents(m int) + Finish() +} + // traceInfo contains tracing information for an RPC. type traceInfo struct { - tr trace.Trace + tr traceLog firstLine firstLine } diff --git a/vendor/google.golang.org/grpc/trace_notrace.go b/vendor/google.golang.org/grpc/trace_notrace.go new file mode 100644 index 0000000000..1da3a2308e --- /dev/null +++ b/vendor/google.golang.org/grpc/trace_notrace.go @@ -0,0 +1,52 @@ +//go:build grpcnotrace + +/* + * + * Copyright 2024 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package grpc + +// grpcnotrace can be used to avoid importing golang.org/x/net/trace, which in +// turn enables binaries using gRPC-Go for dead code elimination, which can +// yield 10-15% improvements in binary size when tracing is not needed. + +import ( + "context" + "fmt" +) + +type notrace struct{} + +func (notrace) LazyLog(x fmt.Stringer, sensitive bool) {} +func (notrace) LazyPrintf(format string, a ...any) {} +func (notrace) SetError() {} +func (notrace) SetRecycler(f func(any)) {} +func (notrace) SetTraceInfo(traceID, spanID uint64) {} +func (notrace) SetMaxEvents(m int) {} +func (notrace) Finish() {} + +func newTrace(family, title string) traceLog { + return notrace{} +} + +func newTraceContext(ctx context.Context, tr traceLog) context.Context { + return ctx +} + +func newTraceEventLog(family, title string) traceEventLog { + return nil +} diff --git a/vendor/google.golang.org/grpc/trace_withtrace.go b/vendor/google.golang.org/grpc/trace_withtrace.go new file mode 100644 index 0000000000..88d6e8571e --- /dev/null +++ b/vendor/google.golang.org/grpc/trace_withtrace.go @@ -0,0 +1,39 @@ +//go:build !grpcnotrace + +/* + * + * Copyright 2024 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package grpc + +import ( + "context" + + t "golang.org/x/net/trace" +) + +func newTrace(family, title string) traceLog { + return t.New(family, title) +} + +func newTraceContext(ctx context.Context, tr traceLog) context.Context { + return t.NewContext(ctx, tr) +} + +func newTraceEventLog(family, title string) traceEventLog { + return t.NewEventLog(family, title) +} diff --git a/vendor/google.golang.org/grpc/version.go b/vendor/google.golang.org/grpc/version.go index 1ad1ba2ad6..46ad8113ff 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.61.0" +const Version = "1.62.1" diff --git a/vendor/google.golang.org/grpc/vet.sh b/vendor/google.golang.org/grpc/vet.sh index 5da38a4099..7a33c215b5 100644 --- a/vendor/google.golang.org/grpc/vet.sh +++ b/vendor/google.golang.org/grpc/vet.sh @@ -41,7 +41,7 @@ if [[ "$1" = "-install" ]]; then popd if [[ -z "${VET_SKIP_PROTO}" ]]; then if [[ "${GITHUB_ACTIONS}" = "true" ]]; then - PROTOBUF_VERSION=22.0 # a.k.a v4.22.0 in pb.go files. + PROTOBUF_VERSION=25.2 # a.k.a. v4.22.0 in pb.go files. PROTOC_FILENAME=protoc-${PROTOBUF_VERSION}-linux-x86_64.zip pushd /home/runner/go wget https://github.com/google/protobuf/releases/download/v${PROTOBUF_VERSION}/${PROTOC_FILENAME} diff --git a/vendor/google.golang.org/protobuf/protoadapt/convert.go b/vendor/google.golang.org/protobuf/protoadapt/convert.go new file mode 100644 index 0000000000..ea276d15a0 --- /dev/null +++ b/vendor/google.golang.org/protobuf/protoadapt/convert.go @@ -0,0 +1,31 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package protoadapt bridges the original and new proto APIs. +package protoadapt + +import ( + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/runtime/protoiface" + "google.golang.org/protobuf/runtime/protoimpl" +) + +// MessageV1 is the original [github.com/golang/protobuf/proto.Message] type. +type MessageV1 = protoiface.MessageV1 + +// MessageV2 is the [google.golang.org/protobuf/proto.Message] type used by the +// current [google.golang.org/protobuf] module, adding support for reflection. +type MessageV2 = proto.Message + +// MessageV1Of converts a v2 message to a v1 message. +// It returns nil if m is nil. +func MessageV1Of(m MessageV2) MessageV1 { + return protoimpl.X.ProtoMessageV1Of(m) +} + +// MessageV2Of converts a v1 message to a v2 message. +// It returns nil if m is nil. +func MessageV2Of(m MessageV1) MessageV2 { + return protoimpl.X.ProtoMessageV2Of(m) +} diff --git a/vendor/gopkg.in/telebot.v3/admin.go b/vendor/gopkg.in/telebot.v3/admin.go index c4c828d19e..cc8b33a287 100644 --- a/vendor/gopkg.in/telebot.v3/admin.go +++ b/vendor/gopkg.in/telebot.v3/admin.go @@ -21,12 +21,29 @@ type Rights struct { CanRestrictMembers bool `json:"can_restrict_members"` CanPromoteMembers bool `json:"can_promote_members"` CanSendMessages bool `json:"can_send_messages"` - CanSendMedia bool `json:"can_send_media_messages"` CanSendPolls bool `json:"can_send_polls"` CanSendOther bool `json:"can_send_other_messages"` CanAddPreviews bool `json:"can_add_web_page_previews"` CanManageVideoChats bool `json:"can_manage_video_chats"` CanManageChat bool `json:"can_manage_chat"` + CanManageTopics bool `json:"can_manage_topics"` + + CanSendMedia bool `json:"can_send_media_messages,omitempty"` // deprecated + CanSendAudios bool `json:"can_send_audios"` + CanSendDocuments bool `json:"can_send_documents"` + CanSendPhotos bool `json:"can_send_photos"` + CanSendVideos bool `json:"can_send_videos"` + CanSendVideoNotes bool `json:"can_send_video_notes"` + CanSendVoiceNotes bool `json:"can_send_voice_notes"` + + // Independent defines whether the chat permissions are set independently. + // If not, the can_send_other_messages and can_add_web_page_previews permissions + // will imply the can_send_messages, can_send_audios, can_send_documents, can_send_photos, + // can_send_videos, can_send_video_notes, and can_send_voice_notes permissions; + // the can_send_polls permission will imply the can_send_messages permission. + // + // Works for Restrict and SetGroupPermissions methods only. + Independent bool `json:"-"` } // NoRights is the default Rights{}. @@ -35,9 +52,8 @@ func NoRights() Rights { return Rights{} } // NoRestrictions should be used when un-restricting or // un-promoting user. // -// member.Rights = tele.NoRestrictions() -// b.Restrict(chat, member) -// +// member.Rights = tele.NoRestrictions() +// b.Restrict(chat, member) func NoRestrictions() Rights { return Rights{ CanBeEdited: true, @@ -50,12 +66,18 @@ func NoRestrictions() Rights { CanPinMessages: false, CanPromoteMembers: false, CanSendMessages: true, - CanSendMedia: true, CanSendPolls: true, CanSendOther: true, CanAddPreviews: true, CanManageVideoChats: false, CanManageChat: false, + CanManageTopics: false, + CanSendAudios: true, + CanSendDocuments: true, + CanSendPhotos: true, + CanSendVideos: true, + CanSendVideoNotes: true, + CanSendVoiceNotes: true, } } @@ -72,12 +94,18 @@ func AdminRights() Rights { CanPinMessages: true, CanPromoteMembers: true, CanSendMessages: true, - CanSendMedia: true, CanSendPolls: true, CanSendOther: true, CanAddPreviews: true, CanManageVideoChats: true, CanManageChat: true, + CanManageTopics: true, + CanSendAudios: true, + CanSendDocuments: true, + CanSendPhotos: true, + CanSendVideos: true, + CanSendVideoNotes: true, + CanSendVoiceNotes: true, } } @@ -120,20 +148,22 @@ func (b *Bot) Unban(chat *Chat, user *User, forBanned ...bool) error { // Restrict lets you restrict a subset of member's rights until // member.RestrictedUntil, such as: // -// * can send messages -// * can send media -// * can send other -// * can add web page previews -// +// - can send messages +// - can send media +// - can send other +// - can add web page previews func (b *Bot) Restrict(chat *Chat, member *ChatMember) error { - prv, until := member.Rights, member.RestrictedUntil + perms, until := member.Rights, member.RestrictedUntil params := map[string]interface{}{ - "chat_id": chat.Recipient(), - "user_id": member.User.Recipient(), - "until_date": strconv.FormatInt(until, 10), + "chat_id": chat.Recipient(), + "user_id": member.User.Recipient(), + "until_date": strconv.FormatInt(until, 10), + "permissions": perms, + } + if perms.Independent { + params["use_independent_chat_permissions"] = true } - embedRights(params, prv) _, err := b.Raw("restrictChatMember", params) return err @@ -141,24 +171,21 @@ func (b *Bot) Restrict(chat *Chat, member *ChatMember) error { // Promote lets you update member's admin rights, such as: // -// * can change info -// * can post messages -// * can edit messages -// * can delete messages -// * can invite users -// * can restrict members -// * can pin messages -// * can promote members -// +// - can change info +// - can post messages +// - can edit messages +// - can delete messages +// - can invite users +// - can restrict members +// - can pin messages +// - can promote members func (b *Bot) Promote(chat *Chat, member *ChatMember) error { - prv := member.Rights - params := map[string]interface{}{ "chat_id": chat.Recipient(), "user_id": member.User.Recipient(), "is_anonymous": member.Anonymous, } - embedRights(params, prv) + embedRights(params, member.Rights) _, err := b.Raw("promoteChatMember", params) return err @@ -171,7 +198,6 @@ func (b *Bot) Promote(chat *Chat, member *ChatMember) error { // // If the chat is a group or a supergroup and // no administrators were appointed, only the creator will be returned. -// func (b *Bot) AdminsOf(chat *Chat) ([]ChatMember, error) { params := map[string]string{ "chat_id": chat.Recipient(), diff --git a/vendor/gopkg.in/telebot.v3/bot.go b/vendor/gopkg.in/telebot.v3/bot.go index 52d6bcc0f9..e3a9a41f26 100644 --- a/vendor/gopkg.in/telebot.v3/bot.go +++ b/vendor/gopkg.in/telebot.v3/bot.go @@ -160,21 +160,20 @@ var ( // // Example: // -// b.Handle("/start", func (c tele.Context) error { -// return c.Reply("Hello!") -// }) +// b.Handle("/start", func (c tele.Context) error { +// return c.Reply("Hello!") +// }) // -// b.Handle(&inlineButton, func (c tele.Context) error { -// return c.Respond(&tele.CallbackResponse{Text: "Hello!"}) -// }) +// b.Handle(&inlineButton, func (c tele.Context) error { +// return c.Respond(&tele.CallbackResponse{Text: "Hello!"}) +// }) // // Middleware usage: // -// b.Handle("/ban", onBan, middleware.Whitelist(ids...)) -// +// b.Handle("/ban", onBan, middleware.Whitelist(ids...)) func (b *Bot) Handle(endpoint interface{}, h HandlerFunc, m ...MiddlewareFunc) { if len(b.group.middleware) > 0 { - m = append(b.group.middleware, m...) + m = appendMiddleware(b.group.middleware, m) } handler := func(c Context) error { @@ -256,16 +255,16 @@ func (b *Bot) NewContext(u Update) Context { // some Sendable (or string!) and optional send options. // // NOTE: -// Since most arguments are of type interface{}, but have pointer -// method receivers, make sure to pass them by-pointer, NOT by-value. // -// What is a send option exactly? It can be one of the following types: +// Since most arguments are of type interface{}, but have pointer +// method receivers, make sure to pass them by-pointer, NOT by-value. // -// - *SendOptions (the actual object accepted by Telegram API) -// - *ReplyMarkup (a component of SendOptions) -// - Option (a shortcut flag for popular options) -// - ParseMode (HTML, Markdown, etc) +// What is a send option exactly? It can be one of the following types: // +// - *SendOptions (the actual object accepted by Telegram API) +// - *ReplyMarkup (a component of SendOptions) +// - Option (a shortcut flag for popular options) +// - ParseMode (HTML, Markdown, etc) func (b *Bot) Send(to Recipient, what interface{}, opts ...interface{}) (*Message, error) { if to == nil { return nil, ErrBadRecipient @@ -284,6 +283,7 @@ func (b *Bot) Send(to Recipient, what interface{}, opts ...interface{}) (*Messag } // SendAlbum sends multiple instances of media as a single message. +// To include the caption, make sure the first Inputtable of an album has it. // From all existing options, it only supports tele.Silent. func (b *Bot) SendAlbum(to Recipient, a Album, opts ...interface{}) ([]Message, error) { if to == nil { @@ -437,14 +437,13 @@ func (b *Bot) Copy(to Recipient, msg Editable, options ...interface{}) (*Message // // Use cases: // -// b.Edit(m, m.Text, newMarkup) -// b.Edit(m, "new text", tele.ModeHTML) -// b.Edit(m, &tele.ReplyMarkup{...}) -// b.Edit(m, &tele.Photo{File: ...}) -// b.Edit(m, tele.Location{42.1337, 69.4242}) -// b.Edit(c, "edit inline message from the callback") -// b.Edit(r, "edit message from chosen inline result") -// +// b.Edit(m, m.Text, newMarkup) +// b.Edit(m, "new text", tele.ModeHTML) +// b.Edit(m, &tele.ReplyMarkup{...}) +// b.Edit(m, &tele.Photo{File: ...}) +// b.Edit(m, tele.Location{42.1337, 69.4242}) +// b.Edit(c, "edit inline message from the callback") +// b.Edit(r, "edit message from chosen inline result") func (b *Bot) Edit(msg Editable, what interface{}, opts ...interface{}) (*Message, error) { var ( method string @@ -503,7 +502,6 @@ func (b *Bot) Edit(msg Editable, what interface{}, opts ...interface{}) (*Messag // // If edited message is sent by the bot, returns it, // otherwise returns nil and ErrTrueResult. -// func (b *Bot) EditReplyMarkup(msg Editable, markup *ReplyMarkup) (*Message, error) { msgID, chatID := msg.MessageSig() params := make(map[string]string) @@ -537,7 +535,6 @@ func (b *Bot) EditReplyMarkup(msg Editable, markup *ReplyMarkup) (*Message, erro // // If edited message is sent by the bot, returns it, // otherwise returns nil and ErrTrueResult. -// func (b *Bot) EditCaption(msg Editable, caption string, opts ...interface{}) (*Message, error) { msgID, chatID := msg.MessageSig() @@ -571,9 +568,8 @@ func (b *Bot) EditCaption(msg Editable, caption string, opts ...interface{}) (*M // // Use cases: // -// b.EditMedia(m, &tele.Photo{File: tele.FromDisk("chicken.jpg")}) -// b.EditMedia(m, &tele.Video{File: tele.FromURL("http://video.mp4")}) -// +// b.EditMedia(m, &tele.Photo{File: tele.FromDisk("chicken.jpg")}) +// b.EditMedia(m, &tele.Video{File: tele.FromURL("http://video.mp4")}) func (b *Bot) EditMedia(msg Editable, media Inputtable, opts ...interface{}) (*Message, error) { var ( repr string @@ -655,15 +651,14 @@ func (b *Bot) EditMedia(msg Editable, media Inputtable, opts ...interface{}) (*M // Delete removes the message, including service messages. // This function will panic upon nil Editable. // -// - A message can only be deleted if it was sent less than 48 hours ago. -// - A dice message in a private chat can only be deleted if it was sent more than 24 hours ago. -// - Bots can delete outgoing messages in private chats, groups, and supergroups. -// - Bots can delete incoming messages in private chats. -// - Bots granted can_post_messages permissions can delete outgoing messages in channels. -// - If the bot is an administrator of a group, it can delete any message there. -// - If the bot has can_delete_messages permission in a supergroup or a -// channel, it can delete any message there. -// +// - A message can only be deleted if it was sent less than 48 hours ago. +// - A dice message in a private chat can only be deleted if it was sent more than 24 hours ago. +// - Bots can delete outgoing messages in private chats, groups, and supergroups. +// - Bots can delete incoming messages in private chats. +// - Bots granted can_post_messages permissions can delete outgoing messages in channels. +// - If the bot is an administrator of a group, it can delete any message there. +// - If the bot has can_delete_messages permission in a supergroup or a +// channel, it can delete any message there. func (b *Bot) Delete(msg Editable) error { msgID, chatID := msg.MessageSig() @@ -685,8 +680,7 @@ func (b *Bot) Delete(msg Editable) error { // // Currently, Telegram supports only a narrow range of possible // actions, these are aligned as constants of this package. -// -func (b *Bot) Notify(to Recipient, action ChatAction) error { +func (b *Bot) Notify(to Recipient, action ChatAction, threadID ...int) error { if to == nil { return ErrBadRecipient } @@ -696,6 +690,10 @@ func (b *Bot) Notify(to Recipient, action ChatAction) error { "action": string(action), } + if len(threadID) > 0 { + params["message_thread_id"] = strconv.Itoa(threadID[0]) + } + _, err := b.Raw("sendChatAction", params) return err } @@ -705,10 +703,9 @@ func (b *Bot) Notify(to Recipient, action ChatAction) error { // // Example: // -// b.Ship(query) // OK -// b.Ship(query, opts...) // OK with options -// b.Ship(query, "Oops!") // Error message -// +// b.Ship(query) // OK +// b.Ship(query, opts...) // OK with options +// b.Ship(query, "Oops!") // Error message func (b *Bot) Ship(query *ShippingQuery, what ...interface{}) error { params := map[string]string{ "shipping_query_id": query.ID, @@ -761,9 +758,8 @@ func (b *Bot) Accept(query *PreCheckoutQuery, errorMessage ...string) error { // // Example: // -// b.Respond(c) -// b.Respond(c, response) -// +// b.Respond(c) +// b.Respond(c, response) func (b *Bot) Respond(c *Callback, resp ...*CallbackResponse) error { var r *CallbackResponse if resp == nil { @@ -821,7 +817,6 @@ func (b *Bot) AnswerWebApp(query *Query, r Result) (*WebAppMessage, error) { // // Usually, Telegram-provided File objects miss FilePath so you might need to // perform an additional request to fetch them. -// func (b *Bot) FileByID(fileID string) (File, error) { params := map[string]string{ "file_id": fileID, @@ -901,7 +896,6 @@ func (b *Bot) File(file *File) (io.ReadCloser, error) { // // If the message is sent by the bot, returns it, // otherwise returns nil and ErrTrueResult. -// func (b *Bot) StopLiveLocation(msg Editable, opts ...interface{}) (*Message, error) { msgID, chatID := msg.MessageSig() @@ -926,7 +920,6 @@ func (b *Bot) StopLiveLocation(msg Editable, opts ...interface{}) (*Message, err // // It supports ReplyMarkup. // This function will panic upon nil Editable. -// func (b *Bot) StopPoll(msg Editable, opts ...interface{}) (*Poll, error) { msgID, chatID := msg.MessageSig() @@ -966,7 +959,6 @@ func (b *Bot) Leave(chat *Chat) error { // // It supports Silent option. // This function will panic upon nil Editable. -// func (b *Bot) Pin(msg Editable, opts ...interface{}) error { msgID, chatID := msg.MessageSig() @@ -1011,7 +1003,6 @@ func (b *Bot) UnpinAll(chat *Chat) error { // // Including current name of the user for one-on-one conversations, // current username of a user, group or channel, etc. -// func (b *Bot) ChatByID(id int64) (*Chat, error) { return b.ChatByUsername(strconv.FormatInt(id, 10)) } @@ -1109,9 +1100,8 @@ func (b *Bot) MenuButton(chat *User) (*MenuButton, error) { // // It accepts two kinds of menu button arguments: // -// - MenuButtonType for simple menu buttons (default, commands) -// - MenuButton complete structure for web_app menu button type -// +// - MenuButtonType for simple menu buttons (default, commands) +// - MenuButton complete structure for web_app menu button type func (b *Bot) SetMenuButton(chat *User, mb interface{}) error { params := map[string]interface{}{ "chat_id": chat.Recipient(), diff --git a/vendor/gopkg.in/telebot.v3/chat.go b/vendor/gopkg.in/telebot.v3/chat.go index ab767463ca..74d6333bf0 100644 --- a/vendor/gopkg.in/telebot.v3/chat.go +++ b/vendor/gopkg.in/telebot.v3/chat.go @@ -10,13 +10,16 @@ import ( type User struct { ID int64 `json:"id"` - FirstName string `json:"first_name"` - LastName string `json:"last_name"` - Username string `json:"username"` - LanguageCode string `json:"language_code"` - IsBot bool `json:"is_bot"` - IsPremium bool `json:"is_premium"` - AddedToMenu bool `json:"added_to_attachment_menu"` + FirstName string `json:"first_name"` + LastName string `json:"last_name"` + IsForum bool `json:"is_forum"` + Username string `json:"username"` + LanguageCode string `json:"language_code"` + IsBot bool `json:"is_bot"` + IsPremium bool `json:"is_premium"` + AddedToMenu bool `json:"added_to_attachment_menu"` + Usernames []string `json:"active_usernames"` + CustomEmojiStatus string `json:"emoji_status_custom_emoji_id"` // Returns only in getMe CanJoinGroups bool `json:"can_join_groups"` @@ -44,20 +47,22 @@ type Chat struct { Username string `json:"username"` // Returns only in getChat - Bio string `json:"bio,omitempty"` - Photo *ChatPhoto `json:"photo,omitempty"` - Description string `json:"description,omitempty"` - InviteLink string `json:"invite_link,omitempty"` - PinnedMessage *Message `json:"pinned_message,omitempty"` - Permissions *Rights `json:"permissions,omitempty"` - SlowMode int `json:"slow_mode_delay,omitempty"` - StickerSet string `json:"sticker_set_name,omitempty"` - CanSetStickerSet bool `json:"can_set_sticker_set,omitempty"` - LinkedChatID int64 `json:"linked_chat_id,omitempty"` - ChatLocation *ChatLocation `json:"location,omitempty"` - Private bool `json:"has_private_forwards,omitempty"` - Protected bool `json:"has_protected_content,omitempty"` - NoVoiceAndVideo bool `json:"has_restricted_voice_and_video_messages"` + Bio string `json:"bio,omitempty"` + Photo *ChatPhoto `json:"photo,omitempty"` + Description string `json:"description,omitempty"` + InviteLink string `json:"invite_link,omitempty"` + PinnedMessage *Message `json:"pinned_message,omitempty"` + Permissions *Rights `json:"permissions,omitempty"` + SlowMode int `json:"slow_mode_delay,omitempty"` + StickerSet string `json:"sticker_set_name,omitempty"` + CanSetStickerSet bool `json:"can_set_sticker_set,omitempty"` + LinkedChatID int64 `json:"linked_chat_id,omitempty"` + ChatLocation *ChatLocation `json:"location,omitempty"` + Private bool `json:"has_private_forwards,omitempty"` + Protected bool `json:"has_protected_content,omitempty"` + NoVoiceAndVideo bool `json:"has_restricted_voice_and_video_messages"` + HiddenMembers bool `json:"has_hidden_members,omitempty"` + AggressiveAntiSpam bool `json:"has_aggressive_anti_spam_enabled,omitempty"` } // Recipient returns chat ID (see Recipient interface). @@ -101,6 +106,7 @@ type ChatMember struct { Role MemberStatus `json:"status"` Title string `json:"custom_title"` Anonymous bool `json:"is_anonymous"` + Member bool `json:"is_member,omitempty"` // Date when restrictions will be lifted for the user, unix time. // @@ -162,14 +168,13 @@ func (c *ChatMemberUpdate) Time() time.Time { // // Example: // -// group := tele.ChatID(-100756389456) -// b.Send(group, "Hello!") -// -// type Config struct { -// AdminGroup tele.ChatID `json:"admin_group"` -// } -// b.Send(conf.AdminGroup, "Hello!") +// group := tele.ChatID(-100756389456) +// b.Send(group, "Hello!") // +// type Config struct { +// AdminGroup tele.ChatID `json:"admin_group"` +// } +// b.Send(conf.AdminGroup, "Hello!") type ChatID int64 // Recipient returns chat ID (see Recipient interface). @@ -185,6 +190,12 @@ type ChatJoinRequest struct { // Sender is the user that sent the join request. Sender *User `json:"from"` + // UserChatID is an ID of a private chat with the user + // who sent the join request. The bot can use this ID + // for 5 minutes to send messages until the join request + // is processed, assuming no other administrator contacted the user. + UserChatID int64 `json:"user_chat_id"` + // Unixtime, use ChatJoinRequest.Time() to get time.Time. Unixtime int64 `json:"date"` @@ -427,6 +438,9 @@ func (b *Bot) SetGroupPermissions(chat *Chat, perms Rights) error { "chat_id": chat.Recipient(), "permissions": perms, } + if perms.Independent { + params["use_independent_chat_permissions"] = true + } _, err := b.Raw("setChatPermissions", params) return err diff --git a/vendor/gopkg.in/telebot.v3/context.go b/vendor/gopkg.in/telebot.v3/context.go index 9654aaeb59..3306c8f737 100644 --- a/vendor/gopkg.in/telebot.v3/context.go +++ b/vendor/gopkg.in/telebot.v3/context.go @@ -46,12 +46,15 @@ type Context interface { // ChatMember returns chat member changes. ChatMember() *ChatMemberUpdate - // ChatJoinRequest returns cha + // ChatJoinRequest returns the chat join request. ChatJoinRequest() *ChatJoinRequest // Migration returns both migration from and to chat IDs. Migration() (int64, int64) + // Topic returns the topic changes. + Topic() *Topic + // Sender returns the current recipient, depending on the context type. // Returns nil if user is not presented. Sender() *User @@ -240,6 +243,22 @@ func (c *nativeContext) Migration() (int64, int64) { return c.u.Message.MigrateFrom, c.u.Message.MigrateTo } +func (c *nativeContext) Topic() *Topic { + m := c.u.Message + if m == nil { + return nil + } + switch { + case m.TopicCreated != nil: + return m.TopicCreated + case m.TopicReopened != nil: + return m.TopicReopened + case m.TopicEdited != nil: + return m.TopicEdited + } + return nil +} + func (c *nativeContext) Sender() *User { switch { case c.u.Callback != nil: diff --git a/vendor/gopkg.in/telebot.v3/errors.go b/vendor/gopkg.in/telebot.v3/errors.go index 73d6d74e1c..0197e1934e 100644 --- a/vendor/gopkg.in/telebot.v3/errors.go +++ b/vendor/gopkg.in/telebot.v3/errors.go @@ -77,6 +77,7 @@ var ( // Bad request errors var ( ErrBadButtonData = NewError(400, "Bad Request: BUTTON_DATA_INVALID") + ErrBadUserID = NewError(400, "Bad Request: USER_ID_INVALID") ErrBadPollOptions = NewError(400, "Bad Request: expected an Array of String as options") ErrBadURLContent = NewError(400, "Bad Request: failed to get HTTP URL content") ErrCantEditMessage = NewError(400, "Bad Request: message can't be edited") @@ -117,6 +118,10 @@ var ( ErrWrongTypeOfContent = NewError(400, "Bad Request: wrong type of the web page content") ErrWrongURL = NewError(400, "Bad Request: wrong HTTP URL specified") ErrForwardMessage = NewError(400, "Bad Request: administrators of the chat restricted message forwarding") + ErrUserAlreadyParticipant = NewError(400, "Bad Request: USER_ALREADY_PARTICIPANT", "User is already a participant") + ErrHideRequesterMissing = NewError(400, "Bad Request: HIDE_REQUESTER_MISSING") + ErrChannelsTooMuch = NewError(400, "Bad Request: CHANNELS_TOO_MUCH") + ErrChannelsTooMuchUser = NewError(400, "Bad Request: USER_CHANNELS_TOO_MUCH") ) // Forbidden errors @@ -124,6 +129,7 @@ var ( ErrBlockedByUser = NewError(403, "Forbidden: bot was blocked by the user") ErrKickedFromGroup = NewError(403, "Forbidden: bot was kicked from the group chat") ErrKickedFromSuperGroup = NewError(403, "Forbidden: bot was kicked from the supergroup chat") + ErrKickedFromChannel = NewError(403, "Forbidden: bot was kicked from the channel chat") ErrNotStartedByUser = NewError(403, "Forbidden: bot can't initiate conversation with a user") ErrUserIsDeactivated = NewError(403, "Forbidden: user is deactivated") ) @@ -141,6 +147,8 @@ func Err(s string) error { return ErrInternal case ErrBadButtonData.ʔ(): return ErrBadButtonData + case ErrBadUserID.ʔ(): + return ErrBadUserID case ErrBadPollOptions.ʔ(): return ErrBadPollOptions case ErrBadURLContent.ʔ(): @@ -225,12 +233,22 @@ func Err(s string) error { return ErrKickedFromGroup case ErrKickedFromSuperGroup.ʔ(): return ErrKickedFromSuperGroup + case ErrKickedFromChannel.ʔ(): + return ErrKickedFromChannel case ErrNotStartedByUser.ʔ(): return ErrNotStartedByUser case ErrUserIsDeactivated.ʔ(): return ErrUserIsDeactivated case ErrForwardMessage.ʔ(): return ErrForwardMessage + case ErrUserAlreadyParticipant.ʔ(): + return ErrUserAlreadyParticipant + case ErrHideRequesterMissing.ʔ(): + return ErrHideRequesterMissing + case ErrChannelsTooMuch.ʔ(): + return ErrChannelsTooMuch + case ErrChannelsTooMuchUser.ʔ(): + return ErrChannelsTooMuchUser default: return nil } diff --git a/vendor/gopkg.in/telebot.v3/inline.go b/vendor/gopkg.in/telebot.v3/inline.go index b3691393cb..2a88958220 100644 --- a/vendor/gopkg.in/telebot.v3/inline.go +++ b/vendor/gopkg.in/telebot.v3/inline.go @@ -93,9 +93,9 @@ type Results []Result // MarshalJSON makes sure IQRs have proper IDs and Type variables set. func (results Results) MarshalJSON() ([]byte, error) { - for _, result := range results { + for i, result := range results { if result.ResultID() == "" { - result.SetResultID(fmt.Sprintf("%d", &result)) + result.SetResultID(fmt.Sprintf("%d", &results[i])) } if err := inferIQR(result); err != nil { return nil, err diff --git a/vendor/gopkg.in/telebot.v3/markup.go b/vendor/gopkg.in/telebot.v3/markup.go index 77bca6bf94..29236db34e 100644 --- a/vendor/gopkg.in/telebot.v3/markup.go +++ b/vendor/gopkg.in/telebot.v3/markup.go @@ -53,6 +53,9 @@ type ReplyMarkup struct { // Placeholder will be shown in the input field when the reply is active. Placeholder string `json:"input_field_placeholder,omitempty"` + + // IsPersistent allows to control when the keyboard is shown. + IsPersistent bool `json:"is_persistent,omitempty"` } func (r *ReplyMarkup) copy() *ReplyMarkup { @@ -79,17 +82,19 @@ func (r *ReplyMarkup) copy() *ReplyMarkup { // Btn is a constructor button, which will later become either a reply, or an inline button. type Btn struct { - Unique string `json:"unique,omitempty"` - Text string `json:"text,omitempty"` - URL string `json:"url,omitempty"` - Data string `json:"callback_data,omitempty"` - InlineQuery string `json:"switch_inline_query,omitempty"` - InlineQueryChat string `json:"switch_inline_query_current_chat,omitempty"` - Contact bool `json:"request_contact,omitempty"` - Location bool `json:"request_location,omitempty"` - Poll PollType `json:"request_poll,omitempty"` - Login *Login `json:"login_url,omitempty"` - WebApp *WebApp `json:"web_app,omitempty"` + Unique string `json:"unique,omitempty"` + Text string `json:"text,omitempty"` + URL string `json:"url,omitempty"` + Data string `json:"callback_data,omitempty"` + InlineQuery string `json:"switch_inline_query,omitempty"` + InlineQueryChat string `json:"switch_inline_query_current_chat,omitempty"` + Login *Login `json:"login_url,omitempty"` + WebApp *WebApp `json:"web_app,omitempty"` + Contact bool `json:"request_contact,omitempty"` + Location bool `json:"request_location,omitempty"` + Poll PollType `json:"request_poll,omitempty"` + User *ReplyRecipient `json:"request_user,omitempty"` + Chat *ReplyRecipient `json:"request_chat,omitempty"` } // Row represents an array of buttons, a row. @@ -106,7 +111,6 @@ func (r *ReplyMarkup) Row(many ...Btn) Row { // // `Split(3, []Btn{six buttons...}) -> [[1, 2, 3], [4, 5, 6]]` // `Split(2, []Btn{six buttons...}) -> [[1, 2],[3, 4],[5, 6]]` -// func (r *ReplyMarkup) Split(max int, btns []Btn) []Row { rows := make([]Row, (max-1+len(btns))/max) for i, b := range btns { @@ -158,18 +162,6 @@ func (r *ReplyMarkup) Text(text string) Btn { return Btn{Text: text} } -func (r *ReplyMarkup) Contact(text string) Btn { - return Btn{Contact: true, Text: text} -} - -func (r *ReplyMarkup) Location(text string) Btn { - return Btn{Location: true, Text: text} -} - -func (r *ReplyMarkup) Poll(text string, poll PollType) Btn { - return Btn{Poll: poll, Text: text} -} - func (r *ReplyMarkup) Data(text, unique string, data ...string) Btn { return Btn{ Unique: unique, @@ -190,6 +182,26 @@ func (r *ReplyMarkup) QueryChat(text, query string) Btn { return Btn{Text: text, InlineQueryChat: query} } +func (r *ReplyMarkup) Contact(text string) Btn { + return Btn{Contact: true, Text: text} +} + +func (r *ReplyMarkup) Location(text string) Btn { + return Btn{Location: true, Text: text} +} + +func (r *ReplyMarkup) Poll(text string, poll PollType) Btn { + return Btn{Poll: poll, Text: text} +} + +func (r *ReplyMarkup) User(text string, user *ReplyRecipient) Btn { + return Btn{Text: text, User: user} +} + +func (r *ReplyMarkup) Chat(text string, chat *ReplyRecipient) Btn { + return Btn{Text: text, Chat: chat} +} + func (r *ReplyMarkup) Login(text string, login *Login) Btn { return Btn{Login: login, Text: text} } @@ -202,14 +214,15 @@ func (r *ReplyMarkup) WebApp(text string, app *WebApp) Btn { // // Set either Contact or Location to true in order to request // sensitive info, such as user's phone number or current location. -// type ReplyButton struct { Text string `json:"text"` - Contact bool `json:"request_contact,omitempty"` - Location bool `json:"request_location,omitempty"` - Poll PollType `json:"request_poll,omitempty"` - WebApp *WebApp `json:"web_app,omitempty"` + Contact bool `json:"request_contact,omitempty"` + Location bool `json:"request_location,omitempty"` + Poll PollType `json:"request_poll,omitempty"` + User *ReplyRecipient `json:"request_user,omitempty"` + Chat *ReplyRecipient `json:"request_chat,omitempty"` + WebApp *WebApp `json:"web_app,omitempty"` } // MarshalJSON implements json.Marshaler. It allows passing PollType as a @@ -222,6 +235,34 @@ func (pt PollType) MarshalJSON() ([]byte, error) { }) } +// ReplyRecipient combines both KeyboardButtonRequestUser +// and KeyboardButtonRequestChat objects. Use inside ReplyButton +// to request the user or chat sharing with respective settings. +// +// To pass the pointers to bool use a special tele.Flag function, +// that way you will be able to reflect the three-state bool (nil, false, true). +type ReplyRecipient struct { + ID int32 `json:"request_id"` + + Bot *bool `json:"user_is_bot,omitempty"` // user only, optional + Premium *bool `json:"user_is_premium,omitempty"` // user only, optional + + Channel bool `json:"chat_is_channel,omitempty"` // chat only, required + Forum *bool `json:"chat_is_forum,omitempty"` // chat only, optional + WithUsername *bool `json:"chat_has_username,omitempty"` // chat only, optional + Created *bool `json:"chat_is_created,omitempty"` // chat only, optional + UserRights *Rights `json:"user_administrator_rights,omitempty"` // chat only, optional + BotRights *Rights `json:"bot_administrator_rights,omitempty"` // chat only, optional + BotMember *bool `json:"bot_is_member,omitempty"` // chat only, optional +} + +// RecipientShared combines both UserShared and ChatShared objects. +type RecipientShared struct { + ID int32 `json:"request_id"` + UserID int64 `json:"user_id"` + ChatID int64 `json:"chat_id"` +} + // InlineButton represents a button displayed in the message. type InlineButton struct { // Unique slagish name for this kind of button, @@ -279,6 +320,8 @@ func (b Btn) Reply() *ReplyButton { Contact: b.Contact, Location: b.Location, Poll: b.Poll, + User: b.User, + Chat: b.Chat, WebApp: b.WebApp, } } diff --git a/vendor/gopkg.in/telebot.v3/media.go b/vendor/gopkg.in/telebot.v3/media.go index 7dcabce9dc..d161aa58a0 100644 --- a/vendor/gopkg.in/telebot.v3/media.go +++ b/vendor/gopkg.in/telebot.v3/media.go @@ -29,6 +29,7 @@ type InputMedia struct { Performer string `json:"performer,omitempty"` Streaming bool `json:"supports_streaming,omitempty"` DisableTypeDetection bool `json:"disable_content_type_detection,omitempty"` + HasSpoiler bool `json:"is_spoiler,omitempty"` } // Inputtable is a generic type for all kinds of media you @@ -279,15 +280,17 @@ func (v *VideoNote) MediaFile() *File { // Sticker object represents a WebP image, so-called sticker. type Sticker struct { File - Width int `json:"width"` - Height int `json:"height"` - Animated bool `json:"is_animated"` - Video bool `json:"is_video"` - Thumbnail *Photo `json:"thumb"` - Emoji string `json:"emoji"` - SetName string `json:"set_name"` - MaskPosition *MaskPosition `json:"mask_position"` - PremiumAnimation *File `json:"premium_animation"` + Width int `json:"width"` + Height int `json:"height"` + Animated bool `json:"is_animated"` + Video bool `json:"is_video"` + Thumbnail *Photo `json:"thumb"` + Emoji string `json:"emoji"` + SetName string `json:"set_name"` + MaskPosition *MaskPosition `json:"mask_position"` + PremiumAnimation *File `json:"premium_animation"` + Type StickerSetType `json:"type"` + CustomEmoji string `json:"custom_emoji_id"` } func (s *Sticker) MediaType() string { diff --git a/vendor/gopkg.in/telebot.v3/message.go b/vendor/gopkg.in/telebot.v3/message.go index 47c072194e..82997569a3 100644 --- a/vendor/gopkg.in/telebot.v3/message.go +++ b/vendor/gopkg.in/telebot.v3/message.go @@ -10,6 +10,9 @@ import ( type Message struct { ID int `json:"message_id"` + // (Optional) Unique identifier of a message thread to which the message belongs; for supergroups only + ThreadID int `json:"message_thread_id"` + // For message sent to channels, Sender will be nil Sender *User `json:"from"` @@ -59,6 +62,9 @@ type Message struct { // (Optional) Time of last edit in Unix. LastEdit int64 `json:"edit_date"` + // (Optional) True, if the message is sent to a forum topic. + TopicMessage bool `json:"is_topic_message"` + // (Optional) Message can't be forwarded. Protected bool `json:"has_protected_content,omitempty"` @@ -223,6 +229,12 @@ type Message struct { // Message is a service message about a successful payment. Payment *Payment `json:"successful_payment"` + // For a service message, a user was shared with the bot. + UserShared *RecipientShared `json:"user_shared,omitempty"` + + // For a service message, a chat was shared with the bot. + ChatShared *RecipientShared `json:"chat_shared,omitempty"` + // The domain name of the website on which the user has logged in. ConnectedWebsite string `json:"connected_website,omitempty"` @@ -250,6 +262,30 @@ type Message struct { // Inline keyboard attached to the message. ReplyMarkup *ReplyMarkup `json:"reply_markup,omitempty"` + + // Service message: forum topic created + TopicCreated *Topic `json:"forum_topic_created,omitempty"` + + // Service message: forum topic closed + TopicClosed *struct{} `json:"forum_topic_closed,omitempty"` + + // Service message: forum topic reopened + TopicReopened *Topic `json:"forum_topic_reopened,omitempty"` + + // Service message: forum topic deleted + TopicEdited *Topic `json:"forum_topic_edited,omitempty"` + + // Service message: general forum topic hidden + GeneralTopicHidden *struct{} `json:"general_topic_hidden,omitempty"` + + // Service message: general forum topic unhidden + GeneralTopicUnhidden *struct{} `json:"general_topic_unhidden,omitempty"` + + // Service message: represents spoiler information about the message. + HasMediaSpoiler bool `json:"has_media_spoiler,omitempty"` + + // Service message: the user allowed the bot added to the attachment menu to write messages + WriteAccessAllowed *WriteAccessAllowed `json:"write_access_allowed,omitempty"` } // MessageEntity object represents "special" parts of text messages, @@ -365,7 +401,6 @@ func (m *Message) FromChannel() bool { // Service messages are automatically sent messages, which // typically occur on some global action. For instance, when // anyone leaves the chat or chat title changes. -// func (m *Message) IsService() bool { fact := false @@ -386,7 +421,6 @@ func (m *Message) IsService() bool { // // It's safer than manually slicing Text because Telegram uses // UTF-16 indices whereas Go string are []byte. -// func (m *Message) EntityText(e MessageEntity) string { text := m.Text if text == "" { diff --git a/vendor/gopkg.in/telebot.v3/middleware.go b/vendor/gopkg.in/telebot.v3/middleware.go index aa21ca2e06..a8e2912a5a 100644 --- a/vendor/gopkg.in/telebot.v3/middleware.go +++ b/vendor/gopkg.in/telebot.v3/middleware.go @@ -4,6 +4,15 @@ package telebot // which get called before the endpoint group or specific handler. type MiddlewareFunc func(HandlerFunc) HandlerFunc +func appendMiddleware(a, b []MiddlewareFunc) []MiddlewareFunc { + if len(a) == 0 { + return b + } + + m := make([]MiddlewareFunc, 0, len(a)+len(b)) + return append(m, append(a, b...)...) +} + func applyMiddleware(h HandlerFunc, m ...MiddlewareFunc) HandlerFunc { for i := len(m) - 1; i >= 0; i-- { h = m[i](h) @@ -25,5 +34,5 @@ func (g *Group) Use(middleware ...MiddlewareFunc) { // Handle adds endpoint handler to the bot, combining group's middleware // with the optional given middleware. func (g *Group) Handle(endpoint interface{}, h HandlerFunc, m ...MiddlewareFunc) { - g.b.Handle(endpoint, h, append(g.middleware, m...)...) + g.b.Handle(endpoint, h, appendMiddleware(g.middleware, m)...) } diff --git a/vendor/gopkg.in/telebot.v3/options.go b/vendor/gopkg.in/telebot.v3/options.go index 2aa28055ec..56e0d9c295 100644 --- a/vendor/gopkg.in/telebot.v3/options.go +++ b/vendor/gopkg.in/telebot.v3/options.go @@ -11,7 +11,6 @@ import ( // flags instead. // // Supported options are defined as iota-constants. -// type Option int const ( @@ -54,7 +53,6 @@ func Placeholder(text string) *SendOptions { // Despite its power, SendOptions is rather inconvenient to use all // the way through bot logic, so you might want to consider storing // and re-using it somewhere or be using Option flags instead. -// type SendOptions struct { // If the message is a reply, original message. ReplyTo *Message @@ -77,8 +75,15 @@ type SendOptions struct { // AllowWithoutReply allows sending messages not a as reply if the replied-to message has already been deleted. AllowWithoutReply bool - // Protected protects the contents of the sent message from forwarding and saving + // Protected protects the contents of sent message from forwarding and saving. Protected bool + + // ThreadID supports sending messages to a thread. + ThreadID int + + // HasSpoiler marks the message as containing a spoiler. + HasSpoiler bool + } func (og *SendOptions) copy() *SendOptions { @@ -189,6 +194,14 @@ func (b *Bot) embedSendOptions(params map[string]string, opt *SendOptions) { if opt.Protected { params["protect_content"] = "true" } + + if opt.ThreadID != 0 { + params["message_thread_id"] = strconv.Itoa(opt.ThreadID) + } + + if opt.HasSpoiler { + params["spoiler"] = "true" + } } func processButtons(keys [][]InlineButton) { diff --git a/vendor/gopkg.in/telebot.v3/sendable.go b/vendor/gopkg.in/telebot.v3/sendable.go index 2e782e33a7..ecaae7fed1 100644 --- a/vendor/gopkg.in/telebot.v3/sendable.go +++ b/vendor/gopkg.in/telebot.v3/sendable.go @@ -18,7 +18,6 @@ type Recipient interface { // This is pretty cool, since it lets bots implement // custom Sendables for complex kind of media or // chat objects spanning across multiple messages. -// type Sendable interface { Send(*Bot, Recipient, *SendOptions) (*Message, error) } diff --git a/vendor/gopkg.in/telebot.v3/telebot.go b/vendor/gopkg.in/telebot.v3/telebot.go index 2aa1cd9a81..b8271e9a4d 100644 --- a/vendor/gopkg.in/telebot.v3/telebot.go +++ b/vendor/gopkg.in/telebot.v3/telebot.go @@ -2,29 +2,28 @@ // // Example: // -// package main +// package main // -// import ( -// "time" -// tele "gopkg.in/telebot.v3" -// ) +// import ( +// "time" +// tele "gopkg.in/telebot.v3" +// ) // -// func main() { -// b, err := tele.NewBot(tele.Settings{ -// Token: "...", -// Poller: &tele.LongPoller{Timeout: 10 * time.Second}, -// }) -// if err != nil { -// return -// } -// -// b.Handle("/start", func(c tele.Context) error { -// return c.Send("Hello world!") -// }) -// -// b.Start() +// func main() { +// b, err := tele.NewBot(tele.Settings{ +// Token: "...", +// Poller: &tele.LongPoller{Timeout: 10 * time.Second}, +// }) +// if err != nil { +// return // } // +// b.Handle("/start", func(c tele.Context) error { +// return c.Send("Hello world!") +// }) +// +// b.Start() +// } package telebot import "errors" @@ -43,35 +42,43 @@ const DefaultApiURL = "https://api.telegram.org" // // For convenience, all Telebot-provided endpoints start with // an "alert" character \a. -// const ( // Basic message handlers. - OnText = "\atext" - OnEdited = "\aedited" - OnPhoto = "\aphoto" - OnAudio = "\aaudio" - OnAnimation = "\aanimation" - OnDocument = "\adocument" - OnSticker = "\asticker" - OnVideo = "\avideo" - OnVoice = "\avoice" - OnVideoNote = "\avideo_note" - OnContact = "\acontact" - OnLocation = "\alocation" - OnVenue = "\avenue" - OnDice = "\adice" - OnInvoice = "\ainvoice" - OnPayment = "\apayment" - OnGame = "\agame" - OnPoll = "\apoll" - OnPollAnswer = "\apoll_answer" - OnPinned = "\apinned" - OnChannelPost = "\achannel_post" - OnEditedChannelPost = "\aedited_channel_post" + OnText = "\atext" + OnEdited = "\aedited" + OnPhoto = "\aphoto" + OnAudio = "\aaudio" + OnAnimation = "\aanimation" + OnDocument = "\adocument" + OnSticker = "\asticker" + OnVideo = "\avideo" + OnVoice = "\avoice" + OnVideoNote = "\avideo_note" + OnContact = "\acontact" + OnLocation = "\alocation" + OnVenue = "\avenue" + OnDice = "\adice" + OnInvoice = "\ainvoice" + OnPayment = "\apayment" + OnGame = "\agame" + OnPoll = "\apoll" + OnPollAnswer = "\apoll_answer" + OnPinned = "\apinned" + OnChannelPost = "\achannel_post" + OnEditedChannelPost = "\aedited_channel_post" + OnTopicCreated = "\atopic_created" + OnTopicReopened = "\atopic_reopened" + OnTopicClosed = "\atopic_closed" + OnTopicEdited = "\atopic_edited" + OnGeneralTopicHidden = "\ageneral_topic_hidden" + OnGeneralTopicUnhidden = "\ageneral_topic_unhidden" + OnWriteAccessAllowed = "\awrite_access_allowed" OnAddedToGroup = "\aadded_to_group" OnUserJoined = "\auser_joined" OnUserLeft = "\auser_left" + OnUserShared = "\auser_shared" + OnChatShared = "\achat_shared" OnNewGroupTitle = "\anew_chat_title" OnNewGroupPhoto = "\anew_chat_photo" OnGroupPhotoDeleted = "\achat_photo_deleted" @@ -131,6 +138,13 @@ const ( ModeHTML ParseMode = "HTML" ) -// M is a shortcut for map[string]interface{}. Use it for passing -// arguments to the layout functions. +// M is a shortcut for map[string]interface{}. +// Useful for passing arguments to the layout functions. type M = map[string]interface{} + +// Flag returns a pointer to the given bool. +// Useful for passing the three-state flags to a Bot API. +// For example, see ReplyRecipient type. +func Flag(b bool) *bool { + return &b +} diff --git a/vendor/gopkg.in/telebot.v3/topic.go b/vendor/gopkg.in/telebot.v3/topic.go new file mode 100644 index 0000000000..d81fe9a943 --- /dev/null +++ b/vendor/gopkg.in/telebot.v3/topic.go @@ -0,0 +1,172 @@ +package telebot + +import ( + "encoding/json" + "strconv" +) + +type Topic struct { + Name string `json:"name"` + IconColor int `json:"icon_color"` + IconCustomEmojiID string `json:"icon_custom_emoji_id"` + ThreadID int `json:"message_thread_id"` +} + +// CreateTopic creates a topic in a forum supergroup chat. +func (b *Bot) CreateTopic(chat *Chat, topic *Topic) (*Topic, error) { + params := map[string]string{ + "chat_id": chat.Recipient(), + "name": topic.Name, + } + + if topic.IconColor != 0 { + params["icon_color"] = strconv.Itoa(topic.IconColor) + } + if topic.IconCustomEmojiID != "" { + params["icon_custom_emoji_id"] = topic.IconCustomEmojiID + } + + data, err := b.Raw("createForumTopic", params) + if err != nil { + return nil, err + } + + var resp struct { + Result *Topic + } + if err := json.Unmarshal(data, &resp); err != nil { + return nil, wrapError(err) + } + return resp.Result, err +} + +// EditTopic edits name and icon of a topic in a forum supergroup chat. +func (b *Bot) EditTopic(chat *Chat, topic *Topic) error { + params := map[string]interface{}{ + "chat_id": chat.Recipient(), + "message_thread_id": topic.ThreadID, + } + + if topic.Name != "" { + params["name"] = topic.Name + } + if topic.IconCustomEmojiID != "" { + params["icon_custom_emoji_id"] = topic.IconCustomEmojiID + } + + _, err := b.Raw("editForumTopic", params) + return err +} + +// CloseTopic closes an open topic in a forum supergroup chat. +func (b *Bot) CloseTopic(chat *Chat, topic *Topic) error { + params := map[string]interface{}{ + "chat_id": chat.Recipient(), + "message_thread_id": topic.ThreadID, + } + + _, err := b.Raw("closeForumTopic", params) + return err +} + +// ReopenTopic reopens a closed topic in a forum supergroup chat. +func (b *Bot) ReopenTopic(chat *Chat, topic *Topic) error { + params := map[string]interface{}{ + "chat_id": chat.Recipient(), + "message_thread_id": topic.ThreadID, + } + + _, err := b.Raw("reopenForumTopic", params) + return err +} + +// DeleteTopic deletes a forum topic along with all its messages in a forum supergroup chat. +func (b *Bot) DeleteTopic(chat *Chat, topic *Topic) error { + params := map[string]interface{}{ + "chat_id": chat.Recipient(), + "message_thread_id": topic.ThreadID, + } + + _, err := b.Raw("deleteForumTopic", params) + return err +} + +// UnpinAllTopicMessages clears the list of pinned messages in a forum topic. The bot must be an administrator in the chat for this to work and must have the can_pin_messages administrator right in the supergroup. +func (b *Bot) UnpinAllTopicMessages(chat *Chat, topic *Topic) error { + params := map[string]interface{}{ + "chat_id": chat.Recipient(), + "message_thread_id": topic.ThreadID, + } + + _, err := b.Raw("unpinAllForumTopicMessages", params) + return err +} + +// TopicIconStickers gets custom emoji stickers, which can be used as a forum topic icon by any user. +func (b *Bot) TopicIconStickers() ([]Sticker, error) { + params := map[string]string{} + + data, err := b.Raw("getForumTopicIconStickers", params) + if err != nil { + return nil, err + } + + var resp struct { + Result []Sticker + } + if err := json.Unmarshal(data, &resp); err != nil { + return nil, wrapError(err) + } + return resp.Result, nil +} + +// EditGeneralTopic edits name of the 'General' topic in a forum supergroup chat. +func (b *Bot) EditGeneralTopic(chat *Chat, topic *Topic) error { + params := map[string]interface{}{ + "chat_id": chat.Recipient(), + "name": topic.Name, + } + + _, err := b.Raw("editGeneralForumTopic", params) + return err +} + +// CloseGeneralTopic closes an open 'General' topic in a forum supergroup chat. +func (b *Bot) CloseGeneralTopic(chat *Chat) error { + params := map[string]interface{}{ + "chat_id": chat.Recipient(), + } + + _, err := b.Raw("closeGeneralForumTopic", params) + return err +} + +// ReopenGeneralTopic reopens a closed 'General' topic in a forum supergroup chat. +func (b *Bot) ReopenGeneralTopic(chat *Chat) error { + params := map[string]interface{}{ + "chat_id": chat.Recipient(), + } + + _, err := b.Raw("reopenGeneralForumTopic", params) + return err +} + +// HideGeneralTopic hides the 'General' topic in a forum supergroup chat. +func (b *Bot) HideGeneralTopic(chat *Chat) error { + params := map[string]interface{}{ + "chat_id": chat.Recipient(), + } + + _, err := b.Raw("hideGeneralForumTopic", params) + return err +} + +// UnhideGeneralTopic unhides the 'General' topic in a forum supergroup chat. +func (b *Bot) UnhideGeneralTopic(chat *Chat) error { + params := map[string]interface{}{ + "chat_id": chat.Recipient(), + } + + _, err := b.Raw("unhideGeneralForumTopic", params) + return err +} diff --git a/vendor/gopkg.in/telebot.v3/update.go b/vendor/gopkg.in/telebot.v3/update.go index 76da7cd8f7..12a065ab22 100644 --- a/vendor/gopkg.in/telebot.v3/update.go +++ b/vendor/gopkg.in/telebot.v3/update.go @@ -99,6 +99,35 @@ func (b *Bot) ProcessUpdate(u Update) { return } + if m.TopicCreated != nil { + b.handle(OnTopicCreated, c) + return + } + if m.TopicReopened != nil { + b.handle(OnTopicReopened, c) + return + } + if m.TopicClosed != nil { + b.handle(OnTopicClosed, c) + return + } + if m.TopicEdited != nil { + b.handle(OnTopicEdited, c) + return + } + if m.GeneralTopicHidden != nil { + b.handle(OnGeneralTopicHidden, c) + return + } + if m.GeneralTopicUnhidden != nil { + b.handle(OnGeneralTopicUnhidden, c) + return + } + if m.WriteAccessAllowed != nil { + b.handle(OnWriteAccessAllowed, c) + return + } + wasAdded := (m.UserJoined != nil && m.UserJoined.ID == b.Me.ID) || (m.UsersJoined != nil && isUserInList(b.Me, m.UsersJoined)) if m.GroupCreated || m.SuperGroupCreated || wasAdded { @@ -110,7 +139,6 @@ func (b *Bot) ProcessUpdate(u Update) { b.handle(OnUserJoined, c) return } - if m.UsersJoined != nil { for _, user := range m.UsersJoined { m.UserJoined = &user @@ -118,22 +146,28 @@ func (b *Bot) ProcessUpdate(u Update) { } return } - if m.UserLeft != nil { b.handle(OnUserLeft, c) return } + if m.UserShared != nil { + b.handle(OnUserShared, c) + return + } + if m.ChatShared != nil { + b.handle(OnChatShared, c) + return + } + if m.NewGroupTitle != "" { b.handle(OnNewGroupTitle, c) return } - if m.NewGroupPhoto != nil { b.handle(OnNewGroupPhoto, c) return } - if m.GroupPhotoDeleted { b.handle(OnGroupPhotoDeleted, c) return @@ -143,12 +177,10 @@ func (b *Bot) ProcessUpdate(u Update) { b.handle(OnGroupCreated, c) return } - if m.SuperGroupCreated { b.handle(OnSuperGroupCreated, c) return } - if m.ChannelCreated { b.handle(OnChannelCreated, c) return @@ -164,17 +196,14 @@ func (b *Bot) ProcessUpdate(u Update) { b.handle(OnVideoChatStarted, c) return } - if m.VideoChatEnded != nil { b.handle(OnVideoChatEnded, c) return } - if m.VideoChatParticipants != nil { b.handle(OnVideoChatParticipants, c) return } - if m.VideoChatScheduled != nil { b.handle(OnVideoChatScheduled, c) return @@ -182,13 +211,13 @@ func (b *Bot) ProcessUpdate(u Update) { if m.WebAppData != nil { b.handle(OnWebApp, c) + return } if m.ProximityAlert != nil { b.handle(OnProximityAlert, c) return } - if m.AutoDeleteTimer != nil { b.handle(OnAutoDeleteTimer, c) return diff --git a/vendor/gopkg.in/telebot.v3/video_chat.go b/vendor/gopkg.in/telebot.v3/video_chat.go index 448db4161e..4952e36b4e 100644 --- a/vendor/gopkg.in/telebot.v3/video_chat.go +++ b/vendor/gopkg.in/telebot.v3/video_chat.go @@ -2,26 +2,28 @@ package telebot import "time" -// VideoChatStarted represents a service message about a video chat -// started in the chat. -type VideoChatStarted struct{} +type ( + // VideoChatStarted represents a service message about a video chat + // started in the chat. + VideoChatStarted struct{} -// VideoChatEnded represents a service message about a video chat -// ended in the chat. -type VideoChatEnded struct { - Duration int `json:"duration"` // in seconds -} + // VideoChatEnded represents a service message about a video chat + // ended in the chat. + VideoChatEnded struct { + Duration int `json:"duration"` // in seconds + } -// VideoChatParticipants represents a service message about new -// members invited to a video chat -type VideoChatParticipants struct { - Users []User `json:"users"` -} + // VideoChatParticipants represents a service message about new + // members invited to a video chat + VideoChatParticipants struct { + Users []User `json:"users"` + } -// VideoChatScheduled represents a service message about a video chat scheduled in the chat. -type VideoChatScheduled struct { - Unixtime int64 `json:"start_date"` -} + // VideoChatScheduled represents a service message about a video chat scheduled in the chat. + VideoChatScheduled struct { + Unixtime int64 `json:"start_date"` + } +) // StartsAt returns the point when the video chat is supposed to be started by a chat administrator. func (v *VideoChatScheduled) StartsAt() time.Time { diff --git a/vendor/gopkg.in/telebot.v3/web_app.go b/vendor/gopkg.in/telebot.v3/web_app.go index 841378416a..e5c9070f2c 100644 --- a/vendor/gopkg.in/telebot.v3/web_app.go +++ b/vendor/gopkg.in/telebot.v3/web_app.go @@ -16,3 +16,9 @@ type WebAppData struct { Data string `json:"data"` Text string `json:"button_text"` } + +// WebAppAccessAllowed represents a service message about a user allowing +// a bot to write messages after adding the bot to the attachment menu or launching a Web App from a link. +type WriteAccessAllowed struct { + WebAppName string `json:"web_app_name,omitempty"` +} diff --git a/vendor/gopkg.in/telebot.v3/webhook.go b/vendor/gopkg.in/telebot.v3/webhook.go index 13e99bcdfd..5a48d6c3b3 100644 --- a/vendor/gopkg.in/telebot.v3/webhook.go +++ b/vendor/gopkg.in/telebot.v3/webhook.go @@ -119,7 +119,7 @@ func (h *Webhook) getParams() map[string]string { func (h *Webhook) Poll(b *Bot, dest chan Update, stop chan struct{}) { if err := b.SetWebhook(h); err != nil { - b.debug(err) + b.OnError(err, nil) close(stop) return } diff --git a/vendor/modules.txt b/vendor/modules.txt index 53932ae5ae..a0fe59bffa 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,26 +1,26 @@ -# cloud.google.com/go v0.111.0 +# cloud.google.com/go v0.112.0 ## explicit; go 1.19 cloud.google.com/go/internal cloud.google.com/go/internal/optional cloud.google.com/go/internal/trace cloud.google.com/go/internal/version -# cloud.google.com/go/compute v1.23.3 +# cloud.google.com/go/compute v1.23.4 ## explicit; go 1.19 cloud.google.com/go/compute/internal # cloud.google.com/go/compute/metadata v0.2.3 ## explicit; go 1.19 cloud.google.com/go/compute/metadata -# cloud.google.com/go/iam v1.1.5 +# cloud.google.com/go/iam v1.1.6 ## explicit; go 1.19 cloud.google.com/go/iam cloud.google.com/go/iam/apiv1/iampb -# cloud.google.com/go/storage v1.35.1 +# cloud.google.com/go/storage v1.36.0 ## explicit; go 1.19 cloud.google.com/go/storage cloud.google.com/go/storage/internal cloud.google.com/go/storage/internal/apiv2 cloud.google.com/go/storage/internal/apiv2/storagepb -# github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.2 +# github.com/Azure/azure-sdk-for-go/sdk/azcore v1.10.0 ## explicit; go 1.18 github.com/Azure/azure-sdk-for-go/sdk/azcore github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/internal/resource @@ -127,7 +127,7 @@ github.com/armon/go-metrics/prometheus # github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 ## explicit; go 1.13 github.com/asaskevich/govalidator -# github.com/aws/aws-sdk-go v1.50.25 +# github.com/aws/aws-sdk-go v1.50.32 ## explicit; go 1.19 github.com/aws/aws-sdk-go/aws github.com/aws/aws-sdk-go/aws/auth/bearer @@ -358,7 +358,7 @@ github.com/go-openapi/analysis/internal/flatten/operations github.com/go-openapi/analysis/internal/flatten/replace github.com/go-openapi/analysis/internal/flatten/schutils github.com/go-openapi/analysis/internal/flatten/sortref -# github.com/go-openapi/errors v0.21.0 +# github.com/go-openapi/errors v0.21.1 ## explicit; go 1.19 github.com/go-openapi/errors # github.com/go-openapi/jsonpointer v0.20.2 @@ -386,13 +386,13 @@ github.com/go-openapi/runtime/yamlpc # github.com/go-openapi/spec v0.20.14 => github.com/go-openapi/spec v0.20.6 ## explicit; go 1.13 github.com/go-openapi/spec -# github.com/go-openapi/strfmt v0.22.0 +# github.com/go-openapi/strfmt v0.22.2 ## explicit; go 1.19 github.com/go-openapi/strfmt # github.com/go-openapi/swag v0.22.9 ## explicit; go 1.19 github.com/go-openapi/swag -# github.com/go-openapi/validate v0.22.6 +# github.com/go-openapi/validate v0.23.0 ## explicit; go 1.19 github.com/go-openapi/validate # github.com/go-redis/redis/v8 v8.11.5 @@ -439,11 +439,9 @@ github.com/golang-migrate/migrate/v4/source/iofs ## explicit github.com/golang/groupcache/lru github.com/golang/groupcache/singleflight -# github.com/golang/protobuf v1.5.3 -## explicit; go 1.9 -github.com/golang/protobuf/jsonpb +# github.com/golang/protobuf v1.5.4 +## explicit; go 1.17 github.com/golang/protobuf/proto -github.com/golang/protobuf/ptypes github.com/golang/protobuf/ptypes/any github.com/golang/protobuf/ptypes/duration github.com/golang/protobuf/ptypes/empty @@ -462,7 +460,7 @@ github.com/google/go-cmp/cmp/internal/diff github.com/google/go-cmp/cmp/internal/flags github.com/google/go-cmp/cmp/internal/function github.com/google/go-cmp/cmp/internal/value -# github.com/google/pprof v0.0.0-20240117000934-35fc243c5815 +# github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7 ## explicit; go 1.19 github.com/google/pprof/profile # github.com/google/s2a-go v0.1.7 @@ -495,7 +493,7 @@ github.com/google/uuid ## explicit; go 1.19 github.com/googleapis/enterprise-certificate-proxy/client github.com/googleapis/enterprise-certificate-proxy/client/util -# github.com/googleapis/gax-go/v2 v2.12.0 +# github.com/googleapis/gax-go/v2 v2.12.2 ## explicit; go 1.19 github.com/googleapis/gax-go/v2 github.com/googleapis/gax-go/v2/apierror @@ -519,12 +517,12 @@ github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tags github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/tracing github.com/grpc-ecosystem/go-grpc-middleware/v2/util/metautils -# github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 -## explicit; go 1.17 +# github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 +## explicit; go 1.19 github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule github.com/grpc-ecosystem/grpc-gateway/v2/runtime github.com/grpc-ecosystem/grpc-gateway/v2/utilities -# github.com/hashicorp/consul/api v1.27.0 +# github.com/hashicorp/consul/api v1.28.2 ## explicit; go 1.19 github.com/hashicorp/consul/api # github.com/hashicorp/errwrap v1.1.0 @@ -558,9 +556,10 @@ github.com/hashicorp/go-version ## explicit; go 1.12 github.com/hashicorp/golang-lru github.com/hashicorp/golang-lru/simplelru -# github.com/hashicorp/golang-lru/v2 v2.0.2 +# github.com/hashicorp/golang-lru/v2 v2.0.7 ## explicit; go 1.18 github.com/hashicorp/golang-lru/v2 +github.com/hashicorp/golang-lru/v2/internal github.com/hashicorp/golang-lru/v2/simplelru # github.com/hashicorp/memberlist v0.5.0 => github.com/grafana/memberlist v0.3.1-0.20220714140823-09ffed8adbbe ## explicit; go 1.12 @@ -586,8 +585,8 @@ github.com/json-iterator/go # github.com/julienschmidt/httprouter v1.3.0 ## explicit; go 1.7 github.com/julienschmidt/httprouter -# github.com/klauspost/compress v1.17.6 -## explicit; go 1.19 +# github.com/klauspost/compress v1.17.7 +## explicit; go 1.20 github.com/klauspost/compress github.com/klauspost/compress/flate github.com/klauspost/compress/fse @@ -715,11 +714,10 @@ github.com/pmezard/go-difflib/difflib # github.com/prometheus-community/prom-label-proxy v0.8.1-0.20240127162815-c1195f9aabc0 ## explicit; go 1.20 github.com/prometheus-community/prom-label-proxy/injectproxy -# github.com/prometheus/alertmanager v0.26.0 -## explicit; go 1.18 +# github.com/prometheus/alertmanager v0.27.0 +## explicit; go 1.21 github.com/prometheus/alertmanager/api github.com/prometheus/alertmanager/api/metrics -github.com/prometheus/alertmanager/api/v1 github.com/prometheus/alertmanager/api/v2 github.com/prometheus/alertmanager/api/v2/client github.com/prometheus/alertmanager/api/v2/client/alert @@ -740,7 +738,10 @@ github.com/prometheus/alertmanager/cluster github.com/prometheus/alertmanager/cluster/clusterpb github.com/prometheus/alertmanager/config github.com/prometheus/alertmanager/dispatch +github.com/prometheus/alertmanager/featurecontrol github.com/prometheus/alertmanager/inhibit +github.com/prometheus/alertmanager/matchers/compat +github.com/prometheus/alertmanager/matchers/parse github.com/prometheus/alertmanager/nflog github.com/prometheus/alertmanager/nflog/nflogpb github.com/prometheus/alertmanager/notify @@ -767,12 +768,13 @@ github.com/prometheus/alertmanager/template github.com/prometheus/alertmanager/timeinterval github.com/prometheus/alertmanager/types github.com/prometheus/alertmanager/ui -# github.com/prometheus/client_golang v1.18.0 -## explicit; go 1.19 +# github.com/prometheus/client_golang v1.19.0 +## explicit; go 1.20 github.com/prometheus/client_golang/api github.com/prometheus/client_golang/api/prometheus/v1 github.com/prometheus/client_golang/prometheus github.com/prometheus/client_golang/prometheus/collectors +github.com/prometheus/client_golang/prometheus/collectors/version github.com/prometheus/client_golang/prometheus/internal github.com/prometheus/client_golang/prometheus/promauto github.com/prometheus/client_golang/prometheus/promhttp @@ -780,11 +782,11 @@ github.com/prometheus/client_golang/prometheus/push github.com/prometheus/client_golang/prometheus/testutil github.com/prometheus/client_golang/prometheus/testutil/promlint github.com/prometheus/client_golang/prometheus/testutil/promlint/validations -# github.com/prometheus/client_model v0.5.0 +# github.com/prometheus/client_model v0.6.0 ## explicit; go 1.19 github.com/prometheus/client_model/go -# github.com/prometheus/common v0.47.0 -## explicit; go 1.20 +# github.com/prometheus/common v0.49.1-0.20240306132007-4199f18c3e92 +## explicit; go 1.21 github.com/prometheus/common/config github.com/prometheus/common/expfmt github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg @@ -802,7 +804,7 @@ github.com/prometheus/exporter-toolkit/web github.com/prometheus/procfs github.com/prometheus/procfs/internal/fs github.com/prometheus/procfs/internal/util -# github.com/prometheus/prometheus v0.50.2-0.20240229164915-d5f0a240faad +# github.com/prometheus/prometheus v0.51.1-0.20240328124728-d81e41d58ec8 ## explicit; go 1.21 github.com/prometheus/prometheus/config github.com/prometheus/prometheus/discovery @@ -863,7 +865,7 @@ github.com/prometheus/prometheus/web/api/v1 github.com/redis/rueidis github.com/redis/rueidis/internal/cmds github.com/redis/rueidis/internal/util -# github.com/rs/cors v1.9.0 +# github.com/rs/cors v1.10.1 ## explicit; go 1.13 github.com/rs/cors # github.com/rs/xid v1.5.0 @@ -900,11 +902,11 @@ github.com/sony/gobreaker github.com/spf13/afero github.com/spf13/afero/internal/common github.com/spf13/afero/mem -# github.com/stretchr/objx v0.5.0 -## explicit; go 1.12 -github.com/stretchr/objx -# github.com/stretchr/testify v1.8.4 +# github.com/stretchr/objx v0.5.2 ## explicit; go 1.20 +github.com/stretchr/objx +# github.com/stretchr/testify v1.9.0 +## explicit; go 1.17 github.com/stretchr/testify/assert github.com/stretchr/testify/mock github.com/stretchr/testify/require @@ -918,8 +920,8 @@ github.com/thanos-io/objstore/providers/gcs github.com/thanos-io/objstore/providers/s3 github.com/thanos-io/objstore/providers/swift github.com/thanos-io/objstore/tracing/opentracing -# github.com/thanos-io/promql-engine v0.0.0-20240318110350-23714ea2522d -## explicit; go 1.20 +# github.com/thanos-io/promql-engine v0.0.0-20240327143517-c5e4b2e6ef02 +## explicit; go 1.21 github.com/thanos-io/promql-engine/api github.com/thanos-io/promql-engine/engine github.com/thanos-io/promql-engine/execution @@ -941,7 +943,7 @@ github.com/thanos-io/promql-engine/query github.com/thanos-io/promql-engine/ringbuffer github.com/thanos-io/promql-engine/storage github.com/thanos-io/promql-engine/storage/prometheus -# github.com/thanos-io/thanos v0.34.2-0.20240327180044-4d7a75f40ae1 +# github.com/thanos-io/thanos v0.34.2-0.20240328185924-943401f726ed ## explicit; go 1.21 github.com/thanos-io/thanos/pkg/block github.com/thanos-io/thanos/pkg/block/indexheader @@ -1065,8 +1067,8 @@ go.etcd.io/etcd/client/v3 go.etcd.io/etcd/client/v3/credentials go.etcd.io/etcd/client/v3/internal/endpoint go.etcd.io/etcd/client/v3/internal/resolver -# go.mongodb.org/mongo-driver v1.13.1 -## explicit; go 1.13 +# go.mongodb.org/mongo-driver v1.14.0 +## explicit; go 1.18 go.mongodb.org/mongo-driver/bson go.mongodb.org/mongo-driver/bson/bsoncodec go.mongodb.org/mongo-driver/bson/bsonoptions @@ -1093,11 +1095,11 @@ go.opencensus.io/trace go.opencensus.io/trace/internal go.opencensus.io/trace/propagation go.opencensus.io/trace/tracestate -# go.opentelemetry.io/collector/featuregate v1.0.1 -## explicit; go 1.20 +# go.opentelemetry.io/collector/featuregate v1.3.0 +## explicit; go 1.21 go.opentelemetry.io/collector/featuregate -# go.opentelemetry.io/collector/pdata v1.0.1 -## explicit; go 1.20 +# go.opentelemetry.io/collector/pdata v1.3.0 +## explicit; go 1.21 go.opentelemetry.io/collector/pdata/internal go.opentelemetry.io/collector/pdata/internal/data go.opentelemetry.io/collector/pdata/internal/data/protogen/collector/logs/v1 @@ -1113,14 +1115,14 @@ go.opentelemetry.io/collector/pdata/internal/otlp go.opentelemetry.io/collector/pdata/pcommon go.opentelemetry.io/collector/pdata/pmetric go.opentelemetry.io/collector/pdata/pmetric/pmetricotlp -# go.opentelemetry.io/collector/semconv v0.93.0 -## explicit; go 1.20 +# go.opentelemetry.io/collector/semconv v0.96.0 +## explicit; go 1.21 go.opentelemetry.io/collector/semconv/v1.6.1 -# go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 +# go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 ## explicit; go 1.20 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/internal -# go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 +# go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 ## explicit; go 1.20 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil @@ -1139,7 +1141,7 @@ go.opentelemetry.io/contrib/propagators/jaeger # go.opentelemetry.io/contrib/propagators/ot v1.13.0 ## explicit; go 1.18 go.opentelemetry.io/contrib/propagators/ot -# go.opentelemetry.io/otel v1.22.0 +# go.opentelemetry.io/otel v1.24.0 ## explicit; go 1.20 go.opentelemetry.io/otel go.opentelemetry.io/otel/attribute @@ -1160,22 +1162,23 @@ go.opentelemetry.io/otel/semconv/v1.24.0 ## explicit; go 1.20 go.opentelemetry.io/otel/bridge/opentracing go.opentelemetry.io/otel/bridge/opentracing/migration -# go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 +# go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 ## explicit; go 1.20 go.opentelemetry.io/otel/exporters/otlp/otlptrace go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/tracetransform -# go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 +# go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 ## explicit; go 1.20 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/envconfig go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/retry -# go.opentelemetry.io/otel/metric v1.22.0 +# go.opentelemetry.io/otel/metric v1.24.0 ## explicit; go 1.20 go.opentelemetry.io/otel/metric go.opentelemetry.io/otel/metric/embedded -# go.opentelemetry.io/otel/sdk v1.22.0 +go.opentelemetry.io/otel/metric/noop +# go.opentelemetry.io/otel/sdk v1.24.0 ## explicit; go 1.20 go.opentelemetry.io/otel/sdk go.opentelemetry.io/otel/sdk/instrumentation @@ -1184,12 +1187,12 @@ go.opentelemetry.io/otel/sdk/internal/env go.opentelemetry.io/otel/sdk/resource go.opentelemetry.io/otel/sdk/trace go.opentelemetry.io/otel/sdk/trace/tracetest -# go.opentelemetry.io/otel/trace v1.22.0 +# go.opentelemetry.io/otel/trace v1.24.0 ## explicit; go 1.20 go.opentelemetry.io/otel/trace go.opentelemetry.io/otel/trace/embedded go.opentelemetry.io/otel/trace/noop -# go.opentelemetry.io/proto/otlp v1.0.0 +# go.opentelemetry.io/proto/otlp v1.1.0 ## explicit; go 1.17 go.opentelemetry.io/proto/otlp/collector/trace/v1 go.opentelemetry.io/proto/otlp/common/v1 @@ -1220,7 +1223,7 @@ go4.org/intern # go4.org/unsafe/assume-no-moving-gc v0.0.0-20230525183740-e7c30c78aeb2 ## explicit; go 1.11 go4.org/unsafe/assume-no-moving-gc -# golang.org/x/crypto v0.19.0 +# golang.org/x/crypto v0.21.0 ## explicit; go 1.18 golang.org/x/crypto/argon2 golang.org/x/crypto/bcrypt @@ -1240,10 +1243,10 @@ golang.org/x/crypto/pkcs12/internal/rc2 golang.org/x/exp/constraints golang.org/x/exp/maps golang.org/x/exp/slices -# golang.org/x/mod v0.14.0 +# golang.org/x/mod v0.16.0 ## explicit; go 1.18 golang.org/x/mod/semver -# golang.org/x/net v0.21.0 +# golang.org/x/net v0.22.0 ## explicit; go 1.18 golang.org/x/net/bpf golang.org/x/net/context @@ -1261,14 +1264,15 @@ golang.org/x/net/ipv6 golang.org/x/net/netutil golang.org/x/net/publicsuffix golang.org/x/net/trace -# golang.org/x/oauth2 v0.16.0 +# golang.org/x/oauth2 v0.18.0 ## explicit; go 1.18 golang.org/x/oauth2 golang.org/x/oauth2/authhandler golang.org/x/oauth2/clientcredentials golang.org/x/oauth2/google -golang.org/x/oauth2/google/internal/externalaccount +golang.org/x/oauth2/google/externalaccount golang.org/x/oauth2/google/internal/externalaccountauthorizeduser +golang.org/x/oauth2/google/internal/impersonate golang.org/x/oauth2/google/internal/stsexchange golang.org/x/oauth2/internal golang.org/x/oauth2/jws @@ -1277,7 +1281,7 @@ golang.org/x/oauth2/jwt ## explicit; go 1.18 golang.org/x/sync/errgroup golang.org/x/sync/semaphore -# golang.org/x/sys v0.17.0 +# golang.org/x/sys v0.18.0 ## explicit; go 1.18 golang.org/x/sys/cpu golang.org/x/sys/unix @@ -1299,12 +1303,13 @@ golang.org/x/text/unicode/norm # golang.org/x/time v0.5.0 ## explicit; go 1.18 golang.org/x/time/rate -# golang.org/x/tools v0.17.0 -## explicit; go 1.18 +# golang.org/x/tools v0.19.0 +## explicit; go 1.19 golang.org/x/tools/go/gcexportdata golang.org/x/tools/go/internal/packagesdriver golang.org/x/tools/go/packages golang.org/x/tools/go/types/objectpath +golang.org/x/tools/internal/aliases golang.org/x/tools/internal/event golang.org/x/tools/internal/event/core golang.org/x/tools/internal/event/keys @@ -1323,7 +1328,7 @@ golang.org/x/tools/internal/versions gonum.org/v1/gonum/floats gonum.org/v1/gonum/floats/scalar gonum.org/v1/gonum/internal/asm/f64 -# google.golang.org/api v0.157.0 +# google.golang.org/api v0.168.0 ## explicit; go 1.19 google.golang.org/api/googleapi google.golang.org/api/googleapi/transport @@ -1353,22 +1358,21 @@ google.golang.org/appengine/internal/modules google.golang.org/appengine/internal/remote_api google.golang.org/appengine/internal/urlfetch google.golang.org/appengine/urlfetch -# google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 +# google.golang.org/genproto v0.0.0-20240205150955-31a09d347014 ## explicit; go 1.19 google.golang.org/genproto/googleapis/type/date google.golang.org/genproto/googleapis/type/expr -google.golang.org/genproto/internal -# google.golang.org/genproto/googleapis/api v0.0.0-20240116215550-a9fa1716bcac +# google.golang.org/genproto/googleapis/api v0.0.0-20240304212257-790db918fca8 ## explicit; go 1.19 google.golang.org/genproto/googleapis/api google.golang.org/genproto/googleapis/api/annotations google.golang.org/genproto/googleapis/api/httpbody -# google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac +# google.golang.org/genproto/googleapis/rpc v0.0.0-20240304161311-37d4d3c04a78 ## explicit; go 1.19 google.golang.org/genproto/googleapis/rpc/code google.golang.org/genproto/googleapis/rpc/errdetails google.golang.org/genproto/googleapis/rpc/status -# google.golang.org/grpc v1.61.0 +# google.golang.org/grpc v1.62.1 ## explicit; go 1.19 google.golang.org/grpc google.golang.org/grpc/attributes @@ -1464,6 +1468,7 @@ google.golang.org/protobuf/internal/set google.golang.org/protobuf/internal/strs google.golang.org/protobuf/internal/version google.golang.org/protobuf/proto +google.golang.org/protobuf/protoadapt google.golang.org/protobuf/reflect/protodesc google.golang.org/protobuf/reflect/protoreflect google.golang.org/protobuf/reflect/protoregistry @@ -1484,7 +1489,7 @@ gopkg.in/alecthomas/kingpin.v2 # gopkg.in/ini.v1 v1.67.0 ## explicit gopkg.in/ini.v1 -# gopkg.in/telebot.v3 v3.1.3 +# gopkg.in/telebot.v3 v3.2.1 ## explicit; go 1.13 gopkg.in/telebot.v3 # gopkg.in/yaml.v2 v2.4.0 @@ -1493,10 +1498,10 @@ gopkg.in/yaml.v2 # gopkg.in/yaml.v3 v3.0.1 ## explicit gopkg.in/yaml.v3 -# k8s.io/apimachinery v0.29.2 +# k8s.io/apimachinery v0.29.3 ## explicit; go 1.21 k8s.io/apimachinery/pkg/util/runtime -# k8s.io/client-go v0.29.2 +# k8s.io/client-go v0.29.3 ## explicit; go 1.21 k8s.io/client-go/tools/metrics k8s.io/client-go/util/workqueue