From 65b8ccdc1b56272bf6279c73803375dc293dbd7b Mon Sep 17 00:00:00 2001 From: Chris Thain <32781396+cthain@users.noreply.github.com> Date: Tue, 30 May 2023 07:17:33 -0700 Subject: [PATCH 01/72] Enable Network filters for Wasm Envoy Extension (#17505) --- .changelog/17505.txt | 3 + agent/envoyextensions/builtin/wasm/wasm.go | 100 ++--- .../envoyextensions/builtin/wasm/wasm_test.go | 388 ++++++++++-------- agent/xds/delta_envoy_extender_oss_test.go | 227 ++-------- agent/xds/delta_envoy_extender_test.go | 40 ++ ...wasm-tcp-local-file-outbound.latest.golden | 145 +++++++ .../wasm-tcp-local-file.latest.golden | 145 +++++++ ...asm-tcp-remote-file-outbound.latest.golden | 145 +++++++ .../wasm-tcp-remote-file.latest.golden | 145 +++++++ ...wasm-tcp-local-file-outbound.latest.golden | 75 ++++ .../wasm-tcp-local-file.latest.golden | 75 ++++ ...asm-tcp-remote-file-outbound.latest.golden | 75 ++++ .../wasm-tcp-remote-file.latest.golden | 75 ++++ ...wasm-tcp-local-file-outbound.latest.golden | 157 +++++++ .../wasm-tcp-local-file.latest.golden | 136 ++++++ ...asm-tcp-remote-file-outbound.latest.golden | 167 ++++++++ .../wasm-tcp-remote-file.latest.golden | 141 +++++++ ...wasm-tcp-local-file-outbound.latest.golden | 5 + .../routes/wasm-tcp-local-file.latest.golden | 5 + ...asm-tcp-remote-file-outbound.latest.golden | 5 + .../routes/wasm-tcp-remote-file.latest.golden | 5 + 21 files changed, 1829 insertions(+), 430 deletions(-) create mode 100644 .changelog/17505.txt create mode 100644 agent/xds/testdata/builtin_extension/clusters/wasm-tcp-local-file-outbound.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/clusters/wasm-tcp-local-file.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/clusters/wasm-tcp-remote-file-outbound.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/clusters/wasm-tcp-remote-file.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/endpoints/wasm-tcp-local-file-outbound.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/endpoints/wasm-tcp-local-file.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/endpoints/wasm-tcp-remote-file-outbound.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/endpoints/wasm-tcp-remote-file.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/listeners/wasm-tcp-local-file-outbound.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/listeners/wasm-tcp-local-file.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/listeners/wasm-tcp-remote-file-outbound.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/listeners/wasm-tcp-remote-file.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/routes/wasm-tcp-local-file-outbound.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/routes/wasm-tcp-local-file.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/routes/wasm-tcp-remote-file-outbound.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/routes/wasm-tcp-remote-file.latest.golden diff --git a/.changelog/17505.txt b/.changelog/17505.txt new file mode 100644 index 0000000000..28ed8d0ed9 --- /dev/null +++ b/.changelog/17505.txt @@ -0,0 +1,3 @@ +```release-note:feature +xds: Add a built-in Envoy extension that inserts Wasm network filters. +``` diff --git a/agent/envoyextensions/builtin/wasm/wasm.go b/agent/envoyextensions/builtin/wasm/wasm.go index ec97454f8e..c16ac4da81 100644 --- a/agent/envoyextensions/builtin/wasm/wasm.go +++ b/agent/envoyextensions/builtin/wasm/wasm.go @@ -4,21 +4,19 @@ package wasm import ( - "errors" "fmt" envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" envoy_http_wasm_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/wasm/v3" - envoy_http_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" - envoy_resource_v3 "github.com/envoyproxy/go-control-plane/pkg/resource/v3" + envoy_wasm_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/wasm/v3" "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/envoyextensions/extensioncommon" + cmn "github.com/hashicorp/consul/envoyextensions/extensioncommon" ) // wasm is a built-in Envoy extension that can patch filter chains to insert Wasm plugins. type wasm struct { - extensioncommon.BasicExtensionAdapter + cmn.BasicExtensionAdapter name string wasmConfig *wasmConfig @@ -26,14 +24,14 @@ type wasm struct { var supportedRuntimes = []string{"v8", "wamr", "wavm", "wasmtime"} -var _ extensioncommon.BasicExtension = (*wasm)(nil) +var _ cmn.BasicExtension = (*wasm)(nil) -func Constructor(ext api.EnvoyExtension) (extensioncommon.EnvoyExtender, error) { +func Constructor(ext api.EnvoyExtension) (cmn.EnvoyExtender, error) { w, err := construct(ext) if err != nil { return nil, err } - return &extensioncommon.BasicEnvoyExtender{ + return &cmn.BasicEnvoyExtender{ Extension: &w, }, nil } @@ -67,72 +65,56 @@ func (w *wasm) fromArguments(args map[string]any) error { } // CanApply indicates if the WASM extension can be applied to the given extension configuration. -// Currently the Wasm extension can be applied if the extension configuration is for an inbound -// listener (checked below) on a local connect-proxy. -func (w wasm) CanApply(config *extensioncommon.RuntimeConfig) bool { - return config.Kind == w.wasmConfig.ProxyType +func (w wasm) CanApply(cfg *cmn.RuntimeConfig) bool { + return cfg.Kind == w.wasmConfig.ProxyType && + cfg.Protocol == w.wasmConfig.Protocol } func (w wasm) matchesConfigDirection(isInboundListener bool) bool { - return isInboundListener && w.wasmConfig.ListenerType == "inbound" + return (isInboundListener && w.wasmConfig.ListenerType == "inbound") || + (!isInboundListener && w.wasmConfig.ListenerType == "outbound") } -// PatchFilter adds a Wasm filter to the HTTP filter chain. -// TODO (wasm/tcp): Add support for TCP filters. -func (w wasm) PatchFilter(cfg *extensioncommon.RuntimeConfig, filter *envoy_listener_v3.Filter, isInboundListener bool) (*envoy_listener_v3.Filter, bool, error) { +// PatchFilters adds a Wasm HTTP or TCP filter to the filter chain. +func (w wasm) PatchFilters(cfg *cmn.RuntimeConfig, filters []*envoy_listener_v3.Filter, isInboundListener bool) ([]*envoy_listener_v3.Filter, error) { if !w.matchesConfigDirection(isInboundListener) { - return filter, false, nil + return filters, nil } - if filter.Name != "envoy.filters.network.http_connection_manager" { - return filter, false, nil - } - if typedConfig := filter.GetTypedConfig(); typedConfig == nil { - return filter, false, errors.New("failed to get typed config for http filter") - } - - httpConnMgr := envoy_resource_v3.GetHTTPConnectionManager(filter) - if httpConnMgr == nil { - return filter, false, errors.New("failed to get HTTP connection manager") + // Check that the Wasm plugin protocol matches the service protocol. + // It is a runtime error if the extension is configured to apply a Wasm plugin + // that doesn't match the service's protocol. + // This shouldn't happen because the caller should check CanApply first, but just in case. + if cfg.Protocol != w.wasmConfig.Protocol { + return filters, fmt.Errorf("failed to apply Wasm filter: service protocol for %q is %q but protocol for the Wasm extension is %q. Please ensure the protocols match", + cfg.ServiceName.Name, cfg.Protocol, w.wasmConfig.Protocol) } + // Generate the Wasm plugin configuration. It is the same config for HTTP and network filters. wasmPluginConfig, err := w.wasmConfig.PluginConfig.envoyPluginConfig(cfg) if err != nil { - return filter, false, fmt.Errorf("failed to encode Envoy Wasm configuration: %w", err) + return filters, fmt.Errorf("failed to encode Envoy Wasm plugin configuration: %w", err) } - extHttpFilter, err := extensioncommon.MakeEnvoyHTTPFilter( - "envoy.filters.http.wasm", - &envoy_http_wasm_v3.Wasm{Config: wasmPluginConfig}, - ) - if err != nil { - return filter, false, err - } + // Insert the filter immediately before the terminal filter. + insertOptions := cmn.InsertOptions{Location: cmn.InsertBeforeFirstMatch} - var ( - changedFilters = make([]*envoy_http_v3.HttpFilter, 0, len(httpConnMgr.HttpFilters)+1) - changed bool - ) - - // We need to be careful about overwriting http filters completely because - // http filters validates intentions with the RBAC filter. This inserts the - // filter before `envoy.filters.http.router` while keeping everything - // else intact. - for _, httpFilter := range httpConnMgr.HttpFilters { - if httpFilter.Name == "envoy.filters.http.router" { - changedFilters = append(changedFilters, extHttpFilter) - changed = true + switch cfg.Protocol { + case "grpc", "http2", "http": + insertOptions.FilterName = "envoy.filters.http.router" + filter, err := cmn.MakeEnvoyHTTPFilter("envoy.filters.http.wasm", &envoy_http_wasm_v3.Wasm{Config: wasmPluginConfig}) + if err != nil { + return filters, fmt.Errorf("failed to make Wasm HTTP filter: %w", err) } - changedFilters = append(changedFilters, httpFilter) - } - if changed { - httpConnMgr.HttpFilters = changedFilters - } - - newFilter, err := extensioncommon.MakeFilter("envoy.filters.network.http_connection_manager", httpConnMgr) - if err != nil { - return filter, false, errors.New("error making new filter") + return cmn.InsertHTTPFilter(filters, filter, insertOptions) + case "tcp": + fallthrough + default: + insertOptions.FilterName = "envoy.filters.network.tcp_proxy" + filter, err := cmn.MakeFilter("envoy.filters.network.wasm", &envoy_wasm_v3.Wasm{Config: wasmPluginConfig}) + if err != nil { + return filters, fmt.Errorf("failed to make Wasm network filter: %w", err) + } + return cmn.InsertNetworkFilter(filters, filter, insertOptions) } - - return newFilter, true, nil } diff --git a/agent/envoyextensions/builtin/wasm/wasm_test.go b/agent/envoyextensions/builtin/wasm/wasm_test.go index f62744077d..1d431ce051 100644 --- a/agent/envoyextensions/builtin/wasm/wasm_test.go +++ b/agent/envoyextensions/builtin/wasm/wasm_test.go @@ -15,8 +15,8 @@ import ( envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" envoy_http_wasm_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/wasm/v3" envoy_http_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" + envoy_network_wasm_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/wasm/v3" envoy_wasm_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/wasm/v3" - "github.com/mitchellh/mapstructure" "github.com/stretchr/testify/require" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" @@ -35,157 +35,121 @@ func TestHttpWasmExtension(t *testing.T) { cases := map[string]struct { extName string canApply bool - args func(bool) map[string]any - rtCfg func(bool) *extensioncommon.RuntimeConfig + cfg func(string, bool) *testWasmConfig + rtCfg func(string, bool) *extensioncommon.RuntimeConfig isInboundFilter bool - inputFilters func() []*envoy_http_v3.HttpFilter - expFilters func(tc testWasmConfig) []*envoy_http_v3.HttpFilter - expPatched bool errStr string debug bool }{ - "http remote file": { + "remote file": { extName: api.BuiltinWasmExtension, canApply: true, - args: func(ent bool) map[string]any { return makeTestWasmConfig(ent).toMap(t) }, - rtCfg: func(ent bool) *extensioncommon.RuntimeConfig { return makeTestRuntimeConfig(ent) }, + cfg: func(proto string, ent bool) *testWasmConfig { return makeTestWasmConfig(proto, ent) }, + rtCfg: func(proto string, ent bool) *extensioncommon.RuntimeConfig { return makeTestRuntimeConfig(proto, ent) }, isInboundFilter: true, - inputFilters: makeTestHttpFilters, - expFilters: func(tc testWasmConfig) []*envoy_http_v3.HttpFilter { - return []*envoy_http_v3.HttpFilter{ - {Name: "one"}, - {Name: "two"}, - { - Name: "envoy.filters.http.wasm", - ConfigType: &envoy_http_v3.HttpFilter_TypedConfig{ - TypedConfig: makeAny(t, - &envoy_http_wasm_v3.Wasm{ - Config: tc.toHttpWasmFilter(t), - }), - }, - }, - {Name: "envoy.filters.http.router"}, - {Name: "three"}, - } - }, - expPatched: true, }, "local file": { extName: api.BuiltinWasmExtension, canApply: true, - args: func(ent bool) map[string]any { - cfg := newTestWasmConfig(ent) - cfg.Protocol = "http" + cfg: func(proto string, ent bool) *testWasmConfig { + cfg := newTestWasmConfig(proto, ent) cfg.ListenerType = "inbound" cfg.PluginConfig.VmConfig.Code.Local.Filename = "plugin.wasm" - return cfg.toMap(t) + return cfg }, - rtCfg: func(ent bool) *extensioncommon.RuntimeConfig { return makeTestRuntimeConfig(ent) }, + rtCfg: func(proto string, ent bool) *extensioncommon.RuntimeConfig { return makeTestRuntimeConfig(proto, ent) }, isInboundFilter: true, - inputFilters: makeTestHttpFilters, - expFilters: func(tc testWasmConfig) []*envoy_http_v3.HttpFilter { - return []*envoy_http_v3.HttpFilter{ - {Name: "one"}, - {Name: "two"}, - { - Name: "envoy.filters.http.wasm", - ConfigType: &envoy_http_v3.HttpFilter_TypedConfig{ - TypedConfig: makeAny(t, - &envoy_http_wasm_v3.Wasm{ - Config: tc.toHttpWasmFilter(t), - }), - }, - }, - {Name: "envoy.filters.http.router"}, - {Name: "three"}, - } - }, - expPatched: true, }, "inbound filters ignored": { extName: api.BuiltinWasmExtension, canApply: true, - args: func(ent bool) map[string]any { return makeTestWasmConfig(ent).toMap(t) }, - rtCfg: func(ent bool) *extensioncommon.RuntimeConfig { return makeTestRuntimeConfig(ent) }, + cfg: func(proto string, ent bool) *testWasmConfig { return makeTestWasmConfig(proto, ent) }, + rtCfg: func(proto string, ent bool) *extensioncommon.RuntimeConfig { return makeTestRuntimeConfig(proto, ent) }, isInboundFilter: false, - inputFilters: makeTestHttpFilters, - expFilters: func(tc testWasmConfig) []*envoy_http_v3.HttpFilter { - return []*envoy_http_v3.HttpFilter{ - {Name: "one"}, - {Name: "two"}, - {Name: "envoy.filters.http.router"}, - {Name: "three"}, - } - }, - expPatched: false, }, "no cluster for remote file": { extName: api.BuiltinWasmExtension, canApply: true, - args: func(ent bool) map[string]any { return makeTestWasmConfig(ent).toMap(t) }, - rtCfg: func(ent bool) *extensioncommon.RuntimeConfig { - rt := makeTestRuntimeConfig(ent) + cfg: func(proto string, ent bool) *testWasmConfig { return makeTestWasmConfig(proto, ent) }, + rtCfg: func(proto string, ent bool) *extensioncommon.RuntimeConfig { + rt := makeTestRuntimeConfig(proto, ent) rt.Upstreams = nil return rt }, isInboundFilter: true, - inputFilters: makeTestHttpFilters, errStr: "no upstream found for remote service", - expPatched: false, + }, + "protocol mismatch": { + extName: api.BuiltinWasmExtension, + canApply: false, + cfg: func(proto string, ent bool) *testWasmConfig { return makeTestWasmConfig(proto, ent) }, + rtCfg: func(proto string, ent bool) *extensioncommon.RuntimeConfig { + rt := makeTestRuntimeConfig(proto, ent) + switch proto { + case "http": + rt.Protocol = "tcp" + case "tcp": + rt.Protocol = "http" + } + return rt + }, + isInboundFilter: true, }, } for _, enterprise := range []bool{false, true} { + for _, protocol := range []string{"tcp", "http"} { + for name, c := range cases { + c := c + t.Run(fmt.Sprintf("%s_%s_ent_%t", name, protocol, enterprise), func(t *testing.T) { + cfg := c.cfg(protocol, enterprise) + rtCfg := c.rtCfg(protocol, enterprise) + rtCfg.EnvoyExtension = api.EnvoyExtension{ + Name: c.extName, + Arguments: cfg.toMap(t), + } - for name, c := range cases { - c := c - t.Run(fmt.Sprintf("%s_ent_%t", name, enterprise), func(t *testing.T) { - t.Parallel() - rtCfg := c.rtCfg(enterprise) - rtCfg.EnvoyExtension = api.EnvoyExtension{ - Name: c.extName, - Arguments: c.args(enterprise), - } - - w, err := construct(rtCfg.EnvoyExtension) - require.NoError(t, err) - require.Equal(t, c.canApply, w.CanApply(rtCfg)) - if !c.canApply { - return - } + w, err := construct(rtCfg.EnvoyExtension) + require.NoError(t, err) + require.Equal(t, c.canApply, w.CanApply(rtCfg)) + if !c.canApply { + return + } - route, patched, err := w.PatchRoute(c.rtCfg(enterprise), nil) - require.Nil(t, route) - require.False(t, patched) - require.NoError(t, err) + var inputFilters []*envoy_listener_v3.Filter + if protocol == "http" { + inputFilters = append(inputFilters, makeHttpConMgr(t, makeTestHttpFilters())) + } else { + inputFilters = makeTestFilters() + } - cluster, patched, err := w.PatchCluster(c.rtCfg(enterprise), nil) - require.Nil(t, cluster) - require.False(t, patched) - require.NoError(t, err) + obsFilters, err := w.PatchFilters(rtCfg, inputFilters, c.isInboundFilter) + if c.errStr == "" { + require.NoError(t, err) - inputHttpConMgr := makeHttpConMgr(t, c.inputFilters()) - obsHttpConMgr, patched, err := w.PatchFilter(c.rtCfg(enterprise), inputHttpConMgr, c.isInboundFilter) - if c.errStr == "" { - require.NoError(t, err) - require.Equal(t, c.expPatched, patched) + expFilters := cfg.expFilters(t) + if !cfg.matchesDirection(c.isInboundFilter) { + // If the listener type does not match the filter direction then the + // filter should not be applied and the output should match the input. + expFilters = inputFilters + } - cfg := testWasmConfigFromMap(t, c.args(enterprise)) - expHttpConMgr := makeHttpConMgr(t, c.expFilters(cfg)) + if c.debug { + t.Logf("cfg =\n%s\n\n", cfg.toJSON(t)) + require.Equal(t, len(expFilters), len(obsFilters)) + for idx, expFilter := range expFilters { + t.Logf("expFilterJSON[%d] =\n%s\n\n", idx, protoToJSON(t, expFilter)) + t.Logf("obsfilterJSON[%d] =\n%s\n\n", idx, protoToJSON(t, obsFilters[idx])) + } + } - if c.debug { - t.Logf("cfg =\n%s\n\n", cfg.toJSON(t)) - t.Logf("expFilterJSON =\n%s\n\n", protoToJSON(t, expHttpConMgr)) - t.Logf("obsfilterJSON =\n%s\n\n", protoToJSON(t, obsHttpConMgr)) + prototest.AssertDeepEqual(t, expFilters, obsFilters) + } else { + require.Error(t, err) + require.Contains(t, err.Error(), c.errStr) } - - prototest.AssertDeepEqual(t, expHttpConMgr, obsHttpConMgr) - } else { - require.Error(t, err) - require.Contains(t, err.Error(), c.errStr) - } - - }) + }) + } } } } @@ -194,18 +158,18 @@ func TestWasmConstructor(t *testing.T) { t.Parallel() cases := map[string]struct { name string - args func(bool) map[string]any + args func(string, bool) map[string]any errStr string }{ "with no arguments": { name: api.BuiltinWasmExtension, - args: func(_ bool) map[string]any { return nil }, + args: func(_ string, _ bool) map[string]any { return nil }, errStr: "VmConfig.Code must provide exactly one of Local or Remote data source", }, "invalid protocol": { name: api.BuiltinWasmExtension, - args: func(ent bool) map[string]any { - cfg := newTestWasmConfig(ent) + args: func(proto string, ent bool) map[string]any { + cfg := newTestWasmConfig(proto, ent) cfg.Protocol = "invalid" return cfg.toMap(t) }, @@ -213,8 +177,8 @@ func TestWasmConstructor(t *testing.T) { }, "invalid proxy type": { name: api.BuiltinWasmExtension, - args: func(ent bool) map[string]any { - cfg := newTestWasmConfig(ent) + args: func(proto string, ent bool) map[string]any { + cfg := newTestWasmConfig(proto, ent) cfg.ProxyType = "invalid" return cfg.toMap(t) }, @@ -222,8 +186,8 @@ func TestWasmConstructor(t *testing.T) { }, "invalid listener type": { name: api.BuiltinWasmExtension, - args: func(ent bool) map[string]any { - cfg := newTestWasmConfig(ent) + args: func(proto string, ent bool) map[string]any { + cfg := newTestWasmConfig(proto, ent) cfg.ListenerType = "invalid" return cfg.toMap(t) }, @@ -231,8 +195,8 @@ func TestWasmConstructor(t *testing.T) { }, "invalid runtime": { name: api.BuiltinWasmExtension, - args: func(ent bool) map[string]any { - cfg := newTestWasmConfig(ent) + args: func(proto string, ent bool) map[string]any { + cfg := newTestWasmConfig(proto, ent) cfg.PluginConfig.VmConfig.Runtime = "invalid" return cfg.toMap(t) }, @@ -240,8 +204,8 @@ func TestWasmConstructor(t *testing.T) { }, "both local and remote files": { name: api.BuiltinWasmExtension, - args: func(ent bool) map[string]any { - cfg := newTestWasmConfig(ent) + args: func(proto string, ent bool) map[string]any { + cfg := newTestWasmConfig(proto, ent) cfg.PluginConfig.VmConfig.Code.Local.Filename = "plugin.wasm" cfg.PluginConfig.VmConfig.Code.Remote.HttpURI.Service.Name = "file-server" cfg.PluginConfig.VmConfig.Code.Remote.HttpURI.URI = "http://file-server/plugin.wasm" @@ -251,8 +215,8 @@ func TestWasmConstructor(t *testing.T) { }, "service and uri required for remote files": { name: api.BuiltinWasmExtension, - args: func(ent bool) map[string]any { - cfg := newTestWasmConfig(ent) + args: func(proto string, ent bool) map[string]any { + cfg := newTestWasmConfig(proto, ent) cfg.PluginConfig.VmConfig.Code.Remote.HttpURI.Service.Name = "file-server" return cfg.toMap(t) }, @@ -260,8 +224,8 @@ func TestWasmConstructor(t *testing.T) { }, "no sha for remote file": { name: api.BuiltinWasmExtension, - args: func(ent bool) map[string]any { - cfg := newTestWasmConfig(ent) + args: func(proto string, ent bool) map[string]any { + cfg := newTestWasmConfig(proto, ent) cfg.PluginConfig.VmConfig.Code.Remote.HttpURI.Service.Name = "file-server" cfg.PluginConfig.VmConfig.Code.Remote.HttpURI.URI = "http://file-server/plugin.wasm" return cfg.toMap(t) @@ -270,8 +234,8 @@ func TestWasmConstructor(t *testing.T) { }, "invalid url for remote file": { name: api.BuiltinWasmExtension, - args: func(ent bool) map[string]any { - cfg := newTestWasmConfig(ent) + args: func(proto string, ent bool) map[string]any { + cfg := newTestWasmConfig(proto, ent) cfg.PluginConfig.VmConfig.Code.Remote.HttpURI.Service.Name = "file-server" cfg.PluginConfig.VmConfig.Code.Remote.HttpURI.URI = "://bogus.url.com/error" return cfg.toMap(t) @@ -280,8 +244,8 @@ func TestWasmConstructor(t *testing.T) { }, "decoding error": { name: api.BuiltinWasmExtension, - args: func(ent bool) map[string]any { - a := makeTestWasmConfig(ent).toMap(t) + args: func(proto string, ent bool) map[string]any { + a := makeTestWasmConfig(proto, ent).toMap(t) setField(a, "PluginConfig.VmConfig.Code.Remote.RetryPolicy.RetryBackOff.BaseInterval", 1000) return a }, @@ -289,8 +253,8 @@ func TestWasmConstructor(t *testing.T) { }, "invalid http timeout": { name: api.BuiltinWasmExtension, - args: func(ent bool) map[string]any { - cfg := newTestWasmConfig(ent) + args: func(proto string, ent bool) map[string]any { + cfg := newTestWasmConfig(proto, ent) cfg.PluginConfig.VmConfig.Code.Remote.HttpURI.Timeout = "invalid" return cfg.toMap(t) }, @@ -298,8 +262,8 @@ func TestWasmConstructor(t *testing.T) { }, "invalid num retries": { name: api.BuiltinWasmExtension, - args: func(ent bool) map[string]any { - cfg := newTestWasmConfig(ent) + args: func(proto string, ent bool) map[string]any { + cfg := newTestWasmConfig(proto, ent) cfg.PluginConfig.VmConfig.Code.Remote.RetryPolicy.NumRetries = -1 return cfg.toMap(t) }, @@ -307,8 +271,8 @@ func TestWasmConstructor(t *testing.T) { }, "invalid base interval": { name: api.BuiltinWasmExtension, - args: func(ent bool) map[string]any { - cfg := newTestWasmConfig(ent) + args: func(proto string, ent bool) map[string]any { + cfg := newTestWasmConfig(proto, ent) cfg.PluginConfig.VmConfig.Code.Remote.RetryPolicy.RetryBackOff.BaseInterval = "0s" return cfg.toMap(t) }, @@ -316,8 +280,8 @@ func TestWasmConstructor(t *testing.T) { }, "invalid max interval": { name: api.BuiltinWasmExtension, - args: func(ent bool) map[string]any { - cfg := newTestWasmConfig(ent) + args: func(proto string, ent bool) map[string]any { + cfg := newTestWasmConfig(proto, ent) cfg.PluginConfig.VmConfig.Code.Remote.RetryPolicy.RetryBackOff.BaseInterval = "10s" cfg.PluginConfig.VmConfig.Code.Remote.RetryPolicy.RetryBackOff.MaxInterval = "5s" return cfg.toMap(t) @@ -326,8 +290,8 @@ func TestWasmConstructor(t *testing.T) { }, "invalid base interval duration": { name: api.BuiltinWasmExtension, - args: func(ent bool) map[string]any { - cfg := newTestWasmConfig(ent) + args: func(proto string, ent bool) map[string]any { + cfg := newTestWasmConfig(proto, ent) cfg.PluginConfig.VmConfig.Code.Remote.RetryPolicy.RetryBackOff.BaseInterval = "invalid" return cfg.toMap(t) }, @@ -335,8 +299,8 @@ func TestWasmConstructor(t *testing.T) { }, "invalid max interval duration": { name: api.BuiltinWasmExtension, - args: func(ent bool) map[string]any { - cfg := newTestWasmConfig(ent) + args: func(proto string, ent bool) map[string]any { + cfg := newTestWasmConfig(proto, ent) cfg.PluginConfig.VmConfig.Code.Remote.RetryPolicy.RetryBackOff.MaxInterval = "invalid" return cfg.toMap(t) }, @@ -344,39 +308,39 @@ func TestWasmConstructor(t *testing.T) { }, "invalid extension name": { name: "invalid", - args: func(ent bool) map[string]any { return newTestWasmConfig(ent).toMap(t) }, + args: func(proto string, ent bool) map[string]any { return newTestWasmConfig(proto, ent).toMap(t) }, errStr: `expected extension name "builtin/wasm" but got "invalid"`, }, "valid configuration": { name: api.BuiltinWasmExtension, - args: func(ent bool) map[string]any { return makeTestWasmConfig(ent).toMap(t) }, + args: func(proto string, ent bool) map[string]any { return makeTestWasmConfig(proto, ent).toMap(t) }, }, } for _, enterprise := range []bool{false, true} { - for name, c := range cases { - c := c - t.Run(fmt.Sprintf("%s_ent_%t", name, enterprise), func(t *testing.T) { - t.Parallel() - - svc := api.CompoundServiceName{Name: "svc"} - ext := extensioncommon.RuntimeConfig{ - ServiceName: svc, - EnvoyExtension: api.EnvoyExtension{ - Name: c.name, - Arguments: c.args(enterprise), - }, - } + for _, protocol := range []string{"tcp", "http"} { + for name, c := range cases { + c := c + t.Run(fmt.Sprintf("%s_%s_ent_%t", name, protocol, enterprise), func(t *testing.T) { + svc := api.CompoundServiceName{Name: "svc"} + ext := extensioncommon.RuntimeConfig{ + ServiceName: svc, + EnvoyExtension: api.EnvoyExtension{ + Name: c.name, + Arguments: c.args(protocol, enterprise), + }, + } - e, err := Constructor(ext.EnvoyExtension) + e, err := Constructor(ext.EnvoyExtension) - if c.errStr == "" { - require.NoError(t, err) - require.NotNil(t, e) - } else { - require.Error(t, err) - require.Contains(t, err.Error(), c.errStr) - } - }) + if c.errStr == "" { + require.NoError(t, err) + require.NotNil(t, e) + } else { + require.Error(t, err) + require.Contains(t, err.Error(), c.errStr) + } + }) + } } } } @@ -425,13 +389,6 @@ type testWasmConfig struct { } } -func testWasmConfigFromMap(t *testing.T, m map[string]any) testWasmConfig { - t.Helper() - var cfg testWasmConfig - require.NoError(t, mapstructure.Decode(m, &cfg)) - return cfg -} - func (c testWasmConfig) toMap(t *testing.T) map[string]any { t.Helper() var m map[string]any @@ -446,7 +403,7 @@ func (c testWasmConfig) toJSON(t *testing.T) []byte { return b } -func (cfg testWasmConfig) toHttpWasmFilter(t *testing.T) *envoy_wasm_v3.PluginConfig { +func (cfg testWasmConfig) toWasmPluginConfig(t *testing.T) *envoy_wasm_v3.PluginConfig { t.Helper() var code *envoy_core_v3.AsyncDataSource if cfg.PluginConfig.VmConfig.Code.Local.Filename != "" { @@ -543,6 +500,63 @@ func (cfg testWasmConfig) toHttpWasmFilter(t *testing.T) *envoy_wasm_v3.PluginCo } } +func (cfg testWasmConfig) toHttpFilter(t *testing.T) *envoy_http_v3.HttpFilter { + return &envoy_http_v3.HttpFilter{ + Name: "envoy.filters.http.wasm", + ConfigType: &envoy_http_v3.HttpFilter_TypedConfig{ + TypedConfig: makeAny(t, + &envoy_http_wasm_v3.Wasm{ + Config: cfg.toWasmPluginConfig(t), + }), + }, + } +} + +func (cfg testWasmConfig) toNetworkFilter(t *testing.T) *envoy_listener_v3.Filter { + return &envoy_listener_v3.Filter{ + Name: "envoy.filters.network.wasm", + ConfigType: &envoy_listener_v3.Filter_TypedConfig{ + TypedConfig: makeAny(t, + &envoy_network_wasm_v3.Wasm{ + Config: cfg.toWasmPluginConfig(t), + }), + }, + } +} + +func (cfg testWasmConfig) expFilters(t *testing.T) []*envoy_listener_v3.Filter { + if cfg.Protocol == "http" { + return []*envoy_listener_v3.Filter{makeHttpConMgr(t, cfg.expHttpFilters(t))} + } else { + return cfg.expNetworkFilters(t) + } +} + +func (cfg testWasmConfig) expHttpFilters(t *testing.T) []*envoy_http_v3.HttpFilter { + return []*envoy_http_v3.HttpFilter{ + {Name: "one"}, + {Name: "two"}, + cfg.toHttpFilter(t), + {Name: "envoy.filters.http.router"}, + {Name: "three"}, + } +} + +func (cfg testWasmConfig) expNetworkFilters(t *testing.T) []*envoy_listener_v3.Filter { + return []*envoy_listener_v3.Filter{ + {Name: "one"}, + {Name: "two"}, + cfg.toNetworkFilter(t), + {Name: "envoy.filters.network.tcp_proxy"}, + {Name: "three"}, + } +} + +func (cfg testWasmConfig) matchesDirection(isInbound bool) bool { + return (isInbound && cfg.ListenerType == "inbound") || + (!isInbound && cfg.ListenerType == "outbound") +} + func makeAny(t *testing.T, m proto.Message) *anypb.Any { t.Helper() v, err := anypb.New(m) @@ -562,6 +576,15 @@ func makeHttpConMgr(t *testing.T, filters []*envoy_http_v3.HttpFilter) *envoy_li } } +func makeTestFilters() []*envoy_listener_v3.Filter { + return []*envoy_listener_v3.Filter{ + {Name: "one"}, + {Name: "two"}, + {Name: "envoy.filters.network.tcp_proxy"}, + {Name: "three"}, + } +} + func makeTestHttpFilters() []*envoy_http_v3.HttpFilter { return []*envoy_http_v3.HttpFilter{ {Name: "one"}, @@ -571,7 +594,7 @@ func makeTestHttpFilters() []*envoy_http_v3.HttpFilter { } } -func makeTestRuntimeConfig(enterprise bool) *extensioncommon.RuntimeConfig { +func makeTestRuntimeConfig(protocol string, enterprise bool) *extensioncommon.RuntimeConfig { var ns, ap string if enterprise { ns = "ns1" @@ -590,13 +613,14 @@ func makeTestRuntimeConfig(enterprise bool) *extensioncommon.RuntimeConfig { EnvoyID: "test-file-server", }, }, + Protocol: protocol, } } -func makeTestWasmConfig(enterprise bool) *testWasmConfig { - cfg := newTestWasmConfig(enterprise) +func makeTestWasmConfig(protocol string, enterprise bool) *testWasmConfig { + cfg := newTestWasmConfig(protocol, enterprise) cfg.Required = false - cfg.Protocol = "http" + cfg.Protocol = protocol cfg.ProxyType = "connect-proxy" cfg.ListenerType = "inbound" cfg.PluginConfig.Name = "test-plugin-name" @@ -618,8 +642,8 @@ func makeTestWasmConfig(enterprise bool) *testWasmConfig { return cfg } -func newTestWasmConfig(enterprise bool) *testWasmConfig { - cfg := &testWasmConfig{} +func newTestWasmConfig(protocol string, enterprise bool) *testWasmConfig { + cfg := &testWasmConfig{Protocol: protocol} if enterprise { cfg.PluginConfig.VmConfig.Code.Remote.HttpURI.Service.Namespace = "ns1" cfg.PluginConfig.VmConfig.Code.Remote.HttpURI.Service.Partition = "ap1" diff --git a/agent/xds/delta_envoy_extender_oss_test.go b/agent/xds/delta_envoy_extender_oss_test.go index 7e0bca8076..e4525d91f7 100644 --- a/agent/xds/delta_envoy_extender_oss_test.go +++ b/agent/xds/delta_envoy_extender_oss_test.go @@ -181,115 +181,6 @@ end`, }, }) - propertyOverrideServiceDefaultsClusterLoadAssignmentOutboundAdd := makePropOverrideNsFunc( - map[string]interface{}{ - "Patches": []map[string]interface{}{ - { - "ResourceFilter": map[string]interface{}{ - "ResourceType": propertyoverride.ResourceTypeClusterLoadAssignment, - "TrafficDirection": propertyoverride.TrafficDirectionOutbound, - }, - "Op": "add", - "Path": "/policy/overprovisioning_factor", - "Value": 123, - }, - }, - }) - - propertyOverrideServiceDefaultsClusterLoadAssignmentInboundAdd := makePropOverrideNsFunc( - map[string]interface{}{ - "Patches": []map[string]interface{}{ - { - "ResourceFilter": map[string]interface{}{ - "ResourceType": propertyoverride.ResourceTypeClusterLoadAssignment, - "TrafficDirection": propertyoverride.TrafficDirectionInbound, - }, - "Op": "add", - "Path": "/policy/overprovisioning_factor", - "Value": 123, - }, - }, - }) - - propertyOverrideServiceDefaultsListenerInboundAdd := makePropOverrideNsFunc( - map[string]interface{}{ - "Patches": []map[string]interface{}{ - { - "ResourceFilter": map[string]interface{}{ - "ResourceType": propertyoverride.ResourceTypeListener, - "TrafficDirection": propertyoverride.TrafficDirectionInbound, - }, - "Op": "add", - "Path": "/stat_prefix", - "Value": "custom.stats", - }, - }, - }) - - propertyOverrideServiceDefaultsListenerOutboundAdd := makePropOverrideNsFunc( - map[string]interface{}{ - "Patches": []map[string]interface{}{ - { - "ResourceFilter": map[string]interface{}{ - "ResourceType": propertyoverride.ResourceTypeListener, - "TrafficDirection": propertyoverride.TrafficDirectionOutbound, - }, - "Op": "add", - "Path": "/stat_prefix", - "Value": "custom.stats", - }, - }, - }) - - propertyOverrideServiceDefaultsListenerOutboundDoesntApplyToInbound := makePropOverrideNsFunc( - map[string]interface{}{ - "Patches": []map[string]interface{}{ - { - "ResourceFilter": map[string]interface{}{ - "ResourceType": propertyoverride.ResourceTypeListener, - "TrafficDirection": propertyoverride.TrafficDirectionInbound, - }, - "Op": "add", - "Path": "/stat_prefix", - "Value": "custom.stats.inbound.only", - }, - { - "ResourceFilter": map[string]interface{}{ - "ResourceType": propertyoverride.ResourceTypeListener, - "TrafficDirection": propertyoverride.TrafficDirectionOutbound, - }, - "Op": "add", - "Path": "/stat_prefix", - "Value": "custom.stats.outbound.only", - }, - }, - }) - - // Reverse order of above patches, to prove order is inconsequential - propertyOverrideServiceDefaultsListenerInboundDoesntApplyToOutbound := makePropOverrideNsFunc( - map[string]interface{}{ - "Patches": []map[string]interface{}{ - { - "ResourceFilter": map[string]interface{}{ - "ResourceType": propertyoverride.ResourceTypeListener, - "TrafficDirection": propertyoverride.TrafficDirectionOutbound, - }, - "Op": "add", - "Path": "/stat_prefix", - "Value": "custom.stats.outbound.only", - }, - { - "ResourceFilter": map[string]interface{}{ - "ResourceType": propertyoverride.ResourceTypeListener, - "TrafficDirection": propertyoverride.TrafficDirectionInbound, - }, - "Op": "add", - "Path": "/stat_prefix", - "Value": "custom.stats.inbound.only", - }, - }, - }) - tests := []struct { name string create func(t testinf.T) *proxycfg.ConfigSnapshot @@ -324,42 +215,6 @@ end`, return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", false, propertyOverrideServiceDefaultsRemoveOutlierDetection, nil) }, }, - { - name: "propertyoverride-cluster-load-assignment-outbound-add", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", false, propertyOverrideServiceDefaultsClusterLoadAssignmentOutboundAdd, nil) - }, - }, - { - name: "propertyoverride-cluster-load-assignment-inbound-add", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", false, propertyOverrideServiceDefaultsClusterLoadAssignmentInboundAdd, nil) - }, - }, - { - name: "propertyoverride-listener-outbound-add", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", false, propertyOverrideServiceDefaultsListenerOutboundAdd, nil) - }, - }, - { - name: "propertyoverride-listener-inbound-add", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", false, propertyOverrideServiceDefaultsListenerInboundAdd, nil) - }, - }, - { - name: "propertyoverride-outbound-doesnt-apply-to-inbound", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", false, propertyOverrideServiceDefaultsListenerOutboundDoesntApplyToInbound, nil) - }, - }, - { - name: "propertyoverride-inbound-doesnt-apply-to-outbound", - create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", false, propertyOverrideServiceDefaultsListenerInboundDoesntApplyToOutbound, nil) - }, - }, { name: "lambda-connect-proxy", create: func(t testinf.T) *proxycfg.ConfigSnapshot { @@ -495,25 +350,7 @@ end`, create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { ns.Proxy.Config["protocol"] = "http" - ns.Proxy.EnvoyExtensions = []structs.EnvoyExtension{ - { - Name: api.BuiltinWasmExtension, - Arguments: map[string]interface{}{ - "Protocol": "http", - "ListenerType": "inbound", - "PluginConfig": map[string]interface{}{ - "VmConfig": map[string]interface{}{ - "Code": map[string]interface{}{ - "Local": map[string]interface{}{ - "Filename": "/path/to/extension.wasm", - }, - }, - }, - "Configuration": `{"foo": "bar"}`, - }, - }, - }, - } + ns.Proxy.EnvoyExtensions = makeWasmEnvoyExtension("http", "inbound", "local") }, nil) }, }, @@ -522,31 +359,43 @@ end`, create: func(t testinf.T) *proxycfg.ConfigSnapshot { return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { ns.Proxy.Config["protocol"] = "http" - ns.Proxy.EnvoyExtensions = []structs.EnvoyExtension{ - { - Name: api.BuiltinWasmExtension, - Arguments: map[string]interface{}{ - "Protocol": "http", - "ListenerType": "inbound", - "PluginConfig": map[string]interface{}{ - "VmConfig": map[string]interface{}{ - "Code": map[string]interface{}{ - "Remote": map[string]interface{}{ - "HttpURI": map[string]interface{}{ - "Service": map[string]interface{}{ - "Name": "db", - }, - "URI": "https://db/plugin.wasm", - }, - "SHA256": "d05d88b0ce8a8f1d5176481e0af3ae5c65ed82cbfb8c61506c5354b076078545", - }, - }, - }, - "Configuration": `{"foo": "bar"}`, - }, - }, - }, - } + ns.Proxy.EnvoyExtensions = makeWasmEnvoyExtension("http", "inbound", "remote") + }, nil) + }, + }, + { + name: "wasm-tcp-local-file", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Config["protocol"] = "tcp" + ns.Proxy.EnvoyExtensions = makeWasmEnvoyExtension("tcp", "inbound", "local") + }, nil) + }, + }, + { + name: "wasm-tcp-remote-file", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Config["protocol"] = "tcp" + ns.Proxy.EnvoyExtensions = makeWasmEnvoyExtension("tcp", "inbound", "remote") + }, nil) + }, + }, + { + name: "wasm-tcp-local-file-outbound", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Config["protocol"] = "tcp" + ns.Proxy.EnvoyExtensions = makeWasmEnvoyExtension("tcp", "outbound", "local") + }, nil) + }, + }, + { + name: "wasm-tcp-remote-file-outbound", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshot(t, func(ns *structs.NodeService) { + ns.Proxy.Config["protocol"] = "tcp" + ns.Proxy.EnvoyExtensions = makeWasmEnvoyExtension("tcp", "outbound", "remote") }, nil) }, }, diff --git a/agent/xds/delta_envoy_extender_test.go b/agent/xds/delta_envoy_extender_test.go index 0835e0ca29..0a76d62219 100644 --- a/agent/xds/delta_envoy_extender_test.go +++ b/agent/xds/delta_envoy_extender_test.go @@ -115,3 +115,43 @@ func makeStringMatcherSlice(match, name string, count int) []map[string]any { } return s } + +func makeWasmEnvoyExtension(proto, listener, locale string) []structs.EnvoyExtension { + var code map[string]interface{} + if locale == "local" { + code = map[string]interface{}{ + "Local": map[string]interface{}{ + "Filename": "/path/to/extension.wasm", + }, + } + } else { + code = map[string]interface{}{ + "Remote": map[string]interface{}{ + "HttpURI": map[string]interface{}{ + "Service": map[string]interface{}{ + "Name": "db", + "Namespace": "bar", + "Partition": "zip", + }, + "URI": "https://db/plugin.wasm", + }, + "SHA256": "d05d88b0ce8a8f1d5176481e0af3ae5c65ed82cbfb8c61506c5354b076078545", + }, + } + } + return []structs.EnvoyExtension{ + { + Name: api.BuiltinWasmExtension, + Arguments: map[string]interface{}{ + "Protocol": proto, + "ListenerType": listener, + "PluginConfig": map[string]interface{}{ + "VmConfig": map[string]interface{}{ + "Code": code, + }, + "Configuration": `{"foo": "bar"}`, + }, + }, + }, + } +} diff --git a/agent/xds/testdata/builtin_extension/clusters/wasm-tcp-local-file-outbound.latest.golden b/agent/xds/testdata/builtin_extension/clusters/wasm-tcp-local-file-outbound.latest.golden new file mode 100644 index 0000000000..2e3c9ea20e --- /dev/null +++ b/agent/xds/testdata/builtin_extension/clusters/wasm-tcp-local-file-outbound.latest.golden @@ -0,0 +1,145 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "type": "EDS", + "edsClusterConfig": { + "edsConfig": { + "ads": { + + }, + "resourceApiVersion": "V3" + } + }, + "connectTimeout": "5s", + "circuitBreakers": { + + }, + "outlierDetection": { + + }, + "commonLbConfig": { + "healthyPanicThreshold": { + + } + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": { + + }, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + }, + "matchSubjectAltNames": [ + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + } + ] + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "type": "EDS", + "edsClusterConfig": { + "edsConfig": { + "ads": { + + }, + "resourceApiVersion": "V3" + } + }, + "connectTimeout": "5s", + "circuitBreakers": { + + }, + "outlierDetection": { + + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": { + + }, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + }, + "matchSubjectAltNames": [ + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + } + ] + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "local_app", + "type": "STATIC", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + } + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/clusters/wasm-tcp-local-file.latest.golden b/agent/xds/testdata/builtin_extension/clusters/wasm-tcp-local-file.latest.golden new file mode 100644 index 0000000000..2e3c9ea20e --- /dev/null +++ b/agent/xds/testdata/builtin_extension/clusters/wasm-tcp-local-file.latest.golden @@ -0,0 +1,145 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "type": "EDS", + "edsClusterConfig": { + "edsConfig": { + "ads": { + + }, + "resourceApiVersion": "V3" + } + }, + "connectTimeout": "5s", + "circuitBreakers": { + + }, + "outlierDetection": { + + }, + "commonLbConfig": { + "healthyPanicThreshold": { + + } + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": { + + }, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + }, + "matchSubjectAltNames": [ + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + } + ] + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "type": "EDS", + "edsClusterConfig": { + "edsConfig": { + "ads": { + + }, + "resourceApiVersion": "V3" + } + }, + "connectTimeout": "5s", + "circuitBreakers": { + + }, + "outlierDetection": { + + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": { + + }, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + }, + "matchSubjectAltNames": [ + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + } + ] + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "local_app", + "type": "STATIC", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + } + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/clusters/wasm-tcp-remote-file-outbound.latest.golden b/agent/xds/testdata/builtin_extension/clusters/wasm-tcp-remote-file-outbound.latest.golden new file mode 100644 index 0000000000..2e3c9ea20e --- /dev/null +++ b/agent/xds/testdata/builtin_extension/clusters/wasm-tcp-remote-file-outbound.latest.golden @@ -0,0 +1,145 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "type": "EDS", + "edsClusterConfig": { + "edsConfig": { + "ads": { + + }, + "resourceApiVersion": "V3" + } + }, + "connectTimeout": "5s", + "circuitBreakers": { + + }, + "outlierDetection": { + + }, + "commonLbConfig": { + "healthyPanicThreshold": { + + } + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": { + + }, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + }, + "matchSubjectAltNames": [ + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + } + ] + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "type": "EDS", + "edsClusterConfig": { + "edsConfig": { + "ads": { + + }, + "resourceApiVersion": "V3" + } + }, + "connectTimeout": "5s", + "circuitBreakers": { + + }, + "outlierDetection": { + + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": { + + }, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + }, + "matchSubjectAltNames": [ + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + } + ] + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "local_app", + "type": "STATIC", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + } + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/clusters/wasm-tcp-remote-file.latest.golden b/agent/xds/testdata/builtin_extension/clusters/wasm-tcp-remote-file.latest.golden new file mode 100644 index 0000000000..2e3c9ea20e --- /dev/null +++ b/agent/xds/testdata/builtin_extension/clusters/wasm-tcp-remote-file.latest.golden @@ -0,0 +1,145 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "type": "EDS", + "edsClusterConfig": { + "edsConfig": { + "ads": { + + }, + "resourceApiVersion": "V3" + } + }, + "connectTimeout": "5s", + "circuitBreakers": { + + }, + "outlierDetection": { + + }, + "commonLbConfig": { + "healthyPanicThreshold": { + + } + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": { + + }, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + }, + "matchSubjectAltNames": [ + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + } + ] + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "type": "EDS", + "edsClusterConfig": { + "edsConfig": { + "ads": { + + }, + "resourceApiVersion": "V3" + } + }, + "connectTimeout": "5s", + "circuitBreakers": { + + }, + "outlierDetection": { + + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": { + + }, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + }, + "matchSubjectAltNames": [ + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + } + ] + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "local_app", + "type": "STATIC", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + } + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/endpoints/wasm-tcp-local-file-outbound.latest.golden b/agent/xds/testdata/builtin_extension/endpoints/wasm-tcp-local-file-outbound.latest.golden new file mode 100644 index 0000000000..6e4d37bc32 --- /dev/null +++ b/agent/xds/testdata/builtin_extension/endpoints/wasm-tcp-local-file-outbound.latest.golden @@ -0,0 +1,75 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/endpoints/wasm-tcp-local-file.latest.golden b/agent/xds/testdata/builtin_extension/endpoints/wasm-tcp-local-file.latest.golden new file mode 100644 index 0000000000..6e4d37bc32 --- /dev/null +++ b/agent/xds/testdata/builtin_extension/endpoints/wasm-tcp-local-file.latest.golden @@ -0,0 +1,75 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/endpoints/wasm-tcp-remote-file-outbound.latest.golden b/agent/xds/testdata/builtin_extension/endpoints/wasm-tcp-remote-file-outbound.latest.golden new file mode 100644 index 0000000000..6e4d37bc32 --- /dev/null +++ b/agent/xds/testdata/builtin_extension/endpoints/wasm-tcp-remote-file-outbound.latest.golden @@ -0,0 +1,75 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/endpoints/wasm-tcp-remote-file.latest.golden b/agent/xds/testdata/builtin_extension/endpoints/wasm-tcp-remote-file.latest.golden new file mode 100644 index 0000000000..6e4d37bc32 --- /dev/null +++ b/agent/xds/testdata/builtin_extension/endpoints/wasm-tcp-remote-file.latest.golden @@ -0,0 +1,75 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/listeners/wasm-tcp-local-file-outbound.latest.golden b/agent/xds/testdata/builtin_extension/listeners/wasm-tcp-local-file-outbound.latest.golden new file mode 100644 index 0000000000..967a2d4d29 --- /dev/null +++ b/agent/xds/testdata/builtin_extension/listeners/wasm-tcp-local-file-outbound.latest.golden @@ -0,0 +1,157 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "db:127.0.0.1:9191", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.wasm", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.wasm.v3.Wasm", + "config": { + "vmConfig": { + "runtime": "envoy.wasm.runtime.v8", + "code": { + "local": { + "filename": "/path/to/extension.wasm" + } + } + }, + "configuration": { + "@type": "type.googleapis.com/google.protobuf.StringValue", + "value": "{\"foo\": \"bar\"}" + }, + "failOpen": true + } + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "statPrefix": "upstream.db.default.default.dc1", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ], + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.wasm", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.wasm.v3.Wasm", + "config": { + "vmConfig": { + "runtime": "envoy.wasm.runtime.v8", + "code": { + "local": { + "filename": "/path/to/extension.wasm" + } + } + }, + "configuration": { + "@type": "type.googleapis.com/google.protobuf.StringValue", + "value": "{\"foo\": \"bar\"}" + }, + "failOpen": true + } + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "statPrefix": "upstream.prepared_query_geo-cache", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ], + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "public_listener:0.0.0.0:9999", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "statPrefix": "public_listener", + "cluster": "local_app" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/listeners/wasm-tcp-local-file.latest.golden b/agent/xds/testdata/builtin_extension/listeners/wasm-tcp-local-file.latest.golden new file mode 100644 index 0000000000..f97ca49ff9 --- /dev/null +++ b/agent/xds/testdata/builtin_extension/listeners/wasm-tcp-local-file.latest.golden @@ -0,0 +1,136 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "db:127.0.0.1:9191", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "statPrefix": "upstream.db.default.default.dc1", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ], + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "statPrefix": "upstream.prepared_query_geo-cache", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ], + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "public_listener:0.0.0.0:9999", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.wasm", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.wasm.v3.Wasm", + "config": { + "vmConfig": { + "runtime": "envoy.wasm.runtime.v8", + "code": { + "local": { + "filename": "/path/to/extension.wasm" + } + } + }, + "configuration": { + "@type": "type.googleapis.com/google.protobuf.StringValue", + "value": "{\"foo\": \"bar\"}" + }, + "failOpen": true + } + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "statPrefix": "public_listener", + "cluster": "local_app" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/listeners/wasm-tcp-remote-file-outbound.latest.golden b/agent/xds/testdata/builtin_extension/listeners/wasm-tcp-remote-file-outbound.latest.golden new file mode 100644 index 0000000000..c67156dbf7 --- /dev/null +++ b/agent/xds/testdata/builtin_extension/listeners/wasm-tcp-remote-file-outbound.latest.golden @@ -0,0 +1,167 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "db:127.0.0.1:9191", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.wasm", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.wasm.v3.Wasm", + "config": { + "vmConfig": { + "runtime": "envoy.wasm.runtime.v8", + "code": { + "remote": { + "httpUri": { + "uri": "https://db/plugin.wasm", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "timeout": "1s" + }, + "sha256": "d05d88b0ce8a8f1d5176481e0af3ae5c65ed82cbfb8c61506c5354b076078545" + } + } + }, + "configuration": { + "@type": "type.googleapis.com/google.protobuf.StringValue", + "value": "{\"foo\": \"bar\"}" + }, + "failOpen": true + } + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "statPrefix": "upstream.db.default.default.dc1", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ], + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.wasm", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.wasm.v3.Wasm", + "config": { + "vmConfig": { + "runtime": "envoy.wasm.runtime.v8", + "code": { + "remote": { + "httpUri": { + "uri": "https://db/plugin.wasm", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "timeout": "1s" + }, + "sha256": "d05d88b0ce8a8f1d5176481e0af3ae5c65ed82cbfb8c61506c5354b076078545" + } + } + }, + "configuration": { + "@type": "type.googleapis.com/google.protobuf.StringValue", + "value": "{\"foo\": \"bar\"}" + }, + "failOpen": true + } + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "statPrefix": "upstream.prepared_query_geo-cache", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ], + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "public_listener:0.0.0.0:9999", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "statPrefix": "public_listener", + "cluster": "local_app" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/listeners/wasm-tcp-remote-file.latest.golden b/agent/xds/testdata/builtin_extension/listeners/wasm-tcp-remote-file.latest.golden new file mode 100644 index 0000000000..438caaf841 --- /dev/null +++ b/agent/xds/testdata/builtin_extension/listeners/wasm-tcp-remote-file.latest.golden @@ -0,0 +1,141 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "db:127.0.0.1:9191", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "statPrefix": "upstream.db.default.default.dc1", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ], + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "statPrefix": "upstream.prepared_query_geo-cache", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ], + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "public_listener:0.0.0.0:9999", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": {}, + "statPrefix": "connect_authz" + } + }, + { + "name": "envoy.filters.network.wasm", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.wasm.v3.Wasm", + "config": { + "vmConfig": { + "runtime": "envoy.wasm.runtime.v8", + "code": { + "remote": { + "httpUri": { + "uri": "https://db/plugin.wasm", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "timeout": "1s" + }, + "sha256": "d05d88b0ce8a8f1d5176481e0af3ae5c65ed82cbfb8c61506c5354b076078545" + } + } + }, + "configuration": { + "@type": "type.googleapis.com/google.protobuf.StringValue", + "value": "{\"foo\": \"bar\"}" + }, + "failOpen": true + } + } + }, + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "statPrefix": "public_listener", + "cluster": "local_app" + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + } + }, + "requireClientCertificate": true + } + } + } + ], + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/routes/wasm-tcp-local-file-outbound.latest.golden b/agent/xds/testdata/builtin_extension/routes/wasm-tcp-local-file-outbound.latest.golden new file mode 100644 index 0000000000..9c050cbe6b --- /dev/null +++ b/agent/xds/testdata/builtin_extension/routes/wasm-tcp-local-file-outbound.latest.golden @@ -0,0 +1,5 @@ +{ + "versionInfo": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/routes/wasm-tcp-local-file.latest.golden b/agent/xds/testdata/builtin_extension/routes/wasm-tcp-local-file.latest.golden new file mode 100644 index 0000000000..9c050cbe6b --- /dev/null +++ b/agent/xds/testdata/builtin_extension/routes/wasm-tcp-local-file.latest.golden @@ -0,0 +1,5 @@ +{ + "versionInfo": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/routes/wasm-tcp-remote-file-outbound.latest.golden b/agent/xds/testdata/builtin_extension/routes/wasm-tcp-remote-file-outbound.latest.golden new file mode 100644 index 0000000000..9c050cbe6b --- /dev/null +++ b/agent/xds/testdata/builtin_extension/routes/wasm-tcp-remote-file-outbound.latest.golden @@ -0,0 +1,5 @@ +{ + "versionInfo": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/routes/wasm-tcp-remote-file.latest.golden b/agent/xds/testdata/builtin_extension/routes/wasm-tcp-remote-file.latest.golden new file mode 100644 index 0000000000..9c050cbe6b --- /dev/null +++ b/agent/xds/testdata/builtin_extension/routes/wasm-tcp-remote-file.latest.golden @@ -0,0 +1,5 @@ +{ + "versionInfo": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "nonce": "00000001" +} \ No newline at end of file From b74e87b70c592712852392046437d260ffa16a01 Mon Sep 17 00:00:00 2001 From: modrake <12264057+modrake@users.noreply.github.com> Date: Tue, 30 May 2023 08:17:53 -0700 Subject: [PATCH 02/72] remove deprecated set-output calls in gha (#17494) --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8f017a3f89..66b5a14a73 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -34,16 +34,16 @@ jobs: run: | CONSUL_DATE=$(build-support/scripts/build-date.sh) ## TODO: This assumes `make version` outputs 1.1.1+ent-prerel - echo "::set-output name=product-date::${CONSUL_DATE}" + echo "product-date=${CONSUL_DATE}" >> "$GITHUB_OUTPUT" - name: Set shared -ldflags id: shared-ldflags run: | T="github.com/hashicorp/consul/version" - echo "::set-output name=shared-ldflags::-X ${T}.GitCommit=${GITHUB_SHA::8} \ + echo "shared-ldflags=-X ${T}.GitCommit=${GITHUB_SHA::8} \ -X ${T}.GitDescribe=${{ steps.set-product-version.outputs.product-version }} \ -X ${T}.BuildDate=${{ steps.get-product-version.outputs.product-date }} \ - " + " >> "$GITHUB_OUTPUT" validate-outputs: needs: set-product-version runs-on: ubuntu-latest From bc9bb99a56afd25975a37edc689b234389f1e213 Mon Sep 17 00:00:00 2001 From: Dan Stough Date: Tue, 30 May 2023 12:48:13 -0400 Subject: [PATCH 03/72] build(deps): update UBI base image to 9.2 (#17513) --- .changelog/17513.txt | 3 +++ Dockerfile | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 .changelog/17513.txt diff --git a/.changelog/17513.txt b/.changelog/17513.txt new file mode 100644 index 0000000000..a87557d08c --- /dev/null +++ b/.changelog/17513.txt @@ -0,0 +1,3 @@ +```release-note:security +Update to UBI base image to 9.2. +``` diff --git a/Dockerfile b/Dockerfile index 6b6e696823..065156752e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -201,7 +201,7 @@ CMD ["agent", "-dev", "-client", "0.0.0.0"] # Red Hat UBI-based image # This target is used to build a Consul image for use on OpenShift. -FROM registry.access.redhat.com/ubi9-minimal:9.1.0 as ubi +FROM registry.access.redhat.com/ubi9-minimal:9.2 as ubi ARG PRODUCT_NAME ARG PRODUCT_VERSION From 55e283dda9b7620fd1d6fb658d0b762ddea2e16e Mon Sep 17 00:00:00 2001 From: Ronald Date: Tue, 30 May 2023 13:38:33 -0400 Subject: [PATCH 04/72] [NET-3092] JWT Verify claims handling (#17452) * [NET-3092] JWT Verify claims handling --- .changelog/17452.txt | 3 + agent/xds/jwt_authn.go | 95 +++++-- agent/xds/jwt_authn_test.go | 145 ++++++++--- agent/xds/rbac.go | 168 ++++++++++++- agent/xds/rbac_test.go | 236 ++++++++++++++++++ .../jwt_authn/intention-with-path.golden | 7 +- .../testdata/jwt_authn/local-provider.golden | 1 + ...ltiple-providers-and-one-permission.golden | 20 +- .../testdata/jwt_authn/remote-provider.golden | 1 + .../top-level-provider-with-permission.golden | 19 +- ...jwt-with-one-permission--httpfilter.golden | 59 +++++ ...y-top-level-jwt-with-one-permission.golden | 10 + ...evel-jwt-no-permissions--httpfilter.golden | 57 +++++ .../rbac/top-level-jwt-no-permissions.golden | 32 +++ ...th-multiple-permissions--httpfilter.golden | 113 +++++++++ ...level-jwt-with-multiple-permissions.golden | 10 + ...jwt-with-one-permission--httpfilter.golden | 98 ++++++++ .../top-level-jwt-with-one-permission.golden | 10 + 18 files changed, 1014 insertions(+), 70 deletions(-) create mode 100644 .changelog/17452.txt create mode 100644 agent/xds/testdata/rbac/empty-top-level-jwt-with-one-permission--httpfilter.golden create mode 100644 agent/xds/testdata/rbac/empty-top-level-jwt-with-one-permission.golden create mode 100644 agent/xds/testdata/rbac/top-level-jwt-no-permissions--httpfilter.golden create mode 100644 agent/xds/testdata/rbac/top-level-jwt-no-permissions.golden create mode 100644 agent/xds/testdata/rbac/top-level-jwt-with-multiple-permissions--httpfilter.golden create mode 100644 agent/xds/testdata/rbac/top-level-jwt-with-multiple-permissions.golden create mode 100644 agent/xds/testdata/rbac/top-level-jwt-with-one-permission--httpfilter.golden create mode 100644 agent/xds/testdata/rbac/top-level-jwt-with-one-permission.golden diff --git a/.changelog/17452.txt b/.changelog/17452.txt new file mode 100644 index 0000000000..2f40095dcd --- /dev/null +++ b/.changelog/17452.txt @@ -0,0 +1,3 @@ +```release-note:feature +mesh: Support configuring JWT authentication in Envoy. +``` diff --git a/agent/xds/jwt_authn.go b/agent/xds/jwt_authn.go index 92c8670355..0dc95f5eec 100644 --- a/agent/xds/jwt_authn.go +++ b/agent/xds/jwt_authn.go @@ -16,6 +16,18 @@ import ( "google.golang.org/protobuf/types/known/wrapperspb" ) +const ( + jwtEnvoyFilter = "envoy.filters.http.jwt_authn" + jwtMetadataKeyPrefix = "jwt_payload" +) + +// This is an intermediate JWTProvider form used to associate +// unique payload keys to providers +type jwtAuthnProvider struct { + ComputedName string + Provider *structs.IntentionJWTProvider +} + func makeJWTAuthFilter(pCE map[string]*structs.JWTProviderConfigEntry, intentions structs.SimplifiedIntentions) (*envoy_http_v3.HttpFilter, error) { providers := map[string]*envoy_http_jwt_authn_v3.JwtProvider{} var rules []*envoy_http_jwt_authn_v3.RequirementRule @@ -24,29 +36,33 @@ func makeJWTAuthFilter(pCE map[string]*structs.JWTProviderConfigEntry, intention if intention.JWT == nil && !hasJWTconfig(intention.Permissions) { continue } - for _, jwtReq := range collectJWTRequirements(intention) { - if _, ok := providers[jwtReq.Name]; ok { + for _, jwtReq := range collectJWTAuthnProviders(intention) { + if _, ok := providers[jwtReq.ComputedName]; ok { continue } - jwtProvider, ok := pCE[jwtReq.Name] + jwtProvider, ok := pCE[jwtReq.Provider.Name] if !ok { - return nil, fmt.Errorf("provider specified in intention does not exist. Provider name: %s", jwtReq.Name) + return nil, fmt.Errorf("provider specified in intention does not exist. Provider name: %s", jwtReq.Provider.Name) } - envoyCfg, err := buildJWTProviderConfig(jwtProvider) + // If intention permissions use HTTP-match criteria with + // VerifyClaims, then generate a clone of the jwt provider with a + // unique key for payload_in_metadata. The RBAC filter relies on + // the key to check the correct claims for the matched request. + envoyCfg, err := buildJWTProviderConfig(jwtProvider, jwtReq.ComputedName) if err != nil { return nil, err } - providers[jwtReq.Name] = envoyCfg + providers[jwtReq.ComputedName] = envoyCfg } - for _, perm := range intention.Permissions { + for k, perm := range intention.Permissions { if perm.JWT == nil { continue } for _, prov := range perm.JWT.Providers { - rule := buildRouteRule(prov, perm, "/") + rule := buildRouteRule(prov, perm, "/", k) rules = append(rules, rule) } } @@ -54,8 +70,7 @@ func makeJWTAuthFilter(pCE map[string]*structs.JWTProviderConfigEntry, intention if intention.JWT != nil { for _, provider := range intention.JWT.Providers { // The top-level provider applies to all requests. - // TODO(roncodingenthusiast): Handle provider.VerifyClaims - rule := buildRouteRule(provider, nil, "/") + rule := buildRouteRule(provider, nil, "/", 0) rules = append(rules, rule) } } @@ -70,37 +85,65 @@ func makeJWTAuthFilter(pCE map[string]*structs.JWTProviderConfigEntry, intention Providers: providers, Rules: rules, } - return makeEnvoyHTTPFilter("envoy.filters.http.jwt_authn", cfg) + return makeEnvoyHTTPFilter(jwtEnvoyFilter, cfg) } -func collectJWTRequirements(i *structs.Intention) []*structs.IntentionJWTProvider { - var jReqs []*structs.IntentionJWTProvider +func collectJWTAuthnProviders(i *structs.Intention) []*jwtAuthnProvider { + var reqs []*jwtAuthnProvider if i.JWT != nil { - jReqs = append(jReqs, i.JWT.Providers...) + for _, prov := range i.JWT.Providers { + reqs = append(reqs, &jwtAuthnProvider{Provider: prov, ComputedName: makeComputedProviderName(prov.Name, nil, 0)}) + } } - jReqs = append(jReqs, getPermissionsProviders(i.Permissions)...) + reqs = append(reqs, getPermissionsProviders(i.Permissions)...) - return jReqs + return reqs } -func getPermissionsProviders(p []*structs.IntentionPermission) []*structs.IntentionJWTProvider { - intentionProviders := []*structs.IntentionJWTProvider{} - for _, perm := range p { +func getPermissionsProviders(p []*structs.IntentionPermission) []*jwtAuthnProvider { + var reqs []*jwtAuthnProvider + for k, perm := range p { if perm.JWT == nil { continue } - intentionProviders = append(intentionProviders, perm.JWT.Providers...) + for _, prov := range perm.JWT.Providers { + reqs = append(reqs, &jwtAuthnProvider{Provider: prov, ComputedName: makeComputedProviderName(prov.Name, perm, k)}) + } + } + + return reqs +} + +// makeComputedProviderName is used to create names for unique provider per permission +// This is to stop jwt claims cross validation across permissions/providers. +// +// eg. If Permission x is the 3rd permission and has a provider of original name okta +// this function will return okta_3 as the computed provider name +func makeComputedProviderName(name string, perm *structs.IntentionPermission, idx int) string { + if perm == nil { + return name } + return fmt.Sprintf("%s_%d", name, idx) +} - return intentionProviders +// buildPayloadInMetadataKey is used to create a unique payload key per provider/permissions. +// This is to ensure claims are validated/forwarded specifically under the right permission/path +// and ensure we don't accidentally validate claims from different permissions/providers. +// +// eg. With a provider named okta, the second permission in permission list will have a provider of: +// okta_2 and a payload key of: jwt_payload_okta_2. Whereas an okta provider with no specific permission +// will have a payload key of: jwt_payload_okta +func buildPayloadInMetadataKey(providerName string, perm *structs.IntentionPermission, idx int) string { + return fmt.Sprintf("%s_%s", jwtMetadataKeyPrefix, makeComputedProviderName(providerName, perm, idx)) } -func buildJWTProviderConfig(p *structs.JWTProviderConfigEntry) (*envoy_http_jwt_authn_v3.JwtProvider, error) { +func buildJWTProviderConfig(p *structs.JWTProviderConfigEntry, metadataKeySuffix string) (*envoy_http_jwt_authn_v3.JwtProvider, error) { envoyCfg := envoy_http_jwt_authn_v3.JwtProvider{ - Issuer: p.Issuer, - Audiences: p.Audiences, + Issuer: p.Issuer, + Audiences: p.Audiences, + PayloadInMetadata: buildPayloadInMetadataKey(metadataKeySuffix, nil, 0), } if p.Forwarding != nil { @@ -216,7 +259,7 @@ func buildJWTRetryPolicy(r *structs.JWKSRetryPolicy) *envoy_core_v3.RetryPolicy return &pol } -func buildRouteRule(provider *structs.IntentionJWTProvider, perm *structs.IntentionPermission, defaultPrefix string) *envoy_http_jwt_authn_v3.RequirementRule { +func buildRouteRule(provider *structs.IntentionJWTProvider, perm *structs.IntentionPermission, defaultPrefix string, permIdx int) *envoy_http_jwt_authn_v3.RequirementRule { rule := &envoy_http_jwt_authn_v3.RequirementRule{ Match: &envoy_route_v3.RouteMatch{ PathSpecifier: &envoy_route_v3.RouteMatch_Prefix{Prefix: defaultPrefix}, @@ -224,7 +267,7 @@ func buildRouteRule(provider *structs.IntentionJWTProvider, perm *structs.Intent RequirementType: &envoy_http_jwt_authn_v3.RequirementRule_Requires{ Requires: &envoy_http_jwt_authn_v3.JwtRequirement{ RequiresType: &envoy_http_jwt_authn_v3.JwtRequirement_ProviderName{ - ProviderName: provider.Name, + ProviderName: makeComputedProviderName(provider.Name, perm, permIdx), }, }, }, diff --git a/agent/xds/jwt_authn_test.go b/agent/xds/jwt_authn_test.go index 1b6179fa0b..589421e8c0 100644 --- a/agent/xds/jwt_authn_test.go +++ b/agent/xds/jwt_authn_test.go @@ -65,21 +65,21 @@ var ( pWithOktaProvider = &structs.IntentionPermission{ Action: structs.IntentionActionAllow, HTTP: &structs.IntentionHTTPPermission{ - PathPrefix: "/some-special-path", + PathPrefix: "some-special-path", }, JWT: oktaIntention, } pWithMultiProviders = &structs.IntentionPermission{ Action: structs.IntentionActionAllow, HTTP: &structs.IntentionHTTPPermission{ - PathPrefix: "/some-special-path", + PathPrefix: "some-special-path", }, JWT: multiProviderIntentions, } pWithNoJWT = &structs.IntentionPermission{ Action: structs.IntentionActionAllow, HTTP: &structs.IntentionHTTPPermission{ - PathPrefix: "/some-special-path", + PathPrefix: "some-special-path", }, } fullRetryPolicy = &structs.JWKSRetryPolicy{ @@ -206,51 +206,123 @@ func TestMakeJWTAUTHFilters(t *testing.T) { } } -func TestCollectJWTRequirements(t *testing.T) { - var ( - emptyReq = []*structs.IntentionJWTProvider{} - oneReq = []*structs.IntentionJWTProvider{&oktaProvider} - multiReq = append(oneReq, &auth0Provider) - ) +func TestMakeComputedProviderName(t *testing.T) { + tests := map[string]struct { + name string + perm *structs.IntentionPermission + idx int + expected string + }{ + "no-permissions": { + name: "okta", + idx: 0, + expected: "okta", + }, + "exact-path-permission": { + name: "auth0", + perm: &structs.IntentionPermission{ + HTTP: &structs.IntentionHTTPPermission{ + PathExact: "admin", + }, + }, + idx: 5, + expected: "auth0_5", + }, + } + + for name, tt := range tests { + tt := tt + t.Run(name, func(t *testing.T) { + reqs := makeComputedProviderName(tt.name, tt.perm, tt.idx) + require.Equal(t, reqs, tt.expected) + }) + } +} + +func TestBuildPayloadInMetadataKey(t *testing.T) { + tests := map[string]struct { + name string + perm *structs.IntentionPermission + permIdx int + expected string + }{ + "no-permissions": { + name: "okta", + expected: "jwt_payload_okta", + }, + "path-prefix-permission": { + name: "auth0", + perm: &structs.IntentionPermission{ + HTTP: &structs.IntentionHTTPPermission{ + PathPrefix: "admin", + }, + }, + permIdx: 4, + expected: "jwt_payload_auth0_4", + }, + } + for name, tt := range tests { + tt := tt + t.Run(name, func(t *testing.T) { + reqs := buildPayloadInMetadataKey(tt.name, tt.perm, tt.permIdx) + require.Equal(t, reqs, tt.expected) + }) + } +} + +func TestCollectJWTAuthnProviders(t *testing.T) { tests := map[string]struct { intention *structs.Intention - expected []*structs.IntentionJWTProvider + expected []*jwtAuthnProvider }{ "empty-top-level-jwt-and-empty-permissions": { intention: makeTestIntention(t, ixnOpts{src: "web"}), - expected: emptyReq, + expected: []*jwtAuthnProvider{}, }, "top-level-jwt-and-empty-permissions": { intention: makeTestIntention(t, ixnOpts{src: "web", jwt: oktaIntention}), - expected: oneReq, + expected: []*jwtAuthnProvider{{Provider: &oktaProvider, ComputedName: oktaProvider.Name}}, }, "multi-top-level-jwt-and-empty-permissions": { intention: makeTestIntention(t, ixnOpts{src: "web", jwt: multiProviderIntentions}), - expected: multiReq, + expected: []*jwtAuthnProvider{ + {Provider: &oktaProvider, ComputedName: oktaProvider.Name}, + {Provider: &auth0Provider, ComputedName: auth0Provider.Name}, + }, }, "top-level-jwt-and-one-jwt-permission": { intention: makeTestIntention(t, ixnOpts{src: "web", jwt: auth0Intention, perms: pWithOktaProvider}), - expected: multiReq, + expected: []*jwtAuthnProvider{ + {Provider: &auth0Provider, ComputedName: auth0Provider.Name}, + {Provider: &oktaProvider, ComputedName: "okta_0"}, + }, }, "top-level-jwt-and-multi-jwt-permissions": { intention: makeTestIntention(t, ixnOpts{src: "web", jwt: fakeIntention, perms: pWithMultiProviders}), - expected: append(multiReq, &fakeProvider), + expected: []*jwtAuthnProvider{ + {Provider: &fakeProvider, ComputedName: fakeProvider.Name}, + {Provider: &oktaProvider, ComputedName: "okta_0"}, + {Provider: &auth0Provider, ComputedName: "auth0_0"}, + }, }, "empty-top-level-jwt-and-one-jwt-permission": { intention: makeTestIntention(t, ixnOpts{src: "web", perms: pWithOktaProvider}), - expected: oneReq, + expected: []*jwtAuthnProvider{{Provider: &oktaProvider, ComputedName: "okta_0"}}, }, "empty-top-level-jwt-and-multi-jwt-permission": { intention: makeTestIntention(t, ixnOpts{src: "web", perms: pWithMultiProviders}), - expected: multiReq, + expected: []*jwtAuthnProvider{ + {Provider: &oktaProvider, ComputedName: "okta_0"}, + {Provider: &auth0Provider, ComputedName: "auth0_0"}, + }, }, } for name, tt := range tests { tt := tt t.Run(name, func(t *testing.T) { - reqs := collectJWTRequirements(tt.intention) + reqs := collectJWTAuthnProviders(tt.intention) require.ElementsMatch(t, reqs, tt.expected) }) } @@ -259,27 +331,32 @@ func TestCollectJWTRequirements(t *testing.T) { func TestGetPermissionsProviders(t *testing.T) { tests := map[string]struct { perms []*structs.IntentionPermission - expected []*structs.IntentionJWTProvider + expected []*jwtAuthnProvider }{ "empty-permissions": { perms: []*structs.IntentionPermission{}, - expected: []*structs.IntentionJWTProvider{}, + expected: []*jwtAuthnProvider{}, }, "nil-permissions": { perms: nil, - expected: []*structs.IntentionJWTProvider{}, + expected: []*jwtAuthnProvider{}, }, "permissions-with-no-jwt": { perms: []*structs.IntentionPermission{pWithNoJWT}, - expected: []*structs.IntentionJWTProvider{}, + expected: []*jwtAuthnProvider{}, }, "permissions-with-one-jwt": { - perms: []*structs.IntentionPermission{pWithOktaProvider, pWithNoJWT}, - expected: []*structs.IntentionJWTProvider{&oktaProvider}, + perms: []*structs.IntentionPermission{pWithOktaProvider, pWithNoJWT}, + expected: []*jwtAuthnProvider{ + {Provider: &oktaProvider, ComputedName: "okta_0"}, + }, }, "permissions-with-multiple-jwt": { - perms: []*structs.IntentionPermission{pWithMultiProviders, pWithNoJWT}, - expected: []*structs.IntentionJWTProvider{&oktaProvider, &auth0Provider}, + perms: []*structs.IntentionPermission{pWithMultiProviders, pWithNoJWT}, + expected: []*jwtAuthnProvider{ + {Provider: &auth0Provider, ComputedName: "auth0_0"}, + {Provider: &oktaProvider, ComputedName: "okta_0"}, + }, }, } @@ -338,6 +415,7 @@ func TestBuildJWTProviderConfig(t *testing.T) { Issuer: fullCE.Issuer, Audiences: fullCE.Audiences, ForwardPayloadHeader: "user-token", + PayloadInMetadata: buildPayloadInMetadataKey(ceRemoteJWKS.Name, nil, 0), PadForwardPayloadHeader: false, Forward: true, JwksSourceSpecifier: &envoy_http_jwt_authn_v3.JwtProvider_LocalJwks{ @@ -353,8 +431,9 @@ func TestBuildJWTProviderConfig(t *testing.T) { "entry-with-remote-jwks": { ce: &ceRemoteJWKS, expected: &envoy_http_jwt_authn_v3.JwtProvider{ - Issuer: fullCE.Issuer, - Audiences: fullCE.Audiences, + Issuer: fullCE.Issuer, + Audiences: fullCE.Audiences, + PayloadInMetadata: buildPayloadInMetadataKey(ceRemoteJWKS.Name, nil, 0), JwksSourceSpecifier: &envoy_http_jwt_authn_v3.JwtProvider_RemoteJwks{ RemoteJwks: &envoy_http_jwt_authn_v3.RemoteJwks{ HttpUri: &envoy_core_v3.HttpUri{ @@ -374,7 +453,7 @@ func TestBuildJWTProviderConfig(t *testing.T) { for name, tt := range tests { tt := tt t.Run(name, func(t *testing.T) { - res, err := buildJWTProviderConfig(tt.ce) + res, err := buildJWTProviderConfig(tt.ce, tt.ce.GetName()) if tt.expectedError != "" { require.Error(t, err) @@ -585,7 +664,7 @@ func TestBuildRouteRule(t *testing.T) { RequirementType: &envoy_http_jwt_authn_v3.RequirementRule_Requires{ Requires: &envoy_http_jwt_authn_v3.JwtRequirement{ RequiresType: &envoy_http_jwt_authn_v3.JwtRequirement_ProviderName{ - ProviderName: oktaProvider.Name, + ProviderName: makeComputedProviderName(oktaProvider.Name, pWithMultiProviders, 0), }, }, }, @@ -602,7 +681,7 @@ func TestBuildRouteRule(t *testing.T) { RequirementType: &envoy_http_jwt_authn_v3.RequirementRule_Requires{ Requires: &envoy_http_jwt_authn_v3.JwtRequirement{ RequiresType: &envoy_http_jwt_authn_v3.JwtRequirement_ProviderName{ - ProviderName: oktaProvider.Name, + ProviderName: makeComputedProviderName(oktaProvider.Name, pWithExactPath, 0), }, }, }, @@ -619,7 +698,7 @@ func TestBuildRouteRule(t *testing.T) { RequirementType: &envoy_http_jwt_authn_v3.RequirementRule_Requires{ Requires: &envoy_http_jwt_authn_v3.JwtRequirement{ RequiresType: &envoy_http_jwt_authn_v3.JwtRequirement_ProviderName{ - ProviderName: oktaProvider.Name, + ProviderName: makeComputedProviderName(oktaProvider.Name, pWithRegex, 0), }, }, }, @@ -630,7 +709,7 @@ func TestBuildRouteRule(t *testing.T) { for name, tt := range tests { tt := tt t.Run(name, func(t *testing.T) { - res := buildRouteRule(tt.provider, tt.perm, tt.route) + res := buildRouteRule(tt.provider, tt.perm, tt.route, 0) require.Equal(t, res, tt.expected) }) } diff --git a/agent/xds/rbac.go b/agent/xds/rbac.go index 9648d3edc5..4cb77ad7f0 100644 --- a/agent/xds/rbac.go +++ b/agent/xds/rbac.go @@ -232,16 +232,40 @@ func intentionToIntermediateRBACForm( rixn.Source.TrustDomain = bundle.TrustDomain } + if isHTTP && ixn.JWT != nil { + var c []*JWTInfo + for _, prov := range ixn.JWT.Providers { + if len(prov.VerifyClaims) > 0 { + c = append(c, makeJWTInfos(prov, nil, 0)) + } + } + if len(c) > 0 { + rixn.jwtInfos = c + } + } + if len(ixn.Permissions) > 0 { if isHTTP { rixn.Action = intentionActionLayer7 rixn.Permissions = make([]*rbacPermission, 0, len(ixn.Permissions)) - for _, perm := range ixn.Permissions { - rixn.Permissions = append(rixn.Permissions, &rbacPermission{ + for k, perm := range ixn.Permissions { + rbacPerm := rbacPermission{ Definition: perm, Action: intentionActionFromString(perm.Action), Perm: convertPermission(perm), - }) + } + if perm.JWT != nil { + var c []*JWTInfo + for _, prov := range perm.JWT.Providers { + if len(prov.VerifyClaims) > 0 { + c = append(c, makeJWTInfos(prov, perm, k)) + } + } + if len(c) > 0 { + rbacPerm.jwtInfos = c + } + } + rixn.Permissions = append(rixn.Permissions, &rbacPerm) } } else { // In case L7 intentions slip through to here, treat them as deny intentions. @@ -254,8 +278,17 @@ func intentionToIntermediateRBACForm( return rixn } +func makeJWTInfos(p *structs.IntentionJWTProvider, perm *structs.IntentionPermission, permKey int) *JWTInfo { + return &JWTInfo{Claims: p.VerifyClaims, MetadataPayloadKey: buildPayloadInMetadataKey(p.Name, perm, permKey)} +} + type intentionAction int +type JWTInfo struct { + Claims []*structs.IntentionJWTClaimVerification + MetadataPayloadKey string +} + const ( intentionActionDeny intentionAction = iota intentionActionAllow @@ -294,6 +327,11 @@ type rbacIntention struct { Permissions []*rbacPermission Precedence int + // JWTInfo is used to track intentions' JWT information + // This information is used to update HTTP filters for + // JWT Payload & claims validation + jwtInfos []*JWTInfo + // Skip is field used to indicate that this intention can be deleted in the // final pass. Items marked as true should generally not escape the method // that marked them. @@ -366,6 +404,11 @@ type rbacPermission struct { Perm *envoy_rbac_v3.Permission NotPerms []*envoy_rbac_v3.Permission + // JWTInfo is used to track intentions' JWT information + // This information is used to update HTTP filters for + // JWT Payload & claims validation + jwtInfos []*JWTInfo + // Skip is field used to indicate that this permission can be deleted in // the final pass. Items marked as true should generally not escape the // method that marked them. @@ -531,6 +574,10 @@ func makeRBACRules( var principalsL4 []*envoy_rbac_v3.Principal for i, rbacIxn := range rbacIxns { + var infos []*JWTInfo + if isHTTP { + infos = collectJWTInfos(rbacIxn) + } if rbacIxn.Action == intentionActionLayer7 { if len(rbacIxn.Permissions) == 0 { panic("invalid state: L7 intention has no permissions") @@ -539,9 +586,14 @@ func makeRBACRules( panic("invalid state: L7 permissions present for TCP service") } + rbacPrincipals := optimizePrincipals([]*envoy_rbac_v3.Principal{rbacIxn.ComputedPrincipal}) + if len(infos) > 0 { + claimsPrincipal := jwtInfosToPrincipals(infos) + rbacPrincipals = combineBasePrincipalWithJWTPrincipals(rbacPrincipals, claimsPrincipal) + } // For L7: we should generate one Policy per Principal and list all of the Permissions policy := &envoy_rbac_v3.Policy{ - Principals: optimizePrincipals([]*envoy_rbac_v3.Principal{rbacIxn.ComputedPrincipal}), + Principals: rbacPrincipals, Permissions: make([]*envoy_rbac_v3.Permission, 0, len(rbacIxn.Permissions)), } for _, perm := range rbacIxn.Permissions { @@ -551,6 +603,11 @@ func makeRBACRules( } else { // For L4: we should generate one big Policy listing all Principals principalsL4 = append(principalsL4, rbacIxn.ComputedPrincipal) + // Append JWT principals to list of principals + if len(infos) > 0 { + claimsPrincipal := jwtInfosToPrincipals(infos) + principalsL4 = combineBasePrincipalWithJWTPrincipals(principalsL4, claimsPrincipal) + } } } if len(principalsL4) > 0 { @@ -566,6 +623,109 @@ func makeRBACRules( return rbac } +// combineBasePrincipalWithJWTPrincipals ensure each RBAC/Network principal is associated with +// the JWT principal +func combineBasePrincipalWithJWTPrincipals(p []*envoy_rbac_v3.Principal, cp *envoy_rbac_v3.Principal) []*envoy_rbac_v3.Principal { + res := make([]*envoy_rbac_v3.Principal, 0) + + for _, principal := range p { + if principal != nil && cp != nil { + p := andPrincipals([]*envoy_rbac_v3.Principal{principal, cp}) + res = append(res, p) + } + } + return res +} + +// collectJWTInfos extracts all the collected JWTInfos top level infos +// and permission level infos and returns them as a single array +func collectJWTInfos(rbacIxn *rbacIntention) []*JWTInfo { + infos := make([]*JWTInfo, 0, len(rbacIxn.jwtInfos)) + + if len(rbacIxn.jwtInfos) > 0 { + infos = append(infos, rbacIxn.jwtInfos...) + } + for _, perm := range rbacIxn.Permissions { + infos = append(infos, perm.jwtInfos...) + } + + return infos +} + +func jwtInfosToPrincipals(c []*JWTInfo) *envoy_rbac_v3.Principal { + ps := make([]*envoy_rbac_v3.Principal, 0) + + for _, jwtInfo := range c { + if jwtInfo != nil { + for _, claim := range jwtInfo.Claims { + ps = append(ps, jwtClaimToPrincipal(claim, jwtInfo.MetadataPayloadKey)) + } + } + } + return orPrincipals(ps) +} + +// jwtClaimToPrincipal takes in a payloadkey which is the metadata key. This key is generated by using provider name, +// permission index with a jwt_payload prefix. See buildPayloadInMetadataKey in agent/xds/jwt_authn.go +// +// This uniquely generated payloadKey is the first segment in the path to validate the JWT claims. The subsequent segments +// come from the Path included in the IntentionJWTClaimVerification param. +func jwtClaimToPrincipal(c *structs.IntentionJWTClaimVerification, payloadKey string) *envoy_rbac_v3.Principal { + segments := pathToSegments(c.Path, payloadKey) + + return &envoy_rbac_v3.Principal{ + Identifier: &envoy_rbac_v3.Principal_Metadata{ + Metadata: &envoy_matcher_v3.MetadataMatcher{ + Filter: jwtEnvoyFilter, + Path: segments, + Value: &envoy_matcher_v3.ValueMatcher{ + MatchPattern: &envoy_matcher_v3.ValueMatcher_StringMatch{ + StringMatch: &envoy_matcher_v3.StringMatcher{ + MatchPattern: &envoy_matcher_v3.StringMatcher_Exact{ + Exact: c.Value, + }, + }, + }, + }, + }, + }, + } +} + +// pathToSegments generates an array of MetadataMatcher_PathSegment that starts with the payloadkey +// and is followed by all existing strings in the path. +// +// eg. calling: pathToSegments([]string{"perms", "roles"}, "jwt_payload_okta") should return the following: +// +// []*envoy_matcher_v3.MetadataMatcher_PathSegment{ +// { +// Segment: &envoy_matcher_v3.MetadataMatcher_PathSegment_Key{Key: "jwt_payload_okta"}, +// }, +// { +// Segment: &envoy_matcher_v3.MetadataMatcher_PathSegment_Key{Key: "perms"}, +// }, +// { +// Segment: &envoy_matcher_v3.MetadataMatcher_PathSegment_Key{Key: "roles"}, +// }, +// }, +func pathToSegments(paths []string, payloadKey string) []*envoy_matcher_v3.MetadataMatcher_PathSegment { + + segments := make([]*envoy_matcher_v3.MetadataMatcher_PathSegment, 0, len(paths)) + segments = append(segments, makeSegment(payloadKey)) + + for _, p := range paths { + segments = append(segments, makeSegment(p)) + } + + return segments +} + +func makeSegment(key string) *envoy_matcher_v3.MetadataMatcher_PathSegment { + return &envoy_matcher_v3.MetadataMatcher_PathSegment{ + Segment: &envoy_matcher_v3.MetadataMatcher_PathSegment_Key{Key: key}, + } +} + func optimizePrincipals(orig []*envoy_rbac_v3.Principal) []*envoy_rbac_v3.Principal { // If they are all ORs, then OR them together. var orIds []*envoy_rbac_v3.Principal diff --git a/agent/xds/rbac_test.go b/agent/xds/rbac_test.go index 421f5b7a90..76f4467bff 100644 --- a/agent/xds/rbac_test.go +++ b/agent/xds/rbac_test.go @@ -484,6 +484,17 @@ func TestMakeRBACNetworkAndHTTPFilters(t *testing.T) { ixn.Permissions = perms return ixn } + testIntentionWithJWT := func(src string, action structs.IntentionAction, jwt *structs.IntentionJWTRequirement, perms ...*structs.IntentionPermission) *structs.Intention { + ixn := testIntention(t, src, "api", action) + ixn.JWT = jwt + ixn.Action = action + if perms != nil { + ixn.Permissions = perms + ixn.Action = "" + } + + return ixn + } testPeerTrustBundle := []*pbpeering.PeeringTrustBundle{ { PeerName: "peer1", @@ -506,6 +517,28 @@ func TestMakeRBACNetworkAndHTTPFilters(t *testing.T) { PathPrefix: "/", }, } + oktaWithClaims = structs.IntentionJWTProvider{ + Name: "okta", + VerifyClaims: []*structs.IntentionJWTClaimVerification{ + {Path: []string{"roles"}, Value: "testing"}, + }, + } + auth0WithClaims = structs.IntentionJWTProvider{ + Name: "auth0", + VerifyClaims: []*structs.IntentionJWTClaimVerification{ + {Path: []string{"perms", "role"}, Value: "admin"}, + }, + } + jwtRequirement = &structs.IntentionJWTRequirement{ + Providers: []*structs.IntentionJWTProvider{ + &oktaWithClaims, + }, + } + auth0Requirement = &structs.IntentionJWTRequirement{ + Providers: []*structs.IntentionJWTProvider{ + &auth0WithClaims, + }, + } permDenySlashPrefix = &structs.IntentionPermission{ Action: structs.IntentionActionDeny, HTTP: &structs.IntentionHTTPPermission{ @@ -804,6 +837,70 @@ func TestMakeRBACNetworkAndHTTPFilters(t *testing.T) { ), ), }, + // ========= JWTAuthn Filter checks + "top-level-jwt-no-permissions": { + intentionDefaultAllow: false, + intentions: sorted( + testIntentionWithJWT("web", structs.IntentionActionAllow, jwtRequirement), + ), + }, + "empty-top-level-jwt-with-one-permission": { + intentionDefaultAllow: false, + intentions: sorted( + testIntentionWithJWT("web", structs.IntentionActionAllow, nil, &structs.IntentionPermission{ + Action: structs.IntentionActionAllow, + HTTP: &structs.IntentionHTTPPermission{ + PathPrefix: "some-path", + }, + JWT: jwtRequirement, + }), + ), + }, + "top-level-jwt-with-one-permission": { + intentionDefaultAllow: false, + intentions: sorted( + testIntentionWithJWT("web", + structs.IntentionActionAllow, + jwtRequirement, + &structs.IntentionPermission{ + Action: structs.IntentionActionAllow, + HTTP: &structs.IntentionHTTPPermission{ + PathExact: "/v1/secret", + }, + JWT: auth0Requirement, + }, + &structs.IntentionPermission{ + Action: structs.IntentionActionAllow, + HTTP: &structs.IntentionHTTPPermission{ + PathExact: "/v1/admin", + }, + }, + ), + ), + }, + "top-level-jwt-with-multiple-permissions": { + intentionDefaultAllow: false, + intentions: sorted( + testIntentionWithJWT("web", + structs.IntentionActionAllow, + jwtRequirement, + &structs.IntentionPermission{ + Action: structs.IntentionActionAllow, + HTTP: &structs.IntentionHTTPPermission{ + PathExact: "/v1/secret", + }, + JWT: auth0Requirement, + }, + &structs.IntentionPermission{ + Action: structs.IntentionActionAllow, + HTTP: &structs.IntentionHTTPPermission{ + PathExact: "/v1/admin", + }, + JWT: auth0Requirement, + }, + ), + ), + }, } testLocalInfo := rbacLocalInfo{ @@ -1060,3 +1157,142 @@ func TestSpiffeMatcher(t *testing.T) { }) } } + +func TestPathToSegments(t *testing.T) { + tests := map[string]struct { + key string + paths []string + expected []*envoy_matcher_v3.MetadataMatcher_PathSegment + }{ + "single-path": { + key: "jwt_payload_okta", + paths: []string{"perms"}, + expected: []*envoy_matcher_v3.MetadataMatcher_PathSegment{ + { + Segment: &envoy_matcher_v3.MetadataMatcher_PathSegment_Key{Key: "jwt_payload_okta"}, + }, + { + Segment: &envoy_matcher_v3.MetadataMatcher_PathSegment_Key{Key: "perms"}, + }, + }, + }, + "multi-paths": { + key: "jwt_payload_okta", + paths: []string{"perms", "roles"}, + expected: []*envoy_matcher_v3.MetadataMatcher_PathSegment{ + { + Segment: &envoy_matcher_v3.MetadataMatcher_PathSegment_Key{Key: "jwt_payload_okta"}, + }, + { + Segment: &envoy_matcher_v3.MetadataMatcher_PathSegment_Key{Key: "perms"}, + }, + { + Segment: &envoy_matcher_v3.MetadataMatcher_PathSegment_Key{Key: "roles"}, + }, + }, + }, + } + + for name, tt := range tests { + tt := tt + t.Run(name, func(t *testing.T) { + segments := pathToSegments(tt.paths, tt.key) + require.ElementsMatch(t, segments, tt.expected) + }) + } +} + +func TestJwtClaimToPrincipal(t *testing.T) { + var ( + firstClaim = structs.IntentionJWTClaimVerification{ + Path: []string{"perms"}, + Value: "admin", + } + secondClaim = structs.IntentionJWTClaimVerification{ + Path: []string{"passage"}, + Value: "secret", + } + payloadKey = "dummy-key" + firstPrincipal = envoy_rbac_v3.Principal{ + Identifier: &envoy_rbac_v3.Principal_Metadata{ + Metadata: &envoy_matcher_v3.MetadataMatcher{ + Filter: jwtEnvoyFilter, + Path: pathToSegments(firstClaim.Path, payloadKey), + Value: &envoy_matcher_v3.ValueMatcher{ + MatchPattern: &envoy_matcher_v3.ValueMatcher_StringMatch{ + StringMatch: &envoy_matcher_v3.StringMatcher{ + MatchPattern: &envoy_matcher_v3.StringMatcher_Exact{ + Exact: firstClaim.Value, + }, + }, + }, + }, + }, + }, + } + secondPrincipal = envoy_rbac_v3.Principal{ + Identifier: &envoy_rbac_v3.Principal_Metadata{ + Metadata: &envoy_matcher_v3.MetadataMatcher{ + Filter: jwtEnvoyFilter, + Path: pathToSegments(secondClaim.Path, "second-key"), + Value: &envoy_matcher_v3.ValueMatcher{ + MatchPattern: &envoy_matcher_v3.ValueMatcher_StringMatch{ + StringMatch: &envoy_matcher_v3.StringMatcher{ + MatchPattern: &envoy_matcher_v3.StringMatcher_Exact{ + Exact: secondClaim.Value, + }, + }, + }, + }, + }, + }, + } + ) + tests := map[string]struct { + jwtInfos []*JWTInfo + expected *envoy_rbac_v3.Principal + }{ + "single-jwt-info": { + jwtInfos: []*JWTInfo{ + { + Claims: []*structs.IntentionJWTClaimVerification{&firstClaim}, + MetadataPayloadKey: payloadKey, + }, + }, + expected: &envoy_rbac_v3.Principal{ + Identifier: &envoy_rbac_v3.Principal_OrIds{ + OrIds: &envoy_rbac_v3.Principal_Set{ + Ids: []*envoy_rbac_v3.Principal{&firstPrincipal}, + }, + }, + }, + }, + "multiple-jwt-info": { + jwtInfos: []*JWTInfo{ + { + Claims: []*structs.IntentionJWTClaimVerification{&firstClaim}, + MetadataPayloadKey: payloadKey, + }, + { + Claims: []*structs.IntentionJWTClaimVerification{&secondClaim}, + MetadataPayloadKey: "second-key", + }, + }, + expected: &envoy_rbac_v3.Principal{ + Identifier: &envoy_rbac_v3.Principal_OrIds{ + OrIds: &envoy_rbac_v3.Principal_Set{ + Ids: []*envoy_rbac_v3.Principal{&firstPrincipal, &secondPrincipal}, + }, + }, + }, + }, + } + + for name, tt := range tests { + tt := tt + t.Run(name, func(t *testing.T) { + principal := jwtInfosToPrincipals(tt.jwtInfos) + require.Equal(t, principal, tt.expected) + }) + } +} diff --git a/agent/xds/testdata/jwt_authn/intention-with-path.golden b/agent/xds/testdata/jwt_authn/intention-with-path.golden index 9f0575f79a..306ecad5f6 100644 --- a/agent/xds/testdata/jwt_authn/intention-with-path.golden +++ b/agent/xds/testdata/jwt_authn/intention-with-path.golden @@ -3,8 +3,9 @@ "typedConfig": { "@type": "type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication", "providers": { - "okta": { + "okta_0": { "issuer": "test-issuer", + "payloadInMetadata": "jwt_payload_okta_0", "remoteJwks": { "httpUri": { "uri": "https://example-okta.com/.well-known/jwks.json", @@ -20,10 +21,10 @@ "rules": [ { "match": { - "prefix": "/some-special-path" + "prefix": "some-special-path" }, "requires": { - "providerName": "okta" + "providerName": "okta_0" } } ] diff --git a/agent/xds/testdata/jwt_authn/local-provider.golden b/agent/xds/testdata/jwt_authn/local-provider.golden index 8d660d3a6b..9efda0042b 100644 --- a/agent/xds/testdata/jwt_authn/local-provider.golden +++ b/agent/xds/testdata/jwt_authn/local-provider.golden @@ -5,6 +5,7 @@ "providers": { "okta": { "issuer": "test-issuer", + "payloadInMetadata": "jwt_payload_okta", "localJwks": { "inlineString": "{\"keys\": [{\n \"crv\": \"P-256\",\n \"key_ops\": [\n \"verify\"\n ],\n \"kty\": \"EC\",\n \"x\": \"Wc9uZuPaB7Kh2FMc9wtJjRe8XD4yT2AYNAAkrYbVjuw\",\n \"y\": \"68hRTJiJNOwtrh4EoPXeVnRuH7hiSDJ_lmbbjfDfWq0\",\n \"alg\": \"ES256\",\n \"use\": \"sig\",\n \"kid\": \"ac1e8f90eddf61c429c61ca05b4f2e07\"\n}]}" } diff --git a/agent/xds/testdata/jwt_authn/multiple-providers-and-one-permission.golden b/agent/xds/testdata/jwt_authn/multiple-providers-and-one-permission.golden index f91d170433..feb1d6012e 100644 --- a/agent/xds/testdata/jwt_authn/multiple-providers-and-one-permission.golden +++ b/agent/xds/testdata/jwt_authn/multiple-providers-and-one-permission.golden @@ -5,6 +5,21 @@ "providers": { "okta": { "issuer": "test-issuer", + "payloadInMetadata": "jwt_payload_okta", + "remoteJwks": { + "httpUri": { + "uri": "https://example-okta.com/.well-known/jwks.json", + "cluster": "jwks_cluster", + "timeout": "1s" + }, + "asyncFetch": { + "fastListener": true + } + } + }, + "okta_0": { + "issuer": "test-issuer", + "payloadInMetadata": "jwt_payload_okta_0", "remoteJwks": { "httpUri": { "uri": "https://example-okta.com/.well-known/jwks.json", @@ -18,6 +33,7 @@ }, "auth0": { "issuer": "another-issuer", + "payloadInMetadata": "jwt_payload_auth0", "remoteJwks": { "httpUri": { "uri": "https://example-auth0.com/.well-known/jwks.json", @@ -33,10 +49,10 @@ "rules": [ { "match": { - "prefix": "/some-special-path" + "prefix": "some-special-path" }, "requires": { - "providerName": "okta" + "providerName": "okta_0" } }, { diff --git a/agent/xds/testdata/jwt_authn/remote-provider.golden b/agent/xds/testdata/jwt_authn/remote-provider.golden index bdfa07a543..b84e1ea102 100644 --- a/agent/xds/testdata/jwt_authn/remote-provider.golden +++ b/agent/xds/testdata/jwt_authn/remote-provider.golden @@ -5,6 +5,7 @@ "providers": { "okta": { "issuer": "test-issuer", + "payloadInMetadata": "jwt_payload_okta", "remoteJwks": { "httpUri": { "uri": "https://example-okta.com/.well-known/jwks.json", diff --git a/agent/xds/testdata/jwt_authn/top-level-provider-with-permission.golden b/agent/xds/testdata/jwt_authn/top-level-provider-with-permission.golden index e8b147b040..42a609470d 100644 --- a/agent/xds/testdata/jwt_authn/top-level-provider-with-permission.golden +++ b/agent/xds/testdata/jwt_authn/top-level-provider-with-permission.golden @@ -5,6 +5,21 @@ "providers": { "okta": { "issuer": "test-issuer", + "payloadInMetadata": "jwt_payload_okta", + "remoteJwks": { + "httpUri": { + "uri": "https://example-okta.com/.well-known/jwks.json", + "cluster": "jwks_cluster", + "timeout": "1s" + }, + "asyncFetch": { + "fastListener": true + } + } + }, + "okta_0": { + "issuer": "test-issuer", + "payloadInMetadata": "jwt_payload_okta_0", "remoteJwks": { "httpUri": { "uri": "https://example-okta.com/.well-known/jwks.json", @@ -20,10 +35,10 @@ "rules": [ { "match": { - "prefix": "/some-special-path" + "prefix": "some-special-path" }, "requires": { - "providerName": "okta" + "providerName": "okta_0" } }, { diff --git a/agent/xds/testdata/rbac/empty-top-level-jwt-with-one-permission--httpfilter.golden b/agent/xds/testdata/rbac/empty-top-level-jwt-with-one-permission--httpfilter.golden new file mode 100644 index 0000000000..cd5c35bab2 --- /dev/null +++ b/agent/xds/testdata/rbac/empty-top-level-jwt-with-one-permission--httpfilter.golden @@ -0,0 +1,59 @@ +{ + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": { + "policies": { + "consul-intentions-layer7-0": { + "permissions": [ + { + "urlPath": { + "path": { + "prefix": "some-path" + } + } + } + ], + "principals": [ + { + "andIds": { + "ids": [ + { + "authenticated": { + "principalName": { + "safeRegex": { + "googleRe2": {}, + "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" + } + } + } + }, + { + "orIds": { + "ids": [ + { + "metadata": { + "filter":"envoy.filters.http.jwt_authn", + "path": [ + {"key": "jwt_payload_okta_0"}, + {"key": "roles"} + ], + "value": { + "stringMatch": { + "exact": "testing" + } + } + } + } + ] + } + } + ] + } + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/agent/xds/testdata/rbac/empty-top-level-jwt-with-one-permission.golden b/agent/xds/testdata/rbac/empty-top-level-jwt-with-one-permission.golden new file mode 100644 index 0000000000..92c7f921ad --- /dev/null +++ b/agent/xds/testdata/rbac/empty-top-level-jwt-with-one-permission.golden @@ -0,0 +1,10 @@ +{ + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": { + + }, + "statPrefix": "connect_authz" + } +} \ No newline at end of file diff --git a/agent/xds/testdata/rbac/top-level-jwt-no-permissions--httpfilter.golden b/agent/xds/testdata/rbac/top-level-jwt-no-permissions--httpfilter.golden new file mode 100644 index 0000000000..35b3792e66 --- /dev/null +++ b/agent/xds/testdata/rbac/top-level-jwt-no-permissions--httpfilter.golden @@ -0,0 +1,57 @@ +{ + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": { + "policies": { + "consul-intentions-layer4": { + "permissions": [ + { + "any": true + } + ], + "principals": [ + { + "andIds": { + "ids": [ + { + "authenticated": { + "principalName": { + "safeRegex": { + "googleRe2": { + + }, + "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" + } + } + } + }, + { + "orIds": { + "ids": [ + { + "metadata": { + "filter":"envoy.filters.http.jwt_authn", + "path": [ + {"key": "jwt_payload_okta"}, + {"key": "roles"} + ], + "value": { + "stringMatch": { + "exact": "testing" + } + } + } + } + ] + } + } + ] + } + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/agent/xds/testdata/rbac/top-level-jwt-no-permissions.golden b/agent/xds/testdata/rbac/top-level-jwt-no-permissions.golden new file mode 100644 index 0000000000..3fc78b2955 --- /dev/null +++ b/agent/xds/testdata/rbac/top-level-jwt-no-permissions.golden @@ -0,0 +1,32 @@ +{ + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": { + "policies": { + "consul-intentions-layer4": { + "permissions": [ + { + "any": true + } + ], + "principals": [ + { + "authenticated": { + "principalName": { + "safeRegex": { + "googleRe2": { + + }, + "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" + } + } + } + } + ] + } + } + }, + "statPrefix": "connect_authz" + } +} \ No newline at end of file diff --git a/agent/xds/testdata/rbac/top-level-jwt-with-multiple-permissions--httpfilter.golden b/agent/xds/testdata/rbac/top-level-jwt-with-multiple-permissions--httpfilter.golden new file mode 100644 index 0000000000..409a3a4bd6 --- /dev/null +++ b/agent/xds/testdata/rbac/top-level-jwt-with-multiple-permissions--httpfilter.golden @@ -0,0 +1,113 @@ +{ + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": { + "policies": { + "consul-intentions-layer7-0": { + "permissions": [ + { + "urlPath": { + "path": { + "exact": "/v1/secret" + } + } + }, + { + "andRules": { + "rules": [ + { + "urlPath": { + "path": { + "exact": "/v1/admin" + } + } + }, + { + "notRule": { + "urlPath": { + "path": { + "exact": "/v1/secret" + } + } + } + } + ] + } + } + ], + "principals": [ + { + "andIds": { + "ids": [ + { + "authenticated": { + "principalName": { + "safeRegex": { + "googleRe2": { + + }, + "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" + } + } + } + }, + { + "orIds": { + "ids": [ + { + "metadata": { + "filter":"envoy.filters.http.jwt_authn", + "path": [ + {"key": "jwt_payload_okta"}, + {"key": "roles"} + ], + "value": { + "stringMatch": { + "exact": "testing" + } + } + } + }, + { + "metadata": { + "filter":"envoy.filters.http.jwt_authn", + "path": [ + {"key": "jwt_payload_auth0_0"}, + {"key": "perms"}, + {"key": "role"} + ], + "value": { + "stringMatch": { + "exact": "admin" + } + } + } + }, + { + "metadata": { + "filter":"envoy.filters.http.jwt_authn", + "path": [ + {"key": "jwt_payload_auth0_1"}, + {"key": "perms"}, + {"key": "role"} + ], + "value": { + "stringMatch": { + "exact": "admin" + } + } + } + } + ] + } + } + ] + } + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/agent/xds/testdata/rbac/top-level-jwt-with-multiple-permissions.golden b/agent/xds/testdata/rbac/top-level-jwt-with-multiple-permissions.golden new file mode 100644 index 0000000000..92c7f921ad --- /dev/null +++ b/agent/xds/testdata/rbac/top-level-jwt-with-multiple-permissions.golden @@ -0,0 +1,10 @@ +{ + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": { + + }, + "statPrefix": "connect_authz" + } +} \ No newline at end of file diff --git a/agent/xds/testdata/rbac/top-level-jwt-with-one-permission--httpfilter.golden b/agent/xds/testdata/rbac/top-level-jwt-with-one-permission--httpfilter.golden new file mode 100644 index 0000000000..edf027f3e0 --- /dev/null +++ b/agent/xds/testdata/rbac/top-level-jwt-with-one-permission--httpfilter.golden @@ -0,0 +1,98 @@ +{ + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": { + "policies": { + "consul-intentions-layer7-0": { + "permissions": [ + { + "urlPath": { + "path": { + "exact": "/v1/secret" + } + } + }, + { + "andRules": { + "rules": [ + { + "urlPath": { + "path": { + "exact": "/v1/admin" + } + } + }, + { + "notRule": { + "urlPath": { + "path": { + "exact": "/v1/secret" + } + } + } + } + ] + } + } + ], + "principals": [ + { + "andIds": { + "ids": [ + { + "authenticated": { + "principalName": { + "safeRegex": { + "googleRe2": { + + }, + "regex": "^spiffe://test.consul/ns/default/dc/[^/]+/svc/web$" + } + } + } + }, + { + "orIds": { + "ids": [ + { + "metadata": { + "filter":"envoy.filters.http.jwt_authn", + "path": [ + {"key": "jwt_payload_okta"}, + {"key": "roles"} + ], + "value": { + "stringMatch": { + "exact": "testing" + } + } + } + }, + { + "metadata": { + "filter":"envoy.filters.http.jwt_authn", + "path": [ + {"key": "jwt_payload_auth0_0"}, + {"key": "perms"}, + {"key": "role"} + ], + "value": { + "stringMatch": { + "exact": "admin" + } + } + } + } + ] + } + } + ] + } + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/agent/xds/testdata/rbac/top-level-jwt-with-one-permission.golden b/agent/xds/testdata/rbac/top-level-jwt-with-one-permission.golden new file mode 100644 index 0000000000..92c7f921ad --- /dev/null +++ b/agent/xds/testdata/rbac/top-level-jwt-with-one-permission.golden @@ -0,0 +1,10 @@ +{ + "name": "envoy.filters.network.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + "rules": { + + }, + "statPrefix": "connect_authz" + } +} \ No newline at end of file From 85cfec6b16958ae93b3d7dcb2fe6d0ea6597a79f Mon Sep 17 00:00:00 2001 From: Ashvitha Date: Tue, 30 May 2023 14:26:09 -0400 Subject: [PATCH 05/72] Add safety checks for the client telemetry gateway payload in case it's down (#17511) --- agent/hcp/client/client.go | 33 +++++++++++---- agent/hcp/client/client_test.go | 74 +++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 9 deletions(-) diff --git a/agent/hcp/client/client.go b/agent/hcp/client/client.go index 4203104500..212647c51e 100644 --- a/agent/hcp/client/client.go +++ b/agent/hcp/client/client.go @@ -115,15 +115,7 @@ func (c *hcpClient) FetchTelemetryConfig(ctx context.Context) (*TelemetryConfig, return nil, err } - payloadConfig := resp.Payload.TelemetryConfig - return &TelemetryConfig{ - Endpoint: payloadConfig.Endpoint, - Labels: payloadConfig.Labels, - MetricsConfig: &MetricsConfig{ - Filters: payloadConfig.Metrics.IncludeList, - Endpoint: payloadConfig.Metrics.Endpoint, - }, - }, nil + return convertTelemetryConfig(resp) } func (c *hcpClient) FetchBootstrap(ctx context.Context) (*BootstrapConfig, error) { @@ -281,6 +273,29 @@ func (c *hcpClient) DiscoverServers(ctx context.Context) ([]string, error) { return servers, nil } +// convertTelemetryConfig validates the AgentTelemetryConfig payload and converts it into a TelemetryConfig object. +func convertTelemetryConfig(resp *hcptelemetry.AgentTelemetryConfigOK) (*TelemetryConfig, error) { + if resp.Payload == nil { + return nil, fmt.Errorf("missing payload") + } + + if resp.Payload.TelemetryConfig == nil { + return nil, fmt.Errorf("missing telemetry config") + } + + payloadConfig := resp.Payload.TelemetryConfig + var metricsConfig MetricsConfig + if payloadConfig.Metrics != nil { + metricsConfig.Endpoint = payloadConfig.Metrics.Endpoint + metricsConfig.Filters = payloadConfig.Metrics.IncludeList + } + return &TelemetryConfig{ + Endpoint: payloadConfig.Endpoint, + Labels: payloadConfig.Labels, + MetricsConfig: &metricsConfig, + }, nil +} + // Enabled verifies if telemetry is enabled by ensuring a valid endpoint has been retrieved. // It returns full metrics endpoint and true if a valid endpoint was obtained. func (t *TelemetryConfig) Enabled() (string, bool) { diff --git a/agent/hcp/client/client_test.go b/agent/hcp/client/client_test.go index 43ecf0fd5c..8c8a6addd7 100644 --- a/agent/hcp/client/client_test.go +++ b/agent/hcp/client/client_test.go @@ -4,6 +4,8 @@ import ( "context" "testing" + "github.com/hashicorp/hcp-sdk-go/clients/cloud-consul-telemetry-gateway/preview/2023-04-14/client/consul_telemetry_service" + "github.com/hashicorp/hcp-sdk-go/clients/cloud-consul-telemetry-gateway/preview/2023-04-14/models" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" ) @@ -73,3 +75,75 @@ func TestFetchTelemetryConfig(t *testing.T) { }) } } + +func TestConvertTelemetryConfig(t *testing.T) { + t.Parallel() + for name, test := range map[string]struct { + resp *consul_telemetry_service.AgentTelemetryConfigOK + expectedTelemetryCfg *TelemetryConfig + wantErr string + }{ + "success": { + resp: &consul_telemetry_service.AgentTelemetryConfigOK{ + Payload: &models.HashicorpCloudConsulTelemetry20230414AgentTelemetryConfigResponse{ + TelemetryConfig: &models.HashicorpCloudConsulTelemetry20230414TelemetryConfig{ + Endpoint: "https://test.com", + Labels: map[string]string{"test": "test"}, + }, + }, + }, + expectedTelemetryCfg: &TelemetryConfig{ + Endpoint: "https://test.com", + Labels: map[string]string{"test": "test"}, + MetricsConfig: &MetricsConfig{}, + }, + }, + "successWithMetricsConfig": { + resp: &consul_telemetry_service.AgentTelemetryConfigOK{ + Payload: &models.HashicorpCloudConsulTelemetry20230414AgentTelemetryConfigResponse{ + TelemetryConfig: &models.HashicorpCloudConsulTelemetry20230414TelemetryConfig{ + Endpoint: "https://test.com", + Labels: map[string]string{"test": "test"}, + Metrics: &models.HashicorpCloudConsulTelemetry20230414TelemetryMetricsConfig{ + Endpoint: "https://metrics-test.com", + IncludeList: []string{"consul.raft.apply"}, + }, + }, + }, + }, + expectedTelemetryCfg: &TelemetryConfig{ + Endpoint: "https://test.com", + Labels: map[string]string{"test": "test"}, + MetricsConfig: &MetricsConfig{ + Endpoint: "https://metrics-test.com", + Filters: []string{"consul.raft.apply"}, + }, + }, + }, + "errorsWithNilPayload": { + resp: &consul_telemetry_service.AgentTelemetryConfigOK{}, + wantErr: "missing payload", + }, + "errorsWithNilTelemetryConfig": { + resp: &consul_telemetry_service.AgentTelemetryConfigOK{ + Payload: &models.HashicorpCloudConsulTelemetry20230414AgentTelemetryConfigResponse{}, + }, + wantErr: "missing telemetry config", + }, + } { + test := test + t.Run(name, func(t *testing.T) { + t.Parallel() + telemetryCfg, err := convertTelemetryConfig(test.resp) + if test.wantErr != "" { + require.Error(t, err) + require.Nil(t, telemetryCfg) + require.Contains(t, err.Error(), test.wantErr) + return + } + + require.NoError(t, err) + require.Equal(t, test.expectedTelemetryCfg, telemetryCfg) + }) + } +} From 44f90132e0addae196b9ba2ad6209f1d185944bc Mon Sep 17 00:00:00 2001 From: Nick Ethier Date: Tue, 30 May 2023 14:43:29 -0400 Subject: [PATCH 06/72] hoststats: add package for collecting host statistics including cpu memory and disk usage (#17038) --- .changelog/17038.txt | 3 + agent/config/builder.go | 3 + agent/config/builder_test.go | 19 ++ agent/config/config.go | 1 + agent/config/runtime_test.go | 19 +- .../TestRuntimeConfig_Sanitize.golden | 1 + agent/config/testdata/full-config.hcl | 1 + agent/config/testdata/full-config.json | 1 + agent/setup.go | 21 +- lib/hoststats/collector.go | 189 ++++++++++++++++++ lib/hoststats/cpu.go | 85 ++++++++ lib/hoststats/cpu_test.go | 58 ++++++ lib/hoststats/host.go | 92 +++++++++ lib/hoststats/metrics.go | 79 ++++++++ lib/telemetry.go | 5 + .../docs/agent/config/config-files.mdx | 3 + website/content/docs/agent/telemetry.mdx | 29 +++ 17 files changed, 598 insertions(+), 11 deletions(-) create mode 100644 .changelog/17038.txt create mode 100644 lib/hoststats/collector.go create mode 100644 lib/hoststats/cpu.go create mode 100644 lib/hoststats/cpu_test.go create mode 100644 lib/hoststats/host.go create mode 100644 lib/hoststats/metrics.go diff --git a/.changelog/17038.txt b/.changelog/17038.txt new file mode 100644 index 0000000000..b3a47f98a7 --- /dev/null +++ b/.changelog/17038.txt @@ -0,0 +1,3 @@ +```release-note:improvement +agent: add new metrics to track cpu disk and memory usage for server hosts (defaults to: enabled) +``` diff --git a/agent/config/builder.go b/agent/config/builder.go index 87ee229406..063771b0f7 100644 --- a/agent/config/builder.go +++ b/agent/config/builder.go @@ -1106,6 +1106,9 @@ func (b *builder) build() (rt RuntimeConfig, err error) { LocalProxyConfigResyncInterval: 30 * time.Second, } + // host metrics are enabled by default if consul is configured with HashiCorp Cloud Platform integration + rt.Telemetry.EnableHostMetrics = boolValWithDefault(c.Telemetry.EnableHostMetrics, rt.IsCloudEnabled()) + rt.TLS, err = b.buildTLSConfig(rt, c.TLS) if err != nil { return RuntimeConfig{}, err diff --git a/agent/config/builder_test.go b/agent/config/builder_test.go index 28d5b2972c..3eb81fdee4 100644 --- a/agent/config/builder_test.go +++ b/agent/config/builder_test.go @@ -556,3 +556,22 @@ func TestBuilder_parsePrefixFilter(t *testing.T) { } }) } + +func TestBuidler_hostMetricsWithCloud(t *testing.T) { + devMode := true + builderOpts := LoadOpts{ + DevMode: &devMode, + DefaultConfig: FileSource{ + Name: "test", + Format: "hcl", + Data: `cloud{ resource_id = "abc" client_id = "abc" client_secret = "abc"}`, + }, + } + + result, err := Load(builderOpts) + require.NoError(t, err) + require.Empty(t, result.Warnings) + cfg := result.RuntimeConfig + require.NotNil(t, cfg) + require.True(t, cfg.Telemetry.EnableHostMetrics) +} diff --git a/agent/config/config.go b/agent/config/config.go index a1f4145292..e26d6edc4d 100644 --- a/agent/config/config.go +++ b/agent/config/config.go @@ -691,6 +691,7 @@ type Telemetry struct { CirconusSubmissionInterval *string `mapstructure:"circonus_submission_interval" json:"circonus_submission_interval,omitempty"` CirconusSubmissionURL *string `mapstructure:"circonus_submission_url" json:"circonus_submission_url,omitempty"` DisableHostname *bool `mapstructure:"disable_hostname" json:"disable_hostname,omitempty"` + EnableHostMetrics *bool `mapstructure:"enable_host_metrics" json:"enable_host_metrics,omitempty"` DogstatsdAddr *string `mapstructure:"dogstatsd_addr" json:"dogstatsd_addr,omitempty"` DogstatsdTags []string `mapstructure:"dogstatsd_tags" json:"dogstatsd_tags,omitempty"` RetryFailedConfiguration *bool `mapstructure:"retry_failed_connection" json:"retry_failed_connection,omitempty"` diff --git a/agent/config/runtime_test.go b/agent/config/runtime_test.go index 1064829cd3..3b1a77b2cb 100644 --- a/agent/config/runtime_test.go +++ b/agent/config/runtime_test.go @@ -46,6 +46,7 @@ type testCase struct { desc string args []string setup func() // TODO: accept a testing.T instead of panic + cleanup func() expected func(rt *RuntimeConfig) expectedErr string expectedWarnings []string @@ -2308,9 +2309,9 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { }, setup: func() { os.Setenv("HCP_RESOURCE_ID", "env-id") - t.Cleanup(func() { - os.Unsetenv("HCP_RESOURCE_ID") - }) + }, + cleanup: func() { + os.Unsetenv("HCP_RESOURCE_ID") }, expected: func(rt *RuntimeConfig) { rt.DataDir = dataDir @@ -2321,6 +2322,7 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { // server things rt.ServerMode = true + rt.Telemetry.EnableHostMetrics = true rt.TLS.ServerMode = true rt.LeaveOnTerm = false rt.SkipLeaveOnInt = true @@ -2337,9 +2339,9 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { }, setup: func() { os.Setenv("HCP_RESOURCE_ID", "env-id") - t.Cleanup(func() { - os.Unsetenv("HCP_RESOURCE_ID") - }) + }, + cleanup: func() { + os.Unsetenv("HCP_RESOURCE_ID") }, json: []string{`{ "cloud": { @@ -2360,6 +2362,7 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { // server things rt.ServerMode = true + rt.Telemetry.EnableHostMetrics = true rt.TLS.ServerMode = true rt.LeaveOnTerm = false rt.SkipLeaveOnInt = true @@ -6032,6 +6035,9 @@ func (tc testCase) run(format string, dataDir string) func(t *testing.T) { expected.ACLResolverSettings.EnterpriseMeta = *structs.NodeEnterpriseMetaInPartition(expected.PartitionOrDefault()) prototest.AssertDeepEqual(t, expected, actual, cmpopts.EquateEmpty()) + if tc.cleanup != nil { + tc.cleanup() + } } } @@ -6754,6 +6760,7 @@ func TestLoad_FullConfig(t *testing.T) { Expiration: 15 * time.Second, Name: "ftO6DySn", // notice this is the same as the metrics prefix }, + EnableHostMetrics: true, }, TLS: tlsutil.Config{ InternalRPC: tlsutil.ProtocolConfig{ diff --git a/agent/config/testdata/TestRuntimeConfig_Sanitize.golden b/agent/config/testdata/TestRuntimeConfig_Sanitize.golden index c17636eef7..334f5f8c8f 100644 --- a/agent/config/testdata/TestRuntimeConfig_Sanitize.golden +++ b/agent/config/testdata/TestRuntimeConfig_Sanitize.golden @@ -465,6 +465,7 @@ "DisableHostname": false, "DogstatsdAddr": "", "DogstatsdTags": [], + "EnableHostMetrics": false, "FilterDefault": false, "MetricsPrefix": "", "PrometheusOpts": { diff --git a/agent/config/testdata/full-config.hcl b/agent/config/testdata/full-config.hcl index c29c334b95..660e103608 100644 --- a/agent/config/testdata/full-config.hcl +++ b/agent/config/testdata/full-config.hcl @@ -690,6 +690,7 @@ telemetry { circonus_check_tags = "prvO4uBl" circonus_submission_interval = "DolzaflP" circonus_submission_url = "gTcbS93G" + enable_host_metrics = true disable_hostname = true dogstatsd_addr = "0wSndumK" dogstatsd_tags = [ "3N81zSUB","Xtj8AnXZ" ] diff --git a/agent/config/testdata/full-config.json b/agent/config/testdata/full-config.json index 7640394a4f..52dab37bfa 100644 --- a/agent/config/testdata/full-config.json +++ b/agent/config/testdata/full-config.json @@ -808,6 +808,7 @@ "circonus_check_tags": "prvO4uBl", "circonus_submission_interval": "DolzaflP", "circonus_submission_url": "gTcbS93G", + "enable_host_metrics": true, "disable_hostname": true, "dogstatsd_addr": "0wSndumK", "dogstatsd_tags": [ diff --git a/agent/setup.go b/agent/setup.go index 9ed993aaf4..fba5c2b5dd 100644 --- a/agent/setup.go +++ b/agent/setup.go @@ -4,6 +4,7 @@ package agent import ( + "context" "fmt" "io" "net" @@ -41,6 +42,7 @@ import ( "github.com/hashicorp/consul/agent/xds" "github.com/hashicorp/consul/ipaddr" "github.com/hashicorp/consul/lib" + "github.com/hashicorp/consul/lib/hoststats" "github.com/hashicorp/consul/logging" "github.com/hashicorp/consul/tlsutil" ) @@ -59,6 +61,7 @@ type BaseDeps struct { WatchedFiles []string deregisterBalancer, deregisterResolver func() + stopHostCollector context.CancelFunc } type ConfigLoader func(source config.Source) (config.LoadResult, error) @@ -117,6 +120,11 @@ func NewBaseDeps(configLoader ConfigLoader, logOut io.Writer, providedLogger hcl if err != nil { return d, fmt.Errorf("failed to initialize telemetry: %w", err) } + if !cfg.Telemetry.Disable && cfg.Telemetry.EnableHostMetrics { + ctx, cancel := context.WithCancel(context.Background()) + hoststats.NewCollector(ctx, d.Logger, cfg.DataDir) + d.stopHostCollector = cancel + } d.TLSConfigurator, err = tlsutil.NewConfigurator(cfg.TLS, d.Logger) if err != nil { @@ -214,11 +222,10 @@ func (bd BaseDeps) Close() { bd.AutoConfig.Stop() bd.MetricsConfig.Cancel() - if fn := bd.deregisterBalancer; fn != nil { - fn() - } - if fn := bd.deregisterResolver; fn != nil { - fn() + for _, fn := range []func(){bd.deregisterBalancer, bd.deregisterResolver, bd.stopHostCollector} { + if fn != nil { + fn() + } } } @@ -297,6 +304,10 @@ func getPrometheusDefs(cfg *config.RuntimeConfig, isServer bool) ([]prometheus.G serverGauges, } + if cfg.Telemetry.EnableHostMetrics { + gauges = append(gauges, hoststats.Gauges) + } + // TODO(ffmmm): conditionally add only leader specific metrics to gauges, counters, summaries, etc if isServer { gauges = append(gauges, diff --git a/lib/hoststats/collector.go b/lib/hoststats/collector.go new file mode 100644 index 0000000000..c4c57b35c5 --- /dev/null +++ b/lib/hoststats/collector.go @@ -0,0 +1,189 @@ +package hoststats + +import ( + "context" + "fmt" + "math" + "runtime" + "sync" + "time" + + "github.com/armon/go-metrics" + "github.com/hashicorp/go-hclog" + "github.com/shirou/gopsutil/v3/disk" + "github.com/shirou/gopsutil/v3/host" + "github.com/shirou/gopsutil/v3/mem" +) + +// Collector collects host resource usage stats +type Collector struct { + numCores int + cpuCalculator map[string]*cpuStatsCalculator + hostStats *HostStats + hostStatsLock sync.RWMutex + dataDir string + + metrics Metrics + baseLabels []metrics.Label + + logger hclog.Logger +} + +// NewCollector returns a Collector. The dataDir is passed in +// so that we can present the disk related statistics for the mountpoint where the dataDir exists +func NewCollector(ctx context.Context, logger hclog.Logger, dataDir string, opts ...CollectorOption) *Collector { + logger = logger.Named("host_stats") + collector := initCollector(logger, dataDir) + go collector.loop(ctx) + return collector +} + +// initCollector initializes the Collector but does not start the collection loop +func initCollector(logger hclog.Logger, dataDir string, opts ...CollectorOption) *Collector { + numCores := runtime.NumCPU() + statsCalculator := make(map[string]*cpuStatsCalculator) + collector := &Collector{ + cpuCalculator: statsCalculator, + numCores: numCores, + logger: logger, + dataDir: dataDir, + } + + for _, opt := range opts { + opt(collector) + } + + if collector.metrics == nil { + collector.metrics = metrics.Default() + } + return collector +} + +func (c *Collector) loop(ctx context.Context) { + // Start collecting host stats right away and then keep collecting every + // collection interval + next := time.NewTimer(0) + defer next.Stop() + for { + select { + case <-next.C: + c.collect() + next.Reset(hostStatsCollectionInterval) + c.Stats().Emit(c.metrics, c.baseLabels) + + case <-ctx.Done(): + return + } + } +} + +// collect will collect stats related to resource usage of the host +func (c *Collector) collect() { + hs := &HostStats{Timestamp: time.Now().UTC().UnixNano()} + + // Determine up-time + uptime, err := host.Uptime() + if err != nil { + c.logger.Error("failed to collect uptime stats", "error", err) + uptime = 0 + } + hs.Uptime = uptime + + // Collect memory stats + mstats, err := c.collectMemoryStats() + if err != nil { + c.logger.Error("failed to collect memory stats", "error", err) + mstats = &MemoryStats{} + } + hs.Memory = mstats + + // Collect cpu stats + cpus, err := c.collectCPUStats() + if err != nil { + c.logger.Error("failed to collect cpu stats", "error", err) + cpus = []*CPUStats{} + } + hs.CPU = cpus + + // Collect disk stats + diskStats, err := c.collectDiskStats(c.dataDir) + if err != nil { + c.logger.Error("failed to collect dataDir disk stats", "error", err) + } + hs.DataDirStats = diskStats + + // Update the collected status object. + c.hostStatsLock.Lock() + c.hostStats = hs + c.hostStatsLock.Unlock() +} + +func (c *Collector) collectDiskStats(dir string) (*DiskStats, error) { + usage, err := disk.Usage(dir) + if err != nil { + return nil, fmt.Errorf("failed to collect disk usage stats: %w", err) + } + return c.toDiskStats(usage), nil +} + +func (c *Collector) collectMemoryStats() (*MemoryStats, error) { + memStats, err := mem.VirtualMemory() + if err != nil { + return nil, err + } + mem := &MemoryStats{ + Total: memStats.Total, + Available: memStats.Available, + Used: memStats.Used, + UsedPercent: memStats.UsedPercent, + Free: memStats.Free, + } + + return mem, nil +} + +// Stats returns the host stats that has been collected +func (c *Collector) Stats() *HostStats { + c.hostStatsLock.RLock() + defer c.hostStatsLock.RUnlock() + + if c.hostStats == nil { + return &HostStats{} + } + + return c.hostStats.Clone() +} + +// toDiskStats merges UsageStat and PartitionStat to create a DiskStat +func (c *Collector) toDiskStats(usage *disk.UsageStat) *DiskStats { + ds := DiskStats{ + Size: usage.Total, + Used: usage.Used, + Available: usage.Free, + UsedPercent: usage.UsedPercent, + InodesUsedPercent: usage.InodesUsedPercent, + Path: usage.Path, + } + if math.IsNaN(ds.UsedPercent) { + ds.UsedPercent = 0.0 + } + if math.IsNaN(ds.InodesUsedPercent) { + ds.InodesUsedPercent = 0.0 + } + + return &ds +} + +type CollectorOption func(c *Collector) + +func WithMetrics(m *metrics.Metrics) CollectorOption { + return func(c *Collector) { + c.metrics = m + } +} + +func WithBaseLabels(labels []metrics.Label) CollectorOption { + return func(c *Collector) { + c.baseLabels = labels + } +} diff --git a/lib/hoststats/cpu.go b/lib/hoststats/cpu.go new file mode 100644 index 0000000000..45633b40df --- /dev/null +++ b/lib/hoststats/cpu.go @@ -0,0 +1,85 @@ +package hoststats + +import ( + "math" + + "github.com/shirou/gopsutil/v3/cpu" +) + +// cpuStatsCalculator calculates cpu usage percentages +type cpuStatsCalculator struct { + prev cpu.TimesStat + prevBusy float64 + prevTotal float64 +} + +// calculate the current cpu usage percentages. +// Since the cpu.TimesStat captures the total time a cpu spent in various states +// this function tracks the last seen stat and derives each cpu state's utilization +// as a percentage of the total change in cpu time between calls. +// The first time calculate is called CPUStats will report %100 idle +// usage since there is not a previous value to calculate against +func (h *cpuStatsCalculator) calculate(times cpu.TimesStat) *CPUStats { + + // sum all none idle counters to get the total busy cpu time + currentBusy := times.User + times.System + times.Nice + times.Iowait + times.Irq + + times.Softirq + times.Steal + times.Guest + times.GuestNice + // sum of the total cpu time + currentTotal := currentBusy + times.Idle + + // calculate how much cpu time has passed since last calculation + deltaTotal := currentTotal - h.prevTotal + + stats := &CPUStats{ + CPU: times.CPU, + + // calculate each percentage as the ratio of the change + // in each state's time to the total change in cpu time + Idle: ((times.Idle - h.prev.Idle) / deltaTotal) * 100, + User: ((times.User - h.prev.User) / deltaTotal) * 100, + System: ((times.System - h.prev.System) / deltaTotal) * 100, + Iowait: ((times.Iowait - h.prev.Iowait) / deltaTotal) * 100, + Total: ((currentBusy - h.prevBusy) / deltaTotal) * 100, + } + + // Protect against any invalid values + if math.IsNaN(stats.Idle) || math.IsInf(stats.Idle, 0) { + stats.Idle = 100.0 + } + if math.IsNaN(stats.User) || math.IsInf(stats.User, 0) { + stats.User = 0.0 + } + if math.IsNaN(stats.System) || math.IsInf(stats.System, 0) { + stats.System = 0.0 + } + if math.IsNaN(stats.Iowait) || math.IsInf(stats.Iowait, 0) { + stats.Iowait = 0.0 + } + if math.IsNaN(stats.Total) || math.IsInf(stats.Total, 0) { + stats.Total = 0.0 + } + + h.prev = times + h.prevTotal = currentTotal + h.prevBusy = currentBusy + return stats +} + +func (c *Collector) collectCPUStats() (cpus []*CPUStats, err error) { + + cpuStats, err := cpu.Times(true) + if err != nil { + return nil, err + } + cs := make([]*CPUStats, len(cpuStats)) + for idx, cpuStat := range cpuStats { + percentCalculator, ok := c.cpuCalculator[cpuStat.CPU] + if !ok { + percentCalculator = &cpuStatsCalculator{} + c.cpuCalculator[cpuStat.CPU] = percentCalculator + } + cs[idx] = percentCalculator.calculate(cpuStat) + } + + return cs, nil +} diff --git a/lib/hoststats/cpu_test.go b/lib/hoststats/cpu_test.go new file mode 100644 index 0000000000..5d5efbe976 --- /dev/null +++ b/lib/hoststats/cpu_test.go @@ -0,0 +1,58 @@ +package hoststats + +import ( + "math" + "os" + "testing" + "time" + + "github.com/hashicorp/consul/sdk/testutil" + "github.com/shirou/gopsutil/v3/cpu" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestHostStats_CPU(t *testing.T) { + logger := testutil.Logger(t) + cwd, err := os.Getwd() + assert.Nil(t, err) + hs := initCollector(logger, cwd) + + // Collect twice so we can calculate percents we need to generate some work + // so that the cpu values change + hs.collect() + for begin := time.Now(); time.Now().Sub(begin) < 100*time.Millisecond; { + } + hs.collect() + stats := hs.Stats() + assert.NotZero(t, len(stats.CPU)) + + for _, cpu := range stats.CPU { + assert.False(t, math.IsNaN(cpu.Idle)) + assert.False(t, math.IsNaN(cpu.Total)) + assert.False(t, math.IsNaN(cpu.System)) + assert.False(t, math.IsNaN(cpu.User)) + + assert.False(t, math.IsInf(cpu.Idle, 0)) + assert.False(t, math.IsInf(cpu.Total, 0)) + assert.False(t, math.IsInf(cpu.System, 0)) + assert.False(t, math.IsInf(cpu.User, 0)) + } +} + +func TestCpuStatsCalculator_Nan(t *testing.T) { + times := cpu.TimesStat{ + User: 0.0, + Idle: 100.0, + System: 0.0, + } + + calculator := &cpuStatsCalculator{} + calculator.calculate(times) + stats := calculator.calculate(times) + require.Equal(t, 100.0, stats.Idle) + require.Zero(t, stats.User) + require.Zero(t, stats.System) + require.Zero(t, stats.Iowait) + require.Zero(t, stats.Total) +} diff --git a/lib/hoststats/host.go b/lib/hoststats/host.go new file mode 100644 index 0000000000..426cf43ea2 --- /dev/null +++ b/lib/hoststats/host.go @@ -0,0 +1,92 @@ +package hoststats + +import ( + "time" + + "github.com/armon/go-metrics" +) + +var hostStatsCollectionInterval = 10 * time.Second + +// HostStats represents resource usage hoststats of the host running a Consul agent +type HostStats struct { + Memory *MemoryStats + CPU []*CPUStats + DataDirStats *DiskStats + Uptime uint64 + Timestamp int64 +} + +func (hs *HostStats) Clone() *HostStats { + clone := &HostStats{} + *clone = *hs + return clone +} + +func (hs *HostStats) Emit(sink Metrics, baseLabels []metrics.Label) { + + if hs.Memory != nil { + sink.SetGaugeWithLabels([]string{"host", "memory", "total"}, float32(hs.Memory.Total), baseLabels) + sink.SetGaugeWithLabels([]string{"host", "memory", "available"}, float32(hs.Memory.Available), baseLabels) + sink.SetGaugeWithLabels([]string{"host", "memory", "used"}, float32(hs.Memory.Used), baseLabels) + sink.SetGaugeWithLabels([]string{"host", "memory", "used_percent"}, float32(hs.Memory.UsedPercent), baseLabels) + sink.SetGaugeWithLabels([]string{"host", "memory", "free"}, float32(hs.Memory.Free), baseLabels) + } + + for _, cpu := range hs.CPU { + labels := append(baseLabels, metrics.Label{ + Name: "cpu", + Value: cpu.CPU, + }) + + sink.SetGaugeWithLabels([]string{"host", "cpu", "total"}, float32(cpu.Total), labels) + sink.SetGaugeWithLabels([]string{"host", "cpu", "user"}, float32(cpu.User), labels) + sink.SetGaugeWithLabels([]string{"host", "cpu", "idle"}, float32(cpu.Idle), labels) + sink.SetGaugeWithLabels([]string{"host", "cpu", "iowait"}, float32(cpu.Iowait), labels) + sink.SetGaugeWithLabels([]string{"host", "cpu", "system"}, float32(cpu.System), labels) + } + + if hs.DataDirStats != nil { + diskLabels := append(baseLabels, metrics.Label{ + Name: "path", + Value: hs.DataDirStats.Path, + }) + + sink.SetGaugeWithLabels([]string{"host", "disk", "size"}, float32(hs.DataDirStats.Size), diskLabels) + sink.SetGaugeWithLabels([]string{"host", "disk", "used"}, float32(hs.DataDirStats.Used), diskLabels) + sink.SetGaugeWithLabels([]string{"host", "disk", "available"}, float32(hs.DataDirStats.Available), diskLabels) + sink.SetGaugeWithLabels([]string{"host", "disk", "used_percent"}, float32(hs.DataDirStats.UsedPercent), diskLabels) + sink.SetGaugeWithLabels([]string{"host", "disk", "inodes_percent"}, float32(hs.DataDirStats.InodesUsedPercent), diskLabels) + } + + sink.SetGaugeWithLabels([]string{"host", "uptime"}, float32(hs.Uptime), baseLabels) +} + +// CPUStats represents hoststats related to cpu usage +type CPUStats struct { + CPU string + User float64 + System float64 + Idle float64 + Iowait float64 + Total float64 +} + +// MemoryStats represents hoststats related to virtual memory usage +type MemoryStats struct { + Total uint64 + Available uint64 + Used uint64 + UsedPercent float64 + Free uint64 +} + +// DiskStats represents hoststats related to disk usage +type DiskStats struct { + Path string + Size uint64 + Used uint64 + Available uint64 + UsedPercent float64 + InodesUsedPercent float64 +} diff --git a/lib/hoststats/metrics.go b/lib/hoststats/metrics.go new file mode 100644 index 0000000000..c89d40b813 --- /dev/null +++ b/lib/hoststats/metrics.go @@ -0,0 +1,79 @@ +package hoststats + +import ( + "github.com/armon/go-metrics" + "github.com/armon/go-metrics/prometheus" +) + +// Metrics defines an interface for the methods used to emit data to the go-metrics library. +// `metrics.Default()` should always satisfy this interface. +type Metrics interface { + SetGaugeWithLabels(key []string, val float32, labels []metrics.Label) +} + +var Gauges = []prometheus.GaugeDefinition{ + { + Name: []string{"host", "memory", "total"}, + Help: "Total physical memory in bytes", + }, + { + Name: []string{"host", "memory", "available"}, + Help: "Available physical memory in bytes", + }, + { + Name: []string{"host", "memory", "free"}, + Help: "Free physical memory in bytes", + }, + { + Name: []string{"host", "memory", "used"}, + Help: "Used physical memory in bytes", + }, + { + Name: []string{"host", "memory", "used_percent"}, + Help: "Percentage of physical memory in use", + }, + { + Name: []string{"host", "cpu", "total"}, + Help: "Total cpu utilization", + }, + { + Name: []string{"host", "cpu", "user"}, + Help: "User cpu utilization", + }, + { + Name: []string{"host", "cpu", "idle"}, + Help: "Idle cpu utilization", + }, + { + Name: []string{"host", "cpu", "iowait"}, + Help: "Iowait cpu utilization", + }, + { + Name: []string{"host", "cpu", "system"}, + Help: "System cpu utilization", + }, + { + Name: []string{"host", "disk", "size"}, + Help: "Size of disk in bytes", + }, + { + Name: []string{"host", "disk", "used"}, + Help: "Disk usage in bytes", + }, + { + Name: []string{"host", "disk", "available"}, + Help: "Available bytes on disk", + }, + { + Name: []string{"host", "disk", "used_percent"}, + Help: "Percentage of disk space usage", + }, + { + Name: []string{"host", "disk", "inodes_percent"}, + Help: "Percentage of disk inodes usage", + }, + { + Name: []string{"host", "uptime"}, + Help: "System uptime", + }, +} diff --git a/lib/telemetry.go b/lib/telemetry.go index 2d87707c33..b66ec721b1 100644 --- a/lib/telemetry.go +++ b/lib/telemetry.go @@ -204,6 +204,11 @@ type TelemetryConfig struct { // hcl: telemetry { statsite_address = string } StatsiteAddr string `json:"statsite_address,omitempty" mapstructure:"statsite_address"` + // EnableHostMetrics will enable metrics collected about the host system such as cpu memory and disk usage. + // + // hcl: telemetry { enable_host_metrics = (true|false) } + EnableHostMetrics bool `json:"enable_host_metrics,omitempty" mapstructure:"enable_host_metrics"` + // PrometheusOpts provides configuration for the PrometheusSink. Currently the only configuration // we acquire from hcl is the retention time. We also use definition slices that are set in agent setup // before being passed to InitTelemmetry. diff --git a/website/content/docs/agent/config/config-files.mdx b/website/content/docs/agent/config/config-files.mdx index 3d6efc68f0..d7ac6923e0 100644 --- a/website/content/docs/agent/config/config-files.mdx +++ b/website/content/docs/agent/config/config-files.mdx @@ -1831,6 +1831,9 @@ subsystem that provides Consul's service mesh capabilities. of global tags that will be added to all telemetry packets sent to DogStatsD. It is a list of strings, where each string looks like "my_tag_name:my_tag_value". + - `enable_host_metrics` ((#telemetry-enable_host_metrics)) + This enables reporting of host metrics about system resources, defaults to false. + - `filter_default` ((#telemetry-filter_default)) This controls whether to allow metrics that have not been specified by the filter. Defaults to `true`, which will allow all metrics when no filters are provided. diff --git a/website/content/docs/agent/telemetry.mdx b/website/content/docs/agent/telemetry.mdx index 27626d9be8..5e1b6b8a88 100644 --- a/website/content/docs/agent/telemetry.mdx +++ b/website/content/docs/agent/telemetry.mdx @@ -755,3 +755,32 @@ Consul attaches the following labels to metric values. | `peer_id` | The ID of a peer connected to the reporting cluster or leader. | Any UUID | | `partition` | Name of the partition that the peering is created in. | Any defined partition name in the cluster | +## Server Host Metrics + +Consul servers can report the following metrics about the host's system resources. +This feature must be enabled in the [agent telemetry configuration](/consul/docs/agent/config/config-files#telemetry-enable_host_metrics). +Note that if the Consul server is operating inside a container these metrics +still report host resource usage and do not report any resource limits placed +on the container. + +**Requirements:** +- Consul 1.15.3+ + +| Metric | Description | Unit | Type | +| ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ------- | +| `consul.host.memory.total` | The total physical memory in bytes | mixed | mixed | +| `consul.host.memory.available` | The available physical memory in bytes | mixed | mixed | +| `consul.host.memory.free` | The free physical memory in bytes | mixed | mixed | +| `consul.host.memory.used` | The used physical memory in bytes | mixed | mixed | +| `consul.host.memory.used_percent` | The used physical memory as a percentage of total physical memory | mixed | mixed | +| `consul.host.cpu.total` | The host's total cpu utilization +| `consul.host.cpu.user` | The cpu utilization in user space +| `consul.host.cpu.idle` | The cpu utilization in idle state +| `consul.host.cpu.iowait` | The cpu utilization in iowait state +| `consul.host.cpu.system` | The cpu utilization in system space +| `consul.host.disk.size` | The size in bytes of the data_dir disk +| `consul.host.disk.used` | The number of bytes used on the data_dir disk +| `consul.host.disk.available` | The number of bytes available on the data_dir disk +| `consul.host.disk.used_percent` | The percentage of disk space used on the data_dir disk +| `consul.host.disk.inodes_percent` | The percentage of inode usage on the data_dir disk +| `consul.host.uptime` | The uptime of the host in seconds From d99312b86e7130357c5982d9c2097e05878846c6 Mon Sep 17 00:00:00 2001 From: Eric Haberkorn Date: Tue, 30 May 2023 14:53:42 -0400 Subject: [PATCH 07/72] Add Upstream Service Targeting to Property Override Extension (#17517) * add upstream service targeting to property override extension * Also add baseline goldens for service specific property override extension. * Refactor the extension framework to put more logic into the templates. * fix up the golden tests --- .../builtin/aws-lambda/aws_lambda.go | 27 +- .../builtin/aws-lambda/aws_lambda_test.go | 19 +- .../builtin/ext-authz/structs.go | 2 +- .../builtin/http/localratelimit/ratelimit.go | 25 +- agent/envoyextensions/builtin/lua/lua.go | 8 +- .../property-override/property_override.go | 163 ++++++----- .../property_override_test.go | 247 +++++++++++++---- agent/envoyextensions/builtin/wasm/structs.go | 2 +- .../envoyextensions/builtin/wasm/wasm_test.go | 2 +- agent/xds/clusters.go | 3 +- agent/xds/delta_envoy_extender_oss_test.go | 222 ++++++++++++++- agent/xds/extensionruntime/runtime_config.go | 25 +- .../runtime_config_oss_test.go | 49 +++- agent/xds/failover_policy.go | 3 +- ...ic-upstream-service-failover.latest.golden | 199 ++++++++++++++ ...ic-upstream-service-splitter.latest.golden | 179 +++++++++++++ ...ch-specific-upstream-service.latest.golden | 192 +++++++++++++ ...ic-upstream-service-failover.latest.golden | 115 ++++++++ ...ic-upstream-service-splitter.latest.golden | 115 ++++++++ ...ch-specific-upstream-service.latest.golden | 109 ++++++++ ...ic-upstream-service-failover.latest.golden | 235 ++++++++++++++++ ...ic-upstream-service-splitter.latest.golden | 252 ++++++++++++++++++ ...ch-specific-upstream-service.latest.golden | 234 ++++++++++++++++ ...ic-upstream-service-failover.latest.golden | 32 +++ ...ic-upstream-service-splitter.latest.golden | 43 +++ ...ch-specific-upstream-service.latest.golden | 31 +++ .../extensioncommon/basic_envoy_extender.go | 36 ++- .../basic_extension_adapter.go | 20 +- envoyextensions/extensioncommon/resources.go | 204 +++++++++++++- .../extensioncommon/runtime_config.go | 9 +- .../extensioncommon/runtime_config_test.go | 2 +- .../upstream_envoy_extender.go | 10 +- envoyextensions/xdscommon/xdscommon.go | 2 + troubleshoot/proxy/validateupstream.go | 2 +- troubleshoot/validate/validate.go | 61 +++-- troubleshoot/validate/validate_test.go | 2 +- 36 files changed, 2634 insertions(+), 247 deletions(-) create mode 100644 agent/xds/testdata/builtin_extension/clusters/propertyoverride-patch-specific-upstream-service-failover.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/clusters/propertyoverride-patch-specific-upstream-service-splitter.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/clusters/propertyoverride-patch-specific-upstream-service.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/endpoints/propertyoverride-patch-specific-upstream-service-failover.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/endpoints/propertyoverride-patch-specific-upstream-service-splitter.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/endpoints/propertyoverride-patch-specific-upstream-service.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service-failover.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service-splitter.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/routes/propertyoverride-patch-specific-upstream-service-failover.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/routes/propertyoverride-patch-specific-upstream-service-splitter.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/routes/propertyoverride-patch-specific-upstream-service.latest.golden diff --git a/agent/envoyextensions/builtin/aws-lambda/aws_lambda.go b/agent/envoyextensions/builtin/aws-lambda/aws_lambda.go index cc7577f3fe..fa36d6fa50 100644 --- a/agent/envoyextensions/builtin/aws-lambda/aws_lambda.go +++ b/agent/envoyextensions/builtin/aws-lambda/aws_lambda.go @@ -72,16 +72,19 @@ func (a *awsLambda) CanApply(config *extensioncommon.RuntimeConfig) bool { // PatchRoute modifies the routing configuration for a service of kind TerminatingGateway. If the kind is // not TerminatingGateway, then it can not be modified. -func (a *awsLambda) PatchRoute(r *extensioncommon.RuntimeConfig, route *envoy_route_v3.RouteConfiguration) (*envoy_route_v3.RouteConfiguration, bool, error) { - if r.Kind != api.ServiceKindTerminatingGateway { - return route, false, nil +func (a *awsLambda) PatchRoute(p extensioncommon.RoutePayload) (*envoy_route_v3.RouteConfiguration, bool, error) { + cfg := p.RuntimeConfig + if cfg.Kind != api.ServiceKindTerminatingGateway { + return p.Message, false, nil } // Only patch outbound routes. - if extensioncommon.IsRouteToLocalAppCluster(route) { - return route, false, nil + if p.IsInbound() { + return p.Message, false, nil } + route := p.Message + for _, virtualHost := range route.VirtualHosts { for _, route := range virtualHost.Routes { action, ok := route.Action.(*envoy_route_v3.Route_Route) @@ -101,16 +104,18 @@ func (a *awsLambda) PatchRoute(r *extensioncommon.RuntimeConfig, route *envoy_ro } // PatchCluster patches the provided envoy cluster with data required to support an AWS lambda function -func (a *awsLambda) PatchCluster(_ *extensioncommon.RuntimeConfig, c *envoy_cluster_v3.Cluster) (*envoy_cluster_v3.Cluster, bool, error) { +func (a *awsLambda) PatchCluster(p extensioncommon.ClusterPayload) (*envoy_cluster_v3.Cluster, bool, error) { // Only patch outbound clusters. - if extensioncommon.IsLocalAppCluster(c) { - return c, false, nil + if p.IsInbound() { + return p.Message, false, nil } transportSocket, err := extensioncommon.MakeUpstreamTLSTransportSocket(&envoy_tls_v3.UpstreamTlsContext{ Sni: "*.amazonaws.com", }) + c := p.Message + if err != nil { return c, false, fmt.Errorf("failed to make transport socket: %w", err) } @@ -168,9 +173,11 @@ func (a *awsLambda) PatchCluster(_ *extensioncommon.RuntimeConfig, c *envoy_clus // PatchFilter patches the provided envoy filter with an inserted lambda filter being careful not to // overwrite the http filters. -func (a *awsLambda) PatchFilter(_ *extensioncommon.RuntimeConfig, filter *envoy_listener_v3.Filter, isInboundListener bool) (*envoy_listener_v3.Filter, bool, error) { +func (a *awsLambda) PatchFilter(p extensioncommon.FilterPayload) (*envoy_listener_v3.Filter, bool, error) { + filter := p.Message + // Only patch outbound filters. - if isInboundListener { + if p.IsInbound() { return filter, false, nil } diff --git a/agent/envoyextensions/builtin/aws-lambda/aws_lambda_test.go b/agent/envoyextensions/builtin/aws-lambda/aws_lambda_test.go index af7b95fd8d..26f49eef4b 100644 --- a/agent/envoyextensions/builtin/aws-lambda/aws_lambda_test.go +++ b/agent/envoyextensions/builtin/aws-lambda/aws_lambda_test.go @@ -202,7 +202,10 @@ func TestPatchCluster(t *testing.T) { // Test patching the cluster rc := extensioncommon.RuntimeConfig{} - patchedCluster, patchSuccess, err := tc.lambda.PatchCluster(&rc, tc.input) + patchedCluster, patchSuccess, err := tc.lambda.PatchCluster(extensioncommon.ClusterPayload{ + RuntimeConfig: &rc, + Message: tc.input, + }) if tc.isErrExpected { assert.Error(t, err) assert.False(t, patchSuccess) @@ -307,7 +310,10 @@ func TestPatchRoute(t *testing.T) { for name, tc := range tests { t.Run(name, func(t *testing.T) { l := awsLambda{} - r, ok, err := l.PatchRoute(tc.conf, tc.route) + r, ok, err := l.PatchRoute(extensioncommon.RoutePayload{ + RuntimeConfig: tc.conf, + Message: tc.route, + }) require.NoError(t, err) require.Equal(t, tc.expectRoute, r) require.Equal(t, tc.expectBool, ok) @@ -456,7 +462,14 @@ func TestPatchFilter(t *testing.T) { PayloadPassthrough: true, InvocationMode: "asynchronous", } - f, ok, err := l.PatchFilter(nil, tc.filter, tc.isInboundFilter) + d := extensioncommon.TrafficDirectionOutbound + if tc.isInboundFilter { + d = extensioncommon.TrafficDirectionInbound + } + f, ok, err := l.PatchFilter(extensioncommon.FilterPayload{ + Message: tc.filter, + TrafficDirection: d, + }) require.Equal(t, tc.expectBool, ok) if tc.expectErr == "" { require.NoError(t, err) diff --git a/agent/envoyextensions/builtin/ext-authz/structs.go b/agent/envoyextensions/builtin/ext-authz/structs.go index 746b2ca7cb..11b7f49453 100644 --- a/agent/envoyextensions/builtin/ext-authz/structs.go +++ b/agent/envoyextensions/builtin/ext-authz/structs.go @@ -601,7 +601,7 @@ func (t Target) clusterName(cfg *cmn.RuntimeConfig) (string, error) { for service, upstream := range cfg.Upstreams { if service == t.Service { - for sni := range upstream.SNI { + for sni := range upstream.SNIs { return sni, nil } } diff --git a/agent/envoyextensions/builtin/http/localratelimit/ratelimit.go b/agent/envoyextensions/builtin/http/localratelimit/ratelimit.go index 686a2390a8..e70a704aeb 100644 --- a/agent/envoyextensions/builtin/http/localratelimit/ratelimit.go +++ b/agent/envoyextensions/builtin/http/localratelimit/ratelimit.go @@ -102,10 +102,11 @@ func (p *ratelimit) CanApply(config *extensioncommon.RuntimeConfig) bool { // PatchFilter inserts a http local rate_limit filter at the head of // envoy.filters.network.http_connection_manager filters -func (p ratelimit) PatchFilter(_ *extensioncommon.RuntimeConfig, filter *envoy_listener_v3.Filter, isInboundListener bool) (*envoy_listener_v3.Filter, bool, error) { +func (r ratelimit) PatchFilter(p extensioncommon.FilterPayload) (*envoy_listener_v3.Filter, bool, error) { + filter := p.Message // rate limit is only applied to the inbound listener of the service itself // since the limit is aggregated from all downstream connections. - if !isInboundListener { + if !p.IsInbound() { return filter, false, nil } @@ -123,34 +124,34 @@ func (p ratelimit) PatchFilter(_ *extensioncommon.RuntimeConfig, filter *envoy_l tokenBucket := envoy_type_v3.TokenBucket{} - if p.TokensPerFill != nil { + if r.TokensPerFill != nil { tokenBucket.TokensPerFill = &wrappers.UInt32Value{ - Value: uint32(*p.TokensPerFill), + Value: uint32(*r.TokensPerFill), } } - if p.MaxTokens != nil { - tokenBucket.MaxTokens = uint32(*p.MaxTokens) + if r.MaxTokens != nil { + tokenBucket.MaxTokens = uint32(*r.MaxTokens) } - if p.FillInterval != nil { - tokenBucket.FillInterval = durationpb.New(time.Duration(*p.FillInterval) * time.Second) + if r.FillInterval != nil { + tokenBucket.FillInterval = durationpb.New(time.Duration(*r.FillInterval) * time.Second) } var FilterEnabledDefault *envoy_core_v3.RuntimeFractionalPercent - if p.FilterEnabled != nil { + if r.FilterEnabled != nil { FilterEnabledDefault = &envoy_core_v3.RuntimeFractionalPercent{ DefaultValue: &envoy_type_v3.FractionalPercent{ - Numerator: *p.FilterEnabled, + Numerator: *r.FilterEnabled, Denominator: envoy_type_v3.FractionalPercent_HUNDRED, }, } } var FilterEnforcedDefault *envoy_core_v3.RuntimeFractionalPercent - if p.FilterEnforced != nil { + if r.FilterEnforced != nil { FilterEnforcedDefault = &envoy_core_v3.RuntimeFractionalPercent{ DefaultValue: &envoy_type_v3.FractionalPercent{ - Numerator: *p.FilterEnforced, + Numerator: *r.FilterEnforced, Denominator: envoy_type_v3.FractionalPercent_HUNDRED, }, } diff --git a/agent/envoyextensions/builtin/lua/lua.go b/agent/envoyextensions/builtin/lua/lua.go index 32092c5ce8..8293228a79 100644 --- a/agent/envoyextensions/builtin/lua/lua.go +++ b/agent/envoyextensions/builtin/lua/lua.go @@ -67,14 +67,16 @@ func (l *lua) CanApply(config *extensioncommon.RuntimeConfig) bool { return string(config.Kind) == l.ProxyType } -func (l *lua) matchesListenerDirection(isInboundListener bool) bool { +func (l *lua) matchesListenerDirection(p extensioncommon.FilterPayload) bool { + isInboundListener := p.IsInbound() return (!isInboundListener && l.Listener == "outbound") || (isInboundListener && l.Listener == "inbound") } // PatchFilter inserts a lua filter directly prior to envoy.filters.http.router. -func (l *lua) PatchFilter(_ *extensioncommon.RuntimeConfig, filter *envoy_listener_v3.Filter, isInboundListener bool) (*envoy_listener_v3.Filter, bool, error) { +func (l *lua) PatchFilter(p extensioncommon.FilterPayload) (*envoy_listener_v3.Filter, bool, error) { + filter := p.Message // Make sure filter matches extension config. - if !l.matchesListenerDirection(isInboundListener) { + if !l.matchesListenerDirection(p) { return filter, false, nil } diff --git a/agent/envoyextensions/builtin/property-override/property_override.go b/agent/envoyextensions/builtin/property-override/property_override.go index dcc8e5a3e5..6bdf9e7a39 100644 --- a/agent/envoyextensions/builtin/property-override/property_override.go +++ b/agent/envoyextensions/builtin/property-override/property_override.go @@ -2,7 +2,6 @@ package propertyoverride import ( "fmt" - "strings" envoy_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3" envoy_endpoint_v3 "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3" @@ -14,14 +13,10 @@ import ( "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/envoyextensions/extensioncommon" - "github.com/hashicorp/consul/lib/maps" ) -type stringSet map[string]struct{} - type propertyOverride struct { extensioncommon.BasicExtensionAdapter - // Patches are an array of Patch operations to be applied to the target resource(s). Patches []Patch // Debug controls error messages when Path matching fails. @@ -43,7 +38,42 @@ type ResourceFilter struct { // TrafficDirection determines whether the patch will be applied to a service's inbound // or outbound resources. // This field is required. - TrafficDirection TrafficDirection + TrafficDirection extensioncommon.TrafficDirection + + // Services indicates which upstream services will have corresponding Envoy resources patched. + // This includes directly targeted and discovery chain services. If Services is omitted or + // empty, all resources matching the filter will be targeted (including TProxy, which + // implicitly corresponds to any number of upstreams). Services must be omitted unless + // TrafficDirection is set to outbound. + Services []*ServiceName +} + +func matchesResourceFilter[K proto.Message](rf ResourceFilter, resourceType ResourceType, payload extensioncommon.Payload[K]) bool { + if resourceType != rf.ResourceType { + return false + } + + if payload.TrafficDirection != rf.TrafficDirection { + return false + } + + if len(rf.Services) == 0 { + return true + } + + for _, s := range rf.Services { + if payload.ServiceName == nil || s.CompoundServiceName != *payload.ServiceName { + continue + } + + return true + } + + return false +} + +type ServiceName struct { + api.CompoundServiceName } // ResourceType is the type of Envoy resource being patched. @@ -56,23 +86,13 @@ const ( ResourceTypeRoute ResourceType = "route" ) -var ResourceTypes = stringSet{ +var ResourceTypes = extensioncommon.StringSet{ string(ResourceTypeCluster): {}, string(ResourceTypeClusterLoadAssignment): {}, - string(ResourceTypeListener): {}, string(ResourceTypeRoute): {}, + string(ResourceTypeListener): {}, } -// TrafficDirection determines whether inbound or outbound Envoy resources will be patched. -type TrafficDirection string - -const ( - TrafficDirectionInbound TrafficDirection = "inbound" - TrafficDirectionOutbound TrafficDirection = "outbound" -) - -var TrafficDirections = stringSet{string(TrafficDirectionInbound): {}, string(TrafficDirectionOutbound): {}} - // Op is the type of JSON Patch operation being applied. type Op string @@ -81,10 +101,10 @@ const ( OpRemove Op = "remove" ) -var Ops = stringSet{string(OpAdd): {}, string(OpRemove): {}} +var Ops = extensioncommon.StringSet{string(OpAdd): {}, string(OpRemove): {}} // validProxyTypes is the set of supported proxy types for this extension. -var validProxyTypes = stringSet{ +var validProxyTypes = extensioncommon.StringSet{ string(api.ServiceKindConnectProxy): struct{}{}, string(api.ServiceKindTerminatingGateway): struct{}{}, } @@ -139,27 +159,58 @@ type Patch struct { var _ extensioncommon.BasicExtension = (*propertyOverride)(nil) -func (c *stringSet) checkRequired(v, fieldName string) error { - if _, ok := (*c)[v]; !ok { - if v == "" { - return fmt.Errorf("field %s is required", fieldName) - } - return fmt.Errorf("invalid %s '%q'; supported values: %s", - fieldName, v, strings.Join(maps.SliceOfKeys(*c), ", ")) +func (f *ResourceFilter) isEmpty() bool { + if f == nil { + return true } - return nil + + if len(f.Services) > 0 { + return false + } + + if string(f.TrafficDirection) != "" { + return false + } + + if string(f.ResourceType) != "" { + return false + } + + return true } func (f *ResourceFilter) validate() error { - if f == nil || *f == (ResourceFilter{}) { + if f == nil || f.isEmpty() { return fmt.Errorf("field ResourceFilter is required") } - if err := ResourceTypes.checkRequired(string(f.ResourceType), "ResourceType"); err != nil { + if err := ResourceTypes.CheckRequired(string(f.ResourceType), "ResourceType"); err != nil { return err } - if err := TrafficDirections.checkRequired(string(f.TrafficDirection), "TrafficDirection"); err != nil { + if err := extensioncommon.TrafficDirections.CheckRequired(string(f.TrafficDirection), "TrafficDirection"); err != nil { return err } + + for i := range f.Services { + sn := f.Services[i] + sn.normalize() + + if err := sn.validate(); err != nil { + return err + } + } + + return nil +} + +func (sn *ServiceName) normalize() { + extensioncommon.NormalizeServiceName(&sn.CompoundServiceName) +} + +func (sn *ServiceName) validate() error { + if sn.Name == "" { + return fmt.Errorf("service name is required") + } + return nil } @@ -169,7 +220,7 @@ func (p *Patch) validate(debug bool) error { return err } - if err := Ops.checkRequired(string(p.Op), "Op"); err != nil { + if err := Ops.CheckRequired(string(p.Op), "Op"); err != nil { return err } @@ -209,7 +260,7 @@ func (p *propertyOverride) validate() error { } } - if err := validProxyTypes.checkRequired(string(p.ProxyType), "ProxyType"); err != nil { + if err := validProxyTypes.CheckRequired(string(p.ProxyType), "ProxyType"); err != nil { resultErr = multierror.Append(resultErr, err) } @@ -243,57 +294,35 @@ func (p *propertyOverride) CanApply(config *extensioncommon.RuntimeConfig) bool } // PatchRoute patches the provided Envoy Route with any applicable `route` ResourceType patches. -func (p *propertyOverride) PatchRoute(_ *extensioncommon.RuntimeConfig, r *envoy_route_v3.RouteConfiguration) (*envoy_route_v3.RouteConfiguration, bool, error) { - d := TrafficDirectionOutbound - if extensioncommon.IsRouteToLocalAppCluster(r) { - d = TrafficDirectionInbound - } - return patchResourceType[*envoy_route_v3.RouteConfiguration](r, p, ResourceTypeRoute, d, &defaultStructPatcher[*envoy_route_v3.RouteConfiguration]{}) +func (p *propertyOverride) PatchRoute(payload extensioncommon.RoutePayload) (*envoy_route_v3.RouteConfiguration, bool, error) { + return patchResourceType[*envoy_route_v3.RouteConfiguration](p, ResourceTypeRoute, payload, &defaultStructPatcher[*envoy_route_v3.RouteConfiguration]{}) } // PatchCluster patches the provided Envoy Cluster with any applicable `cluster` ResourceType patches. -func (p *propertyOverride) PatchCluster(_ *extensioncommon.RuntimeConfig, c *envoy_cluster_v3.Cluster) (*envoy_cluster_v3.Cluster, bool, error) { - d := TrafficDirectionOutbound - if extensioncommon.IsLocalAppCluster(c) { - d = TrafficDirectionInbound - } - return patchResourceType[*envoy_cluster_v3.Cluster](c, p, ResourceTypeCluster, d, &defaultStructPatcher[*envoy_cluster_v3.Cluster]{}) +func (p *propertyOverride) PatchCluster(payload extensioncommon.ClusterPayload) (*envoy_cluster_v3.Cluster, bool, error) { + return patchResourceType[*envoy_cluster_v3.Cluster](p, ResourceTypeCluster, payload, &defaultStructPatcher[*envoy_cluster_v3.Cluster]{}) } // PatchClusterLoadAssignment patches the provided Envoy ClusterLoadAssignment with any applicable `cluster-load-assignment` ResourceType patches. -func (p *propertyOverride) PatchClusterLoadAssignment(_ *extensioncommon.RuntimeConfig, c *envoy_endpoint_v3.ClusterLoadAssignment) (*envoy_endpoint_v3.ClusterLoadAssignment, bool, error) { - d := TrafficDirectionOutbound - if extensioncommon.IsLocalAppClusterLoadAssignment(c) { - d = TrafficDirectionInbound - } - return patchResourceType[*envoy_endpoint_v3.ClusterLoadAssignment](c, p, ResourceTypeClusterLoadAssignment, d, &defaultStructPatcher[*envoy_endpoint_v3.ClusterLoadAssignment]{}) +func (p *propertyOverride) PatchClusterLoadAssignment(payload extensioncommon.ClusterLoadAssignmentPayload) (*envoy_endpoint_v3.ClusterLoadAssignment, bool, error) { + return patchResourceType[*envoy_endpoint_v3.ClusterLoadAssignment](p, ResourceTypeClusterLoadAssignment, payload, &defaultStructPatcher[*envoy_endpoint_v3.ClusterLoadAssignment]{}) } // PatchListener patches the provided Envoy Listener with any applicable `listener` ResourceType patches. -func (p *propertyOverride) PatchListener(_ *extensioncommon.RuntimeConfig, l *envoy_listener_v3.Listener) (*envoy_listener_v3.Listener, bool, error) { - d := TrafficDirectionOutbound - if extensioncommon.IsInboundPublicListener(l) { - d = TrafficDirectionInbound - } - return patchResourceType[*envoy_listener_v3.Listener](l, p, ResourceTypeListener, d, &defaultStructPatcher[*envoy_listener_v3.Listener]{}) -} - -// PatchFilter does nothing as this extension does not target Filters directly. -func (p *propertyOverride) PatchFilter(_ *extensioncommon.RuntimeConfig, f *envoy_listener_v3.Filter, _ bool) (*envoy_listener_v3.Filter, bool, error) { - return f, false, nil +func (p *propertyOverride) PatchListener(payload extensioncommon.ListenerPayload) (*envoy_listener_v3.Listener, bool, error) { + return patchResourceType[*envoy_listener_v3.Listener](p, ResourceTypeListener, payload, &defaultStructPatcher[*envoy_listener_v3.Listener]{}) } // patchResourceType applies Patches matching the given ResourceType to the target K. // This helper simplifies implementation of the above per-type patch methods defined by BasicExtension. -func patchResourceType[K proto.Message](k K, p *propertyOverride, t ResourceType, d TrafficDirection, patcher structPatcher[K]) (K, bool, error) { +func patchResourceType[K proto.Message](p *propertyOverride, resourceType ResourceType, payload extensioncommon.Payload[K], patcher structPatcher[K]) (K, bool, error) { resultPatched := false var resultErr error + k := payload.Message + for _, patch := range p.Patches { - if patch.ResourceFilter.ResourceType != t { - continue - } - if patch.ResourceFilter.TrafficDirection != d { + if !matchesResourceFilter(patch.ResourceFilter, resourceType, payload) { continue } newK, err := patcher.applyPatch(k, patch, p.Debug) diff --git a/agent/envoyextensions/builtin/property-override/property_override_test.go b/agent/envoyextensions/builtin/property-override/property_override_test.go index 40200ca777..f613769aa3 100644 --- a/agent/envoyextensions/builtin/property-override/property_override_test.go +++ b/agent/envoyextensions/builtin/property-override/property_override_test.go @@ -2,11 +2,13 @@ package propertyoverride import ( "fmt" - routev3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" "strings" "testing" clusterv3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3" + endpointv3 "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3" + listenerv3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" + routev3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/envoyextensions/extensioncommon" "github.com/stretchr/testify/require" @@ -32,7 +34,7 @@ func TestConstructor(t *testing.T) { makeResourceFilter := func(overrides map[string]any) map[string]any { f := map[string]any{ "ResourceType": ResourceTypeRoute, - "TrafficDirection": TrafficDirectionOutbound, + "TrafficDirection": extensioncommon.TrafficDirectionOutbound, } return applyOverrides(f, overrides) } @@ -63,7 +65,7 @@ func TestConstructor(t *testing.T) { errMsg string } - validTestCase := func(o Op, d TrafficDirection, t ResourceType) testCase { + validTestCase := func(o Op, d extensioncommon.TrafficDirection, t ResourceType) testCase { var v any = "foo" if o != OpAdd { v = nil @@ -214,6 +216,19 @@ func TestConstructor(t *testing.T) { ok: false, errMsg: fmt.Sprintf("field Value is not supported for %s operation", OpRemove), }, + "empty service name": { + arguments: makeArguments(map[string]any{"Patches": []map[string]any{ + makePatch(map[string]any{ + "ResourceFilter": makeResourceFilter(map[string]any{ + "Services": []ServiceName{ + {CompoundServiceName: api.CompoundServiceName{}}, + }, + }), + }), + }}), + ok: false, + errMsg: "service name is required", + }, // See decode.HookWeakDecodeFromSlice for more details. In practice, we can end up // with a "Patches" field decoded to the single "Patch" value contained in the // serialized slice (raised from the containing slice). Using WeakDecode solves @@ -222,7 +237,7 @@ func TestConstructor(t *testing.T) { // by WeakDecode as it is a more-permissive version of the default behavior. "single value Patches decoded as map construction succeeds": { arguments: makeArguments(map[string]any{"Patches": makePatch(map[string]any{})}), - expected: validTestCase(OpAdd, TrafficDirectionOutbound, ResourceTypeRoute).expected, + expected: validTestCase(OpAdd, extensioncommon.TrafficDirectionOutbound, ResourceTypeRoute).expected, ok: true, }, "invalid ProxyType": { @@ -248,10 +263,10 @@ func TestConstructor(t *testing.T) { } for o := range Ops { - for d := range TrafficDirections { + for d := range extensioncommon.TrafficDirections { for t := range ResourceTypes { cases["valid everything: "+strings.Join([]string{o, d, t}, ",")] = - validTestCase(Op(o), TrafficDirection(d), ResourceType(t)) + validTestCase(Op(o), extensioncommon.TrafficDirection(d), ResourceType(t)) } } } @@ -294,32 +309,62 @@ func Test_patchResourceType(t *testing.T) { Patches: patches, } } - makePatchWithPath := func(t ResourceType, d TrafficDirection, p string) Patch { + makePatchWithPath := func(filter ResourceFilter, p string) Patch { return Patch{ - ResourceFilter: ResourceFilter{ - ResourceType: t, - TrafficDirection: d, - }, - Op: OpAdd, - Path: p, - Value: 1, + ResourceFilter: filter, + Op: OpAdd, + Path: p, + Value: 1, } } - makePatch := func(t ResourceType, d TrafficDirection) Patch { - return makePatchWithPath(t, d, "/foo") + makePatch := func(filter ResourceFilter) Patch { + return makePatchWithPath(filter, "/foo") } - clusterOutbound := makePatch(ResourceTypeCluster, TrafficDirectionOutbound) - clusterInbound := makePatch(ResourceTypeCluster, TrafficDirectionInbound) - routeOutbound := makePatch(ResourceTypeRoute, TrafficDirectionOutbound) - routeOutbound2 := makePatchWithPath(ResourceTypeRoute, TrafficDirectionOutbound, "/bar") - routeInbound := makePatch(ResourceTypeRoute, TrafficDirectionInbound) + svc1 := ServiceName{ + CompoundServiceName: api.CompoundServiceName{Name: "svc1"}, + } + svc2 := ServiceName{ + CompoundServiceName: api.CompoundServiceName{Name: "svc2"}, + } + + clusterOutbound := makePatch(ResourceFilter{ + ResourceType: ResourceTypeCluster, + TrafficDirection: extensioncommon.TrafficDirectionOutbound, + }) + clusterInbound := makePatch(ResourceFilter{ + ResourceType: ResourceTypeCluster, + TrafficDirection: extensioncommon.TrafficDirectionInbound, + }) + listenerOutbound := makePatch(ResourceFilter{ + ResourceType: ResourceTypeListener, + TrafficDirection: extensioncommon.TrafficDirectionOutbound, + }) + listenerOutbound2 := makePatchWithPath(ResourceFilter{ + ResourceType: ResourceTypeListener, + TrafficDirection: extensioncommon.TrafficDirectionOutbound, + }, "/bar") + listenerInbound := makePatch(ResourceFilter{ + ResourceType: ResourceTypeListener, + TrafficDirection: extensioncommon.TrafficDirectionInbound, + }) + routeOutbound := makePatch(ResourceFilter{ + ResourceType: ResourceTypeRoute, + TrafficDirection: extensioncommon.TrafficDirectionOutbound, + }) + routeOutbound2 := makePatchWithPath(ResourceFilter{ + ResourceType: ResourceTypeRoute, + TrafficDirection: extensioncommon.TrafficDirectionOutbound, + }, "/bar") + routeInbound := makePatch(ResourceFilter{ + ResourceType: ResourceTypeRoute, + TrafficDirection: extensioncommon.TrafficDirectionInbound, + }) type args struct { - d TrafficDirection - k proto.Message - p *propertyOverride - t ResourceType + resourceType ResourceType + payload extensioncommon.Payload[proto.Message] + p *propertyOverride } type testCase struct { args args @@ -329,79 +374,179 @@ func Test_patchResourceType(t *testing.T) { cases := map[string]testCase{ "outbound gets matching patch": { args: args{ - d: TrafficDirectionOutbound, - k: &clusterv3.Cluster{}, + resourceType: ResourceTypeCluster, + payload: extensioncommon.Payload[proto.Message]{ + TrafficDirection: extensioncommon.TrafficDirectionOutbound, + Message: &clusterv3.Cluster{}, + }, p: makeExtension(clusterOutbound), - t: ResourceTypeCluster, }, expectPatched: true, wantApplied: []Patch{clusterOutbound}, }, "inbound gets matching patch": { args: args{ - d: TrafficDirectionInbound, - k: &clusterv3.Cluster{}, + resourceType: ResourceTypeCluster, + payload: extensioncommon.Payload[proto.Message]{ + TrafficDirection: extensioncommon.TrafficDirectionInbound, + Message: &clusterv3.Cluster{}, + }, p: makeExtension(clusterInbound), - t: ResourceTypeCluster, }, expectPatched: true, wantApplied: []Patch{clusterInbound}, }, "multiple resources same direction only gets matching resource": { args: args{ - d: TrafficDirectionOutbound, - k: &clusterv3.Cluster{}, - p: makeExtension(clusterOutbound, routeOutbound), - t: ResourceTypeCluster, + resourceType: ResourceTypeCluster, + payload: extensioncommon.Payload[proto.Message]{ + TrafficDirection: extensioncommon.TrafficDirectionOutbound, + Message: &clusterv3.Cluster{}, + }, + p: makeExtension(clusterOutbound, listenerOutbound), }, expectPatched: true, wantApplied: []Patch{clusterOutbound}, }, "multiple directions same resource only gets matching direction": { args: args{ - d: TrafficDirectionOutbound, - k: &clusterv3.Cluster{}, + resourceType: ResourceTypeCluster, + payload: extensioncommon.Payload[proto.Message]{ + TrafficDirection: extensioncommon.TrafficDirectionOutbound, + Message: &clusterv3.Cluster{}, + }, p: makeExtension(clusterOutbound, clusterInbound), - t: ResourceTypeCluster, }, expectPatched: true, wantApplied: []Patch{clusterOutbound}, }, "multiple directions and resources only gets matching patch": { args: args{ - d: TrafficDirectionInbound, - k: &routev3.RouteConfiguration{}, - p: makeExtension(clusterOutbound, clusterInbound, routeOutbound, routeInbound), - t: ResourceTypeRoute, + resourceType: ResourceTypeRoute, + payload: extensioncommon.Payload[proto.Message]{ + TrafficDirection: extensioncommon.TrafficDirectionInbound, + Message: &routev3.RouteConfiguration{}, + }, + p: makeExtension(clusterOutbound, clusterInbound, listenerOutbound, listenerInbound, routeOutbound, routeOutbound2, routeInbound), }, expectPatched: true, wantApplied: []Patch{routeInbound}, }, "multiple directions and resources multiple matches gets all matching patches": { args: args{ - d: TrafficDirectionOutbound, - k: &routev3.RouteConfiguration{}, - p: makeExtension(clusterOutbound, clusterInbound, routeOutbound, routeInbound, routeOutbound2), - t: ResourceTypeRoute, + resourceType: ResourceTypeRoute, + payload: extensioncommon.Payload[proto.Message]{ + TrafficDirection: extensioncommon.TrafficDirectionOutbound, + Message: &routev3.RouteConfiguration{}, + }, + p: makeExtension(clusterOutbound, clusterInbound, listenerOutbound, listenerInbound, listenerOutbound2, routeOutbound, routeOutbound2, routeInbound), }, expectPatched: true, wantApplied: []Patch{routeOutbound, routeOutbound2}, }, "multiple directions and resources no matches gets no patches": { args: args{ - d: TrafficDirectionOutbound, - k: &routev3.RouteConfiguration{}, - p: makeExtension(clusterInbound, routeOutbound, routeInbound, routeOutbound2), - t: ResourceTypeCluster, + resourceType: ResourceTypeCluster, + payload: extensioncommon.Payload[proto.Message]{ + TrafficDirection: extensioncommon.TrafficDirectionOutbound, + Message: &clusterv3.Cluster{}, + }, + p: makeExtension(clusterInbound, listenerOutbound, listenerInbound, listenerOutbound2, routeInbound, routeOutbound), }, expectPatched: false, wantApplied: nil, }, } + + type resourceTypeServiceMatch struct { + resourceType ResourceType + message proto.Message + } + + resourceTypeCases := []resourceTypeServiceMatch{ + { + resourceType: ResourceTypeCluster, + message: &clusterv3.Cluster{}, + }, + { + resourceType: ResourceTypeListener, + message: &listenerv3.Listener{}, + }, + { + resourceType: ResourceTypeRoute, + message: &routev3.RouteConfiguration{}, + }, + { + resourceType: ResourceTypeClusterLoadAssignment, + message: &endpointv3.ClusterLoadAssignment{}, + }, + } + + for _, tc := range resourceTypeCases { + { + patch := makePatch(ResourceFilter{ + ResourceType: tc.resourceType, + TrafficDirection: extensioncommon.TrafficDirectionOutbound, + Services: []*ServiceName{ + {CompoundServiceName: svc2.CompoundServiceName}, + }, + }) + + cases[fmt.Sprintf("%s - no match", tc.resourceType)] = testCase{ + args: args{ + resourceType: tc.resourceType, + payload: extensioncommon.Payload[proto.Message]{ + TrafficDirection: extensioncommon.TrafficDirectionOutbound, + ServiceName: &svc1.CompoundServiceName, + Message: tc.message, + RuntimeConfig: &extensioncommon.RuntimeConfig{ + Upstreams: map[api.CompoundServiceName]*extensioncommon.UpstreamData{ + svc1.CompoundServiceName: {}, + }, + }, + }, + p: makeExtension(patch), + }, + expectPatched: false, + wantApplied: nil, + } + } + + { + patch := makePatch(ResourceFilter{ + ResourceType: tc.resourceType, + TrafficDirection: extensioncommon.TrafficDirectionOutbound, + Services: []*ServiceName{ + {CompoundServiceName: svc2.CompoundServiceName}, + {CompoundServiceName: svc1.CompoundServiceName}, + }, + }) + + cases[fmt.Sprintf("%s - match", tc.resourceType)] = testCase{ + args: args{ + resourceType: tc.resourceType, + payload: extensioncommon.Payload[proto.Message]{ + TrafficDirection: extensioncommon.TrafficDirectionOutbound, + ServiceName: &svc1.CompoundServiceName, + Message: tc.message, + RuntimeConfig: &extensioncommon.RuntimeConfig{ + Upstreams: map[api.CompoundServiceName]*extensioncommon.UpstreamData{ + svc1.CompoundServiceName: {}, + }, + }, + }, + p: makeExtension(patch), + }, + expectPatched: true, + wantApplied: []Patch{patch}, + } + } + } + for n, tc := range cases { t.Run(n, func(t *testing.T) { mockPatcher := MockPatcher[proto.Message]{} - _, patched, err := patchResourceType[proto.Message](tc.args.k, tc.args.p, tc.args.t, tc.args.d, &mockPatcher) + _, patched, err := patchResourceType[proto.Message](tc.args.p, tc.args.resourceType, tc.args.payload, &mockPatcher) require.NoError(t, err, "unexpected error from mock") require.Equal(t, tc.expectPatched, patched) diff --git a/agent/envoyextensions/builtin/wasm/structs.go b/agent/envoyextensions/builtin/wasm/structs.go index 4a29035c15..012099ab62 100644 --- a/agent/envoyextensions/builtin/wasm/structs.go +++ b/agent/envoyextensions/builtin/wasm/structs.go @@ -195,7 +195,7 @@ func (p *pluginConfig) asyncDataSource(rtCfg *extensioncommon.RuntimeConfig) (*e clusterSNI := "" for service, upstream := range rtCfg.Upstreams { if service == remote.HttpURI.Service { - for sni := range upstream.SNI { + for sni := range upstream.SNIs { clusterSNI = sni break } diff --git a/agent/envoyextensions/builtin/wasm/wasm_test.go b/agent/envoyextensions/builtin/wasm/wasm_test.go index 1d431ce051..93f3a4b5e0 100644 --- a/agent/envoyextensions/builtin/wasm/wasm_test.go +++ b/agent/envoyextensions/builtin/wasm/wasm_test.go @@ -609,7 +609,7 @@ func makeTestRuntimeConfig(protocol string, enterprise bool) *extensioncommon.Ru Namespace: acl.NamespaceOrDefault(ns), Partition: acl.PartitionOrDefault(ap), }: { - SNI: map[string]struct{}{"test-file-server": {}}, + SNIs: map[string]struct{}{"test-file-server": {}}, EnvoyID: "test-file-server", }, }, diff --git a/agent/xds/clusters.go b/agent/xds/clusters.go index 569b6c7af4..a6f58a11f2 100644 --- a/agent/xds/clusters.go +++ b/agent/xds/clusters.go @@ -34,7 +34,6 @@ import ( const ( meshGatewayExportedClusterNamePrefix = "exported~" - failoverClusterNamePrefix = "failover-target~" ) // clustersFromSnapshot returns the xDS API representation of the "clusters" in the snapshot. @@ -1915,7 +1914,7 @@ func (s *ResourceGenerator) getTargetClusterName(upstreamsSnapshot *proxycfg.Con } clusterName = CustomizeClusterName(clusterName, chain) if failover { - clusterName = failoverClusterNamePrefix + clusterName + clusterName = xdscommon.FailoverClusterNamePrefix + clusterName } if forMeshGateway { clusterName = meshGatewayExportedClusterNamePrefix + clusterName diff --git a/agent/xds/delta_envoy_extender_oss_test.go b/agent/xds/delta_envoy_extender_oss_test.go index e4525d91f7..ad7a67f7ee 100644 --- a/agent/xds/delta_envoy_extender_oss_test.go +++ b/agent/xds/delta_envoy_extender_oss_test.go @@ -26,6 +26,7 @@ import ( "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/xds/extensionruntime" "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/envoyextensions/extensioncommon" "github.com/hashicorp/consul/envoyextensions/xdscommon" "github.com/hashicorp/consul/sdk/testutil" ) @@ -110,7 +111,7 @@ end`, { "ResourceFilter": map[string]interface{}{ "ResourceType": propertyoverride.ResourceTypeCluster, - "TrafficDirection": propertyoverride.TrafficDirectionOutbound, + "TrafficDirection": extensioncommon.TrafficDirectionOutbound, }, "Op": "add", "Path": "/outlier_detection/success_rate_minimum_hosts", @@ -125,7 +126,7 @@ end`, { "ResourceFilter": map[string]interface{}{ "ResourceType": propertyoverride.ResourceTypeCluster, - "TrafficDirection": propertyoverride.TrafficDirectionOutbound, + "TrafficDirection": extensioncommon.TrafficDirectionOutbound, }, "Op": "add", "Path": "/outlier_detection", @@ -143,7 +144,7 @@ end`, { "ResourceFilter": map[string]interface{}{ "ResourceType": propertyoverride.ResourceTypeCluster, - "TrafficDirection": propertyoverride.TrafficDirectionOutbound, + "TrafficDirection": extensioncommon.TrafficDirectionOutbound, }, "Op": "remove", "Path": "/outlier_detection", @@ -157,7 +158,7 @@ end`, { "ResourceFilter": map[string]interface{}{ "ResourceType": propertyoverride.ResourceTypeCluster, - "TrafficDirection": propertyoverride.TrafficDirectionOutbound, + "TrafficDirection": extensioncommon.TrafficDirectionOutbound, }, "Op": "add", "Path": "/upstream_connection_options/tcp_keepalive/keepalive_probes", @@ -172,7 +173,7 @@ end`, { "ResourceFilter": map[string]interface{}{ "ResourceType": propertyoverride.ResourceTypeCluster, - "TrafficDirection": propertyoverride.TrafficDirectionOutbound, + "TrafficDirection": extensioncommon.TrafficDirectionOutbound, }, "Op": "add", "Path": "/round_robin_lb_config", @@ -181,6 +182,169 @@ end`, }, }) + propertyOverrideServiceDefaultsClusterLoadAssignmentOutboundAdd := makePropOverrideNsFunc( + map[string]interface{}{ + "Patches": []map[string]interface{}{ + { + "ResourceFilter": map[string]interface{}{ + "ResourceType": propertyoverride.ResourceTypeClusterLoadAssignment, + "TrafficDirection": extensioncommon.TrafficDirectionOutbound, + }, + "Op": "add", + "Path": "/policy/overprovisioning_factor", + "Value": 123, + }, + }, + }) + + propertyOverrideServiceDefaultsClusterLoadAssignmentInboundAdd := makePropOverrideNsFunc( + map[string]interface{}{ + "Patches": []map[string]interface{}{ + { + "ResourceFilter": map[string]interface{}{ + "ResourceType": propertyoverride.ResourceTypeClusterLoadAssignment, + "TrafficDirection": extensioncommon.TrafficDirectionInbound, + }, + "Op": "add", + "Path": "/policy/overprovisioning_factor", + "Value": 123, + }, + }, + }) + + propertyOverrideServiceDefaultsListenerInboundAdd := makePropOverrideNsFunc( + map[string]interface{}{ + "Patches": []map[string]interface{}{ + { + "ResourceFilter": map[string]interface{}{ + "ResourceType": propertyoverride.ResourceTypeListener, + "TrafficDirection": extensioncommon.TrafficDirectionInbound, + }, + "Op": "add", + "Path": "/stat_prefix", + "Value": "custom.stats", + }, + }, + }) + + propertyOverrideServiceDefaultsListenerOutboundAdd := makePropOverrideNsFunc( + map[string]interface{}{ + "Patches": []map[string]interface{}{ + { + "ResourceFilter": map[string]interface{}{ + "ResourceType": propertyoverride.ResourceTypeListener, + "TrafficDirection": extensioncommon.TrafficDirectionOutbound, + }, + "Op": "add", + "Path": "/stat_prefix", + "Value": "custom.stats", + }, + }, + }) + + propertyOverrideServiceDefaultsListenerOutboundDoesntApplyToInbound := makePropOverrideNsFunc( + map[string]interface{}{ + "Patches": []map[string]interface{}{ + { + "ResourceFilter": map[string]interface{}{ + "ResourceType": propertyoverride.ResourceTypeListener, + "TrafficDirection": extensioncommon.TrafficDirectionInbound, + }, + "Op": "add", + "Path": "/stat_prefix", + "Value": "custom.stats.inbound.only", + }, + { + "ResourceFilter": map[string]interface{}{ + "ResourceType": propertyoverride.ResourceTypeListener, + "TrafficDirection": extensioncommon.TrafficDirectionOutbound, + }, + "Op": "add", + "Path": "/stat_prefix", + "Value": "custom.stats.outbound.only", + }, + }, + }) + + // Reverse order of above patches, to prove order is inconsequential + propertyOverrideServiceDefaultsListenerInboundDoesntApplyToOutbound := makePropOverrideNsFunc( + map[string]interface{}{ + "Patches": []map[string]interface{}{ + { + "ResourceFilter": map[string]interface{}{ + "ResourceType": propertyoverride.ResourceTypeListener, + "TrafficDirection": extensioncommon.TrafficDirectionOutbound, + }, + "Op": "add", + "Path": "/stat_prefix", + "Value": "custom.stats.outbound.only", + }, + { + "ResourceFilter": map[string]interface{}{ + "ResourceType": propertyoverride.ResourceTypeListener, + "TrafficDirection": extensioncommon.TrafficDirectionInbound, + }, + "Op": "add", + "Path": "/stat_prefix", + "Value": "custom.stats.inbound.only", + }, + }, + }) + + propertyOverridePatchSpecificUpstreamService := makePropOverrideNsFunc( + map[string]interface{}{ + "Patches": []map[string]interface{}{ + { + "ResourceFilter": map[string]interface{}{ + "ResourceType": propertyoverride.ResourceTypeListener, + "TrafficDirection": extensioncommon.TrafficDirectionOutbound, + "Services": []propertyoverride.ServiceName{ + {CompoundServiceName: api.CompoundServiceName{Name: "db"}}, + }, + }, + "Op": "add", + "Path": "/stat_prefix", + "Value": "custom.stats.outbound.only", + }, + { + "ResourceFilter": map[string]interface{}{ + "ResourceType": propertyoverride.ResourceTypeRoute, + "TrafficDirection": extensioncommon.TrafficDirectionOutbound, + "Services": []propertyoverride.ServiceName{ + {CompoundServiceName: api.CompoundServiceName{Name: "db"}}, + }, + }, + "Op": "add", + "Path": "/most_specific_header_mutations_wins", + "Value": true, + }, + { + "ResourceFilter": map[string]interface{}{ + "ResourceType": propertyoverride.ResourceTypeCluster, + "TrafficDirection": extensioncommon.TrafficDirectionOutbound, + "Services": []propertyoverride.ServiceName{ + {CompoundServiceName: api.CompoundServiceName{Name: "db"}}, + }, + }, + "Op": "add", + "Path": "/outlier_detection/success_rate_minimum_hosts", + "Value": 1234, + }, + { + "ResourceFilter": map[string]interface{}{ + "ResourceType": propertyoverride.ResourceTypeClusterLoadAssignment, + "TrafficDirection": extensioncommon.TrafficDirectionOutbound, + "Services": []propertyoverride.ServiceName{ + {CompoundServiceName: api.CompoundServiceName{Name: "db"}}, + }, + }, + "Op": "add", + "Path": "/policy/overprovisioning_factor", + "Value": 1234, + }, + }, + }) + tests := []struct { name string create func(t testinf.T) *proxycfg.ConfigSnapshot @@ -215,6 +379,54 @@ end`, return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", false, propertyOverrideServiceDefaultsRemoveOutlierDetection, nil) }, }, + { + name: "propertyoverride-cluster-load-assignment-outbound-add", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", false, propertyOverrideServiceDefaultsClusterLoadAssignmentOutboundAdd, nil) + }, + }, + { + name: "propertyoverride-cluster-load-assignment-inbound-add", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", false, propertyOverrideServiceDefaultsClusterLoadAssignmentInboundAdd, nil) + }, + }, + { + name: "propertyoverride-listener-outbound-add", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", false, propertyOverrideServiceDefaultsListenerOutboundAdd, nil) + }, + }, + { + name: "propertyoverride-listener-inbound-add", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", false, propertyOverrideServiceDefaultsListenerInboundAdd, nil) + }, + }, + { + name: "propertyoverride-outbound-doesnt-apply-to-inbound", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", false, propertyOverrideServiceDefaultsListenerOutboundDoesntApplyToInbound, nil) + }, + }, + { + name: "propertyoverride-inbound-doesnt-apply-to-outbound", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", false, propertyOverrideServiceDefaultsListenerInboundDoesntApplyToOutbound, nil) + }, + }, + { + name: "propertyoverride-patch-specific-upstream-service-splitter", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "splitter-with-resolver-redirect-multidc", false, propertyOverridePatchSpecificUpstreamService, nil) + }, + }, + { + name: "propertyoverride-patch-specific-upstream-service-failover", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "failover", false, propertyOverridePatchSpecificUpstreamService, nil) + }, + }, { name: "lambda-connect-proxy", create: func(t testinf.T) *proxycfg.ConfigSnapshot { diff --git a/agent/xds/extensionruntime/runtime_config.go b/agent/xds/extensionruntime/runtime_config.go index 2c7522131e..110e3db1df 100644 --- a/agent/xds/extensionruntime/runtime_config.go +++ b/agent/xds/extensionruntime/runtime_config.go @@ -56,19 +56,27 @@ func GetRuntimeConfigurations(cfgSnap *proxycfg.ConfigSnapshot) map[api.Compound // TODO(peering): consider PeerUpstreamEndpoints in addition to DiscoveryChain // These are the discovery chains for upstreams which have the Envoy Extensions applied to the local service. - for uid, dc := range cfgSnap.ConnectProxy.DiscoveryChain { + for uid, chain := range cfgSnap.ConnectProxy.DiscoveryChain { compoundServiceName := upstreamIDToCompoundServiceName(uid) - extensionsMap[compoundServiceName] = convertEnvoyExtensions(dc.EnvoyExtensions) + extensionsMap[compoundServiceName] = convertEnvoyExtensions(chain.EnvoyExtensions) + + primarySNI := connect.ServiceSNI(uid.Name, "", chain.Namespace, chain.Partition, cfgSnap.Datacenter, trustDomain) + snis := make(map[string]struct{}) + for _, t := range chain.Targets { + // SNI isn't set for peered services. We don't support peered services yet. + if t.SNI != "" { + snis[t.SNI] = struct{}{} + } + } - meta := uid.EnterpriseMeta - sni := connect.ServiceSNI(uid.Name, "", meta.NamespaceOrDefault(), meta.PartitionOrDefault(), cfgSnap.Datacenter, trustDomain) outgoingKind, ok := outgoingKindByService[compoundServiceName] if !ok { outgoingKind = api.ServiceKindConnectProxy } upstreamMap[compoundServiceName] = &extensioncommon.UpstreamData{ - SNI: map[string]struct{}{sni: {}}, + PrimarySNI: primarySNI, + SNIs: snis, VIP: vipForService[compoundServiceName], EnvoyID: uid.EnvoyID(), OutgoingProxyKind: outgoingKind, @@ -101,10 +109,10 @@ func GetRuntimeConfigurations(cfgSnap *proxycfg.ConfigSnapshot) map[api.Compound compoundServiceName := serviceNameToCompoundServiceName(svc) extensionsMap[compoundServiceName] = convertEnvoyExtensions(c.EnvoyExtensions) - sni := connect.ServiceSNI(svc.Name, "", svc.NamespaceOrDefault(), svc.PartitionOrDefault(), cfgSnap.Datacenter, trustDomain) + primarySNI := connect.ServiceSNI(svc.Name, "", svc.NamespaceOrDefault(), svc.PartitionOrDefault(), cfgSnap.Datacenter, trustDomain) envoyID := proxycfg.NewUpstreamIDFromServiceName(svc) - snis := map[string]struct{}{sni: {}} + snis := map[string]struct{}{primarySNI: {}} resolver, hasResolver := cfgSnap.TerminatingGateway.ServiceResolvers[svc] if hasResolver { @@ -115,7 +123,8 @@ func GetRuntimeConfigurations(cfgSnap *proxycfg.ConfigSnapshot) map[api.Compound } upstreamMap[compoundServiceName] = &extensioncommon.UpstreamData{ - SNI: snis, + PrimarySNI: primarySNI, + SNIs: snis, EnvoyID: envoyID.EnvoyID(), OutgoingProxyKind: api.ServiceKindTerminatingGateway, } diff --git a/agent/xds/extensionruntime/runtime_config_oss_test.go b/agent/xds/extensionruntime/runtime_config_oss_test.go index 257fd5d737..c70a3f47f4 100644 --- a/agent/xds/extensionruntime/runtime_config_oss_test.go +++ b/agent/xds/extensionruntime/runtime_config_oss_test.go @@ -58,28 +58,32 @@ func TestGetRuntimeConfigurations_TerminatingGateway(t *testing.T) { IsSourcedFromUpstream: true, Upstreams: map[api.CompoundServiceName]*extensioncommon.UpstreamData{ apiService: { - SNI: map[string]struct{}{ + PrimarySNI: "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + SNIs: map[string]struct{}{ "api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul": {}, }, EnvoyID: "api", OutgoingProxyKind: "terminating-gateway", }, cacheService: { - SNI: map[string]struct{}{ + PrimarySNI: "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + SNIs: map[string]struct{}{ "cache.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul": {}, }, EnvoyID: "cache", OutgoingProxyKind: "terminating-gateway", }, dbService: { - SNI: map[string]struct{}{ + PrimarySNI: "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + SNIs: map[string]struct{}{ "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul": {}, }, EnvoyID: "db", OutgoingProxyKind: "terminating-gateway", }, webService: { - SNI: map[string]struct{}{ + PrimarySNI: "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + SNIs: map[string]struct{}{ "canary1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul": {}, "canary2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul": {}, "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul": {}, @@ -134,10 +138,25 @@ func TestGetRuntimeConfigurations_ConnectProxy(t *testing.T) { EnvoyExtensions: envoyExtensions, } + serviceDefaultsV2 := &structs.ServiceConfigEntry{ + Kind: structs.ServiceDefaults, + Name: "db-v2", + Protocol: "http", + } + + serviceSplitter := &structs.ServiceSplitterConfigEntry{ + Kind: structs.ServiceSplitter, + Name: "db", + Splits: []structs.ServiceSplit{ + {Weight: 50}, + {Weight: 50, Service: "db-v2"}, + }, + } + // Setup a snapshot where the db upstream is on a connect proxy. - snapConnect := proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", false, nil, nil, serviceDefaults) + snapConnect := proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", false, nil, nil, serviceDefaults, serviceDefaultsV2, serviceSplitter) // Setup a snapshot where the db upstream is on a terminating gateway. - snapTermGw := proxycfg.TestConfigSnapshotDiscoveryChain(t, "register-to-terminating-gateway", false, nil, nil, serviceDefaults) + snapTermGw := proxycfg.TestConfigSnapshotDiscoveryChain(t, "register-to-terminating-gateway", false, nil, nil, serviceDefaults, serviceDefaultsV2, serviceSplitter) // Setup a snapshot with the local service web has extensions. snapWebConnect := proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", false, func(ns *structs.NodeService) { ns.Proxy.EnvoyExtensions = envoyExtensions @@ -164,8 +183,10 @@ func TestGetRuntimeConfigurations_ConnectProxy(t *testing.T) { IsSourcedFromUpstream: true, Upstreams: map[api.CompoundServiceName]*extensioncommon.UpstreamData{ dbService: { - SNI: map[string]struct{}{ - "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul": {}, + PrimarySNI: "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + SNIs: map[string]struct{}{ + "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul": {}, + "db-v2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul": {}, }, EnvoyID: "db", OutgoingProxyKind: "connect-proxy", @@ -193,8 +214,10 @@ func TestGetRuntimeConfigurations_ConnectProxy(t *testing.T) { IsSourcedFromUpstream: true, Upstreams: map[api.CompoundServiceName]*extensioncommon.UpstreamData{ dbService: { - SNI: map[string]struct{}{ - "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul": {}, + PrimarySNI: "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + SNIs: map[string]struct{}{ + "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul": {}, + "db-v2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul": {}, }, EnvoyID: "db", OutgoingProxyKind: "terminating-gateway", @@ -224,7 +247,8 @@ func TestGetRuntimeConfigurations_ConnectProxy(t *testing.T) { IsSourcedFromUpstream: false, Upstreams: map[api.CompoundServiceName]*extensioncommon.UpstreamData{ dbService: { - SNI: map[string]struct{}{ + PrimarySNI: "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + SNIs: map[string]struct{}{ "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul": {}, }, EnvoyID: "db", @@ -245,7 +269,8 @@ func TestGetRuntimeConfigurations_ConnectProxy(t *testing.T) { IsSourcedFromUpstream: false, Upstreams: map[api.CompoundServiceName]*extensioncommon.UpstreamData{ dbService: { - SNI: map[string]struct{}{ + PrimarySNI: "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + SNIs: map[string]struct{}{ "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul": {}, }, EnvoyID: "db", diff --git a/agent/xds/failover_policy.go b/agent/xds/failover_policy.go index ab2bb9a2b7..5edcae914d 100644 --- a/agent/xds/failover_policy.go +++ b/agent/xds/failover_policy.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/consul/agent/connect" "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/envoyextensions/xdscommon" ) type discoChainTargets struct { @@ -149,7 +150,7 @@ func (ft discoChainTargets) sequential() ([]discoChainTargetGroup, error) { var targetGroups []discoChainTargetGroup for i, t := range ft.targets { targetGroups = append(targetGroups, discoChainTargetGroup{ - ClusterName: fmt.Sprintf("%s%d~%s", failoverClusterNamePrefix, i, ft.baseClusterName), + ClusterName: fmt.Sprintf("%s%d~%s", xdscommon.FailoverClusterNamePrefix, i, ft.baseClusterName), Targets: []targetInfo{t}, }) } diff --git a/agent/xds/testdata/builtin_extension/clusters/propertyoverride-patch-specific-upstream-service-failover.latest.golden b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-patch-specific-upstream-service-failover.latest.golden new file mode 100644 index 0000000000..9e1f64a8c0 --- /dev/null +++ b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-patch-specific-upstream-service-failover.latest.golden @@ -0,0 +1,199 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "clusterType": { + "name": "envoy.clusters.aggregate", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.clusters.aggregate.v3.ClusterConfig", + "clusters": [ + "failover-target~0~db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "failover-target~1~db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + } + }, + "connectTimeout": "33s", + "lbPolicy": "CLUSTER_PROVIDED", + "outlierDetection": { + "successRateMinimumHosts": 1234 + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "failover-target~0~db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "altStatName": "failover-target~0~db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "type": "EDS", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "connectTimeout": "33s", + "circuitBreakers": {}, + "outlierDetection": { + "successRateMinimumHosts": 1234 + }, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + }, + "matchSubjectAltNames": [ + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + } + ] + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "failover-target~1~db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "altStatName": "failover-target~1~db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "type": "EDS", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "connectTimeout": "33s", + "circuitBreakers": {}, + "outlierDetection": { + "successRateMinimumHosts": 1234 + }, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + }, + "matchSubjectAltNames": [ + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/fail" + } + ] + } + }, + "sni": "fail.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "type": "EDS", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "connectTimeout": "5s", + "circuitBreakers": {}, + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + }, + "matchSubjectAltNames": [ + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + } + ] + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "local_app", + "type": "STATIC", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + } + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/clusters/propertyoverride-patch-specific-upstream-service-splitter.latest.golden b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-patch-specific-upstream-service-splitter.latest.golden new file mode 100644 index 0000000000..2c2413ee3b --- /dev/null +++ b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-patch-specific-upstream-service-splitter.latest.golden @@ -0,0 +1,179 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "type": "EDS", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "connectTimeout": "5s", + "circuitBreakers": {}, + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + }, + "matchSubjectAltNames": [ + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + } + ] + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "local_app", + "type": "STATIC", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "v1.db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "altStatName": "v1.db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "type": "EDS", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "connectTimeout": "5s", + "circuitBreakers": {}, + "outlierDetection": { + "successRateMinimumHosts": 1234 + }, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + }, + "matchSubjectAltNames": [ + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + } + ] + } + }, + "sni": "v1.db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "v2.db.default.dc2.internal.11111111-2222-3333-4444-555555555555.consul", + "altStatName": "v2.db.default.dc2.internal.11111111-2222-3333-4444-555555555555.consul", + "type": "EDS", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "connectTimeout": "5s", + "circuitBreakers": {}, + "outlierDetection": { + "successRateMinimumHosts": 1234 + }, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + }, + "matchSubjectAltNames": [ + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/db" + } + ] + } + }, + "sni": "v2.db.default.dc2.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/clusters/propertyoverride-patch-specific-upstream-service.latest.golden b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-patch-specific-upstream-service.latest.golden new file mode 100644 index 0000000000..2f37bfe304 --- /dev/null +++ b/agent/xds/testdata/builtin_extension/clusters/propertyoverride-patch-specific-upstream-service.latest.golden @@ -0,0 +1,192 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "clusterType": { + "name": "envoy.clusters.aggregate", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.clusters.aggregate.v3.ClusterConfig", + "clusters": [ + "failover-target~0~db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "failover-target~1~db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + ] + } + }, + "connectTimeout": "33s", + "lbPolicy": "CLUSTER_PROVIDED" + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "failover-target~0~db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "altStatName": "failover-target~0~db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "type": "EDS", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "connectTimeout": "33s", + "circuitBreakers": {}, + "outlierDetection": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + }, + "matchSubjectAltNames": [ + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + } + ] + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "failover-target~1~db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "altStatName": "failover-target~1~db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "type": "EDS", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "connectTimeout": "33s", + "circuitBreakers": {}, + "outlierDetection": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + }, + "matchSubjectAltNames": [ + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/fail" + } + ] + } + }, + "sni": "fail.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "type": "EDS", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "connectTimeout": "5s", + "circuitBreakers": {}, + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + }, + "matchSubjectAltNames": [ + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + } + ] + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "local_app", + "type": "STATIC", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + } + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/endpoints/propertyoverride-patch-specific-upstream-service-failover.latest.golden b/agent/xds/testdata/builtin_extension/endpoints/propertyoverride-patch-specific-upstream-service-failover.latest.golden new file mode 100644 index 0000000000..ba96001dde --- /dev/null +++ b/agent/xds/testdata/builtin_extension/endpoints/propertyoverride-patch-specific-upstream-service-failover.latest.golden @@ -0,0 +1,115 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "failover-target~0~db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ], + "policy": { + "overprovisioningFactor": 1234 + } + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "failover-target~1~db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ], + "policy": { + "overprovisioningFactor": 1234 + } + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/endpoints/propertyoverride-patch-specific-upstream-service-splitter.latest.golden b/agent/xds/testdata/builtin_extension/endpoints/propertyoverride-patch-specific-upstream-service-splitter.latest.golden new file mode 100644 index 0000000000..98e3abe7e9 --- /dev/null +++ b/agent/xds/testdata/builtin_extension/endpoints/propertyoverride-patch-specific-upstream-service-splitter.latest.golden @@ -0,0 +1,115 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "v1.db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ], + "policy": { + "overprovisioningFactor": 1234 + } + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "v2.db.default.dc2.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ], + "policy": { + "overprovisioningFactor": 1234 + } + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/endpoints/propertyoverride-patch-specific-upstream-service.latest.golden b/agent/xds/testdata/builtin_extension/endpoints/propertyoverride-patch-specific-upstream-service.latest.golden new file mode 100644 index 0000000000..49a84f09b2 --- /dev/null +++ b/agent/xds/testdata/builtin_extension/endpoints/propertyoverride-patch-specific-upstream-service.latest.golden @@ -0,0 +1,109 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "failover-target~0~db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "failover-target~1~db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service-failover.latest.golden b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service-failover.latest.golden new file mode 100644 index 0000000000..e8fc107d19 --- /dev/null +++ b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service-failover.latest.golden @@ -0,0 +1,235 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "db:127.0.0.1:9191", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "statPrefix": "custom.stats.outbound.only", + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "statPrefix": "upstream.db.default.default.dc1", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ], + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "statPrefix": "upstream.prepared_query_geo-cache", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ], + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "public_listener:0.0.0.0:9999", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "statPrefix": "public_listener", + "routeConfig": { + "name": "public_listener", + "virtualHosts": [ + { + "name": "public_listener", + "domains": [ + "*" + ], + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "local_app" + } + } + ] + } + ] + }, + "httpFilters": [ + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": {} + } + }, + { + "name": "envoy.filters.http.header_to_metadata", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.header_to_metadata.v3.Config", + "requestRules": [ + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "metadataNamespace": "consul", + "key": "trust-domain", + "regexValueRewrite": { + "pattern": { + "googleRe2": {}, + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\1" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "metadataNamespace": "consul", + "key": "partition", + "regexValueRewrite": { + "pattern": { + "googleRe2": {}, + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\2" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "metadataNamespace": "consul", + "key": "namespace", + "regexValueRewrite": { + "pattern": { + "googleRe2": {}, + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\3" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "metadataNamespace": "consul", + "key": "datacenter", + "regexValueRewrite": { + "pattern": { + "googleRe2": {}, + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\4" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "metadataNamespace": "consul", + "key": "service", + "regexValueRewrite": { + "pattern": { + "googleRe2": {}, + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\5" + } + } + } + ] + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "tracing": { + "randomSampling": {} + }, + "forwardClientCertDetails": "APPEND_FORWARD", + "setCurrentClientCertDetails": { + "subject": true, + "cert": true, + "chain": true, + "dns": true, + "uri": true + } + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + }, + "alpnProtocols": [ + "http/1.1" + ] + }, + "requireClientCertificate": true + } + } + } + ], + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service-splitter.latest.golden b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service-splitter.latest.golden new file mode 100644 index 0000000000..b17de217f3 --- /dev/null +++ b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service-splitter.latest.golden @@ -0,0 +1,252 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "db:127.0.0.1:9191", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "statPrefix": "custom.stats.outbound.only", + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "statPrefix": "upstream.db.default.default.dc1", + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "db" + }, + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "tracing": { + "randomSampling": {} + } + } + } + ] + } + ], + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "statPrefix": "upstream.prepared_query_geo-cache", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ], + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "public_listener:0.0.0.0:9999", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "statPrefix": "public_listener", + "routeConfig": { + "name": "public_listener", + "virtualHosts": [ + { + "name": "public_listener", + "domains": [ + "*" + ], + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "local_app" + } + } + ] + } + ] + }, + "httpFilters": [ + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": {} + } + }, + { + "name": "envoy.filters.http.header_to_metadata", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.header_to_metadata.v3.Config", + "requestRules": [ + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "metadataNamespace": "consul", + "key": "trust-domain", + "regexValueRewrite": { + "pattern": { + "googleRe2": {}, + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\1" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "metadataNamespace": "consul", + "key": "partition", + "regexValueRewrite": { + "pattern": { + "googleRe2": {}, + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\2" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "metadataNamespace": "consul", + "key": "namespace", + "regexValueRewrite": { + "pattern": { + "googleRe2": {}, + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\3" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "metadataNamespace": "consul", + "key": "datacenter", + "regexValueRewrite": { + "pattern": { + "googleRe2": {}, + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\4" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "metadataNamespace": "consul", + "key": "service", + "regexValueRewrite": { + "pattern": { + "googleRe2": {}, + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\5" + } + } + } + ] + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "tracing": { + "randomSampling": {} + }, + "forwardClientCertDetails": "APPEND_FORWARD", + "setCurrentClientCertDetails": { + "subject": true, + "cert": true, + "chain": true, + "dns": true, + "uri": true + } + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + }, + "alpnProtocols": [ + "http/1.1" + ] + }, + "requireClientCertificate": true + } + } + } + ], + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service.latest.golden b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service.latest.golden new file mode 100644 index 0000000000..7a4514f1d7 --- /dev/null +++ b/agent/xds/testdata/builtin_extension/listeners/propertyoverride-patch-specific-upstream-service.latest.golden @@ -0,0 +1,234 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "db:127.0.0.1:9191", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "statPrefix": "upstream.db.default.default.dc1", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ], + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "statPrefix": "upstream.prepared_query_geo-cache", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ], + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "public_listener:0.0.0.0:9999", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "statPrefix": "public_listener", + "routeConfig": { + "name": "public_listener", + "virtualHosts": [ + { + "name": "public_listener", + "domains": [ + "*" + ], + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "local_app" + } + } + ] + } + ] + }, + "httpFilters": [ + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": {} + } + }, + { + "name": "envoy.filters.http.header_to_metadata", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.header_to_metadata.v3.Config", + "requestRules": [ + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "metadataNamespace": "consul", + "key": "trust-domain", + "regexValueRewrite": { + "pattern": { + "googleRe2": {}, + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\1" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "metadataNamespace": "consul", + "key": "partition", + "regexValueRewrite": { + "pattern": { + "googleRe2": {}, + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\2" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "metadataNamespace": "consul", + "key": "namespace", + "regexValueRewrite": { + "pattern": { + "googleRe2": {}, + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\3" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "metadataNamespace": "consul", + "key": "datacenter", + "regexValueRewrite": { + "pattern": { + "googleRe2": {}, + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\4" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "metadataNamespace": "consul", + "key": "service", + "regexValueRewrite": { + "pattern": { + "googleRe2": {}, + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\5" + } + } + } + ] + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "tracing": { + "randomSampling": {} + }, + "forwardClientCertDetails": "APPEND_FORWARD", + "setCurrentClientCertDetails": { + "subject": true, + "cert": true, + "chain": true, + "dns": true, + "uri": true + } + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + }, + "alpnProtocols": [ + "http/1.1" + ] + }, + "requireClientCertificate": true + } + } + } + ], + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/routes/propertyoverride-patch-specific-upstream-service-failover.latest.golden b/agent/xds/testdata/builtin_extension/routes/propertyoverride-patch-specific-upstream-service-failover.latest.golden new file mode 100644 index 0000000000..3c51e370a4 --- /dev/null +++ b/agent/xds/testdata/builtin_extension/routes/propertyoverride-patch-specific-upstream-service-failover.latest.golden @@ -0,0 +1,32 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "db", + "virtualHosts": [ + { + "name": "db", + "domains": [ + "*" + ], + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "timeout": "33s" + } + } + ] + } + ], + "mostSpecificHeaderMutationsWins": true, + "validateClusters": true + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/routes/propertyoverride-patch-specific-upstream-service-splitter.latest.golden b/agent/xds/testdata/builtin_extension/routes/propertyoverride-patch-specific-upstream-service-splitter.latest.golden new file mode 100644 index 0000000000..0f6260527b --- /dev/null +++ b/agent/xds/testdata/builtin_extension/routes/propertyoverride-patch-specific-upstream-service-splitter.latest.golden @@ -0,0 +1,43 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "db", + "virtualHosts": [ + { + "name": "db", + "domains": [ + "*" + ], + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "weightedClusters": { + "clusters": [ + { + "name": "v1.db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "weight": 5000 + }, + { + "name": "v2.db.default.dc2.internal.11111111-2222-3333-4444-555555555555.consul", + "weight": 5000 + } + ], + "totalWeight": 10000 + } + } + } + ] + } + ], + "mostSpecificHeaderMutationsWins": true, + "validateClusters": true + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/routes/propertyoverride-patch-specific-upstream-service.latest.golden b/agent/xds/testdata/builtin_extension/routes/propertyoverride-patch-specific-upstream-service.latest.golden new file mode 100644 index 0000000000..095330c684 --- /dev/null +++ b/agent/xds/testdata/builtin_extension/routes/propertyoverride-patch-specific-upstream-service.latest.golden @@ -0,0 +1,31 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "db", + "virtualHosts": [ + { + "name": "db", + "domains": [ + "*" + ], + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "timeout": "33s" + } + } + ] + } + ], + "validateClusters": true + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "nonce": "00000001" +} \ No newline at end of file diff --git a/envoyextensions/extensioncommon/basic_envoy_extender.go b/envoyextensions/extensioncommon/basic_envoy_extender.go index 5499d83045..53a44b0aa2 100644 --- a/envoyextensions/extensioncommon/basic_envoy_extender.go +++ b/envoyextensions/extensioncommon/basic_envoy_extender.go @@ -38,7 +38,7 @@ type BasicExtension interface { // PatchRoute patches a route to include the custom Envoy configuration // required to integrate with the built in extension template. // See also PatchRoutes. - PatchRoute(*RuntimeConfig, *envoy_route_v3.RouteConfiguration) (*envoy_route_v3.RouteConfiguration, bool, error) + PatchRoute(RoutePayload) (*envoy_route_v3.RouteConfiguration, bool, error) // PatchRoutes patches routes to include the custom Envoy configuration // required to integrate with the built in extension template. @@ -51,7 +51,7 @@ type BasicExtension interface { // PatchCluster patches a cluster to include the custom Envoy configuration // required to integrate with the built in extension template. // See also PatchClusters. - PatchCluster(*RuntimeConfig, *envoy_cluster_v3.Cluster) (*envoy_cluster_v3.Cluster, bool, error) + PatchCluster(ClusterPayload) (*envoy_cluster_v3.Cluster, bool, error) // PatchClusters patches clusters to include the custom Envoy configuration // required to integrate with the built in extension template. @@ -63,12 +63,12 @@ type BasicExtension interface { // PatchClusterLoadAssignment patches a cluster load assignment to include the custom Envoy configuration // required to integrate with the built in extension template. - PatchClusterLoadAssignment(*RuntimeConfig, *envoy_endpoint_v3.ClusterLoadAssignment) (*envoy_endpoint_v3.ClusterLoadAssignment, bool, error) + PatchClusterLoadAssignment(ClusterLoadAssignmentPayload) (*envoy_endpoint_v3.ClusterLoadAssignment, bool, error) // PatchListener patches a listener to include the custom Envoy configuration // required to integrate with the built in extension template. // See also PatchListeners. - PatchListener(*RuntimeConfig, *envoy_listener_v3.Listener) (*envoy_listener_v3.Listener, bool, error) + PatchListener(ListenerPayload) (*envoy_listener_v3.Listener, bool, error) // PatchListeners patches listeners to include the custom Envoy configuration // required to integrate with the built in extension template. @@ -81,7 +81,7 @@ type BasicExtension interface { // PatchFilter patches an Envoy filter to include the custom Envoy // configuration required to integrate with the built in extension template. // See also PatchFilters. - PatchFilter(cfg *RuntimeConfig, f *envoy_listener_v3.Filter, isInboundListener bool) (*envoy_listener_v3.Filter, bool, error) + PatchFilter(FilterPayload) (*envoy_listener_v3.Filter, bool, error) // PatchFilters patches Envoy filters to include the custom Envoy // configuration required to integrate with the built in extension template. @@ -197,7 +197,7 @@ func (b *BasicEnvoyExtender) patchClusters(config *RuntimeConfig, clusters Clust return clusters, fmt.Errorf("error patching clusters: %w", err) } for nameOrSNI, cluster := range clusters { - patchedCluster, patched, err := b.Extension.PatchCluster(config, cluster) + patchedCluster, patched, err := b.Extension.PatchCluster(config.GetClusterPayload(cluster)) if err != nil { resultErr = multierror.Append(resultErr, fmt.Errorf("error patching cluster %q: %w", nameOrSNI, err)) } @@ -208,7 +208,7 @@ func (b *BasicEnvoyExtender) patchClusters(config *RuntimeConfig, clusters Clust // We patch cluster load assignments directly above for EDS, but also here for CDS, // since updates can come from either. if patchedCluster.LoadAssignment != nil { - patchedClusterLoadAssignment, patched, err := b.Extension.PatchClusterLoadAssignment(config, patchedCluster.LoadAssignment) + patchedClusterLoadAssignment, patched, err := b.Extension.PatchClusterLoadAssignment(config.GetClusterLoadAssignmentPayload(patchedCluster.LoadAssignment)) if err != nil { resultErr = multierror.Append(resultErr, fmt.Errorf("error patching load assignment for cluster %q: %w", nameOrSNI, err)) } else if patched { @@ -225,7 +225,7 @@ func (b *BasicEnvoyExtender) patchClusterLoadAssignments(config *RuntimeConfig, var resultErr error for nameOrSNI, clusterLoadAssignment := range clusterLoadAssignments { - patchedClusterLoadAssignment, patched, err := b.Extension.PatchClusterLoadAssignment(config, clusterLoadAssignment) + patchedClusterLoadAssignment, patched, err := b.Extension.PatchClusterLoadAssignment(config.GetClusterLoadAssignmentPayload(clusterLoadAssignment)) if err != nil { resultErr = multierror.Append(resultErr, fmt.Errorf("error patching cluster load assignment %q: %w", nameOrSNI, err)) } @@ -246,7 +246,7 @@ func (b *BasicEnvoyExtender) patchRoutes(config *RuntimeConfig, routes RouteMap) return routes, fmt.Errorf("error patching routes: %w", err) } for nameOrSNI, route := range patchedRoutes { - patchedRoute, patched, err := b.Extension.PatchRoute(config, route) + patchedRoute, patched, err := b.Extension.PatchRoute(config.GetRoutePayload(route)) if err != nil { resultErr = multierror.Append(resultErr, fmt.Errorf("error patching route %q: %w", nameOrSNI, err)) } @@ -267,7 +267,7 @@ func (b *BasicEnvoyExtender) patchListeners(config *RuntimeConfig, listeners Lis return listeners, fmt.Errorf("error patching listeners: %w", err) } for nameOrSNI, listener := range listeners { - patchedListener, patched, err := b.Extension.PatchListener(config, listener) + patchedListener, patched, err := b.Extension.PatchListener(config.GetListenerPayload(listener)) if err != nil { resultErr = multierror.Append(resultErr, fmt.Errorf("error patching listener %q: %w", nameOrSNI, err)) } @@ -298,7 +298,7 @@ func (b *BasicEnvoyExtender) patchListenerFilterChains(config *RuntimeConfig, l func (b *BasicEnvoyExtender) patchTerminatingGatewayListenerFilterChains(config *RuntimeConfig, l *envoy_listener_v3.Listener, nameOrSNI string) (*envoy_listener_v3.Listener, error) { var resultErr error for idx, filterChain := range l.FilterChains { - if patchedFilterChain, err := b.patchFilterChain(config, filterChain, IsInboundPublicListener(l)); err == nil { + if patchedFilterChain, err := b.patchFilterChain(config, filterChain, l); err == nil { l.FilterChains[idx] = patchedFilterChain } else { resultErr = multierror.Append(resultErr, fmt.Errorf("error patching filter chain of terminating gateway listener %q: %w", nameOrSNI, err)) @@ -330,10 +330,8 @@ func (b *BasicEnvoyExtender) patchConnectProxyListenerFilterChains(config *Runti func (b *BasicEnvoyExtender) patchNonTProxyConnectProxyListenerFilterChains(config *RuntimeConfig, l *envoy_listener_v3.Listener) (*envoy_listener_v3.Listener, error) { var resultErr error - inbound := IsInboundPublicListener(l) - for idx, filterChain := range l.FilterChains { - if patchedFilterChain, err := b.patchFilterChain(config, filterChain, inbound); err == nil { + if patchedFilterChain, err := b.patchFilterChain(config, filterChain, l); err == nil { l.FilterChains[idx] = patchedFilterChain } else { resultErr = multierror.Append(resultErr, fmt.Errorf("error patching filter chain: %w", err)) @@ -346,7 +344,6 @@ func (b *BasicEnvoyExtender) patchTProxyListenerFilterChains(config *RuntimeConf var resultErr error vip := config.Upstreams[config.ServiceName].VIP - inbound := IsInboundPublicListener(l) for idx, filterChain := range l.FilterChains { match := filterChainTProxyMatch(vip, filterChain) @@ -354,7 +351,7 @@ func (b *BasicEnvoyExtender) patchTProxyListenerFilterChains(config *RuntimeConf continue } - if patchedFilterChain, err := b.patchFilterChain(config, filterChain, inbound); err == nil { + if patchedFilterChain, err := b.patchFilterChain(config, filterChain, l); err == nil { l.FilterChains[idx] = patchedFilterChain } else { resultErr = multierror.Append(resultErr, fmt.Errorf("error patching filter chain for %q: %w", vip, err)) @@ -364,14 +361,15 @@ func (b *BasicEnvoyExtender) patchTProxyListenerFilterChains(config *RuntimeConf return l, resultErr } -func (b *BasicEnvoyExtender) patchFilterChain(config *RuntimeConfig, filterChain *envoy_listener_v3.FilterChain, isInboundListener bool) (*envoy_listener_v3.FilterChain, error) { +func (b *BasicEnvoyExtender) patchFilterChain(config *RuntimeConfig, filterChain *envoy_listener_v3.FilterChain, l *envoy_listener_v3.Listener) (*envoy_listener_v3.FilterChain, error) { var resultErr error - patchedFilters, err := b.Extension.PatchFilters(config, filterChain.Filters, isInboundListener) + inbound := IsInboundPublicListener(l) + patchedFilters, err := b.Extension.PatchFilters(config, filterChain.Filters, inbound) if err != nil { return filterChain, fmt.Errorf("error patching filters: %w", err) } for idx, filter := range patchedFilters { - patchedFilter, patched, err := b.Extension.PatchFilter(config, filter, isInboundListener) + patchedFilter, patched, err := b.Extension.PatchFilter(config.GetFilterPayload(filter, l)) if err != nil { resultErr = multierror.Append(resultErr, fmt.Errorf("error patching filter: %w", err)) } diff --git a/envoyextensions/extensioncommon/basic_extension_adapter.go b/envoyextensions/extensioncommon/basic_extension_adapter.go index 85cc5efed8..fbf73f34c2 100644 --- a/envoyextensions/extensioncommon/basic_extension_adapter.go +++ b/envoyextensions/extensioncommon/basic_extension_adapter.go @@ -20,8 +20,8 @@ type BasicExtensionAdapter struct{} func (BasicExtensionAdapter) CanApply(_ *RuntimeConfig) bool { return false } // PatchCluster provides a default implementation of the PatchCluster interface that does nothing. -func (BasicExtensionAdapter) PatchCluster(_ *RuntimeConfig, c *envoy_cluster_v3.Cluster) (*envoy_cluster_v3.Cluster, bool, error) { - return c, false, nil +func (BasicExtensionAdapter) PatchCluster(p ClusterPayload) (*envoy_cluster_v3.Cluster, bool, error) { + return p.Message, false, nil } // PatchClusters provides a default implementation of the PatchClusters interface that does nothing. @@ -30,13 +30,13 @@ func (BasicExtensionAdapter) PatchClusters(_ *RuntimeConfig, c ClusterMap) (Clus } // PatchClusterLoadAssignment provides a default implementation of the PatchClusterLoadAssignment interface that does nothing. -func (BasicExtensionAdapter) PatchClusterLoadAssignment(_ *RuntimeConfig, c *envoy_endpoint_v3.ClusterLoadAssignment) (*envoy_endpoint_v3.ClusterLoadAssignment, bool, error) { - return c, false, nil +func (BasicExtensionAdapter) PatchClusterLoadAssignment(p ClusterLoadAssignmentPayload) (*envoy_endpoint_v3.ClusterLoadAssignment, bool, error) { + return p.Message, false, nil } // PatchListener provides a default implementation of the PatchListener interface that does nothing. -func (BasicExtensionAdapter) PatchListener(_ *RuntimeConfig, l *envoy_listener_v3.Listener) (*envoy_listener_v3.Listener, bool, error) { - return l, false, nil +func (BasicExtensionAdapter) PatchListener(p ListenerPayload) (*envoy_listener_v3.Listener, bool, error) { + return p.Message, false, nil } // PatchListeners provides a default implementation of the PatchListeners interface that does nothing. @@ -45,8 +45,8 @@ func (BasicExtensionAdapter) PatchListeners(_ *RuntimeConfig, l ListenerMap) (Li } // PatchFilter provides a default implementation of the PatchFilter interface that does nothing. -func (BasicExtensionAdapter) PatchFilter(_ *RuntimeConfig, f *envoy_listener_v3.Filter, _ bool) (*envoy_listener_v3.Filter, bool, error) { - return f, false, nil +func (BasicExtensionAdapter) PatchFilter(p FilterPayload) (*envoy_listener_v3.Filter, bool, error) { + return p.Message, false, nil } // PatchFilters provides a default implementation of the PatchFilters interface that does nothing. @@ -55,8 +55,8 @@ func (BasicExtensionAdapter) PatchFilters(_ *RuntimeConfig, f []*envoy_listener_ } // PatchRoute provides a default implementation of the PatchRoute interface that does nothing. -func (BasicExtensionAdapter) PatchRoute(_ *RuntimeConfig, r *envoy_route_v3.RouteConfiguration) (*envoy_route_v3.RouteConfiguration, bool, error) { - return r, false, nil +func (BasicExtensionAdapter) PatchRoute(p RoutePayload) (*envoy_route_v3.RouteConfiguration, bool, error) { + return p.Message, false, nil } // PatchRoutes provides a default implementation of the PatchRoutes interface that does nothing. diff --git a/envoyextensions/extensioncommon/resources.go b/envoyextensions/extensioncommon/resources.go index 8067568ff2..22c6c3ffa9 100644 --- a/envoyextensions/extensioncommon/resources.go +++ b/envoyextensions/extensioncommon/resources.go @@ -17,9 +17,11 @@ import ( envoy_tcp_proxy_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/tcp_proxy/v3" envoy_tls_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" envoy_resource_v3 "github.com/envoyproxy/go-control-plane/pkg/resource/v3" - "github.com/hashicorp/consul/envoyextensions/xdscommon" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/anypb" + + "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/envoyextensions/xdscommon" ) // MakeUpstreamTLSTransportSocket generates an Envoy transport socket for the given TLS context. @@ -70,6 +72,206 @@ func MakeFilter(name string, cfg proto.Message) (*envoy_listener_v3.Filter, erro }, nil } +// TrafficDirection determines whether inbound or outbound Envoy resources will be patched. +type TrafficDirection string + +const ( + TrafficDirectionInbound TrafficDirection = "inbound" + TrafficDirectionOutbound TrafficDirection = "outbound" +) + +var TrafficDirections = StringSet{string(TrafficDirectionInbound): {}, string(TrafficDirectionOutbound): {}} + +type StringSet map[string]struct{} + +func (c *StringSet) CheckRequired(v, fieldName string) error { + if _, ok := (*c)[v]; !ok { + if v == "" { + return fmt.Errorf("field %s is required", fieldName) + } + + var keys []string + for k := range *c { + keys = append(keys, k) + } + + return fmt.Errorf("invalid %s '%q'; supported values: %s", + fieldName, v, strings.Join(keys, ", ")) + } + return nil +} + +func NormalizeEmptyToDefault(s string) string { + if s == "" { + return "default" + } + + return s +} + +func NormalizeServiceName(sn *api.CompoundServiceName) { + sn.Namespace = NormalizeEmptyToDefault(sn.Namespace) + sn.Partition = NormalizeEmptyToDefault(sn.Partition) +} + +// Payload represents a single Envoy resource to be modified by extensions. +// It associates the RuntimeConfig of the local proxy, the TrafficDirection +// of the resource, and the CompoundServiceName and UpstreamData (if outbound) +// of a service the Envoy resource corresponds to. +type Payload[K proto.Message] struct { + RuntimeConfig *RuntimeConfig + ServiceName *api.CompoundServiceName + Upstream *UpstreamData + TrafficDirection TrafficDirection + Message K +} + +func (p Payload[K]) IsInbound() bool { + return p.TrafficDirection == TrafficDirectionInbound +} + +type ClusterPayload = Payload[*envoy_cluster_v3.Cluster] +type ClusterLoadAssignmentPayload = Payload[*envoy_endpoint_v3.ClusterLoadAssignment] +type ListenerPayload = Payload[*envoy_listener_v3.Listener] +type FilterPayload = Payload[*envoy_listener_v3.Filter] +type RoutePayload = Payload[*envoy_route_v3.RouteConfiguration] + +func (cfg *RuntimeConfig) GetClusterPayload(c *envoy_cluster_v3.Cluster) ClusterPayload { + d := TrafficDirectionOutbound + var u *UpstreamData + var sn *api.CompoundServiceName + + if IsLocalAppCluster(c) { + d = TrafficDirectionInbound + } else { + u, sn = cfg.findUpstreamBySNI(c.Name) + } + + return ClusterPayload{ + RuntimeConfig: cfg, + ServiceName: sn, + Upstream: u, + TrafficDirection: d, + Message: c, + } +} + +func (c *RuntimeConfig) GetListenerPayload(l *envoy_listener_v3.Listener) ListenerPayload { + d := TrafficDirectionOutbound + var u *UpstreamData + var sn *api.CompoundServiceName + + if IsInboundPublicListener(l) { + d = TrafficDirectionInbound + } else { + u, sn = c.findUpstreamByEnvoyID(GetListenerEnvoyID(l)) + } + + return ListenerPayload{ + RuntimeConfig: c, + ServiceName: sn, + Upstream: u, + TrafficDirection: d, + Message: l, + } +} + +func (c *RuntimeConfig) GetFilterPayload(f *envoy_listener_v3.Filter, l *envoy_listener_v3.Listener) FilterPayload { + d := TrafficDirectionOutbound + var u *UpstreamData + var sn *api.CompoundServiceName + + if IsInboundPublicListener(l) { + d = TrafficDirectionInbound + } else { + u, sn = c.findUpstreamByEnvoyID(GetListenerEnvoyID(l)) + } + + return FilterPayload{ + RuntimeConfig: c, + ServiceName: sn, + Upstream: u, + TrafficDirection: d, + Message: f, + } +} + +func (c *RuntimeConfig) GetRoutePayload(r *envoy_route_v3.RouteConfiguration) RoutePayload { + d := TrafficDirectionOutbound + var u *UpstreamData + var sn *api.CompoundServiceName + + if IsRouteToLocalAppCluster(r) { + d = TrafficDirectionInbound + } else { + u, sn = c.findUpstreamByEnvoyID(r.Name) + } + + return RoutePayload{ + RuntimeConfig: c, + ServiceName: sn, + Upstream: u, + TrafficDirection: d, + Message: r, + } +} + +func (cfg *RuntimeConfig) GetClusterLoadAssignmentPayload(c *envoy_endpoint_v3.ClusterLoadAssignment) ClusterLoadAssignmentPayload { + d := TrafficDirectionOutbound + var u *UpstreamData + var sn *api.CompoundServiceName + + if IsLocalAppClusterLoadAssignment(c) { + d = TrafficDirectionInbound + } else { + u, sn = cfg.findUpstreamBySNI(c.ClusterName) + + } + + return ClusterLoadAssignmentPayload{ + RuntimeConfig: cfg, + ServiceName: sn, + Upstream: u, + TrafficDirection: d, + Message: c, + } +} + +func (c *RuntimeConfig) findUpstreamByEnvoyID(envoyID string) (*UpstreamData, *api.CompoundServiceName) { + for sn, u := range c.Upstreams { + if u.EnvoyID == envoyID { + return u, &sn + } + } + + return nil, nil +} + +func (c *RuntimeConfig) findUpstreamBySNI(sni string) (*UpstreamData, *api.CompoundServiceName) { + for sn, u := range c.Upstreams { + _, ok := u.SNIs[sni] + if ok { + return u, &sn + } + + if strings.HasPrefix(sni, xdscommon.FailoverClusterNamePrefix) { + parts := strings.Split(sni, "~") + + if len(parts) != 3 { + continue + } + + id := parts[2] + _, ok := u.SNIs[id] + if ok { + return u, &sn + } + } + } + + return nil, nil +} + // GetListenerEnvoyID returns the Envoy ID string parsed from the name of the given Listener. If none is found, it // returns the empty string. func GetListenerEnvoyID(l *envoy_listener_v3.Listener) string { diff --git a/envoyextensions/extensioncommon/runtime_config.go b/envoyextensions/extensioncommon/runtime_config.go index 2572d3f381..9317271e1e 100644 --- a/envoyextensions/extensioncommon/runtime_config.go +++ b/envoyextensions/extensioncommon/runtime_config.go @@ -8,8 +8,11 @@ import "github.com/hashicorp/consul/api" // UpstreamData has the SNI, EnvoyID, and OutgoingProxyKind of the upstream services for the local proxy and this data // is used to choose which Envoy resources to patch. type UpstreamData struct { - // SNI is the SNI header used to reach an upstream service. - SNI map[string]struct{} + // This is the SNI for the upstream service without accounting for any discovery chain magic. + PrimarySNI string + + // SNIs is the SNIs header used to reach an upstream service. + SNIs map[string]struct{} // EnvoyID is the envoy ID of an upstream service, structured or // when using a // non-default namespace or partition. @@ -68,7 +71,7 @@ type RuntimeConfig struct { // Only used when IsSourcedFromUpstream is true. func (c RuntimeConfig) MatchesUpstreamServiceSNI(sni string) bool { u := c.Upstreams[c.ServiceName] - _, match := u.SNI[sni] + _, match := u.SNIs[sni] return match } diff --git a/envoyextensions/extensioncommon/runtime_config_test.go b/envoyextensions/extensioncommon/runtime_config_test.go index a6cca3b64b..fa2ac8df5f 100644 --- a/envoyextensions/extensioncommon/runtime_config_test.go +++ b/envoyextensions/extensioncommon/runtime_config_test.go @@ -20,7 +20,7 @@ func makeTestRuntimeConfig() RuntimeConfig { sn: { EnvoyID: "eid", OutgoingProxyKind: api.ServiceKindTerminatingGateway, - SNI: map[string]struct{}{ + SNIs: map[string]struct{}{ "sni1": {}, "sni2": {}, }, diff --git a/envoyextensions/extensioncommon/upstream_envoy_extender.go b/envoyextensions/extensioncommon/upstream_envoy_extender.go index 96a0969d44..d3ca2faf6a 100644 --- a/envoyextensions/extensioncommon/upstream_envoy_extender.go +++ b/envoyextensions/extensioncommon/upstream_envoy_extender.go @@ -74,7 +74,7 @@ func (ext *UpstreamEnvoyExtender) Extend(resources *xdscommon.IndexedResources, continue } - newCluster, patched, err := ext.Extension.PatchCluster(config, resource) + newCluster, patched, err := ext.Extension.PatchCluster(config.GetClusterPayload(resource)) if err != nil { resultErr = multierror.Append(resultErr, fmt.Errorf("error patching cluster: %w", err)) continue @@ -101,7 +101,7 @@ func (ext *UpstreamEnvoyExtender) Extend(resources *xdscommon.IndexedResources, continue } - newRoute, patched, err := ext.Extension.PatchRoute(config, resource) + newRoute, patched, err := ext.Extension.PatchRoute(config.GetRoutePayload(resource)) if err != nil { resultErr = multierror.Append(resultErr, fmt.Errorf("error patching route: %w", err)) continue @@ -146,7 +146,7 @@ func (ext *UpstreamEnvoyExtender) patchTerminatingGatewayListener(config *Runtim var filters []*envoy_listener_v3.Filter for _, filter := range filterChain.Filters { - newFilter, ok, err := ext.Extension.PatchFilter(config, filter, IsInboundPublicListener(l)) + newFilter, ok, err := ext.Extension.PatchFilter(config.GetFilterPayload(filter, l)) if err != nil { resultErr = multierror.Append(resultErr, fmt.Errorf("error patching listener filter: %w", err)) @@ -190,7 +190,7 @@ func (ext *UpstreamEnvoyExtender) patchConnectProxyListener(config *RuntimeConfi var filters []*envoy_listener_v3.Filter for _, filter := range filterChain.Filters { - newFilter, ok, err := ext.Extension.PatchFilter(config, filter, IsInboundPublicListener(l)) + newFilter, ok, err := ext.Extension.PatchFilter(config.GetFilterPayload(filter, l)) if err != nil { resultErr = multierror.Append(resultErr, fmt.Errorf("error patching listener filter: %w", err)) filters = append(filters, filter) @@ -225,7 +225,7 @@ func (ext *UpstreamEnvoyExtender) patchTProxyListener(config *RuntimeConfig, l * } for _, filter := range filterChain.Filters { - newFilter, ok, err := ext.Extension.PatchFilter(config, filter, IsInboundPublicListener(l)) + newFilter, ok, err := ext.Extension.PatchFilter(config.GetFilterPayload(filter, l)) if err != nil { resultErr = multierror.Append(resultErr, fmt.Errorf("error patching listener filter: %w", err)) filters = append(filters, filter) diff --git a/envoyextensions/xdscommon/xdscommon.go b/envoyextensions/xdscommon/xdscommon.go index b91342f221..e4d293f8c9 100644 --- a/envoyextensions/xdscommon/xdscommon.go +++ b/envoyextensions/xdscommon/xdscommon.go @@ -52,6 +52,8 @@ const ( // SecretType is the TypeURL for Secret discovery responses. SecretType = apiTypePrefix + "envoy.extensions.transport_sockets.tls.v3.Secret" + + FailoverClusterNamePrefix = "failover-target~" ) type IndexedResources struct { diff --git a/troubleshoot/proxy/validateupstream.go b/troubleshoot/proxy/validateupstream.go index d54731a8d2..64be9d02e1 100644 --- a/troubleshoot/proxy/validateupstream.go +++ b/troubleshoot/proxy/validateupstream.go @@ -87,7 +87,7 @@ func Validate(indexedResources *xdscommon.IndexedResources, envoyID string, vip // the cluster SNIs configured on this proxy, not just the upstream being validated. This means the // PatchCluster function in the Validate plugin will be run on all clusters, but errors will only // surface for clusters related to the upstream being validated. - SNI: snis, + SNIs: snis, EnvoyID: envoyID, }, }, diff --git a/troubleshoot/validate/validate.go b/troubleshoot/validate/validate.go index 2177eb304b..f7c6299f99 100644 --- a/troubleshoot/validate/validate.go +++ b/troubleshoot/validate/validate.go @@ -92,10 +92,10 @@ func MakeValidate(ext extensioncommon.RuntimeConfig) (extensioncommon.BasicExten upstream, ok := ext.Upstreams[ext.ServiceName] if ok { vip = upstream.VIP - if upstream.SNI == nil || len(upstream.SNI) == 0 { + if upstream.SNIs == nil || len(upstream.SNIs) == 0 { return nil, fmt.Errorf("no SNIs were set, unable to validate Envoy clusters") } - snis = upstream.SNI + snis = upstream.SNIs } if mainEnvoyID == "" && vip == "" { return nil, fmt.Errorf("envoyID or virtual IP is required") @@ -306,84 +306,87 @@ func (p *Validate) CanApply(config *extensioncommon.RuntimeConfig) bool { return true } -func (p *Validate) PatchRoute(config *extensioncommon.RuntimeConfig, route *envoy_route_v3.RouteConfiguration) (*envoy_route_v3.RouteConfiguration, bool, error) { +func (v *Validate) PatchRoute(p extensioncommon.RoutePayload) (*envoy_route_v3.RouteConfiguration, bool, error) { + route := p.Message // Route name on connect proxies will be the envoy ID. We are only validating routes for the specific upstream with // the envoyID configured. - if route.Name != p.envoyID { + if route.Name != p.Upstream.EnvoyID { return route, false, nil } - p.route = true + v.route = true for sni := range extensioncommon.RouteClusterNames(route) { - if _, ok := p.resources[sni]; ok { + if _, ok := v.resources[sni]; ok { continue } - p.resources[sni] = &resource{required: true} + v.resources[sni] = &resource{required: true} } return route, false, nil } -func (p *Validate) PatchCluster(config *extensioncommon.RuntimeConfig, c *envoy_cluster_v3.Cluster) (*envoy_cluster_v3.Cluster, bool, error) { - v, ok := p.resources[c.Name] +func (v *Validate) PatchCluster(p extensioncommon.ClusterPayload) (*envoy_cluster_v3.Cluster, bool, error) { + c := p.Message + val, ok := v.resources[c.Name] if !ok { - v = &resource{} - p.resources[c.Name] = v + val = &resource{} + v.resources[c.Name] = val } - v.cluster = true + val.cluster = true // If it's an aggregate cluster, add the child clusters to p.resources if they are not already there. aggregateCluster, ok := isAggregateCluster(c) if ok { // Mark this as an aggregate cluster, so we know we do not need to validate its endpoints directly. - v.aggregateCluster = true + val.aggregateCluster = true for _, clusterName := range aggregateCluster.Clusters { - r, ok := p.resources[clusterName] + r, ok := v.resources[clusterName] if !ok { r = &resource{} - p.resources[clusterName] = r + v.resources[clusterName] = r } - if v.aggregateClusterChildren == nil { - v.aggregateClusterChildren = []string{} + if val.aggregateClusterChildren == nil { + val.aggregateClusterChildren = []string{} } // On the parent cluster, add the children. - v.aggregateClusterChildren = append(v.aggregateClusterChildren, clusterName) + val.aggregateClusterChildren = append(val.aggregateClusterChildren, clusterName) // On the child cluster, set the parent. r.parentCluster = c.Name // The child clusters of an aggregate cluster will be required if the parent cluster is. - r.required = v.required + r.required = val.required } return c, false, nil } if c.EdsClusterConfig != nil { - v.usesEDS = true + val.usesEDS = true } else { la := c.LoadAssignment if la == nil { return c, false, nil } - v.endpoints = len(la.Endpoints) + len(la.NamedEndpoints) + val.endpoints = len(la.Endpoints) + len(la.NamedEndpoints) } return c, false, nil } -func (p *Validate) PatchFilter(config *extensioncommon.RuntimeConfig, filter *envoy_listener_v3.Filter, _ bool) (*envoy_listener_v3.Filter, bool, error) { +func (v *Validate) PatchFilter(p extensioncommon.FilterPayload) (*envoy_listener_v3.Filter, bool, error) { + filter := p.Message // If a single filter exists for a listener we say it exists. - p.listener = true + v.listener = true if httpConfig := envoy_resource_v3.GetHTTPConnectionManager(filter); httpConfig != nil { // If the http filter uses RDS, then the clusters we need to validate exist in the route, and there's nothing // else we need to do with the filter. if httpConfig.GetRds() != nil { - p.usesRDS = true + v.usesRDS = true // Edit the runtime configuration to add an envoy ID based on the route name in the filter. This is because // routes are matched by envoyID and in the transparent proxy case, we only have the VIP set in the // RuntimeConfig. - p.envoyID = httpConfig.GetRds().RouteConfigName + v.envoyID = httpConfig.GetRds().RouteConfigName emptyServiceKey := api.CompoundServiceName{} - upstream, ok := config.Upstreams[emptyServiceKey] + upstream, ok := p.RuntimeConfig.Upstreams[emptyServiceKey] if ok { - upstream.EnvoyID = p.envoyID + upstream.EnvoyID = v.envoyID } return filter, true, nil } @@ -392,10 +395,10 @@ func (p *Validate) PatchFilter(config *extensioncommon.RuntimeConfig, filter *en // FilterClusterNames handles the filter being an http or tcp filter. for sni := range extensioncommon.FilterClusterNames(filter) { // Mark any clusters we see as required resources. - if r, ok := p.resources[sni]; ok { + if r, ok := v.resources[sni]; ok { r.required = true } else { - p.resources[sni] = &resource{required: true} + v.resources[sni] = &resource{required: true} } } diff --git a/troubleshoot/validate/validate_test.go b/troubleshoot/validate/validate_test.go index 6747d688e1..9d779c48f4 100644 --- a/troubleshoot/validate/validate_test.go +++ b/troubleshoot/validate/validate_test.go @@ -349,7 +349,7 @@ func TestMakeValidate(t *testing.T) { }, Upstreams: map[api.CompoundServiceName]*extensioncommon.UpstreamData{ svc: { - SNI: tc.snis, + SNIs: tc.snis, }, }, } From 04a0d0133ae4297d089dc5381a0136df192aa4eb Mon Sep 17 00:00:00 2001 From: Dhia Ayachi Date: Tue, 30 May 2023 15:31:07 -0400 Subject: [PATCH 08/72] fix isServer to exclude local address (#17519) --- agent/consul/server.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/agent/consul/server.go b/agent/consul/server.go index c7d6d19c0e..418db2da1f 100644 --- a/agent/consul/server.go +++ b/agent/consul/server.go @@ -1679,12 +1679,18 @@ func (s *Server) IsLeader() bool { // IsServer checks if this addr is of a server func (s *Server) IsServer(addr string) bool { - for _, s := range s.raft.GetConfiguration().Configuration().Servers { - a, err := net.ResolveTCPAddr("tcp", string(s.Address)) + + for _, ss := range s.raft.GetConfiguration().Configuration().Servers { + a, err := net.ResolveTCPAddr("tcp", string(ss.Address)) + if err != nil { + continue + } + localIP, err := net.ResolveTCPAddr("tcp", string(s.config.RaftConfig.LocalID)) if err != nil { continue } - if string(metadata.GetIP(a)) == addr { + // only return true if it's another server and not our local address + if string(metadata.GetIP(a)) == addr && string(metadata.GetIP(localIP)) != addr { return true } } From e559c59eb62cb1d6f7ca8ddb9f67a2ec8450bc81 Mon Sep 17 00:00:00 2001 From: skpratt Date: Tue, 30 May 2023 17:25:48 -0500 Subject: [PATCH 09/72] Add version endpoint (#17506) * add FIPS verison info * separate out feature functionality from build identification * split out ent test * add version endpoint --- agent/agent_endpoint.go | 13 ++++++++++- agent/agent_endpoint_test.go | 29 ++++++++++++++++++++++++ agent/http_register.go | 1 + api/agent.go | 18 +++++++++++++++ version/version.go | 18 +++++++++++++++ website/content/api-docs/agent/index.mdx | 18 +++++++++++++++ 6 files changed, 96 insertions(+), 1 deletion(-) diff --git a/agent/agent_endpoint.go b/agent/agent_endpoint.go index bc35535194..13e993fc70 100644 --- a/agent/agent_endpoint.go +++ b/agent/agent_endpoint.go @@ -11,11 +11,13 @@ import ( "strings" "time" - "github.com/hashicorp/consul/envoyextensions/xdscommon" "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-memdb" "github.com/mitchellh/hashstructure" + "github.com/hashicorp/consul/envoyextensions/xdscommon" + "github.com/hashicorp/consul/version" + "github.com/hashicorp/go-bexpr" "github.com/hashicorp/serf/coordinate" "github.com/hashicorp/serf/serf" @@ -1683,3 +1685,12 @@ func (s *HTTPHandlers) AgentHost(resp http.ResponseWriter, req *http.Request) (i return debug.CollectHostInfo(), nil } + +// AgentVersion +// +// GET /v1/agent/version +// +// Retrieves Consul version information. +func (s *HTTPHandlers) AgentVersion(resp http.ResponseWriter, req *http.Request) (interface{}, error) { + return version.GetBuildInfo(), nil +} diff --git a/agent/agent_endpoint_test.go b/agent/agent_endpoint_test.go index fad7f7d7e4..66b028b7c0 100644 --- a/agent/agent_endpoint_test.go +++ b/agent/agent_endpoint_test.go @@ -21,7 +21,10 @@ import ( "time" "github.com/armon/go-metrics" + "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/version" + "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-uuid" "github.com/hashicorp/serf/serf" @@ -8081,6 +8084,32 @@ func TestAgent_HostBadACL(t *testing.T) { assert.Equal(t, http.StatusOK, resp.Code) } +func TestAgent_Version(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + + dc1 := "dc1" + a := NewTestAgent(t, ` + primary_datacenter = "`+dc1+`" + `) + defer a.Shutdown() + + testrpc.WaitForLeader(t, a.RPC, "dc1") + req, _ := http.NewRequest("GET", "/v1/agent/version", nil) + // req.Header.Add("X-Consul-Token", "initial-management") + resp := httptest.NewRecorder() + respRaw, err := a.srv.AgentVersion(resp, req) + assert.Nil(t, err) + assert.Equal(t, http.StatusOK, resp.Code) + assert.NotNil(t, respRaw) + + obj := respRaw.(*version.BuildInfo) + assert.NotNil(t, obj.HumanVersion) +} + // Thie tests that a proxy with an ExposeConfig is returned as expected. func TestAgent_Services_ExposeConfig(t *testing.T) { if testing.Short() { diff --git a/agent/http_register.go b/agent/http_register.go index 595a83ef52..b3f0dfea3f 100644 --- a/agent/http_register.go +++ b/agent/http_register.go @@ -29,6 +29,7 @@ func init() { registerEndpoint("/v1/agent/token/", []string{"PUT"}, (*HTTPHandlers).AgentToken) registerEndpoint("/v1/agent/self", []string{"GET"}, (*HTTPHandlers).AgentSelf) registerEndpoint("/v1/agent/host", []string{"GET"}, (*HTTPHandlers).AgentHost) + registerEndpoint("/v1/agent/version", []string{"GET"}, (*HTTPHandlers).AgentVersion) registerEndpoint("/v1/agent/maintenance", []string{"PUT"}, (*HTTPHandlers).AgentNodeMaintenance) registerEndpoint("/v1/agent/reload", []string{"PUT"}, (*HTTPHandlers).AgentReload) registerEndpoint("/v1/agent/monitor", []string{"GET"}, (*HTTPHandlers).AgentMonitor) diff --git a/api/agent.go b/api/agent.go index 6dd127b335..f45929cb5b 100644 --- a/api/agent.go +++ b/api/agent.go @@ -503,6 +503,24 @@ func (a *Agent) Host() (map[string]interface{}, error) { return out, nil } +// Version is used to retrieve information about the running Consul version and build. +func (a *Agent) Version() (map[string]interface{}, error) { + r := a.c.newRequest("GET", "/v1/agent/version") + _, resp, err := a.c.doRequest(r) + if err != nil { + return nil, err + } + defer closeResponseBody(resp) + if err := requireOK(resp); err != nil { + return nil, err + } + var out map[string]interface{} + if err := decodeBody(resp, &out); err != nil { + return nil, err + } + return out, nil +} + // Metrics is used to query the agent we are speaking to for // its current internal metric data func (a *Agent) Metrics() (*MetricsInfo, error) { diff --git a/version/version.go b/version/version.go index c66eb804e8..bd2cfd57aa 100644 --- a/version/version.go +++ b/version/version.go @@ -33,6 +33,14 @@ var ( BuildDate string = "1970-01-01T00:00:01Z" ) +// BuildInfo includes all available version info for this build +type BuildInfo struct { + SHA string + BuildDate string + HumanVersion string + FIPS string +} + // GetHumanVersion composes the parts of the version in a way that's suitable // for displaying to humans. func GetHumanVersion() string { @@ -51,3 +59,13 @@ func GetHumanVersion() string { // Strip off any single quotes added by the git information. return strings.ReplaceAll(version, "'", "") } + +// GetBuildInfo returns all available version information for this build. +func GetBuildInfo() *BuildInfo { + return &BuildInfo{ + SHA: GitCommit, + BuildDate: BuildDate, + HumanVersion: GetHumanVersion(), + FIPS: GetFIPSInfo(), + } +} diff --git a/website/content/api-docs/agent/index.mdx b/website/content/api-docs/agent/index.mdx index f84bad1be0..d76cc19107 100644 --- a/website/content/api-docs/agent/index.mdx +++ b/website/content/api-docs/agent/index.mdx @@ -206,6 +206,24 @@ $ curl \ } ``` +## Retrieve version information + +This endpoint returns version information about Consul. + +| Method | Path | Produces | +| ------ | ---------------- | ------------------ | +| `GET` | `/agent/version` | `application/json` | + +The table below shows this endpoint's support for +[blocking queries](/consul/api-docs/features/blocking), +[consistency modes](/consul/api-docs/features/consistency), +[agent caching](/consul/api-docs/features/caching), and +[required ACLs](/consul/api-docs/api-structure#authentication). + +| Blocking Queries | Consistency Modes | Agent Caching | ACL Required | +| ---------------- | ----------------- | ------------- | ------------ | +| `NO` | `none` | `none` | `none` | + ## List Members This endpoint returns the members the agent sees in the cluster gossip pool. Due From a46ac4be07bcf71fbec50fcf66cd07ba43857efc Mon Sep 17 00:00:00 2001 From: skpratt Date: Tue, 30 May 2023 17:40:31 -0500 Subject: [PATCH 10/72] FIPS gossip changes (#17507) * separate fips gossip * clean up --- agent/consul/merge_oss.go | 4 ++++ version/fips.go | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/agent/consul/merge_oss.go b/agent/consul/merge_oss.go index 0f144ab21d..59704f6533 100644 --- a/agent/consul/merge_oss.go +++ b/agent/consul/merge_oss.go @@ -13,6 +13,10 @@ import ( ) func (md *lanMergeDelegate) enterpriseNotifyMergeMember(m *serf.Member) error { + if memberFIPS := m.Tags["fips"]; memberFIPS != "" { + return fmt.Errorf("Member '%s' is FIPS Consul; FIPS Consul is only available in Consul Enterprise", + m.Name) + } if memberPartition := m.Tags["ap"]; memberPartition != "" { return fmt.Errorf("Member '%s' part of partition '%s'; Partitions are a Consul Enterprise feature", m.Name, memberPartition) diff --git a/version/fips.go b/version/fips.go index 5b131754c5..4700bc6813 100644 --- a/version/fips.go +++ b/version/fips.go @@ -2,6 +2,10 @@ package version +func IsFIPS() bool { + return false +} + func GetFIPSInfo() string { return "" } From fdda7adeaa5ae7adc0ec8bc28896dd1373e464fa Mon Sep 17 00:00:00 2001 From: skpratt Date: Wed, 31 May 2023 09:01:44 -0500 Subject: [PATCH 11/72] issue a warning if major FIPS assumptions are broken (#17524) --- agent/agent.go | 6 ++++++ agent/agent_oss.go | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/agent/agent.go b/agent/agent.go index acb0ccd94e..388c7c3e6f 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -597,6 +597,12 @@ func (a *Agent) Start(ctx context.Context) error { // regular and on-demand state synchronizations (anti-entropy). a.sync = ae.NewStateSyncer(a.State, c.AEInterval, a.shutdownCh, a.logger) + err = validateFIPSConfig(a.config) + if err != nil { + // Log warning, rather than force breaking + a.logger.Warn("FIPS 140-2 Compliance", "issue", err) + } + // create the config for the rpc server/client consulCfg, err := newConsulConfig(a.config, a.logger) if err != nil { diff --git a/agent/agent_oss.go b/agent/agent_oss.go index 4153c66a0b..93e633cc65 100644 --- a/agent/agent_oss.go +++ b/agent/agent_oss.go @@ -40,6 +40,11 @@ func (a *Agent) reloadEnterprise(conf *config.RuntimeConfig) error { func enterpriseConsulConfig(_ *consul.Config, _ *config.RuntimeConfig) { } +// validateFIPSConfig is a noop stub for the func defined in agent_ent.go +func validateFIPSConfig(_ *config.RuntimeConfig) error { + return nil +} + // WriteEvent is a noop stub for the func defined agent_ent.go func (a *Agent) WriteEvent(eventType string, payload interface{}) { } From b9c9d79778ea454dd2cc5860baa2d1dff4688519 Mon Sep 17 00:00:00 2001 From: Jared Kirschner <85913323+jkirschner-hashicorp@users.noreply.github.com> Date: Wed, 31 May 2023 11:50:24 -0400 Subject: [PATCH 12/72] Accept ap, datacenter, and namespace query params (#17525) This commit only contains the OSS PR (datacenter query param support). A separate enterprise PR adds support for ap and namespace query params. Resources in Consul can exists within scopes such as datacenters, cluster peers, admin partitions, and namespaces. You can refer to those resources from interfaces such as the CLI, HTTP API, DNS, and configuration files. Some scope levels have consistent naming: cluster peers are always referred to as "peer". Other scope levels use a short-hand in DNS lookups... - "ns" for namespace - "ap" for admin partition - "dc" for datacenter ...But use long-hand in CLI commands: - "namespace" for namespace - "partition" for admin partition - and "datacenter" However, HTTP API query parameters do not follow a consistent pattern, supporting short-hand for some scopes but long-hand for others: - "ns" for namespace - "partition" for admin partition - and "dc" for datacenter. This inconsistency is confusing, especially for users who have been exposed to providing scope names through another interface such as CLI or DNS queries. This commit improves UX by consistently supporting both short-hand and long-hand forms of the namespace, partition, and datacenter scopes in HTTP API query parameters. --- .changelog/17525.txt | 3 +++ agent/http.go | 7 +++++-- agent/http_test.go | 9 +++++++++ api/api.go | 13 +++++++++++++ command/connect/envoy/envoy_test.go | 10 ++++++++-- 5 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 .changelog/17525.txt diff --git a/.changelog/17525.txt b/.changelog/17525.txt new file mode 100644 index 0000000000..66bdcb8d90 --- /dev/null +++ b/.changelog/17525.txt @@ -0,0 +1,3 @@ +```release-note:improvement +http: accept query parameters `datacenter`, `ap` (enterprise-only), and `namespace` (enterprise-only). Both short-hand and long-hand forms of these query params are now supported via the HTTP API (dc/datacenter, ap/partition, ns/namespace). +``` \ No newline at end of file diff --git a/agent/http.go b/agent/http.go index 701674b555..1706794adf 100644 --- a/agent/http.go +++ b/agent/http.go @@ -983,9 +983,12 @@ func parseConsistencyReadRequest(resp http.ResponseWriter, req *http.Request, b } } -// parseDC is used to parse the ?dc query param +// parseDC is used to parse the datacenter from the query params. +// ?datacenter has precedence over ?dc. func (s *HTTPHandlers) parseDC(req *http.Request, dc *string) { - if other := req.URL.Query().Get("dc"); other != "" { + if other := req.URL.Query().Get("datacenter"); other != "" { + *dc = other + } else if other = req.URL.Query().Get("dc"); other != "" { *dc = other } else if *dc == "" { *dc = s.agent.config.Datacenter diff --git a/agent/http_test.go b/agent/http_test.go index 37acc5f8ee..967b1b0b43 100644 --- a/agent/http_test.go +++ b/agent/http_test.go @@ -881,6 +881,15 @@ func TestParseSource(t *testing.T) { t.Fatalf("bad: %v", source) } + // We should follow whatever datacenter parameter was given so that the node is + // looked up correctly on the receiving end. + req, _ = http.NewRequest("GET", "/v1/catalog/nodes?near=bob&datacenter=foo", nil) + source = structs.QuerySource{} + a.srv.parseSource(req, &source) + if source.Datacenter != "foo" || source.Node != "bob" { + t.Fatalf("bad: %v", source) + } + // The magic "_agent" node name will use the agent's local node name. req, _ = http.NewRequest("GET", "/v1/catalog/nodes?near=_agent", nil) source = structs.QuerySource{} diff --git a/api/api.go b/api/api.go index e7109141b5..1fe0c71b61 100644 --- a/api/api.go +++ b/api/api.go @@ -836,12 +836,21 @@ func (r *request) setQueryOptions(q *QueryOptions) { return } if q.Namespace != "" { + // For backwards-compatibility with existing tests, + // use the short-hand query param name "ns" + // rather than the alternative long-hand "namespace" r.params.Set("ns", q.Namespace) } if q.Partition != "" { + // For backwards-compatibility with existing tests, + // use the long-hand query param name "partition" + // rather than the alternative short-hand "ap" r.params.Set("partition", q.Partition) } if q.Datacenter != "" { + // For backwards-compatibility with existing tests, + // use the short-hand query param name "dc" + // rather than the alternative long-hand "datacenter" r.params.Set("dc", q.Datacenter) } if q.Peer != "" { @@ -949,12 +958,16 @@ func (r *request) setWriteOptions(q *WriteOptions) { if q == nil { return } + // For backwards-compatibility, continue to use the shorthand "ns" + // rather than "namespace" if q.Namespace != "" { r.params.Set("ns", q.Namespace) } if q.Partition != "" { r.params.Set("partition", q.Partition) } + // For backwards-compatibility, continue to use the shorthand "dc" + // rather than "datacenter" if q.Datacenter != "" { r.params.Set("dc", q.Datacenter) } diff --git a/command/connect/envoy/envoy_test.go b/command/connect/envoy/envoy_test.go index d1105df0d2..86c48a8e39 100644 --- a/command/connect/envoy/envoy_test.go +++ b/command/connect/envoy/envoy_test.go @@ -1466,6 +1466,9 @@ func testMockAgentGatewayConfig(namespacesEnabled bool) http.HandlerFunc { func namespaceFromQuery(r *http.Request) string { // Use the namespace in the request if there is one, otherwise // use-default. + if queryNamespace := r.URL.Query().Get("namespace"); queryNamespace != "" { + return queryNamespace + } if queryNs := r.URL.Query().Get("ns"); queryNs != "" { return queryNs } @@ -1475,8 +1478,11 @@ func namespaceFromQuery(r *http.Request) string { func partitionFromQuery(r *http.Request) string { // Use the partition in the request if there is one, otherwise // use-default. - if queryAP := r.URL.Query().Get("partition"); queryAP != "" { - return queryAP + if queryPartition := r.URL.Query().Get("partition"); queryPartition != "" { + return queryPartition + } + if queryAp := r.URL.Query().Get("ap"); queryAp != "" { + return queryAp } return "default" } From a065eef3efc928eb2b5618efc9507889d8acc5f5 Mon Sep 17 00:00:00 2001 From: skpratt Date: Wed, 31 May 2023 10:53:37 -0500 Subject: [PATCH 13/72] add FIPS to dataplane features (#17522) --- .../dataplane/get_supported_features.go | 5 + .../dataplane/get_supported_features_test.go | 4 +- proto-public/pbdataplane/dataplane.pb.go | 107 +++++++++--------- proto-public/pbdataplane/dataplane.proto | 1 + 4 files changed, 64 insertions(+), 53 deletions(-) diff --git a/agent/grpc-external/services/dataplane/get_supported_features.go b/agent/grpc-external/services/dataplane/get_supported_features.go index 6d5edac1c5..ea63871533 100644 --- a/agent/grpc-external/services/dataplane/get_supported_features.go +++ b/agent/grpc-external/services/dataplane/get_supported_features.go @@ -11,6 +11,7 @@ import ( external "github.com/hashicorp/consul/agent/grpc-external" "github.com/hashicorp/consul/proto-public/pbdataplane" + "github.com/hashicorp/consul/version" ) func (s *Server) GetSupportedDataplaneFeatures(ctx context.Context, req *pbdataplane.GetSupportedDataplaneFeaturesRequest) (*pbdataplane.GetSupportedDataplaneFeaturesResponse, error) { @@ -40,6 +41,10 @@ func (s *Server) GetSupportedDataplaneFeatures(ctx context.Context, req *pbdatap FeatureName: pbdataplane.DataplaneFeatures_DATAPLANE_FEATURES_ENVOY_BOOTSTRAP_CONFIGURATION, Supported: true, }, + { + FeatureName: pbdataplane.DataplaneFeatures_DATAPLANE_FEATURES_FIPS, + Supported: version.IsFIPS(), + }, } return &pbdataplane.GetSupportedDataplaneFeaturesResponse{SupportedDataplaneFeatures: supportedFeatures}, nil diff --git a/agent/grpc-external/services/dataplane/get_supported_features_test.go b/agent/grpc-external/services/dataplane/get_supported_features_test.go index cbd483ac9f..35079a40a8 100644 --- a/agent/grpc-external/services/dataplane/get_supported_features_test.go +++ b/agent/grpc-external/services/dataplane/get_supported_features_test.go @@ -40,7 +40,7 @@ func TestSupportedDataplaneFeatures_Success(t *testing.T) { client := testClient(t, server) resp, err := client.GetSupportedDataplaneFeatures(ctx, &pbdataplane.GetSupportedDataplaneFeaturesRequest{}) require.NoError(t, err) - require.Equal(t, 3, len(resp.SupportedDataplaneFeatures)) + require.Equal(t, 4, len(resp.SupportedDataplaneFeatures)) for _, feature := range resp.SupportedDataplaneFeatures { switch feature.GetFeatureName() { @@ -72,7 +72,7 @@ func TestSupportedDataplaneFeatures_ACLsDisabled(t *testing.T) { client := testClient(t, server) resp, err := client.GetSupportedDataplaneFeatures(ctx, &pbdataplane.GetSupportedDataplaneFeaturesRequest{}) require.NoError(t, err) - require.Equal(t, 3, len(resp.SupportedDataplaneFeatures)) + require.Equal(t, 4, len(resp.SupportedDataplaneFeatures)) } func TestSupportedDataplaneFeatures_InvalidACLToken(t *testing.T) { diff --git a/proto-public/pbdataplane/dataplane.pb.go b/proto-public/pbdataplane/dataplane.pb.go index c70dd18a32..976c9ff20f 100644 --- a/proto-public/pbdataplane/dataplane.pb.go +++ b/proto-public/pbdataplane/dataplane.pb.go @@ -34,6 +34,7 @@ const ( DataplaneFeatures_DATAPLANE_FEATURES_WATCH_SERVERS DataplaneFeatures = 1 DataplaneFeatures_DATAPLANE_FEATURES_EDGE_CERTIFICATE_MANAGEMENT DataplaneFeatures = 2 DataplaneFeatures_DATAPLANE_FEATURES_ENVOY_BOOTSTRAP_CONFIGURATION DataplaneFeatures = 3 + DataplaneFeatures_DATAPLANE_FEATURES_FIPS DataplaneFeatures = 4 ) // Enum value maps for DataplaneFeatures. @@ -43,12 +44,14 @@ var ( 1: "DATAPLANE_FEATURES_WATCH_SERVERS", 2: "DATAPLANE_FEATURES_EDGE_CERTIFICATE_MANAGEMENT", 3: "DATAPLANE_FEATURES_ENVOY_BOOTSTRAP_CONFIGURATION", + 4: "DATAPLANE_FEATURES_FIPS", } DataplaneFeatures_value = map[string]int32{ "DATAPLANE_FEATURES_UNSPECIFIED": 0, "DATAPLANE_FEATURES_WATCH_SERVERS": 1, "DATAPLANE_FEATURES_EDGE_CERTIFICATE_MANAGEMENT": 2, "DATAPLANE_FEATURES_ENVOY_BOOTSTRAP_CONFIGURATION": 3, + "DATAPLANE_FEATURES_FIPS": 4, } ) @@ -587,7 +590,7 @@ var file_pbdataplane_dataplane_proto_rawDesc = []byte{ 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x73, 0x2a, 0xc7, 0x01, 0x0a, 0x11, 0x44, 0x61, 0x74, 0x61, 0x70, + 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x73, 0x2a, 0xe4, 0x01, 0x0a, 0x11, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x1e, 0x44, 0x41, 0x54, 0x41, 0x50, 0x4c, 0x41, 0x4e, 0x45, 0x5f, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, @@ -600,59 +603,61 @@ var file_pbdataplane_dataplane_proto_rawDesc = []byte{ 0x54, 0x41, 0x50, 0x4c, 0x41, 0x4e, 0x45, 0x5f, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x53, 0x5f, 0x45, 0x4e, 0x56, 0x4f, 0x59, 0x5f, 0x42, 0x4f, 0x4f, 0x54, 0x53, 0x54, 0x52, 0x41, 0x50, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x55, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x03, - 0x2a, 0xea, 0x01, 0x0a, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4b, 0x69, 0x6e, 0x64, - 0x12, 0x1c, 0x0a, 0x18, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, - 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, - 0x0a, 0x14, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x54, - 0x59, 0x50, 0x49, 0x43, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x1e, 0x0a, 0x1a, 0x53, 0x45, 0x52, 0x56, - 0x49, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, - 0x5f, 0x50, 0x52, 0x4f, 0x58, 0x59, 0x10, 0x02, 0x12, 0x1d, 0x0a, 0x19, 0x53, 0x45, 0x52, 0x56, - 0x49, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x45, 0x53, 0x48, 0x5f, 0x47, 0x41, - 0x54, 0x45, 0x57, 0x41, 0x59, 0x10, 0x03, 0x12, 0x24, 0x0a, 0x20, 0x53, 0x45, 0x52, 0x56, 0x49, - 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x54, 0x45, 0x52, 0x4d, 0x49, 0x4e, 0x41, 0x54, - 0x49, 0x4e, 0x47, 0x5f, 0x47, 0x41, 0x54, 0x45, 0x57, 0x41, 0x59, 0x10, 0x04, 0x12, 0x20, 0x0a, - 0x1c, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x49, 0x4e, - 0x47, 0x52, 0x45, 0x53, 0x53, 0x5f, 0x47, 0x41, 0x54, 0x45, 0x57, 0x41, 0x59, 0x10, 0x05, 0x12, - 0x1c, 0x0a, 0x18, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, - 0x41, 0x50, 0x49, 0x5f, 0x47, 0x41, 0x54, 0x45, 0x57, 0x41, 0x59, 0x10, 0x06, 0x32, 0xe2, 0x02, - 0x0a, 0x10, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x12, 0xae, 0x01, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, - 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x73, 0x12, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, - 0x65, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x44, 0x61, - 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x41, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, - 0x61, 0x6e, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, + 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x41, 0x54, 0x41, 0x50, 0x4c, 0x41, 0x4e, 0x45, 0x5f, 0x46, 0x45, + 0x41, 0x54, 0x55, 0x52, 0x45, 0x53, 0x5f, 0x46, 0x49, 0x50, 0x53, 0x10, 0x04, 0x2a, 0xea, 0x01, + 0x0a, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x1c, 0x0a, + 0x18, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x55, 0x4e, + 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x53, + 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x54, 0x59, 0x50, 0x49, + 0x43, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x1e, 0x0a, 0x1a, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, + 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x5f, 0x50, 0x52, + 0x4f, 0x58, 0x59, 0x10, 0x02, 0x12, 0x1d, 0x0a, 0x19, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, + 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x45, 0x53, 0x48, 0x5f, 0x47, 0x41, 0x54, 0x45, 0x57, + 0x41, 0x59, 0x10, 0x03, 0x12, 0x24, 0x0a, 0x20, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x5f, + 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x54, 0x45, 0x52, 0x4d, 0x49, 0x4e, 0x41, 0x54, 0x49, 0x4e, 0x47, + 0x5f, 0x47, 0x41, 0x54, 0x45, 0x57, 0x41, 0x59, 0x10, 0x04, 0x12, 0x20, 0x0a, 0x1c, 0x53, 0x45, + 0x52, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x49, 0x4e, 0x47, 0x52, 0x45, + 0x53, 0x53, 0x5f, 0x47, 0x41, 0x54, 0x45, 0x57, 0x41, 0x59, 0x10, 0x05, 0x12, 0x1c, 0x0a, 0x18, + 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x41, 0x50, 0x49, + 0x5f, 0x47, 0x41, 0x54, 0x45, 0x57, 0x41, 0x59, 0x10, 0x06, 0x32, 0xe2, 0x02, 0x0a, 0x10, 0x44, + 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, + 0xae, 0x01, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x08, 0xe2, 0x86, 0x04, 0x04, 0x08, - 0x02, 0x10, 0x07, 0x12, 0x9c, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x76, 0x6f, 0x79, - 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, - 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x47, 0x65, 0x74, - 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x50, 0x61, - 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x64, - 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x76, 0x6f, - 0x79, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x08, 0xe2, 0x86, 0x04, 0x04, 0x08, 0x02, - 0x10, 0x07, 0x42, 0xf0, 0x01, 0x0a, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x73, 0x12, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x47, + 0x65, 0x74, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x70, + 0x6c, 0x61, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x41, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, + 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, + 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x08, 0xe2, 0x86, 0x04, 0x04, 0x08, 0x02, 0x10, 0x07, + 0x12, 0x9c, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x42, 0x6f, 0x6f, + 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x3a, 0x2e, 0x68, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x76, + 0x6f, 0x79, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x64, 0x61, 0x74, 0x61, - 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x42, 0x0e, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, - 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, - 0x63, 0x2f, 0x70, 0x62, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0xa2, 0x02, 0x03, - 0x48, 0x43, 0x44, 0xaa, 0x02, 0x1a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, - 0xca, 0x02, 0x1a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x5c, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0xe2, 0x02, 0x26, + 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x42, 0x6f, + 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x08, 0xe2, 0x86, 0x04, 0x04, 0x08, 0x02, 0x10, 0x07, 0x42, + 0xf0, 0x01, 0x0a, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, + 0x6e, 0x65, 0x42, 0x0e, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2f, 0x70, + 0x62, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0xa2, 0x02, 0x03, 0x48, 0x43, 0x44, + 0xaa, 0x02, 0x1a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0xca, 0x02, 0x1a, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x5c, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x1c, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, - 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x44, 0x61, 0x74, 0x61, - 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x5c, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0xe2, 0x02, 0x26, 0x48, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x44, 0x61, + 0x74, 0x61, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0xea, 0x02, 0x1c, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, + 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6c, 0x61, + 0x6e, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/proto-public/pbdataplane/dataplane.proto b/proto-public/pbdataplane/dataplane.proto index 244e0e55f7..98a0a750fb 100644 --- a/proto-public/pbdataplane/dataplane.proto +++ b/proto-public/pbdataplane/dataplane.proto @@ -17,6 +17,7 @@ enum DataplaneFeatures { DATAPLANE_FEATURES_WATCH_SERVERS = 1; DATAPLANE_FEATURES_EDGE_CERTIFICATE_MANAGEMENT = 2; DATAPLANE_FEATURES_ENVOY_BOOTSTRAP_CONFIGURATION = 3; + DATAPLANE_FEATURES_FIPS = 4; } message DataplaneFeatureSupport { From 217248ba318a75a1e69732942245582c8856b88a Mon Sep 17 00:00:00 2001 From: Poonam Jadhav Date: Wed, 31 May 2023 13:18:00 -0400 Subject: [PATCH 14/72] feat: expose logs method on container interface (#17526) --- test/integration/consul-container/libs/cluster/agent.go | 2 ++ test/integration/consul-container/libs/cluster/container.go | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/test/integration/consul-container/libs/cluster/agent.go b/test/integration/consul-container/libs/cluster/agent.go index d5a12f481e..b360ee444f 100644 --- a/test/integration/consul-container/libs/cluster/agent.go +++ b/test/integration/consul-container/libs/cluster/agent.go @@ -5,6 +5,7 @@ package cluster import ( "context" + "io" "github.com/testcontainers/testcontainers-go" @@ -22,6 +23,7 @@ type Agent interface { GetAgentName() string GetPartition() string GetPod() testcontainers.Container + Logs(context.Context) (io.ReadCloser, error) ClaimAdminPort() (int, error) GetConfig() Config GetInfo() AgentInfo diff --git a/test/integration/consul-container/libs/cluster/container.go b/test/integration/consul-container/libs/cluster/container.go index 4f9e8227d3..7ed88b0d82 100644 --- a/test/integration/consul-container/libs/cluster/container.go +++ b/test/integration/consul-container/libs/cluster/container.go @@ -68,6 +68,10 @@ func (c *consulContainerNode) GetPod() testcontainers.Container { return c.pod } +func (c *consulContainerNode) Logs(context context.Context) (io.ReadCloser, error) { + return c.container.Logs(context) +} + func (c *consulContainerNode) ClaimAdminPort() (int, error) { if c.nextAdminPortOffset >= MaxEnvoyOnNode { return 0, fmt.Errorf("running out of envoy admin port, max %d, already claimed %d", From da94cbdb25db593c2ad267097770f52c9f423372 Mon Sep 17 00:00:00 2001 From: Dhia Ayachi Date: Wed, 31 May 2023 13:29:59 -0400 Subject: [PATCH 15/72] add changelog (#17528) --- .changelog/4633.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/4633.txt diff --git a/.changelog/4633.txt b/.changelog/4633.txt new file mode 100644 index 0000000000..ffacfccced --- /dev/null +++ b/.changelog/4633.txt @@ -0,0 +1,3 @@ +```release-note:feature +server: **(Enterprise Only)** added server side RPC requests IP based read/write rate-limiter. +``` From b438a07326b49c7e9a5330faad124421b7ef44e5 Mon Sep 17 00:00:00 2001 From: Nathan Coleman Date: Wed, 31 May 2023 14:27:35 -0400 Subject: [PATCH 16/72] Export peering cli (#15654) * Sujata's peering-cli branch * Added error message for connecting to cluster * We can export service to peer * export handling multiple peers * export handles multiple peers * export now can handle multiple services * Export after 1st cleanup * Successful export * Added the namespace option * Add .changelog entry * go mod tidy * Stub unit tests for peering export command * added export in peering.go * Adding export_test * Moved the code to services from peers and cleaned the serviceNamespace * Added support for exporting to partitions * Fixed partition bug * Added unit tests for export command * Add multi-tenancy flags * gofmt * Add some helpful comments * Exclude namespace + partition flags when running OSS * cleaned up partition stuff * Validate required flags differently for OSS vs. ENT * Update success output to include only the requested consumers * cleaned up * fixed broken test * gofmt * Include all flags in OSS build * Remove example previously added to peering command * Move stray import into correct block * Update changelog entry to include support for exporting to a partition * Add required-ness label to consumer-peers flag description * Update command/services/export/export.go Co-authored-by: Dan Stough * Add docs placeholder for new services export command * Moved piece of code to OSS * Break config entry init + update into separate functions * fixed * Vary existing service export comparison for OSS vs. ENT * Move OSS-specific test to export_oss_test.go * Set config entry name based on partition being exported from * Set namespace on added services * Adding namespace * Remove export documentation We will include documentation in a followup PR * Consolidate code from export_oss into export.go * Consolidated export_oss_test.go and export_test.go * Add example of partition export to command synopsis * Allow empty peers flag if partitions flag provided * Add test coverage for -consumer-partitions flag * Update command/services/export/export.go Co-authored-by: Jared Kirschner <85913323+jkirschner-hashicorp@users.noreply.github.com> * Update command/services/export/export.go Co-authored-by: Jared Kirschner <85913323+jkirschner-hashicorp@users.noreply.github.com> * Update changelog entry * Use "cluster peers" to clear up any possible confusion * Update test assertions --------- Co-authored-by: 20sr20 Co-authored-by: Dan Stough Co-authored-by: Jared Kirschner <85913323+jkirschner-hashicorp@users.noreply.github.com> --- .changelog/15654.txt | 3 + command/flags/http.go | 4 + command/registry.go | 4 +- command/services/export/export.go | 260 +++++++++++++++++++++++++ command/services/export/export_test.go | 152 +++++++++++++++ 5 files changed, 422 insertions(+), 1 deletion(-) create mode 100644 .changelog/15654.txt create mode 100644 command/services/export/export.go create mode 100644 command/services/export/export_test.go diff --git a/.changelog/15654.txt b/.changelog/15654.txt new file mode 100644 index 0000000000..169191377b --- /dev/null +++ b/.changelog/15654.txt @@ -0,0 +1,3 @@ +```release-note:feature +cli: Adds new command - `consul services export` - for exporting a service to a peer or partition +``` diff --git a/command/flags/http.go b/command/flags/http.go index 4c3a343927..82e59431ae 100644 --- a/command/flags/http.go +++ b/command/flags/http.go @@ -101,6 +101,10 @@ func (f *HTTPFlags) Datacenter() string { return f.datacenter.String() } +func (f *HTTPFlags) Namespace() string { + return f.namespace.String() +} + func (f *HTTPFlags) Partition() string { return f.partition.String() } diff --git a/command/registry.go b/command/registry.go index 55b9e9f8a1..b370f14bc8 100644 --- a/command/registry.go +++ b/command/registry.go @@ -111,6 +111,7 @@ import ( "github.com/hashicorp/consul/command/rtt" "github.com/hashicorp/consul/command/services" svcsderegister "github.com/hashicorp/consul/command/services/deregister" + svcsexport "github.com/hashicorp/consul/command/services/export" svcsregister "github.com/hashicorp/consul/command/services/register" "github.com/hashicorp/consul/command/snapshot" snapinspect "github.com/hashicorp/consul/command/snapshot/inspect" @@ -121,7 +122,7 @@ import ( tlscacreate "github.com/hashicorp/consul/command/tls/ca/create" tlscert "github.com/hashicorp/consul/command/tls/cert" tlscertcreate "github.com/hashicorp/consul/command/tls/cert/create" - troubleshoot "github.com/hashicorp/consul/command/troubleshoot" + "github.com/hashicorp/consul/command/troubleshoot" troubleshootproxy "github.com/hashicorp/consul/command/troubleshoot/proxy" troubleshootupstreams "github.com/hashicorp/consul/command/troubleshoot/upstreams" "github.com/hashicorp/consul/command/validate" @@ -241,6 +242,7 @@ func RegisteredCommands(ui cli.Ui) map[string]mcli.CommandFactory { entry{"services", func(cli.Ui) (cli.Command, error) { return services.New(), nil }}, entry{"services register", func(ui cli.Ui) (cli.Command, error) { return svcsregister.New(ui), nil }}, entry{"services deregister", func(ui cli.Ui) (cli.Command, error) { return svcsderegister.New(ui), nil }}, + entry{"services export", func(ui cli.Ui) (cli.Command, error) { return svcsexport.New(ui), nil }}, entry{"snapshot", func(cli.Ui) (cli.Command, error) { return snapshot.New(), nil }}, entry{"snapshot inspect", func(ui cli.Ui) (cli.Command, error) { return snapinspect.New(ui), nil }}, entry{"snapshot restore", func(ui cli.Ui) (cli.Command, error) { return snaprestore.New(ui), nil }}, diff --git a/command/services/export/export.go b/command/services/export/export.go new file mode 100644 index 0000000000..637553f93e --- /dev/null +++ b/command/services/export/export.go @@ -0,0 +1,260 @@ +package export + +import ( + "errors" + "flag" + "fmt" + "strings" + + "github.com/mitchellh/cli" + + "github.com/hashicorp/consul/agent" + "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/command/flags" +) + +func New(ui cli.Ui) *cmd { + c := &cmd{UI: ui} + c.init() + return c +} + +type cmd struct { + UI cli.Ui + flags *flag.FlagSet + http *flags.HTTPFlags + help string + + serviceName string + peerNames string + partitionNames string +} + +func (c *cmd) init() { + c.flags = flag.NewFlagSet("", flag.ContinueOnError) + + c.flags.StringVar(&c.serviceName, "name", "", "(Required) Specify the name of the service you want to export.") + c.flags.StringVar(&c.peerNames, "consumer-peers", "", "(Required) A comma-separated list of cluster peers to export the service to. In Consul Enterprise, this flag is optional if -consumer-partitions is specified.") + c.flags.StringVar(&c.partitionNames, "consumer-partitions", "", "(Enterprise only) A comma-separated list of admin partitions within the same datacenter to export the service to. This flag is optional if -consumer-peers is specified.") + + c.http = &flags.HTTPFlags{} + flags.Merge(c.flags, c.http.ClientFlags()) + flags.Merge(c.flags, c.http.MultiTenancyFlags()) + c.help = flags.Usage(help, c.flags) +} + +func (c *cmd) Run(args []string) int { + if err := c.flags.Parse(args); err != nil { + return 1 + } + + if err := c.validateFlags(); err != nil { + c.UI.Error(err.Error()) + return 1 + } + + peerNames, err := c.getPeerNames() + if err != nil { + c.UI.Error(err.Error()) + return 1 + } + + partitionNames, err := c.getPartitionNames() + if err != nil { + c.UI.Error(err.Error()) + return 1 + } + + client, err := c.http.APIClient() + if err != nil { + c.UI.Error(fmt.Sprintf("Error connect to Consul agent: %s", err)) + return 1 + } + + // Name matches partition, so "default" if none specified + cfgName := "default" + if c.http.Partition() != "" { + cfgName = c.http.Partition() + } + + entry, _, err := client.ConfigEntries().Get(api.ExportedServices, cfgName, &api.QueryOptions{Namespace: ""}) + if err != nil && !strings.Contains(err.Error(), agent.ConfigEntryNotFoundErr) { + c.UI.Error(fmt.Sprintf("Error reading config entry %s/%s: %v", "exported-services", "default", err)) + return 1 + } + + var cfg *api.ExportedServicesConfigEntry + if entry == nil { + cfg = c.initializeConfigEntry(cfgName, peerNames, partitionNames) + } else { + existingCfg, ok := entry.(*api.ExportedServicesConfigEntry) + if !ok { + c.UI.Error(fmt.Sprintf("Existing config entry has incorrect type: %t", entry)) + return 1 + } + + cfg = c.updateConfigEntry(existingCfg, peerNames, partitionNames) + } + + ok, _, err := client.ConfigEntries().CAS(cfg, cfg.GetModifyIndex(), nil) + if err != nil { + c.UI.Error(fmt.Sprintf("Error writing config entry: %s", err)) + return 1 + } else if !ok { + c.UI.Error(fmt.Sprintf("Config entry was changed during update. Please try again")) + return 1 + } + + switch { + case len(c.peerNames) > 0 && len(c.partitionNames) > 0: + c.UI.Info(fmt.Sprintf("Successfully exported service %q to cluster peers %q and to partitions %q", c.serviceName, c.peerNames, c.partitionNames)) + case len(c.peerNames) > 0: + c.UI.Info(fmt.Sprintf("Successfully exported service %q to cluster peers %q", c.serviceName, c.peerNames)) + case len(c.partitionNames) > 0: + c.UI.Info(fmt.Sprintf("Successfully exported service %q to partitions %q", c.serviceName, c.partitionNames)) + } + + return 0 +} + +func (c *cmd) validateFlags() error { + if c.serviceName == "" { + return errors.New("Missing the required -name flag") + } + + if c.peerNames == "" && c.partitionNames == "" { + return errors.New("Missing the required -consumer-peers or -consumer-partitions flag") + } + + return nil +} + +func (c *cmd) getPeerNames() ([]string, error) { + var peerNames []string + if c.peerNames != "" { + peerNames = strings.Split(c.peerNames, ",") + for _, peerName := range peerNames { + if peerName == "" { + return nil, fmt.Errorf("Invalid peer %q", peerName) + } + } + } + return peerNames, nil +} + +func (c *cmd) getPartitionNames() ([]string, error) { + var partitionNames []string + if c.partitionNames != "" { + partitionNames = strings.Split(c.partitionNames, ",") + for _, partitionName := range partitionNames { + if partitionName == "" { + return nil, fmt.Errorf("Invalid partition %q", partitionName) + } + } + } + return partitionNames, nil +} + +func (c *cmd) initializeConfigEntry(cfgName string, peerNames, partitionNames []string) *api.ExportedServicesConfigEntry { + return &api.ExportedServicesConfigEntry{ + Name: cfgName, + Services: []api.ExportedService{ + { + Name: c.serviceName, + Namespace: c.http.Namespace(), + Consumers: buildConsumers(peerNames, partitionNames), + }, + }, + } +} + +func (c *cmd) updateConfigEntry(cfg *api.ExportedServicesConfigEntry, peerNames, partitionNames []string) *api.ExportedServicesConfigEntry { + serviceExists := false + + for i, service := range cfg.Services { + if service.Name == c.serviceName && service.Namespace == c.http.Namespace() { + serviceExists = true + + // Add a consumer for each peer where one doesn't already exist + for _, peerName := range peerNames { + peerExists := false + for _, consumer := range service.Consumers { + if consumer.Peer == peerName { + peerExists = true + break + } + } + if !peerExists { + cfg.Services[i].Consumers = append(cfg.Services[i].Consumers, api.ServiceConsumer{Peer: peerName}) + } + } + + // Add a consumer for each partition where one doesn't already exist + for _, partitionName := range partitionNames { + partitionExists := false + + for _, consumer := range service.Consumers { + if consumer.Partition == partitionName { + partitionExists = true + break + } + } + if !partitionExists { + cfg.Services[i].Consumers = append(cfg.Services[i].Consumers, api.ServiceConsumer{Partition: partitionName}) + } + } + } + } + + if !serviceExists { + cfg.Services = append(cfg.Services, api.ExportedService{ + Name: c.serviceName, + Namespace: c.http.Namespace(), + Consumers: buildConsumers(peerNames, partitionNames), + }) + } + + return cfg +} + +func buildConsumers(peerNames []string, partitionNames []string) []api.ServiceConsumer { + var consumers []api.ServiceConsumer + for _, peer := range peerNames { + consumers = append(consumers, api.ServiceConsumer{ + Peer: peer, + }) + } + for _, partition := range partitionNames { + consumers = append(consumers, api.ServiceConsumer{ + Partition: partition, + }) + } + return consumers +} + +//======== + +func (c *cmd) Synopsis() string { + return synopsis +} + +func (c *cmd) Help() string { + return flags.Usage(c.help, nil) +} + +const ( + synopsis = "Export a service from one peer or admin partition to another" + help = ` +Usage: consul services export [options] -name -consumer-peers + + Export a service to a peered cluster. + + $ consul services export -name=web -consumer-peers=other-cluster + + Use the -consumer-partitions flag instead of -consumer-peers to export to a different partition in the same cluster. + + $ consul services export -name=web -consumer-partitions=other-partition + + Additional flags and more advanced use cases are detailed below. +` +) diff --git a/command/services/export/export_test.go b/command/services/export/export_test.go new file mode 100644 index 0000000000..6a2dfa9d67 --- /dev/null +++ b/command/services/export/export_test.go @@ -0,0 +1,152 @@ +package export + +import ( + "strings" + "testing" + + "github.com/mitchellh/cli" + "github.com/stretchr/testify/require" + + "github.com/hashicorp/consul/agent" + "github.com/hashicorp/consul/testrpc" +) + +func TestExportCommand(t *testing.T) { + + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + + t.Run("help output should have no tabs", func(t *testing.T) { + if strings.ContainsRune(New(cli.NewMockUi()).Help(), '\t') { + t.Fatal("help has tabs") + } + }) + + a := agent.NewTestAgent(t, ``) + t.Cleanup(func() { _ = a.Shutdown() }) + testrpc.WaitForTestAgent(t, a.RPC, "dc1") + t.Run("peer or partition is required", func(t *testing.T) { + + ui := cli.NewMockUi() + cmd := New(ui) + + args := []string{ + "-name=testservice", + } + + code := cmd.Run(args) + require.Equal(t, 1, code, "err: %s", ui.ErrorWriter.String()) + require.Contains(t, ui.ErrorWriter.String(), "Missing the required -consumer-peers or -consumer-partitions flag") + }) + t.Run("service name is required", func(t *testing.T) { + + ui := cli.NewMockUi() + cmd := New(ui) + + args := []string{} + + code := cmd.Run(args) + require.Equal(t, 1, code, "err: %s", ui.ErrorWriter.String()) + require.Contains(t, ui.ErrorWriter.String(), "Missing the required -name flag") + }) + + t.Run("valid peer name is required", func(t *testing.T) { + + ui := cli.NewMockUi() + cmd := New(ui) + + args := []string{ + "-name=testservice", + "-consumer-peers=a,", + } + + code := cmd.Run(args) + require.Equal(t, 1, code, "err: %s", ui.ErrorWriter.String()) + require.Contains(t, ui.ErrorWriter.String(), "Invalid peer") + }) + + t.Run("valid partition name is required", func(t *testing.T) { + + ui := cli.NewMockUi() + cmd := New(ui) + + args := []string{ + "-name=testservice", + "-consumer-partitions=a,", + } + + code := cmd.Run(args) + require.Equal(t, 1, code, "err: %s", ui.ErrorWriter.String()) + require.Contains(t, ui.ErrorWriter.String(), "Invalid partition") + }) + + t.Run("initial config entry should be created w/ partitions", func(t *testing.T) { + + ui := cli.NewMockUi() + cmd := New(ui) + + args := []string{ + "-http-addr=" + a.HTTPAddr(), + "-name=testservice", + "-consumer-partitions=a,b", + } + + code := cmd.Run(args) + require.Equal(t, 0, code) + require.Contains(t, ui.OutputWriter.String(), "Successfully exported service") + }) + + t.Run("initial config entry should be created w/ peers", func(t *testing.T) { + + ui := cli.NewMockUi() + cmd := New(ui) + + args := []string{ + "-http-addr=" + a.HTTPAddr(), + "-name=testservice", + "-consumer-peers=a,b", + } + + code := cmd.Run(args) + require.Equal(t, 0, code) + require.Contains(t, ui.OutputWriter.String(), "Successfully exported service") + }) + + t.Run("existing config entry should be updated w/ new peers and partitions", func(t *testing.T) { + + ui := cli.NewMockUi() + + args := []string{ + "-http-addr=" + a.HTTPAddr(), + "-name=testservice", + "-consumer-peers=a,b", + } + + code := New(ui).Run(args) + require.Equal(t, 0, code) + require.Contains(t, ui.OutputWriter.String(), `Successfully exported service "testservice" to cluster peers "a,b"`) + + args = []string{ + "-http-addr=" + a.HTTPAddr(), + "-name=testservice", + "-consumer-peers=c", + } + + code = New(ui).Run(args) + require.Equal(t, 0, code) + require.Contains(t, ui.OutputWriter.String(), `Successfully exported service "testservice" to cluster peers "c"`) + + args = []string{ + "-http-addr=" + a.HTTPAddr(), + "-name=testservice", + "-consumer-partitions=d", + } + + code = New(ui).Run(args) + require.Equal(t, 0, code) + require.Contains(t, ui.OutputWriter.String(), `Successfully exported service "testservice" to partitions "d"`) + }) +} From ba26e188d542bb9b101215112d5f6c3b82bd7c8c Mon Sep 17 00:00:00 2001 From: Derek Menteer <105233703+hashi-derek@users.noreply.github.com> Date: Wed, 31 May 2023 15:40:06 -0500 Subject: [PATCH 17/72] Fix tproxy failover issue with sameness groups (#17533) Sameness groups with default-for-failover enabled did not function properly with tproxy whenever all instances of the service disappeared from the local cluster. This occured, because there were no corresponding resolvers (due to the implicit failover policy) which caused VIPs to be deallocated. This ticket expands upon the VIP allocations so that both service-defaults and service-intentions (without destination wildcards) will ensure that the virtual IP exists. --- agent/consul/fsm/snapshot_test.go | 42 ++++++++++++++++++++-------- agent/consul/state/catalog.go | 15 +++++++--- agent/consul/state/config_entry.go | 41 +++++++++++++++++++++------ agent/consul/state/intention.go | 2 +- agent/consul/state/intention_test.go | 8 ++++-- 5 files changed, 81 insertions(+), 27 deletions(-) diff --git a/agent/consul/fsm/snapshot_test.go b/agent/consul/fsm/snapshot_test.go index a846812be4..a34e1f3e33 100644 --- a/agent/consul/fsm/snapshot_test.go +++ b/agent/consul/fsm/snapshot_test.go @@ -44,6 +44,8 @@ func TestFSM_SnapshotRestore_OSS(t *testing.T) { StorageBackend: storageBackend, }) + fsm.state.SystemMetadataSet(10, &structs.SystemMetadataEntry{Key: structs.SystemMetadataVirtualIPsEnabled, Value: "true"}) + // Add some state node1 := &structs.Node{ ID: "610918a6-464f-fa9b-1a95-03bd6e88ed92", @@ -79,8 +81,14 @@ func TestFSM_SnapshotRestore_OSS(t *testing.T) { Connect: connectConf, }) + psn := structs.PeeredServiceName{ServiceName: structs.NewServiceName("web", nil)} + vip, err := fsm.state.VirtualIPForService(psn) + require.NoError(t, err) + require.Equal(t, vip, "240.0.0.1") + fsm.state.EnsureService(4, "foo", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"primary"}, Address: "127.0.0.1", Port: 5000}) fsm.state.EnsureService(5, "baz", &structs.NodeService{ID: "web", Service: "web", Tags: nil, Address: "127.0.0.2", Port: 80}) + fsm.state.EnsureService(6, "baz", &structs.NodeService{ID: "db", Service: "db", Tags: []string{"secondary"}, Address: "127.0.0.2", Port: 5000}) fsm.state.EnsureCheck(7, &structs.HealthCheck{ Node: "foo", @@ -442,6 +450,10 @@ func TestFSM_SnapshotRestore_OSS(t *testing.T) { }, } require.NoError(t, fsm.state.EnsureConfigEntry(26, serviceIxn)) + psn = structs.PeeredServiceName{ServiceName: structs.NewServiceName("foo", nil)} + vip, err = fsm.state.VirtualIPForService(psn) + require.NoError(t, err) + require.Equal(t, vip, "240.0.0.2") // mesh config entry meshConfig := &structs.MeshConfigEntry{ @@ -465,10 +477,10 @@ func TestFSM_SnapshotRestore_OSS(t *testing.T) { Port: 8000, Connect: connectConf, }) - psn := structs.PeeredServiceName{ServiceName: structs.NewServiceName("frontend", nil)} - vip, err := fsm.state.VirtualIPForService(psn) + psn = structs.PeeredServiceName{ServiceName: structs.NewServiceName("frontend", nil)} + vip, err = fsm.state.VirtualIPForService(psn) require.NoError(t, err) - require.Equal(t, vip, "240.0.0.1") + require.Equal(t, vip, "240.0.0.3") fsm.state.EnsureService(30, "foo", &structs.NodeService{ ID: "backend", @@ -480,7 +492,7 @@ func TestFSM_SnapshotRestore_OSS(t *testing.T) { psn = structs.PeeredServiceName{ServiceName: structs.NewServiceName("backend", nil)} vip, err = fsm.state.VirtualIPForService(psn) require.NoError(t, err) - require.Equal(t, vip, "240.0.0.2") + require.Equal(t, vip, "240.0.0.4") _, serviceNames, err := fsm.state.ServiceNamesOfKind(nil, structs.ServiceKindTypical) require.NoError(t, err) @@ -534,15 +546,15 @@ func TestFSM_SnapshotRestore_OSS(t *testing.T) { }, })) - // Add a service-resolver entry to get a virtual IP for service foo + // Add a service-resolver entry to get a virtual IP for service goo resolverEntry := &structs.ServiceResolverConfigEntry{ Kind: structs.ServiceResolver, - Name: "foo", + Name: "goo", } require.NoError(t, fsm.state.EnsureConfigEntry(34, resolverEntry)) - vip, err = fsm.state.VirtualIPForService(structs.PeeredServiceName{ServiceName: structs.NewServiceName("foo", nil)}) + vip, err = fsm.state.VirtualIPForService(structs.PeeredServiceName{ServiceName: structs.NewServiceName("goo", nil)}) require.NoError(t, err) - require.Equal(t, vip, "240.0.0.3") + require.Equal(t, vip, "240.0.0.5") // Resources resource, err := storageBackend.WriteCAS(context.Background(), &pbresource.Resource{ @@ -665,18 +677,26 @@ func TestFSM_SnapshotRestore_OSS(t *testing.T) { require.Equal(t, uint64(25), checks[0].ModifyIndex) // Verify virtual IPs are consistent. - psn = structs.PeeredServiceName{ServiceName: structs.NewServiceName("frontend", nil)} + psn = structs.PeeredServiceName{ServiceName: structs.NewServiceName("web", nil)} vip, err = fsm2.state.VirtualIPForService(psn) require.NoError(t, err) require.Equal(t, vip, "240.0.0.1") - psn = structs.PeeredServiceName{ServiceName: structs.NewServiceName("backend", nil)} + psn = structs.PeeredServiceName{ServiceName: structs.NewServiceName("foo", nil)} vip, err = fsm2.state.VirtualIPForService(psn) require.NoError(t, err) require.Equal(t, vip, "240.0.0.2") - psn = structs.PeeredServiceName{ServiceName: structs.NewServiceName("foo", nil)} + psn = structs.PeeredServiceName{ServiceName: structs.NewServiceName("frontend", nil)} vip, err = fsm2.state.VirtualIPForService(psn) require.NoError(t, err) require.Equal(t, vip, "240.0.0.3") + psn = structs.PeeredServiceName{ServiceName: structs.NewServiceName("backend", nil)} + vip, err = fsm2.state.VirtualIPForService(psn) + require.NoError(t, err) + require.Equal(t, vip, "240.0.0.4") + psn = structs.PeeredServiceName{ServiceName: structs.NewServiceName("goo", nil)} + vip, err = fsm2.state.VirtualIPForService(psn) + require.NoError(t, err) + require.Equal(t, vip, "240.0.0.5") // Verify key is set _, d, err := fsm2.state.KVSGet(nil, "/test", nil) diff --git a/agent/consul/state/catalog.go b/agent/consul/state/catalog.go index 083c3af801..74efc32295 100644 --- a/agent/consul/state/catalog.go +++ b/agent/consul/state/catalog.go @@ -915,7 +915,7 @@ func ensureServiceTxn(tx WriteTxn, idx uint64, node string, preserveIndexes bool if err != nil { return err } - if supported { + if supported && sn.Name != "" { psn := structs.PeeredServiceName{Peer: svc.PeerName, ServiceName: sn} vip, err := assignServiceVirtualIP(tx, idx, psn) if err != nil { @@ -2110,7 +2110,13 @@ func freeServiceVirtualIP( // Don't deregister the virtual IP if at least one resolver/router/splitter config entry still // references this service. - configEntryVIPKinds := []string{structs.ServiceResolver, structs.ServiceRouter, structs.ServiceSplitter} + configEntryVIPKinds := []string{ + structs.ServiceResolver, + structs.ServiceRouter, + structs.ServiceSplitter, + structs.ServiceDefaults, + structs.ServiceIntentions, + } for _, kind := range configEntryVIPKinds { _, entry, err := configEntryTxn(tx, nil, kind, psn.ServiceName.Name, &psn.ServiceName.EnterpriseMeta) if err != nil { @@ -3051,14 +3057,15 @@ func (s *Store) ServiceVirtualIPs() (uint64, []ServiceVirtualIP, error) { tx := s.db.Txn(false) defer tx.Abort() - return servicesVirtualIPsTxn(tx) + return servicesVirtualIPsTxn(tx, nil) } -func servicesVirtualIPsTxn(tx ReadTxn) (uint64, []ServiceVirtualIP, error) { +func servicesVirtualIPsTxn(tx ReadTxn, ws memdb.WatchSet) (uint64, []ServiceVirtualIP, error) { iter, err := tx.Get(tableServiceVirtualIPs, indexID) if err != nil { return 0, nil, err } + ws.Add(iter.WatchCh()) var vips []ServiceVirtualIP for raw := iter.Next(); raw != nil; raw = iter.Next() { diff --git a/agent/consul/state/config_entry.go b/agent/consul/state/config_entry.go index fd1d9cbccd..340a53f119 100644 --- a/agent/consul/state/config_entry.go +++ b/agent/consul/state/config_entry.go @@ -6,6 +6,7 @@ package state import ( "errors" "fmt" + "strings" memdb "github.com/hashicorp/go-memdb" "github.com/hashicorp/go-multierror" @@ -465,9 +466,8 @@ func deleteConfigEntryTxn(tx WriteTxn, idx uint64, kind, name string, entMeta *a return fmt.Errorf("failed updating index: %s", err) } - // If this is a resolver/router/splitter, attempt to delete the virtual IP associated - // with this service. - if kind == structs.ServiceResolver || kind == structs.ServiceRouter || kind == structs.ServiceSplitter { + // Attempt to delete the virtual IP associated with this service, if applicable. + if configEntryHasVirtualIP(c) { psn := structs.PeeredServiceName{ServiceName: sn} if err := freeServiceVirtualIP(tx, idx, psn, nil); err != nil { return fmt.Errorf("failed to clean up virtual IP for %q: %v", psn.String(), err) @@ -519,11 +519,14 @@ func insertConfigEntryWithTxn(tx WriteTxn, idx uint64, conf structs.ConfigEntry) if err != nil { return err } - case structs.ServiceResolver: - fallthrough - case structs.ServiceRouter: - fallthrough - case structs.ServiceSplitter: + } + + // Assign virtual-ips, if needed + supported, err := virtualIPsSupported(tx, nil) + if err != nil { + return err + } + if supported && configEntryHasVirtualIP(conf) { psn := structs.PeeredServiceName{ServiceName: structs.NewServiceName(conf.GetName(), conf.GetEnterpriseMeta())} if _, err := assignServiceVirtualIP(tx, idx, psn); err != nil { return err @@ -541,6 +544,28 @@ func insertConfigEntryWithTxn(tx WriteTxn, idx uint64, conf structs.ConfigEntry) return nil } +func configEntryHasVirtualIP(c structs.ConfigEntry) bool { + if c == nil || c.GetName() == "" { + return false + } + switch c.GetKind() { + case structs.ServiceRouter: + return true + case structs.ServiceResolver: + return true + case structs.ServiceSplitter: + return true + case structs.ServiceDefaults: + return true + case structs.ServiceIntentions: + entMeta := c.GetEnterpriseMeta() + return !strings.Contains(c.GetName(), "*") && + !strings.Contains(entMeta.NamespaceOrDefault(), "*") && + !strings.Contains(entMeta.PartitionOrDefault(), "*") + } + return false +} + // validateProposedConfigEntryInGraph can be used to verify graph integrity for // a proposed graph create/update/delete. // diff --git a/agent/consul/state/intention.go b/agent/consul/state/intention.go index 212b7ba033..4341590e4e 100644 --- a/agent/consul/state/intention.go +++ b/agent/consul/state/intention.go @@ -1106,7 +1106,7 @@ func (s *Store) intentionTopologyTxn( // We only need to do this for upstreams currently, so that tproxy can find which discovery chains should be // contacted for failover scenarios. Virtual services technically don't need to be considered as downstreams, // because they will take on the identity of the calling service, rather than the chain itself. - vipIndex, vipServices, err := servicesVirtualIPsTxn(tx) + vipIndex, vipServices, err := servicesVirtualIPsTxn(tx, ws) if err != nil { return index, nil, fmt.Errorf("failed to list service virtual IPs: %v", err) } diff --git a/agent/consul/state/intention_test.go b/agent/consul/state/intention_test.go index 34343b145a..3545527b79 100644 --- a/agent/consul/state/intention_test.go +++ b/agent/consul/state/intention_test.go @@ -2097,6 +2097,7 @@ func disableLegacyIntentions(s *Store) error { func testConfigStateStore(t *testing.T) *Store { s := testStateStore(t) + s.SystemMetadataSet(5, &structs.SystemMetadataEntry{Key: structs.SystemMetadataVirtualIPsEnabled, Value: "true"}) disableLegacyIntentions(s) return s } @@ -2651,6 +2652,7 @@ func TestStore_IntentionTopology_Destination(t *testing.T) { func TestStore_IntentionTopology_Watches(t *testing.T) { s := testConfigStateStore(t) + s.SystemMetadataSet(10, &structs.SystemMetadataEntry{Key: structs.SystemMetadataVirtualIPsEnabled, Value: "true"}) var i uint64 = 1 require.NoError(t, s.EnsureNode(i, &structs.Node{ @@ -2687,7 +2689,8 @@ func TestStore_IntentionTopology_Watches(t *testing.T) { index, got, err = s.IntentionTopology(ws, target, false, acl.Deny, structs.IntentionTargetService) require.NoError(t, err) require.Equal(t, uint64(2), index) - require.Empty(t, got) + // Because API is a virtual service, it is included in this output. + require.Equal(t, structs.ServiceList{structs.NewServiceName("api", nil)}, got) // Watch should not fire after unrelated intention changes require.NoError(t, s.EnsureConfigEntry(i, &structs.ServiceIntentionsConfigEntry{ @@ -2701,7 +2704,6 @@ func TestStore_IntentionTopology_Watches(t *testing.T) { }, })) i++ - // TODO(freddy) Why is this firing? // require.False(t, watchFired(ws)) @@ -2709,7 +2711,7 @@ func TestStore_IntentionTopology_Watches(t *testing.T) { index, got, err = s.IntentionTopology(ws, target, false, acl.Deny, structs.IntentionTargetService) require.NoError(t, err) require.Equal(t, uint64(3), index) - require.Empty(t, got) + require.Equal(t, structs.ServiceList{structs.NewServiceName("api", nil)}, got) // Watch should fire after service list changes require.NoError(t, s.EnsureService(i, "foo", &structs.NodeService{ From ca12ce926b76f0faa894b5bbd9e70a2ce28f59fc Mon Sep 17 00:00:00 2001 From: Andrew Stucki Date: Wed, 31 May 2023 16:58:40 -0400 Subject: [PATCH 18/72] [API Gateway] Fix use of virtual resolvers in HTTPRoutes (#17055) * [API Gateway] Fix use of virtual resolvers in routes * Add changelog entry --- .changelog/17055.txt | 3 + agent/consul/discoverychain/gateway.go | 7 ++ agent/consul/discoverychain/gateway_test.go | 112 ++++++++++++++++++++ 3 files changed, 122 insertions(+) create mode 100644 .changelog/17055.txt diff --git a/.changelog/17055.txt b/.changelog/17055.txt new file mode 100644 index 0000000000..9300c41121 --- /dev/null +++ b/.changelog/17055.txt @@ -0,0 +1,3 @@ +```release-note:bug +gateways: Fix an bug where targeting a virtual service defined by a service-resolver was broken for HTTPRoutes. +``` diff --git a/agent/consul/discoverychain/gateway.go b/agent/consul/discoverychain/gateway.go index 8c13bb59a8..e43e4b631f 100644 --- a/agent/consul/discoverychain/gateway.go +++ b/agent/consul/discoverychain/gateway.go @@ -249,6 +249,13 @@ func targetForResolverNode(nodeName string, chains []*structs.CompiledDiscoveryC splitterName := splitterPrefix + strings.TrimPrefix(nodeName, resolverPrefix) for _, c := range chains { + targetChainPrefix := resolverPrefix + c.ServiceName + "." + if strings.HasPrefix(nodeName, targetChainPrefix) && len(c.Nodes) == 1 { + // we have a virtual resolver that just maps to another resolver, return + // the given node name + return c.StartNode + } + for name, node := range c.Nodes { if node.IsSplitter() && strings.HasPrefix(splitterName, name) { return name diff --git a/agent/consul/discoverychain/gateway_test.go b/agent/consul/discoverychain/gateway_test.go index a98aaf0555..42bbed65eb 100644 --- a/agent/consul/discoverychain/gateway_test.go +++ b/agent/consul/discoverychain/gateway_test.go @@ -599,6 +599,118 @@ func TestGatewayChainSynthesizer_Synthesize(t *testing.T) { }, }}, }, + "HTTPRoute with virtual resolver": { + synthesizer: NewGatewayChainSynthesizer("dc1", "domain", "suffix", &structs.APIGatewayConfigEntry{ + Kind: structs.APIGateway, + Name: "gateway", + }), + httpRoutes: []*structs.HTTPRouteConfigEntry{ + { + Kind: structs.HTTPRoute, + Name: "http-route", + Rules: []structs.HTTPRouteRule{{ + Services: []structs.HTTPService{{ + Name: "foo", + }}, + }}, + }, + }, + chain: &structs.CompiledDiscoveryChain{ + ServiceName: "foo", + Namespace: "default", + Datacenter: "dc1", + StartNode: "resolver:foo-2.default.default.dc2", + Nodes: map[string]*structs.DiscoveryGraphNode{ + "resolver:foo-2.default.default.dc2": { + Type: "resolver", + Name: "foo-2.default.default.dc2", + Resolver: &structs.DiscoveryResolver{ + Target: "foo-2.default.default.dc2", + Default: true, + ConnectTimeout: 5000000000, + }, + }, + }, + }, + extra: []*structs.CompiledDiscoveryChain{}, + expectedIngressServices: []structs.IngressService{{ + Name: "gateway-suffix-9b9265b", + Hosts: []string{"*"}, + }}, + expectedDiscoveryChains: []*structs.CompiledDiscoveryChain{{ + ServiceName: "gateway-suffix-9b9265b", + Partition: "default", + Namespace: "default", + Datacenter: "dc1", + Protocol: "http", + StartNode: "router:gateway-suffix-9b9265b.default.default", + Nodes: map[string]*structs.DiscoveryGraphNode{ + "router:gateway-suffix-9b9265b.default.default": { + Type: "router", + Name: "gateway-suffix-9b9265b.default.default", + Routes: []*structs.DiscoveryRoute{{ + Definition: &structs.ServiceRoute{ + Match: &structs.ServiceRouteMatch{ + HTTP: &structs.ServiceRouteHTTPMatch{ + PathPrefix: "/", + }, + }, + Destination: &structs.ServiceRouteDestination{ + Service: "foo", + Partition: "default", + Namespace: "default", + RequestHeaders: &structs.HTTPHeaderModifiers{ + Add: make(map[string]string), + Set: make(map[string]string), + }, + }, + }, + NextNode: "resolver:foo-2.default.default.dc2", + }}, + }, + "resolver:foo.default.default.dc1": { + Type: "resolver", + Name: "foo.default.default.dc1", + Resolver: &structs.DiscoveryResolver{ + Target: "foo.default.default.dc1", + Default: true, + ConnectTimeout: 5000000000, + }, + }, + "resolver:foo-2.default.default.dc2": { + Type: "resolver", + Name: "foo-2.default.default.dc2", + Resolver: &structs.DiscoveryResolver{ + Target: "foo-2.default.default.dc2", + Default: true, + ConnectTimeout: 5000000000, + }, + }, + }, + Targets: map[string]*structs.DiscoveryTarget{ + "gateway-suffix-9b9265b.default.default.dc1": { + ID: "gateway-suffix-9b9265b.default.default.dc1", + Service: "gateway-suffix-9b9265b", + Datacenter: "dc1", + Partition: "default", + Namespace: "default", + ConnectTimeout: 5000000000, + SNI: "gateway-suffix-9b9265b.default.dc1.internal.domain", + Name: "gateway-suffix-9b9265b.default.dc1.internal.domain", + }, + "foo.default.default.dc1": { + ID: "foo.default.default.dc1", + Service: "foo", + Datacenter: "dc1", + Partition: "default", + Namespace: "default", + ConnectTimeout: 5000000000, + SNI: "foo.default.dc1.internal.domain", + Name: "foo.default.dc1.internal.domain", + }, + }, + }}, + }, } for name, tc := range cases { From ad03a5d0f22edfe31c0b40514c6cb481448b6306 Mon Sep 17 00:00:00 2001 From: Michael Zalimeni Date: Thu, 1 Jun 2023 13:04:39 -0400 Subject: [PATCH 19/72] Avoid panic applying TProxy Envoy extensions (#17537) When UpstreamEnvoyExtender was introduced, some code was left duplicated between it and BasicEnvoyExtender. One path in that code panics when a TProxy listener patch is attempted due to no upstream data in RuntimeConfig matching the local service (which would only happen in rare cases). Instead, we can remove the special handling of upstream VIPs from BasicEnvoyExtender entirely, greatly simplifying the listener filter patch code and avoiding the panic. UpstreamEnvoyExtender, which needs this code to function, is modified to ensure a panic does not occur. This also fixes a second regression in which the Lua extension was not applied to TProxy outbound listeners. --- agent/proxycfg/testing_tproxy.go | 5 +- agent/xds/delta_envoy_extender_oss_test.go | 7 + agent/xds/resources_test.go | 6 +- ...es-to-local-upstreams-tproxy.latest.golden | 315 ++++++++++++++++ ...es-to-local-upstreams-tproxy.latest.golden | 163 +++++++++ ...es-to-local-upstreams-tproxy.latest.golden | 339 ++++++++++++++++++ ...es-to-local-upstreams-tproxy.latest.golden | 85 +++++ .../extensioncommon/basic_envoy_extender.go | 66 +--- .../upstream_envoy_extender.go | 6 +- 9 files changed, 928 insertions(+), 64 deletions(-) create mode 100644 agent/xds/testdata/builtin_extension/clusters/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/endpoints/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/listeners/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/routes/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden diff --git a/agent/proxycfg/testing_tproxy.go b/agent/proxycfg/testing_tproxy.go index e1ec75724f..52bbf2f5ec 100644 --- a/agent/proxycfg/testing_tproxy.go +++ b/agent/proxycfg/testing_tproxy.go @@ -728,7 +728,7 @@ func TestConfigSnapshotTransparentProxyDestination(t testing.T) *ConfigSnapshot }) } -func TestConfigSnapshotTransparentProxyDestinationHTTP(t testing.T) *ConfigSnapshot { +func TestConfigSnapshotTransparentProxyDestinationHTTP(t testing.T, nsFn func(ns *structs.NodeService)) *ConfigSnapshot { // DiscoveryChain without an UpstreamConfig should yield a // filter chain when in transparent proxy mode var ( @@ -773,6 +773,9 @@ func TestConfigSnapshotTransparentProxyDestinationHTTP(t testing.T) *ConfigSnaps }, } return TestConfigSnapshot(t, func(ns *structs.NodeService) { + if nsFn != nil { + nsFn(ns) + } ns.Proxy.Mode = structs.ProxyModeTransparent }, []UpdateEvent{ { diff --git a/agent/xds/delta_envoy_extender_oss_test.go b/agent/xds/delta_envoy_extender_oss_test.go index ad7a67f7ee..dc1521edbe 100644 --- a/agent/xds/delta_envoy_extender_oss_test.go +++ b/agent/xds/delta_envoy_extender_oss_test.go @@ -508,6 +508,13 @@ end`, return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", false, makeLuaNsFunc(false), nil) }, }, + { + name: "lua-outbound-applies-to-local-upstreams-tproxy", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + // upstreams need to be http in order for lua to be applied to listeners. + return proxycfg.TestConfigSnapshotTransparentProxyDestinationHTTP(t, makeLuaNsFunc(false)) + }, + }, { name: "lua-connect-proxy-with-terminating-gateway-upstream", create: func(t testinf.T) *proxycfg.ConfigSnapshot { diff --git a/agent/xds/resources_test.go b/agent/xds/resources_test.go index 9e878e02c9..4687c4a7d6 100644 --- a/agent/xds/resources_test.go +++ b/agent/xds/resources_test.go @@ -203,8 +203,10 @@ func getConnectProxyTransparentProxyGoldenTestCases() []goldenTestCase { create: proxycfg.TestConfigSnapshotTransparentProxyDestination, }, { - name: "transparent-proxy-destination-http", - create: proxycfg.TestConfigSnapshotTransparentProxyDestinationHTTP, + name: "transparent-proxy-destination-http", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + return proxycfg.TestConfigSnapshotTransparentProxyDestinationHTTP(t, nil) + }, }, { name: "transparent-proxy-terminating-gateway-destinations-only", diff --git a/agent/xds/testdata/builtin_extension/clusters/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden b/agent/xds/testdata/builtin_extension/clusters/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden new file mode 100644 index 0000000000..3938673d58 --- /dev/null +++ b/agent/xds/testdata/builtin_extension/clusters/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden @@ -0,0 +1,315 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "type": "EDS", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "connectTimeout": "5s", + "circuitBreakers": {}, + "outlierDetection": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + }, + "matchSubjectAltNames": [ + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + } + ] + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "destination.192-168-2-1.kafka.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "altStatName": "destination.192-168-2-1.kafka.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "type": "EDS", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "connectTimeout": "5s", + "outlierDetection": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + }, + "matchSubjectAltNames": [ + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/kafka" + } + ] + } + }, + "sni": "destination.192-168-2-1.kafka.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "destination.192-168-2-2.kafka2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "altStatName": "destination.192-168-2-2.kafka2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "type": "EDS", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "connectTimeout": "5s", + "outlierDetection": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + }, + "matchSubjectAltNames": [ + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/kafka2" + } + ] + } + }, + "sni": "destination.192-168-2-2.kafka2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "destination.192-168-2-3.kafka2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "altStatName": "destination.192-168-2-3.kafka2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "type": "EDS", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "connectTimeout": "5s", + "outlierDetection": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + }, + "matchSubjectAltNames": [ + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/kafka2" + } + ] + } + }, + "sni": "destination.192-168-2-3.kafka2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "destination.www-google-com.google.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "altStatName": "destination.www-google-com.google.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "type": "EDS", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "connectTimeout": "5s", + "outlierDetection": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + }, + "matchSubjectAltNames": [ + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/google" + } + ] + } + }, + "sni": "destination.www-google-com.google.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "type": "EDS", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "connectTimeout": "5s", + "circuitBreakers": {}, + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + }, + "matchSubjectAltNames": [ + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + } + ] + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "local_app", + "type": "STATIC", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + } + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/endpoints/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden b/agent/xds/testdata/builtin_extension/endpoints/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden new file mode 100644 index 0000000000..284d7722a6 --- /dev/null +++ b/agent/xds/testdata/builtin_extension/endpoints/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden @@ -0,0 +1,163 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "destination.192-168-2-1.kafka.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.168.0.1", + "portValue": 8443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "destination.192-168-2-2.kafka2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.168.0.1", + "portValue": 8443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "destination.192-168-2-3.kafka2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.168.0.1", + "portValue": 8443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "destination.www-google-com.google.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "172.168.0.1", + "portValue": 8443 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/listeners/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden b/agent/xds/testdata/builtin_extension/listeners/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden new file mode 100644 index 0000000000..9cf14135f1 --- /dev/null +++ b/agent/xds/testdata/builtin_extension/listeners/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden @@ -0,0 +1,339 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "db:127.0.0.1:9191", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "statPrefix": "upstream.db.default.default.dc1", + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ], + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "outbound_listener:127.0.0.1:15001", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 15001 + } + }, + "filterChains": [ + { + "filterChainMatch": { + "destinationPort": 443 + }, + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "statPrefix": "upstream.destination.443.~http.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "destination.443.~http.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + }, + "httpFilters": [ + { + "name": "envoy.filters.http.lua", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", + "inlineCode": "\nfunction envoy_on_request(request_handle)\n request_handle:headers():add(\"test\", \"test\")\nend" + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "tracing": { + "randomSampling": {} + } + } + } + ] + }, + { + "filterChainMatch": { + "destinationPort": 9093 + }, + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "statPrefix": "upstream.destination.9093.~http.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "rds": { + "configSource": { + "ads": {}, + "resourceApiVersion": "V3" + }, + "routeConfigName": "destination.9093.~http.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + }, + "httpFilters": [ + { + "name": "envoy.filters.http.lua", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua", + "inlineCode": "\nfunction envoy_on_request(request_handle)\n request_handle:headers():add(\"test\", \"test\")\nend" + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "tracing": { + "randomSampling": {} + } + } + } + ] + } + ], + "listenerFilters": [ + { + "name": "envoy.filters.listener.original_dst", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.listener.original_dst.v3.OriginalDst" + } + }, + { + "name": "envoy.filters.listener.http_inspector", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.listener.http_inspector.v3.HttpInspector" + } + } + ], + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "statPrefix": "upstream.prepared_query_geo-cache", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ], + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "public_listener:0.0.0.0:9999", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "statPrefix": "public_listener", + "routeConfig": { + "name": "public_listener", + "virtualHosts": [ + { + "name": "public_listener", + "domains": [ + "*" + ], + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "local_app" + } + } + ] + } + ] + }, + "httpFilters": [ + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": {} + } + }, + { + "name": "envoy.filters.http.header_to_metadata", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.header_to_metadata.v3.Config", + "requestRules": [ + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "metadataNamespace": "consul", + "key": "trust-domain", + "regexValueRewrite": { + "pattern": { + "googleRe2": {}, + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\1" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "metadataNamespace": "consul", + "key": "partition", + "regexValueRewrite": { + "pattern": { + "googleRe2": {}, + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\2" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "metadataNamespace": "consul", + "key": "namespace", + "regexValueRewrite": { + "pattern": { + "googleRe2": {}, + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\3" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "metadataNamespace": "consul", + "key": "datacenter", + "regexValueRewrite": { + "pattern": { + "googleRe2": {}, + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\4" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "metadataNamespace": "consul", + "key": "service", + "regexValueRewrite": { + "pattern": { + "googleRe2": {}, + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\5" + } + } + } + ] + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "tracing": { + "randomSampling": {} + }, + "forwardClientCertDetails": "APPEND_FORWARD", + "setCurrentClientCertDetails": { + "subject": true, + "cert": true, + "chain": true, + "dns": true, + "uri": true + } + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + }, + "alpnProtocols": [ + "http/1.1" + ] + }, + "requireClientCertificate": true + } + } + } + ], + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/routes/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden b/agent/xds/testdata/builtin_extension/routes/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden new file mode 100644 index 0000000000..173aa56476 --- /dev/null +++ b/agent/xds/testdata/builtin_extension/routes/lua-outbound-applies-to-local-upstreams-tproxy.latest.golden @@ -0,0 +1,85 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "destination.443.~http.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "virtualHosts": [ + { + "name": "destination.www-google-com.google.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "domains": [ + "www.google.com" + ], + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "destination.www-google-com.google.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ], + "validateClusters": true + }, + { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "destination.9093.~http.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "virtualHosts": [ + { + "name": "destination.192-168-2-3.kafka2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "domains": [ + "192.168.2.3" + ], + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "destination.192-168-2-3.kafka2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + }, + { + "name": "destination.192-168-2-2.kafka2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "domains": [ + "192.168.2.2" + ], + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "destination.192-168-2-2.kafka2.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + }, + { + "name": "destination.192-168-2-1.kafka.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "domains": [ + "192.168.2.1" + ], + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "destination.192-168-2-1.kafka.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ], + "validateClusters": true + } + ], + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "nonce": "00000001" +} \ No newline at end of file diff --git a/envoyextensions/extensioncommon/basic_envoy_extender.go b/envoyextensions/extensioncommon/basic_envoy_extender.go index 53a44b0aa2..eee8cc32fb 100644 --- a/envoyextensions/extensioncommon/basic_envoy_extender.go +++ b/envoyextensions/extensioncommon/basic_envoy_extender.go @@ -275,7 +275,7 @@ func (b *BasicEnvoyExtender) patchListeners(config *RuntimeConfig, listeners Lis patchedListener = listener } - if patchedListener, err = b.patchListenerFilterChains(config, patchedListener, nameOrSNI); err == nil { + if patchedListener, err = b.patchSupportedListenerFilterChains(config, patchedListener, nameOrSNI); err == nil { patchedListeners[nameOrSNI] = patchedListener } else { resultErr = multierror.Append(resultErr, err) @@ -285,76 +285,22 @@ func (b *BasicEnvoyExtender) patchListeners(config *RuntimeConfig, listeners Lis return patchedListeners, resultErr } -func (b *BasicEnvoyExtender) patchListenerFilterChains(config *RuntimeConfig, l *envoy_listener_v3.Listener, nameOrSNI string) (*envoy_listener_v3.Listener, error) { +func (b *BasicEnvoyExtender) patchSupportedListenerFilterChains(config *RuntimeConfig, l *envoy_listener_v3.Listener, nameOrSNI string) (*envoy_listener_v3.Listener, error) { switch config.Kind { - case api.ServiceKindTerminatingGateway: - return b.patchTerminatingGatewayListenerFilterChains(config, l, nameOrSNI) - case api.ServiceKindConnectProxy: - return b.patchConnectProxyListenerFilterChains(config, l, nameOrSNI) + case api.ServiceKindTerminatingGateway, api.ServiceKindConnectProxy: + return b.patchListenerFilterChains(config, l, nameOrSNI) } return l, nil } -func (b *BasicEnvoyExtender) patchTerminatingGatewayListenerFilterChains(config *RuntimeConfig, l *envoy_listener_v3.Listener, nameOrSNI string) (*envoy_listener_v3.Listener, error) { - var resultErr error - for idx, filterChain := range l.FilterChains { - if patchedFilterChain, err := b.patchFilterChain(config, filterChain, l); err == nil { - l.FilterChains[idx] = patchedFilterChain - } else { - resultErr = multierror.Append(resultErr, fmt.Errorf("error patching filter chain of terminating gateway listener %q: %w", nameOrSNI, err)) - } - } - - return l, resultErr -} - -func (b *BasicEnvoyExtender) patchConnectProxyListenerFilterChains(config *RuntimeConfig, l *envoy_listener_v3.Listener, nameOrSNI string) (*envoy_listener_v3.Listener, error) { - if IsOutboundTProxyListener(l) { - patchedListener, err := b.patchTProxyListenerFilterChains(config, l) - if err == nil { - return patchedListener, nil - } else { - return l, fmt.Errorf("error patching filter chain of TProxy listener %q: %w", nameOrSNI, err) - } - } else { - - patchedListener, err := b.patchNonTProxyConnectProxyListenerFilterChains(config, l) - if err == nil { - return patchedListener, nil - } else { - return l, fmt.Errorf("error patching filter chain of connect proxy listener %q: %w", nameOrSNI, err) - } - } -} - -func (b *BasicEnvoyExtender) patchNonTProxyConnectProxyListenerFilterChains(config *RuntimeConfig, l *envoy_listener_v3.Listener) (*envoy_listener_v3.Listener, error) { - var resultErr error - - for idx, filterChain := range l.FilterChains { - if patchedFilterChain, err := b.patchFilterChain(config, filterChain, l); err == nil { - l.FilterChains[idx] = patchedFilterChain - } else { - resultErr = multierror.Append(resultErr, fmt.Errorf("error patching filter chain: %w", err)) - } - } - return l, resultErr -} - -func (b *BasicEnvoyExtender) patchTProxyListenerFilterChains(config *RuntimeConfig, l *envoy_listener_v3.Listener) (*envoy_listener_v3.Listener, error) { +func (b *BasicEnvoyExtender) patchListenerFilterChains(config *RuntimeConfig, l *envoy_listener_v3.Listener, nameOrSNI string) (*envoy_listener_v3.Listener, error) { var resultErr error - vip := config.Upstreams[config.ServiceName].VIP - for idx, filterChain := range l.FilterChains { - match := filterChainTProxyMatch(vip, filterChain) - if !match { - continue - } - if patchedFilterChain, err := b.patchFilterChain(config, filterChain, l); err == nil { l.FilterChains[idx] = patchedFilterChain } else { - resultErr = multierror.Append(resultErr, fmt.Errorf("error patching filter chain for %q: %w", vip, err)) + resultErr = multierror.Append(resultErr, fmt.Errorf("error patching listener filter chain %q: %w", nameOrSNI, err)) } } diff --git a/envoyextensions/extensioncommon/upstream_envoy_extender.go b/envoyextensions/extensioncommon/upstream_envoy_extender.go index d3ca2faf6a..0df0d0049d 100644 --- a/envoyextensions/extensioncommon/upstream_envoy_extender.go +++ b/envoyextensions/extensioncommon/upstream_envoy_extender.go @@ -214,7 +214,11 @@ func (ext *UpstreamEnvoyExtender) patchTProxyListener(config *RuntimeConfig, l * var resultErr error patched := false - vip := config.Upstreams[config.ServiceName].VIP + upstream := config.Upstreams[config.ServiceName] + if upstream == nil { + return l, false, nil + } + vip := upstream.VIP for _, filterChain := range l.FilterChains { var filters []*envoy_listener_v3.Filter From a043981cc6215e7a0ab21cbf6ca5b6053100a591 Mon Sep 17 00:00:00 2001 From: Dan Stough Date: Thu, 1 Jun 2023 13:10:41 -0400 Subject: [PATCH 20/72] =?UTF-8?q?Revert=20"fix(connect=20envoy):=20set=20i?= =?UTF-8?q?nitial=5Ffetch=5Ftimeout=20to=20wait=20for=20initial=20xDS?= =?UTF-8?q?=E2=80=A6=20(#17317)"=20(#17540)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit be7d2a4d842a8cbab7ce6161e88807a1f0a946b0. --- .changelog/17317.txt | 3 --- command/connect/envoy/bootstrap_tpl.go | 2 -- .../CONSUL_GRPC_ADDR-with-https-scheme-enables-tls.golden | 2 -- ...HTTP_ADDR-with-https-scheme-does-not-affect-grpc-tls.golden | 2 -- command/connect/envoy/testdata/access-log-path.golden | 2 -- .../connect/envoy/testdata/access-logs-enabled-custom.golden | 2 -- command/connect/envoy/testdata/access-logs-enabled.golden | 2 -- command/connect/envoy/testdata/acl-enabled-and-token.golden | 2 -- command/connect/envoy/testdata/acl-enabled-but-no-token.golden | 2 -- ...NSUL_HTTP_ADDR-PLAIN-and-CONSUL_GRPC_ADDR-TLS-is-tls.golden | 2 -- ...UL_HTTP_ADDR-TLS-and-CONSUL_GRPC_ADDR-PLAIN-is-plain.golden | 2 -- command/connect/envoy/testdata/defaults-nodemeta.golden | 2 -- command/connect/envoy/testdata/defaults.golden | 2 -- .../connect/envoy/testdata/deprecated-grpc-addr-config.golden | 2 -- command/connect/envoy/testdata/envoy-readiness-probe.golden | 2 -- command/connect/envoy/testdata/existing-ca-file.golden | 2 -- command/connect/envoy/testdata/existing-ca-path.golden | 2 -- command/connect/envoy/testdata/extra_-multiple.golden | 2 -- command/connect/envoy/testdata/extra_-single.golden | 2 -- command/connect/envoy/testdata/grpc-addr-env.golden | 2 -- command/connect/envoy/testdata/grpc-addr-flag.golden | 2 -- command/connect/envoy/testdata/grpc-addr-unix-with-tls.golden | 2 -- command/connect/envoy/testdata/grpc-addr-unix.golden | 2 -- command/connect/envoy/testdata/grpc-tls-addr-config.golden | 2 -- .../envoy/testdata/ingress-gateway-address-specified.golden | 2 -- .../envoy/testdata/ingress-gateway-no-auto-register.golden | 2 -- command/connect/envoy/testdata/ingress-gateway-nodemeta.golden | 2 -- .../ingress-gateway-register-with-service-and-proxy-id.golden | 2 -- ...gress-gateway-register-with-service-without-proxy-id.golden | 2 -- command/connect/envoy/testdata/ingress-gateway.golden | 2 -- .../envoy/testdata/prometheus-metrics-tls-ca-file.golden | 2 -- .../envoy/testdata/prometheus-metrics-tls-ca-path.golden | 2 -- command/connect/envoy/testdata/prometheus-metrics.golden | 2 -- command/connect/envoy/testdata/stats-config-override.golden | 2 -- command/connect/envoy/testdata/telemetry-collector.golden | 2 -- command/connect/envoy/testdata/token-arg.golden | 2 -- command/connect/envoy/testdata/token-env.golden | 2 -- command/connect/envoy/testdata/token-file-arg.golden | 2 -- command/connect/envoy/testdata/token-file-env.golden | 2 -- command/connect/envoy/testdata/xds-addr-config.golden | 2 -- command/connect/envoy/testdata/zipkin-tracing-config.golden | 2 -- 41 files changed, 83 deletions(-) delete mode 100644 .changelog/17317.txt diff --git a/.changelog/17317.txt b/.changelog/17317.txt deleted file mode 100644 index 76c86a0a28..0000000000 --- a/.changelog/17317.txt +++ /dev/null @@ -1,3 +0,0 @@ -```release-note:bug -connect: fix a bug with Envoy potentially starting with incomplete configuration by not waiting enough for initial xDS configuration. -``` diff --git a/command/connect/envoy/bootstrap_tpl.go b/command/connect/envoy/bootstrap_tpl.go index 26b8e2118b..78d88f9b1d 100644 --- a/command/connect/envoy/bootstrap_tpl.go +++ b/command/connect/envoy/bootstrap_tpl.go @@ -281,12 +281,10 @@ const bootstrapTemplate = `{ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/CONSUL_GRPC_ADDR-with-https-scheme-enables-tls.golden b/command/connect/envoy/testdata/CONSUL_GRPC_ADDR-with-https-scheme-enables-tls.golden index c8144ac72f..a8ba4704f5 100644 --- a/command/connect/envoy/testdata/CONSUL_GRPC_ADDR-with-https-scheme-enables-tls.golden +++ b/command/connect/envoy/testdata/CONSUL_GRPC_ADDR-with-https-scheme-enables-tls.golden @@ -197,12 +197,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/CONSUL_HTTP_ADDR-with-https-scheme-does-not-affect-grpc-tls.golden b/command/connect/envoy/testdata/CONSUL_HTTP_ADDR-with-https-scheme-does-not-affect-grpc-tls.golden index a89575d2c1..5485256b4f 100644 --- a/command/connect/envoy/testdata/CONSUL_HTTP_ADDR-with-https-scheme-does-not-affect-grpc-tls.golden +++ b/command/connect/envoy/testdata/CONSUL_HTTP_ADDR-with-https-scheme-does-not-affect-grpc-tls.golden @@ -184,12 +184,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/access-log-path.golden b/command/connect/envoy/testdata/access-log-path.golden index 184a290b24..18a28a491e 100644 --- a/command/connect/envoy/testdata/access-log-path.golden +++ b/command/connect/envoy/testdata/access-log-path.golden @@ -184,12 +184,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/access-logs-enabled-custom.golden b/command/connect/envoy/testdata/access-logs-enabled-custom.golden index 50531f89c2..6af720bdac 100644 --- a/command/connect/envoy/testdata/access-logs-enabled-custom.golden +++ b/command/connect/envoy/testdata/access-logs-enabled-custom.golden @@ -197,12 +197,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/access-logs-enabled.golden b/command/connect/envoy/testdata/access-logs-enabled.golden index ea2e150607..892cf46324 100644 --- a/command/connect/envoy/testdata/access-logs-enabled.golden +++ b/command/connect/envoy/testdata/access-logs-enabled.golden @@ -219,12 +219,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/acl-enabled-and-token.golden b/command/connect/envoy/testdata/acl-enabled-and-token.golden index a5427c7f24..3342f03904 100644 --- a/command/connect/envoy/testdata/acl-enabled-and-token.golden +++ b/command/connect/envoy/testdata/acl-enabled-and-token.golden @@ -184,12 +184,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/acl-enabled-but-no-token.golden b/command/connect/envoy/testdata/acl-enabled-but-no-token.golden index a89575d2c1..5485256b4f 100644 --- a/command/connect/envoy/testdata/acl-enabled-but-no-token.golden +++ b/command/connect/envoy/testdata/acl-enabled-but-no-token.golden @@ -184,12 +184,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/both-CONSUL_HTTP_ADDR-PLAIN-and-CONSUL_GRPC_ADDR-TLS-is-tls.golden b/command/connect/envoy/testdata/both-CONSUL_HTTP_ADDR-PLAIN-and-CONSUL_GRPC_ADDR-TLS-is-tls.golden index c8144ac72f..a8ba4704f5 100644 --- a/command/connect/envoy/testdata/both-CONSUL_HTTP_ADDR-PLAIN-and-CONSUL_GRPC_ADDR-TLS-is-tls.golden +++ b/command/connect/envoy/testdata/both-CONSUL_HTTP_ADDR-PLAIN-and-CONSUL_GRPC_ADDR-TLS-is-tls.golden @@ -197,12 +197,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/both-CONSUL_HTTP_ADDR-TLS-and-CONSUL_GRPC_ADDR-PLAIN-is-plain.golden b/command/connect/envoy/testdata/both-CONSUL_HTTP_ADDR-TLS-and-CONSUL_GRPC_ADDR-PLAIN-is-plain.golden index a89575d2c1..5485256b4f 100644 --- a/command/connect/envoy/testdata/both-CONSUL_HTTP_ADDR-TLS-and-CONSUL_GRPC_ADDR-PLAIN-is-plain.golden +++ b/command/connect/envoy/testdata/both-CONSUL_HTTP_ADDR-TLS-and-CONSUL_GRPC_ADDR-PLAIN-is-plain.golden @@ -184,12 +184,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/defaults-nodemeta.golden b/command/connect/envoy/testdata/defaults-nodemeta.golden index ea65421109..41788c3c42 100644 --- a/command/connect/envoy/testdata/defaults-nodemeta.golden +++ b/command/connect/envoy/testdata/defaults-nodemeta.golden @@ -185,12 +185,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/defaults.golden b/command/connect/envoy/testdata/defaults.golden index a89575d2c1..5485256b4f 100644 --- a/command/connect/envoy/testdata/defaults.golden +++ b/command/connect/envoy/testdata/defaults.golden @@ -184,12 +184,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/deprecated-grpc-addr-config.golden b/command/connect/envoy/testdata/deprecated-grpc-addr-config.golden index e604c61d50..ab87aa9b43 100644 --- a/command/connect/envoy/testdata/deprecated-grpc-addr-config.golden +++ b/command/connect/envoy/testdata/deprecated-grpc-addr-config.golden @@ -184,12 +184,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/envoy-readiness-probe.golden b/command/connect/envoy/testdata/envoy-readiness-probe.golden index 18680a3206..444528e880 100644 --- a/command/connect/envoy/testdata/envoy-readiness-probe.golden +++ b/command/connect/envoy/testdata/envoy-readiness-probe.golden @@ -273,12 +273,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/existing-ca-file.golden b/command/connect/envoy/testdata/existing-ca-file.golden index c8144ac72f..a8ba4704f5 100644 --- a/command/connect/envoy/testdata/existing-ca-file.golden +++ b/command/connect/envoy/testdata/existing-ca-file.golden @@ -197,12 +197,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/existing-ca-path.golden b/command/connect/envoy/testdata/existing-ca-path.golden index c0566ab351..e246dbb324 100644 --- a/command/connect/envoy/testdata/existing-ca-path.golden +++ b/command/connect/envoy/testdata/existing-ca-path.golden @@ -197,12 +197,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/extra_-multiple.golden b/command/connect/envoy/testdata/extra_-multiple.golden index 819994f0c0..038e65d8d9 100644 --- a/command/connect/envoy/testdata/extra_-multiple.golden +++ b/command/connect/envoy/testdata/extra_-multiple.golden @@ -206,12 +206,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/extra_-single.golden b/command/connect/envoy/testdata/extra_-single.golden index b1fb71997b..14b8f08205 100644 --- a/command/connect/envoy/testdata/extra_-single.golden +++ b/command/connect/envoy/testdata/extra_-single.golden @@ -197,12 +197,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/grpc-addr-env.golden b/command/connect/envoy/testdata/grpc-addr-env.golden index e604c61d50..ab87aa9b43 100644 --- a/command/connect/envoy/testdata/grpc-addr-env.golden +++ b/command/connect/envoy/testdata/grpc-addr-env.golden @@ -184,12 +184,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/grpc-addr-flag.golden b/command/connect/envoy/testdata/grpc-addr-flag.golden index e604c61d50..ab87aa9b43 100644 --- a/command/connect/envoy/testdata/grpc-addr-flag.golden +++ b/command/connect/envoy/testdata/grpc-addr-flag.golden @@ -184,12 +184,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/grpc-addr-unix-with-tls.golden b/command/connect/envoy/testdata/grpc-addr-unix-with-tls.golden index 2b902d48d4..89764c310a 100644 --- a/command/connect/envoy/testdata/grpc-addr-unix-with-tls.golden +++ b/command/connect/envoy/testdata/grpc-addr-unix-with-tls.golden @@ -196,12 +196,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/grpc-addr-unix.golden b/command/connect/envoy/testdata/grpc-addr-unix.golden index 88e6e46bfb..eb8841ae99 100644 --- a/command/connect/envoy/testdata/grpc-addr-unix.golden +++ b/command/connect/envoy/testdata/grpc-addr-unix.golden @@ -183,12 +183,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/grpc-tls-addr-config.golden b/command/connect/envoy/testdata/grpc-tls-addr-config.golden index e65fc5f09c..e79cf0455d 100644 --- a/command/connect/envoy/testdata/grpc-tls-addr-config.golden +++ b/command/connect/envoy/testdata/grpc-tls-addr-config.golden @@ -197,12 +197,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/ingress-gateway-address-specified.golden b/command/connect/envoy/testdata/ingress-gateway-address-specified.golden index 038c8fcc5d..cc2e504eaf 100644 --- a/command/connect/envoy/testdata/ingress-gateway-address-specified.golden +++ b/command/connect/envoy/testdata/ingress-gateway-address-specified.golden @@ -273,12 +273,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/ingress-gateway-no-auto-register.golden b/command/connect/envoy/testdata/ingress-gateway-no-auto-register.golden index 80f1f9a8b7..cddaa490dd 100644 --- a/command/connect/envoy/testdata/ingress-gateway-no-auto-register.golden +++ b/command/connect/envoy/testdata/ingress-gateway-no-auto-register.golden @@ -273,12 +273,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/ingress-gateway-nodemeta.golden b/command/connect/envoy/testdata/ingress-gateway-nodemeta.golden index 8a2d5f6276..d79739ed72 100644 --- a/command/connect/envoy/testdata/ingress-gateway-nodemeta.golden +++ b/command/connect/envoy/testdata/ingress-gateway-nodemeta.golden @@ -274,12 +274,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/ingress-gateway-register-with-service-and-proxy-id.golden b/command/connect/envoy/testdata/ingress-gateway-register-with-service-and-proxy-id.golden index 6192f674ac..3149fc4b33 100644 --- a/command/connect/envoy/testdata/ingress-gateway-register-with-service-and-proxy-id.golden +++ b/command/connect/envoy/testdata/ingress-gateway-register-with-service-and-proxy-id.golden @@ -273,12 +273,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/ingress-gateway-register-with-service-without-proxy-id.golden b/command/connect/envoy/testdata/ingress-gateway-register-with-service-without-proxy-id.golden index 92d80e033e..f8eb447541 100644 --- a/command/connect/envoy/testdata/ingress-gateway-register-with-service-without-proxy-id.golden +++ b/command/connect/envoy/testdata/ingress-gateway-register-with-service-without-proxy-id.golden @@ -273,12 +273,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/ingress-gateway.golden b/command/connect/envoy/testdata/ingress-gateway.golden index 40a5c74d1b..c4fba520ed 100644 --- a/command/connect/envoy/testdata/ingress-gateway.golden +++ b/command/connect/envoy/testdata/ingress-gateway.golden @@ -273,12 +273,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/prometheus-metrics-tls-ca-file.golden b/command/connect/envoy/testdata/prometheus-metrics-tls-ca-file.golden index c93286e64e..71b82250e3 100644 --- a/command/connect/envoy/testdata/prometheus-metrics-tls-ca-file.golden +++ b/command/connect/envoy/testdata/prometheus-metrics-tls-ca-file.golden @@ -310,12 +310,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/prometheus-metrics-tls-ca-path.golden b/command/connect/envoy/testdata/prometheus-metrics-tls-ca-path.golden index 272175f707..07e56ae878 100644 --- a/command/connect/envoy/testdata/prometheus-metrics-tls-ca-path.golden +++ b/command/connect/envoy/testdata/prometheus-metrics-tls-ca-path.golden @@ -310,12 +310,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/prometheus-metrics.golden b/command/connect/envoy/testdata/prometheus-metrics.golden index 5806dd671f..5adc8a9485 100644 --- a/command/connect/envoy/testdata/prometheus-metrics.golden +++ b/command/connect/envoy/testdata/prometheus-metrics.golden @@ -273,12 +273,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/stats-config-override.golden b/command/connect/envoy/testdata/stats-config-override.golden index dd4ff53dd1..d2a2371f20 100644 --- a/command/connect/envoy/testdata/stats-config-override.golden +++ b/command/connect/envoy/testdata/stats-config-override.golden @@ -62,12 +62,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/telemetry-collector.golden b/command/connect/envoy/testdata/telemetry-collector.golden index 983e51633b..7c584864a0 100644 --- a/command/connect/envoy/testdata/telemetry-collector.golden +++ b/command/connect/envoy/testdata/telemetry-collector.golden @@ -221,12 +221,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/token-arg.golden b/command/connect/envoy/testdata/token-arg.golden index 816bf74875..ac057e9a60 100644 --- a/command/connect/envoy/testdata/token-arg.golden +++ b/command/connect/envoy/testdata/token-arg.golden @@ -184,12 +184,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/token-env.golden b/command/connect/envoy/testdata/token-env.golden index 816bf74875..ac057e9a60 100644 --- a/command/connect/envoy/testdata/token-env.golden +++ b/command/connect/envoy/testdata/token-env.golden @@ -184,12 +184,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/token-file-arg.golden b/command/connect/envoy/testdata/token-file-arg.golden index 816bf74875..ac057e9a60 100644 --- a/command/connect/envoy/testdata/token-file-arg.golden +++ b/command/connect/envoy/testdata/token-file-arg.golden @@ -184,12 +184,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/token-file-env.golden b/command/connect/envoy/testdata/token-file-env.golden index 816bf74875..ac057e9a60 100644 --- a/command/connect/envoy/testdata/token-file-env.golden +++ b/command/connect/envoy/testdata/token-file-env.golden @@ -184,12 +184,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/xds-addr-config.golden b/command/connect/envoy/testdata/xds-addr-config.golden index e604c61d50..ab87aa9b43 100644 --- a/command/connect/envoy/testdata/xds-addr-config.golden +++ b/command/connect/envoy/testdata/xds-addr-config.golden @@ -184,12 +184,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { diff --git a/command/connect/envoy/testdata/zipkin-tracing-config.golden b/command/connect/envoy/testdata/zipkin-tracing-config.golden index dc4779a775..fd52f5ae3f 100644 --- a/command/connect/envoy/testdata/zipkin-tracing-config.golden +++ b/command/connect/envoy/testdata/zipkin-tracing-config.golden @@ -217,12 +217,10 @@ "dynamic_resources": { "lds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "cds_config": { "ads": {}, - "initial_fetch_timeout": "0s", "resource_api_version": "V3" }, "ads_config": { From 7293e1a9970053e59a7efcc7a476f8521aef5916 Mon Sep 17 00:00:00 2001 From: Luiz Aoqui Date: Thu, 1 Jun 2023 18:09:21 -0400 Subject: [PATCH 21/72] docs: add note about Nomad support for Consul 1.13.8 (#17512) * docs: add note about Nomad support for Consul 1.13.8 * apply code review changes --- website/content/docs/upgrading/upgrade-specific.mdx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/website/content/docs/upgrading/upgrade-specific.mdx b/website/content/docs/upgrading/upgrade-specific.mdx index 62e466d668..985a703353 100644 --- a/website/content/docs/upgrading/upgrade-specific.mdx +++ b/website/content/docs/upgrading/upgrade-specific.mdx @@ -28,7 +28,7 @@ Before upgrading, ensure that all of your applications can handle this new API b #### Remove deprecated service-defaults peer upstream override behavior -When configuring a service defaults configuration entry, the [`UpstreamConfig.Overrides` configuration](/consul/docs/connect/config-entries/service-defaults#upstreamconfig-overrides) +When configuring a service defaults configuration entry, the [`UpstreamConfig.Overrides` configuration](/consul/docs/connect/config-entries/service-defaults#upstreamconfig-overrides) does not apply to peer upstreams unless the [`Peer`](/consul/docs/connect/config-entries/service-defaults#upstreamconfig-overrides-peer) field is explicitly provided. This change removes the backward-compatibility behavior introduced in Consul 1.15.x. Refer to the [upgrade instructions for 1.15.x](#service-defaults-overrides-for-upstream-peered-services) for more information. @@ -152,7 +152,7 @@ In Consul v1.15 and higher: UpstreamConfig = { Overrides = [ { - Name = foo # Applies to local service `foo` + Name = foo # Applies to local service `foo` }, { Name = foo # Applies to `foo` imported from peered cluster `bar` @@ -402,6 +402,12 @@ if the Vault policy is not modified as described. As a precaution, we recommend both modifying the Vault policy and upgrading to Consul 1.13.3 or later to avoid the breaking nature of that change. +### Nomad Incompatibility + +Nomad users should not upgrade to Consul v1.13.8. An API change in this Consul +release prevents Nomad from correctly detecting the Consul agent version. As a +result, allocations are not placed in clients running v1.13.8. + ## Consul 1.12.x ((#consul-1-12-0)) ### Modify Vault Policy for Vault CA Provider From d9e18b4bf0e10776cd816ff448908a529e52aafc Mon Sep 17 00:00:00 2001 From: Poonam Jadhav Date: Fri, 2 Jun 2023 08:59:48 -0400 Subject: [PATCH 22/72] changelog: add changelog for reporting (#17535) --- .changelog/5102.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/5102.txt diff --git a/.changelog/5102.txt b/.changelog/5102.txt new file mode 100644 index 0000000000..97d8c7bf8b --- /dev/null +++ b/.changelog/5102.txt @@ -0,0 +1,3 @@ +```release-note:feature +server: **(Enterprise Only)** allow automatic license utilization reporting. +``` \ No newline at end of file From cf4059f3ce57b5b507f55bc8b48871c62d9dad8c Mon Sep 17 00:00:00 2001 From: cskh Date: Fri, 2 Jun 2023 09:37:44 -0400 Subject: [PATCH 23/72] chore: fix the error message format (#17554) --- agent/agent.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/agent/agent.go b/agent/agent.go index 388c7c3e6f..678d110d53 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -4571,13 +4571,13 @@ func (a *Agent) persistServerMetadata() { f, err := consul.OpenServerMetadata(file) if err != nil { - a.logger.Error("failed to open existing server metadata: %w", err) + a.logger.Error("failed to open existing server metadata", "error", err) continue } if err := consul.WriteServerMetadata(f); err != nil { f.Close() - a.logger.Error("failed to write server metadata: %w", err) + a.logger.Error("failed to write server metadata", "error", err) continue } From a55d368a0ec1e71517437f6a76404de729c19773 Mon Sep 17 00:00:00 2001 From: Dave Rawks Date: Fri, 2 Jun 2023 10:04:48 -0700 Subject: [PATCH 24/72] Resolves issue-16844 - systemd notify by default (#16845) * updates `consul.service` systemd service unit to use `Type=notify` to resolve issue #16844 * add changelog update to match --- .changelog/16845.txt | 3 +++ .release/linux/package/usr/lib/systemd/system/consul.service | 1 + 2 files changed, 4 insertions(+) create mode 100644 .changelog/16845.txt diff --git a/.changelog/16845.txt b/.changelog/16845.txt new file mode 100644 index 0000000000..7181e319e3 --- /dev/null +++ b/.changelog/16845.txt @@ -0,0 +1,3 @@ +```release-note:improvement +systemd: set service type to notify. +``` diff --git a/.release/linux/package/usr/lib/systemd/system/consul.service b/.release/linux/package/usr/lib/systemd/system/consul.service index 1bbf51a7a1..65eca696e1 100644 --- a/.release/linux/package/usr/lib/systemd/system/consul.service +++ b/.release/linux/package/usr/lib/systemd/system/consul.service @@ -6,6 +6,7 @@ After=network-online.target ConditionFileNotEmpty=/etc/consul.d/consul.hcl [Service] +Type=notify EnvironmentFile=-/etc/consul.d/consul.env User=consul Group=consul From 88951bfafaa969f52235dc5b443cb64ba329660c Mon Sep 17 00:00:00 2001 From: malizz Date: Fri, 2 Jun 2023 12:35:21 -0700 Subject: [PATCH 25/72] add changelog entries for 1.15.3 (#17558) --- CHANGELOG.md | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd3379535a..ee1dccacc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,61 @@ +## 1.15.3 (June 1, 2023) + +BREAKING CHANGES: + +* extensions: The Lua extension now targets local proxy listeners for the configured service's upstreams, rather than remote downstream listeners for the configured service, when ListenerType is set to outbound in extension configuration. See [CVE-2023-2816](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-2816) changelog entry for more details. [[GH-17415](https://github.com/hashicorp/consul/issues/17415)] + +SECURITY: + +* Update to UBI base image to 9.2. [[GH-17513](https://github.com/hashicorp/consul/issues/17513)] +* Upgrade golang.org/x/net to address [CVE-2022-41723](https://nvd.nist.gov/vuln/detail/CVE-2022-41723) [[GH-16754](https://github.com/hashicorp/consul/issues/16754)] +* Upgrade to use Go 1.20.4. +This resolves vulnerabilities [CVE-2023-24537](https://github.com/advisories/GHSA-9f7g-gqwh-jpf5)(`go/scanner`), +[CVE-2023-24538](https://github.com/advisories/GHSA-v4m2-x4rp-hv22)(`html/template`), +[CVE-2023-24534](https://github.com/advisories/GHSA-8v5j-pwr7-w5f8)(`net/textproto`) and +[CVE-2023-24536](https://github.com/advisories/GHSA-9f7g-gqwh-jpf5)(`mime/multipart`). +Also, `golang.org/x/net` has been updated to v0.7.0 to resolve CVEs [CVE-2022-41721 +](https://github.com/advisories/GHSA-fxg5-wq6x-vr4w +), [CVE-2022-27664](https://github.com/advisories/GHSA-69cg-p879-7622) and [CVE-2022-41723 +](https://github.com/advisories/GHSA-vvpx-j8f3-3w6h +.) [[GH-17240](https://github.com/hashicorp/consul/issues/17240)] +* extensions: Disable remote downstream proxy patching by Envoy Extensions other than AWS Lambda. Previously, an operator with service:write ACL permissions for an upstream service could modify Envoy proxy config for downstream services without equivalent permissions for those services. This issue only impacts the Lua extension. [[CVE-2023-2816](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-2816)] [[GH-17415](https://github.com/hashicorp/consul/issues/17415)] + +FEATURES: + +* hcp: Add new metrics sink to collect, aggregate and export server metrics to HCP in OTEL format. [[GH-17460](https://github.com/hashicorp/consul/issues/17460)] + +IMPROVEMENTS: + +* Fixes a performance issue in Raft where commit latency can increase by 100x or more when under heavy load. For more details see https://github.com/hashicorp/raft/pull/541. [[GH-17081](https://github.com/hashicorp/consul/issues/17081)] +* agent: add a configurable maximimum age (default: 7 days) to prevent servers re-joining a cluster with stale data [[GH-17171](https://github.com/hashicorp/consul/issues/17171)] +* agent: add new metrics to track cpu disk and memory usage for server hosts (defaults to: enabled) [[GH-17038](https://github.com/hashicorp/consul/issues/17038)] +* connect: update supported envoy versions to 1.22.11, 1.23.8, 1.24.6, 1.25.4 [[GH-16889](https://github.com/hashicorp/consul/issues/16889)] +* envoy: add `MaxEjectionPercent` and `BaseEjectionTime` to passive health check configs. [[GH-15979](https://github.com/hashicorp/consul/issues/15979)] +* hcp: Add support for linking existing Consul clusters to HCP management plane. [[GH-16916](https://github.com/hashicorp/consul/issues/16916)] +* logging: change snapshot log header from `agent.server.snapshot` to `agent.server.raft.snapshot` [[GH-17236](https://github.com/hashicorp/consul/issues/17236)] +* peering: allow re-establishing terminated peering from new token without deleting existing peering first. [[GH-16776](https://github.com/hashicorp/consul/issues/16776)] +* peering: gRPC queries for TrustBundleList, TrustBundleRead, PeeringList, and PeeringRead now support blocking semantics, + reducing network and CPU demand. + The HTTP APIs for Peering List and Read have been updated to support blocking. [[GH-17426](https://github.com/hashicorp/consul/issues/17426)] +* raft: Remove expensive reflection from raft/mesh hot path [[GH-16552](https://github.com/hashicorp/consul/issues/16552)] +* xds: rename envoy_hcp_metrics_bind_socket_dir to envoy_telemetry_collector_bind_socket_dir to remove HCP naming references. [[GH-17327](https://github.com/hashicorp/consul/issues/17327)] + +BUG FIXES: + +* Fix an bug where decoding some Config structs with unset pointer fields could fail with `reflect: call of reflect.Value.Type on zero Value`. [[GH-17048](https://github.com/hashicorp/consul/issues/17048)] +* acl: **(Enterprise only)** Check permissions in correct partition/namespace when resolving service in non-default partition/namespace +* acl: Fix an issue where the anonymous token was synthesized in non-primary datacenters which could cause permission errors when federating clusters with ACL replication enabled. [[GH-17231](https://github.com/hashicorp/consul/issues/17231)] +* acls: Fix ACL bug that can result in sidecar proxies having incorrect endpoints. +* connect: Fix multiple inefficient behaviors when querying service health. [[GH-17241](https://github.com/hashicorp/consul/issues/17241)] +* gateways: Fix an bug where targeting a virtual service defined by a service-resolver was broken for HTTPRoutes. [[GH-17055](https://github.com/hashicorp/consul/issues/17055)] +* grpc: ensure grpc resolver correctly uses lan/wan addresses on servers [[GH-17270](https://github.com/hashicorp/consul/issues/17270)] +* namespaces: adjusts the return type from HTTP list API to return the `api` module representation of a namespace. +This fixes an error with the `consul namespace list` command when a namespace has a deferred deletion timestamp. +* peering: Fix issue where modifying the list of exported services did not correctly replicate changes for services that exist in a non-default namespace. [[GH-17456](https://github.com/hashicorp/consul/issues/17456)] +* peering: Fix issue where peer streams could incorrectly deregister services in various scenarios. [[GH-17235](https://github.com/hashicorp/consul/issues/17235)] +* peering: ensure that merged central configs of peered upstreams for partitioned downstreams work [[GH-17179](https://github.com/hashicorp/consul/issues/17179)] +* xds: Fix possible panic that can when generating clusters before the root certificates have been fetched. [[GH-17185](https://github.com/hashicorp/consul/issues/17185)] + ## 1.14.7 (May 16, 2023) SECURITY: From 4ddb88ec7e538dc1896007ee9332c63952d1d606 Mon Sep 17 00:00:00 2001 From: Andrew Stucki Date: Mon, 5 Jun 2023 13:10:17 -0400 Subject: [PATCH 26/72] Fix up case where subscription is terminated due to ACLs changing or a snapshot restore occurring (#17566) * Fix up case where subscription is terminated due to ACLs changing or a snapshot restore occurring * Add changelog entry * Switch to use errors.Is --- .changelog/17566.txt | 3 +++ agent/proxycfg-glue/glue.go | 7 +++++++ 2 files changed, 10 insertions(+) create mode 100644 .changelog/17566.txt diff --git a/.changelog/17566.txt b/.changelog/17566.txt new file mode 100644 index 0000000000..f15718bd76 --- /dev/null +++ b/.changelog/17566.txt @@ -0,0 +1,3 @@ +```release-note:bug +xds: Fixed a bug where modifying ACLs on a token being actively used for an xDS connection caused all xDS updates to fail. +``` diff --git a/agent/proxycfg-glue/glue.go b/agent/proxycfg-glue/glue.go index 03afd5c155..320d2fc258 100644 --- a/agent/proxycfg-glue/glue.go +++ b/agent/proxycfg-glue/glue.go @@ -5,6 +5,7 @@ package proxycfgglue import ( "context" + "errors" "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-memdb" @@ -141,6 +142,12 @@ func newUpdateEvent(correlationID string, result any, err error) proxycfg.Update if acl.IsErrNotFound(err) { err = proxycfg.TerminalError(err) } + // these are also errors where we should mark them + // as terminal for the sake of proxycfg, since they require + // a resubscribe. + if errors.Is(err, stream.ErrSubForceClosed) || errors.Is(err, stream.ErrShuttingDown) { + err = proxycfg.TerminalError(err) + } return proxycfg.UpdateEvent{ CorrelationID: correlationID, Result: result, From 8617f8af16184e1de42f22aca7448e1d8e86fab6 Mon Sep 17 00:00:00 2001 From: malizz Date: Mon, 5 Jun 2023 12:16:21 -0700 Subject: [PATCH 27/72] continue anti-entropy sync when failures exist (#17560) --- agent/local/state.go | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/agent/local/state.go b/agent/local/state.go index cd1cfa3ed4..3e43ddc9a1 100644 --- a/agent/local/state.go +++ b/agent/local/state.go @@ -13,20 +13,20 @@ import ( "sync/atomic" "time" + "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/acl/resolver" + "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/agent/token" + "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/lib/stringslice" + "github.com/hashicorp/consul/types" "github.com/armon/go-metrics" "github.com/armon/go-metrics/prometheus" "github.com/hashicorp/go-hclog" + "github.com/hashicorp/go-multierror" "github.com/mitchellh/copystructure" - - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/agent/token" - "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/lib" - "github.com/hashicorp/consul/types" ) var StateCounters = []prometheus.CounterDefinition{ @@ -1252,6 +1252,7 @@ func (l *State) SyncChanges() error { } } + var errs error // Sync the services // (logging happens in the helper methods) for id, s := range l.services { @@ -1265,7 +1266,7 @@ func (l *State) SyncChanges() error { l.logger.Debug("Service in sync", "service", id.String()) } if err != nil { - return err + errs = multierror.Append(errs, err) } } @@ -1286,10 +1287,10 @@ func (l *State) SyncChanges() error { l.logger.Debug("Check in sync", "check", id.String()) } if err != nil { - return err + errs = multierror.Append(errs, err) } } - return nil + return errs } // deleteService is used to delete a service from the server From caa044fce5ac0c516d6d19f09f090038459b484c Mon Sep 17 00:00:00 2001 From: Curt Bushko Date: Mon, 5 Jun 2023 16:04:54 -0400 Subject: [PATCH 28/72] Generate helm docs for release consul-k8s 1.1.2 (#17568) * generate docs --- website/content/docs/k8s/helm.mdx | 226 ++++++++++++++++++++++-------- 1 file changed, 164 insertions(+), 62 deletions(-) diff --git a/website/content/docs/k8s/helm.mdx b/website/content/docs/k8s/helm.mdx index 6a1f5c197a..c4f639b279 100644 --- a/website/content/docs/k8s/helm.mdx +++ b/website/content/docs/k8s/helm.mdx @@ -23,21 +23,22 @@ Use these links to navigate to a particular top-level stanza. - [Helm Chart Reference](#helm-chart-reference) - [Top-Level Stanzas](#top-level-stanzas) - [All Values](#all-values) - - [global ((#h-global))](#global-h-global) - - [server ((#h-server))](#server-h-server) - - [externalServers ((#h-externalservers))](#externalservers-h-externalservers) - - [client ((#h-client))](#client-h-client) - - [dns ((#h-dns))](#dns-h-dns) - - [ui ((#h-ui))](#ui-h-ui) - - [syncCatalog ((#h-synccatalog))](#synccatalog-h-synccatalog) - - [connectInject ((#h-connectinject))](#connectinject-h-connectinject) - - [meshGateway ((#h-meshgateway))](#meshgateway-h-meshgateway) - - [ingressGateways ((#h-ingressgateways))](#ingressgateways-h-ingressgateways) - - [terminatingGateways ((#h-terminatinggateways))](#terminatinggateways-h-terminatinggateways) - - [apiGateway ((#h-apigateway))](#apigateway-h-apigateway) - - [webhookCertManager ((#h-webhookcertmanager))](#webhookcertmanager-h-webhookcertmanager) - - [prometheus ((#h-prometheus))](#prometheus-h-prometheus) - - [tests ((#h-tests))](#tests-h-tests) + - [`global`](#h-global) + - [`server`](#h-server) + - [`externalServers`](#h-externalservers) + - [`client`](#h-client) + - [`dns`](#h-dns) + - [`ui`](#h-ui) + - [`syncCatalog`](#h-synccatalog) + - [`connectInject`](#h-connectinject) + - [`meshGateway`](#h-meshgateway) + - [`ingressGateways`](#h-ingressgateways) + - [`terminatingGateways`](#h-terminatinggateways) + - [`apiGateway`](#h-apigateway) + - [`webhookCertManager`](#h-webhookcertmanager) + - [`prometheus`](#h-prometheus) + - [`tests`](#h-tests) + - [`telemetryCollector`](#h-telemetrycollector) - [Helm Chart Examples](#helm-chart-examples) - [Customizing the Helm Chart](#customizing-the-helm-chart) @@ -63,7 +64,7 @@ Use these links to navigate to a particular top-level stanza. the prefix will be `-consul`. - `domain` ((#v-global-domain)) (`string: consul`) - The domain Consul will answer DNS queries for - (Refer to [`-domain`](/consul/docs/agent/config/cli-flags#_domain)) and the domain services synced from + (Refer to [`-domain`](https://developer.hashicorp.com/consul/docs/agent/config/cli-flags#_domain)) and the domain services synced from Consul into Kubernetes will have, e.g. `service-name.service.consul`. - `peering` ((#v-global-peering)) - Configures the Cluster Peering feature. Requires Consul v1.14+ and Consul-K8s v1.0.0+. @@ -124,7 +125,7 @@ Use these links to navigate to a particular top-level stanza. - `secretsBackend` ((#v-global-secretsbackend)) - secretsBackend is used to configure Vault as the secrets backend for the Consul on Kubernetes installation. The Vault cluster needs to have the Kubernetes Auth Method, KV2 and PKI secrets engines enabled and have necessary secrets, policies and roles created prior to installing Consul. - Refer to [Vault as the Secrets Backend](/consul/docs/k8s/deployment-configurations/vault) + Refer to [Vault as the Secrets Backend](https://developer.hashicorp.com/consul/docs/k8s/deployment-configurations/vault) documentation for full instructions. The Vault cluster _must_ not have the Consul cluster installed by this Helm chart as its storage backend @@ -215,7 +216,7 @@ Use these links to navigate to a particular top-level stanza. The provider will be configured to use the Vault Kubernetes auth method and therefore requires the role provided by `global.secretsBackend.vault.consulServerRole` to have permissions to the root and intermediate PKI paths. - Please refer to [Vault ACL policies](/consul/docs/connect/ca/vault#vault-acl-policies) + Please refer to [Vault ACL policies](https://developer.hashicorp.com/consul/docs/connect/ca/vault#vault-acl-policies) documentation for information on how to configure the Vault policies. - `address` ((#v-global-secretsbackend-vault-connectca-address)) (`string: ""`) - The address of the Vault server. @@ -223,13 +224,13 @@ Use these links to navigate to a particular top-level stanza. - `authMethodPath` ((#v-global-secretsbackend-vault-connectca-authmethodpath)) (`string: kubernetes`) - The mount path of the Kubernetes auth method in Vault. - `rootPKIPath` ((#v-global-secretsbackend-vault-connectca-rootpkipath)) (`string: ""`) - The path to a PKI secrets engine for the root certificate. - For more details, please refer to [Vault service mesh CA configuration](/consul/docs/connect/ca/vault#rootpkipath). + For more details, please refer to [Vault service mesh CA configuration](https://developer.hashicorp.com/consul/docs/connect/ca/vault#rootpkipath). - `intermediatePKIPath` ((#v-global-secretsbackend-vault-connectca-intermediatepkipath)) (`string: ""`) - The path to a PKI secrets engine for the generated intermediate certificate. - For more details, please refer to [Vault service mesh CA configuration](/consul/docs/connect/ca/vault#intermediatepkipath). + For more details, please refer to [Vault service mesh CA configuration](https://developer.hashicorp.com/consul/docs/connect/ca/vault#intermediatepkipath). - `additionalConfig` ((#v-global-secretsbackend-vault-connectca-additionalconfig)) (`string: {}`) - Additional service mesh CA configuration in JSON format. - Please refer to [Vault service mesh CA configuration](/consul/docs/connect/ca/vault#configuration) + Please refer to [Vault service mesh CA configuration](https://developer.hashicorp.com/consul/docs/connect/ca/vault#configuration) for all configuration options available for that provider. Example: @@ -263,7 +264,7 @@ Use these links to navigate to a particular top-level stanza. inject webhooks. - `gossipEncryption` ((#v-global-gossipencryption)) - Configures Consul's gossip encryption key. - (Refer to [`-encrypt`](/consul/docs/agent/config/cli-flags#_encrypt)). + (Refer to [`-encrypt`](https://developer.hashicorp.com/consul/docs/agent/config/cli-flags#_encrypt)). By default, gossip encryption is not enabled. The gossip encryption key may be set automatically or manually. The recommended method is to automatically generate the key. To automatically generate and set a gossip encryption key, set autoGenerate to true. @@ -294,17 +295,17 @@ Use these links to navigate to a particular top-level stanza. - `recursors` ((#v-global-recursors)) (`array: []`) - A list of addresses of upstream DNS servers that are used to recursively resolve DNS queries. These values are given as `-recursor` flags to Consul servers and clients. - Refer to [`-recursor`](/consul/docs/agent/config/cli-flags#_recursor) for more details. + Refer to [`-recursor`](https://developer.hashicorp.com/consul/docs/agent/config/cli-flags#_recursor) for more details. If this is an empty array (the default), then Consul DNS will only resolve queries for the Consul top level domain (by default `.consul`). - - `tls` ((#v-global-tls)) - Enables [TLS](/consul/tutorials/security/tls-encryption-secure) + - `tls` ((#v-global-tls)) - Enables [TLS](https://developer.hashicorp.com/consul/tutorials/security/tls-encryption-secure) across the cluster to verify authenticity of the Consul servers and clients. Requires Consul v1.4.1+. - `enabled` ((#v-global-tls-enabled)) (`boolean: false`) - If true, the Helm chart will enable TLS for Consul servers and clients and all consul-k8s-control-plane components, as well as generate certificate authority (optional) and server and client certificates. - This setting is required for [cluster peering](/consul/docs/k8s/connect/cluster-peering/tech-specs). + This setting is required for [Cluster Peering](https://developer.hashicorp.com/consul/docs/connect/cluster-peering/k8s). - `enableAutoEncrypt` ((#v-global-tls-enableautoencrypt)) (`boolean: false`) - If true, turns on the auto-encrypt feature on clients and servers. It also switches consul-k8s-control-plane components to retrieve the CA from the servers @@ -321,7 +322,7 @@ Use these links to navigate to a particular top-level stanza. - `verify` ((#v-global-tls-verify)) (`boolean: true`) - If true, `verify_outgoing`, `verify_server_hostname`, and `verify_incoming` for internal RPC communication will be set to `true` for Consul servers and clients. Set this to false to incrementally roll out TLS on an existing Consul cluster. - Please refer to [TLS on existing clusters](/consul/docs/k8s/operations/tls-on-existing-cluster) + Please refer to [TLS on existing clusters](https://developer.hashicorp.com/consul/docs/k8s/operations/tls-on-existing-cluster) for more details. - `httpsOnly` ((#v-global-tls-httpsonly)) (`boolean: true`) - If true, the Helm chart will configure Consul to disable the HTTP port on @@ -474,7 +475,7 @@ Use these links to navigate to a particular top-level stanza. This address must be reachable from the Consul servers in the primary datacenter. This auth method will be used to provision ACL tokens for Consul components and is different from the one used by the Consul Service Mesh. - Please refer to the [Kubernetes Auth Method documentation](/consul/docs/security/acl/auth-methods/kubernetes). + Please refer to the [Kubernetes Auth Method documentation](https://developer.hashicorp.com/consul/docs/security/acl/auth-methods/kubernetes). You can retrieve this value from your `kubeconfig` by running: @@ -501,6 +502,9 @@ Use these links to navigate to a particular top-level stanza. Envoy metrics on port `20200` at the `/metrics` path and all gateway pods will have Prometheus scrape annotations. Only applicable if `global.metrics.enabled` is true. + - `enableTelemetryCollector` ((#v-global-metrics-enabletelemetrycollector)) (`boolean: false`) - Configures the Helm chart’s components to forward envoy metrics for the Consul service mesh to the + consul-telemetry-collector. This includes gateway metrics and sidecar metrics. + - `imageConsulDataplane` ((#v-global-imageconsuldataplane)) (`string: hashicorp/consul-dataplane:`) - The name (and tag) of the consul-dataplane Docker image used for the connect-injected sidecar proxies and mesh, terminating, and ingress gateways. @@ -571,6 +575,19 @@ Use these links to navigate to a particular top-level stanza. anotherLabelKey: another-label-value ``` + - `trustedCAs` ((#v-global-trustedcas)) (`array: []`) - Optional PEM-encoded CA certificates that will be added to trusted system CAs. + + Example: + + ```yaml + trustedCAs: [ + | + -----BEGIN CERTIFICATE----- + MIIC7jCCApSgAwIBAgIRAIq2zQEVexqxvtxP6J0bXAwwCgYIKoZIzj0EAwIwgbkx + ... + ] + ``` + ### server ((#h-server)) - `server` ((#v-server)) - Server, when enabled, configures a server cluster to run. This should @@ -585,7 +602,7 @@ Use these links to navigate to a particular top-level stanza. Consul server agents. - `replicas` ((#v-server-replicas)) (`integer: 1`) - The number of server agents to run. This determines the fault tolerance of - the cluster. Please refer to the [deployment table](/consul/docs/architecture/consensus#deployment-table) + the cluster. Please refer to the [deployment table](https://developer.hashicorp.com/consul/docs/architecture/consensus#deployment-table) for more information. - `bootstrapExpect` ((#v-server-bootstrapexpect)) (`int: null`) - The number of servers that are expected to be running. @@ -624,7 +641,7 @@ Use these links to navigate to a particular top-level stanza. Vault Secrets backend: If you are using Vault as a secrets backend, a Vault Policy must be created which allows `["create", "update"]` capabilities on the PKI issuing endpoint, which is usually of the form `pki/issue/consul-server`. - Complete [this tutorial](/consul/tutorials/vault-secure/vault-pki-consul-secure-tls) + Complete [this tutorial](https://developer.hashicorp.com/consul/tutorials/vault-secure/vault-pki-consul-secure-tls) to learn how to generate a compatible certificate. Note: when using TLS, both the `server.serverCert` and `global.tls.caCert` which points to the CA endpoint of this PKI engine must be provided. @@ -664,15 +681,15 @@ Use these links to navigate to a particular top-level stanza. storage classes, the PersistentVolumeClaims would need to be manually created. A `null` value will use the Kubernetes cluster's default StorageClass. If a default StorageClass does not exist, you will need to create one. - Refer to the [Read/Write Tuning](/consul/docs/install/performance#read-write-tuning) + Refer to the [Read/Write Tuning](https://developer.hashicorp.com/consul/docs/install/performance#read-write-tuning) section of the Server Performance Requirements documentation for considerations around choosing a performant storage class. - ~> **Note:** The [Reference Architecture](/consul/tutorials/production-deploy/reference-architecture#hardware-sizing-for-consul-servers) + ~> **Note:** The [Reference Architecture](https://developer.hashicorp.com/consul/tutorials/production-deploy/reference-architecture#hardware-sizing-for-consul-servers) contains best practices and recommendations for selecting suitable hardware sizes for your Consul servers. - - `connect` ((#v-server-connect)) (`boolean: true`) - This will enable/disable [service mesh](/consul/docs/connect). Setting this to true + - `connect` ((#v-server-connect)) (`boolean: true`) - This will enable/disable [service mesh](https://developer.hashicorp.com/consul/docs/connect). Setting this to true _will not_ automatically secure pod communication, this setting will only enable usage of the feature. Consul will automatically initialize a new CA and set of certificates. Additional service mesh settings can be configured @@ -724,7 +741,7 @@ Use these links to navigate to a particular top-level stanza. control a rolling update of Consul server agents. This value specifies the [partition](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#partitions) for performing a rolling update. Please read the linked Kubernetes - and [Upgrade Consul](/consul/docs/k8s/upgrade#upgrading-consul-servers) + and [Upgrade Consul](https://developer.hashicorp.com/consul/docs/k8s/upgrade#upgrading-consul-servers) documentation for more information. - `disruptionBudget` ((#v-server-disruptionbudget)) - This configures the [`PodDisruptionBudget`](https://kubernetes.io/docs/tasks/run-application/configure-pdb/) @@ -740,7 +757,7 @@ Use these links to navigate to a particular top-level stanza. --set 'server.disruptionBudget.maxUnavailable=0'` flag to the helm chart installation command because of a limitation in the Helm templating language. - - `extraConfig` ((#v-server-extraconfig)) (`string: {}`) - A raw string of extra [JSON configuration](/consul/docs/agent/config/config-files) for Consul + - `extraConfig` ((#v-server-extraconfig)) (`string: {}`) - A raw string of extra [JSON configuration](https://developer.hashicorp.com/consul/docs/agent/config/config-files) for Consul servers. This will be saved as-is into a ConfigMap that is read by the Consul server agents. This can be used to add additional configuration that isn't directly exposed by the chart. @@ -817,13 +834,13 @@ Use these links to navigate to a particular top-level stanza. ``` - `tolerations` ((#v-server-tolerations)) (`string: ""`) - Toleration settings for server pods. This - should be a multi-line string matching the - [Tolerations](https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/) + should be a multi-line string matching the + [Tolerations](https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/) array in a Pod spec. - `topologySpreadConstraints` ((#v-server-topologyspreadconstraints)) (`string: ""`) - Pod topology spread constraints for server pods. - This should be a multi-line YAML string matching the - [`topologySpreadConstraints`](https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/) + This should be a multi-line YAML string matching the + [`topologySpreadConstraints`](https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/) array in a Pod Spec. This requires K8S >= 1.18 (beta) or 1.19 (stable). @@ -916,19 +933,19 @@ Use these links to navigate to a particular top-level stanza. feature, in case kubernetes cluster is behind egress http proxies. Additionally, it could be used to configure custom consul parameters. - - `snapshotAgent` ((#v-server-snapshotagent)) - Values for setting up and running - [snapshot agents](/consul/commands/snapshot/agent) + - `snapshotAgent` ((#v-server-snapshotagent)) - Values for setting up and running + [snapshot agents](https://developer.hashicorp.com/consul/commands/snapshot/agent) within the Consul clusters. They run as a sidecar with Consul servers. - `enabled` ((#v-server-snapshotagent-enabled)) (`boolean: false`) - If true, the chart will install resources necessary to run the snapshot agent. - `interval` ((#v-server-snapshotagent-interval)) (`string: 1h`) - Interval at which to perform snapshots. - Refer to [`interval`](/consul/commands/snapshot/agent#interval) + Refer to [`interval`](https://developer.hashicorp.com/consul/commands/snapshot/agent#interval) - `configSecret` ((#v-server-snapshotagent-configsecret)) - A Kubernetes or Vault secret that should be manually created to contain the entire config to be used on the snapshot agent. This is the preferred method of configuration since there are usually storage - credentials present. Please refer to the [Snapshot agent config](/consul/commands/snapshot/agent#config-file-options) + credentials present. Please refer to the [Snapshot agent config](https://developer.hashicorp.com/consul/commands/snapshot/agent#config-file-options) for details. - `secretName` ((#v-server-snapshotagent-configsecret-secretname)) (`string: null`) - The name of the Kubernetes secret or Vault secret path that holds the snapshot agent config. @@ -986,7 +1003,7 @@ Use these links to navigate to a particular top-level stanza. - `k8sAuthMethodHost` ((#v-externalservers-k8sauthmethodhost)) (`string: null`) - If you are setting `global.acls.manageSystemACLs` and `connectInject.enabled` to true, set `k8sAuthMethodHost` to the address of the Kubernetes API server. This address must be reachable from the Consul servers. - Please refer to the [Kubernetes Auth Method documentation](/consul/docs/security/acl/auth-methods/kubernetes). + Please refer to the [Kubernetes Auth Method documentation](https://developer.hashicorp.com/consul/docs/security/acl/auth-methods/kubernetes). You could retrieve this value from your `kubeconfig` by running: @@ -1009,7 +1026,7 @@ Use these links to navigate to a particular top-level stanza. - `image` ((#v-client-image)) (`string: null`) - The name of the Docker image (including any tag) for the containers running Consul client agents. - - `join` ((#v-client-join)) (`array: null`) - A list of valid [`-retry-join` values](/consul/docs/agent/config/cli-flags#_retry_join). + - `join` ((#v-client-join)) (`array: null`) - A list of valid [`-retry-join` values](https://developer.hashicorp.com/consul/docs/agent/config/cli-flags#_retry_join). If this is `null` (default), then the clients will attempt to automatically join the server cluster running within Kubernetes. This means that with `server.enabled` set to true, clients will automatically @@ -1030,7 +1047,7 @@ Use these links to navigate to a particular top-level stanza. required for service mesh. - `nodeMeta` ((#v-client-nodemeta)) - nodeMeta specifies an arbitrary metadata key/value pair to associate with the node - (refer to [`-node-meta`](/consul/docs/agent/config/cli-flags#_node_meta)) + (refer to [`-node-meta`](https://developer.hashicorp.com/consul/docs/agent/config/cli-flags#_node_meta)) - `pod-name` ((#v-client-nodemeta-pod-name)) (`string: ${HOSTNAME}`) @@ -1074,7 +1091,7 @@ Use these links to navigate to a particular top-level stanza. - `tlsInit` ((#v-client-containersecuritycontext-tlsinit)) (`map`) - The tls-init initContainer - - `extraConfig` ((#v-client-extraconfig)) (`string: {}`) - A raw string of extra [JSON configuration](/consul/docs/agent/config/config-files) for Consul + - `extraConfig` ((#v-client-extraconfig)) (`string: {}`) - A raw string of extra [JSON configuration](https://developer.hashicorp.com/consul/docs/agent/config/config-files) for Consul clients. This will be saved as-is into a ConfigMap that is read by the Consul client agents. This can be used to add additional configuration that isn't directly exposed by the chart. @@ -1340,16 +1357,16 @@ Use these links to navigate to a particular top-level stanza. will inherit from `global.metrics.enabled` value. - `provider` ((#v-ui-metrics-provider)) (`string: prometheus`) - Provider for metrics. Refer to - [`metrics_provider`](/consul/docs/agent/config/config-files#ui_config_metrics_provider) + [`metrics_provider`](https://developer.hashicorp.com/consul/docs/agent/config/config-files#ui_config_metrics_provider) This value is only used if `ui.enabled` is set to true. - `baseURL` ((#v-ui-metrics-baseurl)) (`string: http://prometheus-server`) - baseURL is the URL of the prometheus server, usually the service URL. This value is only used if `ui.enabled` is set to true. - - `dashboardURLTemplates` ((#v-ui-dashboardurltemplates)) - Corresponds to [`dashboard_url_templates`](/consul/docs/agent/config/config-files#ui_config_dashboard_url_templates) + - `dashboardURLTemplates` ((#v-ui-dashboardurltemplates)) - Corresponds to [`dashboard_url_templates`](https://developer.hashicorp.com/consul/docs/agent/config/config-files#ui_config_dashboard_url_templates) configuration. - - `service` ((#v-ui-dashboardurltemplates-service)) (`string: ""`) - Sets [`dashboardURLTemplates.service`](/consul/docs/agent/config/config-files#ui_config_dashboard_url_templates_service). + - `service` ((#v-ui-dashboardurltemplates-service)) (`string: ""`) - Sets [`dashboardURLTemplates.service`](https://developer.hashicorp.com/consul/docs/agent/config/config-files#ui_config_dashboard_url_templates_service). ### syncCatalog ((#h-synccatalog)) @@ -1369,7 +1386,7 @@ Use these links to navigate to a particular top-level stanza. to run the sync program. - `default` ((#v-synccatalog-default)) (`boolean: true`) - If true, all valid services in K8S are - synced by default. If false, the service must be [annotated](/consul/docs/k8s/service-sync#enable-and-disable-sync) + synced by default. If false, the service must be [annotated](https://developer.hashicorp.com/consul/docs/k8s/service-sync#enable-and-disable-sync) properly to sync. In either case an annotation can override the default. @@ -1467,6 +1484,19 @@ Use these links to navigate to a particular top-level stanza. or may not be broadly accessible depending on your Kubernetes cluster. Set this to false to skip syncing ClusterIP services. + - `ingress` ((#v-synccatalog-ingress)) + + - `enabled` ((#v-synccatalog-ingress-enabled)) (`boolean: false`) - Syncs the hostname from a Kubernetes Ingress resource to service registrations + when a rule matched a service. Currently only supports host based routing and + not path based routing. The only supported path on an ingress rule is "/". + Set this to false to skip syncing Ingress services. + + Currently, port 80 is synced if there is not TLS entry for the hostname. Syncs the port + 443 if there is a TLS entry that matches the hostname. + + - `loadBalancerIPs` ((#v-synccatalog-ingress-loadbalancerips)) (`boolean: false`) - Requires syncIngress to be `true`. syncs the LoadBalancer IP from a Kubernetes Ingress + resource instead of the hostname to service registrations when a rule matched a service. + - `nodePortSyncType` ((#v-synccatalog-nodeportsynctype)) (`string: ExternalFirst`) - Configures the type of syncing that happens for NodePort services. The valid options are: ExternalOnly, InternalOnly, ExternalFirst. @@ -1549,7 +1579,7 @@ Use these links to navigate to a particular top-level stanza. - `default` ((#v-connectinject-default)) (`boolean: false`) - If true, the injector will inject the Connect sidecar into all pods by default. Otherwise, pods must specify the - [injection annotation](/consul/docs/k8s/connect#consul-hashicorp-com-connect-inject) + [injection annotation](https://developer.hashicorp.com/consul/docs/k8s/connect#consul-hashicorp-com-connect-inject) to opt-in to service mesh sidecar injection. If this is true, pods can use the same annotation to explicitly opt-out of injection. @@ -1839,8 +1869,8 @@ Use these links to navigate to a particular top-level stanza. If set to an empty string all service accounts can log in. This only has effect if ACLs are enabled. - Refer to Auth methods [Binding rules](/consul/docs/security/acl/auth-methods#binding-rules) - and [Trusted identiy attributes](/consul/docs/security/acl/auth-methods/kubernetes#trusted-identity-attributes) + Refer to Auth methods [Binding rules](https://developer.hashicorp.com/consul/docs/security/acl/auth-methods#binding-rules) + and [Trusted identiy attributes](https://developer.hashicorp.com/consul/docs/security/acl/auth-methods/kubernetes#trusted-identity-attributes) for more details. Requires Consul >= v1.5. @@ -1893,7 +1923,7 @@ Use these links to navigate to a particular top-level stanza. - `cpu` ((#v-connectinject-sidecarproxy-resources-limits-cpu)) (`string: null`) - Recommended production default: 100m - `initContainer` ((#v-connectinject-initcontainer)) (`map`) - The resource settings for the connect injected init container. If null, the resources - won't be set for the initContainer. The defaults are optimized for developer instances of + won't be set for the initContainer. The defaults are optimized for developer instances of Kubernetes, however they should be tweaked with the recommended defaults as shown below to speed up service registration times. - `resources` ((#v-connectinject-initcontainer-resources)) @@ -1912,11 +1942,11 @@ Use these links to navigate to a particular top-level stanza. ### meshGateway ((#h-meshgateway)) -- `meshGateway` ((#v-meshgateway)) - [Mesh Gateways](/consul/docs/connect/gateways/mesh-gateway) enable Consul service mesh to work across Consul datacenters. +- `meshGateway` ((#v-meshgateway)) - [Mesh Gateways](https://developer.hashicorp.com/consul/docs/connect/gateways/mesh-gateway) enable Consul service mesh to work across Consul datacenters. - - `enabled` ((#v-meshgateway-enabled)) (`boolean: false`) - If [mesh gateways](/consul/docs/connect/gateways/mesh-gateway) are enabled, a Deployment will be created that runs + - `enabled` ((#v-meshgateway-enabled)) (`boolean: false`) - If [mesh gateways](https://developer.hashicorp.com/consul/docs/connect/gateways/mesh-gateway) are enabled, a Deployment will be created that runs gateways and Consul service mesh will be configured to use gateways. - This setting is required for [cluster peering](/consul/docs/k8s/connect/cluster-peering/tech-specs). + This setting is required for [cluster peering](https://developer.hashicorp.com/consul/docs/connect/cluster-peering/k8s). Requirements: consul 1.6.0+ if using `global.acls.manageSystemACLs``. - `replicas` ((#v-meshgateway-replicas)) (`integer: 1`) - Number of replicas for the Deployment. @@ -2037,7 +2067,7 @@ Use these links to navigate to a particular top-level stanza. - `tolerations` ((#v-meshgateway-tolerations)) (`string: null`) - Optional YAML string to specify tolerations. - `topologySpreadConstraints` ((#v-meshgateway-topologyspreadconstraints)) (`string: ""`) - Pod topology spread constraints for mesh gateway pods. - This should be a multi-line YAML string matching the + This should be a multi-line YAML string matching the [`topologySpreadConstraints`](https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/) array in a Pod Spec. @@ -2080,7 +2110,8 @@ Use these links to navigate to a particular top-level stanza. for a specific gateway. Requirements: consul >= 1.8.0 - - `enabled` ((#v-ingressgateways-enabled)) (`boolean: false`) - Enable ingress gateway deployment. Requires `connectInject.enabled=true`. + - `enabled` ((#v-ingressgateways-enabled)) (`boolean: false`) - Enable ingress gateway deployment. Requires `connectInject.enabled=true` + and `client.enabled=true`. - `defaults` ((#v-ingressgateways-defaults)) - Defaults sets default values for all gateway fields. With the exception of annotations, defining any of these values in the `gateways` list @@ -2150,7 +2181,7 @@ Use these links to navigate to a particular top-level stanza. - `tolerations` ((#v-ingressgateways-defaults-tolerations)) (`string: null`) - Optional YAML string to specify tolerations. - `topologySpreadConstraints` ((#v-ingressgateways-defaults-topologyspreadconstraints)) (`string: ""`) - Pod topology spread constraints for ingress gateway pods. - This should be a multi-line YAML string matching the + This should be a multi-line YAML string matching the [`topologySpreadConstraints`](https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/) array in a Pod Spec. @@ -2209,7 +2240,8 @@ Use these links to navigate to a particular top-level stanza. for a specific gateway. Requirements: consul >= 1.8.0 - - `enabled` ((#v-terminatinggateways-enabled)) (`boolean: false`) - Enable terminating gateway deployment. Requires `connectInject.enabled=true`. + - `enabled` ((#v-terminatinggateways-enabled)) (`boolean: false`) - Enable terminating gateway deployment. Requires `connectInject.enabled=true` + and `client.enabled=true`. - `defaults` ((#v-terminatinggateways-defaults)) - Defaults sets default values for all gateway fields. With the exception of annotations, defining any of these values in the `gateways` list @@ -2343,7 +2375,7 @@ Use these links to navigate to a particular top-level stanza. beta.kubernetes.io/arch: amd64 ``` - - `tolerations` ((#v-apigateway-managedgatewayclass-tolerations)) (`string: null`) - Toleration settings for gateway pods created with the managed gateway class. + - `tolerations` ((#v-apigateway-managedgatewayclass-tolerations)) (`string: null`) - Toleration settings for gateway pods created with the managed gateway class. This should be a multi-line string matching the [Tolerations](https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/) array in a Pod spec. @@ -2460,6 +2492,76 @@ Use these links to navigate to a particular top-level stanza. - `enabled` ((#v-tests-enabled)) (`boolean: true`) +### telemetryCollector ((#h-telemetrycollector)) + +- `telemetryCollector` ((#v-telemetrycollector)) + + - `enabled` ((#v-telemetrycollector-enabled)) (`boolean: false`) - Enables the consul-telemetry-collector deployment + + - `image` ((#v-telemetrycollector-image)) (`string: hashicorp/consul-telemetry-collector:0.0.1`) - The name of the Docker image (including any tag) for the containers running + the consul-telemetry-collector + + - `resources` ((#v-telemetrycollector-resources)) (`map`) - The resource settings for consul-telemetry-collector pods. + + - `replicas` ((#v-telemetrycollector-replicas)) (`integer: 1`) - This value sets the number of consul-telemetry-collector replicas to deploy. + + - `customExporterConfig` ((#v-telemetrycollector-customexporterconfig)) (`string: null`) - This value defines additional configuration for the telemetry collector. It should be formatted as a multi-line + json blob string + + ```yaml + customExporterConfig: | + {"http_collector_endpoint": "other-otel-collector"} + ``` + + - `service` ((#v-telemetrycollector-service)) + + - `annotations` ((#v-telemetrycollector-service-annotations)) (`string: null`) - This value defines additional annotations for the server service account. This should be formatted as a multi-line + string. + + ```yaml + annotations: | + "sample/annotation1": "foo" + "sample/annotation2": "bar" + ``` + + - `serviceAccount` ((#v-telemetrycollector-serviceaccount)) + + - `annotations` ((#v-telemetrycollector-serviceaccount-annotations)) (`string: null`) - This value defines additional annotations for the telemetry-collector's service account. This should be formatted + as a multi-line string. + + ```yaml + annotations: | + "sample/annotation1": "foo" + "sample/annotation2": "bar" + ``` + + - `cloud` ((#v-telemetrycollector-cloud)) + + - `clientId` ((#v-telemetrycollector-cloud-clientid)) + + - `secretName` ((#v-telemetrycollector-cloud-clientid-secretname)) (`string: null`) + + - `secretKey` ((#v-telemetrycollector-cloud-clientid-secretkey)) (`string: null`) + + - `clientSecret` ((#v-telemetrycollector-cloud-clientsecret)) + + - `secretName` ((#v-telemetrycollector-cloud-clientsecret-secretname)) (`string: null`) + + - `secretKey` ((#v-telemetrycollector-cloud-clientsecret-secretkey)) (`string: null`) + + - `initContainer` ((#v-telemetrycollector-initcontainer)) + + - `resources` ((#v-telemetrycollector-initcontainer-resources)) (`map`) - The resource settings for consul-telemetry-collector initContainer. + + - `nodeSelector` ((#v-telemetrycollector-nodeselector)) (`string: null`) - Optional YAML string to specify a nodeSelector config. + + - `priorityClassName` ((#v-telemetrycollector-priorityclassname)) (`string: ""`) - Optional priorityClassName. + + - `extraEnvironmentVars` ((#v-telemetrycollector-extraenvironmentvars)) (`map`) - A list of extra environment variables to set within the stateful set. + These could be used to include proxy settings required for cloud auto-join + feature, in case kubernetes cluster is behind egress http proxies. Additionally, + it could be used to configure custom consul parameters. + ## Helm Chart Examples From 77f44fa87823ac59cbe41068b742b9e02c122ed8 Mon Sep 17 00:00:00 2001 From: Matt Keeler Date: Mon, 5 Jun 2023 16:08:39 -0400 Subject: [PATCH 29/72] Various bits of cleanup detected when using Go Workspaces (#17462) TLDR with many modules the versions included in each diverged quite a bit. Attempting to use Go Workspaces produces a bunch of errors. This commit: 1. Fixes envoy-library-references.sh to work again 2. Ensures we are pulling in go-control-plane@v0.11.0 everywhere (previously it was at that version in some modules and others were much older) 3. Remove one usage of golang/protobuf that caused us to have a direct dependency on it. 4. Remove deprecated usage of the Endpoint field in the grpc resolver.Target struct. The current version of grpc (v1.55.0) has removed that field and recommended replacement with URL.Opaque and calls to the Endpoint() func when needing to consume the previous field. 4. `go work init ` && `go work sync`. This syncrhonized versions of dependencies from the main workspace/root module to all submodules 5. Updated .gitignore to ignore the go.work and go.work.sum files. This seems to be standard practice at the moment. 6. Update doc comments in protoc-gen-consul-rate-limit to be go fmt compatible 7. Upgraded makefile infra to perform linting, testing and go mod tidy on all modules in a flexible manner. 8. Updated linter rules to prevent usage of golang/protobuf 9. Updated a leader peering test to account for an extra colon in a grpc error message. --- .gitignore | 2 + .golangci.yml | 5 + GNUmakefile | 61 +- agent/consul/leader_peering_test.go | 2 +- .../builtin/ext-authz/structs.go | 4 +- .../builtin/http/localratelimit/ratelimit.go | 4 +- .../property_override_test.go | 1 + .../property-override/structpatcher_test.go | 5 +- agent/grpc-internal/resolver/resolver.go | 2 +- agent/grpc-internal/resolver/resolver_test.go | 3 +- .../testutil/testservice/simple.pb.go | 2 +- agent/xds/z_xds_packages.go | 66 +- api/go.mod | 44 +- api/go.sum | 169 +- .../scripts/envoy-library-references.sh | 7 +- envoyextensions/go.mod | 45 +- envoyextensions/go.sum | 217 +- go.mod | 98 +- go.sum | 189 +- internal/tools/proto-gen-rpc-glue/e2e/go.mod | 5 +- internal/tools/proto-gen-rpc-glue/e2e/go.sum | 1 - internal/tools/proto-gen-rpc-glue/go.mod | 11 +- internal/tools/proto-gen-rpc-glue/go.sum | 34 +- .../tools/protoc-gen-consul-rate-limit/go.mod | 4 +- .../tools/protoc-gen-consul-rate-limit/go.sum | 8 +- .../protoc-gen-consul-rate-limit/main.go | 51 +- .../annotations/ratelimit/ratelimit.pb.go | 2 +- proto-public/go.mod | 27 +- proto-public/go.sum | 133 +- proto-public/pbacl/acl.pb.go | 2 +- proto-public/pbcatalog/v1alpha1/dns.pb.go | 2 +- proto-public/pbcatalog/v1alpha1/health.pb.go | 2 +- proto-public/pbcatalog/v1alpha1/node.pb.go | 2 +- .../pbcatalog/v1alpha1/protocol.pb.go | 2 +- .../pbcatalog/v1alpha1/selector.pb.go | 2 +- proto-public/pbcatalog/v1alpha1/service.pb.go | 2 +- .../v1alpha1/service_endpoints.pb.go | 2 +- proto-public/pbcatalog/v1alpha1/vip.pb.go | 2 +- .../pbcatalog/v1alpha1/workload.pb.go | 14 +- proto-public/pbconnectca/ca.pb.go | 2 +- proto-public/pbdataplane/dataplane.pb.go | 2 +- proto-public/pbdns/dns.pb.go | 2 +- proto-public/pbmesh/v1alpha1/connection.pb.go | 2 +- proto-public/pbmesh/v1alpha1/expose.pb.go | 2 +- proto-public/pbmesh/v1alpha1/proxy.pb.go | 18 +- proto-public/pbmesh/v1alpha1/routing.pb.go | 2 +- proto-public/pbmesh/v1alpha1/upstreams.pb.go | 2 +- proto-public/pbresource/resource.pb.go | 2 +- .../pbserverdiscovery/serverdiscovery.pb.go | 2 +- proto/private/pbacl/acl.pb.go | 2 +- proto/private/pbautoconf/auto_config.pb.go | 2 +- proto/private/pbcommon/common.pb.go | 2 +- proto/private/pbconfig/config.pb.go | 10 +- .../private/pbconfigentry/config_entry.pb.go | 2 +- proto/private/pbconnect/connect.pb.go | 2 +- proto/private/pbdemo/v1/demo.pb.go | 2 +- proto/private/pbdemo/v2/demo.pb.go | 2 +- proto/private/pboperator/operator.pb.go | 2 +- proto/private/pbpeering/peering.pb.go | 2 +- proto/private/pbpeerstream/peerstream.pb.go | 2 +- proto/private/pbservice/healthcheck.pb.go | 2 +- proto/private/pbservice/node.pb.go | 2 +- proto/private/pbservice/service.pb.go | 2 +- proto/private/pbstatus/status.pb.go | 2 +- proto/private/pbstorage/raft.pb.go | 2 +- proto/private/pbsubscribe/subscribe.pb.go | 2 +- sdk/go.mod | 29 +- sdk/go.sum | 84 +- .../connect/envoy/test-sds-server/go.mod | 12 +- .../connect/envoy/test-sds-server/go.sum | 2476 ++++++++++++++++- .../connect/envoy/test-sds-server/sds.go | 7 +- test/integration/consul-container/go.mod | 13 +- test/integration/consul-container/go.sum | 34 +- troubleshoot/go.mod | 44 +- troubleshoot/go.sum | 367 ++- troubleshoot/proxy/z_xds_packages.go | 66 +- 76 files changed, 3756 insertions(+), 688 deletions(-) diff --git a/.gitignore b/.gitignore index 9bb786209c..a48d19b74c 100644 --- a/.gitignore +++ b/.gitignore @@ -66,3 +66,5 @@ override.tf.json # Ignore CLI configuration files .terraformrc terraform.rc +/go.work +/go.work.sum diff --git a/.golangci.yml b/.golangci.yml index 245f04d7a9..bac9b716a3 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -88,6 +88,9 @@ linters-settings: - github.com/hashicorp/go-msgpack: recommendations: - github.com/hashicorp/consul-net-rpc/go-msgpack + - github.com/golang/protobuf: + recommendations: + - google.golang.org/protobuf depguard: list-type: denylist @@ -101,7 +104,9 @@ linters-settings: # Default: [] packages-with-error-message: - net/rpc: "only use forked copy in github.com/hashicorp/consul-net-rpc/net/rpc" + - github.com/golang/protobuf: "only use google.golang.org/protobuf" run: timeout: 10m concurrency: 4 + skip-dirs-use-default: false diff --git a/GNUmakefile b/GNUmakefile index 1eed638aa9..e874fa0eb7 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -3,6 +3,8 @@ SHELL = bash +GO_MODULES := $(shell find . -name go.mod -exec dirname {} \; | grep -v "proto-gen-rpc-glue/e2e" | sort) + ### # These version variables can either be a valid string for "go install @" # or the string @DEV to imply use what is currently installed locally. @@ -249,19 +251,13 @@ cov: other-consul dev-build test: other-consul dev-build lint test-internal -go-mod-tidy: - @echo "--> Running go mod tidy" - @cd sdk && go mod tidy - @cd api && go mod tidy - @go mod tidy - @cd test/integration/consul-container && go mod tidy - @cd test/integration/connect/envoy/test-sds-server && go mod tidy - @cd proto-public && go mod tidy - @cd internal/tools/proto-gen-rpc-glue && go mod tidy - @cd internal/tools/proto-gen-rpc-glue/e2e && go mod tidy - @cd internal/tools/proto-gen-rpc-glue/e2e/consul && go mod tidy - @cd internal/tools/protoc-gen-consul-rate-limit && go mod tidy +.PHONY: go-mod-tidy +go-mod-tidy: $(foreach mod,$(GO_MODULES),go-mod-tidy/$(mod)) +.PHONY: mod-tidy/% +go-mod-tidy/%: + @echo "--> Running go mod tidy ($*)" + @cd $* && go mod tidy test-internal: @echo "--> Running go test" @@ -292,6 +288,12 @@ test-internal: @grep '^FAIL' test.log || true @if [ "$$(cat exit-code)" == "0" ] ; then echo "PASS" ; exit 0 ; else exit 1 ; fi +test-all: other-consul dev-build lint $(foreach mod,$(GO_MODULES),test-module/$(mod)) + +test-module/%: + @echo "--> Running go test ($*)" + cd $* && go test $(GOTEST_FLAGS) -tags '$(GOTAGS)' ./... + test-race: $(MAKE) GOTEST_FLAGS=-race @@ -328,21 +330,26 @@ other-consul: echo "Found other running consul agents. This may affect your tests." ; \ exit 1 ; \ fi - -lint: -lint-main lint-container-test-deps - -.PHONY: -lint-main --lint-main: lint-tools - @echo "--> Running golangci-lint" - @golangci-lint run --build-tags '$(GOTAGS)' && \ - (cd api && golangci-lint run --build-tags '$(GOTAGS)') && \ - (cd sdk && golangci-lint run --build-tags '$(GOTAGS)') - @echo "--> Running golangci-lint (container tests)" - @cd test/integration/consul-container && golangci-lint run --build-tags '$(GOTAGS)' - @echo "--> Running lint-consul-retry" - @lint-consul-retry - @echo "--> Running enumcover" - @enumcover ./... + +.PHONY: fmt +fmt: $(foreach mod,$(GO_MODULES),fmt/$(mod)) + +.PHONY: fmt/% +fmt/%: + @echo "--> Running go fmt ($*)" + @cd $* && go fmt ./... + +.PHONY: lint +lint: $(foreach mod,$(GO_MODULES),lint/$(mod)) lint-container-test-deps + +.PHONY: lint/% +lint/%: + @echo "--> Running golangci-lint ($*)" + @cd $* && GOWORK=off golangci-lint run --build-tags '$(GOTAGS)' + @echo "--> Running lint-consul-retry ($*)" + @cd $* && GOWORK=off lint-consul-retry + @echo "--> Running enumcover ($*)" + @cd $* && GOWORK=off enumcover ./... .PHONY: lint-container-test-deps lint-container-test-deps: diff --git a/agent/consul/leader_peering_test.go b/agent/consul/leader_peering_test.go index 55c595fd55..0787115ca7 100644 --- a/agent/consul/leader_peering_test.go +++ b/agent/consul/leader_peering_test.go @@ -1921,7 +1921,7 @@ func Test_Leader_PeeringSync_ServerAddressUpdates(t *testing.T) { require.True(r, found) // We assert for this error to be set which would indicate that we iterated // through a bad address. - require.Contains(r, status.LastSendErrorMessage, "transport: Error while dialing dial tcp: address bad: missing port in address") + require.Contains(r, status.LastSendErrorMessage, "transport: Error while dialing: dial tcp: address bad: missing port in address") require.False(r, status.Connected) }) }) diff --git a/agent/envoyextensions/builtin/ext-authz/structs.go b/agent/envoyextensions/builtin/ext-authz/structs.go index 11b7f49453..979bc8a86c 100644 --- a/agent/envoyextensions/builtin/ext-authz/structs.go +++ b/agent/envoyextensions/builtin/ext-authz/structs.go @@ -167,7 +167,7 @@ func (c extAuthzConfig) isHTTP() bool { // // If the extension is configured with the ext_authz service as an upstream there is no need to insert // a new cluster so this method returns nil. -func (c *extAuthzConfig) toEnvoyCluster(cfg *cmn.RuntimeConfig) (*envoy_cluster_v3.Cluster, error) { +func (c *extAuthzConfig) toEnvoyCluster(_ *cmn.RuntimeConfig) (*envoy_cluster_v3.Cluster, error) { var target *Target if c.isHTTP() { target = c.HttpService.Target @@ -678,8 +678,10 @@ type TransportApiVersion string func (t TransportApiVersion) toEnvoy() envoy_core_v3.ApiVersion { switch strings.ToLower(string(t)) { case "v2": + //nolint:staticcheck return envoy_core_v3.ApiVersion_V2 case "auto": + //nolint:staticcheck return envoy_core_v3.ApiVersion_AUTO default: return envoy_core_v3.ApiVersion_V3 diff --git a/agent/envoyextensions/builtin/http/localratelimit/ratelimit.go b/agent/envoyextensions/builtin/http/localratelimit/ratelimit.go index e70a704aeb..7761982604 100644 --- a/agent/envoyextensions/builtin/http/localratelimit/ratelimit.go +++ b/agent/envoyextensions/builtin/http/localratelimit/ratelimit.go @@ -14,10 +14,10 @@ import ( envoy_http_v3 "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3" envoy_type_v3 "github.com/envoyproxy/go-control-plane/envoy/type/v3" envoy_resource_v3 "github.com/envoyproxy/go-control-plane/pkg/resource/v3" - "github.com/golang/protobuf/ptypes/wrappers" "github.com/hashicorp/go-multierror" "github.com/mitchellh/mapstructure" "google.golang.org/protobuf/types/known/durationpb" + "google.golang.org/protobuf/types/known/wrapperspb" "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/envoyextensions/extensioncommon" @@ -125,7 +125,7 @@ func (r ratelimit) PatchFilter(p extensioncommon.FilterPayload) (*envoy_listener tokenBucket := envoy_type_v3.TokenBucket{} if r.TokensPerFill != nil { - tokenBucket.TokensPerFill = &wrappers.UInt32Value{ + tokenBucket.TokensPerFill = &wrapperspb.UInt32Value{ Value: uint32(*r.TokensPerFill), } } diff --git a/agent/envoyextensions/builtin/property-override/property_override_test.go b/agent/envoyextensions/builtin/property-override/property_override_test.go index f613769aa3..7faa3795c2 100644 --- a/agent/envoyextensions/builtin/property-override/property_override_test.go +++ b/agent/envoyextensions/builtin/property-override/property_override_test.go @@ -559,6 +559,7 @@ type MockPatcher[K proto.Message] struct { appliedPatches []Patch } +//nolint:unparam func (m *MockPatcher[K]) applyPatch(k K, p Patch, _ bool) (result K, e error) { m.appliedPatches = append(m.appliedPatches, p) return k, nil diff --git a/agent/envoyextensions/builtin/property-override/structpatcher_test.go b/agent/envoyextensions/builtin/property-override/structpatcher_test.go index d81f15ebd5..579f0f71c9 100644 --- a/agent/envoyextensions/builtin/property-override/structpatcher_test.go +++ b/agent/envoyextensions/builtin/property-override/structpatcher_test.go @@ -2,18 +2,19 @@ package propertyoverride import ( "fmt" + "testing" + envoy_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3" corev3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" envoy_endpoint_v3 "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3" envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" envoy_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" - _struct "github.com/golang/protobuf/ptypes/struct" "github.com/google/go-cmp/cmp" "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/testing/protocmp" + _struct "google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/wrapperspb" - "testing" ) func TestPatchStruct(t *testing.T) { diff --git a/agent/grpc-internal/resolver/resolver.go b/agent/grpc-internal/resolver/resolver.go index bb2224ee08..d04f1e657e 100644 --- a/agent/grpc-internal/resolver/resolver.go +++ b/agent/grpc-internal/resolver/resolver.go @@ -96,7 +96,7 @@ func (s *ServerResolverBuilder) Build(target resolver.Target, cc resolver.Client } //nolint:staticcheck - serverType, datacenter, err := parseEndpoint(target.Endpoint) + serverType, datacenter, err := parseEndpoint(target.Endpoint()) if err != nil { return nil, err } diff --git a/agent/grpc-internal/resolver/resolver_test.go b/agent/grpc-internal/resolver/resolver_test.go index ab6e403d7d..2bd3f24f99 100644 --- a/agent/grpc-internal/resolver/resolver_test.go +++ b/agent/grpc-internal/resolver/resolver_test.go @@ -3,6 +3,7 @@ package resolver import ( "fmt" "net" + "net/url" "strings" "testing" @@ -40,7 +41,7 @@ func TestServerResolverBuilder(t *testing.T) { _, err := rs.Build(resolver.Target{ Scheme: "consul", Authority: rs.Authority(), - Endpoint: endpoint, + URL: url.URL{Opaque: endpoint}, }, cc, resolver.BuildOptions{}) require.NoError(t, err) diff --git a/agent/grpc-middleware/testutil/testservice/simple.pb.go b/agent/grpc-middleware/testutil/testservice/simple.pb.go index a2981c2f79..18022b3dad 100644 --- a/agent/grpc-middleware/testutil/testservice/simple.pb.go +++ b/agent/grpc-middleware/testutil/testservice/simple.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: simple.proto diff --git a/agent/xds/z_xds_packages.go b/agent/xds/z_xds_packages.go index f2ca8ed13a..7af650a25a 100644 --- a/agent/xds/z_xds_packages.go +++ b/agent/xds/z_xds_packages.go @@ -3,16 +3,31 @@ package xds import ( + _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/config/v3alpha" + _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/http/dynamo/v3" + _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/http/golang/v3alpha" + _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/http/language/v3alpha" _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/http/squash/v3" _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/http/sxg/v3alpha" + _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/client_ssl_auth/v3" + _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/generic_proxy/action/v3" + _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/generic_proxy/codecs/dubbo/v3" + _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/generic_proxy/matcher/v3" + _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/generic_proxy/router/v3" + _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/generic_proxy/v3" _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/kafka_broker/v3" _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/kafka_mesh/v3alpha" _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/mysql_proxy/v3" _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/postgres_proxy/v3alpha" _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/rocketmq_proxy/v3" _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/sip_proxy/router/v3alpha" + _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/sip_proxy/tra/v3alpha" _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/sip_proxy/v3alpha" + _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/matching/input_matchers/hyperscan/v3alpha" + _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/network/connection_balance/dlb/v3alpha" _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/private_key_providers/cryptomb/v3alpha" + _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/private_key_providers/qat/v3alpha" + _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/regex_engines/hyperscan/v3alpha" _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/vcl/v3alpha" _ "github.com/envoyproxy/go-control-plane/envoy/admin/v2alpha" _ "github.com/envoyproxy/go-control-plane/envoy/admin/v3" @@ -36,6 +51,7 @@ import ( _ "github.com/envoyproxy/go-control-plane/envoy/config/common/dynamic_forward_proxy/v2alpha" _ "github.com/envoyproxy/go-control-plane/envoy/config/common/key_value/v3" _ "github.com/envoyproxy/go-control-plane/envoy/config/common/matcher/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/config/common/mutation_rules/v3" _ "github.com/envoyproxy/go-control-plane/envoy/config/common/tap/v2alpha" _ "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" _ "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3" @@ -135,14 +151,16 @@ import ( _ "github.com/envoyproxy/go-control-plane/envoy/data/tap/v2alpha" _ "github.com/envoyproxy/go-control-plane/envoy/data/tap/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/access_loggers/file/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/access_loggers/filters/cel/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/access_loggers/grpc/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/access_loggers/open_telemetry/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/access_loggers/stream/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/access_loggers/wasm/v3" - _ "github.com/envoyproxy/go-control-plane/envoy/extensions/cache/simple_http_cache/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/bootstrap/internal_listener/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/clusters/aggregate/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/clusters/dynamic_forward_proxy/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/clusters/redis/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/common/async_files/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/common/dynamic_forward_proxy/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/common/matching/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/common/ratelimit/v3" @@ -151,6 +169,10 @@ import ( _ "github.com/envoyproxy/go-control-plane/envoy/extensions/compression/brotli/decompressor/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/compression/gzip/compressor/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/compression/gzip/decompressor/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/compression/zstd/compressor/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/compression/zstd/decompressor/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/config/validators/minimum_clusters/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/early_data/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/common/dependency/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/common/fault/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/common/matcher/action/v3" @@ -167,12 +189,14 @@ import ( _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/compressor/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/cors/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/csrf/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/custom_response/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/decompressor/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/dynamic_forward_proxy/v3" - _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/dynamo/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/ext_authz/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/ext_proc/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/fault/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/file_system_buffer/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/gcp_authn/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/grpc_http1_bridge/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/grpc_http1_reverse_bridge/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/grpc_json_transcoder/v3" @@ -189,18 +213,20 @@ import ( _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/oauth2/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/on_demand/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/original_src/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/rate_limit_quota/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/ratelimit/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/rbac/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/router/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/set_metadata/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/stateful_session/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/tap/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/upstream_codec/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/wasm/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/listener/http_inspector/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/listener/original_dst/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/listener/original_src/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/listener/proxy_protocol/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/listener/tls_inspector/v3" - _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/client_ssl_auth/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/connection_limit/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/direct_response/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/dubbo_proxy/router/v3" @@ -217,6 +243,7 @@ import ( _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/sni_dynamic_forward_proxy/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/tcp_proxy/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/thrift_proxy/filters/header_to_metadata/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/thrift_proxy/filters/payload_to_metadata/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/thrift_proxy/filters/ratelimit/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/thrift_proxy/router/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/thrift_proxy/v3" @@ -227,24 +254,49 @@ import ( _ "github.com/envoyproxy/go-control-plane/envoy/extensions/formatter/metadata/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/formatter/req_without_query/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/health_checkers/redis/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/health_checkers/thrift/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/http/cache/file_system_http_cache/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/http/cache/simple_http_cache/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/http/custom_response/local_response_policy/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/http/custom_response/redirect_policy/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/http/early_header_mutation/header_mutation/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/http/header_formatters/preserve_case/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/http/header_validators/envoy_default/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/http/original_ip_detection/custom_header/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/http/original_ip_detection/xff/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/http/stateful_session/cookie/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/http/stateful_session/header/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/internal_redirect/allow_listed_routes/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/internal_redirect/previous_routes/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/internal_redirect/safe_cross_scheme/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/key_value/file_based/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/load_balancing_policies/common/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/load_balancing_policies/least_request/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/load_balancing_policies/maglev/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/load_balancing_policies/random/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/load_balancing_policies/ring_hash/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/load_balancing_policies/round_robin/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/load_balancing_policies/wrr_locality/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/matching/common_inputs/environment_variable/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/matching/common_inputs/network/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/matching/common_inputs/ssl/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/matching/input_matchers/consistent_hashing/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/matching/input_matchers/ip/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/network/dns_resolver/apple/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/network/dns_resolver/cares/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/network/dns_resolver/getaddrinfo/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/network/socket_interface/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/path/match/uri_template/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/path/rewrite/uri_template/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/quic/connection_id_generator/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/quic/crypto_stream/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/quic/proof_source/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/rate_limit_descriptors/expr/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/rbac/matchers/upstream_ip_port/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/regex_engines/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/request_id/uuid/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/resource_monitors/downstream_connections/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/resource_monitors/fixed_heap/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/resource_monitors/injected_resource/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/retry/host/omit_canary_hosts/v3" @@ -254,6 +306,8 @@ import ( _ "github.com/envoyproxy/go-control-plane/envoy/extensions/stat_sinks/graphite_statsd/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/stat_sinks/wasm/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/alts/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/http_11_proxy/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/internal_upstream/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/proxy_protocol/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/quic/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/raw_buffer/v3" @@ -262,11 +316,13 @@ import ( _ "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tap/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tcp_stats/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/udp_packet_writer/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/upstreams/http/generic/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/upstreams/http/http/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/upstreams/http/tcp/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/upstreams/http/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/upstreams/tcp/generic/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/upstreams/tcp/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/wasm/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/watchdog/profile_action/v3" _ "github.com/envoyproxy/go-control-plane/envoy/service/accesslog/v2" @@ -288,6 +344,7 @@ import ( _ "github.com/envoyproxy/go-control-plane/envoy/service/load_stats/v3" _ "github.com/envoyproxy/go-control-plane/envoy/service/metrics/v2" _ "github.com/envoyproxy/go-control-plane/envoy/service/metrics/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/service/rate_limit_quota/v3" _ "github.com/envoyproxy/go-control-plane/envoy/service/ratelimit/v2" _ "github.com/envoyproxy/go-control-plane/envoy/service/ratelimit/v3" _ "github.com/envoyproxy/go-control-plane/envoy/service/route/v3" @@ -309,4 +366,7 @@ import ( _ "github.com/envoyproxy/go-control-plane/envoy/type/tracing/v3" _ "github.com/envoyproxy/go-control-plane/envoy/type/v3" _ "github.com/envoyproxy/go-control-plane/envoy/watchdog/v3" + _ "github.com/envoyproxy/go-control-plane/ratelimit/config/ratelimit/v3" + _ "github.com/envoyproxy/go-control-plane/ratelimit/service/ratelimit/v3" + _ "github.com/envoyproxy/go-control-plane/xdsmatcher/test/proto" ) diff --git a/api/go.mod b/api/go.mod index bd9b2c6780..335a6df7ce 100644 --- a/api/go.mod +++ b/api/go.mod @@ -5,42 +5,42 @@ go 1.19 replace github.com/hashicorp/consul/sdk => ../sdk require ( - github.com/google/go-cmp v0.5.8 + github.com/google/go-cmp v0.5.9 github.com/hashicorp/consul/sdk v0.13.1 - github.com/hashicorp/go-cleanhttp v0.5.1 - github.com/hashicorp/go-hclog v0.12.0 + github.com/hashicorp/go-cleanhttp v0.5.2 + github.com/hashicorp/go-hclog v1.5.0 github.com/hashicorp/go-rootcerts v1.0.2 - github.com/hashicorp/go-uuid v1.0.2 + github.com/hashicorp/go-uuid v1.0.3 github.com/hashicorp/serf v0.10.1 - github.com/mitchellh/mapstructure v1.4.1 - github.com/stretchr/testify v1.7.0 + github.com/mitchellh/mapstructure v1.5.0 + github.com/stretchr/testify v1.8.3 golang.org/x/exp v0.0.0-20230321023759-10a507213a29 ) require ( - github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/fatih/color v1.9.0 // indirect - github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c // indirect - github.com/hashicorp/errwrap v1.0.0 // indirect - github.com/hashicorp/go-immutable-radix v1.0.0 // indirect - github.com/hashicorp/go-msgpack v0.5.3 // indirect - github.com/hashicorp/go-multierror v1.1.0 // indirect + github.com/armon/go-metrics v0.4.1 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/fatih/color v1.14.1 // indirect + github.com/google/btree v1.0.1 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/go-msgpack v0.5.5 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-sockaddr v1.0.2 // indirect github.com/hashicorp/go-version v1.2.1 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/memberlist v0.5.0 // indirect - github.com/kr/pretty v0.2.1 // indirect github.com/kr/text v0.2.0 // indirect - github.com/mattn/go-colorable v0.1.6 // indirect - github.com/mattn/go-isatty v0.0.12 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect github.com/miekg/dns v1.1.41 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect - github.com/stretchr/objx v0.1.0 // indirect - golang.org/x/net v0.0.0-20211216030914-fe4d6282115f // indirect - golang.org/x/sys v0.1.0 // indirect - gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect + github.com/stretchr/objx v0.5.0 // indirect + golang.org/x/net v0.10.0 // indirect + golang.org/x/sync v0.2.0 // indirect + golang.org/x/sys v0.8.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/api/go.sum b/api/go.sum index 8e56a6b16f..fd85203e34 100644 --- a/api/go.sum +++ b/api/go.sum @@ -1,33 +1,67 @@ +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= +github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= +github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= +github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-hclog v0.12.0 h1:d4QkX8FRTYaKaCZBoXYY8zJX2BXjWxurN/GA2tkrmZM= -github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= +github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4= +github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= +github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= @@ -36,8 +70,8 @@ github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjG github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= -github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI= github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -49,22 +83,33 @@ github.com/hashicorp/memberlist v0.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0= github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY= github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.41 h1:WMszZWJG0XmzbK9FEmzH2TVcqYzFesusSIB41b8KHxY= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= @@ -74,55 +119,100 @@ github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= +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= +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.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +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/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= 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/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 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/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= -golang.org/x/net v0.0.0-20211216030914-fe4d6282115f h1:hEYJvxw1lSnWIl8X9ofsYMklzaDs90JI2az5YMd4fPM= -golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= +golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -131,8 +221,15 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/build-support/scripts/envoy-library-references.sh b/build-support/scripts/envoy-library-references.sh index ac8f8a23e0..7f5413bbf7 100644 --- a/build-support/scripts/envoy-library-references.sh +++ b/build-support/scripts/envoy-library-references.sh @@ -28,7 +28,7 @@ if [[ ! -f GNUmakefile ]] || [[ ! -f go.mod ]]; then exit 1 fi -readonly LIBRARY_VERSION="$(grep github.com/envoyproxy/go-control-plane go.mod | awk '{print $2}')" +readonly LIBRARY_VERSION="$(grep -e "github.com/envoyproxy/go-control-plane[[:space:]]" go.mod | awk '{print $2}')" readonly OUTFILE=z_xds_packages.go echo "Fetching envoyproxy/go-control-plane @ ${LIBRARY_VERSION}..." @@ -39,7 +39,7 @@ trap "rm -rf _envoy_tmp" EXIT ( cd _envoy_tmp -git clone git@github.com:envoyproxy/go-control-plane +git clone https://github.com/envoyproxy/go-control-plane cd go-control-plane git checkout -b consul-temp "${LIBRARY_VERSION}" @@ -64,7 +64,6 @@ echo ")" >> "${OUTFILE}" goimports -w "${OUTFILE}" mv -f "${OUTFILE}" ../../agent/xds -) echo "Generating a fresh troubleshoot ${OUTFILE} file..." cat <<-EOF > "${OUTFILE}" @@ -84,7 +83,7 @@ echo ")" >> "${OUTFILE}" goimports -w "${OUTFILE}" -mv -f "${OUTFILE}" ../../troubleshoot/connect +mv -f "${OUTFILE}" ../../troubleshoot/proxy ) diff --git a/envoyextensions/go.mod b/envoyextensions/go.mod index 225ed86d58..6a6128fa6c 100644 --- a/envoyextensions/go.mod +++ b/envoyextensions/go.mod @@ -1,42 +1,45 @@ module github.com/hashicorp/consul/envoyextensions -go 1.19 +go 1.20 replace github.com/hashicorp/consul/api => ../api require ( - github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1 + github.com/envoyproxy/go-control-plane v0.11.0 github.com/hashicorp/consul/api v1.20.0 github.com/hashicorp/consul/sdk v0.13.1 - github.com/hashicorp/go-hclog v1.2.1 + github.com/hashicorp/go-hclog v1.5.0 github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/go-version v1.2.1 - github.com/stretchr/testify v1.7.2 - google.golang.org/protobuf v1.27.1 + github.com/stretchr/testify v1.8.3 + google.golang.org/protobuf v1.30.0 ) require ( - github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da // indirect - github.com/census-instrumentation/opencensus-proto v0.2.1 // indirect - github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/envoyproxy/protoc-gen-validate v0.1.0 // indirect - github.com/fatih/color v1.13.0 // indirect - github.com/golang/protobuf v1.5.0 // indirect - github.com/hashicorp/errwrap v1.0.0 // indirect - github.com/hashicorp/go-cleanhttp v0.5.1 // indirect - github.com/hashicorp/go-immutable-radix v1.0.0 // indirect + github.com/armon/go-metrics v0.4.1 // indirect + github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect + github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/envoyproxy/protoc-gen-validate v0.10.0 // indirect + github.com/fatih/color v1.14.1 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect - github.com/hashicorp/go-uuid v1.0.2 // indirect + github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/serf v0.10.1 // indirect - github.com/mattn/go-colorable v0.1.12 // indirect - github.com/mattn/go-isatty v0.0.14 // indirect + github.com/kr/pretty v0.3.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/mapstructure v1.4.1 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect - golang.org/x/sys v0.1.0 // indirect + golang.org/x/sys v0.8.0 // indirect + google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/envoyextensions/go.sum b/envoyextensions/go.sum index c0b34dd3c7..52d5f9ed00 100644 --- a/envoyextensions/go.sum +++ b/envoyextensions/go.sum @@ -1,79 +1,87 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= +github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= +github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe h1:QJDJubh0OEcpeGjC7/8uF9tt4e39U/Ya1uyK+itnNPQ= -github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195 h1:58f1tJ1ra+zFINPlwLWvQsR9CzAKt2e+EWV2yX9oXQ4= +github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1 h1:xvqufLtNVwAhN8NMyWklVgxnWohi+wtMGQMhtxexlm0= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= -github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= +github.com/envoyproxy/go-control-plane v0.11.0 h1:jtLewhRR2vMRNnq2ZZUoCjUlgut+Y0+sDDWPOfwOi1o= +github.com/envoyproxy/go-control-plane v0.11.0/go.mod h1:VnHyVMpzcLvCFt9yUz1UnCwHLhwx1WguiVDV7pTG/tI= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v0.10.0 h1:oIfnZFdC0YhpNNEX+SuIqko4cqqVZeN9IGTrhZje83Y= +github.com/envoyproxy/protoc-gen-validate v0.10.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= +github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw= +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/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/hashicorp/consul/sdk v0.13.1 h1:EygWVWWMczTzXGpO93awkHFzfUka6hLYJ0qhETd+6lY= github.com/hashicorp/consul/sdk v0.13.1/go.mod h1:SW/mM4LbKfqmMvcFu8v+eiQQ7oitXEFeiBe9StxERb0= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-hclog v1.2.1 h1:YQsLlGDJgwhXFpucSPyVbCBviQtjlHv3jLTlp8YmtEw= -github.com/hashicorp/go-hclog v1.2.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= -github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= +github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4= +github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= @@ -81,8 +89,8 @@ github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0S github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= -github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI= github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -94,20 +102,35 @@ github.com/hashicorp/memberlist v0.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0= github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY= github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.41 h1:WMszZWJG0XmzbK9FEmzH2TVcqYzFesusSIB41b8KHxY= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= @@ -115,33 +138,57 @@ github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXx github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= +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= +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/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +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/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= 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/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= @@ -150,46 +197,46 @@ golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvx golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= -golang.org/x/net v0.0.0-20211216030914-fe4d6282115f h1:hEYJvxw1lSnWIl8X9ofsYMklzaDs90JI2az5YMd4fPM= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -203,36 +250,30 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/go.mod b/go.mod index 89ef735d98..4c421c4653 100644 --- a/go.mod +++ b/go.mod @@ -24,18 +24,18 @@ require ( github.com/aws/aws-sdk-go v1.42.34 github.com/coredns/coredns v1.6.6 github.com/coreos/go-oidc v2.1.0+incompatible - github.com/docker/go-connections v0.3.0 - github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1 - github.com/fatih/color v1.13.0 - github.com/fsnotify/fsnotify v1.5.1 + github.com/docker/go-connections v0.4.0 + github.com/envoyproxy/go-control-plane v0.11.0 + github.com/envoyproxy/go-control-plane/xdsmatcher v0.0.0-20230524161521-aaaacbfbe53e + github.com/fatih/color v1.14.1 + github.com/fsnotify/fsnotify v1.6.0 github.com/go-openapi/runtime v0.25.0 github.com/go-openapi/strfmt v0.21.3 - github.com/golang/protobuf v1.5.2 github.com/google/go-cmp v0.5.9 github.com/google/gofuzz v1.2.0 github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 github.com/google/tcpproxy v0.0.0-20180808230851-dfa16c61dad2 - github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 + github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 github.com/hashicorp/consul-awsauth v0.0.0-20220713182709-05ac1c5c2706 github.com/hashicorp/consul-net-rpc v0.0.0-20221205195236-156cfab66a69 github.com/hashicorp/consul/api v1.20.0 @@ -75,7 +75,7 @@ require ( github.com/hashicorp/vault/api/auth/gcp v0.3.0 github.com/hashicorp/vault/sdk v0.7.0 github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 - github.com/imdario/mergo v0.3.13 + github.com/imdario/mergo v0.3.15 github.com/kr/text v0.2.0 github.com/miekg/dns v1.1.41 github.com/mitchellh/cli v1.1.0 @@ -95,31 +95,33 @@ require ( github.com/ryanuber/columnize v2.1.2+incompatible github.com/shirou/gopsutil/v3 v3.22.8 github.com/stretchr/testify v1.8.3 - go.etcd.io/bbolt v1.3.6 + go.etcd.io/bbolt v1.3.7 go.opentelemetry.io/otel v1.16.0 go.opentelemetry.io/otel/metric v1.16.0 go.opentelemetry.io/otel/sdk v1.16.0 go.opentelemetry.io/otel/sdk/metric v0.39.0 go.opentelemetry.io/proto/otlp v0.19.0 go.uber.org/goleak v1.1.10 - golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d - golang.org/x/net v0.8.0 + golang.org/x/crypto v0.1.0 + golang.org/x/net v0.10.0 golang.org/x/oauth2 v0.6.0 - golang.org/x/sync v0.1.0 + golang.org/x/sync v0.2.0 golang.org/x/sys v0.8.0 golang.org/x/time v0.3.0 - google.golang.org/genproto v0.0.0-20220921223823-23cae91e6737 - google.golang.org/grpc v1.49.0 - google.golang.org/protobuf v1.28.1 + google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 + google.golang.org/grpc v1.55.0 + google.golang.org/protobuf v1.30.0 gopkg.in/square/go-jose.v2 v2.5.1 - gotest.tools/v3 v3.0.3 - k8s.io/api v0.18.2 - k8s.io/apimachinery v0.18.2 - k8s.io/client-go v0.18.2 + gotest.tools/v3 v3.4.0 + k8s.io/api v0.26.2 + k8s.io/apimachinery v0.26.2 + k8s.io/client-go v0.26.2 ) require ( - cloud.google.com/go v0.97.0 // indirect + cloud.google.com/go/compute v1.19.0 // indirect + cloud.google.com/go/compute/metadata v0.2.3 // indirect + cloud.google.com/go/iam v0.13.0 // indirect github.com/Azure/azure-sdk-for-go v44.0.0+incompatible // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect github.com/Azure/go-autorest/autorest v0.11.18 // indirect @@ -132,18 +134,18 @@ require ( github.com/Azure/go-autorest/logger v0.2.1 // indirect github.com/Azure/go-autorest/tracing v0.6.0 // indirect github.com/DataDog/datadog-go v3.2.0+incompatible // indirect - github.com/Microsoft/go-winio v0.4.3 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect github.com/benbjohnson/immutable v0.4.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/speakeasy v0.1.0 // indirect github.com/boltdb/bolt v1.3.1 // indirect github.com/cenkalti/backoff/v3 v3.0.0 // indirect - github.com/census-instrumentation/opencensus-proto v0.2.1 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible // indirect github.com/circonus-labs/circonusllhist v0.1.3 // indirect - github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1 // indirect + github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195 // indirect github.com/coreos/etcd v3.3.27+incompatible // indirect github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect github.com/coreos/pkg v0.0.0-20220810130054-c7d1c02cb6cf // indirect @@ -151,7 +153,8 @@ require ( github.com/denverdino/aliyungo v0.0.0-20170926055100-d3308649c661 // indirect github.com/digitalocean/godo v1.10.0 // indirect github.com/dimchansky/utfbom v1.1.0 // indirect - github.com/envoyproxy/protoc-gen-validate v0.1.0 // indirect + github.com/emicklei/go-restful/v3 v3.10.1 // indirect + github.com/envoyproxy/protoc-gen-validate v0.10.0 // indirect github.com/form3tech-oss/jwt-go v3.2.2+incompatible // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect @@ -166,14 +169,17 @@ require ( github.com/go-openapi/validate v0.22.1 // indirect github.com/go-ozzo/ozzo-validation v3.6.0+incompatible // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect - github.com/google/btree v1.0.0 // indirect + github.com/google/btree v1.0.1 // indirect + github.com/google/gnostic v0.5.7-v3refs // indirect github.com/google/go-querystring v1.0.0 // indirect - github.com/googleapis/gax-go/v2 v2.1.0 // indirect - github.com/googleapis/gnostic v0.2.0 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect + github.com/googleapis/gax-go/v2 v2.7.1 // indirect github.com/gophercloud/gophercloud v0.3.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-msgpack v0.5.5 // indirect github.com/hashicorp/go-msgpack/v2 v2.0.0 // indirect @@ -189,18 +195,18 @@ require ( github.com/josharian/intern v1.0.0 // indirect github.com/joyent/triton-go v1.7.1-0.20200416154420-6801d15b779f // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect github.com/linode/linodego v0.10.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/mailru/easyjson v0.7.7 // indirect - github.com/mattn/go-colorable v0.1.12 // indirect - github.com/mattn/go-isatty v0.0.14 // indirect - github.com/mattn/go-runewidth v0.0.7 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mattn/go-runewidth v0.0.13 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/nicolai86/scaleway-sdk v1.10.2-0.20180628010248-798f60e20bb2 // indirect github.com/oklog/run v1.0.0 // indirect github.com/oklog/ulid v1.3.1 // indirect @@ -215,10 +221,11 @@ require ( github.com/prometheus/common v0.37.0 // indirect github.com/prometheus/procfs v0.8.0 // indirect github.com/renier/xmlrpc v0.0.0-20170708154548-ce4a1a486c03 // indirect + github.com/rivo/uniseg v0.2.0 // indirect github.com/ryanuber/go-glob v1.0.0 // indirect github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect github.com/segmentio/fasthash v1.0.3 // indirect - github.com/sirupsen/logrus v1.6.0 // indirect + github.com/sirupsen/logrus v1.9.0 // indirect github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect github.com/softlayer/softlayer-go v0.0.0-20180806151055-260589d94c7d // indirect github.com/spf13/pflag v1.0.5 // indirect @@ -230,23 +237,26 @@ require ( github.com/vmware/govmomi v0.18.0 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect go.mongodb.org/mongo-driver v1.11.0 // indirect - go.opencensus.io v0.23.0 // indirect + go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/otel/trace v1.16.0 // indirect go.uber.org/atomic v1.9.0 // indirect golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect - golang.org/x/term v0.6.0 // indirect - golang.org/x/text v0.8.0 // indirect - golang.org/x/tools v0.6.0 // indirect - google.golang.org/api v0.57.0 // indirect + golang.org/x/mod v0.10.0 // indirect + golang.org/x/term v0.8.0 // indirect + golang.org/x/text v0.9.0 // indirect + golang.org/x/tools v0.9.1 // indirect + google.golang.org/api v0.114.0 // indirect google.golang.org/appengine v1.6.7 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.66.2 // indirect gopkg.in/resty.v1 v1.12.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/klog v1.0.0 // indirect - k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89 // indirect - sigs.k8s.io/structured-merge-diff/v3 v3.0.0 // indirect - sigs.k8s.io/yaml v1.2.0 // indirect + k8s.io/klog/v2 v2.90.1 // indirect + k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect + k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 // indirect + sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect ) diff --git a/go.sum b/go.sum index 59ebf57327..3fa9a355c1 100644 --- a/go.sum +++ b/go.sum @@ -25,16 +25,23 @@ cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWc cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= -cloud.google.com/go v0.97.0 h1:3DXvAyifywvq64LfkKaMOmkWPS1CikIQdMe2lY9vxU8= cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/compute v1.19.0 h1:+9zda3WGgW1ZSTlVppLCYFIr48Pa35q1uG2N1itbCEQ= +cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/iam v0.13.0 h1:+CmB+K0J/33d0zSQ9SlFWUeCCEn5XJA0ZMZ3pHE9u8k= +cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= +cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -106,8 +113,8 @@ github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3 github.com/DataDog/datadog-go v3.2.0+incompatible h1:qSG2N4FghB1He/r2mFrWKCaL7dXCilEuNEeAn20fdD4= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.3.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= -github.com/Microsoft/go-winio v0.4.3 h1:M3NHMuPgMSUPdE5epwNUHlRPSVzHs8HpRTrVXhR0myo= -github.com/Microsoft/go-winio v0.4.3/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v1.0.1 h1:iLrQrdwjDd52kHDA5op2UBJFjmOb9g+7scBan4RN8F0= github.com/NYTimes/gziphandler v1.0.1/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= @@ -171,13 +178,15 @@ github.com/caddyserver/caddy v1.0.4/go.mod h1:uruyfVsyMcDb3IOzSKsi1x0wOjy1my/PxO github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c= github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= +github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= @@ -195,9 +204,9 @@ github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XP github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1 h1:zH8ljVhhq7yC0MIeUL/IviMtY8hx2mK8cN9wEYb8ggw= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195 h1:58f1tJ1ra+zFINPlwLWvQsR9CzAKt2e+EWV2yX9oXQ4= +github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/coredns/coredns v1.6.6 h1:GFJXHHBiN2YGp4vS1tltNR0AhI1+TXhb79WT1VAS47I= @@ -245,9 +254,10 @@ github.com/dnaeon/go-vcr v1.0.1 h1:r8L/HqC0Hje5AXMu1ooW8oyQyOFv4GxqpL0nRP7SLLY= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/dnsimple/dnsimple-go v0.30.0/go.mod h1:O5TJ0/U6r7AfT8niYNlmohpLbCSG+c71tQlGr9SeGrg= github.com/dnstap/golang-dnstap v0.0.0-20170829151710-2cf77a2b5e11/go.mod h1:s1PfVYYVmTMgCSPtho4LKBDecEHJWtiVDPNv78Z985U= -github.com/docker/go-connections v0.3.0 h1:3lOnM9cSzgGwx8VfK/NGOW5fLQ0GjIlCkaktF+n1M6o= -github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= @@ -256,6 +266,8 @@ github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFP github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful/v3 v3.10.1 h1:rc42Y5YTp7Am7CS630D7JmhRjq4UlEUuEKfrDac4bSQ= +github.com/emicklei/go-restful/v3 v3.10.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -264,10 +276,13 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1 h1:xvqufLtNVwAhN8NMyWklVgxnWohi+wtMGQMhtxexlm0= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= -github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= +github.com/envoyproxy/go-control-plane v0.11.0 h1:jtLewhRR2vMRNnq2ZZUoCjUlgut+Y0+sDDWPOfwOi1o= +github.com/envoyproxy/go-control-plane v0.11.0/go.mod h1:VnHyVMpzcLvCFt9yUz1UnCwHLhwx1WguiVDV7pTG/tI= +github.com/envoyproxy/go-control-plane/xdsmatcher v0.0.0-20230524161521-aaaacbfbe53e h1:g8euodkL4GdSpVAjfzhssb07KgVmOUqyF4QOmwFumTs= +github.com/envoyproxy/go-control-plane/xdsmatcher v0.0.0-20230524161521-aaaacbfbe53e/go.mod h1:/NGEcKqwNq3HAS2vCqHfsPx9sJZbkiNQ6dGx9gTE/NA= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v0.10.0 h1:oIfnZFdC0YhpNNEX+SuIqko4cqqVZeN9IGTrhZje83Y= +github.com/envoyproxy/protoc-gen-validate v0.10.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.1.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= @@ -276,8 +291,9 @@ github.com/exoscale/egoscale v0.18.1/go.mod h1:Z7OOdzzTOz1Q1PjQXumlz9Wn/CddH0zSY github.com/farsightsec/golang-framestream v0.0.0-20181102145529-8a0cb8ba8710/go.mod h1:eNde4IQyEiA5br02AouhEHCu3p3UzrCdFR4LuQHklMI= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= +github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= @@ -287,8 +303,8 @@ github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq github.com/frankban/quicktest v1.13.0 h1:yNZif1OkDfNoDfb9zZa9aXIpejNR4F23Wely0c+Qdqk= github.com/frankban/quicktest v1.13.0/go.mod h1:qLE0fzW0VuyUAJgPU19zByoIr0HtCHN/r/VLSOOIySU= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= -github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-acme/lego/v3 v3.1.0/go.mod h1:074uqt+JS6plx+c9Xaiz6+L+GBb+7itGtzfcDM2AhEE= @@ -310,6 +326,7 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -396,14 +413,15 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= +github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 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 h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= @@ -431,8 +449,9 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 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 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= 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.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -440,8 +459,11 @@ github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20160524151835-7d79101e329e/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= +github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= +github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= +github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -491,13 +513,16 @@ github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k= +github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.1.0 h1:6DWmvNpomjL1+3liNSZbVns3zsYzzCjm6pRBO1tLeso= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.7.1 h1:gF4c0zjUP2H/s/hEGyLA3I0fA2ZWjzYiONAD6cvPr8A= +github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= -github.com/googleapis/gnostic v0.2.0 h1:l6N3VoaVzTncYYW+9yOz2LJJammFZGBO13sqgEhpy9g= github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4= github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= @@ -512,15 +537,17 @@ github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoA github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 h1:z53tR0945TRRQO/fLEVPI6SMv7ZflF0TEaTAoU7tOzg= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 h1:BZHcxBETFHIdVyhyEfOvn/RdU/QGdLI4y34qQGjGWO0= 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 h1:lLT7ZLSzGLI08vc9cpd+tYmNWjdKDqyr/2L+f6U12Fk= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= github.com/hashicorp/consul-awsauth v0.0.0-20220713182709-05ac1c5c2706 h1:1ZEjnveDe20yFa6lSkfdQZm5BR/b271n0MsB5R2L3us= @@ -660,8 +687,8 @@ github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhK github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= -github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= +github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= +github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/infobloxopen/go-trees v0.0.0-20190313150506-2af4e13f9062/go.mod h1:PcNJqIlcX/dj3DTG/+QQnRvSgTMG6CLpRMjWcv4+J6w= github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ= @@ -712,7 +739,6 @@ github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgo github.com/kolo/xmlrpc v0.0.0-20190717152603-07c4ee3fd181/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -751,24 +777,29 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-tty v0.0.0-20180219170247-931426f7535a/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mholt/certmagic v0.8.3/go.mod h1:91uJzK5K8IWtYQqTi5R2tsxV1pCde+wdGfaRaOZi6aQ= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= @@ -816,6 +847,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G 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/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= @@ -843,11 +876,14 @@ github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FW github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo/v2 v2.4.0 h1:+Ig9nvqgS5OBSACXNk15PLdp0U9XPYROt9CFzVdFGIs= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.23.0 h1:/oxKu9c2HVap+F3PfKort2Hw5DEU+HGlW8n+tguWsys= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A= @@ -938,13 +974,15 @@ github.com/rboyer/safeio v0.2.1/go.mod h1:Cq/cEPK+YXFn622lsQ0K4KsPZSPtaptHHEldsy github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/renier/xmlrpc v0.0.0-20170708154548-ce4a1a486c03 h1:Wdi9nwnhFNAlseAOekn6B5G/+GMtks9UKbvRU/CMM/o= github.com/renier/xmlrpc v0.0.0-20170708154548-ce4a1a486c03/go.mod h1:gRAiPF5C5Nd0eyyRdqIu9qTiFSoZzpTq727b5B8fkkU= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rs/zerolog v1.4.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/russross/blackfriday v0.0.0-20170610170232-067529f716f4/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= @@ -972,8 +1010,9 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/skratchdot/open-golang v0.0.0-20160302144031-75fb7ed4208c/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA= github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= @@ -997,6 +1036,7 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -1011,6 +1051,7 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= 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.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= @@ -1062,8 +1103,8 @@ github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQ go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= -go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= -go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= +go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= +go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= go.etcd.io/etcd v0.5.0-alpha.5.0.20190917205325-a14579fbfb1a/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg= go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng= @@ -1078,8 +1119,9 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= 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/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s= go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4= go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo= @@ -1125,8 +1167,9 @@ golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1165,7 +1208,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= +golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= +golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180611182652-db08ff08e862/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1225,8 +1269,8 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= 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-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1259,8 +1303,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= +golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180622082034-63fc586f45fe/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1321,7 +1365,6 @@ golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1353,13 +1396,16 @@ golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 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= @@ -1371,8 +1417,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1404,7 +1450,6 @@ golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190624190245-7f2218787638/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1449,8 +1494,8 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= +golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= 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= @@ -1483,8 +1528,9 @@ google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNe google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.57.0 h1:4t9zuDlHLcIx0ZEhmXEeFVCRsiOgpgn2QOH9N0MNjPI= google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.114.0 h1:1xQPji6cO2E2vLiI+C/XiFAnsn1WV3mjaEwGLhi3grE= +google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= 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= @@ -1517,6 +1563,7 @@ google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= @@ -1527,6 +1574,7 @@ google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -1552,8 +1600,8 @@ google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEc google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220921223823-23cae91e6737 h1:K1zaaMdYBXRyX+cwFnxj7M6zwDyumLQMZ5xqwGvjreQ= -google.golang.org/genproto v0.0.0-20220921223823-23cae91e6737/go.mod h1:2r/26NEF3bFmT3eC3aZreahSal0C3Shl8Gi6vyDYqOQ= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -1586,8 +1634,8 @@ google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.49.0 h1:WTLtQzmQori5FUH25Pq4WT22oCsv8USpQ+F6rqtsmxw= -google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= +google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= 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= @@ -1602,8 +1650,9 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/DataDog/dd-trace-go.v1 v1.19.0/go.mod h1:DVp8HmDh8PuTu2Z0fVVlBsyWaC++fzwVCaGWylTe3tg= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -1648,11 +1697,10 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= -gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= +gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1662,34 +1710,45 @@ 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= k8s.io/api v0.0.0-20190620084959-7cf5895f2711/go.mod h1:TBhBqb1AWbBQbW3XRusr7n7E4v2+5ZY8r8sAMnyFC5A= -k8s.io/api v0.18.2 h1:wG5g5ZmSVgm5B+eHMIbI9EGATS2L8Z72rda19RIEgY8= k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78= +k8s.io/api v0.26.2 h1:dM3cinp3PGB6asOySalOZxEG4CZ0IAdJsrYZXE/ovGQ= +k8s.io/api v0.26.2/go.mod h1:1kjMQsFE+QHPfskEcVNgL3+Hp88B80uj0QtSOlj8itU= k8s.io/apimachinery v0.0.0-20190612205821-1799e75a0719/go.mod h1:I4A+glKBHiTgiEjQiCCQfCAIcIMFGt291SmsvcrFzJA= -k8s.io/apimachinery v0.18.2 h1:44CmtbmkzVDAhCpRVSiP2R5PPrC2RtlIv/MoB8xpdRA= k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA= +k8s.io/apimachinery v0.26.2 h1:da1u3D5wfR5u2RpLhE/ZtZS2P7QvDgLZTi9wrNZl/tQ= +k8s.io/apimachinery v0.26.2/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I= k8s.io/client-go v0.0.0-20190620085101-78d2af792bab/go.mod h1:E95RaSlHr79aHaX0aGSwcPNfygDiPKOVXdmivCIZT0k= -k8s.io/client-go v0.18.2 h1:aLB0iaD4nmwh7arT2wIn+lMnAq7OswjaejkQ8p9bBYE= k8s.io/client-go v0.18.2/go.mod h1:Xcm5wVGXX9HAA2JJ2sSBUn3tCJ+4SVlCbl2MNNv+CIU= +k8s.io/client-go v0.26.2 h1:s1WkVujHX3kTp4Zn4yGNFK+dlDXy1bAAkIl+cFAiuYI= +k8s.io/client-go v0.26.2/go.mod h1:u5EjOuSyBa09yqqyY7m3abZeovO/7D/WehVVlZ2qcqU= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.1/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.4.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= -k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= +k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw= +k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= k8s.io/kube-openapi v0.0.0-20190306001800-15615b16d372/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= +k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E= +k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= k8s.io/utils v0.0.0-20190221042446-c2654d5206da/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0= k8s.io/utils v0.0.0-20190529001817-6999998975a7/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= -k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89 h1:d4vVOjXm687F1iLSP2q3lyPPuyvTUt3aVoBpi2DqRsU= k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= +k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 h1:kmDqav+P+/5e1i9tFfHq1qcF3sOrDp+YEkVDAHu7Jwk= +k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= +sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= -sigs.k8s.io/structured-merge-diff/v3 v3.0.0 h1:dOmIZBMfhcHS09XZkMyUgkq5trg3/jRyJYFZUiaOp8E= sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/internal/tools/proto-gen-rpc-glue/e2e/go.mod b/internal/tools/proto-gen-rpc-glue/e2e/go.mod index d3d031c002..222f9f9c1a 100644 --- a/internal/tools/proto-gen-rpc-glue/e2e/go.mod +++ b/internal/tools/proto-gen-rpc-glue/e2e/go.mod @@ -4,7 +4,4 @@ go 1.13 replace github.com/hashicorp/consul => ./consul -require ( - github.com/hashicorp/consul v1.11.4 - google.golang.org/protobuf v1.28.1 // indirect -) +require github.com/hashicorp/consul v1.11.4 diff --git a/internal/tools/proto-gen-rpc-glue/e2e/go.sum b/internal/tools/proto-gen-rpc-glue/e2e/go.sum index ca65ab6a32..00f5993c95 100644 --- a/internal/tools/proto-gen-rpc-glue/e2e/go.sum +++ b/internal/tools/proto-gen-rpc-glue/e2e/go.sum @@ -1,4 +1,3 @@ -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= diff --git a/internal/tools/proto-gen-rpc-glue/go.mod b/internal/tools/proto-gen-rpc-glue/go.mod index 1ae6e1d999..0dc54c62df 100644 --- a/internal/tools/proto-gen-rpc-glue/go.mod +++ b/internal/tools/proto-gen-rpc-glue/go.mod @@ -2,10 +2,13 @@ module github.com/hashicorp/consul/internal/tools/proto-gen-rpc-glue go 1.17 -require github.com/stretchr/testify v1.7.1 +require github.com/stretchr/testify v1.8.3 require ( - github.com/davecgh/go-spew v1.1.0 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/kr/pretty v0.3.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/rogpeppe/go-internal v1.9.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/internal/tools/proto-gen-rpc-glue/go.sum b/internal/tools/proto-gen-rpc-glue/go.sum index 2dca7c9c64..5135bf7e71 100644 --- a/internal/tools/proto-gen-rpc-glue/go.sum +++ b/internal/tools/proto-gen-rpc-glue/go.sum @@ -1,11 +1,35 @@ -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/tools/protoc-gen-consul-rate-limit/go.mod b/internal/tools/protoc-gen-consul-rate-limit/go.mod index c1c40938e2..1337ca7371 100644 --- a/internal/tools/protoc-gen-consul-rate-limit/go.mod +++ b/internal/tools/protoc-gen-consul-rate-limit/go.mod @@ -6,5 +6,7 @@ replace github.com/hashicorp/consul/proto-public => ../../../proto-public require ( github.com/hashicorp/consul/proto-public v0.0.0-00010101000000-000000000000 - google.golang.org/protobuf v1.28.1 + google.golang.org/protobuf v1.30.0 ) + +require github.com/google/go-cmp v0.5.9 // indirect diff --git a/internal/tools/protoc-gen-consul-rate-limit/go.sum b/internal/tools/protoc-gen-consul-rate-limit/go.sum index 00f5993c95..a3ed1d4569 100644 --- a/internal/tools/protoc-gen-consul-rate-limit/go.sum +++ b/internal/tools/protoc-gen-consul-rate-limit/go.sum @@ -1,8 +1,8 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= diff --git a/internal/tools/protoc-gen-consul-rate-limit/main.go b/internal/tools/protoc-gen-consul-rate-limit/main.go index b086988c71..b4bf571158 100644 --- a/internal/tools/protoc-gen-consul-rate-limit/main.go +++ b/internal/tools/protoc-gen-consul-rate-limit/main.go @@ -1,38 +1,41 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 -// protoc-gen-consul-rate-limit maintains the mapping of gRPC method names to +// protoc-gen-consul-rate-limit +// This protoc plugin maintains the mapping of gRPC method names to // a specification of how they should be rate-limited. This is used by the gRPC // InTapHandle function (see agent/grpc-middleware/rate.go) to enforce relevant -// limits without having to call the handler. +// limits without having to call the handler. It works in two phases: // -// It works in two phases: +// # Phase 1 // -// 1. Buf/protoc invokes this plugin for each .proto file. We extract the rate -// limit specification from an annotation on the RPC: +// Buf/protoc invokes this plugin for each .proto file. We extract the rate limit +// specification from an annotation on the RPC: // -// service Foo { -// rpc Bar(BarRequest) returns (BarResponse) { -// option (hashicorp.consul.internal.ratelimit.spec) = { -// operation_type: OPERATION_TYPE_WRITE, -// operation_category: OPERATION_CATEGORY_ACL -// }; -// } -// } +// service Foo { +// rpc Bar(BarRequest) returns (BarResponse) { +// option (hashicorp.consul.internal.ratelimit.spec) = { +// operation_type: OPERATION_TYPE_WRITE, +// operation_category: OPERATION_CATEGORY_ACL +// }; +// } +// } // -// We write a JSON array of the limits to protobuf/package/path/.ratelimit.tmp: +// We write a JSON array of the limits to protobuf/package/path/.ratelimit.tmp: // -// [ -// { -// "MethodName": "/Foo/Bar", -// "OperationType": "OPERATION_TYPE_WRITE", -// "OperationCategory": "OPERATION_CATEGORY_ACL" -// } -// ] +// [ +// { +// "MethodName": "/Foo/Bar", +// "OperationType": "OPERATION_TYPE_WRITE", +// "OperationCategory": "OPERATION_CATEGORY_ACL" +// } +// ] // -// 2. The protobuf.sh script (invoked by make proto) runs our postprocess script -// which reads all of the .ratelimit.tmp files in proto and proto-public and -// generates a single Go map in agent/grpc-middleware/rate_limit_mappings.gen.go +// # Phase 2 +// +// The protobuf.sh script (invoked by make proto) runs our postprocess script +// which reads all of the .ratelimit.tmp files in proto and proto-public and +// generates a single Go map in agent/grpc-middleware/rate_limit_mappings.gen.go package main import ( diff --git a/proto-public/annotations/ratelimit/ratelimit.pb.go b/proto-public/annotations/ratelimit/ratelimit.pb.go index c807eacbc2..3514d47ceb 100644 --- a/proto-public/annotations/ratelimit/ratelimit.pb.go +++ b/proto-public/annotations/ratelimit/ratelimit.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: annotations/ratelimit/ratelimit.proto diff --git a/proto-public/go.mod b/proto-public/go.mod index 33a1de3850..d4da0094c1 100644 --- a/proto-public/go.mod +++ b/proto-public/go.mod @@ -3,19 +3,22 @@ module github.com/hashicorp/consul/proto-public go 1.19 require ( - github.com/stretchr/testify v1.5.1 - google.golang.org/grpc v1.37.1 - google.golang.org/protobuf v1.27.1 + github.com/stretchr/testify v1.8.3 + google.golang.org/grpc v1.55.0 + google.golang.org/protobuf v1.30.0 ) require ( - github.com/davecgh/go-spew v1.1.0 // indirect - github.com/golang/protobuf v1.5.0 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/stretchr/objx v0.1.0 // indirect - golang.org/x/net v0.0.0-20190311183353-d8887717615a // indirect - golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a // indirect - golang.org/x/text v0.3.0 // indirect - google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect - gopkg.in/yaml.v2 v2.2.2 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/kr/pretty v0.3.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/rogpeppe/go-internal v1.10.0 // indirect + github.com/stretchr/objx v0.5.0 // indirect + golang.org/x/net v0.10.0 // indirect + golang.org/x/sys v0.8.0 // indirect + golang.org/x/text v0.9.0 // indirect + google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/proto-public/go.sum b/proto-public/go.sum index 212cecb78b..324f509880 100644 --- a/proto-public/go.sum +++ b/proto-public/go.sum @@ -1,94 +1,55 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +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/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +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/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.37.1 h1:ARnQJNWxGyYJpdf/JXscNlQr/uv607ZPU9Z7ogHi+iI= -google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= +google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= +google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/proto-public/pbacl/acl.pb.go b/proto-public/pbacl/acl.pb.go index 61518522e6..f85a9e0b48 100644 --- a/proto-public/pbacl/acl.pb.go +++ b/proto-public/pbacl/acl.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: pbacl/acl.proto diff --git a/proto-public/pbcatalog/v1alpha1/dns.pb.go b/proto-public/pbcatalog/v1alpha1/dns.pb.go index 1c66131ef7..9f6ed584df 100644 --- a/proto-public/pbcatalog/v1alpha1/dns.pb.go +++ b/proto-public/pbcatalog/v1alpha1/dns.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: pbcatalog/v1alpha1/dns.proto diff --git a/proto-public/pbcatalog/v1alpha1/health.pb.go b/proto-public/pbcatalog/v1alpha1/health.pb.go index 01bc1ea6a6..071c405d99 100644 --- a/proto-public/pbcatalog/v1alpha1/health.pb.go +++ b/proto-public/pbcatalog/v1alpha1/health.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: pbcatalog/v1alpha1/health.proto diff --git a/proto-public/pbcatalog/v1alpha1/node.pb.go b/proto-public/pbcatalog/v1alpha1/node.pb.go index 5ee5809a2f..b59d03bb91 100644 --- a/proto-public/pbcatalog/v1alpha1/node.pb.go +++ b/proto-public/pbcatalog/v1alpha1/node.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: pbcatalog/v1alpha1/node.proto diff --git a/proto-public/pbcatalog/v1alpha1/protocol.pb.go b/proto-public/pbcatalog/v1alpha1/protocol.pb.go index 39f13e212b..71e89aab4a 100644 --- a/proto-public/pbcatalog/v1alpha1/protocol.pb.go +++ b/proto-public/pbcatalog/v1alpha1/protocol.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: pbcatalog/v1alpha1/protocol.proto diff --git a/proto-public/pbcatalog/v1alpha1/selector.pb.go b/proto-public/pbcatalog/v1alpha1/selector.pb.go index 51b0d7cc5d..a6f5a3ef88 100644 --- a/proto-public/pbcatalog/v1alpha1/selector.pb.go +++ b/proto-public/pbcatalog/v1alpha1/selector.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: pbcatalog/v1alpha1/selector.proto diff --git a/proto-public/pbcatalog/v1alpha1/service.pb.go b/proto-public/pbcatalog/v1alpha1/service.pb.go index b388472b0e..cd72ccf268 100644 --- a/proto-public/pbcatalog/v1alpha1/service.pb.go +++ b/proto-public/pbcatalog/v1alpha1/service.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: pbcatalog/v1alpha1/service.proto diff --git a/proto-public/pbcatalog/v1alpha1/service_endpoints.pb.go b/proto-public/pbcatalog/v1alpha1/service_endpoints.pb.go index d1c7045103..903de0706b 100644 --- a/proto-public/pbcatalog/v1alpha1/service_endpoints.pb.go +++ b/proto-public/pbcatalog/v1alpha1/service_endpoints.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: pbcatalog/v1alpha1/service_endpoints.proto diff --git a/proto-public/pbcatalog/v1alpha1/vip.pb.go b/proto-public/pbcatalog/v1alpha1/vip.pb.go index dda5ea8238..7ba05aa850 100644 --- a/proto-public/pbcatalog/v1alpha1/vip.pb.go +++ b/proto-public/pbcatalog/v1alpha1/vip.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: pbcatalog/v1alpha1/vip.proto diff --git a/proto-public/pbcatalog/v1alpha1/workload.pb.go b/proto-public/pbcatalog/v1alpha1/workload.pb.go index e5d914e2f6..e1f75d810c 100644 --- a/proto-public/pbcatalog/v1alpha1/workload.pb.go +++ b/proto-public/pbcatalog/v1alpha1/workload.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: pbcatalog/v1alpha1/workload.proto @@ -44,16 +44,16 @@ type Workload struct { Locality *Locality `protobuf:"bytes,5,opt,name=locality,proto3" json:"locality,omitempty"` // deprecated: tags correspond to service tags that you can add to a service for DNS resolution. // - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in pbcatalog/v1alpha1/workload.proto. Tags []string `protobuf:"bytes,6,rep,name=tags,proto3" json:"tags,omitempty"` // deprecated: enable_tag_override indicates whether agents should be overriding tags during anti-entropy syncs. // - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in pbcatalog/v1alpha1/workload.proto. EnableTagOverride bool `protobuf:"varint,7,opt,name=enable_tag_override,json=enableTagOverride,proto3" json:"enable_tag_override,omitempty"` // deprecated: connect_native indicates whether this workload is connect native which will allow it to be // part of MeshEndpoints without having the corresponding Proxy resource. // - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in pbcatalog/v1alpha1/workload.proto. ConnectNative bool `protobuf:"varint,8,opt,name=connect_native,json=connectNative,proto3" json:"connect_native,omitempty"` } @@ -124,7 +124,7 @@ func (x *Workload) GetLocality() *Locality { return nil } -// Deprecated: Do not use. +// Deprecated: Marked as deprecated in pbcatalog/v1alpha1/workload.proto. func (x *Workload) GetTags() []string { if x != nil { return x.Tags @@ -132,7 +132,7 @@ func (x *Workload) GetTags() []string { return nil } -// Deprecated: Do not use. +// Deprecated: Marked as deprecated in pbcatalog/v1alpha1/workload.proto. func (x *Workload) GetEnableTagOverride() bool { if x != nil { return x.EnableTagOverride @@ -140,7 +140,7 @@ func (x *Workload) GetEnableTagOverride() bool { return false } -// Deprecated: Do not use. +// Deprecated: Marked as deprecated in pbcatalog/v1alpha1/workload.proto. func (x *Workload) GetConnectNative() bool { if x != nil { return x.ConnectNative diff --git a/proto-public/pbconnectca/ca.pb.go b/proto-public/pbconnectca/ca.pb.go index 756ab03be6..b4312816f3 100644 --- a/proto-public/pbconnectca/ca.pb.go +++ b/proto-public/pbconnectca/ca.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: pbconnectca/ca.proto diff --git a/proto-public/pbdataplane/dataplane.pb.go b/proto-public/pbdataplane/dataplane.pb.go index 976c9ff20f..eeecbc2bd0 100644 --- a/proto-public/pbdataplane/dataplane.pb.go +++ b/proto-public/pbdataplane/dataplane.pb.go @@ -5,7 +5,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: pbdataplane/dataplane.proto diff --git a/proto-public/pbdns/dns.pb.go b/proto-public/pbdns/dns.pb.go index cdc34de798..c3825d68e9 100644 --- a/proto-public/pbdns/dns.pb.go +++ b/proto-public/pbdns/dns.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: pbdns/dns.proto diff --git a/proto-public/pbmesh/v1alpha1/connection.pb.go b/proto-public/pbmesh/v1alpha1/connection.pb.go index c720a23093..5edc0ee76d 100644 --- a/proto-public/pbmesh/v1alpha1/connection.pb.go +++ b/proto-public/pbmesh/v1alpha1/connection.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: pbmesh/v1alpha1/connection.proto diff --git a/proto-public/pbmesh/v1alpha1/expose.pb.go b/proto-public/pbmesh/v1alpha1/expose.pb.go index 8905de369f..c5e13ecf00 100644 --- a/proto-public/pbmesh/v1alpha1/expose.pb.go +++ b/proto-public/pbmesh/v1alpha1/expose.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: pbmesh/v1alpha1/expose.proto diff --git a/proto-public/pbmesh/v1alpha1/proxy.pb.go b/proto-public/pbmesh/v1alpha1/proxy.pb.go index 036b7a214b..b6ef2edf87 100644 --- a/proto-public/pbmesh/v1alpha1/proxy.pb.go +++ b/proto-public/pbmesh/v1alpha1/proxy.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: pbmesh/v1alpha1/proxy.proto @@ -99,7 +99,7 @@ type ProxyConfiguration struct { // deprecated: prevent usage when using v2 APIs directly. // needed for backwards compatibility // - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in pbmesh/v1alpha1/proxy.proto. OpaqueConfig *structpb.Struct `protobuf:"bytes,4,opt,name=opaque_config,json=opaqueConfig,proto3" json:"opaque_config,omitempty"` } @@ -156,7 +156,7 @@ func (x *ProxyConfiguration) GetBootstrapConfig() *BootstrapConfig { return nil } -// Deprecated: Do not use. +// Deprecated: Marked as deprecated in pbmesh/v1alpha1/proxy.proto. func (x *ProxyConfiguration) GetOpaqueConfig() *structpb.Struct { if x != nil { return x.OpaqueConfig @@ -187,11 +187,11 @@ type DynamicConfig struct { // local_workload_address, local_workload_port, and local_workload_socket_path // are deprecated and are only needed for migration of existing resources. // - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in pbmesh/v1alpha1/proxy.proto. LocalWorkloadAddress string `protobuf:"bytes,10,opt,name=local_workload_address,json=localWorkloadAddress,proto3" json:"local_workload_address,omitempty"` - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in pbmesh/v1alpha1/proxy.proto. LocalWorkloadPort uint32 `protobuf:"varint,11,opt,name=local_workload_port,json=localWorkloadPort,proto3" json:"local_workload_port,omitempty"` - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in pbmesh/v1alpha1/proxy.proto. LocalWorkloadSocketPath string `protobuf:"bytes,12,opt,name=local_workload_socket_path,json=localWorkloadSocketPath,proto3" json:"local_workload_socket_path,omitempty"` } @@ -290,7 +290,7 @@ func (x *DynamicConfig) GetLocalClusterJson() string { return "" } -// Deprecated: Do not use. +// Deprecated: Marked as deprecated in pbmesh/v1alpha1/proxy.proto. func (x *DynamicConfig) GetLocalWorkloadAddress() string { if x != nil { return x.LocalWorkloadAddress @@ -298,7 +298,7 @@ func (x *DynamicConfig) GetLocalWorkloadAddress() string { return "" } -// Deprecated: Do not use. +// Deprecated: Marked as deprecated in pbmesh/v1alpha1/proxy.proto. func (x *DynamicConfig) GetLocalWorkloadPort() uint32 { if x != nil { return x.LocalWorkloadPort @@ -306,7 +306,7 @@ func (x *DynamicConfig) GetLocalWorkloadPort() uint32 { return 0 } -// Deprecated: Do not use. +// Deprecated: Marked as deprecated in pbmesh/v1alpha1/proxy.proto. func (x *DynamicConfig) GetLocalWorkloadSocketPath() string { if x != nil { return x.LocalWorkloadSocketPath diff --git a/proto-public/pbmesh/v1alpha1/routing.pb.go b/proto-public/pbmesh/v1alpha1/routing.pb.go index f979d3bf68..19f6a7d1c1 100644 --- a/proto-public/pbmesh/v1alpha1/routing.pb.go +++ b/proto-public/pbmesh/v1alpha1/routing.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: pbmesh/v1alpha1/routing.proto diff --git a/proto-public/pbmesh/v1alpha1/upstreams.pb.go b/proto-public/pbmesh/v1alpha1/upstreams.pb.go index 6d8abade40..575fe43006 100644 --- a/proto-public/pbmesh/v1alpha1/upstreams.pb.go +++ b/proto-public/pbmesh/v1alpha1/upstreams.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: pbmesh/v1alpha1/upstreams.proto diff --git a/proto-public/pbresource/resource.pb.go b/proto-public/pbresource/resource.pb.go index 4a46d1ea8b..889a0314af 100644 --- a/proto-public/pbresource/resource.pb.go +++ b/proto-public/pbresource/resource.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: pbresource/resource.proto diff --git a/proto-public/pbserverdiscovery/serverdiscovery.pb.go b/proto-public/pbserverdiscovery/serverdiscovery.pb.go index 473dfb6be2..37b3b592e7 100644 --- a/proto-public/pbserverdiscovery/serverdiscovery.pb.go +++ b/proto-public/pbserverdiscovery/serverdiscovery.pb.go @@ -6,7 +6,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: pbserverdiscovery/serverdiscovery.proto diff --git a/proto/private/pbacl/acl.pb.go b/proto/private/pbacl/acl.pb.go index 1f229979bd..e8d0719e8d 100644 --- a/proto/private/pbacl/acl.pb.go +++ b/proto/private/pbacl/acl.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: private/pbacl/acl.proto diff --git a/proto/private/pbautoconf/auto_config.pb.go b/proto/private/pbautoconf/auto_config.pb.go index 0af033d5bf..55da1b07f9 100644 --- a/proto/private/pbautoconf/auto_config.pb.go +++ b/proto/private/pbautoconf/auto_config.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: private/pbautoconf/auto_config.proto diff --git a/proto/private/pbcommon/common.pb.go b/proto/private/pbcommon/common.pb.go index e66e840ca3..8a8ae5fe94 100644 --- a/proto/private/pbcommon/common.pb.go +++ b/proto/private/pbcommon/common.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: private/pbcommon/common.proto diff --git a/proto/private/pbconfig/config.pb.go b/proto/private/pbconfig/config.pb.go index 6cb7498d9e..61c394944f 100644 --- a/proto/private/pbconfig/config.pb.go +++ b/proto/private/pbconfig/config.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: private/pbconfig/config.proto @@ -264,7 +264,7 @@ type TLS struct { // Deprecated_PreferServerCipherSuites is deprecated. It is no longer // populated and should be ignored by clients. // - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in private/pbconfig/config.proto. Deprecated_PreferServerCipherSuites bool `protobuf:"varint,5,opt,name=Deprecated_PreferServerCipherSuites,json=DeprecatedPreferServerCipherSuites,proto3" json:"Deprecated_PreferServerCipherSuites,omitempty"` } @@ -328,7 +328,7 @@ func (x *TLS) GetMinVersion() string { return "" } -// Deprecated: Do not use. +// Deprecated: Marked as deprecated in private/pbconfig/config.proto. func (x *TLS) GetDeprecated_PreferServerCipherSuites() bool { if x != nil { return x.Deprecated_PreferServerCipherSuites @@ -352,7 +352,7 @@ type ACL struct { // Deprecated_DisabledTTL is deprecated. It is no longer populated and should // be ignored by clients. // - // Deprecated: Do not use. + // Deprecated: Marked as deprecated in private/pbconfig/config.proto. Deprecated_DisabledTTL string `protobuf:"bytes,9,opt,name=Deprecated_DisabledTTL,json=DeprecatedDisabledTTL,proto3" json:"Deprecated_DisabledTTL,omitempty"` EnableTokenPersistence bool `protobuf:"varint,10,opt,name=EnableTokenPersistence,proto3" json:"EnableTokenPersistence,omitempty"` MSPDisableBootstrap bool `protobuf:"varint,11,opt,name=MSPDisableBootstrap,proto3" json:"MSPDisableBootstrap,omitempty"` @@ -446,7 +446,7 @@ func (x *ACL) GetTokens() *ACLTokens { return nil } -// Deprecated: Do not use. +// Deprecated: Marked as deprecated in private/pbconfig/config.proto. func (x *ACL) GetDeprecated_DisabledTTL() string { if x != nil { return x.Deprecated_DisabledTTL diff --git a/proto/private/pbconfigentry/config_entry.pb.go b/proto/private/pbconfigentry/config_entry.pb.go index 019782047b..5dbb9737e4 100644 --- a/proto/private/pbconfigentry/config_entry.pb.go +++ b/proto/private/pbconfigentry/config_entry.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: private/pbconfigentry/config_entry.proto diff --git a/proto/private/pbconnect/connect.pb.go b/proto/private/pbconnect/connect.pb.go index 8c3eaba1da..278114b3b4 100644 --- a/proto/private/pbconnect/connect.pb.go +++ b/proto/private/pbconnect/connect.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: private/pbconnect/connect.proto diff --git a/proto/private/pbdemo/v1/demo.pb.go b/proto/private/pbdemo/v1/demo.pb.go index 84717919b8..9ee119d76f 100644 --- a/proto/private/pbdemo/v1/demo.pb.go +++ b/proto/private/pbdemo/v1/demo.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: private/pbdemo/v1/demo.proto diff --git a/proto/private/pbdemo/v2/demo.pb.go b/proto/private/pbdemo/v2/demo.pb.go index 8d9b1e5e26..2ffed20dcc 100644 --- a/proto/private/pbdemo/v2/demo.pb.go +++ b/proto/private/pbdemo/v2/demo.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: private/pbdemo/v2/demo.proto diff --git a/proto/private/pboperator/operator.pb.go b/proto/private/pboperator/operator.pb.go index 65e0ed4fe8..5f264c5393 100644 --- a/proto/private/pboperator/operator.pb.go +++ b/proto/private/pboperator/operator.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: private/pboperator/operator.proto diff --git a/proto/private/pbpeering/peering.pb.go b/proto/private/pbpeering/peering.pb.go index 82b88d1d78..65a75ada26 100644 --- a/proto/private/pbpeering/peering.pb.go +++ b/proto/private/pbpeering/peering.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: private/pbpeering/peering.proto diff --git a/proto/private/pbpeerstream/peerstream.pb.go b/proto/private/pbpeerstream/peerstream.pb.go index e427d63a90..f20496642d 100644 --- a/proto/private/pbpeerstream/peerstream.pb.go +++ b/proto/private/pbpeerstream/peerstream.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: private/pbpeerstream/peerstream.proto diff --git a/proto/private/pbservice/healthcheck.pb.go b/proto/private/pbservice/healthcheck.pb.go index 865785bb46..aa7a4c7325 100644 --- a/proto/private/pbservice/healthcheck.pb.go +++ b/proto/private/pbservice/healthcheck.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: private/pbservice/healthcheck.proto diff --git a/proto/private/pbservice/node.pb.go b/proto/private/pbservice/node.pb.go index 157906fcbc..7b8fa6a334 100644 --- a/proto/private/pbservice/node.pb.go +++ b/proto/private/pbservice/node.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: private/pbservice/node.proto diff --git a/proto/private/pbservice/service.pb.go b/proto/private/pbservice/service.pb.go index 2b16416838..13826aa752 100644 --- a/proto/private/pbservice/service.pb.go +++ b/proto/private/pbservice/service.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: private/pbservice/service.proto diff --git a/proto/private/pbstatus/status.pb.go b/proto/private/pbstatus/status.pb.go index c3d1568c6d..ce1658b68c 100644 --- a/proto/private/pbstatus/status.pb.go +++ b/proto/private/pbstatus/status.pb.go @@ -14,7 +14,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: private/pbstatus/status.proto diff --git a/proto/private/pbstorage/raft.pb.go b/proto/private/pbstorage/raft.pb.go index 8060fb6936..8ae22a6aba 100644 --- a/proto/private/pbstorage/raft.pb.go +++ b/proto/private/pbstorage/raft.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: private/pbstorage/raft.proto diff --git a/proto/private/pbsubscribe/subscribe.pb.go b/proto/private/pbsubscribe/subscribe.pb.go index bc1f4e458a..f71a855107 100644 --- a/proto/private/pbsubscribe/subscribe.pb.go +++ b/proto/private/pbsubscribe/subscribe.pb.go @@ -6,7 +6,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 +// protoc-gen-go v1.30.0 // protoc (unknown) // source: private/pbsubscribe/subscribe.proto diff --git a/sdk/go.mod b/sdk/go.mod index 8a04b9e103..0732bcf139 100644 --- a/sdk/go.mod +++ b/sdk/go.mod @@ -3,22 +3,23 @@ module github.com/hashicorp/consul/sdk go 1.19 require ( - github.com/hashicorp/go-cleanhttp v0.5.1 - github.com/hashicorp/go-hclog v0.12.0 - github.com/hashicorp/go-uuid v1.0.1 + github.com/hashicorp/go-cleanhttp v0.5.2 + github.com/hashicorp/go-hclog v1.5.0 + github.com/hashicorp/go-uuid v1.0.3 github.com/hashicorp/go-version v1.2.1 - github.com/pkg/errors v0.8.1 - github.com/stretchr/testify v1.4.0 - golang.org/x/sys v0.0.0-20220412211240-33da011f77ad + github.com/pkg/errors v0.9.1 + github.com/stretchr/testify v1.8.3 + golang.org/x/sys v0.8.0 ) require ( - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/fatih/color v1.9.0 // indirect - github.com/kr/pretty v0.2.0 // indirect - github.com/mattn/go-colorable v0.1.4 // indirect - github.com/mattn/go-isatty v0.0.12 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect - gopkg.in/yaml.v2 v2.2.8 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/fatih/color v1.14.1 // indirect + github.com/kr/pretty v0.3.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/rogpeppe/go-internal v1.10.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/sdk/go.sum b/sdk/go.sum index 65c687138f..a073220bef 100644 --- a/sdk/go.sum +++ b/sdk/go.sum @@ -1,46 +1,60 @@ +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= -github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-hclog v0.12.0 h1:d4QkX8FRTYaKaCZBoXYY8zJX2BXjWxurN/GA2tkrmZM= -github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= +github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= +github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI= github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= -github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/test/integration/connect/envoy/test-sds-server/go.mod b/test/integration/connect/envoy/test-sds-server/go.mod index 7aa65b5815..c0c4f13857 100644 --- a/test/integration/connect/envoy/test-sds-server/go.mod +++ b/test/integration/connect/envoy/test-sds-server/go.mod @@ -3,7 +3,13 @@ module test-sds-server go 1.16 require ( - github.com/envoyproxy/go-control-plane v0.9.9 - github.com/hashicorp/go-hclog v0.16.2 - google.golang.org/grpc v1.40.0 + github.com/envoyproxy/go-control-plane v0.11.0 + github.com/fatih/color v1.14.1 // indirect + github.com/hashicorp/consul v1.15.2 + github.com/hashicorp/go-hclog v1.5.0 + github.com/hashicorp/go-uuid v1.0.3 // indirect + github.com/stretchr/testify v1.8.3 // indirect + golang.org/x/net v0.10.0 // indirect + google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect + google.golang.org/grpc v1.55.0 ) diff --git a/test/integration/connect/envoy/test-sds-server/go.sum b/test/integration/connect/envoy/test-sds-server/go.sum index f4cb806dfc..b6ee5b6be5 100644 --- a/test/integration/connect/envoy/test-sds-server/go.sum +++ b/test/integration/connect/envoy/test-sds-server/go.sum @@ -1,36 +1,1046 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.41.0/go.mod h1:OauMR7DV8fzvZIl2qg6rkaIhD/vmgk4iwEw/h6ercmg= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= +cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= +cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= +cloud.google.com/go v0.100.1/go.mod h1:fs4QogzfH5n2pBXBP9vRiU+eCny7lD2vmFZy79Iuw1U= +cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= +cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= +cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= +cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= +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/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= +cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o= +cloud.google.com/go/accesscontextmanager v1.4.0/go.mod h1:/Kjh7BBu/Gh83sv+K60vN9QE5NJcd80sU33vIe2IFPE= +cloud.google.com/go/accesscontextmanager v1.6.0/go.mod h1:8XCvZWfYw3K/ji0iVnp+6pu7huxoQTLmxAbVjbloTtM= +cloud.google.com/go/accesscontextmanager v1.7.0/go.mod h1:CEGLewx8dwa33aDAZQujl7Dx+uYhS0eay198wB/VumQ= +cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= +cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= +cloud.google.com/go/aiplatform v1.27.0/go.mod h1:Bvxqtl40l0WImSb04d0hXFU7gDOiq9jQmorivIiWcKg= +cloud.google.com/go/aiplatform v1.35.0/go.mod h1:7MFT/vCaOyZT/4IIFfxH4ErVg/4ku6lKv3w0+tFTgXQ= +cloud.google.com/go/aiplatform v1.36.1/go.mod h1:WTm12vJRPARNvJ+v6P52RDHCNe4AhvjcIZ/9/RRHy/k= +cloud.google.com/go/aiplatform v1.37.0/go.mod h1:IU2Cv29Lv9oCn/9LkFiiuKfwrRTq+QQMbW+hPCxJGZw= +cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= +cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= +cloud.google.com/go/analytics v0.17.0/go.mod h1:WXFa3WSym4IZ+JiKmavYdJwGG/CvpqiqczmL59bTD9M= +cloud.google.com/go/analytics v0.18.0/go.mod h1:ZkeHGQlcIPkw0R/GW+boWHhCOR43xz9RN/jn7WcqfIE= +cloud.google.com/go/analytics v0.19.0/go.mod h1:k8liqf5/HCnOUkbawNtrWWc+UAzyDlW89doe8TtoDsE= +cloud.google.com/go/apigateway v1.3.0/go.mod h1:89Z8Bhpmxu6AmUxuVRg/ECRGReEdiP3vQtk4Z1J9rJk= +cloud.google.com/go/apigateway v1.4.0/go.mod h1:pHVY9MKGaH9PQ3pJ4YLzoj6U5FUDeDFBllIz7WmzJoc= +cloud.google.com/go/apigateway v1.5.0/go.mod h1:GpnZR3Q4rR7LVu5951qfXPJCHquZt02jf7xQx7kpqN8= +cloud.google.com/go/apigeeconnect v1.3.0/go.mod h1:G/AwXFAKo0gIXkPTVfZDd2qA1TxBXJ3MgMRBQkIi9jc= +cloud.google.com/go/apigeeconnect v1.4.0/go.mod h1:kV4NwOKqjvt2JYR0AoIWo2QGfoRtn/pkS3QlHp0Ni04= +cloud.google.com/go/apigeeconnect v1.5.0/go.mod h1:KFaCqvBRU6idyhSNyn3vlHXc8VMDJdRmwDF6JyFRqZ8= +cloud.google.com/go/apigeeregistry v0.4.0/go.mod h1:EUG4PGcsZvxOXAdyEghIdXwAEi/4MEaoqLMLDMIwKXY= +cloud.google.com/go/apigeeregistry v0.5.0/go.mod h1:YR5+s0BVNZfVOUkMa5pAR2xGd0A473vA5M7j247o1wM= +cloud.google.com/go/apigeeregistry v0.6.0/go.mod h1:BFNzW7yQVLZ3yj0TKcwzb8n25CFBri51GVGOEUcgQsc= +cloud.google.com/go/apikeys v0.4.0/go.mod h1:XATS/yqZbaBK0HOssf+ALHp8jAlNHUgyfprvNcBIszU= +cloud.google.com/go/apikeys v0.5.0/go.mod h1:5aQfwY4D+ewMMWScd3hm2en3hCj+BROlyrt3ytS7KLI= +cloud.google.com/go/apikeys v0.6.0/go.mod h1:kbpXu5upyiAlGkKrJgQl8A0rKNNJ7dQ377pdroRSSi8= +cloud.google.com/go/appengine v1.4.0/go.mod h1:CS2NhuBuDXM9f+qscZ6V86m1MIIqPj3WC/UoEuR1Sno= +cloud.google.com/go/appengine v1.5.0/go.mod h1:TfasSozdkFI0zeoxW3PTBLiNqRmzraodCWatWI9Dmak= +cloud.google.com/go/appengine v1.6.0/go.mod h1:hg6i0J/BD2cKmDJbaFSYHFyZkgBEfQrDg/X0V5fJn84= +cloud.google.com/go/appengine v1.7.0/go.mod h1:eZqpbHFCqRGa2aCdope7eC0SWLV1j0neb/QnMJVWx6A= +cloud.google.com/go/appengine v1.7.1/go.mod h1:IHLToyb/3fKutRysUlFO0BPt5j7RiQ45nrzEJmKTo6E= +cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4= +cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0= +cloud.google.com/go/area120 v0.7.0/go.mod h1:a3+8EUD1SX5RUcCs3MY5YasiO1z6yLiNLRiFrykbynY= +cloud.google.com/go/area120 v0.7.1/go.mod h1:j84i4E1RboTWjKtZVWXPqvK5VHQFJRF2c1Nm69pWm9k= +cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ= +cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk= +cloud.google.com/go/artifactregistry v1.8.0/go.mod h1:w3GQXkJX8hiKN0v+at4b0qotwijQbYUqF2GWkZzAhC0= +cloud.google.com/go/artifactregistry v1.9.0/go.mod h1:2K2RqvA2CYvAeARHRkLDhMDJ3OXy26h3XW+3/Jh2uYc= +cloud.google.com/go/artifactregistry v1.11.1/go.mod h1:lLYghw+Itq9SONbCa1YWBoWs1nOucMH0pwXN1rOBZFI= +cloud.google.com/go/artifactregistry v1.11.2/go.mod h1:nLZns771ZGAwVLzTX/7Al6R9ehma4WUEhZGWV6CeQNQ= +cloud.google.com/go/artifactregistry v1.12.0/go.mod h1:o6P3MIvtzTOnmvGagO9v/rOjjA0HmhJ+/6KAXrmYDCI= +cloud.google.com/go/artifactregistry v1.13.0/go.mod h1:uy/LNfoOIivepGhooAUpL1i30Hgee3Cu0l4VTWHUC08= +cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o= +cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s= +cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0= +cloud.google.com/go/asset v1.9.0/go.mod h1:83MOE6jEJBMqFKadM9NLRcs80Gdw76qGuHn8m3h8oHQ= +cloud.google.com/go/asset v1.10.0/go.mod h1:pLz7uokL80qKhzKr4xXGvBQXnzHn5evJAEAtZiIb0wY= +cloud.google.com/go/asset v1.11.1/go.mod h1:fSwLhbRvC9p9CXQHJ3BgFeQNM4c9x10lqlrdEUYXlJo= +cloud.google.com/go/asset v1.12.0/go.mod h1:h9/sFOa4eDIyKmH6QMpm4eUK3pDojWnUhTgJlk762Hg= +cloud.google.com/go/asset v1.13.0/go.mod h1:WQAMyYek/b7NBpYq/K4KJWcRqzoalEsxz/t/dTk4THw= +cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY= +cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw= +cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI= +cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEarXQk6WEKkxYfL6kGIo= +cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0= +cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E= +cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= +cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= +cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8= +cloud.google.com/go/automl v1.8.0/go.mod h1:xWx7G/aPEe/NP+qzYXktoBSDfjO+vnKMGgsApGJJquM= +cloud.google.com/go/automl v1.12.0/go.mod h1:tWDcHDp86aMIuHmyvjuKeeHEGq76lD7ZqfGLN6B0NuU= +cloud.google.com/go/baremetalsolution v0.3.0/go.mod h1:XOrocE+pvK1xFfleEnShBlNAXf+j5blPPxrhjKgnIFc= +cloud.google.com/go/baremetalsolution v0.4.0/go.mod h1:BymplhAadOO/eBa7KewQ0Ppg4A4Wplbn+PsFKRLo0uI= +cloud.google.com/go/baremetalsolution v0.5.0/go.mod h1:dXGxEkmR9BMwxhzBhV0AioD0ULBmuLZI8CdwalUxuss= +cloud.google.com/go/batch v0.3.0/go.mod h1:TR18ZoAekj1GuirsUsR1ZTKN3FC/4UDnScjT8NXImFE= +cloud.google.com/go/batch v0.4.0/go.mod h1:WZkHnP43R/QCGQsZ+0JyG4i79ranE2u8xvjq/9+STPE= +cloud.google.com/go/batch v0.7.0/go.mod h1:vLZN95s6teRUqRQ4s3RLDsH8PvboqBK+rn1oevL159g= +cloud.google.com/go/beyondcorp v0.2.0/go.mod h1:TB7Bd+EEtcw9PCPQhCJtJGjk/7TC6ckmnSFS+xwTfm4= +cloud.google.com/go/beyondcorp v0.3.0/go.mod h1:E5U5lcrcXMsCuoDNyGrpyTm/hn7ne941Jz2vmksAxW8= +cloud.google.com/go/beyondcorp v0.4.0/go.mod h1:3ApA0mbhHx6YImmuubf5pyW8srKnCEPON32/5hj+RmM= +cloud.google.com/go/beyondcorp v0.5.0/go.mod h1:uFqj9X+dSfrheVp7ssLTaRHd2EHqSL4QZmH4e8WXGGU= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA= +cloud.google.com/go/bigquery v1.43.0/go.mod h1:ZMQcXHsl+xmU1z36G2jNGZmKp9zNY5BUua5wDgmNCfw= +cloud.google.com/go/bigquery v1.44.0/go.mod h1:0Y33VqXTEsbamHJvJHdFmtqHvMIY28aK1+dFsvaChGc= +cloud.google.com/go/bigquery v1.47.0/go.mod h1:sA9XOgy0A8vQK9+MWhEQTY6Tix87M/ZurWFIxmF9I/E= +cloud.google.com/go/bigquery v1.48.0/go.mod h1:QAwSz+ipNgfL5jxiaK7weyOhzdoAy1zFm0Nf1fysJac= +cloud.google.com/go/bigquery v1.49.0/go.mod h1:Sv8hMmTFFYBlt/ftw2uN6dFdQPzBlREY9yBh7Oy7/4Q= +cloud.google.com/go/bigquery v1.50.0/go.mod h1:YrleYEh2pSEbgTBZYMJ5SuSr0ML3ypjRB1zgf7pvQLU= +cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY= +cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= +cloud.google.com/go/billing v1.6.0/go.mod h1:WoXzguj+BeHXPbKfNWkqVtDdzORazmCjraY+vrxcyvI= +cloud.google.com/go/billing v1.7.0/go.mod h1:q457N3Hbj9lYwwRbnlD7vUpyjq6u5U1RAOArInEiD5Y= +cloud.google.com/go/billing v1.12.0/go.mod h1:yKrZio/eu+okO/2McZEbch17O5CB5NpZhhXG6Z766ss= +cloud.google.com/go/billing v1.13.0/go.mod h1:7kB2W9Xf98hP9Sr12KfECgfGclsH3CQR0R08tnRlRbc= +cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM= +cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI= +cloud.google.com/go/binaryauthorization v1.3.0/go.mod h1:lRZbKgjDIIQvzYQS1p99A7/U1JqvqeZg0wiI5tp6tg0= +cloud.google.com/go/binaryauthorization v1.4.0/go.mod h1:tsSPQrBd77VLplV70GUhBf/Zm3FsKmgSqgm4UmiDItk= +cloud.google.com/go/binaryauthorization v1.5.0/go.mod h1:OSe4OU1nN/VswXKRBmciKpo9LulY41gch5c68htf3/Q= +cloud.google.com/go/certificatemanager v1.3.0/go.mod h1:n6twGDvcUBFu9uBgt4eYvvf3sQ6My8jADcOVwHmzadg= +cloud.google.com/go/certificatemanager v1.4.0/go.mod h1:vowpercVFyqs8ABSmrdV+GiFf2H/ch3KyudYQEMM590= +cloud.google.com/go/certificatemanager v1.6.0/go.mod h1:3Hh64rCKjRAX8dXgRAyOcY5vQ/fE1sh8o+Mdd6KPgY8= +cloud.google.com/go/channel v1.8.0/go.mod h1:W5SwCXDJsq/rg3tn3oG0LOxpAo6IMxNa09ngphpSlnk= +cloud.google.com/go/channel v1.9.0/go.mod h1:jcu05W0my9Vx4mt3/rEHpfxc9eKi9XwsdDL8yBMbKUk= +cloud.google.com/go/channel v1.11.0/go.mod h1:IdtI0uWGqhEeatSB62VOoJ8FSUhJ9/+iGkJVqp74CGE= +cloud.google.com/go/channel v1.12.0/go.mod h1:VkxCGKASi4Cq7TbXxlaBezonAYpp1GCnKMY6tnMQnLU= +cloud.google.com/go/cloudbuild v1.3.0/go.mod h1:WequR4ULxlqvMsjDEEEFnOG5ZSRSgWOywXYDb1vPE6U= +cloud.google.com/go/cloudbuild v1.4.0/go.mod h1:5Qwa40LHiOXmz3386FrjrYM93rM/hdRr7b53sySrTqA= +cloud.google.com/go/cloudbuild v1.6.0/go.mod h1:UIbc/w9QCbH12xX+ezUsgblrWv+Cv4Tw83GiSMHOn9M= +cloud.google.com/go/cloudbuild v1.7.0/go.mod h1:zb5tWh2XI6lR9zQmsm1VRA+7OCuve5d8S+zJUul8KTg= +cloud.google.com/go/cloudbuild v1.9.0/go.mod h1:qK1d7s4QlO0VwfYn5YuClDGg2hfmLZEb4wQGAbIgL1s= +cloud.google.com/go/clouddms v1.3.0/go.mod h1:oK6XsCDdW4Ib3jCCBugx+gVjevp2TMXFtgxvPSee3OM= +cloud.google.com/go/clouddms v1.4.0/go.mod h1:Eh7sUGCC+aKry14O1NRljhjyrr0NFC0G2cjwX0cByRk= +cloud.google.com/go/clouddms v1.5.0/go.mod h1:QSxQnhikCLUw13iAbffF2CZxAER3xDGNHjsTAkQJcQA= +cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY= +cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI= +cloud.google.com/go/cloudtasks v1.7.0/go.mod h1:ImsfdYWwlWNJbdgPIIGJWC+gemEGTBK/SunNQQNCAb4= +cloud.google.com/go/cloudtasks v1.8.0/go.mod h1:gQXUIwCSOI4yPVK7DgTVFiiP0ZW/eQkydWzwVMdHxrI= +cloud.google.com/go/cloudtasks v1.9.0/go.mod h1:w+EyLsVkLWHcOaqNEyvcKAsWp9p29dL6uL9Nst1cI7Y= +cloud.google.com/go/cloudtasks v1.10.0/go.mod h1:NDSoTLkZ3+vExFEWu2UJV1arUyzVDAiZtdWcsUyNwBs= +cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= +cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= +cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= +cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= +cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= +cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= +cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= +cloud.google.com/go/compute v1.12.0/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= +cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= +cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE= +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.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= +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= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= +cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= +cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= +cloud.google.com/go/container v1.6.0/go.mod h1:Xazp7GjJSeUYo688S+6J5V+n/t+G5sKBTFkKNudGRxg= +cloud.google.com/go/container v1.7.0/go.mod h1:Dp5AHtmothHGX3DwwIHPgq45Y8KmNsgN3amoYfxVkLo= +cloud.google.com/go/container v1.13.1/go.mod h1:6wgbMPeQRw9rSnKBCAJXnds3Pzj03C4JHamr8asWKy4= +cloud.google.com/go/container v1.14.0/go.mod h1:3AoJMPhHfLDxLvrlVWaK57IXzaPnLaZq63WX59aQBfM= +cloud.google.com/go/container v1.15.0/go.mod h1:ft+9S0WGjAyjDggg5S06DXj+fHJICWg8L7isCQe9pQA= +cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= +cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= +cloud.google.com/go/containeranalysis v0.7.0/go.mod h1:9aUL+/vZ55P2CXfuZjS4UjQ9AgXoSw8Ts6lemfmxBxI= +cloud.google.com/go/containeranalysis v0.9.0/go.mod h1:orbOANbwk5Ejoom+s+DUCTTJ7IBdBQJDcSylAx/on9s= +cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= +cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs= +cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc= +cloud.google.com/go/datacatalog v1.7.0/go.mod h1:9mEl4AuDYWw81UGc41HonIHH7/sn52H0/tc8f8ZbZIE= +cloud.google.com/go/datacatalog v1.8.0/go.mod h1:KYuoVOv9BM8EYz/4eMFxrr4DUKhGIOXxZoKYF5wdISM= +cloud.google.com/go/datacatalog v1.8.1/go.mod h1:RJ58z4rMp3gvETA465Vg+ag8BGgBdnRPEMMSTr5Uv+M= +cloud.google.com/go/datacatalog v1.12.0/go.mod h1:CWae8rFkfp6LzLumKOnmVh4+Zle4A3NXLzVJ1d1mRm0= +cloud.google.com/go/datacatalog v1.13.0/go.mod h1:E4Rj9a5ZtAxcQJlEBTLgMTphfP11/lNaAshpoBgemX8= +cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM= +cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ= +cloud.google.com/go/dataflow v0.8.0/go.mod h1:Rcf5YgTKPtQyYz8bLYhFoIV/vP39eL7fWNcSOyFfLJE= +cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo= +cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE= +cloud.google.com/go/dataform v0.5.0/go.mod h1:GFUYRe8IBa2hcomWplodVmUx/iTL0FrsauObOM3Ipr0= +cloud.google.com/go/dataform v0.6.0/go.mod h1:QPflImQy33e29VuapFdf19oPbE4aYTJxr31OAPV+ulA= +cloud.google.com/go/dataform v0.7.0/go.mod h1:7NulqnVozfHvWUBpMDfKMUESr+85aJsC/2O0o3jWPDE= +cloud.google.com/go/datafusion v1.4.0/go.mod h1:1Zb6VN+W6ALo85cXnM1IKiPw+yQMKMhB9TsTSRDo/38= +cloud.google.com/go/datafusion v1.5.0/go.mod h1:Kz+l1FGHB0J+4XF2fud96WMmRiq/wj8N9u007vyXZ2w= +cloud.google.com/go/datafusion v1.6.0/go.mod h1:WBsMF8F1RhSXvVM8rCV3AeyWVxcC2xY6vith3iw3S+8= +cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I= +cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ= +cloud.google.com/go/datalabeling v0.7.0/go.mod h1:WPQb1y08RJbmpM3ww0CSUAGweL0SxByuW2E+FU+wXcM= +cloud.google.com/go/dataplex v1.3.0/go.mod h1:hQuRtDg+fCiFgC8j0zV222HvzFQdRd+SVX8gdmFcZzA= +cloud.google.com/go/dataplex v1.4.0/go.mod h1:X51GfLXEMVJ6UN47ESVqvlsRplbLhcsAt0kZCCKsU0A= +cloud.google.com/go/dataplex v1.5.2/go.mod h1:cVMgQHsmfRoI5KFYq4JtIBEUbYwc3c7tXmIDhRmNNVQ= +cloud.google.com/go/dataplex v1.6.0/go.mod h1:bMsomC/aEJOSpHXdFKFGQ1b0TDPIeL28nJObeO1ppRs= +cloud.google.com/go/dataproc v1.7.0/go.mod h1:CKAlMjII9H90RXaMpSxQ8EU6dQx6iAYNPcYPOkSbi8s= +cloud.google.com/go/dataproc v1.8.0/go.mod h1:5OW+zNAH0pMpw14JVrPONsxMQYMBqJuzORhIBfBn9uI= +cloud.google.com/go/dataproc v1.12.0/go.mod h1:zrF3aX0uV3ikkMz6z4uBbIKyhRITnxvr4i3IjKsKrw4= +cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo= +cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA= +cloud.google.com/go/dataqna v0.7.0/go.mod h1:Lx9OcIIeqCrw1a6KdO3/5KMP1wAmTc0slZWwP12Qq3c= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/datastore v1.10.0/go.mod h1:PC5UzAmDEkAmkfaknstTYbNpgE49HAgW2J1gcgUfmdM= +cloud.google.com/go/datastore v1.11.0/go.mod h1:TvGxBIHCS50u8jzG+AW/ppf87v1of8nwzFNgEZU1D3c= +cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo= +cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ= +cloud.google.com/go/datastream v1.4.0/go.mod h1:h9dpzScPhDTs5noEMQVWP8Wx8AFBRyS0s8KWPx/9r0g= +cloud.google.com/go/datastream v1.5.0/go.mod h1:6TZMMNPwjUqZHBKPQ1wwXpb0d5VDVPl2/XoS5yi88q4= +cloud.google.com/go/datastream v1.6.0/go.mod h1:6LQSuswqLa7S4rPAOZFVjHIG3wJIjZcZrw8JDEDJuIs= +cloud.google.com/go/datastream v1.7.0/go.mod h1:uxVRMm2elUSPuh65IbZpzJNMbuzkcvu5CjMqVIUHrww= +cloud.google.com/go/deploy v1.4.0/go.mod h1:5Xghikd4VrmMLNaF6FiRFDlHb59VM59YoDQnOUdsH/c= +cloud.google.com/go/deploy v1.5.0/go.mod h1:ffgdD0B89tToyW/U/D2eL0jN2+IEV/3EMuXHA0l4r+s= +cloud.google.com/go/deploy v1.6.0/go.mod h1:f9PTHehG/DjCom3QH0cntOVRm93uGBDt2vKzAPwpXQI= +cloud.google.com/go/deploy v1.8.0/go.mod h1:z3myEJnA/2wnB4sgjqdMfgxCA0EqC3RBTNcVPs93mtQ= +cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4= +cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0= +cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8= +cloud.google.com/go/dialogflow v1.18.0/go.mod h1:trO7Zu5YdyEuR+BhSNOqJezyFQ3aUzz0njv7sMx/iek= +cloud.google.com/go/dialogflow v1.19.0/go.mod h1:JVmlG1TwykZDtxtTXujec4tQ+D8SBFMoosgy+6Gn0s0= +cloud.google.com/go/dialogflow v1.29.0/go.mod h1:b+2bzMe+k1s9V+F2jbJwpHPzrnIyHihAdRFMtn2WXuM= +cloud.google.com/go/dialogflow v1.31.0/go.mod h1:cuoUccuL1Z+HADhyIA7dci3N5zUssgpBJmCzI6fNRB4= +cloud.google.com/go/dialogflow v1.32.0/go.mod h1:jG9TRJl8CKrDhMEcvfcfFkkpp8ZhgPz3sBGmAUYJ2qE= +cloud.google.com/go/dlp v1.6.0/go.mod h1:9eyB2xIhpU0sVwUixfBubDoRwP+GjeUoxxeueZmqvmM= +cloud.google.com/go/dlp v1.7.0/go.mod h1:68ak9vCiMBjbasxeVD17hVPxDEck+ExiHavX8kiHG+Q= +cloud.google.com/go/dlp v1.9.0/go.mod h1:qdgmqgTyReTz5/YNSSuueR8pl7hO0o9bQ39ZhtgkWp4= +cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU= +cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU= +cloud.google.com/go/documentai v1.9.0/go.mod h1:FS5485S8R00U10GhgBC0aNGrJxBP8ZVpEeJ7PQDZd6k= +cloud.google.com/go/documentai v1.10.0/go.mod h1:vod47hKQIPeCfN2QS/jULIvQTugbmdc0ZvxxfQY1bg4= +cloud.google.com/go/documentai v1.16.0/go.mod h1:o0o0DLTEZ+YnJZ+J4wNfTxmDVyrkzFvttBXXtYRMHkM= +cloud.google.com/go/documentai v1.18.0/go.mod h1:F6CK6iUH8J81FehpskRmhLq/3VlwQvb7TvwOceQ2tbs= +cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y= +cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= +cloud.google.com/go/domains v0.8.0/go.mod h1:M9i3MMDzGFXsydri9/vW+EWz9sWb4I6WyHqdlAk0idE= +cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk= +cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= +cloud.google.com/go/edgecontainer v0.3.0/go.mod h1:FLDpP4nykgwwIfcLt6zInhprzw0lEi2P1fjO6Ie0qbc= +cloud.google.com/go/edgecontainer v1.0.0/go.mod h1:cttArqZpBB2q58W/upSG++ooo6EsblxDIolxa3jSjbY= +cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= +cloud.google.com/go/essentialcontacts v1.3.0/go.mod h1:r+OnHa5jfj90qIfZDO/VztSFqbQan7HV75p8sA+mdGI= +cloud.google.com/go/essentialcontacts v1.4.0/go.mod h1:8tRldvHYsmnBCHdFpvU+GL75oWiBKl80BiqlFh9tp+8= +cloud.google.com/go/essentialcontacts v1.5.0/go.mod h1:ay29Z4zODTuwliK7SnX8E86aUF2CTzdNtvv42niCX0M= +cloud.google.com/go/eventarc v1.7.0/go.mod h1:6ctpF3zTnaQCxUjHUdcfgcA1A2T309+omHZth7gDfmc= +cloud.google.com/go/eventarc v1.8.0/go.mod h1:imbzxkyAU4ubfsaKYdQg04WS1NvncblHEup4kvF+4gw= +cloud.google.com/go/eventarc v1.10.0/go.mod h1:u3R35tmZ9HvswGRBnF48IlYgYeBcPUCjkr4BTdem2Kw= +cloud.google.com/go/eventarc v1.11.0/go.mod h1:PyUjsUKPWoRBCHeOxZd/lbOOjahV41icXyUY5kSTvVY= +cloud.google.com/go/filestore v1.3.0/go.mod h1:+qbvHGvXU1HaKX2nD0WEPo92TP/8AQuCVEBXNY9z0+w= +cloud.google.com/go/filestore v1.4.0/go.mod h1:PaG5oDfo9r224f8OYXURtAsY+Fbyq/bLYoINEK8XQAI= +cloud.google.com/go/filestore v1.5.0/go.mod h1:FqBXDWBp4YLHqRnVGveOkHDf8svj9r5+mUDLupOWEDs= +cloud.google.com/go/filestore v1.6.0/go.mod h1:di5unNuss/qfZTw2U9nhFqo8/ZDSc466dre85Kydllg= +cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE= +cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk= +cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= +cloud.google.com/go/functions v1.8.0/go.mod h1:RTZ4/HsQjIqIYP9a9YPbU+QFoQsAlYgrwOXJWHn1POY= +cloud.google.com/go/functions v1.9.0/go.mod h1:Y+Dz8yGguzO3PpIjhLTbnqV1CWmgQ5UwtlpzoyquQ08= +cloud.google.com/go/functions v1.10.0/go.mod h1:0D3hEOe3DbEvCXtYOZHQZmD+SzYsi1YbI7dGvHfldXw= +cloud.google.com/go/functions v1.12.0/go.mod h1:AXWGrF3e2C/5ehvwYo/GH6O5s09tOPksiKhz+hH8WkA= +cloud.google.com/go/functions v1.13.0/go.mod h1:EU4O007sQm6Ef/PwRsI8N2umygGqPBS/IZQKBQBcJ3c= +cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM= +cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA= +cloud.google.com/go/gaming v1.7.0/go.mod h1:LrB8U7MHdGgFG851iHAfqUdLcKBdQ55hzXy9xBJz0+w= +cloud.google.com/go/gaming v1.8.0/go.mod h1:xAqjS8b7jAVW0KFYeRUxngo9My3f33kFmua++Pi+ggM= +cloud.google.com/go/gaming v1.9.0/go.mod h1:Fc7kEmCObylSWLO334NcO+O9QMDyz+TKC4v1D7X+Bc0= +cloud.google.com/go/gkebackup v0.2.0/go.mod h1:XKvv/4LfG829/B8B7xRkk8zRrOEbKtEam6yNfuQNH60= +cloud.google.com/go/gkebackup v0.3.0/go.mod h1:n/E671i1aOQvUxT541aTkCwExO/bTer2HDlj4TsBRAo= +cloud.google.com/go/gkebackup v0.4.0/go.mod h1:byAyBGUwYGEEww7xsbnUTBHIYcOPy/PgUWUtOeRm9Vg= +cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o= +cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A= +cloud.google.com/go/gkeconnect v0.7.0/go.mod h1:SNfmVqPkaEi3bF/B3CNZOAYPYdg7sU+obZ+QTky2Myw= +cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0= +cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0= +cloud.google.com/go/gkehub v0.11.0/go.mod h1:JOWHlmN+GHyIbuWQPl47/C2RFhnFKH38jH9Ascu3n0E= +cloud.google.com/go/gkehub v0.12.0/go.mod h1:djiIwwzTTBrF5NaXCGv3mf7klpEMcST17VBTVVDcuaw= +cloud.google.com/go/gkemulticloud v0.3.0/go.mod h1:7orzy7O0S+5kq95e4Hpn7RysVA7dPs8W/GgfUtsPbrA= +cloud.google.com/go/gkemulticloud v0.4.0/go.mod h1:E9gxVBnseLWCk24ch+P9+B2CoDFJZTyIgLKSalC7tuI= +cloud.google.com/go/gkemulticloud v0.5.0/go.mod h1:W0JDkiyi3Tqh0TJr//y19wyb1yf8llHVto2Htf2Ja3Y= +cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= +cloud.google.com/go/gsuiteaddons v1.3.0/go.mod h1:EUNK/J1lZEZO8yPtykKxLXI6JSVN2rg9bN8SXOa0bgM= +cloud.google.com/go/gsuiteaddons v1.4.0/go.mod h1:rZK5I8hht7u7HxFQcFei0+AtfS9uSushomRlg+3ua1o= +cloud.google.com/go/gsuiteaddons v1.5.0/go.mod h1:TFCClYLd64Eaa12sFVmUyG62tk4mdIsI7pAnSXRkcFo= +cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c= +cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= +cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= +cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc= +cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= +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 v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= +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= +cloud.google.com/go/iap v1.7.0/go.mod h1:beqQx56T9O1G1yNPph+spKpNibDlYIiIixiqsQXxLIo= +cloud.google.com/go/iap v1.7.1/go.mod h1:WapEwPc7ZxGt2jFGB/C/bm+hP0Y6NXzOYGjpPnmMS74= +cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM= +cloud.google.com/go/ids v1.2.0/go.mod h1:5WXvp4n25S0rA/mQWAg1YEEBBq6/s+7ml1RDCW1IrcY= +cloud.google.com/go/ids v1.3.0/go.mod h1:JBdTYwANikFKaDP6LtW5JAi4gubs57SVNQjemdt6xV4= +cloud.google.com/go/iot v1.3.0/go.mod h1:r7RGh2B61+B8oz0AGE+J72AhA0G7tdXItODWsaA2oLs= +cloud.google.com/go/iot v1.4.0/go.mod h1:dIDxPOn0UvNDUMD8Ger7FIaTuvMkj+aGk94RPP0iV+g= +cloud.google.com/go/iot v1.5.0/go.mod h1:mpz5259PDl3XJthEmh9+ap0affn/MqNSP4My77Qql9o= +cloud.google.com/go/iot v1.6.0/go.mod h1:IqdAsmE2cTYYNO1Fvjfzo9po179rAtJeVGUvkLN3rLE= +cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA= +cloud.google.com/go/kms v1.5.0/go.mod h1:QJS2YY0eJGBg3mnDfuaCyLauWwBJiHRboYxJ++1xJNg= +cloud.google.com/go/kms v1.6.0/go.mod h1:Jjy850yySiasBUDi6KFUwUv2n1+o7QZFyuUJg6OgjA0= +cloud.google.com/go/kms v1.8.0/go.mod h1:4xFEhYFqvW+4VMELtZyxomGSYtSQKzM178ylFW4jMAg= +cloud.google.com/go/kms v1.9.0/go.mod h1:qb1tPTgfF9RQP8e1wq4cLFErVuTJv7UsSC915J8dh3w= +cloud.google.com/go/kms v1.10.0/go.mod h1:ng3KTUtQQU9bPX3+QGLsflZIHlkbn8amFAMY63m8d24= +cloud.google.com/go/kms v1.10.1/go.mod h1:rIWk/TryCkR59GMC3YtHtXeLzd634lBbKenvyySAyYI= +cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= +cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= +cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiPzPCJa2MIE= +cloud.google.com/go/language v1.8.0/go.mod h1:qYPVHf7SPoNNiCL2Dr0FfEFNil1qi3pQEyygwpgVKB8= +cloud.google.com/go/language v1.9.0/go.mod h1:Ns15WooPM5Ad/5no/0n81yUetis74g3zrbeJBE+ptUY= +cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= +cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= +cloud.google.com/go/lifesciences v0.8.0/go.mod h1:lFxiEOMqII6XggGbOnKiyZ7IBwoIqA84ClvoezaA/bo= +cloud.google.com/go/logging v1.6.1/go.mod h1:5ZO0mHHbvm8gEmeEUHrmDlTDSu5imF6MUP9OfilNXBw= +cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeNqVNkzY8M= +cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE= +cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= +cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= +cloud.google.com/go/managedidentities v1.3.0/go.mod h1:UzlW3cBOiPrzucO5qWkNkh0w33KFtBJU281hacNvsdE= +cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtqOsxY1ZrGM+9RgDqInM= +cloud.google.com/go/managedidentities v1.5.0/go.mod h1:+dWcZ0JlUmpuxpIDfyP5pP5y0bLdRwOS4Lp7gMni/LA= +cloud.google.com/go/maps v0.1.0/go.mod h1:BQM97WGyfw9FWEmQMpZ5T6cpovXXSd1cGmFma94eubI= +cloud.google.com/go/maps v0.6.0/go.mod h1:o6DAMMfb+aINHz/p/jbcY+mYeXBoZoxTfdSQ8VAJaCw= +cloud.google.com/go/maps v0.7.0/go.mod h1:3GnvVl3cqeSvgMcpRlQidXsPYuDGQ8naBis7MVzpXsY= +cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= +cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= +cloud.google.com/go/mediatranslation v0.7.0/go.mod h1:LCnB/gZr90ONOIQLgSXagp8XUW1ODs2UmUMvcgMfI2I= +cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= +cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM= +cloud.google.com/go/memcache v1.6.0/go.mod h1:XS5xB0eQZdHtTuTF9Hf8eJkKtR3pVRCcvJwtm68T3rA= +cloud.google.com/go/memcache v1.7.0/go.mod h1:ywMKfjWhNtkQTxrWxCkCFkoPjLHPW6A7WOTVI8xy3LY= +cloud.google.com/go/memcache v1.9.0/go.mod h1:8oEyzXCu+zo9RzlEaEjHl4KkgjlNDaXbCQeQWlzNFJM= +cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY= +cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s= +cloud.google.com/go/metastore v1.7.0/go.mod h1:s45D0B4IlsINu87/AsWiEVYbLaIMeUSoxlKKDqBGFS8= +cloud.google.com/go/metastore v1.8.0/go.mod h1:zHiMc4ZUpBiM7twCIFQmJ9JMEkDSyZS9U12uf7wHqSI= +cloud.google.com/go/metastore v1.10.0/go.mod h1:fPEnH3g4JJAk+gMRnrAnoqyv2lpUCqJPWOodSaf45Eo= +cloud.google.com/go/monitoring v1.7.0/go.mod h1:HpYse6kkGo//7p6sT0wsIC6IBDET0RhIsnmlA53dvEk= +cloud.google.com/go/monitoring v1.8.0/go.mod h1:E7PtoMJ1kQXWxPjB6mv2fhC5/15jInuulFdYYtlcvT4= +cloud.google.com/go/monitoring v1.12.0/go.mod h1:yx8Jj2fZNEkL/GYZyTLS4ZtZEZN8WtDEiEqG4kLK50w= +cloud.google.com/go/monitoring v1.13.0/go.mod h1:k2yMBAB1H9JT/QETjNkgdCGD9bPF712XiLTVr+cBrpw= +cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA= +cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o= +cloud.google.com/go/networkconnectivity v1.6.0/go.mod h1:OJOoEXW+0LAxHh89nXd64uGG+FbQoeH8DtxCHVOMlaM= +cloud.google.com/go/networkconnectivity v1.7.0/go.mod h1:RMuSbkdbPwNMQjB5HBWD5MpTBnNm39iAVpC3TmsExt8= +cloud.google.com/go/networkconnectivity v1.10.0/go.mod h1:UP4O4sWXJG13AqrTdQCD9TnLGEbtNRqjuaaA7bNjF5E= +cloud.google.com/go/networkconnectivity v1.11.0/go.mod h1:iWmDD4QF16VCDLXUqvyspJjIEtBR/4zq5hwnY2X3scM= +cloud.google.com/go/networkmanagement v1.4.0/go.mod h1:Q9mdLLRn60AsOrPc8rs8iNV6OHXaGcDdsIQe1ohekq8= +cloud.google.com/go/networkmanagement v1.5.0/go.mod h1:ZnOeZ/evzUdUsnvRt792H0uYEnHQEMaz+REhhzJRcf4= +cloud.google.com/go/networkmanagement v1.6.0/go.mod h1:5pKPqyXjB/sgtvB5xqOemumoQNB7y95Q7S+4rjSOPYY= +cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ= +cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU= +cloud.google.com/go/networksecurity v0.7.0/go.mod h1:mAnzoxx/8TBSyXEeESMy9OOYwo1v+gZ5eMRnsT5bC8k= +cloud.google.com/go/networksecurity v0.8.0/go.mod h1:B78DkqsxFG5zRSVuwYFRZ9Xz8IcQ5iECsNrPn74hKHU= +cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY= +cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34= +cloud.google.com/go/notebooks v1.4.0/go.mod h1:4QPMngcwmgb6uw7Po99B2xv5ufVoIQ7nOGDyL4P8AgA= +cloud.google.com/go/notebooks v1.5.0/go.mod h1:q8mwhnP9aR8Hpfnrc5iN5IBhrXUy8S2vuYs+kBJ/gu0= +cloud.google.com/go/notebooks v1.7.0/go.mod h1:PVlaDGfJgj1fl1S3dUwhFMXFgfYGhYQt2164xOMONmE= +cloud.google.com/go/notebooks v1.8.0/go.mod h1:Lq6dYKOYOWUCTvw5t2q1gp1lAp0zxAxRycayS0iJcqQ= +cloud.google.com/go/optimization v1.1.0/go.mod h1:5po+wfvX5AQlPznyVEZjGJTMr4+CAkJf2XSTQOOl9l4= +cloud.google.com/go/optimization v1.2.0/go.mod h1:Lr7SOHdRDENsh+WXVmQhQTrzdu9ybg0NecjHidBq6xs= +cloud.google.com/go/optimization v1.3.1/go.mod h1:IvUSefKiwd1a5p0RgHDbWCIbDFgKuEdB+fPPuP0IDLI= +cloud.google.com/go/orchestration v1.3.0/go.mod h1:Sj5tq/JpWiB//X/q3Ngwdl5K7B7Y0KZ7bfv0wL6fqVA= +cloud.google.com/go/orchestration v1.4.0/go.mod h1:6W5NLFWs2TlniBphAViZEVhrXRSMgUGDfW7vrWKvsBk= +cloud.google.com/go/orchestration v1.6.0/go.mod h1:M62Bevp7pkxStDfFfTuCOaXgaaqRAga1yKyoMtEoWPQ= +cloud.google.com/go/orgpolicy v1.4.0/go.mod h1:xrSLIV4RePWmP9P3tBl8S93lTmlAxjm06NSm2UTmKvE= +cloud.google.com/go/orgpolicy v1.5.0/go.mod h1:hZEc5q3wzwXJaKrsx5+Ewg0u1LxJ51nNFlext7Tanwc= +cloud.google.com/go/orgpolicy v1.10.0/go.mod h1:w1fo8b7rRqlXlIJbVhOMPrwVljyuW5mqssvBtU18ONc= +cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs= +cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg= +cloud.google.com/go/osconfig v1.9.0/go.mod h1:Yx+IeIZJ3bdWmzbQU4fxNl8xsZ4amB+dygAwFPlvnNo= +cloud.google.com/go/osconfig v1.10.0/go.mod h1:uMhCzqC5I8zfD9zDEAfvgVhDS8oIjySWh+l4WK6GnWw= +cloud.google.com/go/osconfig v1.11.0/go.mod h1:aDICxrur2ogRd9zY5ytBLV89KEgT2MKB2L/n6x1ooPw= +cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E= +cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU= +cloud.google.com/go/oslogin v1.6.0/go.mod h1:zOJ1O3+dTU8WPlGEkFSh7qeHPPSoxrcMbbK1Nm2iX70= +cloud.google.com/go/oslogin v1.7.0/go.mod h1:e04SN0xO1UNJ1M5GP0vzVBFicIe4O53FOfcixIqTyXo= +cloud.google.com/go/oslogin v1.9.0/go.mod h1:HNavntnH8nzrn8JCTT5fj18FuJLFJc4NaZJtBnQtKFs= +cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0= +cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA= +cloud.google.com/go/phishingprotection v0.7.0/go.mod h1:8qJI4QKHoda/sb/7/YmMQ2omRLSLYSu9bU0EKCNI+Lk= +cloud.google.com/go/policytroubleshooter v1.3.0/go.mod h1:qy0+VwANja+kKrjlQuOzmlvscn4RNsAc0e15GGqfMxg= +cloud.google.com/go/policytroubleshooter v1.4.0/go.mod h1:DZT4BcRw3QoO8ota9xw/LKtPa8lKeCByYeKTIf/vxdE= +cloud.google.com/go/policytroubleshooter v1.5.0/go.mod h1:Rz1WfV+1oIpPdN2VvvuboLVRsB1Hclg3CKQ53j9l8vw= +cloud.google.com/go/policytroubleshooter v1.6.0/go.mod h1:zYqaPTsmfvpjm5ULxAyD/lINQxJ0DDsnWOP/GZ7xzBc= +cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0= +cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI= +cloud.google.com/go/privatecatalog v0.7.0/go.mod h1:2s5ssIFO69F5csTXcwBP7NPFTZvps26xGzvQ2PQaBYg= +cloud.google.com/go/privatecatalog v0.8.0/go.mod h1:nQ6pfaegeDAq/Q5lrfCQzQLhubPiZhSaNhIgfJlnIXs= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/pubsub v1.26.0/go.mod h1:QgBH3U/jdJy/ftjPhTkyXNj543Tin1pRYcdcPRnFIRI= +cloud.google.com/go/pubsub v1.27.1/go.mod h1:hQN39ymbV9geqBnfQq6Xf63yNhUAhv9CZhzp5O6qsW0= +cloud.google.com/go/pubsub v1.28.0/go.mod h1:vuXFpwaVoIPQMGXqRyUQigu/AX1S3IWugR9xznmcXX8= +cloud.google.com/go/pubsub v1.30.0/go.mod h1:qWi1OPS0B+b5L+Sg6Gmc9zD1Y+HaM0MdUr7LsupY1P4= +cloud.google.com/go/pubsublite v1.5.0/go.mod h1:xapqNQ1CuLfGi23Yda/9l4bBCKz/wC3KIJ5gKcxveZg= +cloud.google.com/go/pubsublite v1.6.0/go.mod h1:1eFCS0U11xlOuMFV/0iBqw3zP12kddMeCbj/F3FSj9k= +cloud.google.com/go/pubsublite v1.7.0/go.mod h1:8hVMwRXfDfvGm3fahVbtDbiLePT3gpoiJYJY+vxWxVM= +cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4= +cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o= +cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk= +cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7dd5NwwNQUErSgEDit1DLNTdo= +cloud.google.com/go/recaptchaenterprise/v2 v2.4.0/go.mod h1:Am3LHfOuBstrLrNCBrlI5sbwx9LBg3te2N6hGvHn2mE= +cloud.google.com/go/recaptchaenterprise/v2 v2.5.0/go.mod h1:O8LzcHXN3rz0j+LBC91jrwI3R+1ZSZEWrfL7XHgNo9U= +cloud.google.com/go/recaptchaenterprise/v2 v2.6.0/go.mod h1:RPauz9jeLtB3JVzg6nCbe12qNoaa8pXc4d/YukAmcnA= +cloud.google.com/go/recaptchaenterprise/v2 v2.7.0/go.mod h1:19wVj/fs5RtYtynAPJdDTb69oW0vNHYDBTbB4NvMD9c= +cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg= +cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4= +cloud.google.com/go/recommendationengine v0.7.0/go.mod h1:1reUcE3GIu6MeBz/h5xZJqNLuuVjNg1lmWMPyjatzac= +cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg= +cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c= +cloud.google.com/go/recommender v1.7.0/go.mod h1:XLHs/W+T8olwlGOgfQenXBTbIseGclClff6lhFVe9Bs= +cloud.google.com/go/recommender v1.8.0/go.mod h1:PkjXrTT05BFKwxaUxQmtIlrtj0kph108r02ZZQ5FE70= +cloud.google.com/go/recommender v1.9.0/go.mod h1:PnSsnZY7q+VL1uax2JWkt/UegHssxjUVVCrX52CuEmQ= +cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y= +cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A= +cloud.google.com/go/redis v1.9.0/go.mod h1:HMYQuajvb2D0LvMgZmLDZW8V5aOC/WxstZHiy4g8OiA= +cloud.google.com/go/redis v1.10.0/go.mod h1:ThJf3mMBQtW18JzGgh41/Wld6vnDDc/F/F35UolRZPM= +cloud.google.com/go/redis v1.11.0/go.mod h1:/X6eicana+BWcUda5PpwZC48o37SiFVTFSs0fWAJ7uQ= +cloud.google.com/go/resourcemanager v1.3.0/go.mod h1:bAtrTjZQFJkiWTPDb1WBjzvc6/kifjj4QBYuKCCoqKA= +cloud.google.com/go/resourcemanager v1.4.0/go.mod h1:MwxuzkumyTX7/a3n37gmsT3py7LIXwrShilPh3P1tR0= +cloud.google.com/go/resourcemanager v1.5.0/go.mod h1:eQoXNAiAvCf5PXxWxXjhKQoTMaUSNrEfg+6qdf/wots= +cloud.google.com/go/resourcemanager v1.6.0/go.mod h1:YcpXGRs8fDzcUl1Xw8uOVmI8JEadvhRIkoXXUNVYcVo= +cloud.google.com/go/resourcemanager v1.7.0/go.mod h1:HlD3m6+bwhzj9XCouqmeiGuni95NTrExfhoSrkC/3EI= +cloud.google.com/go/resourcesettings v1.3.0/go.mod h1:lzew8VfESA5DQ8gdlHwMrqZs1S9V87v3oCnKCWoOuQU= +cloud.google.com/go/resourcesettings v1.4.0/go.mod h1:ldiH9IJpcrlC3VSuCGvjR5of/ezRrOxFtpJoJo5SmXg= +cloud.google.com/go/resourcesettings v1.5.0/go.mod h1:+xJF7QSG6undsQDfsCJyqWXyBwUoJLhetkRMDRnIoXA= +cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4= +cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY= +cloud.google.com/go/retail v1.10.0/go.mod h1:2gDk9HsL4HMS4oZwz6daui2/jmKvqShXKQuB2RZ+cCc= +cloud.google.com/go/retail v1.11.0/go.mod h1:MBLk1NaWPmh6iVFSz9MeKG/Psyd7TAgm6y/9L2B4x9Y= +cloud.google.com/go/retail v1.12.0/go.mod h1:UMkelN/0Z8XvKymXFbD4EhFJlYKRx1FGhQkVPU5kF14= +cloud.google.com/go/run v0.2.0/go.mod h1:CNtKsTA1sDcnqqIFR3Pb5Tq0usWxJJvsWOCPldRU3Do= +cloud.google.com/go/run v0.3.0/go.mod h1:TuyY1+taHxTjrD0ZFk2iAR+xyOXEA0ztb7U3UNA0zBo= +cloud.google.com/go/run v0.8.0/go.mod h1:VniEnuBwqjigv0A7ONfQUaEItaiCRVujlMqerPPiktM= +cloud.google.com/go/run v0.9.0/go.mod h1:Wwu+/vvg8Y+JUApMwEDfVfhetv30hCG4ZwDR/IXl2Qg= +cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s= +cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI= +cloud.google.com/go/scheduler v1.6.0/go.mod h1:SgeKVM7MIwPn3BqtcBntpLyrIJftQISRrYB5ZtT+KOk= +cloud.google.com/go/scheduler v1.7.0/go.mod h1:jyCiBqWW956uBjjPMMuX09n3x37mtyPJegEWKxRsn44= +cloud.google.com/go/scheduler v1.8.0/go.mod h1:TCET+Y5Gp1YgHT8py4nlg2Sew8nUHMqcpousDgXJVQc= +cloud.google.com/go/scheduler v1.9.0/go.mod h1:yexg5t+KSmqu+njTIh3b7oYPheFtBWGcbVUYF1GGMIc= +cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA= +cloud.google.com/go/secretmanager v1.8.0/go.mod h1:hnVgi/bN5MYHd3Gt0SPuTPPp5ENina1/LxM+2W9U9J4= +cloud.google.com/go/secretmanager v1.9.0/go.mod h1:b71qH2l1yHmWQHt9LC80akm86mX8AL6X1MA01dW8ht4= +cloud.google.com/go/secretmanager v1.10.0/go.mod h1:MfnrdvKMPNra9aZtQFvBcvRU54hbPD8/HayQdlUgJpU= +cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4= +cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0= +cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU= +cloud.google.com/go/security v1.9.0/go.mod h1:6Ta1bO8LXI89nZnmnsZGp9lVoVWXqsVbIq/t9dzI+2Q= +cloud.google.com/go/security v1.10.0/go.mod h1:QtOMZByJVlibUT2h9afNDWRZ1G96gVywH8T5GUSb9IA= +cloud.google.com/go/security v1.12.0/go.mod h1:rV6EhrpbNHrrxqlvW0BWAIawFWq3X90SduMJdFwtLB8= +cloud.google.com/go/security v1.13.0/go.mod h1:Q1Nvxl1PAgmeW0y3HTt54JYIvUdtcpYKVfIB8AOMZ+0= +cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU= +cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc= +cloud.google.com/go/securitycenter v1.15.0/go.mod h1:PeKJ0t8MoFmmXLXWm41JidyzI3PJjd8sXWaVqg43WWk= +cloud.google.com/go/securitycenter v1.16.0/go.mod h1:Q9GMaLQFUD+5ZTabrbujNWLtSLZIZF7SAR0wWECrjdk= +cloud.google.com/go/securitycenter v1.18.1/go.mod h1:0/25gAzCM/9OL9vVx4ChPeM/+DlfGQJDwBy/UC8AKK0= +cloud.google.com/go/securitycenter v1.19.0/go.mod h1:LVLmSg8ZkkyaNy4u7HCIshAngSQ8EcIRREP3xBnyfag= +cloud.google.com/go/servicecontrol v1.4.0/go.mod h1:o0hUSJ1TXJAmi/7fLJAedOovnujSEvjKCAFNXPQ1RaU= +cloud.google.com/go/servicecontrol v1.5.0/go.mod h1:qM0CnXHhyqKVuiZnGKrIurvVImCs8gmqWsDoqe9sU1s= +cloud.google.com/go/servicecontrol v1.10.0/go.mod h1:pQvyvSRh7YzUF2efw7H87V92mxU8FnFDawMClGCNuAA= +cloud.google.com/go/servicecontrol v1.11.0/go.mod h1:kFmTzYzTUIuZs0ycVqRHNaNhgR+UMUpw9n02l/pY+mc= +cloud.google.com/go/servicecontrol v1.11.1/go.mod h1:aSnNNlwEFBY+PWGQ2DoM0JJ/QUXqV5/ZD9DOLB7SnUk= +cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs= +cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg= +cloud.google.com/go/servicedirectory v1.6.0/go.mod h1:pUlbnWsLH9c13yGkxCmfumWEPjsRs1RlmJ4pqiNjVL4= +cloud.google.com/go/servicedirectory v1.7.0/go.mod h1:5p/U5oyvgYGYejufvxhgwjL8UVXjkuw7q5XcG10wx1U= +cloud.google.com/go/servicedirectory v1.8.0/go.mod h1:srXodfhY1GFIPvltunswqXpVxFPpZjf8nkKQT7XcXaY= +cloud.google.com/go/servicedirectory v1.9.0/go.mod h1:29je5JjiygNYlmsGz8k6o+OZ8vd4f//bQLtvzkPPT/s= +cloud.google.com/go/servicemanagement v1.4.0/go.mod h1:d8t8MDbezI7Z2R1O/wu8oTggo3BI2GKYbdG4y/SJTco= +cloud.google.com/go/servicemanagement v1.5.0/go.mod h1:XGaCRe57kfqu4+lRxaFEAuqmjzF0r+gWHjWqKqBvKFo= +cloud.google.com/go/servicemanagement v1.6.0/go.mod h1:aWns7EeeCOtGEX4OvZUWCCJONRZeFKiptqKf1D0l/Jc= +cloud.google.com/go/servicemanagement v1.8.0/go.mod h1:MSS2TDlIEQD/fzsSGfCdJItQveu9NXnUniTrq/L8LK4= +cloud.google.com/go/serviceusage v1.3.0/go.mod h1:Hya1cozXM4SeSKTAgGXgj97GlqUvF5JaoXacR1JTP/E= +cloud.google.com/go/serviceusage v1.4.0/go.mod h1:SB4yxXSaYVuUBYUml6qklyONXNLt83U0Rb+CXyhjEeU= +cloud.google.com/go/serviceusage v1.5.0/go.mod h1:w8U1JvqUqwJNPEOTQjrMHkw3IaIFLoLsPLvsE3xueec= +cloud.google.com/go/serviceusage v1.6.0/go.mod h1:R5wwQcbOWsyuOfbP9tGdAnCAc6B9DRwPG1xtWMDeuPA= +cloud.google.com/go/shell v1.3.0/go.mod h1:VZ9HmRjZBsjLGXusm7K5Q5lzzByZmJHf1d0IWHEN5X4= +cloud.google.com/go/shell v1.4.0/go.mod h1:HDxPzZf3GkDdhExzD/gs8Grqk+dmYcEjGShZgYa9URw= +cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+qE2f9A= +cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos= +cloud.google.com/go/spanner v1.44.0/go.mod h1:G8XIgYdOK+Fbcpbs7p2fiprDw4CaZX63whnSMLVBxjk= +cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M= +cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= +cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= +cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= +cloud.google.com/go/speech v1.9.0/go.mod h1:xQ0jTcmnRFFM2RfX/U+rk6FQNUF6DQlydUSyoooSpco= +cloud.google.com/go/speech v1.14.1/go.mod h1:gEosVRPJ9waG7zqqnsHpYTOoAS4KouMRLDFMekpJ0J0= +cloud.google.com/go/speech v1.15.0/go.mod h1:y6oH7GhqCaZANH7+Oe0BhgIogsNInLlz542tg3VqeYI= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= +cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= +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.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4= +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= +cloud.google.com/go/storagetransfer v1.8.0/go.mod h1:JpegsHHU1eXg7lMHkvf+KE5XDJ7EQu0GwNJbbVGanEw= +cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= +cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= +cloud.google.com/go/talent v1.3.0/go.mod h1:CmcxwJ/PKfRgd1pBjQgU6W3YBwiewmUzQYH5HHmSCmM= +cloud.google.com/go/talent v1.4.0/go.mod h1:ezFtAgVuRf8jRsvyE6EwmbTK5LKciD4KVnHuDEFmOOA= +cloud.google.com/go/talent v1.5.0/go.mod h1:G+ODMj9bsasAEJkQSzO2uHQWXHHXUomArjWQQYkqK6c= +cloud.google.com/go/texttospeech v1.4.0/go.mod h1:FX8HQHA6sEpJ7rCMSfXuzBcysDAuWusNNNvN9FELDd8= +cloud.google.com/go/texttospeech v1.5.0/go.mod h1:oKPLhR4n4ZdQqWKURdwxMy0uiTS1xU161C8W57Wkea4= +cloud.google.com/go/texttospeech v1.6.0/go.mod h1:YmwmFT8pj1aBblQOI3TfKmwibnsfvhIBzPXcW4EBovc= +cloud.google.com/go/tpu v1.3.0/go.mod h1:aJIManG0o20tfDQlRIej44FcwGGl/cD0oiRyMKG19IQ= +cloud.google.com/go/tpu v1.4.0/go.mod h1:mjZaX8p0VBgllCzF6wcU2ovUXN9TONFLd7iz227X2Xg= +cloud.google.com/go/tpu v1.5.0/go.mod h1:8zVo1rYDFuW2l4yZVY0R0fb/v44xLh3llq7RuV61fPM= +cloud.google.com/go/trace v1.3.0/go.mod h1:FFUE83d9Ca57C+K8rDl/Ih8LwOzWIV1krKgxg6N0G28= +cloud.google.com/go/trace v1.4.0/go.mod h1:UG0v8UBqzusp+z63o7FK74SdFE+AXpCLdFb1rshXG+Y= +cloud.google.com/go/trace v1.8.0/go.mod h1:zH7vcsbAhklH8hWFig58HvxcxyQbaIqMarMg9hn5ECA= +cloud.google.com/go/trace v1.9.0/go.mod h1:lOQqpE5IaWY0Ixg7/r2SjixMuc6lfTFeO4QGM4dQWOk= +cloud.google.com/go/translate v1.3.0/go.mod h1:gzMUwRjvOqj5i69y/LYLd8RrNQk+hOmIXTi9+nb3Djs= +cloud.google.com/go/translate v1.4.0/go.mod h1:06Dn/ppvLD6WvA5Rhdp029IX2Mi3Mn7fpMRLPvXT5Wg= +cloud.google.com/go/translate v1.5.0/go.mod h1:29YDSYveqqpA1CQFD7NQuP49xymq17RXNaUDdc0mNu0= +cloud.google.com/go/translate v1.6.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= +cloud.google.com/go/translate v1.7.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= +cloud.google.com/go/video v1.8.0/go.mod h1:sTzKFc0bUSByE8Yoh8X0mn8bMymItVGPfTuUBUyRgxk= +cloud.google.com/go/video v1.9.0/go.mod h1:0RhNKFRF5v92f8dQt0yhaHrEuH95m068JYOvLZYnJSw= +cloud.google.com/go/video v1.12.0/go.mod h1:MLQew95eTuaNDEGriQdcYn0dTwf9oWiA4uYebxM5kdg= +cloud.google.com/go/video v1.13.0/go.mod h1:ulzkYlYgCp15N2AokzKjy7MQ9ejuynOJdf1tR5lGthk= +cloud.google.com/go/video v1.14.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= +cloud.google.com/go/video v1.15.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= +cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= +cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4= +cloud.google.com/go/videointelligence v1.8.0/go.mod h1:dIcCn4gVDdS7yte/w+koiXn5dWVplOZkE+xwG9FgK+M= +cloud.google.com/go/videointelligence v1.9.0/go.mod h1:29lVRMPDYHikk3v8EdPSaL8Ku+eMzDljjuvRs105XoU= +cloud.google.com/go/videointelligence v1.10.0/go.mod h1:LHZngX1liVtUhZvi2uNS0VQuOzNi2TkY1OakiuoUOjU= +cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0= +cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo= +cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo= +cloud.google.com/go/vision/v2 v2.4.0/go.mod h1:VtI579ll9RpVTrdKdkMzckdnwMyX2JILb+MhPqRbPsY= +cloud.google.com/go/vision/v2 v2.5.0/go.mod h1:MmaezXOOE+IWa+cS7OhRRLK2cNv1ZL98zhqFFZaaH2E= +cloud.google.com/go/vision/v2 v2.6.0/go.mod h1:158Hes0MvOS9Z/bDMSFpjwsUrZ5fPrdwuyyvKSGAGMY= +cloud.google.com/go/vision/v2 v2.7.0/go.mod h1:H89VysHy21avemp6xcf9b9JvZHVehWbET0uT/bcuY/0= +cloud.google.com/go/vmmigration v1.2.0/go.mod h1:IRf0o7myyWFSmVR1ItrBSFLFD/rJkfDCUTO4vLlJvsE= +cloud.google.com/go/vmmigration v1.3.0/go.mod h1:oGJ6ZgGPQOFdjHuocGcLqX4lc98YQ7Ygq8YQwHh9A7g= +cloud.google.com/go/vmmigration v1.5.0/go.mod h1:E4YQ8q7/4W9gobHjQg4JJSgXXSgY21nA5r8swQV+Xxc= +cloud.google.com/go/vmmigration v1.6.0/go.mod h1:bopQ/g4z+8qXzichC7GW1w2MjbErL54rk3/C843CjfY= +cloud.google.com/go/vmwareengine v0.1.0/go.mod h1:RsdNEf/8UDvKllXhMz5J40XxDrNJNN4sagiox+OI208= +cloud.google.com/go/vmwareengine v0.2.2/go.mod h1:sKdctNJxb3KLZkE/6Oui94iw/xs9PRNC2wnNLXsHvH8= +cloud.google.com/go/vmwareengine v0.3.0/go.mod h1:wvoyMvNWdIzxMYSpH/R7y2h5h3WFkx6d+1TIsP39WGY= +cloud.google.com/go/vpcaccess v1.4.0/go.mod h1:aQHVbTWDYUR1EbTApSVvMq1EnT57ppDmQzZ3imqIk4w= +cloud.google.com/go/vpcaccess v1.5.0/go.mod h1:drmg4HLk9NkZpGfCmZ3Tz0Bwnm2+DKqViEpeEpOq0m8= +cloud.google.com/go/vpcaccess v1.6.0/go.mod h1:wX2ILaNhe7TlVa4vC5xce1bCnqE3AeH27RV31lnmZes= +cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE= +cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= +cloud.google.com/go/webrisk v1.6.0/go.mod h1:65sW9V9rOosnc9ZY7A7jsy1zoHS5W9IAXv6dGqhMQMc= +cloud.google.com/go/webrisk v1.7.0/go.mod h1:mVMHgEYH0r337nmt1JyLthzMr6YxwN1aAIEc2fTcq7A= +cloud.google.com/go/webrisk v1.8.0/go.mod h1:oJPDuamzHXgUc+b8SiHRcVInZQuybnvEW72PqTc7sSg= +cloud.google.com/go/websecurityscanner v1.3.0/go.mod h1:uImdKm2wyeXQevQJXeh8Uun/Ym1VqworNDlBXQevGMo= +cloud.google.com/go/websecurityscanner v1.4.0/go.mod h1:ebit/Fp0a+FWu5j4JOmJEV8S8CzdTkAS77oDsiSqYWQ= +cloud.google.com/go/websecurityscanner v1.5.0/go.mod h1:Y6xdCPy81yi0SQnDY1xdNTNpfY1oAgXUlcfN3B3eSng= +cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= +cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= +cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M= +cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA= +cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw= +contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA= +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 v32.4.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v32.6.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v44.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/go-autorest v11.1.2+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest v0.1.0/go.mod h1:AKyIcETwSUFxIcs/Wnq/C+kwCtlEYGUVd7FPNb2slmg= +github.com/Azure/go-autorest/autorest v0.5.0/go.mod h1:9HLKlQjVBH6U3oDfsXOeVc56THsLPw1L03yban4xThw= +github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= +github.com/Azure/go-autorest/autorest v0.9.2/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= +github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0= +github.com/Azure/go-autorest/autorest v0.11.0/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= +github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= +github.com/Azure/go-autorest/autorest/adal v0.1.0/go.mod h1:MeS4XhScH55IST095THyTxElntu7WqB7pNbZo8Q5G3E= +github.com/Azure/go-autorest/autorest/adal v0.2.0/go.mod h1:MeS4XhScH55IST095THyTxElntu7WqB7pNbZo8Q5G3E= +github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= +github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= +github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= +github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= +github.com/Azure/go-autorest/autorest/azure/auth v0.1.0/go.mod h1:Gf7/i2FUpyb/sGBLIFxTBzrNzBo7aPXXE3ZVeDRwdpM= +github.com/Azure/go-autorest/autorest/azure/auth v0.4.1/go.mod h1:5TgH20II424SXIV9YDBsO4rBCKsh39Vbx9DvhJZZ8rU= +github.com/Azure/go-autorest/autorest/azure/auth v0.5.0/go.mod h1:QRTvSZQpxqm8mSErhnbI+tANIBAKP7B+UIE2z4ypUO0= +github.com/Azure/go-autorest/autorest/azure/cli v0.1.0/go.mod h1:Dk8CUAt/b/PzkfeRsWzVG9Yj3ps8mS8ECztu43rdU8U= +github.com/Azure/go-autorest/autorest/azure/cli v0.3.1/go.mod h1:ZG5p860J94/0kI9mNJVoIoLgXcirM2gF5i2kWloofxw= +github.com/Azure/go-autorest/autorest/azure/cli v0.4.0/go.mod h1:JljT387FplPzBA31vUcvsetLKF3pec5bdAxjVU4kI2s= +github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= +github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= +github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= +github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc= +github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= +github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8= +github.com/Azure/go-autorest/autorest/validation v0.3.0/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E= +github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= +github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/tracing v0.1.0/go.mod h1:ROEEAFwXycQw7Sn3DXNtEedEvdeRAgDr0izn4z5Ij88= +github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= +github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/DataDog/zstd v1.3.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/HdrHistogram/hdrhistogram-go v1.0.1/go.mod h1:BWJ+nMSHY3L41Zj7CA3uXnloDp7xxV0YvstAE7nKTaM= +github.com/HdrHistogram/hdrhistogram-go v1.1.0/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= +github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= +github.com/Microsoft/go-winio v0.4.3/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= +github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/NYTimes/gziphandler v1.0.1/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87/go.mod h1:iGLljf5n9GjT6kc0HBvyI1nOKnGQbNB66VzSNbK5iks= +github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/sarama v1.21.0/go.mod h1:yuqtN/pe8cXRWG5zPaO7hCfNJp5MwmkoJEoLjkm5tCQ= +github.com/Shopify/sarama v1.26.1/go.mod h1:NbSGBSSndYaIhRcBtY9V0U7AyH+x71bG668AuWys/yU= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af/go.mod h1:5Jv4cbFiHJMsVxt52+i0Ha45fjshj6wxYr1r19tB9bw= +github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= +github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= +github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= +github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= +github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= +github.com/akamai/AkamaiOPEN-edgegrid-golang v0.9.0/go.mod h1:zpDJeKyp9ScW4NNrbdr+Eyxvry3ilGPewKoXw3XGN1k= +github.com/alangpierce/go-forceexport v0.0.0-20160317203124-8f1d6941cd75/go.mod h1:uAXEEpARkRhCZfEvy/y0Jcc888f9tHCc1W7/UeEtreE= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190808125512-07798873deee/go.mod h1:myCDvQSzCW+wB1WAlocEru4wMGJxy+vlxHdhegi1CDQ= +github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk= +github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0= +github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg= +github.com/armon/go-metrics v0.3.8/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= +github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= +github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= +github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= +github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= +github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= +github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= +github.com/aws/aws-sdk-go v1.23.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.25.41/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.30.27/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= +github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48= +github.com/aws/aws-sdk-go v1.42.34/go.mod h1:OGr6lGMAKGlG9CVrYnWYDKIyb829c6EVBRjxqjmPepc= +github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc= +github.com/benbjohnson/immutable v0.4.0/go.mod h1:iAr8OjJGLnLmVUr9MZ/rz4PWUy6Ouc2JLYuMArmvAJM= +github.com/benmathews/bench v0.0.0-20210120214102-f7c75b9ef6e7/go.mod h1:peX7BEhSFSvvnxdido50pUMhlFi24dVgtTU1oZkHTUU= +github.com/benmathews/hdrhistogram-writer v0.0.0-20180430173243-73b8d31ba571/go.mod h1:W24iTD3jetRjSLj2yz0IBNF6wKdbRUvBMG5oaw4ZbzM= +github.com/benmathews/hdrhistogram-writer v0.0.0-20210120211942-3cb1c7c33f95/go.mod h1:2MBckC8FahPaeLz58Qe6ZyVKm8UU1gHkINEv9Sw7pnI= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= +github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= +github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= +github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/caddyserver/caddy v1.0.4/go.mod h1:uruyfVsyMcDb3IOzSKsi1x0wOjy1my/PxOSTcD+24jM= +github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= +github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= +github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudflare/cloudflare-go v0.10.2/go.mod h1:qhVI5MKwBGhdNU89ZRz2plgYutcJ5PCekLxXn56w6SY= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed h1:OZmjad4L3H8ncOIR8rnb5MREYqG8ixi5+WbeUsquF0c= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +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 h1:58f1tJ1ra+zFINPlwLWvQsR9CzAKt2e+EWV2yX9oXQ4= +github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/coredns/coredns v1.6.6/go.mod h1:Bdcnka9HmKGYj12ZIDF3lpQSfDHSsMc85Wj9xEyZUts= +github.com/coredns/federation v0.0.0-20190818181423-e032b096babe/go.mod h1:MoqTEFX8GlnKkyq8eBCF94VzkNAOgjdlCJ+Pz/oCLPk= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.27+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190212144455-93d5ec2c7f76/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/pkg v0.0.0-20220810130054-c7d1c02cb6cf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpu/goacmedns v0.0.1/go.mod h1:sesf/pNnCYwUevQEQfEwY0Y3DydlQWSGZbaMElOWxok= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decker502/dnspod-go v0.2.0/go.mod h1:qsurYu1FgxcDwfSwXJdLt4kRsBLZeosEb9uq4Sy+08g= +github.com/denverdino/aliyungo v0.0.0-20170926055100-d3308649c661/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= +github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/digitalocean/godo v1.7.5/go.mod h1:h6faOIcZ8lWIwNQ+DN7b3CgX4Kwby5T+nbpNqkUIozU= +github.com/digitalocean/godo v1.10.0/go.mod h1:h6faOIcZ8lWIwNQ+DN7b3CgX4Kwby5T+nbpNqkUIozU= +github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= +github.com/dnaeon/go-vcr v0.0.0-20180814043457-aafff18a5cc2/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= +github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= +github.com/dnsimple/dnsimple-go v0.30.0/go.mod h1:O5TJ0/U6r7AfT8niYNlmohpLbCSG+c71tQlGr9SeGrg= +github.com/dnstap/golang-dnstap v0.0.0-20170829151710-2cf77a2b5e11/go.mod h1:s1PfVYYVmTMgCSPtho4LKBDecEHJWtiVDPNv78Z985U= +github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.9 h1:vQLjymTobffN2R0F8eTqw6q7iozfRO5Z0m+/4Vw+/uA= -github.com/envoyproxy/go-control-plane v0.9.9/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= +github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= +github.com/envoyproxy/go-control-plane v0.11.0 h1:jtLewhRR2vMRNnq2ZZUoCjUlgut+Y0+sDDWPOfwOi1o= +github.com/envoyproxy/go-control-plane v0.11.0/go.mod h1:VnHyVMpzcLvCFt9yUz1UnCwHLhwx1WguiVDV7pTG/tI= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= +github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= +github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= +github.com/envoyproxy/protoc-gen-validate v0.10.0 h1:oIfnZFdC0YhpNNEX+SuIqko4cqqVZeN9IGTrhZje83Y= +github.com/envoyproxy/protoc-gen-validate v0.10.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= +github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.1.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch/v5 v5.5.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= +github.com/exoscale/egoscale v0.18.1/go.mod h1:Z7OOdzzTOz1Q1PjQXumlz9Wn/CddH0zSYdCF3rnBKXE= +github.com/farsightsec/golang-framestream v0.0.0-20181102145529-8a0cb8ba8710/go.mod h1:eNde4IQyEiA5br02AouhEHCu3p3UzrCdFR4LuQHklMI= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= +github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/frankban/quicktest v1.7.2/go.mod h1:jaStnuzAqU1AJdCO0l53JDCJrVDKcS03DbaAcR7Ks/o= +github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y= +github.com/frankban/quicktest v1.13.0/go.mod h1:qLE0fzW0VuyUAJgPU19zByoIr0HtCHN/r/VLSOOIySU= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= +github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= +github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= +github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= +github.com/go-acme/lego/v3 v3.1.0/go.mod h1:074uqt+JS6plx+c9Xaiz6+L+GBb+7itGtzfcDM2AhEE= +github.com/go-acme/lego/v3 v3.2.0/go.mod h1:074uqt+JS6plx+c9Xaiz6+L+GBb+7itGtzfcDM2AhEE= +github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= +github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s= +github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= +github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= +github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= +github.com/go-fonts/liberation v0.2.0/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= +github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-ini/ini v1.44.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= +github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk= +github.com/go-ldap/ldap/v3 v3.1.10/go.mod h1:5Zun81jBTabRaI8lzN7E1JjyEl1g6zI6u9pd8luAK4Q= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= +github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= +github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= +github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk= +github.com/go-openapi/analysis v0.19.4/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk= +github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU= +github.com/go-openapi/analysis v0.19.10/go.mod h1:qmhS3VNFxBlquFJ0RGoDtylO9y4pgTAUNE9AEEMdlJQ= +github.com/go-openapi/analysis v0.19.16/go.mod h1:GLInF007N83Ad3m8a/CbQ5TPzdnGT7workfHwuVjNVk= +github.com/go-openapi/analysis v0.20.0/go.mod h1:BMchjvaHDykmRMsK40iPtvyOfFdMMxlOmQr9FBZk+Og= +github.com/go-openapi/analysis v0.21.2/go.mod h1:HZwRk4RRisyG8vx2Oe6aqeSQcoxRp47Xkp3+K6q+LdY= +github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= +github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= +github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= +github.com/go-openapi/errors v0.19.3/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= +github.com/go-openapi/errors v0.19.6/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= +github.com/go-openapi/errors v0.19.7/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= +github.com/go-openapi/errors v0.19.8/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= +github.com/go-openapi/errors v0.19.9/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= +github.com/go-openapi/errors v0.20.1/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= +github.com/go-openapi/errors v0.20.2/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= +github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= +github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= +github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= +github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= +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/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= +github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= +github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= +github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= +github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= +github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= +github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= +github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= +github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= +github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs= +github.com/go-openapi/loads v0.19.3/go.mod h1:YVfqhUCdahYwR3f3iiwQLhicVRvLlU/WO5WPaZvcvSI= +github.com/go-openapi/loads v0.19.5/go.mod h1:dswLCAdonkRufe/gSUC3gN8nTSaB9uaS2es0x5/IbjY= +github.com/go-openapi/loads v0.19.6/go.mod h1:brCsvE6j8mnbmGBh103PT/QLHfbyDxA4hsKvYBNEGVc= +github.com/go-openapi/loads v0.19.7/go.mod h1:brCsvE6j8mnbmGBh103PT/QLHfbyDxA4hsKvYBNEGVc= +github.com/go-openapi/loads v0.20.0/go.mod h1:2LhKquiE513rN5xC6Aan6lYOSddlL8Mp20AW9kpviM4= +github.com/go-openapi/loads v0.20.2/go.mod h1:hTVUotJ+UonAMMZsvakEgmWKgtulweO9vYP2bQYKA/o= +github.com/go-openapi/loads v0.21.1/go.mod h1:/DtAMXXneXFjbQMGEtbamCZb+4x7eGwkvZCvBmwUG+g= +github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA= +github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64= +github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4= +github.com/go-openapi/runtime v0.19.15/go.mod h1:dhGWCTKRXlAfGnQG0ONViOZpjfg0m2gUt9nTQPQZuoo= +github.com/go-openapi/runtime v0.19.16/go.mod h1:5P9104EJgYcizotuXhEuUrzVc+j1RiSjahULvYmlv98= +github.com/go-openapi/runtime v0.19.24/go.mod h1:Lm9YGCeecBnUUkFTxPC4s1+lwrkJ0pthx8YvyjCfkgk= +github.com/go-openapi/runtime v0.24.1/go.mod h1:AKurw9fNre+h3ELZfk6ILsfvPN+bvvlaU/M9q/r9hpk= +github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= +github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= +github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= +github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= +github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= +github.com/go-openapi/spec v0.19.6/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= +github.com/go-openapi/spec v0.19.8/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= +github.com/go-openapi/spec v0.19.15/go.mod h1:+81FIL1JwC5P3/Iuuozq3pPE9dXdIEGxFutcFKaVbmU= +github.com/go-openapi/spec v0.20.0/go.mod h1:+81FIL1JwC5P3/Iuuozq3pPE9dXdIEGxFutcFKaVbmU= +github.com/go-openapi/spec v0.20.1/go.mod h1:93x7oh+d+FQsmsieroS4cmR3u0p/ywH649a3qwC9OsQ= +github.com/go-openapi/spec v0.20.3/go.mod h1:gG4F8wdEDN+YPBMVnzE85Rbhf+Th2DTvA9nFPQ5AYEg= +github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= +github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= +github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= +github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY= +github.com/go-openapi/strfmt v0.19.2/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU= +github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU= +github.com/go-openapi/strfmt v0.19.4/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= +github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= +github.com/go-openapi/strfmt v0.19.11/go.mod h1:UukAYgTaQfqJuAFlNxxMWNvMYiwiXtLsF2VwmoFtbtc= +github.com/go-openapi/strfmt v0.20.0/go.mod h1:UukAYgTaQfqJuAFlNxxMWNvMYiwiXtLsF2VwmoFtbtc= +github.com/go-openapi/strfmt v0.21.0/go.mod h1:ZRQ409bWMj+SOgXofQAGTIo2Ebu72Gs+WaRADcS5iNg= +github.com/go-openapi/strfmt v0.21.1/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k= +github.com/go-openapi/strfmt v0.21.2/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k= +github.com/go-openapi/strfmt v0.21.3/go.mod h1:k+RzNO0Da+k3FrrynSNN8F7n/peCmQQqbbXjtDfvmGg= +github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= +github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= +github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= +github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.7/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY= +github.com/go-openapi/swag v0.19.9/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY= +github.com/go-openapi/swag v0.19.12/go.mod h1:eFdyEBkTdoAf/9RXBvj4cr1nH7GD8Kzo5HTt47gr72M= +github.com/go-openapi/swag v0.19.13/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= +github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= +github.com/go-openapi/validate v0.19.3/go.mod h1:90Vh6jjkTn+OT1Eefm0ZixWNFjhtOH7vS9k0lo6zwJo= +github.com/go-openapi/validate v0.19.10/go.mod h1:RKEZTUWDkxKQxN2jDT7ZnZi2bhZlbNMAuKvKB+IaGx8= +github.com/go-openapi/validate v0.19.12/go.mod h1:Rzou8hA/CBw8donlS6WNEUQupNvUZ0waH08tGe6kAQ4= +github.com/go-openapi/validate v0.19.15/go.mod h1:tbn/fdOwYHgrhPBzidZfJC2MIVvs9GA7monOmWBbeCI= +github.com/go-openapi/validate v0.20.1/go.mod h1:b60iJT+xNNLfaQJUqLI7946tYiFEOuE9E4k54HpKcJ0= +github.com/go-openapi/validate v0.20.2/go.mod h1:e7OJoKNgd0twXZwIn0A43tHbvIcr/rZIVCbJBpTUoY0= +github.com/go-openapi/validate v0.21.0/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg= +github.com/go-ozzo/ozzo-validation v3.6.0+incompatible/go.mod h1:gsEKFIVnabGBt6mXmxK0MoFy+cZoTJY6mu5Ll3LVLBU= +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-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= +github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= +github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= +github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= +github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= +github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs= +github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= +github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= +github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk= +github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28= +github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo= +github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk= +github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw= +github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360= +github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg= +github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE= +github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8= +github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= +github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= +github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= +github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= +github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= +github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= +github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= +github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/gocql/gocql v0.0.0-20200228163523-cd4b606dd2fb/go.mod h1:DL0ekTmBSTdlNF25Orwt/JMzqIq3EJ4MVa/J/uK64OY= +github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= 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/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +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= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -38,84 +1048,1388 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +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.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20160524151835-7d79101e329e/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/tcpproxy v0.0.0-20180808230851-dfa16c61dad2/go.mod h1:DavVbd41y+b7ukKDmlnPR4nGYmkWXR6vHUkjQNiHPBs= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= +github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= +github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= +github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= +github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= +github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= +github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= +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.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= +github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +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 v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4= +github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= +github.com/gophercloud/gophercloud v0.3.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/go-hclog v0.16.2 h1:K4ev2ib4LdQETX5cSZBG0DVLk1jwGqSPXBjdah3veNs= +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-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw= +github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= +github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= +github.com/hashicorp/consul v1.15.2 h1:asG6/ZyA1Z5dw0SuhZ5sh/SG9605NI/L/PNJtCnl93M= +github.com/hashicorp/consul v1.15.2/go.mod h1:1pu3llMOz2pwT+KU3Hxqycm//67l9znFCxyhe2ufRHo= +github.com/hashicorp/consul-awsauth v0.0.0-20220713182709-05ac1c5c2706/go.mod h1:1Cs8FlmD1BfSQXJGcFLSV5FuIx1AbJP+EJGdxosoS2g= +github.com/hashicorp/consul-net-rpc v0.0.0-20221205195236-156cfab66a69/go.mod h1:svUZZDvotY8zTODknUePc6mZ9pX8nN0ViGwWcUSOBEA= +github.com/hashicorp/consul/api v1.20.0/go.mod h1:nR64eD44KQ59Of/ECwt2vUmIK2DKsDzAwTmwmLl8Wpo= +github.com/hashicorp/consul/envoyextensions v0.1.2/go.mod h1:N94DQQkgITiA40zuTQ/UdPOLAAWobgHfVT5u7wxE/aU= +github.com/hashicorp/consul/proto-public v0.2.1/go.mod h1:iWNlBDJIZQJC3bBiCThoqg9i7uk/4RQZYkqH1wiQrss= +github.com/hashicorp/consul/sdk v0.13.1 h1:EygWVWWMczTzXGpO93awkHFzfUka6hLYJ0qhETd+6lY= +github.com/hashicorp/consul/sdk v0.13.1/go.mod h1:SW/mM4LbKfqmMvcFu8v+eiQQ7oitXEFeiBe9StxERb0= +github.com/hashicorp/consul/troubleshoot v0.1.2/go.mod h1:q35QOtN7K5kFLPm2SXHBDD+PzsuBekcqTZuuoOTzbWA= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-bexpr v0.1.2/go.mod h1:ANbpTX1oAql27TZkKVeW8p1w8NTdnyzPe/0qqPCKohU= +github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-connlimit v0.3.0/go.mod h1:OUj9FGL1tPIhl/2RCfzYHrIiWj+VVPGNyVPnUX8AqS0= +github.com/hashicorp/go-discover v0.0.0-20220714221025-1c234a67149a/go.mod h1:1xfdKvc3pe5WKxfUUHHOGaKMk7NLGhHY1jkyhKo6098= +github.com/hashicorp/go-hclog v0.9.1/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= +github.com/hashicorp/go-hclog v1.2.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= +github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-kms-wrapping/entropy/v2 v2.0.0/go.mod h1:xvb32K2keAc+R8DSFG2IwDcydK9DBQE+fGA5fsw6hSk= +github.com/hashicorp/go-memdb v1.3.4/go.mod h1:uBTr1oQbtuMgd1SSGoR8YV27eT3sBHbYiNm53bMpgSg= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-msgpack v1.1.5/go.mod h1:gWVc3sv/wbDmR3rQsj1CAktEZzoz1YNK9NfGLXJ69/4= +github.com/hashicorp/go-msgpack/v2 v2.0.0/go.mod h1:JIxYkkFJRDDRSoWQBSh7s9QAVThq+82iWmUpmE4jKak= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-plugin v1.4.3/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ= +github.com/hashicorp/go-plugin v1.4.5/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= +github.com/hashicorp/go-raftchunking v0.7.0/go.mod h1:Dg/eBOaJzE0jYKNwNLs5IA5j0OSmL5HoCUiMy3mDmrI= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/go-retryablehttp v0.6.7/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= +github.com/hashicorp/go-secure-stdlib/awsutil v0.1.6/go.mod h1:MpCPSPGLDILGb4JMm94/mMi3YysIqsXzGCzkEZjcjXg= +github.com/hashicorp/go-secure-stdlib/base62 v0.1.1/go.mod h1:EdWO6czbmthiwZ3/PUsDV+UD1D5IRU4ActiaWGwt0Yw= +github.com/hashicorp/go-secure-stdlib/mlock v0.1.1/go.mod h1:zq93CJChV6L9QTfGKtfBxKqD7BqqXx5O04A/ns2p5+I= +github.com/hashicorp/go-secure-stdlib/parseutil v0.1.1/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8= +github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8= +github.com/hashicorp/go-secure-stdlib/password v0.1.1/go.mod h1:9hH302QllNwu1o2TGYtSk8I8kTAN0ca1EHpwhm5Mmzo= +github.com/hashicorp/go-secure-stdlib/strutil v0.1.1/go.mod h1:gKOamz3EwoIoJq7mlMIRBpVTAUn8qPCrEclOKKWhD3U= +github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4= +github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.1/go.mod h1:l8slYwnJA26yBz+ErHpp2IRCLr0vuOMGBORIz4rRiAs= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= +github.com/hashicorp/go-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI= +github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/hcp-scada-provider v0.2.0/go.mod h1:Q0WpS2RyhBKOPD4X/8oW7AJe7jA2HXB09EwDzwRTao0= +github.com/hashicorp/hcp-sdk-go v0.23.0/go.mod h1:/9UoDY2FYYA8lFaKBb2HmM/jKYZGANmf65q9QRc/cVw= +github.com/hashicorp/hcp-sdk-go v0.23.1-0.20220921131124-49168300a7dc/go.mod h1:/9UoDY2FYYA8lFaKBb2HmM/jKYZGANmf65q9QRc/cVw= +github.com/hashicorp/hil v0.0.0-20200423225030-a18a1cd20038/go.mod h1:n2TSygSNwsLJ76m8qFXTSc7beTb+auJxYdqrnoqwZWE= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= +github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= +github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0= +github.com/hashicorp/net-rpc-msgpackrpc/v2 v2.0.0/go.mod h1:6pdNz0vo0mF0GvhwDG56O3N18qBrAz/XRIcfINfTbwo= +github.com/hashicorp/raft v1.1.0/go.mod h1:4Ak7FSPnuvmb0GV6vgIAJ4vYT4bek9bb6Q+7HVbyzqM= +github.com/hashicorp/raft v1.2.0/go.mod h1:vPAJM8Asw6u8LxC3eJCUZmRP/E4QmUGE1R7g7k8sG/8= +github.com/hashicorp/raft v1.3.11/go.mod h1:J8naEwc6XaaCfts7+28whSeRvCqTd6e20BlCU3LtEO4= +github.com/hashicorp/raft v1.4.0/go.mod h1:nz64BIjXphDLATfKGG5RzHtNUPioLeKFsXEm88yTVew= +github.com/hashicorp/raft-autopilot v0.1.6/go.mod h1:Af4jZBwaNOI+tXfIqIdbcAnh/UyyqIMj/pOISIfhArw= +github.com/hashicorp/raft-boltdb v0.0.0-20171010151810-6e5ba93211ea/go.mod h1:pNv7Wc3ycL6F5oOWn+tPGo2gWD4a5X+yp/ntwdKLjRk= +github.com/hashicorp/raft-boltdb v0.0.0-20210409134258-03c10cc3d4ea/go.mod h1:qRd6nFJYYS6Iqnc/8HcUmko2/2Gw8qTFEmxDLii6W5I= +github.com/hashicorp/raft-boltdb v0.0.0-20220329195025-15018e9b97e0/go.mod h1:nTakvJ4XYq45UXtn0DbwR4aU9ZdjlnIenpbs6Cd+FM0= +github.com/hashicorp/raft-boltdb/v2 v2.2.2/go.mod h1:N8YgaZgNJLpZC+h+by7vDu5rzsRgONThTEeUS3zWbfY= +github.com/hashicorp/raft-wal v0.3.0/go.mod h1:A6vP5o8hGOs1LHfC1Okh9xPwWDcmb6Vvuz/QyqUXlOE= +github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= +github.com/hashicorp/vault/api v1.8.0/go.mod h1:uJrw6D3y9Rv7hhmS17JQC50jbPDAZdjZoTtrCCxxs7E= +github.com/hashicorp/vault/api v1.8.2/go.mod h1:ML8aYzBIhY5m1MD1B2Q0JV89cC85YVH4t5kBaZiyVaE= +github.com/hashicorp/vault/api/auth/gcp v0.3.0/go.mod h1:gnNBFOASYUaFunedTHOzdir7vKcHL3skWBUzEn263bo= +github.com/hashicorp/vault/sdk v0.6.0/go.mod h1:+DRpzoXIdMvKc88R4qxr+edwy/RvH5QK8itmxLiDHLc= +github.com/hashicorp/vic v1.5.1-0.20190403131502-bbfe86ec9443/go.mod h1:bEpDU35nTu0ey1EXjwNwPjI9xErAsoOCmcMb9GKvyxo= +github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= +github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/iancoleman/strcase v0.1.3/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= +github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4= +github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/infobloxopen/go-trees v0.0.0-20190313150506-2af4e13f9062/go.mod h1:PcNJqIlcX/dj3DTG/+QQnRvSgTMG6CLpRMjWcv4+J6w= +github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ= +github.com/jackc/pgx v3.3.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I= +github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da/go.mod h1:ks+b9deReOc7jgqp+e7LuFiCBH6Rm5hL32cLcEAArb4= +github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74= +github.com/jimstudt/http-authentication v0.0.0-20140401203705-3eca13d6893a/go.mod h1:wK6yTYYcgjHE1Z1QtXACPDjcFJyBskHEdagmnq3vsP8= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/joyent/triton-go v0.0.0-20180628001255-830d2b111e62/go.mod h1:U+RSyWxWd04xTqnuOQxnai7XGS2PrPY2cfGoDKtMHjA= +github.com/joyent/triton-go v1.7.1-0.20200416154420-6801d15b779f/go.mod h1:KDSfL7qe5ZfQqvlDMkVjCztbmcpp/c8M77vhQP8ZPvk= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= +github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +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.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.9.8/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +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/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/kolo/xmlrpc v0.0.0-20190717152603-07c4ee3fd181/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= +github.com/labbsr0x/bindman-dns-webhook v1.0.2/go.mod h1:p6b+VCXIR8NYKpDr8/dg1HKfQoRHCdcsROXKvmoehKA= +github.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c027w= +github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/linode/linodego v0.7.1/go.mod h1:ga11n3ivecUrPCHN0rANxKmfWBJVkOXfLMZinAbj2sY= +github.com/linode/linodego v0.10.0/go.mod h1:cziNP7pbvE3mXIPneHj0oRY8L1WtGEIKlZ8LANE4eXA= +github.com/liquidweb/liquidweb-go v1.6.0/go.mod h1:UDcVnAMDkZxpw4Y7NOHkqoeiGacVLEIG/i5J9cyixzQ= +github.com/lucas-clemente/quic-go v0.13.1/go.mod h1:Vn3/Fb0/77b02SGhQk36KzOUmXgVpFfizUfW5WMaqyU= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +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= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.1/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= +github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= +github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= +github.com/marten-seemann/chacha20 v0.2.0/go.mod h1:HSdjFau7GzYRj+ahFNwsO3ouVJr1HFkWoEwNDb4TMtE= +github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGDAUWqna+CNTrI= +github.com/marten-seemann/qtls v0.4.1/go.mod h1:pxVXcHHw1pNIt8Qo0pwSYQEoZ8yYOOPXTCZLQQunvRc= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-tty v0.0.0-20180219170247-931426f7535a/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mholt/certmagic v0.8.3/go.mod h1:91uJzK5K8IWtYQqTi5R2tsxV1pCde+wdGfaRaOZi6aQ= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.25/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= +github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= +github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= +github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/go-testing-interface v1.14.0/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= +github.com/mitchellh/go-vnc v0.0.0-20150629162542-723ed9867aed/go.mod h1:3rdaFaCv4AyBgu5ALFM0+tSuHrBh6v692nyQe3ikrq0= +github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= +github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ= +github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/pointerstructure v1.2.1/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= +github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04/go.mod h1:5sN+Lt1CaY4wsPvgQH/jsuJi4XO2ssZbdsIizr4CVC8= +github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= +github.com/naoina/toml v0.1.1/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/jwt v1.1.0/go.mod h1:n3cvmLfBfnpV4JJRN7lRYCyZnw48ksGsbThGXEk4w9M= +github.com/nats-io/nats-server/v2 v2.1.9/go.mod h1:9qVyoewoYXzG1ME9ox0HwkkzyYvnlBDugfR4Gg/8uHU= +github.com/nats-io/nats-streaming-server v0.20.0/go.mod h1:yJjUp4TmfYqllCtctAQ6Kz6ZRy5kaLgqHvuU1TGSrCw= +github.com/nats-io/nats.go v1.10.0/go.mod h1:AjGArbfyR50+afOUotNX2Xs5SYHf+CoOa5HH1eEl2HE= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.4/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/nats-io/stan.go v0.8.1/go.mod h1:Ci6mUIpGQTjl++MqK2XzkWI/0vF+Bl72uScx7ejSYmU= +github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= +github.com/nicolai86/scaleway-sdk v1.10.2-0.20180628010248-798f60e20bb2/go.mod h1:TLb2Sg7HQcgGdloNxkrmtgDNR9uVYF3lfdFIN4Ro6Sk= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nrdcg/auroradns v1.0.0/go.mod h1:6JPXKzIRzZzMqtTDgueIhTi6rFf1QvYE/HzqidhOhjw= +github.com/nrdcg/goinwx v0.6.1/go.mod h1:XPiut7enlbEdntAqalBIqcYcTEVhpv/dKWgDCX2SwKQ= +github.com/nrdcg/namesilo v0.2.1/go.mod h1:lwMvfQTyYq+BbjJd30ylEG4GPSS6PII0Tia4rRpRiyw= +github.com/nsqio/go-nsq v1.0.8/go.mod h1:vKq36oyeVXgsS5Q8YEO7WghqidAVXQlcFxzQbQTuDEY= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.0-20180130162743-b8a9be070da4/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.3.5/go.mod h1:uVHyebswE1cCXr2A73cRM2frx5ld1RJUCJkFNZ90ZiI= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/oracle/oci-go-sdk v7.0.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888= +github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014/go.mod h1:joRatxRJaZBsY3JAOEMcoOp05CnZzsx4scTxi95DHyQ= +github.com/packethost/packngo v0.1.1-0.20180711074735-b9cb5096f54c/go.mod h1:otzZQXgoO96RTzDB/Hycg0qZcXZsWJGJRSXbmEIJ+4M= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo= +github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= +github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= +github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= +github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pierrec/lz4 v2.4.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= +github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/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/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +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= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +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/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKcyumwBO6qip7RNQ5r77yrssm9bfCowcLEBcU5IA= +github.com/rboyer/safeio v0.2.1/go.mod h1:Cq/cEPK+YXFn622lsQ0K4KsPZSPtaptHHEldsy7Fmig= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/renier/xmlrpc v0.0.0-20170708154548-ce4a1a486c03/go.mod h1:gRAiPF5C5Nd0eyyRdqIu9qTiFSoZzpTq727b5B8fkkU= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rs/zerolog v1.4.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= +github.com/russross/blackfriday v0.0.0-20170610170232-067529f716f4/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +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/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/ryanuber/columnize v2.1.2+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= +github.com/sacloud/libsacloud v1.26.1/go.mod h1:79ZwATmHLIFZIMd7sxA3LwzVy/B77uj3LDoToVTxDoQ= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/sean-/conswriter v0.0.0-20180208195008-f5ae3917a627/go.mod h1:7zjs06qF79/FKAJpBvFx3P8Ww4UTIMAe+lpNXDHziac= +github.com/sean-/pager v0.0.0-20180208200047-666be9bf53b5/go.mod h1:BeybITEsBEg6qbIiqJ6/Bqeq25bCLbL7YFmpaFfJDuM= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/shirou/gopsutil/v3 v3.22.8/go.mod h1:s648gW4IywYzUfE/KjXxUsqrqx/T2xO5VqOXxONeRfI= +github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/skratchdot/open-golang v0.0.0-20160302144031-75fb7ed4208c/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= +github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/softlayer/softlayer-go v0.0.0-20180806151055-260589d94c7d/go.mod h1:Cw4GTlQccdRGSEf6KiMju767x0NEHE0YIVPJSaXjlsw= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.2.1/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/streadway/amqp v0.0.0-20200108173154-1c71cc93ed71/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= 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.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +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.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tencentcloud/tencentcloud-sdk-go v1.0.162/go.mod h1:asUz5BPXxgoPGaRgZaVm1iGcUAuHyYUo1nXqKa83cvI= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/timewasted/linode v0.0.0-20160829202747-37e84520dcf7/go.mod h1:imsgLplxEC/etjIhdr3dNzV3JeT27LbVu5pYWm0JCBY= +github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= +github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk= +github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/transip/gotransip v0.0.0-20190812104329-6d8d9179b66f/go.mod h1:i0f4R4o2HM0m3DZYQWsj6/MEowD57VzoH0v3d7igeFY= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= +github.com/vmware/govmomi v0.18.0/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= +github.com/vultr/govultr v0.1.4/go.mod h1:9H008Uxr/C4vFNGLqKx232C206GL0PBHzOP0809bGNA= +github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= +github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= +github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= +github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= +github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= +github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= +github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= +github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.1.0/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +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= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= +github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= +go.etcd.io/etcd v0.5.0-alpha.5.0.20190917205325-a14579fbfb1a/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.mongodb.org/mongo-driver v1.3.0/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE= +go.mongodb.org/mongo-driver v1.3.4/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE= +go.mongodb.org/mongo-driver v1.4.3/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc= +go.mongodb.org/mongo-driver v1.4.4/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc= +go.mongodb.org/mongo-driver v1.4.6/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc= +go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg= +go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng= +go.mongodb.org/mongo-driver v1.8.3/go.mod h1:0sQWfOeY63QTntERDJJ/0SuKK0T1uVSgKCuAROlKEPY= +go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +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= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +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/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= 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.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/ratelimit v0.0.0-20180316092928-c15da0234277/go.mod h1:2X8KaoNd1J0lZV+PxJk/5+DGbO/tpwLR1m++a7FnB/Y= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181025213731-e84da0312774/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +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-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +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= +golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20220518171630-0b5c67f07fdf/go.mod h1:yh0Ynu2b5ZUe3MQfp2nM0ecK7wsgouWTDN0FNeJuIys= +golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= +golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20220302094943-723b81ca9867/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +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/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180611182652-db08ff08e862/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190206173232-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190228165749-92fc7df08ae7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190930134127-c5a3c61f89f3/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= +golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +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.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= 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-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +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/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180622082034-63fc586f45fe/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190523142557-0e01d883c5c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= +golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +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.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +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= +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.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +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= +golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190424220101-1e8e1cfdf96b/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190624190245-7f2218787638/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= +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/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= +gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= +gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA= +gonum.org/v1/gonum v0.12.0/go.mod h1:73TDxJfAAHeA8Mk9mf8NlIppyhQNo5GLTcYeqgo2lvY= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= +gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= +gonum.org/v1/plot v0.10.1/go.mod h1:VZW5OlhkL1mysU9vaqNHnsy86inf6Ot+jB3r+BczCEo= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= +google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= +google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= +google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= +google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= +google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= +google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= +google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= +google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= +google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= +google.golang.org/api v0.77.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= +google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= +google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= +google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= +google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6FO2g= +google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= +google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= +google.golang.org/api v0.95.0/go.mod h1:eADj+UBuxkh5zlrSntJghuNeg8HwQ1w5lTKkuqaETEI= +google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.99.0/go.mod h1:1YOf74vkVndF7pG6hIHuINsM7eWwpVTAfNMNiL91A08= +google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= +google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo= +google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= +google.golang.org/api v0.106.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= +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.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= +google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= 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= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190626174449-989357319d63/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20220329172620-7be39ac1afc7/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220722212130-b98a9ff5e252/go.mod h1:GkXuJDJ6aQ7lnJcRF+SJVgFdQhypqgl3LB1C9vabdRE= +google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc= +google.golang.org/genproto v0.0.0-20220815135757-37a418bb8959/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220817144833-d7fd3f11b9b1/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220829144015-23454907ede3/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220829175752-36a9c930ecbf/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220913154956-18f8339a66a5/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220914142337-ca0e39ece12f/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220915135415-7fd63a7952de/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220916172020-2692e8806bfa/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220919141832-68c03719ef51/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar2npT/g4vkk7O0WYS1sHOHbdujxbEp7CJWbw= +google.golang.org/genproto v0.0.0-20220921223823-23cae91e6737/go.mod h1:2r/26NEF3bFmT3eC3aZreahSal0C3Shl8Gi6vyDYqOQ= +google.golang.org/genproto v0.0.0-20220926165614-551eb538f295/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= +google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= +google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U= +google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= +google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= +google.golang.org/genproto v0.0.0-20221024153911-1573dae28c9c/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= +google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= +google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo= +google.golang.org/genproto v0.0.0-20221109142239-94d6d90a7d66/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221117204609-8f9c96812029/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221201204527-e3fa12d562f3/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE= +google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230112194545-e10362b5ecf9/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230113154510-dbe35b8444a5/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230123190316-2c411cf9d197/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230124163310-31e0e69b6fc2/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230125152338-dcaf20b6aeaa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230127162408-596548ed4efa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +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-20230223222841-637eb2293923/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= +google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA= +google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= +google.golang.org/genproto v0.0.0-20230320184635-7606e756e683/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= +google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= +google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= +google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= +google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= +google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= +google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= +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.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= +google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= +google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= +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= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -124,11 +2438,129 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/DataDog/dd-trace-go.v1 v1.19.0/go.mod h1:DVp8HmDh8PuTu2Z0fVVlBsyWaC++fzwVCaGWylTe3tg= +gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= +gopkg.in/h2non/gock.v1 v1.0.15/go.mod h1:sX4zAkdYX1TRGJ2JY156cFspQn4yRWn6p9EMdODlynE= +gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.44.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo= +gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q= +gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4= +gopkg.in/jcmturner/gokrb5.v7 v7.5.0/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM= +gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8= +gopkg.in/mcuadros/go-syslog.v2 v2.2.1/go.mod h1:l5LPIyOOyIdQquNg+oU6Z3524YwrcqEm0aKH+5zpt2U= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/ns1/ns1-go.v2 v2.0.0-20190730140822-b51389932cbc/go.mod h1:VV+3haRsgDiVLxyifmMBrBIuCWFBPYKbRssXB9z67Hw= +gopkg.in/resty.v1 v1.9.1/go.mod h1:vo52Hzryw9PnPHcJfPsBiFW62XhNx5OczbV9y+IMpgc= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3 h1:fvjTMHxHEw/mxHbtzPi3JCcKXQRAnQTBRo6YCJSVHKI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +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.0.0-20190620084959-7cf5895f2711/go.mod h1:TBhBqb1AWbBQbW3XRusr7n7E4v2+5ZY8r8sAMnyFC5A= +k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78= +k8s.io/apimachinery v0.0.0-20190612205821-1799e75a0719/go.mod h1:I4A+glKBHiTgiEjQiCCQfCAIcIMFGt291SmsvcrFzJA= +k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA= +k8s.io/client-go v0.0.0-20190620085101-78d2af792bab/go.mod h1:E95RaSlHr79aHaX0aGSwcPNfygDiPKOVXdmivCIZT0k= +k8s.io/client-go v0.18.2/go.mod h1:Xcm5wVGXX9HAA2JJ2sSBUn3tCJ+4SVlCbl2MNNv+CIU= +k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v0.3.1/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v0.4.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= +k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= +k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= +k8s.io/kube-openapi v0.0.0-20190306001800-15615b16d372/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= +k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= +k8s.io/utils v0.0.0-20190221042446-c2654d5206da/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0= +k8s.io/utils v0.0.0-20190529001817-6999998975a7/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= +k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= +lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/cc/v3 v3.36.2/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/cc/v3 v3.36.3/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc= +modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw= +modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= +modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= +modernc.org/ccgo/v3 v3.16.8/go.mod h1:zNjwkizS+fIFDrDjIAgBSCLkWbJuHF+ar3QRn+Z9aws= +modernc.org/ccgo/v3 v3.16.9/go.mod h1:zNMzC9A9xeNUepy6KuZBbugn3c0Mc9TeiJO4lgvkJDo= +modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= +modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= +modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= +modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A= +modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU= +modernc.org/libc v1.16.17/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU= +modernc.org/libc v1.16.19/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= +modernc.org/libc v1.17.0/go.mod h1:XsgLldpP4aWlPlsjqKRdHPqCxCjISdHfM/yeWC5GyW0= +modernc.org/libc v1.17.1/go.mod h1:FZ23b+8LjxZs7XtFMbSzL/EhPxNbfZbErxEHc7cbD9s= +modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= +modernc.org/memory v1.2.0/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= +modernc.org/memory v1.2.1/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= +modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/sqlite v1.18.1/go.mod h1:6ho+Gow7oX5V+OiOQ6Tr4xeqbx13UZ6t+Fw9IRUG4d4= +modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= +modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= +modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw= +modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= +sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/test/integration/connect/envoy/test-sds-server/sds.go b/test/integration/connect/envoy/test-sds-server/sds.go index 78e1916d7f..6c1ed208cd 100644 --- a/test/integration/connect/envoy/test-sds-server/sds.go +++ b/test/integration/connect/envoy/test-sds-server/sds.go @@ -19,6 +19,7 @@ import ( "github.com/envoyproxy/go-control-plane/pkg/cache/types" cache "github.com/envoyproxy/go-control-plane/pkg/cache/v3" xds "github.com/envoyproxy/go-control-plane/pkg/server/v3" + "github.com/hashicorp/consul/logging" "github.com/hashicorp/go-hclog" "google.golang.org/grpc" "google.golang.org/grpc/grpclog" @@ -67,7 +68,7 @@ func run(log hclog.Logger) error { xdsServer := xds.NewServer(ctx, cache, callbacks) grpcServer := grpc.NewServer() - grpclog.SetLogger(log.StandardLogger(nil)) + grpclog.SetLoggerV2(logging.NewGRPCLogger("DEBUG", log)) secretservice.RegisterSecretDiscoveryServiceServer(grpcServer, xdsServer) @@ -143,7 +144,7 @@ func makeLoggerCallbacks(log hclog.Logger) *xds.CallbackFuncs { log.Trace("gRPC stream opened", "id", id, "addr", addr) return nil }, - StreamClosedFunc: func(id int64) { + StreamClosedFunc: func(id int64, _ *core.Node) { log.Trace("gRPC stream closed", "id", id) }, StreamRequestFunc: func(id int64, req *discovery.DiscoveryRequest) error { @@ -154,7 +155,7 @@ func makeLoggerCallbacks(log hclog.Logger) *xds.CallbackFuncs { ) return nil }, - StreamResponseFunc: func(id int64, req *discovery.DiscoveryRequest, resp *discovery.DiscoveryResponse) { + StreamResponseFunc: func(_ context.Context, id int64, req *discovery.DiscoveryRequest, resp *discovery.DiscoveryResponse) { log.Trace("gRPC stream response", "id", id, "resp.typeURL", resp.TypeUrl, "resp.version", resp.VersionInfo, diff --git a/test/integration/consul-container/go.mod b/test/integration/consul-container/go.mod index 93d63b8167..27d1357bd1 100644 --- a/test/integration/consul-container/go.mod +++ b/test/integration/consul-container/go.mod @@ -12,14 +12,14 @@ require ( github.com/hashicorp/consul/sdk v0.13.1 github.com/hashicorp/go-cleanhttp v0.5.2 github.com/hashicorp/go-multierror v1.1.1 - github.com/hashicorp/go-uuid v1.0.2 + github.com/hashicorp/go-uuid v1.0.3 github.com/hashicorp/go-version v1.2.1 github.com/hashicorp/serf v0.10.1 github.com/itchyny/gojq v0.12.9 github.com/mitchellh/copystructure v1.2.0 github.com/otiai10/copy v1.10.0 github.com/pkg/errors v0.9.1 - github.com/stretchr/testify v1.8.2 + github.com/stretchr/testify v1.8.3 github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569 github.com/testcontainers/testcontainers-go v0.20.1 golang.org/x/mod v0.10.0 @@ -46,12 +46,12 @@ require ( github.com/fatih/color v1.14.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/google/btree v1.0.0 // indirect + github.com/google/btree v1.0.1 // indirect github.com/google/uuid v1.3.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/hashicorp/go-hclog v1.2.1 // indirect + github.com/hashicorp/go-hclog v1.5.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect - github.com/hashicorp/go-msgpack v1.1.5 // indirect + github.com/hashicorp/go-msgpack v0.5.5 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect github.com/hashicorp/go-sockaddr v1.0.2 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect @@ -64,7 +64,7 @@ require ( github.com/mattn/go-isatty v0.0.17 // indirect github.com/miekg/dns v1.1.41 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/mapstructure v1.4.3 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/moby/patternmatcher v0.5.0 // indirect github.com/moby/sys/sequential v0.5.0 // indirect @@ -80,6 +80,7 @@ require ( golang.org/x/net v0.10.0 // indirect golang.org/x/sys v0.8.0 // indirect golang.org/x/text v0.9.0 // indirect + golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.9.1 // indirect google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect google.golang.org/protobuf v1.30.0 // indirect diff --git a/test/integration/consul-container/go.sum b/test/integration/consul-container/go.sum index be214724ea..44574893cd 100644 --- a/test/integration/consul-container/go.sum +++ b/test/integration/consul-container/go.sum @@ -88,8 +88,8 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS 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/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= +github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -104,14 +104,14 @@ github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brv github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-hclog v1.2.1 h1:YQsLlGDJgwhXFpucSPyVbCBviQtjlHv3jLTlp8YmtEw= -github.com/hashicorp/go-hclog v1.2.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= +github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-msgpack v1.1.5 h1:9byZdVjKTe5mce63pRVNP1L7UAmdHOTEMGehn6KvJWs= -github.com/hashicorp/go-msgpack v1.1.5/go.mod h1:gWVc3sv/wbDmR3rQsj1CAktEZzoz1YNK9NfGLXJ69/4= +github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= +github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= @@ -125,8 +125,8 @@ github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjG github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= -github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI= github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -187,8 +187,8 @@ github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= -github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/patternmatcher v0.5.0 h1:YCZgJOeULcxLw1Q+sVR636pmS7sPEn1Qo2iAN6M7DBo= @@ -237,7 +237,7 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= @@ -248,18 +248,14 @@ github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0 github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= 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/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569 h1:xzABM9let0HLLqFypcxvLmlvEciCHL7+Lv+4vwZqecI= github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569/go.mod h1:2Ly+NIftZN4de9zRmENdYbvPQeaVIYKWpLFStLFEBgI= github.com/testcontainers/testcontainers-go v0.20.1 h1:mK15UPJ8c5P+NsQKmkqzs/jMdJt6JMs5vlw2y4j92c0= @@ -341,12 +337,12 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190424220101-1e8e1cfdf96b/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= diff --git a/troubleshoot/go.mod b/troubleshoot/go.mod index 48529793be..1a6ca3559a 100644 --- a/troubleshoot/go.mod +++ b/troubleshoot/go.mod @@ -12,46 +12,44 @@ exclude ( ) require ( - github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1 + github.com/envoyproxy/go-control-plane v0.11.0 + github.com/envoyproxy/go-control-plane/xdsmatcher v0.0.0-20230524161521-aaaacbfbe53e github.com/hashicorp/consul/api v1.20.0 github.com/hashicorp/consul/envoyextensions v0.1.2 - github.com/stretchr/testify v1.8.0 - google.golang.org/protobuf v1.28.1 + github.com/stretchr/testify v1.8.3 + google.golang.org/protobuf v1.30.0 ) require ( - github.com/armon/go-metrics v0.3.10 // indirect - github.com/census-instrumentation/opencensus-proto v0.2.1 // indirect - github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1 // indirect + github.com/armon/go-metrics v0.4.1 // indirect + github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect + github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/envoyproxy/protoc-gen-validate v0.1.0 // indirect - github.com/fatih/color v1.13.0 // indirect - github.com/golang/protobuf v1.5.2 // indirect - github.com/google/btree v1.0.0 // indirect + github.com/envoyproxy/protoc-gen-validate v0.10.0 // indirect + github.com/fatih/color v1.14.1 // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-hclog v1.2.1 // indirect + github.com/hashicorp/go-hclog v1.5.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect - github.com/hashicorp/go-msgpack v0.5.5 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect github.com/hashicorp/go-version v1.2.1 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/serf v0.10.1 // indirect - github.com/mattn/go-colorable v0.1.12 // indirect - github.com/mattn/go-isatty v0.0.14 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_model v0.2.0 // indirect - go.opentelemetry.io/proto/otlp v0.7.0 // indirect + github.com/prometheus/client_model v0.3.0 // indirect + github.com/rogpeppe/go-internal v1.10.0 // indirect + go.opentelemetry.io/proto/otlp v0.19.0 // indirect golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect - golang.org/x/net v0.4.0 // indirect - golang.org/x/sys v0.3.0 // indirect - golang.org/x/text v0.5.0 // indirect - google.golang.org/genproto v0.0.0-20220921223823-23cae91e6737 // indirect - google.golang.org/grpc v1.49.0 // indirect - gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect + golang.org/x/net v0.10.0 // indirect + golang.org/x/sys v0.8.0 // indirect + golang.org/x/text v0.9.0 // indirect + google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect + google.golang.org/grpc v1.55.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/troubleshoot/go.sum b/troubleshoot/go.sum index 7629cbde9e..dc482f3d5e 100644 --- a/troubleshoot/go.sum +++ b/troubleshoot/go.sum @@ -1,7 +1,40 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -9,25 +42,34 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-metrics v0.3.10 h1:FR+drcQStOe+32sYyJYyZ7FIdgoGGBnwLl+flodp8Uo= -github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= +github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= +github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= +github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1 h1:zH8ljVhhq7yC0MIeUL/IviMtY8hx2mK8cN9wEYb8ggw= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195 h1:58f1tJ1ra+zFINPlwLWvQsR9CzAKt2e+EWV2yX9oXQ4= +github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -36,15 +78,24 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1 h1:xvqufLtNVwAhN8NMyWklVgxnWohi+wtMGQMhtxexlm0= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= -github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.11.0 h1:jtLewhRR2vMRNnq2ZZUoCjUlgut+Y0+sDDWPOfwOi1o= +github.com/envoyproxy/go-control-plane v0.11.0/go.mod h1:VnHyVMpzcLvCFt9yUz1UnCwHLhwx1WguiVDV7pTG/tI= +github.com/envoyproxy/go-control-plane/xdsmatcher v0.0.0-20230524161521-aaaacbfbe53e h1:g8euodkL4GdSpVAjfzhssb07KgVmOUqyF4QOmwFumTs= +github.com/envoyproxy/go-control-plane/xdsmatcher v0.0.0-20230524161521-aaaacbfbe53e/go.mod h1:/NGEcKqwNq3HAS2vCqHfsPx9sJZbkiNQ6dGx9gTE/NA= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v0.10.0 h1:oIfnZFdC0YhpNNEX+SuIqko4cqqVZeN9IGTrhZje83Y= +github.com/envoyproxy/protoc-gen-validate v0.10.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= +github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= @@ -52,11 +103,23 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 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/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= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -66,22 +129,38 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= 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/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= 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/hashicorp/consul/sdk v0.13.1 h1:EygWVWWMczTzXGpO93awkHFzfUka6hLYJ0qhETd+6lY= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= @@ -89,14 +168,13 @@ github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brv github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-hclog v1.2.1 h1:YQsLlGDJgwhXFpucSPyVbCBviQtjlHv3jLTlp8YmtEw= -github.com/hashicorp/go-hclog v1.2.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= +github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= -github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= @@ -109,10 +187,11 @@ github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0S github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI= github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= @@ -121,12 +200,17 @@ github.com/hashicorp/memberlist v0.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0= github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY= github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -134,14 +218,17 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.41 h1:WMszZWJG0XmzbK9FEmzH2TVcqYzFesusSIB41b8KHxY= @@ -157,8 +244,6 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -176,45 +261,86 @@ github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3O 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 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= 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/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= 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/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 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 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= -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/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= -go.opentelemetry.io/proto/otlp v0.7.0 h1:rwOQPCuKAKmwGKq2aVNnYIibI6wnV7EvzgfTCzcdGg8= +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= +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= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= +go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -222,22 +348,47 @@ golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= -golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU= -golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= 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= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -245,58 +396,176 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +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= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= 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= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20220921223823-23cae91e6737 h1:K1zaaMdYBXRyX+cwFnxj7M6zwDyumLQMZ5xqwGvjreQ= -google.golang.org/genproto v0.0.0-20220921223823-23cae91e6737/go.mod h1:2r/26NEF3bFmT3eC3aZreahSal0C3Shl8Gi6vyDYqOQ= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.49.0 h1:WTLtQzmQori5FUH25Pq4WT22oCsv8USpQ+F6rqtsmxw= -google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= +google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -305,17 +574,19 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -325,4 +596,12 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +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= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/troubleshoot/proxy/z_xds_packages.go b/troubleshoot/proxy/z_xds_packages.go index 081f945359..71eb344f65 100644 --- a/troubleshoot/proxy/z_xds_packages.go +++ b/troubleshoot/proxy/z_xds_packages.go @@ -3,16 +3,31 @@ package troubleshoot import ( + _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/config/v3alpha" + _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/http/dynamo/v3" + _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/http/golang/v3alpha" + _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/http/language/v3alpha" _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/http/squash/v3" _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/http/sxg/v3alpha" + _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/client_ssl_auth/v3" + _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/generic_proxy/action/v3" + _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/generic_proxy/codecs/dubbo/v3" + _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/generic_proxy/matcher/v3" + _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/generic_proxy/router/v3" + _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/generic_proxy/v3" _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/kafka_broker/v3" _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/kafka_mesh/v3alpha" _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/mysql_proxy/v3" _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/postgres_proxy/v3alpha" _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/rocketmq_proxy/v3" _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/sip_proxy/router/v3alpha" + _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/sip_proxy/tra/v3alpha" _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/filters/network/sip_proxy/v3alpha" + _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/matching/input_matchers/hyperscan/v3alpha" + _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/network/connection_balance/dlb/v3alpha" _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/private_key_providers/cryptomb/v3alpha" + _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/private_key_providers/qat/v3alpha" + _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/regex_engines/hyperscan/v3alpha" _ "github.com/envoyproxy/go-control-plane/contrib/envoy/extensions/vcl/v3alpha" _ "github.com/envoyproxy/go-control-plane/envoy/admin/v2alpha" _ "github.com/envoyproxy/go-control-plane/envoy/admin/v3" @@ -36,6 +51,7 @@ import ( _ "github.com/envoyproxy/go-control-plane/envoy/config/common/dynamic_forward_proxy/v2alpha" _ "github.com/envoyproxy/go-control-plane/envoy/config/common/key_value/v3" _ "github.com/envoyproxy/go-control-plane/envoy/config/common/matcher/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/config/common/mutation_rules/v3" _ "github.com/envoyproxy/go-control-plane/envoy/config/common/tap/v2alpha" _ "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" _ "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3" @@ -135,14 +151,16 @@ import ( _ "github.com/envoyproxy/go-control-plane/envoy/data/tap/v2alpha" _ "github.com/envoyproxy/go-control-plane/envoy/data/tap/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/access_loggers/file/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/access_loggers/filters/cel/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/access_loggers/grpc/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/access_loggers/open_telemetry/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/access_loggers/stream/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/access_loggers/wasm/v3" - _ "github.com/envoyproxy/go-control-plane/envoy/extensions/cache/simple_http_cache/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/bootstrap/internal_listener/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/clusters/aggregate/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/clusters/dynamic_forward_proxy/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/clusters/redis/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/common/async_files/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/common/dynamic_forward_proxy/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/common/matching/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/common/ratelimit/v3" @@ -151,6 +169,10 @@ import ( _ "github.com/envoyproxy/go-control-plane/envoy/extensions/compression/brotli/decompressor/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/compression/gzip/compressor/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/compression/gzip/decompressor/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/compression/zstd/compressor/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/compression/zstd/decompressor/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/config/validators/minimum_clusters/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/early_data/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/common/dependency/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/common/fault/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/common/matcher/action/v3" @@ -167,12 +189,14 @@ import ( _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/compressor/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/cors/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/csrf/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/custom_response/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/decompressor/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/dynamic_forward_proxy/v3" - _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/dynamo/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/ext_authz/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/ext_proc/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/fault/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/file_system_buffer/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/gcp_authn/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/grpc_http1_bridge/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/grpc_http1_reverse_bridge/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/grpc_json_transcoder/v3" @@ -189,18 +213,20 @@ import ( _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/oauth2/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/on_demand/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/original_src/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/rate_limit_quota/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/ratelimit/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/rbac/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/router/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/set_metadata/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/stateful_session/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/tap/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/upstream_codec/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/wasm/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/listener/http_inspector/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/listener/original_dst/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/listener/original_src/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/listener/proxy_protocol/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/listener/tls_inspector/v3" - _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/client_ssl_auth/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/connection_limit/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/direct_response/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/dubbo_proxy/router/v3" @@ -217,6 +243,7 @@ import ( _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/sni_dynamic_forward_proxy/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/tcp_proxy/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/thrift_proxy/filters/header_to_metadata/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/thrift_proxy/filters/payload_to_metadata/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/thrift_proxy/filters/ratelimit/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/thrift_proxy/router/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/thrift_proxy/v3" @@ -227,24 +254,49 @@ import ( _ "github.com/envoyproxy/go-control-plane/envoy/extensions/formatter/metadata/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/formatter/req_without_query/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/health_checkers/redis/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/health_checkers/thrift/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/http/cache/file_system_http_cache/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/http/cache/simple_http_cache/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/http/custom_response/local_response_policy/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/http/custom_response/redirect_policy/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/http/early_header_mutation/header_mutation/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/http/header_formatters/preserve_case/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/http/header_validators/envoy_default/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/http/original_ip_detection/custom_header/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/http/original_ip_detection/xff/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/http/stateful_session/cookie/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/http/stateful_session/header/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/internal_redirect/allow_listed_routes/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/internal_redirect/previous_routes/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/internal_redirect/safe_cross_scheme/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/key_value/file_based/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/load_balancing_policies/client_side_weighted_round_robin/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/load_balancing_policies/common/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/load_balancing_policies/least_request/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/load_balancing_policies/maglev/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/load_balancing_policies/random/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/load_balancing_policies/ring_hash/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/load_balancing_policies/round_robin/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/load_balancing_policies/wrr_locality/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/matching/common_inputs/environment_variable/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/matching/common_inputs/network/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/matching/common_inputs/ssl/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/matching/input_matchers/consistent_hashing/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/matching/input_matchers/ip/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/network/dns_resolver/apple/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/network/dns_resolver/cares/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/network/dns_resolver/getaddrinfo/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/network/socket_interface/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/path/match/uri_template/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/path/rewrite/uri_template/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/quic/connection_id_generator/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/quic/crypto_stream/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/quic/proof_source/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/rate_limit_descriptors/expr/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/rbac/matchers/upstream_ip_port/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/regex_engines/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/request_id/uuid/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/resource_monitors/downstream_connections/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/resource_monitors/fixed_heap/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/resource_monitors/injected_resource/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/retry/host/omit_canary_hosts/v3" @@ -254,6 +306,8 @@ import ( _ "github.com/envoyproxy/go-control-plane/envoy/extensions/stat_sinks/graphite_statsd/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/stat_sinks/wasm/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/alts/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/http_11_proxy/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/internal_upstream/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/proxy_protocol/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/quic/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/raw_buffer/v3" @@ -262,11 +316,13 @@ import ( _ "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tap/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tcp_stats/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/udp_packet_writer/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/upstreams/http/generic/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/upstreams/http/http/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/upstreams/http/tcp/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/upstreams/http/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/upstreams/tcp/generic/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/extensions/upstreams/tcp/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/wasm/v3" _ "github.com/envoyproxy/go-control-plane/envoy/extensions/watchdog/profile_action/v3" _ "github.com/envoyproxy/go-control-plane/envoy/service/accesslog/v2" @@ -288,6 +344,7 @@ import ( _ "github.com/envoyproxy/go-control-plane/envoy/service/load_stats/v3" _ "github.com/envoyproxy/go-control-plane/envoy/service/metrics/v2" _ "github.com/envoyproxy/go-control-plane/envoy/service/metrics/v3" + _ "github.com/envoyproxy/go-control-plane/envoy/service/rate_limit_quota/v3" _ "github.com/envoyproxy/go-control-plane/envoy/service/ratelimit/v2" _ "github.com/envoyproxy/go-control-plane/envoy/service/ratelimit/v3" _ "github.com/envoyproxy/go-control-plane/envoy/service/route/v3" @@ -309,4 +366,7 @@ import ( _ "github.com/envoyproxy/go-control-plane/envoy/type/tracing/v3" _ "github.com/envoyproxy/go-control-plane/envoy/type/v3" _ "github.com/envoyproxy/go-control-plane/envoy/watchdog/v3" + _ "github.com/envoyproxy/go-control-plane/ratelimit/config/ratelimit/v3" + _ "github.com/envoyproxy/go-control-plane/ratelimit/service/ratelimit/v3" + _ "github.com/envoyproxy/go-control-plane/xdsmatcher/test/proto" ) From dd71bb80d6bc0152e8350b9d96bf50df8c8e8efa Mon Sep 17 00:00:00 2001 From: cskh Date: Mon, 5 Jun 2023 19:47:26 -0400 Subject: [PATCH 30/72] docs: clarify the behavior of prepending hostname to metrics (#17521) * docs: clarify the behavior of prepending hostname to metrics * Update website/content/docs/agent/config/config-files.mdx Co-authored-by: trujillo-adam <47586768+trujillo-adam@users.noreply.github.com> --------- Co-authored-by: trujillo-adam <47586768+trujillo-adam@users.noreply.github.com> --- website/content/docs/agent/config/config-files.mdx | 3 +-- website/content/docs/agent/telemetry.mdx | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/website/content/docs/agent/config/config-files.mdx b/website/content/docs/agent/config/config-files.mdx index d7ac6923e0..6e50cbb44a 100644 --- a/website/content/docs/agent/config/config-files.mdx +++ b/website/content/docs/agent/config/config-files.mdx @@ -1818,8 +1818,7 @@ subsystem that provides Consul's service mesh capabilities. geo location or datacenter, dc:sfo). By default, this is left blank and not used. - `disable_hostname` ((#telemetry-disable_hostname)) - This controls whether or not to prepend runtime telemetry with the machine's - hostname, defaults to false. + Set to `true` to stop prepending the machine's hostname to gauge-type metrics. Default is `false`. - `dogstatsd_addr` ((#telemetry-dogstatsd_addr)) This provides the address of a DogStatsD instance in the format `host:port`. DogStatsD is a protocol-compatible diff --git a/website/content/docs/agent/telemetry.mdx b/website/content/docs/agent/telemetry.mdx index 5e1b6b8a88..ebb73a303a 100644 --- a/website/content/docs/agent/telemetry.mdx +++ b/website/content/docs/agent/telemetry.mdx @@ -27,6 +27,10 @@ This telemetry information can be used for debugging or otherwise getting a better view of what Consul is doing. Review the [Monitoring and Metrics tutorial](/consul/tutorials/day-2-operations/monitor-datacenter-health?utm_source=docs) to learn how collect and interpret Consul data. +By default, all metric names of gauge type are prefixed with the hostname of the consul agent, e.g., +`consul.hostname.server.isLeader`. To disable prefixing the hostname, set +`telemetry.disable_hostname=true` in the [agent configuration](/consul/docs/agent/config/config-files#telemetry). + Additionally, if the [`telemetry` configuration options](/consul/docs/agent/config/config-files#telemetry) are provided, the telemetry information will be streamed to a [statsite](http://github.com/armon/statsite) or [statsd](http://github.com/etsy/statsd) server where From f9d9d4db6066b146a18499d68e00f3228c463463 Mon Sep 17 00:00:00 2001 From: Andrew Stucki Date: Tue, 6 Jun 2023 09:09:33 -0400 Subject: [PATCH 31/72] Fix subscribing/fetching objects not in the default partition (#17581) * Fix subscribing/fetching objects not in the default namespace * add changelog --- .changelog/17581.txt | 3 +++ agent/consul/gateways/controller_gateways.go | 16 +++++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 .changelog/17581.txt diff --git a/.changelog/17581.txt b/.changelog/17581.txt new file mode 100644 index 0000000000..9277dbcd3e --- /dev/null +++ b/.changelog/17581.txt @@ -0,0 +1,3 @@ +```release-note:bug +gateways: **(Enterprise only)** Fixed a bug in API gateways where gateway configuration objects in non-default partitions did not reconcile properly. +``` diff --git a/agent/consul/gateways/controller_gateways.go b/agent/consul/gateways/controller_gateways.go index 46651f0043..cf4f25aa5d 100644 --- a/agent/consul/gateways/controller_gateways.go +++ b/agent/consul/gateways/controller_gateways.go @@ -93,7 +93,7 @@ func (r *apiGatewayReconciler) enqueueCertificateReferencedGateways(store *state logger.Trace("certificate changed, enqueueing dependent gateways") defer logger.Trace("finished enqueuing gateways") - _, entries, err := store.ConfigEntriesByKind(nil, structs.APIGateway, acl.WildcardEnterpriseMeta()) + _, entries, err := store.ConfigEntriesByKind(nil, structs.APIGateway, wildcardMeta()) if err != nil { logger.Warn("error retrieving api gateways", "error", err) return err @@ -564,11 +564,11 @@ type gatewayMeta struct { // tuples based on the state coming from the store. Any gateway that does not have // a corresponding bound-api-gateway config entry will be filtered out. func getAllGatewayMeta(store *state.Store) ([]*gatewayMeta, error) { - _, gateways, err := store.ConfigEntriesByKind(nil, structs.APIGateway, acl.WildcardEnterpriseMeta()) + _, gateways, err := store.ConfigEntriesByKind(nil, structs.APIGateway, wildcardMeta()) if err != nil { return nil, err } - _, boundGateways, err := store.ConfigEntriesByKind(nil, structs.BoundAPIGateway, acl.WildcardEnterpriseMeta()) + _, boundGateways, err := store.ConfigEntriesByKind(nil, structs.BoundAPIGateway, wildcardMeta()) if err != nil { return nil, err } @@ -1074,12 +1074,12 @@ func requestToResourceRef(req controller.Request) structs.ResourceReference { // retrieveAllRoutesFromStore retrieves all HTTP and TCP routes from the given store func retrieveAllRoutesFromStore(store *state.Store) ([]structs.BoundRoute, error) { - _, httpRoutes, err := store.ConfigEntriesByKind(nil, structs.HTTPRoute, acl.WildcardEnterpriseMeta()) + _, httpRoutes, err := store.ConfigEntriesByKind(nil, structs.HTTPRoute, wildcardMeta()) if err != nil { return nil, err } - _, tcpRoutes, err := store.ConfigEntriesByKind(nil, structs.TCPRoute, acl.WildcardEnterpriseMeta()) + _, tcpRoutes, err := store.ConfigEntriesByKind(nil, structs.TCPRoute, wildcardMeta()) if err != nil { return nil, err } @@ -1141,3 +1141,9 @@ func routeLogger(logger hclog.Logger, route structs.ConfigEntry) hclog.Logger { meta := route.GetEnterpriseMeta() return logger.With("route.kind", route.GetKind(), "route.name", route.GetName(), "route.namespace", meta.NamespaceOrDefault(), "route.partition", meta.PartitionOrDefault()) } + +func wildcardMeta() *acl.EnterpriseMeta { + meta := acl.WildcardEnterpriseMeta() + meta.OverridePartition(acl.WildcardPartitionName) + return meta +} From 8e52d489ce092b820469415968e59178592ac212 Mon Sep 17 00:00:00 2001 From: Michael Zalimeni Date: Tue, 6 Jun 2023 10:04:31 -0400 Subject: [PATCH 32/72] Add Prop Override Envoy extension integration test (#17569) --- .../envoy/case-property-override/capture.sh | 7 +++ .../case-property-override/service_s1.hcl | 19 +++++++ .../case-property-override/service_s2.hcl | 8 +++ .../envoy/case-property-override/setup.sh | 57 +++++++++++++++++++ .../envoy/case-property-override/vars.sh | 6 ++ .../envoy/case-property-override/verify.bats | 29 ++++++++++ test/integration/connect/envoy/helpers.bash | 7 +++ 7 files changed, 133 insertions(+) create mode 100644 test/integration/connect/envoy/case-property-override/capture.sh create mode 100644 test/integration/connect/envoy/case-property-override/service_s1.hcl create mode 100644 test/integration/connect/envoy/case-property-override/service_s2.hcl create mode 100644 test/integration/connect/envoy/case-property-override/setup.sh create mode 100644 test/integration/connect/envoy/case-property-override/vars.sh create mode 100644 test/integration/connect/envoy/case-property-override/verify.bats diff --git a/test/integration/connect/envoy/case-property-override/capture.sh b/test/integration/connect/envoy/case-property-override/capture.sh new file mode 100644 index 0000000000..5268305f8f --- /dev/null +++ b/test/integration/connect/envoy/case-property-override/capture.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + + +snapshot_envoy_admin localhost:19000 s1 primary || true +snapshot_envoy_admin localhost:19001 s2 primary || true diff --git a/test/integration/connect/envoy/case-property-override/service_s1.hcl b/test/integration/connect/envoy/case-property-override/service_s1.hcl new file mode 100644 index 0000000000..6eaca12985 --- /dev/null +++ b/test/integration/connect/envoy/case-property-override/service_s1.hcl @@ -0,0 +1,19 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +services { + name = "s1" + port = 8080 + connect { + sidecar_service { + proxy { + upstreams = [ + { + destination_name = "s2" + local_bind_port = 5000 + } + ] + } + } + } +} diff --git a/test/integration/connect/envoy/case-property-override/service_s2.hcl b/test/integration/connect/envoy/case-property-override/service_s2.hcl new file mode 100644 index 0000000000..c01f4b2fef --- /dev/null +++ b/test/integration/connect/envoy/case-property-override/service_s2.hcl @@ -0,0 +1,8 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +services { + name = "s2" + port = 8181 + connect { sidecar_service {} } +} diff --git a/test/integration/connect/envoy/case-property-override/setup.sh b/test/integration/connect/envoy/case-property-override/setup.sh new file mode 100644 index 0000000000..0bc569a706 --- /dev/null +++ b/test/integration/connect/envoy/case-property-override/setup.sh @@ -0,0 +1,57 @@ +#!/bin/bash +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + + +set -eEuo pipefail + +upsert_config_entry primary ' +Kind = "service-defaults" +Name = "s2" +Protocol = "http" +EnvoyExtensions = [ + { + Name = "builtin/property-override" + Arguments = { + ProxyType = "connect-proxy" + Patches = [{ + ResourceFilter = { + ResourceType = "listener" + TrafficDirection = "inbound" + } + Op = "add" + Path = "/stat_prefix" + Value = "custom.stats.s2" + }] + } + } +] +' + +upsert_config_entry primary ' +Kind = "service-defaults" +Name = "s1" +Protocol = "http" +EnvoyExtensions = [ + { + Name = "builtin/property-override" + Arguments = { + ProxyType = "connect-proxy" + Patches = [{ + ResourceFilter = { + ResourceType = "cluster" + TrafficDirection = "outbound" + } + Op = "add" + Path = "/upstream_connection_options/tcp_keepalive/keepalive_probes" + Value = 1234 + }] + } + } +] +' + +register_services primary + +gen_envoy_bootstrap s1 19000 primary +gen_envoy_bootstrap s2 19001 primary diff --git a/test/integration/connect/envoy/case-property-override/vars.sh b/test/integration/connect/envoy/case-property-override/vars.sh new file mode 100644 index 0000000000..091a358e13 --- /dev/null +++ b/test/integration/connect/envoy/case-property-override/vars.sh @@ -0,0 +1,6 @@ +#!/bin/bash +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + + +export REQUIRED_SERVICES="s1 s1-sidecar-proxy s2 s2-sidecar-proxy" diff --git a/test/integration/connect/envoy/case-property-override/verify.bats b/test/integration/connect/envoy/case-property-override/verify.bats new file mode 100644 index 0000000000..8b8997f82a --- /dev/null +++ b/test/integration/connect/envoy/case-property-override/verify.bats @@ -0,0 +1,29 @@ +#!/usr/bin/env bats + +load helpers + +@test "s1 proxy admin is up on :19000" { + retry_default curl -f -s localhost:19000/stats -o /dev/null +} + +@test "s2 proxy admin is up on :19001" { + retry_default curl -f -s localhost:19001/stats -o /dev/null +} + +@test "s1 proxy listener should be up and have right cert" { + assert_proxy_presents_cert_uri localhost:21000 s1 +} + +@test "s1 proxy is configured with the expected envoy patches" { + run get_envoy_cluster_config localhost:19000 s2 + [ "$status" == 0 ] + + [ "$(echo "$output" | jq -r '.upstream_connection_options.tcp_keepalive.keepalive_probes')" == "1234" ] +} + +@test "s2 proxy is configured with the expected envoy patches" { + run get_envoy_public_listener_once localhost:19001 + [ "$status" == 0 ] + + [ "$(echo "$output" | jq -r '.active_state.listener.stat_prefix')" == "custom.stats.s2" ] +} diff --git a/test/integration/connect/envoy/helpers.bash b/test/integration/connect/envoy/helpers.bash index 81ee390128..009c88cd90 100755 --- a/test/integration/connect/envoy/helpers.bash +++ b/test/integration/connect/envoy/helpers.bash @@ -228,6 +228,13 @@ function get_envoy_expose_checks_listener_once { echo "$output" | jq --raw-output '.configs[] | select(.["@type"] == "type.googleapis.com/envoy.admin.v3.ListenersConfigDump") | .dynamic_listeners[] | select(.name | startswith("exposed_path_"))' } +function get_envoy_public_listener_once { + local HOSTPORT=$1 + run curl -s -f $HOSTPORT/config_dump + [ "$status" -eq 0 ] + echo "$output" | jq --raw-output '.configs[] | select(.["@type"] == "type.googleapis.com/envoy.admin.v3.ListenersConfigDump") | .dynamic_listeners[] | select(.name | startswith("public_listener:"))' +} + function assert_envoy_http_rbac_policy_count { local HOSTPORT=$1 local EXPECT_COUNT=$2 From 7a2ee145bfd92b887a27de4456e317800ff6c38e Mon Sep 17 00:00:00 2001 From: Joshua Timmons Date: Tue, 6 Jun 2023 14:42:30 -0400 Subject: [PATCH 33/72] Fix metric names in Consul agent telemetry docs (#17577) --- .changelog/17577.txt | 3 ++ website/content/docs/agent/telemetry.mdx | 54 ++++++++++++------------ 2 files changed, 30 insertions(+), 27 deletions(-) create mode 100644 .changelog/17577.txt diff --git a/.changelog/17577.txt b/.changelog/17577.txt new file mode 100644 index 0000000000..3699d52611 --- /dev/null +++ b/.changelog/17577.txt @@ -0,0 +1,3 @@ +```release-note:improvement +fix metric names in /docs/agent/telemetry +``` \ No newline at end of file diff --git a/website/content/docs/agent/telemetry.mdx b/website/content/docs/agent/telemetry.mdx index ebb73a303a..59e78e27e0 100644 --- a/website/content/docs/agent/telemetry.mdx +++ b/website/content/docs/agent/telemetry.mdx @@ -381,34 +381,34 @@ This is a full list of metrics emitted by Consul. | `consul.client.rpc` | Increments whenever a Consul agent in client mode makes an RPC request to a Consul server. This gives a measure of how much a given agent is loading the Consul servers. Currently, this is only generated by agents in client mode, not Consul servers. | requests | counter | | `consul.client.rpc.exceeded` | Increments whenever a Consul agent in client mode makes an RPC request to a Consul server gets rate limited by that agent's [`limits`](/consul/docs/agent/config/config-files#limits) configuration. This gives an indication that there's an abusive application making too many requests on the agent, or that the rate limit needs to be increased. Currently, this only applies to agents in client mode, not Consul servers. | rejected requests | counter | | `consul.client.rpc.failed` | Increments whenever a Consul agent in client mode makes an RPC request to a Consul server and fails. | requests | counter | -| `consul.client.api.catalog_register.` | Increments whenever a Consul agent receives a catalog register request. | requests | counter | -| `consul.client.api.success.catalog_register.` | Increments whenever a Consul agent successfully responds to a catalog register request. | requests | counter | -| `consul.client.rpc.error.catalog_register.` | Increments whenever a Consul agent receives an RPC error for a catalog register request. | errors | counter | -| `consul.client.api.catalog_deregister.` | Increments whenever a Consul agent receives a catalog deregister request. | requests | counter | -| `consul.client.api.success.catalog_deregister.` | Increments whenever a Consul agent successfully responds to a catalog deregister request. | requests | counter | -| `consul.client.rpc.error.catalog_deregister.` | Increments whenever a Consul agent receives an RPC error for a catalog deregister request. | errors | counter | -| `consul.client.api.catalog_datacenters.` | Increments whenever a Consul agent receives a request to list datacenters in the catalog. | requests | counter | -| `consul.client.api.success.catalog_datacenters.` | Increments whenever a Consul agent successfully responds to a request to list datacenters. | requests | counter | -| `consul.client.rpc.error.catalog_datacenters.` | Increments whenever a Consul agent receives an RPC error for a request to list datacenters. | errors | counter | -| `consul.client.api.catalog_nodes.` | Increments whenever a Consul agent receives a request to list nodes from the catalog. | requests | counter | -| `consul.client.api.success.catalog_nodes.` | Increments whenever a Consul agent successfully responds to a request to list nodes. | requests | counter | -| `consul.client.rpc.error.catalog_nodes.` | Increments whenever a Consul agent receives an RPC error for a request to list nodes. | errors | counter | -| `consul.client.api.catalog_services.` | Increments whenever a Consul agent receives a request to list services from the catalog. | requests | counter | -| `consul.client.api.success.catalog_services.` | Increments whenever a Consul agent successfully responds to a request to list services. | requests | counter | -| `consul.client.rpc.error.catalog_services.` | Increments whenever a Consul agent receives an RPC error for a request to list services. | errors | counter | -| `consul.client.api.catalog_service_nodes.` | Increments whenever a Consul agent receives a request to list nodes offering a service. | requests | counter | -| `consul.client.api.success.catalog_service_nodes.` | Increments whenever a Consul agent successfully responds to a request to list nodes offering a service. | requests | counter | -| `consul.client.api.error.catalog_service_nodes.` | Increments whenever a Consul agent receives an RPC error for request to list nodes offering a service. | requests | counter | -| `consul.client.rpc.error.catalog_service_nodes.` | Increments whenever a Consul agent receives an RPC error for a request to list nodes offering a service.   | errors | counter | -| `consul.client.api.catalog_node_services.` | Increments whenever a Consul agent receives a request to list services registered in a node.   | requests | counter | -| `consul.client.api.success.catalog_node_services.` | Increments whenever a Consul agent successfully responds to a request to list services in a node.   | requests | counter | -| `consul.client.rpc.error.catalog_node_services.` | Increments whenever a Consul agent receives an RPC error for a request to list services in a node.   | errors | counter | +| `consul.client.api.catalog_register` | Increments whenever a Consul agent receives a catalog register request. | requests | counter | +| `consul.client.api.success.catalog_register` | Increments whenever a Consul agent successfully responds to a catalog register request. | requests | counter | +| `consul.client.rpc.error.catalog_register` | Increments whenever a Consul agent receives an RPC error for a catalog register request. | errors | counter | +| `consul.client.api.catalog_deregister` | Increments whenever a Consul agent receives a catalog deregister request. | requests | counter | +| `consul.client.api.success.catalog_deregister` | Increments whenever a Consul agent successfully responds to a catalog deregister request. | requests | counter | +| `consul.client.rpc.error.catalog_deregister` | Increments whenever a Consul agent receives an RPC error for a catalog deregister request. | errors | counter | +| `consul.client.api.catalog_datacenters` | Increments whenever a Consul agent receives a request to list datacenters in the catalog. | requests | counter | +| `consul.client.api.success.catalog_datacenters` | Increments whenever a Consul agent successfully responds to a request to list datacenters. | requests | counter | +| `consul.client.rpc.error.catalog_datacenters` | Increments whenever a Consul agent receives an RPC error for a request to list datacenters. | errors | counter | +| `consul.client.api.catalog_nodes` | Increments whenever a Consul agent receives a request to list nodes from the catalog. | requests | counter | +| `consul.client.api.success.catalog_nodes` | Increments whenever a Consul agent successfully responds to a request to list nodes. | requests | counter | +| `consul.client.rpc.error.catalog_nodes` | Increments whenever a Consul agent receives an RPC error for a request to list nodes. | errors | counter | +| `consul.client.api.catalog_services` | Increments whenever a Consul agent receives a request to list services from the catalog. | requests | counter | +| `consul.client.api.success.catalog_services` | Increments whenever a Consul agent successfully responds to a request to list services. | requests | counter | +| `consul.client.rpc.error.catalog_services` | Increments whenever a Consul agent receives an RPC error for a request to list services. | errors | counter | +| `consul.client.api.catalog_service_nodes` | Increments whenever a Consul agent receives a request to list nodes offering a service. | requests | counter | +| `consul.client.api.success.catalog_service_nodes` | Increments whenever a Consul agent successfully responds to a request to list nodes offering a service. | requests | counter | +| `consul.client.api.error.catalog_service_nodes` | Increments whenever a Consul agent receives an RPC error for request to list nodes offering a service. | requests | counter | +| `consul.client.rpc.error.catalog_service_nodes` | Increments whenever a Consul agent receives an RPC error for a request to list nodes offering a service.   | errors | counter | +| `consul.client.api.catalog_node_services` | Increments whenever a Consul agent receives a request to list services registered in a node.   | requests | counter | +| `consul.client.api.success.catalog_node_services` | Increments whenever a Consul agent successfully responds to a request to list services in a node.   | requests | counter | +| `consul.client.rpc.error.catalog_node_services` | Increments whenever a Consul agent receives an RPC error for a request to list services in a node.   | errors | counter | | `consul.client.api.catalog_node_service_list` | Increments whenever a Consul agent receives a request to list a node's registered services. | requests | counter | | `consul.client.rpc.error.catalog_node_service_list` | Increments whenever a Consul agent receives an RPC error for request to list a node's registered services. | errors | counter | | `consul.client.api.success.catalog_node_service_list` | Increments whenever a Consul agent successfully responds to a request to list a node's registered services. | requests | counter | -| `consul.client.api.catalog_gateway_services.` | Increments whenever a Consul agent receives a request to list services associated with a gateway. | requests | counter | -| `consul.client.api.success.catalog_gateway_services.` | Increments whenever a Consul agent successfully responds to a request to list services associated with a gateway. | requests | counter | -| `consul.client.rpc.error.catalog_gateway_services.` | Increments whenever a Consul agent receives an RPC error for a request to list services associated with a gateway. | errors | counter | +| `consul.client.api.catalog_gateway_services` | Increments whenever a Consul agent receives a request to list services associated with a gateway. | requests | counter | +| `consul.client.api.success.catalog_gateway_services` | Increments whenever a Consul agent successfully responds to a request to list services associated with a gateway. | requests | counter | +| `consul.client.rpc.error.catalog_gateway_services` | Increments whenever a Consul agent receives an RPC error for a request to list services associated with a gateway. | errors | counter | | `consul.runtime.num_goroutines` | Tracks the number of running goroutines and is a general load pressure indicator. This may burst from time to time but should return to a steady state value. | number of goroutines | gauge | | `consul.runtime.alloc_bytes` | Measures the number of bytes allocated by the Consul process. This may burst from time to time but should return to a steady state value. | bytes | gauge | | `consul.runtime.heap_objects` | Measures the number of objects allocated on the heap and is a general memory pressure indicator. This may burst from time to time but should return to a steady state value. | number of objects | gauge | @@ -422,8 +422,8 @@ This is a full list of metrics emitted by Consul. | `consul.members.clients` | Measures the current number of client agents registered with Consul. It is only emitted by Consul servers. Added in v1.9.6. | number of clients | gauge | | `consul.members.servers` | Measures the current number of server agents registered with Consul. It is only emitted by Consul servers. Added in v1.9.6. | number of servers | gauge | | `consul.dns.stale_queries` | Increments when an agent serves a query within the allowed stale threshold. | queries | counter | -| `consul.dns.ptr_query.` | Measures the time spent handling a reverse DNS query for the given node. | ms | timer | -| `consul.dns.domain_query.` | Measures the time spent handling a domain query for the given node. | ms | timer | +| `consul.dns.ptr_query` | Measures the time spent handling a reverse DNS query for the given node. | ms | timer | +| `consul.dns.domain_query` | Measures the time spent handling a domain query for the given node. | ms | timer | | `consul.system.licenseExpiration` | This measures the number of hours remaining on the agents license. | hours | gauge | | `consul.version` | Represents the Consul version. | agents | gauge | From 2dd55510033526c02bd1c96ddf37ec57741c5622 Mon Sep 17 00:00:00 2001 From: Michael Zalimeni Date: Tue, 6 Jun 2023 15:40:37 -0400 Subject: [PATCH 34/72] Fix Property Override Services parsing (#17584) Ensure that the embedded api struct is properly parsed when deserializing config containing a set ResourceFilter.Services field. Also enhance existing integration test to guard against bugs and exercise this field. --- .../property-override/property_override.go | 19 ++++++++- .../property_override_test.go | 40 ++++++++++++++++++- .../envoy/case-property-override/capture.sh | 1 + .../case-property-override/service_s1.hcl | 4 ++ .../case-property-override/service_s3.hcl | 8 ++++ .../envoy/case-property-override/setup.sh | 23 ++++++++++- .../envoy/case-property-override/vars.sh | 2 +- .../envoy/case-property-override/verify.bats | 7 ++++ 8 files changed, 97 insertions(+), 7 deletions(-) create mode 100644 test/integration/connect/envoy/case-property-override/service_s3.hcl diff --git a/agent/envoyextensions/builtin/property-override/property_override.go b/agent/envoyextensions/builtin/property-override/property_override.go index 6bdf9e7a39..c018d334a5 100644 --- a/agent/envoyextensions/builtin/property-override/property_override.go +++ b/agent/envoyextensions/builtin/property-override/property_override.go @@ -7,6 +7,7 @@ import ( envoy_endpoint_v3 "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3" envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" envoy_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" + "github.com/hashicorp/consul/lib/decode" "github.com/hashicorp/go-multierror" "github.com/mitchellh/mapstructure" "google.golang.org/protobuf/proto" @@ -73,7 +74,7 @@ func matchesResourceFilter[K proto.Message](rf ResourceFilter, resourceType Reso } type ServiceName struct { - api.CompoundServiceName + api.CompoundServiceName `mapstructure:",squash"` } // ResourceType is the type of Envoy resource being patched. @@ -275,7 +276,21 @@ func Constructor(ext api.EnvoyExtension) (extensioncommon.EnvoyExtender, error) if name := ext.Name; name != api.BuiltinPropertyOverrideExtension { return nil, fmt.Errorf("expected extension name %q but got %q", api.BuiltinPropertyOverrideExtension, name) } - if err := mapstructure.WeakDecode(ext.Arguments, &p); err != nil { + // This avoids issues with decoding nested slices, which are error-prone + // due to slice<->map coercion by mapstructure. See HookWeakDecodeFromSlice + // and WeaklyTypedInput docs for more details. + d, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ + DecodeHook: mapstructure.ComposeDecodeHookFunc( + decode.HookWeakDecodeFromSlice, + decode.HookTranslateKeys, + ), + WeaklyTypedInput: true, + Result: &p, + }) + if err != nil { + return nil, fmt.Errorf("error configuring decoder: %v", err) + } + if err := d.Decode(ext.Arguments); err != nil { return nil, fmt.Errorf("error decoding extension arguments: %v", err) } if err := p.validate(); err != nil { diff --git a/agent/envoyextensions/builtin/property-override/property_override_test.go b/agent/envoyextensions/builtin/property-override/property_override_test.go index 7faa3795c2..68a895edb8 100644 --- a/agent/envoyextensions/builtin/property-override/property_override_test.go +++ b/agent/envoyextensions/builtin/property-override/property_override_test.go @@ -220,8 +220,8 @@ func TestConstructor(t *testing.T) { arguments: makeArguments(map[string]any{"Patches": []map[string]any{ makePatch(map[string]any{ "ResourceFilter": makeResourceFilter(map[string]any{ - "Services": []ServiceName{ - {CompoundServiceName: api.CompoundServiceName{}}, + "Services": []map[string]any{ + {}, }, }), }), @@ -240,6 +240,42 @@ func TestConstructor(t *testing.T) { expected: validTestCase(OpAdd, extensioncommon.TrafficDirectionOutbound, ResourceTypeRoute).expected, ok: true, }, + // Ensure that embedded api struct used for Services is parsed correctly. + // See also above comment on decode.HookWeakDecodeFromSlice. + "single value Services decoded as map construction succeeds": { + arguments: makeArguments(map[string]any{"Patches": []map[string]any{ + makePatch(map[string]any{ + "ResourceFilter": makeResourceFilter(map[string]any{ + "Services": []map[string]any{ + {"Name": "foo"}, + }, + }), + }), + }}), + expected: propertyOverride{ + Patches: []Patch{ + { + ResourceFilter: ResourceFilter{ + ResourceType: ResourceTypeRoute, + TrafficDirection: extensioncommon.TrafficDirectionOutbound, + Services: []*ServiceName{ + {CompoundServiceName: api.CompoundServiceName{ + Name: "foo", + Namespace: "default", + Partition: "default", + }}, + }, + }, + Op: OpAdd, + Path: "/name", + Value: "foo", + }, + }, + Debug: true, + ProxyType: api.ServiceKindConnectProxy, + }, + ok: true, + }, "invalid ProxyType": { arguments: makeArguments(map[string]any{ "Patches": []map[string]any{ diff --git a/test/integration/connect/envoy/case-property-override/capture.sh b/test/integration/connect/envoy/case-property-override/capture.sh index 5268305f8f..88f1dd6465 100644 --- a/test/integration/connect/envoy/case-property-override/capture.sh +++ b/test/integration/connect/envoy/case-property-override/capture.sh @@ -5,3 +5,4 @@ snapshot_envoy_admin localhost:19000 s1 primary || true snapshot_envoy_admin localhost:19001 s2 primary || true +snapshot_envoy_admin localhost:19002 s3 primary || true diff --git a/test/integration/connect/envoy/case-property-override/service_s1.hcl b/test/integration/connect/envoy/case-property-override/service_s1.hcl index 6eaca12985..6bacecf916 100644 --- a/test/integration/connect/envoy/case-property-override/service_s1.hcl +++ b/test/integration/connect/envoy/case-property-override/service_s1.hcl @@ -11,6 +11,10 @@ services { { destination_name = "s2" local_bind_port = 5000 + }, + { + destination_name = "s3" + local_bind_port = 5001 } ] } diff --git a/test/integration/connect/envoy/case-property-override/service_s3.hcl b/test/integration/connect/envoy/case-property-override/service_s3.hcl new file mode 100644 index 0000000000..d616906e4c --- /dev/null +++ b/test/integration/connect/envoy/case-property-override/service_s3.hcl @@ -0,0 +1,8 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +services { + name = "s3" + port = 8181 + connect { sidecar_service {} } +} diff --git a/test/integration/connect/envoy/case-property-override/setup.sh b/test/integration/connect/envoy/case-property-override/setup.sh index 0bc569a706..1bf2021c0c 100644 --- a/test/integration/connect/envoy/case-property-override/setup.sh +++ b/test/integration/connect/envoy/case-property-override/setup.sh @@ -28,6 +28,12 @@ EnvoyExtensions = [ ] ' +upsert_config_entry primary ' +Kind = "service-defaults" +Name = "s3" +Protocol = "http" +' + upsert_config_entry primary ' Kind = "service-defaults" Name = "s1" @@ -37,7 +43,8 @@ EnvoyExtensions = [ Name = "builtin/property-override" Arguments = { ProxyType = "connect-proxy" - Patches = [{ + Patches = [ + { ResourceFilter = { ResourceType = "cluster" TrafficDirection = "outbound" @@ -45,7 +52,19 @@ EnvoyExtensions = [ Op = "add" Path = "/upstream_connection_options/tcp_keepalive/keepalive_probes" Value = 1234 - }] + }, + { + ResourceFilter = { + ResourceType = "cluster" + TrafficDirection = "outbound" + Services = [{ + Name = "s2" + }] + } + Op = "remove" + Path = "/outlier_detection" + } + ] } } ] diff --git a/test/integration/connect/envoy/case-property-override/vars.sh b/test/integration/connect/envoy/case-property-override/vars.sh index 091a358e13..358866872a 100644 --- a/test/integration/connect/envoy/case-property-override/vars.sh +++ b/test/integration/connect/envoy/case-property-override/vars.sh @@ -3,4 +3,4 @@ # SPDX-License-Identifier: MPL-2.0 -export REQUIRED_SERVICES="s1 s1-sidecar-proxy s2 s2-sidecar-proxy" +export REQUIRED_SERVICES="s1 s1-sidecar-proxy s2 s2-sidecar-proxy s3 s3-sidecar-proxy" diff --git a/test/integration/connect/envoy/case-property-override/verify.bats b/test/integration/connect/envoy/case-property-override/verify.bats index 8b8997f82a..4453409eed 100644 --- a/test/integration/connect/envoy/case-property-override/verify.bats +++ b/test/integration/connect/envoy/case-property-override/verify.bats @@ -19,6 +19,13 @@ load helpers [ "$status" == 0 ] [ "$(echo "$output" | jq -r '.upstream_connection_options.tcp_keepalive.keepalive_probes')" == "1234" ] + [ "$(echo "$output" | jq -r '.outlier_detection')" == "null" ] + + run get_envoy_cluster_config localhost:19000 s3 + [ "$status" == 0 ] + + [ "$(echo "$output" | jq -r '.upstream_connection_options.tcp_keepalive.keepalive_probes')" == "1234" ] + [ "$(echo "$output" | jq -r '.outlier_detection')" == "{}" ] } @test "s2 proxy is configured with the expected envoy patches" { From a5ba889034bd9f3af1254bb567b94d30cf2e65af Mon Sep 17 00:00:00 2001 From: Matt Keeler Date: Tue, 6 Jun 2023 17:09:48 -0400 Subject: [PATCH 35/72] Implement the service endpoints controller (#17216) * Add a ReplaceType dep mapper and move them into their own file * Implement the service endpoints controller * Implement a Catalog Controllers Integration Test --- go.mod | 2 +- .../v1alpha1/api-service.json | 37 + .../v1alpha1/api-workload-1-health.json | 33 + .../v1alpha1/api-workload-1.json | 46 ++ .../v1alpha1/api-workload-10-health.json | 33 + .../v1alpha1/api-workload-10.json | 46 ++ .../v1alpha1/api-workload-11-health.json | 33 + .../v1alpha1/api-workload-11.json | 46 ++ .../v1alpha1/api-workload-12-health.json | 33 + .../v1alpha1/api-workload-12.json | 46 ++ .../v1alpha1/api-workload-13-health.json | 33 + .../v1alpha1/api-workload-13.json | 46 ++ .../v1alpha1/api-workload-14-health.json | 33 + .../v1alpha1/api-workload-14.json | 46 ++ .../v1alpha1/api-workload-15-health.json | 33 + .../v1alpha1/api-workload-15.json | 46 ++ .../v1alpha1/api-workload-16-health.json | 33 + .../v1alpha1/api-workload-16.json | 46 ++ .../v1alpha1/api-workload-17-health.json | 33 + .../v1alpha1/api-workload-17.json | 45 ++ .../v1alpha1/api-workload-18-health.json | 33 + .../v1alpha1/api-workload-18.json | 45 ++ .../v1alpha1/api-workload-19-health.json | 33 + .../v1alpha1/api-workload-19.json | 45 ++ .../v1alpha1/api-workload-2-health.json | 33 + .../v1alpha1/api-workload-2.json | 46 ++ .../v1alpha1/api-workload-20-health.json | 33 + .../v1alpha1/api-workload-20.json | 45 ++ .../v1alpha1/api-workload-3-health.json | 33 + .../v1alpha1/api-workload-3.json | 46 ++ .../v1alpha1/api-workload-4-health.json | 33 + .../v1alpha1/api-workload-4.json | 46 ++ .../v1alpha1/api-workload-5-health.json | 33 + .../v1alpha1/api-workload-5.json | 46 ++ .../v1alpha1/api-workload-6-health.json | 33 + .../v1alpha1/api-workload-6.json | 46 ++ .../v1alpha1/api-workload-7-health.json | 33 + .../v1alpha1/api-workload-7.json | 46 ++ .../v1alpha1/api-workload-8-health.json | 33 + .../v1alpha1/api-workload-8.json | 46 ++ .../v1alpha1/api-workload-9-health.json | 33 + .../v1alpha1/api-workload-9.json | 46 ++ .../v1alpha1/foo-service-endpoints.json | 47 ++ .../v1alpha1/foo-service.json | 24 + .../v1alpha1/grpc-api-service.json | 42 ++ .../v1alpha1/http-api-service.json | 29 + .../v1alpha1/node-1-health.json | 33 + .../v1alpha1/node-1.json | 27 + .../v1alpha1/node-2-health.json | 33 + .../v1alpha1/node-2.json | 27 + .../v1alpha1/node-3-health.json | 33 + .../v1alpha1/node-3.json | 27 + .../v1alpha1/node-4-health.json | 33 + .../v1alpha1/node-4.json | 27 + internal/catalog/catalogtest/run_test.go | 39 + .../catalogtest/test_integration_v1alpha1.go | 707 +++++++++++++++++ internal/catalog/exports.go | 2 + .../controllers/endpoints/controller.go | 384 ++++++++++ .../controllers/endpoints/controller_test.go | 709 ++++++++++++++++++ .../endpoints/reconciliation_data.go | 177 +++++ .../endpoints/reconciliation_data_test.go | 260 +++++++ .../internal/controllers/endpoints/status.go | 33 + .../controllers/nodehealth/controller.go | 14 +- .../internal/controllers/nodehealth/status.go | 42 ++ .../catalog/internal/controllers/register.go | 3 + .../controllers/workloadhealth/controller.go | 32 +- .../controllers/workloadhealth/status.go | 125 +++ .../selectiontracker/selection_tracker.go | 163 ++++ .../selection_tracker_test.go | 275 +++++++ internal/catalog/internal/types/errors.go | 9 + .../catalog/internal/types/errors_test.go | 4 + .../catalog/internal/types/health_status.go | 2 +- .../internal/types/health_status_test.go | 4 +- internal/catalog/internal/types/service.go | 2 +- .../internal/types/service_endpoints.go | 40 +- .../catalog/internal/types/service_test.go | 12 + .../errInvalidEndpointsOwnerName.golden | 1 + internal/controller/api.go | 40 - internal/controller/api_test.go | 74 -- internal/controller/dependency_mappers.go | 58 ++ .../controller/dependency_mappers_test.go | 137 ++++ internal/radix/doc.go | 4 + internal/radix/radix.go | 568 ++++++++++++++ internal/radix/radix_test.go | 408 ++++++++++ internal/resource/errors.go | 18 +- internal/resource/errors_test.go | 2 +- internal/resource/resourcetest/builder.go | 26 +- internal/resource/resourcetest/client.go | 218 ++++++ internal/resource/resourcetest/fs.go | 40 + internal/resource/resourcetest/require.go | 62 ++ internal/resource/resourcetest/testing.go | 17 + sdk/testutil/retry/retry.go | 4 + 92 files changed, 6550 insertions(+), 162 deletions(-) create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-service.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-1-health.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-1.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-10-health.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-10.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-11-health.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-11.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-12-health.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-12.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-13-health.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-13.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-14-health.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-14.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-15-health.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-15.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-16-health.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-16.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-17-health.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-17.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-18-health.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-18.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-19-health.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-19.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-2-health.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-2.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-20-health.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-20.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-3-health.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-3.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-4-health.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-4.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-5-health.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-5.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-6-health.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-6.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-7-health.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-7.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-8-health.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-8.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-9-health.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-9.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/foo-service-endpoints.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/foo-service.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/grpc-api-service.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/http-api-service.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/node-1-health.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/node-1.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/node-2-health.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/node-2.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/node-3-health.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/node-3.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/node-4-health.json create mode 100644 internal/catalog/catalogtest/integration_test_data/v1alpha1/node-4.json create mode 100644 internal/catalog/catalogtest/run_test.go create mode 100644 internal/catalog/catalogtest/test_integration_v1alpha1.go create mode 100644 internal/catalog/internal/controllers/endpoints/controller.go create mode 100644 internal/catalog/internal/controllers/endpoints/controller_test.go create mode 100644 internal/catalog/internal/controllers/endpoints/reconciliation_data.go create mode 100644 internal/catalog/internal/controllers/endpoints/reconciliation_data_test.go create mode 100644 internal/catalog/internal/controllers/endpoints/status.go create mode 100644 internal/catalog/internal/mappers/selectiontracker/selection_tracker.go create mode 100644 internal/catalog/internal/mappers/selectiontracker/selection_tracker_test.go create mode 100644 internal/catalog/internal/types/testdata/errInvalidEndpointsOwnerName.golden create mode 100644 internal/controller/dependency_mappers.go create mode 100644 internal/controller/dependency_mappers_test.go create mode 100644 internal/radix/doc.go create mode 100644 internal/radix/radix.go create mode 100644 internal/radix/radix_test.go create mode 100644 internal/resource/resourcetest/client.go create mode 100644 internal/resource/resourcetest/fs.go create mode 100644 internal/resource/resourcetest/require.go create mode 100644 internal/resource/resourcetest/testing.go diff --git a/go.mod b/go.mod index 4c421c4653..cd4ed5a890 100644 --- a/go.mod +++ b/go.mod @@ -103,6 +103,7 @@ require ( go.opentelemetry.io/proto/otlp v0.19.0 go.uber.org/goleak v1.1.10 golang.org/x/crypto v0.1.0 + golang.org/x/exp v0.0.0-20230321023759-10a507213a29 golang.org/x/net v0.10.0 golang.org/x/oauth2 v0.6.0 golang.org/x/sync v0.2.0 @@ -240,7 +241,6 @@ require ( go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/otel/trace v1.16.0 // indirect go.uber.org/atomic v1.9.0 // indirect - golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect golang.org/x/mod v0.10.0 // indirect golang.org/x/term v0.8.0 // indirect diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-service.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-service.json new file mode 100644 index 0000000000..866c384b1d --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-service.json @@ -0,0 +1,37 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Service" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.Service", + "workloads": { + "prefixes": [ + "api-" + ] + }, + "ports": [ + { + "target_port": "http", + "protocol": "PROTOCOL_HTTP" + }, + { + "target_port": "grpc", + "protocol": "PROTOCOL_GRPC" + }, + { + "target_port": "mesh", + "protocol": "PROTOCOL_MESH" + } + ] + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-1-health.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-1-health.json new file mode 100644 index 0000000000..a1dd1609f2 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-1-health.json @@ -0,0 +1,33 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "HealthStatus" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-1-health" + }, + "owner": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-1" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.HealthStatus", + "type": "synthetic", + "status": "HEALTH_PASSING" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-1.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-1.json new file mode 100644 index 0000000000..1935a767a1 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-1.json @@ -0,0 +1,46 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-1" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.Workload", + "addresses": [ + { + "host": "172.16.1.1" + }, + { + "host": "198.18.2.1", + "external": true, + "ports": [ + "mesh" + ] + } + ], + "ports": { + "http": { + "port": 8080, + "protocol": "PROTOCOL_HTTP" + }, + "grpc": { + "port": 9090, + "protocol": "PROTOCOL_GRPC" + }, + "mesh": { + "port": 10000, + "protocol": "PROTOCOL_MESH" + } + }, + "identity": "api", + "node_name": "node-1" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-10-health.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-10-health.json new file mode 100644 index 0000000000..9c60ce7b09 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-10-health.json @@ -0,0 +1,33 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "HealthStatus" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-10-health" + }, + "owner": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-10" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.HealthStatus", + "type": "synthetic", + "status": "HEALTH_WARNING" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-10.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-10.json new file mode 100644 index 0000000000..362baa4099 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-10.json @@ -0,0 +1,46 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-10" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.Workload", + "addresses": [ + { + "host": "172.16.1.10" + }, + { + "host": "198.18.2.10", + "external": true, + "ports": [ + "mesh" + ] + } + ], + "ports": { + "http": { + "port": 8080, + "protocol": "PROTOCOL_HTTP" + }, + "grpc": { + "port": 9090, + "protocol": "PROTOCOL_GRPC" + }, + "mesh": { + "port": 10000, + "protocol": "PROTOCOL_MESH" + } + }, + "identity": "api", + "node_name": "node-3" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-11-health.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-11-health.json new file mode 100644 index 0000000000..2f80252580 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-11-health.json @@ -0,0 +1,33 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "HealthStatus" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-11-health" + }, + "owner": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-11" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.HealthStatus", + "type": "synthetic", + "status": "HEALTH_CRITICAL" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-11.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-11.json new file mode 100644 index 0000000000..be9c189883 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-11.json @@ -0,0 +1,46 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-11" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.Workload", + "addresses": [ + { + "host": "172.16.1.11" + }, + { + "host": "198.18.2.11", + "external": true, + "ports": [ + "mesh" + ] + } + ], + "ports": { + "http": { + "port": 8080, + "protocol": "PROTOCOL_HTTP" + }, + "grpc": { + "port": 9090, + "protocol": "PROTOCOL_GRPC" + }, + "mesh": { + "port": 10000, + "protocol": "PROTOCOL_MESH" + } + }, + "identity": "api", + "node_name": "node-3" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-12-health.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-12-health.json new file mode 100644 index 0000000000..dd1026eed1 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-12-health.json @@ -0,0 +1,33 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "HealthStatus" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-12-health" + }, + "owner": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-12" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.HealthStatus", + "type": "synthetic", + "status": "HEALTH_MAINTENANCE" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-12.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-12.json new file mode 100644 index 0000000000..34f34d5342 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-12.json @@ -0,0 +1,46 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-12" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.Workload", + "addresses": [ + { + "host": "172.16.1.12" + }, + { + "host": "198.18.2.12", + "external": true, + "ports": [ + "mesh" + ] + } + ], + "ports": { + "http": { + "port": 8080, + "protocol": "PROTOCOL_HTTP" + }, + "grpc": { + "port": 9090, + "protocol": "PROTOCOL_GRPC" + }, + "mesh": { + "port": 10000, + "protocol": "PROTOCOL_MESH" + } + }, + "identity": "api", + "node_name": "node-3" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-13-health.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-13-health.json new file mode 100644 index 0000000000..2a5084afa1 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-13-health.json @@ -0,0 +1,33 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "HealthStatus" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-13-health" + }, + "owner": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-13" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.HealthStatus", + "type": "synthetic", + "status": "HEALTH_PASSING" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-13.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-13.json new file mode 100644 index 0000000000..3d896e0365 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-13.json @@ -0,0 +1,46 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-13" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.Workload", + "addresses": [ + { + "host": "172.16.1.13" + }, + { + "host": "198.18.2.13", + "external": true, + "ports": [ + "mesh" + ] + } + ], + "ports": { + "http": { + "port": 8080, + "protocol": "PROTOCOL_HTTP" + }, + "grpc": { + "port": 9090, + "protocol": "PROTOCOL_GRPC" + }, + "mesh": { + "port": 10000, + "protocol": "PROTOCOL_MESH" + } + }, + "identity": "api", + "node_name": "node-4" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-14-health.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-14-health.json new file mode 100644 index 0000000000..991b66ee52 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-14-health.json @@ -0,0 +1,33 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "HealthStatus" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-14-health" + }, + "owner": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-14" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.HealthStatus", + "type": "synthetic", + "status": "HEALTH_WARNING" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-14.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-14.json new file mode 100644 index 0000000000..e8712a6c65 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-14.json @@ -0,0 +1,46 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-14" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.Workload", + "addresses": [ + { + "host": "172.16.1.14" + }, + { + "host": "198.18.2.14", + "external": true, + "ports": [ + "mesh" + ] + } + ], + "ports": { + "http": { + "port": 8080, + "protocol": "PROTOCOL_HTTP" + }, + "grpc": { + "port": 9090, + "protocol": "PROTOCOL_GRPC" + }, + "mesh": { + "port": 10000, + "protocol": "PROTOCOL_MESH" + } + }, + "identity": "api", + "node_name": "node-4" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-15-health.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-15-health.json new file mode 100644 index 0000000000..22b2ff8334 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-15-health.json @@ -0,0 +1,33 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "HealthStatus" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-15-health" + }, + "owner": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-15" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.HealthStatus", + "type": "synthetic", + "status": "HEALTH_CRITICAL" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-15.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-15.json new file mode 100644 index 0000000000..dbe0f0a44a --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-15.json @@ -0,0 +1,46 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-15" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.Workload", + "addresses": [ + { + "host": "172.16.1.15" + }, + { + "host": "198.18.2.15", + "external": true, + "ports": [ + "mesh" + ] + } + ], + "ports": { + "http": { + "port": 8080, + "protocol": "PROTOCOL_HTTP" + }, + "grpc": { + "port": 9090, + "protocol": "PROTOCOL_GRPC" + }, + "mesh": { + "port": 10000, + "protocol": "PROTOCOL_MESH" + } + }, + "identity": "api", + "node_name": "node-4" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-16-health.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-16-health.json new file mode 100644 index 0000000000..06e3699438 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-16-health.json @@ -0,0 +1,33 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "HealthStatus" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-16-health" + }, + "owner": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-16" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.HealthStatus", + "type": "synthetic", + "status": "HEALTH_MAINTENANCE" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-16.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-16.json new file mode 100644 index 0000000000..3db40493b1 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-16.json @@ -0,0 +1,46 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-16" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.Workload", + "addresses": [ + { + "host": "172.16.1.16" + }, + { + "host": "198.18.2.16", + "external": true, + "ports": [ + "mesh" + ] + } + ], + "ports": { + "http": { + "port": 8080, + "protocol": "PROTOCOL_HTTP" + }, + "grpc": { + "port": 9090, + "protocol": "PROTOCOL_GRPC" + }, + "mesh": { + "port": 10000, + "protocol": "PROTOCOL_MESH" + } + }, + "identity": "api", + "node_name": "node-4" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-17-health.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-17-health.json new file mode 100644 index 0000000000..3b4614cd6f --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-17-health.json @@ -0,0 +1,33 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "HealthStatus" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-17-health" + }, + "owner": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-17" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.HealthStatus", + "type": "synthetic", + "status": "HEALTH_PASSING" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-17.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-17.json new file mode 100644 index 0000000000..79d26a2b33 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-17.json @@ -0,0 +1,45 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-17" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.Workload", + "addresses": [ + { + "host": "172.16.1.17" + }, + { + "host": "198.18.2.17", + "external": true, + "ports": [ + "mesh" + ] + } + ], + "ports": { + "http": { + "port": 8080, + "protocol": "PROTOCOL_HTTP" + }, + "grpc": { + "port": 9090, + "protocol": "PROTOCOL_GRPC" + }, + "mesh": { + "port": 10000, + "protocol": "PROTOCOL_MESH" + } + }, + "identity": "api" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-18-health.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-18-health.json new file mode 100644 index 0000000000..7764016a98 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-18-health.json @@ -0,0 +1,33 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "HealthStatus" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-18-health" + }, + "owner": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-18" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.HealthStatus", + "type": "synthetic", + "status": "HEALTH_WARNING" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-18.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-18.json new file mode 100644 index 0000000000..04df2611c8 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-18.json @@ -0,0 +1,45 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-18" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.Workload", + "addresses": [ + { + "host": "172.16.1.18" + }, + { + "host": "198.18.2.18", + "external": true, + "ports": [ + "mesh" + ] + } + ], + "ports": { + "http": { + "port": 8080, + "protocol": "PROTOCOL_HTTP" + }, + "grpc": { + "port": 9090, + "protocol": "PROTOCOL_GRPC" + }, + "mesh": { + "port": 10000, + "protocol": "PROTOCOL_MESH" + } + }, + "identity": "api" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-19-health.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-19-health.json new file mode 100644 index 0000000000..468cddfbcb --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-19-health.json @@ -0,0 +1,33 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "HealthStatus" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-19-health" + }, + "owner": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-19" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.HealthStatus", + "type": "synthetic", + "status": "HEALTH_CRITICAL" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-19.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-19.json new file mode 100644 index 0000000000..bf9c8fe25a --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-19.json @@ -0,0 +1,45 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-19" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.Workload", + "addresses": [ + { + "host": "172.16.1.19" + }, + { + "host": "198.18.2.19", + "external": true, + "ports": [ + "mesh" + ] + } + ], + "ports": { + "http": { + "port": 8080, + "protocol": "PROTOCOL_HTTP" + }, + "grpc": { + "port": 9090, + "protocol": "PROTOCOL_GRPC" + }, + "mesh": { + "port": 10000, + "protocol": "PROTOCOL_MESH" + } + }, + "identity": "api" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-2-health.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-2-health.json new file mode 100644 index 0000000000..d9bf96b62b --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-2-health.json @@ -0,0 +1,33 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "HealthStatus" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-2-health" + }, + "owner": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-2" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.HealthStatus", + "type": "synthetic", + "status": "HEALTH_WARNING" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-2.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-2.json new file mode 100644 index 0000000000..b80c0ccb85 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-2.json @@ -0,0 +1,46 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-2" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.Workload", + "addresses": [ + { + "host": "172.16.1.2" + }, + { + "host": "198.18.2.2", + "external": true, + "ports": [ + "mesh" + ] + } + ], + "ports": { + "http": { + "port": 8080, + "protocol": "PROTOCOL_HTTP" + }, + "grpc": { + "port": 9090, + "protocol": "PROTOCOL_GRPC" + }, + "mesh": { + "port": 10000, + "protocol": "PROTOCOL_MESH" + } + }, + "identity": "api", + "node_name": "node-1" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-20-health.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-20-health.json new file mode 100644 index 0000000000..98af32bd00 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-20-health.json @@ -0,0 +1,33 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "HealthStatus" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-20-health" + }, + "owner": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-20" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.HealthStatus", + "type": "synthetic", + "status": "HEALTH_MAINTENANCE" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-20.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-20.json new file mode 100644 index 0000000000..89723f54fe --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-20.json @@ -0,0 +1,45 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-20" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.Workload", + "addresses": [ + { + "host": "172.16.1.20" + }, + { + "host": "198.18.2.20", + "external": true, + "ports": [ + "mesh" + ] + } + ], + "ports": { + "http": { + "port": 8080, + "protocol": "PROTOCOL_HTTP" + }, + "grpc": { + "port": 9090, + "protocol": "PROTOCOL_GRPC" + }, + "mesh": { + "port": 10000, + "protocol": "PROTOCOL_MESH" + } + }, + "identity": "api" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-3-health.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-3-health.json new file mode 100644 index 0000000000..28670cc337 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-3-health.json @@ -0,0 +1,33 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "HealthStatus" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-3-health" + }, + "owner": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-3" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.HealthStatus", + "type": "synthetic", + "status": "HEALTH_CRITICAL" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-3.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-3.json new file mode 100644 index 0000000000..c5ea7d82a5 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-3.json @@ -0,0 +1,46 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-3" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.Workload", + "addresses": [ + { + "host": "172.16.1.3" + }, + { + "host": "198.18.2.3", + "external": true, + "ports": [ + "mesh" + ] + } + ], + "ports": { + "http": { + "port": 8080, + "protocol": "PROTOCOL_HTTP" + }, + "grpc": { + "port": 9090, + "protocol": "PROTOCOL_GRPC" + }, + "mesh": { + "port": 10000, + "protocol": "PROTOCOL_MESH" + } + }, + "identity": "api", + "node_name": "node-1" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-4-health.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-4-health.json new file mode 100644 index 0000000000..041d6eed5a --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-4-health.json @@ -0,0 +1,33 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "HealthStatus" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-4-health" + }, + "owner": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-4" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.HealthStatus", + "type": "synthetic", + "status": "HEALTH_MAINTENANCE" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-4.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-4.json new file mode 100644 index 0000000000..53934b9d5e --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-4.json @@ -0,0 +1,46 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-4" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.Workload", + "addresses": [ + { + "host": "172.16.1.4" + }, + { + "host": "198.18.2.4", + "external": true, + "ports": [ + "mesh" + ] + } + ], + "ports": { + "http": { + "port": 8080, + "protocol": "PROTOCOL_HTTP" + }, + "grpc": { + "port": 9090, + "protocol": "PROTOCOL_GRPC" + }, + "mesh": { + "port": 10000, + "protocol": "PROTOCOL_MESH" + } + }, + "identity": "api", + "node_name": "node-1" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-5-health.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-5-health.json new file mode 100644 index 0000000000..1773cb44ca --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-5-health.json @@ -0,0 +1,33 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "HealthStatus" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-5-health" + }, + "owner": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-5" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.HealthStatus", + "type": "synthetic", + "status": "HEALTH_PASSING" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-5.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-5.json new file mode 100644 index 0000000000..cbed9843ad --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-5.json @@ -0,0 +1,46 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-5" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.Workload", + "addresses": [ + { + "host": "172.16.1.5" + }, + { + "host": "198.18.2.5", + "external": true, + "ports": [ + "mesh" + ] + } + ], + "ports": { + "http": { + "port": 8080, + "protocol": "PROTOCOL_HTTP" + }, + "grpc": { + "port": 9090, + "protocol": "PROTOCOL_GRPC" + }, + "mesh": { + "port": 10000, + "protocol": "PROTOCOL_MESH" + } + }, + "identity": "api", + "node_name": "node-2" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-6-health.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-6-health.json new file mode 100644 index 0000000000..3cf2104ef4 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-6-health.json @@ -0,0 +1,33 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "HealthStatus" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-6-health" + }, + "owner": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-6" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.HealthStatus", + "type": "synthetic", + "status": "HEALTH_WARNING" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-6.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-6.json new file mode 100644 index 0000000000..1646e7c029 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-6.json @@ -0,0 +1,46 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-6" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.Workload", + "addresses": [ + { + "host": "172.16.1.6" + }, + { + "host": "198.18.2.6", + "external": true, + "ports": [ + "mesh" + ] + } + ], + "ports": { + "http": { + "port": 8080, + "protocol": "PROTOCOL_HTTP" + }, + "grpc": { + "port": 9090, + "protocol": "PROTOCOL_GRPC" + }, + "mesh": { + "port": 10000, + "protocol": "PROTOCOL_MESH" + } + }, + "identity": "api", + "node_name": "node-2" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-7-health.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-7-health.json new file mode 100644 index 0000000000..d1dbc895fd --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-7-health.json @@ -0,0 +1,33 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "HealthStatus" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-7-health" + }, + "owner": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-7" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.HealthStatus", + "type": "synthetic", + "status": "HEALTH_CRITICAL" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-7.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-7.json new file mode 100644 index 0000000000..240f1e29a6 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-7.json @@ -0,0 +1,46 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-7" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.Workload", + "addresses": [ + { + "host": "172.16.1.7" + }, + { + "host": "198.18.2.7", + "external": true, + "ports": [ + "mesh" + ] + } + ], + "ports": { + "http": { + "port": 8080, + "protocol": "PROTOCOL_HTTP" + }, + "grpc": { + "port": 9090, + "protocol": "PROTOCOL_GRPC" + }, + "mesh": { + "port": 10000, + "protocol": "PROTOCOL_MESH" + } + }, + "identity": "api", + "node_name": "node-2" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-8-health.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-8-health.json new file mode 100644 index 0000000000..cdbb062703 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-8-health.json @@ -0,0 +1,33 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "HealthStatus" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-8-health" + }, + "owner": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-8" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.HealthStatus", + "type": "synthetic", + "status": "HEALTH_MAINTENANCE" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-8.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-8.json new file mode 100644 index 0000000000..16e686c4b4 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-8.json @@ -0,0 +1,46 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-8" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.Workload", + "addresses": [ + { + "host": "172.16.1.8" + }, + { + "host": "198.18.2.8", + "external": true, + "ports": [ + "mesh" + ] + } + ], + "ports": { + "http": { + "port": 8080, + "protocol": "PROTOCOL_HTTP" + }, + "grpc": { + "port": 9090, + "protocol": "PROTOCOL_GRPC" + }, + "mesh": { + "port": 10000, + "protocol": "PROTOCOL_MESH" + } + }, + "identity": "api", + "node_name": "node-2" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-9-health.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-9-health.json new file mode 100644 index 0000000000..6d221b07bd --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-9-health.json @@ -0,0 +1,33 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "HealthStatus" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-9-health" + }, + "owner": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-9" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.HealthStatus", + "type": "synthetic", + "status": "HEALTH_PASSING" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-9.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-9.json new file mode 100644 index 0000000000..9081ff2e9c --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/api-workload-9.json @@ -0,0 +1,46 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Workload" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "api-9" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.Workload", + "addresses": [ + { + "host": "172.16.1.9" + }, + { + "host": "198.18.2.9", + "external": true, + "ports": [ + "mesh" + ] + } + ], + "ports": { + "http": { + "port": 8080, + "protocol": "PROTOCOL_HTTP" + }, + "grpc": { + "port": 9090, + "protocol": "PROTOCOL_GRPC" + }, + "mesh": { + "port": 10000, + "protocol": "PROTOCOL_MESH" + } + }, + "identity": "api", + "node_name": "node-3" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/foo-service-endpoints.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/foo-service-endpoints.json new file mode 100644 index 0000000000..b96f8805b1 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/foo-service-endpoints.json @@ -0,0 +1,47 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "ServiceEndpoints" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "foo" + }, + "owner": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Service" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "foo" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.ServiceEndpoints", + "endpoints": [ + { + "addresses": [ + { + "host": "198.18.0.1" + } + ], + "ports": { + "external-service-port": { + "port": 9876, + "protocol": "PROTOCOL_HTTP2" + } + }, + "health_status": "HEALTH_PASSING" + } + ] + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/foo-service.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/foo-service.json new file mode 100644 index 0000000000..a79cdb2331 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/foo-service.json @@ -0,0 +1,24 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Service" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "foo" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.Service", + "ports": [ + { + "target_port": "external-service-port", + "protocol": "PROTOCOL_HTTP2" + } + ] + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/grpc-api-service.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/grpc-api-service.json new file mode 100644 index 0000000000..6aa39628bf --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/grpc-api-service.json @@ -0,0 +1,42 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Service" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "grpc-api" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.Service", + "workloads": { + "names": [ + "api-1", + "api-2", + "api-3", + "api-4", + "api-5", + "api-6", + "api-7", + "api-8", + "api-9", + "api-20" + ] + }, + "ports": [ + { + "target_port": "grpc", + "protocol": "PROTOCOL_GRPC" + }, + { + "target_port": "mesh", + "protocol": "PROTOCOL_MESH" + } + ] + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/http-api-service.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/http-api-service.json new file mode 100644 index 0000000000..989851e725 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/http-api-service.json @@ -0,0 +1,29 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Service" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "http-api" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.Service", + "workloads": { + "prefixes": [ + "api-1" + ] + }, + "ports": [ + { + "target_port": "http", + "protocol": "PROTOCOL_HTTP" + } + ] + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/node-1-health.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/node-1-health.json new file mode 100644 index 0000000000..5f58cda6ae --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/node-1-health.json @@ -0,0 +1,33 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "HealthStatus" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "node-1-health" + }, + "owner": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Node" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "node-1" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.HealthStatus", + "type": "synthetic", + "status": "HEALTH_PASSING" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/node-1.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/node-1.json new file mode 100644 index 0000000000..c0f618279d --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/node-1.json @@ -0,0 +1,27 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Node" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "node-1" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.Node", + "addresses": [ + { + "host": "198.18.1.1", + "external": true + }, + { + "host": "172.16.0.1" + } + ] + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/node-2-health.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/node-2-health.json new file mode 100644 index 0000000000..6c67a1c1d1 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/node-2-health.json @@ -0,0 +1,33 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "HealthStatus" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "node-2-health" + }, + "owner": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Node" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "node-2" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.HealthStatus", + "type": "synthetic", + "status": "HEALTH_WARNING" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/node-2.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/node-2.json new file mode 100644 index 0000000000..f68fd86ded --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/node-2.json @@ -0,0 +1,27 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Node" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "node-2" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.Node", + "addresses": [ + { + "host": "198.18.1.2", + "external": true + }, + { + "host": "172.16.0.2" + } + ] + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/node-3-health.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/node-3-health.json new file mode 100644 index 0000000000..2efa143afa --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/node-3-health.json @@ -0,0 +1,33 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "HealthStatus" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "node-3-health" + }, + "owner": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Node" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "node-3" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.HealthStatus", + "type": "synthetic", + "status": "HEALTH_CRITICAL" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/node-3.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/node-3.json new file mode 100644 index 0000000000..b8d9a4e165 --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/node-3.json @@ -0,0 +1,27 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Node" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "node-3" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.Node", + "addresses": [ + { + "host": "198.18.1.3", + "external": true + }, + { + "host": "172.16.0.3" + } + ] + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/node-4-health.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/node-4-health.json new file mode 100644 index 0000000000..a4f425e3cd --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/node-4-health.json @@ -0,0 +1,33 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "HealthStatus" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "node-4-health" + }, + "owner": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Node" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "node-4" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.HealthStatus", + "type": "synthetic", + "status": "HEALTH_MAINTENANCE" + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/integration_test_data/v1alpha1/node-4.json b/internal/catalog/catalogtest/integration_test_data/v1alpha1/node-4.json new file mode 100644 index 0000000000..17c98cd98d --- /dev/null +++ b/internal/catalog/catalogtest/integration_test_data/v1alpha1/node-4.json @@ -0,0 +1,27 @@ +{ + "id": { + "type": { + "group": "catalog", + "group_version": "v1alpha1", + "kind": "Node" + }, + "tenancy": { + "partition": "default", + "namespace": "default", + "peer_name": "local" + }, + "name": "node-4" + }, + "data": { + "@type": "hashicorp.consul.catalog.v1alpha1.Node", + "addresses": [ + { + "host": "198.18.1.4", + "external": true + }, + { + "host": "172.16.0.4" + } + ] + } +} \ No newline at end of file diff --git a/internal/catalog/catalogtest/run_test.go b/internal/catalog/catalogtest/run_test.go new file mode 100644 index 0000000000..7c17052d82 --- /dev/null +++ b/internal/catalog/catalogtest/run_test.go @@ -0,0 +1,39 @@ +package catalogtest + +import ( + "testing" + + svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" + "github.com/hashicorp/consul/internal/catalog" + "github.com/hashicorp/consul/internal/catalog/internal/controllers" + "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/internal/resource/reaper" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/sdk/testutil" +) + +func runInMemResourceServiceAndControllers(t *testing.T, deps controllers.Dependencies) pbresource.ResourceServiceClient { + t.Helper() + + ctx := testutil.TestContext(t) + + // Create the in-mem resource service + client := svctest.RunResourceService(t, catalog.RegisterTypes) + + // Setup/Run the controller manager + mgr := controller.NewManager(client, testutil.Logger(t)) + catalog.RegisterControllers(mgr, deps) + + // We also depend on the reaper to take care of cleaning up owned health statuses and + // service endpoints so we must enable that controller as well + reaper.RegisterControllers(mgr) + mgr.SetRaftLeader(true) + go mgr.Run(ctx) + + return client +} + +func TestControllers_Integration(t *testing.T) { + client := runInMemResourceServiceAndControllers(t, catalog.DefaultControllerDependencies()) + RunCatalogV1Alpha1IntegrationTest(t, client) +} diff --git a/internal/catalog/catalogtest/test_integration_v1alpha1.go b/internal/catalog/catalogtest/test_integration_v1alpha1.go new file mode 100644 index 0000000000..8a7f4cd9a2 --- /dev/null +++ b/internal/catalog/catalogtest/test_integration_v1alpha1.go @@ -0,0 +1,707 @@ +package catalogtest + +import ( + "embed" + "fmt" + "testing" + + "github.com/hashicorp/consul/internal/catalog" + "github.com/hashicorp/consul/internal/catalog/internal/controllers/endpoints" + "github.com/hashicorp/consul/internal/catalog/internal/controllers/nodehealth" + "github.com/hashicorp/consul/internal/catalog/internal/controllers/workloadhealth" + "github.com/hashicorp/consul/internal/catalog/internal/types" + rtest "github.com/hashicorp/consul/internal/resource/resourcetest" + pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/proto/private/prototest" + "github.com/hashicorp/consul/sdk/testutil" + "github.com/stretchr/testify/require" +) + +var ( + //go:embed integration_test_data + testData embed.FS +) + +// RunCatalogV1Alpha1IntegrationTest will push up a bunch of catalog related data and then +// verify that all the expected reconciliations happened correctly. This test is +// intended to exercise a large swathe of behavior of the overall catalog package. +// Besides just controller reconciliation behavior, the intent is also to verify +// that integrations with the resource service are also working (i.e. the various +// validation, mutation and ACL hooks get invoked and are working properly) +// +// This test specifically is not doing any sort of lifecycle related tests to ensure +// that modification to values results in re-reconciliation as expected. Instead there +// is another RunCatalogIntegrationTestLifeCycle function that can be used for those +// purposes. The two are distinct so that the data being published and the assertions +// made against the system can be reused in upgrade tests. +func RunCatalogV1Alpha1IntegrationTest(t *testing.T, client pbresource.ResourceServiceClient) { + t.Helper() + + PublishCatalogV1Alpha1IntegrationTestData(t, client) + VerifyCatalogV1Alpha1IntegrationTestResults(t, client) +} + +// PublishCatalogV1Alpha1IntegrationTestData will perform a whole bunch of resource writes +// for Service, ServiceEndpoints, Workload, Node and HealthStatus objects +func PublishCatalogV1Alpha1IntegrationTestData(t *testing.T, client pbresource.ResourceServiceClient) { + t.Helper() + + c := rtest.NewClient(client) + + resources := rtest.ParseResourcesFromFilesystem(t, testData, "integration_test_data/v1alpha1") + c.PublishResources(t, resources) +} + +func VerifyCatalogV1Alpha1IntegrationTestResults(t *testing.T, client pbresource.ResourceServiceClient) { + t.Helper() + + c := rtest.NewClient(client) + + testutil.RunStep(t, "resources-exist", func(t *testing.T) { + c.RequireResourceExists(t, rtest.Resource(catalog.ServiceV1Alpha1Type, "api").ID()) + c.RequireResourceExists(t, rtest.Resource(catalog.ServiceV1Alpha1Type, "http-api").ID()) + c.RequireResourceExists(t, rtest.Resource(catalog.ServiceV1Alpha1Type, "grpc-api").ID()) + c.RequireResourceExists(t, rtest.Resource(catalog.ServiceV1Alpha1Type, "foo").ID()) + + for i := 1; i < 5; i++ { + nodeId := rtest.Resource(catalog.NodeV1Alpha1Type, fmt.Sprintf("node-%d", i)).ID() + c.RequireResourceExists(t, nodeId) + + res := c.RequireResourceExists(t, rtest.Resource(catalog.HealthStatusV1Alpha1Type, fmt.Sprintf("node-%d-health", i)).ID()) + rtest.RequireOwner(t, res, nodeId, true) + } + + for i := 1; i < 21; i++ { + workloadId := rtest.Resource(catalog.WorkloadV1Alpha1Type, fmt.Sprintf("api-%d", i)).ID() + c.RequireResourceExists(t, workloadId) + + res := c.RequireResourceExists(t, rtest.Resource(catalog.HealthStatusV1Alpha1Type, fmt.Sprintf("api-%d-health", i)).ID()) + rtest.RequireOwner(t, res, workloadId, true) + } + }) + + testutil.RunStep(t, "node-health-reconciliation", func(t *testing.T) { + c.WaitForStatusCondition(t, rtest.Resource(catalog.NodeV1Alpha1Type, "node-1").ID(), nodehealth.StatusKey, nodehealth.ConditionPassing) + c.WaitForStatusCondition(t, rtest.Resource(catalog.NodeV1Alpha1Type, "node-2").ID(), nodehealth.StatusKey, nodehealth.ConditionWarning) + c.WaitForStatusCondition(t, rtest.Resource(catalog.NodeV1Alpha1Type, "node-3").ID(), nodehealth.StatusKey, nodehealth.ConditionCritical) + c.WaitForStatusCondition(t, rtest.Resource(catalog.NodeV1Alpha1Type, "node-4").ID(), nodehealth.StatusKey, nodehealth.ConditionMaintenance) + }) + + testutil.RunStep(t, "workload-health-reconciliation", func(t *testing.T) { + c.WaitForStatusCondition(t, rtest.Resource(catalog.WorkloadV1Alpha1Type, "api-1").ID(), workloadhealth.StatusKey, workloadhealth.ConditionNodeAndWorkloadPassing) + c.WaitForStatusCondition(t, rtest.Resource(catalog.WorkloadV1Alpha1Type, "api-2").ID(), workloadhealth.StatusKey, workloadhealth.ConditionWorkloadWarning) + c.WaitForStatusCondition(t, rtest.Resource(catalog.WorkloadV1Alpha1Type, "api-3").ID(), workloadhealth.StatusKey, workloadhealth.ConditionWorkloadCritical) + c.WaitForStatusCondition(t, rtest.Resource(catalog.WorkloadV1Alpha1Type, "api-4").ID(), workloadhealth.StatusKey, workloadhealth.ConditionWorkloadMaintenance) + c.WaitForStatusCondition(t, rtest.Resource(catalog.WorkloadV1Alpha1Type, "api-5").ID(), workloadhealth.StatusKey, workloadhealth.ConditionNodeWarning) + c.WaitForStatusCondition(t, rtest.Resource(catalog.WorkloadV1Alpha1Type, "api-6").ID(), workloadhealth.StatusKey, workloadhealth.ConditionNodeAndWorkloadWarning) + c.WaitForStatusCondition(t, rtest.Resource(catalog.WorkloadV1Alpha1Type, "api-7").ID(), workloadhealth.StatusKey, workloadhealth.ConditionNodeAndWorkloadCritical) + c.WaitForStatusCondition(t, rtest.Resource(catalog.WorkloadV1Alpha1Type, "api-8").ID(), workloadhealth.StatusKey, workloadhealth.ConditionNodeAndWorkloadMaintenance) + c.WaitForStatusCondition(t, rtest.Resource(catalog.WorkloadV1Alpha1Type, "api-9").ID(), workloadhealth.StatusKey, workloadhealth.ConditionNodeCritical) + c.WaitForStatusCondition(t, rtest.Resource(catalog.WorkloadV1Alpha1Type, "api-10").ID(), workloadhealth.StatusKey, workloadhealth.ConditionNodeAndWorkloadCritical) + c.WaitForStatusCondition(t, rtest.Resource(catalog.WorkloadV1Alpha1Type, "api-11").ID(), workloadhealth.StatusKey, workloadhealth.ConditionNodeAndWorkloadCritical) + c.WaitForStatusCondition(t, rtest.Resource(catalog.WorkloadV1Alpha1Type, "api-12").ID(), workloadhealth.StatusKey, workloadhealth.ConditionNodeAndWorkloadMaintenance) + c.WaitForStatusCondition(t, rtest.Resource(catalog.WorkloadV1Alpha1Type, "api-13").ID(), workloadhealth.StatusKey, workloadhealth.ConditionNodeMaintenance) + c.WaitForStatusCondition(t, rtest.Resource(catalog.WorkloadV1Alpha1Type, "api-14").ID(), workloadhealth.StatusKey, workloadhealth.ConditionNodeAndWorkloadMaintenance) + c.WaitForStatusCondition(t, rtest.Resource(catalog.WorkloadV1Alpha1Type, "api-15").ID(), workloadhealth.StatusKey, workloadhealth.ConditionNodeAndWorkloadMaintenance) + c.WaitForStatusCondition(t, rtest.Resource(catalog.WorkloadV1Alpha1Type, "api-16").ID(), workloadhealth.StatusKey, workloadhealth.ConditionNodeAndWorkloadMaintenance) + c.WaitForStatusCondition(t, rtest.Resource(catalog.WorkloadV1Alpha1Type, "api-17").ID(), workloadhealth.StatusKey, workloadhealth.ConditionWorkloadPassing) + c.WaitForStatusCondition(t, rtest.Resource(catalog.WorkloadV1Alpha1Type, "api-18").ID(), workloadhealth.StatusKey, workloadhealth.ConditionWorkloadWarning) + c.WaitForStatusCondition(t, rtest.Resource(catalog.WorkloadV1Alpha1Type, "api-19").ID(), workloadhealth.StatusKey, workloadhealth.ConditionWorkloadCritical) + c.WaitForStatusCondition(t, rtest.Resource(catalog.WorkloadV1Alpha1Type, "api-20").ID(), workloadhealth.StatusKey, workloadhealth.ConditionWorkloadMaintenance) + }) + + testutil.RunStep(t, "service-reconciliation", func(t *testing.T) { + c.WaitForStatusCondition(t, rtest.Resource(catalog.ServiceV1Alpha1Type, "foo").ID(), endpoints.StatusKey, endpoints.ConditionUnmanaged) + c.WaitForStatusCondition(t, rtest.Resource(catalog.ServiceV1Alpha1Type, "api").ID(), endpoints.StatusKey, endpoints.ConditionManaged) + c.WaitForStatusCondition(t, rtest.Resource(catalog.ServiceV1Alpha1Type, "http-api").ID(), endpoints.StatusKey, endpoints.ConditionManaged) + c.WaitForStatusCondition(t, rtest.Resource(catalog.ServiceV1Alpha1Type, "grpc-api").ID(), endpoints.StatusKey, endpoints.ConditionManaged) + }) + + testutil.RunStep(t, "service-endpoints-generation", func(t *testing.T) { + verifyServiceEndpoints(t, c, rtest.Resource(catalog.ServiceEndpointsV1Alpha1Type, "foo").ID(), expectedFooServiceEndpoints()) + verifyServiceEndpoints(t, c, rtest.Resource(catalog.ServiceEndpointsV1Alpha1Type, "api").ID(), expectedApiServiceEndpoints(t, c)) + verifyServiceEndpoints(t, c, rtest.Resource(catalog.ServiceEndpointsV1Alpha1Type, "http-api").ID(), expectedHTTPApiServiceEndpoints(t, c)) + verifyServiceEndpoints(t, c, rtest.Resource(catalog.ServiceEndpointsV1Alpha1Type, "grpc-api").ID(), expectedGRPCApiServiceEndpoints(t, c)) + }) +} + +func expectedFooServiceEndpoints() *pbcatalog.ServiceEndpoints { + return &pbcatalog.ServiceEndpoints{ + Endpoints: []*pbcatalog.Endpoint{ + { + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "198.18.0.1"}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "external-service-port": { + Port: 9876, + Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2, + }, + }, + HealthStatus: pbcatalog.Health_HEALTH_PASSING, + }, + }, + } +} + +func expectedApiServiceEndpoints(t *testing.T, c *rtest.Client) *pbcatalog.ServiceEndpoints { + return &pbcatalog.ServiceEndpoints{ + Endpoints: []*pbcatalog.Endpoint{ + // api-1 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-1").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.1", Ports: []string{"grpc", "http", "mesh"}}, + {Host: "198.18.2.1", External: true, Ports: []string{"mesh"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + HealthStatus: pbcatalog.Health_HEALTH_PASSING, + }, + // api-2 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-2").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.2", Ports: []string{"grpc", "http", "mesh"}}, + {Host: "198.18.2.2", External: true, Ports: []string{"mesh"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + HealthStatus: pbcatalog.Health_HEALTH_WARNING, + }, + // api-3 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-3").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.3", Ports: []string{"grpc", "http", "mesh"}}, + {Host: "198.18.2.3", External: true, Ports: []string{"mesh"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, + }, + // api-4 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-4").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.4", Ports: []string{"grpc", "http", "mesh"}}, + {Host: "198.18.2.4", External: true, Ports: []string{"mesh"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, + }, + // api-5 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-5").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.5", Ports: []string{"grpc", "http", "mesh"}}, + {Host: "198.18.2.5", External: true, Ports: []string{"mesh"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + HealthStatus: pbcatalog.Health_HEALTH_WARNING, + }, + // api-6 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-6").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.6", Ports: []string{"grpc", "http", "mesh"}}, + {Host: "198.18.2.6", External: true, Ports: []string{"mesh"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + HealthStatus: pbcatalog.Health_HEALTH_WARNING, + }, + // api-7 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-7").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.7", Ports: []string{"grpc", "http", "mesh"}}, + {Host: "198.18.2.7", External: true, Ports: []string{"mesh"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, + }, + // api-8 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-8").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.8", Ports: []string{"grpc", "http", "mesh"}}, + {Host: "198.18.2.8", External: true, Ports: []string{"mesh"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, + }, + // api-9 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-9").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.9", Ports: []string{"grpc", "http", "mesh"}}, + {Host: "198.18.2.9", External: true, Ports: []string{"mesh"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, + }, + // api-10 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-10").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.10", Ports: []string{"grpc", "http", "mesh"}}, + {Host: "198.18.2.10", External: true, Ports: []string{"mesh"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, + }, + // api-11 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-11").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.11", Ports: []string{"grpc", "http", "mesh"}}, + {Host: "198.18.2.11", External: true, Ports: []string{"mesh"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, + }, + // api-12 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-12").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.12", Ports: []string{"grpc", "http", "mesh"}}, + {Host: "198.18.2.12", External: true, Ports: []string{"mesh"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, + }, + // api-13 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-13").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.13", Ports: []string{"grpc", "http", "mesh"}}, + {Host: "198.18.2.13", External: true, Ports: []string{"mesh"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, + }, + // api-14 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-14").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.14", Ports: []string{"grpc", "http", "mesh"}}, + {Host: "198.18.2.14", External: true, Ports: []string{"mesh"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, + }, + // api-15 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-15").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.15", Ports: []string{"grpc", "http", "mesh"}}, + {Host: "198.18.2.15", External: true, Ports: []string{"mesh"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, + }, + // api-16 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-16").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.16", Ports: []string{"grpc", "http", "mesh"}}, + {Host: "198.18.2.16", External: true, Ports: []string{"mesh"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, + }, + // api-17 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-17").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.17", Ports: []string{"grpc", "http", "mesh"}}, + {Host: "198.18.2.17", External: true, Ports: []string{"mesh"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + HealthStatus: pbcatalog.Health_HEALTH_PASSING, + }, + // api-18 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-18").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.18", Ports: []string{"grpc", "http", "mesh"}}, + {Host: "198.18.2.18", External: true, Ports: []string{"mesh"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + HealthStatus: pbcatalog.Health_HEALTH_WARNING, + }, + // api-19 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-19").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.19", Ports: []string{"grpc", "http", "mesh"}}, + {Host: "198.18.2.19", External: true, Ports: []string{"mesh"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, + }, + // api-20 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-20").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.20", Ports: []string{"grpc", "http", "mesh"}}, + {Host: "198.18.2.20", External: true, Ports: []string{"mesh"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, + }, + }, + } +} + +func expectedHTTPApiServiceEndpoints(t *testing.T, c *rtest.Client) *pbcatalog.ServiceEndpoints { + return &pbcatalog.ServiceEndpoints{ + Endpoints: []*pbcatalog.Endpoint{ + // api-1 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-1").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.1", Ports: []string{"http"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + HealthStatus: pbcatalog.Health_HEALTH_PASSING, + }, + // api-10 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-10").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.10", Ports: []string{"http"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, + }, + // api-11 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-11").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.11", Ports: []string{"http"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, + }, + // api-12 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-12").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.12", Ports: []string{"http"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, + }, + // api-13 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-13").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.13", Ports: []string{"http"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, + }, + // api-14 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-14").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.14", Ports: []string{"http"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, + }, + // api-15 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-15").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.15", Ports: []string{"http"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, + }, + // api-16 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-16").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.16", Ports: []string{"http"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, + }, + // api-17 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-17").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.17", Ports: []string{"http"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + HealthStatus: pbcatalog.Health_HEALTH_PASSING, + }, + // api-18 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-18").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.18", Ports: []string{"http"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + HealthStatus: pbcatalog.Health_HEALTH_WARNING, + }, + // api-19 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-19").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.19", Ports: []string{"http"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, + }, + }, + } +} + +func expectedGRPCApiServiceEndpoints(t *testing.T, c *rtest.Client) *pbcatalog.ServiceEndpoints { + return &pbcatalog.ServiceEndpoints{ + Endpoints: []*pbcatalog.Endpoint{ + // api-1 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-1").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.1", Ports: []string{"grpc", "mesh"}}, + {Host: "198.18.2.1", External: true, Ports: []string{"mesh"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + HealthStatus: pbcatalog.Health_HEALTH_PASSING, + }, + // api-2 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-2").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.2", Ports: []string{"grpc", "mesh"}}, + {Host: "198.18.2.2", External: true, Ports: []string{"mesh"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + HealthStatus: pbcatalog.Health_HEALTH_WARNING, + }, + // api-3 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-3").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.3", Ports: []string{"grpc", "mesh"}}, + {Host: "198.18.2.3", External: true, Ports: []string{"mesh"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, + }, + // api-4 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-4").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.4", Ports: []string{"grpc", "mesh"}}, + {Host: "198.18.2.4", External: true, Ports: []string{"mesh"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, + }, + // api-5 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-5").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.5", Ports: []string{"grpc", "mesh"}}, + {Host: "198.18.2.5", External: true, Ports: []string{"mesh"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + HealthStatus: pbcatalog.Health_HEALTH_WARNING, + }, + // api-6 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-6").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.6", Ports: []string{"grpc", "mesh"}}, + {Host: "198.18.2.6", External: true, Ports: []string{"mesh"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + HealthStatus: pbcatalog.Health_HEALTH_WARNING, + }, + // api-7 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-7").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.7", Ports: []string{"grpc", "mesh"}}, + {Host: "198.18.2.7", External: true, Ports: []string{"mesh"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, + }, + // api-8 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-8").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.8", Ports: []string{"grpc", "mesh"}}, + {Host: "198.18.2.8", External: true, Ports: []string{"mesh"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, + }, + // api-9 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-9").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.9", Ports: []string{"grpc", "mesh"}}, + {Host: "198.18.2.9", External: true, Ports: []string{"mesh"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, + }, + // api-20 + { + TargetRef: c.ResolveResourceID(t, rtest.Resource(types.WorkloadV1Alpha1Type, "api-20").ID()), + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "172.16.1.20", Ports: []string{"grpc", "mesh"}}, + {Host: "198.18.2.20", External: true, Ports: []string{"mesh"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + "mesh": {Port: 10000, Protocol: pbcatalog.Protocol_PROTOCOL_MESH}, + }, + HealthStatus: pbcatalog.Health_HEALTH_MAINTENANCE, + }, + }, + } +} + +func verifyServiceEndpoints(t *testing.T, c *rtest.Client, id *pbresource.ID, expected *pbcatalog.ServiceEndpoints) { + c.WaitForResourceState(t, id, func(t rtest.T, res *pbresource.Resource) { + var actual pbcatalog.ServiceEndpoints + err := res.Data.UnmarshalTo(&actual) + require.NoError(t, err) + prototest.AssertElementsMatch(t, expected.Endpoints, actual.Endpoints) + }) +} diff --git a/internal/catalog/exports.go b/internal/catalog/exports.go index 10f2f9be0f..61247091be 100644 --- a/internal/catalog/exports.go +++ b/internal/catalog/exports.go @@ -6,6 +6,7 @@ package catalog import ( "github.com/hashicorp/consul/internal/catalog/internal/controllers" "github.com/hashicorp/consul/internal/catalog/internal/mappers/nodemapper" + "github.com/hashicorp/consul/internal/catalog/internal/mappers/selectiontracker" "github.com/hashicorp/consul/internal/catalog/internal/types" "github.com/hashicorp/consul/internal/controller" "github.com/hashicorp/consul/internal/resource" @@ -52,6 +53,7 @@ type ControllerDependencies = controllers.Dependencies func DefaultControllerDependencies() ControllerDependencies { return ControllerDependencies{ WorkloadHealthNodeMapper: nodemapper.New(), + EndpointsWorkloadMapper: selectiontracker.New(), } } diff --git a/internal/catalog/internal/controllers/endpoints/controller.go b/internal/catalog/internal/controllers/endpoints/controller.go new file mode 100644 index 0000000000..1be2a3fd2f --- /dev/null +++ b/internal/catalog/internal/controllers/endpoints/controller.go @@ -0,0 +1,384 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package endpoints + +import ( + "context" + "sort" + + "github.com/hashicorp/consul/internal/catalog/internal/controllers/workloadhealth" + "github.com/hashicorp/consul/internal/catalog/internal/types" + "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/internal/resource" + pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" + "github.com/hashicorp/consul/proto-public/pbresource" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/anypb" +) + +const ( + endpointsMetaManagedBy = "managed-by-controller" +) + +// The WorkloadMapper interface is used to provide an implementation around being able +// to map a watch even for a Workload resource and translate it to reconciliation requests +type WorkloadMapper interface { + // MapWorkload conforms to the controller.DependencyMapper signature. Given a Workload + // resource it should report the resource IDs that have selected the workload. + MapWorkload(context.Context, controller.Runtime, *pbresource.Resource) ([]controller.Request, error) + + // TrackIDForSelector should be used to associate the specified WorkloadSelector with + // the given resource ID. Future calls to MapWorkload + TrackIDForSelector(*pbresource.ID, *pbcatalog.WorkloadSelector) + + // UntrackID should be used to inform the tracker to forget about the specified ID + UntrackID(*pbresource.ID) +} + +// ServiceEndpointsController creates a controller to perform automatic endpoint management for +// services. +func ServiceEndpointsController(workloadMap WorkloadMapper) controller.Controller { + if workloadMap == nil { + panic("No WorkloadMapper was provided to the ServiceEndpointsController constructor") + } + + return controller.ForType(types.ServiceEndpointsType). + WithWatch(types.ServiceType, controller.ReplaceType(types.ServiceEndpointsType)). + WithWatch(types.WorkloadType, workloadMap.MapWorkload). + WithReconciler(newServiceEndpointsReconciler(workloadMap)) +} + +type serviceEndpointsReconciler struct { + workloadMap WorkloadMapper +} + +func newServiceEndpointsReconciler(workloadMap WorkloadMapper) *serviceEndpointsReconciler { + return &serviceEndpointsReconciler{ + workloadMap: workloadMap, + } +} + +// Reconcile will reconcile one ServiceEndpoints resource in response to some event. +func (r *serviceEndpointsReconciler) Reconcile(ctx context.Context, rt controller.Runtime, req controller.Request) error { + // The runtime is passed by value so replacing it here for the remainder of this + // reconciliation request processing will not affect future invocations. + rt.Logger = rt.Logger.With("resource-id", req.ID, "controller", StatusKey) + + rt.Logger.Trace("reconciling service endpoints") + + endpointsID := req.ID + serviceID := &pbresource.ID{ + Type: types.ServiceType, + Tenancy: endpointsID.Tenancy, + Name: endpointsID.Name, + } + + // First we read and unmarshal the service + + serviceData, err := getServiceData(ctx, rt, serviceID) + if err != nil { + rt.Logger.Error("error retrieving corresponding Service", "error", err) + return err + } + + // Check if the service exists. If it doesn't we can avoid a bunch of other work. + if serviceData == nil { + rt.Logger.Trace("service has been deleted") + + // The service was deleted so we need to update the WorkloadMapper to tell it to + // stop tracking this service + r.workloadMap.UntrackID(req.ID) + + // Note that because we configured ServiceEndpoints to be owned by the service, + // the service endpoints object should eventually be automatically deleted. + // There is no reason to attempt deletion here. + return nil + } + + // Now read and unmarshal the endpoints. We don't need this data just yet but all + // code paths from this point on will need this regardless of branching so we pull + // it now. + endpointsData, err := getEndpointsData(ctx, rt, endpointsID) + if err != nil { + rt.Logger.Error("error retrieving existing endpoints", "error", err) + return err + } + + var status *pbresource.Condition + + if serviceUnderManagement(serviceData.service) { + rt.Logger.Trace("service is enabled for automatic endpoint management") + // This service should have its endpoints automatically managed + status = ConditionManaged + + // Inform the WorkloadMapper to track this service and its selectors. So + // future workload updates that would be matched by the services selectors + // cause this service to be rereconciled. + r.workloadMap.TrackIDForSelector(req.ID, serviceData.service.GetWorkloads()) + + // Now read and umarshal all workloads selected by the service. It is imperative + // that this happens after we notify the selection tracker to be tracking that + // selection criteria. If the order were reversed we could potentially miss + // workload creations that should be selected if they happen after gathering + // the workloads but before tracking the selector. Tracking first ensures that + // any event that happens after that would get mapped to an event for these + // endpoints. + workloadData, err := getWorkloadData(ctx, rt, serviceData) + if err != nil { + rt.Logger.Trace("error retrieving selected workloads", "error", err) + return err + } + + // Calculate the latest endpoints from the already gathered workloads + latestEndpoints := workloadsToEndpoints(serviceData.service, workloadData) + + // Before writing the endpoints actually check to see if they are changed + if endpointsData == nil || !proto.Equal(endpointsData.endpoints, latestEndpoints) { + rt.Logger.Trace("endpoints have changed") + + // First encode the endpoints data as an Any type. + endpointData, err := anypb.New(latestEndpoints) + if err != nil { + rt.Logger.Error("error marshalling latest endpoints", "error", err) + return err + } + + // Now perform the write. The endpoints resource should be owned by the service + // so that it will automatically be deleted upon service deletion. We are using + // a special metadata entry to track that this controller is responsible for + // the management of this resource. + _, err = rt.Client.Write(ctx, &pbresource.WriteRequest{ + Resource: &pbresource.Resource{ + Id: req.ID, + Owner: serviceData.resource.Id, + Metadata: map[string]string{ + endpointsMetaManagedBy: StatusKey, + }, + Data: endpointData, + }, + }) + if err != nil { + rt.Logger.Error("error writing generated endpoints", "error", err) + return err + } else { + rt.Logger.Trace("updated endpoints were successfully written") + } + } + } else { + rt.Logger.Trace("endpoints are not being automatically managed") + // This service is not having its endpoints automatically managed + status = ConditionUnmanaged + + // Inform the WorkloadMapper that it no longer needs to track this service + // as it is no longer under endpoint management + r.workloadMap.UntrackID(req.ID) + + // Delete the managed ServiceEndpoints if necessary if the metadata would + // indicate that they were previously managed by this controller + if endpointsData != nil && endpointsData.resource.Metadata[endpointsMetaManagedBy] == StatusKey { + rt.Logger.Trace("removing previous managed endpoints") + + // This performs a CAS deletion to protect against the case where the user + // has overwritten the endpoints since we fetched them. + _, err := rt.Client.Delete(ctx, &pbresource.DeleteRequest{ + Id: endpointsData.resource.Id, + Version: endpointsData.resource.Version, + }) + + // Potentially we could look for CAS failures by checking if the gRPC + // status code is Aborted. However its an edge case and there could + // possibly be other reasons why the gRPC status code would be aborted + // besides CAS version mismatches. The simplest thing to do is to just + // propagate the error and retry reconciliation later. + if err != nil { + rt.Logger.Error("error deleting previously managed endpoints", "error", err) + return err + } + } + } + + // Update the Service status if necessary. Mainly we want to inform the user + // whether we are automatically managing the endpoints to set expectations + // for that object existing or not. + newStatus := &pbresource.Status{ + ObservedGeneration: serviceData.resource.Generation, + Conditions: []*pbresource.Condition{ + status, + }, + } + // If the status is unchanged then we should return and avoid the unnecessary write + if resource.EqualStatus(serviceData.resource.Status[StatusKey], newStatus, false) { + return nil + } + + _, err = rt.Client.WriteStatus(ctx, &pbresource.WriteStatusRequest{ + Id: serviceData.resource.Id, + Key: StatusKey, + Status: newStatus, + }) + + if err != nil { + rt.Logger.Error("error updating the service's status", "error", err, "service", serviceID) + } + return err +} + +// determineWorkloadHealth will find the workload-health controller's status +// within the resource status and parse the workloads health out of it. If +// the workload-health controller has yet to reconcile the workload health +// or the status isn't in the expected form then this function will return +// HEALTH_CRITICAL. +func determineWorkloadHealth(workload *pbresource.Resource) pbcatalog.Health { + status, found := workload.Status[workloadhealth.StatusKey] + if !found { + return pbcatalog.Health_HEALTH_CRITICAL + } + + for _, condition := range status.Conditions { + if condition.Type == workloadhealth.StatusConditionHealthy { + raw, found := pbcatalog.Health_value[condition.Reason] + if found { + return pbcatalog.Health(raw) + } + return pbcatalog.Health_HEALTH_CRITICAL + } + } + return pbcatalog.Health_HEALTH_CRITICAL +} + +// serviceUnderManagement detects whether this service should have its +// endpoints automatically managed by the controller +func serviceUnderManagement(svc *pbcatalog.Service) bool { + sel := svc.GetWorkloads() + if sel == nil { + // The selector wasn't present at all. Therefore this service is not under + // automatic endpoint management. + return false + } + + if len(sel.Names) < 1 && len(sel.Prefixes) < 1 { + // The selector was set in the request but the list of workload names + // and prefixes were both empty. Therefore this service is not under + // automatic endpoint management + return false + } + + // Some workload selection criteria exists, so this service is considered + // under automatic endpoint management. + return true +} + +// workloadsToEndpoints will translate the Workload resources into a ServiceEndpoints resource +func workloadsToEndpoints(svc *pbcatalog.Service, workloads []*workloadData) *pbcatalog.ServiceEndpoints { + var endpoints []*pbcatalog.Endpoint + + for _, workload := range workloads { + endpoint := workloadToEndpoint(svc, workload) + if endpoint != nil { + endpoints = append(endpoints, endpoint) + } + } + + return &pbcatalog.ServiceEndpoints{ + Endpoints: endpoints, + } +} + +// workloadToEndpoint will convert a workload resource into a singular Endpoint to be +// put within a ServiceEndpoints resource. +// +// The conversion process involves parsing the workloads health and filtering its +// addresses and ports down to just what the service wants to consume. +// +// Determining the workloads health requires the workload-health controller to already +// have reconciled the workloads health and stored it within the resources Status field. +// Any unreconciled workload health will be represented in the ServiceEndpoints with +// the ANY health status. +func workloadToEndpoint(svc *pbcatalog.Service, data *workloadData) *pbcatalog.Endpoint { + health := determineWorkloadHealth(data.resource) + + endpointPorts := make(map[string]*pbcatalog.WorkloadPort) + + // Create the endpoints filtered ports map. Only workload ports specified in + // one of the services ports are included. Ports with a protocol mismatch + // between the service and workload will be excluded as well. + for _, svcPort := range svc.Ports { + workloadPort, found := data.workload.Ports[svcPort.TargetPort] + if !found { + // this workload doesn't have this port so ignore it + continue + } + + if workloadPort.Protocol != svcPort.Protocol { + // workload port mismatch - ignore it + continue + } + + endpointPorts[svcPort.TargetPort] = workloadPort + } + + var workloadAddrs []*pbcatalog.WorkloadAddress + + // Now we filter down the addresses and their corresponding port usage to just + // what the service needs to consume. If the address isn't being used to serve + // any of the services target ports, it will be entirely excluded from the + // address list. If some but not all of its ports are served, then the list + // of ports will be reduced to just the intersection of the service ports + // and the workload addresses ports + for _, addr := range data.workload.Addresses { + var ports []string + + if len(addr.Ports) > 0 { + // The workload address has defined ports, filter these as necessary + + for _, portName := range addr.Ports { + // check if the workload port has been selected by the service + _, found := endpointPorts[portName] + if !found { + // this port isn't selected by the service so drop this port + continue + } + + ports = append(ports, portName) + } + } else { + // The workload address doesn't specify ports. This lack of port specification + // means that all ports are exposed on the interface so here we create a list + // of all the port names exposed by the service. + for portName := range endpointPorts { + ports = append(ports, portName) + } + } + + // sort the ports to keep them stable and prevent unnecessary rewrites when the endpoints + // get diffed + sort.Slice(ports, func(i, j int) bool { + return ports[i] < ports[j] + }) + + // Only record this workload address if one or more of its ports were consumed + // by the service. + if len(ports) > 0 { + workloadAddrs = append(workloadAddrs, &pbcatalog.WorkloadAddress{ + Host: addr.Host, + External: addr.External, + Ports: ports, + }) + } + } + + // If all the workload addresses were filtered out then we should completely ignore + // the workload. While the name matched nothing else did so it isn't useable as + // far as the service is concerned. + if len(workloadAddrs) < 1 { + return nil + } + + return &pbcatalog.Endpoint{ + TargetRef: data.resource.Id, + HealthStatus: health, + Addresses: workloadAddrs, + Ports: endpointPorts, + } +} diff --git a/internal/catalog/internal/controllers/endpoints/controller_test.go b/internal/catalog/internal/controllers/endpoints/controller_test.go new file mode 100644 index 0000000000..ff53509057 --- /dev/null +++ b/internal/catalog/internal/controllers/endpoints/controller_test.go @@ -0,0 +1,709 @@ +package endpoints + +import ( + "context" + "testing" + + svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" + "github.com/hashicorp/consul/internal/catalog/internal/controllers/workloadhealth" + "github.com/hashicorp/consul/internal/catalog/internal/mappers/selectiontracker" + "github.com/hashicorp/consul/internal/catalog/internal/types" + "github.com/hashicorp/consul/internal/controller" + rtest "github.com/hashicorp/consul/internal/resource/resourcetest" + pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/proto/private/prototest" + "github.com/hashicorp/consul/sdk/testutil" + "github.com/hashicorp/consul/sdk/testutil/retry" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" +) + +var ( + badId = rtest.Resource(&pbresource.Type{Group: "not", Kind: "found", GroupVersion: "vfake"}, "foo").ID() +) + +func TestWorkloadsToEndpoints(t *testing.T) { + // This test's purpose is to ensure that converting multiple workloads to endpoints + // happens as expected. It is not concerned with the data in each endpoint but rather + // the removal of unconvertable workloads (nil endpoints returned by workloadToEndpoint). + + // The workload to endpoint conversion only cares about the service ports + service := &pbcatalog.Service{ + Ports: []*pbcatalog.ServicePort{ + {TargetPort: "http2", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2}, + }, + } + + workloadAddresses := []*pbcatalog.WorkloadAddress{ + {Host: "127.0.0.1"}, + } + + // This workload is port-matched with the service and should show up as an + // endpoint in the final set. + workloadData1 := &pbcatalog.Workload{ + Addresses: workloadAddresses, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http2": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2}, + }, + } + + // This workload is NOT port-matched with the service and should be omitted. + workloadData2 := &pbcatalog.Workload{ + Addresses: workloadAddresses, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + } + + // Build out the workloads. + workloads := []*workloadData{ + { + // this workload should result in an endpoints + resource: rtest.Resource(types.WorkloadType, "foo"). + WithData(t, workloadData1). + Build(), + workload: workloadData1, + }, + { + // this workload should be filtered out + resource: rtest.Resource(types.WorkloadType, "bar"). + WithData(t, workloadData2). + Build(), + workload: workloadData2, + }, + } + + endpoints := workloadsToEndpoints(service, workloads) + require.Len(t, endpoints.Endpoints, 1) + prototest.AssertDeepEqual(t, workloads[0].resource.Id, endpoints.Endpoints[0].TargetRef) +} + +func TestWorkloadToEndpoint(t *testing.T) { + // This test handles ensuring that the bulk of the functionality of + // the workloadToEndpoint function works correctly. + // + // * WorkloadPorts that are not selected by one service port are ignored + // and not present in the resulting Endpoint + // * WorkloadPorts that have a protocol mismatch with the service port + // are ignored and not present in the resulting Endpoint + // * WorkloadAddresses with 0 non-ignored ports are omitted from the + // resulting Endpoint. + // * Specifying no ports for a WorkloadAddress will use all the non-ignored + // ports. These are explicitly set but that is intended to be an + // implementation detail at this point. + + service := &pbcatalog.Service{ + Ports: []*pbcatalog.ServicePort{ + // the workload will not have this port so it should be ignored + {TargetPort: "not-found", Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + // the workload will have a different protocol for this port and so it + // will be ignored. + {TargetPort: "grpc", Protocol: pbcatalog.Protocol_PROTOCOL_GRPC}, + }, + } + + workload := &pbcatalog.Workload{ + Addresses: []*pbcatalog.WorkloadAddress{ + // this address will be in the endpoint with all the ports that are + // not filtered out - so just http + {Host: "127.0.0.1"}, + // this address will be in the endpoint but with a filtered ports list + {Host: "198.18.1.1", Ports: []string{"http", "grpc"}}, + // this address should not show up in the endpoint because the port it + // uses is filtered out + {Host: "198.8.0.1", Ports: []string{"grpc"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + // the protocol is wrong here so it will not show up in the endpoints. + "grpc": {Port: 9090, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2}, + }, + } + + data := &workloadData{ + resource: rtest.Resource(types.WorkloadType, "foo"). + WithData(t, workload). + Build(), + workload: workload, + } + + expected := &pbcatalog.Endpoint{ + TargetRef: data.resource.Id, + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "127.0.0.1", Ports: []string{"http"}}, + {Host: "198.18.1.1", Ports: []string{"http"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": workload.Ports["http"], + }, + // The health is critical because we are not setting the workload's + // health status. The tests for determineWorkloadHealth will ensure + // that we can properly determine the health status and the overall + // controller tests will prove that the integration works as expected. + HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, + } + + prototest.AssertDeepEqual(t, expected, workloadToEndpoint(service, data)) +} + +func TestWorkloadToEndpoint_AllAddressesFiltered(t *testing.T) { + // This test checks the specific case where the workload has no + // address/port combinations that remain unfiltered. In this + // case we want to ensure nil is returned instead of an Endpoint + // with no addresses. + + service := &pbcatalog.Service{ + Ports: []*pbcatalog.ServicePort{ + {TargetPort: "not-found", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + } + + workload := &pbcatalog.Workload{ + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "127.0.0.1"}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + } + + data := &workloadData{ + resource: rtest.Resource(types.WorkloadType, "foo"). + WithData(t, workload). + Build(), + workload: workload, + } + + require.Nil(t, workloadToEndpoint(service, data)) +} + +func TestServiceUnderManagement(t *testing.T) { + // This test ensures that we can properly detect when a service + // should have endpoints generated for it vs when those endpoints + // are not being automatically managed. + + type testCase struct { + svc *pbcatalog.Service + managed bool + } + + cases := map[string]testCase{ + "nil": { + svc: nil, + managed: false, + }, + "nil-selector": { + svc: &pbcatalog.Service{Workloads: nil}, + managed: false, + }, + "empty-selector": { + svc: &pbcatalog.Service{Workloads: &pbcatalog.WorkloadSelector{}}, + managed: false, + }, + "exact-match": { + svc: &pbcatalog.Service{Workloads: &pbcatalog.WorkloadSelector{ + Names: []string{"foo"}, + }}, + managed: true, + }, + "prefix-match": { + svc: &pbcatalog.Service{Workloads: &pbcatalog.WorkloadSelector{ + Prefixes: []string{"foo"}, + }}, + managed: true, + }, + "multiple": { + svc: &pbcatalog.Service{Workloads: &pbcatalog.WorkloadSelector{ + Names: []string{"foo"}, + Prefixes: []string{"api-"}, + }}, + managed: true, + }, + } + + for name, tcase := range cases { + t.Run(name, func(t *testing.T) { + require.Equal(t, tcase.managed, serviceUnderManagement(tcase.svc)) + }) + } +} + +func TestDetermineWorkloadHealth(t *testing.T) { + // This test ensures that parsing workload health out of the + // resource status works as expected. + + type testCase struct { + res *pbresource.Resource + expected pbcatalog.Health + } + + cases := map[string]testCase{ + "no-status": { + res: rtest.Resource(types.WorkloadType, "foo").Build(), + expected: pbcatalog.Health_HEALTH_CRITICAL, + }, + "condition-not-found": { + res: rtest.Resource(types.WorkloadType, "foo"). + WithStatus(workloadhealth.StatusKey, &pbresource.Status{ + Conditions: []*pbresource.Condition{ + { + Type: "other", + State: pbresource.Condition_STATE_TRUE, + Reason: "NOT_RELEVANT", + }, + }, + }). + Build(), + expected: pbcatalog.Health_HEALTH_CRITICAL, + }, + "invalid-reason": { + res: rtest.Resource(types.WorkloadType, "foo"). + WithStatus(workloadhealth.StatusKey, &pbresource.Status{ + Conditions: []*pbresource.Condition{ + { + Type: workloadhealth.StatusConditionHealthy, + State: pbresource.Condition_STATE_TRUE, + Reason: "INVALID_HEALTH_STATUS_REASON", + }, + }, + }). + Build(), + expected: pbcatalog.Health_HEALTH_CRITICAL, + }, + "passing": { + res: rtest.Resource(types.WorkloadType, "foo"). + WithStatus(workloadhealth.StatusKey, &pbresource.Status{ + Conditions: []*pbresource.Condition{ + { + Type: workloadhealth.StatusConditionHealthy, + State: pbresource.Condition_STATE_TRUE, + Reason: pbcatalog.Health_HEALTH_PASSING.String(), + }, + }, + }). + Build(), + expected: pbcatalog.Health_HEALTH_PASSING, + }, + "warning": { + res: rtest.Resource(types.WorkloadType, "foo"). + WithStatus(workloadhealth.StatusKey, &pbresource.Status{ + Conditions: []*pbresource.Condition{ + { + Type: workloadhealth.StatusConditionHealthy, + State: pbresource.Condition_STATE_TRUE, + Reason: pbcatalog.Health_HEALTH_WARNING.String(), + }, + }, + }). + Build(), + expected: pbcatalog.Health_HEALTH_WARNING, + }, + "critical": { + res: rtest.Resource(types.WorkloadType, "foo"). + WithStatus(workloadhealth.StatusKey, &pbresource.Status{ + Conditions: []*pbresource.Condition{ + { + Type: workloadhealth.StatusConditionHealthy, + State: pbresource.Condition_STATE_TRUE, + Reason: pbcatalog.Health_HEALTH_CRITICAL.String(), + }, + }, + }). + Build(), + expected: pbcatalog.Health_HEALTH_CRITICAL, + }, + "maintenance": { + res: rtest.Resource(types.WorkloadType, "foo"). + WithStatus(workloadhealth.StatusKey, &pbresource.Status{ + Conditions: []*pbresource.Condition{ + { + Type: workloadhealth.StatusConditionHealthy, + State: pbresource.Condition_STATE_TRUE, + Reason: pbcatalog.Health_HEALTH_MAINTENANCE.String(), + }, + }, + }). + Build(), + expected: pbcatalog.Health_HEALTH_MAINTENANCE, + }, + } + + for name, tcase := range cases { + t.Run(name, func(t *testing.T) { + require.Equal(t, tcase.expected, determineWorkloadHealth(tcase.res)) + }) + } +} + +type controllerSuite struct { + suite.Suite + + ctx context.Context + client *rtest.Client + rt controller.Runtime + + tracker *selectiontracker.WorkloadSelectionTracker + reconciler *serviceEndpointsReconciler +} + +func (suite *controllerSuite) SetupTest() { + suite.ctx = testutil.TestContext(suite.T()) + client := svctest.RunResourceService(suite.T(), types.Register) + suite.rt = controller.Runtime{ + Client: client, + Logger: testutil.Logger(suite.T()), + } + suite.client = rtest.NewClient(client) + suite.tracker = selectiontracker.New() + suite.reconciler = newServiceEndpointsReconciler(suite.tracker) +} + +func (suite *controllerSuite) requireTracking(workload *pbresource.Resource, ids ...*pbresource.ID) { + reqs, err := suite.tracker.MapWorkload(suite.ctx, suite.rt, workload) + require.NoError(suite.T(), err) + require.Len(suite.T(), reqs, len(ids)) + for _, id := range ids { + prototest.AssertContainsElement(suite.T(), reqs, controller.Request{ID: id}) + } +} + +func (suite *controllerSuite) requireEndpoints(resource *pbresource.Resource, expected ...*pbcatalog.Endpoint) { + var svcEndpoints pbcatalog.ServiceEndpoints + require.NoError(suite.T(), resource.Data.UnmarshalTo(&svcEndpoints)) + require.Len(suite.T(), svcEndpoints.Endpoints, len(expected)) + prototest.AssertElementsMatch(suite.T(), expected, svcEndpoints.Endpoints) +} + +func (suite *controllerSuite) TestReconcile_ServiceNotFound() { + // This test's purpose is to ensure that when we are reconciling + // endpoints for a service that no longer exists, we stop + // tracking the endpoints resource ID in the selection tracker. + + // generate a workload resource to use for checking if it maps + // to a service endpoints object + workload := rtest.Resource(types.WorkloadType, "foo").Build() + + // ensure that the tracker knows about the service prior to + // calling reconcile so that we can ensure it removes tracking + id := rtest.Resource(types.ServiceEndpointsType, "not-found").ID() + suite.tracker.TrackIDForSelector(id, &pbcatalog.WorkloadSelector{Prefixes: []string{""}}) + + // verify that mapping the workload to service endpoints returns a + // non-empty list prior to reconciliation which should remove the + // tracking. + suite.requireTracking(workload, id) + + // Because the endpoints don't exist, this reconcile call should + // cause tracking of the endpoints to be removed + err := suite.reconciler.Reconcile(suite.ctx, suite.rt, controller.Request{ID: id}) + require.NoError(suite.T(), err) + + // Now ensure that the tracking was removed + suite.requireTracking(workload) +} + +func (suite *controllerSuite) TestReconcile_NoSelector_NoEndpoints() { + // This test's purpose is to ensure that the service's status is + // updated to record that its endpoints are not being automatically + // managed. Additionally, with no endpoints pre-existing it will + // not attempt to delete them. + + service := rtest.Resource(types.ServiceType, "test"). + WithData(suite.T(), &pbcatalog.Service{ + Ports: []*pbcatalog.ServicePort{ + {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + }). + Write(suite.T(), suite.client) + + endpointsID := rtest.Resource(types.ServiceEndpointsType, "test").ID() + + err := suite.reconciler.Reconcile(suite.ctx, suite.rt, controller.Request{ID: endpointsID}) + require.NoError(suite.T(), err) + + suite.client.RequireStatusCondition(suite.T(), service.Id, StatusKey, ConditionUnmanaged) +} + +func (suite *controllerSuite) TestReconcile_NoSelector_ManagedEndpoints() { + // This test's purpose is to ensure that when moving from managed endpoints + // to unmanaged endpoints for a service, any already generated managed endpoints + // get deleted. + + service := rtest.Resource(types.ServiceType, "test"). + WithData(suite.T(), &pbcatalog.Service{ + Ports: []*pbcatalog.ServicePort{ + {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + }). + Write(suite.T(), suite.client) + + endpoints := rtest.Resource(types.ServiceEndpointsType, "test"). + WithData(suite.T(), &pbcatalog.ServiceEndpoints{}). + // this marks these endpoints as under management + WithMeta(endpointsMetaManagedBy, StatusKey). + Write(suite.T(), suite.client) + + err := suite.reconciler.Reconcile(suite.ctx, suite.rt, controller.Request{ID: endpoints.Id}) + require.NoError(suite.T(), err) + // the status should indicate the services endpoints are not being managed + suite.client.RequireStatusCondition(suite.T(), service.Id, StatusKey, ConditionUnmanaged) + // endpoints under management should be deleted + suite.client.RequireResourceNotFound(suite.T(), endpoints.Id) +} + +func (suite *controllerSuite) TestReconcile_NoSelector_UnmanagedEndpoints() { + // This test's purpose is to ensure that when re-reconciling a service that + // doesn't have its endpoints managed, that we do not delete any unmanaged + // ServiceEndpoints resource that the user would have manually written. + + service := rtest.Resource(types.ServiceType, "test"). + WithData(suite.T(), &pbcatalog.Service{ + Ports: []*pbcatalog.ServicePort{ + {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + }). + Write(suite.T(), suite.client) + + endpoints := rtest.Resource(types.ServiceEndpointsType, "test"). + WithData(suite.T(), &pbcatalog.ServiceEndpoints{}). + Write(suite.T(), suite.client) + + err := suite.reconciler.Reconcile(suite.ctx, suite.rt, controller.Request{ID: endpoints.Id}) + require.NoError(suite.T(), err) + // the status should indicate the services endpoints are not being managed + suite.client.RequireStatusCondition(suite.T(), service.Id, StatusKey, ConditionUnmanaged) + // unmanaged endpoints should not be deleted when the service is unmanaged + suite.client.RequireResourceExists(suite.T(), endpoints.Id) +} + +func (suite *controllerSuite) TestReconcile_Managed_NoPreviousEndpoints() { + // This test's purpose is to ensure the managed endpoint generation occurs + // as expected when there are no pre-existing endpoints. + + service := rtest.Resource(types.ServiceType, "test"). + WithData(suite.T(), &pbcatalog.Service{ + Workloads: &pbcatalog.WorkloadSelector{ + Prefixes: []string{""}, + }, + Ports: []*pbcatalog.ServicePort{ + {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + }). + Write(suite.T(), suite.client) + + endpointsID := rtest.Resource(types.ServiceEndpointsType, "test").ID() + + rtest.Resource(types.WorkloadType, "test-workload"). + WithData(suite.T(), &pbcatalog.Workload{ + Addresses: []*pbcatalog.WorkloadAddress{{Host: "127.0.0.1"}}, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + }). + Write(suite.T(), suite.client) + + err := suite.reconciler.Reconcile(suite.ctx, suite.rt, controller.Request{ID: endpointsID}) + require.NoError(suite.T(), err) + + // Verify that the services status has been set to indicate endpoints are automatically managed. + suite.client.RequireStatusCondition(suite.T(), service.Id, StatusKey, ConditionManaged) + + // The service endpoints metadata should include our tag to indcate it was generated by this controller + res := suite.client.RequireResourceMeta(suite.T(), endpointsID, endpointsMetaManagedBy, StatusKey) + + var endpoints pbcatalog.ServiceEndpoints + err = res.Data.UnmarshalTo(&endpoints) + require.NoError(suite.T(), err) + require.Len(suite.T(), endpoints.Endpoints, 1) + // We are not going to retest that the workloads to endpoints conversion process + // The length check should be sufficient to prove the endpoints are being + // converted. The unit tests for the workloadsToEndpoints functions prove that + // the process works correctly in all cases. +} + +func (suite *controllerSuite) TestReconcile_Managed_ExistingEndpoints() { + // This test's purpose is to ensure that when the current set of endpoints + // differs from any prior set of endpoints that the resource gets rewritten. + + service := rtest.Resource(types.ServiceType, "test"). + WithData(suite.T(), &pbcatalog.Service{ + Workloads: &pbcatalog.WorkloadSelector{ + Prefixes: []string{""}, + }, + Ports: []*pbcatalog.ServicePort{ + {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + }). + Write(suite.T(), suite.client) + + endpoints := rtest.Resource(types.ServiceEndpointsType, "test"). + WithData(suite.T(), &pbcatalog.ServiceEndpoints{}). + WithOwner(service.Id). + Write(suite.T(), suite.client) + + rtest.Resource(types.WorkloadType, "test-workload"). + WithData(suite.T(), &pbcatalog.Workload{ + Addresses: []*pbcatalog.WorkloadAddress{{Host: "127.0.0.1"}}, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + }). + Write(suite.T(), suite.client) + + err := suite.reconciler.Reconcile(suite.ctx, suite.rt, controller.Request{ID: endpoints.Id}) + require.NoError(suite.T(), err) + + suite.client.RequireStatusCondition(suite.T(), service.Id, StatusKey, ConditionManaged) + res := suite.client.RequireResourceMeta(suite.T(), endpoints.Id, endpointsMetaManagedBy, StatusKey) + + var newEndpoints pbcatalog.ServiceEndpoints + err = res.Data.UnmarshalTo(&newEndpoints) + require.NoError(suite.T(), err) + require.Len(suite.T(), newEndpoints.Endpoints, 1) +} + +func (suite *controllerSuite) TestController() { + // This test's purpose is to exercise the controller in a halfway realistic way. + // Generally we are trying to go through the whole lifecycle of creating services, + // adding workloads, modifying workload health and modifying the service selection + // criteria. This isn't a full integration test as that would require also + // executing the workload health controller. Instead workload health status is + // synthesized as necessary. + + // Run the controller manager + mgr := controller.NewManager(suite.client, suite.rt.Logger) + mgr.Register(ServiceEndpointsController(suite.tracker)) + mgr.SetRaftLeader(true) + go mgr.Run(suite.ctx) + + // Add a service - there are no workloads so an empty endpoints + // object should be created. + service := rtest.Resource(types.ServiceType, "api"). + WithData(suite.T(), &pbcatalog.Service{ + Workloads: &pbcatalog.WorkloadSelector{ + Prefixes: []string{"api-"}, + }, + Ports: []*pbcatalog.ServicePort{ + {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + }). + Write(suite.T(), suite.client) + + // Wait for the controller to record that the endpoints are being managed + res := suite.client.WaitForReconciliation(suite.T(), service.Id, StatusKey) + // Check that the services status was updated accordingly + rtest.RequireStatusCondition(suite.T(), res, StatusKey, ConditionManaged) + + // Check that the endpoints resource exists and contains 0 endpoints + endpointsID := rtest.Resource(types.ServiceEndpointsType, "api").ID() + endpoints := suite.client.RequireResourceExists(suite.T(), endpointsID) + suite.requireEndpoints(endpoints) + + // Now add a workload that would be selected by the service. Leave + // the workload in a state where its health has not been reconciled + workload := rtest.Resource(types.WorkloadType, "api-1"). + WithData(suite.T(), &pbcatalog.Workload{ + Addresses: []*pbcatalog.WorkloadAddress{{Host: "127.0.0.1"}}, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + Identity: "api", + }). + Write(suite.T(), suite.client) + + // Wait for the endpoints to be regenerated + endpoints = suite.client.WaitForNewVersion(suite.T(), endpointsID, endpoints.Version) + + // Verify that the generated endpoints now contain the workload + suite.requireEndpoints(endpoints, &pbcatalog.Endpoint{ + TargetRef: workload.Id, + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "127.0.0.1", Ports: []string{"http"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + HealthStatus: pbcatalog.Health_HEALTH_CRITICAL, + }) + + // Update the health status of the workload + suite.client.WriteStatus(suite.ctx, &pbresource.WriteStatusRequest{ + Id: workload.Id, + Key: workloadhealth.StatusKey, + Status: &pbresource.Status{ + ObservedGeneration: workload.Generation, + Conditions: []*pbresource.Condition{ + { + Type: workloadhealth.StatusConditionHealthy, + State: pbresource.Condition_STATE_TRUE, + Reason: "HEALTH_PASSING", + }, + }, + }, + }) + + // Wait for the endpoints to be regenerated + endpoints = suite.client.WaitForNewVersion(suite.T(), endpointsID, endpoints.Version) + + // ensure the endpoint was put into the passing state + suite.requireEndpoints(endpoints, &pbcatalog.Endpoint{ + TargetRef: workload.Id, + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "127.0.0.1", Ports: []string{"http"}}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + HealthStatus: pbcatalog.Health_HEALTH_PASSING, + }) + + // rewrite the service to add more selection criteria. This should trigger + // reconciliation but shouldn't result in updating the endpoints because + // the actual list of currently selected workloads has not changed + rtest.Resource(types.ServiceType, "api"). + WithData(suite.T(), &pbcatalog.Service{ + Workloads: &pbcatalog.WorkloadSelector{ + Prefixes: []string{"api-"}, + Names: []string{"doesnt-matter"}, + }, + Ports: []*pbcatalog.ServicePort{ + {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + }). + Write(suite.T(), suite.client) + + // Wait for the service status' observed generation to get bumped + service = suite.client.WaitForReconciliation(suite.T(), service.Id, StatusKey) + + // Verify that the endpoints were not regenerated + suite.client.RequireVersionUnchanged(suite.T(), endpointsID, endpoints.Version) + + // Delete the endpoints. The controller should bring these back momentarily + suite.client.Delete(suite.ctx, &pbresource.DeleteRequest{Id: endpointsID}) + + // Wait for controller to recreate the endpoints + retry.Run(suite.T(), func(r *retry.R) { + suite.client.RequireResourceExists(r, endpointsID) + }) + + // Move the service to having unmanaged endpoints + rtest.Resource(types.ServiceType, "api"). + WithData(suite.T(), &pbcatalog.Service{ + Ports: []*pbcatalog.ServicePort{ + {TargetPort: "http", Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + }). + Write(suite.T(), suite.client) + + res = suite.client.WaitForReconciliation(suite.T(), service.Id, StatusKey) + rtest.RequireStatusCondition(suite.T(), res, StatusKey, ConditionUnmanaged) + + // Verify that the endpoints were deleted + suite.client.RequireResourceNotFound(suite.T(), endpointsID) +} + +func TestController(t *testing.T) { + suite.Run(t, new(controllerSuite)) +} diff --git a/internal/catalog/internal/controllers/endpoints/reconciliation_data.go b/internal/catalog/internal/controllers/endpoints/reconciliation_data.go new file mode 100644 index 0000000000..f00ac1595a --- /dev/null +++ b/internal/catalog/internal/controllers/endpoints/reconciliation_data.go @@ -0,0 +1,177 @@ +package endpoints + +import ( + "context" + "sort" + + "github.com/hashicorp/consul/internal/catalog/internal/types" + "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/internal/resource" + pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" + "github.com/hashicorp/consul/proto-public/pbresource" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +type serviceData struct { + resource *pbresource.Resource + service *pbcatalog.Service +} + +type endpointsData struct { + resource *pbresource.Resource + endpoints *pbcatalog.ServiceEndpoints +} + +type workloadData struct { + resource *pbresource.Resource + workload *pbcatalog.Workload +} + +// getServiceData will read the service with the given ID and unmarshal the +// Data field. The return value is a struct that contains the retrieved +// resource as well as the unmsashalled form. If the resource doesn't +// exist, nil will be returned. Any other error either with retrieving +// the resource or unmarshalling it will cause the error to be returned +// to the caller +func getServiceData(ctx context.Context, rt controller.Runtime, id *pbresource.ID) (*serviceData, error) { + rsp, err := rt.Client.Read(ctx, &pbresource.ReadRequest{Id: id}) + switch { + case status.Code(err) == codes.NotFound: + return nil, nil + case err != nil: + return nil, err + } + + var service pbcatalog.Service + err = rsp.Resource.Data.UnmarshalTo(&service) + if err != nil { + return nil, resource.NewErrDataParse(&service, err) + } + + return &serviceData{resource: rsp.Resource, service: &service}, nil +} + +// getEndpointsData will read the endpoints with the given ID and unmarshal the +// Data field. The return value is a struct that contains the retrieved +// resource as well as the unmsashalled form. If the resource doesn't +// exist, nil will be returned. Any other error either with retrieving +// the resource or unmarshalling it will cause the error to be returned +// to the caller +func getEndpointsData(ctx context.Context, rt controller.Runtime, id *pbresource.ID) (*endpointsData, error) { + rsp, err := rt.Client.Read(ctx, &pbresource.ReadRequest{Id: id}) + switch { + case status.Code(err) == codes.NotFound: + return nil, nil + case err != nil: + return nil, err + } + + var endpoints pbcatalog.ServiceEndpoints + err = rsp.Resource.Data.UnmarshalTo(&endpoints) + if err != nil { + return nil, resource.NewErrDataParse(&endpoints, err) + } + + return &endpointsData{resource: rsp.Resource, endpoints: &endpoints}, nil +} + +// getWorkloadData will retrieve all workloads for the given services selector +// and unmarhshal them, returning a slic of objects hold both the resource and +// unmarshaled forms. Unmarshalling errors, or other resource service errors +// will be returned to the caller. +func getWorkloadData(ctx context.Context, rt controller.Runtime, svc *serviceData) ([]*workloadData, error) { + workloadResources, err := gatherWorkloadsForService(ctx, rt, svc) + if err != nil { + return nil, err + } + + var results []*workloadData + for _, res := range workloadResources { + var workload pbcatalog.Workload + err = res.Data.UnmarshalTo(&workload) + if err != nil { + return nil, resource.NewErrDataParse(&workload, err) + } + + results = append(results, &workloadData{resource: res, workload: &workload}) + } + + return results, nil +} + +// gatherWorkloadsForService will retrieve all the unique workloads for a given selector. +// NotFound errors for workloads selected by Name will be ignored. Any other +// resource service errors will be returned to the caller. Prior to returning +// the slice of resources, they will be sorted by name. The consistent ordering +// will allow callers to diff two versions of the data to determine if anything +// has changed but it also will make testing a little easier. +func gatherWorkloadsForService(ctx context.Context, rt controller.Runtime, svc *serviceData) ([]*pbresource.Resource, error) { + var workloads []*pbresource.Resource + + sel := svc.service.GetWorkloads() + + // this map will track all the gathered workloads by name, this is mainly to deduplicate workloads if they + // are specified multiple times throughout the list of selection criteria + workloadNames := make(map[string]struct{}) + + // First gather all the prefix matched workloads. We could do this second but by doing + // it first its possible we can avoid some resource service calls to read individual + // workloads selected by name if they are also matched by a prefix. + for _, prefix := range sel.GetPrefixes() { + rsp, err := rt.Client.List(ctx, &pbresource.ListRequest{ + Type: types.WorkloadType, + Tenancy: svc.resource.Id.Tenancy, + NamePrefix: prefix, + }) + if err != nil { + return nil, err + } + + // append all workloads in the list response to our list of all selected workloads + for _, workload := range rsp.Resources { + // ignore duplicate workloads + if _, found := workloadNames[workload.Id.Name]; !found { + workloads = append(workloads, workload) + workloadNames[workload.Id.Name] = struct{}{} + } + } + } + + // Now gather the exact match selections + for _, name := range sel.GetNames() { + // ignore names we have already fetched + if _, found := workloadNames[name]; found { + continue + } + + workloadID := &pbresource.ID{ + Type: types.WorkloadType, + Tenancy: svc.resource.Id.Tenancy, + Name: name, + } + + rsp, err := rt.Client.Read(ctx, &pbresource.ReadRequest{Id: workloadID}) + switch { + case status.Code(err) == codes.NotFound: + // Ignore not found errors as services may select workloads that do not + // yet exist. This is not considered an error state or mis-configuration + // as the user could be getting ready to add the workloads. + continue + case err != nil: + return nil, err + } + + workloads = append(workloads, rsp.Resource) + workloadNames[rsp.Resource.Id.Name] = struct{}{} + } + + // Sorting ensures deterministic output. This will help for testing but + // the real reason to do this is so we will be able to diff the set of + // workloads endpoints to determine if we need to update them. + sort.Slice(workloads, func(i, j int) bool { + return workloads[i].Id.Name < workloads[j].Id.Name + }) + + return workloads, nil +} diff --git a/internal/catalog/internal/controllers/endpoints/reconciliation_data_test.go b/internal/catalog/internal/controllers/endpoints/reconciliation_data_test.go new file mode 100644 index 0000000000..c0c83deda9 --- /dev/null +++ b/internal/catalog/internal/controllers/endpoints/reconciliation_data_test.go @@ -0,0 +1,260 @@ +package endpoints + +import ( + "context" + "testing" + + svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" + "github.com/hashicorp/consul/internal/catalog/internal/types" + "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/internal/resource" + rtest "github.com/hashicorp/consul/internal/resource/resourcetest" + pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/proto/private/prototest" + "github.com/hashicorp/consul/sdk/testutil" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +type reconciliationDataSuite struct { + suite.Suite + + ctx context.Context + client pbresource.ResourceServiceClient + rt controller.Runtime + + apiServiceData *pbcatalog.Service + apiService *pbresource.Resource + apiEndpoints *pbresource.Resource + api1Workload *pbresource.Resource + api2Workload *pbresource.Resource + api123Workload *pbresource.Resource + web1Workload *pbresource.Resource + web2Workload *pbresource.Resource +} + +func (suite *reconciliationDataSuite) SetupTest() { + suite.ctx = testutil.TestContext(suite.T()) + suite.client = svctest.RunResourceService(suite.T(), types.Register) + suite.rt = controller.Runtime{ + Client: suite.client, + Logger: testutil.Logger(suite.T()), + } + + suite.apiServiceData = &pbcatalog.Service{ + Workloads: &pbcatalog.WorkloadSelector{ + // This services selectors are specially crafted to exercise both the + // dedeuplication and sorting behaviors of gatherWorkloadsForService + Prefixes: []string{"api-"}, + Names: []string{"api-1", "web-2", "web-1", "api-1", "not-found"}, + }, + Ports: []*pbcatalog.ServicePort{ + { + TargetPort: "http", + Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, + }, + }, + } + + suite.apiService = rtest.Resource(types.ServiceType, "api"). + WithData(suite.T(), suite.apiServiceData). + Write(suite.T(), suite.client) + + suite.api1Workload = rtest.Resource(types.WorkloadType, "api-1"). + WithData(suite.T(), &pbcatalog.Workload{ + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "127.0.0.1"}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + Identity: "api", + }). + Write(suite.T(), suite.client) + + suite.api2Workload = rtest.Resource(types.WorkloadType, "api-2"). + WithData(suite.T(), &pbcatalog.Workload{ + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "127.0.0.1"}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + Identity: "api", + }). + Write(suite.T(), suite.client) + + suite.api123Workload = rtest.Resource(types.WorkloadType, "api-123"). + WithData(suite.T(), &pbcatalog.Workload{ + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "127.0.0.1"}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + Identity: "api", + }). + Write(suite.T(), suite.client) + + suite.web1Workload = rtest.Resource(types.WorkloadType, "web-1"). + WithData(suite.T(), &pbcatalog.Workload{ + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "127.0.0.1"}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + Identity: "web", + }). + Write(suite.T(), suite.client) + + suite.web2Workload = rtest.Resource(types.WorkloadType, "web-2"). + WithData(suite.T(), &pbcatalog.Workload{ + Addresses: []*pbcatalog.WorkloadAddress{ + {Host: "127.0.0.1"}, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + Identity: "web", + }). + Write(suite.T(), suite.client) + + suite.apiEndpoints = rtest.Resource(types.ServiceEndpointsType, "api"). + WithData(suite.T(), &pbcatalog.ServiceEndpoints{ + Endpoints: []*pbcatalog.Endpoint{ + { + TargetRef: rtest.Resource(types.WorkloadType, "api-1").ID(), + Addresses: []*pbcatalog.WorkloadAddress{ + { + Host: "127.0.0.1", + Ports: []string{"http"}, + }, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": {Port: 8080, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP}, + }, + HealthStatus: pbcatalog.Health_HEALTH_PASSING, + }, + }, + }). + Write(suite.T(), suite.client) +} + +func (suite *reconciliationDataSuite) TestGetServiceData_NotFound() { + // This test's purposes is to ensure that NotFound errors when retrieving + // the service data are ignored properly. + data, err := getServiceData(suite.ctx, suite.rt, rtest.Resource(types.ServiceType, "not-found").ID()) + require.NoError(suite.T(), err) + require.Nil(suite.T(), data) +} + +func (suite *reconciliationDataSuite) TestGetServiceData_ReadError() { + // This test's purpose is to ensure that Read errors other than NotFound + // are propagated back to the caller. Specifying a resource ID with an + // unregistered type is the easiest way to force a resource service error. + badType := &pbresource.Type{ + Group: "not", + Kind: "found", + GroupVersion: "vfake", + } + data, err := getServiceData(suite.ctx, suite.rt, rtest.Resource(badType, "foo").ID()) + require.Error(suite.T(), err) + require.Equal(suite.T(), codes.InvalidArgument, status.Code(err)) + require.Nil(suite.T(), data) +} + +func (suite *reconciliationDataSuite) TestGetServiceData_UnmarshalError() { + // This test's purpose is to ensure that unmarshlling errors are returned + // to the caller. We are using a resource id that points to an endpoints + // object instead of a service to ensure that the data will be unmarshallable. + data, err := getServiceData(suite.ctx, suite.rt, rtest.Resource(types.ServiceEndpointsType, "api").ID()) + require.Error(suite.T(), err) + var parseErr resource.ErrDataParse + require.ErrorAs(suite.T(), err, &parseErr) + require.Nil(suite.T(), data) +} + +func (suite *reconciliationDataSuite) TestGetServiceData_Ok() { + // This test's purpose is to ensure that the happy path for + // retrieving a service works as expected. + data, err := getServiceData(suite.ctx, suite.rt, suite.apiService.Id) + require.NoError(suite.T(), err) + require.NotNil(suite.T(), data) + require.NotNil(suite.T(), data.resource) + prototest.AssertDeepEqual(suite.T(), suite.apiService.Id, data.resource.Id) + require.Len(suite.T(), data.service.Ports, 1) +} + +func (suite *reconciliationDataSuite) TestGetEndpointsData_NotFound() { + // This test's purposes is to ensure that NotFound errors when retrieving + // the endpoint data are ignored properly. + data, err := getEndpointsData(suite.ctx, suite.rt, rtest.Resource(types.ServiceEndpointsType, "not-found").ID()) + require.NoError(suite.T(), err) + require.Nil(suite.T(), data) +} + +func (suite *reconciliationDataSuite) TestGetEndpointsData_ReadError() { + // This test's purpose is to ensure that Read errors other than NotFound + // are propagated back to the caller. Specifying a resource ID with an + // unregistered type is the easiest way to force a resource service error. + badType := &pbresource.Type{ + Group: "not", + Kind: "found", + GroupVersion: "vfake", + } + data, err := getEndpointsData(suite.ctx, suite.rt, rtest.Resource(badType, "foo").ID()) + require.Error(suite.T(), err) + require.Equal(suite.T(), codes.InvalidArgument, status.Code(err)) + require.Nil(suite.T(), data) +} + +func (suite *reconciliationDataSuite) TestGetEndpointsData_UnmarshalError() { + // This test's purpose is to ensure that unmarshlling errors are returned + // to the caller. We are using a resource id that points to a service object + // instead of an endpoints object to ensure that the data will be unmarshallable. + data, err := getEndpointsData(suite.ctx, suite.rt, rtest.Resource(types.ServiceType, "api").ID()) + require.Error(suite.T(), err) + var parseErr resource.ErrDataParse + require.ErrorAs(suite.T(), err, &parseErr) + require.Nil(suite.T(), data) +} + +func (suite *reconciliationDataSuite) TestGetEndpointsData_Ok() { + // This test's purpose is to ensure that the happy path for + // retrieving an endpoints object works as expected. + data, err := getEndpointsData(suite.ctx, suite.rt, suite.apiEndpoints.Id) + require.NoError(suite.T(), err) + require.NotNil(suite.T(), data) + require.NotNil(suite.T(), data.resource) + prototest.AssertDeepEqual(suite.T(), suite.apiEndpoints.Id, data.resource.Id) + require.Len(suite.T(), data.endpoints.Endpoints, 1) +} + +func (suite *reconciliationDataSuite) TestGetWorkloadData() { + // This test's purpose is to ensure that gather workloads for + // a service work as expected. The services selector was crafted + // to exercise the deduplication behavior as well as the sorting + // behavior. The assertions in this test will verify that only + // unique workloads are returned and that they are ordered. + + data, err := getWorkloadData(suite.ctx, suite.rt, &serviceData{ + resource: suite.apiService, + service: suite.apiServiceData, + }) + + require.NoError(suite.T(), err) + require.Len(suite.T(), data, 5) + prototest.AssertDeepEqual(suite.T(), suite.api1Workload, data[0].resource) + prototest.AssertDeepEqual(suite.T(), suite.api123Workload, data[1].resource) + prototest.AssertDeepEqual(suite.T(), suite.api2Workload, data[2].resource) + prototest.AssertDeepEqual(suite.T(), suite.web1Workload, data[3].resource) + prototest.AssertDeepEqual(suite.T(), suite.web2Workload, data[4].resource) +} + +func TestReconciliationData(t *testing.T) { + suite.Run(t, new(reconciliationDataSuite)) +} diff --git a/internal/catalog/internal/controllers/endpoints/status.go b/internal/catalog/internal/controllers/endpoints/status.go new file mode 100644 index 0000000000..5388a0fda9 --- /dev/null +++ b/internal/catalog/internal/controllers/endpoints/status.go @@ -0,0 +1,33 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package endpoints + +import "github.com/hashicorp/consul/proto-public/pbresource" + +const ( + StatusKey = "consul.io/endpoint-manager" + StatusConditionEndpointsManaged = "EndpointsManaged" + + StatusReasonSelectorNotFound = "SelectorNotFound" + StatusReasonSelectorFound = "SelectorFound" + + SelectorFoundMessage = "A valid workload selector is present within the service." + SelectorNotFoundMessage = "Either the workload selector was not present or contained no selection criteria." +) + +var ( + ConditionManaged = &pbresource.Condition{ + Type: StatusConditionEndpointsManaged, + State: pbresource.Condition_STATE_TRUE, + Reason: StatusReasonSelectorFound, + Message: SelectorFoundMessage, + } + + ConditionUnmanaged = &pbresource.Condition{ + Type: StatusConditionEndpointsManaged, + State: pbresource.Condition_STATE_FALSE, + Reason: StatusReasonSelectorNotFound, + Message: SelectorNotFoundMessage, + } +) diff --git a/internal/catalog/internal/controllers/nodehealth/controller.go b/internal/catalog/internal/controllers/nodehealth/controller.go index d7586f6121..4e3aff9993 100644 --- a/internal/catalog/internal/controllers/nodehealth/controller.go +++ b/internal/catalog/internal/controllers/nodehealth/controller.go @@ -50,22 +50,10 @@ func (r *nodeHealthReconciler) Reconcile(ctx context.Context, rt controller.Runt return err } - message := NodeHealthyMessage - statusState := pbresource.Condition_STATE_TRUE - if health != pbcatalog.Health_HEALTH_PASSING { - statusState = pbresource.Condition_STATE_FALSE - message = NodeUnhealthyMessage - } - newStatus := &pbresource.Status{ ObservedGeneration: res.Generation, Conditions: []*pbresource.Condition{ - { - Type: StatusConditionHealthy, - State: statusState, - Reason: health.String(), - Message: message, - }, + Conditions[health], }, } diff --git a/internal/catalog/internal/controllers/nodehealth/status.go b/internal/catalog/internal/controllers/nodehealth/status.go index 8cb989101d..14a3151484 100644 --- a/internal/catalog/internal/controllers/nodehealth/status.go +++ b/internal/catalog/internal/controllers/nodehealth/status.go @@ -3,6 +3,11 @@ package nodehealth +import ( + pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" + "github.com/hashicorp/consul/proto-public/pbresource" +) + const ( StatusKey = "consul.io/node-health" StatusConditionHealthy = "healthy" @@ -10,3 +15,40 @@ const ( NodeHealthyMessage = "All node health checks are passing" NodeUnhealthyMessage = "One or more node health checks are not passing" ) + +var ( + ConditionPassing = &pbresource.Condition{ + Type: StatusConditionHealthy, + State: pbresource.Condition_STATE_TRUE, + Reason: pbcatalog.Health_HEALTH_PASSING.String(), + Message: NodeHealthyMessage, + } + + ConditionWarning = &pbresource.Condition{ + Type: StatusConditionHealthy, + State: pbresource.Condition_STATE_FALSE, + Reason: pbcatalog.Health_HEALTH_WARNING.String(), + Message: NodeUnhealthyMessage, + } + + ConditionCritical = &pbresource.Condition{ + Type: StatusConditionHealthy, + State: pbresource.Condition_STATE_FALSE, + Reason: pbcatalog.Health_HEALTH_CRITICAL.String(), + Message: NodeUnhealthyMessage, + } + + ConditionMaintenance = &pbresource.Condition{ + Type: StatusConditionHealthy, + State: pbresource.Condition_STATE_FALSE, + Reason: pbcatalog.Health_HEALTH_MAINTENANCE.String(), + Message: NodeUnhealthyMessage, + } + + Conditions = map[pbcatalog.Health]*pbresource.Condition{ + pbcatalog.Health_HEALTH_PASSING: ConditionPassing, + pbcatalog.Health_HEALTH_WARNING: ConditionWarning, + pbcatalog.Health_HEALTH_CRITICAL: ConditionCritical, + pbcatalog.Health_HEALTH_MAINTENANCE: ConditionMaintenance, + } +) diff --git a/internal/catalog/internal/controllers/register.go b/internal/catalog/internal/controllers/register.go index 1a7987d12d..5f7fc631a5 100644 --- a/internal/catalog/internal/controllers/register.go +++ b/internal/catalog/internal/controllers/register.go @@ -4,6 +4,7 @@ package controllers import ( + "github.com/hashicorp/consul/internal/catalog/internal/controllers/endpoints" "github.com/hashicorp/consul/internal/catalog/internal/controllers/nodehealth" "github.com/hashicorp/consul/internal/catalog/internal/controllers/workloadhealth" "github.com/hashicorp/consul/internal/controller" @@ -11,9 +12,11 @@ import ( type Dependencies struct { WorkloadHealthNodeMapper workloadhealth.NodeMapper + EndpointsWorkloadMapper endpoints.WorkloadMapper } func Register(mgr *controller.Manager, deps Dependencies) { mgr.Register(nodehealth.NodeHealthController()) mgr.Register(workloadhealth.WorkloadHealthController(deps.WorkloadHealthNodeMapper)) + mgr.Register(endpoints.ServiceEndpointsController(deps.EndpointsWorkloadMapper)) } diff --git a/internal/catalog/internal/controllers/workloadhealth/controller.go b/internal/catalog/internal/controllers/workloadhealth/controller.go index b9c19b5414..77009697bc 100644 --- a/internal/catalog/internal/controllers/workloadhealth/controller.go +++ b/internal/catalog/internal/controllers/workloadhealth/controller.go @@ -58,7 +58,7 @@ type workloadHealthReconciler struct { } func (r *workloadHealthReconciler) Reconcile(ctx context.Context, rt controller.Runtime, req controller.Request) error { - // The runtime is passed by value so replacing it here for the remaineder of this + // The runtime is passed by value so replacing it here for the remainder of this // reconciliation request processing will not affect future invocations. rt.Logger = rt.Logger.With("resource-id", req.ID, "controller", StatusKey) @@ -90,6 +90,12 @@ func (r *workloadHealthReconciler) Reconcile(ctx context.Context, rt controller. if workload.NodeName != "" { nodeID := r.nodeMap.NodeIDFromWorkload(res, &workload) r.nodeMap.TrackWorkload(res.Id, nodeID) + + // It is important that getting the nodes health happens after tracking the + // Workload with the node mapper. If the order were reversed we could + // potentially miss events for data that changes after we read the node but + // before we configured the node mapper to map subsequent events to this + // workload. nodeHealth, err = getNodeHealth(ctx, rt, nodeID) if err != nil { rt.Logger.Error("error looking up node health", "error", err, "node-id", nodeID) @@ -114,33 +120,15 @@ func (r *workloadHealthReconciler) Reconcile(ctx context.Context, rt controller. health = workloadHealth } - statusState := pbresource.Condition_STATE_TRUE - if health != pbcatalog.Health_HEALTH_PASSING { - statusState = pbresource.Condition_STATE_FALSE - } - - message := WorkloadHealthyMessage + condition := WorkloadConditions[workloadHealth] if workload.NodeName != "" { - message = NodeAndWorkloadHealthyMessage - } - switch { - case workloadHealth != pbcatalog.Health_HEALTH_PASSING && nodeHealth != pbcatalog.Health_HEALTH_PASSING: - message = NodeAndWorkloadUnhealthyMessage - case workloadHealth != pbcatalog.Health_HEALTH_PASSING: - message = WorkloadUnhealthyMessage - case nodeHealth != pbcatalog.Health_HEALTH_PASSING: - message = nodehealth.NodeUnhealthyMessage + condition = NodeAndWorkloadConditions[workloadHealth][nodeHealth] } newStatus := &pbresource.Status{ ObservedGeneration: res.Generation, Conditions: []*pbresource.Condition{ - { - Type: StatusConditionHealthy, - State: statusState, - Reason: health.String(), - Message: message, - }, + condition, }, } diff --git a/internal/catalog/internal/controllers/workloadhealth/status.go b/internal/catalog/internal/controllers/workloadhealth/status.go index a7da3fad6b..05cc989ddd 100644 --- a/internal/catalog/internal/controllers/workloadhealth/status.go +++ b/internal/catalog/internal/controllers/workloadhealth/status.go @@ -1,5 +1,11 @@ package workloadhealth +import ( + "github.com/hashicorp/consul/internal/catalog/internal/controllers/nodehealth" + pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" + "github.com/hashicorp/consul/proto-public/pbresource" +) + const ( StatusKey = "consul.io/workload-health" StatusConditionHealthy = "healthy" @@ -9,3 +15,122 @@ const ( NodeAndWorkloadUnhealthyMessage = "One or more workload and node health checks are not passing" WorkloadUnhealthyMessage = "One or more workload health checks are not passing" ) + +var ( + ConditionWorkloadPassing = &pbresource.Condition{ + Type: StatusConditionHealthy, + State: pbresource.Condition_STATE_TRUE, + Reason: pbcatalog.Health_HEALTH_PASSING.String(), + Message: WorkloadHealthyMessage, + } + + ConditionWorkloadWarning = &pbresource.Condition{ + Type: StatusConditionHealthy, + State: pbresource.Condition_STATE_FALSE, + Reason: pbcatalog.Health_HEALTH_WARNING.String(), + Message: WorkloadUnhealthyMessage, + } + + ConditionWorkloadCritical = &pbresource.Condition{ + Type: StatusConditionHealthy, + State: pbresource.Condition_STATE_FALSE, + Reason: pbcatalog.Health_HEALTH_CRITICAL.String(), + Message: WorkloadUnhealthyMessage, + } + + ConditionWorkloadMaintenance = &pbresource.Condition{ + Type: StatusConditionHealthy, + State: pbresource.Condition_STATE_FALSE, + Reason: pbcatalog.Health_HEALTH_MAINTENANCE.String(), + Message: WorkloadUnhealthyMessage, + } + + ConditionNodeAndWorkloadPassing = &pbresource.Condition{ + Type: StatusConditionHealthy, + State: pbresource.Condition_STATE_TRUE, + Reason: pbcatalog.Health_HEALTH_PASSING.String(), + Message: NodeAndWorkloadHealthyMessage, + } + + ConditionNodeAndWorkloadWarning = &pbresource.Condition{ + Type: StatusConditionHealthy, + State: pbresource.Condition_STATE_FALSE, + Reason: pbcatalog.Health_HEALTH_WARNING.String(), + Message: NodeAndWorkloadUnhealthyMessage, + } + + ConditionNodeAndWorkloadCritical = &pbresource.Condition{ + Type: StatusConditionHealthy, + State: pbresource.Condition_STATE_FALSE, + Reason: pbcatalog.Health_HEALTH_CRITICAL.String(), + Message: NodeAndWorkloadUnhealthyMessage, + } + + ConditionNodeAndWorkloadMaintenance = &pbresource.Condition{ + Type: StatusConditionHealthy, + State: pbresource.Condition_STATE_FALSE, + Reason: pbcatalog.Health_HEALTH_MAINTENANCE.String(), + Message: NodeAndWorkloadUnhealthyMessage, + } + + ConditionNodeWarning = &pbresource.Condition{ + Type: StatusConditionHealthy, + State: pbresource.Condition_STATE_FALSE, + Reason: pbcatalog.Health_HEALTH_WARNING.String(), + Message: nodehealth.NodeUnhealthyMessage, + } + + ConditionNodeCritical = &pbresource.Condition{ + Type: StatusConditionHealthy, + State: pbresource.Condition_STATE_FALSE, + Reason: pbcatalog.Health_HEALTH_CRITICAL.String(), + Message: nodehealth.NodeUnhealthyMessage, + } + + ConditionNodeMaintenance = &pbresource.Condition{ + Type: StatusConditionHealthy, + State: pbresource.Condition_STATE_FALSE, + Reason: pbcatalog.Health_HEALTH_MAINTENANCE.String(), + Message: nodehealth.NodeUnhealthyMessage, + } + + // WorkloadConditions is a map of the workloadhealth to the status condition + // used to represent that health. + WorkloadConditions = map[pbcatalog.Health]*pbresource.Condition{ + pbcatalog.Health_HEALTH_PASSING: ConditionWorkloadPassing, + pbcatalog.Health_HEALTH_WARNING: ConditionWorkloadWarning, + pbcatalog.Health_HEALTH_CRITICAL: ConditionWorkloadCritical, + pbcatalog.Health_HEALTH_MAINTENANCE: ConditionWorkloadMaintenance, + } + + // NodeAndWorkloadConditions is a map whose ultimate values are the status conditions + // used to represent the combined health of a workload and its associated node. + // The outer map's keys are the workloads health and the inner maps keys are the nodes + // health + NodeAndWorkloadConditions = map[pbcatalog.Health]map[pbcatalog.Health]*pbresource.Condition{ + pbcatalog.Health_HEALTH_PASSING: { + pbcatalog.Health_HEALTH_PASSING: ConditionNodeAndWorkloadPassing, + pbcatalog.Health_HEALTH_WARNING: ConditionNodeWarning, + pbcatalog.Health_HEALTH_CRITICAL: ConditionNodeCritical, + pbcatalog.Health_HEALTH_MAINTENANCE: ConditionNodeMaintenance, + }, + pbcatalog.Health_HEALTH_WARNING: { + pbcatalog.Health_HEALTH_PASSING: ConditionWorkloadWarning, + pbcatalog.Health_HEALTH_WARNING: ConditionNodeAndWorkloadWarning, + pbcatalog.Health_HEALTH_CRITICAL: ConditionNodeAndWorkloadCritical, + pbcatalog.Health_HEALTH_MAINTENANCE: ConditionNodeAndWorkloadMaintenance, + }, + pbcatalog.Health_HEALTH_CRITICAL: { + pbcatalog.Health_HEALTH_PASSING: ConditionWorkloadCritical, + pbcatalog.Health_HEALTH_WARNING: ConditionNodeAndWorkloadCritical, + pbcatalog.Health_HEALTH_CRITICAL: ConditionNodeAndWorkloadCritical, + pbcatalog.Health_HEALTH_MAINTENANCE: ConditionNodeAndWorkloadMaintenance, + }, + pbcatalog.Health_HEALTH_MAINTENANCE: { + pbcatalog.Health_HEALTH_PASSING: ConditionWorkloadMaintenance, + pbcatalog.Health_HEALTH_WARNING: ConditionNodeAndWorkloadMaintenance, + pbcatalog.Health_HEALTH_CRITICAL: ConditionNodeAndWorkloadMaintenance, + pbcatalog.Health_HEALTH_MAINTENANCE: ConditionNodeAndWorkloadMaintenance, + }, + } +) diff --git a/internal/catalog/internal/mappers/selectiontracker/selection_tracker.go b/internal/catalog/internal/mappers/selectiontracker/selection_tracker.go new file mode 100644 index 0000000000..3bf229bff6 --- /dev/null +++ b/internal/catalog/internal/mappers/selectiontracker/selection_tracker.go @@ -0,0 +1,163 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package selectiontracker + +import ( + "context" + "sync" + + "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/internal/radix" + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/lib/stringslice" + pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +type WorkloadSelectionTracker struct { + lock sync.Mutex + prefixes *radix.Tree[[]controller.Request] + exact *radix.Tree[[]controller.Request] + + // workloadSelectors contains a map keyed on resource names with values + // being the selector that resource is currently associated with. This map + // is kept mainly to make tracking removal operations more efficient. + // Generally any operation that could take advantage of knowing where + // in the trees the resource id is referenced can use this to prevent + // needing to search the whole tree. + workloadSelectors map[string]*pbcatalog.WorkloadSelector +} + +func New() *WorkloadSelectionTracker { + return &WorkloadSelectionTracker{ + prefixes: radix.New[[]controller.Request](), + exact: radix.New[[]controller.Request](), + workloadSelectors: make(map[string]*pbcatalog.WorkloadSelector), + } +} + +// MapWorkload will return a slice of controller.Requests with 1 resource for +// each resource that selects the specified Workload resource. +func (t *WorkloadSelectionTracker) MapWorkload(_ context.Context, _ controller.Runtime, res *pbresource.Resource) ([]controller.Request, error) { + t.lock.Lock() + defer t.lock.Unlock() + + var reqs []controller.Request + + // gather the list of all resources that select the specified workload using a prefix match + t.prefixes.WalkPath(res.Id.Name, func(path string, requests []controller.Request) bool { + reqs = append(reqs, requests...) + return false + }) + + // gather the list of all resources that select the specified workload using an exact match + exactReqs, _ := t.exact.Get(res.Id.Name) + + // return the combined list of all resources that select the specified workload + return append(reqs, exactReqs...), nil +} + +// TrackIDForSelector will associate workloads matching the specified workload +// selector with the given resource id. +func (t *WorkloadSelectionTracker) TrackIDForSelector(id *pbresource.ID, selector *pbcatalog.WorkloadSelector) { + t.lock.Lock() + defer t.lock.Unlock() + + if previousSelector, found := t.workloadSelectors[id.Name]; found { + if stringslice.Equal(previousSelector.Names, selector.Names) && + stringslice.Equal(previousSelector.Prefixes, selector.Prefixes) { + // the selector is unchanged so do nothing + return + } + + // Potentially we could detect differences and do more minimal work. However + // users are not expected to alter workload selectors often and therefore + // not optimizing this further is probably fine. Therefore we are going + // to wipe all tracking of the id and reinsert things. + t.untrackID(id) + } + + // loop over all the exact matching rules and associate those workload names + // with the given resource id + for _, name := range selector.GetNames() { + // lookup any resource id associations for the given workload name + leaf, _ := t.exact.Get(name) + + // append the ID to the existing request list + t.exact.Insert(name, append(leaf, controller.Request{ID: id})) + } + + // loop over all the prefix matching rules and associate those prefixes + // with the given resource id. + for _, prefix := range selector.GetPrefixes() { + // lookup any resource id associations for the given workload name prefix + leaf, _ := t.prefixes.Get(prefix) + + // append the new resource ID to the existing request list + t.prefixes.Insert(prefix, append(leaf, controller.Request{ID: id})) + } + + t.workloadSelectors[id.Name] = selector +} + +// UntrackID causes the tracker to stop tracking the given resource ID +func (t *WorkloadSelectionTracker) UntrackID(id *pbresource.ID) { + t.lock.Lock() + defer t.lock.Unlock() + t.untrackID(id) +} + +// untrackID should be called to stop tracking a resource ID. +// This method assumes the lock is already held. Besides modifying +// the prefix & name trees to not reference this ID, it will also +// delete any corresponding entry within the workloadSelectors map +func (t *WorkloadSelectionTracker) untrackID(id *pbresource.ID) { + selector, found := t.workloadSelectors[id.Name] + if !found { + return + } + + removeIDFromTreeAtPaths(t.exact, id, selector.Names) + removeIDFromTreeAtPaths(t.prefixes, id, selector.Prefixes) + + // If we don't do this deletion then reinsertion of the id for + // tracking in the future could prevent selection criteria from + // being properly inserted into the radix trees. + delete(t.workloadSelectors, id.Name) +} + +// removeIDFromTree will remove the given resource ID from all leaf nodes in the radix tree. +func removeIDFromTreeAtPaths(t *radix.Tree[[]controller.Request], id *pbresource.ID, paths []string) { + for _, path := range paths { + requests, _ := t.Get(path) + + foundIdx := -1 + for idx, req := range requests { + if resource.EqualID(req.ID, id) { + foundIdx = idx + break + } + } + + if foundIdx != -1 { + l := len(requests) + + if l == 1 { + requests = nil + } else if foundIdx == l-1 { + requests = requests[:foundIdx] + } else if foundIdx == 0 { + requests = requests[1:] + } else { + requests = append(requests[:foundIdx], requests[foundIdx+1:]...) + } + + if len(requests) > 1 { + t.Insert(path, requests) + } else { + t.Delete(path) + } + } + } +} diff --git a/internal/catalog/internal/mappers/selectiontracker/selection_tracker_test.go b/internal/catalog/internal/mappers/selectiontracker/selection_tracker_test.go new file mode 100644 index 0000000000..75fa0967c9 --- /dev/null +++ b/internal/catalog/internal/mappers/selectiontracker/selection_tracker_test.go @@ -0,0 +1,275 @@ +package selectiontracker + +import ( + "context" + "testing" + + "github.com/hashicorp/consul/internal/catalog/internal/types" + "github.com/hashicorp/consul/internal/controller" + "github.com/hashicorp/consul/internal/radix" + rtest "github.com/hashicorp/consul/internal/resource/resourcetest" + pbcatalog "github.com/hashicorp/consul/proto-public/pbcatalog/v1alpha1" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/proto/private/prototest" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" +) + +var ( + workloadData = &pbcatalog.Workload{ + Addresses: []*pbcatalog.WorkloadAddress{ + { + Host: "198.18.0.1", + }, + }, + Ports: map[string]*pbcatalog.WorkloadPort{ + "http": { + Port: 8080, + Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, + }, + }, + } +) + +func TestRemoveIDFromTreeAtPaths(t *testing.T) { + tree := radix.New[[]controller.Request]() + + toRemove := rtest.Resource(types.ServiceEndpointsType, "blah").ID() + other1 := rtest.Resource(types.ServiceEndpointsType, "other1").ID() + other2 := rtest.Resource(types.ServiceEndpointsType, "other1").ID() + + // we are trying to create a tree such that removal of the toRemove id causes a + // few things to happen. + // + // * All the slice modification conditions are executed + // - removal from beginning of the list + // - removal from the end of the list + // - removal of only element in the list + // - removal from middle of the list + // * Paths without matching ids are ignored + + notMatching := []controller.Request{ + {ID: other1}, + {ID: other2}, + } + + matchAtBeginning := []controller.Request{ + {ID: toRemove}, + {ID: other1}, + {ID: other2}, + } + + matchAtEnd := []controller.Request{ + {ID: other1}, + {ID: other2}, + {ID: toRemove}, + } + + matchInMiddle := []controller.Request{ + {ID: other1}, + {ID: toRemove}, + {ID: other2}, + } + + matchOnly := []controller.Request{ + {ID: toRemove}, + } + + tree.Insert("no-match", notMatching) + tree.Insert("match-beginning", matchAtBeginning) + tree.Insert("match-end", matchAtEnd) + tree.Insert("match-middle", matchInMiddle) + tree.Insert("match-only", matchOnly) + + removeIDFromTreeAtPaths(tree, toRemove, []string{ + "no-match", + "match-beginning", + "match-end", + "match-middle", + "match-only", + }) + + reqs, found := tree.Get("no-match") + require.True(t, found) + require.Equal(t, notMatching, reqs) + + reqs, found = tree.Get("match-beginning") + require.True(t, found) + require.Equal(t, notMatching, reqs) + + reqs, found = tree.Get("match-end") + require.True(t, found) + require.Equal(t, notMatching, reqs) + + reqs, found = tree.Get("match-middle") + require.True(t, found) + require.Equal(t, notMatching, reqs) + + // The last tracked request should cause removal from the tree + _, found = tree.Get("match-only") + require.False(t, found) +} + +type selectionTrackerSuite struct { + suite.Suite + + rt controller.Runtime + tracker *WorkloadSelectionTracker + + workloadAPI1 *pbresource.Resource + workloadWeb1 *pbresource.Resource + endpointsFoo *pbresource.ID + endpointsBar *pbresource.ID +} + +func (suite *selectionTrackerSuite) SetupTest() { + suite.tracker = New() + + suite.workloadAPI1 = rtest.Resource(types.WorkloadType, "api-1").WithData(suite.T(), workloadData).Build() + suite.workloadWeb1 = rtest.Resource(types.WorkloadType, "web-1").WithData(suite.T(), workloadData).Build() + suite.endpointsFoo = rtest.Resource(types.ServiceEndpointsType, "foo").ID() + suite.endpointsBar = rtest.Resource(types.ServiceEndpointsType, "bar").ID() +} + +func (suite *selectionTrackerSuite) requireMappedIDs(workload *pbresource.Resource, ids ...*pbresource.ID) { + suite.T().Helper() + + reqs, err := suite.tracker.MapWorkload(context.Background(), suite.rt, workload) + require.NoError(suite.T(), err) + require.Len(suite.T(), reqs, len(ids)) + for _, id := range ids { + prototest.AssertContainsElement(suite.T(), reqs, controller.Request{ID: id}) + } +} + +func (suite *selectionTrackerSuite) TestMapWorkload_Empty() { + // If we aren't tracking anything than the default mapping behavior + // should be to return an empty list of requests. + suite.requireMappedIDs(suite.workloadAPI1) +} + +func (suite *selectionTrackerSuite) TestUntrackID_Empty() { + // this test has no assertions but mainly is here to prove that things + // dont explode if this is attempted. + suite.tracker.UntrackID(suite.endpointsFoo) +} + +func (suite *selectionTrackerSuite) TestTrackAndMap_SingleResource_MultipleWorkloadMappings() { + // This test aims to prove that tracking a resources workload selector and + // then mapping a workload back to that resource works as expected when the + // result set is a single resource. This test will ensure that both prefix + // and exact match criteria are handle correctly and that one resource + // can be mapped from multiple distinct workloads. + + // associate the foo endpoints with some workloads + suite.tracker.TrackIDForSelector(suite.endpointsFoo, &pbcatalog.WorkloadSelector{ + Names: []string{"bar", "api", "web-1"}, + Prefixes: []string{"api-"}, + }) + + // Ensure that mappings tracked by prefix work. + suite.requireMappedIDs(suite.workloadAPI1, suite.endpointsFoo) + + // Ensure that mappings tracked by exact match work. + suite.requireMappedIDs(suite.workloadWeb1, suite.endpointsFoo) +} + +func (suite *selectionTrackerSuite) TestTrackAndMap_MultiResource_SingleWorkloadMapping() { + // This test aims to prove that multiple resources selecting of a workload + // will result in multiple requests when mapping that workload. + + // associate the foo endpoints with some workloads + suite.tracker.TrackIDForSelector(suite.endpointsFoo, &pbcatalog.WorkloadSelector{ + Prefixes: []string{"api-"}, + }) + + // associate the bar endpoints with some workloads + suite.tracker.TrackIDForSelector(suite.endpointsBar, &pbcatalog.WorkloadSelector{ + Names: []string{"api-1"}, + }) + + // now the mapping should return both endpoints resource ids + suite.requireMappedIDs(suite.workloadAPI1, suite.endpointsFoo, suite.endpointsBar) +} + +func (suite *selectionTrackerSuite) TestDuplicateTracking() { + // This test aims to prove that tracking some ID multiple times doesn't + // result in multiple requests for the same ID + + // associate the foo endpoints with some workloads 3 times without changing + // the selection criteria. The second two times should be no-ops + suite.tracker.TrackIDForSelector(suite.endpointsFoo, &pbcatalog.WorkloadSelector{ + Prefixes: []string{"api-"}, + }) + + suite.tracker.TrackIDForSelector(suite.endpointsFoo, &pbcatalog.WorkloadSelector{ + Prefixes: []string{"api-"}, + }) + + suite.tracker.TrackIDForSelector(suite.endpointsFoo, &pbcatalog.WorkloadSelector{ + Prefixes: []string{"api-"}, + }) + + // regardless of the number of times tracked we should only see a single request + suite.requireMappedIDs(suite.workloadAPI1, suite.endpointsFoo) +} + +func (suite *selectionTrackerSuite) TestModifyTracking() { + // This test aims to prove that modifying selection criteria for a resource + // works as expected. Adding new criteria results in all being tracked. + // Removal of some criteria does't result in removal of all etc. More or + // less we want to ensure that updating selection criteria leaves the + // tracker in a consistent/expected state. + + // track the web-1 workload + suite.tracker.TrackIDForSelector(suite.endpointsFoo, &pbcatalog.WorkloadSelector{ + Names: []string{"web-1"}, + }) + + // ensure that api-1 isn't mapped but web-1 is + suite.requireMappedIDs(suite.workloadAPI1) + suite.requireMappedIDs(suite.workloadWeb1, suite.endpointsFoo) + + // now also track the api- prefix + suite.tracker.TrackIDForSelector(suite.endpointsFoo, &pbcatalog.WorkloadSelector{ + Names: []string{"web-1"}, + Prefixes: []string{"api-"}, + }) + + // ensure that both workloads are mapped appropriately + suite.requireMappedIDs(suite.workloadAPI1, suite.endpointsFoo) + suite.requireMappedIDs(suite.workloadWeb1, suite.endpointsFoo) + + // now remove the web tracking + suite.tracker.TrackIDForSelector(suite.endpointsFoo, &pbcatalog.WorkloadSelector{ + Prefixes: []string{"api-"}, + }) + + // ensure that only api-1 is mapped + suite.requireMappedIDs(suite.workloadAPI1, suite.endpointsFoo) + suite.requireMappedIDs(suite.workloadWeb1) +} + +func (suite *selectionTrackerSuite) TestRemove() { + // This test aims to prove that removal of a resource from tracking + // actually prevents subsequent mapping calls from returning the + // workload. + + // track the web-1 workload + suite.tracker.TrackIDForSelector(suite.endpointsFoo, &pbcatalog.WorkloadSelector{ + Names: []string{"web-1"}, + }) + + // ensure that api-1 isn't mapped but web-1 is + suite.requireMappedIDs(suite.workloadWeb1, suite.endpointsFoo) + + // untrack the resource + suite.tracker.UntrackID(suite.endpointsFoo) + + // ensure that we no longer map the previous workload to the resource + suite.requireMappedIDs(suite.workloadWeb1) +} + +func TestWorkloadSelectionSuite(t *testing.T) { + suite.Run(t, new(selectionTrackerSuite)) +} diff --git a/internal/catalog/internal/types/errors.go b/internal/catalog/internal/types/errors.go index 39a7131ae0..6f0b44c1b3 100644 --- a/internal/catalog/internal/types/errors.go +++ b/internal/catalog/internal/types/errors.go @@ -60,3 +60,12 @@ type errTooMuchMesh struct { func (err errTooMuchMesh) Error() string { return fmt.Sprintf("protocol \"mesh\" was specified in more than 1 port: %+v", err.Ports) } + +type errInvalidEndpointsOwnerName struct { + Name string + OwnerName string +} + +func (err errInvalidEndpointsOwnerName) Error() string { + return fmt.Sprintf("invalid owner name %q. ServiceEndpoints objects must be owned by a Service with the same name: %q", err.OwnerName, err.Name) +} diff --git a/internal/catalog/internal/types/errors_test.go b/internal/catalog/internal/types/errors_test.go index d8249549d5..7a81577273 100644 --- a/internal/catalog/internal/types/errors_test.go +++ b/internal/catalog/internal/types/errors_test.go @@ -52,6 +52,10 @@ func TestErrorStrings(t *testing.T) { "errTooMuchMesh": errTooMuchMesh{ Ports: []string{"http", "grpc"}, }, + "errInvalidEndpointsOwnerName": errInvalidEndpointsOwnerName{ + Name: "foo", + OwnerName: "bar", + }, "errNotDNSLabel": errNotDNSLabel, "errNotIPAddress": errNotIPAddress, "errUnixSocketMultiport": errUnixSocketMultiport, diff --git a/internal/catalog/internal/types/health_status.go b/internal/catalog/internal/types/health_status.go index 0dc73f6320..5e5a659475 100644 --- a/internal/catalog/internal/types/health_status.go +++ b/internal/catalog/internal/types/health_status.go @@ -73,7 +73,7 @@ func ValidateHealthStatus(res *pbresource.Resource) error { Wrapped: resource.ErrMissing, }) } else if !resource.EqualType(res.Owner.Type, WorkloadType) && !resource.EqualType(res.Owner.Type, NodeType) { - err = multierror.Append(err, resource.ErrOwnerInvalid{ResourceType: res.Id.Type, OwnerType: res.Owner.Type}) + err = multierror.Append(err, resource.ErrOwnerTypeInvalid{ResourceType: res.Id.Type, OwnerType: res.Owner.Type}) } return err diff --git a/internal/catalog/internal/types/health_status_test.go b/internal/catalog/internal/types/health_status_test.go index 5fa9eaa5af..be9d30d501 100644 --- a/internal/catalog/internal/types/health_status_test.go +++ b/internal/catalog/internal/types/health_status_test.go @@ -203,11 +203,11 @@ func TestValidateHealthStatus_InvalidOwner(t *testing.T) { res := createHealthStatusResource(t, data, tcase.owner) err := ValidateHealthStatus(res) require.Error(t, err) - expected := resource.ErrOwnerInvalid{ + expected := resource.ErrOwnerTypeInvalid{ ResourceType: HealthStatusType, OwnerType: tcase.owner.Type, } - var actual resource.ErrOwnerInvalid + var actual resource.ErrOwnerTypeInvalid require.ErrorAs(t, err, &actual) require.Equal(t, expected, actual) }) diff --git a/internal/catalog/internal/types/service.go b/internal/catalog/internal/types/service.go index f4da3cd8e4..27e13530e5 100644 --- a/internal/catalog/internal/types/service.go +++ b/internal/catalog/internal/types/service.go @@ -71,7 +71,7 @@ func ValidateService(res *pbresource.Resource) error { }, }, }) - } else { + } else if port.VirtualPort != 0 { usedVirtualPorts[port.VirtualPort] = idx } diff --git a/internal/catalog/internal/types/service_endpoints.go b/internal/catalog/internal/types/service_endpoints.go index 9a2ce37230..8c3d1cf109 100644 --- a/internal/catalog/internal/types/service_endpoints.go +++ b/internal/catalog/internal/types/service_endpoints.go @@ -30,10 +30,48 @@ func RegisterServiceEndpoints(r resource.Registry) { r.Register(resource.Registration{ Type: ServiceEndpointsV1Alpha1Type, Proto: &pbcatalog.ServiceEndpoints{}, - Validate: nil, + Validate: ValidateServiceEndpoints, + Mutate: MutateServiceEndpoints, }) } +func MutateServiceEndpoints(res *pbresource.Resource) error { + if res.Owner == nil { + res.Owner = &pbresource.ID{ + Type: ServiceV1Alpha1Type, + Tenancy: res.Id.Tenancy, + Name: res.Id.Name, + } + } + + var err error + if !resource.EqualType(res.Owner.Type, ServiceV1Alpha1Type) { + err = multierror.Append(err, resource.ErrOwnerTypeInvalid{ + ResourceType: ServiceEndpointsV1Alpha1Type, + OwnerType: res.Owner.Type, + }) + } + + if !resource.EqualTenancy(res.Owner.Tenancy, res.Id.Tenancy) { + err = multierror.Append(err, resource.ErrOwnerTenantInvalid{ + ResourceTenancy: res.Id.Tenancy, + OwnerTenancy: res.Owner.Tenancy, + }) + } + + if res.Owner.Name != res.Id.Name { + err = multierror.Append(err, resource.ErrInvalidField{ + Name: "name", + Wrapped: errInvalidEndpointsOwnerName{ + Name: res.Id.Name, + OwnerName: res.Owner.Name, + }, + }) + } + + return err +} + func ValidateServiceEndpoints(res *pbresource.Resource) error { var svcEndpoints pbcatalog.ServiceEndpoints diff --git a/internal/catalog/internal/types/service_test.go b/internal/catalog/internal/types/service_test.go index 241a49939d..1a0a035d91 100644 --- a/internal/catalog/internal/types/service_test.go +++ b/internal/catalog/internal/types/service_test.go @@ -45,6 +45,18 @@ func TestValidateService_Ok(t *testing.T) { VirtualPort: 42, Protocol: pbcatalog.Protocol_PROTOCOL_HTTP, }, + { + TargetPort: "other", + // leaving VirtualPort unset to verify that seeing + // a zero virtual port multiple times is fine. + Protocol: pbcatalog.Protocol_PROTOCOL_HTTP2, + }, + { + TargetPort: "other2", + // leaving VirtualPort unset to verify that seeing + // a zero virtual port multiple times is fine. + Protocol: pbcatalog.Protocol_PROTOCOL_GRPC, + }, }, VirtualIps: []string{"198.18.0.1"}, } diff --git a/internal/catalog/internal/types/testdata/errInvalidEndpointsOwnerName.golden b/internal/catalog/internal/types/testdata/errInvalidEndpointsOwnerName.golden new file mode 100644 index 0000000000..38fc896f57 --- /dev/null +++ b/internal/catalog/internal/types/testdata/errInvalidEndpointsOwnerName.golden @@ -0,0 +1 @@ +invalid owner name "bar". ServiceEndpoints objects must be owned by a Service with the same name: "foo" \ No newline at end of file diff --git a/internal/controller/api.go b/internal/controller/api.go index c2cc0925da..8f5d873368 100644 --- a/internal/controller/api.go +++ b/internal/controller/api.go @@ -152,46 +152,6 @@ type Reconciler interface { Reconcile(ctx context.Context, rt Runtime, req Request) error } -// DependencyMapper is called when a dependency watched via WithWatch is changed -// to determine which of the controller's managed resources need to be reconciled. -type DependencyMapper func( - ctx context.Context, - rt Runtime, - res *pbresource.Resource, -) ([]Request, error) - -// MapOwner implements a DependencyMapper that returns the updated resource's owner. -func MapOwner(_ context.Context, _ Runtime, res *pbresource.Resource) ([]Request, error) { - var reqs []Request - if res.Owner != nil { - reqs = append(reqs, Request{ID: res.Owner}) - } - return reqs, nil -} - -func MapOwnerFiltered(filter *pbresource.Type) DependencyMapper { - return func(_ context.Context, _ Runtime, res *pbresource.Resource) ([]Request, error) { - if res.Owner == nil { - return nil, nil - } - - ownerType := res.Owner.GetType() - if ownerType.Group != filter.Group { - return nil, nil - } - - if ownerType.GroupVersion != filter.GroupVersion { - return nil, nil - } - - if ownerType.Kind != filter.Kind { - return nil, nil - } - - return []Request{{ID: res.Owner}}, nil - } -} - // Placement determines where and how many replicas of the controller will run. type Placement int diff --git a/internal/controller/api_test.go b/internal/controller/api_test.go index 51bb62843f..2006664b20 100644 --- a/internal/controller/api_test.go +++ b/internal/controller/api_test.go @@ -9,7 +9,6 @@ import ( "testing" "time" - "github.com/google/go-cmp/cmp/cmpopts" "github.com/stretchr/testify/require" svctest "github.com/hashicorp/consul/agent/grpc-external/services/resource/testing" @@ -267,76 +266,3 @@ func testContext(t *testing.T) context.Context { return ctx } - -func resourceID(group string, version string, kind string, name string) *pbresource.ID { - return &pbresource.ID{ - Type: &pbresource.Type{ - Group: group, - GroupVersion: version, - Kind: kind, - }, - Tenancy: &pbresource.Tenancy{ - Partition: "default", - Namespace: "default", - PeerName: "local", - }, - Name: name, - } -} - -func TestMapOwnerFiltered(t *testing.T) { - mapper := controller.MapOwnerFiltered(&pbresource.Type{ - Group: "foo", - GroupVersion: "v1", - Kind: "bar", - }) - - type testCase struct { - owner *pbresource.ID - matches bool - } - - cases := map[string]testCase{ - "nil-owner": { - owner: nil, - matches: false, - }, - "group-mismatch": { - owner: resourceID("other", "v1", "bar", "irrelevant"), - matches: false, - }, - "group-version-mismatch": { - owner: resourceID("foo", "v2", "bar", "irrelevant"), - matches: false, - }, - "kind-mismatch": { - owner: resourceID("foo", "v1", "baz", "irrelevant"), - matches: false, - }, - "match": { - owner: resourceID("foo", "v1", "bar", "irrelevant"), - matches: true, - }, - } - - for name, tcase := range cases { - t.Run(name, func(t *testing.T) { - // the runtime is not used by the mapper so its fine to pass an empty struct - req, err := mapper(context.Background(), controller.Runtime{}, &pbresource.Resource{ - Id: resourceID("foo", "v1", "other", "x"), - Owner: tcase.owner, - }) - - // The mapper has no error paths at present - require.NoError(t, err) - - if tcase.matches { - require.NotNil(t, req) - require.Len(t, req, 1) - prototest.AssertDeepEqual(t, req[0].ID, tcase.owner, cmpopts.EquateEmpty()) - } else { - require.Nil(t, req) - } - }) - } -} diff --git a/internal/controller/dependency_mappers.go b/internal/controller/dependency_mappers.go new file mode 100644 index 0000000000..c054c4369e --- /dev/null +++ b/internal/controller/dependency_mappers.go @@ -0,0 +1,58 @@ +package controller + +import ( + "context" + + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/proto-public/pbresource" +) + +// DependencyMapper is called when a dependency watched via WithWatch is changed +// to determine which of the controller's managed resources need to be reconciled. +type DependencyMapper func( + ctx context.Context, + rt Runtime, + res *pbresource.Resource, +) ([]Request, error) + +// MapOwner implements a DependencyMapper that returns the updated resource's owner. +func MapOwner(_ context.Context, _ Runtime, res *pbresource.Resource) ([]Request, error) { + var reqs []Request + if res.Owner != nil { + reqs = append(reqs, Request{ID: res.Owner}) + } + return reqs, nil +} + +// MapOwnerFiltered creates a DependencyMapper that returns owner IDs as Requests +// if the type of the owner ID matches the given filter type. +func MapOwnerFiltered(filter *pbresource.Type) DependencyMapper { + return func(_ context.Context, _ Runtime, res *pbresource.Resource) ([]Request, error) { + if res.Owner == nil { + return nil, nil + } + + if !resource.EqualType(res.Owner.GetType(), filter) { + return nil, nil + } + + return []Request{{ID: res.Owner}}, nil + } +} + +// ReplaceType creates a DependencyMapper that returns request IDs with the same +// name and tenancy as the original resource but with the type replaced with +// the type specified as this functions parameter. +func ReplaceType(desiredType *pbresource.Type) DependencyMapper { + return func(_ context.Context, _ Runtime, res *pbresource.Resource) ([]Request, error) { + return []Request{ + { + ID: &pbresource.ID{ + Type: desiredType, + Tenancy: res.Id.Tenancy, + Name: res.Id.Name, + }, + }, + }, nil + } +} diff --git a/internal/controller/dependency_mappers_test.go b/internal/controller/dependency_mappers_test.go new file mode 100644 index 0000000000..b5300bfb9a --- /dev/null +++ b/internal/controller/dependency_mappers_test.go @@ -0,0 +1,137 @@ +package controller + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/proto/private/prototest" + "github.com/stretchr/testify/require" +) + +func resourceID(group string, version string, kind string, name string) *pbresource.ID { + return &pbresource.ID{ + Type: &pbresource.Type{ + Group: group, + GroupVersion: version, + Kind: kind, + }, + Tenancy: &pbresource.Tenancy{ + Partition: "default", + Namespace: "default", + PeerName: "local", + }, + Name: name, + } +} + +func TestMapOwner(t *testing.T) { + owner := resourceID("foo", "v99", "bar", "object") + + res := &pbresource.Resource{ + Id: resourceID("something", "v1", "else", "x"), + Owner: owner, + } + + reqs, err := MapOwner(context.Background(), Runtime{}, res) + require.NoError(t, err) + require.Len(t, reqs, 1) + prototest.AssertDeepEqual(t, owner, reqs[0].ID) +} + +func TestMapOwnerFiltered(t *testing.T) { + mapper := MapOwnerFiltered(&pbresource.Type{ + Group: "foo", + GroupVersion: "v1", + Kind: "bar", + }) + + type testCase struct { + owner *pbresource.ID + matches bool + } + + cases := map[string]testCase{ + "nil-owner": { + owner: nil, + matches: false, + }, + "group-mismatch": { + owner: resourceID("other", "v1", "bar", "irrelevant"), + matches: false, + }, + "group-version-mismatch": { + owner: resourceID("foo", "v2", "bar", "irrelevant"), + matches: false, + }, + "kind-mismatch": { + owner: resourceID("foo", "v1", "baz", "irrelevant"), + matches: false, + }, + "match": { + owner: resourceID("foo", "v1", "bar", "irrelevant"), + matches: true, + }, + } + + for name, tcase := range cases { + t.Run(name, func(t *testing.T) { + // the runtime is not used by the mapper so its fine to pass an empty struct + req, err := mapper(context.Background(), Runtime{}, &pbresource.Resource{ + Id: resourceID("foo", "v1", "other", "x"), + Owner: tcase.owner, + }) + + // The mapper has no error paths at present + require.NoError(t, err) + + if tcase.matches { + require.NotNil(t, req) + require.Len(t, req, 1) + prototest.AssertDeepEqual(t, req[0].ID, tcase.owner, cmpopts.EquateEmpty()) + } else { + require.Nil(t, req) + } + }) + } +} + +func TestReplaceType(t *testing.T) { + rtype := &pbresource.Type{ + Group: "foo", + GroupVersion: "v1", + Kind: "bar", + } + + tenant := &pbresource.Tenancy{ + Partition: "not", + Namespace: "using", + PeerName: "the-defaults", + } + + in := &pbresource.Resource{ + Id: &pbresource.ID{ + Type: &pbresource.Type{ + Group: "other", + GroupVersion: "v2", + Kind: "baz", + }, + Tenancy: tenant, + Name: "arr-matey", + }, + } + + mapper := ReplaceType(rtype) + + reqs, err := mapper(nil, Runtime{}, in) + require.NoError(t, err) + require.Len(t, reqs, 1) + + expected := &pbresource.ID{ + Type: rtype, + Tenancy: tenant, + Name: "arr-matey", + } + prototest.AssertDeepEqual(t, expected, reqs[0].ID) +} diff --git a/internal/radix/doc.go b/internal/radix/doc.go new file mode 100644 index 0000000000..47e8961d0d --- /dev/null +++ b/internal/radix/doc.go @@ -0,0 +1,4 @@ +// This packages contents were originally copied from github.com/armon/go-radix. +// After the intial copy all the data structures were made to use Go 1.18 generics +// instead of relying on the use of interface{} or the any type. +package radix diff --git a/internal/radix/radix.go b/internal/radix/radix.go new file mode 100644 index 0000000000..0f1d8d772a --- /dev/null +++ b/internal/radix/radix.go @@ -0,0 +1,568 @@ +package radix + +import ( + "sort" + "strings" +) + +// WalkFn is used when walking the tree. Takes a +// key and value, returning if iteration should +// be terminated. +type WalkFn[T any] func(s string, v T) bool + +// leafNode is used to represent a value +type leafNode[T any] struct { + key string + val T +} + +// edge is used to represent an edge node +type edge[T any] struct { + label byte + node *node[T] +} + +type node[T any] struct { + // leaf is used to store possible leaf + leaf *leafNode[T] + + // prefix is the common prefix we ignore + prefix string + + // Edges should be stored in-order for iteration. + // We avoid a fully materialized slice to save memory, + // since in most cases we expect to be sparse + edges edges[T] +} + +func (n *node[T]) isLeaf() bool { + return n.leaf != nil +} + +func (n *node[T]) addEdge(e edge[T]) { + num := len(n.edges) + idx := sort.Search(num, func(i int) bool { + return n.edges[i].label >= e.label + }) + + n.edges = append(n.edges, edge[T]{}) + copy(n.edges[idx+1:], n.edges[idx:]) + n.edges[idx] = e +} + +func (n *node[T]) updateEdge(label byte, node *node[T]) { + num := len(n.edges) + idx := sort.Search(num, func(i int) bool { + return n.edges[i].label >= label + }) + if idx < num && n.edges[idx].label == label { + n.edges[idx].node = node + return + } + panic("replacing missing edge") +} + +func (n *node[T]) getEdge(label byte) *node[T] { + num := len(n.edges) + idx := sort.Search(num, func(i int) bool { + return n.edges[i].label >= label + }) + if idx < num && n.edges[idx].label == label { + return n.edges[idx].node + } + return nil +} + +func (n *node[T]) delEdge(label byte) { + num := len(n.edges) + idx := sort.Search(num, func(i int) bool { + return n.edges[i].label >= label + }) + if idx < num && n.edges[idx].label == label { + copy(n.edges[idx:], n.edges[idx+1:]) + n.edges[len(n.edges)-1] = edge[T]{} + n.edges = n.edges[:len(n.edges)-1] + } +} + +type edges[T any] []edge[T] + +func (e edges[T]) Len() int { + return len(e) +} + +func (e edges[T]) Less(i, j int) bool { + return e[i].label < e[j].label +} + +func (e edges[T]) Swap(i, j int) { + e[i], e[j] = e[j], e[i] +} + +func (e edges[T]) Sort() { + sort.Sort(e) +} + +// Tree implements a radix tree. This can be treated as a +// Dictionary abstract data type. The main advantage over +// a standard hash map is prefix-based lookups and +// ordered iteration, +type Tree[T any] struct { + root *node[T] + size int +} + +// New returns an empty Tree +func New[T any]() *Tree[T] { + return NewFromMap[T](nil) +} + +// NewFromMap returns a new tree containing the keys +// from an existing map +func NewFromMap[T any](m map[string]T) *Tree[T] { + t := &Tree[T]{root: &node[T]{}} + for k, v := range m { + t.Insert(k, v) + } + return t +} + +// Len is used to return the number of elements in the tree +func (t *Tree[T]) Len() int { + return t.size +} + +// longestPrefix finds the length of the shared prefix +// of two strings +func longestPrefix(k1, k2 string) int { + max := len(k1) + if l := len(k2); l < max { + max = l + } + var i int + for i = 0; i < max; i++ { + if k1[i] != k2[i] { + break + } + } + return i +} + +// Insert is used to add a newentry or update +// an existing entry. Returns true if an existing record is updated. +func (t *Tree[T]) Insert(s string, v T) (T, bool) { + var zeroVal T + var parent *node[T] + n := t.root + search := s + for { + // Handle key exhaution + if len(search) == 0 { + if n.isLeaf() { + old := n.leaf.val + n.leaf.val = v + return old, true + } + + n.leaf = &leafNode[T]{ + key: s, + val: v, + } + t.size++ + return zeroVal, false + } + + // Look for the edge + parent = n + n = n.getEdge(search[0]) + + // No edge, create one + if n == nil { + e := edge[T]{ + label: search[0], + node: &node[T]{ + leaf: &leafNode[T]{ + key: s, + val: v, + }, + prefix: search, + }, + } + parent.addEdge(e) + t.size++ + return zeroVal, false + } + + // Determine longest prefix of the search key on match + commonPrefix := longestPrefix(search, n.prefix) + if commonPrefix == len(n.prefix) { + search = search[commonPrefix:] + continue + } + + // Split the node + t.size++ + child := &node[T]{ + prefix: search[:commonPrefix], + } + parent.updateEdge(search[0], child) + + // Restore the existing node + child.addEdge(edge[T]{ + label: n.prefix[commonPrefix], + node: n, + }) + n.prefix = n.prefix[commonPrefix:] + + // Create a new leaf node + leaf := &leafNode[T]{ + key: s, + val: v, + } + + // If the new key is a subset, add to this node + search = search[commonPrefix:] + if len(search) == 0 { + child.leaf = leaf + return zeroVal, false + } + + // Create a new edge for the node + child.addEdge(edge[T]{ + label: search[0], + node: &node[T]{ + leaf: leaf, + prefix: search, + }, + }) + return zeroVal, false + } +} + +// Delete is used to delete a key, returning the previous +// value and if it was deleted +func (t *Tree[T]) Delete(s string) (T, bool) { + var zeroVal T + + var parent *node[T] + var label byte + n := t.root + search := s + for { + // Check for key exhaution + if len(search) == 0 { + if !n.isLeaf() { + break + } + goto DELETE + } + + // Look for an edge + parent = n + label = search[0] + n = n.getEdge(label) + if n == nil { + break + } + + // Consume the search prefix + if strings.HasPrefix(search, n.prefix) { + search = search[len(n.prefix):] + } else { + break + } + } + return zeroVal, false + +DELETE: + // Delete the leaf + leaf := n.leaf + n.leaf = nil + t.size-- + + // Check if we should delete this node from the parent + if parent != nil && len(n.edges) == 0 { + parent.delEdge(label) + } + + // Check if we should merge this node + if n != t.root && len(n.edges) == 1 { + n.mergeChild() + } + + // Check if we should merge the parent's other child + if parent != nil && parent != t.root && len(parent.edges) == 1 && !parent.isLeaf() { + parent.mergeChild() + } + + return leaf.val, true +} + +// DeletePrefix is used to delete the subtree under a prefix +// Returns how many nodes were deleted +// Use this to delete large subtrees efficiently +func (t *Tree[T]) DeletePrefix(s string) int { + return t.deletePrefix(nil, t.root, s) +} + +// delete does a recursive deletion +func (t *Tree[T]) deletePrefix(parent, n *node[T], prefix string) int { + // Check for key exhaustion + if len(prefix) == 0 { + // Remove the leaf node + subTreeSize := 0 + //recursively walk from all edges of the node to be deleted + recursiveWalk(n, func(s string, v T) bool { + subTreeSize++ + return false + }) + if n.isLeaf() { + n.leaf = nil + } + n.edges = nil // deletes the entire subtree + + // Check if we should merge the parent's other child + if parent != nil && parent != t.root && len(parent.edges) == 1 && !parent.isLeaf() { + parent.mergeChild() + } + t.size -= subTreeSize + return subTreeSize + } + + // Look for an edge + label := prefix[0] + child := n.getEdge(label) + if child == nil || (!strings.HasPrefix(child.prefix, prefix) && !strings.HasPrefix(prefix, child.prefix)) { + return 0 + } + + // Consume the search prefix + if len(child.prefix) > len(prefix) { + prefix = prefix[len(prefix):] + } else { + prefix = prefix[len(child.prefix):] + } + return t.deletePrefix(n, child, prefix) +} + +func (n *node[T]) mergeChild() { + e := n.edges[0] + child := e.node + n.prefix = n.prefix + child.prefix + n.leaf = child.leaf + n.edges = child.edges +} + +// Get is used to lookup a specific key, returning +// the value and if it was found +func (t *Tree[T]) Get(s string) (T, bool) { + var zeroVal T + n := t.root + search := s + for { + // Check for key exhaution + if len(search) == 0 { + if n.isLeaf() { + return n.leaf.val, true + } + break + } + + // Look for an edge + n = n.getEdge(search[0]) + if n == nil { + break + } + + // Consume the search prefix + if strings.HasPrefix(search, n.prefix) { + search = search[len(n.prefix):] + } else { + break + } + } + return zeroVal, false +} + +// LongestPrefix is like Get, but instead of an +// exact match, it will return the longest prefix match. +func (t *Tree[T]) LongestPrefix(s string) (string, T, bool) { + var zeroVal T + var last *leafNode[T] + n := t.root + search := s + for { + // Look for a leaf node + if n.isLeaf() { + last = n.leaf + } + + // Check for key exhaution + if len(search) == 0 { + break + } + + // Look for an edge + n = n.getEdge(search[0]) + if n == nil { + break + } + + // Consume the search prefix + if strings.HasPrefix(search, n.prefix) { + search = search[len(n.prefix):] + } else { + break + } + } + if last != nil { + return last.key, last.val, true + } + return "", zeroVal, false +} + +// Minimum is used to return the minimum value in the tree +func (t *Tree[T]) Minimum() (string, T, bool) { + var zeroVal T + n := t.root + for { + if n.isLeaf() { + return n.leaf.key, n.leaf.val, true + } + if len(n.edges) > 0 { + n = n.edges[0].node + } else { + break + } + } + return "", zeroVal, false +} + +// Maximum is used to return the maximum value in the tree +func (t *Tree[T]) Maximum() (string, T, bool) { + var zeroVal T + n := t.root + for { + if num := len(n.edges); num > 0 { + n = n.edges[num-1].node + continue + } + if n.isLeaf() { + return n.leaf.key, n.leaf.val, true + } + break + } + return "", zeroVal, false +} + +// Walk is used to walk the tree +func (t *Tree[T]) Walk(fn WalkFn[T]) { + recursiveWalk(t.root, fn) +} + +// WalkPrefix is used to walk the tree under a prefix +func (t *Tree[T]) WalkPrefix(prefix string, fn WalkFn[T]) { + n := t.root + search := prefix + for { + // Check for key exhaustion + if len(search) == 0 { + recursiveWalk(n, fn) + return + } + + // Look for an edge + n = n.getEdge(search[0]) + if n == nil { + return + } + + // Consume the search prefix + if strings.HasPrefix(search, n.prefix) { + search = search[len(n.prefix):] + continue + } + if strings.HasPrefix(n.prefix, search) { + // Child may be under our search prefix + recursiveWalk(n, fn) + } + return + } +} + +// WalkPath is used to walk the tree, but only visiting nodes +// from the root down to a given leaf. Where WalkPrefix walks +// all the entries *under* the given prefix, this walks the +// entries *above* the given prefix. +func (t *Tree[T]) WalkPath(path string, fn WalkFn[T]) { + n := t.root + search := path + for { + // Visit the leaf values if any + if n.leaf != nil && fn(n.leaf.key, n.leaf.val) { + return + } + + // Check for key exhaution + if len(search) == 0 { + return + } + + // Look for an edge + n = n.getEdge(search[0]) + if n == nil { + return + } + + // Consume the search prefix + if strings.HasPrefix(search, n.prefix) { + search = search[len(n.prefix):] + } else { + break + } + } +} + +// recursiveWalk is used to do a pre-order walk of a node +// recursively. Returns true if the walk should be aborted +func recursiveWalk[T any](n *node[T], fn WalkFn[T]) bool { + // Visit the leaf values if any + if n.leaf != nil && fn(n.leaf.key, n.leaf.val) { + return true + } + + // Recurse on the children + i := 0 + k := len(n.edges) // keeps track of number of edges in previous iteration + for i < k { + e := n.edges[i] + if recursiveWalk(e.node, fn) { + return true + } + // It is a possibility that the WalkFn modified the node we are + // iterating on. If there are no more edges, mergeChild happened, + // so the last edge became the current node n, on which we'll + // iterate one last time. + if len(n.edges) == 0 { + return recursiveWalk(n, fn) + } + // If there are now less edges than in the previous iteration, + // then do not increment the loop index, since the current index + // points to a new edge. Otherwise, get to the next index. + if len(n.edges) >= k { + i++ + } + k = len(n.edges) + } + return false +} + +// ToMap is used to walk the tree and convert it into a map +func (t *Tree[T]) ToMap() map[string]T { + out := make(map[string]T, t.size) + t.Walk(func(k string, v T) bool { + out[k] = v + return false + }) + return out +} diff --git a/internal/radix/radix_test.go b/internal/radix/radix_test.go new file mode 100644 index 0000000000..9f616b73f4 --- /dev/null +++ b/internal/radix/radix_test.go @@ -0,0 +1,408 @@ +package radix + +import ( + crand "crypto/rand" + "fmt" + "reflect" + "sort" + "strconv" + "testing" +) + +func TestRadix(t *testing.T) { + var min, max string + inp := make(map[string]interface{}) + for i := 0; i < 1000; i++ { + gen := generateUUID() + inp[gen] = i + if gen < min || i == 0 { + min = gen + } + if gen > max || i == 0 { + max = gen + } + } + + r := NewFromMap(inp) + if r.Len() != len(inp) { + t.Fatalf("bad length: %v %v", r.Len(), len(inp)) + } + + r.Walk(func(k string, v interface{}) bool { + println(k) + return false + }) + + for k, v := range inp { + out, ok := r.Get(k) + if !ok { + t.Fatalf("missing key: %v", k) + } + if out != v { + t.Fatalf("value mis-match: %v %v", out, v) + } + } + + // Check min and max + outMin, _, _ := r.Minimum() + if outMin != min { + t.Fatalf("bad minimum: %v %v", outMin, min) + } + outMax, _, _ := r.Maximum() + if outMax != max { + t.Fatalf("bad maximum: %v %v", outMax, max) + } + + for k, v := range inp { + out, ok := r.Delete(k) + if !ok { + t.Fatalf("missing key: %v", k) + } + if out != v { + t.Fatalf("value mis-match: %v %v", out, v) + } + } + if r.Len() != 0 { + t.Fatalf("bad length: %v", r.Len()) + } +} + +func TestRoot(t *testing.T) { + r := New[bool]() + _, ok := r.Delete("") + if ok { + t.Fatalf("bad") + } + _, ok = r.Insert("", true) + if ok { + t.Fatalf("bad") + } + val, ok := r.Get("") + if !ok || val != true { + t.Fatalf("bad: %v", val) + } + val, ok = r.Delete("") + if !ok || val != true { + t.Fatalf("bad: %v", val) + } +} + +func TestDelete(t *testing.T) { + + r := New[bool]() + + s := []string{"", "A", "AB"} + + for _, ss := range s { + r.Insert(ss, true) + } + + for _, ss := range s { + _, ok := r.Delete(ss) + if !ok { + t.Fatalf("bad %q", ss) + } + } +} + +func TestDeletePrefix(t *testing.T) { + type exp struct { + inp []string + prefix string + out []string + numDeleted int + } + + cases := []exp{ + {[]string{"", "A", "AB", "ABC", "R", "S"}, "A", []string{"", "R", "S"}, 3}, + {[]string{"", "A", "AB", "ABC", "R", "S"}, "ABC", []string{"", "A", "AB", "R", "S"}, 1}, + {[]string{"", "A", "AB", "ABC", "R", "S"}, "", []string{}, 6}, + {[]string{"", "A", "AB", "ABC", "R", "S"}, "S", []string{"", "A", "AB", "ABC", "R"}, 1}, + {[]string{"", "A", "AB", "ABC", "R", "S"}, "SS", []string{"", "A", "AB", "ABC", "R", "S"}, 0}, + } + + for _, test := range cases { + r := New[bool]() + for _, ss := range test.inp { + r.Insert(ss, true) + } + + deleted := r.DeletePrefix(test.prefix) + if deleted != test.numDeleted { + t.Fatalf("Bad delete, expected %v to be deleted but got %v", test.numDeleted, deleted) + } + + out := []string{} + fn := func(s string, v bool) bool { + out = append(out, s) + return false + } + r.Walk(fn) + + if !reflect.DeepEqual(out, test.out) { + t.Fatalf("mis-match: %v %v", out, test.out) + } + } +} + +func TestLongestPrefix(t *testing.T) { + r := New[interface{}]() + + keys := []string{ + "", + "foo", + "foobar", + "foobarbaz", + "foobarbazzip", + "foozip", + } + for _, k := range keys { + r.Insert(k, nil) + } + if r.Len() != len(keys) { + t.Fatalf("bad len: %v %v", r.Len(), len(keys)) + } + + type exp struct { + inp string + out string + } + cases := []exp{ + {"a", ""}, + {"abc", ""}, + {"fo", ""}, + {"foo", "foo"}, + {"foob", "foo"}, + {"foobar", "foobar"}, + {"foobarba", "foobar"}, + {"foobarbaz", "foobarbaz"}, + {"foobarbazzi", "foobarbaz"}, + {"foobarbazzip", "foobarbazzip"}, + {"foozi", "foo"}, + {"foozip", "foozip"}, + {"foozipzap", "foozip"}, + } + for _, test := range cases { + m, _, ok := r.LongestPrefix(test.inp) + if !ok { + t.Fatalf("no match: %v", test) + } + if m != test.out { + t.Fatalf("mis-match: %v %v", m, test) + } + } +} + +func TestWalkPrefix(t *testing.T) { + r := New[interface{}]() + + keys := []string{ + "foobar", + "foo/bar/baz", + "foo/baz/bar", + "foo/zip/zap", + "zipzap", + } + for _, k := range keys { + r.Insert(k, nil) + } + if r.Len() != len(keys) { + t.Fatalf("bad len: %v %v", r.Len(), len(keys)) + } + + type exp struct { + inp string + out []string + } + cases := []exp{ + { + "f", + []string{"foobar", "foo/bar/baz", "foo/baz/bar", "foo/zip/zap"}, + }, + { + "foo", + []string{"foobar", "foo/bar/baz", "foo/baz/bar", "foo/zip/zap"}, + }, + { + "foob", + []string{"foobar"}, + }, + { + "foo/", + []string{"foo/bar/baz", "foo/baz/bar", "foo/zip/zap"}, + }, + { + "foo/b", + []string{"foo/bar/baz", "foo/baz/bar"}, + }, + { + "foo/ba", + []string{"foo/bar/baz", "foo/baz/bar"}, + }, + { + "foo/bar", + []string{"foo/bar/baz"}, + }, + { + "foo/bar/baz", + []string{"foo/bar/baz"}, + }, + { + "foo/bar/bazoo", + []string{}, + }, + { + "z", + []string{"zipzap"}, + }, + } + + for _, test := range cases { + out := []string{} + fn := func(s string, v interface{}) bool { + out = append(out, s) + return false + } + r.WalkPrefix(test.inp, fn) + sort.Strings(out) + sort.Strings(test.out) + if !reflect.DeepEqual(out, test.out) { + t.Fatalf("mis-match: %v %v", out, test.out) + } + } +} + +func TestWalkPath(t *testing.T) { + r := New[interface{}]() + + keys := []string{ + "foo", + "foo/bar", + "foo/bar/baz", + "foo/baz/bar", + "foo/zip/zap", + "zipzap", + } + for _, k := range keys { + r.Insert(k, nil) + } + if r.Len() != len(keys) { + t.Fatalf("bad len: %v %v", r.Len(), len(keys)) + } + + type exp struct { + inp string + out []string + } + cases := []exp{ + { + "f", + []string{}, + }, + { + "foo", + []string{"foo"}, + }, + { + "foo/", + []string{"foo"}, + }, + { + "foo/ba", + []string{"foo"}, + }, + { + "foo/bar", + []string{"foo", "foo/bar"}, + }, + { + "foo/bar/baz", + []string{"foo", "foo/bar", "foo/bar/baz"}, + }, + { + "foo/bar/bazoo", + []string{"foo", "foo/bar", "foo/bar/baz"}, + }, + { + "z", + []string{}, + }, + } + + for _, test := range cases { + out := []string{} + fn := func(s string, v interface{}) bool { + out = append(out, s) + return false + } + r.WalkPath(test.inp, fn) + sort.Strings(out) + sort.Strings(test.out) + if !reflect.DeepEqual(out, test.out) { + t.Fatalf("mis-match: %v %v", out, test.out) + } + } +} + +func TestWalkDelete(t *testing.T) { + r := New[interface{}]() + r.Insert("init0/0", nil) + r.Insert("init0/1", nil) + r.Insert("init0/2", nil) + r.Insert("init0/3", nil) + r.Insert("init1/0", nil) + r.Insert("init1/1", nil) + r.Insert("init1/2", nil) + r.Insert("init1/3", nil) + r.Insert("init2", nil) + + deleteFn := func(s string, v interface{}) bool { + r.Delete(s) + return false + } + + r.WalkPrefix("init1", deleteFn) + + for _, s := range []string{"init0/0", "init0/1", "init0/2", "init0/3", "init2"} { + if _, ok := r.Get(s); !ok { + t.Fatalf("expecting to still find %q", s) + } + } + if n := r.Len(); n != 5 { + t.Fatalf("expected to find exactly 5 nodes, instead found %d: %v", n, r.ToMap()) + } + + r.Walk(deleteFn) + if n := r.Len(); n != 0 { + t.Fatalf("expected to find exactly 0 nodes, instead found %d: %v", n, r.ToMap()) + } +} + +// generateUUID is used to generate a random UUID +func generateUUID() string { + buf := make([]byte, 16) + if _, err := crand.Read(buf); err != nil { + panic(fmt.Errorf("failed to read random bytes: %v", err)) + } + + return fmt.Sprintf("%08x-%04x-%04x-%04x-%12x", + buf[0:4], + buf[4:6], + buf[6:8], + buf[8:10], + buf[10:16]) +} + +func BenchmarkInsert(b *testing.B) { + r := New[bool]() + for i := 0; i < 10000; i++ { + r.Insert(fmt.Sprintf("init%d", i), true) + } + b.ResetTimer() + for n := 0; n < b.N; n++ { + _, updated := r.Insert(strconv.Itoa(n), true) + if updated { + b.Fatal("bad") + } + } +} diff --git a/internal/resource/errors.go b/internal/resource/errors.go index 55fbb95d6a..c258f9ad35 100644 --- a/internal/resource/errors.go +++ b/internal/resource/errors.go @@ -92,12 +92,12 @@ func (err ErrInvalidMapKey) Unwrap() error { return err.Wrapped } -type ErrOwnerInvalid struct { +type ErrOwnerTypeInvalid struct { ResourceType *pbresource.Type OwnerType *pbresource.Type } -func (err ErrOwnerInvalid) Error() string { +func (err ErrOwnerTypeInvalid) Error() string { return fmt.Sprintf( "resources of type %s cannot be owned by resources with type %s", ToGVK(err.ResourceType), @@ -105,6 +105,20 @@ func (err ErrOwnerInvalid) Error() string { ) } +type ErrOwnerTenantInvalid struct { + ResourceType *pbresource.Type + ResourceTenancy *pbresource.Tenancy + OwnerTenancy *pbresource.Tenancy +} + +func (err ErrOwnerTenantInvalid) Error() string { + return fmt.Sprintf( + "resource in partition %s, namespace %s and peer %s cannot be owned by a resource in partition %s, namespace %s and peer %s", + err.ResourceTenancy.Partition, err.ResourceTenancy.Namespace, err.ResourceTenancy.PeerName, + err.OwnerTenancy.Partition, err.OwnerTenancy.Namespace, err.OwnerTenancy.PeerName, + ) +} + type ErrInvalidReferenceType struct { AllowedType *pbresource.Type } diff --git a/internal/resource/errors_test.go b/internal/resource/errors_test.go index 5705457d59..990a916077 100644 --- a/internal/resource/errors_test.go +++ b/internal/resource/errors_test.go @@ -63,7 +63,7 @@ func TestErrorStrings(t *testing.T) { Key: "http", Wrapped: fakeWrappedErr, }, - "ErrOwnerInvalid": ErrOwnerInvalid{ + "ErrOwnerInvalid": ErrOwnerTypeInvalid{ ResourceType: &pbresource.Type{Group: "foo", GroupVersion: "v1", Kind: "bar"}, OwnerType: &pbresource.Type{Group: "other", GroupVersion: "v2", Kind: "something"}, }, diff --git a/internal/resource/resourcetest/builder.go b/internal/resource/resourcetest/builder.go index 46039e209a..7355f38824 100644 --- a/internal/resource/resourcetest/builder.go +++ b/internal/resource/resourcetest/builder.go @@ -2,7 +2,6 @@ package resourcetest import ( "context" - "testing" "github.com/hashicorp/consul/proto-public/pbresource" "github.com/oklog/ulid/v2" @@ -38,13 +37,24 @@ func Resource(rtype *pbresource.Type, name string) *resourceBuilder { } } -func (b *resourceBuilder) WithData(t *testing.T, data protoreflect.ProtoMessage) *resourceBuilder { +func (b *resourceBuilder) WithData(t T, data protoreflect.ProtoMessage) *resourceBuilder { + t.Helper() + anyData, err := anypb.New(data) require.NoError(t, err) b.resource.Data = anyData return b } +func (b *resourceBuilder) WithMeta(key string, value string) *resourceBuilder { + if b.resource.Metadata == nil { + b.resource.Metadata = make(map[string]string) + } + + b.resource.Metadata[key] = value + return b +} + func (b *resourceBuilder) WithOwner(id *pbresource.ID) *resourceBuilder { b.resource.Owner = id return b @@ -91,7 +101,13 @@ func (b *resourceBuilder) Build() *pbresource.Resource { return res } -func (b *resourceBuilder) Write(t *testing.T, client pbresource.ResourceServiceClient) *pbresource.Resource { +func (b *resourceBuilder) ID() *pbresource.ID { + return b.resource.Id +} + +func (b *resourceBuilder) Write(t T, client pbresource.ResourceServiceClient) *pbresource.Resource { + t.Helper() + res := b.resource rsp, err := client.Write(context.Background(), &pbresource.WriteRequest{ @@ -101,7 +117,9 @@ func (b *resourceBuilder) Write(t *testing.T, client pbresource.ResourceServiceC require.NoError(t, err) if !b.dontCleanup { - t.Cleanup(func() { + cleaner, ok := t.(CleanupT) + require.True(t, ok, "T does not implement a Cleanup method and cannot be used with automatic resource cleanup") + cleaner.Cleanup(func() { _, err := client.Delete(context.Background(), &pbresource.DeleteRequest{ Id: rsp.Resource.Id, }) diff --git a/internal/resource/resourcetest/client.go b/internal/resource/resourcetest/client.go new file mode 100644 index 0000000000..dab5b03c3a --- /dev/null +++ b/internal/resource/resourcetest/client.go @@ -0,0 +1,218 @@ +package resourcetest + +import ( + "context" + "math/rand" + "time" + + "github.com/hashicorp/consul/internal/resource" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/sdk/testutil/retry" + "github.com/stretchr/testify/require" + "golang.org/x/exp/slices" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +type Client struct { + pbresource.ResourceServiceClient + + timeout time.Duration + wait time.Duration +} + +func NewClient(client pbresource.ResourceServiceClient) *Client { + return &Client{ + ResourceServiceClient: client, + timeout: 7 * time.Second, + wait: 25 * time.Millisecond, + } +} + +func (client *Client) SetRetryerConfig(timeout time.Duration, wait time.Duration) { + client.timeout = timeout + client.wait = wait +} + +func (client *Client) retry(t T, fn func(r *retry.R)) { + retryer := &retry.Timer{Timeout: client.timeout, Wait: client.wait} + retry.RunWith(retryer, t, fn) +} + +func (client *Client) PublishResources(t T, resources []*pbresource.Resource) { + // Randomize the order of insertion. Generally insertion order shouldn't matter as the + // controllers should eventually converge on the desired state. The exception to this + // is that you cannot insert resources with owner refs before the resource they are + // owned by or insert a resource into a non-default tenant before that tenant exists. + rand.Shuffle(len(resources), func(i, j int) { + temp := resources[i] + resources[i] = resources[j] + resources[j] = temp + }) + + // This slice will be used to track the resources actually published each round. When + // a resource with an owner ID is encountered we will not attempt to write but defer it + // to the next round of publishing + var written []*pbresource.ID + + for len(resources) > 0 { + var left []*pbresource.Resource + published := 0 + for _, res := range resources { + + // check that any owner references would be satisfied + if res.Owner != nil { + found := slices.ContainsFunc(written, func(id *pbresource.ID) bool { + return resource.EqualID(res.Owner, id) + }) + + // the owner hasn't yet been published then we cannot publish this resource + if !found { + left = append(left, res) + continue + } + } + + t.Logf("Writing resource %s with type %s", res.Id.Name, resource.ToGVK(res.Id.Type)) + _, err := client.Write(context.Background(), &pbresource.WriteRequest{ + Resource: res, + }) + require.NoError(t, err) + + // track the number o + published += 1 + written = append(written, res.Id) + } + + // the next round only has this subset of resources to attempt writing + resources = left + + // if we didn't publish any resources this round then nothing would + // enable us to do so by iterating again so we break to prevent infinite + // loooping. + if published == 0 { + break + } + } + + require.Empty(t, resources, "Could not publish all resources - some resources have invalid owner references") +} + +func (client *Client) RequireResourceNotFound(t T, id *pbresource.ID) { + t.Helper() + + rsp, err := client.Read(context.Background(), &pbresource.ReadRequest{Id: id}) + require.Error(t, err) + require.Equal(t, codes.NotFound, status.Code(err)) + require.Nil(t, rsp) +} + +func (client *Client) RequireResourceExists(t T, id *pbresource.ID) *pbresource.Resource { + t.Helper() + + rsp, err := client.Read(context.Background(), &pbresource.ReadRequest{Id: id}) + require.NoError(t, err, "error reading %s with type %s", id.Name, resource.ToGVK(id.Type)) + require.NotNil(t, rsp) + return rsp.Resource +} + +func (client *Client) RequireVersionUnchanged(t T, id *pbresource.ID, version string) *pbresource.Resource { + t.Helper() + + res := client.RequireResourceExists(t, id) + RequireVersionUnchanged(t, res, version) + return res +} + +func (client *Client) RequireVersionChanged(t T, id *pbresource.ID, version string) *pbresource.Resource { + t.Helper() + + res := client.RequireResourceExists(t, id) + RequireVersionChanged(t, res, version) + return res +} + +func (client *Client) RequireStatusCondition(t T, id *pbresource.ID, statusKey string, condition *pbresource.Condition) *pbresource.Resource { + t.Helper() + + res := client.RequireResourceExists(t, id) + RequireStatusCondition(t, res, statusKey, condition) + return res +} + +func (client *Client) RequireStatusConditionForCurrentGen(t T, id *pbresource.ID, statusKey string, condition *pbresource.Condition) *pbresource.Resource { + t.Helper() + + res := client.RequireResourceExists(t, id) + RequireStatusConditionForCurrentGen(t, res, statusKey, condition) + return res +} + +func (client *Client) RequireResourceMeta(t T, id *pbresource.ID, key string, value string) *pbresource.Resource { + t.Helper() + + res := client.RequireResourceExists(t, id) + RequireResourceMeta(t, res, key, value) + return res +} + +func (client *Client) RequireReconciledCurrentGen(t T, id *pbresource.ID, statusKey string) *pbresource.Resource { + t.Helper() + + res := client.RequireResourceExists(t, id) + RequireReconciledCurrentGen(t, res, statusKey) + return res +} + +func (client *Client) WaitForReconciliation(t T, id *pbresource.ID, statusKey string) *pbresource.Resource { + t.Helper() + + var res *pbresource.Resource + + client.retry(t, func(r *retry.R) { + res = client.RequireReconciledCurrentGen(r, id, statusKey) + }) + + return res +} + +func (client *Client) WaitForStatusCondition(t T, id *pbresource.ID, statusKey string, condition *pbresource.Condition) *pbresource.Resource { + t.Helper() + + var res *pbresource.Resource + client.retry(t, func(r *retry.R) { + res = client.RequireStatusConditionForCurrentGen(t, id, statusKey, condition) + }) + + return res +} + +func (client *Client) WaitForNewVersion(t T, id *pbresource.ID, version string) *pbresource.Resource { + t.Helper() + + var res *pbresource.Resource + client.retry(t, func(r *retry.R) { + res = client.RequireVersionChanged(r, id, version) + }) + return res +} + +func (client *Client) WaitForResourceState(t T, id *pbresource.ID, verify func(T, *pbresource.Resource)) *pbresource.Resource { + t.Helper() + + var res *pbresource.Resource + client.retry(t, func(r *retry.R) { + res = client.RequireResourceExists(r, id) + verify(r, res) + }) + + return res +} + +// ResolveResourceID will read the specified resource and returns its full ID. +// This is mainly useful to get the ID with the Uid filled out. +func (client *Client) ResolveResourceID(t T, id *pbresource.ID) *pbresource.ID { + t.Helper() + + return client.RequireResourceExists(t, id).Id +} diff --git a/internal/resource/resourcetest/fs.go b/internal/resource/resourcetest/fs.go new file mode 100644 index 0000000000..e7a1417a59 --- /dev/null +++ b/internal/resource/resourcetest/fs.go @@ -0,0 +1,40 @@ +package resourcetest + +import ( + "fmt" + "io/fs" + + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/encoding/protojson" +) + +// ParseResourcesFromFilesystem will walk the filesystem at the given path +// and parse all files as protobuf/JSON resources. +func ParseResourcesFromFilesystem(t T, files fs.FS, path string) []*pbresource.Resource { + t.Helper() + + var resources []*pbresource.Resource + err := fs.WalkDir(files, path, func(fpath string, dent fs.DirEntry, _ error) error { + if dent.IsDir() { + return nil + } + + data, err := fs.ReadFile(files, fpath) + if err != nil { + return err + } + + var res pbresource.Resource + err = protojson.Unmarshal(data, &res) + if err != nil { + return fmt.Errorf("error decoding data from %s: %w", fpath, err) + } + + resources = append(resources, &res) + return nil + }) + + require.NoError(t, err) + return resources +} diff --git a/internal/resource/resourcetest/require.go b/internal/resource/resourcetest/require.go new file mode 100644 index 0000000000..fff8cb2aeb --- /dev/null +++ b/internal/resource/resourcetest/require.go @@ -0,0 +1,62 @@ +package resourcetest + +import ( + "github.com/google/go-cmp/cmp" + "github.com/hashicorp/consul/proto-public/pbresource" + "github.com/hashicorp/consul/proto/private/prototest" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/testing/protocmp" +) + +func RequireVersionUnchanged(t T, res *pbresource.Resource, version string) { + t.Helper() + require.Equal(t, version, res.Version) +} + +func RequireVersionChanged(t T, res *pbresource.Resource, version string) { + t.Helper() + require.NotEqual(t, version, res.Version) +} + +func RequireStatusCondition(t T, res *pbresource.Resource, statusKey string, condition *pbresource.Condition) { + t.Helper() + require.NotNil(t, res.Status) + status, found := res.Status[statusKey] + require.True(t, found) + prototest.AssertContainsElement(t, status.Conditions, condition) +} + +func RequireStatusConditionForCurrentGen(t T, res *pbresource.Resource, statusKey string, condition *pbresource.Condition) { + t.Helper() + require.NotNil(t, res.Status) + status, found := res.Status[statusKey] + require.True(t, found) + require.Equal(t, res.Generation, status.ObservedGeneration) + prototest.AssertContainsElement(t, status.Conditions, condition) +} + +func RequireResourceMeta(t T, res *pbresource.Resource, key string, value string) { + t.Helper() + require.NotNil(t, res.Metadata) + require.Contains(t, res.Metadata, key) + require.Equal(t, value, res.Metadata[key]) +} + +func RequireReconciledCurrentGen(t T, res *pbresource.Resource, statusKey string) { + t.Helper() + require.NotNil(t, res.Status) + status, found := res.Status[statusKey] + require.True(t, found) + require.Equal(t, res.Generation, status.ObservedGeneration) +} + +func RequireOwner(t T, res *pbresource.Resource, owner *pbresource.ID, ignoreUid bool) { + t.Helper() + + var opts []cmp.Option + if ignoreUid { + opts = append(opts, protocmp.IgnoreFields(owner, "uid")) + } + + prototest.AssertDeepEqual(t, res.Owner, owner, opts...) +} diff --git a/internal/resource/resourcetest/testing.go b/internal/resource/resourcetest/testing.go new file mode 100644 index 0000000000..d02b70da9d --- /dev/null +++ b/internal/resource/resourcetest/testing.go @@ -0,0 +1,17 @@ +package resourcetest + +// T represents the subset of testing.T methods that will be used +// by the various functionality in this package +type T interface { + Helper() + Log(args ...interface{}) + Logf(format string, args ...interface{}) + Errorf(format string, args ...interface{}) + Fatalf(format string, args ...interface{}) + FailNow() +} + +type CleanupT interface { + T + Cleanup(func()) +} diff --git a/sdk/testutil/retry/retry.go b/sdk/testutil/retry/retry.go index 8817b6e8fb..30045f0c62 100644 --- a/sdk/testutil/retry/retry.go +++ b/sdk/testutil/retry/retry.go @@ -59,6 +59,10 @@ func (r *R) Logf(format string, args ...interface{}) { r.log(fmt.Sprintf(format, args...)) } +func (r *R) Log(args ...interface{}) { + r.log(fmt.Sprintln(args...)) +} + func (r *R) Helper() {} // runFailed is a sentinel value to indicate that the func itself From a35cafa728f8be2450ce785e865e722eaad10062 Mon Sep 17 00:00:00 2001 From: skpratt Date: Wed, 7 Jun 2023 10:57:56 -0500 Subject: [PATCH 36/72] update tests for fips (#17592) --- agent/consul/merge_test.go | 2 ++ .../services/dataplane/get_supported_features_test.go | 3 +++ tlsutil/config_test.go | 2 ++ version/version.go | 4 ++++ 4 files changed, 11 insertions(+) diff --git a/agent/consul/merge_test.go b/agent/consul/merge_test.go index 66992136aa..f5f5c6d88f 100644 --- a/agent/consul/merge_test.go +++ b/agent/consul/merge_test.go @@ -12,6 +12,7 @@ import ( "github.com/hashicorp/consul/sdk/testutil" "github.com/hashicorp/consul/types" + "github.com/hashicorp/consul/version" ) func TestMerge_LAN(t *testing.T) { @@ -282,6 +283,7 @@ func makeTestNode(t *testing.T, tm testMember) *serf.Member { "vsn": "2", "vsn_max": "3", "vsn_min": "2", + "fips": version.GetFIPSInfo(), }, } if tm.partition != "" { diff --git a/agent/grpc-external/services/dataplane/get_supported_features_test.go b/agent/grpc-external/services/dataplane/get_supported_features_test.go index 35079a40a8..329b5df0f6 100644 --- a/agent/grpc-external/services/dataplane/get_supported_features_test.go +++ b/agent/grpc-external/services/dataplane/get_supported_features_test.go @@ -19,6 +19,7 @@ import ( "github.com/hashicorp/consul/agent/grpc-external/testutils" structs "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/proto-public/pbdataplane" + "github.com/hashicorp/consul/version" ) const testACLToken = "acl-token" @@ -50,6 +51,8 @@ func TestSupportedDataplaneFeatures_Success(t *testing.T) { require.True(t, feature.GetSupported()) case pbdataplane.DataplaneFeatures_DATAPLANE_FEATURES_ENVOY_BOOTSTRAP_CONFIGURATION: require.True(t, feature.GetSupported()) + case pbdataplane.DataplaneFeatures_DATAPLANE_FEATURES_FIPS: + require.Equal(t, version.IsFIPS(), feature.GetSupported()) default: require.False(t, feature.GetSupported()) } diff --git a/tlsutil/config_test.go b/tlsutil/config_test.go index 18ba11e38b..30ebd62c20 100644 --- a/tlsutil/config_test.go +++ b/tlsutil/config_test.go @@ -1,5 +1,7 @@ // Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 +//go:build !fips +// +build !fips package tlsutil diff --git a/version/version.go b/version/version.go index bd2cfd57aa..0b81e19d2b 100644 --- a/version/version.go +++ b/version/version.go @@ -52,6 +52,10 @@ func GetHumanVersion() string { version += fmt.Sprintf("-%s", release) } + if IsFIPS() { + version += ".fips1402" + } + if metadata != "" { version += fmt.Sprintf("+%s", metadata) } From 39d4aaf22496ff245a3a4f132b8f485f0f39ba15 Mon Sep 17 00:00:00 2001 From: Dhia Ayachi Date: Wed, 7 Jun 2023 14:50:22 -0400 Subject: [PATCH 37/72] fix rate limiting mapping to be the same between api and struct packages (#17599) --- agent/consul/rate/handler.go | 6 ++-- agent/rpc/middleware/rate_limit_mappings.go | 5 +++ api/config_entry_rate_limit_ip.go | 36 +++++++++++++-------- 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/agent/consul/rate/handler.go b/agent/consul/rate/handler.go index 84faefb6c3..c18ec85edd 100644 --- a/agent/consul/rate/handler.go +++ b/agent/consul/rate/handler.go @@ -119,15 +119,15 @@ const ( OperationCategoryKV OperationCategory = "KV" OperationCategoryPreparedQuery OperationCategory = "PreparedQuery" OperationCategorySession OperationCategory = "Session" - OperationCategoryStatus OperationCategory = "Status" + OperationCategoryStatus OperationCategory = "Status" // not limited OperationCategoryTxn OperationCategory = "Txn" OperationCategoryAutoConfig OperationCategory = "AutoConfig" OperationCategoryFederationState OperationCategory = "FederationState" OperationCategoryInternal OperationCategory = "Internal" - OperationCategoryOperator OperationCategory = "Operator" + OperationCategoryOperator OperationCategory = "Operator" // not limited OperationCategoryPeerStream OperationCategory = "PeerStream" OperationCategoryPeering OperationCategory = "Peering" - OperationCategoryPartition OperationCategory = "Partition" + OperationCategoryPartition OperationCategory = "Tenancy" OperationCategoryDataPlane OperationCategory = "DataPlane" OperationCategoryDNS OperationCategory = "DNS" OperationCategorySubscribe OperationCategory = "Subscribe" diff --git a/agent/rpc/middleware/rate_limit_mappings.go b/agent/rpc/middleware/rate_limit_mappings.go index a31343bb23..0df249c932 100644 --- a/agent/rpc/middleware/rate_limit_mappings.go +++ b/agent/rpc/middleware/rate_limit_mappings.go @@ -144,4 +144,9 @@ var rpcRateLimitSpecs = map[string]rate.OperationSpec{ "Txn.Apply": {Type: rate.OperationTypeWrite, Category: rate.OperationCategoryTxn}, "Txn.Read": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryTxn}, + + "Namespace.Write": {Type: rate.OperationTypeWrite, Category: rate.OperationCategoryPartition}, + "Namespace.Delete": {Type: rate.OperationTypeWrite, Category: rate.OperationCategoryPartition}, + "Namespace.List": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryPartition}, + "Namespace.Read": {Type: rate.OperationTypeRead, Category: rate.OperationCategoryPartition}, } diff --git a/api/config_entry_rate_limit_ip.go b/api/config_entry_rate_limit_ip.go index 1c91b811a9..8df7d4c98e 100644 --- a/api/config_entry_rate_limit_ip.go +++ b/api/config_entry_rate_limit_ip.go @@ -20,19 +20,29 @@ type RateLimitIPConfigEntry struct { WriteRate float64 //limits specific to a type of call - ACL *ReadWriteRatesConfig `json:",omitempty"` - Catalog *ReadWriteRatesConfig `json:",omitempty"` - ConfigEntry *ReadWriteRatesConfig `json:",omitempty"` - ConnectCA *ReadWriteRatesConfig `json:",omitempty"` - Coordinate *ReadWriteRatesConfig `json:",omitempty"` - DiscoveryChain *ReadWriteRatesConfig `json:",omitempty"` - Health *ReadWriteRatesConfig `json:",omitempty"` - Intention *ReadWriteRatesConfig `json:",omitempty"` - KV *ReadWriteRatesConfig `json:",omitempty"` - Tenancy *ReadWriteRatesConfig `json:",omitempty"` - PreparedQuery *ReadWriteRatesConfig `json:",omitempty"` - Session *ReadWriteRatesConfig `json:",omitempty"` - Txn *ReadWriteRatesConfig `json:",omitempty"` + ACL *ReadWriteRatesConfig `json:",omitempty"` // OperationCategoryACL OperationCategory = "ACL" + Catalog *ReadWriteRatesConfig `json:",omitempty"` // OperationCategoryCatalog OperationCategory = "Catalog" + ConfigEntry *ReadWriteRatesConfig `json:",omitempty"` // OperationCategoryConfigEntry OperationCategory = "ConfigEntry" + ConnectCA *ReadWriteRatesConfig `json:",omitempty"` // OperationCategoryConnectCA OperationCategory = "ConnectCA" + Coordinate *ReadWriteRatesConfig `json:",omitempty"` // OperationCategoryCoordinate OperationCategory = "Coordinate" + DiscoveryChain *ReadWriteRatesConfig `json:",omitempty"` // OperationCategoryDiscoveryChain OperationCategory = "DiscoveryChain" + ServerDiscovery *ReadWriteRatesConfig `json:",omitempty"` // OperationCategoryServerDiscovery OperationCategory = "ServerDiscovery" + Health *ReadWriteRatesConfig `json:",omitempty"` // OperationCategoryHealth OperationCategory = "Health" + Intention *ReadWriteRatesConfig `json:",omitempty"` // OperationCategoryIntention OperationCategory = "Intention" + KV *ReadWriteRatesConfig `json:",omitempty"` // OperationCategoryKV OperationCategory = "KV" + Tenancy *ReadWriteRatesConfig `json:",omitempty"` // OperationCategoryPartition OperationCategory = "Tenancy" + PreparedQuery *ReadWriteRatesConfig `json:",omitempty"` // OperationCategoryPreparedQuery OperationCategory = "PreparedQuery" + Session *ReadWriteRatesConfig `json:",omitempty"` // OperationCategorySession OperationCategory = "Session" + Txn *ReadWriteRatesConfig `json:",omitempty"` // OperationCategoryTxn OperationCategory = "Txn" + AutoConfig *ReadWriteRatesConfig `json:",omitempty"` // OperationCategoryAutoConfig OperationCategory = "AutoConfig" + FederationState *ReadWriteRatesConfig `json:",omitempty"` // OperationCategoryFederationState OperationCategory = "FederationState" + Internal *ReadWriteRatesConfig `json:",omitempty"` // OperationCategoryInternal OperationCategory = "Internal" + PeerStream *ReadWriteRatesConfig `json:",omitempty"` // OperationCategoryPeerStream OperationCategory = "PeerStream" + Peering *ReadWriteRatesConfig `json:",omitempty"` // OperationCategoryPeering OperationCategory = "Peering" + DataPlane *ReadWriteRatesConfig `json:",omitempty"` // OperationCategoryDataPlane OperationCategory = "DataPlane" + DNS *ReadWriteRatesConfig `json:",omitempty"` // OperationCategoryDNS OperationCategory = "DNS" + Subscribe *ReadWriteRatesConfig `json:",omitempty"` // OperationCategorySubscribe OperationCategory = "Subscribe" + Resource *ReadWriteRatesConfig `json:",omitempty"` // OperationCategoryResource OperationCategory = "Resource" // Partition is the partition the config entry is associated with. // Partitioning is a Consul Enterprise feature. From 820cdf53daa5eb4ac8cd507ab88ecb0853331022 Mon Sep 17 00:00:00 2001 From: "R.B. Boyer" <4903+rboyer@users.noreply.github.com> Date: Wed, 7 Jun 2023 13:53:27 -0500 Subject: [PATCH 38/72] fix some testing.T retry.R mixups (#17600) Fix some linter warnings before updating the lint-consul-retry code in hashicorp/lint-consul-retry#4 --- agent/agent_endpoint_test.go | 56 +++++++++---------- agent/consul/acl_endpoint_test.go | 4 +- agent/consul/client_test.go | 2 +- .../consul/multilimiter/multilimiter_test.go | 2 +- agent/consul/prepared_query_endpoint_test.go | 15 ++--- agent/dns_test.go | 6 +- .../services/peerstream/stream_test.go | 18 +++--- agent/local/state_test.go | 20 +++---- 8 files changed, 60 insertions(+), 63 deletions(-) diff --git a/agent/agent_endpoint_test.go b/agent/agent_endpoint_test.go index 66b028b7c0..2955871c72 100644 --- a/agent/agent_endpoint_test.go +++ b/agent/agent_endpoint_test.go @@ -1822,7 +1822,7 @@ func TestAgent_ReloadDoesNotTriggerWatch(t *testing.T) { for i := 1; i < 7; i++ { contents, err := os.ReadFile(tmpFile) if err != nil { - t.Fatalf("should be able to read file, but had: %#v", err) + r.Fatalf("should be able to read file, but had: %#v", err) } contentsStr = string(contents) if contentsStr != "" { @@ -1909,14 +1909,14 @@ func TestAgent_ReloadDoesNotTriggerWatch(t *testing.T) { ensureNothingCritical(r, "red-is-dead") if err := a.reloadConfigInternal(cfg2); err != nil { - t.Fatalf("got error %v want nil", err) + r.Fatalf("got error %v want nil", err) } // We check that reload does not go to critical ensureNothingCritical(r, "red-is-dead") ensureNothingCritical(r, "testing-agent-reload-001") - require.NoError(t, a.updateTTLCheck(checkID, api.HealthPassing, "testing-agent-reload-002")) + require.NoError(r, a.updateTTLCheck(checkID, api.HealthPassing, "testing-agent-reload-002")) ensureNothingCritical(r, "red-is-dead") }) @@ -2926,7 +2926,7 @@ func TestAgent_RegisterCheck_ACLDeny(t *testing.T) { req, _ := http.NewRequest("PUT", "/v1/agent/check/register", jsonReader(nodeCheck)) resp := httptest.NewRecorder() a.srv.h.ServeHTTP(resp, req) - require.Equal(t, http.StatusForbidden, resp.Code) + require.Equal(r, http.StatusForbidden, resp.Code) }) }) @@ -2936,7 +2936,7 @@ func TestAgent_RegisterCheck_ACLDeny(t *testing.T) { req.Header.Add("X-Consul-Token", svcToken.SecretID) resp := httptest.NewRecorder() a.srv.h.ServeHTTP(resp, req) - require.Equal(t, http.StatusForbidden, resp.Code) + require.Equal(r, http.StatusForbidden, resp.Code) }) }) @@ -2946,7 +2946,7 @@ func TestAgent_RegisterCheck_ACLDeny(t *testing.T) { req.Header.Add("X-Consul-Token", nodeToken.SecretID) resp := httptest.NewRecorder() a.srv.h.ServeHTTP(resp, req) - require.Equal(t, http.StatusOK, resp.Code) + require.Equal(r, http.StatusOK, resp.Code) }) }) @@ -2955,7 +2955,7 @@ func TestAgent_RegisterCheck_ACLDeny(t *testing.T) { req, _ := http.NewRequest("PUT", "/v1/agent/check/register", jsonReader(svcCheck)) resp := httptest.NewRecorder() a.srv.h.ServeHTTP(resp, req) - require.Equal(t, http.StatusForbidden, resp.Code) + require.Equal(r, http.StatusForbidden, resp.Code) }) }) @@ -2965,7 +2965,7 @@ func TestAgent_RegisterCheck_ACLDeny(t *testing.T) { req.Header.Add("X-Consul-Token", nodeToken.SecretID) resp := httptest.NewRecorder() a.srv.h.ServeHTTP(resp, req) - require.Equal(t, http.StatusForbidden, resp.Code) + require.Equal(r, http.StatusForbidden, resp.Code) }) }) @@ -2975,7 +2975,7 @@ func TestAgent_RegisterCheck_ACLDeny(t *testing.T) { req.Header.Add("X-Consul-Token", svcToken.SecretID) resp := httptest.NewRecorder() a.srv.h.ServeHTTP(resp, req) - require.Equal(t, http.StatusOK, resp.Code) + require.Equal(r, http.StatusOK, resp.Code) }) }) } @@ -5976,17 +5976,17 @@ func TestAgent_Monitor(t *testing.T) { res := httptest.NewRecorder() a.srv.h.ServeHTTP(res, registerReq) if http.StatusOK != res.Code { - t.Fatalf("expected 200 but got %v", res.Code) + r.Fatalf("expected 200 but got %v", res.Code) } // Wait until we have received some type of logging output - require.Eventually(t, func() bool { + require.Eventually(r, func() bool { return len(resp.Body.Bytes()) > 0 }, 3*time.Second, 100*time.Millisecond) cancelFunc() code := <-codeCh - require.Equal(t, http.StatusOK, code) + require.Equal(r, http.StatusOK, code) got := resp.Body.String() // Only check a substring that we are highly confident in finding @@ -6026,11 +6026,11 @@ func TestAgent_Monitor(t *testing.T) { res := httptest.NewRecorder() a.srv.h.ServeHTTP(res, registerReq) if http.StatusOK != res.Code { - t.Fatalf("expected 200 but got %v", res.Code) + r.Fatalf("expected 200 but got %v", res.Code) } // Wait until we have received some type of logging output - require.Eventually(t, func() bool { + require.Eventually(r, func() bool { return len(resp.Body.Bytes()) > 0 }, 3*time.Second, 100*time.Millisecond) cancelFunc() @@ -6063,24 +6063,24 @@ func TestAgent_Monitor(t *testing.T) { res := httptest.NewRecorder() a.srv.h.ServeHTTP(res, registerReq) if http.StatusOK != res.Code { - t.Fatalf("expected 200 but got %v", res.Code) + r.Fatalf("expected 200 but got %v", res.Code) } // Wait until we have received some type of logging output - require.Eventually(t, func() bool { + require.Eventually(r, func() bool { return len(resp.Body.Bytes()) > 0 }, 3*time.Second, 100*time.Millisecond) cancelFunc() code := <-codeCh - require.Equal(t, http.StatusOK, code) + require.Equal(r, http.StatusOK, code) // Each line is output as a separate JSON object, we grab the first and // make sure it can be unmarshalled. firstLine := bytes.Split(resp.Body.Bytes(), []byte("\n"))[0] var output map[string]interface{} if err := json.Unmarshal(firstLine, &output); err != nil { - t.Fatalf("err: %v", err) + r.Fatalf("err: %v", err) } }) }) @@ -6672,7 +6672,7 @@ func TestAgentConnectCARoots_list(t *testing.T) { dec := json.NewDecoder(resp.Body) value := &structs.IndexedCARoots{} - require.NoError(t, dec.Decode(value)) + require.NoError(r, dec.Decode(value)) if ca.ID != value.ActiveRootID { r.Fatalf("%s != %s", ca.ID, value.ActiveRootID) } @@ -7080,7 +7080,7 @@ func TestAgentConnectCALeafCert_goodNotLocal(t *testing.T) { dec := json.NewDecoder(resp.Body) issued2 := &structs.IssuedCert{} - require.NoError(t, dec.Decode(issued2)) + require.NoError(r, dec.Decode(issued2)) if issued.CertPEM == issued2.CertPEM { r.Fatalf("leaf has not updated") } @@ -7092,9 +7092,9 @@ func TestAgentConnectCALeafCert_goodNotLocal(t *testing.T) { } // Verify that the cert is signed by the new CA - requireLeafValidUnderCA(t, issued2, ca) + requireLeafValidUnderCA(r, issued2, ca) - require.NotEqual(t, issued, issued2) + require.NotEqual(r, issued, issued2) }) } } @@ -7471,11 +7471,11 @@ func TestAgentConnectCALeafCert_secondaryDC_good(t *testing.T) { // Try and sign again (note no index/wait arg since cache should update in // background even if we aren't actively blocking) a2.srv.h.ServeHTTP(resp, req) - require.Equal(t, http.StatusOK, resp.Code) + require.Equal(r, http.StatusOK, resp.Code) dec := json.NewDecoder(resp.Body) issued2 := &structs.IssuedCert{} - require.NoError(t, dec.Decode(issued2)) + require.NoError(r, dec.Decode(issued2)) if issued.CertPEM == issued2.CertPEM { r.Fatalf("leaf has not updated") } @@ -7487,9 +7487,9 @@ func TestAgentConnectCALeafCert_secondaryDC_good(t *testing.T) { } // Verify that the cert is signed by the new CA - requireLeafValidUnderCA(t, issued2, dc1_ca2) + requireLeafValidUnderCA(r, issued2, dc1_ca2) - require.NotEqual(t, issued, issued2) + require.NotEqual(r, issued, issued2) }) } @@ -7499,12 +7499,12 @@ func waitForActiveCARoot(t *testing.T, srv *HTTPHandlers, expect *structs.CARoot resp := httptest.NewRecorder() srv.h.ServeHTTP(resp, req) if http.StatusOK != resp.Code { - t.Fatalf("expected 200 but got %v", resp.Code) + r.Fatalf("expected 200 but got %v", resp.Code) } dec := json.NewDecoder(resp.Body) roots := &structs.IndexedCARoots{} - require.NoError(t, dec.Decode(roots)) + require.NoError(r, dec.Decode(roots)) var root *structs.CARoot for _, r := range roots.Roots { diff --git a/agent/consul/acl_endpoint_test.go b/agent/consul/acl_endpoint_test.go index 6f674810b5..7e09880ad3 100644 --- a/agent/consul/acl_endpoint_test.go +++ b/agent/consul/acl_endpoint_test.go @@ -143,7 +143,7 @@ func TestACLEndpoint_ReplicationStatus(t *testing.T) { retry.Run(t, func(r *retry.R) { var status structs.ACLReplicationStatus err := msgpackrpc.CallWithCodec(codec, "ACL.ReplicationStatus", &getR, &status) - require.NoError(t, err) + require.NoError(r, err) require.True(r, status.Enabled) require.True(r, status.Running) @@ -220,7 +220,7 @@ func TestACLEndpoint_TokenRead(t *testing.T) { time.Sleep(200 * time.Millisecond) err := aclEp.TokenRead(&req, &resp) require.Error(r, err) - require.ErrorContains(t, err, "ACL not found") + require.ErrorContains(r, err, "ACL not found") require.Nil(r, resp.Token) }) }) diff --git a/agent/consul/client_test.go b/agent/consul/client_test.go index 3f7542d090..4b8f5c433d 100644 --- a/agent/consul/client_test.go +++ b/agent/consul/client_test.go @@ -179,7 +179,7 @@ func TestClient_LANReap(t *testing.T) { retry.Run(t, func(r *retry.R) { require.Len(r, c1.LANMembersInAgentPartition(), 1) server := c1.router.FindLANServer() - require.Nil(t, server) + require.Nil(r, server) }) } diff --git a/agent/consul/multilimiter/multilimiter_test.go b/agent/consul/multilimiter/multilimiter_test.go index 991cd3b989..b649bdb6c9 100644 --- a/agent/consul/multilimiter/multilimiter_test.go +++ b/agent/consul/multilimiter/multilimiter_test.go @@ -95,7 +95,7 @@ func TestRateLimiterCleanup(t *testing.T) { retry.RunWith(&retry.Timer{Wait: 100 * time.Millisecond, Timeout: 10 * time.Second}, t, func(r *retry.R) { v, ok := limiters.Get(key) require.True(r, ok) - require.NotNil(t, v) + require.NotNil(r, v) }) time.Sleep(c.ReconcileCheckInterval) diff --git a/agent/consul/prepared_query_endpoint_test.go b/agent/consul/prepared_query_endpoint_test.go index 63277adfe2..af1fd65a87 100644 --- a/agent/consul/prepared_query_endpoint_test.go +++ b/agent/consul/prepared_query_endpoint_test.go @@ -1539,8 +1539,7 @@ func TestPreparedQuery_Execute(t *testing.T) { assert.Len(t, reply.Nodes, 0) }) - expectNodes := func(t *testing.T, query *structs.PreparedQueryRequest, reply *structs.PreparedQueryExecuteResponse, n int) { - t.Helper() + expectNodes := func(t require.TestingT, query *structs.PreparedQueryRequest, reply *structs.PreparedQueryExecuteResponse, n int) { assert.Len(t, reply.Nodes, n) assert.Equal(t, "dc1", reply.Datacenter) assert.Equal(t, 0, reply.Failovers) @@ -1548,8 +1547,7 @@ func TestPreparedQuery_Execute(t *testing.T) { assert.Equal(t, query.Query.DNS, reply.DNS) assert.True(t, reply.QueryMeta.KnownLeader) } - expectFailoverNodes := func(t *testing.T, query *structs.PreparedQueryRequest, reply *structs.PreparedQueryExecuteResponse, n int) { - t.Helper() + expectFailoverNodes := func(t require.TestingT, query *structs.PreparedQueryRequest, reply *structs.PreparedQueryExecuteResponse, n int) { assert.Len(t, reply.Nodes, n) assert.Equal(t, "dc2", reply.Datacenter) assert.Equal(t, 1, reply.Failovers) @@ -1558,8 +1556,7 @@ func TestPreparedQuery_Execute(t *testing.T) { assert.True(t, reply.QueryMeta.KnownLeader) } - expectFailoverPeerNodes := func(t *testing.T, query *structs.PreparedQueryRequest, reply *structs.PreparedQueryExecuteResponse, n int) { - t.Helper() + expectFailoverPeerNodes := func(t require.TestingT, query *structs.PreparedQueryRequest, reply *structs.PreparedQueryExecuteResponse, n int) { assert.Len(t, reply.Nodes, n) assert.Equal(t, "", reply.Datacenter) assert.Equal(t, es.peeringServer.acceptingPeerName, reply.PeerName) @@ -2372,13 +2369,13 @@ func TestPreparedQuery_Execute(t *testing.T) { } var reply structs.PreparedQueryExecuteResponse - require.NoError(t, msgpackrpc.CallWithCodec(es.server.codec, "PreparedQuery.Execute", &req, &reply)) + require.NoError(r, msgpackrpc.CallWithCodec(es.server.codec, "PreparedQuery.Execute", &req, &reply)) for _, node := range reply.Nodes { - assert.NotEqual(t, "node3", node.Node.Node) + assert.NotEqual(r, "node3", node.Node.Node) } - expectNodes(t, &query, &reply, 9) + expectNodes(r, &query, &reply, 9) }) }) } diff --git a/agent/dns_test.go b/agent/dns_test.go index b9d8f86a78..46a7e758c7 100644 --- a/agent/dns_test.go +++ b/agent/dns_test.go @@ -3189,7 +3189,7 @@ func TestDNS_ServiceLookup_WanTranslation(t *testing.T) { } var out struct{} - require.NoError(t, a2.RPC(context.Background(), "Catalog.Register", args, &out)) + require.NoError(r, a2.RPC(context.Background(), "Catalog.Register", args, &out)) }) // Look up the SRV record via service and prepared query. @@ -3517,11 +3517,11 @@ func TestDNS_CaseInsensitiveServiceLookup(t *testing.T) { retry.Run(t, func(r *retry.R) { in, _, err := c.Exchange(m, a.DNSAddr()) if err != nil { - t.Fatalf("err: %v", err) + r.Fatalf("err: %v", err) } if len(in.Answer) != 1 { - t.Fatalf("question %v, empty lookup: %#v", question, in) + r.Fatalf("question %v, empty lookup: %#v", question, in) } }) } diff --git a/agent/grpc-external/services/peerstream/stream_test.go b/agent/grpc-external/services/peerstream/stream_test.go index da4c55b227..2d8f6f3e16 100644 --- a/agent/grpc-external/services/peerstream/stream_test.go +++ b/agent/grpc-external/services/peerstream/stream_test.go @@ -1048,7 +1048,7 @@ func TestStreamResources_Server_ServiceUpdates(t *testing.T) { require.Equal(r, mongo.Service.CompoundServiceName().String(), msg.GetResponse().ResourceID) var nodes pbpeerstream.ExportedService - require.NoError(t, msg.GetResponse().Resource.UnmarshalTo(&nodes)) + require.NoError(r, msg.GetResponse().Resource.UnmarshalTo(&nodes)) require.Len(r, nodes.Nodes, 1) }) }) @@ -1077,12 +1077,12 @@ func TestStreamResources_Server_ServiceUpdates(t *testing.T) { msg, err := client.RecvWithTimeout(100 * time.Millisecond) require.NoError(r, err) require.Equal(r, pbpeerstream.TypeURLExportedServiceList, msg.GetResponse().ResourceURL) - require.Equal(t, subExportedServiceList, msg.GetResponse().ResourceID) - require.Equal(t, pbpeerstream.Operation_OPERATION_UPSERT, msg.GetResponse().Operation) + require.Equal(r, subExportedServiceList, msg.GetResponse().ResourceID) + require.Equal(r, pbpeerstream.Operation_OPERATION_UPSERT, msg.GetResponse().Operation) var exportedServices pbpeerstream.ExportedServiceList - require.NoError(t, msg.GetResponse().Resource.UnmarshalTo(&exportedServices)) - require.Equal(t, []string{structs.ServiceName{Name: "mongo"}.String()}, exportedServices.Services) + require.NoError(r, msg.GetResponse().Resource.UnmarshalTo(&exportedServices)) + require.Equal(r, []string{structs.ServiceName{Name: "mongo"}.String()}, exportedServices.Services) }) }) @@ -1094,12 +1094,12 @@ func TestStreamResources_Server_ServiceUpdates(t *testing.T) { msg, err := client.RecvWithTimeout(100 * time.Millisecond) require.NoError(r, err) require.Equal(r, pbpeerstream.TypeURLExportedServiceList, msg.GetResponse().ResourceURL) - require.Equal(t, subExportedServiceList, msg.GetResponse().ResourceID) - require.Equal(t, pbpeerstream.Operation_OPERATION_UPSERT, msg.GetResponse().Operation) + require.Equal(r, subExportedServiceList, msg.GetResponse().ResourceID) + require.Equal(r, pbpeerstream.Operation_OPERATION_UPSERT, msg.GetResponse().Operation) var exportedServices pbpeerstream.ExportedServiceList - require.NoError(t, msg.GetResponse().Resource.UnmarshalTo(&exportedServices)) - require.Len(t, exportedServices.Services, 0) + require.NoError(r, msg.GetResponse().Resource.UnmarshalTo(&exportedServices)) + require.Len(r, exportedServices.Services, 0) }) }) } diff --git a/agent/local/state_test.go b/agent/local/state_test.go index 372bf5b8ca..0a78f321f7 100644 --- a/agent/local/state_test.go +++ b/agent/local/state_test.go @@ -1320,13 +1320,13 @@ func TestAgentAntiEntropy_Checks(t *testing.T) { chk.CreateIndex, chk.ModifyIndex = 0, 0 switch chk.CheckID { case "mysql": - require.Equal(t, chk, chk1) + require.Equal(r, chk, chk1) case "redis": - require.Equal(t, chk, chk2) + require.Equal(r, chk, chk2) case "web": - require.Equal(t, chk, chk3) + require.Equal(r, chk, chk3) case "cache": - require.Equal(t, chk, chk5) + require.Equal(r, chk, chk5) case "serfHealth": // ignore default: @@ -1356,9 +1356,9 @@ func TestAgentAntiEntropy_Checks(t *testing.T) { addrs := services.NodeServices.Node.TaggedAddresses meta := services.NodeServices.Node.Meta delete(meta, structs.MetaSegmentKey) // Added later, not in config. - assert.Equal(t, a.Config.NodeID, id) - assert.Equal(t, a.Config.TaggedAddresses, addrs) - assert.Equal(t, unNilMap(a.Config.NodeMeta), meta) + assert.Equal(r, a.Config.NodeID, id) + assert.Equal(r, a.Config.TaggedAddresses, addrs) + assert.Equal(r, unNilMap(a.Config.NodeMeta), meta) } }) retry.Run(t, func(r *retry.R) { @@ -1385,11 +1385,11 @@ func TestAgentAntiEntropy_Checks(t *testing.T) { chk.CreateIndex, chk.ModifyIndex = 0, 0 switch chk.CheckID { case "mysql": - require.Equal(t, chk1, chk) + require.Equal(r, chk1, chk) case "web": - require.Equal(t, chk3, chk) + require.Equal(r, chk3, chk) case "cache": - require.Equal(t, chk5, chk) + require.Equal(r, chk5, chk) case "serfHealth": // ignore default: From 1db02a03498d037132950b9672672627fe5968d7 Mon Sep 17 00:00:00 2001 From: Michael Zalimeni Date: Wed, 7 Jun 2023 15:39:25 -0400 Subject: [PATCH 39/72] Disable terminating-gateway for property-override (#17605) More validation is needed to ensure this behaves as expected; in the meantime, align with docs and disable this proxy type. --- .../builtin/property-override/property_override.go | 4 ++-- .../builtin/property-override/property_override_test.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/agent/envoyextensions/builtin/property-override/property_override.go b/agent/envoyextensions/builtin/property-override/property_override.go index c018d334a5..8164a8092a 100644 --- a/agent/envoyextensions/builtin/property-override/property_override.go +++ b/agent/envoyextensions/builtin/property-override/property_override.go @@ -106,8 +106,8 @@ var Ops = extensioncommon.StringSet{string(OpAdd): {}, string(OpRemove): {}} // validProxyTypes is the set of supported proxy types for this extension. var validProxyTypes = extensioncommon.StringSet{ - string(api.ServiceKindConnectProxy): struct{}{}, - string(api.ServiceKindTerminatingGateway): struct{}{}, + // For now, we only support `connect-proxy`. + string(api.ServiceKindConnectProxy): struct{}{}, } // Patch describes a single patch operation to modify the specific field of matching diff --git a/agent/envoyextensions/builtin/property-override/property_override_test.go b/agent/envoyextensions/builtin/property-override/property_override_test.go index 68a895edb8..ca549353fa 100644 --- a/agent/envoyextensions/builtin/property-override/property_override_test.go +++ b/agent/envoyextensions/builtin/property-override/property_override_test.go @@ -618,7 +618,7 @@ func TestCanApply(t *testing.T) { }, "invalid proxy type": { ext: &propertyOverride{ - ProxyType: api.ServiceKindTerminatingGateway, + ProxyType: api.ServiceKindConnectProxy, }, conf: &extensioncommon.RuntimeConfig{ Kind: api.ServiceKindMeshGateway, From 1e920a7f016f41479a1a09887a1ac6512a2e0575 Mon Sep 17 00:00:00 2001 From: Michael Zalimeni Date: Wed, 7 Jun 2023 17:46:49 -0400 Subject: [PATCH 40/72] [OSS] Post Consul 1.16 updates (#17606) * chore: update dev build to 1.17 * chore(ci): add nightly 1.16 test Drop the oldest and add the newest running release branch to nightly builds. --- .../{nightly-test-1.12.x.yaml => nightly-test-1.16.x.yaml} | 6 +++--- version/VERSION | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) rename .github/workflows/{nightly-test-1.12.x.yaml => nightly-test-1.16.x.yaml} (98%) diff --git a/.github/workflows/nightly-test-1.12.x.yaml b/.github/workflows/nightly-test-1.16.x.yaml similarity index 98% rename from .github/workflows/nightly-test-1.12.x.yaml rename to .github/workflows/nightly-test-1.16.x.yaml index 0f016075e2..c30ed6811c 100644 --- a/.github/workflows/nightly-test-1.12.x.yaml +++ b/.github/workflows/nightly-test-1.16.x.yaml @@ -1,7 +1,7 @@ # Copyright (c) HashiCorp, Inc. # SPDX-License-Identifier: MPL-2.0 -name: Nightly Test 1.12.x +name: Nightly Test 1.16.x on: schedule: - cron: '0 4 * * *' @@ -9,8 +9,8 @@ on: env: EMBER_PARTITION_TOTAL: 4 # Has to be changed in tandem with the matrix.partition - BRANCH: "release/1.12.x" - BRANCH_NAME: "release-1.12.x" # Used for naming artifacts + BRANCH: "release/1.16.x" + BRANCH_NAME: "release-1.16.x" # Used for naming artifacts jobs: frontend-test-workspace-node: diff --git a/version/VERSION b/version/VERSION index 1f0d2f3351..ee8855caa4 100644 --- a/version/VERSION +++ b/version/VERSION @@ -1 +1 @@ -1.16.0-dev +1.17.0-dev From 8118aae5c14e26c3c0bc2c2fd2687da2e091e0f3 Mon Sep 17 00:00:00 2001 From: Ronald Date: Wed, 7 Jun 2023 18:35:48 -0400 Subject: [PATCH 41/72] Add writeAuditRPCEvent to agent_oss (#17607) * Add writeAuditRPCEvent to agent_oss * fix the other diffs * backport change log --- .changelog/_5740.txt | 3 +++ .changelog/_5750.txt | 3 +++ agent/agent.go | 11 +++++++++++ agent/agent_oss.go | 4 ++++ agent/config/config.go | 5 +++-- 5 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 .changelog/_5740.txt create mode 100644 .changelog/_5750.txt diff --git a/.changelog/_5740.txt b/.changelog/_5740.txt new file mode 100644 index 0000000000..4f1d6f6448 --- /dev/null +++ b/.changelog/_5740.txt @@ -0,0 +1,3 @@ +```release-note:feature +api: (Enterprise only) Add `POST /v1/operator/audit-hash` endpoint to calculate the hash of the data used by the audit log hash function and salt. +``` \ No newline at end of file diff --git a/.changelog/_5750.txt b/.changelog/_5750.txt new file mode 100644 index 0000000000..027753c721 --- /dev/null +++ b/.changelog/_5750.txt @@ -0,0 +1,3 @@ +```release-note:feature +cli: (Enterprise only) Add a new `consul operator audit hash` command to retrieve and compare the hash of the data used by the audit log hash function and salt. +``` \ No newline at end of file diff --git a/agent/agent.go b/agent/agent.go index 678d110d53..0b06688c48 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -1621,7 +1621,18 @@ func (a *Agent) RPC(ctx context.Context, method string, args interface{}, reply method = e + "." + p[1] } } + + // audit log only on consul clients + _, ok := a.delegate.(*consul.Client) + if ok { + a.writeAuditRPCEvent(method, "OperationStart") + } + a.endpointsLock.RUnlock() + + defer func() { + a.writeAuditRPCEvent(method, "OperationComplete") + }() return a.delegate.RPC(ctx, method, args, reply) } diff --git a/agent/agent_oss.go b/agent/agent_oss.go index 93e633cc65..e8cfea681b 100644 --- a/agent/agent_oss.go +++ b/agent/agent_oss.go @@ -69,3 +69,7 @@ func (a *Agent) AgentEnterpriseMeta() *acl.EnterpriseMeta { func (a *Agent) registerEntCache() {} func (*Agent) fillEnterpriseProxyDataSources(*proxycfg.DataSources) {} + +func (a *Agent) writeAuditRPCEvent(_ string, _ string) interface{} { + return nil +} diff --git a/agent/config/config.go b/agent/config/config.go index e26d6edc4d..d8d7149afe 100644 --- a/agent/config/config.go +++ b/agent/config/config.go @@ -807,8 +807,9 @@ type ConfigEntries struct { // Audit allows us to enable and define destinations for auditing type Audit struct { - Enabled *bool `mapstructure:"enabled"` - Sinks map[string]AuditSink `mapstructure:"sink"` + Enabled *bool `mapstructure:"enabled"` + Sinks map[string]AuditSink `mapstructure:"sink"` + RPCEnabled *bool `mapstructure:"rpc_enabled"` } // AuditSink can be provided multiple times to define pipelines for auditing From 779647b9486e239de1f868854ac6f367f3e5af4e Mon Sep 17 00:00:00 2001 From: Eric Haberkorn Date: Thu, 8 Jun 2023 10:26:11 -0400 Subject: [PATCH 42/72] Add Envoy and Consul version constraints to Envoy extensions (#17612) --- .../envoyextensions/registered_extensions.go | 21 +- .../registered_extensions_test.go | 24 ++ agent/structs/envoy_extension.go | 16 +- agent/structs/structs_filtering_test.go | 10 + agent/xds/delta.go | 158 +++++++---- agent/xds/delta_envoy_extender_oss_test.go | 59 +++- agent/xds/delta_test.go | 108 +++++++ ...-consul-constraint-violation.latest.golden | 127 +++++++++ ...h-envoy-constraint-violation.latest.golden | 127 +++++++++ ...-consul-constraint-violation.latest.golden | 75 +++++ ...h-envoy-constraint-violation.latest.golden | 75 +++++ ...-consul-constraint-violation.latest.golden | 265 ++++++++++++++++++ ...h-envoy-constraint-violation.latest.golden | 265 ++++++++++++++++++ ...-consul-constraint-violation.latest.golden | 5 + ...h-envoy-constraint-violation.latest.golden | 5 + api/config_entry.go | 8 +- envoyextensions/xdscommon/envoy_versioning.go | 4 +- .../xdscommon/envoy_versioning_test.go | 2 +- proto/private/pbcommon/common.gen.go | 4 + proto/private/pbcommon/common.pb.go | 82 ++++-- proto/private/pbcommon/common.proto | 2 + proto/private/pbcommon/convert_pbstruct.go | 16 +- 22 files changed, 1344 insertions(+), 114 deletions(-) create mode 100644 agent/xds/testdata/builtin_extension/clusters/lua-outbound-doesnt-apply-to-local-upstreams-with-consul-constraint-violation.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/clusters/lua-outbound-doesnt-apply-to-local-upstreams-with-envoy-constraint-violation.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/endpoints/lua-outbound-doesnt-apply-to-local-upstreams-with-consul-constraint-violation.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/endpoints/lua-outbound-doesnt-apply-to-local-upstreams-with-envoy-constraint-violation.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-local-upstreams-with-consul-constraint-violation.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-local-upstreams-with-envoy-constraint-violation.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/routes/lua-outbound-doesnt-apply-to-local-upstreams-with-consul-constraint-violation.latest.golden create mode 100644 agent/xds/testdata/builtin_extension/routes/lua-outbound-doesnt-apply-to-local-upstreams-with-envoy-constraint-violation.latest.golden diff --git a/agent/envoyextensions/registered_extensions.go b/agent/envoyextensions/registered_extensions.go index 4d4d266116..177ab9cb03 100644 --- a/agent/envoyextensions/registered_extensions.go +++ b/agent/envoyextensions/registered_extensions.go @@ -6,6 +6,9 @@ package envoyextensions import ( "fmt" + "github.com/hashicorp/go-multierror" + "github.com/hashicorp/go-version" + awslambda "github.com/hashicorp/consul/agent/envoyextensions/builtin/aws-lambda" extauthz "github.com/hashicorp/consul/agent/envoyextensions/builtin/ext-authz" "github.com/hashicorp/consul/agent/envoyextensions/builtin/http/localratelimit" @@ -14,7 +17,6 @@ import ( "github.com/hashicorp/consul/agent/envoyextensions/builtin/wasm" "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/envoyextensions/extensioncommon" - "github.com/hashicorp/go-multierror" ) type extensionConstructor func(api.EnvoyExtension) (extensioncommon.EnvoyExtender, error) @@ -50,6 +52,23 @@ func ValidateExtensions(extensions []api.EnvoyExtension) error { output = multierror.Append(output, fmt.Errorf("invalid EnvoyExtensions[%d]: Name is required", i)) continue } + + if v := ext.EnvoyVersion; v != "" { + _, err := version.NewConstraint(v) + if err != nil { + output = multierror.Append(output, fmt.Errorf("invalid EnvoyExtensions[%d].EnvoyVersion: %w", i, err)) + continue + } + } + + if v := ext.ConsulVersion; v != "" { + _, err := version.NewConstraint(v) + if err != nil { + output = multierror.Append(output, fmt.Errorf("invalid EnvoyExtensions[%d].ConsulVersion: %w", i, err)) + continue + } + } + _, err := ConstructExtension(ext) if err != nil { output = multierror.Append(output, fmt.Errorf("invalid EnvoyExtensions[%d][%s]: %w", i, ext.Name, err)) diff --git a/agent/envoyextensions/registered_extensions_test.go b/agent/envoyextensions/registered_extensions_test.go index ebd1bfbbc9..7f3cb6bbac 100644 --- a/agent/envoyextensions/registered_extensions_test.go +++ b/agent/envoyextensions/registered_extensions_test.go @@ -48,6 +48,30 @@ func TestValidateExtensions(t *testing.T) { "missing Script value", }, }, + "invalid consul version constraint": { + input: []api.EnvoyExtension{{ + Name: "builtin/aws/lambda", + Arguments: map[string]interface{}{ + "ARN": "arn:aws:lambda:us-east-1:111111111111:function:lambda-1234", + }, + ConsulVersion: "bad", + }}, + expectErrs: []string{ + "invalid EnvoyExtensions[0].ConsulVersion: Malformed constraint: bad", + }, + }, + "invalid envoy version constraint": { + input: []api.EnvoyExtension{{ + Name: "builtin/aws/lambda", + Arguments: map[string]interface{}{ + "ARN": "arn:aws:lambda:us-east-1:111111111111:function:lambda-1234", + }, + EnvoyVersion: "bad", + }}, + expectErrs: []string{ + "invalid EnvoyExtensions[0].EnvoyVersion: Malformed constraint: bad", + }, + }, } for name, tc := range tests { diff --git a/agent/structs/envoy_extension.go b/agent/structs/envoy_extension.go index 5b69afb0d9..c788aedf37 100644 --- a/agent/structs/envoy_extension.go +++ b/agent/structs/envoy_extension.go @@ -9,9 +9,11 @@ import ( // EnvoyExtension has configuration for an extension that patches Envoy resources. type EnvoyExtension struct { - Name string - Required bool - Arguments map[string]interface{} `bexpr:"-"` + Name string + Required bool + Arguments map[string]interface{} `bexpr:"-"` + ConsulVersion string + EnvoyVersion string } type EnvoyExtensions []EnvoyExtension @@ -20,9 +22,11 @@ func (es EnvoyExtensions) ToAPI() []api.EnvoyExtension { extensions := make([]api.EnvoyExtension, len(es)) for i, e := range es { extensions[i] = api.EnvoyExtension{ - Name: e.Name, - Required: e.Required, - Arguments: e.Arguments, + Name: e.Name, + Required: e.Required, + Arguments: e.Arguments, + EnvoyVersion: e.EnvoyVersion, + ConsulVersion: e.ConsulVersion, } } return extensions diff --git a/agent/structs/structs_filtering_test.go b/agent/structs/structs_filtering_test.go index 1bc6599650..9739923e0e 100644 --- a/agent/structs/structs_filtering_test.go +++ b/agent/structs/structs_filtering_test.go @@ -197,6 +197,16 @@ var expectedFieldConfigEnvoyExtensions bexpr.FieldConfigurations = bexpr.FieldCo CoerceFn: bexpr.CoerceBool, SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual}, }, + "ConsulVersion": &bexpr.FieldConfiguration{ + StructFieldName: "ConsulVersion", + CoerceFn: bexpr.CoerceString, + SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches}, + }, + "EnvoyVersion": &bexpr.FieldConfiguration{ + StructFieldName: "EnvoyVersion", + CoerceFn: bexpr.CoerceString, + SupportedOperations: []bexpr.MatchOperator{bexpr.MatchEqual, bexpr.MatchNotEqual, bexpr.MatchIn, bexpr.MatchNotIn, bexpr.MatchMatches, bexpr.MatchNotMatches}, + }, } var expectedFieldConfigUpstreams bexpr.FieldConfigurations = bexpr.FieldConfigurations{ "DestinationType": &bexpr.FieldConfiguration{ diff --git a/agent/xds/delta.go b/agent/xds/delta.go index 66072e0b81..5e4cf70209 100644 --- a/agent/xds/delta.go +++ b/agent/xds/delta.go @@ -17,6 +17,8 @@ import ( envoy_config_core_v3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" envoy_discovery_v3 "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3" + "github.com/hashicorp/go-hclog" + goversion "github.com/hashicorp/go-version" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -29,6 +31,7 @@ import ( "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/xds/extensionruntime" + "github.com/hashicorp/consul/envoyextensions/extensioncommon" "github.com/hashicorp/consul/envoyextensions/xdscommon" "github.com/hashicorp/consul/logging" "github.com/hashicorp/consul/version" @@ -255,7 +258,7 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove s.ResourceMapMutateFn(newResourceMap) } - if err = s.applyEnvoyExtensions(newResourceMap, cfgSnap); err != nil { + if err = s.applyEnvoyExtensions(newResourceMap, cfgSnap, node); err != nil { // err is already the result of calling status.Errorf return err } @@ -400,70 +403,123 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove } } -func (s *Server) applyEnvoyExtensions(resources *xdscommon.IndexedResources, cfgSnap *proxycfg.ConfigSnapshot) error { +func (s *Server) applyEnvoyExtensions(resources *xdscommon.IndexedResources, cfgSnap *proxycfg.ConfigSnapshot, node *envoy_config_core_v3.Node) error { + var err error + envoyVersion := xdscommon.DetermineEnvoyVersionFromNode(node) + consulVersion, err := goversion.NewVersion(version.Version) + + if err != nil { + return status.Errorf(codes.InvalidArgument, "failed to parse Consul version") + } + serviceConfigs := extensionruntime.GetRuntimeConfigurations(cfgSnap) for _, cfgs := range serviceConfigs { for _, cfg := range cfgs { - logFn := s.Logger.Warn - if cfg.EnvoyExtension.Required { - logFn = s.Logger.Error - } - errorParams := []interface{}{ - "extension", cfg.EnvoyExtension.Name, - "service", cfg.ServiceName.Name, - "namespace", cfg.ServiceName.Namespace, - "partition", cfg.ServiceName.Partition, - } - - getMetricLabels := func(err error) []metrics.Label { - return []metrics.Label{ - {Name: "extension", Value: cfg.EnvoyExtension.Name}, - {Name: "version", Value: "builtin/" + version.Version}, - {Name: "service", Value: cfgSnap.Service}, - {Name: "partition", Value: cfgSnap.ProxyID.PartitionOrDefault()}, - {Name: "namespace", Value: cfgSnap.ProxyID.NamespaceOrDefault()}, - {Name: "error", Value: strconv.FormatBool(err != nil)}, - } - } + err = applyEnvoyExtension(s.Logger, cfgSnap, resources, cfg, envoyVersion, consulVersion) - now := time.Now() - extender, err := envoyextensions.ConstructExtension(cfg.EnvoyExtension) - metrics.MeasureSinceWithLabels([]string{"envoy_extension", "validate_arguments"}, now, getMetricLabels(err)) if err != nil { - logFn("failed to construct extension", errorParams...) + return err + } + } + } - if cfg.EnvoyExtension.Required { - return status.Errorf(codes.Unavailable, "failed to construct extension %q for service %q", cfg.EnvoyExtension.Name, cfg.ServiceName.Name) - } + return nil +} - continue - } +func applyEnvoyExtension(logger hclog.Logger, cfgSnap *proxycfg.ConfigSnapshot, resources *xdscommon.IndexedResources, runtimeConfig extensioncommon.RuntimeConfig, envoyVersion, consulVersion *goversion.Version) error { + logFn := logger.Warn + if runtimeConfig.EnvoyExtension.Required { + logFn = logger.Error + } - now = time.Now() - err = extender.Validate(&cfg) - metrics.MeasureSinceWithLabels([]string{"envoy_extension", "validate"}, now, getMetricLabels(err)) - if err != nil { - errorParams = append(errorParams, "error", err) - logFn("failed to validate extension arguments", errorParams...) - if cfg.EnvoyExtension.Required { - return status.Errorf(codes.Unavailable, "failed to validate arguments for extension %q for service %q", cfg.EnvoyExtension.Name, cfg.ServiceName.Name) - } + svc := runtimeConfig.ServiceName - continue - } + errorParams := []interface{}{ + "extension", runtimeConfig.EnvoyExtension.Name, + "service", svc.Name, + "namespace", svc.Namespace, + "partition", svc.Partition, + } - now = time.Now() - resources, err = extender.Extend(resources, &cfg) - metrics.MeasureSinceWithLabels([]string{"envoy_extension", "extend"}, now, getMetricLabels(err)) - if err == nil { - continue + getMetricLabels := func(err error) []metrics.Label { + return []metrics.Label{ + {Name: "extension", Value: runtimeConfig.EnvoyExtension.Name}, + {Name: "version", Value: "builtin/" + version.Version}, + {Name: "service", Value: cfgSnap.Service}, + {Name: "partition", Value: cfgSnap.ProxyID.PartitionOrDefault()}, + {Name: "namespace", Value: cfgSnap.ProxyID.NamespaceOrDefault()}, + {Name: "error", Value: strconv.FormatBool(err != nil)}, + } + } + + ext := runtimeConfig.EnvoyExtension + + if v := ext.EnvoyVersion; v != "" { + c, err := goversion.NewConstraint(v) + if err != nil { + logFn("failed to parse Envoy extension version constraint", errorParams...) + + if ext.Required { + return status.Errorf(codes.InvalidArgument, "failed to parse Envoy version constraint for extension %q for service %q", ext.Name, svc.Name) } + return nil + } + + if !c.Check(envoyVersion) { + logger.Info("skipping envoy extension due to Envoy version constraint violation", errorParams...) + return nil + } + } + + if v := ext.ConsulVersion; v != "" { + c, err := goversion.NewConstraint(v) + if err != nil { + logFn("failed to parse Consul extension version constraint", errorParams...) - logFn("failed to apply envoy extension", errorParams...) - if cfg.EnvoyExtension.Required { - return status.Errorf(codes.Unavailable, "failed to patch xDS resources in the %q extension: %v", cfg.EnvoyExtension.Name, err) + if ext.Required { + return status.Errorf(codes.InvalidArgument, "failed to parse Consul version constraint for extension %q for service %q", ext.Name, svc.Name) } + return nil + } + + if !c.Check(consulVersion) { + logger.Info("skipping envoy extension due to Consul version constraint violation", errorParams...) + return nil + } + } + + now := time.Now() + extender, err := envoyextensions.ConstructExtension(ext) + metrics.MeasureSinceWithLabels([]string{"envoy_extension", "validate_arguments"}, now, getMetricLabels(err)) + if err != nil { + logFn("failed to construct extension", errorParams...) + + if ext.Required { + return status.Errorf(codes.InvalidArgument, "failed to construct extension %q for service %q", ext.Name, svc.Name) + } + + return nil + } + + now = time.Now() + err = extender.Validate(&runtimeConfig) + metrics.MeasureSinceWithLabels([]string{"envoy_extension", "validate"}, now, getMetricLabels(err)) + if err != nil { + errorParams = append(errorParams, "error", err) + logFn("failed to validate extension arguments", errorParams...) + if ext.Required { + return status.Errorf(codes.InvalidArgument, "failed to validate arguments for extension %q for service %q", ext.Name, svc.Name) } + + return nil + } + + now = time.Now() + _, err = extender.Extend(resources, &runtimeConfig) + metrics.MeasureSinceWithLabels([]string{"envoy_extension", "extend"}, now, getMetricLabels(err)) + logFn("failed to apply envoy extension", errorParams...) + if err != nil && ext.Required { + return status.Errorf(codes.InvalidArgument, "failed to patch xDS resources in the %q extension: %v", ext.Name, err) } return nil diff --git a/agent/xds/delta_envoy_extender_oss_test.go b/agent/xds/delta_envoy_extender_oss_test.go index dc1521edbe..3d92b6d25d 100644 --- a/agent/xds/delta_envoy_extender_oss_test.go +++ b/agent/xds/delta_envoy_extender_oss_test.go @@ -16,11 +16,12 @@ import ( envoy_listener_v3 "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3" envoy_route_v3 "github.com/envoyproxy/go-control-plane/envoy/config/route/v3" "github.com/hashicorp/consul/agent/xds/testcommon" + "github.com/hashicorp/go-hclog" + goversion "github.com/hashicorp/go-version" testinf "github.com/mitchellh/go-testing-interface" "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" - "github.com/hashicorp/consul/agent/envoyextensions" propertyoverride "github.com/hashicorp/consul/agent/envoyextensions/builtin/property-override" "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" @@ -29,9 +30,12 @@ import ( "github.com/hashicorp/consul/envoyextensions/extensioncommon" "github.com/hashicorp/consul/envoyextensions/xdscommon" "github.com/hashicorp/consul/sdk/testutil" + "github.com/hashicorp/consul/version" ) func TestEnvoyExtenderWithSnapshot(t *testing.T) { + consulVersion, _ := goversion.NewVersion(version.Version) + // If opposite is true, the returned service defaults config entry will have // payload-passthrough=true and invocation-mode=asynchronous. // Otherwise payload-passthrough=false and invocation-mode=synchronous. @@ -65,7 +69,7 @@ func TestEnvoyExtenderWithSnapshot(t *testing.T) { } // Apply Lua extension to the local service and ensure http is used so the extension can be applied. - makeLuaNsFunc := func(inbound bool) func(ns *structs.NodeService) { + makeLuaNsFunc := func(inbound bool, envoyVersion, consulVersion string) func(ns *structs.NodeService) { listener := "inbound" if !inbound { listener = "outbound" @@ -75,7 +79,9 @@ func TestEnvoyExtenderWithSnapshot(t *testing.T) { ns.Proxy.Config["protocol"] = "http" ns.Proxy.EnvoyExtensions = []structs.EnvoyExtension{ { - Name: api.BuiltinLuaExtension, + Name: api.BuiltinLuaExtension, + EnvoyVersion: envoyVersion, + ConsulVersion: consulVersion, Arguments: map[string]interface{}{ "ProxyType": "connect-proxy", "Listener": listener, @@ -464,11 +470,41 @@ end`, name: "lambda-terminating-gateway-with-service-resolvers", create: proxycfg.TestConfigSnapshotTerminatingGatewayWithLambdaServiceAndServiceResolvers, }, + { + name: "lua-outbound-doesnt-apply-to-local-upstreams-with-envoy-constraint-violation", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + // upstreams need to be http in order for lua to be applied to listeners. + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", false, makeLuaNsFunc(false, "< 1.0.0", ">= 1.0.0"), nil, &structs.ServiceConfigEntry{ + Kind: structs.ServiceDefaults, + Name: "db", + Protocol: "http", + }, &structs.ServiceConfigEntry{ + Kind: structs.ServiceDefaults, + Name: "geo-cache", + Protocol: "http", + }) + }, + }, + { + name: "lua-outbound-doesnt-apply-to-local-upstreams-with-consul-constraint-violation", + create: func(t testinf.T) *proxycfg.ConfigSnapshot { + // upstreams need to be http in order for lua to be applied to listeners. + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", false, makeLuaNsFunc(false, ">= 1.0.0", "< 1.0.0"), nil, &structs.ServiceConfigEntry{ + Kind: structs.ServiceDefaults, + Name: "db", + Protocol: "http", + }, &structs.ServiceConfigEntry{ + Kind: structs.ServiceDefaults, + Name: "geo-cache", + Protocol: "http", + }) + }, + }, { name: "lua-outbound-applies-to-local-upstreams", create: func(t testinf.T) *proxycfg.ConfigSnapshot { // upstreams need to be http in order for lua to be applied to listeners. - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", false, makeLuaNsFunc(false), nil, &structs.ServiceConfigEntry{ + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", false, makeLuaNsFunc(false, ">= 1.0.0", ">= 1.0.0"), nil, &structs.ServiceConfigEntry{ Kind: structs.ServiceDefaults, Name: "db", Protocol: "http", @@ -487,7 +523,7 @@ end`, create: func(t testinf.T) *proxycfg.ConfigSnapshot { // db is made an HTTP upstream so that the extension _could_ apply, but does not because // the direction for the extension is inbound. - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", false, makeLuaNsFunc(true), nil, &structs.ServiceConfigEntry{ + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", false, makeLuaNsFunc(true, "", ""), nil, &structs.ServiceConfigEntry{ Kind: structs.ServiceDefaults, Name: "db", Protocol: "http", @@ -497,7 +533,7 @@ end`, { name: "lua-inbound-applies-to-inbound", create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", false, makeLuaNsFunc(true), nil) + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", false, makeLuaNsFunc(true, "", ""), nil) }, }, { @@ -505,14 +541,14 @@ end`, // no upstream HTTP services. We also should not see public listener, which is HTTP, patched. name: "lua-outbound-doesnt-apply-to-inbound", create: func(t testinf.T) *proxycfg.ConfigSnapshot { - return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", false, makeLuaNsFunc(false), nil) + return proxycfg.TestConfigSnapshotDiscoveryChain(t, "default", false, makeLuaNsFunc(false, "", ""), nil) }, }, { name: "lua-outbound-applies-to-local-upstreams-tproxy", create: func(t testinf.T) *proxycfg.ConfigSnapshot { // upstreams need to be http in order for lua to be applied to listeners. - return proxycfg.TestConfigSnapshotTransparentProxyDestinationHTTP(t, makeLuaNsFunc(false)) + return proxycfg.TestConfigSnapshotTransparentProxyDestinationHTTP(t, makeLuaNsFunc(false, "", "")) }, }, { @@ -707,6 +743,7 @@ end`, latestEnvoyVersion := xdscommon.EnvoyVersions[0] for _, envoyVersion := range xdscommon.EnvoyVersions { + parsedEnvoyVersion, _ := goversion.NewVersion(envoyVersion) sf, err := xdscommon.DetermineSupportedProxyFeaturesFromString(envoyVersion) require.NoError(t, err) t.Run("envoy-"+envoyVersion, func(t *testing.T) { @@ -730,11 +767,7 @@ end`, cfgs := extensionruntime.GetRuntimeConfigurations(snap) for _, extensions := range cfgs { for _, ext := range extensions { - extender, err := envoyextensions.ConstructExtension(ext.EnvoyExtension) - require.NoError(t, err) - err = extender.Validate(&ext) - require.NoError(t, err) - indexedResources, err = extender.Extend(indexedResources, &ext) + err := applyEnvoyExtension(hclog.NewNullLogger(), snap, indexedResources, ext, parsedEnvoyVersion, consulVersion) require.NoError(t, err) } } diff --git a/agent/xds/delta_test.go b/agent/xds/delta_test.go index a9febfedfa..f9c77835ad 100644 --- a/agent/xds/delta_test.go +++ b/agent/xds/delta_test.go @@ -14,6 +14,8 @@ import ( "github.com/armon/go-metrics" envoy_discovery_v3 "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3" + "github.com/hashicorp/go-hclog" + goversion "github.com/hashicorp/go-version" "github.com/stretchr/testify/require" rpcstatus "google.golang.org/genproto/googleapis/rpc/status" "google.golang.org/grpc/codes" @@ -25,6 +27,7 @@ import ( "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/envoyextensions/extensioncommon" "github.com/hashicorp/consul/envoyextensions/xdscommon" "github.com/hashicorp/consul/sdk/testutil" "github.com/hashicorp/consul/sdk/testutil/retry" @@ -1609,3 +1612,108 @@ func requireExtensionMetrics( require.True(t, foundLabel) } } + +func Test_applyEnvoyExtension_Validations(t *testing.T) { + type testCase struct { + name string + runtimeConfig extensioncommon.RuntimeConfig + err bool + errString string + } + + envoyVersion, _ := goversion.NewVersion("1.25.0") + consulVersion, _ := goversion.NewVersion("1.16.0") + + svc := api.CompoundServiceName{ + Name: "s1", + Partition: "ap1", + Namespace: "ns1", + } + + makeRuntimeConfig := func(required bool, consulVersion string, envoyVersion string, args map[string]interface{}) extensioncommon.RuntimeConfig { + if args == nil { + args = map[string]interface{}{ + "ARN": "arn:aws:lambda:us-east-1:111111111111:function:lambda-1234", + } + + } + return extensioncommon.RuntimeConfig{ + EnvoyExtension: api.EnvoyExtension{ + Name: api.BuiltinAWSLambdaExtension, + Required: required, + ConsulVersion: consulVersion, + EnvoyVersion: envoyVersion, + Arguments: args, + }, + ServiceName: svc, + } + } + + cases := []testCase{ + { + name: "invalid consul version constraint - required", + runtimeConfig: makeRuntimeConfig(true, "bad", ">= 1.0", nil), + err: true, + errString: "failed to parse Consul version constraint for extension", + }, + { + name: "invalid consul version constraint - not required", + runtimeConfig: makeRuntimeConfig(false, "bad", ">= 1.0", nil), + err: false, + }, + { + name: "invalid envoy version constraint - required", + runtimeConfig: makeRuntimeConfig(true, ">= 1.0", "bad", nil), + err: true, + errString: "failed to parse Envoy version constraint for extension", + }, + { + name: "invalid envoy version constraint - not required", + runtimeConfig: makeRuntimeConfig(false, ">= 1.0", "bad", nil), + err: false, + }, + { + name: "no envoy version constraint match", + runtimeConfig: makeRuntimeConfig(false, "", ">= 2.0.0", nil), + err: false, + }, + { + name: "no consul version constraint match", + runtimeConfig: makeRuntimeConfig(false, ">= 2.0.0", "", nil), + err: false, + }, + { + name: "invalid extension arguments - required", + runtimeConfig: makeRuntimeConfig(true, ">= 1.15.0", ">= 1.25.0", map[string]interface{}{"bad": "args"}), + err: true, + errString: "failed to construct extension", + }, + { + name: "invalid extension arguments - not required", + runtimeConfig: makeRuntimeConfig(false, ">= 1.15.0", ">= 1.25.0", map[string]interface{}{"bad": "args"}), + err: false, + }, + { + name: "valid everything", + runtimeConfig: makeRuntimeConfig(false, ">= 1.15.0", ">= 1.25.0", nil), + err: false, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + snap := proxycfg.ConfigSnapshot{ + ProxyID: proxycfg.ProxyID{ + ServiceID: structs.NewServiceID("s1", nil), + }, + } + err := applyEnvoyExtension(hclog.NewNullLogger(), &snap, nil, tc.runtimeConfig, envoyVersion, consulVersion) + if tc.err { + require.Error(t, err) + require.Contains(t, err.Error(), tc.errString) + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/agent/xds/testdata/builtin_extension/clusters/lua-outbound-doesnt-apply-to-local-upstreams-with-consul-constraint-violation.latest.golden b/agent/xds/testdata/builtin_extension/clusters/lua-outbound-doesnt-apply-to-local-upstreams-with-consul-constraint-violation.latest.golden new file mode 100644 index 0000000000..c010ac87b0 --- /dev/null +++ b/agent/xds/testdata/builtin_extension/clusters/lua-outbound-doesnt-apply-to-local-upstreams-with-consul-constraint-violation.latest.golden @@ -0,0 +1,127 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "type": "EDS", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "connectTimeout": "5s", + "circuitBreakers": {}, + "outlierDetection": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + }, + "matchSubjectAltNames": [ + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + } + ] + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "type": "EDS", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "connectTimeout": "5s", + "circuitBreakers": {}, + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + }, + "matchSubjectAltNames": [ + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + } + ] + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "local_app", + "type": "STATIC", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + } + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/clusters/lua-outbound-doesnt-apply-to-local-upstreams-with-envoy-constraint-violation.latest.golden b/agent/xds/testdata/builtin_extension/clusters/lua-outbound-doesnt-apply-to-local-upstreams-with-envoy-constraint-violation.latest.golden new file mode 100644 index 0000000000..c010ac87b0 --- /dev/null +++ b/agent/xds/testdata/builtin_extension/clusters/lua-outbound-doesnt-apply-to-local-upstreams-with-envoy-constraint-violation.latest.golden @@ -0,0 +1,127 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "altStatName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "type": "EDS", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "connectTimeout": "5s", + "circuitBreakers": {}, + "outlierDetection": {}, + "commonLbConfig": { + "healthyPanicThreshold": {} + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + }, + "matchSubjectAltNames": [ + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/db" + } + ] + } + }, + "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "type": "EDS", + "edsClusterConfig": { + "edsConfig": { + "ads": {}, + "resourceApiVersion": "V3" + } + }, + "connectTimeout": "5s", + "circuitBreakers": {}, + "outlierDetection": {}, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + }, + "matchSubjectAltNames": [ + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/geo-cache-target" + }, + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/geo-cache-target" + } + ] + } + }, + "sni": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "local_app", + "type": "STATIC", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "local_app", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 8080 + } + } + } + } + ] + } + ] + } + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/endpoints/lua-outbound-doesnt-apply-to-local-upstreams-with-consul-constraint-violation.latest.golden b/agent/xds/testdata/builtin_extension/endpoints/lua-outbound-doesnt-apply-to-local-upstreams-with-consul-constraint-violation.latest.golden new file mode 100644 index 0000000000..5cb4171b97 --- /dev/null +++ b/agent/xds/testdata/builtin_extension/endpoints/lua-outbound-doesnt-apply-to-local-upstreams-with-consul-constraint-violation.latest.golden @@ -0,0 +1,75 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/endpoints/lua-outbound-doesnt-apply-to-local-upstreams-with-envoy-constraint-violation.latest.golden b/agent/xds/testdata/builtin_extension/endpoints/lua-outbound-doesnt-apply-to-local-upstreams-with-envoy-constraint-violation.latest.golden new file mode 100644 index 0000000000..5cb4171b97 --- /dev/null +++ b/agent/xds/testdata/builtin_extension/endpoints/lua-outbound-doesnt-apply-to-local-upstreams-with-envoy-constraint-violation.latest.golden @@ -0,0 +1,75 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "clusterName": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.10.1.1", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + }, + { + "endpoint": { + "address": { + "socketAddress": { + "address": "10.20.1.2", + "portValue": 8080 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + } + ], + "typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-local-upstreams-with-consul-constraint-violation.latest.golden b/agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-local-upstreams-with-consul-constraint-violation.latest.golden new file mode 100644 index 0000000000..8024198d7c --- /dev/null +++ b/agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-local-upstreams-with-consul-constraint-violation.latest.golden @@ -0,0 +1,265 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "db:127.0.0.1:9191", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "statPrefix": "upstream.db.default.default.dc1", + "routeConfig": { + "name": "db", + "virtualHosts": [ + { + "name": "db.default.default.dc1", + "domains": [ + "*" + ], + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "tracing": { + "randomSampling": {} + } + } + } + ] + } + ], + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "statPrefix": "upstream.prepared_query_geo-cache", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ], + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "public_listener:0.0.0.0:9999", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "statPrefix": "public_listener", + "routeConfig": { + "name": "public_listener", + "virtualHosts": [ + { + "name": "public_listener", + "domains": [ + "*" + ], + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "local_app" + } + } + ] + } + ] + }, + "httpFilters": [ + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": {} + } + }, + { + "name": "envoy.filters.http.header_to_metadata", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.header_to_metadata.v3.Config", + "requestRules": [ + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "metadataNamespace": "consul", + "key": "trust-domain", + "regexValueRewrite": { + "pattern": { + "googleRe2": {}, + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\1" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "metadataNamespace": "consul", + "key": "partition", + "regexValueRewrite": { + "pattern": { + "googleRe2": {}, + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\2" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "metadataNamespace": "consul", + "key": "namespace", + "regexValueRewrite": { + "pattern": { + "googleRe2": {}, + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\3" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "metadataNamespace": "consul", + "key": "datacenter", + "regexValueRewrite": { + "pattern": { + "googleRe2": {}, + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\4" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "metadataNamespace": "consul", + "key": "service", + "regexValueRewrite": { + "pattern": { + "googleRe2": {}, + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\5" + } + } + } + ] + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "tracing": { + "randomSampling": {} + }, + "forwardClientCertDetails": "APPEND_FORWARD", + "setCurrentClientCertDetails": { + "subject": true, + "cert": true, + "chain": true, + "dns": true, + "uri": true + } + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + }, + "alpnProtocols": [ + "http/1.1" + ] + }, + "requireClientCertificate": true + } + } + } + ], + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-local-upstreams-with-envoy-constraint-violation.latest.golden b/agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-local-upstreams-with-envoy-constraint-violation.latest.golden new file mode 100644 index 0000000000..8024198d7c --- /dev/null +++ b/agent/xds/testdata/builtin_extension/listeners/lua-outbound-doesnt-apply-to-local-upstreams-with-envoy-constraint-violation.latest.golden @@ -0,0 +1,265 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "db:127.0.0.1:9191", + "address": { + "socketAddress": { + "address": "127.0.0.1", + "portValue": 9191 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "statPrefix": "upstream.db.default.default.dc1", + "routeConfig": { + "name": "db", + "virtualHosts": [ + { + "name": "db.default.default.dc1", + "domains": [ + "*" + ], + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ] + }, + "httpFilters": [ + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "tracing": { + "randomSampling": {} + } + } + } + ] + } + ], + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "prepared_query:geo-cache:127.10.10.10:8181", + "address": { + "socketAddress": { + "address": "127.10.10.10", + "portValue": 8181 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "statPrefix": "upstream.prepared_query_geo-cache", + "cluster": "geo-cache.default.dc1.query.11111111-2222-3333-4444-555555555555.consul" + } + } + ] + } + ], + "trafficDirection": "OUTBOUND" + }, + { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "public_listener:0.0.0.0:9999", + "address": { + "socketAddress": { + "address": "0.0.0.0", + "portValue": 9999 + } + }, + "filterChains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "statPrefix": "public_listener", + "routeConfig": { + "name": "public_listener", + "virtualHosts": [ + { + "name": "public_listener", + "domains": [ + "*" + ], + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "local_app" + } + } + ] + } + ] + }, + "httpFilters": [ + { + "name": "envoy.filters.http.rbac", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": {} + } + }, + { + "name": "envoy.filters.http.header_to_metadata", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.header_to_metadata.v3.Config", + "requestRules": [ + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "metadataNamespace": "consul", + "key": "trust-domain", + "regexValueRewrite": { + "pattern": { + "googleRe2": {}, + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\1" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "metadataNamespace": "consul", + "key": "partition", + "regexValueRewrite": { + "pattern": { + "googleRe2": {}, + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\2" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "metadataNamespace": "consul", + "key": "namespace", + "regexValueRewrite": { + "pattern": { + "googleRe2": {}, + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\3" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "metadataNamespace": "consul", + "key": "datacenter", + "regexValueRewrite": { + "pattern": { + "googleRe2": {}, + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\4" + } + } + }, + { + "header": "x-forwarded-client-cert", + "onHeaderPresent": { + "metadataNamespace": "consul", + "key": "service", + "regexValueRewrite": { + "pattern": { + "googleRe2": {}, + "regex": ".*URI=spiffe://([^/]+.[^/]+)(?:/ap/([^/]+))?/ns/([^/]+)/dc/([^/]+)/svc/([^/;,]+).*" + }, + "substitution": "\\5" + } + } + } + ] + } + }, + { + "name": "envoy.filters.http.router", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "tracing": { + "randomSampling": {} + }, + "forwardClientCertDetails": "APPEND_FORWARD", + "setCurrentClientCertDetails": { + "subject": true, + "cert": true, + "chain": true, + "dns": true, + "uri": true + } + } + } + ], + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "commonTlsContext": { + "tlsParams": {}, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + } + }, + "alpnProtocols": [ + "http/1.1" + ] + }, + "requireClientCertificate": true + } + } + } + ], + "trafficDirection": "INBOUND" + } + ], + "typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/routes/lua-outbound-doesnt-apply-to-local-upstreams-with-consul-constraint-violation.latest.golden b/agent/xds/testdata/builtin_extension/routes/lua-outbound-doesnt-apply-to-local-upstreams-with-consul-constraint-violation.latest.golden new file mode 100644 index 0000000000..306f5220e7 --- /dev/null +++ b/agent/xds/testdata/builtin_extension/routes/lua-outbound-doesnt-apply-to-local-upstreams-with-consul-constraint-violation.latest.golden @@ -0,0 +1,5 @@ +{ + "versionInfo": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/builtin_extension/routes/lua-outbound-doesnt-apply-to-local-upstreams-with-envoy-constraint-violation.latest.golden b/agent/xds/testdata/builtin_extension/routes/lua-outbound-doesnt-apply-to-local-upstreams-with-envoy-constraint-violation.latest.golden new file mode 100644 index 0000000000..306f5220e7 --- /dev/null +++ b/agent/xds/testdata/builtin_extension/routes/lua-outbound-doesnt-apply-to-local-upstreams-with-envoy-constraint-violation.latest.golden @@ -0,0 +1,5 @@ +{ + "versionInfo": "00000001", + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "nonce": "00000001" +} \ No newline at end of file diff --git a/api/config_entry.go b/api/config_entry.go index b4cc966d1f..125619b55d 100644 --- a/api/config_entry.go +++ b/api/config_entry.go @@ -144,9 +144,11 @@ type ExposeConfig struct { // EnvoyExtension has configuration for an extension that patches Envoy resources. type EnvoyExtension struct { - Name string - Required bool - Arguments map[string]interface{} `bexpr:"-"` + Name string + Required bool + Arguments map[string]interface{} `bexpr:"-"` + ConsulVersion string + EnvoyVersion string } type ExposePath struct { diff --git a/envoyextensions/xdscommon/envoy_versioning.go b/envoyextensions/xdscommon/envoy_versioning.go index 06764f2b65..393a96bf9e 100644 --- a/envoyextensions/xdscommon/envoy_versioning.go +++ b/envoyextensions/xdscommon/envoy_versioning.go @@ -30,7 +30,7 @@ type SupportedProxyFeatures struct { } func DetermineSupportedProxyFeatures(node *envoy_core_v3.Node) (SupportedProxyFeatures, error) { - version := determineEnvoyVersionFromNode(node) + version := DetermineEnvoyVersionFromNode(node) return determineSupportedProxyFeaturesFromVersion(version) } @@ -69,7 +69,7 @@ func determineSupportedProxyFeaturesFromVersion(version *version.Version) (Suppo return sf, nil } -func determineEnvoyVersionFromNode(node *envoy_core_v3.Node) *version.Version { +func DetermineEnvoyVersionFromNode(node *envoy_core_v3.Node) *version.Version { if node == nil { return nil } diff --git a/envoyextensions/xdscommon/envoy_versioning_test.go b/envoyextensions/xdscommon/envoy_versioning_test.go index ff93182393..3e7507dec5 100644 --- a/envoyextensions/xdscommon/envoy_versioning_test.go +++ b/envoyextensions/xdscommon/envoy_versioning_test.go @@ -59,7 +59,7 @@ func TestDetermineEnvoyVersionFromNode(t *testing.T) { for name, tc := range cases { tc := tc t.Run(name, func(t *testing.T) { - got := determineEnvoyVersionFromNode(tc.node) + got := DetermineEnvoyVersionFromNode(tc.node) if tc.expect != nil { require.Equal(t, tc.expect, got) } else { diff --git a/proto/private/pbcommon/common.gen.go b/proto/private/pbcommon/common.gen.go index d7659b834e..c29598a2ab 100644 --- a/proto/private/pbcommon/common.gen.go +++ b/proto/private/pbcommon/common.gen.go @@ -11,6 +11,8 @@ func EnvoyExtensionToStructs(s *EnvoyExtension, t *structs.EnvoyExtension) { t.Name = s.Name t.Required = s.Required t.Arguments = ProtobufTypesStructToMapStringInterface(s.Arguments) + t.ConsulVersion = s.ConsulVersion + t.EnvoyVersion = s.EnvoyVersion } func EnvoyExtensionFromStructs(t *structs.EnvoyExtension, s *EnvoyExtension) { if s == nil { @@ -19,6 +21,8 @@ func EnvoyExtensionFromStructs(t *structs.EnvoyExtension, s *EnvoyExtension) { s.Name = t.Name s.Required = t.Required s.Arguments = MapStringInterfaceToProtobufTypesStruct(t.Arguments) + s.ConsulVersion = t.ConsulVersion + s.EnvoyVersion = t.EnvoyVersion } func LocalityToStructs(s *Locality, t *structs.Locality) { if s == nil { diff --git a/proto/private/pbcommon/common.pb.go b/proto/private/pbcommon/common.pb.go index 8a8ae5fe94..dd6240ad85 100644 --- a/proto/private/pbcommon/common.pb.go +++ b/proto/private/pbcommon/common.pb.go @@ -607,7 +607,9 @@ type EnvoyExtension struct { Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"` Required bool `protobuf:"varint,2,opt,name=Required,proto3" json:"Required,omitempty"` // mog: func-to=ProtobufTypesStructToMapStringInterface func-from=MapStringInterfaceToProtobufTypesStruct - Arguments *structpb.Struct `protobuf:"bytes,3,opt,name=Arguments,proto3" json:"Arguments,omitempty"` + Arguments *structpb.Struct `protobuf:"bytes,3,opt,name=Arguments,proto3" json:"Arguments,omitempty"` + ConsulVersion string `protobuf:"bytes,4,opt,name=ConsulVersion,proto3" json:"ConsulVersion,omitempty"` + EnvoyVersion string `protobuf:"bytes,5,opt,name=EnvoyVersion,proto3" json:"EnvoyVersion,omitempty"` } func (x *EnvoyExtension) Reset() { @@ -663,6 +665,20 @@ func (x *EnvoyExtension) GetArguments() *structpb.Struct { return nil } +func (x *EnvoyExtension) GetConsulVersion() string { + if x != nil { + return x.ConsulVersion + } + return "" +} + +func (x *EnvoyExtension) GetEnvoyVersion() string { + if x != nil { + return x.EnvoyVersion + } + return "" +} + // mog annotation: // // target=github.com/hashicorp/consul/agent/structs.Locality @@ -802,36 +818,40 @@ var file_private_pbcommon_common_proto_rawDesc = []byte{ 0x1c, 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x77, 0x0a, 0x0e, 0x45, - 0x6e, 0x76, 0x6f, 0x79, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, - 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, - 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x08, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x12, 0x35, 0x0a, - 0x09, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x09, 0x41, 0x72, 0x67, 0x75, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x22, 0x36, 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, - 0x12, 0x16, 0x0a, 0x06, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x5a, 0x6f, 0x6e, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x5a, 0x6f, 0x6e, 0x65, 0x42, 0x8b, 0x02, 0x0a, - 0x24, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, - 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x42, 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x2f, - 0x70, 0x62, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0xa2, 0x02, 0x04, 0x48, 0x43, 0x49, 0x43, 0xaa, - 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, - 0x6f, 0x6e, 0xca, 0x02, 0x20, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x43, - 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0xe2, 0x02, 0x2c, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x5c, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x23, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x3a, 0x3a, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xc1, 0x01, 0x0a, 0x0e, + 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, + 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, + 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x12, 0x35, + 0x0a, 0x09, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x09, 0x41, 0x72, 0x67, 0x75, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x43, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x45, + 0x6e, 0x76, 0x6f, 0x79, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x45, 0x6e, 0x76, 0x6f, 0x79, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, + 0x36, 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x52, + 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x52, 0x65, 0x67, + 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x5a, 0x6f, 0x6e, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x5a, 0x6f, 0x6e, 0x65, 0x42, 0x8b, 0x02, 0x0a, 0x24, 0x63, 0x6f, 0x6d, 0x2e, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, + 0x42, 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, + 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x2f, 0x70, 0x62, 0x63, 0x6f, 0x6d, + 0x6d, 0x6f, 0x6e, 0xa2, 0x02, 0x04, 0x48, 0x43, 0x49, 0x43, 0xaa, 0x02, 0x20, 0x48, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x49, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0xca, 0x02, 0x20, + 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, + 0xe2, 0x02, 0x2c, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x43, 0x6f, 0x6d, + 0x6d, 0x6f, 0x6e, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, + 0x02, 0x23, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x3a, 0x3a, 0x43, + 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/proto/private/pbcommon/common.proto b/proto/private/pbcommon/common.proto index 237e9b4e29..a86aa2dde5 100644 --- a/proto/private/pbcommon/common.proto +++ b/proto/private/pbcommon/common.proto @@ -185,6 +185,8 @@ message EnvoyExtension { bool Required = 2; // mog: func-to=ProtobufTypesStructToMapStringInterface func-from=MapStringInterfaceToProtobufTypesStruct google.protobuf.Struct Arguments = 3; + string ConsulVersion = 4; + string EnvoyVersion = 5; } // mog annotation: diff --git a/proto/private/pbcommon/convert_pbstruct.go b/proto/private/pbcommon/convert_pbstruct.go index 4370d7f2e7..e48dce9ae6 100644 --- a/proto/private/pbcommon/convert_pbstruct.go +++ b/proto/private/pbcommon/convert_pbstruct.go @@ -47,9 +47,11 @@ func EnvoyExtensionsToStructs(args []*EnvoyExtension) []structs.EnvoyExtension { var e structs.EnvoyExtension if args[i] != nil { e = structs.EnvoyExtension{ - Name: args[i].Name, - Required: args[i].Required, - Arguments: ProtobufTypesStructToMapStringInterface(args[i].Arguments), + Name: args[i].Name, + Required: args[i].Required, + ConsulVersion: args[i].ConsulVersion, + EnvoyVersion: args[i].EnvoyVersion, + Arguments: ProtobufTypesStructToMapStringInterface(args[i].Arguments), } } @@ -65,9 +67,11 @@ func EnvoyExtensionsFromStructs(args []structs.EnvoyExtension) []*EnvoyExtension o := make([]*EnvoyExtension, len(args)) for i, e := range args { o[i] = &EnvoyExtension{ - Name: e.Name, - Required: e.Required, - Arguments: MapStringInterfaceToProtobufTypesStruct(e.Arguments), + Name: e.Name, + Required: e.Required, + ConsulVersion: e.ConsulVersion, + EnvoyVersion: e.EnvoyVersion, + Arguments: MapStringInterfaceToProtobufTypesStruct(e.Arguments), } } From 9a4f503b2b379610ec6f7bf84db45c4d5a716fd9 Mon Sep 17 00:00:00 2001 From: Andrew Stucki Date: Thu, 8 Jun 2023 12:18:17 -0400 Subject: [PATCH 43/72] [API Gateway] Fix trust domain for external peered services in synthesis code (#17609) * [API Gateway] Fix trust domain for external peered services in synthesis code * Add changelog --- .changelog/17609.txt | 4 ++++ agent/proxycfg/snapshot.go | 15 ++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 .changelog/17609.txt diff --git a/.changelog/17609.txt b/.changelog/17609.txt new file mode 100644 index 0000000000..cbace1f8c7 --- /dev/null +++ b/.changelog/17609.txt @@ -0,0 +1,4 @@ +```release-note:bug +gateways: Fixed a bug in API gateways where binding a route that only targets a service imported from a peer results +in the programmed gateway having no routes. +``` diff --git a/agent/proxycfg/snapshot.go b/agent/proxycfg/snapshot.go index 5e92013b27..1880dcd669 100644 --- a/agent/proxycfg/snapshot.go +++ b/agent/proxycfg/snapshot.go @@ -741,14 +741,23 @@ type configSnapshotAPIGateway struct { func (c *configSnapshotAPIGateway) synthesizeChains(datacenter string, listener structs.APIGatewayListener, boundListener structs.BoundAPIGatewayListener) ([]structs.IngressService, structs.Upstreams, []*structs.CompiledDiscoveryChain, error) { chains := []*structs.CompiledDiscoveryChain{} - trustDomain := "" + + // We leverage the test trust domain knowing + // that the domain will get overridden if + // there is a target to something other than an + // external/peered service. If the below + // code doesn't get a trust domain due to all the + // targets being external, the chain will + // have the domain munged anyway during synthesis. + trustDomain := connect.TestTrustDomain DOMAIN_LOOP: for _, chain := range c.DiscoveryChain { for _, target := range chain.Targets { if !target.External { - trustDomain = connect.TrustDomainForTarget(*target) - if trustDomain != "" { + domain := connect.TrustDomainForTarget(*target) + if domain != "" { + trustDomain = domain break DOMAIN_LOOP } } From 17f46893796017dc9152ff014112644c6dddd4d0 Mon Sep 17 00:00:00 2001 From: Ronald Date: Thu, 8 Jun 2023 12:34:31 -0400 Subject: [PATCH 44/72] backport ent changes to oss (#17614) * backport ent changes to oss * Update .changelog/_5669.txt Co-authored-by: Michael Zalimeni --------- Co-authored-by: Michael Zalimeni --- .changelog/_5669.txt | 3 +++ api/api_test.go | 16 ++++++++++++++++ sdk/testutil/server.go | 6 ++++++ 3 files changed, 25 insertions(+) create mode 100644 .changelog/_5669.txt diff --git a/.changelog/_5669.txt b/.changelog/_5669.txt new file mode 100644 index 0000000000..6528460e69 --- /dev/null +++ b/.changelog/_5669.txt @@ -0,0 +1,3 @@ +```release-note:improvement +audit-logging: **(Enterprise only)** enable error response and request body logging +``` \ No newline at end of file diff --git a/api/api_test.go b/api/api_test.go index 49670b41eb..4d5dd1fda8 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -53,6 +53,22 @@ func makeACLClient(t *testing.T) (*Client, *testutil.TestServer) { }) } +// Makes a client with Audit enabled, it requires ACLs +func makeAuditClient(t *testing.T) (*Client, *testutil.TestServer) { + return makeClientWithConfig(t, func(clientConfig *Config) { + clientConfig.Token = "root" + }, func(serverConfig *testutil.TestServerConfig) { + serverConfig.PrimaryDatacenter = "dc1" + serverConfig.ACL.Tokens.InitialManagement = "root" + serverConfig.ACL.Tokens.Agent = "root" + serverConfig.ACL.Enabled = true + serverConfig.ACL.DefaultPolicy = "deny" + serverConfig.Audit = &testutil.TestAuditConfig{ + Enabled: true, + } + }) +} + func makeNonBootstrappedACLClient(t *testing.T, defaultPolicy string) (*Client, *testutil.TestServer) { return makeClientWithConfig(t, func(clientConfig *Config) { diff --git a/sdk/testutil/server.go b/sdk/testutil/server.go index 1c7167d98d..d00850d5e1 100644 --- a/sdk/testutil/server.go +++ b/sdk/testutil/server.go @@ -75,6 +75,11 @@ type TestNetworkSegment struct { Advertise string `json:"advertise"` } +// TestAudigConfig contains the configuration for Audit +type TestAuditConfig struct { + Enabled bool `json:"enabled,omitempty"` +} + // Locality is used as the TestServerConfig's Locality. type Locality struct { Region string `json:"region"` @@ -124,6 +129,7 @@ type TestServerConfig struct { Stderr io.Writer `json:"-"` Args []string `json:"-"` ReturnPorts func() `json:"-"` + Audit *TestAuditConfig `json:"audit,omitempty"` } type TestACLs struct { From 85982889a1801ecf4596f9afd013d09da84a2708 Mon Sep 17 00:00:00 2001 From: Luke Kysow <1034429+lkysow@users.noreply.github.com> Date: Thu, 8 Jun 2023 13:30:05 -0700 Subject: [PATCH 45/72] Update intentions.mdx (#17619) Make behaviour of L7 intentions clearer --- website/content/api-docs/connect/intentions.mdx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/website/content/api-docs/connect/intentions.mdx b/website/content/api-docs/connect/intentions.mdx index cdfeb463cd..20a6b5054b 100644 --- a/website/content/api-docs/connect/intentions.mdx +++ b/website/content/api-docs/connect/intentions.mdx @@ -536,9 +536,7 @@ This endpoint evaluates the intentions for a specific source and destination and returns whether the connection would be authorized or not given the current Consul configuration and set of intentions. --> **Note:** This endpoint will always evaluate intentions with `Permissions` -defined as _deny_ intentions during. This endpoint is only suited for -networking layer 4 (e.g. TCP) integration. +-> **Note:** This endpoint will always evaluate matching intentions with L7 `Permissions` defined as _deny_ intentions because there is no request to check against. For performance and reliability reasons it is desirable to implement intention enforcement by listing [intentions that match the From 7ae457c5867a446a1e694c10eb03a9ca723dfb6c Mon Sep 17 00:00:00 2001 From: Ronald Date: Thu, 8 Jun 2023 19:50:51 -0400 Subject: [PATCH 46/72] enterprise changelog update for audit (#17625) --- .changelog/_5805.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/_5805.txt diff --git a/.changelog/_5805.txt b/.changelog/_5805.txt new file mode 100644 index 0000000000..786effc310 --- /dev/null +++ b/.changelog/_5805.txt @@ -0,0 +1,3 @@ +```release-note:security +audit-logging: **(Enterprise only)** limit `v1/operator/audit-hash` endpoint to ACL token with `operator:read` privileges. +``` \ No newline at end of file From 30e0c234abce0f0a0dba46bb950dc533fb273c7f Mon Sep 17 00:00:00 2001 From: Michael Zalimeni Date: Thu, 8 Jun 2023 22:37:49 -0400 Subject: [PATCH 47/72] Update list of Envoy versions (#17546) --- .changelog/17546.txt | 3 +++ .github/workflows/test-integrations.yml | 4 ++-- envoyextensions/xdscommon/envoy_versioning_test.go | 7 ++++--- envoyextensions/xdscommon/proxysupport.go | 8 ++++---- website/content/docs/connect/proxies/envoy.mdx | 2 +- 5 files changed, 14 insertions(+), 10 deletions(-) create mode 100644 .changelog/17546.txt diff --git a/.changelog/17546.txt b/.changelog/17546.txt new file mode 100644 index 0000000000..6f40255539 --- /dev/null +++ b/.changelog/17546.txt @@ -0,0 +1,3 @@ +```release-note:improvement +connect: update supported envoy versions to 1.23.10, 1.24.8, 1.25.7, 1.26.2 +``` diff --git a/.github/workflows/test-integrations.yml b/.github/workflows/test-integrations.yml index 260044aee8..38b6a44cbe 100644 --- a/.github/workflows/test-integrations.yml +++ b/.github/workflows/test-integrations.yml @@ -239,7 +239,7 @@ jobs: # this is further going to multiplied in envoy-integration tests by the # other dimensions in the matrix. Currently TOTAL_RUNNERS would be # multiplied by 8 based on these values: - # envoy-version: ["1.23.8", "1.24.6", "1.25.4", "1.26.0"] + # envoy-version: ["1.23.10", "1.24.8", "1.25.7", "1.26.2"] # xds-target: ["server", "client"] TOTAL_RUNNERS: 4 JQ_SLICER: '[ inputs ] | [_nwise(length / $runnercount | floor)]' @@ -273,7 +273,7 @@ jobs: strategy: fail-fast: false matrix: - envoy-version: ["1.23.8", "1.24.6", "1.25.4", "1.26.0"] + envoy-version: ["1.23.10", "1.24.8", "1.25.7", "1.26.2"] xds-target: ["server", "client"] test-cases: ${{ fromJSON(needs.generate-envoy-job-matrices.outputs.envoy-matrix) }} env: diff --git a/envoyextensions/xdscommon/envoy_versioning_test.go b/envoyextensions/xdscommon/envoy_versioning_test.go index 3e7507dec5..cc2134c732 100644 --- a/envoyextensions/xdscommon/envoy_versioning_test.go +++ b/envoyextensions/xdscommon/envoy_versioning_test.go @@ -151,9 +151,10 @@ func TestDetermineSupportedProxyFeaturesFromString(t *testing.T) { } */ for _, v := range []string{ - "1.23.0", "1.23.1", "1.23.2", "1.23.3", "1.23.4", "1.23.5", "1.23.6", "1.23.7", "1.23.8", - "1.24.0", "1.24.1", "1.24.2", "1.24.3", "1.24.4", "1.24.5", "1.24.6", - "1.25.0", "1.25.1", "1.25.2", "1.25.3", "1.25.4", "1.26.0", + "1.23.0", "1.23.1", "1.23.2", "1.23.3", "1.23.4", "1.23.5", "1.23.6", "1.23.7", "1.23.8", "1.23.9", "1.23.10", + "1.24.0", "1.24.1", "1.24.2", "1.24.3", "1.24.4", "1.24.5", "1.24.6", "1.24.7", "1.24.8", + "1.25.0", "1.25.1", "1.25.2", "1.25.3", "1.25.4", "1.25.5", "1.25.6", "1.25.7", + "1.26.0", "1.26.1", "1.26.2", } { cases[v] = testcase{expect: SupportedProxyFeatures{}} } diff --git a/envoyextensions/xdscommon/proxysupport.go b/envoyextensions/xdscommon/proxysupport.go index ff4b79d735..250133a138 100644 --- a/envoyextensions/xdscommon/proxysupport.go +++ b/envoyextensions/xdscommon/proxysupport.go @@ -12,10 +12,10 @@ import "strings" // // see: https://www.consul.io/docs/connect/proxies/envoy#supported-versions var EnvoyVersions = []string{ - "1.26.0", - "1.25.4", - "1.24.6", - "1.23.8", + "1.26.2", + "1.25.7", + "1.24.8", + "1.23.10", } // UnsupportedEnvoyVersions lists any unsupported Envoy versions (mainly minor versions) that fall diff --git a/website/content/docs/connect/proxies/envoy.mdx b/website/content/docs/connect/proxies/envoy.mdx index 65a01ca615..e6759113c2 100644 --- a/website/content/docs/connect/proxies/envoy.mdx +++ b/website/content/docs/connect/proxies/envoy.mdx @@ -39,7 +39,7 @@ Consul supports **four major Envoy releases** at the beginning of each major Con | Consul Version | Compatible Envoy Versions | | ------------------- | -----------------------------------------------------------------------------------| -| 1.15.x | 1.25.4, 1.24.6, 1.23.8, 1.22.11 | +| 1.15.x | 1.25.6, 1.24.7, 1.23.9, 1.22.11 | | 1.14.x | 1.24.0, 1.23.1, 1.22.5, 1.21.5 | | 1.13.x | 1.23.1, 1.22.5, 1.21.5, 1.20.7 | From 3cb70566a907423795b8e218111f2efc8acb52c2 Mon Sep 17 00:00:00 2001 From: Andrew Stucki Date: Fri, 9 Jun 2023 08:22:32 -0400 Subject: [PATCH 48/72] [API Gateway] Fix rate limiting for API gateways (#17631) * [API Gateway] Fix rate limiting for API gateways * Add changelog * Fix failing unit tests * Fix operator usage tests for api package --- .changelog/17631.txt | 3 + agent/consul/state/state_store_test.go | 19 +++++- agent/consul/state/usage.go | 1 + agent/consul/state/usage_test.go | 15 +++- .../usagemetrics/usagemetrics_oss_test.go | 68 ++++++++++++++++--- agent/operator_endpoint_oss_test.go | 1 + agent/structs/testing_catalog.go | 8 +++ api/operator_usage_test.go | 1 + 8 files changed, 104 insertions(+), 12 deletions(-) create mode 100644 .changelog/17631.txt diff --git a/.changelog/17631.txt b/.changelog/17631.txt new file mode 100644 index 0000000000..b24b7461ec --- /dev/null +++ b/.changelog/17631.txt @@ -0,0 +1,3 @@ +```release-note:bug +gateways: Fixed a bug where API gateways were not being taken into account in determining xDS rate limits. +``` diff --git a/agent/consul/state/state_store_test.go b/agent/consul/state/state_store_test.go index dfe8c988b3..fef7502532 100644 --- a/agent/consul/state/state_store_test.go +++ b/agent/consul/state/state_store_test.go @@ -203,11 +203,27 @@ func testRegisterConnectService(t *testing.T, s *Store, idx uint64, nodeID, serv }) } +func testRegisterAPIService(t *testing.T, s *Store, idx uint64, nodeID, serviceID string) { + testRegisterGatewayService(t, s, structs.ServiceKindAPIGateway, idx, nodeID, serviceID) +} + +func testRegisterTerminatingService(t *testing.T, s *Store, idx uint64, nodeID, serviceID string) { + testRegisterGatewayService(t, s, structs.ServiceKindTerminatingGateway, idx, nodeID, serviceID) +} + func testRegisterIngressService(t *testing.T, s *Store, idx uint64, nodeID, serviceID string) { + testRegisterGatewayService(t, s, structs.ServiceKindIngressGateway, idx, nodeID, serviceID) +} + +func testRegisterMeshService(t *testing.T, s *Store, idx uint64, nodeID, serviceID string) { + testRegisterGatewayService(t, s, structs.ServiceKindMeshGateway, idx, nodeID, serviceID) +} + +func testRegisterGatewayService(t *testing.T, s *Store, kind structs.ServiceKind, idx uint64, nodeID, serviceID string) { svc := &structs.NodeService{ ID: serviceID, Service: serviceID, - Kind: structs.ServiceKindIngressGateway, + Kind: kind, Address: "1.1.1.1", Port: 1111, } @@ -227,6 +243,7 @@ func testRegisterIngressService(t *testing.T, s *Store, idx uint64, nodeID, serv t.Fatalf("bad service: %#v", result) } } + func testRegisterCheck(t *testing.T, s *Store, idx uint64, nodeID string, serviceID string, checkID types.CheckID, state string) { testRegisterCheckWithPartition(t, s, idx, diff --git a/agent/consul/state/usage.go b/agent/consul/state/usage.go index 8e455241c2..b379410550 100644 --- a/agent/consul/state/usage.go +++ b/agent/consul/state/usage.go @@ -25,6 +25,7 @@ var allConnectKind = []string{ string(structs.ServiceKindIngressGateway), string(structs.ServiceKindMeshGateway), string(structs.ServiceKindTerminatingGateway), + string(structs.ServiceKindAPIGateway), connectNativeInstancesTable, } diff --git a/agent/consul/state/usage_test.go b/agent/consul/state/usage_test.go index 6ccaddb9f7..68844ebc11 100644 --- a/agent/consul/state/usage_test.go +++ b/agent/consul/state/usage_test.go @@ -179,16 +179,25 @@ func TestStateStore_Usage_ServiceUsage(t *testing.T) { testRegisterConnectNativeService(t, s, 13, "node1", "service-native") testRegisterConnectNativeService(t, s, 14, "node2", "service-native") testRegisterConnectNativeService(t, s, 15, "node2", "service-native-1") + testRegisterIngressService(t, s, 16, "node1", "ingress") + testRegisterMeshService(t, s, 17, "node1", "mesh") + testRegisterTerminatingService(t, s, 18, "node1", "terminating") + testRegisterAPIService(t, s, 19, "node1", "api") + testRegisterAPIService(t, s, 20, "node2", "api") ws := memdb.NewWatchSet() idx, usage, err := s.ServiceUsage(ws) require.NoError(t, err) - require.Equal(t, idx, uint64(15)) - require.Equal(t, 5, usage.Services) - require.Equal(t, 8, usage.ServiceInstances) + require.Equal(t, idx, uint64(20)) + require.Equal(t, 9, usage.Services) + require.Equal(t, 13, usage.ServiceInstances) require.Equal(t, 2, usage.ConnectServiceInstances[string(structs.ServiceKindConnectProxy)]) require.Equal(t, 3, usage.ConnectServiceInstances[connectNativeInstancesTable]) require.Equal(t, 6, usage.BillableServiceInstances) + require.Equal(t, 2, usage.ConnectServiceInstances[string(structs.ServiceKindAPIGateway)]) + require.Equal(t, 1, usage.ConnectServiceInstances[string(structs.ServiceKindIngressGateway)]) + require.Equal(t, 1, usage.ConnectServiceInstances[string(structs.ServiceKindTerminatingGateway)]) + require.Equal(t, 1, usage.ConnectServiceInstances[string(structs.ServiceKindMeshGateway)]) testRegisterSidecarProxy(t, s, 16, "node2", "service2") diff --git a/agent/consul/usagemetrics/usagemetrics_oss_test.go b/agent/consul/usagemetrics/usagemetrics_oss_test.go index 1781dca4c5..8a4b511577 100644 --- a/agent/consul/usagemetrics/usagemetrics_oss_test.go +++ b/agent/consul/usagemetrics/usagemetrics_oss_test.go @@ -149,6 +149,22 @@ var baseCases = map[string]testCase{ {Name: "kind", Value: "ingress-gateway"}, }, }, + "consul.usage.test.consul.state.connect_instances;datacenter=dc1;kind=api-gateway": { // Legacy + Name: "consul.usage.test.consul.state.connect_instances", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "api-gateway"}, + }, + }, + "consul.usage.test.state.connect_instances;datacenter=dc1;kind=api-gateway": { + Name: "consul.usage.test.state.connect_instances", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "api-gateway"}, + }, + }, "consul.usage.test.consul.state.connect_instances;datacenter=dc1;kind=mesh-gateway": { // Legacy Name: "consul.usage.test.consul.state.connect_instances", Value: 0, @@ -624,6 +640,22 @@ var baseCases = map[string]testCase{ {Name: "kind", Value: "ingress-gateway"}, }, }, + "consul.usage.test.consul.state.connect_instances;datacenter=dc1;kind=api-gateway": { // Legacy + Name: "consul.usage.test.consul.state.connect_instances", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "api-gateway"}, + }, + }, + "consul.usage.test.state.connect_instances;datacenter=dc1;kind=api-gateway": { + Name: "consul.usage.test.state.connect_instances", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "api-gateway"}, + }, + }, "consul.usage.test.consul.state.connect_instances;datacenter=dc1;kind=mesh-gateway": { // Legacy Name: "consul.usage.test.consul.state.connect_instances", Value: 0, @@ -1127,6 +1159,9 @@ func TestUsageReporter_emitServiceUsage_OSS(t *testing.T) { require.NoError(t, s.EnsureNode(3, &structs.Node{Node: "baz", Address: "127.0.0.2"})) require.NoError(t, s.EnsureNode(4, &structs.Node{Node: "qux", Address: "127.0.0.3"})) + apigw := structs.TestNodeServiceAPIGateway(t) + apigw.ID = "api-gateway" + mgw := structs.TestNodeServiceMeshGateway(t) mgw.ID = "mesh-gateway" @@ -1141,16 +1176,17 @@ func TestUsageReporter_emitServiceUsage_OSS(t *testing.T) { require.NoError(t, s.EnsureRegistration(10, structs.TestRegisterIngressGateway(t))) require.NoError(t, s.EnsureService(11, "foo", mgw)) require.NoError(t, s.EnsureService(12, "foo", tgw)) - require.NoError(t, s.EnsureService(13, "bar", &structs.NodeService{ID: "db-native", Service: "db", Tags: nil, Address: "", Port: 5000, Connect: structs.ServiceConnect{Native: true}})) - require.NoError(t, s.EnsureConfigEntry(14, &structs.IngressGatewayConfigEntry{ + require.NoError(t, s.EnsureService(13, "foo", apigw)) + require.NoError(t, s.EnsureService(14, "bar", &structs.NodeService{ID: "db-native", Service: "db", Tags: nil, Address: "", Port: 5000, Connect: structs.ServiceConnect{Native: true}})) + require.NoError(t, s.EnsureConfigEntry(15, &structs.IngressGatewayConfigEntry{ Kind: structs.IngressGateway, Name: "foo", })) - require.NoError(t, s.EnsureConfigEntry(15, &structs.IngressGatewayConfigEntry{ + require.NoError(t, s.EnsureConfigEntry(16, &structs.IngressGatewayConfigEntry{ Kind: structs.IngressGateway, Name: "bar", })) - require.NoError(t, s.EnsureConfigEntry(16, &structs.IngressGatewayConfigEntry{ + require.NoError(t, s.EnsureConfigEntry(17, &structs.IngressGatewayConfigEntry{ Kind: structs.IngressGateway, Name: "baz", })) @@ -1191,22 +1227,22 @@ func TestUsageReporter_emitServiceUsage_OSS(t *testing.T) { } nodesAndSvcsCase.expectedGauges["consul.usage.test.consul.state.services;datacenter=dc1"] = metrics.GaugeValue{ // Legacy Name: "consul.usage.test.consul.state.services", - Value: 7, + Value: 8, Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, } nodesAndSvcsCase.expectedGauges["consul.usage.test.state.services;datacenter=dc1"] = metrics.GaugeValue{ Name: "consul.usage.test.state.services", - Value: 7, + Value: 8, Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, } nodesAndSvcsCase.expectedGauges["consul.usage.test.consul.state.service_instances;datacenter=dc1"] = metrics.GaugeValue{ // Legacy Name: "consul.usage.test.consul.state.service_instances", - Value: 9, + Value: 10, Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, } nodesAndSvcsCase.expectedGauges["consul.usage.test.state.service_instances;datacenter=dc1"] = metrics.GaugeValue{ Name: "consul.usage.test.state.service_instances", - Value: 9, + Value: 10, Labels: []metrics.Label{{Name: "datacenter", Value: "dc1"}}, } nodesAndSvcsCase.expectedGauges["consul.usage.test.consul.state.connect_instances;datacenter=dc1;kind=connect-proxy"] = metrics.GaugeValue{ // Legacy @@ -1257,6 +1293,22 @@ func TestUsageReporter_emitServiceUsage_OSS(t *testing.T) { {Name: "kind", Value: "ingress-gateway"}, }, } + nodesAndSvcsCase.expectedGauges["consul.usage.test.consul.state.connect_instances;datacenter=dc1;kind=api-gateway"] = metrics.GaugeValue{ // Legacy + Name: "consul.usage.test.consul.state.connect_instances", + Value: 1, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "api-gateway"}, + }, + } + nodesAndSvcsCase.expectedGauges["consul.usage.test.state.connect_instances;datacenter=dc1;kind=api-gateway"] = metrics.GaugeValue{ + Name: "consul.usage.test.state.connect_instances", + Value: 1, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "api-gateway"}, + }, + } nodesAndSvcsCase.expectedGauges["consul.usage.test.consul.state.connect_instances;datacenter=dc1;kind=mesh-gateway"] = metrics.GaugeValue{ // Legacy Name: "consul.usage.test.consul.state.connect_instances", Value: 1, diff --git a/agent/operator_endpoint_oss_test.go b/agent/operator_endpoint_oss_test.go index ea144cffa6..90f0e7d0cd 100644 --- a/agent/operator_endpoint_oss_test.go +++ b/agent/operator_endpoint_oss_test.go @@ -56,6 +56,7 @@ func TestOperator_Usage(t *testing.T) { Services: 5, ServiceInstances: 6, ConnectServiceInstances: map[string]int{ + "api-gateway": 0, "connect-native": 1, "connect-proxy": 1, "ingress-gateway": 0, diff --git a/agent/structs/testing_catalog.go b/agent/structs/testing_catalog.go index 0e560b3906..9e72aebc77 100644 --- a/agent/structs/testing_catalog.go +++ b/agent/structs/testing_catalog.go @@ -174,6 +174,14 @@ func TestNodeServiceMeshGateway(t testing.T) *NodeService { ServiceAddress{Address: "198.18.4.5", Port: 443}) } +func TestNodeServiceAPIGateway(t testing.T) *NodeService { + return &NodeService{ + Kind: ServiceKindAPIGateway, + Service: "api-gateway", + Address: "1.1.1.1", + } +} + func TestNodeServiceTerminatingGateway(t testing.T, address string) *NodeService { return &NodeService{ Kind: ServiceKindTerminatingGateway, diff --git a/api/operator_usage_test.go b/api/operator_usage_test.go index a276682e07..77b15fcdb5 100644 --- a/api/operator_usage_test.go +++ b/api/operator_usage_test.go @@ -56,6 +56,7 @@ func TestAPI_OperatorUsage(t *testing.T) { require.Equal(t, 4, usage.Usage["dc1"].Services) require.Equal(t, 5, usage.Usage["dc1"].ServiceInstances) require.Equal(t, map[string]int{ + "api-gateway": 0, "connect-native": 1, "connect-proxy": 1, "ingress-gateway": 0, From ec347ef01d8a43b9d8407750a8c92bd1d5d404e7 Mon Sep 17 00:00:00 2001 From: "R.B. Boyer" <4903+rboyer@users.noreply.github.com> Date: Fri, 9 Jun 2023 11:30:56 -0500 Subject: [PATCH 49/72] sort some imports that are wonky between oss and ent (#17637) --- agent/agent_endpoint.go | 10 ++++------ agent/agent_endpoint_test.go | 6 ++---- agent/proxycfg/mesh_gateway.go | 1 - 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/agent/agent_endpoint.go b/agent/agent_endpoint.go index 13e993fc70..d63936e294 100644 --- a/agent/agent_endpoint.go +++ b/agent/agent_endpoint.go @@ -11,16 +11,12 @@ import ( "strings" "time" + "github.com/hashicorp/go-bexpr" "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-memdb" - "github.com/mitchellh/hashstructure" - - "github.com/hashicorp/consul/envoyextensions/xdscommon" - "github.com/hashicorp/consul/version" - - "github.com/hashicorp/go-bexpr" "github.com/hashicorp/serf/coordinate" "github.com/hashicorp/serf/serf" + "github.com/mitchellh/hashstructure" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" @@ -31,11 +27,13 @@ import ( "github.com/hashicorp/consul/agent/structs" token_store "github.com/hashicorp/consul/agent/token" "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/envoyextensions/xdscommon" "github.com/hashicorp/consul/ipaddr" "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/logging" "github.com/hashicorp/consul/logging/monitor" "github.com/hashicorp/consul/types" + "github.com/hashicorp/consul/version" ) type Self struct { diff --git a/agent/agent_endpoint_test.go b/agent/agent_endpoint_test.go index 2955871c72..fc0345cee4 100644 --- a/agent/agent_endpoint_test.go +++ b/agent/agent_endpoint_test.go @@ -21,10 +21,6 @@ import ( "time" "github.com/armon/go-metrics" - - "github.com/hashicorp/consul/api" - "github.com/hashicorp/consul/version" - "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-uuid" "github.com/hashicorp/serf/serf" @@ -44,12 +40,14 @@ import ( "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/token" tokenStore "github.com/hashicorp/consul/agent/token" + "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/envoyextensions/xdscommon" "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/sdk/testutil" "github.com/hashicorp/consul/sdk/testutil/retry" "github.com/hashicorp/consul/testrpc" "github.com/hashicorp/consul/types" + "github.com/hashicorp/consul/version" ) func createACLTokenWithAgentReadPolicy(t *testing.T, srv *HTTPHandlers) string { diff --git a/agent/proxycfg/mesh_gateway.go b/agent/proxycfg/mesh_gateway.go index 2267a2960a..cf090b7b04 100644 --- a/agent/proxycfg/mesh_gateway.go +++ b/agent/proxycfg/mesh_gateway.go @@ -15,7 +15,6 @@ import ( "github.com/hashicorp/go-hclog" "github.com/hashicorp/consul/acl" - cachetype "github.com/hashicorp/consul/agent/cache-types" "github.com/hashicorp/consul/agent/proxycfg/internal/watch" "github.com/hashicorp/consul/agent/structs" From 5e846747f4602dd08f3f1a877b95af48c2c3cce7 Mon Sep 17 00:00:00 2001 From: trujillo-adam <47586768+trujillo-adam@users.noreply.github.com> Date: Sat, 10 Jun 2023 08:35:22 -0700 Subject: [PATCH 50/72] PmTLS and tproxy improvements with failover and L7 traffic mgmt for k8s (#17624) * porting over changes from enterprise repo to oss * applied feedback on service mesh for k8s overview * fixed typo * removed ent-only build script file * Apply suggestions from code review Co-authored-by: Jeff Boruszak <104028618+boruszak@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: David Yu Co-authored-by: Jeff Boruszak <104028618+boruszak@users.noreply.github.com> --------- Co-authored-by: Jeff Boruszak <104028618+boruszak@users.noreply.github.com> Co-authored-by: David Yu --- .../content/docs/connect/failover/index.mdx | 45 +++ .../content/docs/connect/l7-traffic/index.mdx | 132 +++----- website/content/docs/k8s/connect/index.mdx | 71 ++--- .../k8s/connect/onboarding-tproxy-mode.mdx | 295 ++++++++++++++++++ .../enable-transparent-proxy.mdx} | 76 ++--- .../k8s/connect/transparent-proxy/index.mdx | 47 +++ .../docs/k8s/l7-traffic/failover-tproxy.mdx | 124 ++++++++ .../l7-traffic/route-to-virtual-services.mdx | 122 ++++++++ website/data/docs-nav-data.json | 79 ++++- 9 files changed, 795 insertions(+), 196 deletions(-) create mode 100644 website/content/docs/connect/failover/index.mdx create mode 100644 website/content/docs/k8s/connect/onboarding-tproxy-mode.mdx rename website/content/docs/{connect/transparent-proxy.mdx => k8s/connect/transparent-proxy/enable-transparent-proxy.mdx} (81%) create mode 100644 website/content/docs/k8s/connect/transparent-proxy/index.mdx create mode 100644 website/content/docs/k8s/l7-traffic/failover-tproxy.mdx create mode 100644 website/content/docs/k8s/l7-traffic/route-to-virtual-services.mdx diff --git a/website/content/docs/connect/failover/index.mdx b/website/content/docs/connect/failover/index.mdx new file mode 100644 index 0000000000..2d96906440 --- /dev/null +++ b/website/content/docs/connect/failover/index.mdx @@ -0,0 +1,45 @@ +--- +layout: docs +page_title: Failover configuration overview +description: Learn about failover strategies and service mesh features you can implement to route traffic if services become unhealthy or unreachable, including sameness groups, prepared queries, and service resolvers. +--- + +# Failover overview + +Services in your mesh may become unhealthy or unreachable for many reasons, but you can mitigate some of the effects associated with infrastructure issues by configuring Consul to automatically route traffic to and from failover service instances. This topic provides an overview of the failover strategies you can implement with Consul. + +## Service failover strategies in Consul + +There are several methods for implementing failover strategies between datacenters in Consul. You can adopt one of the following strategies based on your deployment configuration and network requirements: + +- Configure the `Failover` stanza in a service resolver configuration entry to explicitly define which services should failover and the targeting logic they should follow. +- Make a prepared query for each service that you can use to automate geo-failover. +- Create a sameness group to identify partitions with identical namespaces and service names to establish default failover targets. + +The following table compares these strategies in deployments with multiple datacenters to help you determine the best approach for your service: + +| Failover Strategy | Supports WAN Federation | Supports Cluster Peering | Multi-Datacenter Failover Strength | Multi-Datacenter Usage Scenario | +| :---------------: | :---------------------: | :----------------------: | :--------------------------------- | :------------------------------ | +| `Failover` stanza | ✅ | ✅ | Enables more granular logic for failover targeting | Configuring failover for a single service or service subset, especially for testing or debugging purposes | +| Prepared query | ✅ | ✅ | Central policies that can automatically target the nearest datacenter | WAN-federated deployments where a primary datacenter is configured. Prepared queries are not replicated over peer connections. | +| Sameness groups | ❌ | ✅ | Group size changes without edits to existing member configurations | Cluster peering deployments with consistently named services and namespaces | + +### Failover configurations for a service mesh with a single datacenter + +You can implement a service resolver configuration entry and specify a pool of failover service instances that other services can exchange messages with when the primary service becomes unhealthy or unreachable. We recommend adopting this strategy as a minimum baseline when implementing Consul service mesh and layering additional failover strategies to build resilience into your application network. + +Refer to the [`Failover` configuration ](/consul/docs/connect/config-entries/service-resolver#failover) for examples of how to configure failover services in the service resolver configuration entry on both VMs and Kubernetes deployments. + +### Failover configuration for WAN-federated datacenters + +If your network has multiple Consul datacenters that are WAN-federated, you can configure your applications to look for failover services with prepared queries. [Prepared queries](/consul/api-docs/) are configurations that enable you to define complex service discovery lookups. This strategy hinges on the secondary datacenter containing service instances that have the same name and residing in the same namespace as their counterparts in the primary datacenter. + +Refer to the [Automate geo-failover with prepared queries tutorial](/consul/tutorials/developer-discovery/automate-geo-failover) for additional information. + +### Failover configuration for peered clusters and partitions + +In networks with multiple datacenters or partitions that share a peer connection, each datacenter or partition functions as an independent unit. As a result, Consul does not correlate services that have the same name, even if they are in the same namespace. + +You can configure sameness groups for this type of network. Sameness groups allow you to define a group of admin partitions where identical services are deployed in identical namespaces. After you configure the sameness group, you can reference the `SamenessGroup` parameter in service resolver, exported service, and service intention configuration entries, enabling you to add or remove cluster peers from the group without making changes to every cluster peer every time. + +Refer to [Sameness groups usage page](/consul/docs/connect/cluster-peering/usage/sameness-groups) for more information. diff --git a/website/content/docs/connect/l7-traffic/index.mdx b/website/content/docs/connect/l7-traffic/index.mdx index 9f5fe8da2b..3fb7b392b8 100644 --- a/website/content/docs/connect/l7-traffic/index.mdx +++ b/website/content/docs/connect/l7-traffic/index.mdx @@ -1,126 +1,80 @@ --- layout: docs -page_title: Service Mesh Traffic Management - Overview +page_title: Service mesh traffic management overview description: >- Consul can route, split, and resolve Layer 7 traffic in a service mesh to support workflows like canary testing and blue/green deployments. Learn about the three configuration entry kinds that define L7 traffic management behavior in Consul. --- --> **1.6.0+:** This feature is available in Consul versions 1.6.0 and newer. +# Service mesh traffic management overview -# Service Mesh Traffic Management Overview +This topic provides overview information about the application layer traffic management capabilities available in Consul service mesh. These capabilities are also referred to as *Layer 7* or *L7 traffic management*. -Layer 7 traffic management allows operators to divide L7 traffic between -different -[subsets](/consul/docs/connect/config-entries/service-resolver#service-subsets) of -service instances when using service mesh. +## Introduction -There are many ways you may wish to carve up a single datacenter's pool of -services beyond simply returning all healthy instances for load balancing. -Canary testing, A/B tests, blue/green deploys, and soft multi-tenancy -(prod/qa/staging sharing compute resources) all require some mechanism of -carving out portions of the Consul catalog smaller than the level of a single -service and configuring when that subset should receive traffic. +Consul service mesh allows you to divide application layer traffic between different subsets of service instances. You can leverage L7 traffic management capabilities to perform complex processes, such as configuring backup services for failover scenarios, canary and A-B testing, blue-green deployments, and soft multi-tenancy in which production, QA, and staging environments share compute resources. L7 traffic management with Consul service mesh allows you to designate groups of service instances in the Consul catalog smaller than all instances of single service and configure when that subset should receive traffic. --> **Note:** This feature is not compatible with the -[built-in proxy](/consul/docs/connect/proxies/built-in), -[native proxies](/consul/docs/connect/native), -and some [Envoy proxy escape hatches](/consul/docs/connect/proxies/envoy#escape-hatch-overrides). +You cannot manage L7 traffic with the [built-in proxy](/consul/docs/connect/proxies/built-in), +[native proxies](/consul/docs/connect/native), or some [Envoy proxy escape hatches](/consul/docs/connect/proxies/envoy#escape-hatch-overrides). -## Stages +## Discovery chain -Service mesh proxy upstreams are discovered using a series of stages: routing, -splitting, and resolution. These stages represent different ways of managing L7 -traffic. +Consul uses a series of stages to discover service mesh proxy upstreams. Each stage represents different ways of managing L7 traffic. They are referred to as the _discovery chain_: -![screenshot of L7 traffic visualization in the UI](/img/l7-routing/full.png) - -Each stage of this discovery process can be dynamically reconfigured via various -[configuration entries](/consul/docs/agent/config-entries). When a configuration -entry is missing, that stage will fall back on reasonable default behavior. - -### Routing - -A [`service-router`](/consul/docs/connect/config-entries/service-router) config -entry kind is the first configurable stage. +- routing +- splitting +- resolution -![screenshot of service router in the UI](/img/l7-routing/Router.png) - -A router config entry allows for a user to intercept traffic using L7 criteria -such as path prefixes or http headers, and change behavior such as by sending -traffic to a different service or service subset. - -These config entries may only reference `service-splitter` or -`service-resolver` entries. - -[Examples](/consul/docs/connect/config-entries/service-router#sample-config-entries) -can be found in the `service-router` documentation. - -### Splitting +For information about integrating service mesh proxy upstream discovery using the discovery chain, refer to [Discovery Chain for Service Mesh Traffic Management](/consul/docs/connect/l7-traffic/discovery-chain). -A [`service-splitter`](/consul/docs/connect/config-entries/service-splitter) config -entry kind is the next stage after routing. +The Consul UI shows discovery chain stages in the **Routing** tab of the **Services** page: -![screenshot of service splitter in the UI](/img/l7-routing/Splitter.png) +![screenshot of L7 traffic visualization in the UI](/img/l7-routing/full.png) -A splitter config entry allows for a user to choose to split incoming requests -across different subsets of a single service (like during staged canary -rollouts), or perhaps across different services (like during a v2 rewrite or -other type of codebase migration). +You can define how Consul manages each stage of the discovery chain in a Consul _configuration entry_. [Configuration entries](/consul/docs/connect/config-entries) modify the default behavior of the Consul service mesh. -These config entries may only reference `service-splitter` or -`service-resolver` entries. +When managing L7 traffic with cluster peering, there are additional configuration requirements to resolve peers in the discovery chain. Refer to [Cluster peering L7 traffic management](/consul/docs/connect/cluster-peering/usage/peering-traffic-management) for more information. -If one splitter references another splitter the overall effects are flattened -into one effective splitter config entry which reflects the multiplicative -union. For instance: +### Routing - splitter[A]: A_v1=50%, A_v2=50% - splitter[B]: A=50%, B=50% - --------------------- - splitter[effective_B]: A_v1=25%, A_v2=25%, B=50% +The first stage of the discovery chain is the service router. Routers intercept traffic according to a set of L7 attributes, such as path prefixes and HTTP headers, and route the traffic to a different service or service subset. -[Examples](/consul/docs/connect/config-entries/service-splitter#sample-config-entries) -can be found in the `service-splitter` documentation. +Apply a [service router configuration entry](/consul/docs/connect/config-entries/service-router) to implement a router. Service router configuration entries can only reference service splitter or service resolver configuration entries. -### Resolution +![screenshot of service router in the UI](/img/l7-routing/Router.png) -A [`service-resolver`](/consul/docs/connect/config-entries/service-resolver) config -entry kind is the last stage. +### Splitting -![screenshot of service resolver in the UI](/img/l7-routing/Resolver.png) +The second stage of the discovery chain is the service splitter. Service splitters split incoming requests and route them to different services or service subsets. Splitters enable staged canary rollouts, versioned releases, and similar use cases. -A resolver config entry allows for a user to define which instances of a -service should satisfy discovery requests for the provided name. +Apply a [service splitter configuration entry](/consul/docs/connect/config-entries/service-splitter) to implement a splitter. Service splitters configuration entries can only reference other service splitters or service resolver configuration entries. -Examples of things you can do with resolver config entries: +![screenshot of service splitter in the UI](/img/l7-routing/Splitter.png) -- Control where to send traffic if all instances of `api` in the current - datacenter are unhealthy. +If multiple service splitters are chained, Consul flattens the splits so that they behave as a single service spitter. In the following equation, `splitter[A]` references `splitter[B]`: -- Configure service subsets based on `Service.Meta.version` values. +```text +splitter[A]: A_v1=50%, A_v2=50% +splitter[B]: A=50%, B=50% +--------------------- +splitter[effective_B]: A_v1=25%, A_v2=25%, B=50% +``` -- Send all traffic for `web` that does not specify a service subset to the - `version1` subset. -- Send all traffic for `api` to `new-api`. +### Resolution -- Send all traffic for `api` in all datacenters to instances of `api` in `dc2`. +The third stage of the discovery chain is the service resolver. Service resolvers specify which instances of a service satisfy discovery requests for the provided service name. Service resolvers enable several use cases, including: -- Create a "virtual service" `api-dc2` that sends traffic to instances of `api` - in `dc2`. This can be referenced in upstreams or in other config entries. +- Designate failovers when service instances become unhealthy or unreachable. +- Configure service subsets based on DNS values. +- Route traffic to the latest version of a service. +- Route traffic to specific Consul datacenters. +- Create virtual services that route traffic to instances of the actual service in specific Consul datacenters. -If no resolver config is defined for a service it is assumed 100% of traffic -flows to the healthy instances of a service with the same name in the current -datacenter/namespace and discovery terminates. +Apply a [service resolver configuration entry](/consul/docs/connect/config-entries/service-resolver) to implement a resolver. Service resolver configuration entries can only reference other service resolvers. -This should feel similar in spirit to various uses of Prepared Queries, but is -not intended to be a drop-in replacement currently. -These config entries may only reference other `service-resolver` entries. +![screenshot of service resolver in the UI](/img/l7-routing/Resolver.png) -[Examples](/consul/docs/connect/config-entries/service-resolver#sample-config-entries) -can be found in the `service-resolver` documentation. +If no resolver is configured for a service, Consul sends all traffic to healthy instances of the service that have the same name in the current datacenter or specified namespace and ends the discovery chain. --> **Note:** `service-resolver` config entries kinds can function at L4 (unlike -`service-router` and `service-splitter` kinds). These can be created for -services of any protocol such as `tcp`. \ No newline at end of file +Service resolver configuration entries can also process network layer, also called level 4 (L4), traffic. As a result, you can implement service resolvers for services that communicate over `tcp` and other non-HTTP protocols. \ No newline at end of file diff --git a/website/content/docs/k8s/connect/index.mdx b/website/content/docs/k8s/connect/index.mdx index 7f1dd71c8e..afa625a0ba 100644 --- a/website/content/docs/k8s/connect/index.mdx +++ b/website/content/docs/k8s/connect/index.mdx @@ -7,30 +7,21 @@ description: >- # How does Consul Service Mesh Work on Kubernetes? -[Consul service mesh](/consul/docs/connect) is a feature built into to Consul that enables -automatic service-to-service authorization and connection encryption across -your Consul services. Consul Service Mesh can be used with Kubernetes to secure pod -communication with other pods and external Kubernetes services. - -The noun _connect_ is used throughout this documentation to refer to the connect -subsystem that provides Consul's service mesh capabilities. -Where you encounter the _noun_ connect, it is usually functionality specific to -service mesh. +Consul service mesh automates service-to-service authorization and encryption across your Consul services. You can use service mesh in Kubernetes-orchestrated networks to secure communication between pods as well as communication between pods and external Kubernetes services. + +## Workflow -Consul can automatically inject the sidecar running Envoy into pods in -your cluster, making configuration for Kubernetes automatic. -This functionality is provided by the -[consul-k8s project](https://github.com/hashicorp/consul-k8s) and can be -automatically installed and configured using the -[Consul Helm chart](/consul/docs/k8s/installation/install#helm-chart-installation). +Consul service mesh is enabled by default when you install Consul on Kubernetes using the Consul Helm chart. Consul also automatically injects sidecars into the pods in your clusters that run Envoy. These sidecar proxies, called Consul dataplanes, are enabled when `connectInject.default` is set to `false` in the Helm chart. Refer to the following documentation for additional information about these concepts: -## Usage +- [Installation and Configuration](#installation-and-configuration) in this topic +- [Consul Helm chart reference](/consul/docs/k8s/helm) +- [Simplified Service Mesh with Consul Dataplane](/consul/docs/connect/dataplane) --> **Important:** As of consul-k8s `v0.26.0` and Consul Helm `v0.32.0`, a Kubernetes -service is required to run services on the Consul service mesh. +If `connectInject.default` is set to `false` or you want to explicitly enable service mesh sidecar proxy injection for a specific deployment, add the `consul.hashicorp.com/connect-inject` annotation to the pod specification template and set it to `true` when connecting services to the mesh. -Installing Consul on Kubernetes with [`connect-inject` enabled](/consul/docs/k8s/connect#installation-and-configuration) adds a sidecar to all pods. By default, it enables service mesh functionality with Consul Dataplane by injecting an Envoy proxy. You can also configure Consul to inject a client agent sidecar to connect to your service mesh. Refer to [Simplified Service Mesh with Consul Dataplane](/consul/docs/connect/dataplane) for more information. +### Example +The following example shows a Kubernetes configuration that specifically enables service mesh connections for the `static-server` service. Consul starts and registers a sidecar proxy that listens on port 20000 by default and proxies valid inbound connections to port 8080. ```yaml apiVersion: v1 @@ -81,37 +72,17 @@ spec: serviceAccountName: static-server ``` -The only change for service mesh is the addition of the -`consul.hashicorp.com/connect-inject` annotation. This enables injection -for the Pod in this Deployment. The injector can also be -[configured](/consul/docs/k8s/connect#installation-and-configuration) -to automatically inject unless explicitly disabled, but the default -installation requires opt-in using the annotation shown above. - -~> **A common mistake** is to set the annotation on the Deployment or -other resource. Ensure that the injector annotations are specified on -the _pod specification template_ as shown above. - -This will start a sidecar proxy that listens on port `20000` registered -with Consul and proxies valid inbound connections to port 8080 in the pod. -To establish a connection to the pod using service mesh, a client must use another mesh -proxy. The client mesh proxy will use Consul service discovery to find -all available upstream proxies and their public ports. - -In the example above, the server is listening on `:8080`. -By default, the Consul service mesh runs in [transparent proxy](/consul/docs/connect/transparent-proxy) mode. -This means that even though the server binds to all interfaces, -the inbound and outbound connections will automatically go through to the sidecar proxy. -It also allows you to use Kubernetes DNS like you normally would without the -Consul Service Mesh. - --> **Note:** As of consul `v1.10.0`, consul-k8s `v0.26.0` and Consul Helm `v0.32.0`, -all Consul Service Mesh services will run with transparent proxy enabled by default. Running with transparent -proxy will enforce all inbound and outbound traffic to go through the Envoy proxy. - -The service name registered in Consul will be set to the name of the Kubernetes service -associated with the Pod. This can be customized with the `consul.hashicorp.com/connect-service` -annotation. If using ACLs, this name must be the same as the Pod's `ServiceAccount` name. +To establish a connection to the Pod using service mesh, a client must use another mesh proxy. The client mesh proxy will use Consul service discovery to find all available upstream proxies and their public ports. + +### Service names + +When the service is onboarded, the name registered in Consul is set to the name of the Kubernetes Service associated with the Pod. You can specify a custom name for the service in the [`consul.hashicorp.com/connect-service` annotation](/consul/docs/k8s/annotations-and-labels#consul-hashicorp-com-connect-service), but if ACLs are enabled, then the name of the service registered in Consul must match the Pod's `ServiceAccount` name. + +### Transparent proxy mode + +By default, the Consul service mesh runs in transparent proxy mode. This mode forces inbound and outbound traffic through the sidecar proxy even though the service binds to all interfaces. Transparent proxy infers the location of upstream services using Consul service intentions, and also allows you to use Kubernetes DNS as you normally would for your workloads. + +When transparent proxy mode is enabled, all service-to-service traffic is required to use mTLS. While onboarding new services to service mesh, your network may have mixed mTLS and non-mTLS traffic, which can result in broken service-to-service communication. You can temporarily enable permissive mTLS mode during the onboarding process so that existing mesh services can accept traffic from services that are not yet fully onboarded. Permissive mTLS enables sidecar proxies to access both mTLS and non-mTLS traffic. Refer to [Onboard mesh services in transparent proxy mode](/consul/docs/k8s/connect/onboarding-tproxy-mode) for additional information. ### Connecting to Mesh-Enabled Services diff --git a/website/content/docs/k8s/connect/onboarding-tproxy-mode.mdx b/website/content/docs/k8s/connect/onboarding-tproxy-mode.mdx new file mode 100644 index 0000000000..03636b0443 --- /dev/null +++ b/website/content/docs/k8s/connect/onboarding-tproxy-mode.mdx @@ -0,0 +1,295 @@ +--- +layout: docs +page_title: Onboard services in transparent proxy mode +description: Learn how to enable permissive mutual transport layer security (permissive mTLS) so that you can safely add services to your service mesh when transparent proxy is enabled in Kubernetes deployments. +--- + +# Onboard services while in transparent proxy mode + +This topic describes how to run Consul in permissive mTLS mode so that you can safely onboard existing applications to Consul service mesh when transparent proxy mode is enabled. + +## Background + +When [transparent proxy mode](/consul/docs/k8s/transparent-proxy/) is enabled, all service-to-service traffic is secured by mTLS. Until the services that you want to add to the network are fully onboarded, your network may have a mix of mTLS and non-mTLS traffic, which can result in broken service-to-service communication. This situation occurs because sidecar proxies for existing mesh services reject traffic from services that are not yet onboarded. + +You can enable the `permissive` mTLS mode to ensure existing non-mTLS service-to-service traffic is allowed during the onboarding phase. The `permissive` mTLS mode enables sidecar proxies to accept both mTLS and non-mTLS traffic to an application. Using this mode enables you to onboard without downtime and without being required to reconfigure or redeploy your application. + +We recommend enabling permissive mTLS as a temporary operating mode. After onboarding is complete, you should reconfigure all services to `strict` mTLS mode to ensure all service-to-service communication is automatically secured by Consul service mesh. + +!> **Security warning**: We recommend that you disable permissive mTLS mode after onboarding services to prevent non-mTLS connections to the service. Intentions are not enforced and encryption is not enabled for non-mTLS connections. + +## Workflow + +The workflow to configure mTLS settings depends on the applications you are onboarding and the order you intend to onboard them, but the following steps describe the general workflow: + +1. **Configure global settings**: Configure the mesh to allow services to send non-mTLS messages to services outside the mesh. Additionally, configure the mesh to let services in the mesh use permissive mTLS mode. +1. **Enable permissive mTLS mode**: If you are onboarding an upstream service prior to its related downstream services, then enable permissive mTLS mode in the service defaults configuration entry. This allows the upstream service to send encrypted messages from the mesh when you register the service with Consul. +1. **Configure intentions**: Intentions are controls that authorize traffic between services in the mesh. Transparent proxy uses intentions to infer traffic routes between Envoy proxies. Consul does not enforce intentions for non-mTLS connections made while proxies are in permissive mTLS mode, but intentions are necessary for completing the onboarding process. +1. **Register the service**: Create the service definition and configure and deploy its sidecar proxy. +1. **Re-secure the mesh**: If you enabled permissive mTLS mode, switch back to strict mTLS mode and revert the global settings to disable non-mTLS traffic in the service mesh. + +## Requirements + +Permissive mTLS is only supported for services running in transparent proxy mode. Transparent proxy mode is only available on Kubernetes deployments. + +## Configure global settings + +Configure Consul to allow services that are already in the mesh to send non-mTLS messages to services outside the mesh. You can also Consul to allow services to run in permissive mTLS mode. Set both configurations in the mesh gateway configuration entry, which is the global configuration that defines service mesh proxy behavior. + +### Allow outgoing non-mTLS traffic + +You can configure a global setting that allows services in the mesh to send non-mTLS messages to services outside the mesh. + +Add the `MeshDestinationsOnly` property to the mesh configuration entry and set the property to `false`. If the services belong to multiple admin partitions, you must apply the setting in each partition: + + + +```hcl +Kind = "mesh" + +TransparentProxy { + MeshDestinationsOnly = false +} +``` + +```yaml +apiVersion: consul.hashicorp.com/v1alpha1 +kind: Mesh +metadata: + name: mesh +spec: + allowEnablingPermissiveMutualTLS: true +``` + +```json +{ + "Kind": "mesh", + "TransparentProxy": [ + { + "MeshDestinationsOnly": false + } + ] +} +``` + + + +Alternatively, you can selectively allow outgoing traffic on a per-service basis by configuring [outbound port exclusions](/consul/docs/k8s/connect/transparent-proxy/enable-transparent-proxy#exclude-outbound-ports). This setting excludes outgoing traffic from traffic redirection imposed by transparent proxy. When changing this setting, you must redeploy your application. + +### Allow permissive mTLS modes for incoming traffic + +Set the `AllowEnablingPermissiveMutualTLS` parameter in the mesh configuration entry to `true` so that services in the mesh _are able_ to use permissive mTLS mode for incoming traffic. The parameter does not direct services to use permissive mTLS. It is a global parameter that allows services to run in permissive mTLS mode. + + + +```hcl +Kind = "mesh" + +AllowEnablingPermissiveMutualTLS = true +TransparentProxy { + MeshDestinationsOnly = false +} +``` + +```yaml +apiVersion: consul.hashicorp.com/v1alpha1 +kind: Mesh +metadata: + name: mesh +spec: + allowEnablingPermissiveMutualTLS: true + transparentProxy: + meshDestinationsOnly: false +``` + + +```json +{ + "Kind": "mesh", + "AllowEnablingPermissiveMutualTLS": true, + "TransparentProxy": [ + { + "MeshDestinationsOnly": false + } + ] +} +``` + + + +You can change this setting back to `false` at any time, even if there are services currently running in permissive mode. Doing so allows you to decide at which point during the onboarding process to stop allowing services to use permissive mTLS. When the `MeshDestinationOnly` is set to `false`, you must configure all new services added to the mesh with `MutualTLSMode=strict` for the Consul to securely route traffic throughout the mesh. + +## Enable permissive mTLS mode + +Depending on the services you are onboarding, you may not need to enable permissive mTLS mode. If the service does not accept incoming traffic or accepts traffic from downstream services that are already part of the service mesh, then permissive mTLS mode is not required to continue. + +To enable permissive mTLS mode for the service, set [`MutualTLSMode=permissive`](/consul/docs/connect/config-entries/service-defaults#mutualtlsmode) in the service defaults configuration entry for the service. The following example shows how to configure this setting for a service named `example-service`. + + + +```hcl +Kind = "service-defaults" +Name = "example-service" + +MutualTLSMode = "permissive" +``` + +```yaml +apiVersion: consul.hashicorp.com/v1alpha1 +kind: ServiceDefaults +metadata: + name: example-service +spec: + mutualTLSMode: "permissive" +``` + +```json +{ + "Kind": "service-defaults", + "Name": "example-service", + "MutualTLSMode": "permissive" +} +``` + + + +Refer to the [service defaults configuration reference](/consul/docs/connect/config-entries/service-defaults) for information about all settings. + +You can change this setting back to `strict` at any time to ensure mTLS is required for incoming traffic to this service. + +## Configure intentions + +Service intentions are mechanisms in Consul that control traffic between services in the mesh. + +We recommend creating intentions that restrict services to accepting only necessary traffic. You must identify the downstream services that send messages to the service you want to add to the mesh and then create an intention to allow traffic to the service from its downstreams. + +When transparent proxy enabled and the `MutualTLSMode` parameter is set to `permissive`, incoming traffic from a downstream service to another upstream service is not secured by mTLS unless that upstream relationship is known to Consul. You must either define an intention so that Consul can infer the upstream relationship from the intention, or you must include an explicit upstream as part of the service definition for the downstream. + +Refer to [Service intentions](/consul/docs/connect/intentions) for additional information about how intentions work and how to create them. + +## Add the service to the mesh + +Register your service into the catalog and update your application to deploy a sidecar proxy. You should also monitor your service to verify its configuration. Refer to the [Consul on Kubernetes service mesh overview](/consul/docs/k8s/connect) for additional information. + +## Re-secure mesh traffic + +If the newly added service was placed in permissive mTLS mode for onboarding, then you should switch to strict mode when it is safe to do so. You should also revert the global settings that allow services to send and receive non-mTLS traffic. + +### Disable permissive mTLS mode + +Configure the service to operate in strict mTLS mode after the service is no longer receiving incoming non-mTLS traffic. After the downstream services that send messages to this service are all onboarded to the mesh, this service should no longer receive non-mTLS traffic. + +Check the following Envoy listener statistics for the sidecar proxy to determine if the sidecar is receiving non-mTLS traffic: + +- The `tcp.permissive_public_listener.*` statistics indicate non-mTLS traffic. If these metrics are static over a sufficient period of time, that indicates the sidecar is not receiving non-mTLS traffic. +- The `tcp.public_listener.*` statistics indicate mTLS traffic. If incoming traffic is expected to this service and these statistics are changing, then the sidecar is receiving mTLS traffic. + +Refer to the [service mesh observability overview](/consul/docs/connect/observability) and [metrics configuration for Consul on Kubernetes documentation](/consul/docs/k8s/connect/observability/metrics) for additional information. + +If your service is still receiving non-mTLS traffic, complete the following steps to determine the source of the non-mTLS traffic: + +1. Verify the list of downstream services. Optionally, you can enable [Envoy access logging](/consul/docs/connect/observability/access-logs) to determine source IP addresses for incoming traffic, and cross-reference those IP addresses with services in your network. +1. Verify that each downstream is onboarded to the service mesh. If a downstream is not onboarded, consider onboarding it next. +1. Verify that each downstream has an intention that allows it to send traffic to the upstream service. + +After you determine it is safe to move the service to strict mode, set `MutualTLSMode=strict` in the service defaults configuration entry. + + + +```hcl +Kind = "service-defaults" +Name = "example-service" + +MutualTLSMode = "strict" +``` + +```yaml +apiVersion: consul.hashicorp.com/v1alpha1 +kind: ServiceDefaults +metadata: + name: example-service +spec: + mutualTLSMode: "strict" +``` + +```json +{ + "Kind": "service-defaults", + "MutualTLSMode": "strict", + "Name": "example-service" +} +``` + + + +### Disable non-mTLS traffic + +After all services are onboarded, revert the global settings that allow non-mTLS traffic and verify that permissive mTLS mode is not being used in the mesh. + +Set `AllowEnablingPermissiveMutualTLS=false` and `MeshDestinationsOnly=true` in the mesh config entry. + + + +```hcl +Kind = “mesh” + +AllowEnablingPermissiveMutualTLS = false +TransparentProxy { + MeshDestinationsOnly = true +} +``` + +```yaml +apiVersion: consul.hashicorp.com/v1alpha1 +kind: Mesh +metadata: + name: mesh +spec: + allowEnablingPermissiveMutualTLS: false + transparentProxy: + meshDestinationsOnly: true +``` + + +```json +{ + "Kind": "mesh", + "AllowEnablingPermissiveMutualTLS": false, + "TransparentProxy": [ + { + "MeshDestinationsOnly": true + } + ] +} +``` + + + +For each namespace, admin partition, and datacenter in your Consul deployment, run the `consul config list` and `consul config read` commands to verify that no services are using `permissive` mTLS mode. + +The following command returns any service defaults configuration entries that contain `'MutualTLSMode = "permissive"'`: + +```shell-session +$ consul config list -kind service-defaults -filter 'MutualTLSMode == "permissive"' +``` + + In each admin partition and datacenter, verify that `MutualTLSMode = "permissive"` is not set in the proxy defaults configuration entry . If `MutualTLSMode` is either empty or if the configuration entry is not found, then the mode is `strict` by default. + + The following command fetches the proxy defaults configuration entry: + +```shell-session +$ consul config read -kind proxy-defaults -name global +{ + "Kind": "proxy-defaults", + "Name": "global", + "Partition": "default", + "Namespace": "default", + "TransparentProxy": {}, + "MutualTLSMode": "", + "MeshGateway": {}, + "Expose": {}, + "AccessLogs": {}, + "CreateIndex": 26, + "ModifyIndex": 30 +} +``` \ No newline at end of file diff --git a/website/content/docs/connect/transparent-proxy.mdx b/website/content/docs/k8s/connect/transparent-proxy/enable-transparent-proxy.mdx similarity index 81% rename from website/content/docs/connect/transparent-proxy.mdx rename to website/content/docs/k8s/connect/transparent-proxy/enable-transparent-proxy.mdx index 59a00e6507..7db6a6db03 100644 --- a/website/content/docs/connect/transparent-proxy.mdx +++ b/website/content/docs/k8s/connect/transparent-proxy/enable-transparent-proxy.mdx @@ -1,37 +1,13 @@ --- layout: docs -page_title: Service Mesh - Enable Transparent Proxy Mode +page_title: Enable transparent proxy mode description: >- - Learn how transparent proxy enables Consul on Kubernetes to direct inbound and outbound traffic through the service mesh. Use transparent proxying to increase application security without configuring individual upstream services. + Learn how to enable transparent proxy mode, which enables Consul on Kubernetes to direct inbound and outbound traffic through the service mesh and increase application security without configuring individual upstream services. --- -# Enable Transparent Proxy Mode +# Enable transparent proxy mode -This topic describes how to use Consul’s transparent proxy feature, which allows applications to communicate through the service mesh without modifying their configurations. Transparent proxy also hardens application security by preventing direct inbound connections that bypass the mesh. - -## Introduction - -When transparent proxy is enabled, Consul is able to perform the following actions automatically: - -- Infer the location of upstream services using service intentions. -- Redirect outbound connections that point to KubeDNS through the proxy. -- Force traffic through the proxy to prevent unauthorized direct access to the application. - -The following diagram shows how transparent proxy routes traffic: - -![Diagram demonstrating that with transparent proxy, connections are automatically routed through the mesh](/img/consul-connect/with-transparent-proxy.png) - -When transparent proxy is disabled, you must manually specify the following configurations so that your applications can communicate with other services in the mesh: - -* Explicitly configure upstream services by specifying a local port to access them. -* Change application to access `localhost:`. -* Configure applications to only listen on the loopback interface to prevent unauthorized traffic from bypassing the mesh. - -The following diagram shows how traffic flows through the mesh without transparent proxy enabled: - -![Diagram demonstrating that without transparent proxy, applications must "opt in" to connecting to their dependencies through the mesh](/img/consul-connect/without-transparent-proxy.png) - -Transparent proxy is available for Kubernetes environments. As part of the integration with Kubernetes, Consul registers Kubernetes Services, injects sidecar proxies, and enables traffic redirection. +This topic describes how to use transparent proxy mode in your service mesh. Transparent proxy allows applications to communicate through the service mesh without modifying their configurations. Transparent proxy also hardens application security by preventing direct inbound connections that bypass the mesh. Refer to [Transparent proxy overview](/consul/docs/k8s/connect/transparent-proxy) for additional information. ## Requirements @@ -40,24 +16,20 @@ Your network must meet the following environment and software requirements to us * Transparent proxy is available for Kubernetes environments. * Consul 1.10.0+ * Consul Helm chart 0.32.0+. If you want to use the Consul CNI plugin to redirect traffic, Helm chart 0.48.0+ is required. Refer to [Enable the Consul CNI plugin](#enable-the-consul-cni-plugin) for additional information. -* [Service intentions](/consul/docs/connect/intentions) must be configured to allow communication between intended services. +* You must create [service intentions](/consul/docs/connect/intentions) that explicitly allow communication between intended services so that Consul can infer upstream connections and use sidecar proxies to route messages appropriately. * The `ip_tables` kernel module must be running on all worker nodes within a Kubernetes cluster. If you are using the `modprobe` Linux utility, for example, issue the following command: `$ modprobe ip_tables` ~> **Upgrading to a supported version**: Always follow the [proper upgrade path](/consul/docs/upgrading/upgrade-specific/#transparent-proxy-on-kubernetes) when upgrading to a supported version of Consul, Consul on Kubernetes (`consul-k8s`), and the Consul Helm chart. -## Configuration - -This section describes how to configure the transparent proxy. - -### Enable transparent proxy +## Enable transparent proxy -You can enable the transparent proxy for an entire cluster, individual Kubernetes namespaces, and individual services. +Transparent proxy mode is enabled for the entire cluster by default when you install Consul on Kubernetes using the Consul Helm chart. Refer to the [Consul Helm chart reference](/consul/docs/k8s/helm) for information about all default configurations. -When you install Consul using the Helm chart, transparent proxy is enabled for the entire cluster by default. +You can explicitly enable transparent proxy for the entire cluster, individual namespaces, and individual services. -#### Entire cluster +### Entire cluster Use the `connectInject.transparentProxy.defaultEnabled` Helm value to enable or disable transparent proxy for the entire cluster: @@ -67,14 +39,14 @@ connectInject: defaultEnabled: true ``` -#### Kubernetes namespace +### Kubernetes namespace Apply the `consul.hashicorp.com/transparent-proxy=true` label to enable transparent proxy for a Kubernetes namespace. The label overrides the `connectInject.transparentProxy.defaultEnabled` Helm value and defines the default behavior of Pods in the namespace. The following example enables transparent proxy for Pods in the `my-app` namespace: ```bash kubectl label namespaces my-app "consul.hashicorp.com/transparent-proxy=true" ``` -#### Individual service +### Individual service Apply the `consul.hashicorp.com/transparent-proxy=true` annotation to enable transparent proxy on the Pod for each service. The annotation overrides the Helm value and the namespace label. The following example enables transparent proxy for the `static-server` service: @@ -126,7 +98,7 @@ spec: serviceAccountName: static-server ``` -### Enable the Consul CNI plugin +## Enable the Consul CNI plugin By default, Consul generates a `connect-inject init` container as part of the Kubernetes Pod startup process. The container configures traffic redirection in the service mesh through the sidecar proxy. To configure redirection, the container requires elevated CAP_NET_ADMIN privileges, which may not be compatible with security policies in your organization. @@ -134,7 +106,7 @@ Instead, you can enable the Consul container network interface (CNI) plugin to p The Consul Helm chart installs the CNI plugin, but it is disabled by default. Refer to the [instructions for enabling the CNI plugin](/consul/docs/k8s/installation/install#enable-the-consul-cni-plugin) in the Consul on Kubernetes installation documentation for additional information. -### Traffic redirection +## Traffic redirection There are two mechanisms for redirecting traffic through the sidecar proxies. By default, Consul injects an init container that redirects all inbound and outbound traffic. The default mechanism requires elevated permissions (CAP_NET_ADMIN) in order to redirect traffic to the service mesh. @@ -142,7 +114,7 @@ Alternatively, you can enable the Consul CNI plugin to handle traffic redirectio Both mechanisms redirect all inbound and outbound traffic, but you can configure exceptions for specific Pods or groups of Pods. The following annotations enable you to exclude certain traffic from being redirected to sidecar proxies. -#### Exclude inbound ports +### Exclude inbound ports The [`consul.hashicorp.com/transparent-proxy-exclude-inbound-ports`](/consul/docs/k8s/annotations-and-labels#consul-hashicorp-com-transparent-proxy-exclude-inbound-ports) annotation defines a comma-separated list of inbound ports to exclude from traffic redirection when running in transparent proxy mode. The port numbers are string data values. In the following example, services in the pod at port `8200` and `8201` are not redirected through the transparent proxy: @@ -157,7 +129,7 @@ The [`consul.hashicorp.com/transparent-proxy-exclude-inbound-ports`](/consul/doc ``` -#### Exclude outbound ports +### Exclude outbound ports The [`consul.hashicorp.com/transparent-proxy-exclude-outbound-ports`](/consul/docs/k8s/annotations-and-labels#consul-hashicorp-com-transparent-proxy-exclude-outbound-ports) annotation defines a comma-separated list of outbound ports to exclude from traffic redirection when running in transparent proxy mode. The port numbers are string data values. In the following example, services in the pod at port `8200` and `8201` are not redirected through the transparent proxy: @@ -173,7 +145,7 @@ The [`consul.hashicorp.com/transparent-proxy-exclude-outbound-ports`](/consul/do -#### Exclude outbound CIDR blocks +### Exclude outbound CIDR blocks The [`consul.hashicorp.com/transparent-proxy-exclude-outbound-cidrs`](/consul/docs/k8s/annotations-and-labels#consul-hashicorp-com-transparent-proxy-exclude-outbound-cidrs) annotation defines a comma-separated list of outbound CIDR blocks to exclude from traffic redirection when running in transparent proxy mode. The CIDR blocks are string data values. @@ -190,7 +162,7 @@ In the following example, services in the `3.3.3.3/24` IP range are not redirect ``` -#### Exclude user IDs +### Exclude user IDs The [`consul.hashicorp.com/transparent-proxy-exclude-uids`](/consul/docs/k8s/annotations-and-labels#consul-hashicorp-com-transparent-proxy-exclude-uids) annotation defines a comma-separated list of additional user IDs to exclude from traffic redirection when running in transparent proxy mode. The user IDs are string data values. @@ -208,20 +180,20 @@ In the following example, services with the IDs `4444 ` and `44444 ` are not red -### Kubernetes HTTP health probes configuration +## Kubernetes HTTP health probes configuration By default, `connect-inject` is disabled. As a result, Consul on Kubernetes uses a mechanism for traffic redirection that interferes with [Kubernetes HTTP health probes](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/). This is because probes expect the kubelet to reach the application container on the probe's endpoint. Instead, traffic is redirected through the sidecar proxy. As a result, health probes return errors because the kubelet does not encrypt that traffic using a mesh proxy. There are two methods for solving this issue. The first method is to set the `connectInject.transparentProxy.defaultOverwriteProbes` annotation to overwrite the Kubernetes HTTP health probes so that they point to the proxy. The second method is to [enable the Consul container network interface (CNI) plugin](#enable-the-consul-cni-plugin) to perform traffic redirection. Refer to the [Consul on Kubernetes installation instructions](/consul/docs/k8s/installation/install) for additional information. -#### Overwrite Kubernetes HTTP health probes +### Overwrite Kubernetes HTTP health probes You can either include the `connectInject.transparentProxy.defaultOverwriteProbes` Helm value to your command or add the `consul.hashicorp.com/transparent-proxy-overwrite-probes` Kubernetes annotation to your pod configuration to overwrite health probes. Refer to [Kubernetes Health Checks in Consul on Kubernetes](/consul/docs/k8s/connect/health) for additional information. -### Dial services across Kubernetes cluster +## Dial services across Kubernetes cluster If your [Consul servers are federated between Kubernetes clusters](/consul/docs/k8s/deployment-configurations/multi-cluster/kubernetes), then you must configure services in one Kubernetes cluster to explicitly dial a service in the datacenter of another Kubernetes cluster using the @@ -243,7 +215,7 @@ The following example configures the service to dial an upstream service called You do not need to configure services to explicitly dial upstream services if your Consul clusters are connected with a [peering connection](/consul/docs/connect/cluster-peering). -## Usage +## Configure service selectors When transparent proxy is enabled, traffic sent to [KubeDNS](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/) or Pod IP addresses is redirected through the proxy. You must use a selector to bind Kubernetes Services to Pods as you define Kubernetes Services in the mesh. @@ -275,13 +247,13 @@ spec: Additional services can query the [KubeDNS](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/) at `sample-app.default.svc.cluster.local` to reach `sample-app`. If ACLs are enabled and configured with default `deny` policies, the configuration also requires a [`ServiceIntention`](/consul/docs/connect/config-entries/service-intentions) to allow it to talk to `sample-app`. -### Headless Services +### Headless services For services that are not addressed using a virtual cluster IP, you must configure the upstream service using the [DialedDirectly](/consul/docs/connect/config-entries/service-defaults#dialeddirectly) option. Then, use DNS to discover individual instance addresses and dial them through the transparent proxy. When this mode is enabled on the upstream, services present service mesh certificates for mTLS and intentions are enforced at the destination. Note that when dialing individual instances, Consul ignores the HTTP routing rules configured with configuration entries. The transparent proxy acts as a TCP proxy to the original destination IP address. -## Known Limitations +## Known limitations - Deployment configurations with federation across or a single datacenter spanning multiple clusters must explicitly dial a service in another datacenter or cluster using annotations. -- When dialing headless services, the request is proxied using a plain TCP proxy. Consul does not take into consideration the upstream's protocol. +- When dialing headless services, the request is proxied using a plain TCP proxy. Consul does not take into consideration the upstream's protocol. \ No newline at end of file diff --git a/website/content/docs/k8s/connect/transparent-proxy/index.mdx b/website/content/docs/k8s/connect/transparent-proxy/index.mdx new file mode 100644 index 0000000000..78db657133 --- /dev/null +++ b/website/content/docs/k8s/connect/transparent-proxy/index.mdx @@ -0,0 +1,47 @@ +--- +layout: docs +page_title: Transparent proxy overview +description: >- + Transparent proxy enables Consul on Kubernetes to direct inbound and outbound traffic through the service mesh. Learn how transparently proxying increases application security without configuring individual upstream services. +--- + +# Transparent proxy overview + +This topic provides overview information about transparent proxy mode, which allows applications to communicate through the service mesh without modifying their configurations. Transparent proxy also hardens application security by preventing direct inbound connections that bypass the mesh. + +## Introduction + +When service mesh proxies are in transparent mode, Consul service mesh uses IPtables to direct all inbound and outbound traffic to the sidecar. Consul also uses information configured in service intentions to infer routes, which eliminates the need to explicitly configure upstreams. + +### Transparent proxy enabled + +The following diagram shows how Consul routes traffic when proxies are in transparent mode: + +![Diagram demonstrating that with transparent proxy, connections are automatically routed through the mesh](/img/consul-connect/with-transparent-proxy.png) + +### Transparent proxy disabled + +When transparent proxy mode is disabled, you must manually configure explicit upstreams, configure your applications to query for services at `localhost:`, and configure applications to only listen on the loopback interface to prevent services from bypassing the mesh. + +The following diagram shows how Consul routes traffic when transparent proxy mode is disabled: + +![Diagram demonstrating that without transparent proxy, applications must "opt in" to connecting to their dependencies through the mesh](/img/consul-connect/without-transparent-proxy.png) + +Transparent proxy is available for Kubernetes environments. As part of the integration with Kubernetes, Consul registers Kubernetes Services, injects sidecar proxies, and enables traffic redirection. + +## Supported networking architectures + +Transparent proxy mode enables several networking architectures and workflows. You can query Consul DNS to discover upstreams for single services, virtual services, and failover service instances that are in peered clusters. + +Consul supports the following intra-datacenter connection types for discovering upstreams when transparent proxy mode is enabled: + +- KubeDNS lookups across WAN-federated datacenters +- Consul DNS lookups across WAN-federated datacenters +- KubeDNS lookups in peered clusters and admin partitions +- Consul DNS lookups in peered clusters and admin partitions + +## Mutual TLS for transparent proxy mode + +Transparent proxy mode is enabled by default when you install Consul on Kubernetes using the Consul Helm chart. As a result, all services in the mesh must communicate through sidecar proxies, which enforce service intentions and mTLS encryption for the service mesh. While onboarding new services to service mesh, your network may have mixed mTLS and non-mTLS traffic, which can result in broken service-to-service communication. + +You can temporarily enable permissive mTLS mode during the onboarding process so that existing mesh services can accept traffic from services that are not yet fully onboarded. Permissive mTLS enables sidecar proxies to access both mTLS and non-mTLS traffic. Refer to [Onboard mesh services in transparent proxy mode](/consul/docs/k8s/connect/onboarding-tproxy-mode) for additional information. diff --git a/website/content/docs/k8s/l7-traffic/failover-tproxy.mdx b/website/content/docs/k8s/l7-traffic/failover-tproxy.mdx new file mode 100644 index 0000000000..6c76b6bd87 --- /dev/null +++ b/website/content/docs/k8s/l7-traffic/failover-tproxy.mdx @@ -0,0 +1,124 @@ +--- +layout: docs +page_title: Configure failover service instances +description: Learn how to define failover services in Consul on Kubernetes when proxies are in transparent proxy mode. Consul can send traffic to backup service instances if a destination service becomes unhealthy or unresponsive. +--- + +# Configure failover service instances + +This topic describes how to configure failover service instances in Consul on Kubernetes when proxies are in transparent proxy mode. If a service becomes unhealthy or unresponsive, Consul can use the service resolver configuration entry to send inbound requests to backup services. Service resolvers are part of the service mesh proxy upstream discovery chain. Refer to [Service mesh traffic management](/consul/docs/connect/l7-traffic) for additional information. + +## Overview + +Complete the following steps to configure failover service instances in Consul on Kubernetes when proxies are in transparent proxy mode: + +- Create a service resolver configuration entry +- Create intentions that allow the downstream service to access the primary and failover service instances. +- Configure your application to call the discovery chain using the Consul DNS or KubeDNS. + +## Requirements + +- `consul-k8s` v1.2.0-beta1 or newer. +- Consul service mesh must be enabled. Refer to [How does Consul Service Mesh Work on Kubernetes](/consul/docs/k8s/connect). +- Proxies must be configured to run in transparent proxy mode. +- To query virtual DNS names, you must use Consul DNS. +- To query the discovery chain using KubeDNS, the service resolver must be in the same partition as the running service. + +### ACL requirements + +The default ACLs that the Consul Helm chart configures are suitable for most cases, but if you have more complex security policies for Consul API access, refer to the [ACL documentation](/consul/docs/security/acl) for additional guidance. + +## Create a service resolver configuration entry + +Specify the target failover in the [`spec.failover.targets`](/consul/docs/connect/config-entries/service-resolver#failover-targets-service) field in the service resolver configuration entry. In the following example, the `api-beta` service is configured to failover to the `api` service in any service subset: + + + +```yaml +apiversion: consul.hashicorp.com/v1alpha1 +kind: ServiceResolver +metadata: + name: api-beta +spec: + failover: + '*': + targets: + - service: api +``` + + + +Refer to the [service resolver configuration entry reference](/consul/docs/connect/config-entries/service-resolver) documentation for information about all service resolver configurations. + +You can apply the configuration using the `kubectl apply` command: + +```shell-session +$ kubectl apply -f api-beta-failover.yaml +``` + +## Create service intentions + +If intentions are not already defined, create and apply intentions that allow the appropriate downstream to access the target service and the failover service. In the following examples, the `frontend` service is allowed to send messages to the `api` service, which is allowed to send messages to the `api-beta` failover service. + + + + +```yaml +apiVersion: consul.hashicorp.com/v1alpha1 +kind: ServiceIntentions +metadata: + name: api +spec: + destination: + name: api + sources: + - name: frontend + action: allow +--- +apiVersion: consul.hashicorp.com/v1alpha1 +kind: ServiceIntentions +metadata: + name: api-beta +spec: + destination: + name: api-beta + sources: + - name: frontend + action: allow +``` + + + +Refer to the [service intentions configuration entry reference](/consul/docs/connect/config-entries/service-intentions) for additional information about configuring service intentions. + +You can apply the configuration using the `kubectl apply` command: + +```shell-session +$ kubectl apply -f frontend-api-api-beta-allow.yaml +``` + +## Configure your application to call the DNS + +Configure your application to contact the discovery chain in either the Consul DNS or the KubeDNS. + +### Consul DNS + +You can query the Consul DNS using the `.virtual.consul` lookup format. For Consul Enterprise, your query string may need to include the namespace, partition, or both. Refer to the [DNS documentation](/consul/docs/services/discovery/dns-static-lookups#service-virtual-ip-lookups) for details on building virtual service lookups. + +In the following example, the application queries the Consul catalog for `api-beta` over HTTP. By default, the lookup would query the `default` partition and `default` namespace if Consul Enterprise manages the network infrastructure: + +```text +http://api-beta.virtual.consul/ +``` + +### KubeDNS + +You can query the KubeDNS if the failover service is in the same Kubernetes cluster as the primary service. In the following example, the application queries KubeDNS for `api-beta` over HTTP: + +```text +http://api-beta..svc.cluster.local +``` + +Note that you cannot use KubeDNS if a corresponding Kubernetes service and pod do not exist. + + diff --git a/website/content/docs/k8s/l7-traffic/route-to-virtual-services.mdx b/website/content/docs/k8s/l7-traffic/route-to-virtual-services.mdx new file mode 100644 index 0000000000..c8951d356c --- /dev/null +++ b/website/content/docs/k8s/l7-traffic/route-to-virtual-services.mdx @@ -0,0 +1,122 @@ +--- +layout: docs +page_title: Route traffic to a virtual service +description: Define virtual services in service resolver config entries so that Consul on Kubernetes can route traffic to virtual services when transparent proxy mode is enabled for Envoy proxies. +--- + +# Route traffic to a virtual service + +This topic describes how to define virtual services so that Consul on Kubernetes can route traffic to virtual services when transparent proxy mode is enabled for Envoy proxies. + +## Overview + +You can define virtual services in service resolver configuration entries so that downstream applications can send requests to a virtual service using a Consul DNS name in peered clusters. Your applications can send requests to virtual services in the same cluster using KubeDNS. Service resolvers are part of the service mesh proxy upstream discovery chain. Refer to [Service mesh traffic management](/consul/docs/connect/l7-traffic) for additional information. + +Complete the following steps to configure failover service instances in Consul on Kubernetes when proxies are in transparent proxy mode: + +1. Create a service resolver configuration entry. +1. Create intentions that allow the downstream service to access the real service and the virtual service. +1. Configure your application to call the discovery chain using the Consul DNS or KubeDNS. + +## Requirements + +- `consul-k8s` v1.2.0-beta1 or newer. +- Consul service mesh must be enabled. Refer to [How does Consul service mesh work on Kubernetes](/consul/docs/k8s/connect). +- Proxies must be configured to run in transparent proxy mode. +- To query virtual DNS names, you must use Consul DNS. +- To query the discovery chain using KubeDNS, the service resolver must be in the same partition as the running service. + +### ACL requirements + +The default ACLs that the Consul Helm chart configures are suitable for most cases, but if you have more complex security policies for Consul API access, refer to the [ACL documentation](/consul/docs/security/acl) for additional guidance. + +## Create a service resolver configuration entry + +Specify the target failover in the [`spec.redirect.service`](/consul/docs/connect/config-entries/service-resolver#spec-redirect-service) field in the service resolver configuration entry. In the following example, the `virtual-api` service is configured to redirect to the `real-api`: + + + +```yaml +apiversion: consul.hashicorp.com/v1alpha1 +kind: ServiceResolver +metadata: + name: virtual-api +spec: + redirect: + service: real-api +``` + + + +Refer to the [service resolver configuration entry reference](/consul/docs/connect/config-entries/service-resolver) documentation for information about all service resolver configurations. + +You can apply the configuration using the `kubectl apply` command: + +```shell-session +$ kubectl apply -f virtual-api-redirect.yaml +``` + +## Create service intentions + +If intentions are not already defined, create and apply intentions that allow the appropriate downstream to access the real service and the target redirect service. In the following examples, the `frontend` service is allowed to send messages to the `virtual-api` and `real-api` services: + + + + +```yaml +apiversion: consul.hashicorp.com/v1alpha1 +kind: ServiceIntentions +metadata: + name: virtual-api +spec: + destination: + name: virtual-api + sources: + - name: frontend + action: allow +--- +apiversion: consul.hashicorp.com/v1alpha1 +kind: ServiceIntentions +metadata: + name: real-api +spec: + destination: + name: real-api + sources: + - name: frontend + action: allow +``` + + + +Refer to the [service intentions configuration entry reference](/consul/docs/connect/config-entries/service-intentions) for additional information about configuring service intentions. + +You can apply the configuration using the `kubectl apply` command: + +```shell-session +$ kubectl apply -f frontend-api-api-beta-allow.yaml +``` + +## Configure your application to call the DNS + +Configure your application to contact the discovery chain in either the Consul DNS or the KubeDNS. + +### Consul DNS + +You can query the Consul DNS using the `.virtual.consul` lookup format. For Consul Enterprise, your query string may need to include the namespace, partition, or both. Refer to the [DNS documentation](/consul/docs/services/discovery/dns-static-lookups#service-virtual-ip-lookups) for details on building virtual service lookups. + +In the following example, the application queries the Consul catalog for `virtual-api` over HTTP. By default, the lookup would query the `default` partition and `default` namespace if Consul Enterprise manages the network infrastructure: + +```text +http://virtual-api.virtual.consul/ +``` + +### KubeDNS + +You can query the KubeDNS if the real and virtual services are in the same Kubernetes cluster by specifying the name of the service. In the following example, the application queries KubeDNS for `virtual-api` over HTTP: + +```text +http://virtual-api..svc.cluster.local +``` + +Note that you cannot use KubeDNS if a corresponding Kubernetes service and pod do not exist. \ No newline at end of file diff --git a/website/data/docs-nav-data.json b/website/data/docs-nav-data.json index e8f3ce7d59..20335f715b 100644 --- a/website/data/docs-nav-data.json +++ b/website/data/docs-nav-data.json @@ -559,10 +559,6 @@ } ] }, - { - "title": "Transparent Proxy", - "path": "connect/transparent-proxy" - }, { "title": "Observability", "routes": [ @@ -729,6 +725,45 @@ } ] }, + { + "title": "Failover", + "routes": [ + { + "title": "Overview", + "path": "connect/failover" + }, + { + "title": "Usage", + "routes": [ + { + "title": "Configure failover services for Kubernetes", + "href": "/docs/k8s/l7-traffic/failover-tproxy" + }, + { + "title": "Automate geo-failover with prepared queries", + "href": "/tutorials/developer-discovery/automate-geo-failover" + } + ] + }, + { + "title": "Configuration", + "routes": [ + { + "title": "Sameness groups", + "href": "/consul/docs/connect/config-entries/service-resolver" + }, + { + "title": "Service resolver", + "href": "/consul/docs/connect/config-entries/service-resolver" + }, + { + "title": "Service intentions", + "href": "/consul/docs/connect/config-entries/service-intentions" + } + ] + } + ] + }, { "title": "Nomad", "path": "connect/nomad" @@ -1222,7 +1257,24 @@ }, { "title": "Transparent Proxy", - "href": "/docs/connect/transparent-proxy" + "routes": [ + { + "title": "Overview", + "path": "k8s/connect/transparent-proxy" + }, + { + "title": "Enable transparent proxy", + "path": "k8s/connect/transparent-proxy/enable-transparent-proxy" + }, + { + "title": "Route traffic to virtual services", + "href": "/docs/k8s/l7-traffic/route-to-virtual-services" + } + ] + }, + { + "title": "Onboarding services in transparent proxy mode", + "path": "k8s/connect/onboarding-tproxy-mode" }, { "title": "Ingress Gateways", @@ -1255,6 +1307,23 @@ } ] }, + { + "title": "L7 traffic management", + "routes": [ + { + "title": "Overview", + "href": "/docs/connect/l7-traffic" + }, + { + "title": "Configure failover services", + "path": "k8s/l7-traffic/failover-tproxy" + }, + { + "title": "Route traffic to virtual services", + "path": "k8s/l7-traffic/route-to-virtual-services" + } + ] + }, { "title": "Service Sync", "path": "k8s/service-sync" From b1d3ec0cdbd39ecdb84f9bbeb64693ad2197f0fd Mon Sep 17 00:00:00 2001 From: Bryce Kalow Date: Mon, 12 Jun 2023 09:20:29 -0500 Subject: [PATCH 51/72] Delete check-legacy-links-format.yml (#17647) --- .../workflows/check-legacy-links-format.yml | 20 ------------------- 1 file changed, 20 deletions(-) delete mode 100644 .github/workflows/check-legacy-links-format.yml diff --git a/.github/workflows/check-legacy-links-format.yml b/.github/workflows/check-legacy-links-format.yml deleted file mode 100644 index 85dbb0e70f..0000000000 --- a/.github/workflows/check-legacy-links-format.yml +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (c) HashiCorp, Inc. -# SPDX-License-Identifier: MPL-2.0 - -name: Legacy Link Format Checker - -on: - push: - paths: - - "website/content/**/*.mdx" - - "website/data/*-nav-data.json" - -jobs: - check-links: - uses: hashicorp/dev-portal/.github/workflows/docs-content-check-legacy-links-format.yml@475289345d312552b745224b46895f51cc5fc490 - with: - repo-owner: "hashicorp" - repo-name: "consul" - commit-sha: ${{ github.sha }} - mdx-directory: "website/content" - nav-data-directory: "website/data" From 809c188b341e1076c495d7125f8ced09678a4c4f Mon Sep 17 00:00:00 2001 From: Paul Glass Date: Mon, 12 Jun 2023 10:11:36 -0500 Subject: [PATCH 52/72] docs: Reference doc updates for permissive mTLS settings (#17371) * Reference doc updates for permissive mTLS settings * Document config entry filtering * Fix minor doc errors (double slashes in link url paths) --------- Co-authored-by: trujillo-adam <47586768+trujillo-adam@users.noreply.github.com> --- website/content/api-docs/config.mdx | 1 + website/content/commands/config/list.mdx | 10 +++++ .../docs/connect/config-entries/mesh.mdx | 6 +++ .../connect/config-entries/proxy-defaults.mdx | 17 +++++++++ .../config-entries/service-defaults.mdx | 37 ++++++++++++++++++- .../docs/release-notes/consul/v1_13_x.mdx | 4 +- .../services/discovery/dns-configuration.mdx | 24 ++++++------ 7 files changed, 83 insertions(+), 16 deletions(-) diff --git a/website/content/api-docs/config.mdx b/website/content/api-docs/config.mdx index 96e6a7b4de..a79e024fa4 100644 --- a/website/content/api-docs/config.mdx +++ b/website/content/api-docs/config.mdx @@ -215,6 +215,7 @@ The corresponding CLI command is [`consul config list`](/consul/commands/config/ ### Path Parameters - `kind` `(string: )` - Specifies the kind of the entry to list. +- `filter` `(string: "")` - Specifies an expression to use for filtering the results. ### Query Parameters diff --git a/website/content/commands/config/list.mdx b/website/content/commands/config/list.mdx index 1a70af1787..e453b11943 100644 --- a/website/content/commands/config/list.mdx +++ b/website/content/commands/config/list.mdx @@ -44,6 +44,7 @@ Usage: `consul config list [options]` #### Command Options - `-kind` - Specifies the kind of the config entry to list. +- `-filter` - Specifies an expression to use for filtering the results. #### Enterprise Options @@ -57,7 +58,16 @@ Usage: `consul config list [options]` ## Examples +To list all service-defaults config entries: + $ consul config list -kind service-defaults billing db web + +The following lists service-defaults with a filter expression: + + $ consul config list -kind service-defaults -filter 'MutualTLSMode == "permissive"' + db + web + diff --git a/website/content/docs/connect/config-entries/mesh.mdx b/website/content/docs/connect/config-entries/mesh.mdx index f65ed61622..a323a6d90f 100644 --- a/website/content/docs/connect/config-entries/mesh.mdx +++ b/website/content/docs/connect/config-entries/mesh.mdx @@ -338,6 +338,12 @@ Note that the Kubernetes example does not include a `partition` field. Configura }, ], }, + { + name: 'AllowEnablingPermissiveMutualTLS', + type: 'bool: false', + description: + 'Controls whether `MutualTLSMode=permissive` can be set in the `proxy-defaults` and `service-defaults` configuration entries. ' + }, { name: 'TLS', type: 'TLSConfig: ', diff --git a/website/content/docs/connect/config-entries/proxy-defaults.mdx b/website/content/docs/connect/config-entries/proxy-defaults.mdx index 917bc05044..1d94a79389 100644 --- a/website/content/docs/connect/config-entries/proxy-defaults.mdx +++ b/website/content/docs/connect/config-entries/proxy-defaults.mdx @@ -53,6 +53,7 @@ TransparentProxy { OutboundListenerPort = DialedDirectly = } +MutualTLSMode = "" MeshGateway { Mode = "" } @@ -92,6 +93,7 @@ spec: transparentProxy: outboundListenerPort: dialedDirectly: + mutualTLSMode: meshGateway: mode: expose: @@ -120,6 +122,7 @@ spec: "Config": { "": }, + "MutualTLSMode": "", "Mode": "", "TransparentProxy": { "OutboundListenerPort": , @@ -175,6 +178,7 @@ TransparentProxy { OutboundListenerPort = DialedDirectly = } +MutualTLSMode = "" MeshGateway { Mode = "" } @@ -215,6 +219,7 @@ spec: transparentProxy: outboundListenerPort: dialedDirectly: + mutualTLSMode: meshGateway: mode: expose: @@ -249,6 +254,7 @@ spec: "OutboundListenerPort": , "DialedDirectly": }, + "MutualTLSMode": "", "MeshGateway": { "Mode": = "" }, @@ -405,6 +411,17 @@ spec: }, ], }, + { + name: 'MutualTLSMode', + type: 'string: ""', + description: `Controls the default mutual TLS mode for all proxies. This setting is only + supported for services with transparent proxy enabled. One of \`""\`, \`strict\`, or \`permissive\`. + When unset or \`""\`, the mode defaults to \`strict\`. When set to \`strict\`, the sidecar proxy + requires mutual TLS for incoming traffic. When set to \`permissive\`, the sidecar proxy accepts + mutual TLS traffic on the sidecar proxy service port and accepts any traffic on the destination + service port. We recommend only using \`permissive\` mode if necessary while onboarding services to + the service mesh. `, + }, { name: 'MeshGateway', type: 'MeshGatewayConfig: ', diff --git a/website/content/docs/connect/config-entries/service-defaults.mdx b/website/content/docs/connect/config-entries/service-defaults.mdx index 000b63246c..507176506f 100644 --- a/website/content/docs/connect/config-entries/service-defaults.mdx +++ b/website/content/docs/connect/config-entries/service-defaults.mdx @@ -10,7 +10,7 @@ This topic describes how to configure service defaults configuration entries. Th ## Configuration model -The following outline shows how to format the service splitter configuration entry. Click on a property name to view details about the configuration. +The following outline shows how to format the service defaults configuration entry. Click on a property name to view details about the configuration. @@ -58,6 +58,7 @@ The following outline shows how to format the service splitter configuration ent - [`TransparentProxy`](#transparentproxy): map | no default - [`OutboundListenerPort`](#transparentproxy): integer | `15001` - [`DialedDirectly`](#transparentproxy ): boolean | `false` +- [`MutualTLSMode`](#mutualtlsmode): string | `""` - [`EnvoyExtensions`](#envoyextensions): list | no default - [`Name`](#envoyextensions): string | `""` - [`Required`](#envoyextensions): string | `""` @@ -126,6 +127,7 @@ The following outline shows how to format the service splitter configuration ent - [`transparentProxy`](#transparentproxy): map | no default - [`outboundListenerPort`](#transparentproxy): integer | `15001` - [`dialedDirectly`](#transparentproxy): boolean | `false` + - [`mutualTLSMode`](#mutualtlsmode): string | `""` - [`envoyExtensions`](#envoyextensions): list | no default - [`name`](#envoyextensions): string | `""` - [`required`](#envoyextensions): string | `""` @@ -152,7 +154,7 @@ The following outline shows how to format the service splitter configuration ent ## Complete configuration -When every field is defined, a service splitter configuration entry has the following form: +When every field is defined, a service-defaults configuration entry has the following form: @@ -213,6 +215,7 @@ TransparentProxy = { OutboundListenerPort = 15002 DialedDirectly = true } +MutualTLSMode = "strict" Destination = { Addresses = [ "First IP address", @@ -288,6 +291,7 @@ spec: transparentProxy: outboundListenerPort: 15001 dialedDirectly: false + mutualTLSMode: strict destination: addresses: - @@ -370,6 +374,7 @@ spec: "outboundListenerPort": 15001, "dialedDirectly": false }, + "mutualTLSMode": "strict", "destination": { "addresses": [ "", @@ -697,6 +702,19 @@ You can configure the following parameters in the `TransparentProxy` block: | `OutboundListenerPort` | Specifies the port that the proxy listens on for outbound traffic. This must be the same port number where outbound application traffic is redirected. | integer | `15001` | | `DialedDirectly` | Enables transparent proxies to dial the proxy instance's IP address directly when set to `true`. Transparent proxies commonly dial upstreams at the `"virtual"` tagged address, which load balances across instances. Dialing individual instances can be helpful for stateful services, such as a database cluster with a leader. | boolean | `false` | +### `MutualTLSMode` + +Controls whether mutual TLS is required for incoming connections to this service. This setting is +only supported for services with transparent proxy enabled. We recommend only using `permissive` +mode if necessary while onboarding services to the service mesh. + +You can specify the following string values for the `MutualTLSMode` field: + +- `""`: When this field is empty, the value is inherited from the `proxy-defaults` config entry. +- `strict`: The sidecar proxy requires mutual TLS for incoming traffic. +- `permissive`: The sidecar proxy accepts mutual TLS traffic on the sidecar proxy service port, + and accepts any traffic on the destination service's port. + ### `EnvoyExtensions` List of extensions to modify Envoy proxy configuration. Refer to [Envoy Extensions](/consul/docs/connect/proxies/envoy-extensions) for additional information. @@ -1089,6 +1107,21 @@ You can configure the following parameters in the `TransparentProxy` block: | `outboundListenerPort` | Specifies the port that the proxy listens on for outbound traffic. This must be the same port number where outbound application traffic is redirected. | integer | `15001` | | `dialedDirectly` | Enables transparent proxies to dial the proxy instance's IP address directly when set to `true`. Transparent proxies commonly dial upstreams at the `"virtual"` tagged address, which load balances across instances. Dialing individual instances can be helpful for stateful services, such as a database cluster with a leader. | boolean | `false` | +### `spec.mutualTLSMode` + +Controls whether mutual TLS is required for incoming connections to this service. This setting is +only supported for services with transparent proxy enabled. We recommend only using `permissive` +mode if necessary while onboarding services to the service mesh. + +#### Values + +You can specify the following string values for the `MutualTLSMode` field: + +- `""`: When this field is empty, the value is inherited from the `proxy-defaults` config entry. +- `strict`: The sidecar proxy requires mutual TLS for incoming traffic. +- `permissive`: The sidecar proxy accepts mutual TLS traffic on the sidecar proxy service port, + and accepts any traffic on the destination service's port. + ### `spec.envoyExtensions` List of extensions to modify Envoy proxy configuration. Refer to [Envoy Extensions](/consul/docs/connect/proxies/envoy-extensions) for additional information. diff --git a/website/content/docs/release-notes/consul/v1_13_x.mdx b/website/content/docs/release-notes/consul/v1_13_x.mdx index dd3f7cfe30..f0c4f586a9 100644 --- a/website/content/docs/release-notes/consul/v1_13_x.mdx +++ b/website/content/docs/release-notes/consul/v1_13_x.mdx @@ -15,7 +15,7 @@ description: >- - **Enables TLS on the Envoy Prometheus endpoint**: The Envoy prometheus endpoint can be enabled when `envoy_prometheus_bind_addr` is set and then secured over TLS using new CLI flags for the `consul connect envoy` command. These commands are: `-prometheus-ca-file`, `-prometheus-ca-path`, `-prometheus-cert-file` and `-prometheus-key-file`. The CA, cert, and key can be provided to Envoy by a Kubernetes mounted volume so that Envoy can watch the files and dynamically reload the certs when the volume is updated. -- **UDP Health Checks**: Adds the ability to register service discovery health checks that periodically send UDP datagrams to the specified IP/hostname and port. Refer to [UDP checks](/consul/docs//services/usage/checks#udp-checks). +- **UDP Health Checks**: Adds the ability to register service discovery health checks that periodically send UDP datagrams to the specified IP/hostname and port. Refer to [UDP checks](/consul/docs/services/usage/checks#udp-checks). ## What's Changed @@ -46,4 +46,4 @@ The changelogs for this major release version and any maintenance versions are l - [1.13.3](https://github.com/hashicorp/consul/releases/tag/v1.13.3) - [1.13.4](https://github.com/hashicorp/consul/releases/tag/v1.13.4) - [1.13.5](https://github.com/hashicorp/consul/releases/tag/v1.13.5) -- [1.13.6](https://github.com/hashicorp/consul/releases/tag/v1.13.6) \ No newline at end of file +- [1.13.6](https://github.com/hashicorp/consul/releases/tag/v1.13.6) diff --git a/website/content/docs/services/discovery/dns-configuration.mdx b/website/content/docs/services/discovery/dns-configuration.mdx index 794be43a20..0a10edecdd 100644 --- a/website/content/docs/services/discovery/dns-configuration.mdx +++ b/website/content/docs/services/discovery/dns-configuration.mdx @@ -1,7 +1,7 @@ --- layout: docs -page_title: Configure Consul DNS behavior -description: -> +page_title: Configure Consul DNS behavior +description: -> Learn how to modify the default DNS behavior so that services and nodes can easily discover other services and nodes in your network. --- @@ -12,29 +12,29 @@ This topic describes the default behavior of the Consul DNS functionality and ho ## Introduction The Consul DNS is the primary interface for querying records when Consul service mesh is disabled and your network runs in a non-Kubernetes environment. The DNS enables you to look up services and nodes registered with Consul using terminal commands instead of making HTTP API requests to Consul. Refer to the [Discover Consul Nodes and Services Overview](/consul/docs/services/discovery/dns-overview) for additional information. -## Configure DNS behaviors +## Configure DNS behaviors By default, the Consul DNS listens for queries at `127.0.0.1:8600` and uses the `consul` domain. Specify the following parameters in the agent configuration to determine DNS behavior when querying services: - [`client_addr`](/consul/docs/agent/config/config-files#client_addr) - [`ports.dns`](/consul/docs/agent/config/config-files#dns_port) - [`recursors`](/consul/docs/agent/config/config-files#recursors) -- [`domain`](/consul/docs/agent/config/config-files#domain) +- [`domain`](/consul/docs/agent/config/config-files#domain) - [`alt_domain`](/consul/docs/agent/config/config-files#alt_domain) -- [`dns_config`](/consul/docs/agent/config/config-files#dns_config) +- [`dns_config`](/consul/docs/agent/config/config-files#dns_config) ### Configure WAN address translation By default, Consul DNS queries return a node's local address, even when being queried from a remote datacenter. You can configure the DNS to reach a node from outside its datacenter by specifying the address in the following configuration fields in the Consul agent: -- [advertise-wan](/consul/docs/agent/config/cli-flags#_advertise-wan) -- [translate_wan_addrs](/consul//docs/agent/config/config-files#translate_wan_addrs) +- [advertise-wan](/consul/docs/agent/config/cli-flags#_advertise-wan) +- [translate_wan_addrs](/consul/docs/agent/config/config-files#translate_wan_addrs) ### Use a custom DNS resolver library You can specify a list of addresses in the agent's [`recursors`](/consul/docs/agent/config/config-files#recursors) field to provide upstream DNS servers that recursively resolve queries that are outside the service domain for Consul. - -Nodes that query records outside the `consul.` domain resolve to an upstream DNS. You can specify IP addresses or use `go-sockaddr` templates. Consul resolves IP addresses in the specified order and ignores duplicates. + +Nodes that query records outside the `consul.` domain resolve to an upstream DNS. You can specify IP addresses or use `go-sockaddr` templates. Consul resolves IP addresses in the specified order and ignores duplicates. ### Enable non-Consul queries -You enable non-Consul queries to be resolved by setting Consul as the DNS server for a node and providing a [`recursors`](/consul/docs/agent/config/config-files#recursors) configuration. +You enable non-Consul queries to be resolved by setting Consul as the DNS server for a node and providing a [`recursors`](/consul/docs/agent/config/config-files#recursors) configuration. ### Forward queries to an agent You can forward all queries sent to the `consul.` domain from the existing DNS server to a Consul agent. Refer to [Forward DNS for Consul Service Discovery](/consul/tutorials/networking/dns-forwarding) for instructions. @@ -42,7 +42,7 @@ You can forward all queries sent to the `consul.` domain from the existing DNS s ### Query an alternate domain By default, Consul responds to DNS queries in the `consul` domain, but you can set a specific domain for responding to DNS queries by configuring the [`domain`](/consul/docs/agent/config/config-files#domain) parameter. -You can also specify an additional domain in the [`alt_domain`](/consul/docs/agent/config/config-files#alt_domain) agent configuration option, which configures Consul to respond to queries in a secondary domain. Configuring an alternate domain may be useful during a DNS migration or to distinguish between internal and external queries, for example. +You can also specify an additional domain in the [`alt_domain`](/consul/docs/agent/config/config-files#alt_domain) agent configuration option, which configures Consul to respond to queries in a secondary domain. Configuring an alternate domain may be useful during a DNS migration or to distinguish between internal and external queries, for example. Consul's DNS response uses the same domain as the query. @@ -62,7 +62,7 @@ machine.node.dc1.test-domain. 0 IN A 127.0.0.1 machine.node.dc1.test-domain. 0 IN TXT "consul-network-segment=" ``` #### PTR queries -Responses to pointer record (PTR) queries, such as `.in-addr.arpa.`, always use the [primary domain](/consul/docs/agent/config/config-files#domain) and not the alternative domain. +Responses to pointer record (PTR) queries, such as `.in-addr.arpa.`, always use the [primary domain](/consul/docs/agent/config/config-files#domain) and not the alternative domain. ### Caching By default, DNS results served by Consul are not cached. Refer to the [DNS Caching tutorial](/consul/tutorials/networking/dns-caching) for instructions on how to enable caching. From baaf6d84c749f7abb7b99d895c39b677647e87cd Mon Sep 17 00:00:00 2001 From: Matt Keeler Date: Mon, 12 Jun 2023 11:32:43 -0400 Subject: [PATCH 53/72] Add generic experiments configuration and use it to enable catalog v2 resources (#17604) * Add generic experiments configuration and use it to enable catalog v2 resources * Run formatting with -s as CI will validate that this has been done --- GNUmakefile | 2 +- agent/config/builder.go | 1 + agent/config/config.go | 1 + agent/config/default.go | 3 +++ agent/config/runtime.go | 3 +++ agent/config/runtime_test.go | 2 ++ .../testdata/TestRuntimeConfig_Sanitize.golden | 1 + agent/config/testdata/full-config.hcl | 3 +++ agent/config/testdata/full-config.json | 17 ++++++++++------- agent/consul/options.go | 2 ++ agent/consul/server.go | 16 +++++++++++----- agent/setup.go | 1 + 12 files changed, 39 insertions(+), 13 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index e874fa0eb7..3443b71db7 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -337,7 +337,7 @@ fmt: $(foreach mod,$(GO_MODULES),fmt/$(mod)) .PHONY: fmt/% fmt/%: @echo "--> Running go fmt ($*)" - @cd $* && go fmt ./... + @cd $* && gofmt -s -l -w . .PHONY: lint lint: $(foreach mod,$(GO_MODULES),lint/$(mod)) lint-container-test-deps diff --git a/agent/config/builder.go b/agent/config/builder.go index 063771b0f7..665688b8c8 100644 --- a/agent/config/builder.go +++ b/agent/config/builder.go @@ -828,6 +828,7 @@ func (b *builder) build() (rt RuntimeConfig, err error) { Version: stringVal(c.Version), VersionPrerelease: stringVal(c.VersionPrerelease), VersionMetadata: stringVal(c.VersionMetadata), + Experiments: c.Experiments, // What is a sensible default for BuildDate? BuildDate: timeValWithDefault(c.BuildDate, time.Date(1970, 1, 00, 00, 00, 01, 0, time.UTC)), diff --git a/agent/config/config.go b/agent/config/config.go index d8d7149afe..8917a60858 100644 --- a/agent/config/config.go +++ b/agent/config/config.go @@ -183,6 +183,7 @@ type Config struct { EncryptKey *string `mapstructure:"encrypt" json:"encrypt,omitempty"` EncryptVerifyIncoming *bool `mapstructure:"encrypt_verify_incoming" json:"encrypt_verify_incoming,omitempty"` EncryptVerifyOutgoing *bool `mapstructure:"encrypt_verify_outgoing" json:"encrypt_verify_outgoing,omitempty"` + Experiments []string `mapstructure:"experiments" json:"experiments,omitempty"` GossipLAN GossipLANConfig `mapstructure:"gossip_lan" json:"-"` GossipWAN GossipWANConfig `mapstructure:"gossip_wan" json:"-"` HTTPConfig HTTPConfig `mapstructure:"http_config" json:"-"` diff --git a/agent/config/default.go b/agent/config/default.go index 3af8d0867d..536ac7ac33 100644 --- a/agent/config/default.go +++ b/agent/config/default.go @@ -209,6 +209,9 @@ func DevSource() Source { ports = { grpc = 8502 } + experiments = [ + "resource-apis" + ] `, } } diff --git a/agent/config/runtime.go b/agent/config/runtime.go index dca9abe0e7..1a8dc13794 100644 --- a/agent/config/runtime.go +++ b/agent/config/runtime.go @@ -1498,6 +1498,9 @@ type RuntimeConfig struct { Reporting ReportingConfig + // List of experiments to enable + Experiments []string + EnterpriseRuntimeConfig } diff --git a/agent/config/runtime_test.go b/agent/config/runtime_test.go index 3b1a77b2cb..c1cd85ac50 100644 --- a/agent/config/runtime_test.go +++ b/agent/config/runtime_test.go @@ -325,6 +325,7 @@ func TestLoad_IntegrationWithFlags(t *testing.T) { rt.DisableAnonymousSignature = true rt.DisableKeyringFile = true rt.EnableDebug = true + rt.Experiments = []string{"resource-apis"} rt.UIConfig.Enabled = true rt.LeaveOnTerm = false rt.Logging.LogLevel = "DEBUG" @@ -6355,6 +6356,7 @@ func TestLoad_FullConfig(t *testing.T) { EnableRemoteScriptChecks: true, EnableLocalScriptChecks: true, EncryptKey: "A4wELWqH", + Experiments: []string{"foo"}, StaticRuntimeConfig: StaticRuntimeConfig{ EncryptVerifyIncoming: true, EncryptVerifyOutgoing: true, diff --git a/agent/config/testdata/TestRuntimeConfig_Sanitize.golden b/agent/config/testdata/TestRuntimeConfig_Sanitize.golden index 334f5f8c8f..b6ee9a9812 100644 --- a/agent/config/testdata/TestRuntimeConfig_Sanitize.golden +++ b/agent/config/testdata/TestRuntimeConfig_Sanitize.golden @@ -199,6 +199,7 @@ "EnableRemoteScriptChecks": false, "EncryptKey": "hidden", "EnterpriseRuntimeConfig": {}, + "Experiments": [], "ExposeMaxPort": 0, "ExposeMinPort": 0, "GRPCAddrs": [], diff --git a/agent/config/testdata/full-config.hcl b/agent/config/testdata/full-config.hcl index 660e103608..6029d2ea2e 100644 --- a/agent/config/testdata/full-config.hcl +++ b/agent/config/testdata/full-config.hcl @@ -285,6 +285,9 @@ enable_syslog = true encrypt = "A4wELWqH" encrypt_verify_incoming = true encrypt_verify_outgoing = true +experiments = [ + "foo" +] http_config { block_endpoints = [ "RBvAFcGD", "fWOWFznh" ] allow_write_http_from = [ "127.0.0.1/8", "22.33.44.55/32", "0.0.0.0/0" ] diff --git a/agent/config/testdata/full-config.json b/agent/config/testdata/full-config.json index 52dab37bfa..cd407d3e5d 100644 --- a/agent/config/testdata/full-config.json +++ b/agent/config/testdata/full-config.json @@ -327,6 +327,9 @@ "encrypt": "A4wELWqH", "encrypt_verify_incoming": true, "encrypt_verify_outgoing": true, + "experiments": [ + "foo" + ], "http_config": { "block_endpoints": [ "RBvAFcGD", @@ -407,17 +410,17 @@ "raft_snapshot_interval": "30s", "raft_trailing_logs": 83749, "raft_logstore": { - "backend" : "wal", - "disable_log_cache": true, + "backend": "wal", + "disable_log_cache": true, "verification": { - "enabled": true, - "interval":"12345s" + "enabled": true, + "interval": "12345s" }, "boltdb": { - "no_freelist_sync": true + "no_freelist_sync": true }, "wal": { - "segment_size_mb": 15 + "segment_size_mb": 15 } }, "read_replica": true, @@ -927,4 +930,4 @@ "xds": { "update_max_per_second": 9526.2 } -} +} \ No newline at end of file diff --git a/agent/consul/options.go b/agent/consul/options.go index ac6bfc4106..26cb2471a8 100644 --- a/agent/consul/options.go +++ b/agent/consul/options.go @@ -39,6 +39,8 @@ type Deps struct { // HCP contains the dependencies required when integrating with the HashiCorp Cloud Platform HCP hcp.Deps + Experiments []string + EnterpriseDeps } diff --git a/agent/consul/server.go b/agent/consul/server.go index 418db2da1f..6bb424c675 100644 --- a/agent/consul/server.go +++ b/agent/consul/server.go @@ -79,6 +79,7 @@ import ( raftstorage "github.com/hashicorp/consul/internal/storage/raft" "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/lib/routine" + "github.com/hashicorp/consul/lib/stringslice" "github.com/hashicorp/consul/logging" "github.com/hashicorp/consul/proto-public/pbresource" "github.com/hashicorp/consul/proto/private/pbsubscribe" @@ -131,6 +132,8 @@ const ( reconcileChSize = 256 LeaderTransferMinVersion = "1.6.0" + + catalogResourceExperimentName = "resource-apis" ) const ( @@ -807,7 +810,7 @@ func NewServer(config *Config, flat Deps, externalGRPCServer *grpc.Server, incom s.internalResourceServiceClient, logger.Named(logging.ControllerRuntime), ) - s.registerResources() + s.registerResources(flat) go s.controllerManager.Run(&lib.StopChannelContext{StopCh: shutdownCh}) go s.trackLeaderChanges() @@ -858,11 +861,14 @@ func NewServer(config *Config, flat Deps, externalGRPCServer *grpc.Server, incom return s, nil } -func (s *Server) registerResources() { - catalog.RegisterTypes(s.typeRegistry) - catalog.RegisterControllers(s.controllerManager, catalog.DefaultControllerDependencies()) +func (s *Server) registerResources(deps Deps) { + if stringslice.Contains(deps.Experiments, catalogResourceExperimentName) { + catalog.RegisterTypes(s.typeRegistry) + catalog.RegisterControllers(s.controllerManager, catalog.DefaultControllerDependencies()) + + mesh.RegisterTypes(s.typeRegistry) + } - mesh.RegisterTypes(s.typeRegistry) reaper.RegisterControllers(s.controllerManager) if s.config.DevMode { diff --git a/agent/setup.go b/agent/setup.go index fba5c2b5dd..6a9efb5f74 100644 --- a/agent/setup.go +++ b/agent/setup.go @@ -73,6 +73,7 @@ func NewBaseDeps(configLoader ConfigLoader, logOut io.Writer, providedLogger hcl return d, err } d.WatchedFiles = result.WatchedFiles + d.Experiments = result.RuntimeConfig.Experiments cfg := result.RuntimeConfig logConf := cfg.Logging logConf.Name = logging.Agent From 1074252361949b02fe6d43c744dfcecb8a23613e Mon Sep 17 00:00:00 2001 From: Nathan Coleman Date: Mon, 12 Jun 2023 12:06:04 -0400 Subject: [PATCH 54/72] api-gateway: stop adding all header filters to virtual host when generating xDS (#17644) * Add header filter to api-gateway xDS golden test * Stop adding all header filters to virtual host when generating xDS for api-gateway * Regenerate xDS golden file for api-gateway w/ header filter --- agent/xds/resources_test.go | 13 +++++ agent/xds/routes.go | 12 ----- ...route-and-inline-certificate.latest.golden | 51 +++++++++++++------ 3 files changed, 48 insertions(+), 28 deletions(-) diff --git a/agent/xds/resources_test.go b/agent/xds/resources_test.go index 4687c4a7d6..29743c060b 100644 --- a/agent/xds/resources_test.go +++ b/agent/xds/resources_test.go @@ -415,6 +415,19 @@ func getAPIGatewayGoldenTestCases(t *testing.T) []goldenTestCase { Kind: structs.HTTPRoute, Name: "route", Rules: []structs.HTTPRouteRule{{ + Filters: structs.HTTPFilters{ + Headers: []structs.HTTPHeaderFilter{ + { + Add: map[string]string{ + "X-Header-Add": "added", + }, + Set: map[string]string{ + "X-Header-Set": "set", + }, + Remove: []string{"X-Header-Remove"}, + }, + }, + }, Services: []structs.HTTPService{{ Name: "service", }}, diff --git a/agent/xds/routes.go b/agent/xds/routes.go index dbd74f511e..a86747a9c0 100644 --- a/agent/xds/routes.go +++ b/agent/xds/routes.go @@ -477,8 +477,6 @@ func (s *ResourceGenerator) routesForAPIGateway(cfgSnap *proxycfg.ConfigSnapshot return nil, err } - addHeaderFiltersToVirtualHost(&reformatedRoute, virtualHost) - defaultRoute.VirtualHosts = append(defaultRoute.VirtualHosts, virtualHost) } @@ -1097,16 +1095,6 @@ func injectHeaderManipToRoute(dest *structs.ServiceRouteDestination, r *envoy_ro return nil } -func addHeaderFiltersToVirtualHost(dest *structs.HTTPRouteConfigEntry, vh *envoy_route_v3.VirtualHost) { - for _, rule := range dest.Rules { - for _, header := range rule.Filters.Headers { - vh.RequestHeadersToAdd = append(vh.RequestHeadersToAdd, makeHeadersValueOptions(header.Add, true)...) - vh.RequestHeadersToAdd = append(vh.RequestHeadersToAdd, makeHeadersValueOptions(header.Set, false)...) - vh.RequestHeadersToRemove = append(vh.RequestHeadersToRemove, header.Remove...) - } - } -} - func injectHeaderManipToVirtualHost(dest *structs.IngressService, vh *envoy_route_v3.VirtualHost) error { if !dest.RequestHeaders.IsZero() { vh.RequestHeadersToAdd = append( diff --git a/agent/xds/testdata/routes/api-gateway-with-http-route-and-inline-certificate.latest.golden b/agent/xds/testdata/routes/api-gateway-with-http-route-and-inline-certificate.latest.golden index 6abc6f2946..a1669268ec 100644 --- a/agent/xds/testdata/routes/api-gateway-with-http-route-and-inline-certificate.latest.golden +++ b/agent/xds/testdata/routes/api-gateway-with-http-route-and-inline-certificate.latest.golden @@ -1,31 +1,50 @@ { - "versionInfo": "00000001", - "resources": [ + "versionInfo": "00000001", + "resources": [ { - "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "name": "8080", - "virtualHosts": [ + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "8080", + "virtualHosts": [ { - "name": "api-gateway-listener-9b9265b", - "domains": [ + "name": "api-gateway-listener-9b9265b", + "domains": [ "*", "*:8080" ], - "routes": [ + "routes": [ { - "match": { - "prefix": "/" + "match": { + "prefix": "/" }, - "route": { - "cluster": "service.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" - } + "route": { + "cluster": "service.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + }, + "requestHeadersToAdd": [ + { + "header": { + "key": "X-Header-Add", + "value": "added" + }, + "append": true + }, + { + "header": { + "key": "X-Header-Set", + "value": "set" + }, + "append": false + } + ], + "requestHeadersToRemove": [ + "X-Header-Remove" + ] } ] } ], - "validateClusters": true + "validateClusters": true } ], - "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "nonce": "00000001" + "typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "nonce": "00000001" } \ No newline at end of file From f8d3721885e2a1bbf0a078b5940b340197853081 Mon Sep 17 00:00:00 2001 From: Poonam Jadhav Date: Mon, 12 Jun 2023 12:07:43 -0400 Subject: [PATCH 55/72] fix: add agent info reporting log (#17654) --- command/agent/agent.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/command/agent/agent.go b/command/agent/agent.go index c2d0dcea09..c241fa2b7b 100644 --- a/command/agent/agent.go +++ b/command/agent/agent.go @@ -231,6 +231,9 @@ func (c *cmd) run(args []string) int { ui.Info(fmt.Sprintf(" Gossip Encryption: %t", config.EncryptKey != "")) ui.Info(fmt.Sprintf(" Auto-Encrypt-TLS: %t", config.AutoEncryptTLS || config.AutoEncryptAllowTLS)) ui.Info(fmt.Sprintf(" ACL Enabled: %t", config.ACLsEnabled)) + if config.ServerMode { + ui.Info(fmt.Sprintf(" Reporting Enabled: %t", config.Reporting.License.Enabled)) + } ui.Info(fmt.Sprintf("ACL Default Policy: %s", config.ACLResolverSettings.ACLDefaultPolicy)) ui.Info(fmt.Sprintf(" HTTPS TLS: Verify Incoming: %t, Verify Outgoing: %t, Min Version: %s", config.TLS.HTTPS.VerifyIncoming, config.TLS.HTTPS.VerifyOutgoing, config.TLS.HTTPS.TLSMinVersion)) From 862e78f063b40db49d1160690b092a6e9afa5888 Mon Sep 17 00:00:00 2001 From: Tu Nguyen Date: Mon, 12 Jun 2023 10:30:04 -0700 Subject: [PATCH 56/72] Add new Consul 1.16 docs (#17651) * Merge pull request #5773 from hashicorp/docs/rate-limiting-from-ip-addresses-1.16 updated docs for rate limiting for IP addresses - 1.16 * Merge pull request #5609 from hashicorp/docs/enterprise-utilization-reporting Add docs for enterprise utilization reporting * Merge pull request #5734 from hashicorp/docs/envoy-ext-1.16 Docs/envoy ext 1.16 * Merge pull request #5773 from hashicorp/docs/rate-limiting-from-ip-addresses-1.16 updated docs for rate limiting for IP addresses - 1.16 * Merge pull request #5609 from hashicorp/docs/enterprise-utilization-reporting Add docs for enterprise utilization reporting * Merge pull request #5734 from hashicorp/docs/envoy-ext-1.16 Docs/envoy ext 1.16 * fix build errors --------- Co-authored-by: trujillo-adam <47586768+trujillo-adam@users.noreply.github.com> --- .../docs/agent/config/config-files.mdx | 4 + website/content/docs/agent/config/index.mdx | 1 + website/content/docs/agent/limits/index.mdx | 49 +- .../limits/set-global-traffic-rate-limits.mdx | 114 --- .../limits/{ => usage}/init-rate-limits.mdx | 9 +- .../usage/limit-request-rates-from-ips.mdx | 66 ++ .../limits/usage/monitor-rate-limits.mdx | 77 ++ .../usage/set-global-traffic-rate-limits.mdx | 62 ++ .../control-plane-request-limit.mdx | 224 ++++++ .../configuration/ext-authz.mdx | 726 ++++++++++++++++++ .../configuration/property-override.mdx | 273 +++++++ .../envoy-extensions/configuration/wasm.mdx | 484 ++++++++++++ .../proxies/envoy-extensions/index.mdx | 23 +- .../envoy-extensions/usage/ext-authz.mdx | 147 ++++ .../usage/property-override.mdx | 203 +++++ .../proxies/envoy-extensions/usage/wasm.mdx | 191 +++++ .../license/utilization-reporting.mdx | 168 ++++ .../partials/envoy_ext_rule_matcher.mdx | 9 + website/data/docs-nav-data.json | 93 ++- 19 files changed, 2765 insertions(+), 158 deletions(-) delete mode 100644 website/content/docs/agent/limits/set-global-traffic-rate-limits.mdx rename website/content/docs/agent/limits/{ => usage}/init-rate-limits.mdx (66%) create mode 100644 website/content/docs/agent/limits/usage/limit-request-rates-from-ips.mdx create mode 100644 website/content/docs/agent/limits/usage/monitor-rate-limits.mdx create mode 100644 website/content/docs/agent/limits/usage/set-global-traffic-rate-limits.mdx create mode 100644 website/content/docs/connect/config-entries/control-plane-request-limit.mdx create mode 100644 website/content/docs/connect/proxies/envoy-extensions/configuration/ext-authz.mdx create mode 100644 website/content/docs/connect/proxies/envoy-extensions/configuration/property-override.mdx create mode 100644 website/content/docs/connect/proxies/envoy-extensions/configuration/wasm.mdx create mode 100644 website/content/docs/connect/proxies/envoy-extensions/usage/ext-authz.mdx create mode 100644 website/content/docs/connect/proxies/envoy-extensions/usage/property-override.mdx create mode 100644 website/content/docs/connect/proxies/envoy-extensions/usage/wasm.mdx create mode 100644 website/content/docs/enterprise/license/utilization-reporting.mdx create mode 100644 website/content/partials/envoy_ext_rule_matcher.mdx diff --git a/website/content/docs/agent/config/config-files.mdx b/website/content/docs/agent/config/config-files.mdx index 6e50cbb44a..4183a5a7d2 100644 --- a/website/content/docs/agent/config/config-files.mdx +++ b/website/content/docs/agent/config/config-files.mdx @@ -711,6 +711,10 @@ Refer to the [formatting specification](https://golang.org/pkg/time/#ParseDurati servers in all federated datacenters must have this enabled before any client can use [`use_streaming_backend`](#use_streaming_backend). +- `reporting` - This option allows options for HashiCorp reporting. + - `license` - The license object allows users to control automatic reporting of license utilization metrics to HashiCorp. + - `enabled`: (Defaults to `true`) Enables automatic license utilization reporting. + - `segment` - Equivalent to the [`-segment` command-line flag](/consul/docs/agent/config/cli-flags#_segment). ~> **Warning:** The `segment` option cannot be used with the [`partition`](#partition-1) option. diff --git a/website/content/docs/agent/config/index.mdx b/website/content/docs/agent/config/index.mdx index 0ea4a030fb..c620ef72e0 100644 --- a/website/content/docs/agent/config/index.mdx +++ b/website/content/docs/agent/config/index.mdx @@ -73,6 +73,7 @@ The following agent configuration options are reloadable at runtime: them without a restart provides a recovery path that doesn't involve downtime. They generally shouldn't be changed otherwise. - [RPC rate limits](/consul/docs/agent/config/config-files#limits) +- [Reporting](/consul/docs/agent/config/config-files#reporting) - [HTTP Maximum Connections per Client](/consul/docs/agent/config/config-files#http_max_conns_per_client) - Services - TLS Configuration diff --git a/website/content/docs/agent/limits/index.mdx b/website/content/docs/agent/limits/index.mdx index ffa259cfd6..0d12f1127a 100644 --- a/website/content/docs/agent/limits/index.mdx +++ b/website/content/docs/agent/limits/index.mdx @@ -2,32 +2,51 @@ layout: docs page_title: Limit Traffic Rates Overview description: Rate limiting is a set of Consul server agent configurations that you can use to mitigate the risks to Consul servers when clients send excessive requests to Consul resources. - --- # Traffic rate limiting overview -This topic provides an overview of the rates limits you can configure for Consul servers. + +This topic provides overview information about the traffic rates limits you can configure for Consul datacenters. ## Introduction -You can configure global RPC rate limits to mitigate the risks to Consul servers when clients send excessive read or write requests to Consul resources. A _read request_ is defined as any request that does not modify Consul internal state. A _write request_ is defined as any request that modifies Consul internal state. Rate limits for read and write requests are configured separately. -## Rate limit modes +Configuring rate limits on RPC and gRPC traffic mitigates the risks to Consul servers when client agents or services send excessive read or write requests to Consul resources. A _read_ request is defined as any request that does not modify Consul internal state. A _write_ request is defined as any request that modifies Consul internal state. Configure read and write request limits independently. + +## Workflow + +You can set global limits on the rate of read and write requests that affect individual servers in the datacenter. You can set limits for all source IP addresses, which enables you to specify a budget for read and write requests to prevent any single source IP from overwhelming the Consul server and negatively affecting the network. The following steps describe the general process for setting global read and write rate limits: + +1. Set arbitrary limits to begin understanding the upper boundary of RPC and gRPC loads in your network. Refer to [Initialize rate limit settings](/consul/docs/agent/limits/usage/init-rate-limits) for additional information. -You can set one of the following modes to determine how Consul servers react when exceeding request limits. - -- **Enforcing mode**: The rate limiter denies requests to a server once they exceed the configured rate. In this mode, Consul generates metrics and logs to help you understand your network's load and configure limits accordingly. -- **Permissive mode**: The rate limiter allows requests to a server once they exceed the configured rate. In this mode, Consul generates metrics and logs to help you understand your Consul load and configure limits accordingly. Use this mode to help you debug specific issues as you configure limits. -- **Disabled mode**: Disables the rate limiter. This mode allows all requests Consul does not generate logs or metrics. This is the default mode. +1. Monitor the metrics and logs and readjust the initial configurations as necessary. Refer to [Monitor rate limit data](/consul/docs/agent/limits/usage/monitor-rate-limit-data) -Refer to [`rate_limits`](/consul/docs/agent/config/config-files#request_limits) for additional configuration information. +1. Define your final operational limits based on your observations. If you are defining global rate limits, refer to [Set global traffic rate limits](/consul/docs/agent/limits/usage/set-global-rate-limits) for additional information. For information about setting limits based on source IP, refer to [Limit traffic rates for a source IP](/consul/docs/agent/limits/usage/set-source-ip-rate-limits). -## Request denials +### Order of operations -When an HTTP request is denied for rate limiting reason, Consul returns one of the following errors: +You can define request rate limits in the agent configuration and in the control plane request limit configuration entry. The configuration entry also supports rate limit configurations for Consul resources. Consul perfroms the following order of operations when determing request rate limits: -- **429 Resource Exhausted**: Indicates that a server is not able to perform the request but that another server could potentially fulfill it. This error is most common on stale reads because any server may fulfill stale read requests. To resolve this type of error, we recommend immediately retrying the request to another server. If the request came from a Consul client agent, the agent automatically retries the request up to the limit set in the [`rpc_hold_timeout`](/consul/docs/agent/config/config-files#rpc_hold_timeout) configuration . +1. Parse request. +1. Does the request reach a global server limit? + - No: Proceed to the next stage. + - Yes: Return an error that the requested resource has been exhausted. +1. Does the request reach a limit associated with its source IP address? + - No: Proceed to the next stage. + - Yes: Return an error that the requested resource has been exhausted. +1. Resolve the Consul Enterprise metadata. +1. Does the request reach a limit associated with the source partition? + - No: Proceed to the next stage. + - Yes: Return an error that the requested resource has been exhausted. +1. Does the request reach a limit associated with the source namespace? + - No: Proceed to the next stage. + - Yes: Return an error that the requested resource has been exhausted. +1. Resolve the ACL identity associated with the request. +1. Does the request reach a limit associated with its identity? + - No: Proceed to the next stage. + - Yes: Return an error that the requested resource has been exhausted. +1. Handle the request. -- **503 Service Unavailable**: Indicates that server is unable to perform the request and that no other server can fulfill the request, either. This usually occurs on consistent reads or for writes. In this case we recommend retrying according to an exponential backoff schedule. If the request came from a Consul client agent, the agent automatically retries the request according to the [`rpc_hold_timeout`](/consul/docs/agent/config/config-files#rpc_hold_timeout) configuration. +## Kubernetes -Refer to [Rate limit reached on the server](/consul/docs/troubleshoot/common-errors#rate-limit-reached-on-the-server) for additional information. \ No newline at end of file +To define global rate limits, configure the `request_limits` settings in the Consul Helm chart. Refer to the [Helm chart reference](/consul/docs/k8s/helm) for additional information. Refer to the [control plane request limit configuration entry reference](/consul/docs/connect/config-entries/control-plane-request-limit) for information about applying a CRD for limiting traffic rates from source IPs. \ No newline at end of file diff --git a/website/content/docs/agent/limits/set-global-traffic-rate-limits.mdx b/website/content/docs/agent/limits/set-global-traffic-rate-limits.mdx deleted file mode 100644 index 5d4fc43df0..0000000000 --- a/website/content/docs/agent/limits/set-global-traffic-rate-limits.mdx +++ /dev/null @@ -1,114 +0,0 @@ ---- -layout: docs -page_title: Set a Global Limit on Traffic Rates -description: Use global rate limits to prevent excessive rates of requests to Consul servers. ---- - -# Set a global limit on traffic rates - -This topic describes how to configure rate limits for RPC and gRPC traffic to the Consul server. - -## Introduction - -Rate limits apply to each Consul server separately and limit the number of read requests or write requests to the server on the RPC and internal gRPC endpoints. - -Because all requests coming to a Consul server eventually perform an RPC or an internal gRPC request, global rate limits apply to Consul's user interfaces, such as the HTTP API interface, the CLI, and the external gRPC endpoint for services in the service mesh. - -Refer to [Initialize Rate Limit Settings](/consul/docs/agent/limits/init-rate-limits) for additional information about right-sizing your gRPC request configurations. - -## Set a global rate limit for a Consul server - -Configure the following settings in your Consul server configuration to limit the RPC and gRPC traffic rates. - -- Set the rate limiter [`mode`](/consul/docs/agent/config/config-files#mode-1) -- Set the [`read_rate`](/consul/docs/agent/config/config-files#read_rate) -- Set the [`write_rate`](/consul/docs/agent/config/config-files#write_rate) - -In the following example, the Consul server is configured to prevent more than `500` read and `200` write RPC calls: - - - -```hcl -limits = { - rate_limit = { - mode = "enforcing" - read_rate = 500 - write_rate = 200 - } -} -``` - -```json -{ - "limits" : { - "rate_limit" : { - "mode" : "enforcing", - "read_rate" : 500, - "write_rate" : 200 - } - } -} - -``` - - - -## Access rate limit logs - -Consul prints a log line for each rate limit request. The log includes information to identify the source of the request and the server's configured limit. Consul prints to `DEBUG` log level, and can be configured to drop log lines to avoid affecting the server health. Dropping a log line increments the `rpc.rate_limit.log_dropped` metric. - -The following example log shows that RPC request from `127.0.0.1:53562` to `KVS.Apply` exceeded the rate limit: - - - -```shell-session -2023-02-17T10:01:15.565-0500 [DEBUG] agent.server.rpc-rate-limit: RPC -exceeded allowed rate limit: rpc=KVS.Apply source_addr=127.0.0.1:53562 -limit_type=global/write limit_enforced=false -``` - - -## Review rate limit metrics - -Consul captures the following metrics associated with rate limits: - -- Type of limit -- Operation -- Rate limit mode - -Call the `agent/metrics` API endpoint to view the metrics associated with rate limits. Refer to [View Metrics](/consul/api-docs/agent#view-metrics) for API usage information. - -In the following example, Consul dropped a call to the `consul` service because it exceeded the limit by one call: - -```shell-session -$ curl http://127.0.0.1:8500/v1/agent/metrics -{ - . . . - "Counters": [ - { - "Name": "consul.rpc.rate_limit.exceeded", - "Count": 1, - "Sum": 1, - "Min": 1, - "Max": 1, - "Mean": 1, - "Stddev": 0, - "Labels": { - "service": "consul" - } - }, - { - "Name": "consul.rpc.rate_limit.log_dropped", - "Count": 1, - "Sum": 1, - "Min": 1, - "Max": 1, - "Mean": 1, - "Stddev": 0, - "Labels": {} - } - ], - . . . -``` - -Refer to [Telemetry](/consul/docs/agent/telemetry) for additional information. diff --git a/website/content/docs/agent/limits/init-rate-limits.mdx b/website/content/docs/agent/limits/usage/init-rate-limits.mdx similarity index 66% rename from website/content/docs/agent/limits/init-rate-limits.mdx rename to website/content/docs/agent/limits/usage/init-rate-limits.mdx index 7dbabbe6c7..e90aaf77af 100644 --- a/website/content/docs/agent/limits/init-rate-limits.mdx +++ b/website/content/docs/agent/limits/usage/init-rate-limits.mdx @@ -1,6 +1,6 @@ --- layout: docs -page_title: Initialize Rate Limit Settings +page_title: Initialize rate limit settings description: Learn how to determine regular and peak loads in your network so that you can set the initial global rate limit configurations. --- @@ -14,7 +14,7 @@ Because each network has different needs and application, you need to find out w - Number of servers and the projected load - Existing metrics expressing requests per second -1. Set the `mode` to `permissive`. In the following example, the configuration allows up to 1000 reads and 500 writes per second for each Consul agent: +1. Set the [`limits.request_limits.mode`](/consul/docs/agent/config/config-files#mode-1) parameter in the agent configuration to `permissive`. In the following example, the configuration allows up to 1000 reads and 500 writes per second for each Consul agent: ```hcl request_limits { @@ -22,9 +22,8 @@ Because each network has different needs and application, you need to find out w read_rate = 1000.0 write_rate = 500.0 } - ``` - -1. Observe the logs and metrics for your application's typical cycle, such as a 24 hour period. Refer to [`log_file`](/consul/docs/agent/config/config-files#log_file) for information about where to retrieve logs. Call the [`/agent/metrics`](/consul/api-docs/agent#view-metrics) HTTP API endpoint and check the data for the following metrics: + ``` +1. Observe the logs and metrics for your application's typical cycle, such as a 24 hour period. Refer to [Monitor traffic rate limit data](/consul/docs/agent/limits/usage/monitor-rate-limit) for additional information. Call the [`/agent/metrics`](/consul/api-docs/agent#view-metrics) HTTP API endpoint and check the data for the following metrics: - `rpc.rate_limit.exceeded` with value `global/read` for label `limit_type` - `rpc.rate_limit.exceeded` with value `global/write` for label `limit_type` diff --git a/website/content/docs/agent/limits/usage/limit-request-rates-from-ips.mdx b/website/content/docs/agent/limits/usage/limit-request-rates-from-ips.mdx new file mode 100644 index 0000000000..c074d3007a --- /dev/null +++ b/website/content/docs/agent/limits/usage/limit-request-rates-from-ips.mdx @@ -0,0 +1,66 @@ +--- +layout: docs +page_title: Limit traffic rates for a source IP address +description: Learn how to set read and request rate limits on RPC and gRPC traffic from all source IP addresses to a Consul resource. +--- + +# Limit traffic rates from source IP addresses + +This topic describes how to configure RPC and gRPC traffic rate limits for source IP addresses. This enables you to specify a budget for read and write requests to prevent any single source IP from overwhelming the Consul server and negatively affecting the network. For information about setting global traffic rate limits, refer to [Set a global limit on traffic rates](/consul/docs/agent/limits/usage/set-glogal-traffic-rate-limits). For an overview of Consul's server rate limiting capabilities, refer to [Limit traffic rates overview](/consul/docs/agent/limits/overview). + +## Overview + +You can set limits on the rate of read and write requests from source IP addresses to specific resources, which mitigates the risks to Consul servers when consul clients send excessive requests to a specific resource type. Before configuring traffic rate limits, you should complete the initialization process to understand normal traffic loads in your network. Refer to [Initialize rate limit settings](/consul/docs/agent/limits/init-rate-limits) for additional information. + +Complete the following steps to configure traffic rate limits from a source IP address: + +1. Define rate limits in a control plan request limit configuration entry. You can set limits for different types of resources calls. + +1. Apply the configuration entry to enact the limits. + +You should also monitor read and write rate activity and make any necessary adjustments. Refer to [Monitor rate limit data](/consul/docs/agent/limits/usage/monitor-rate-limits) for additional information. + +## Define rate limits + +Create a control plane request limit configuration entry in the `default` partition. The configuration entry applies to all client requests targeting any partition. Refer to the [control plane request limit configuration entry](/consul/docs/connect/config-entries/control-plan-request-limit) reference documentation for details about the available configuration parameters. + +Specify the following parameters: + +- `kind`: This must be set to `control-plane-request-limit`. +- `name`: Specify the name of the service that you want to limit read and write operations to. +- `read_rate`: Specify overall number of read operations per second allowed from the service. +- `write_rate`: Specify overall number of write operations per second allowed from the service. + +You can also configure limits on calls to the key-value store, ACL system, and Consul catalog. + +## Apply the configuration entry + +If your network is deployed to virtual machines, use the `consul config write` command and specify the control plane request limit configuration entry to apply the configuration. For Kubernetes-orchestrated networks, use the `kubectl apply` command. + + + + +```shell-session +$ consul config write control-plane-request-limit.hcl +``` + + + + +```shell-session +$ consul config write control-plane-request-limit.json +``` + + + + +```shell-session +$ kubectl apply control-plane-request-limit.yaml +``` + + + + +## Disable request rate limits + +Set the [limits.request_limits.mode](/consul/docs/agent/config/config-files#mode-1) in the agent configuration to `disabled` to allow services to exceed the specified read and write requests limits. The `disabled` mode applies to all request rate limits, even limits specifed in the [control plane request limits configuration entry](/consul/docs/connect/config-entries/control-plane-request-limits). Note that any other mode specified in the agent configuration only applies to global traffic rate limits. \ No newline at end of file diff --git a/website/content/docs/agent/limits/usage/monitor-rate-limits.mdx b/website/content/docs/agent/limits/usage/monitor-rate-limits.mdx new file mode 100644 index 0000000000..23906041b3 --- /dev/null +++ b/website/content/docs/agent/limits/usage/monitor-rate-limits.mdx @@ -0,0 +1,77 @@ +--- +layout: docs +page_title: Monitor traffic rate limit data +description: Learn about the metrics and logs you can use to monitor server rate limiting activity, include rate limits for read operations and writer operations +--- + +# Monitor traffic rate limit data + +This topic describes Consul functionality that enables you to monitor read and write request operations taking place in your network. Use the functionality to help you understand normal workloads and set safe limits on the number of requests Consul client agents and services can make to Consul servers. + +## Access rate limit logs + +Consul prints a log line for each rate limit request. The log provides the necessary information for identifying the source of the request and the configured limit. The log provides the information necessary for identifying the source of the request and the configured limit. Consul prints the log `DEBUG` log level and can drop the log to avoid affecting the server health. Dropping a log line increments the `rpc.rate_limit.log_dropped` metric. + +The following example log shows that RPC request from `127.0.0.1:53562` to `KVS.Apply` exceeded the limit: + +```text +2023-02-17T10:01:15.565-0500 [DEBUG] agent.server.rpc-rate-limit: RPC +exceeded allowed rate limit: rpc=KVS.Apply source_addr=127.0.0.1:53562 +limit_type=global/write limit_enforced=false +``` + +Refer to [`log_file`](/consul/docs/agent/config/config-files#log_file) for information about where to retrieve log files. + +## Review rate limit metrics + +Consul captures the following metrics associated with rate limits: + +- Type of limit +- Operation +- Rate limit mode + +Call the `/agent/metrics` API endpoint to view the metrics associated with rate limits. Refer to [View Metrics](/consul/api-docs/agent#view-metrics) for API usage information. In the following example, Consul dropped a call to the consul service because it exceeded the limit by one call: + +```shell-session +$ curl http://127.0.0.1:8500/v1/agent/metrics +{ + . . . + "Counters": [ + { + "Name": "consul.rpc.rate_limit.exceeded", + "Count": 1, + "Sum": 1, + "Min": 1, + "Max": 1, + "Mean": 1, + "Stddev": 0, + "Labels": { + "service": "consul" + } + }, + { + "Name": "consul.rpc.rate_limit.log_dropped", + "Count": 1, + "Sum": 1, + "Min": 1, + "Max": 1, + "Mean": 1, + "Stddev": 0, + "Labels": {} + } + ], + . . . +} +``` + +Refer to [Telemetry](/consul/docs/telemetry) for additional information. + +## Request denials + +When an HTTP request is denied for rate limiting reason, Consul returns one of the following errors: + +- **429 Resource Exhausted**: Indicates that a server is not able to perform the request but that another server could potentially fulfill it. This error is most common on stale reads because any server may fulfill stale read requests. To resolve this type of error, we recommend immediately retrying the request to another server. If the request came from a Consul client agent, the agent automatically retries the request up to the limit set in the [`rpc_hold_timeout`](/consul/docs/agent/config/config-files#rpc_hold_timeout) configuration . + +- **503 Service Unavailable**: Indicates that server is unable to perform the request and that no other server can fulfill the request, either. This usually occurs on consistent reads or for writes. In this case we recommend retrying according to an exponential backoff schedule. If the request came from a Consul client agent, the agent automatically retries the request according to the [`rpc_hold_timeout`](/consul/docs/agent/config/config-files#rpc_hold_timeout) configuration. + +Refer to [Rate limit reached on the server](/consul/docs/troubleshoot/common-errors#rate-limit-reached-on-the-server) for additional information. \ No newline at end of file diff --git a/website/content/docs/agent/limits/usage/set-global-traffic-rate-limits.mdx b/website/content/docs/agent/limits/usage/set-global-traffic-rate-limits.mdx new file mode 100644 index 0000000000..61a4066ec9 --- /dev/null +++ b/website/content/docs/agent/limits/usage/set-global-traffic-rate-limits.mdx @@ -0,0 +1,62 @@ +--- +layout: docs +page_title: Set a global limit on traffic rates +description: Use global rate limits to prevent excessive rates of requests to Consul servers. +--- + +# Set a global limit on traffic rates + +This topic describes how to configure rate limits for RPC and gRPC traffic to the Consul server. + +## Introduction + +Rate limits apply to each Consul server separately and limit the number of read requests or write requests to the server on the RPC and internal gRPC endpoints. + +Because all requests coming to a Consul server eventually perform an RPC or an internal gRPC request, global rate limits apply to Consul's user interfaces, such as the HTTP API interface, the CLI, and the external gRPC endpoint for services in the service mesh. + +Refer to [Initialize Rate Limit Settings](/consul/docs/agent/limits/init-rate-limits) for additional information about right-sizing your gRPC request configurations. + +## Set a global rate limit for a Consul server + +Configure the following settings in your Consul server configuration to limit the RPC and gRPC traffic rates. + +- Set the rate limiter [`mode`](/consul/docs/agent/config/config-files#mode-1) +- Set the [`read_rate`](/consul/docs/agent/config/config-files#read_rate) +- Set the [`write_rate`](/consul/docs/agent/config/config-files#write_rate) + +In the following example, the Consul server is configured to prevent more than `500` read and `200` write RPC calls: + + + +```hcl +limits = { + rate_limit = { + mode = "enforcing" + read_rate = 500 + write_rate = 200 + } +} +``` + +```json +{ + "limits" : { + "rate_limit" : { + "mode" : "enforcing", + "read_rate" : 500, + "write_rate" : 200 + } + } +} + +``` + + + +## Monitor request rate traffic + +You should continue to mmonitor request traffic to ensure that request rates remain within the threshold you defined. Refer to [Monitor traffic rate limit data](/consul/docs/agent/limits/usage/monitor-rate-limits) for instructions about checking metrics and log entries, as well as troubleshooting informaiton. + +## Disable request rate limits + +Set the [limits.request_limits.mode](/consul/docs/agent/config/config-files#mode-1) to `disabled` to allow services to exceed the specified read and write requests limits, even limits specifed in the [control plane request limits configuration entry](/consul/docs/connect/config-entries/control-plane-request-limits). Note that any other mode specified in the agent configuration only applies to global traffic rate limits. diff --git a/website/content/docs/connect/config-entries/control-plane-request-limit.mdx b/website/content/docs/connect/config-entries/control-plane-request-limit.mdx new file mode 100644 index 0000000000..c6b44436ac --- /dev/null +++ b/website/content/docs/connect/config-entries/control-plane-request-limit.mdx @@ -0,0 +1,224 @@ +--- +layout: docs +page_title: Control Plane Request Limit Configuration Entry Configuration Reference +description: Learn how to configure the control-plane-request-limit configuration entry, which defines how Consul agents limit read and reqeust traffic rate limits. +--- + +# Control Plane Request Limit Configuration Entry Configuration Reference + +This topic describes the configuration options for the `control-plane-request-limit` configuration entry. You can only write the `control-plane-request-limit` configuration entry to the `default` partition, but the configuration entry applies to all client requests that target any partition. + +## Configuration model + +The following list outlines field hierarchy, language-specific data types, and requirements in a control plane request limit configuration entry. Click on a property name to view additional details, including default values. + +- [`kind`](#kind): string | required | must be set to `control-plane-request-limit` +- [`mode`](#mode): string | required | default is `permissive` +- [`name`](#name): string | required +- [`read_rate`](#read-rate): number | `100` +- [`write_rate`](#write-rate): number | `100` +- [`kv`](#kv): map | no default + - [`read_rate`](#kv-read-rate): number | `100` + - [`write_rate`](#kv-write-rate): number | `100` +- [`acl`](#acl): map | no default + - [`read_rate`](#acl-read-rate): number | `100` + - [`write_rate`](#acl-write-rate): number | `100` +- [`catalog`](#catalog): map + - [`read_rate`](#catalog-read-rate): number | default is `100` + - [`write_rate`](#catalog-write-rate): number | default is `100` + +## Complete configuration + +When every field is defined, a control plane request limit configuration entry has the following form: + + + +```hcl +kind = "control-plane-request-limit" +mode = "permissive" +name = "" +read_rate = 100 +write_rate = 100 +kv = { + read_rate = 100 + write_rate = 100 + } +acl = { + read_rate = 100 + write_rate = 100 +mode = "permissive" + } +catalog = { + read_rate = 100 + write_rate = 100 + } +``` + +```json +{ + "kind": "control-plane-request-limit", + "mode": "permissive", + "name": "", + "read_rate": 100, + "write_rate": 100, + "kv": { + "read_rate": 100, + "write_rate": 100 + }, + "acl": { + "read_rate": 100, + "write_rate": 100 + }, + "catalog: { + "read_rate": 100, + "write_rate": 100 + } +} +``` + +```yaml +kind: control-plane-request-limit +mode: permissive +name: +read_rate: 100 +write_rate: 100 +kv: + read_rate: 100 + write_rate: 100 +acl: + read_rate: 100 + write_rate: 100 +catalog: + read_rate: 100 + write_rate: 100 +``` + + + +## Specification + +This section provides details about the fields you can configure in the control plane request limit configuration entry. + +### `kind` + +Specifies the type of configuration entry to implement. Must be set to`control-plane-request-limit` + +#### Values + +- Default: none +- This field is required. +- Data type: String value that must be set to`control-plane-request-limit`. + +### `mode` + +Specifies an action to take if the rate of requests exceeds the limit. + +#### Values + +- Default: None +- This field is required. +- One of the following string values: + - `permissive`: The server continues to allow requests and records an error in the logs. This is the default value for `mode`. + - `enforcing`: The server stops accepting requests and records an error in the logs. + - `disabled`: Limits are not enforced or tracked. + +### `name` + +Specifies the name of the configuration entry. + +#### Values + +- Default: none +- This field is required. +- Data type: string + +### `read_rate` + +Specifies the maximum number of read requests per second that the agent allows. + +#### Values + +- Default: No limit. +- Data type: number + +### `write_rate` + +Specifies the maximum number of write requests per second that the agent allows. + +#### Values + +- Default: No limit. +- Data type: number + +### `kv` + +Specifies the maximum number of read and write requests to the Consul key-value store. + +#### Values + +- Default: none +- Data type is a map containing the following parameters: + - `read_rate` + - `write_rate` + +### `kv.read_rate` + +Specifies the maximum number of read requests per second allowed to the Consul key-value store. + +#### Values + +- Default: No limit. +- Data type: number + +### `kv.write_rate` + +Specifies the maximum number of write requests per second allowed to the Consul key-value store. + +#### Values + +- Default: No limit. +- Data type: number + +### `acl` + +Specifies the maximum number of read and write ACL requests to the Consul server. + +### `acl.read_rate` +S +pecifies the maximum number of ACL read requests per second allowed to the Consul server. + +#### Values + +- Default: No limit. +- Data type: number + +### `acl.write_rate` + +Specifies the maximum number of ACL write requests per second allowed to the Consul server. + +#### Values + +- Default: No limit. +- Data type: number + +### catalog + +Specifies the maximum number of read and write requests to the Consul catalog. + +### `catalog.read_rate` + +Specifies the maximum number of read requests per second allowed to the Consul catalog. + +#### Values + +- Default: No limit. +- Data type: number + +### `catalog.write_rate` + +Specifies the maximum number of write requests per second allowed to the Consul catalog. + +#### Values + +- Default: No limit. +- Data type: number \ No newline at end of file diff --git a/website/content/docs/connect/proxies/envoy-extensions/configuration/ext-authz.mdx b/website/content/docs/connect/proxies/envoy-extensions/configuration/ext-authz.mdx new file mode 100644 index 0000000000..6b5d8cc272 --- /dev/null +++ b/website/content/docs/connect/proxies/envoy-extensions/configuration/ext-authz.mdx @@ -0,0 +1,726 @@ +--- +layout: docs +page_title: External authorization extension configuration reference +description: Learn how to configure the ext-authz Envoy extension, which is a builtin Consul extension that configures Envoy proxies to request authorization from an external service. +--- + +# External authorization extension configuration reference + +This topic describes how to configure the external authorization Envoy extension, which configures Envoy proxies to request authorization from an external service. Refer to [Delegate authorization to an external service](/consul/docs/connect/proxies/envoy-extensions/usage/ext-authz) for usage information. + +## Configuration model + +The following list outlines the field hierarchy, data types, and requirements for the external authorization configuration. Place the configuration inside the `EnvoyExtension.Arguments` field in the proxy defaults or service defaults configuration entry. Refer to the following documentation for additional information: + +- [`EnvoyExtensions` in proxy defaults](/consul/docs/connect/config-entries/proxy-defaults#envoyextensions) +- [`EnvoyExtensions` in service defaults](/consul/docs/connect/config-entries/service-defaults#envoyextensions) + - [Envoy External Authorization documentation](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto) + +Click on a property name to view additional details, including default values. + +- [`Name`](#name): string | required | must be set to `builtin/ext-authz` +- [`Arguments`](#arguments): map | required + - [`ProxyType`](#arguments-proxytype): string | required | `connect-proxy` + - [`InsertOptions`](#arguments-insertoptions): map + - [`Location`](#arguments-insertoptions-location): string + - [FilterName](#arguments-insertoptions-filtername): string + - [`Config`](#arguments-config): map | required + - [`BootstrapMetadataLabelsKey`](#arguments-config-bootstrapmetadatalabelskey): string + - [`ClearRouteCache`](#arguments-config-grpcservice): boolean | `false` | HTTP only + - [`GrpcService`](#arguments-config-grpcservice): map + - [`Target`](#arguments-config-grpcservice-target): map | required + - [`Service`](#arguments-config-grpcservice-target-service): map + - [`Name`](#arguments-config-grpcservice-target-service): string + - [`Namespace`](#arguments-config-grpcservice-target-service): string | + - [`Partition`](#arguments-config-grpcservice-target-service): string | + - [`URI`](#arguments-config-grpcservice-target-uri): string + - [`Timeout`](#arguments-config-grpcservice-target-uri): string | `1s` + - [`Authority`](#arguments-config-grpcservice-authority): string + - [`InitialMetadata`](#arguments-config-grpcservice-initialmetadata): list + - [`Key`](#arguments-config-grpcservice-initialmetadata): string + - [`Value`](#arguments-config-grpcservice-initialmetadata): string + - [`HttpService`](#arguments-config-httpservice): map + - [`Target`](#arguments-config-httpservice-target): map | required + - [`Service`](#arguments-config-httpservice): string + - [`Name`](#arguments-config-httpservice-target-service): string + - [`Namespace`](#arguments-config-httpservice-target-service): string | + - [`Partition`](#arguments-config-httpservice-target-service): string | + - [`URI`](#arguments-config-httpservice): string + - [`Timeout`](#arguments-config-httpservice): string | `1s` + - [`PathPrefix`](#arguments-config-httpservice-pathprefix): string + - [`AuthorizationRequest`](#arguments-config-httpservice-authorizationrequest): map + - [`AllowedHeaders`](#arguments-config-httpservice-authorizationrequest-allowedheaders): list + - [`Contains`](#arguments-config-httpservice-authorizationrequest-allowedheaders): string + - [`Exact`](#arguments-config-httpservice-authorizationrequest-allowedheaders): string + - [`IgnoreCase`](#arguments-config-httpservice-authorizationrequest-allowedheaders): boolean + - [`Prefix`](#arguments-config-httpservice-authorizationrequest-allowedheaders): string + - [`SafeRegex`](#arguments-config-httpservice-authorizationrequest-allowedheaders): string + - [`HeadersToAdd`](#arguments-config-httpservice-authorizationrequest-headerstoadd): list + - [`Key`](#arguments-config-httpservice-authorizationrequest-headerstoadd): string + - [`Value`](#arguments-config-httpservice-authorizationrequest-headerstoadd): string + - [`AuthorizationResponse`](#arguments-config-httpservice-authorizationresponse): map + - [`AllowedUpstreamHeaders`](#arguments-config-httpservice-authorizationresponse-allowedupstreamheaders): list + - [`Contains`](#arguments-config-httpservice-authorizationresponse-allowedupstreamheaders): string + - [`Exact`](#arguments-config-httpservice-authorizationresponse-allowedheaders): string + - [`IgnoreCase`](#arguments-config-httpservice-authorizationresponse-allowedheaders): boolean + - [`Prefix`](#arguments-config-httpservice-authorizationresponse-allowedheaders): string + - [`SafeRegex`](#arguments-config-httpservice-authorizationresponse-allowedheaders): string + - [`Suffix`](#arguments-config-httpservice-authorizationresponse-allowedheaders): string + - [`AllowedUpstreamHeadersToAppend`](#arguments-config-httpservice-authorizationresponse-allowedupstreamheaderstoappend): list + - [`Contains`](#arguments-config-httpservice-authorizationresponse-allowedupstreamheaderstoappend): string + - [`Exact`](#arguments-config-httpservice-authorizationresponse-allowedupstreamheaderstoappend): string + - [`IgnoreCase`](#arguments-config-httpservice-authorizationresponse-allowedupstreamheaderstoappend): boolean + - [`Prefix`](#arguments-config-httpservice-authorizationresponse-allowedupstreamheaderstoappend): string + - [`SafeRegex`](#arguments-config-httpservice-authorizationresponse-allowedupstreamheaderstoappend): string + - [`Suffix`](#arguments-config-httpservice-authorizationresponse-allowedupstreamheaderstoappend): string + - [`AllowedClientHeaders`](#arguments-config-httpservice-authorizationresponse-allowedclientheaders): list + - [`Contains`](#arguments-config-httpservice-authorizationresponse-allowedclientheaders): string + - [`Exact`](#arguments-config-httpservice-authorizationresponse-allowedclientheaders): string + - [`IgnoreCase`](#arguments-config-httpservice-authorizationresponse-allowedclientheaders): boolean + - [`Prefix`](#arguments-config-httpservice-authorizationresponse-allowedclientheaders): string + - [`SafeRegex`](#arguments-config-httpservice-authorizationresponse-allowedclientheaders): string + - [`Suffix`](#arguments-config-httpservice-authorizationresponse-allowedclientheaders): string + - [`AllowedClientHeadersOnSuccess`](#arguments-config-httpservice-authorizationresponse-allowedclientheadersonsuccess): list + - [`Contains`](#arguments-config-httpservice-authorizationresponse-allowedclientheadersonsuccess): string + - [`Exact`](#arguments-config-httpservice-authorizationresponse-allowedclientheadersonsuccess): string + - [`IgnoreCase`](#arguments-config-httpservice-authorizationresponse-allowedclientheadersonsuccess): boolean + - [`Prefix`](#arguments-config-httpservice-authorizationresponse-allowedclientheadersonsuccess): string + - [`SafeRegex`](#arguments-config-httpservice-authorizationresponse-allowedclientheadersonsuccess): string + - [`Suffix`](#arguments-config-httpservice-authorizationresponse-allowedclientheadersonsuccess): string + - [`DynamicMetadataFromHeaders`](#arguments-config-httpservice-authorizationresponse-dynamicmetadatafromheaders): list + - [`Contains`](#arguments-config-httpservice-authorizationresponse-dynamicmetadatafromheaders): string + - [`Exact`](#arguments-config-httpservice-authorizationresponse-dynamicmetadatafromheaders): string + - [`IgnoreCase`](#arguments-config-httpservice-authorizationresponse-dynamicmetadatafromheaders): boolean + - [`Prefix`](#arguments-config-httpservice-authorizationresponse-dynamicmetadatafromheaders): string + - [`SafeRegex`](#arguments-config-httpservice-authorizationresponse-dynamicmetadatafromheaders): string + - [`Suffix`](#arguments-config-httpservice-authorizationresponse-dynamicmetadatafromheaders): string + - [`IncludePeerCertificate`](#arguments-config-includepeercertificate): boolean | `false` + - [`MetadataContextNamespaces`](#arguments-config-metadatacontextnamespaces): list of strings | HTTP only + - [`StatusOnError`](#arguments-config-statusonerror): number | `403` | HTTP only + - [`StatPrefix`](#arguments-config-statprefix): string | `response` + - [`WithRequestBody`](#arguments-config-withrequestbody): map | HTTP only + - [`MaxRequestBytes`](#arguments-config-withrequestbody-maxrequestbytes): number + - [`AllowPartialMessage`](#arguments-config-withrequestbody-allowpartialmessage): boolean | `false` + - [`PackAsBytes`](#arguments-config-withrequestbody-packasbytes): boolean | `false` + +## Complete configuration + +When each field is defined, an `ext-authz` configuration has the following form: + +```hcl +Name = "builtin/ext-authz" +Arguments = { + ProxyType = "connect-proxy" + InsertOptions = { + Location = "" + FilterName = "" + } + Config = { + BootstrapMetadataLabelsKey = "" + ClearRouteCache = false // HTTP only + GrpcService = { + Target = { + Service = { + Name = "" + Namespace = "" + Partition = "" + URI = "" + Timeout = "1s" + Authority = "" + InitialMetadata = [ + "" : "" + HttpService = { + Target = { + Service = { + Name = "" + Namespace = "" + Partition = "" + URI = "" + Timeout = "1s" + } + } + PathPrefix = "//" + AuthorizationRequest = { + AllowedHeaders = [ + Contains = "", + Exact = "", + IgnoreCase = false, + Prefix = "", + SafeRegex = "" + ] + HeadersToAdd = [ + "
" = "
" + ] + } + AuthorizationResponse = { + AllowedUpstreamHeaders = [ + Contains = "", + Exact = "", + IgnoreCase = false, + Prefix = "", + SafeRegex = "" + Suffix = "" + ] + AllowedUpstreamHeadersToAppend = [ + Contains = "", + Exact = "", + IgnoreCase = false, + Prefix = "", + SafeRegex = "" + Suffix = "" + ] + AllowedClientHeaders = [ + Contains = "", + Exact = "", + IgnoreCase = false, + Prefix = "", + SafeRegex = "" + Suffix = "" + ] + AllowedClientHeadersOnSuccess = [ + Contains = "", + Exact = "", + IgnoreCase = false, + Prefix = "", + SafeRegex = "" + Suffix = "" + DynamicMetadataFromHeaders = [ + Contains = "", + Exact = "", + IgnoreCase = false, + Prefix = "", + SafeRegex = "" + Suffix = "" + ] + IncludePeerCertificate = false + MetadataContextNamespaces = [ + "" + ] + StatusOnError = 403 // HTTP only + StatPrefix = "response" + WithRequestBody = { //HTTP only + MaxRequestBytes = + AllowPartialMessage = false + PackAsBytes = false +``` + +## Specification + +This section provides details about the fields you can configure for the external authorization extension. +### `Name` + +Specifies the name of the extension. Must be set to `builtin/ext-authz`. + +#### Values + +- Default: None +- This field is required. +- Data type: String value set to `builtin/ext-authz`. + +### `Arguments` + +Contains the global configuration for the extension. + +#### Values + +- Default: None +- This field is required. +- Data type: Map + +### `Arguments.ProxyType` + +Specifies the type of Envoy proxy that this extension applies to. The extension only applies to proxies that match this type and is ignored for all other proxy types. The only supported value is `connect-proxy`. + +#### Values + +- Default: `connect-proxy` +- This field is required. +- Data type: String + +### `Arguments.InsertOptions` + +Specifies options for defining the insertion point for the external authorization filter in the Envoy filter chain. By default, the external authorization filter is inserted as the first filter in the filter chain per the default setting for the [`Location`](#arguments-insertoptions-location) field. + +#### Values + +- Default: None +- Data type: Map + +### `Arguments.InsertOptions.Location` + +Specifies the insertion point for the external authorization filter in the Envoy filter chain. You can specify one of the following string values: + +- `First`: Inserts the filter as the first filter in the filter chain, regardless of the filter specified in the `FilterName` field. +- `BeforeLast`: Inserts the filter before the last filter in the chain, regardless of the filter specified in the `FilterName` field. This allows the filter to be inserted after all other filters and immediately before the terminal filter. +- `AfterFirstMatch`: Inserts the filter after the first filter in the chain that has a name matching the value of the `FilterName` field. +- `AfterLastMatch`: Inserts the filter after the last filter in the chain that has a name matching the value of the `FilterName` field. +- `BeforeFirstMatch`: Inserts the filter before the first filter in the chain that has a name matching the value of the `FilterName` field. +- `BeforeLastMatch`: Inserts the filter before the last filter in the chain that has a name matching the value of the `FilterName` field. + +#### Values + +- Default: `BeforeFirstMatch` +- Data type: String + +### `Arguments.InsertOptions.FilterName` + +Specifies the name of an existing filter in the chain to match when inserting the external authorization filter. Specifying a filter name enables you to configure an insertion point relative to the position of another filter in the chain. + +#### Values + +- Default: `envoy.filters.network.tcp_proxy` for TCP services. `envoy.filters.http.router` for HTTP services. +- Data type: String + +### `Arguments.Config` + +Contains the configuration settings for the extension. + +#### Values + +- Default: None +- This field is required. +- Data type: Map + +### `Arguments.Config.BootstrapMetadataLabelsKey` + +Specifies a key from the Envoy bootstrap metadata. Envoy adds labels associated with the key to the authorization request context. + +#### Values + +- Default: None +- Data type: String + +### `Arguments.Config.ClearRouteCache` + +Directs Envoy to clear the route cache so that the external authorization service correctly affects routing decisions. If set to `true`, the filter clears all cached routes. + +Envoy also clears cached routes if the status returned from the authorization service is `200` for HTTP responses or `0` for gRPC responses. Envoy also clears cached routes if at least one authorization response header is added to the client request or is used for altering another client request header. + +#### Values + +- Default: `false` +- Data type: Boolean + + +### `Arguments.Config.GrpcService` + +Specifies the external authorization configuration for gRPC requests. Configure the `GrpcService` or the [`HttpService`](#arguments-config-httpservice) settings, but not both. + +#### Values + +- Default: None +- Either the `GrpcService` or the `HttpService` configuration is required. +- Data type: Map + +### `Arguments.Config.GrpcService.Target` + +Configuration for specifying the service to send gRPC authorization requests to. The `Target` field may contain the following fields: + +- [`Service`](#arguments-config-grpcservice-target-service) or [`Uri`](#arguments-config-grpcservice-target-uri) +- [`Timeout`](#arguments-config-grpcservice-target-timeout) + + +#### Values + +- Default: None +- This field is required. +- Data type: Map + +### `Arguments{}.Config{}.GrpcService{}.Target{}.Service{}` + +Specifies the upstream external authorization service. Configure this field when authorization requests are sent to an upstream service within the service mesh. The service must be configured as an upstream of the service that the filter is applied to. + +Configure either the `Service` field or the [`Uri`](#arguments-config-grpcservice-target-uri) field, but not both. + +#### Values + +- Default: None +- This field or [`Uri`](#arguments-config-grpcservice-target-uri) is required. +- Data type: Map + +The following table describes how to configure parameters for the `Service` field: + +| Parameter | Description | Data type | Default | +| --- | --- | --- | --- | +| `Name` | Specifies the name of the upstream service. | String | None | +| `Namespace` | Specifies the Consul namespace that the upstream service belongs to. | String | `default` | +| `Partition` | Specifies the Consul admin partition that the upstream service belongs to. | String | `default` | + +### `Arguments.Config.GrpcService.Target.Uri` + +Specifies the URI of the external authorization service. Configure this field when you must provide an explicit URI to the external authorization service, such as cases in which the authorization service is running on the same host or pod. If set, the value of this field must be either `localhost:` or `127.0.0.1:` + +Configure either the `Uri` field or the [`Service`](#arguments-config-grpcservice-target-service) field, but not both. + +#### Values + +- Default: None +- This field or [`Service`](#arguments-config-grpcservice-target-service) is required. +- Data type: String + +### `Arguments.Config.GrpcService.Target.Timeout` + +Specifies the maximum duration that a response can take to arrive upon request. + +#### Values + +- Default: `1s` +- Data type: String + +### `Arguments.Config.GrpcService.Authority` + +Specifies the authority header to send in the gRPC request. If this field is not set, the authority field is set to the cluster name. This field does not override the SNI that Envoy sends to the external authorization service. + +#### Values + +- Default: Cluster name +- Data type: String + +### `Arguments.Config.GrpcService.InitialMetadata[]` + +Specifies additional metadata to include in streams initiated to the `GrpcService`. You can specify metadata for injecting additional ad-hoc authorization headers, for example, `x-foo-bar: baz-key`. For more information, including details on header value syntax, refer to the [Envoy documentation on custom request headers](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/headers#config-http-conn-man-headers-custom-request-headers). + +#### Values + +- Default: None +- Data type: List of one or more key-value pairs: + + - KEY: String + - VALUE: String + +### `Arguments{}.Config{}.HttpService{}` + +Contains the configuration for raw HTTP communication between the filter and the external authorization service. Configure the `HttpService` or the [`GrpcService`](#arguments-config-grpcservice) settings, but not both. + +#### Values + +- Default: None +- Either the `HttpService` or the `GrpcService` configuration is required. +- Data type: Map + +### `Arguments{}.Config{}.HttpService{}.Target{}` + +Configuration for specifying the service to send HTTP authorization requests to. The `Target` field may contain the following fields: + +- [`Service`](#arguments-config-httpservice-target-service) or [`Uri`](#arguments-config-httpservice-target-uri) +- [`Timeout`](#arguments-config-httpservice-target-timeout) + + +#### Values + +- Default: None +- This field is required. +- Data type: Map + +### `Arguments{}.Config{}.HttpService{}.Target{}.Service{}` + +Specifies the upstream external authorization service. Configure this field when HTTP authorization requests are sent to an upstream service within the service mesh. The service must be configured as an upstream of the service that the filter is applied to. + +Configure either the `Service` field or the [`Uri`](#arguments-config-httpservice-target-uri) field, but not both. + +#### Values + +- Default: None +- This field or [`Uri`](#arguments-config-httpservice-target-uri) is required. +- Data type: Map + +The following table describes how to configure parameters for the `Service` field: + +| Parameter | Description | Data type | Default | +| --- | --- | --- | --- | +| `Name` | Specifies the name of the upstream service. | String | None | +| `Namespace` | Specifies the Consul namespace that the upstream service belongs to. | String | `default` | +| `Partition` | Specifies the Consul admin partition that the upstream service belongs to. | String | `default` | + +### `Arguments{}.Config{}.HttpService{}.Target{}.Uri` + +Specifies the URI of the external authorization service. Configure this field when you must provide an explicit URI to the external authorization service, such as cases in which the authorization service is running on the same host or pod. + +Configure either the `Uri` field or the [`Service`](#arguments-config-httpservice-target-service) field, but not both. + +#### Values + +- Default: None +- This field or [`Service`](#arguments-config-httpservice-target-service) is required. +- Data type: String + +### `Arguments{}.Config{}.HttpService{}.Target{}.Timeout` + +Specifies the maximum duration that a response can take to arrive upon request. + +#### Values + +- Default: `1s` +- Data type: String + +### `Arguments{}.Config{}.HttpService{}.PathPrefix` + +Specifies a prefix for the value of the authorization request header `Path`. You must include the preceding forward slash (`/`). + +#### Values + +- Default: None +- Data type: String + +### `Arguments{}.Config{}.HttpService{}.AuthorizationRequest{}` + +HTTP-only configuration that controls the HTTP authorization request metadata. The `AuthorizationRequest` field may contain the following parameters: + +- [`AllowHeaders`](#arguments-config-httpservice-authorizationrequest-allowheaders) +- [`HeadersToAdd`](#arguments-config-httpservice-authorizationrequest-headerstoadd) + +#### Values + +- Default: None +- Data type: Map + +### `Arguments{}.Config{}.HttpService{}.AuthorizationRequest{}.AllowHeaders[]` + +Specifies a set of rules for matching client request headers. The request to the external authorization service includes any client request headers that satisfy any of the rules. Refer to the [Envoy documentation](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_authz/v3/ext_authz.proto#extensions-filters-http-ext-authz-v3-extauthz) for a detailed explanation. + +#### Values + +- Default: None +- Data type: List of key-value pairs + +The following table describes the matching rules you can configure in the `AllowHeaders` field: + +@include 'envoy_ext_rule_matcher.mdx' + +### `Arguments{}.Config{}.HttpService{}.AuthorizationRequest{}.HeadersToAdd[]` + +Specifies a list of headers to include in the request to the authorization service. Note that Envoy overwrites client request headers with the same key. + +#### Values + +- Default: None +- Data type: List of one or more key-value pairs: + + - KEY: String + - VALUE: String + +### `Arguments{}.Config{}.HttpService{}.AuthorizationResponse{}` + +HTTP-only configuration that controls HTTP authorization response metadata. The `AuthorizationResponse` field may contain the following parameters: + +- [`AllowedUpstreamHeaders`](#arguments-config-httpservice-authorizationresponse-allowedupstreamheaders) +- [`AllowedUpstreamHeadersToAppend`](#arguments-config-httpservice-authorizationresponse-allowedupstreamheaderstoappend) +- [`AllowedClientHeaders`](#arguments-config-httpservice-authorizationresponse-allowedclientheaders) +- [`AllowedClientHeadersOnSuccess`](#arguments-config-httpservice-authorizationresponse-allowedclientheadersonsuccess) +- [`DynamicMetadataFromHeaders`](#arguments-config-httpservice-authorizationresponse-dynamicmetadatafromheaders) + +#### Values + +- Default: None +- Data type: Map + +### `Arguments{}.Config{}.HttpService{}.AuthorizationResponse{}.AllowedUpstreamHeaders[]` + +Specifies a set of rules for matching authorization response headers. Envoy adds any headers from the external authorization service to the client response that satisfy the rules. Envoy overwrites existing headers. + +#### Values + +- Default: None +- Data type: Map + +The following table describes the matching rules you can configure in the `AllowedUpstreamHeaders` field: + +@include 'envoy_ext_rule_matcher.mdx' + +### `Arguments{}.Config{}.HttpService{}.AuthorizationResponse{}.AllowedUpstreamHeadersToAppend[]` + +Specifies a set of rules for matching authorization response headers. Envoy appends any headers from the external authorization service to the client response that satisfy the rules. Envoy appends existing headers. + +#### Values + +- Default: None +- Data type: Map + +The following table describes the matching rules you can configure in the `AllowedUpstreamHeadersToAppend` field: + +@include 'envoy_ext_rule_matcher.mdx' + +### `Arguments{}.Config{}.HttpService{}.AuthorizationResponse{}.AllowedClientHeaders[]` + +Specifies a set of rules for matching client response headers. Envoy adds any headers from the external authorization service to the client response that satisfy the rules. When the list is not set, Envoy includes all authorization response headers except `Authority (Host)`. When a header is included in this list, Envoy automatically adds the following headers: + +- `Path` +- `Status` +- `Content-Length` +- `WWWAuthenticate` +- `Location` + +#### Values + +- Default: None +- Data type: Map + +The following table describes the matching rules you can configure in the `AllowedClientHeaders` field: + +@include 'envoy_ext_rule_matcher.mdx' + +### `Arguments{}.Config{}.HttpService{}.AuthorizationResponse{}.AllowedClientHeadersOnSuccess[]` + +Specifies a set of rules for matching client response headers. Envoy adds headers from the external authorization service to the client response when the headers satisfy the rules and the authorization is successful. If the headers match the rules but the authorization fails or is denied, the headers are not added. If this field is not set, Envoy does not add any additional headers to the client's response on success. + +#### Values + +- Default: None +- Data type: Map + +The following table describes the matching rules you can configure in the `AllowedClientHeadersOnSuccess` field: + +@include 'envoy_ext_rule_matcher.mdx' + +### `Arguments{}.Config{}.HttpService{}.AuthorizationResponse{}.DynamicMetadataFromHeaders[]` + +Specifies a set of rules for matching authorization response headers. Envoy emits headers from the external authorization service as dynamic metadata that the next filter in the chain can consume. + +#### Values + +- Default: None +- Data type: Map + +The following table describes the matching rules you can configure in the `DynamicMetadataFromHeaders` field: + +@include 'envoy_ext_rule_matcher.mdx' + +### `Arguments{}.Config{}.IncludePeerCertificate` + +If set to `true`, Envoy includes the peer X.509 certificate in the authorization request if the certificate is available. + +#### Values + +- Default: `false` +- Data type: Boolean + +### `Arguments{}.Config{}.MetadataContextNamespace[]` + +HTTP only field that specifies a list of metadata namespaces. The values of the namespaces are included in the authorization request context. The `consul` namespace is always included in addition to the namespaces you configure. + +#### Values + +- Default: `["consul"]` +- Data type: List of string values + +### `Arguments{}.Config{}.StatusOnError` + +HTTP only field that specifies a return code status to respond with on error. Refer to the [Envoy documentation](https://www.envoyproxy.io/docs/envoy/latest/api-v3/type/v3/http_status.proto#enum-type-v3-statuscode) for additional information. + +#### Values + +- Default: `403` +- Data type: Integer + +### `Arguments{}.Config{}.StatPrefix` + +Specifies a prefix to add when writing statistics. + +#### Values + +- Default: `response` +- Data type: String + +### `Arguments{}.Config{}.WithRequestBody{}` + +HTTP only field that configures Envoy to buffer the client request body and send it with the authorization request. If unset, the request body is not sent with the authorization request. + +#### Values + +- Default: None +- Data type: Map + +The following table describes the parameters that you can include in the `WithRequestBody` field: + +| Parameter | Description | Data type | Default | +| --- | --- | --- | --- | +| `MaxRequestBytes` | Specifies the maximum size of the message body that the filter holds in memory. Envoy returns HTTP `403` and does not initiate the authorization process when the buffer reaches the number set in this field unless `AllowPartialMessage` is set to `true`. | uint32 | None | +| `AllowPartialMessage` | If set to `true`, Envoy buffers the request body until the value of `MaxRequestBytes` is reached. The authorization request is dispatched with a partial body and no `413` HTTP error returns by the filter. | Boolean | `false` | +| `PackAsBytes` | If set to `true`, Envoy sends the request body to the external authorization as raw bytes. Otherwise, Envoy sends the request body as a UTF-8 encoded string. | Boolean | `false` | + +## Examples + +The following examples demonstrate common configuration patterns for specific use cases. + +### Authorize gRPC requests to a URI + +In the following example, a service defaults configuration entry contains an `ext-authz` configuration. The configuration allows the `api` service to make gRPC authorization requests to a service at `localhost:9191`: + +```hcl +Kind = "service-defaults" +Name = "api" +EnvoyExtensions = [ + { + Name = "builtin/ext-authz" + Arguments = { + ProxyType = "connect-proxy" + Config = { + GrpcService = { + Target = { + URI = "127.0.0.1:9191" + } + } + } + } + } +] +``` + +### Upstream authorization + +In the following example, a service defaults configuration entry contains an `ext-authz` configuration. The configuration allows the `api` service to make gRPC authorization requests to a service named `authz`: + +```hcl +Kind = "service-defaults" +Name = "api" +EnvoyExtensions = [ + { + Name = "builtin/ext-authz" + Arguments = { + ProxyType = "connect-proxy" + Config = { + GrpcService = { + Target = { + Service = { + Name = "authz" + } + } + } + } + } + } +] +``` + +### Authorization requests after service intentions for Consul Enterprise + +In the following example for Consul Enterprise, the `api` service is configured to make an HTTP authorization requests to a service named `authz` in the `foo` namespace and `bar` partition. Envoy also inserts the external authorization filter after the `envoy.filters.http.rbac` filter: + +```hcl +Kind = "service-defaults" +Name = "api" +Protocol = "http" +EnvoyExtensions = [ + { + Name = "builtin/ext-authz" + Arguments = { + ProxyType = "connect-proxy" + InsertOptions = { + Location = "AfterLastMatch" + FilterName = "envoy.filters.http.rbac" + } + Config = { + HttpService = { + Target = { + Service = { + Name = "authz" + Namespace = "foo" + Partition = "bar" + } + } + } + } + } + } +] +``` diff --git a/website/content/docs/connect/proxies/envoy-extensions/configuration/property-override.mdx b/website/content/docs/connect/proxies/envoy-extensions/configuration/property-override.mdx new file mode 100644 index 0000000000..9b13cb940b --- /dev/null +++ b/website/content/docs/connect/proxies/envoy-extensions/configuration/property-override.mdx @@ -0,0 +1,273 @@ +--- +layout: docs +page_title: Property override configuration reference +description: Learn how to configure the property-override plugin, which is a builtin Consul plugin that allows you to set and remove Envoy proxy properties. +--- + +# Property override configuration reference + +This topic describes how to configure the `property-override` extension so that you can set and remove individual properties on the Envoy resources Consul generates. Refer to [Configure Envoy proxy properties](/consul/docs/connect/proxies/envoy-extensions/usage/property-override) for usage information. + +## Configuration model + +The following list outlines the field hierarchy, data types, and requirements for the `property-override` configuration. Place the configuration inside the `EnvoyExtension.Arguments` field in the proxy defaults or service defaults configuration entry. Refer the following documentation for additional information: + +- [`EnvoyExtensions` in proxy defaults](/consul/docs/connect/config-entries/proxy-defaults#envoyextensions) +- [`EnvoyExtensions` in service defaults](/consul/docs/connect/config-entries/service-defaults#envoyextensions) + +Click on a property name to view additional details, including default values. + +- [`ProxyType`](#proxytype): string | required +- [`Debug`](#debug): bool | `false` +- [`Patches`](#patches): list | required + - [`ResourceFilter`](#patches-resourcefilter): map + - [`ResourceType`](#patches-resourcefilter-resourcetype): string | required + - [`TrafficDirection`](#patches-resourcefilter-trafficdirection): string | required + - [`Services`](#patches-resourcefilter-services): list + - [`Name`](#patches-resourcefilter-services-name): string + - [`Namespace`](#patches-resourcefilter-services-namespace): string | `default` | + - [`Partition`](#patches-resourcefilter-services-partition): string | `default` | + - [`Op`](#patches-op): string | required + - [`Path`](#patches-path): string | required + - [`Value`](#patches-value): map, number, boolean, or string + +## Complete configuration + +When each field is defined, a `property-override` configuration has the following form: + + +```hcl +ProxyType = "connect-proxy" +Debug = false +Patches = [ + { + ResourceFilter = { + ResourceType = "" + TrafficDirection = "" + Services = [ + { + Name = "", + Namespace = "" + Partition = "" + } + ] + Op = "", + Path = "", + Value = "" + } +] +``` + +## Specification + +This section provides details about the fields you can configure for the `property-override` extension. + +### `ProxyType` + +Specifies the type of Envoy proxy that the extension applies to. The only supported value is `connect-proxy`. + +#### Values + +- Default: `connect-proxy` +- This field is required. +- Data type: String + +### `Debug` + +Enables full debug mode. When `Debug` is set to `true`, all possible fields for the given `ResourceType` and first unmatched segment of `Path` are returned on error. When set to `false`, the error message only includes the first ten possible fields. + +#### Values + +- Default: `false` +- Data type: Boolean + +### `Patches[]` + +Specifies a list of one or more JSON Patches that map to the Envoy proxy configurations you want to modify. Refer to [IETF RFC 6902](https://datatracker.ietf.org/doc/html/rfc6902/) for information about the JSON Patch specification. + +#### Values + +- Default: None +- The `Patches` parameter is a list of configurations in JSON Patch format. Each patch can contain the following fields: + - [`ResourceFilter`](#patches-resourcefilter) + - [`Op`](#patches-op) + - [`Path`](#patches-path) + - [`Value`](#patches-value) + + +### `Patches[].ResourceFilter{}` + +Specifies the filter for targeting specific Envoy resources. The `ResourceFilter` configuration is not part of the JSON Patch specification. + +#### Values + +- Default: None +- This field is required. +- Data type: Map + +The following table describes how to configure a `ResourceFilter`: + +| Parameter | Description | Type | +| --- | --- | --- | +| `ProxyType` | Specifies the proxy type that the extension applies to. The only supported value is `connect-proxy`. | String | +| `ResourceType` | Specifies the Envoy resource type that the extension applies to. You can specify one of the following values for each `ResourceFilter`:
  • `cluster`
  • `cluster-load-assignment`
  • `route`
  • `listener`
| String | +| `TrafficDirection` | Specifies the type of traffic that the extension applies to relative to the current proxy. You can specify one of the following values for each `ResourceFilter`:
  • `inbound`: Targets resources for the proxy's inbound traffic.
  • `outbound`: Targets resources for the proxy's upstream services.
| String | +| `Services` | Specifies a list of services to target. Each member of the list has the following fields:
  • `Name`: Specifies the service associated with the traffic.
  • `Namespace`: Specifies the Consul Enterprise namespace the service is in.
  • `Partition`: Specifies the Consul Enterprise admin partition the service is in.
If `TrafficDirection` is set to `outbound`, upstream services in this field correspond to local Envoy resources that Consul patches at runtime.

Do not configure the `Services` field if `TrafficDirection` is set to `inbound`.

If this field is not set, Envoy targets all applicable resources. When patching outbound listeners, the patch includes the outbound transparent proxy listener only if `Services` is unset and if the local service is in transparent proxy mode. | List of maps | + +### `Patches[].Op` + +Specifies the JSON Patch operation to perform when the `ResourceFilter` matches a local Envoy proxy configuration. You can specify one of the following values for each patch: + +- `add`: Replaces a property or message specified by [`Path`](#patches-path) with the given value. The JSON patch format does not merge objects. To emulate merges, you must configure discrete `add` operations for each changed field. Consul returns an error if the target field does not exist in the corresponding schema. +- `remove`: Unsets the value of the field specified by [`Path`](#patches-path). If the field is not set, no changes are made. Consul returns an error if the target field does not exist in the corresponding schema. + +#### Values + +- Default: None +- This field is required. +- Data type is one of the following string values: + - `add` + - `remove` + +### `Patches[].Path` + +Specifies where the extension performs the associated operation on the specified resource type. Refer to [`ResourceType`](#patches-resourcefilter) for information about specifying a resource type to target. Refer to [`Op`](#patches-op) for information about setting an operation to perform on the resources. + +The `Path` field does not support addressing array elements or protobuf map field entries. Refer to [Constructing paths](/consul/docs/connect/proxies/envoy-extensions/usage/property-override#constructing-paths) for information about how to construct paths. + +When setting fields, the extension sets any unset intermediate fields to their default values. A a single operation on a nested field can set multiple intermediate fields. Because Consul sets the intermediate fields to their default values, you may need to configure subsequent patches to satisfy Envoy or Consul validation. + +#### Values + +- Default: None +- This field is required. +- Data type: String + +### `Patches[].Value{}` + +Defines a value to set at the specified [path](#patches-path) if the [operation](#patches-op) is set to `add`. You can specify either a scalar or enum value or define a map that contains string keys and values corresponding to scalar or enum child fields. Refer to the [example configurations](#examples) for additional guidance and to the [Envoy API documentation](https://www.envoyproxy.io/docs/envoy/latest/api-v3/api) for additional information about Envoy proxy interfaces. + +If Envoy specifies a wrapper as the target field type, the extension automatically coerces simple values to the wrapped type when patching. For example, the value `32768` is allowed when targeting a cluster's `per_connection_buffer_limit_bytes`, which is a `UInt32Value` field. Refer to the [protobuf documentation](https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/wrappers.proto) for additional information about wrappers. +#### Values + +- Default: None +- This field is required if [`Op`](#patches-op) is set to `add`, otherwise you must omit the field. +- This field takes one of the following data types: + - scalar + - enum + - map + +## Examples + +The following examples demonstrate patterns that you may be able to model your configurations on. + +### Enable `enforcing_consecutive_5xx` outlier detection + +In the following example, the `add` operation patches an outlier detection property into outbound cluster traffic. The `Path` specifies the `enforcing_consecutive_5xx` interface and sets a value of `1234`: + +```hcl +Kind = "service-defaults" +Name = "my-svc" +Protocol = "http" +EnvoyExtensions = [ + { + Name = "builtin/property-override", + Arguments = { + ProxyType = "connect-proxy", + Patches = [ + { + "ResourceFilter" = { + "ResourceType" = "cluster", + "TrafficDirection" = "outbound", + "Service" = { + "Name" = "other-svc" + }, + }, + "Op" = "add", + "Path" = "/outlier_detection/enforcing_consecutive_5xx", + "Value" = 1234, + } + ] + } + } +] +``` + +### Update multiple values in the default map + +In the following example, two `ResourceFilter` blocks target outbound traffic to the `db` service and add `/outlier_detection/enforcing_consecutive_5xx` and `/outlier_detection/failure_percentage_request_volume` properties: + +```hcl +Kind = "service-defaults" +Name = "my-svc" +Protocol = "http" +EnvoyExtensions = [ + { + Name = "builtin/property-override", + Arguments = { + ProxyType = "connect-proxy", + Patches = [ + { + ResourceFilter = { + ResourceType = "cluster", + TrafficDirection = "outbound", + Services = [{ + Name = "other-svc" + }], + }, + Op = "add", + Path = "/outlier_detection/enforcing_consecutive_5xx", + Value = 1234, + }, + { + ResourceFilter = { + ResourceType = "cluster", + TrafficDirection = "outbound", + Services = [{ + Name = "other-svc" + }], + }, + Op = "add", + Path = "/outlier_detection/failure_percentage_request_volume", + Value = 2345, + } + ] + } + } +] +``` + +### Set multiple values that replace the map + +In the following example, a `ResourceFilter` targets outbound traffic to the `db` service and replaces the map of properties located at `/outlier_detection` with `enforcing_consecutive_5xx` and `failure_percentage_request_volume` and properties: + +```hcl +Kind = "service-defaults" +Name = "my-svc" +Protocol = "http" +EnvoyExtensions = [ + { + Name = "builtin/property-override", + Arguments = { + ProxyType = "connect-proxy", + Patches = [ + { + ResourceFilter = { + ResourceType = "cluster", + TrafficDirection = "outbound", + Services = [{ + Name = "other-svc" + }], + }, + Op = "add", + Path = "/outlier_detection", + Value = { + "enforcing_consecutive_5xx" = 1234, + "failure_percentage_request_volume" = 2345, + }, + } + ] + } + } +] +``` diff --git a/website/content/docs/connect/proxies/envoy-extensions/configuration/wasm.mdx b/website/content/docs/connect/proxies/envoy-extensions/configuration/wasm.mdx new file mode 100644 index 0000000000..ed1e2061a5 --- /dev/null +++ b/website/content/docs/connect/proxies/envoy-extensions/configuration/wasm.mdx @@ -0,0 +1,484 @@ +--- +layout: docs +page_title: WebAssembly extension configuration reference +description: Learn how to configure the wasm Envoy extension, which is a builtin Consul extension that allows you to run WebAssembly plugins in Envoy proxies. +--- + +# WebAssembly extension configuration reference + +This topic describes how to configure the `wasm` extension, which directs Consul to run WebAssembly (Wasm) plugins in Envoy proxies. Refer to [Run WebAssembly plug-ins in Envoy proxy](/consul/docs/connect/proxies/envoy-extensions/usage/wasm) for usage information. + +## Configuration model + +The following list outlines the field hierarchy, data types, and requirements for the `wasm` configuration. Place the configuration inside the `EnvoyExtension.Arguments` field in the proxy defaults or service defaults configuration entry. Refer the following documentation for additional information: + +- [`EnvoyExtensions` in proxy defaults](/consul/docs/connect/config-entries/proxy-defaults#envoyextensions) +- [`EnvoyExtensions` in service defaults](/consul/docs/connect/config-entries/service-defaults#envoyextensions) + +Click on a property name to view additional details, including default values. + +- [`Protocol`](#protocol): string +- [`ListenerType`](#listenertype): string | required +- [`ProxyType`](#proxytype): string | `connect-proxy` +- [`PluginConfig`](#pluginconfig): map | required + - [`Name`](#pluginconfig-name): string + - [`RootID`](#pluginconfig-rootid): string | required + - [`VmConfig`](#pluginconfig-vmconfig): map + - [`VmID`](#pluginconfig-vmconfig-vmid): string + - [`Runtime`](#pluginconfig-vmconfig): string | `v8` + - [`Code`](#pluginconfig-vmconfig-code): map + - [`Local`](#pluginconfig-vmconfig-code-local): map + - [`Filename`](#pluginconfig-vmconfig-code-local): string + - [`Remote`](#pluginconfig-vmconfig-code-remote): map + - [`HttpURI`](#pluginconfig-vmconfig-code-remote-httpuri): map + - [`Service`](#pluginconfig-vmconfig-code-remote-httpuri-service): map + - [`Name`](#pluginconfig-vmconfig-code-remote-httpuri-service): string + - [`Namespace`](#pluginconfig-vmconfig-code-remote-httpuri-service): string + - [`Partition`](#pluginconfig-vmconfig-code-remote-httpuri-service): string + - [`URI`](#pluginconfig-vmconfig-code-remote-httpuri-uri): string + - [`Timeout`](#pluginconfig-vmconfig-code-remote-httpuri-timeout): string + - [`SHA256`](#pluginconfig-vmconfig-code-remote-sha256): string + - [`RetryPolicy`](#pluginconfig-vmconfig-code-remote-retrypolicy): map + - [`RetryBackOff`](#pluginconfig-vmconfig-code-remote-retrypolicy-retrybackoff): map + - [`BaseInterval`](#pluginconfig-vmconfig-code-remote-retrypolicy-retrybackoff): string + - [`MaxInterval`](#pluginconfig-vmconfig-code-remote-retrypolicy-retrybackoff): string + - [`NumRetries`](#pluginconfig-vmconfig-code-remote-retrypolicy-numretries): number | `-1` + - [`Configuration`](#pluginconfig-vmconfig-configuration): string + - [`EnvironmentVariables`](#pluginconfig-vmconfig-environmentvariables): map + - [`HostEnvKeys`](#pluginconfig-vmconfig-environmentvariables-hostenvkeys): list of strings + - [`KeyValues`](#pluginconfig-vmconfig-environmentvariables-keyvalues): map + - [`Configuration`](#pluginconfig-configuration): string + - [`CapabilityRestrictionConfiguration`](#pluginconfig-vmconfig-capabilityrestrictionconfiguration): map + - [`AllowedCapabilities`](#pluginconfig-vmconfig-capabilityrestrictionconfiguration): map of strings + +## Complete configuration + +When all parameters are set for the extension, the configuration has the following form: + +```hcl +Protocol = "" +ListenerType = "" +ProxyType = "connect-proxy" +PluginConfig = { + Name = "" + RootID = "" + VmConfig = { + VmID = "" + Runtime = "v8" + Code = { + Local = { # Set either `Local` or `Remote', not both + Filename = "
" + } + Remote = { # Set either `Local` or `Remote', not both + HttpURI = { + Service = { + Name = "" + Namespace = "" + Partition = "" + } + URI = "" + Timeout = "1s" + SHA256 = "" + RetryPolicy = { + RetryBackOff = { + BaseInterval = "1s" + MaxInterval = "10s" + } + NumRetries = -1 + } + } + Configuration = "" + EnvironmentVariables = { + HostEnvKeys = [ + <"keys"> + ] + KeyValues = { + [ + <"key = value"> + ] + } + } + Configuration = "" + CapabilityRestrictionConfiguration = { + AllowedCapabilities = { + "fd_read" = {} + "fd_seek" = {} + "environ_get" = {} + "clock_get_time" = {} + } + } +} +``` + +## Specification + +This section provides details about the fields you can configure for the `wasm` extension. + +### `Protocol` + +Specifies the type of Wasm filter to apply. You can set either `tcp` or `http`. Set the `Protocol` to the protocol that the Wasm plugin implements when loaded by the filter. For Consul to apply the filter, the protocol must match the service’s protocol. + +#### Values + +- Default: None +- This field is required. +- Data type is one of the following string values: + - `tcp` + - `http` + +### `ListenerType` + +Specifies the type of listener the extension applies to. The listener type is either `inbound` or `outbound`. If the listener type is set to `inbound`, Consul applies the extension so the Wasm plugin is run when other services in the mesh send messages to the service attached to the proxy. If the listener type is set to `outbound`, Consul applies the extension so the Wasm plugin is run when the attached proxy sends messages to other services in the mesh. + +#### Values + +- Default: None +- This field is required. +- Data type is one of the following string values: + - `inbound` + - `outbound` + +### `ProxyType` + +Specifies the type of Envoy proxy that the extension applies to. The only supported value is `connect-proxy`. + +#### Values + +- Default: `connect-proxy` +- This field is required. +- Data type: String + +### `PluginConfig{}` + +Map containing the following configuration parameters for your Wasm plugin: + +- [`Name`](#pluginconfig-name) +- [`RootID`](#pluginconfig-rootid) +- [`VmConfig`](#pluginconfig-vmconfig) +- [`Configuration`](#pluginconfig-configuration) +- [`CapabilitiesRestrictionConfiguration`](#pluginconfig-capabilitiesrestrictionconfiguration) + +#### Values + +- Default: None +- This field is required. +- Data type: Map + +### `PluginConfig{}.Name` + +Specifies a unique name for a filter in a VM. Envoy uses the name to identify specific filters if multiple filters are processed on a VM with the same `VmID` and `RootID`. The name also appears in logs for debugging purposes. + +#### Values + +- Default: None +- Data type: String + +### `PluginConfig{}.RootID` + +Specifies a unique ID for a set of filters in a VM that share a `RootContext` and `Contexts`, such as a Wasm `HttpFilter` and a Wasm `AccessLog`, if applicable. All filters with the same `RootID` and `VmID` share `Context`s. + +#### Values + +- Default: None +- Data type: String + +### `PluginConfig{}.VmConfig{}` + +Map containing the following configuration parameters for the VM that runs your Wasm plugin: + +- [`VmID`](#pluginconfig-vmconfig-vmid) +- [`Runtime`](#pluginconfig-vmconfig-runtime) +- [`Code`](#pluginconfig-vmconfig-code) +- [`Configuration`](#pluginconfig-vmconfig-configuration) +- [`EnvironmentVariables`](#pluginconfig-vmconfig-environmentvariables) + +#### Values + +- Default: None +- Data type: Map + +### `PluginConfig{}.VmConfig{}.VmID` + +Specifies an ID that Envoy uses with a hash of the Wasm code to determine which VM runs the plugin. All plugins with the same `VmID` and `Code` use the same VM. If unspecified, all plugins with the same code run in the same VM. Sharing a VM between plugins may have security implications, but can reduce memory utilization and can make data sharing easier. + +#### Values + +- Default: None +- Data type: String + +### `PluginConfig{}.VmConfig{}.Runtime` + +Specifies the type of Wasm runtime. +#### Values + +- Default: `v8` +- Data type is one of the following string values: + - `v8` + - `wastime` + - `wamr` + - `wavm` + +### `PluginConfig{}.VmConfig{}.Code{}` + +Map containing one of the following configuration parameters: + +- [`Local`](#pluginconfig-vmconfig-code-local) +- [`Remote`](#pluginconfig-vmconfig-code-local) + +You can configure either `Local` or `Remote`, but not both. The `Code` block instructs Consul how to find the Wasm plugin code for Envoy to execute. + +#### Values + +- Default: None +- This field is required. +- Data type is a map containing one of the following configurations: + - [`Local`](#pluginconfig-vmconfig-code-local) + - [`Remote`](#pluginconfig-vmconfig-code-local) + +### `PluginConfig{}.VmConfig{}.Code{}.Local{}` + +Instructs Envoy to load the plugin code from a local volume. Do not configure the `Local` parameter if the plugin code is on a remote server. + +The `Local` field is a map that contains a `Filename` parameter. The `Filename` parameter takes a string value that specifies the path to the plugin on the local file system. + +Local plug-ins are not supported in Kubernetes-orchestrated environments. + +#### Values + +- Default: None +- Data type is a map containing the `Filename` parameter. The `Filename` parameter takes a string value that specifies the path to the plugin on the local file system. + +### `PluginConfig{}.VmConfig{}.Code{}.Remote{}` + +Instructs Envoy to load the plugin code from a remote server. Do not configure the `Remote` parameter if the plugin code is on the local VM. + +The `Remote` field is a map containing the following parameters: + +- [`HttpURI`](#pluginconfig-vmconfig-code-remote-httpuri) +- [`SHA256`](#pluginconfig-vmconfig-code-remote-sha256) +- [`RetryPolicy`](#pluginconfig-vmconfig-code-remote-retrypolicy) + +#### Values + +- Default: None +- Data type: Map + +### `PluginConfig{}.VmConfig{}.Code{}.Remote{}.HttpURI{}` + +Specifies the configuration for fetching the remote data. The `HttpURI` field is a map containing the following parameters: + +- [`Service`](#pluginconfig-vmconfig-code-remote-httpuri-service) +- [`URI`](#pluginconfig-vmconfig-code-remote-httpuri-uri) +- [`Timeout`](#pluginconfig-vmconfig-code-remote-httpuri-uri) + +#### Values + +- Default: None +- Data type: Map + +### `PluginConfig{}.VmConfig{}.Code{}.Remote{}.HttpURI{}.Service` + +Specifies the upstream service to fetch the remote plugin from. + +#### Values + +- Default: None +- Data type: Map + +The following table describes the fields you can specify in the `Service` map: + +| Parameter | Description | Data type | Default | +| --- | --- | --- | --- | +| `Name` | Specifies the name of the upstream service. | String | None | +| `Namespace` | Specifies the Consul namespace that the upstream service belongs to. | String | `default` | +| `Partition` | Specifies the Consul admin partition that the upstream service belongs to. | String | `default` | + +### `PluginConfig{}.VmConfig{}.Code{}.Remote{}.HttpURI{}.URI` + +Specifies the URI Envoy uses to fetch the plugin file from the upstream. This field is required for Envoy to retrieve plugin code from a remote location. You must specify the fully-qualified domain name (FDQN) of the remote URI, which includes the protocol, host, and path. + +#### Values + +- Default: None +- This field is required. +- Data type: String value that specifies a FDQN + +### `PluginConfig{}.VmConfig{}.Code{}.Remote{}.HttpURI{}.Timeout` + +Specifies the maximum duration that a response can take to complete the request for the plugin data. + +#### Values + +- Default: `1s` +- Data type: String + +### `PluginConfig{}.VmConfig{}.Code{}.Remote{}.SHA256` + +Specifies the required SHA256 string for verifying the remote data. + +#### Values + +- Default: None +- This field is required. +- Data type: String + +### `PluginConfig{}.VmConfig{}.Code{}.Remote{}.RetryPolicy{}` + +Defines a policy for retrying requests to the upstream service when fetching the plugin data. The `RetryPolicy` field is a map containing the following parameters: + +- [`RetryBackoff`](#pluginconfig-vmconfig-code-remote-retrypolicy) +- [`NumRetries`](#pluginconfig-vmconfig-code-remote-numretries) + +#### Values + +- Default: None +- Data type: Map +### `PluginConfig{}.VmConfig{}.Code{}.Remote{}.RetryPolicy{}.RetryBackOff{}` + +Specifies parameters that control retry backoff strategy. + +#### Values + +- Default: None +- Data type: Map + +The following table describes the fields you can specify in the `RetryBackOff` map: + +| Parameter | Description | Data type | Default | +| --- | --- | --- | --- | +| `BaseInterval` | Specifies the base interval for determining the next backoff computation. Set a value greater than `0` and less than or equal to the `MaxInterval` value. | String | `1s` | +| `MaxInterval` | Specifies the maximum interval between retries. Set the value greater than or equal to the `BaseInterval` value. | String | `10s` | + +### `PluginConfig{}.VmConfig{}.Code{}.Remote{}.RetryPolicy{}.NumRetries` + +Specifies the number of times Envoy retries to fetch plugin data if the initial attempt is unsuccessful. + +#### Values + +- Default: `1` +- Data type: Integer + +### `PluginConfig{}.VmConfig{}.Configuration` + +Specifies the configuration Envoy encodes as bytes and passes to the plugin during VM startup. Refer to [`proxy_on_vm_start` in the Proxy Wasm ABI documentation](https://github.com/proxy-wasm/spec/tree/master/abi-versions/vNEXT#proxy_on_vm_start) for additional information. + +#### Values + +- Default: None +- This field is required. +- Data type: String + +### `PluginConfig{}.VmConfig{}.EnvironmentVariables{}` + +Specifies environment variables for Enovy to inject into this VM so that they are available through WASI’s `environ_get` and `environ_get_sizes` system calls. + +In most cases, WASI calls the functions implicitly in your language’s standard library. As a result, you do not need to call them directly. You can also access environment variables as you would on native platforms. + +Envoy rejects the configuration if there’s conflict of key space. + +The `EnvironmentVariables` field is a map containing parameters for setting the keys and values. + +#### Values + +- Default: None +- Data type: Map + +The following table describes the parameters contained in the `EnvironmentVariables` map: + +| Parameter | Description | Data type | Default | +| --- | --- | --- | --- | +| `HostEnvKeys` | Specifies a list of Envoy environment variable keys to expose to the VM. If a key exists in Envoy’s environment variables, then the key-value pair is injected. Envoy ignores `HostEnvKeys` that do not exist in its environment variables. | List | None | +| `KeyValues` | Specifies a map of explicit key-value pairs to inject into the VM. | Map of string keys and values | None | + +### `PluginConfig{}.Configuration` + +Specifies the configuration Consul encodes as bytes and passes to the plugin during plugin startup. Refer to [`proxy_on_configure` in the Envoy documentation](https://github.com/proxy-wasm/spec/tree/master/abi-versions/vNEXT#proxy_on_configure) for additional information. + +#### Values + +- Default: None +- Data type: String + +### `PluginConfig{}.CapabilityRestrictionConfiguration{}` + +Specifies a configuration for restricting the proxy-Wasm capabilities that are available to the module. + +The `CapabilityRestrictionConfiguration` field is a map that contains a `AllowedCapabilities` parameter. The `AllowedCapabilities` parameter takes a map of string values that correspond to Envoy capability names. Refer to the [Envoy documentation](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/wasm/v3/wasm.proto#extensions-wasm-v3-capabilityrestrictionconfig) for additional information. + +!> **Security warning**: Consul ignores the value that each capability maps to. You can leave the `AllowedCapabilities` empty to allow all capabilities, but doing so gives the configured plugin full unrestricted access to the runtime API provided by the Wasm VM. You must set this to a non-empty map if you want to restrict access to specific capabilities provided by the Wasm runtime API. + +#### Values + +- Default: `""` +- Data type is a map containing the `AllowedCapabilities` parameter. The `AllowedCapabilities` parameter takes a map of string values that correspond to Envoy capability names. Refer to the [Envoy documentation](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/wasm/v3/wasm.proto#extensions-wasm-v3-capabilityrestrictionconfig) for additional information. + +## Examples + +The following examples demonstrate patterns that you may be able to model your configurations on. + +### Run a Wasm plugin from a local file + +In the following example, Consul figures the Envoy proxy for the `db` service with an inbound TCP Wasm filter that uses the plugin code from the local `/consul/extensions/sqli.wasm` file. + +```hcl + +Kind = "service-defaults" +Name = "db" +Protocol = "tcp" +EnvoyExtensions = [ + { + Name = "builtin/wasm" + Required = true + Arguments = { + Protocol = "tcp" + ListenerType = “inbound” + PluginConfig = { + VmConfig = { + Code = { + Local = { + Filename = "file:///consul/extensions/sqli.wasm" + } + } + } + Configuration = < + + + +```hcl +Kind = "service-defaults" +Name = "api" +EnvoyExtensions = [ + { + Name = "builtin/ext-authz" + Arguments = { + ProxyType = "connect-proxy" + Config = { + GrpcService = { + Target = { + Service = { + Name = "authz" + } + } + } + } + } + } +] +``` + + + + + +```json +"Kind": "service-defaults", +"Name": "api", +"EnvoyExtensions": [{ + "Name": "builtin/ext-authz", + "Arguments": { + "ProxyType": "connect-proxy", + "Config": { + "GrpcService": { + "Target": { + "Service": { + "Name": "authz" + } + } + } + } + } + } +] +``` + + + + + + +```yaml +kind: ServiceDefaults +name: api +envoyExtensions: + - name: builtin/ext-authz + arguments: + proxyType: connect-proxy + config: + grpcService: + target: + service: + name: authz +``` + + + + +Refer to the [external authorization extension configuration reference](/consul/docs/connect/proxies/envoy-extensions/configuration/ext-authz) for details on how to configure the extension. + +Refer to the [proxy defaults configuration entry reference](/consul/docs/connect/config-entries/proxy-defaults) and [service defaults configuration entry reference](/consul/docs/connect/config-entries/service-defaults) for details on how to define the configuration entries. + +!> **Warning:** Adding Envoy extensions default proxy configurations may have unintended consequences. We recommend configuring `EnvoyExtensions` in service defaults configuration entries in most cases. + +### Unsupported Envoy configuration fields + +The following Envoy configurations are not supported: + +| Configuration | Workaround | +| --- | --- | +| `deny_at_disable` | Disable filter by removing it from the service’s configuration in the configuration entry. | +| `failure_mode_allow` | Set the `EnvoyExtension.Required` field to `true` in the [service defaults configuration entry](/consul/docs/connect/config-entries/service-defaults#envoyextensions) or [proxy defaults configuration entry](/consul/docs/connect/config-entries/proxy-defaults#envoyextensions). | +| `filter_enabled` | Set the `EnvoyExtension.Required` field to `true` in the [service defaults configuration entry](/consul/docs/connect/config-entries/service-defaults#envoyextensions) or [proxy defaults configuration entry](/consul/docs/connect/config-entries/proxy-defaults#envoyextensions). | +| `filter_enabled_metadata` | Set the `EnvoyExtension.Required` field to `true` in the [service defaults configuration entry](/consul/docs/connect/config-entries/service-defaults#envoyextensions) or [proxy defaults configuration entry](/consul/docs/connect/config-entries/proxy-defaults#envoyextensions). | +| `transport_api_version` | Consul only supports v3 of the transport API. As a result, there is no workaround for implement the behavior of this field. | + +## Apply the configuration entry + +If your network is deployed to virtual machines, use the `consul config write` command and specify the proxy defaults or service defaults configuration entry to apply the configuration. For Kubernetes-orchestrated networks, use the `kubectl apply` command. The following example applies the extension in a proxy defaults configuration entry. + + + + +```shell-session +$ consul config write api-auth-service-defaults.hcl +``` + + + + +```shell-session +$ consul config write api-auth-service-defaults.json + +``` + + + + +```shell-session +$ kubectl apply api-auth-service-defaults.yaml +``` + + + diff --git a/website/content/docs/connect/proxies/envoy-extensions/usage/property-override.mdx b/website/content/docs/connect/proxies/envoy-extensions/usage/property-override.mdx new file mode 100644 index 0000000000..0166f84ec1 --- /dev/null +++ b/website/content/docs/connect/proxies/envoy-extensions/usage/property-override.mdx @@ -0,0 +1,203 @@ +--- +layout: docs +page_title: Configure Envoy proxy properties +description: Learn how to use the property-override extension for Envoy proxies to set and remove individual properties for the Envoy resources Consul generates. +--- + +# Configure Envoy proxy properties + +This topic describes how to use the `property-override` extension to set and remove individual properties for the Envoy resources Consul generates. The extension uses the [protoreflect](https://pkg.go.dev/google.golang.org/protobuf/reflect/protoreflect), which enables Consul to dynamically manipulate messages. + +## Workflow + +- Complete the following steps to use the `property-override` extension: +- Configure an `EnvoyExtensions` block in a service defaults or proxy defaults configuration entry. +- Apply the configuration entry. + +!> **Security warning**: The property override extension is an advanced feature capable of introducing unintended consequences or reducing cluster security if used incorrectly. Consul does not enforce TLS retention, intentions, or other security-critical components of the Envoy configuration. Additionally, Consul does not verify that the configuration does not contain errors that affect service traffic. + +## Add the `EnvoyExtensions` + +Add Envoy extension configurations to a proxy defaults or service defaults configuration entry. Place the extension configuration in an `EnvoyExtensions` block in the configuration entry. + +- When you configure Envoy extensions on proxy defaults, they apply to every service. +- When you configure Envoy extensions on service defaults, they apply to a specific service. + +Consul applies Envoy extensions configured in proxy defaults before it applies extensions in service defaults. As a result, the Envoy extension configuration in service defaults may override configurations in proxy defaults. + +In the following service defaults configuration entry example, Consul adds a new `/upstream_connection_options/tcp_keepalive/keepalive_probes-5` field to each of the proxy's cluster configuration for the outbound `db`service upstream. The configuration applies to all `connect-proxy` proxies with services configured to communicate over HTTP: + + + + + +```hcl +Kind = "service-defaults" +Name = "global" +Protocol = "http" +EnvoyExtensions = [ + { + Name = "builtin/property-override" + Arguments = { + ProxyType = "connect-proxy", + Patches = [ + { + ResourceFilter = { + ResourceType = "cluster", + TrafficDirection = "outbound" + Services = [{ + Name = "other-svc" + }], + Op = "add" + Path = "/upstream_connection_options/tcp_keepalive/keepalive_probes", + Value = 5, + } + ] + } +] +``` + + + + + + +```json +"kind": "service-defaults", +"name": "global", +"protocol": "http", +"envoy_extensions": [{ + "name": "builtin/property-override", + "arguments": { + "proxyType": "connect-proxy", + "patches": [{ + "resourceFilter": { + "resourceType": "cluster", + "trafficDirection": "outbound", + "services": [{ "name": "other-svc" }], + "op": "add", + "path": "/upstream_connection_options/tcp_keepalive/keepalive_probes", + "value": 5 + } + }] + } +}] +``` + + + + + +```yaml +apiversion: consul.hashicorp.com/v1alpha1 +kind: ServiceDefaults +metadata: + name: global +spec: + protocol: http + envoyExtensions: + name = "builtin/property-override" + arguments: + proxyType: "connect-proxy", + patches: + - resourceFilter: + resourceType: "cluster" + trafficDirection: "outbound" + services: + - name: "other-svc" + op: "add" + path: "/upstream_connection_options/tcp_keepalive/keepalive_probes", + value: 5 +``` + + + + + + +Refer to the [property override configuration reference](/consul/docs/connect/proxies/envoy-extensions/configuration/property-override) for details on how to configure the extension. + +Refer to the [proxy defaults configuration entry reference](/consul/docs/connect/config-entries/proxy-defaults) and [service defaults configuration entry reference](/consul/docs/connect/config-entries/service-defaults) for details on how to define the configuration entries. + +!> **Warning:** Adding Envoy extensions default proxy configurations may have unintended consequences. We recommend configuring `EnvoyExtensions` in service defaults configuration entries in most cases. + +### Constructing paths + +To target the properties for an Envoy resource type, you must specify the path where the properties exist in the [`Path` field](/consul/docs/connect/proxies/envoy-extensions/configuration/property-override#patches-path) of the property override extension configuration. Set the `Path` field to an empty or partially invalid string when saving the configuration entry and Consul returns an error with a list of supported fields for the first unrecognized segment of the path. By default, Consul only returns the first ten fields, but you can set the [`Debug` field](/consul/docs/connect/proxies/envoy-extensions/configuration/property-override#debug) to `true` to direct Consul to output all possible fields. + +In the following example, Consul outputs the top-level fields available for the Envoy cluster resource: + +```hcl +Kind = "service-defaults" +Name = "api" +EnvoyExtensions = [ + { + Name = "builtin/property-override" + Arguments = { + ProxyType = "connect-proxy" + Patches = [ + { + ResourceFilter = { + ResourceType = "cluster" + TrafficDirection = "outbound" + } + Op = "add" + Path = "" + Value = 5 + } + ] + } + } +] +``` + +After applying the configuration entry, Consul prints a message that includes the possible fields for the resource: + +```shell-session +$ consul config write api.hcl +non-empty, non-root Path is required. available cluster fields: +/outlier_detection +/outlier_detection/enforcing_consecutive_5xx +/outlier_detection/failure_percentage_request_volume +/round_robin_lb_config +/round_robin_lb_config/slow_start_config +``` + +You can use the output to help you construct the appropriate value for the `Path` field. For example: + +```shell-session +$ consul config write api.hcl | grep round_robin +/round_robin_lb_config +``` + + + + +## Apply the configuration entry + +If your network is deployed to virtual machines, use the `consul config write` command and specify the proxy defaults or service defaults configuration entry to apply the configuration. For Kubernetes-orchestrated networks, use the `kubectl apply` command. The following example applies the extension in a proxy defaults configuration entry. + + + + +```shell-session +$ consul config write property-override-extension-service-defaults.hcl +``` + + + + +```shell-session +$ consul config write property-override-extension-service-defaults.json + +``` + + + + +```shell-session +$ kubectl apply property-override-extension-service-defaults.yaml +``` + + + diff --git a/website/content/docs/connect/proxies/envoy-extensions/usage/wasm.mdx b/website/content/docs/connect/proxies/envoy-extensions/usage/wasm.mdx new file mode 100644 index 0000000000..de899efe48 --- /dev/null +++ b/website/content/docs/connect/proxies/envoy-extensions/usage/wasm.mdx @@ -0,0 +1,191 @@ +--- +layout: docs +page_title: Run WebAssembly plug-ins in Envoy proxy +description: Learn how to use the Consul wasm extension for Envoy, which directs Consul to run your WebAssembly (Wasm) plugins for Envoy proxies in your service mesh. +--- + + +# Run WebAssembly plug-ins in Envoy proxy + +This topic describes how to use the `wasm` extension, which directs Consul to run your WebAssembly (Wasm) plug-ins for Envoy proxies. + +## Workflow + +You can create Wasm plugins for Envoy and integrate them using the `wasm` extension. Wasm is a binary instruction format for stack-based virtual machines that has the potential to run anywhere after it has been compiled. Wasm plug-ins run as filters in a service mesh application's sidecar proxy. + +The following steps describe the process of integrating Wasm plugins: + +- Create your Wasm plugin. You must ensure that your plugin functions as expected. Refer to the [WebAssembly website](https://webassembly.org/) for information and links to documentation. +- Configure an `EnvoyExtensions` block in a service defaults or proxy defaults configuration entry. +- Apply the configuration entry. + +## Add the `EnvoyExtensions` + +Add Envoy extension configuration to a proxy defaults or service defaults configuration entry. Place the extension configuration in an `EnvoyExtensions` block in the configuration entry. + +- When you configure Envoy extensions on proxy defaults, they apply to every service. +- When you configure Envoy extensions on service defaults, they apply to a specific service. + +Consul applies Envoy extensions configured in proxy defaults before it applies extensions in service defaults. As a result, the Envoy extension configuration in service defaults may override configurations in proxy defaults. + +In the following example, the extension uses an upstream service named `file-server` to serve a Wasm-based web application firewall (WAF). + + + + + +```hcl +Kind = "service-defaults" +Name = "api" +Protocol = "http" +EnvoyExtensions = [ + { + Name = "builtin/wasm" + Arguments = { + Protocol = "http" + ListenerType = "inbound" + PluginConfig = { + VmConfig = { + Code = { + Remote = { + HttpURI = { + Service = { + Name = "file-server" + } + URI = "https://file-server/waf.wasm" + } + SHA256 = "c9ef17f48dcf0738b912111646de6d30575718ce16c0cbde3e38b21bb1771807" + } + } + } + Configuration = < + + + + +```json +{ + "kind": "service-defaults", + "name": "api", + "protocol": "http", + "envoyExtensions": [{ + "name": "builtin/wasm", + "arguments": { + "protocol": "http", + "listenerType": "inbound", + "pluginConfig": { + "VmConfig": { + "Code": { + "Remote": { + "HttpURI": { + "Service": { + "Name": "file-server" + }, + "URI": "https://file-server/waf.wasm" + } + } + } + }, + "Configuration": { + "rules": [ + "Include @demo-conf", + "Include @crs-setup-demo-conf", + "SecDebugLogLevel 9", + "SecRuleEngine On", + "Include @owasp_crs/*.conf" + ] + } + + } + } + }] +} +``` + + + + + + + +```yaml +kind: service-defaults +name: api +protocol: http +envoyExtensions: + - name: builtin/wasm + required: true + arguments: + protocol: http + listenerType: inbound + pluginConfig: + VmConfig: + Code: + Remote: + HttpURI: + Service: + Name: file-server + URI: https://file-server/waf.wasm + Configuration: + rules: + - Include @demo-conf + - Include @crs-setup-demo-conf + - SecDebugLogLevel 9 + - SecRuleEngine On + - Include @owasp_crs/*.conf +``` + + + + + + +Refer to the [Wasm extension configuration reference](/consul/docs/connect/proxies/envoy-extensions/configuration/wasm) for details on how to configure the extension. + +Refer to the [proxy defaults configuration entry reference](/consul/docs/connect/config-entries/proxy-defaults) and [service defaults configuration entry reference](/consul/docs/connect/config-entries/service-defaults) for details on how to define the configuration entries. + +!> **Warning:** Adding Envoy extensions default proxy configurations may have unintended consequences. We recommend configuring `EnvoyExtensions` in service defaults configuration entries in most cases. + +## Apply the configuration entry + +If your network is deployed to virtual machines, use the `consul config write` command and specify the proxy defaults or service defaults configuration entry to apply the configuration. For Kubernetes-orchestrated networks, use the `kubectl apply` command. The following example applies the extension in a proxy defaults configuration entry. + + + + +```shell-session +$ consul config write wasm-extension-serve-waf.hcl +``` + + + + +```shell-session +$ consul config write wasm-extension-serve-waf.json +``` + + + + +```shell-session +$ kubectl apply wasm-extension-serve-waf.yaml +``` + + + diff --git a/website/content/docs/enterprise/license/utilization-reporting.mdx b/website/content/docs/enterprise/license/utilization-reporting.mdx new file mode 100644 index 0000000000..50db538609 --- /dev/null +++ b/website/content/docs/enterprise/license/utilization-reporting.mdx @@ -0,0 +1,168 @@ +--- +page_title: Automated license utilization reporting +description: >- + Learn what data HashiCorp collects to meter Enterprise license utilization. Enable or disable reporting. Review sample payloads and logs. +--- + +# Automated license utilization reporting + +Automated license utilization reporting sends license utilization data to HashiCorp without requiring you to manually collect and report them. It also enables you to review your license usage with the monitoring solution you already use, such as Splunk and Datadog, as you optimize and manage your deployments. You can use these reports to understand how much more you can deploy under your current contract, which can help you protect against overutilization and budget for predicted consumption. + +Automated reporting shares the minimum data required to validate license utilization as defined in our contracts. This data mostly consists of computed metrics, and it will never contain Personal Identifiable Information (PII) or other sensitive information. Automated reporting shares the data with HashiCorp using a secure unidirectional HTTPS API and makes an auditable record in the product logs each time it submits a report. + +## Enable automated reporting + +Before you enable automated reporting, make sure that outbound network traffic is configured correctly and upgrade your enterprise product to a version that supports it. If your installation is air-gapped or network settings are not in place, automated reporting will not work. + +To enable automated reporting, complete the following steps: + +1. [Allow outbound HTTPS traffic on port 443](#allow-outbound-https-traffic) +1. Upgrade to Consul Enterprise v1.16.0 or newer (#upgrade-to-consul-enterprise) +1. Check product logs(#check-product-logs) + +### Allow outbound HTTPS traffic on port 443 + +Make sure that your network allows HTTPS egress on port 443 from `https://reporting.hashicorp.services` by allow-listing the following IP addresses: + +- `100.20.70.12` +- `35.166.5.222` +- `23.95.85.111` +- `44.215.244.1` + +### Upgrade to Consul Enterprise v1.16.0 or newer + +Upgrade to a release that supports license utilization reporting. These [releases](https://releases.hashicorp.com/consul/) include: + +- Consul Enterprise 1.16.0 and newer. +- Consul Enterprise 1.15.4 and newer. +- Consul Enterprise 1.14.8 and newer. +- Consul Enterprise 1.13.9 and newer. + +### Check product logs + +Automatic license utilization reporting starts sending data within 24 hours. Check the product logs for records that the data sent successfully. + + + +``` +[DEBUG] beginning snapshot export +[DEBUG] creating payload +[DEBUG] marshalling payload to json +[DEBUG] generating authentication headers +[DEBUG] creating request +[DEBUG] sending request +[DEBUG] performing request: method=POST url=https://census.license.hashicorp.services +[DEBUG] recording audit record +[INFO] reporting: Report sent: auditRecord={"payload":{"payload_version":"1","license_id":"d2cdd857-4202-5a45-70a6-e4b531050c34","product":"consul","product_version":"1.16.0-dev+ent","export_timestamp":"2023-05-26T20:09:13.753921087Z","snapshots":[{"snapshot_version":1,"snapshot_id":"0001J724F90F4XWQDSAA76ZQWA","process_id":"01H1CTJPC1S8H7Q45MKTJ689ZW","timestamp":"2023-05-26T20:09:13.753513962Z","schema_version":"1.0.0","service":"consul","metrics":{"consul.billable.nodes":{"key":"consul.billable.nodes","kind":"counter","mode":"write","value":2},"consul.billable.service_instances":{"key":"consul.billable.service_instances","kind":"counter","mode":"write","value":2}}}],"metadata":{}}} +[DEBUG] completed recording audit record +[DEBUG] export finished successfully" +``` + + + +If your installation is air-gapped or your network does not allow the correct egress, the logs show an error. + + + +``` +[DEBUG] reporting: beginning snapshot export +[DEBUG] reporting: creating payload +[DEBUG] reporting: marshalling payload to json +[DEBUG] reporting: generating authentication headers +[DEBUG] reporting: creating request +[DEBUG] reporting: sending request +[DEBUG] reporting: performing request: method=POST url=https://census.license.hashicorp.services +[DEBUG] reporting: error status code received: statusCode=403 +``` + + + +In this case, reconfigure your network to allow egress and check back in 24 hours. + +## Opt out + +If your installation is air-gapped or you want to manually collect and report on the same license utilization metrics, you can opt out of automated reporting. + +Manually reporting these metrics can be time consuming. Opting out of automated reporting does not mean that you also opt out from sending license utilization metrics. Customers who opt out of automated reporting are still required to manually collect and send license utilization metrics to HashiCorp. + +If you are considering opting out because you are worried about the data, we strongly recommend that you review the [example payloads](#example-payloads) before opting out. If you have concerns with any of the automatically reported data, raise these concerns with your account manager. + +There are two methods for opting out of automated reporting: + +- HCL configuration (recommended) +- Environment variable (requires restart) + +We recommend opting out in your product's configuration file because it does not require a system restart. Add the following block to your `configuration.hcl` or `configuration.json` file. + +```hcl +reporting { + license { + enabled = false + } +} +``` + +When you opt out using an environment variable, once you restart your system it will provide a startup message confirming that you have disabled automated reporting. Set the following environment variable to disable automated reporting: + + + +```shell-session +$ export OPTOUT_LICENSE_REPORTING=true +``` + + + +After you set the environment variable, restart your system to complete the process for opting out. + +```shell-session +$ consul reload +``` + + +Check your product logs 24 hours after opting out to make sure that the system is not trying to send reports. Keep in mind that if your configuration file and environment variable differ, the environment variable setting takes precedence. + +## Example payloads + +HashiCorp collects the following utilization data as JSON payloads: +`exporter_version` - The version of the licensing exporter + + + +```json +{ + "payload": { + "payload_version": "1", + "license_id": "d2cdd857-4202-5a45-70a6-e4b531050c34", + "product": "consul", + "product_version": "1.16.0-dev+ent", + "export_timestamp": "2023-05-26T20:09:13.753921087Z", + "snapshots": [ + { + "snapshot_version": 1, + "snapshot_id": "0001J724F90F4XWQDSAA76ZQWA", + "process_id": "01H1CTJPC1S8H7Q45MKTJ689ZW", + "timestamp": "2023-05-26T20:09:13.753513962Z", + "schema_version": "1.0.0", + "service": "consul", + "metrics": { + "consul.billable.nodes": { + "key": "consul.billable.nodes", + "kind": "counter", + "mode": "write", + "value": 2 + }, + "consul.billable.service_instances": { + "key": "consul.billable.service_instances", + "kind": "counter", + "mode": "write", + "value": 2 + } + } + } + ], + "metadata": {} + } +} +``` + + \ No newline at end of file diff --git a/website/content/partials/envoy_ext_rule_matcher.mdx b/website/content/partials/envoy_ext_rule_matcher.mdx new file mode 100644 index 0000000000..1d97c34e4b --- /dev/null +++ b/website/content/partials/envoy_ext_rule_matcher.mdx @@ -0,0 +1,9 @@ + +| Rule | Description | Data type | Default | +| --- | --- | --- | --- | +| `Contains` | Specifies a string that the input string must contain. | String | N/A | +| `Exact` | Specifies a string that the input string must match exactly. | String | N/A | +| `IgnoreCase` | Directs Envoy to ignore capitalization. If set to `true`, the other matching rules in the configuration are not case sensitive. This rule does not affect `SafeRegex`. | Boolean | `false` | +| `Prefix` | Specifies a string that the input string must begin with. | String | N/A | +| `SafeRegex` | Specifies a regular expression for matching the input string programmatically. Envoy supports [Google's RE2 regex engine](https://github.com/google/re2/wiki/Syntax). | String | N/A | +| `Suffix` | Specifies a string that the input string must end with. | String | N/A | \ No newline at end of file diff --git a/website/data/docs-nav-data.json b/website/data/docs-nav-data.json index 20335f715b..edd16a4eb8 100644 --- a/website/data/docs-nav-data.json +++ b/website/data/docs-nav-data.json @@ -394,14 +394,14 @@ "path": "connect/configuration" }, { - "title": "Configuration Entries", + "title": "Configuration entries", "routes": [ { "title": "Overview", "path": "connect/config-entries" }, { - "title": "API Gateway", + "title": "API gateway", "href": "/consul/docs/connect/gateways/api-gateway/configuration/api-gateway", "badge": { "text": "BETA", @@ -410,7 +410,7 @@ } }, { - "title": "HTTP Route", + "title": "HTTP route", "href": "/consul/docs/connect/gateways/api-gateway/configuration/http-route", "badge": { "text": "BETA", @@ -419,7 +419,7 @@ } }, { - "title": "TCP Route", + "title": "TCP route", "href": "/consul/docs/connect/gateways/api-gateway/configuration/tcp-route", "badge": { "text": "BETA", @@ -428,7 +428,7 @@ } }, { - "title": "Inline Certificate", + "title": "Inline certificate", "href": "/consul/docs/connect/gateways/api-gateway/configuration/inline-certificate", "badge": { "text": "BETA", @@ -437,7 +437,7 @@ } }, { - "title": "Ingress Gateway", + "title": "Ingress gateway", "path": "connect/config-entries/ingress-gateway" }, { @@ -445,36 +445,40 @@ "path": "connect/config-entries/mesh" }, { - "title": "Exported Services", + "title": "Exported services", "path": "connect/config-entries/exported-services" }, { - "title": "Proxy Defaults", + "title": "Proxy defaults", "path": "connect/config-entries/proxy-defaults" }, { - "title": "Service Defaults", + "title": "Service defaults", "path": "connect/config-entries/service-defaults" }, { - "title": "Service Intentions", + "title": "Service intentions", "path": "connect/config-entries/service-intentions" }, { - "title": "Service Resolver", + "title": "Service resolver", "path": "connect/config-entries/service-resolver" }, { - "title": "Service Router", + "title": "Service router", "path": "connect/config-entries/service-router" }, { - "title": "Service Splitter", + "title": "Service splitter", "path": "connect/config-entries/service-splitter" }, { - "title": "Terminating Gateway", + "title": "Terminating gateway", "path": "connect/config-entries/terminating-gateway" + }, + { + "title": "Control plane request limit", + "path": "connect/config-entries/control-plane-request-limit" } ] }, @@ -499,6 +503,10 @@ { "title": "Usage", "routes": [ + { + "title": "Delegate authorization to external services", + "path": "connect/proxies/envoy-extensions/usage/ext-authz" + }, { "title": "Run Lua scripts in Envoy proxies", "path": "connect/proxies/envoy-extensions/usage/lua" @@ -506,8 +514,32 @@ { "title": "Invoke Lambda functions in Envoy proxies", "path": "connect/proxies/envoy-extensions/usage/lambda" + }, + { + "title": "Configure Envoy proxy properties", + "path": "connect/proxies/envoy-extensions/usage/property-override" + }, + { + "title": "Run WebAssembly plug-ins in Envoy proxies", + "path": "connect/proxies/envoy-extensions/usage/wasm" + } ] + }, + { + "title": "Configuration", + "routes": [ + { + "title": "External authorization", + "path": "connect/proxies/envoy-extensions/configuration/ext-authz" + }, + { + "title": "Property override", + "path": "connect/proxies/envoy-extensions/configuration/property-override" + }, + { + "title": "WebAssembly", + "path": "connect/proxies/envoy-extensions/configuration/wasm" } - ] + ] } ] }, @@ -960,19 +992,36 @@ ] }, { - "title": "Limit Traffic Rates", + "title": "Limit traffic rates", "routes": [ { "title": "Overview", "path": "agent/limits" }, { - "title": "Initialize Rate Limit Settings", - "path": "agent/limits/init-rate-limits" + "title": "Usage", + "routes": [ + { + "title": "Initialize rate limit settings", + "path": "agent/limits/usage/init-rate-limits" + }, + { + "title": "Monitor traffic rate limits", + "path": "agent/limits/usage/monitor-rate-limits" + }, + { + "title": "Set global traffic rate limits", + "path": "agent/limits/usage/set-global-traffic-rate-limits" + }, + { + "title": "Limit traffic rates from source IP addresses", + "path": "agent/limits/usage/limit-request-rates-from-ips" + } + ] }, { - "title": "Set Global Traffic Rate Limits", - "path": "agent/limits/set-global-traffic-rate-limits" + "title": "Configuration", + "href": "/docs/connect/config-entries/control-plane-request-limit" } ] }, @@ -1607,6 +1656,10 @@ "title": "Overview", "path": "enterprise/license/overview" }, + { + "title": "Automated entitlement utilization reporting", + "path": "enterprise/license/utilization-reporting" + }, { "title": "FAQ", "path": "enterprise/license/faq" From c04c122ef3a02bd23dd63851923cf1e257003466 Mon Sep 17 00:00:00 2001 From: Chris Thain <32781396+cthain@users.noreply.github.com> Date: Mon, 12 Jun 2023 10:47:31 -0700 Subject: [PATCH 57/72] Default `ProxyType` for builtin extensions (#17657) --- .../builtin/http/localratelimit/ratelimit.go | 5 +++- .../http/localratelimit/ratelimit_test.go | 24 +++++++++++++++++++ agent/envoyextensions/builtin/lua/lua.go | 5 +++- agent/envoyextensions/builtin/lua/lua_test.go | 9 +++++++ .../property-override/property_override.go | 3 +++ .../property_override_test.go | 2 +- 6 files changed, 45 insertions(+), 3 deletions(-) diff --git a/agent/envoyextensions/builtin/http/localratelimit/ratelimit.go b/agent/envoyextensions/builtin/http/localratelimit/ratelimit.go index 7761982604..07e981ae2d 100644 --- a/agent/envoyextensions/builtin/http/localratelimit/ratelimit.go +++ b/agent/envoyextensions/builtin/http/localratelimit/ratelimit.go @@ -60,6 +60,9 @@ func (r *ratelimit) fromArguments(args map[string]interface{}) error { if err := mapstructure.Decode(args, r); err != nil { return fmt.Errorf("error decoding extension arguments: %v", err) } + if r.ProxyType == "" { + r.ProxyType = string(api.ServiceKindConnectProxy) + } return r.validate() } @@ -188,7 +191,7 @@ func (r ratelimit) PatchFilter(p extensioncommon.FilterPayload) (*envoy_listener } func validateProxyType(t string) error { - if t != "connect-proxy" { + if t != string(api.ServiceKindConnectProxy) { return fmt.Errorf("unexpected ProxyType %q", t) } diff --git a/agent/envoyextensions/builtin/http/localratelimit/ratelimit_test.go b/agent/envoyextensions/builtin/http/localratelimit/ratelimit_test.go index 4d8344ad1d..2b208bf3e7 100644 --- a/agent/envoyextensions/builtin/http/localratelimit/ratelimit_test.go +++ b/agent/envoyextensions/builtin/http/localratelimit/ratelimit_test.go @@ -111,6 +111,30 @@ func TestConstructor(t *testing.T) { expectedErrMsg: "cannot parse 'FilterEnforced', -1 overflows uint", ok: false, }, + "invalid proxy type": { + arguments: makeArguments(map[string]interface{}{ + "ProxyType": "invalid", + "FillInterval": 30, + "MaxTokens": 20, + "TokensPerFill": 5, + }), + expectedErrMsg: `unexpected ProxyType "invalid"`, + ok: false, + }, + "default proxy type": { + arguments: makeArguments(map[string]interface{}{ + "FillInterval": 30, + "MaxTokens": 20, + "TokensPerFill": 5, + }), + expected: ratelimit{ + ProxyType: "connect-proxy", + MaxTokens: intPointer(20), + FillInterval: intPointer(30), + TokensPerFill: intPointer(5), + }, + ok: true, + }, "valid everything": { arguments: makeArguments(map[string]interface{}{ "ProxyType": "connect-proxy", diff --git a/agent/envoyextensions/builtin/lua/lua.go b/agent/envoyextensions/builtin/lua/lua.go index 8293228a79..aefea37e6c 100644 --- a/agent/envoyextensions/builtin/lua/lua.go +++ b/agent/envoyextensions/builtin/lua/lua.go @@ -45,6 +45,9 @@ func (l *lua) fromArguments(args map[string]interface{}) error { if err := mapstructure.Decode(args, l); err != nil { return fmt.Errorf("error decoding extension arguments: %v", err) } + if l.ProxyType == "" { + l.ProxyType = string(api.ServiceKindConnectProxy) + } return l.validate() } @@ -53,7 +56,7 @@ func (l *lua) validate() error { if l.Script == "" { resultErr = multierror.Append(resultErr, fmt.Errorf("missing Script value")) } - if l.ProxyType != "connect-proxy" { + if l.ProxyType != string(api.ServiceKindConnectProxy) { resultErr = multierror.Append(resultErr, fmt.Errorf("unexpected ProxyType %q", l.ProxyType)) } if l.Listener != "inbound" && l.Listener != "outbound" { diff --git a/agent/envoyextensions/builtin/lua/lua_test.go b/agent/envoyextensions/builtin/lua/lua_test.go index d80a3b333a..3ea2ba716c 100644 --- a/agent/envoyextensions/builtin/lua/lua_test.go +++ b/agent/envoyextensions/builtin/lua/lua_test.go @@ -54,6 +54,15 @@ func TestConstructor(t *testing.T) { arguments: makeArguments(map[string]interface{}{"Listener": "invalid"}), ok: false, }, + "default proxy type": { + arguments: makeArguments(map[string]interface{}{"ProxyType": ""}), + expected: lua{ + ProxyType: "connect-proxy", + Listener: "inbound", + Script: "lua-script", + }, + ok: true, + }, "valid everything": { arguments: makeArguments(map[string]interface{}{}), expected: lua{ diff --git a/agent/envoyextensions/builtin/property-override/property_override.go b/agent/envoyextensions/builtin/property-override/property_override.go index 8164a8092a..51d7836852 100644 --- a/agent/envoyextensions/builtin/property-override/property_override.go +++ b/agent/envoyextensions/builtin/property-override/property_override.go @@ -261,6 +261,9 @@ func (p *propertyOverride) validate() error { } } + if p.ProxyType == "" { + p.ProxyType = api.ServiceKindConnectProxy + } if err := validProxyTypes.CheckRequired(string(p.ProxyType), "ProxyType"); err != nil { resultErr = multierror.Append(resultErr, err) } diff --git a/agent/envoyextensions/builtin/property-override/property_override_test.go b/agent/envoyextensions/builtin/property-override/property_override_test.go index ca549353fa..21889d840f 100644 --- a/agent/envoyextensions/builtin/property-override/property_override_test.go +++ b/agent/envoyextensions/builtin/property-override/property_override_test.go @@ -236,7 +236,7 @@ func TestConstructor(t *testing.T) { // enforces expected behavior until we do. Multi-member slices should be unaffected // by WeakDecode as it is a more-permissive version of the default behavior. "single value Patches decoded as map construction succeeds": { - arguments: makeArguments(map[string]any{"Patches": makePatch(map[string]any{})}), + arguments: makeArguments(map[string]any{"Patches": makePatch(map[string]any{}), "ProxyType": nil}), expected: validTestCase(OpAdd, extensioncommon.TrafficDirectionOutbound, ResourceTypeRoute).expected, ok: true, }, From 446a64032351a9865863cb8014ef0cdc0ea76df1 Mon Sep 17 00:00:00 2001 From: Michael Zalimeni Date: Mon, 12 Jun 2023 14:28:51 -0400 Subject: [PATCH 58/72] Post 1.16.0-rc1 updates (#17663) - Update changelog to include new entries from release - Update submodule versions to latest published --- CHANGELOG.md | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++ go.mod | 10 ++++---- 2 files changed, 72 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee1dccacc1..ef4edc7004 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,70 @@ +## 1.16.0-rc1 (June 12, 2023) + +BREAKING CHANGES: + +* api: The `/v1/health/connect/` and `/v1/health/ingress/` endpoints now immediately return 403 "Permission Denied" errors whenever a token with insufficient `service:read` permissions is provided. Prior to this change, the endpoints returned a success code with an empty result list when a token with insufficient permissions was provided. [[GH-17424](https://github.com/hashicorp/consul/issues/17424)] +* peering: Removed deprecated backward-compatibility behavior. +Upstream overrides in service-defaults will now only apply to peer upstreams when the `peer` field is provided. +Visit the 1.16.x [upgrade instructions](https://developer.hashicorp.com/consul/docs/upgrading/upgrade-specific) for more information. [[GH-16957](https://github.com/hashicorp/consul/issues/16957)] + +SECURITY: + +* audit-logging: **(Enterprise only)** limit `v1/operator/audit-hash` endpoint to ACL token with `operator:read` privileges. + +FEATURES: + +* api: (Enterprise only) Add `POST /v1/operator/audit-hash` endpoint to calculate the hash of the data used by the audit log hash function and salt. +* cli: (Enterprise only) Add a new `consul operator audit hash` command to retrieve and compare the hash of the data used by the audit log hash function and salt. +* cli: Adds new command - `consul services export` - for exporting a service to a peer or partition [[GH-15654](https://github.com/hashicorp/consul/issues/15654)] +* connect: **(Consul Enterprise only)** Implement order-by-locality failover. +* mesh: Add new permissive mTLS mode that allows sidecar proxies to forward incoming traffic unmodified to the application. This adds `AllowEnablingPermissiveMutualTLS` setting to the mesh config entry and the `MutualTLSMode` setting to proxy-defaults and service-defaults. [[GH-17035](https://github.com/hashicorp/consul/issues/17035)] +* mesh: Support configuring JWT authentication in Envoy. [[GH-17452](https://github.com/hashicorp/consul/issues/17452)] +* server: **(Enterprise Only)** added server side RPC requests IP based read/write rate-limiter. [[GH-4633](https://github.com/hashicorp/consul/issues/4633)] +* server: **(Enterprise Only)** allow automatic license utilization reporting. [[GH-5102](https://github.com/hashicorp/consul/issues/5102)] +* server: added server side RPC requests global read/write rate-limiter. [[GH-16292](https://github.com/hashicorp/consul/issues/16292)] +* xds: Add `property-override` built-in Envoy extension that directly patches Envoy resources. [[GH-17487](https://github.com/hashicorp/consul/issues/17487)] +* xds: Add a built-in Envoy extension that inserts External Authorization (ext_authz) network and HTTP filters. [[GH-17495](https://github.com/hashicorp/consul/issues/17495)] +* xds: Add a built-in Envoy extension that inserts Wasm HTTP filters. [[GH-16877](https://github.com/hashicorp/consul/issues/16877)] +* xds: Add a built-in Envoy extension that inserts Wasm network filters. [[GH-17505](https://github.com/hashicorp/consul/issues/17505)] + +IMPROVEMENTS: + +* * api: Support filtering for config entries. [[GH-17183](https://github.com/hashicorp/consul/issues/17183)] +* * cli: Add `-filter` option to `consul config list` for filtering config entries. [[GH-17183](https://github.com/hashicorp/consul/issues/17183)] +* api: Enable setting query options on agent force-leave endpoint. [[GH-15987](https://github.com/hashicorp/consul/issues/15987)] +* audit-logging: (Enterprise only) enable error response and request body logging [[GH-5669](https://github.com/hashicorp/consul/issues/5669)] +* audit-logging: **(Enterprise only)** enable error response and request body logging +* ca: automatically set up Vault's auto-tidy setting for tidy_expired_issuers when using Vault as a CA provider. [[GH-17138](https://github.com/hashicorp/consul/issues/17138)] +* ca: support Vault agent auto-auth config for Vault CA provider using AliCloud authentication. [[GH-16224](https://github.com/hashicorp/consul/issues/16224)] +* ca: support Vault agent auto-auth config for Vault CA provider using AppRole authentication. [[GH-16259](https://github.com/hashicorp/consul/issues/16259)] +* ca: support Vault agent auto-auth config for Vault CA provider using Azure MSI authentication. [[GH-16298](https://github.com/hashicorp/consul/issues/16298)] +* ca: support Vault agent auto-auth config for Vault CA provider using JWT authentication. [[GH-16266](https://github.com/hashicorp/consul/issues/16266)] +* ca: support Vault agent auto-auth config for Vault CA provider using Kubernetes authentication. [[GH-16262](https://github.com/hashicorp/consul/issues/16262)] +* command: Adds ACL enabled to status output on agent startup. [[GH-17086](https://github.com/hashicorp/consul/issues/17086)] +* command: Allow creating ACL Token TTL with greater than 24 hours with the -expires-ttl flag. [[GH-17066](https://github.com/hashicorp/consul/issues/17066)] +* connect: **(Enterprise Only)** Add support for specifying "Partition" and "Namespace" in Prepared Queries failover rules. +* connect: update supported envoy versions to 1.23.10, 1.24.8, 1.25.7, 1.26.2 [[GH-17546](https://github.com/hashicorp/consul/issues/17546)] +* connect: update supported envoy versions to 1.23.8, 1.24.6, 1.25.4, 1.26.0 [[GH-5200](https://github.com/hashicorp/consul/issues/5200)] +* fix metric names in /docs/agent/telemetry [[GH-17577](https://github.com/hashicorp/consul/issues/17577)] +* gateway: Change status condition reason for invalid certificate on a listener from "Accepted" to "ResolvedRefs". [[GH-17115](https://github.com/hashicorp/consul/issues/17115)] +* http: accept query parameters `datacenter`, `ap` (enterprise-only), and `namespace` (enterprise-only). Both short-hand and long-hand forms of these query params are now supported via the HTTP API (dc/datacenter, ap/partition, ns/namespace). [[GH-17525](https://github.com/hashicorp/consul/issues/17525)] +* systemd: set service type to notify. [[GH-16845](https://github.com/hashicorp/consul/issues/16845)] +* ui: Update alerts to Hds::Alert component [[GH-16412](https://github.com/hashicorp/consul/issues/16412)] +* ui: Update to use Hds::Toast component to show notifications [[GH-16519](https://github.com/hashicorp/consul/issues/16519)] +* ui: update from