From 4ea5a52cf8c5c881a6ecfcaaae3c4a510e14ba73 Mon Sep 17 00:00:00 2001 From: Zahari Dichev Date: Fri, 23 Jul 2021 11:03:14 +0300 Subject: [PATCH] Add agent commands functionality + flare (#19) This is much of the scafolding needed to support sending commands to the agent. To begin with, we will be sending commands to request diagnostic data about the Linkerd proxy. Signed-off-by: Zahari Dichev --- agent/main.go | 24 +- agent/pkg/api/api.go | 24 +- agent/pkg/api/manage_agent.go | 9 + agent/pkg/api/manage_agent_stream.go | 83 +++ agent/pkg/api/manage_agent_test.go | 79 +++ agent/pkg/api/proxy_diagnostics.go | 33 + agent/pkg/api/proxy_diagnostics_test.go | 81 +++ agent/pkg/api/test_helpers.go | 99 ++- agent/pkg/api/workload.go | 77 +-- agent/pkg/api/workload_stream.go | 99 +++ agent/pkg/api/workload_test.go | 4 +- agent/pkg/handler/event_test.go | 2 +- agent/pkg/handler/manage_agent.go | 102 +++ agent/pkg/handler/workload.go | 8 +- agent/pkg/handler/workload_test.go | 2 +- agent/pkg/k8s/certificates.go | 42 +- agent/pkg/k8s/certificates_test.go | 38 +- agent/pkg/k8s/diagnostics.go | 141 ++++ agent/pkg/k8s/helpers_test.go | 2 +- agent/pkg/k8s/k8s.go | 81 ++- gen/bcloud/buoyant-cloud-api.pb.go | 852 +++++++++++++++++++----- gen/bcloud/buoyant-cloud-api_grpc.pb.go | 99 +++ go.mod | 1 - go.sum | 2 - proto/buoyant-cloud-api.proto | 46 ++ 25 files changed, 1681 insertions(+), 349 deletions(-) create mode 100644 agent/pkg/api/manage_agent.go create mode 100644 agent/pkg/api/manage_agent_stream.go create mode 100644 agent/pkg/api/manage_agent_test.go create mode 100644 agent/pkg/api/proxy_diagnostics.go create mode 100644 agent/pkg/api/proxy_diagnostics_test.go create mode 100644 agent/pkg/api/workload_stream.go create mode 100644 agent/pkg/handler/manage_agent.go create mode 100644 agent/pkg/k8s/diagnostics.go diff --git a/agent/main.go b/agent/main.go index 439913f..927efa8 100644 --- a/agent/main.go +++ b/agent/main.go @@ -13,6 +13,7 @@ import ( "github.com/buoyantio/linkerd-buoyant/agent/pkg/k8s" pb "github.com/buoyantio/linkerd-buoyant/gen/bcloud" "github.com/linkerd/linkerd2/pkg/admin" + l5dk8s "github.com/linkerd/linkerd2/pkg/k8s" log "github.com/sirupsen/logrus" "google.golang.org/grpc" "google.golang.org/grpc/credentials" @@ -41,8 +42,8 @@ func main() { grpcAddr := flag.String("grpc-addr", "api.buoyant.cloud:443", "address of the Buoyant Cloud API") kubeConfigPath := flag.String("kubeconfig", "", "path to kube config") logLevel := flag.String("log-level", "info", "log level, must be one of: panic, fatal, error, warn, info, debug, trace") + localMode := flag.Bool("local-mode", false, "enable port forwarding for local development") insecure := flag.Bool("insecure", false, "disable TLS in development mode") - proxyAddrOverride := flag.String("proxy-addr-override", "", "overrides the proxy address for development mode") // klog flags klog.InitFlags(nil) @@ -93,12 +94,6 @@ func main() { } // setup kubernetes clients and shared informers - - var proxyAddr string - if proxyAddrOverride != nil { - proxyAddr = *proxyAddrOverride - } - rules := clientcmd.NewDefaultClientConfigLoadingRules() if *kubeConfigPath != "" { rules.ExplicitPath = *kubeConfigPath @@ -113,7 +108,13 @@ func main() { dieIf(err) sharedInformers := informers.NewSharedInformerFactory(k8sCS, 10*time.Minute) - k8sClient := k8s.NewClient(sharedInformers, proxyAddr) + var l5dApi *l5dk8s.KubernetesAPI + if *localMode { + l5dApi, err = l5dk8s.NewAPIForConfig(k8sConfig, "", nil, 0) + dieIf(err) + } + + k8sClient := k8s.NewClient(k8sCS, sharedInformers, l5dApi) // wait for discovery API to load @@ -148,16 +149,22 @@ func main() { // create handlers eventHandler := handler.NewEvent(k8sClient, apiClient) workloadHandler := handler.NewWorkload(k8sClient, apiClient) + linkerdInfoHandler := handler.NewLinkerdInfo(k8sClient, apiClient) + manageAgentHandler := handler.NewManageAgent(k8sClient, apiClient) // start shared informer and wait for sync err = k8sClient.Sync(shutdown, 60*time.Second) dieIf(err) + // start api client stream management logic + go apiClient.Start() + // start handlers go eventHandler.Start(sharedInformers) go workloadHandler.Start(sharedInformers) go linkerdInfoHandler.Start() + go manageAgentHandler.Start() // run admin server go admin.StartServer(*adminAddr) @@ -167,5 +174,6 @@ func main() { log.Info("shutting down") workloadHandler.Stop() linkerdInfoHandler.Stop() + manageAgentHandler.Stop() close(shutdown) } diff --git a/agent/pkg/api/api.go b/agent/pkg/api/api.go index bb6a3b5..aa2fc24 100644 --- a/agent/pkg/api/api.go +++ b/agent/pkg/api/api.go @@ -11,8 +11,9 @@ import ( type Client struct { auth *pb.Auth - client pb.ApiClient - stream pb.Api_WorkloadStreamClient + client pb.ApiClient + workloadStream *workloadStream + manageAgentStream *manageAgentStream log *log.Entry @@ -22,12 +23,19 @@ type Client struct { // NewClient instantiates a new Buoyant Cloud API client. func NewClient(id string, key string, client pb.ApiClient) *Client { + auth := &pb.Auth{ + AgentId: id, + AgentKey: key, + } return &Client{ - auth: &pb.Auth{ - AgentId: id, - AgentKey: key, - }, - client: client, - log: log.WithField("api", id), + auth: auth, + workloadStream: newWorkloadStream(auth, client), + manageAgentStream: newManageAgentStream(auth, client), + client: client, + log: log.WithField("api", id), } } + +func (c *Client) Start() { + c.manageAgentStream.startStream() +} diff --git a/agent/pkg/api/manage_agent.go b/agent/pkg/api/manage_agent.go new file mode 100644 index 0000000..8fe01c4 --- /dev/null +++ b/agent/pkg/api/manage_agent.go @@ -0,0 +1,9 @@ +package api + +import ( + pb "github.com/buoyantio/linkerd-buoyant/gen/bcloud" +) + +func (c *Client) AgentCommands() <-chan *pb.AgentCommand { + return c.manageAgentStream.commands +} diff --git a/agent/pkg/api/manage_agent_stream.go b/agent/pkg/api/manage_agent_stream.go new file mode 100644 index 0000000..359a900 --- /dev/null +++ b/agent/pkg/api/manage_agent_stream.go @@ -0,0 +1,83 @@ +package api + +import ( + "context" + "sync" + "time" + + pb "github.com/buoyantio/linkerd-buoyant/gen/bcloud" + log "github.com/sirupsen/logrus" +) + +// manageAgentStream wraps the Buoyant Cloud API ManageAgent gRPC endpoint, and +// manages the stream. +type manageAgentStream struct { + auth *pb.Auth + client pb.ApiClient + stream pb.Api_ManageAgentClient + log *log.Entry + + commands chan *pb.AgentCommand + + // protects stream + sync.Mutex +} + +func newManageAgentStream(auth *pb.Auth, client pb.ApiClient) *manageAgentStream { + return &manageAgentStream{ + auth: auth, + client: client, + log: log.WithField("stream", "ManageAgentStream"), + commands: make(chan *pb.AgentCommand), + } +} + +func (s *manageAgentStream) startStream() { + for { + command, err := s.recvCommand() + if err != nil { + s.log.Infof("stream closed, reseting: %s", err) + s.resetStream() + continue + } + s.commands <- command + } +} + +func (s *manageAgentStream) recvCommand() (*pb.AgentCommand, error) { + s.Lock() + defer s.Unlock() + if s.stream == nil { + s.stream = s.newStream() + } + + return s.stream.Recv() +} + +func (s *manageAgentStream) newStream() pb.Api_ManageAgentClient { + var stream pb.Api_ManageAgentClient + + // loop until the request to initiate a stream succeeds + for { + var err error + stream, err = s.client.ManageAgent(context.Background(), s.auth) + if err != nil { + s.log.Errorf("failed to initiate stream: %s", err) + time.Sleep(100 * time.Millisecond) + continue + } + break + } + + s.log.Info("ManageAgentStream connected") + return stream +} + +func (s *manageAgentStream) resetStream() { + s.Lock() + defer s.Unlock() + if s.stream != nil { + s.stream.CloseSend() + s.stream = nil + } +} diff --git a/agent/pkg/api/manage_agent_test.go b/agent/pkg/api/manage_agent_test.go new file mode 100644 index 0000000..a4bcb4c --- /dev/null +++ b/agent/pkg/api/manage_agent_test.go @@ -0,0 +1,79 @@ +package api + +import ( + "reflect" + "testing" + "time" + + pb "github.com/buoyantio/linkerd-buoyant/gen/bcloud" +) + +func TestManageAgentStream(t *testing.T) { + t.Run("streams and resets", func(t *testing.T) { + fixtures := []*struct { + testName string + commandsFromApi []*pb.AgentCommand + }{ + { + "receives commands", + []*pb.AgentCommand{ + createDiagnosticCommand("id1", "pod1", "ns1"), + createDiagnosticCommand("id2", "pod2", "ns2"), + createDiagnosticCommand("id3", "pod3", "ns3"), + createDiagnosticCommand("id4", "pod4", "ns4"), + createDiagnosticCommand("id5", "pod5", "ns5"), + createDiagnosticCommand("id6", "pod6", "ns6"), + }, + }, + } + + for _, tc := range fixtures { + tc := tc + t.Run(tc.testName, func(t *testing.T) { + m := &MockBcloudClient{agentCommandMessages: tc.commandsFromApi} + c := NewClient("", "", m) + go c.Start() + + receivedCommands := []*pb.AgentCommand{} + + timeout := time.After(time.Second * 10) + + out: + for { + select { + case cmd := <-c.AgentCommands(): + receivedCommands = append(receivedCommands, cmd) + if len(receivedCommands) >= len(tc.commandsFromApi) { + break out + } + case <-timeout: + t.Fatal("test timed out") + } + } + + if len(receivedCommands) != len(tc.commandsFromApi) { + t.Fatalf("Expected to receive %d commands, got: %d", len(tc.commandsFromApi), len(receivedCommands)) + } + + for i, expectedCommand := range tc.commandsFromApi { + actualCommand := receivedCommands[i] + if !reflect.DeepEqual(expectedCommand, actualCommand) { + t.Fatalf("Expected command %d to be %+v, got %+v", i, expectedCommand, actualCommand) + } + } + }) + } + }) +} + +func createDiagnosticCommand(diagnosticID, podName string, podNamespace string) *pb.AgentCommand { + return &pb.AgentCommand{ + Command: &pb.AgentCommand_GetProxyDiagnostics{ + GetProxyDiagnostics: &pb.GetProxyDiagnostics{ + DiagnosticId: diagnosticID, + PodName: podName, + PodNamespace: podNamespace, + }, + }, + } +} diff --git a/agent/pkg/api/proxy_diagnostics.go b/agent/pkg/api/proxy_diagnostics.go new file mode 100644 index 0000000..a80b101 --- /dev/null +++ b/agent/pkg/api/proxy_diagnostics.go @@ -0,0 +1,33 @@ +package api + +import ( + "context" + + pb "github.com/buoyantio/linkerd-buoyant/gen/bcloud" + "google.golang.org/protobuf/encoding/prototext" +) + +// ProxyDiagnostics wraps the Buoyant Cloud API ProxyDiagnostics gRPC unary endpoint. +func (c *Client) ProxyDiagnostics( + diagnosticID string, + logs []byte, + metrics [][]byte, + podManifest *pb.Pod, + linkerdConfigMap *pb.ConfigMap, + nodes []*pb.Node, + k8sServiceManifest *pb.Service) error { + diagnostic := &pb.ProxyDiagnostic{ + Auth: c.auth, + DiagnosticId: diagnosticID, + Logs: logs, + Metrics: metrics, + PodManifest: podManifest, + LinkerdConfigMap: linkerdConfigMap, + Nodes: nodes, + K8SServiceManifest: k8sServiceManifest, + } + c.log.Tracef("ProxyDiagnostics: %s", prototext.Format(diagnostic)) + + _, err := c.client.ProxyDiagnostics(context.Background(), diagnostic) + return err +} diff --git a/agent/pkg/api/proxy_diagnostics_test.go b/agent/pkg/api/proxy_diagnostics_test.go new file mode 100644 index 0000000..0e993ea --- /dev/null +++ b/agent/pkg/api/proxy_diagnostics_test.go @@ -0,0 +1,81 @@ +package api + +import ( + "errors" + "testing" + + pb "github.com/buoyantio/linkerd-buoyant/gen/bcloud" +) + +func TestProxyDiagnostic(t *testing.T) { + t.Run("calls the api and gets a response", func(t *testing.T) { + fixtures := []*struct { + testName string + diagnosticId string + logs []byte + metrics [][]byte + podManifest *pb.Pod + configMap *pb.ConfigMap + nodes []*pb.Node + k8sSvcManifest *pb.Service + err error + }{ + { + "bad API response", + "diagnosticId", + []byte("logs"), + [][]byte{[]byte("snapshot1"), []byte("snapshot2")}, + &pb.Pod{Pod: []byte("pod")}, + &pb.ConfigMap{ConfigMap: []byte("cm")}, + []*pb.Node{{Node: []byte("node1")}, {Node: []byte("node2")}}, + &pb.Service{Service: []byte("svc")}, + errors.New("bad response"), + }, + { + "ok rsp", + "diagnosticId", + []byte("logs"), + [][]byte{[]byte("snapshot1"), []byte("snapshot2")}, + &pb.Pod{Pod: []byte("pod")}, + &pb.ConfigMap{ConfigMap: []byte("cm")}, + []*pb.Node{{Node: []byte("node1")}, {Node: []byte("node2")}}, + &pb.Service{Service: []byte("svc")}, + nil, + }, + } + + for _, tc := range fixtures { + tc := tc + t.Run(tc.testName, func(t *testing.T) { + m := &MockBcloudClient{err: tc.err} + c := NewClient("", "", m) + + err := c.ProxyDiagnostics(tc.diagnosticId, tc.logs, tc.metrics, tc.podManifest, tc.configMap, tc.nodes, tc.k8sSvcManifest) + if tc.err != err { + t.Errorf("Expected %s, got %s", tc.err, err) + } + + if len(m.ProxyDiagnosticMessages()) != 1 { + t.Errorf("Expected 1 message, got %d", len(m.ProxyDiagnosticMessages())) + } + }) + } + }) + + t.Run("sets auth info", func(t *testing.T) { + m := &MockBcloudClient{} + c := NewClient(fakeID, fakeKey, m) + + err := c.ProxyDiagnostics("id1", nil, nil, nil, nil, nil, nil) + if err != nil { + t.Error(err) + } + + if m.id != fakeID { + t.Errorf("Expected %s, got %s", fakeID, m.id) + } + if m.key != fakeKey { + t.Errorf("Expected %s, got %s", fakeKey, m.key) + } + }) +} diff --git a/agent/pkg/api/test_helpers.go b/agent/pkg/api/test_helpers.go index ca01efd..6922eb6 100644 --- a/agent/pkg/api/test_helpers.go +++ b/agent/pkg/api/test_helpers.go @@ -2,6 +2,7 @@ package api import ( "context" + "fmt" "sync" pb "github.com/buoyantio/linkerd-buoyant/gen/bcloud" @@ -14,6 +15,36 @@ const ( fakeKey = "fake-key" ) +type MockAPI_ManageAgentClient struct { + agentCommandMessages []*pb.AgentCommand + grpc.ClientStream + + // protects state + sync.Mutex +} + +func (c *MockAPI_ManageAgentClient) Recv() (*pb.AgentCommand, error) { + c.Lock() + defer c.Unlock() + + if len(c.agentCommandMessages) == 0 { + return nil, fmt.Errorf("no more messages") + } + + command := c.agentCommandMessages[0] + if len(c.agentCommandMessages) > 1 { + c.agentCommandMessages = c.agentCommandMessages[1:] + } else { + c.agentCommandMessages = make([]*pb.AgentCommand, 0) + } + + return command, nil +} + +func (c *MockAPI_ManageAgentClient) CloseSend() error { + return nil // noop +} + // MockBcloudClient satisfies the bcloud.ApiClient and // bcloud.Api_WorkloadStreamClient interfaces, and saves all params and messages // passed to it. @@ -22,11 +53,16 @@ type MockBcloudClient struct { err error // output - id string - key string - messages []*pb.WorkloadMessage - events []*pb.Event - linkerdMessages []*pb.LinkerdMessage + id string + key string + messages []*pb.WorkloadMessage + events []*pb.Event + linkerdMessages []*pb.LinkerdMessage + proxyDiagnosticMessages []*pb.ProxyDiagnostic + proxyDiagnosticAuth *pb.Auth + + // simulates commands received from bcloud-api + agentCommandMessages []*pb.AgentCommand // protects messages and events sync.Mutex @@ -39,37 +75,31 @@ type MockBcloudClient struct { func (m *MockBcloudClient) Events() []*pb.Event { m.Lock() defer m.Unlock() - - events := make([]*pb.Event, len(m.events)) - for i, e := range m.events { - events[i] = e - } - - return events + return m.events } func (m *MockBcloudClient) Messages() []*pb.WorkloadMessage { m.Lock() defer m.Unlock() - - messages := make([]*pb.WorkloadMessage, len(m.messages)) - for i, m := range m.messages { - messages[i] = m - } - - return messages + return m.messages } func (m *MockBcloudClient) LinkerdMessages() []*pb.LinkerdMessage { m.Lock() defer m.Unlock() + return m.linkerdMessages +} - messages := make([]*pb.LinkerdMessage, len(m.linkerdMessages)) - for i, m := range m.linkerdMessages { - messages[i] = m - } +func (m *MockBcloudClient) ProxyDiagnosticMessages() []*pb.ProxyDiagnostic { + m.Lock() + defer m.Unlock() + return m.proxyDiagnosticMessages +} - return messages +func (m *MockBcloudClient) ProxyDiagnosticsAuth() *pb.Auth { + m.Lock() + defer m.Unlock() + return m.proxyDiagnosticAuth } // @@ -106,6 +136,27 @@ func (m *MockBcloudClient) LinkerdInfo( return nil, m.err } +func (m *MockBcloudClient) ManageAgent( + ctx context.Context, auth *pb.Auth, opts ...grpc.CallOption) (pb.Api_ManageAgentClient, error) { + m.Lock() + defer m.Unlock() + m.proxyDiagnosticAuth = auth + stream := &MockAPI_ManageAgentClient{ + agentCommandMessages: m.agentCommandMessages, + } + return stream, nil +} + +func (m *MockBcloudClient) ProxyDiagnostics(ctx context.Context, message *pb.ProxyDiagnostic, opts ...grpc.CallOption) (*pb.Empty, error) { + m.Lock() + defer m.Unlock() + + m.id = message.GetAuth().GetAgentId() + m.key = message.GetAuth().GetAgentKey() + m.proxyDiagnosticMessages = append(m.proxyDiagnosticMessages, message) + return nil, m.err +} + // // bcloud.Api_WorkloadStreamClient methods // diff --git a/agent/pkg/api/workload.go b/agent/pkg/api/workload.go index 8bde724..9fb67ed 100644 --- a/agent/pkg/api/workload.go +++ b/agent/pkg/api/workload.go @@ -1,79 +1,12 @@ package api import ( - "context" - "io" - "time" - pb "github.com/buoyantio/linkerd-buoyant/gen/bcloud" ) -// WorkloadStream wraps the Buoyant Cloud API WorkloadStream gRPC endpoint, and -// manages the client-side stream. -func (c *Client) WorkloadStream(msg *pb.WorkloadMessage) error { - // loop and reset the stream if it has been closed - for { - err := c.sendMessage(msg) - if err == io.EOF { - c.log.Info("WorkloadStream closed") - c.resetStream() - continue - } else if err != nil { - c.log.Errorf("WorkloadStream failed to send: %s", err) - } - - return err - } -} - -func (c *Client) sendMessage(msg *pb.WorkloadMessage) error { - c.Lock() - defer c.Unlock() - if c.stream == nil { - c.stream = c.newStream() - } - - return c.stream.Send(msg) -} - -func (c *Client) newStream() pb.Api_WorkloadStreamClient { - var stream pb.Api_WorkloadStreamClient - - // loop until the request to initiate a stream succeeds - for { - var err error - stream, err = c.client.WorkloadStream(context.Background()) - if err != nil { - c.log.Errorf("failed to initiate stream: %s", err) - time.Sleep(100 * time.Millisecond) - continue - } - - c.log.Info("WorkloadStream opened") - - err = stream.Send(&pb.WorkloadMessage{ - Message: &pb.WorkloadMessage_Auth{ - Auth: c.auth, - }, - }) - if err != nil { - c.log.Errorf("failed to send auth message: %s", err) - time.Sleep(100 * time.Millisecond) - continue - } - - break - } - - c.log.Info("WorkloadStream connected") - return stream -} - -func (c *Client) resetStream() { - c.Lock() - defer c.Unlock() - if c.stream != nil { - c.stream.CloseSend() - c.stream = nil - } +// SendWorkloadMessage sends a message via the Buoyant Cloud API WorkloadStream gRPC +// endpoint. It abstracts away the details around managing and protecting +// the client-side stream +func (c *Client) SendWorkloadMessage(msg *pb.WorkloadMessage) error { + return c.workloadStream.send(msg) } diff --git a/agent/pkg/api/workload_stream.go b/agent/pkg/api/workload_stream.go new file mode 100644 index 0000000..e8a1915 --- /dev/null +++ b/agent/pkg/api/workload_stream.go @@ -0,0 +1,99 @@ +package api + +import ( + "context" + "io" + "sync" + "time" + + pb "github.com/buoyantio/linkerd-buoyant/gen/bcloud" + log "github.com/sirupsen/logrus" +) + +// WorkloadStream wraps the Buoyant Cloud API WorkloadStream gRPC endpoint, and +// manages the client-side stream. +type workloadStream struct { + auth *pb.Auth + client pb.ApiClient + stream pb.Api_WorkloadStreamClient + log *log.Entry + + // protects stream + sync.Mutex +} + +func newWorkloadStream(auth *pb.Auth, client pb.ApiClient) *workloadStream { + return &workloadStream{ + auth: auth, + client: client, + log: log.WithField("stream", "WorkloadStream"), + } +} + +func (s *workloadStream) send(msg *pb.WorkloadMessage) error { + // loop and reset the stream if it has been closed + for { + err := s.sendMessage(msg) + if err == io.EOF { + s.log.Info("WorkloadStream closed") + s.resetStream() + continue + } else if err != nil { + s.log.Errorf("WorkloadStream failed to send: %s", err) + } + + return err + } +} + +func (s *workloadStream) sendMessage(msg *pb.WorkloadMessage) error { + s.Lock() + defer s.Unlock() + if s.stream == nil { + s.stream = s.newStream() + } + + return s.stream.Send(msg) +} + +func (s *workloadStream) newStream() pb.Api_WorkloadStreamClient { + var stream pb.Api_WorkloadStreamClient + + // loop until the request to initiate a stream succeeds + for { + var err error + stream, err = s.client.WorkloadStream(context.Background()) + if err != nil { + s.log.Errorf("failed to initiate stream: %s", err) + time.Sleep(100 * time.Millisecond) + continue + } + + s.log.Info("WorkloadStream opened") + + err = stream.Send(&pb.WorkloadMessage{ + Message: &pb.WorkloadMessage_Auth{ + Auth: s.auth, + }, + }) + if err != nil { + s.log.Errorf("failed to send auth message: %s", err) + time.Sleep(100 * time.Millisecond) + continue + } + + break + } + + s.log.Info("WorkloadStream connected") + return stream +} + +func (s *workloadStream) resetStream() { + s.Lock() + defer s.Unlock() + if s.stream != nil { + s.stream.CloseSend() + s.stream = nil + } +} diff --git a/agent/pkg/api/workload_test.go b/agent/pkg/api/workload_test.go index abbb875..3fa774b 100644 --- a/agent/pkg/api/workload_test.go +++ b/agent/pkg/api/workload_test.go @@ -37,7 +37,7 @@ func TestWorkloadStream(t *testing.T) { c := NewClient("", "", m) for _, msg := range tc.msgs { - err := c.WorkloadStream(msg) + err := c.SendWorkloadMessage(msg) if err != nil { t.Error(err) } @@ -78,7 +78,7 @@ func TestWorkloadStream(t *testing.T) { c := NewClient(fakeID, fakeKey, m) for _, msg := range tc.msgs { - err := c.WorkloadStream(msg) + err := c.SendWorkloadMessage(msg) if err != nil { t.Error(err) } diff --git a/agent/pkg/handler/event_test.go b/agent/pkg/handler/event_test.go index dd02e7e..d5c4540 100644 --- a/agent/pkg/handler/event_test.go +++ b/agent/pkg/handler/event_test.go @@ -130,7 +130,7 @@ func TestEvent(t *testing.T) { t.Run(tc.testName, func(t *testing.T) { cs := fake.NewSimpleClientset(tc.objs...) sharedInformers := informers.NewSharedInformerFactory(cs, 10*time.Minute) - k8sClient := k8s.NewClient(sharedInformers, "") + k8sClient := k8s.NewClient(cs, sharedInformers, nil) m := &api.MockBcloudClient{} apiClient := api.NewClient("", "", m) diff --git a/agent/pkg/handler/manage_agent.go b/agent/pkg/handler/manage_agent.go new file mode 100644 index 0000000..8425dae --- /dev/null +++ b/agent/pkg/handler/manage_agent.go @@ -0,0 +1,102 @@ +package handler + +import ( + "context" + + "github.com/buoyantio/linkerd-buoyant/agent/pkg/api" + "github.com/buoyantio/linkerd-buoyant/agent/pkg/k8s" + pb "github.com/buoyantio/linkerd-buoyant/gen/bcloud" + log "github.com/sirupsen/logrus" +) + +type ManageAgent struct { + api *api.Client + k8s *k8s.Client + log *log.Entry + stopCh chan struct{} +} + +// NewManageAgent instantiates a new agent commands handler +func NewManageAgent(k8sClient *k8s.Client, apiClient *api.Client) *ManageAgent { + log := log.WithField("handler", "manage_agent") + log.Debug("initializing") + + return &ManageAgent{ + api: apiClient, + k8s: k8sClient, + log: log, + stopCh: make(chan struct{}), + } +} + +// Start initiates ManageAgent handler +func (h *ManageAgent) Start() { + h.log.Info("Starting manage agent handler") + for { + select { + case <-h.stopCh: + return + case agentCommand := <-h.api.AgentCommands(): + switch command := agentCommand.Command.(type) { + case *pb.AgentCommand_GetProxyDiagnostics: + proxyDiagnostic := command.GetProxyDiagnostics + go h.handleProxyDiagnostics(context.Background(), proxyDiagnostic.PodName, proxyDiagnostic.PodNamespace, proxyDiagnostic.DiagnosticId) + } + } + } +} + +// Stop terminates the handler. +func (h *ManageAgent) Stop() { + h.log.Info("shutting down") + close(h.stopCh) +} + +func (h *ManageAgent) handleProxyDiagnostics(ctx context.Context, podName, namespace, diagnosticID string) { + logs, err := h.k8s.GetProxyLogs(ctx, podName, namespace) + if err != nil { + h.log.Errorf("cannot obtain proxy logs for diagnosticID %s: %s", diagnosticID, err) + } else { + h.log.Debugf("Successfully obtained proxy logs for diagnosticID: %s", diagnosticID) + } + + podSpec, err := h.k8s.GetPodSpec(ctx, podName, namespace) + if err != nil { + h.log.Errorf("cannot obtain pod manifest for diagnosticID %s: %s", diagnosticID, err) + } else { + h.log.Debugf("Successfully obtained pod manifest for diagnosticID: %s", diagnosticID) + } + + metrics, err := h.k8s.GetPrometheusScrape(ctx, podName, namespace) + if err != nil { + h.log.Errorf("cannot obtain proxy metrics for diagnosticID %s: %s", diagnosticID, err) + } else { + h.log.Debugf("Successfully obtained proxy metrics for diagnosticID: %s", diagnosticID) + } + + l5dConfigMap, err := h.k8s.GetLinkerdConfigMap(ctx) + if err != nil { + h.log.Errorf("cannot Linkerd config map for diagnosticID %s: %s", diagnosticID, err) + } else { + h.log.Debugf("Successfully obtained Linkerd config map for for diagnosticID: %s", diagnosticID) + } + + nodes, err := h.k8s.GetNodeManifests(ctx) + if err != nil { + h.log.Errorf("cannot obtain nodes for diagnosticID %s: %s", diagnosticID, err) + } else { + h.log.Debugf("Successfully obtained nodes for diagnosticID: %s", diagnosticID) + } + + svcManifest, err := h.k8s.GetK8sServiceManifest(ctx) + if err != nil { + h.log.Errorf("cannot obtain K8s svc manifest for diagnosticID %s: %s", diagnosticID, err) + } else { + h.log.Debugf("Successfully obtained K8s svc manifest for diagnosticID: %s", diagnosticID) + } + + err = h.api.ProxyDiagnostics(diagnosticID, logs, metrics, podSpec, l5dConfigMap, nodes, svcManifest) + if err != nil { + h.log.Errorf("error sending ProxyDiagnostics message: %s", err) + } +} diff --git a/agent/pkg/handler/workload.go b/agent/pkg/handler/workload.go index 9d99fa0..12b992d 100644 --- a/agent/pkg/handler/workload.go +++ b/agent/pkg/handler/workload.go @@ -212,7 +212,7 @@ func (h *Workload) handleAdd(workload *pb.Workload) { } h.log.Tracef("handleAdd: %s", prototext.Format(m)) - err := h.api.WorkloadStream(m) + err := h.api.SendWorkloadMessage(m) if err != nil { h.log.Errorf("error sending add message: %s", err) } @@ -234,7 +234,7 @@ func (h *Workload) handleUpdate(oldWorkload *pb.Workload, newWorkload *pb.Worklo } h.log.Tracef("handleUpdate: %s", prototext.Format(m)) - err := h.api.WorkloadStream(m) + err := h.api.SendWorkloadMessage(m) if err != nil { h.log.Errorf("error sending update message: %s", err) } @@ -249,7 +249,7 @@ func (h *Workload) handleDelete(workload *pb.Workload) { h.log.Tracef("handleDelete: %s", prototext.Format(m)) - err := h.api.WorkloadStream(m) + err := h.api.SendWorkloadMessage(m) if err != nil { h.log.Errorf("error sending delete message: %s", err) } @@ -269,7 +269,7 @@ func (h *Workload) handleWorkloadList() { } h.log.Tracef("handleWorkloadList: %s", prototext.Format(m)) - err = h.api.WorkloadStream(m) + err = h.api.SendWorkloadMessage(m) if err != nil { h.log.Errorf("error sending list message: %s", err) } diff --git a/agent/pkg/handler/workload_test.go b/agent/pkg/handler/workload_test.go index dd1484a..20a4d43 100644 --- a/agent/pkg/handler/workload_test.go +++ b/agent/pkg/handler/workload_test.go @@ -172,7 +172,7 @@ func TestWorkloadStream(t *testing.T) { } cs := fake.NewSimpleClientset(objs...) sharedInformers := informers.NewSharedInformerFactory(cs, 10*time.Minute) - k8sClient := k8s.NewClient(sharedInformers, "") + k8sClient := k8s.NewClient(cs, sharedInformers, nil) m := &api.MockBcloudClient{} apiClient := api.NewClient("", "", m) diff --git a/agent/pkg/k8s/certificates.go b/agent/pkg/k8s/certificates.go index 8ecac2e..fc31136 100644 --- a/agent/pkg/k8s/certificates.go +++ b/agent/pkg/k8s/certificates.go @@ -8,7 +8,7 @@ import ( pb "github.com/buoyantio/linkerd-buoyant/gen/bcloud" "github.com/linkerd/linkerd2/pkg/identity" - ldConsts "github.com/linkerd/linkerd2/pkg/k8s" + l5dk8s "github.com/linkerd/linkerd2/pkg/k8s" ldTls "github.com/linkerd/linkerd2/pkg/tls" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/labels" @@ -36,7 +36,7 @@ func (c *Client) GetControlPlaneCerts() (*pb.ControlPlaneCerts, error) { return nil, err } - issuerCerts, err := extractIssuerCertChain(identityPod, container, c.proxyAddrOverride) + issuerCerts, err := c.extractIssuerCertChain(identityPod, container) if err != nil { return nil, err } @@ -51,7 +51,7 @@ func (c *Client) GetControlPlaneCerts() (*pb.ControlPlaneCerts, error) { func (c *Client) getControlPlaneComponentPod(component string) (*v1.Pod, error) { selector := labels.Set(map[string]string{ - ldConsts.ControllerComponentLabel: component, + l5dk8s.ControllerComponentLabel: component, }).AsSelector() pods, err := c.podLister.List(selector) @@ -73,27 +73,6 @@ func (c *Client) getControlPlaneComponentPod(component string) (*v1.Pod, error) return nil, fmt.Errorf("could not find running pod for linkerd-%s", component) } -func getProxyContainer(pod *v1.Pod) (*v1.Container, error) { - for _, c := range pod.Spec.Containers { - if c.Name == ldConsts.ProxyContainerName { - container := c - return &container, nil - } - } - - return nil, fmt.Errorf("could not find proxy container in pod %s/%s", pod.Namespace, pod.Name) -} - -func getProxyAdminPort(container *v1.Container) (int32, error) { - for _, p := range container.Ports { - if p.Name == ldConsts.ProxyAdminPortName { - return p.ContainerPort, nil - } - } - - return 0, fmt.Errorf("could not find port %s on proxy container [%s]", ldConsts.ProxyAdminPortName, container.Name) -} - func getServerName(podsa string, podns string, container *v1.Container) (string, error) { var l5dns string var l5dtrustdomain string @@ -137,26 +116,23 @@ func extractRootsCerts(container *v1.Container) ([]*pb.CertData, error) { return nil, fmt.Errorf("could not find env var with name %s on proxy container [%s]", identity.EnvTrustAnchors, container.Name) } -func extractIssuerCertChain(pod *v1.Pod, container *v1.Container, proxyAddrOverride string) ([]*pb.CertData, error) { - port, err := getProxyAdminPort(container) +func (c *Client) extractIssuerCertChain(pod *v1.Pod, container *v1.Container) ([]*pb.CertData, error) { + sn, err := getServerName(pod.Spec.ServiceAccountName, pod.ObjectMeta.Namespace, container) if err != nil { return nil, err } - sn, err := getServerName(pod.Spec.ServiceAccountName, pod.ObjectMeta.Namespace, container) + proxyConnection, err := c.getContainerConnection(pod, container, l5dk8s.ProxyAdminPortName) if err != nil { return nil, err } - - podAddr := pod.Status.PodIP - if proxyAddrOverride != "" { - podAddr = proxyAddrOverride - } + defer proxyConnection.cleanup() conn, err := tls.DialWithDialer( &net.Dialer{Timeout: 5 * time.Second}, "tcp", - fmt.Sprintf("%s:%d", podAddr, port), &tls.Config{ + proxyConnection.host, + &tls.Config{ // we want to subvert TLS verification as we do not need // to verify that we actually trust these certs. We just // want the certificates and are not sending any data here. diff --git a/agent/pkg/k8s/certificates_test.go b/agent/pkg/k8s/certificates_test.go index ff40c3f..0712db1 100644 --- a/agent/pkg/k8s/certificates_test.go +++ b/agent/pkg/k8s/certificates_test.go @@ -8,7 +8,7 @@ import ( "time" "github.com/linkerd/linkerd2/pkg/identity" - ldConsts "github.com/linkerd/linkerd2/pkg/k8s" + l5dk8s "github.com/linkerd/linkerd2/pkg/k8s" ldTls "github.com/linkerd/linkerd2/pkg/tls" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -29,7 +29,7 @@ func TestFindIdentityPod(t *testing.T) { Name: "linkerd-identity", Namespace: "linkerd", Labels: map[string]string{ - ldConsts.ControllerComponentLabel: identityComponentName, + l5dk8s.ControllerComponentLabel: identityComponentName, }, }, Status: v1.PodStatus{ @@ -53,7 +53,7 @@ func TestFindIdentityPod(t *testing.T) { Name: "linkerd-identity", Namespace: "linkerd", Labels: map[string]string{ - ldConsts.ControllerComponentLabel: identityComponentName, + l5dk8s.ControllerComponentLabel: identityComponentName, }, }, Status: v1.PodStatus{ @@ -88,7 +88,7 @@ func TestFindIdentityPod(t *testing.T) { t.Run(tc.testName, func(t *testing.T) { c := fakeClient(tc.pods...) c.Sync(nil, time.Second) - client := NewClient(c.sharedInformers, "") + client := NewClient(nil, c.sharedInformers, nil) pod, err := client.getControlPlaneComponentPod(identityComponentName) if tc.expectedErr != nil { @@ -120,7 +120,7 @@ func TestGetProxyContainer(t *testing.T) { Spec: v1.PodSpec{ Containers: []v1.Container{ { - Name: ldConsts.ProxyContainerName, + Name: l5dk8s.ProxyContainerName, }, { Name: "some-other-container", @@ -158,8 +158,8 @@ func TestGetProxyContainer(t *testing.T) { t.Fatalf("exepected err %s, got %s", tc.expectedErr, err) } } else { - if container.Name != ldConsts.ProxyContainerName { - t.Fatalf("exepected container with name %s, got %s", ldConsts.ProxyContainerName, container.Name) + if container.Name != l5dk8s.ProxyContainerName { + t.Fatalf("exepected container with name %s, got %s", l5dk8s.ProxyContainerName, container.Name) } } }) @@ -176,10 +176,10 @@ func TestGetAdminPort(t *testing.T) { { "container with admin port", &v1.Container{ - Name: ldConsts.ProxyContainerName, + Name: l5dk8s.ProxyContainerName, Ports: []v1.ContainerPort{ { - Name: ldConsts.ProxyAdminPortName, + Name: l5dk8s.ProxyAdminPortName, ContainerPort: 555, }, { @@ -194,7 +194,7 @@ func TestGetAdminPort(t *testing.T) { { "container without admin port", &v1.Container{ - Name: ldConsts.ProxyContainerName, + Name: l5dk8s.ProxyContainerName, Ports: []v1.ContainerPort{ { Name: "another port", @@ -203,14 +203,14 @@ func TestGetAdminPort(t *testing.T) { }, }, 0, - fmt.Errorf("could not find port linkerd-admin on proxy container [linkerd-proxy]"), + fmt.Errorf("could not find port linkerd-admin on container [linkerd-proxy]"), }, } for _, tc := range fixtures { tc := tc t.Run(tc.testName, func(t *testing.T) { - port, err := getProxyAdminPort(tc.container) + port, err := getContainerPort(tc.container, l5dk8s.ProxyAdminPortName) if tc.expectedErr != nil { if tc.expectedErr.Error() != err.Error() { t.Fatalf("exepected err %s, got %s", tc.expectedErr, err) @@ -237,7 +237,7 @@ func TestGetServerName(t *testing.T) { { "gets correct name", &v1.Container{ - Name: ldConsts.ProxyContainerName, + Name: l5dk8s.ProxyContainerName, Env: []v1.EnvVar{ { Name: linkerdNsEnvVarName, @@ -255,7 +255,7 @@ func TestGetServerName(t *testing.T) { { "missing ns env var", &v1.Container{ - Name: ldConsts.ProxyContainerName, + Name: l5dk8s.ProxyContainerName, Env: []v1.EnvVar{ { Name: linkerdTrustDomainEnvVarName, @@ -264,12 +264,12 @@ func TestGetServerName(t *testing.T) { }, }, "", - fmt.Errorf("could not find %s env var on proxy container [%s]", linkerdNsEnvVarName, ldConsts.ProxyContainerName), + fmt.Errorf("could not find %s env var on proxy container [%s]", linkerdNsEnvVarName, l5dk8s.ProxyContainerName), }, { "missing trust domain env var", &v1.Container{ - Name: ldConsts.ProxyContainerName, + Name: l5dk8s.ProxyContainerName, Env: []v1.EnvVar{ { Name: linkerdNsEnvVarName, @@ -278,7 +278,7 @@ func TestGetServerName(t *testing.T) { }, }, "", - fmt.Errorf("could not find %s env var on proxy container [%s]", linkerdTrustDomainEnvVarName, ldConsts.ProxyContainerName), + fmt.Errorf("could not find %s env var on proxy container [%s]", linkerdTrustDomainEnvVarName, l5dk8s.ProxyContainerName), }, } @@ -323,7 +323,7 @@ AiAtuoI5XuCtrGVRzSmRTl2ra28aV9MyTU7d5qnTAFHKSgIgRKCvluOSgA5O21p5 { "gets correct cert", &v1.Container{ - Name: ldConsts.ProxyContainerName, + Name: l5dk8s.ProxyContainerName, Env: []v1.EnvVar{ { Name: identity.EnvTrustAnchors, @@ -337,7 +337,7 @@ AiAtuoI5XuCtrGVRzSmRTl2ra28aV9MyTU7d5qnTAFHKSgIgRKCvluOSgA5O21p5 { "no roots", &v1.Container{ - Name: ldConsts.ProxyContainerName, + Name: l5dk8s.ProxyContainerName, Env: []v1.EnvVar{}, }, "", diff --git a/agent/pkg/k8s/diagnostics.go b/agent/pkg/k8s/diagnostics.go new file mode 100644 index 0000000..f01d899 --- /dev/null +++ b/agent/pkg/k8s/diagnostics.go @@ -0,0 +1,141 @@ +package k8s + +import ( + "bytes" + "context" + "fmt" + "io" + "io/ioutil" + "net/http" + "time" + + pb "github.com/buoyantio/linkerd-buoyant/gen/bcloud" + l5dk8s "github.com/linkerd/linkerd2/pkg/k8s" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const linkerdNamespace = "linkerd" +const k8sServiceName = "kubernetes" + +// GetProxyLogs retrieves the proxy logs of a pod +func (c *Client) GetProxyLogs(ctx context.Context, podName, namespace string) ([]byte, error) { + req := c.k8sClient.CoreV1().Pods(namespace).GetLogs(podName, &v1.PodLogOptions{Container: l5dk8s.ProxyContainerName}) + logs, err := req.Stream(ctx) + if err != nil { + return nil, err + } + defer logs.Close() + + buf := new(bytes.Buffer) + _, err = io.Copy(buf, logs) + if err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +// GetPrometheusScrape retrieves the raw prom scrape from the proxy of a pod +func (c *Client) GetPrometheusScrape(ctx context.Context, podName, namespace string) ([][]byte, error) { + // first get the pod + pod, err := c.k8sClient.CoreV1().Pods(namespace).Get(ctx, podName, metav1.GetOptions{}) + if err != nil { + return nil, err + } + + if pod.Status.Phase != v1.PodRunning { + return nil, fmt.Errorf("pod not running: %s/%s", namespace, podName) + } + + if pod.Status.PodIP == "" { + return nil, fmt.Errorf("pod IP not allocated: %s/%s", namespace, podName) + } + + proxyContainer, err := getProxyContainer(pod) + if err != nil { + return nil, err + } + + proxyConnection, err := c.getContainerConnection(pod, proxyContainer, l5dk8s.ProxyAdminPortName) + if err != nil { + return nil, err + } + defer proxyConnection.cleanup() + + metricsUrl := fmt.Sprintf("http://%s/metrics", proxyConnection.host) + data := [][]byte{} + for { + resp, err := http.Get(metricsUrl) + if err != nil { + return nil, err + } + + sample, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + resp.Body.Close() + data = append(data, sample) + if len(data) == 6 { + break + } + time.Sleep(time.Second * 10) + } + + return data, nil +} + +// GetPodSpec retrieves pod manifest +func (c *Client) GetPodSpec(ctx context.Context, podName, namespace string) (*pb.Pod, error) { + pod, err := c.k8sClient.CoreV1().Pods(namespace).Get(ctx, podName, metav1.GetOptions{}) + if err != nil { + return nil, err + } + + return &pb.Pod{Pod: c.serialize(pod, v1.SchemeGroupVersion)}, nil +} + +// GetLinkerdConfigMap retrieves Linkerd config map +func (c *Client) GetLinkerdConfigMap(ctx context.Context) (*pb.ConfigMap, error) { + cm, err := c.k8sClient.CoreV1().ConfigMaps(linkerdNamespace).Get(ctx, l5dk8s.ConfigConfigMapName, metav1.GetOptions{}) + if err != nil { + return nil, err + } + + return &pb.ConfigMap{ConfigMap: c.serialize(cm, v1.SchemeGroupVersion)}, nil +} + +// GetNodeManifests retrieves all nodes in the cluster +func (c *Client) GetNodeManifests(ctx context.Context) ([]*pb.Node, error) { + nodes, err := c.k8sClient.CoreV1().Nodes().List(ctx, metav1.ListOptions{}) + if err != nil { + return nil, err + } + + data := make([]*pb.Node, len(nodes.Items)) + for i, node := range nodes.Items { + data[i] = &pb.Node{Node: c.serialize(&node, v1.SchemeGroupVersion)} + } + + return data, nil +} + +// GetK8sServiceManifest the manifest of the kubernetes service residing in the default namespace +func (c *Client) GetK8sServiceManifest(ctx context.Context) (*pb.Service, error) { + svc, err := c.k8sClient.CoreV1().Services(v1.NamespaceDefault).Get(ctx, k8sServiceName, metav1.GetOptions{}) + if err != nil { + return nil, err + } + return &pb.Service{Service: c.serialize(svc, v1.SchemeGroupVersion)}, nil +} + +func getProxyContainer(pod *v1.Pod) (*v1.Container, error) { + for _, c := range pod.Spec.Containers { + if c.Name == l5dk8s.ProxyContainerName { + container := c + return &container, nil + } + } + + return nil, fmt.Errorf("could not find proxy container in pod %s/%s", pod.Namespace, pod.Name) +} diff --git a/agent/pkg/k8s/helpers_test.go b/agent/pkg/k8s/helpers_test.go index 8979a86..dfb72be 100644 --- a/agent/pkg/k8s/helpers_test.go +++ b/agent/pkg/k8s/helpers_test.go @@ -11,5 +11,5 @@ import ( func fakeClient(objects ...runtime.Object) *Client { cs := fake.NewSimpleClientset(objects...) sharedInformers := informers.NewSharedInformerFactory(cs, 10*time.Minute) - return NewClient(sharedInformers, "") + return NewClient(cs, sharedInformers, nil) } diff --git a/agent/pkg/k8s/k8s.go b/agent/pkg/k8s/k8s.go index c0229d1..ad7cdee 100644 --- a/agent/pkg/k8s/k8s.go +++ b/agent/pkg/k8s/k8s.go @@ -3,8 +3,11 @@ package k8s import ( "context" "errors" + "fmt" + "net/url" "time" + l5dk8s "github.com/linkerd/linkerd2/pkg/k8s" log "github.com/sirupsen/logrus" appsv1 "k8s.io/api/apps/v1" v1 "k8s.io/api/core/v1" @@ -12,6 +15,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/serializer/protobuf" "k8s.io/client-go/informers" corev1informers "k8s.io/client-go/informers/core/v1" + "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/scheme" appsv1listers "k8s.io/client-go/listers/apps/v1" corev1listers "k8s.io/client-go/listers/core/v1" @@ -19,6 +23,11 @@ import ( ) type Client struct { + k8sClient kubernetes.Interface + // the presence of the L5D k8s api signifies that we are running in local mode + // and that we should use it for port forwarding + l5dApi *l5dk8s.KubernetesAPI + encoders map[runtime.GroupVersioner]runtime.Encoder sharedInformers informers.SharedInformerFactory @@ -38,11 +47,14 @@ type Client struct { eventInformer corev1informers.EventInformer eventSynced cache.InformerSynced - proxyAddrOverride string - log *log.Entry } +type containerConnection struct { + host string + cleanup func() +} + const ( DaemonSet = "DaemonSet" Deployment = "Deployment" @@ -54,7 +66,7 @@ const ( var errSyncCache = errors.New("failed to sync caches") -func NewClient(sharedInformers informers.SharedInformerFactory, proxyAddrOverride string) *Client { +func NewClient(k8sClient kubernetes.Interface, sharedInformers informers.SharedInformerFactory, l5dApi *l5dk8s.KubernetesAPI) *Client { log := log.WithField("client", "k8s") log.Debug("initializing") @@ -83,7 +95,8 @@ func NewClient(sharedInformers informers.SharedInformerFactory, proxyAddrOverrid eventInformerSynced := eventInformer.Informer().HasSynced return &Client{ - encoders: encoders, + k8sClient: k8sClient, + encoders: encoders, sharedInformers: sharedInformers, @@ -102,9 +115,8 @@ func NewClient(sharedInformers informers.SharedInformerFactory, proxyAddrOverrid eventInformer: eventInformer, eventSynced: eventInformerSynced, - proxyAddrOverride: proxyAddrOverride, - - log: log, + l5dApi: l5dApi, + log: log, } } @@ -149,3 +161,58 @@ func (c *Client) serialize(obj runtime.Object, gv runtime.GroupVersioner) []byte } return buf } + +func (c *Client) localMode() bool { + return c.l5dApi != nil +} + +// this method establishes a connection to a specific container in a pod +// and gives you the host addr. This logic is abstracted away in order to +// enable running this agent outside of a K8s cluster for the purpose of +// local development. The `containerConnection` struct returned contains +// a `cleanup()` function that must be called when this connection is not +// needed anymore +func (c *Client) getContainerConnection(pod *v1.Pod, container *v1.Container, portName string) (*containerConnection, error) { + if c.localMode() { + // running in local mode, we need a port forward + pf, err := l5dk8s.NewContainerMetricsForward(c.l5dApi, *pod, *container, false, l5dk8s.ProxyAdminPortName) + if err != nil { + return nil, err + } + + // not very elegant... We need a way to get the port and host from PortForward + httpUrl, err := url.Parse(pf.URLFor("")) + if err != nil { + return nil, err + } + + if err = pf.Init(); err != nil { + return nil, err + } + + return &containerConnection{ + host: httpUrl.Host, + cleanup: func() { pf.Stop() }, + }, nil + } else { + port, err := getContainerPort(container, portName) + if err != nil { + return nil, err + } + + return &containerConnection{ + host: fmt.Sprintf("%s:%d", pod.Status.PodIP, port), + cleanup: func() {}, // noop + }, nil + } +} + +func getContainerPort(container *v1.Container, portName string) (int32, error) { + for _, p := range container.Ports { + if p.Name == portName { + return p.ContainerPort, nil + } + } + + return 0, fmt.Errorf("could not find port %s on container [%s]", portName, container.Name) +} diff --git a/gen/bcloud/buoyant-cloud-api.pb.go b/gen/bcloud/buoyant-cloud-api.pb.go index 628530a..8c53049 100644 --- a/gen/bcloud/buoyant-cloud-api.pb.go +++ b/gen/bcloud/buoyant-cloud-api.pb.go @@ -475,6 +475,147 @@ func (x *Pod) GetPod() []byte { return nil } +type ConfigMap struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ConfigMap []byte `protobuf:"bytes,1,opt,name=config_map,json=configMap,proto3" json:"config_map,omitempty"` +} + +func (x *ConfigMap) Reset() { + *x = ConfigMap{} + if protoimpl.UnsafeEnabled { + mi := &file_buoyant_cloud_api_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ConfigMap) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ConfigMap) ProtoMessage() {} + +func (x *ConfigMap) ProtoReflect() protoreflect.Message { + mi := &file_buoyant_cloud_api_proto_msgTypes[8] + 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 ConfigMap.ProtoReflect.Descriptor instead. +func (*ConfigMap) Descriptor() ([]byte, []int) { + return file_buoyant_cloud_api_proto_rawDescGZIP(), []int{8} +} + +func (x *ConfigMap) GetConfigMap() []byte { + if x != nil { + return x.ConfigMap + } + return nil +} + +type Node struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Node []byte `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"` +} + +func (x *Node) Reset() { + *x = Node{} + if protoimpl.UnsafeEnabled { + mi := &file_buoyant_cloud_api_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Node) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Node) ProtoMessage() {} + +func (x *Node) ProtoReflect() protoreflect.Message { + mi := &file_buoyant_cloud_api_proto_msgTypes[9] + 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 Node.ProtoReflect.Descriptor instead. +func (*Node) Descriptor() ([]byte, []int) { + return file_buoyant_cloud_api_proto_rawDescGZIP(), []int{9} +} + +func (x *Node) GetNode() []byte { + if x != nil { + return x.Node + } + return nil +} + +type Service struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Service []byte `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"` +} + +func (x *Service) Reset() { + *x = Service{} + if protoimpl.UnsafeEnabled { + mi := &file_buoyant_cloud_api_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Service) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Service) ProtoMessage() {} + +func (x *Service) ProtoReflect() protoreflect.Message { + mi := &file_buoyant_cloud_api_proto_msgTypes[10] + 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 Service.ProtoReflect.Descriptor instead. +func (*Service) Descriptor() ([]byte, []int) { + return file_buoyant_cloud_api_proto_rawDescGZIP(), []int{10} +} + +func (x *Service) GetService() []byte { + if x != nil { + return x.Service + } + return nil +} + type WorkloadMessage struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -492,7 +633,7 @@ type WorkloadMessage struct { func (x *WorkloadMessage) Reset() { *x = WorkloadMessage{} if protoimpl.UnsafeEnabled { - mi := &file_buoyant_cloud_api_proto_msgTypes[8] + mi := &file_buoyant_cloud_api_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -505,7 +646,7 @@ func (x *WorkloadMessage) String() string { func (*WorkloadMessage) ProtoMessage() {} func (x *WorkloadMessage) ProtoReflect() protoreflect.Message { - mi := &file_buoyant_cloud_api_proto_msgTypes[8] + mi := &file_buoyant_cloud_api_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -518,7 +659,7 @@ func (x *WorkloadMessage) ProtoReflect() protoreflect.Message { // Deprecated: Use WorkloadMessage.ProtoReflect.Descriptor instead. func (*WorkloadMessage) Descriptor() ([]byte, []int) { - return file_buoyant_cloud_api_proto_rawDescGZIP(), []int{8} + return file_buoyant_cloud_api_proto_rawDescGZIP(), []int{11} } func (m *WorkloadMessage) GetMessage() isWorkloadMessage_Message { @@ -608,7 +749,7 @@ type AddWorkload struct { func (x *AddWorkload) Reset() { *x = AddWorkload{} if protoimpl.UnsafeEnabled { - mi := &file_buoyant_cloud_api_proto_msgTypes[9] + mi := &file_buoyant_cloud_api_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -621,7 +762,7 @@ func (x *AddWorkload) String() string { func (*AddWorkload) ProtoMessage() {} func (x *AddWorkload) ProtoReflect() protoreflect.Message { - mi := &file_buoyant_cloud_api_proto_msgTypes[9] + mi := &file_buoyant_cloud_api_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -634,7 +775,7 @@ func (x *AddWorkload) ProtoReflect() protoreflect.Message { // Deprecated: Use AddWorkload.ProtoReflect.Descriptor instead. func (*AddWorkload) Descriptor() ([]byte, []int) { - return file_buoyant_cloud_api_proto_rawDescGZIP(), []int{9} + return file_buoyant_cloud_api_proto_rawDescGZIP(), []int{12} } func (x *AddWorkload) GetWorkload() *Workload { @@ -655,7 +796,7 @@ type DeleteWorkload struct { func (x *DeleteWorkload) Reset() { *x = DeleteWorkload{} if protoimpl.UnsafeEnabled { - mi := &file_buoyant_cloud_api_proto_msgTypes[10] + mi := &file_buoyant_cloud_api_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -668,7 +809,7 @@ func (x *DeleteWorkload) String() string { func (*DeleteWorkload) ProtoMessage() {} func (x *DeleteWorkload) ProtoReflect() protoreflect.Message { - mi := &file_buoyant_cloud_api_proto_msgTypes[10] + mi := &file_buoyant_cloud_api_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -681,7 +822,7 @@ func (x *DeleteWorkload) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteWorkload.ProtoReflect.Descriptor instead. func (*DeleteWorkload) Descriptor() ([]byte, []int) { - return file_buoyant_cloud_api_proto_rawDescGZIP(), []int{10} + return file_buoyant_cloud_api_proto_rawDescGZIP(), []int{13} } func (x *DeleteWorkload) GetWorkload() *Workload { @@ -704,7 +845,7 @@ type UpdateWorkload struct { func (x *UpdateWorkload) Reset() { *x = UpdateWorkload{} if protoimpl.UnsafeEnabled { - mi := &file_buoyant_cloud_api_proto_msgTypes[11] + mi := &file_buoyant_cloud_api_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -717,7 +858,7 @@ func (x *UpdateWorkload) String() string { func (*UpdateWorkload) ProtoMessage() {} func (x *UpdateWorkload) ProtoReflect() protoreflect.Message { - mi := &file_buoyant_cloud_api_proto_msgTypes[11] + mi := &file_buoyant_cloud_api_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -730,7 +871,7 @@ func (x *UpdateWorkload) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateWorkload.ProtoReflect.Descriptor instead. func (*UpdateWorkload) Descriptor() ([]byte, []int) { - return file_buoyant_cloud_api_proto_rawDescGZIP(), []int{11} + return file_buoyant_cloud_api_proto_rawDescGZIP(), []int{14} } func (x *UpdateWorkload) GetOldWorkload() *Workload { @@ -765,7 +906,7 @@ type ListWorkloads struct { func (x *ListWorkloads) Reset() { *x = ListWorkloads{} if protoimpl.UnsafeEnabled { - mi := &file_buoyant_cloud_api_proto_msgTypes[12] + mi := &file_buoyant_cloud_api_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -778,7 +919,7 @@ func (x *ListWorkloads) String() string { func (*ListWorkloads) ProtoMessage() {} func (x *ListWorkloads) ProtoReflect() protoreflect.Message { - mi := &file_buoyant_cloud_api_proto_msgTypes[12] + mi := &file_buoyant_cloud_api_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -791,7 +932,7 @@ func (x *ListWorkloads) ProtoReflect() protoreflect.Message { // Deprecated: Use ListWorkloads.ProtoReflect.Descriptor instead. func (*ListWorkloads) Descriptor() ([]byte, []int) { - return file_buoyant_cloud_api_proto_rawDescGZIP(), []int{12} + return file_buoyant_cloud_api_proto_rawDescGZIP(), []int{15} } func (x *ListWorkloads) GetWorkloads() []*Workload { @@ -814,7 +955,7 @@ type Event struct { func (x *Event) Reset() { *x = Event{} if protoimpl.UnsafeEnabled { - mi := &file_buoyant_cloud_api_proto_msgTypes[13] + mi := &file_buoyant_cloud_api_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -827,7 +968,7 @@ func (x *Event) String() string { func (*Event) ProtoMessage() {} func (x *Event) ProtoReflect() protoreflect.Message { - mi := &file_buoyant_cloud_api_proto_msgTypes[13] + mi := &file_buoyant_cloud_api_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -840,7 +981,7 @@ func (x *Event) ProtoReflect() protoreflect.Message { // Deprecated: Use Event.ProtoReflect.Descriptor instead. func (*Event) Descriptor() ([]byte, []int) { - return file_buoyant_cloud_api_proto_rawDescGZIP(), []int{13} + return file_buoyant_cloud_api_proto_rawDescGZIP(), []int{16} } func (x *Event) GetAuth() *Auth { @@ -876,7 +1017,7 @@ type CertData struct { func (x *CertData) Reset() { *x = CertData{} if protoimpl.UnsafeEnabled { - mi := &file_buoyant_cloud_api_proto_msgTypes[14] + mi := &file_buoyant_cloud_api_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -889,7 +1030,7 @@ func (x *CertData) String() string { func (*CertData) ProtoMessage() {} func (x *CertData) ProtoReflect() protoreflect.Message { - mi := &file_buoyant_cloud_api_proto_msgTypes[14] + mi := &file_buoyant_cloud_api_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -902,7 +1043,7 @@ func (x *CertData) ProtoReflect() protoreflect.Message { // Deprecated: Use CertData.ProtoReflect.Descriptor instead. func (*CertData) Descriptor() ([]byte, []int) { - return file_buoyant_cloud_api_proto_rawDescGZIP(), []int{14} + return file_buoyant_cloud_api_proto_rawDescGZIP(), []int{17} } func (x *CertData) GetRaw() []byte { @@ -930,7 +1071,7 @@ type ControlPlaneCerts struct { func (x *ControlPlaneCerts) Reset() { *x = ControlPlaneCerts{} if protoimpl.UnsafeEnabled { - mi := &file_buoyant_cloud_api_proto_msgTypes[15] + mi := &file_buoyant_cloud_api_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -943,7 +1084,7 @@ func (x *ControlPlaneCerts) String() string { func (*ControlPlaneCerts) ProtoMessage() {} func (x *ControlPlaneCerts) ProtoReflect() protoreflect.Message { - mi := &file_buoyant_cloud_api_proto_msgTypes[15] + mi := &file_buoyant_cloud_api_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -956,7 +1097,7 @@ func (x *ControlPlaneCerts) ProtoReflect() protoreflect.Message { // Deprecated: Use ControlPlaneCerts.ProtoReflect.Descriptor instead. func (*ControlPlaneCerts) Descriptor() ([]byte, []int) { - return file_buoyant_cloud_api_proto_rawDescGZIP(), []int{15} + return file_buoyant_cloud_api_proto_rawDescGZIP(), []int{18} } func (x *ControlPlaneCerts) GetIssuerCrtChain() []*CertData { @@ -986,7 +1127,7 @@ type CertificateInfo struct { func (x *CertificateInfo) Reset() { *x = CertificateInfo{} if protoimpl.UnsafeEnabled { - mi := &file_buoyant_cloud_api_proto_msgTypes[16] + mi := &file_buoyant_cloud_api_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -999,7 +1140,7 @@ func (x *CertificateInfo) String() string { func (*CertificateInfo) ProtoMessage() {} func (x *CertificateInfo) ProtoReflect() protoreflect.Message { - mi := &file_buoyant_cloud_api_proto_msgTypes[16] + mi := &file_buoyant_cloud_api_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1012,7 +1153,7 @@ func (x *CertificateInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use CertificateInfo.ProtoReflect.Descriptor instead. func (*CertificateInfo) Descriptor() ([]byte, []int) { - return file_buoyant_cloud_api_proto_rawDescGZIP(), []int{16} + return file_buoyant_cloud_api_proto_rawDescGZIP(), []int{19} } func (m *CertificateInfo) GetInfo() isCertificateInfo_Info { @@ -1053,7 +1194,7 @@ type LinkerdMessage struct { func (x *LinkerdMessage) Reset() { *x = LinkerdMessage{} if protoimpl.UnsafeEnabled { - mi := &file_buoyant_cloud_api_proto_msgTypes[17] + mi := &file_buoyant_cloud_api_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1066,7 +1207,7 @@ func (x *LinkerdMessage) String() string { func (*LinkerdMessage) ProtoMessage() {} func (x *LinkerdMessage) ProtoReflect() protoreflect.Message { - mi := &file_buoyant_cloud_api_proto_msgTypes[17] + mi := &file_buoyant_cloud_api_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1079,7 +1220,7 @@ func (x *LinkerdMessage) ProtoReflect() protoreflect.Message { // Deprecated: Use LinkerdMessage.ProtoReflect.Descriptor instead. func (*LinkerdMessage) Descriptor() ([]byte, []int) { - return file_buoyant_cloud_api_proto_rawDescGZIP(), []int{17} + return file_buoyant_cloud_api_proto_rawDescGZIP(), []int{20} } func (x *LinkerdMessage) GetAuth() *Auth { @@ -1113,6 +1254,238 @@ type LinkerdMessage_CrtInfo struct { func (*LinkerdMessage_CrtInfo) isLinkerdMessage_Message() {} +type GetProxyDiagnostics struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + DiagnosticId string `protobuf:"bytes,1,opt,name=diagnostic_id,json=diagnosticId,proto3" json:"diagnostic_id,omitempty"` + PodName string `protobuf:"bytes,2,opt,name=pod_name,json=podName,proto3" json:"pod_name,omitempty"` + PodNamespace string `protobuf:"bytes,3,opt,name=pod_namespace,json=podNamespace,proto3" json:"pod_namespace,omitempty"` +} + +func (x *GetProxyDiagnostics) Reset() { + *x = GetProxyDiagnostics{} + if protoimpl.UnsafeEnabled { + mi := &file_buoyant_cloud_api_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetProxyDiagnostics) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetProxyDiagnostics) ProtoMessage() {} + +func (x *GetProxyDiagnostics) ProtoReflect() protoreflect.Message { + mi := &file_buoyant_cloud_api_proto_msgTypes[21] + 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 GetProxyDiagnostics.ProtoReflect.Descriptor instead. +func (*GetProxyDiagnostics) Descriptor() ([]byte, []int) { + return file_buoyant_cloud_api_proto_rawDescGZIP(), []int{21} +} + +func (x *GetProxyDiagnostics) GetDiagnosticId() string { + if x != nil { + return x.DiagnosticId + } + return "" +} + +func (x *GetProxyDiagnostics) GetPodName() string { + if x != nil { + return x.PodName + } + return "" +} + +func (x *GetProxyDiagnostics) GetPodNamespace() string { + if x != nil { + return x.PodNamespace + } + return "" +} + +type AgentCommand struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Command: + // *AgentCommand_GetProxyDiagnostics + Command isAgentCommand_Command `protobuf_oneof:"command"` +} + +func (x *AgentCommand) Reset() { + *x = AgentCommand{} + if protoimpl.UnsafeEnabled { + mi := &file_buoyant_cloud_api_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AgentCommand) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AgentCommand) ProtoMessage() {} + +func (x *AgentCommand) ProtoReflect() protoreflect.Message { + mi := &file_buoyant_cloud_api_proto_msgTypes[22] + 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 AgentCommand.ProtoReflect.Descriptor instead. +func (*AgentCommand) Descriptor() ([]byte, []int) { + return file_buoyant_cloud_api_proto_rawDescGZIP(), []int{22} +} + +func (m *AgentCommand) GetCommand() isAgentCommand_Command { + if m != nil { + return m.Command + } + return nil +} + +func (x *AgentCommand) GetGetProxyDiagnostics() *GetProxyDiagnostics { + if x, ok := x.GetCommand().(*AgentCommand_GetProxyDiagnostics); ok { + return x.GetProxyDiagnostics + } + return nil +} + +type isAgentCommand_Command interface { + isAgentCommand_Command() +} + +type AgentCommand_GetProxyDiagnostics struct { + GetProxyDiagnostics *GetProxyDiagnostics `protobuf:"bytes,1,opt,name=get_proxy_diagnostics,json=getProxyDiagnostics,proto3,oneof"` +} + +func (*AgentCommand_GetProxyDiagnostics) isAgentCommand_Command() {} + +type ProxyDiagnostic struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Auth *Auth `protobuf:"bytes,1,opt,name=auth,proto3" json:"auth,omitempty"` + DiagnosticId string `protobuf:"bytes,2,opt,name=diagnostic_id,json=diagnosticId,proto3" json:"diagnostic_id,omitempty"` + Logs []byte `protobuf:"bytes,3,opt,name=logs,proto3" json:"logs,omitempty"` + Metrics [][]byte `protobuf:"bytes,4,rep,name=metrics,proto3" json:"metrics,omitempty"` + PodManifest *Pod `protobuf:"bytes,5,opt,name=pod_manifest,json=podManifest,proto3" json:"pod_manifest,omitempty"` + LinkerdConfigMap *ConfigMap `protobuf:"bytes,6,opt,name=linkerd_config_map,json=linkerdConfigMap,proto3" json:"linkerd_config_map,omitempty"` + Nodes []*Node `protobuf:"bytes,7,rep,name=nodes,proto3" json:"nodes,omitempty"` + K8SServiceManifest *Service `protobuf:"bytes,8,opt,name=k8s_service_manifest,json=k8sServiceManifest,proto3" json:"k8s_service_manifest,omitempty"` +} + +func (x *ProxyDiagnostic) Reset() { + *x = ProxyDiagnostic{} + if protoimpl.UnsafeEnabled { + mi := &file_buoyant_cloud_api_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ProxyDiagnostic) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ProxyDiagnostic) ProtoMessage() {} + +func (x *ProxyDiagnostic) ProtoReflect() protoreflect.Message { + mi := &file_buoyant_cloud_api_proto_msgTypes[23] + 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 ProxyDiagnostic.ProtoReflect.Descriptor instead. +func (*ProxyDiagnostic) Descriptor() ([]byte, []int) { + return file_buoyant_cloud_api_proto_rawDescGZIP(), []int{23} +} + +func (x *ProxyDiagnostic) GetAuth() *Auth { + if x != nil { + return x.Auth + } + return nil +} + +func (x *ProxyDiagnostic) GetDiagnosticId() string { + if x != nil { + return x.DiagnosticId + } + return "" +} + +func (x *ProxyDiagnostic) GetLogs() []byte { + if x != nil { + return x.Logs + } + return nil +} + +func (x *ProxyDiagnostic) GetMetrics() [][]byte { + if x != nil { + return x.Metrics + } + return nil +} + +func (x *ProxyDiagnostic) GetPodManifest() *Pod { + if x != nil { + return x.PodManifest + } + return nil +} + +func (x *ProxyDiagnostic) GetLinkerdConfigMap() *ConfigMap { + if x != nil { + return x.LinkerdConfigMap + } + return nil +} + +func (x *ProxyDiagnostic) GetNodes() []*Node { + if x != nil { + return x.Nodes + } + return nil +} + +func (x *ProxyDiagnostic) GetK8SServiceManifest() *Service { + if x != nil { + return x.K8SServiceManifest + } + return nil +} + var File_buoyant_cloud_api_proto protoreflect.FileDescriptor var file_buoyant_cloud_api_proto_rawDesc = []byte{ @@ -1162,100 +1535,156 @@ var file_buoyant_cloud_api_proto_rawDesc = []byte{ 0x6f, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x50, 0x6f, 0x64, 0x52, 0x04, 0x70, 0x6f, 0x64, 0x73, 0x22, 0x17, 0x0a, 0x03, 0x50, 0x6f, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x6f, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x70, 0x6f, 0x64, 0x22, 0xa5, 0x02, 0x0a, - 0x0f, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x12, 0x29, 0x0a, 0x04, 0x61, 0x75, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, - 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x41, - 0x75, 0x74, 0x68, 0x48, 0x00, 0x52, 0x04, 0x61, 0x75, 0x74, 0x68, 0x12, 0x32, 0x0a, 0x05, 0x61, - 0x64, 0x64, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x62, 0x75, 0x6f, - 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x57, 0x6f, - 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x00, 0x52, 0x05, 0x61, 0x64, 0x64, 0x65, 0x64, 0x12, - 0x39, 0x0a, 0x07, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1d, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, - 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x48, - 0x00, 0x52, 0x07, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x12, 0x39, 0x0a, 0x07, 0x64, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x62, 0x75, - 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x00, 0x52, 0x07, 0x64, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x32, 0x0a, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, - 0x6f, 0x75, 0x64, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, - 0x73, 0x48, 0x00, 0x52, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x22, 0x42, 0x0a, 0x0b, 0x41, 0x64, 0x64, 0x57, 0x6f, 0x72, 0x6b, 0x6c, - 0x6f, 0x61, 0x64, 0x12, 0x33, 0x0a, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x18, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x70, 0x6f, 0x64, 0x22, 0x2a, 0x0a, 0x09, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x5f, 0x6d, 0x61, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, 0x70, 0x22, 0x1a, 0x0a, 0x04, 0x4e, 0x6f, 0x64, 0x65, + 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, + 0x6e, 0x6f, 0x64, 0x65, 0x22, 0x23, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, + 0x18, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x22, 0xa5, 0x02, 0x0a, 0x0f, 0x57, 0x6f, + 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x29, 0x0a, + 0x04, 0x61, 0x75, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x62, 0x75, + 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x41, 0x75, 0x74, 0x68, + 0x48, 0x00, 0x52, 0x04, 0x61, 0x75, 0x74, 0x68, 0x12, 0x32, 0x0a, 0x05, 0x61, 0x64, 0x64, 0x65, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, + 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x57, 0x6f, 0x72, 0x6b, 0x6c, + 0x6f, 0x61, 0x64, 0x48, 0x00, 0x52, 0x05, 0x61, 0x64, 0x64, 0x65, 0x64, 0x12, 0x39, 0x0a, 0x07, + 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, + 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x00, 0x52, 0x07, + 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x12, 0x39, 0x0a, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, + 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x57, + 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x00, 0x52, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x64, 0x12, 0x32, 0x0a, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1c, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x48, 0x00, + 0x52, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x22, 0x42, 0x0a, 0x0b, 0x41, 0x64, 0x64, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, + 0x12, 0x33, 0x0a, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, + 0x75, 0x64, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x08, 0x77, 0x6f, 0x72, + 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x45, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x57, + 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x33, 0x0a, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x6c, + 0x6f, 0x61, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x62, 0x75, 0x6f, 0x79, + 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, + 0x61, 0x64, 0x52, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xc2, 0x01, 0x0a, + 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x12, + 0x3a, 0x0a, 0x0c, 0x6f, 0x6c, 0x64, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, - 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x08, - 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x45, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x33, 0x0a, 0x08, 0x77, 0x6f, - 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x62, - 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x57, 0x6f, 0x72, - 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x22, - 0xc2, 0x01, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, - 0x61, 0x64, 0x12, 0x3a, 0x0a, 0x0c, 0x6f, 0x6c, 0x64, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, - 0x61, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, - 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, - 0x64, 0x52, 0x0b, 0x6f, 0x6c, 0x64, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x3a, - 0x0a, 0x0c, 0x6e, 0x65, 0x77, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, - 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x0b, 0x6e, - 0x65, 0x77, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x22, 0x46, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, - 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x12, 0x35, 0x0a, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, - 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, - 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, - 0x64, 0x52, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x22, 0x75, 0x0a, 0x05, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x27, 0x0a, 0x04, 0x61, 0x75, 0x74, 0x68, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, - 0x6f, 0x75, 0x64, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x52, 0x04, 0x61, 0x75, 0x74, 0x68, 0x12, 0x14, - 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x12, 0x2d, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, - 0x6f, 0x75, 0x64, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x05, 0x6f, 0x77, - 0x6e, 0x65, 0x72, 0x22, 0x1c, 0x0a, 0x08, 0x43, 0x65, 0x72, 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, - 0x10, 0x0a, 0x03, 0x72, 0x61, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x72, 0x61, - 0x77, 0x22, 0x85, 0x01, 0x0a, 0x11, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x50, 0x6c, 0x61, - 0x6e, 0x65, 0x43, 0x65, 0x72, 0x74, 0x73, 0x12, 0x41, 0x0a, 0x10, 0x69, 0x73, 0x73, 0x75, 0x65, - 0x72, 0x5f, 0x63, 0x72, 0x74, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x0b, + 0x6f, 0x6c, 0x64, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x3a, 0x0a, 0x0c, 0x6e, + 0x65, 0x77, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, - 0x64, 0x2e, 0x43, 0x65, 0x72, 0x74, 0x44, 0x61, 0x74, 0x61, 0x52, 0x0e, 0x69, 0x73, 0x73, 0x75, - 0x65, 0x72, 0x43, 0x72, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x2d, 0x0a, 0x05, 0x72, 0x6f, - 0x6f, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x62, 0x75, 0x6f, 0x79, - 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x43, 0x65, 0x72, 0x74, 0x44, 0x61, - 0x74, 0x61, 0x52, 0x05, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x22, 0x62, 0x0a, 0x0f, 0x43, 0x65, 0x72, - 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x47, 0x0a, 0x0d, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, - 0x6f, 0x75, 0x64, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x50, 0x6c, 0x61, 0x6e, 0x65, - 0x43, 0x65, 0x72, 0x74, 0x73, 0x48, 0x00, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x50, 0x6c, 0x61, 0x6e, 0x65, 0x42, 0x06, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x22, 0x81, 0x01, - 0x0a, 0x0e, 0x4c, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x12, 0x27, 0x0a, 0x04, 0x61, 0x75, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, - 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x41, - 0x75, 0x74, 0x68, 0x52, 0x04, 0x61, 0x75, 0x74, 0x68, 0x12, 0x3b, 0x0a, 0x08, 0x63, 0x72, 0x74, - 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x62, 0x75, - 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x43, 0x65, 0x72, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x48, 0x00, 0x52, 0x07, 0x63, - 0x72, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x32, 0xd1, 0x01, 0x0a, 0x03, 0x41, 0x70, 0x69, 0x12, 0x4a, 0x0a, 0x0e, 0x57, 0x6f, 0x72, - 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1e, 0x2e, 0x62, 0x75, - 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x57, 0x6f, 0x72, 0x6b, - 0x6c, 0x6f, 0x61, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x14, 0x2e, 0x62, 0x75, - 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x22, 0x00, 0x28, 0x01, 0x12, 0x38, 0x0a, 0x08, 0x41, 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x12, 0x14, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, - 0x64, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x1a, 0x14, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, - 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, - 0x44, 0x0a, 0x0b, 0x4c, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1d, - 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x4c, - 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x14, 0x2e, + 0x64, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x0b, 0x6e, 0x65, 0x77, 0x57, + 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x22, 0x46, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, + 0x64, 0x73, 0x12, 0x35, 0x0a, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, + 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x09, + 0x77, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x22, 0x75, 0x0a, 0x05, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x12, 0x27, 0x0a, 0x04, 0x61, 0x75, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x13, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, + 0x2e, 0x41, 0x75, 0x74, 0x68, 0x52, 0x04, 0x61, 0x75, 0x74, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x12, 0x2d, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x17, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, + 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, + 0x22, 0x1c, 0x0a, 0x08, 0x43, 0x65, 0x72, 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, 0x10, 0x0a, 0x03, + 0x72, 0x61, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x72, 0x61, 0x77, 0x22, 0x85, + 0x01, 0x0a, 0x11, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x50, 0x6c, 0x61, 0x6e, 0x65, 0x43, + 0x65, 0x72, 0x74, 0x73, 0x12, 0x41, 0x0a, 0x10, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x5f, 0x63, + 0x72, 0x74, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, + 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x43, + 0x65, 0x72, 0x74, 0x44, 0x61, 0x74, 0x61, 0x52, 0x0e, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x43, + 0x72, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x2d, 0x0a, 0x05, 0x72, 0x6f, 0x6f, 0x74, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, + 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x43, 0x65, 0x72, 0x74, 0x44, 0x61, 0x74, 0x61, 0x52, + 0x05, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x22, 0x62, 0x0a, 0x0f, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x47, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x20, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, + 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x50, 0x6c, 0x61, 0x6e, 0x65, 0x43, 0x65, 0x72, + 0x74, 0x73, 0x48, 0x00, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x50, 0x6c, 0x61, + 0x6e, 0x65, 0x42, 0x06, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x22, 0x81, 0x01, 0x0a, 0x0e, 0x4c, + 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x27, 0x0a, + 0x04, 0x61, 0x75, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x62, 0x75, + 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x41, 0x75, 0x74, 0x68, + 0x52, 0x04, 0x61, 0x75, 0x74, 0x68, 0x12, 0x3b, 0x0a, 0x08, 0x63, 0x72, 0x74, 0x5f, 0x69, 0x6e, + 0x66, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, + 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x48, 0x00, 0x52, 0x07, 0x63, 0x72, 0x74, 0x49, + 0x6e, 0x66, 0x6f, 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x7a, + 0x0a, 0x13, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, + 0x73, 0x74, 0x69, 0x63, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, + 0x74, 0x69, 0x63, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x69, + 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x6f, + 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x6f, + 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x6f, 0x64, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x6f, + 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x73, 0x0a, 0x0c, 0x41, 0x67, + 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x58, 0x0a, 0x15, 0x67, 0x65, + 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, + 0x69, 0x63, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x62, 0x75, 0x6f, 0x79, + 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, + 0x78, 0x79, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, 0x48, 0x00, 0x52, + 0x13, 0x67, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, + 0x74, 0x69, 0x63, 0x73, 0x42, 0x09, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x22, + 0x81, 0x03, 0x0a, 0x0f, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, + 0x74, 0x69, 0x63, 0x12, 0x27, 0x0a, 0x04, 0x61, 0x75, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x13, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, + 0x64, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x52, 0x04, 0x61, 0x75, 0x74, 0x68, 0x12, 0x23, 0x0a, 0x0d, + 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x49, + 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x04, 0x6c, 0x6f, 0x67, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, + 0x18, 0x04, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, + 0x35, 0x0a, 0x0c, 0x70, 0x6f, 0x64, 0x5f, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, + 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x50, 0x6f, 0x64, 0x52, 0x0b, 0x70, 0x6f, 0x64, 0x4d, 0x61, + 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x12, 0x46, 0x0a, 0x12, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x72, + 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x6d, 0x61, 0x70, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, + 0x75, 0x64, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, 0x70, 0x52, 0x10, 0x6c, 0x69, + 0x6e, 0x6b, 0x65, 0x72, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x4d, 0x61, 0x70, 0x12, 0x29, + 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, + 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x4e, 0x6f, + 0x64, 0x65, 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x48, 0x0a, 0x14, 0x6b, 0x38, 0x73, + 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, + 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, + 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, + 0x12, 0x6b, 0x38, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x61, 0x6e, 0x69, 0x66, + 0x65, 0x73, 0x74, 0x32, 0xe2, 0x02, 0x0a, 0x03, 0x41, 0x70, 0x69, 0x12, 0x4a, 0x0a, 0x0e, 0x57, + 0x6f, 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1e, 0x2e, + 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x57, 0x6f, + 0x72, 0x6b, 0x6c, 0x6f, 0x61, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x14, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x22, 0x00, 0x42, 0x31, 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x69, 0x6f, 0x2f, 0x6c, 0x69, - 0x6e, 0x6b, 0x65, 0x72, 0x64, 0x2d, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2f, 0x67, 0x65, - 0x6e, 0x2f, 0x62, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x70, 0x74, 0x79, 0x22, 0x00, 0x28, 0x01, 0x12, 0x38, 0x0a, 0x08, 0x41, 0x64, 0x64, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x12, 0x14, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, + 0x6f, 0x75, 0x64, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x1a, 0x14, 0x2e, 0x62, 0x75, 0x6f, 0x79, + 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, + 0x00, 0x12, 0x44, 0x0a, 0x0b, 0x4c, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x64, 0x49, 0x6e, 0x66, 0x6f, + 0x12, 0x1d, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, + 0x2e, 0x4c, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, + 0x14, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0b, 0x4d, 0x61, 0x6e, 0x61, 0x67, + 0x65, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x13, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, + 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x1a, 0x1b, 0x2e, 0x62, 0x75, + 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x41, 0x67, 0x65, 0x6e, + 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x22, 0x00, 0x30, 0x01, 0x12, 0x4a, 0x0a, 0x10, + 0x50, 0x72, 0x6f, 0x78, 0x79, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x73, + 0x12, 0x1e, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, + 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, + 0x1a, 0x14, 0x2e, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x42, 0x31, 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, 0x69, 0x6f, + 0x2f, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x64, 0x2d, 0x62, 0x75, 0x6f, 0x79, 0x61, 0x6e, 0x74, + 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x62, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( @@ -1270,7 +1699,7 @@ func file_buoyant_cloud_api_proto_rawDescGZIP() []byte { return file_buoyant_cloud_api_proto_rawDescData } -var file_buoyant_cloud_api_proto_msgTypes = make([]protoimpl.MessageInfo, 18) +var file_buoyant_cloud_api_proto_msgTypes = make([]protoimpl.MessageInfo, 24) var file_buoyant_cloud_api_proto_goTypes = []interface{}{ (*Empty)(nil), // 0: buoyant.cloud.Empty (*Auth)(nil), // 1: buoyant.cloud.Auth @@ -1280,17 +1709,23 @@ var file_buoyant_cloud_api_proto_goTypes = []interface{}{ (*StatefulSet)(nil), // 5: buoyant.cloud.StatefulSet (*ReplicaSet)(nil), // 6: buoyant.cloud.ReplicaSet (*Pod)(nil), // 7: buoyant.cloud.Pod - (*WorkloadMessage)(nil), // 8: buoyant.cloud.WorkloadMessage - (*AddWorkload)(nil), // 9: buoyant.cloud.AddWorkload - (*DeleteWorkload)(nil), // 10: buoyant.cloud.DeleteWorkload - (*UpdateWorkload)(nil), // 11: buoyant.cloud.UpdateWorkload - (*ListWorkloads)(nil), // 12: buoyant.cloud.ListWorkloads - (*Event)(nil), // 13: buoyant.cloud.Event - (*CertData)(nil), // 14: buoyant.cloud.CertData - (*ControlPlaneCerts)(nil), // 15: buoyant.cloud.ControlPlaneCerts - (*CertificateInfo)(nil), // 16: buoyant.cloud.CertificateInfo - (*LinkerdMessage)(nil), // 17: buoyant.cloud.LinkerdMessage - (*timestamppb.Timestamp)(nil), // 18: google.protobuf.Timestamp + (*ConfigMap)(nil), // 8: buoyant.cloud.ConfigMap + (*Node)(nil), // 9: buoyant.cloud.Node + (*Service)(nil), // 10: buoyant.cloud.Service + (*WorkloadMessage)(nil), // 11: buoyant.cloud.WorkloadMessage + (*AddWorkload)(nil), // 12: buoyant.cloud.AddWorkload + (*DeleteWorkload)(nil), // 13: buoyant.cloud.DeleteWorkload + (*UpdateWorkload)(nil), // 14: buoyant.cloud.UpdateWorkload + (*ListWorkloads)(nil), // 15: buoyant.cloud.ListWorkloads + (*Event)(nil), // 16: buoyant.cloud.Event + (*CertData)(nil), // 17: buoyant.cloud.CertData + (*ControlPlaneCerts)(nil), // 18: buoyant.cloud.ControlPlaneCerts + (*CertificateInfo)(nil), // 19: buoyant.cloud.CertificateInfo + (*LinkerdMessage)(nil), // 20: buoyant.cloud.LinkerdMessage + (*GetProxyDiagnostics)(nil), // 21: buoyant.cloud.GetProxyDiagnostics + (*AgentCommand)(nil), // 22: buoyant.cloud.AgentCommand + (*ProxyDiagnostic)(nil), // 23: buoyant.cloud.ProxyDiagnostic + (*timestamppb.Timestamp)(nil), // 24: google.protobuf.Timestamp } var file_buoyant_cloud_api_proto_depIdxs = []int32{ 3, // 0: buoyant.cloud.Workload.daemonset:type_name -> buoyant.cloud.DaemonSet @@ -1301,34 +1736,44 @@ var file_buoyant_cloud_api_proto_depIdxs = []int32{ 7, // 5: buoyant.cloud.StatefulSet.pods:type_name -> buoyant.cloud.Pod 7, // 6: buoyant.cloud.ReplicaSet.pods:type_name -> buoyant.cloud.Pod 1, // 7: buoyant.cloud.WorkloadMessage.auth:type_name -> buoyant.cloud.Auth - 9, // 8: buoyant.cloud.WorkloadMessage.added:type_name -> buoyant.cloud.AddWorkload - 11, // 9: buoyant.cloud.WorkloadMessage.updated:type_name -> buoyant.cloud.UpdateWorkload - 10, // 10: buoyant.cloud.WorkloadMessage.deleted:type_name -> buoyant.cloud.DeleteWorkload - 12, // 11: buoyant.cloud.WorkloadMessage.list:type_name -> buoyant.cloud.ListWorkloads + 12, // 8: buoyant.cloud.WorkloadMessage.added:type_name -> buoyant.cloud.AddWorkload + 14, // 9: buoyant.cloud.WorkloadMessage.updated:type_name -> buoyant.cloud.UpdateWorkload + 13, // 10: buoyant.cloud.WorkloadMessage.deleted:type_name -> buoyant.cloud.DeleteWorkload + 15, // 11: buoyant.cloud.WorkloadMessage.list:type_name -> buoyant.cloud.ListWorkloads 2, // 12: buoyant.cloud.AddWorkload.workload:type_name -> buoyant.cloud.Workload 2, // 13: buoyant.cloud.DeleteWorkload.workload:type_name -> buoyant.cloud.Workload 2, // 14: buoyant.cloud.UpdateWorkload.old_workload:type_name -> buoyant.cloud.Workload 2, // 15: buoyant.cloud.UpdateWorkload.new_workload:type_name -> buoyant.cloud.Workload - 18, // 16: buoyant.cloud.UpdateWorkload.timestamp:type_name -> google.protobuf.Timestamp + 24, // 16: buoyant.cloud.UpdateWorkload.timestamp:type_name -> google.protobuf.Timestamp 2, // 17: buoyant.cloud.ListWorkloads.workloads:type_name -> buoyant.cloud.Workload 1, // 18: buoyant.cloud.Event.auth:type_name -> buoyant.cloud.Auth 2, // 19: buoyant.cloud.Event.owner:type_name -> buoyant.cloud.Workload - 14, // 20: buoyant.cloud.ControlPlaneCerts.issuer_crt_chain:type_name -> buoyant.cloud.CertData - 14, // 21: buoyant.cloud.ControlPlaneCerts.roots:type_name -> buoyant.cloud.CertData - 15, // 22: buoyant.cloud.CertificateInfo.control_plane:type_name -> buoyant.cloud.ControlPlaneCerts + 17, // 20: buoyant.cloud.ControlPlaneCerts.issuer_crt_chain:type_name -> buoyant.cloud.CertData + 17, // 21: buoyant.cloud.ControlPlaneCerts.roots:type_name -> buoyant.cloud.CertData + 18, // 22: buoyant.cloud.CertificateInfo.control_plane:type_name -> buoyant.cloud.ControlPlaneCerts 1, // 23: buoyant.cloud.LinkerdMessage.auth:type_name -> buoyant.cloud.Auth - 16, // 24: buoyant.cloud.LinkerdMessage.crt_info:type_name -> buoyant.cloud.CertificateInfo - 8, // 25: buoyant.cloud.Api.WorkloadStream:input_type -> buoyant.cloud.WorkloadMessage - 13, // 26: buoyant.cloud.Api.AddEvent:input_type -> buoyant.cloud.Event - 17, // 27: buoyant.cloud.Api.LinkerdInfo:input_type -> buoyant.cloud.LinkerdMessage - 0, // 28: buoyant.cloud.Api.WorkloadStream:output_type -> buoyant.cloud.Empty - 0, // 29: buoyant.cloud.Api.AddEvent:output_type -> buoyant.cloud.Empty - 0, // 30: buoyant.cloud.Api.LinkerdInfo:output_type -> buoyant.cloud.Empty - 28, // [28:31] is the sub-list for method output_type - 25, // [25:28] is the sub-list for method input_type - 25, // [25:25] is the sub-list for extension type_name - 25, // [25:25] is the sub-list for extension extendee - 0, // [0:25] is the sub-list for field type_name + 19, // 24: buoyant.cloud.LinkerdMessage.crt_info:type_name -> buoyant.cloud.CertificateInfo + 21, // 25: buoyant.cloud.AgentCommand.get_proxy_diagnostics:type_name -> buoyant.cloud.GetProxyDiagnostics + 1, // 26: buoyant.cloud.ProxyDiagnostic.auth:type_name -> buoyant.cloud.Auth + 7, // 27: buoyant.cloud.ProxyDiagnostic.pod_manifest:type_name -> buoyant.cloud.Pod + 8, // 28: buoyant.cloud.ProxyDiagnostic.linkerd_config_map:type_name -> buoyant.cloud.ConfigMap + 9, // 29: buoyant.cloud.ProxyDiagnostic.nodes:type_name -> buoyant.cloud.Node + 10, // 30: buoyant.cloud.ProxyDiagnostic.k8s_service_manifest:type_name -> buoyant.cloud.Service + 11, // 31: buoyant.cloud.Api.WorkloadStream:input_type -> buoyant.cloud.WorkloadMessage + 16, // 32: buoyant.cloud.Api.AddEvent:input_type -> buoyant.cloud.Event + 20, // 33: buoyant.cloud.Api.LinkerdInfo:input_type -> buoyant.cloud.LinkerdMessage + 1, // 34: buoyant.cloud.Api.ManageAgent:input_type -> buoyant.cloud.Auth + 23, // 35: buoyant.cloud.Api.ProxyDiagnostics:input_type -> buoyant.cloud.ProxyDiagnostic + 0, // 36: buoyant.cloud.Api.WorkloadStream:output_type -> buoyant.cloud.Empty + 0, // 37: buoyant.cloud.Api.AddEvent:output_type -> buoyant.cloud.Empty + 0, // 38: buoyant.cloud.Api.LinkerdInfo:output_type -> buoyant.cloud.Empty + 22, // 39: buoyant.cloud.Api.ManageAgent:output_type -> buoyant.cloud.AgentCommand + 0, // 40: buoyant.cloud.Api.ProxyDiagnostics:output_type -> buoyant.cloud.Empty + 36, // [36:41] is the sub-list for method output_type + 31, // [31:36] is the sub-list for method input_type + 31, // [31:31] is the sub-list for extension type_name + 31, // [31:31] is the sub-list for extension extendee + 0, // [0:31] is the sub-list for field type_name } func init() { file_buoyant_cloud_api_proto_init() } @@ -1434,7 +1879,7 @@ func file_buoyant_cloud_api_proto_init() { } } file_buoyant_cloud_api_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WorkloadMessage); i { + switch v := v.(*ConfigMap); i { case 0: return &v.state case 1: @@ -1446,7 +1891,7 @@ func file_buoyant_cloud_api_proto_init() { } } file_buoyant_cloud_api_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddWorkload); i { + switch v := v.(*Node); i { case 0: return &v.state case 1: @@ -1458,7 +1903,7 @@ func file_buoyant_cloud_api_proto_init() { } } file_buoyant_cloud_api_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DeleteWorkload); i { + switch v := v.(*Service); i { case 0: return &v.state case 1: @@ -1470,7 +1915,7 @@ func file_buoyant_cloud_api_proto_init() { } } file_buoyant_cloud_api_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpdateWorkload); i { + switch v := v.(*WorkloadMessage); i { case 0: return &v.state case 1: @@ -1482,7 +1927,7 @@ func file_buoyant_cloud_api_proto_init() { } } file_buoyant_cloud_api_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListWorkloads); i { + switch v := v.(*AddWorkload); i { case 0: return &v.state case 1: @@ -1494,7 +1939,7 @@ func file_buoyant_cloud_api_proto_init() { } } file_buoyant_cloud_api_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Event); i { + switch v := v.(*DeleteWorkload); i { case 0: return &v.state case 1: @@ -1506,7 +1951,7 @@ func file_buoyant_cloud_api_proto_init() { } } file_buoyant_cloud_api_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CertData); i { + switch v := v.(*UpdateWorkload); i { case 0: return &v.state case 1: @@ -1518,7 +1963,7 @@ func file_buoyant_cloud_api_proto_init() { } } file_buoyant_cloud_api_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ControlPlaneCerts); i { + switch v := v.(*ListWorkloads); i { case 0: return &v.state case 1: @@ -1530,7 +1975,7 @@ func file_buoyant_cloud_api_proto_init() { } } file_buoyant_cloud_api_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CertificateInfo); i { + switch v := v.(*Event); i { case 0: return &v.state case 1: @@ -1542,6 +1987,42 @@ func file_buoyant_cloud_api_proto_init() { } } file_buoyant_cloud_api_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CertData); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_buoyant_cloud_api_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ControlPlaneCerts); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_buoyant_cloud_api_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CertificateInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_buoyant_cloud_api_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*LinkerdMessage); i { case 0: return &v.state @@ -1553,32 +2034,71 @@ func file_buoyant_cloud_api_proto_init() { return nil } } + file_buoyant_cloud_api_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetProxyDiagnostics); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_buoyant_cloud_api_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AgentCommand); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_buoyant_cloud_api_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ProxyDiagnostic); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } file_buoyant_cloud_api_proto_msgTypes[2].OneofWrappers = []interface{}{ (*Workload_Daemonset)(nil), (*Workload_Deployment)(nil), (*Workload_Statefulset)(nil), } - file_buoyant_cloud_api_proto_msgTypes[8].OneofWrappers = []interface{}{ + file_buoyant_cloud_api_proto_msgTypes[11].OneofWrappers = []interface{}{ (*WorkloadMessage_Auth)(nil), (*WorkloadMessage_Added)(nil), (*WorkloadMessage_Updated)(nil), (*WorkloadMessage_Deleted)(nil), (*WorkloadMessage_List)(nil), } - file_buoyant_cloud_api_proto_msgTypes[16].OneofWrappers = []interface{}{ + file_buoyant_cloud_api_proto_msgTypes[19].OneofWrappers = []interface{}{ (*CertificateInfo_ControlPlane)(nil), } - file_buoyant_cloud_api_proto_msgTypes[17].OneofWrappers = []interface{}{ + file_buoyant_cloud_api_proto_msgTypes[20].OneofWrappers = []interface{}{ (*LinkerdMessage_CrtInfo)(nil), } + file_buoyant_cloud_api_proto_msgTypes[22].OneofWrappers = []interface{}{ + (*AgentCommand_GetProxyDiagnostics)(nil), + } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_buoyant_cloud_api_proto_rawDesc, NumEnums: 0, - NumMessages: 18, + NumMessages: 24, NumExtensions: 0, NumServices: 1, }, diff --git a/gen/bcloud/buoyant-cloud-api_grpc.pb.go b/gen/bcloud/buoyant-cloud-api_grpc.pb.go index 3a2e944..9e3b067 100644 --- a/gen/bcloud/buoyant-cloud-api_grpc.pb.go +++ b/gen/bcloud/buoyant-cloud-api_grpc.pb.go @@ -21,6 +21,8 @@ type ApiClient interface { WorkloadStream(ctx context.Context, opts ...grpc.CallOption) (Api_WorkloadStreamClient, error) AddEvent(ctx context.Context, in *Event, opts ...grpc.CallOption) (*Empty, error) LinkerdInfo(ctx context.Context, in *LinkerdMessage, opts ...grpc.CallOption) (*Empty, error) + ManageAgent(ctx context.Context, in *Auth, opts ...grpc.CallOption) (Api_ManageAgentClient, error) + ProxyDiagnostics(ctx context.Context, in *ProxyDiagnostic, opts ...grpc.CallOption) (*Empty, error) } type apiClient struct { @@ -83,6 +85,47 @@ func (c *apiClient) LinkerdInfo(ctx context.Context, in *LinkerdMessage, opts .. return out, nil } +func (c *apiClient) ManageAgent(ctx context.Context, in *Auth, opts ...grpc.CallOption) (Api_ManageAgentClient, error) { + stream, err := c.cc.NewStream(ctx, &Api_ServiceDesc.Streams[1], "/buoyant.cloud.Api/ManageAgent", opts...) + if err != nil { + return nil, err + } + x := &apiManageAgentClient{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 Api_ManageAgentClient interface { + Recv() (*AgentCommand, error) + grpc.ClientStream +} + +type apiManageAgentClient struct { + grpc.ClientStream +} + +func (x *apiManageAgentClient) Recv() (*AgentCommand, error) { + m := new(AgentCommand) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *apiClient) ProxyDiagnostics(ctx context.Context, in *ProxyDiagnostic, opts ...grpc.CallOption) (*Empty, error) { + out := new(Empty) + err := c.cc.Invoke(ctx, "/buoyant.cloud.Api/ProxyDiagnostics", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // ApiServer is the server API for Api service. // All implementations must embed UnimplementedApiServer // for forward compatibility @@ -90,6 +133,8 @@ type ApiServer interface { WorkloadStream(Api_WorkloadStreamServer) error AddEvent(context.Context, *Event) (*Empty, error) LinkerdInfo(context.Context, *LinkerdMessage) (*Empty, error) + ManageAgent(*Auth, Api_ManageAgentServer) error + ProxyDiagnostics(context.Context, *ProxyDiagnostic) (*Empty, error) mustEmbedUnimplementedApiServer() } @@ -106,6 +151,12 @@ func (UnimplementedApiServer) AddEvent(context.Context, *Event) (*Empty, error) func (UnimplementedApiServer) LinkerdInfo(context.Context, *LinkerdMessage) (*Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method LinkerdInfo not implemented") } +func (UnimplementedApiServer) ManageAgent(*Auth, Api_ManageAgentServer) error { + return status.Errorf(codes.Unimplemented, "method ManageAgent not implemented") +} +func (UnimplementedApiServer) ProxyDiagnostics(context.Context, *ProxyDiagnostic) (*Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method ProxyDiagnostics not implemented") +} func (UnimplementedApiServer) mustEmbedUnimplementedApiServer() {} // UnsafeApiServer may be embedded to opt out of forward compatibility for this service. @@ -181,6 +232,45 @@ func _Api_LinkerdInfo_Handler(srv interface{}, ctx context.Context, dec func(int return interceptor(ctx, in, info, handler) } +func _Api_ManageAgent_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(Auth) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(ApiServer).ManageAgent(m, &apiManageAgentServer{stream}) +} + +type Api_ManageAgentServer interface { + Send(*AgentCommand) error + grpc.ServerStream +} + +type apiManageAgentServer struct { + grpc.ServerStream +} + +func (x *apiManageAgentServer) Send(m *AgentCommand) error { + return x.ServerStream.SendMsg(m) +} + +func _Api_ProxyDiagnostics_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ProxyDiagnostic) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ApiServer).ProxyDiagnostics(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/buoyant.cloud.Api/ProxyDiagnostics", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ApiServer).ProxyDiagnostics(ctx, req.(*ProxyDiagnostic)) + } + return interceptor(ctx, in, info, handler) +} + // Api_ServiceDesc is the grpc.ServiceDesc for Api service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -196,6 +286,10 @@ var Api_ServiceDesc = grpc.ServiceDesc{ MethodName: "LinkerdInfo", Handler: _Api_LinkerdInfo_Handler, }, + { + MethodName: "ProxyDiagnostics", + Handler: _Api_ProxyDiagnostics_Handler, + }, }, Streams: []grpc.StreamDesc{ { @@ -203,6 +297,11 @@ var Api_ServiceDesc = grpc.ServiceDesc{ Handler: _Api_WorkloadStream_Handler, ClientStreams: true, }, + { + StreamName: "ManageAgent", + Handler: _Api_ManageAgent_Handler, + ServerStreams: true, + }, }, Metadata: "buoyant-cloud-api.proto", } diff --git a/go.mod b/go.mod index 7da65d6..856adde 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,6 @@ require ( github.com/sirupsen/logrus v1.8.1 github.com/spf13/cobra v1.2.1 google.golang.org/grpc v1.39.0 - google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 // indirect google.golang.org/protobuf v1.27.1 k8s.io/api v0.21.2 k8s.io/apimachinery v0.21.2 diff --git a/go.sum b/go.sum index 0a50aaa..835287f 100644 --- a/go.sum +++ b/go.sum @@ -1251,8 +1251,6 @@ google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.39.0 h1:Klz8I9kdtkIN6EpHHUOMLCYhTn/2WAe5a0s1hcBkdTI= google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 h1:M1YKkFIboKNieVO5DLUEVzQfGwJD30Nv2jfUgzb5UcE= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= diff --git a/proto/buoyant-cloud-api.proto b/proto/buoyant-cloud-api.proto index ed01f77..319f2d5 100644 --- a/proto/buoyant-cloud-api.proto +++ b/proto/buoyant-cloud-api.proto @@ -49,6 +49,18 @@ message Pod { bytes pod = 1; } +message ConfigMap { + bytes config_map = 1; +} + +message Node { + bytes node = 1; +} + +message Service { + bytes service = 1; +} + // // WorkloadStream messages // @@ -125,6 +137,38 @@ message LinkerdMessage { } } +// +// ManageAgent Messages +// + +message GetProxyDiagnostics { + string diagnostic_id = 1; + string pod_name = 2; + string pod_namespace = 3; +} + +message AgentCommand { + oneof command { + GetProxyDiagnostics get_proxy_diagnostics = 1; + } +} + +// +// ProxyDiagnostic Messages +// + + +message ProxyDiagnostic { + Auth auth = 1; + string diagnostic_id = 2; + bytes logs = 3; + repeated bytes metrics = 4; + Pod pod_manifest = 5; + ConfigMap linkerd_config_map = 6; + repeated Node nodes = 7; + Service k8s_service_manifest = 8; +} + // // API // @@ -133,4 +177,6 @@ service Api { rpc WorkloadStream(stream WorkloadMessage) returns (Empty) {} rpc AddEvent(Event) returns (Empty) {} rpc LinkerdInfo(LinkerdMessage) returns (Empty) {} + rpc ManageAgent(Auth) returns (stream AgentCommand) {} + rpc ProxyDiagnostics(ProxyDiagnostic) returns (Empty) {} }