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) {} }