diff --git a/NOTICE.txt b/NOTICE.txt index 2c681c9c798..40e09ed2462 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -1134,11 +1134,11 @@ Contents of probable licence file $GOMODCACHE/github.com/elastic/elastic-agent-a -------------------------------------------------------------------------------- Dependency : github.com/elastic/elastic-agent-client/v7 -Version: v7.1.2 +Version: v7.2.0 Licence type (autodetected): Elastic -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/github.com/elastic/elastic-agent-client/v7@v7.1.2/LICENSE.txt: +Contents of probable licence file $GOMODCACHE/github.com/elastic/elastic-agent-client/v7@v7.2.0/LICENSE.txt: ELASTIC LICENSE AGREEMENT @@ -6446,11 +6446,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- Dependency : google.golang.org/grpc -Version: v1.46.0 +Version: v1.53.0 Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/google.golang.org/grpc@v1.46.0/LICENSE: +Contents of probable licence file $GOMODCACHE/google.golang.org/grpc@v1.53.0/LICENSE: Apache License @@ -6658,11 +6658,11 @@ Contents of probable licence file $GOMODCACHE/google.golang.org/grpc@v1.46.0/LIC -------------------------------------------------------------------------------- Dependency : google.golang.org/protobuf -Version: v1.28.0 +Version: v1.29.1 Licence type (autodetected): BSD-3-Clause -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/google.golang.org/protobuf@v1.28.0/LICENSE: +Contents of probable licence file $GOMODCACHE/google.golang.org/protobuf@v1.29.1/LICENSE: Copyright (c) 2018 The Go Authors. All rights reserved. @@ -16280,11 +16280,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- Dependency : golang.org/x/oauth2 -Version: v0.0.0-20211104180415-d3ed0bb246c8 +Version: v0.4.0 Licence type (autodetected): BSD-3-Clause -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/golang.org/x/oauth2@v0.0.0-20211104180415-d3ed0bb246c8/LICENSE: +Contents of probable licence file $GOMODCACHE/golang.org/x/oauth2@v0.4.0/LICENSE: Copyright (c) 2009 The Go Authors. All rights reserved. @@ -16566,11 +16566,11 @@ Contents of probable licence file $GOMODCACHE/google.golang.org/appengine@v1.6.7 -------------------------------------------------------------------------------- Dependency : google.golang.org/genproto -Version: v0.0.0-20220426171045-31bebdecfb46 +Version: v0.0.0-20230110181048-76db0878b65f Licence type (autodetected): Apache-2.0 -------------------------------------------------------------------------------- -Contents of probable licence file $GOMODCACHE/google.golang.org/genproto@v0.0.0-20220426171045-31bebdecfb46/LICENSE: +Contents of probable licence file $GOMODCACHE/google.golang.org/genproto@v0.0.0-20230110181048-76db0878b65f/LICENSE: Apache License diff --git a/changelog/fragments/1690219594-component-diagnostics.yaml b/changelog/fragments/1690219594-component-diagnostics.yaml new file mode 100644 index 00000000000..479451585a9 --- /dev/null +++ b/changelog/fragments/1690219594-component-diagnostics.yaml @@ -0,0 +1,32 @@ +# Kind can be one of: +# - breaking-change: a change to previously-documented behavior +# - deprecation: functionality that is being removed in a later release +# - bug-fix: fixes a problem in a previous version +# - enhancement: extends functionality but does not break or fix existing behavior +# - feature: new functionality +# - known-issue: problems that we are aware of in a given version +# - security: impacts on the security of a product or a user’s deployment. +# - upgrade: important information for someone upgrading from a prior version +# - other: does not fit into any of the other categories +kind: feature + +# Change summary; a 80ish characters long description of the change. +summary: Add compoonent-level diagnostics, cpu profiling + +# Long description; in case the summary is not enough to describe the change +# this field accommodate a description without length limits. +# NOTE: This field will be rendered only for breaking-change and known-issue kinds at the moment. +#description: + +# Affected component; a word indicating the component this changeset affects. +component: diagnostics + +# PR URL; optional; the PR number that added the changeset. +# If not present is automatically filled by the tooling finding the PR where this changelog fragment has been added. +# NOTE: the tooling supports backports, so it's able to fill the original PR number instead of the backport PR number. +# Please provide it if you are adding a fragment for a different PR. +pr: https://github.com/elastic/elastic-agent/pull/3118 + +# Issue URL; optional; the GitHub issue related to this changeset (either closes or is part of). +# If not present is automatically filled by the tooling with the issue linked to the PR number. +#issue: https://github.com/owner/repo/1234 diff --git a/control_v2.proto b/control_v2.proto index 5b76ef34c1c..c3de7641cdf 100644 --- a/control_v2.proto +++ b/control_v2.proto @@ -197,6 +197,24 @@ message DiagnosticFileResult { // DiagnosticAgentRequest is request to gather diagnostic information about the Elastic Agent. message DiagnosticAgentRequest { + repeated AdditionalDiagnosticRequest additional_metrics = 1; +} + +// DiagnosticAgentRequestAdditional is an enum of additional diagnostic metrics that can be requested from Elastic Agent. +enum AdditionalDiagnosticRequest { + CPU = 0; +} + +// DiagnosticComponentsRequest is the message to request diagnostics from individual components. +message DiagnosticComponentsRequest { + repeated DiagnosticComponentRequest components = 1; + repeated AdditionalDiagnosticRequest additional_metrics = 2; +} + +// DiagnosticComponentRequest specifies the component to send a diagnostic request to. +message DiagnosticComponentRequest { + // ID of the component. + string component_id = 1; } // DiagnosticAgentResponse is response to gathered diagnostic information about the Elastic Agent. @@ -235,6 +253,16 @@ message DiagnosticUnitResponse { repeated DiagnosticFileResult results = 5; } +// DiagnosticComponentResponse is the response diagnostic information for a component-level diagnostic request +message DiagnosticComponentResponse { + // ID of the component. + string component_id = 1; + // Error message for the failure fetching diagnostic information for this unit. + string error = 4; + // Diagnostic results for the unit. + repeated DiagnosticFileResult results = 5; +} + // DiagnosticUnitsResponse is response to gathered units diagnostic information. message DiagnosticUnitsResponse { // Diagnostics results per unit. @@ -272,6 +300,9 @@ service ElasticAgentControl { // Gather diagnostic information for the running units. rpc DiagnosticUnits(DiagnosticUnitsRequest) returns (stream DiagnosticUnitResponse); + // Gather diagnostic information for the running components. + rpc DiagnosticComponents(DiagnosticComponentsRequest) returns (stream DiagnosticComponentResponse); + // Configure adjusts the running Elastic Agent configuration with the configuration // provided over the RPC. // diff --git a/go.mod b/go.mod index 32959010a23..26ce7317d91 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/dolmen-go/contextio v0.0.0-20200217195037-68fc5150bcd5 github.com/elastic/e2e-testing v1.99.2-0.20221205111528-ade3c840d0c0 github.com/elastic/elastic-agent-autodiscover v0.6.2 - github.com/elastic/elastic-agent-client/v7 v7.1.2 + github.com/elastic/elastic-agent-client/v7 v7.2.0 github.com/elastic/elastic-agent-libs v0.3.9-0.20230608184016-1f368a55a6ac github.com/elastic/elastic-agent-system-metrics v0.6.1 github.com/elastic/elastic-transport-go/v8 v8.3.0 @@ -60,8 +60,8 @@ require ( golang.org/x/text v0.9.0 golang.org/x/time v0.3.0 golang.org/x/tools v0.7.0 - google.golang.org/grpc v1.46.0 - google.golang.org/protobuf v1.28.0 + google.golang.org/grpc v1.53.0 + google.golang.org/protobuf v1.29.1 gopkg.in/yaml.v2 v2.4.0 gotest.tools v2.2.0+incompatible gotest.tools/gotestsum v1.7.0 @@ -139,10 +139,10 @@ require ( golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect golang.org/x/mod v0.9.0 // indirect golang.org/x/net v0.9.0 // indirect - golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect + golang.org/x/oauth2 v0.4.0 // indirect golang.org/x/term v0.7.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20220426171045-31bebdecfb46 // indirect + google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect google.golang.org/grpc/examples v0.0.0-20220304170021-431ea809a767 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 574819bf5e5..4b53cb65445 100644 --- a/go.sum +++ b/go.sum @@ -395,8 +395,8 @@ github.com/elastic/e2e-testing v1.99.2-0.20221205111528-ade3c840d0c0 h1:dTrVPE6H github.com/elastic/e2e-testing v1.99.2-0.20221205111528-ade3c840d0c0/go.mod h1:hzqVK19fiowHGWldLoKRHl3eXLErKyP89o7L/R3aHsk= github.com/elastic/elastic-agent-autodiscover v0.6.2 h1:7P3cbMBWXjbzA80rxitQjc+PiWyZ4I4F4LqrCYgYlNc= github.com/elastic/elastic-agent-autodiscover v0.6.2/go.mod h1:yXYKFAG+Py+TcE4CCR8EAbJiYb+6Dz9sCDoWgOveqtU= -github.com/elastic/elastic-agent-client/v7 v7.1.2 h1:p6KvvDMoFCBPvchxcx9cRXpRjsDaii0m/wE3lqQxpmM= -github.com/elastic/elastic-agent-client/v7 v7.1.2/go.mod h1:G3Mk1pHXxvj3wC5FvsGUlPOsvapTB5SfrUmWiJDXT6Q= +github.com/elastic/elastic-agent-client/v7 v7.2.0 h1:WCPu7t+NGrnjzfu76FxyZpAzoQirIEBn1ne6kKHacIU= +github.com/elastic/elastic-agent-client/v7 v7.2.0/go.mod h1:9/amG2K2y2oqx39zURcc+hnqcX+nyJ1cZrLgzsgo5c0= github.com/elastic/elastic-agent-libs v0.3.9-0.20230608184016-1f368a55a6ac h1:0tNQuC+Tz+j9/O6Oq5LH+ccvpmEQOFAaSyxaNREAdXM= github.com/elastic/elastic-agent-libs v0.3.9-0.20230608184016-1f368a55a6ac/go.mod h1:Fy5QqIOax0EOVeQJ2l5Ux+GmJsX549Obllru5R1bHLI= github.com/elastic/elastic-agent-system-metrics v0.6.1 h1:LCN1lvQTkdUuU/rKlpKyVMDU/G/I8/iZWCaW6K+mo4o= @@ -441,7 +441,6 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m 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.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ= -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/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= @@ -1495,8 +1494,9 @@ golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ 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-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.4.0 h1:NF0gk8LVPg1Ml7SSbGyySuoxdsXitj7TvgvuRxIMc/M= +golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= 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= @@ -1869,8 +1869,8 @@ google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ6 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-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220426171045-31bebdecfb46 h1:G1IeWbjrqEq9ChWxEuRPJu6laA67+XgTFHVSAvepr38= -google.golang.org/genproto v0.0.0-20220426171045-31bebdecfb46/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w= +google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/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= @@ -1904,9 +1904,8 @@ google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9K google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.43.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 h1:oCjezcn6g6A75TGoKYBPgKmVBLexhYLM6MebdrPApP8= -google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc= +google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/grpc/examples v0.0.0-20220304170021-431ea809a767 h1:r16FSFCMhn7+LU8CzbtAIKppYeU6NUPJVdvXeIqVIq8= google.golang.org/grpc/examples v0.0.0-20220304170021-431ea809a767/go.mod h1:wKDg0brwMZpaizQ1i7IzYcJjH1TmbJudYdnQC9+J+LE= @@ -1923,8 +1922,8 @@ 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.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.29.1 h1:7QBf+IK2gx70Ap/hDsOmam3GE0v9HicjfEdAxE62UoM= +google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 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= diff --git a/internal/pkg/agent/application/actions/handlers/handler_action_diagnostics.go b/internal/pkg/agent/application/actions/handlers/handler_action_diagnostics.go index bdd0ec1bce3..8ff339bff31 100644 --- a/internal/pkg/agent/application/actions/handlers/handler_action_diagnostics.go +++ b/internal/pkg/agent/application/actions/handlers/handler_action_diagnostics.go @@ -145,7 +145,8 @@ func (h *Diagnostics) collectDiag(ctx context.Context, action *fleetapi.ActionDi h.log.Warn(str) } }() - err := diagnostics.ZipArchive(&wBuf, &b, aDiag, uDiag) + // NOTE: Right now, actions don't support component-level diagnostics + err := diagnostics.ZipArchive(&wBuf, &b, aDiag, uDiag, []client.DiagnosticComponentResult{}) if err != nil { h.log.Errorw( "diagnostics action handler failed generate zip archive", @@ -254,7 +255,7 @@ func (h *Diagnostics) diagFile(aDiag []client.DiagnosticFileResult, uDiag []clie h.log.Warn(str) } }() - if err := diagnostics.ZipArchive(&wBuf, f, aDiag, uDiag); err != nil { + if err := diagnostics.ZipArchive(&wBuf, f, aDiag, uDiag, []client.DiagnosticComponentResult{}); err != nil { os.Remove(name) return nil, 0, err } diff --git a/internal/pkg/agent/application/coordinator/coordinator.go b/internal/pkg/agent/application/coordinator/coordinator.go index 36a3f77c674..6a2d2b5429c 100644 --- a/internal/pkg/agent/application/coordinator/coordinator.go +++ b/internal/pkg/agent/application/coordinator/coordinator.go @@ -106,6 +106,10 @@ type RuntimeManager interface { // PerformDiagnostics executes the diagnostic action for the provided units. If no units are provided then // it performs diagnostics for all current units. PerformDiagnostics(context.Context, ...runtime.ComponentUnitDiagnosticRequest) []runtime.ComponentUnitDiagnostic + + //PerformComponentDiagnostics executes the diagnostic action for the provided components. If no components are provided, + // then it performs the diagnostics for all current units. + PerformComponentDiagnostics(ctx context.Context, additionalMetrics []cproto.AdditionalDiagnosticRequest, req ...component.Component) ([]runtime.ComponentDiagnostic, error) } // ConfigChange provides an interface for receiving a new configuration. @@ -455,6 +459,11 @@ func (c *Coordinator) PerformDiagnostics(ctx context.Context, req ...runtime.Com return c.runtimeMgr.PerformDiagnostics(ctx, req...) } +// PerformComponentDiagnostics executes the diagnostic action for the provided components. +func (c *Coordinator) PerformComponentDiagnostics(ctx context.Context, additionalMetrics []cproto.AdditionalDiagnosticRequest, req ...component.Component) ([]runtime.ComponentDiagnostic, error) { + return c.runtimeMgr.PerformComponentDiagnostics(ctx, additionalMetrics, req...) +} + // SetLogLevel changes the entire log level for the running Elastic Agent. // Called from external goroutines. func (c *Coordinator) SetLogLevel(ctx context.Context, lvl logp.Level) error { diff --git a/internal/pkg/agent/application/coordinator/coordinator_test.go b/internal/pkg/agent/application/coordinator/coordinator_test.go index f5439483be6..03e61035273 100644 --- a/internal/pkg/agent/application/coordinator/coordinator_test.go +++ b/internal/pkg/agent/application/coordinator/coordinator_test.go @@ -19,6 +19,7 @@ import ( "github.com/elastic/elastic-agent-client/v7/pkg/client" agentclient "github.com/elastic/elastic-agent/pkg/control/v2/client" + "github.com/elastic/elastic-agent/pkg/control/v2/cproto" "github.com/stretchr/testify/require" "go.elastic.co/apm/apmtest" @@ -721,7 +722,7 @@ func (r *fakeRuntimeManager) State() []runtime.ComponentComponentState { } // PerformAction executes an action on a unit. -func (r *fakeRuntimeManager) PerformAction(ctx context.Context, comp component.Component, unit component.Unit, name string, params map[string]interface{}) (map[string]interface{}, error) { +func (r *fakeRuntimeManager) PerformAction(_ context.Context, _ component.Component, _ component.Unit, _ string, _ map[string]interface{}) (map[string]interface{}, error) { return nil, nil } @@ -736,6 +737,11 @@ func (r *fakeRuntimeManager) PerformDiagnostics(context.Context, ...runtime.Comp return nil } +// PerformComponentDiagnostics executes the diagnostic action for the provided components. +func (r *fakeRuntimeManager) PerformComponentDiagnostics(_ context.Context, _ []cproto.AdditionalDiagnosticRequest, _ ...component.Component) ([]runtime.ComponentDiagnostic, error) { + return nil, nil +} + func testBinary(t *testing.T, name string) string { t.Helper() diff --git a/internal/pkg/agent/cmd/diagnostics.go b/internal/pkg/agent/cmd/diagnostics.go index 3bc0df8ad93..375b4a0cc52 100644 --- a/internal/pkg/agent/cmd/diagnostics.go +++ b/internal/pkg/agent/cmd/diagnostics.go @@ -11,6 +11,7 @@ import ( "time" "github.com/elastic/elastic-agent/pkg/control/v2/client" + "github.com/elastic/elastic-agent/pkg/control/v2/cproto" "github.com/spf13/cobra" @@ -32,6 +33,7 @@ func newDiagnosticsCommand(_ []string, streams *cli.IOStreams) *cobra.Command { } cmd.Flags().StringP("file", "f", "", "name of the output diagnostics zip archive") + cmd.Flags().BoolP("cpu-profile", "p", false, "wait to collect a CPU profile") return cmd } @@ -52,23 +54,37 @@ func diagnosticCmd(streams *cli.IOStreams, cmd *cobra.Command) error { } defer daemon.Disconnect() - agentDiag, err := daemon.DiagnosticAgent(ctx) + fetchCPU, _ := cmd.Flags().GetBool("cpu-profile") + + additionalDiags := []cproto.AdditionalDiagnosticRequest{} + if fetchCPU { + // console will just hang while we wait for the CPU profile; print something so user doesn't get confused + fmt.Fprintf(streams.Out, "Creating diagnostics archive, waiting for CPU profile...\n") + additionalDiags = []cproto.AdditionalDiagnosticRequest{cproto.AdditionalDiagnosticRequest_CPU} + } + + agentDiag, err := daemon.DiagnosticAgent(ctx, additionalDiags) if err != nil { return fmt.Errorf("failed to fetch agent diagnostics: %w", err) } unitDiags, err := daemon.DiagnosticUnits(ctx) if err != nil { - return fmt.Errorf("failed to fetch component/unit diagnostics: %w", err) + return fmt.Errorf("failed to fetch unit diagnostics: %w", err) + } + + compDiags, err := daemon.DiagnosticComponents(ctx, additionalDiags) + if err != nil { + return fmt.Errorf("failed to fetch component diagnostics: %w", err) } f, err := os.Create(fileName) if err != nil { - return err + return fmt.Errorf("error creating .zip file: %w", err) } defer f.Close() - if err := diagnostics.ZipArchive(streams.Err, f, agentDiag, unitDiags); err != nil { + if err := diagnostics.ZipArchive(streams.Err, f, agentDiag, unitDiags, compDiags); err != nil { return fmt.Errorf("unable to create archive %q: %w", fileName, err) } fmt.Fprintf(streams.Out, "Created diagnostics archive %q\n", fileName) diff --git a/internal/pkg/diagnostics/diagnostics.go b/internal/pkg/diagnostics/diagnostics.go index 91e65f36bb0..661bc9791cc 100644 --- a/internal/pkg/diagnostics/diagnostics.go +++ b/internal/pkg/diagnostics/diagnostics.go @@ -69,6 +69,7 @@ func GlobalHooks() Hooks { { Name: "package version", Filename: ".package.version", + Description: "Package Version", ContentType: "text/plain", Hook: func(_ context.Context) []byte { pkgVersionPath, err := version.GetAgentPackageVersionFilePath() @@ -112,7 +113,7 @@ func GlobalHooks() Hooks { }, { Name: "block", - Filename: "block.pprog.gz", + Filename: "block.pprof.gz", Description: "stack traces that led to blocking on synchronization primitives", ContentType: "application/octet-stream", Hook: pprofDiag("block", 0), @@ -139,13 +140,32 @@ func pprofDiag(name string, debug int) func(context.Context) []byte { } } +// CreateCPUProfile will gather a CPU profile over a given time duration. +func CreateCPUProfile(ctx context.Context, period time.Duration) ([]byte, error) { + var writeBuf bytes.Buffer + err := pprof.StartCPUProfile(&writeBuf) + if err != nil { + return nil, fmt.Errorf("error starting CPU profile: %w", err) + } + tc := time.After(period) + select { + case <-ctx.Done(): + pprof.StopCPUProfile() + return nil, ctx.Err() + case <-tc: + break + } + + pprof.StopCPUProfile() + return writeBuf.Bytes(), nil +} + // ZipArchive creates a zipped diagnostics bundle using the passed writer with the passed diagnostics and local logs. // If any error is encountered when writing the contents of the archive it is returned. -func ZipArchive(errOut, w io.Writer, agentDiag []client.DiagnosticFileResult, unitDiags []client.DiagnosticUnitResult) error { +func ZipArchive(errOut, w io.Writer, agentDiag []client.DiagnosticFileResult, unitDiags []client.DiagnosticUnitResult, compDiags []client.DiagnosticComponentResult) error { ts := time.Now().UTC() zw := zip.NewWriter(w) defer zw.Close() - // Write agent diagnostics content for _, ad := range agentDiag { zf, err := zw.CreateHeader(&zip.FileHeader{ @@ -154,11 +174,11 @@ func ZipArchive(errOut, w io.Writer, agentDiag []client.DiagnosticFileResult, un Modified: ad.Generated, }) if err != nil { - return err + return fmt.Errorf("error creating header for agent diagnostics: %w", err) } err = writeRedacted(errOut, zf, ad.Filename, ad) if err != nil { - return err + return fmt.Errorf("error writing file for agent diagnostics: %w", err) } } @@ -169,6 +189,13 @@ func ZipArchive(errOut, w io.Writer, agentDiag []client.DiagnosticFileResult, un compDir := strings.ReplaceAll(ud.ComponentID, "/", "-") compDirs[compDir] = append(compDirs[compDir], ud) } + + componentResults := map[string]client.DiagnosticComponentResult{} + // handle component diagnostics + for _, comp := range compDiags { + compDir := strings.ReplaceAll(comp.ComponentID, "/", "-") + componentResults[compDir] = comp + } // write each units diagnostics into its own directory // layout becomes components/// _, err := zw.CreateHeader(&zip.FileHeader{ @@ -177,8 +204,9 @@ func ZipArchive(errOut, w io.Writer, agentDiag []client.DiagnosticFileResult, un Modified: ts, }) if err != nil { - return err + return fmt.Errorf("error creating .zip header for components/ directory: %w", err) } + // iterate over components for dirName, units := range compDirs { _, err := zw.CreateHeader(&zip.FileHeader{ Name: fmt.Sprintf("components/%s/", dirName), @@ -186,8 +214,37 @@ func ZipArchive(errOut, w io.Writer, agentDiag []client.DiagnosticFileResult, un Modified: ts, }) if err != nil { - return err + return fmt.Errorf("error creating .zip header for component directory: %w", err) + } + // create component diags + if comp, ok := componentResults[dirName]; ok { + // check for component-level errors + if comp.Err != nil { + err = writeErrorResult(zw, fmt.Sprintf("components/%s/error.txt", dirName), comp.Err.Error()) + if err != nil { + return fmt.Errorf("error while writing error result for component %s: %w", comp.ComponentID, err) + } + } else { + for _, res := range comp.Results { + + filePath := fmt.Sprintf("components/%s/%s", dirName, res.Filename) + resFileWriter, err := zw.CreateHeader(&zip.FileHeader{ + Name: filePath, + Method: zip.Deflate, + Modified: ts, + }) + if err != nil { + return fmt.Errorf("error creating .zip header for %s: %w", res.Filename, err) + } + err = writeRedacted(errOut, resFileWriter, filePath, res) + if err != nil { + return fmt.Errorf("error writing %s in zip file: %w", res.Filename, err) + } + } + } + } + // create unit diags for _, ud := range units { unitDir := strings.ReplaceAll(strings.TrimPrefix(ud.UnitID, ud.ComponentID+"-"), "/", "-") _, err := zw.CreateHeader(&zip.FileHeader{ @@ -196,20 +253,13 @@ func ZipArchive(errOut, w io.Writer, agentDiag []client.DiagnosticFileResult, un Modified: ts, }) if err != nil { - return err + return fmt.Errorf("error creating .zip header for unit directory: %w", err) } + // check for unit-level errors if ud.Err != nil { - w, err := zw.CreateHeader(&zip.FileHeader{ - Name: fmt.Sprintf("components/%s/%s/error.txt", dirName, unitDir), - Method: zip.Deflate, - Modified: ts, - }) - if err != nil { - return err - } - _, err = w.Write([]byte(fmt.Sprintf("%s\n", ud.Err))) + err = writeErrorResult(zw, fmt.Sprintf("components/%s/%s/error.txt", dirName, unitDir), ud.Err.Error()) if err != nil { - return err + return fmt.Errorf("error while writing error result for unit %s: %w", ud.UnitID, err) } continue } @@ -235,6 +285,24 @@ func ZipArchive(errOut, w io.Writer, agentDiag []client.DiagnosticFileResult, un return zipLogs(zw, ts) } +func writeErrorResult(zw *zip.Writer, path string, errBody string) error { + ts := time.Now().UTC() + w, err := zw.CreateHeader(&zip.FileHeader{ + Name: path, + Method: zip.Deflate, + Modified: ts, + }) + if err != nil { + return fmt.Errorf("error writing header for error.txt file for component: %w", err) + } + _, err = w.Write([]byte(fmt.Sprintf("%s\n", errBody))) + if err != nil { + return fmt.Errorf("error writing error.txt file for component: %w", err) + } + + return nil +} + func writeRedacted(errOut, w io.Writer, fullFilePath string, fr client.DiagnosticFileResult) error { out := &fr.Content diff --git a/pkg/component/runtime/manager.go b/pkg/component/runtime/manager.go index 1e7d3e4b163..3beb67f6482 100644 --- a/pkg/component/runtime/manager.go +++ b/pkg/component/runtime/manager.go @@ -32,6 +32,7 @@ import ( "github.com/elastic/elastic-agent/internal/pkg/agent/configuration" "github.com/elastic/elastic-agent/internal/pkg/core/authority" "github.com/elastic/elastic-agent/pkg/component" + "github.com/elastic/elastic-agent/pkg/control/v2/cproto" "github.com/elastic/elastic-agent/pkg/core/logger" ) @@ -43,15 +44,17 @@ const ( // and restarted. maxCheckinMisses = 3 // diagnosticTimeout is the maximum amount of time to wait for a diagnostic response from a unit. - diagnosticTimeout = 20 * time.Second + diagnosticTimeout = time.Minute // stopCheckRetryPeriod is a idle time between checks for component stopped state stopCheckRetryPeriod = 200 * time.Millisecond ) var ( - // ErrNoUnit returned when manager is not controlling this unit. + // ErrNoUnit is returned when manager is not controlling this unit. ErrNoUnit = errors.New("no unit under control of this manager") + // ErrNoComponent is returned when manager is not controlling this component + ErrNoComponent = errors.New("no component under control of this manager") ) // ComponentComponentState provides a structure to map a component to current component state. @@ -75,6 +78,13 @@ type ComponentUnitDiagnostic struct { Err error } +// ComponentDiagnostic provides a structure to map a component to a diagnostic result. +type ComponentDiagnostic struct { + Component component.Component + Results []*proto.ActionDiagnosticUnitResult + Err error +} + // Manager for the entire runtime of operating components. type Manager struct { proto.UnimplementedElasticAgentServer @@ -405,6 +415,63 @@ func (m *Manager) PerformAction(ctx context.Context, comp component.Component, u return respBody, nil } +// PerformComponentDiagnostics executes the diagnostic action for the given components. If no components are provided then +// it performs diagnostics for all running components. +func (m *Manager) PerformComponentDiagnostics(ctx context.Context, additionalMetrics []cproto.AdditionalDiagnosticRequest, req ...component.Component) ([]ComponentDiagnostic, error) { + if len(req) == 0 { + if len(req) == 0 { + m.currentMx.RLock() + for _, runtime := range m.current { + currComp := runtime.getCurrent() + req = append(req, currComp) + } + m.currentMx.RUnlock() + } + } + + resp := []ComponentDiagnostic{} + + diagnosticCount := len(req) + respChan := make(chan ComponentDiagnostic, diagnosticCount) + for diag := 0; diag < diagnosticCount; diag++ { + // transform the additional metrics field into JSON params + params := client.DiagnosticParams{} + if len(additionalMetrics) > 0 { + for _, param := range additionalMetrics { + params.AdditionalMetrics = append(params.AdditionalMetrics, param.String()) + } + } + // perform diagnostics in parallel; if we have a CPU pprof request, it'll take 30 seconds each. + go func(iter int) { + diagResponse, err := m.performDiagAction(ctx, req[iter], component.Unit{}, proto.ActionRequest_COMPONENT, params) + respStruct := ComponentDiagnostic{ + Component: req[iter], + Err: err, + Results: diagResponse, + } + respChan <- respStruct + + }(diag) + } + + // performDiagAction will have timeouts at various points, + // but for the sake of paranoia, create our own timeout + collectTimeout, cancel := context.WithTimeout(ctx, time.Minute*2) + defer cancel() + + for res := 0; res < diagnosticCount; res++ { + select { + case <-collectTimeout.Done(): + return nil, fmt.Errorf("got context done waiting for diagnostics") + case data := <-respChan: + resp = append(resp, data) + } + } + + return resp, nil + +} + // PerformDiagnostics executes the diagnostic action for the provided units. If no units are provided then // it performs diagnostics for all current units. func (m *Manager) PerformDiagnostics(ctx context.Context, req ...ComponentUnitDiagnosticRequest) []ComponentUnitDiagnostic { @@ -458,7 +525,8 @@ func (m *Manager) PerformDiagnostics(ctx context.Context, req ...ComponentUnitDi // already in error don't perform diagnostics continue } - diag, err := m.performDiagAction(ctx, r.Component, r.Unit) + + diag, err := m.performDiagAction(ctx, r.Component, r.Unit, proto.ActionRequest_UNIT, client.DiagnosticParams{}) if err != nil { r.Err = err } else { @@ -599,7 +667,6 @@ func (m *Manager) CheckinV2(server proto.ElasticAgent_CheckinV2Server) error { t.Stop() case <-t.C: // close connection - m.logger.Debug("check-in stream never sent initial observed message; closing connection") return status.Error(codes.DeadlineExceeded, "never sent initial observed message") } if !ok { @@ -610,7 +677,6 @@ func (m *Manager) CheckinV2(server proto.ElasticAgent_CheckinV2Server) error { runtime := m.getRuntimeFromToken(initCheckin.Token) if runtime == nil { // no component runtime with token; close connection - m.logger.Debug("check-in stream sent an invalid token; closing connection") return status.Error(codes.PermissionDenied, "invalid token") } @@ -895,6 +961,17 @@ func (m *Manager) getRuntimeFromUnit(comp component.Component, unit component.Un return nil } +func (m *Manager) getRuntimeFromComponent(comp component.Component) *componentRuntimeState { + m.currentMx.RLock() + defer m.currentMx.RUnlock() + for _, currentComp := range m.current { + if currentComp.id == comp.ID { + return currentComp + } + } + return nil +} + func (m *Manager) getListenAddr() string { addr := strings.SplitN(m.listenAddr, ":", 2) if len(addr) == 2 && addr[1] == "0" { @@ -909,7 +986,9 @@ func (m *Manager) getListenAddr() string { return m.listenAddr } -func (m *Manager) performDiagAction(ctx context.Context, comp component.Component, unit component.Unit) ([]*proto.ActionDiagnosticUnitResult, error) { +// performDiagAction creates a diagnostic ActionRequest and executes it against the runtime that's mapped to the specified component. +// if the specified actionLevel is ActionRequest_COMPONENT, the unit field is ignored. +func (m *Manager) performDiagAction(ctx context.Context, comp component.Component, unit component.Unit, actionLevel proto.ActionRequest_Level, params client.DiagnosticParams) ([]*proto.ActionDiagnosticUnitResult, error) { ctx, cancel := context.WithTimeout(ctx, diagnosticTimeout) defer cancel() @@ -918,27 +997,53 @@ func (m *Manager) performDiagAction(ctx context.Context, comp component.Componen return nil, err } - runtime := m.getRuntimeFromUnit(comp, unit) - if runtime == nil { - return nil, ErrNoUnit + var runtime *componentRuntimeState + if actionLevel == proto.ActionRequest_UNIT { + runtime = m.getRuntimeFromUnit(comp, unit) + if runtime == nil { + return nil, ErrNoUnit + } + } else { + runtime = m.getRuntimeFromComponent(comp) + if runtime == nil { + return nil, ErrNoComponent + } + } + + if len(params.AdditionalMetrics) > 0 { + m.logger.Debugf("Performing diagnostic action with params: %v", params.AdditionalMetrics) + } + marshalParams, err := json.Marshal(params) + if err != nil { + return nil, fmt.Errorf("error marshalling json for params: %w", err) } req := &proto.ActionRequest{ - Id: id.String(), - UnitId: unit.ID, - UnitType: proto.UnitType(unit.Type), - Type: proto.ActionRequest_DIAGNOSTICS, + Id: id.String(), + Type: proto.ActionRequest_DIAGNOSTICS, + Level: actionLevel, + Params: marshalParams, } + + if actionLevel == proto.ActionRequest_UNIT { + req.UnitId = unit.ID + req.UnitType = proto.UnitType(unit.Type) + } + res, err := runtime.performAction(ctx, req) + // the only way this can return an error is a context Done(), be sure to make that explicit. if err != nil { - return nil, err + if errors.Is(context.DeadlineExceeded, err) { + return nil, fmt.Errorf("diagnostic action timed out, deadline is %s: %w", diagnosticTimeout, err) + } + return nil, fmt.Errorf("error running performAction: %w", err) } if res.Status == proto.ActionResponse_FAILED { var respBody map[string]interface{} if res.Result != nil { err = json.Unmarshal(res.Result, &respBody) if err != nil { - return nil, err + return nil, fmt.Errorf("error unmarshaling JSON in FAILED response: %w", err) } errMsgT, ok := respBody["error"] if ok { diff --git a/pkg/control/v1/proto/control_v1.pb.go b/pkg/control/v1/proto/control_v1.pb.go index c7848cde8e6..dd5d586fec4 100644 --- a/pkg/control/v1/proto/control_v1.pb.go +++ b/pkg/control/v1/proto/control_v1.pb.go @@ -4,8 +4,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.0 -// protoc v3.21.9 +// protoc-gen-go v1.28.1 +// protoc v3.19.6 // source: control_v1.proto // proto namespace/package name is shared with elastic-agent-client diff --git a/pkg/control/v1/proto/control_v1_grpc.pb.go b/pkg/control/v1/proto/control_v1_grpc.pb.go index 43e62f56985..8ce57aafa7a 100644 --- a/pkg/control/v1/proto/control_v1_grpc.pb.go +++ b/pkg/control/v1/proto/control_v1_grpc.pb.go @@ -5,7 +5,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.2.0 -// - protoc v3.21.9 +// - protoc v3.19.6 // source: control_v1.proto package proto diff --git a/pkg/control/v2/client/client.go b/pkg/control/v2/client/client.go index 165b0caef41..764088ad504 100644 --- a/pkg/control/v2/client/client.go +++ b/pkg/control/v2/client/client.go @@ -25,6 +25,9 @@ type UnitType = cproto.UnitType // State is the state codes type State = cproto.State +// AdditionalMetrics is the type for additional diagnostic requests +type AdditionalMetrics = cproto.AdditionalDiagnosticRequest + const ( // UnitTypeInput is an input unit. UnitTypeInput UnitType = cproto.UnitType_INPUT @@ -53,6 +56,11 @@ const ( Rollback State = cproto.State_ROLLBACK ) +const ( + // CPU requests additional CPU diagnostics + CPU AdditionalMetrics = cproto.AdditionalDiagnosticRequest_CPU +) + // Version is the current running version of the daemon. type Version struct { Version string `json:"version" yaml:"version"` @@ -126,6 +134,11 @@ type DiagnosticUnitRequest struct { UnitType UnitType } +// DiagnosticComponentRequest targets a specific component for diagnostics +type DiagnosticComponentRequest struct { + ComponentID string +} + // DiagnosticUnitResult is a set of results for a unit. type DiagnosticUnitResult struct { ComponentID string @@ -135,6 +148,13 @@ type DiagnosticUnitResult struct { Results []DiagnosticFileResult } +// DiagnosticComponentResult is a set of diagnostic results for a component +type DiagnosticComponentResult struct { + ComponentID string + Err error + Results []DiagnosticFileResult +} + // Client communicates to Elastic Agent through the control protocol. type Client interface { // Connect connects to the running Elastic Agent. @@ -152,11 +172,13 @@ type Client interface { // Upgrade triggers upgrade of the current running daemon. Upgrade(ctx context.Context, version string, sourceURI string, skipVerify bool, pgpBytes ...string) (string, error) // DiagnosticAgent gathers diagnostics information for the running Elastic Agent. - DiagnosticAgent(ctx context.Context) ([]DiagnosticFileResult, error) + DiagnosticAgent(ctx context.Context, additionalDiags []AdditionalMetrics) ([]DiagnosticFileResult, error) // DiagnosticUnits gathers diagnostics information from specific units (or all if non are provided). DiagnosticUnits(ctx context.Context, units ...DiagnosticUnitRequest) ([]DiagnosticUnitResult, error) + // DiagnosticComponents gathers diagnostic information for specific components + // the additionalDiags field specifies optional diagnostics that can also be collected. + DiagnosticComponents(ctx context.Context, additionalDiags []AdditionalMetrics, components ...DiagnosticComponentRequest) ([]DiagnosticComponentResult, error) // Configure sends a new configuration to the Elastic Agent. - // // Only works in the case that Elastic Agent is started in testing mode. Configure(ctx context.Context, config string) error } @@ -294,10 +316,10 @@ func (c *client) Upgrade(ctx context.Context, version string, sourceURI string, } // DiagnosticAgent gathers diagnostics information for the running Elastic Agent. -func (c *client) DiagnosticAgent(ctx context.Context) ([]DiagnosticFileResult, error) { - resp, err := c.client.DiagnosticAgent(ctx, &cproto.DiagnosticAgentRequest{}) +func (c *client) DiagnosticAgent(ctx context.Context, additionalMetrics []AdditionalMetrics) ([]DiagnosticFileResult, error) { + resp, err := c.client.DiagnosticAgent(ctx, &cproto.DiagnosticAgentRequest{AdditionalMetrics: additionalMetrics}) if err != nil { - return nil, err + return nil, fmt.Errorf("error in DiagnosticAgent RPC call: %w", err) } files := make([]DiagnosticFileResult, 0, len(resp.Results)) @@ -314,6 +336,55 @@ func (c *client) DiagnosticAgent(ctx context.Context) ([]DiagnosticFileResult, e return files, nil } +// DiagnosticComponents gathers diagnostic information for components running under elastic-agent +// errors at the DiagnosticComponents() level are returned as an error value, errors at the level of individual components are returned in +// the DiagnosticComponentResult struct. +func (c *client) DiagnosticComponents(ctx context.Context, additionalMetrics []AdditionalMetrics, components ...DiagnosticComponentRequest) ([]DiagnosticComponentResult, error) { + reqs := make([]*cproto.DiagnosticComponentRequest, 0, len(components)) + for _, u := range components { + reqs = append(reqs, &cproto.DiagnosticComponentRequest{ + ComponentId: u.ComponentID, + }) + } + respStream, err := c.client.DiagnosticComponents(ctx, &cproto.DiagnosticComponentsRequest{AdditionalMetrics: additionalMetrics, Components: reqs}) + if err != nil { + return nil, fmt.Errorf("error in DiagnosticComponents RPC call: %w", err) + } + + results := []DiagnosticComponentResult{} + for { + compResp, err := respStream.Recv() + if errors.Is(err, io.EOF) { + break + } + if err != nil { + return nil, fmt.Errorf("error reading response stream: %w", err) + } + resultFiles := []DiagnosticFileResult{} + for _, file := range compResp.Results { + resultFiles = append(resultFiles, DiagnosticFileResult{ + Name: file.Name, + Filename: file.Filename, + Description: file.Description, + ContentType: file.ContentType, + Content: file.Content, + Generated: file.Generated.AsTime(), + }) + } + if compResp.Error != "" { + err = errors.New(compResp.Error) + } + results = append(results, DiagnosticComponentResult{ + ComponentID: compResp.ComponentId, + Err: err, + Results: resultFiles, + }) + } + + return results, nil + +} + // DiagnosticUnits gathers diagnostics information from specific units (or all if non are provided). func (c *client) DiagnosticUnits(ctx context.Context, units ...DiagnosticUnitRequest) ([]DiagnosticUnitResult, error) { reqs := make([]*cproto.DiagnosticUnitRequest, 0, len(units)) diff --git a/pkg/control/v2/cproto/control_v2.pb.go b/pkg/control/v2/cproto/control_v2.pb.go index 27059dcfba9..236e7b22aa0 100644 --- a/pkg/control/v2/cproto/control_v2.pb.go +++ b/pkg/control/v2/cproto/control_v2.pb.go @@ -4,8 +4,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.0 -// protoc v3.21.9 +// protoc-gen-go v1.28.1 +// protoc v3.19.6 // source: control_v2.proto package cproto @@ -258,6 +258,50 @@ func (PprofOption) EnumDescriptor() ([]byte, []int) { return file_control_v2_proto_rawDescGZIP(), []int{3} } +// DiagnosticAgentRequestAdditional is an enum of additional diagnostic metrics that can be requested from Elastic Agent. +type AdditionalDiagnosticRequest int32 + +const ( + AdditionalDiagnosticRequest_CPU AdditionalDiagnosticRequest = 0 +) + +// Enum value maps for AdditionalDiagnosticRequest. +var ( + AdditionalDiagnosticRequest_name = map[int32]string{ + 0: "CPU", + } + AdditionalDiagnosticRequest_value = map[string]int32{ + "CPU": 0, + } +) + +func (x AdditionalDiagnosticRequest) Enum() *AdditionalDiagnosticRequest { + p := new(AdditionalDiagnosticRequest) + *p = x + return p +} + +func (x AdditionalDiagnosticRequest) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (AdditionalDiagnosticRequest) Descriptor() protoreflect.EnumDescriptor { + return file_control_v2_proto_enumTypes[4].Descriptor() +} + +func (AdditionalDiagnosticRequest) Type() protoreflect.EnumType { + return &file_control_v2_proto_enumTypes[4] +} + +func (x AdditionalDiagnosticRequest) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use AdditionalDiagnosticRequest.Descriptor instead. +func (AdditionalDiagnosticRequest) EnumDescriptor() ([]byte, []int) { + return file_control_v2_proto_rawDescGZIP(), []int{4} +} + // Empty message. type Empty struct { state protoimpl.MessageState @@ -1106,6 +1150,8 @@ type DiagnosticAgentRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + + AdditionalMetrics []AdditionalDiagnosticRequest `protobuf:"varint,1,rep,packed,name=additional_metrics,json=additionalMetrics,proto3,enum=cproto.AdditionalDiagnosticRequest" json:"additional_metrics,omitempty"` } func (x *DiagnosticAgentRequest) Reset() { @@ -1140,6 +1186,118 @@ func (*DiagnosticAgentRequest) Descriptor() ([]byte, []int) { return file_control_v2_proto_rawDescGZIP(), []int{11} } +func (x *DiagnosticAgentRequest) GetAdditionalMetrics() []AdditionalDiagnosticRequest { + if x != nil { + return x.AdditionalMetrics + } + return nil +} + +// DiagnosticComponentsRequest is the message to request diagnostics from individual components. +type DiagnosticComponentsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Components []*DiagnosticComponentRequest `protobuf:"bytes,1,rep,name=components,proto3" json:"components,omitempty"` + AdditionalMetrics []AdditionalDiagnosticRequest `protobuf:"varint,2,rep,packed,name=additional_metrics,json=additionalMetrics,proto3,enum=cproto.AdditionalDiagnosticRequest" json:"additional_metrics,omitempty"` +} + +func (x *DiagnosticComponentsRequest) Reset() { + *x = DiagnosticComponentsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_control_v2_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DiagnosticComponentsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DiagnosticComponentsRequest) ProtoMessage() {} + +func (x *DiagnosticComponentsRequest) ProtoReflect() protoreflect.Message { + mi := &file_control_v2_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DiagnosticComponentsRequest.ProtoReflect.Descriptor instead. +func (*DiagnosticComponentsRequest) Descriptor() ([]byte, []int) { + return file_control_v2_proto_rawDescGZIP(), []int{12} +} + +func (x *DiagnosticComponentsRequest) GetComponents() []*DiagnosticComponentRequest { + if x != nil { + return x.Components + } + return nil +} + +func (x *DiagnosticComponentsRequest) GetAdditionalMetrics() []AdditionalDiagnosticRequest { + if x != nil { + return x.AdditionalMetrics + } + return nil +} + +// DiagnosticComponentRequest specifies the component to send a diagnostic request to. +type DiagnosticComponentRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // ID of the component. + ComponentId string `protobuf:"bytes,1,opt,name=component_id,json=componentId,proto3" json:"component_id,omitempty"` +} + +func (x *DiagnosticComponentRequest) Reset() { + *x = DiagnosticComponentRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_control_v2_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DiagnosticComponentRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DiagnosticComponentRequest) ProtoMessage() {} + +func (x *DiagnosticComponentRequest) ProtoReflect() protoreflect.Message { + mi := &file_control_v2_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DiagnosticComponentRequest.ProtoReflect.Descriptor instead. +func (*DiagnosticComponentRequest) Descriptor() ([]byte, []int) { + return file_control_v2_proto_rawDescGZIP(), []int{13} +} + +func (x *DiagnosticComponentRequest) GetComponentId() string { + if x != nil { + return x.ComponentId + } + return "" +} + // DiagnosticAgentResponse is response to gathered diagnostic information about the Elastic Agent. type DiagnosticAgentResponse struct { state protoimpl.MessageState @@ -1153,7 +1311,7 @@ type DiagnosticAgentResponse struct { func (x *DiagnosticAgentResponse) Reset() { *x = DiagnosticAgentResponse{} if protoimpl.UnsafeEnabled { - mi := &file_control_v2_proto_msgTypes[12] + mi := &file_control_v2_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1166,7 +1324,7 @@ func (x *DiagnosticAgentResponse) String() string { func (*DiagnosticAgentResponse) ProtoMessage() {} func (x *DiagnosticAgentResponse) ProtoReflect() protoreflect.Message { - mi := &file_control_v2_proto_msgTypes[12] + mi := &file_control_v2_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1179,7 +1337,7 @@ func (x *DiagnosticAgentResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DiagnosticAgentResponse.ProtoReflect.Descriptor instead. func (*DiagnosticAgentResponse) Descriptor() ([]byte, []int) { - return file_control_v2_proto_rawDescGZIP(), []int{12} + return file_control_v2_proto_rawDescGZIP(), []int{14} } func (x *DiagnosticAgentResponse) GetResults() []*DiagnosticFileResult { @@ -1206,7 +1364,7 @@ type DiagnosticUnitRequest struct { func (x *DiagnosticUnitRequest) Reset() { *x = DiagnosticUnitRequest{} if protoimpl.UnsafeEnabled { - mi := &file_control_v2_proto_msgTypes[13] + mi := &file_control_v2_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1219,7 +1377,7 @@ func (x *DiagnosticUnitRequest) String() string { func (*DiagnosticUnitRequest) ProtoMessage() {} func (x *DiagnosticUnitRequest) ProtoReflect() protoreflect.Message { - mi := &file_control_v2_proto_msgTypes[13] + mi := &file_control_v2_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1232,7 +1390,7 @@ func (x *DiagnosticUnitRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DiagnosticUnitRequest.ProtoReflect.Descriptor instead. func (*DiagnosticUnitRequest) Descriptor() ([]byte, []int) { - return file_control_v2_proto_rawDescGZIP(), []int{13} + return file_control_v2_proto_rawDescGZIP(), []int{15} } func (x *DiagnosticUnitRequest) GetComponentId() string { @@ -1269,7 +1427,7 @@ type DiagnosticUnitsRequest struct { func (x *DiagnosticUnitsRequest) Reset() { *x = DiagnosticUnitsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_control_v2_proto_msgTypes[14] + mi := &file_control_v2_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1282,7 +1440,7 @@ func (x *DiagnosticUnitsRequest) String() string { func (*DiagnosticUnitsRequest) ProtoMessage() {} func (x *DiagnosticUnitsRequest) ProtoReflect() protoreflect.Message { - mi := &file_control_v2_proto_msgTypes[14] + mi := &file_control_v2_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1295,7 +1453,7 @@ func (x *DiagnosticUnitsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DiagnosticUnitsRequest.ProtoReflect.Descriptor instead. func (*DiagnosticUnitsRequest) Descriptor() ([]byte, []int) { - return file_control_v2_proto_rawDescGZIP(), []int{14} + return file_control_v2_proto_rawDescGZIP(), []int{16} } func (x *DiagnosticUnitsRequest) GetUnits() []*DiagnosticUnitRequest { @@ -1326,7 +1484,7 @@ type DiagnosticUnitResponse struct { func (x *DiagnosticUnitResponse) Reset() { *x = DiagnosticUnitResponse{} if protoimpl.UnsafeEnabled { - mi := &file_control_v2_proto_msgTypes[15] + mi := &file_control_v2_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1339,7 +1497,7 @@ func (x *DiagnosticUnitResponse) String() string { func (*DiagnosticUnitResponse) ProtoMessage() {} func (x *DiagnosticUnitResponse) ProtoReflect() protoreflect.Message { - mi := &file_control_v2_proto_msgTypes[15] + mi := &file_control_v2_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1352,7 +1510,7 @@ func (x *DiagnosticUnitResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DiagnosticUnitResponse.ProtoReflect.Descriptor instead. func (*DiagnosticUnitResponse) Descriptor() ([]byte, []int) { - return file_control_v2_proto_rawDescGZIP(), []int{15} + return file_control_v2_proto_rawDescGZIP(), []int{17} } func (x *DiagnosticUnitResponse) GetComponentId() string { @@ -1390,6 +1548,73 @@ func (x *DiagnosticUnitResponse) GetResults() []*DiagnosticFileResult { return nil } +// DiagnosticComponentResponse is the response diagnostic information for a component-level diagnostic request +type DiagnosticComponentResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // ID of the component. + ComponentId string `protobuf:"bytes,1,opt,name=component_id,json=componentId,proto3" json:"component_id,omitempty"` + // Error message for the failure fetching diagnostic information for this unit. + Error string `protobuf:"bytes,4,opt,name=error,proto3" json:"error,omitempty"` + // Diagnostic results for the unit. + Results []*DiagnosticFileResult `protobuf:"bytes,5,rep,name=results,proto3" json:"results,omitempty"` +} + +func (x *DiagnosticComponentResponse) Reset() { + *x = DiagnosticComponentResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_control_v2_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DiagnosticComponentResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DiagnosticComponentResponse) ProtoMessage() {} + +func (x *DiagnosticComponentResponse) ProtoReflect() protoreflect.Message { + mi := &file_control_v2_proto_msgTypes[18] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DiagnosticComponentResponse.ProtoReflect.Descriptor instead. +func (*DiagnosticComponentResponse) Descriptor() ([]byte, []int) { + return file_control_v2_proto_rawDescGZIP(), []int{18} +} + +func (x *DiagnosticComponentResponse) GetComponentId() string { + if x != nil { + return x.ComponentId + } + return "" +} + +func (x *DiagnosticComponentResponse) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +func (x *DiagnosticComponentResponse) GetResults() []*DiagnosticFileResult { + if x != nil { + return x.Results + } + return nil +} + // DiagnosticUnitsResponse is response to gathered units diagnostic information. type DiagnosticUnitsResponse struct { state protoimpl.MessageState @@ -1403,7 +1628,7 @@ type DiagnosticUnitsResponse struct { func (x *DiagnosticUnitsResponse) Reset() { *x = DiagnosticUnitsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_control_v2_proto_msgTypes[16] + mi := &file_control_v2_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1416,7 +1641,7 @@ func (x *DiagnosticUnitsResponse) String() string { func (*DiagnosticUnitsResponse) ProtoMessage() {} func (x *DiagnosticUnitsResponse) ProtoReflect() protoreflect.Message { - mi := &file_control_v2_proto_msgTypes[16] + mi := &file_control_v2_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1429,7 +1654,7 @@ func (x *DiagnosticUnitsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DiagnosticUnitsResponse.ProtoReflect.Descriptor instead. func (*DiagnosticUnitsResponse) Descriptor() ([]byte, []int) { - return file_control_v2_proto_rawDescGZIP(), []int{16} + return file_control_v2_proto_rawDescGZIP(), []int{19} } func (x *DiagnosticUnitsResponse) GetUnits() []*DiagnosticUnitResponse { @@ -1452,7 +1677,7 @@ type ConfigureRequest struct { func (x *ConfigureRequest) Reset() { *x = ConfigureRequest{} if protoimpl.UnsafeEnabled { - mi := &file_control_v2_proto_msgTypes[17] + mi := &file_control_v2_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1465,7 +1690,7 @@ func (x *ConfigureRequest) String() string { func (*ConfigureRequest) ProtoMessage() {} func (x *ConfigureRequest) ProtoReflect() protoreflect.Message { - mi := &file_control_v2_proto_msgTypes[17] + mi := &file_control_v2_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1478,7 +1703,7 @@ func (x *ConfigureRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ConfigureRequest.ProtoReflect.Descriptor instead. func (*ConfigureRequest) Descriptor() ([]byte, []int) { - return file_control_v2_proto_rawDescGZIP(), []int{17} + return file_control_v2_proto_rawDescGZIP(), []int{20} } func (x *ConfigureRequest) GetConfig() string { @@ -1601,105 +1826,143 @@ var file_control_v2_proto_rawDesc = []byte{ 0x0a, 0x09, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x67, - 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x22, 0x18, 0x0a, 0x16, 0x44, 0x69, 0x61, 0x67, - 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x22, 0x51, 0x0a, 0x17, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, - 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, - 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, - 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, - 0x69, 0x63, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x07, 0x72, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x73, 0x22, 0x82, 0x01, 0x0a, 0x15, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, - 0x73, 0x74, 0x69, 0x63, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, - 0x49, 0x64, 0x12, 0x2d, 0x0a, 0x09, 0x75, 0x6e, 0x69, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x10, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x55, - 0x6e, 0x69, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x08, 0x75, 0x6e, 0x69, 0x74, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x6e, 0x69, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x75, 0x6e, 0x69, 0x74, 0x49, 0x64, 0x22, 0x4d, 0x0a, 0x16, 0x44, 0x69, - 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x55, 0x6e, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x05, 0x75, 0x6e, 0x69, 0x74, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x69, 0x61, - 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x52, 0x05, 0x75, 0x6e, 0x69, 0x74, 0x73, 0x22, 0xd1, 0x01, 0x0a, 0x16, 0x44, 0x69, - 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, - 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x70, - 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x2d, 0x0a, 0x09, 0x75, 0x6e, 0x69, 0x74, 0x5f, - 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x10, 0x2e, 0x63, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x55, 0x6e, 0x69, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x08, 0x75, 0x6e, - 0x69, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x6e, 0x69, 0x74, 0x5f, 0x69, - 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x6e, 0x69, 0x74, 0x49, 0x64, 0x12, - 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x36, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, - 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x22, 0x4f, 0x0a, - 0x17, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x55, 0x6e, 0x69, 0x74, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x05, 0x75, 0x6e, 0x69, 0x74, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x55, 0x6e, 0x69, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x05, 0x75, 0x6e, 0x69, 0x74, 0x73, 0x22, 0x2a, - 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2a, 0x85, 0x01, 0x0a, 0x05, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x54, 0x41, 0x52, 0x54, 0x49, 0x4e, 0x47, - 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x55, 0x52, 0x49, 0x4e, - 0x47, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x59, 0x10, 0x02, - 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x45, 0x47, 0x52, 0x41, 0x44, 0x45, 0x44, 0x10, 0x03, 0x12, 0x0a, - 0x0a, 0x06, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x54, - 0x4f, 0x50, 0x50, 0x49, 0x4e, 0x47, 0x10, 0x05, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x54, 0x4f, 0x50, - 0x50, 0x45, 0x44, 0x10, 0x06, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x50, 0x47, 0x52, 0x41, 0x44, 0x49, - 0x4e, 0x47, 0x10, 0x07, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x4f, 0x4c, 0x4c, 0x42, 0x41, 0x43, 0x4b, - 0x10, 0x08, 0x2a, 0x21, 0x0a, 0x08, 0x55, 0x6e, 0x69, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x09, - 0x0a, 0x05, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4f, 0x55, 0x54, - 0x50, 0x55, 0x54, 0x10, 0x01, 0x2a, 0x28, 0x0a, 0x0c, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, - 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x10, 0x01, 0x2a, - 0x7f, 0x0a, 0x0b, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0a, - 0x0a, 0x06, 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x53, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x42, 0x4c, - 0x4f, 0x43, 0x4b, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x4d, 0x44, 0x4c, 0x49, 0x4e, 0x45, - 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x47, 0x4f, 0x52, 0x4f, 0x55, 0x54, 0x49, 0x4e, 0x45, 0x10, - 0x03, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x45, 0x41, 0x50, 0x10, 0x04, 0x12, 0x09, 0x0a, 0x05, 0x4d, - 0x55, 0x54, 0x45, 0x58, 0x10, 0x05, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x4f, 0x46, 0x49, 0x4c, - 0x45, 0x10, 0x06, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x48, 0x52, 0x45, 0x41, 0x44, 0x43, 0x52, 0x45, - 0x41, 0x54, 0x45, 0x10, 0x07, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x52, 0x41, 0x43, 0x45, 0x10, 0x08, - 0x32, 0xfb, 0x03, 0x0a, 0x13, 0x45, 0x6c, 0x61, 0x73, 0x74, 0x69, 0x63, 0x41, 0x67, 0x65, 0x6e, - 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x12, 0x31, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x12, 0x0d, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x1a, 0x17, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x05, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x12, 0x0d, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x1a, 0x15, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x0a, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x57, 0x61, 0x74, 0x63, 0x68, 0x12, 0x0d, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x15, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, - 0x12, 0x31, 0x0a, 0x07, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x0d, 0x2e, 0x63, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x17, 0x2e, 0x63, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x07, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x12, 0x16, - 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x52, 0x0a, 0x0f, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x41, 0x67, 0x65, - 0x6e, 0x74, 0x12, 0x1e, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x69, 0x61, 0x67, + 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x22, 0x6c, 0x0a, 0x16, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x69, 0x61, 0x67, - 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x0f, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, - 0x63, 0x55, 0x6e, 0x69, 0x74, 0x73, 0x12, 0x1e, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x55, 0x6e, 0x69, 0x74, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x34, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x75, 0x72, 0x65, 0x12, 0x18, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x0d, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x29, - 0x5a, 0x24, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, - 0x67, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2f, 0x76, 0x32, 0x2f, - 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0xf8, 0x01, 0x01, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x73, 0x74, 0x12, 0x52, 0x0a, 0x12, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, + 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x23, + 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x61, 0x6c, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x52, 0x11, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x4d, + 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x22, 0xb5, 0x01, 0x0a, 0x1b, 0x44, 0x69, 0x61, 0x67, 0x6e, + 0x6f, 0x73, 0x74, 0x69, 0x63, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x42, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, + 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x43, 0x6f, + 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x0a, + 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x52, 0x0a, 0x12, 0x61, 0x64, + 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, + 0x73, 0x74, 0x69, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x11, 0x61, 0x64, 0x64, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x22, 0x3f, + 0x0a, 0x1a, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x43, 0x6f, 0x6d, 0x70, + 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, + 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x22, + 0x51, 0x0a, 0x17, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x41, 0x67, 0x65, + 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x07, 0x72, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x46, + 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x73, 0x22, 0x82, 0x01, 0x0a, 0x15, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, + 0x63, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, + 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, + 0x2d, 0x0a, 0x09, 0x75, 0x6e, 0x69, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x10, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x55, 0x6e, 0x69, 0x74, + 0x54, 0x79, 0x70, 0x65, 0x52, 0x08, 0x75, 0x6e, 0x69, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, + 0x0a, 0x07, 0x75, 0x6e, 0x69, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x75, 0x6e, 0x69, 0x74, 0x49, 0x64, 0x22, 0x4d, 0x0a, 0x16, 0x44, 0x69, 0x61, 0x67, 0x6e, + 0x6f, 0x73, 0x74, 0x69, 0x63, 0x55, 0x6e, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x33, 0x0a, 0x05, 0x75, 0x6e, 0x69, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x1d, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, + 0x73, 0x74, 0x69, 0x63, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, + 0x05, 0x75, 0x6e, 0x69, 0x74, 0x73, 0x22, 0xd1, 0x01, 0x0a, 0x16, 0x44, 0x69, 0x61, 0x67, 0x6e, + 0x6f, 0x73, 0x74, 0x69, 0x63, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, + 0x6e, 0x74, 0x49, 0x64, 0x12, 0x2d, 0x0a, 0x09, 0x75, 0x6e, 0x69, 0x74, 0x5f, 0x74, 0x79, 0x70, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x10, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x55, 0x6e, 0x69, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x08, 0x75, 0x6e, 0x69, 0x74, 0x54, + 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x6e, 0x69, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x6e, 0x69, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, + 0x6f, 0x72, 0x12, 0x36, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x05, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x69, 0x61, + 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x22, 0x8e, 0x01, 0x0a, 0x1b, 0x44, + 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, + 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, + 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, + 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x12, 0x36, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x05, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x69, + 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x75, + 0x6c, 0x74, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x22, 0x4f, 0x0a, 0x17, 0x44, + 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x55, 0x6e, 0x69, 0x74, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x05, 0x75, 0x6e, 0x69, 0x74, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, + 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x05, 0x75, 0x6e, 0x69, 0x74, 0x73, 0x22, 0x2a, 0x0a, 0x10, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2a, 0x85, 0x01, 0x0a, 0x05, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x54, 0x41, 0x52, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x00, + 0x12, 0x0f, 0x0a, 0x0b, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x55, 0x52, 0x49, 0x4e, 0x47, 0x10, + 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x59, 0x10, 0x02, 0x12, 0x0c, + 0x0a, 0x08, 0x44, 0x45, 0x47, 0x52, 0x41, 0x44, 0x45, 0x44, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, + 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x54, 0x4f, 0x50, + 0x50, 0x49, 0x4e, 0x47, 0x10, 0x05, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x54, 0x4f, 0x50, 0x50, 0x45, + 0x44, 0x10, 0x06, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x50, 0x47, 0x52, 0x41, 0x44, 0x49, 0x4e, 0x47, + 0x10, 0x07, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x4f, 0x4c, 0x4c, 0x42, 0x41, 0x43, 0x4b, 0x10, 0x08, + 0x2a, 0x21, 0x0a, 0x08, 0x55, 0x6e, 0x69, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x09, 0x0a, 0x05, + 0x49, 0x4e, 0x50, 0x55, 0x54, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4f, 0x55, 0x54, 0x50, 0x55, + 0x54, 0x10, 0x01, 0x2a, 0x28, 0x0a, 0x0c, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x00, + 0x12, 0x0b, 0x0a, 0x07, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x10, 0x01, 0x2a, 0x7f, 0x0a, + 0x0b, 0x50, 0x70, 0x72, 0x6f, 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0a, 0x0a, 0x06, + 0x41, 0x4c, 0x4c, 0x4f, 0x43, 0x53, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x42, 0x4c, 0x4f, 0x43, + 0x4b, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x4d, 0x44, 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x02, + 0x12, 0x0d, 0x0a, 0x09, 0x47, 0x4f, 0x52, 0x4f, 0x55, 0x54, 0x49, 0x4e, 0x45, 0x10, 0x03, 0x12, + 0x08, 0x0a, 0x04, 0x48, 0x45, 0x41, 0x50, 0x10, 0x04, 0x12, 0x09, 0x0a, 0x05, 0x4d, 0x55, 0x54, + 0x45, 0x58, 0x10, 0x05, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x4f, 0x46, 0x49, 0x4c, 0x45, 0x10, + 0x06, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x48, 0x52, 0x45, 0x41, 0x44, 0x43, 0x52, 0x45, 0x41, 0x54, + 0x45, 0x10, 0x07, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x52, 0x41, 0x43, 0x45, 0x10, 0x08, 0x2a, 0x26, + 0x0a, 0x1b, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x44, 0x69, 0x61, 0x67, + 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x07, 0x0a, + 0x03, 0x43, 0x50, 0x55, 0x10, 0x00, 0x32, 0xdf, 0x04, 0x0a, 0x13, 0x45, 0x6c, 0x61, 0x73, 0x74, + 0x69, 0x63, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x12, 0x31, + 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x0d, 0x2e, 0x63, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x17, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x2d, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0d, 0x2e, 0x63, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x15, 0x2e, 0x63, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x34, 0x0a, 0x0a, 0x53, 0x74, 0x61, 0x74, 0x65, 0x57, 0x61, 0x74, 0x63, 0x68, 0x12, 0x0d, + 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x15, 0x2e, + 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x31, 0x0a, 0x07, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x12, 0x0d, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x1a, 0x17, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x07, 0x55, 0x70, 0x67, + 0x72, 0x61, 0x64, 0x65, 0x12, 0x16, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x55, 0x70, + 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x52, 0x0a, 0x0f, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, + 0x74, 0x69, 0x63, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x1e, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x41, 0x67, 0x65, 0x6e, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x41, 0x67, 0x65, 0x6e, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x0f, 0x44, 0x69, 0x61, + 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x55, 0x6e, 0x69, 0x74, 0x73, 0x12, 0x1e, 0x2e, 0x63, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, + 0x55, 0x6e, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, + 0x55, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x62, + 0x0a, 0x14, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x43, 0x6f, 0x6d, 0x70, + 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x23, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, + 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, + 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x63, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x43, + 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x30, 0x01, 0x12, 0x34, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x12, + 0x18, 0x2e, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, + 0x72, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0d, 0x2e, 0x63, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x29, 0x5a, 0x24, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2f, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2f, 0x76, 0x32, 0x2f, 0x63, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0xf8, 0x01, 0x01, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1714,75 +1977,85 @@ func file_control_v2_proto_rawDescGZIP() []byte { return file_control_v2_proto_rawDescData } -var file_control_v2_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_control_v2_proto_msgTypes = make([]protoimpl.MessageInfo, 19) +var file_control_v2_proto_enumTypes = make([]protoimpl.EnumInfo, 5) +var file_control_v2_proto_msgTypes = make([]protoimpl.MessageInfo, 22) var file_control_v2_proto_goTypes = []interface{}{ - (State)(0), // 0: cproto.State - (UnitType)(0), // 1: cproto.UnitType - (ActionStatus)(0), // 2: cproto.ActionStatus - (PprofOption)(0), // 3: cproto.PprofOption - (*Empty)(nil), // 4: cproto.Empty - (*VersionResponse)(nil), // 5: cproto.VersionResponse - (*RestartResponse)(nil), // 6: cproto.RestartResponse - (*UpgradeRequest)(nil), // 7: cproto.UpgradeRequest - (*UpgradeResponse)(nil), // 8: cproto.UpgradeResponse - (*ComponentUnitState)(nil), // 9: cproto.ComponentUnitState - (*ComponentVersionInfo)(nil), // 10: cproto.ComponentVersionInfo - (*ComponentState)(nil), // 11: cproto.ComponentState - (*StateAgentInfo)(nil), // 12: cproto.StateAgentInfo - (*StateResponse)(nil), // 13: cproto.StateResponse - (*DiagnosticFileResult)(nil), // 14: cproto.DiagnosticFileResult - (*DiagnosticAgentRequest)(nil), // 15: cproto.DiagnosticAgentRequest - (*DiagnosticAgentResponse)(nil), // 16: cproto.DiagnosticAgentResponse - (*DiagnosticUnitRequest)(nil), // 17: cproto.DiagnosticUnitRequest - (*DiagnosticUnitsRequest)(nil), // 18: cproto.DiagnosticUnitsRequest - (*DiagnosticUnitResponse)(nil), // 19: cproto.DiagnosticUnitResponse - (*DiagnosticUnitsResponse)(nil), // 20: cproto.DiagnosticUnitsResponse - (*ConfigureRequest)(nil), // 21: cproto.ConfigureRequest - nil, // 22: cproto.ComponentVersionInfo.MetaEntry - (*timestamppb.Timestamp)(nil), // 23: google.protobuf.Timestamp + (State)(0), // 0: cproto.State + (UnitType)(0), // 1: cproto.UnitType + (ActionStatus)(0), // 2: cproto.ActionStatus + (PprofOption)(0), // 3: cproto.PprofOption + (AdditionalDiagnosticRequest)(0), // 4: cproto.AdditionalDiagnosticRequest + (*Empty)(nil), // 5: cproto.Empty + (*VersionResponse)(nil), // 6: cproto.VersionResponse + (*RestartResponse)(nil), // 7: cproto.RestartResponse + (*UpgradeRequest)(nil), // 8: cproto.UpgradeRequest + (*UpgradeResponse)(nil), // 9: cproto.UpgradeResponse + (*ComponentUnitState)(nil), // 10: cproto.ComponentUnitState + (*ComponentVersionInfo)(nil), // 11: cproto.ComponentVersionInfo + (*ComponentState)(nil), // 12: cproto.ComponentState + (*StateAgentInfo)(nil), // 13: cproto.StateAgentInfo + (*StateResponse)(nil), // 14: cproto.StateResponse + (*DiagnosticFileResult)(nil), // 15: cproto.DiagnosticFileResult + (*DiagnosticAgentRequest)(nil), // 16: cproto.DiagnosticAgentRequest + (*DiagnosticComponentsRequest)(nil), // 17: cproto.DiagnosticComponentsRequest + (*DiagnosticComponentRequest)(nil), // 18: cproto.DiagnosticComponentRequest + (*DiagnosticAgentResponse)(nil), // 19: cproto.DiagnosticAgentResponse + (*DiagnosticUnitRequest)(nil), // 20: cproto.DiagnosticUnitRequest + (*DiagnosticUnitsRequest)(nil), // 21: cproto.DiagnosticUnitsRequest + (*DiagnosticUnitResponse)(nil), // 22: cproto.DiagnosticUnitResponse + (*DiagnosticComponentResponse)(nil), // 23: cproto.DiagnosticComponentResponse + (*DiagnosticUnitsResponse)(nil), // 24: cproto.DiagnosticUnitsResponse + (*ConfigureRequest)(nil), // 25: cproto.ConfigureRequest + nil, // 26: cproto.ComponentVersionInfo.MetaEntry + (*timestamppb.Timestamp)(nil), // 27: google.protobuf.Timestamp } var file_control_v2_proto_depIdxs = []int32{ 2, // 0: cproto.RestartResponse.status:type_name -> cproto.ActionStatus 2, // 1: cproto.UpgradeResponse.status:type_name -> cproto.ActionStatus 1, // 2: cproto.ComponentUnitState.unit_type:type_name -> cproto.UnitType 0, // 3: cproto.ComponentUnitState.state:type_name -> cproto.State - 22, // 4: cproto.ComponentVersionInfo.meta:type_name -> cproto.ComponentVersionInfo.MetaEntry + 26, // 4: cproto.ComponentVersionInfo.meta:type_name -> cproto.ComponentVersionInfo.MetaEntry 0, // 5: cproto.ComponentState.state:type_name -> cproto.State - 9, // 6: cproto.ComponentState.units:type_name -> cproto.ComponentUnitState - 10, // 7: cproto.ComponentState.version_info:type_name -> cproto.ComponentVersionInfo - 12, // 8: cproto.StateResponse.info:type_name -> cproto.StateAgentInfo + 10, // 6: cproto.ComponentState.units:type_name -> cproto.ComponentUnitState + 11, // 7: cproto.ComponentState.version_info:type_name -> cproto.ComponentVersionInfo + 13, // 8: cproto.StateResponse.info:type_name -> cproto.StateAgentInfo 0, // 9: cproto.StateResponse.state:type_name -> cproto.State - 11, // 10: cproto.StateResponse.components:type_name -> cproto.ComponentState + 12, // 10: cproto.StateResponse.components:type_name -> cproto.ComponentState 0, // 11: cproto.StateResponse.fleetState:type_name -> cproto.State - 23, // 12: cproto.DiagnosticFileResult.generated:type_name -> google.protobuf.Timestamp - 14, // 13: cproto.DiagnosticAgentResponse.results:type_name -> cproto.DiagnosticFileResult - 1, // 14: cproto.DiagnosticUnitRequest.unit_type:type_name -> cproto.UnitType - 17, // 15: cproto.DiagnosticUnitsRequest.units:type_name -> cproto.DiagnosticUnitRequest - 1, // 16: cproto.DiagnosticUnitResponse.unit_type:type_name -> cproto.UnitType - 14, // 17: cproto.DiagnosticUnitResponse.results:type_name -> cproto.DiagnosticFileResult - 19, // 18: cproto.DiagnosticUnitsResponse.units:type_name -> cproto.DiagnosticUnitResponse - 4, // 19: cproto.ElasticAgentControl.Version:input_type -> cproto.Empty - 4, // 20: cproto.ElasticAgentControl.State:input_type -> cproto.Empty - 4, // 21: cproto.ElasticAgentControl.StateWatch:input_type -> cproto.Empty - 4, // 22: cproto.ElasticAgentControl.Restart:input_type -> cproto.Empty - 7, // 23: cproto.ElasticAgentControl.Upgrade:input_type -> cproto.UpgradeRequest - 15, // 24: cproto.ElasticAgentControl.DiagnosticAgent:input_type -> cproto.DiagnosticAgentRequest - 18, // 25: cproto.ElasticAgentControl.DiagnosticUnits:input_type -> cproto.DiagnosticUnitsRequest - 21, // 26: cproto.ElasticAgentControl.Configure:input_type -> cproto.ConfigureRequest - 5, // 27: cproto.ElasticAgentControl.Version:output_type -> cproto.VersionResponse - 13, // 28: cproto.ElasticAgentControl.State:output_type -> cproto.StateResponse - 13, // 29: cproto.ElasticAgentControl.StateWatch:output_type -> cproto.StateResponse - 6, // 30: cproto.ElasticAgentControl.Restart:output_type -> cproto.RestartResponse - 8, // 31: cproto.ElasticAgentControl.Upgrade:output_type -> cproto.UpgradeResponse - 16, // 32: cproto.ElasticAgentControl.DiagnosticAgent:output_type -> cproto.DiagnosticAgentResponse - 19, // 33: cproto.ElasticAgentControl.DiagnosticUnits:output_type -> cproto.DiagnosticUnitResponse - 4, // 34: cproto.ElasticAgentControl.Configure:output_type -> cproto.Empty - 27, // [27:35] is the sub-list for method output_type - 19, // [19:27] is the sub-list for method input_type - 19, // [19:19] is the sub-list for extension type_name - 19, // [19:19] is the sub-list for extension extendee - 0, // [0:19] is the sub-list for field type_name + 27, // 12: cproto.DiagnosticFileResult.generated:type_name -> google.protobuf.Timestamp + 4, // 13: cproto.DiagnosticAgentRequest.additional_metrics:type_name -> cproto.AdditionalDiagnosticRequest + 18, // 14: cproto.DiagnosticComponentsRequest.components:type_name -> cproto.DiagnosticComponentRequest + 4, // 15: cproto.DiagnosticComponentsRequest.additional_metrics:type_name -> cproto.AdditionalDiagnosticRequest + 15, // 16: cproto.DiagnosticAgentResponse.results:type_name -> cproto.DiagnosticFileResult + 1, // 17: cproto.DiagnosticUnitRequest.unit_type:type_name -> cproto.UnitType + 20, // 18: cproto.DiagnosticUnitsRequest.units:type_name -> cproto.DiagnosticUnitRequest + 1, // 19: cproto.DiagnosticUnitResponse.unit_type:type_name -> cproto.UnitType + 15, // 20: cproto.DiagnosticUnitResponse.results:type_name -> cproto.DiagnosticFileResult + 15, // 21: cproto.DiagnosticComponentResponse.results:type_name -> cproto.DiagnosticFileResult + 22, // 22: cproto.DiagnosticUnitsResponse.units:type_name -> cproto.DiagnosticUnitResponse + 5, // 23: cproto.ElasticAgentControl.Version:input_type -> cproto.Empty + 5, // 24: cproto.ElasticAgentControl.State:input_type -> cproto.Empty + 5, // 25: cproto.ElasticAgentControl.StateWatch:input_type -> cproto.Empty + 5, // 26: cproto.ElasticAgentControl.Restart:input_type -> cproto.Empty + 8, // 27: cproto.ElasticAgentControl.Upgrade:input_type -> cproto.UpgradeRequest + 16, // 28: cproto.ElasticAgentControl.DiagnosticAgent:input_type -> cproto.DiagnosticAgentRequest + 21, // 29: cproto.ElasticAgentControl.DiagnosticUnits:input_type -> cproto.DiagnosticUnitsRequest + 17, // 30: cproto.ElasticAgentControl.DiagnosticComponents:input_type -> cproto.DiagnosticComponentsRequest + 25, // 31: cproto.ElasticAgentControl.Configure:input_type -> cproto.ConfigureRequest + 6, // 32: cproto.ElasticAgentControl.Version:output_type -> cproto.VersionResponse + 14, // 33: cproto.ElasticAgentControl.State:output_type -> cproto.StateResponse + 14, // 34: cproto.ElasticAgentControl.StateWatch:output_type -> cproto.StateResponse + 7, // 35: cproto.ElasticAgentControl.Restart:output_type -> cproto.RestartResponse + 9, // 36: cproto.ElasticAgentControl.Upgrade:output_type -> cproto.UpgradeResponse + 19, // 37: cproto.ElasticAgentControl.DiagnosticAgent:output_type -> cproto.DiagnosticAgentResponse + 22, // 38: cproto.ElasticAgentControl.DiagnosticUnits:output_type -> cproto.DiagnosticUnitResponse + 23, // 39: cproto.ElasticAgentControl.DiagnosticComponents:output_type -> cproto.DiagnosticComponentResponse + 5, // 40: cproto.ElasticAgentControl.Configure:output_type -> cproto.Empty + 32, // [32:41] is the sub-list for method output_type + 23, // [23:32] is the sub-list for method input_type + 23, // [23:23] is the sub-list for extension type_name + 23, // [23:23] is the sub-list for extension extendee + 0, // [0:23] is the sub-list for field type_name } func init() { file_control_v2_proto_init() } @@ -1936,7 +2209,7 @@ func file_control_v2_proto_init() { } } file_control_v2_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DiagnosticAgentResponse); i { + switch v := v.(*DiagnosticComponentsRequest); i { case 0: return &v.state case 1: @@ -1948,7 +2221,7 @@ func file_control_v2_proto_init() { } } file_control_v2_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DiagnosticUnitRequest); i { + switch v := v.(*DiagnosticComponentRequest); i { case 0: return &v.state case 1: @@ -1960,7 +2233,7 @@ func file_control_v2_proto_init() { } } file_control_v2_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DiagnosticUnitsRequest); i { + switch v := v.(*DiagnosticAgentResponse); i { case 0: return &v.state case 1: @@ -1972,7 +2245,7 @@ func file_control_v2_proto_init() { } } file_control_v2_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DiagnosticUnitResponse); i { + switch v := v.(*DiagnosticUnitRequest); i { case 0: return &v.state case 1: @@ -1984,7 +2257,7 @@ func file_control_v2_proto_init() { } } file_control_v2_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DiagnosticUnitsResponse); i { + switch v := v.(*DiagnosticUnitsRequest); i { case 0: return &v.state case 1: @@ -1996,6 +2269,42 @@ func file_control_v2_proto_init() { } } file_control_v2_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DiagnosticUnitResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_control_v2_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DiagnosticComponentResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_control_v2_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DiagnosticUnitsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_control_v2_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ConfigureRequest); i { case 0: return &v.state @@ -2013,8 +2322,8 @@ func file_control_v2_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_control_v2_proto_rawDesc, - NumEnums: 4, - NumMessages: 19, + NumEnums: 5, + NumMessages: 22, NumExtensions: 0, NumServices: 1, }, diff --git a/pkg/control/v2/cproto/control_v2_grpc.pb.go b/pkg/control/v2/cproto/control_v2_grpc.pb.go index fa63fabc634..22a6c9117c0 100644 --- a/pkg/control/v2/cproto/control_v2_grpc.pb.go +++ b/pkg/control/v2/cproto/control_v2_grpc.pb.go @@ -5,7 +5,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.2.0 -// - protoc v3.21.9 +// - protoc v3.19.6 // source: control_v2.proto package cproto @@ -44,6 +44,8 @@ type ElasticAgentControlClient interface { DiagnosticAgent(ctx context.Context, in *DiagnosticAgentRequest, opts ...grpc.CallOption) (*DiagnosticAgentResponse, error) // Gather diagnostic information for the running units. DiagnosticUnits(ctx context.Context, in *DiagnosticUnitsRequest, opts ...grpc.CallOption) (ElasticAgentControl_DiagnosticUnitsClient, error) + // Gather diagnostic information for the running components. + DiagnosticComponents(ctx context.Context, in *DiagnosticComponentsRequest, opts ...grpc.CallOption) (ElasticAgentControl_DiagnosticComponentsClient, error) // Configure adjusts the running Elastic Agent configuration with the configuration // provided over the RPC. // @@ -170,6 +172,38 @@ func (x *elasticAgentControlDiagnosticUnitsClient) Recv() (*DiagnosticUnitRespon return m, nil } +func (c *elasticAgentControlClient) DiagnosticComponents(ctx context.Context, in *DiagnosticComponentsRequest, opts ...grpc.CallOption) (ElasticAgentControl_DiagnosticComponentsClient, error) { + stream, err := c.cc.NewStream(ctx, &ElasticAgentControl_ServiceDesc.Streams[2], "/cproto.ElasticAgentControl/DiagnosticComponents", opts...) + if err != nil { + return nil, err + } + x := &elasticAgentControlDiagnosticComponentsClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type ElasticAgentControl_DiagnosticComponentsClient interface { + Recv() (*DiagnosticComponentResponse, error) + grpc.ClientStream +} + +type elasticAgentControlDiagnosticComponentsClient struct { + grpc.ClientStream +} + +func (x *elasticAgentControlDiagnosticComponentsClient) Recv() (*DiagnosticComponentResponse, error) { + m := new(DiagnosticComponentResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + func (c *elasticAgentControlClient) Configure(ctx context.Context, in *ConfigureRequest, opts ...grpc.CallOption) (*Empty, error) { out := new(Empty) err := c.cc.Invoke(ctx, "/cproto.ElasticAgentControl/Configure", in, out, opts...) @@ -200,6 +234,8 @@ type ElasticAgentControlServer interface { DiagnosticAgent(context.Context, *DiagnosticAgentRequest) (*DiagnosticAgentResponse, error) // Gather diagnostic information for the running units. DiagnosticUnits(*DiagnosticUnitsRequest, ElasticAgentControl_DiagnosticUnitsServer) error + // Gather diagnostic information for the running components. + DiagnosticComponents(*DiagnosticComponentsRequest, ElasticAgentControl_DiagnosticComponentsServer) error // Configure adjusts the running Elastic Agent configuration with the configuration // provided over the RPC. // @@ -235,6 +271,9 @@ func (UnimplementedElasticAgentControlServer) DiagnosticAgent(context.Context, * func (UnimplementedElasticAgentControlServer) DiagnosticUnits(*DiagnosticUnitsRequest, ElasticAgentControl_DiagnosticUnitsServer) error { return status.Errorf(codes.Unimplemented, "method DiagnosticUnits not implemented") } +func (UnimplementedElasticAgentControlServer) DiagnosticComponents(*DiagnosticComponentsRequest, ElasticAgentControl_DiagnosticComponentsServer) error { + return status.Errorf(codes.Unimplemented, "method DiagnosticComponents not implemented") +} func (UnimplementedElasticAgentControlServer) Configure(context.Context, *ConfigureRequest) (*Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method Configure not implemented") } @@ -383,6 +422,27 @@ func (x *elasticAgentControlDiagnosticUnitsServer) Send(m *DiagnosticUnitRespons return x.ServerStream.SendMsg(m) } +func _ElasticAgentControl_DiagnosticComponents_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(DiagnosticComponentsRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(ElasticAgentControlServer).DiagnosticComponents(m, &elasticAgentControlDiagnosticComponentsServer{stream}) +} + +type ElasticAgentControl_DiagnosticComponentsServer interface { + Send(*DiagnosticComponentResponse) error + grpc.ServerStream +} + +type elasticAgentControlDiagnosticComponentsServer struct { + grpc.ServerStream +} + +func (x *elasticAgentControlDiagnosticComponentsServer) Send(m *DiagnosticComponentResponse) error { + return x.ServerStream.SendMsg(m) +} + func _ElasticAgentControl_Configure_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ConfigureRequest) if err := dec(in); err != nil { @@ -444,6 +504,11 @@ var ElasticAgentControl_ServiceDesc = grpc.ServiceDesc{ Handler: _ElasticAgentControl_DiagnosticUnits_Handler, ServerStreams: true, }, + { + StreamName: "DiagnosticComponents", + Handler: _ElasticAgentControl_DiagnosticComponents_Handler, + ServerStreams: true, + }, }, Metadata: "control_v2.proto", } diff --git a/pkg/control/v2/server/server.go b/pkg/control/v2/server/server.go index c111cdda7e4..e9fcf807bec 100644 --- a/pkg/control/v2/server/server.go +++ b/pkg/control/v2/server/server.go @@ -183,7 +183,7 @@ func (s *Server) Upgrade(ctx context.Context, request *cproto.UpgradeRequest) (* } // DiagnosticAgent returns diagnostic information for this running Elastic Agent. -func (s *Server) DiagnosticAgent(ctx context.Context, _ *cproto.DiagnosticAgentRequest) (*cproto.DiagnosticAgentResponse, error) { +func (s *Server) DiagnosticAgent(ctx context.Context, req *cproto.DiagnosticAgentRequest) (*cproto.DiagnosticAgentResponse, error) { res := make([]*cproto.DiagnosticFileResult, 0, len(s.diagHooks)) for _, h := range s.diagHooks { if ctx.Err() != nil { @@ -199,12 +199,71 @@ func (s *Server) DiagnosticAgent(ctx context.Context, _ *cproto.DiagnosticAgentR Generated: timestamppb.New(time.Now().UTC()), }) } + + for _, metric := range req.AdditionalMetrics { + switch metric { + case cproto.AdditionalDiagnosticRequest_CPU: + duration := time.Second * 30 + s.logger.Infof("Collecting CPU metrics, waiting for %s", duration) + cpuResults, err := diagnostics.CreateCPUProfile(ctx, duration) + if err != nil { + return nil, fmt.Errorf("error gathering CPU profile: %w", err) + } + res = append(res, &cproto.DiagnosticFileResult{ + Name: "cpuprofile", + Filename: "cpu.pprof", + Description: "CPU profile", + ContentType: "application/octet-stream", + Content: cpuResults, + Generated: timestamppb.New(time.Now().UTC()), + }) + } + } + if ctx.Err() != nil { return nil, ctx.Err() } return &cproto.DiagnosticAgentResponse{Results: res}, nil } +// DiagnosticComponents returns diagnostic information for the given components +func (s *Server) DiagnosticComponents(req *cproto.DiagnosticComponentsRequest, respServ cproto.ElasticAgentControl_DiagnosticComponentsServer) error { + reqs := []component.Component{} + for _, comp := range req.Components { + reqs = append(reqs, component.Component{ID: comp.GetComponentId()}) + } + + diags, err := s.coord.PerformComponentDiagnostics(respServ.Context(), req.AdditionalMetrics, reqs...) + if err != nil { + return fmt.Errorf("error fetching component-level diagnostics: %w", err) + } + for _, diag := range diags { + respFiles := []*cproto.DiagnosticFileResult{} + for _, file := range diag.Results { + respFiles = append(respFiles, &cproto.DiagnosticFileResult{ + Name: file.Name, + Filename: file.Filename, + Description: file.Description, + ContentType: file.ContentType, + Content: file.Content, + Generated: file.Generated, + }) + } + respStruct := &cproto.DiagnosticComponentResponse{ + ComponentId: diag.Component.ID, + Results: respFiles, + } + if diag.Err != nil { + respStruct.Error = diag.Err.Error() + } + err := respServ.Send(respStruct) + if err != nil { + return fmt.Errorf("error sending response: %w", err) + } + } + return nil +} + // DiagnosticUnits returns diagnostic information for the specific units (or all units if non-provided). func (s *Server) DiagnosticUnits(req *cproto.DiagnosticUnitsRequest, srv cproto.ElasticAgentControl_DiagnosticUnitsServer) error { reqs := make([]runtime.ComponentUnitDiagnosticRequest, 0, len(req.Units)) diff --git a/testing/integration/diagnostics_test.go b/testing/integration/diagnostics_test.go index d86cef6ef43..fb4c14b42a2 100644 --- a/testing/integration/diagnostics_test.go +++ b/testing/integration/diagnostics_test.go @@ -31,7 +31,7 @@ const diagnosticsArchiveGlobPattern = "elastic-agent-diagnostics-*.zip" var diagnosticsFiles = []string{ ".package.version", "allocs.pprof.gz", - "block.pprog.gz", + "block.pprof.gz", "components-actual.yaml", "components-expected.yaml", "computed-config.yaml", @@ -47,7 +47,7 @@ var diagnosticsFiles = []string{ "version.txt", } -var unitsDiagnosticsFiles = []string{ +var compDiagnosticsFiles = []string{ "allocs.pprof.gz", "block.pprof.gz", "goroutine.pprof.gz", @@ -56,12 +56,111 @@ var unitsDiagnosticsFiles = []string{ "threadcreate.pprof.gz", } +var componentSetup = map[string]integrationtest.ComponentState{ + "fake-default": { + State: integrationtest.NewClientState(client.Healthy), + Units: map[integrationtest.ComponentUnitKey]integrationtest.ComponentUnitState{ + integrationtest.ComponentUnitKey{UnitType: client.UnitTypeOutput, UnitID: "fake-default"}: { + State: integrationtest.NewClientState(client.Healthy), + }, + integrationtest.ComponentUnitKey{UnitType: client.UnitTypeInput, UnitID: "fake-default-fake"}: { + State: integrationtest.NewClientState(client.Healthy), + }, + }, + }, + "fake-shipper-default": { + State: integrationtest.NewClientState(client.Healthy), + Units: map[integrationtest.ComponentUnitKey]integrationtest.ComponentUnitState{ + integrationtest.ComponentUnitKey{UnitType: client.UnitTypeOutput, UnitID: "fake-shipper-default"}: { + State: integrationtest.NewClientState(client.Healthy), + }, + integrationtest.ComponentUnitKey{UnitType: client.UnitTypeInput, UnitID: "fake-default"}: { + State: integrationtest.NewClientState(client.Healthy), + }, + }, + }, +} + type componentAndUnitNames struct { name string unitNames []string } -func verifyDiagnosticArchive(t *testing.T, diagArchive string, avi *client.Version) { +func TestDiagnosticsOptionalValues(t *testing.T) { + define.Require(t, define.Requirements{ + Local: true, + }) + + fixture, err := define.NewFixture(t, define.Version()) + require.NoError(t, err) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + err = fixture.Prepare(ctx, fakeComponent, fakeShipper) + require.NoError(t, err) + + diagpprof := append(diagnosticsFiles, "cpu.pprof") + diagCompPprof := append(compDiagnosticsFiles, "cpu.pprof") + + err = fixture.Run(ctx, integrationtest.State{ + Configure: simpleConfig2, + AgentState: integrationtest.NewClientState(client.Healthy), + Components: componentSetup, + After: testDiagnosticsFactory(ctx, t, diagpprof, diagCompPprof, fixture, []string{"diagnostics", "-p"}), + }) + +} + +func TestDiagnosticsCommand(t *testing.T) { + define.Require(t, define.Requirements{ + Local: true, + }) + + f, err := define.NewFixture(t, define.Version()) + require.NoError(t, err) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + err = f.Prepare(ctx, fakeComponent, fakeShipper) + require.NoError(t, err) + + ctx, cancel = context.WithCancel(context.Background()) + defer cancel() + + err = f.Run(ctx, integrationtest.State{ + Configure: simpleConfig2, + AgentState: integrationtest.NewClientState(client.Healthy), + Components: componentSetup, + After: testDiagnosticsFactory(ctx, t, diagnosticsFiles, compDiagnosticsFiles, f, []string{"diagnostics", "collect"}), + }) + assert.NoError(t, err) +} + +func testDiagnosticsFactory(ctx context.Context, t *testing.T, diagFiles []string, diagCompFiles []string, fix *integrationtest.Fixture, cmd []string) func() error { + return func() error { + diagnosticCommandWD := t.TempDir() + diagnosticCmdOutput, err := fix.Exec(ctx, cmd, process.WithWorkDir(diagnosticCommandWD)) + + t.Logf("diagnostic command completed with output \n%q\n", diagnosticCmdOutput) + require.NoErrorf(t, err, "error running diagnostic command: %v", err) + + t.Logf("checking directory %q for the generated archive", diagnosticCommandWD) + files, err := filepath.Glob(filepath.Join(diagnosticCommandWD, diagnosticsArchiveGlobPattern)) + require.NoError(t, err) + require.Len(t, files, 1) + t.Logf("Found %q diagnostic archive.", files[0]) + + // get the version of the running agent + avi, err := getRunningAgentVersion(ctx, fix) + require.NoError(t, err) + + verifyDiagnosticArchive(t, files[0], diagFiles, diagCompFiles, avi) + + return nil + } +} + +func verifyDiagnosticArchive(t *testing.T, diagArchive string, diagFiles []string, diagCompFiles []string, avi *client.Version) { // check that the archive is not an empty file stat, err := os.Stat(diagArchive) require.NoErrorf(t, err, "stat file %q failed", diagArchive) @@ -72,7 +171,7 @@ func verifyDiagnosticArchive(t *testing.T, diagArchive string, avi *client.Versi extractZipArchive(t, diagArchive, extractionDir) - expectedDiagArchiveFilePatterns := compileExpectedDiagnosticFilePatterns(avi, []componentAndUnitNames{ + expectedDiagArchiveFilePatterns := compileExpectedDiagnosticFilePatterns(avi, diagFiles, diagCompFiles, []componentAndUnitNames{ { name: "fake-default", unitNames: []string{"fake-default", "fake"}, @@ -116,76 +215,6 @@ func verifyDiagnosticArchive(t *testing.T, diagArchive string, avi *client.Versi assert.ElementsMatch(t, extractKeysFromMap(expectedExtractedFiles), extractKeysFromMap(actualExtractedDiagFiles)) } -func TestDiagnosticsCommand(t *testing.T) { - define.Require(t, define.Requirements{ - Local: true, - }) - - f, err := define.NewFixture(t, define.Version()) - require.NoError(t, err) - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - err = f.Prepare(ctx, fakeComponent, fakeShipper) - require.NoError(t, err) - - ctx, cancel = context.WithCancel(context.Background()) - defer cancel() - - testDiagnostics := func() error { - diagnosticCommandWD := t.TempDir() - diagnosticCmdOutput, err := f.Exec(ctx, []string{"diagnostics", "collect"}, process.WithWorkDir(diagnosticCommandWD)) - - t.Logf("diagnostic command completed with output \n%q\n", diagnosticCmdOutput) - require.NoErrorf(t, err, "error running diagnostic command: %v", err) - - t.Logf("checking directory %q for the generated archive", diagnosticCommandWD) - files, err := filepath.Glob(filepath.Join(diagnosticCommandWD, diagnosticsArchiveGlobPattern)) - require.NoError(t, err) - require.Len(t, files, 1) - t.Logf("Found %q diagnostic archive.", files[0]) - - // get the version of the running agent - avi, err := getRunningAgentVersion(ctx, f) - require.NoError(t, err) - - verifyDiagnosticArchive(t, files[0], avi) - - return nil - } - - err = f.Run(ctx, integrationtest.State{ - Configure: simpleConfig2, - AgentState: integrationtest.NewClientState(client.Healthy), - Components: map[string]integrationtest.ComponentState{ - "fake-default": { - State: integrationtest.NewClientState(client.Healthy), - Units: map[integrationtest.ComponentUnitKey]integrationtest.ComponentUnitState{ - integrationtest.ComponentUnitKey{UnitType: client.UnitTypeOutput, UnitID: "fake-default"}: { - State: integrationtest.NewClientState(client.Healthy), - }, - integrationtest.ComponentUnitKey{UnitType: client.UnitTypeInput, UnitID: "fake-default-fake"}: { - State: integrationtest.NewClientState(client.Healthy), - }, - }, - }, - "fake-shipper-default": { - State: integrationtest.NewClientState(client.Healthy), - Units: map[integrationtest.ComponentUnitKey]integrationtest.ComponentUnitState{ - integrationtest.ComponentUnitKey{UnitType: client.UnitTypeOutput, UnitID: "fake-shipper-default"}: { - State: integrationtest.NewClientState(client.Healthy), - }, - integrationtest.ComponentUnitKey{UnitType: client.UnitTypeInput, UnitID: "fake-default"}: { - State: integrationtest.NewClientState(client.Healthy), - }, - }, - }, - }, - After: testDiagnostics, - }) - assert.NoError(t, err) -} - func extractZipArchive(t *testing.T, zipFile string, dst string) { zReader, err := zip.OpenReader(zipFile) require.NoErrorf(t, err, "file %q is not a valid zip archive", zipFile) @@ -236,10 +265,10 @@ func getRunningAgentVersion(ctx context.Context, f *integrationtest.Fixture) (*c return &avi, err } -func compileExpectedDiagnosticFilePatterns(avi *client.Version, comps []componentAndUnitNames) []filePattern { - files := make([]filePattern, 0, len(diagnosticsFiles)+len(comps)*len(unitsDiagnosticsFiles)) +func compileExpectedDiagnosticFilePatterns(avi *client.Version, diagfiles []string, diagCompFiles []string, comps []componentAndUnitNames) []filePattern { + files := make([]filePattern, 0, len(diagnosticsFiles)+len(comps)*len(compDiagnosticsFiles)) - for _, file := range diagnosticsFiles { + for _, file := range diagfiles { files = append(files, filePattern{ pattern: file, optional: false, @@ -247,15 +276,13 @@ func compileExpectedDiagnosticFilePatterns(avi *client.Version, comps []componen } for _, comp := range comps { - for _, unitName := range comp.unitNames { - unitPath := path.Join("components", comp.name, unitName) - for _, fileName := range unitsDiagnosticsFiles { - files = append(files, - filePattern{ - pattern: path.Join(unitPath, fileName), - optional: false, - }) - } + compPath := path.Join("components", comp.name) + for _, fileName := range diagCompFiles { + files = append(files, + filePattern{ + pattern: path.Join(compPath, fileName), + optional: false, + }) } }