Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d8f45ca520 | |||
| 95f86157b4 | |||
| 93e26d3789 | |||
| 3d2edb7c26 | |||
| bf02935716 |
@@ -38,7 +38,7 @@ func main() {
|
||||
if err != nil {
|
||||
return fmt.Errorf("load config: %w", err)
|
||||
}
|
||||
return agent.Run(cfg)
|
||||
return agent.Run(cfg, version)
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
87
cmd/mcp/dns.go
Normal file
87
cmd/mcp/dns.go
Normal file
@@ -0,0 +1,87 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
mcpv1 "git.wntrmute.dev/mc/mcp/gen/mcp/v1"
|
||||
"git.wntrmute.dev/mc/mcp/internal/config"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func dnsCmd() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "dns",
|
||||
Short: "List all DNS zones and records from MCNS",
|
||||
RunE: runDNS,
|
||||
}
|
||||
}
|
||||
|
||||
func runDNS(_ *cobra.Command, _ []string) error {
|
||||
cfg, err := config.LoadCLIConfig(cfgPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("load config: %w", err)
|
||||
}
|
||||
|
||||
// DNS is centralized — query the first reachable agent.
|
||||
resp, nodeName, err := queryDNS(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(resp.GetZones()) == 0 {
|
||||
fmt.Println("no DNS zones configured")
|
||||
return nil
|
||||
}
|
||||
|
||||
_ = nodeName
|
||||
for i, zone := range resp.GetZones() {
|
||||
if i > 0 {
|
||||
fmt.Println()
|
||||
}
|
||||
fmt.Printf("ZONE: %s\n", zone.GetName())
|
||||
|
||||
if len(zone.GetRecords()) == 0 {
|
||||
fmt.Println(" (no records)")
|
||||
continue
|
||||
}
|
||||
|
||||
w := newTable()
|
||||
_, _ = fmt.Fprintln(w, " NAME\tTYPE\tVALUE\tTTL")
|
||||
for _, r := range zone.GetRecords() {
|
||||
_, _ = fmt.Fprintf(w, " %s\t%s\t%s\t%d\n",
|
||||
r.GetName(), r.GetType(), r.GetValue(), r.GetTtl())
|
||||
}
|
||||
_ = w.Flush()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// queryDNS tries each configured agent and returns the first successful
|
||||
// DNS listing. DNS is centralized so any agent with MCNS configured works.
|
||||
func queryDNS(cfg *config.CLIConfig) (*mcpv1.ListDNSRecordsResponse, string, error) {
|
||||
for _, node := range cfg.Nodes {
|
||||
client, conn, err := dialAgent(node.Address, cfg)
|
||||
if err != nil {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "warning: %s: %v\n", node.Name, err)
|
||||
continue
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
resp, err := client.ListDNSRecords(ctx, &mcpv1.ListDNSRecordsRequest{})
|
||||
cancel()
|
||||
_ = conn.Close()
|
||||
|
||||
if err != nil {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "warning: %s: list DNS: %v\n", node.Name, err)
|
||||
continue
|
||||
}
|
||||
|
||||
return resp, node.Name, nil
|
||||
}
|
||||
|
||||
return nil, "", fmt.Errorf("no reachable agent with DNS configured")
|
||||
}
|
||||
@@ -52,6 +52,8 @@ func main() {
|
||||
root.AddCommand(purgeCmd())
|
||||
root.AddCommand(logsCmd())
|
||||
root.AddCommand(editCmd())
|
||||
root.AddCommand(dnsCmd())
|
||||
root.AddCommand(routeCmd())
|
||||
|
||||
if err := root.Execute(); err != nil {
|
||||
log.Fatal(err)
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
|
||||
toml "github.com/pelletier/go-toml/v2"
|
||||
|
||||
mcpv1 "git.wntrmute.dev/mc/mcp/gen/mcp/v1"
|
||||
"git.wntrmute.dev/mc/mcp/internal/config"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@@ -48,13 +51,35 @@ func runNodeList(_ *cobra.Command, _ []string) error {
|
||||
}
|
||||
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 4, 2, ' ', 0)
|
||||
_, _ = fmt.Fprintln(w, "NAME\tADDRESS")
|
||||
_, _ = fmt.Fprintln(w, "NAME\tADDRESS\tVERSION")
|
||||
for _, n := range cfg.Nodes {
|
||||
_, _ = fmt.Fprintf(w, "%s\t%s\n", n.Name, n.Address)
|
||||
ver := queryAgentVersion(cfg, n.Address)
|
||||
_, _ = fmt.Fprintf(w, "%s\t%s\t%s\n", n.Name, n.Address, ver)
|
||||
}
|
||||
return w.Flush()
|
||||
}
|
||||
|
||||
// queryAgentVersion dials the agent and returns its version, or an error indicator.
|
||||
func queryAgentVersion(cfg *config.CLIConfig, address string) string {
|
||||
client, conn, err := dialAgent(address, cfg)
|
||||
if err != nil {
|
||||
return "error"
|
||||
}
|
||||
defer func() { _ = conn.Close() }()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
resp, err := client.NodeStatus(ctx, &mcpv1.NodeStatusRequest{})
|
||||
if err != nil {
|
||||
return "error"
|
||||
}
|
||||
if resp.AgentVersion == "" {
|
||||
return "unknown"
|
||||
}
|
||||
return resp.AgentVersion
|
||||
}
|
||||
|
||||
func runNodeAdd(_ *cobra.Command, args []string) error {
|
||||
cfg, err := config.LoadCLIConfig(cfgPath)
|
||||
if err != nil {
|
||||
|
||||
212
cmd/mcp/route.go
Normal file
212
cmd/mcp/route.go
Normal file
@@ -0,0 +1,212 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
mcpv1 "git.wntrmute.dev/mc/mcp/gen/mcp/v1"
|
||||
"git.wntrmute.dev/mc/mcp/internal/config"
|
||||
)
|
||||
|
||||
func routeCmd() *cobra.Command {
|
||||
var nodeName string
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "route",
|
||||
Short: "Manage mc-proxy routes",
|
||||
}
|
||||
|
||||
list := &cobra.Command{
|
||||
Use: "list",
|
||||
Short: "List mc-proxy routes",
|
||||
RunE: func(_ *cobra.Command, _ []string) error {
|
||||
return runRouteList(nodeName)
|
||||
},
|
||||
}
|
||||
|
||||
add := &cobra.Command{
|
||||
Use: "add <listener> <hostname> <backend>",
|
||||
Short: "Add a route to mc-proxy",
|
||||
Long: "Add a route. Example: mcp route add -n rift :443 mcq.metacircular.net 100.95.252.120:443",
|
||||
Args: cobra.ExactArgs(3),
|
||||
RunE: func(_ *cobra.Command, args []string) error {
|
||||
return runRouteAdd(nodeName, args)
|
||||
},
|
||||
}
|
||||
add.Flags().String("mode", "l4", "route mode (l4 or l7)")
|
||||
add.Flags().Bool("backend-tls", false, "re-encrypt traffic to backend")
|
||||
|
||||
remove := &cobra.Command{
|
||||
Use: "remove <listener> <hostname>",
|
||||
Short: "Remove a route from mc-proxy",
|
||||
Long: "Remove a route. Example: mcp route remove -n rift :443 mcq.metacircular.net",
|
||||
Args: cobra.ExactArgs(2),
|
||||
RunE: func(_ *cobra.Command, args []string) error {
|
||||
return runRouteRemove(nodeName, args)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.PersistentFlags().StringVarP(&nodeName, "node", "n", "", "target node (required)")
|
||||
|
||||
cmd.AddCommand(list, add, remove)
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runRouteList(nodeName string) error {
|
||||
if nodeName == "" {
|
||||
return runRouteListAll()
|
||||
}
|
||||
|
||||
cfg, err := config.LoadCLIConfig(cfgPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("load config: %w", err)
|
||||
}
|
||||
|
||||
address, err := findNodeAddress(cfg, nodeName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, conn, err := dialAgent(address, cfg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("dial agent: %w", err)
|
||||
}
|
||||
defer func() { _ = conn.Close() }()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
resp, err := client.ListProxyRoutes(ctx, &mcpv1.ListProxyRoutesRequest{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("list routes: %w", err)
|
||||
}
|
||||
|
||||
printRoutes(nodeName, resp)
|
||||
return nil
|
||||
}
|
||||
|
||||
func runRouteListAll() error {
|
||||
first := true
|
||||
return forEachNode(func(node config.NodeConfig, client mcpv1.McpAgentServiceClient) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
resp, err := client.ListProxyRoutes(ctx, &mcpv1.ListProxyRoutesRequest{})
|
||||
if err != nil {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "warning: %s: list routes: %v\n", node.Name, err)
|
||||
return nil
|
||||
}
|
||||
|
||||
if !first {
|
||||
fmt.Println()
|
||||
}
|
||||
first = false
|
||||
|
||||
printRoutes(node.Name, resp)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func printRoutes(nodeName string, resp *mcpv1.ListProxyRoutesResponse) {
|
||||
fmt.Printf("NODE: %s\n", nodeName)
|
||||
fmt.Printf("mc-proxy %s\n", resp.GetVersion())
|
||||
if resp.GetStartedAt() != nil {
|
||||
uptime := time.Since(resp.GetStartedAt().AsTime()).Truncate(time.Second)
|
||||
fmt.Printf("uptime: %s\n", uptime)
|
||||
}
|
||||
fmt.Printf("connections: %d\n", resp.GetTotalConnections())
|
||||
fmt.Println()
|
||||
|
||||
for _, ls := range resp.GetListeners() {
|
||||
fmt.Printf(" %s routes=%d active=%d\n",
|
||||
ls.GetAddr(), ls.GetRouteCount(), ls.GetActiveConnections())
|
||||
for _, r := range ls.GetRoutes() {
|
||||
mode := r.GetMode()
|
||||
if mode == "" {
|
||||
mode = "l4"
|
||||
}
|
||||
extra := ""
|
||||
if r.GetBackendTls() {
|
||||
extra = " (re-encrypt)"
|
||||
}
|
||||
fmt.Printf(" %s %s → %s%s\n", mode, r.GetHostname(), r.GetBackend(), extra)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func runRouteAdd(nodeName string, args []string) error {
|
||||
if nodeName == "" {
|
||||
return fmt.Errorf("--node is required")
|
||||
}
|
||||
|
||||
cfg, err := config.LoadCLIConfig(cfgPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("load config: %w", err)
|
||||
}
|
||||
|
||||
address, err := findNodeAddress(cfg, nodeName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, conn, err := dialAgent(address, cfg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("dial agent: %w", err)
|
||||
}
|
||||
defer func() { _ = conn.Close() }()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
_, err = client.AddProxyRoute(ctx, &mcpv1.AddProxyRouteRequest{
|
||||
ListenerAddr: args[0],
|
||||
Hostname: args[1],
|
||||
Backend: args[2],
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("add route: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Added route: %s → %s on %s (%s)\n", args[1], args[2], args[0], nodeName)
|
||||
return nil
|
||||
}
|
||||
|
||||
func runRouteRemove(nodeName string, args []string) error {
|
||||
if nodeName == "" {
|
||||
return fmt.Errorf("--node is required")
|
||||
}
|
||||
|
||||
cfg, err := config.LoadCLIConfig(cfgPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("load config: %w", err)
|
||||
}
|
||||
|
||||
address, err := findNodeAddress(cfg, nodeName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, conn, err := dialAgent(address, cfg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("dial agent: %w", err)
|
||||
}
|
||||
defer func() { _ = conn.Close() }()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
_, err = client.RemoveProxyRoute(ctx, &mcpv1.RemoveProxyRouteRequest{
|
||||
ListenerAddr: args[0],
|
||||
Hostname: args[1],
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("remove route: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Removed route: %s from %s (%s)\n", args[1], args[0], nodeName)
|
||||
return nil
|
||||
}
|
||||
@@ -1926,6 +1926,7 @@ type NodeStatusResponse struct {
|
||||
MemoryFreeBytes uint64 `protobuf:"varint,9,opt,name=memory_free_bytes,json=memoryFreeBytes,proto3" json:"memory_free_bytes,omitempty"`
|
||||
CpuUsagePercent float64 `protobuf:"fixed64,10,opt,name=cpu_usage_percent,json=cpuUsagePercent,proto3" json:"cpu_usage_percent,omitempty"`
|
||||
UptimeSince *timestamppb.Timestamp `protobuf:"bytes,11,opt,name=uptime_since,json=uptimeSince,proto3" json:"uptime_since,omitempty"`
|
||||
AgentVersion string `protobuf:"bytes,12,opt,name=agent_version,json=agentVersion,proto3" json:"agent_version,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
@@ -2037,6 +2038,13 @@ func (x *NodeStatusResponse) GetUptimeSince() *timestamppb.Timestamp {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *NodeStatusResponse) GetAgentVersion() string {
|
||||
if x != nil {
|
||||
return x.AgentVersion
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type PurgeRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// Service name (empty = all services).
|
||||
@@ -2352,6 +2360,654 @@ func (x *LogsResponse) GetData() []byte {
|
||||
return nil
|
||||
}
|
||||
|
||||
type ListDNSRecordsRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ListDNSRecordsRequest) Reset() {
|
||||
*x = ListDNSRecordsRequest{}
|
||||
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[41]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ListDNSRecordsRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ListDNSRecordsRequest) ProtoMessage() {}
|
||||
|
||||
func (x *ListDNSRecordsRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[41]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ListDNSRecordsRequest.ProtoReflect.Descriptor instead.
|
||||
func (*ListDNSRecordsRequest) Descriptor() ([]byte, []int) {
|
||||
return file_proto_mcp_v1_mcp_proto_rawDescGZIP(), []int{41}
|
||||
}
|
||||
|
||||
type DNSZone struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Records []*DNSRecord `protobuf:"bytes,2,rep,name=records,proto3" json:"records,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *DNSZone) Reset() {
|
||||
*x = DNSZone{}
|
||||
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[42]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *DNSZone) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*DNSZone) ProtoMessage() {}
|
||||
|
||||
func (x *DNSZone) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[42]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use DNSZone.ProtoReflect.Descriptor instead.
|
||||
func (*DNSZone) Descriptor() ([]byte, []int) {
|
||||
return file_proto_mcp_v1_mcp_proto_rawDescGZIP(), []int{42}
|
||||
}
|
||||
|
||||
func (x *DNSZone) GetName() string {
|
||||
if x != nil {
|
||||
return x.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *DNSZone) GetRecords() []*DNSRecord {
|
||||
if x != nil {
|
||||
return x.Records
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type DNSRecord struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Type string `protobuf:"bytes,3,opt,name=type,proto3" json:"type,omitempty"`
|
||||
Value string `protobuf:"bytes,4,opt,name=value,proto3" json:"value,omitempty"`
|
||||
Ttl int32 `protobuf:"varint,5,opt,name=ttl,proto3" json:"ttl,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *DNSRecord) Reset() {
|
||||
*x = DNSRecord{}
|
||||
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[43]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *DNSRecord) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*DNSRecord) ProtoMessage() {}
|
||||
|
||||
func (x *DNSRecord) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[43]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use DNSRecord.ProtoReflect.Descriptor instead.
|
||||
func (*DNSRecord) Descriptor() ([]byte, []int) {
|
||||
return file_proto_mcp_v1_mcp_proto_rawDescGZIP(), []int{43}
|
||||
}
|
||||
|
||||
func (x *DNSRecord) GetId() int64 {
|
||||
if x != nil {
|
||||
return x.Id
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *DNSRecord) GetName() string {
|
||||
if x != nil {
|
||||
return x.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *DNSRecord) GetType() string {
|
||||
if x != nil {
|
||||
return x.Type
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *DNSRecord) GetValue() string {
|
||||
if x != nil {
|
||||
return x.Value
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *DNSRecord) GetTtl() int32 {
|
||||
if x != nil {
|
||||
return x.Ttl
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type ListDNSRecordsResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Zones []*DNSZone `protobuf:"bytes,1,rep,name=zones,proto3" json:"zones,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ListDNSRecordsResponse) Reset() {
|
||||
*x = ListDNSRecordsResponse{}
|
||||
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[44]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ListDNSRecordsResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ListDNSRecordsResponse) ProtoMessage() {}
|
||||
|
||||
func (x *ListDNSRecordsResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[44]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ListDNSRecordsResponse.ProtoReflect.Descriptor instead.
|
||||
func (*ListDNSRecordsResponse) Descriptor() ([]byte, []int) {
|
||||
return file_proto_mcp_v1_mcp_proto_rawDescGZIP(), []int{44}
|
||||
}
|
||||
|
||||
func (x *ListDNSRecordsResponse) GetZones() []*DNSZone {
|
||||
if x != nil {
|
||||
return x.Zones
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ListProxyRoutesRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ListProxyRoutesRequest) Reset() {
|
||||
*x = ListProxyRoutesRequest{}
|
||||
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[45]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ListProxyRoutesRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ListProxyRoutesRequest) ProtoMessage() {}
|
||||
|
||||
func (x *ListProxyRoutesRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[45]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ListProxyRoutesRequest.ProtoReflect.Descriptor instead.
|
||||
func (*ListProxyRoutesRequest) Descriptor() ([]byte, []int) {
|
||||
return file_proto_mcp_v1_mcp_proto_rawDescGZIP(), []int{45}
|
||||
}
|
||||
|
||||
type ProxyRouteInfo struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Hostname string `protobuf:"bytes,1,opt,name=hostname,proto3" json:"hostname,omitempty"`
|
||||
Backend string `protobuf:"bytes,2,opt,name=backend,proto3" json:"backend,omitempty"`
|
||||
Mode string `protobuf:"bytes,3,opt,name=mode,proto3" json:"mode,omitempty"`
|
||||
BackendTls bool `protobuf:"varint,4,opt,name=backend_tls,json=backendTls,proto3" json:"backend_tls,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ProxyRouteInfo) Reset() {
|
||||
*x = ProxyRouteInfo{}
|
||||
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[46]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ProxyRouteInfo) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ProxyRouteInfo) ProtoMessage() {}
|
||||
|
||||
func (x *ProxyRouteInfo) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[46]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ProxyRouteInfo.ProtoReflect.Descriptor instead.
|
||||
func (*ProxyRouteInfo) Descriptor() ([]byte, []int) {
|
||||
return file_proto_mcp_v1_mcp_proto_rawDescGZIP(), []int{46}
|
||||
}
|
||||
|
||||
func (x *ProxyRouteInfo) GetHostname() string {
|
||||
if x != nil {
|
||||
return x.Hostname
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ProxyRouteInfo) GetBackend() string {
|
||||
if x != nil {
|
||||
return x.Backend
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ProxyRouteInfo) GetMode() string {
|
||||
if x != nil {
|
||||
return x.Mode
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ProxyRouteInfo) GetBackendTls() bool {
|
||||
if x != nil {
|
||||
return x.BackendTls
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type ProxyListenerInfo struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Addr string `protobuf:"bytes,1,opt,name=addr,proto3" json:"addr,omitempty"`
|
||||
RouteCount int32 `protobuf:"varint,2,opt,name=route_count,json=routeCount,proto3" json:"route_count,omitempty"`
|
||||
ActiveConnections int64 `protobuf:"varint,3,opt,name=active_connections,json=activeConnections,proto3" json:"active_connections,omitempty"`
|
||||
Routes []*ProxyRouteInfo `protobuf:"bytes,4,rep,name=routes,proto3" json:"routes,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ProxyListenerInfo) Reset() {
|
||||
*x = ProxyListenerInfo{}
|
||||
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[47]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ProxyListenerInfo) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ProxyListenerInfo) ProtoMessage() {}
|
||||
|
||||
func (x *ProxyListenerInfo) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[47]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ProxyListenerInfo.ProtoReflect.Descriptor instead.
|
||||
func (*ProxyListenerInfo) Descriptor() ([]byte, []int) {
|
||||
return file_proto_mcp_v1_mcp_proto_rawDescGZIP(), []int{47}
|
||||
}
|
||||
|
||||
func (x *ProxyListenerInfo) GetAddr() string {
|
||||
if x != nil {
|
||||
return x.Addr
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ProxyListenerInfo) GetRouteCount() int32 {
|
||||
if x != nil {
|
||||
return x.RouteCount
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *ProxyListenerInfo) GetActiveConnections() int64 {
|
||||
if x != nil {
|
||||
return x.ActiveConnections
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *ProxyListenerInfo) GetRoutes() []*ProxyRouteInfo {
|
||||
if x != nil {
|
||||
return x.Routes
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ListProxyRoutesResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"`
|
||||
TotalConnections int64 `protobuf:"varint,2,opt,name=total_connections,json=totalConnections,proto3" json:"total_connections,omitempty"`
|
||||
StartedAt *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=started_at,json=startedAt,proto3" json:"started_at,omitempty"`
|
||||
Listeners []*ProxyListenerInfo `protobuf:"bytes,4,rep,name=listeners,proto3" json:"listeners,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ListProxyRoutesResponse) Reset() {
|
||||
*x = ListProxyRoutesResponse{}
|
||||
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[48]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ListProxyRoutesResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ListProxyRoutesResponse) ProtoMessage() {}
|
||||
|
||||
func (x *ListProxyRoutesResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[48]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ListProxyRoutesResponse.ProtoReflect.Descriptor instead.
|
||||
func (*ListProxyRoutesResponse) Descriptor() ([]byte, []int) {
|
||||
return file_proto_mcp_v1_mcp_proto_rawDescGZIP(), []int{48}
|
||||
}
|
||||
|
||||
func (x *ListProxyRoutesResponse) GetVersion() string {
|
||||
if x != nil {
|
||||
return x.Version
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ListProxyRoutesResponse) GetTotalConnections() int64 {
|
||||
if x != nil {
|
||||
return x.TotalConnections
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *ListProxyRoutesResponse) GetStartedAt() *timestamppb.Timestamp {
|
||||
if x != nil {
|
||||
return x.StartedAt
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ListProxyRoutesResponse) GetListeners() []*ProxyListenerInfo {
|
||||
if x != nil {
|
||||
return x.Listeners
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type AddProxyRouteRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
ListenerAddr string `protobuf:"bytes,1,opt,name=listener_addr,json=listenerAddr,proto3" json:"listener_addr,omitempty"` // e.g. ":443"
|
||||
Hostname string `protobuf:"bytes,2,opt,name=hostname,proto3" json:"hostname,omitempty"`
|
||||
Backend string `protobuf:"bytes,3,opt,name=backend,proto3" json:"backend,omitempty"`
|
||||
Mode string `protobuf:"bytes,4,opt,name=mode,proto3" json:"mode,omitempty"` // "l4" or "l7"
|
||||
BackendTls bool `protobuf:"varint,5,opt,name=backend_tls,json=backendTls,proto3" json:"backend_tls,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *AddProxyRouteRequest) Reset() {
|
||||
*x = AddProxyRouteRequest{}
|
||||
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[49]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *AddProxyRouteRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*AddProxyRouteRequest) ProtoMessage() {}
|
||||
|
||||
func (x *AddProxyRouteRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[49]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use AddProxyRouteRequest.ProtoReflect.Descriptor instead.
|
||||
func (*AddProxyRouteRequest) Descriptor() ([]byte, []int) {
|
||||
return file_proto_mcp_v1_mcp_proto_rawDescGZIP(), []int{49}
|
||||
}
|
||||
|
||||
func (x *AddProxyRouteRequest) GetListenerAddr() string {
|
||||
if x != nil {
|
||||
return x.ListenerAddr
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *AddProxyRouteRequest) GetHostname() string {
|
||||
if x != nil {
|
||||
return x.Hostname
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *AddProxyRouteRequest) GetBackend() string {
|
||||
if x != nil {
|
||||
return x.Backend
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *AddProxyRouteRequest) GetMode() string {
|
||||
if x != nil {
|
||||
return x.Mode
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *AddProxyRouteRequest) GetBackendTls() bool {
|
||||
if x != nil {
|
||||
return x.BackendTls
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type AddProxyRouteResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *AddProxyRouteResponse) Reset() {
|
||||
*x = AddProxyRouteResponse{}
|
||||
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[50]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *AddProxyRouteResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*AddProxyRouteResponse) ProtoMessage() {}
|
||||
|
||||
func (x *AddProxyRouteResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[50]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use AddProxyRouteResponse.ProtoReflect.Descriptor instead.
|
||||
func (*AddProxyRouteResponse) Descriptor() ([]byte, []int) {
|
||||
return file_proto_mcp_v1_mcp_proto_rawDescGZIP(), []int{50}
|
||||
}
|
||||
|
||||
type RemoveProxyRouteRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
ListenerAddr string `protobuf:"bytes,1,opt,name=listener_addr,json=listenerAddr,proto3" json:"listener_addr,omitempty"` // e.g. ":443"
|
||||
Hostname string `protobuf:"bytes,2,opt,name=hostname,proto3" json:"hostname,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *RemoveProxyRouteRequest) Reset() {
|
||||
*x = RemoveProxyRouteRequest{}
|
||||
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[51]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *RemoveProxyRouteRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*RemoveProxyRouteRequest) ProtoMessage() {}
|
||||
|
||||
func (x *RemoveProxyRouteRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[51]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use RemoveProxyRouteRequest.ProtoReflect.Descriptor instead.
|
||||
func (*RemoveProxyRouteRequest) Descriptor() ([]byte, []int) {
|
||||
return file_proto_mcp_v1_mcp_proto_rawDescGZIP(), []int{51}
|
||||
}
|
||||
|
||||
func (x *RemoveProxyRouteRequest) GetListenerAddr() string {
|
||||
if x != nil {
|
||||
return x.ListenerAddr
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *RemoveProxyRouteRequest) GetHostname() string {
|
||||
if x != nil {
|
||||
return x.Hostname
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type RemoveProxyRouteResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *RemoveProxyRouteResponse) Reset() {
|
||||
*x = RemoveProxyRouteResponse{}
|
||||
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[52]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *RemoveProxyRouteResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*RemoveProxyRouteResponse) ProtoMessage() {}
|
||||
|
||||
func (x *RemoveProxyRouteResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_mcp_v1_mcp_proto_msgTypes[52]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use RemoveProxyRouteResponse.ProtoReflect.Descriptor instead.
|
||||
func (*RemoveProxyRouteResponse) Descriptor() ([]byte, []int) {
|
||||
return file_proto_mcp_v1_mcp_proto_rawDescGZIP(), []int{52}
|
||||
}
|
||||
|
||||
var File_proto_mcp_v1_mcp_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_proto_mcp_v1_mcp_proto_rawDesc = "" +
|
||||
@@ -2474,7 +3130,7 @@ const file_proto_mcp_v1_mcp_proto_rawDesc = "" +
|
||||
"\acontent\x18\x01 \x01(\fR\acontent\x12\x12\n" +
|
||||
"\x04mode\x18\x02 \x01(\rR\x04mode\x12\x14\n" +
|
||||
"\x05error\x18\x03 \x01(\tR\x05error\"\x13\n" +
|
||||
"\x11NodeStatusRequest\"\xd9\x03\n" +
|
||||
"\x11NodeStatusRequest\"\xfe\x03\n" +
|
||||
"\x12NodeStatusResponse\x12\x1b\n" +
|
||||
"\tnode_name\x18\x01 \x01(\tR\bnodeName\x12\x18\n" +
|
||||
"\aruntime\x18\x02 \x01(\tR\aruntime\x12'\n" +
|
||||
@@ -2487,7 +3143,8 @@ const file_proto_mcp_v1_mcp_proto_rawDesc = "" +
|
||||
"\x11memory_free_bytes\x18\t \x01(\x04R\x0fmemoryFreeBytes\x12*\n" +
|
||||
"\x11cpu_usage_percent\x18\n" +
|
||||
" \x01(\x01R\x0fcpuUsagePercent\x12=\n" +
|
||||
"\fuptime_since\x18\v \x01(\v2\x1a.google.protobuf.TimestampR\vuptimeSince\"\x8e\x01\n" +
|
||||
"\fuptime_since\x18\v \x01(\v2\x1a.google.protobuf.TimestampR\vuptimeSince\x12#\n" +
|
||||
"\ragent_version\x18\f \x01(\tR\fagentVersion\"\x8e\x01\n" +
|
||||
"\fPurgeRequest\x12\x18\n" +
|
||||
"\aservice\x18\x01 \x01(\tR\aservice\x12\x1c\n" +
|
||||
"\tcomponent\x18\x02 \x01(\tR\tcomponent\x12\x17\n" +
|
||||
@@ -2510,7 +3167,50 @@ const file_proto_mcp_v1_mcp_proto_rawDesc = "" +
|
||||
"timestamps\x12\x14\n" +
|
||||
"\x05since\x18\x06 \x01(\tR\x05since\"\"\n" +
|
||||
"\fLogsResponse\x12\x12\n" +
|
||||
"\x04data\x18\x01 \x01(\fR\x04data2\xc8\b\n" +
|
||||
"\x04data\x18\x01 \x01(\fR\x04data\"\x17\n" +
|
||||
"\x15ListDNSRecordsRequest\"J\n" +
|
||||
"\aDNSZone\x12\x12\n" +
|
||||
"\x04name\x18\x01 \x01(\tR\x04name\x12+\n" +
|
||||
"\arecords\x18\x02 \x03(\v2\x11.mcp.v1.DNSRecordR\arecords\"k\n" +
|
||||
"\tDNSRecord\x12\x0e\n" +
|
||||
"\x02id\x18\x01 \x01(\x03R\x02id\x12\x12\n" +
|
||||
"\x04name\x18\x02 \x01(\tR\x04name\x12\x12\n" +
|
||||
"\x04type\x18\x03 \x01(\tR\x04type\x12\x14\n" +
|
||||
"\x05value\x18\x04 \x01(\tR\x05value\x12\x10\n" +
|
||||
"\x03ttl\x18\x05 \x01(\x05R\x03ttl\"?\n" +
|
||||
"\x16ListDNSRecordsResponse\x12%\n" +
|
||||
"\x05zones\x18\x01 \x03(\v2\x0f.mcp.v1.DNSZoneR\x05zones\"\x18\n" +
|
||||
"\x16ListProxyRoutesRequest\"{\n" +
|
||||
"\x0eProxyRouteInfo\x12\x1a\n" +
|
||||
"\bhostname\x18\x01 \x01(\tR\bhostname\x12\x18\n" +
|
||||
"\abackend\x18\x02 \x01(\tR\abackend\x12\x12\n" +
|
||||
"\x04mode\x18\x03 \x01(\tR\x04mode\x12\x1f\n" +
|
||||
"\vbackend_tls\x18\x04 \x01(\bR\n" +
|
||||
"backendTls\"\xa7\x01\n" +
|
||||
"\x11ProxyListenerInfo\x12\x12\n" +
|
||||
"\x04addr\x18\x01 \x01(\tR\x04addr\x12\x1f\n" +
|
||||
"\vroute_count\x18\x02 \x01(\x05R\n" +
|
||||
"routeCount\x12-\n" +
|
||||
"\x12active_connections\x18\x03 \x01(\x03R\x11activeConnections\x12.\n" +
|
||||
"\x06routes\x18\x04 \x03(\v2\x16.mcp.v1.ProxyRouteInfoR\x06routes\"\xd4\x01\n" +
|
||||
"\x17ListProxyRoutesResponse\x12\x18\n" +
|
||||
"\aversion\x18\x01 \x01(\tR\aversion\x12+\n" +
|
||||
"\x11total_connections\x18\x02 \x01(\x03R\x10totalConnections\x129\n" +
|
||||
"\n" +
|
||||
"started_at\x18\x03 \x01(\v2\x1a.google.protobuf.TimestampR\tstartedAt\x127\n" +
|
||||
"\tlisteners\x18\x04 \x03(\v2\x19.mcp.v1.ProxyListenerInfoR\tlisteners\"\xa6\x01\n" +
|
||||
"\x14AddProxyRouteRequest\x12#\n" +
|
||||
"\rlistener_addr\x18\x01 \x01(\tR\flistenerAddr\x12\x1a\n" +
|
||||
"\bhostname\x18\x02 \x01(\tR\bhostname\x12\x18\n" +
|
||||
"\abackend\x18\x03 \x01(\tR\abackend\x12\x12\n" +
|
||||
"\x04mode\x18\x04 \x01(\tR\x04mode\x12\x1f\n" +
|
||||
"\vbackend_tls\x18\x05 \x01(\bR\n" +
|
||||
"backendTls\"\x17\n" +
|
||||
"\x15AddProxyRouteResponse\"Z\n" +
|
||||
"\x17RemoveProxyRouteRequest\x12#\n" +
|
||||
"\rlistener_addr\x18\x01 \x01(\tR\flistenerAddr\x12\x1a\n" +
|
||||
"\bhostname\x18\x02 \x01(\tR\bhostname\"\x1a\n" +
|
||||
"\x18RemoveProxyRouteResponse2\x92\v\n" +
|
||||
"\x0fMcpAgentService\x127\n" +
|
||||
"\x06Deploy\x12\x15.mcp.v1.DeployRequest\x1a\x16.mcp.v1.DeployResponse\x12R\n" +
|
||||
"\x0fUndeployService\x12\x1e.mcp.v1.UndeployServiceRequest\x1a\x1f.mcp.v1.UndeployServiceResponse\x12F\n" +
|
||||
@@ -2526,7 +3226,11 @@ const file_proto_mcp_v1_mcp_proto_rawDesc = "" +
|
||||
"\bPushFile\x12\x17.mcp.v1.PushFileRequest\x1a\x18.mcp.v1.PushFileResponse\x12=\n" +
|
||||
"\bPullFile\x12\x17.mcp.v1.PullFileRequest\x1a\x18.mcp.v1.PullFileResponse\x12C\n" +
|
||||
"\n" +
|
||||
"NodeStatus\x12\x19.mcp.v1.NodeStatusRequest\x1a\x1a.mcp.v1.NodeStatusResponse\x123\n" +
|
||||
"NodeStatus\x12\x19.mcp.v1.NodeStatusRequest\x1a\x1a.mcp.v1.NodeStatusResponse\x12O\n" +
|
||||
"\x0eListDNSRecords\x12\x1d.mcp.v1.ListDNSRecordsRequest\x1a\x1e.mcp.v1.ListDNSRecordsResponse\x12R\n" +
|
||||
"\x0fListProxyRoutes\x12\x1e.mcp.v1.ListProxyRoutesRequest\x1a\x1f.mcp.v1.ListProxyRoutesResponse\x12L\n" +
|
||||
"\rAddProxyRoute\x12\x1c.mcp.v1.AddProxyRouteRequest\x1a\x1d.mcp.v1.AddProxyRouteResponse\x12U\n" +
|
||||
"\x10RemoveProxyRoute\x12\x1f.mcp.v1.RemoveProxyRouteRequest\x1a .mcp.v1.RemoveProxyRouteResponse\x123\n" +
|
||||
"\x04Logs\x12\x13.mcp.v1.LogsRequest\x1a\x14.mcp.v1.LogsResponse0\x01B*Z(git.wntrmute.dev/mc/mcp/gen/mcp/v1;mcpv1b\x06proto3"
|
||||
|
||||
var (
|
||||
@@ -2541,7 +3245,7 @@ func file_proto_mcp_v1_mcp_proto_rawDescGZIP() []byte {
|
||||
return file_proto_mcp_v1_mcp_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_proto_mcp_v1_mcp_proto_msgTypes = make([]protoimpl.MessageInfo, 41)
|
||||
var file_proto_mcp_v1_mcp_proto_msgTypes = make([]protoimpl.MessageInfo, 53)
|
||||
var file_proto_mcp_v1_mcp_proto_goTypes = []any{
|
||||
(*RouteSpec)(nil), // 0: mcp.v1.RouteSpec
|
||||
(*ComponentSpec)(nil), // 1: mcp.v1.ComponentSpec
|
||||
@@ -2584,7 +3288,19 @@ var file_proto_mcp_v1_mcp_proto_goTypes = []any{
|
||||
(*PurgeResult)(nil), // 38: mcp.v1.PurgeResult
|
||||
(*LogsRequest)(nil), // 39: mcp.v1.LogsRequest
|
||||
(*LogsResponse)(nil), // 40: mcp.v1.LogsResponse
|
||||
(*timestamppb.Timestamp)(nil), // 41: google.protobuf.Timestamp
|
||||
(*ListDNSRecordsRequest)(nil), // 41: mcp.v1.ListDNSRecordsRequest
|
||||
(*DNSZone)(nil), // 42: mcp.v1.DNSZone
|
||||
(*DNSRecord)(nil), // 43: mcp.v1.DNSRecord
|
||||
(*ListDNSRecordsResponse)(nil), // 44: mcp.v1.ListDNSRecordsResponse
|
||||
(*ListProxyRoutesRequest)(nil), // 45: mcp.v1.ListProxyRoutesRequest
|
||||
(*ProxyRouteInfo)(nil), // 46: mcp.v1.ProxyRouteInfo
|
||||
(*ProxyListenerInfo)(nil), // 47: mcp.v1.ProxyListenerInfo
|
||||
(*ListProxyRoutesResponse)(nil), // 48: mcp.v1.ListProxyRoutesResponse
|
||||
(*AddProxyRouteRequest)(nil), // 49: mcp.v1.AddProxyRouteRequest
|
||||
(*AddProxyRouteResponse)(nil), // 50: mcp.v1.AddProxyRouteResponse
|
||||
(*RemoveProxyRouteRequest)(nil), // 51: mcp.v1.RemoveProxyRouteRequest
|
||||
(*RemoveProxyRouteResponse)(nil), // 52: mcp.v1.RemoveProxyRouteResponse
|
||||
(*timestamppb.Timestamp)(nil), // 53: google.protobuf.Timestamp
|
||||
}
|
||||
var file_proto_mcp_v1_mcp_proto_depIdxs = []int32{
|
||||
0, // 0: mcp.v1.ComponentSpec.routes:type_name -> mcp.v1.RouteSpec
|
||||
@@ -2598,51 +3314,64 @@ var file_proto_mcp_v1_mcp_proto_depIdxs = []int32{
|
||||
2, // 8: mcp.v1.SyncDesiredStateRequest.services:type_name -> mcp.v1.ServiceSpec
|
||||
16, // 9: mcp.v1.SyncDesiredStateResponse.results:type_name -> mcp.v1.ServiceSyncResult
|
||||
19, // 10: mcp.v1.ServiceInfo.components:type_name -> mcp.v1.ComponentInfo
|
||||
41, // 11: mcp.v1.ComponentInfo.started:type_name -> google.protobuf.Timestamp
|
||||
53, // 11: mcp.v1.ComponentInfo.started:type_name -> google.protobuf.Timestamp
|
||||
18, // 12: mcp.v1.ListServicesResponse.services:type_name -> mcp.v1.ServiceInfo
|
||||
41, // 13: mcp.v1.EventInfo.timestamp:type_name -> google.protobuf.Timestamp
|
||||
53, // 13: mcp.v1.EventInfo.timestamp:type_name -> google.protobuf.Timestamp
|
||||
18, // 14: mcp.v1.GetServiceStatusResponse.services:type_name -> mcp.v1.ServiceInfo
|
||||
22, // 15: mcp.v1.GetServiceStatusResponse.drift:type_name -> mcp.v1.DriftInfo
|
||||
23, // 16: mcp.v1.GetServiceStatusResponse.recent_events:type_name -> mcp.v1.EventInfo
|
||||
18, // 17: mcp.v1.LiveCheckResponse.services:type_name -> mcp.v1.ServiceInfo
|
||||
28, // 18: mcp.v1.AdoptContainersResponse.results:type_name -> mcp.v1.AdoptResult
|
||||
41, // 19: mcp.v1.NodeStatusResponse.uptime_since:type_name -> google.protobuf.Timestamp
|
||||
53, // 19: mcp.v1.NodeStatusResponse.uptime_since:type_name -> google.protobuf.Timestamp
|
||||
38, // 20: mcp.v1.PurgeResponse.results:type_name -> mcp.v1.PurgeResult
|
||||
3, // 21: mcp.v1.McpAgentService.Deploy:input_type -> mcp.v1.DeployRequest
|
||||
12, // 22: mcp.v1.McpAgentService.UndeployService:input_type -> mcp.v1.UndeployServiceRequest
|
||||
6, // 23: mcp.v1.McpAgentService.StopService:input_type -> mcp.v1.StopServiceRequest
|
||||
8, // 24: mcp.v1.McpAgentService.StartService:input_type -> mcp.v1.StartServiceRequest
|
||||
10, // 25: mcp.v1.McpAgentService.RestartService:input_type -> mcp.v1.RestartServiceRequest
|
||||
14, // 26: mcp.v1.McpAgentService.SyncDesiredState:input_type -> mcp.v1.SyncDesiredStateRequest
|
||||
17, // 27: mcp.v1.McpAgentService.ListServices:input_type -> mcp.v1.ListServicesRequest
|
||||
21, // 28: mcp.v1.McpAgentService.GetServiceStatus:input_type -> mcp.v1.GetServiceStatusRequest
|
||||
25, // 29: mcp.v1.McpAgentService.LiveCheck:input_type -> mcp.v1.LiveCheckRequest
|
||||
27, // 30: mcp.v1.McpAgentService.AdoptContainers:input_type -> mcp.v1.AdoptContainersRequest
|
||||
36, // 31: mcp.v1.McpAgentService.PurgeComponent:input_type -> mcp.v1.PurgeRequest
|
||||
30, // 32: mcp.v1.McpAgentService.PushFile:input_type -> mcp.v1.PushFileRequest
|
||||
32, // 33: mcp.v1.McpAgentService.PullFile:input_type -> mcp.v1.PullFileRequest
|
||||
34, // 34: mcp.v1.McpAgentService.NodeStatus:input_type -> mcp.v1.NodeStatusRequest
|
||||
39, // 35: mcp.v1.McpAgentService.Logs:input_type -> mcp.v1.LogsRequest
|
||||
4, // 36: mcp.v1.McpAgentService.Deploy:output_type -> mcp.v1.DeployResponse
|
||||
13, // 37: mcp.v1.McpAgentService.UndeployService:output_type -> mcp.v1.UndeployServiceResponse
|
||||
7, // 38: mcp.v1.McpAgentService.StopService:output_type -> mcp.v1.StopServiceResponse
|
||||
9, // 39: mcp.v1.McpAgentService.StartService:output_type -> mcp.v1.StartServiceResponse
|
||||
11, // 40: mcp.v1.McpAgentService.RestartService:output_type -> mcp.v1.RestartServiceResponse
|
||||
15, // 41: mcp.v1.McpAgentService.SyncDesiredState:output_type -> mcp.v1.SyncDesiredStateResponse
|
||||
20, // 42: mcp.v1.McpAgentService.ListServices:output_type -> mcp.v1.ListServicesResponse
|
||||
24, // 43: mcp.v1.McpAgentService.GetServiceStatus:output_type -> mcp.v1.GetServiceStatusResponse
|
||||
26, // 44: mcp.v1.McpAgentService.LiveCheck:output_type -> mcp.v1.LiveCheckResponse
|
||||
29, // 45: mcp.v1.McpAgentService.AdoptContainers:output_type -> mcp.v1.AdoptContainersResponse
|
||||
37, // 46: mcp.v1.McpAgentService.PurgeComponent:output_type -> mcp.v1.PurgeResponse
|
||||
31, // 47: mcp.v1.McpAgentService.PushFile:output_type -> mcp.v1.PushFileResponse
|
||||
33, // 48: mcp.v1.McpAgentService.PullFile:output_type -> mcp.v1.PullFileResponse
|
||||
35, // 49: mcp.v1.McpAgentService.NodeStatus:output_type -> mcp.v1.NodeStatusResponse
|
||||
40, // 50: mcp.v1.McpAgentService.Logs:output_type -> mcp.v1.LogsResponse
|
||||
36, // [36:51] is the sub-list for method output_type
|
||||
21, // [21:36] is the sub-list for method input_type
|
||||
21, // [21:21] is the sub-list for extension type_name
|
||||
21, // [21:21] is the sub-list for extension extendee
|
||||
0, // [0:21] is the sub-list for field type_name
|
||||
43, // 21: mcp.v1.DNSZone.records:type_name -> mcp.v1.DNSRecord
|
||||
42, // 22: mcp.v1.ListDNSRecordsResponse.zones:type_name -> mcp.v1.DNSZone
|
||||
46, // 23: mcp.v1.ProxyListenerInfo.routes:type_name -> mcp.v1.ProxyRouteInfo
|
||||
53, // 24: mcp.v1.ListProxyRoutesResponse.started_at:type_name -> google.protobuf.Timestamp
|
||||
47, // 25: mcp.v1.ListProxyRoutesResponse.listeners:type_name -> mcp.v1.ProxyListenerInfo
|
||||
3, // 26: mcp.v1.McpAgentService.Deploy:input_type -> mcp.v1.DeployRequest
|
||||
12, // 27: mcp.v1.McpAgentService.UndeployService:input_type -> mcp.v1.UndeployServiceRequest
|
||||
6, // 28: mcp.v1.McpAgentService.StopService:input_type -> mcp.v1.StopServiceRequest
|
||||
8, // 29: mcp.v1.McpAgentService.StartService:input_type -> mcp.v1.StartServiceRequest
|
||||
10, // 30: mcp.v1.McpAgentService.RestartService:input_type -> mcp.v1.RestartServiceRequest
|
||||
14, // 31: mcp.v1.McpAgentService.SyncDesiredState:input_type -> mcp.v1.SyncDesiredStateRequest
|
||||
17, // 32: mcp.v1.McpAgentService.ListServices:input_type -> mcp.v1.ListServicesRequest
|
||||
21, // 33: mcp.v1.McpAgentService.GetServiceStatus:input_type -> mcp.v1.GetServiceStatusRequest
|
||||
25, // 34: mcp.v1.McpAgentService.LiveCheck:input_type -> mcp.v1.LiveCheckRequest
|
||||
27, // 35: mcp.v1.McpAgentService.AdoptContainers:input_type -> mcp.v1.AdoptContainersRequest
|
||||
36, // 36: mcp.v1.McpAgentService.PurgeComponent:input_type -> mcp.v1.PurgeRequest
|
||||
30, // 37: mcp.v1.McpAgentService.PushFile:input_type -> mcp.v1.PushFileRequest
|
||||
32, // 38: mcp.v1.McpAgentService.PullFile:input_type -> mcp.v1.PullFileRequest
|
||||
34, // 39: mcp.v1.McpAgentService.NodeStatus:input_type -> mcp.v1.NodeStatusRequest
|
||||
41, // 40: mcp.v1.McpAgentService.ListDNSRecords:input_type -> mcp.v1.ListDNSRecordsRequest
|
||||
45, // 41: mcp.v1.McpAgentService.ListProxyRoutes:input_type -> mcp.v1.ListProxyRoutesRequest
|
||||
49, // 42: mcp.v1.McpAgentService.AddProxyRoute:input_type -> mcp.v1.AddProxyRouteRequest
|
||||
51, // 43: mcp.v1.McpAgentService.RemoveProxyRoute:input_type -> mcp.v1.RemoveProxyRouteRequest
|
||||
39, // 44: mcp.v1.McpAgentService.Logs:input_type -> mcp.v1.LogsRequest
|
||||
4, // 45: mcp.v1.McpAgentService.Deploy:output_type -> mcp.v1.DeployResponse
|
||||
13, // 46: mcp.v1.McpAgentService.UndeployService:output_type -> mcp.v1.UndeployServiceResponse
|
||||
7, // 47: mcp.v1.McpAgentService.StopService:output_type -> mcp.v1.StopServiceResponse
|
||||
9, // 48: mcp.v1.McpAgentService.StartService:output_type -> mcp.v1.StartServiceResponse
|
||||
11, // 49: mcp.v1.McpAgentService.RestartService:output_type -> mcp.v1.RestartServiceResponse
|
||||
15, // 50: mcp.v1.McpAgentService.SyncDesiredState:output_type -> mcp.v1.SyncDesiredStateResponse
|
||||
20, // 51: mcp.v1.McpAgentService.ListServices:output_type -> mcp.v1.ListServicesResponse
|
||||
24, // 52: mcp.v1.McpAgentService.GetServiceStatus:output_type -> mcp.v1.GetServiceStatusResponse
|
||||
26, // 53: mcp.v1.McpAgentService.LiveCheck:output_type -> mcp.v1.LiveCheckResponse
|
||||
29, // 54: mcp.v1.McpAgentService.AdoptContainers:output_type -> mcp.v1.AdoptContainersResponse
|
||||
37, // 55: mcp.v1.McpAgentService.PurgeComponent:output_type -> mcp.v1.PurgeResponse
|
||||
31, // 56: mcp.v1.McpAgentService.PushFile:output_type -> mcp.v1.PushFileResponse
|
||||
33, // 57: mcp.v1.McpAgentService.PullFile:output_type -> mcp.v1.PullFileResponse
|
||||
35, // 58: mcp.v1.McpAgentService.NodeStatus:output_type -> mcp.v1.NodeStatusResponse
|
||||
44, // 59: mcp.v1.McpAgentService.ListDNSRecords:output_type -> mcp.v1.ListDNSRecordsResponse
|
||||
48, // 60: mcp.v1.McpAgentService.ListProxyRoutes:output_type -> mcp.v1.ListProxyRoutesResponse
|
||||
50, // 61: mcp.v1.McpAgentService.AddProxyRoute:output_type -> mcp.v1.AddProxyRouteResponse
|
||||
52, // 62: mcp.v1.McpAgentService.RemoveProxyRoute:output_type -> mcp.v1.RemoveProxyRouteResponse
|
||||
40, // 63: mcp.v1.McpAgentService.Logs:output_type -> mcp.v1.LogsResponse
|
||||
45, // [45:64] is the sub-list for method output_type
|
||||
26, // [26:45] is the sub-list for method input_type
|
||||
26, // [26:26] is the sub-list for extension type_name
|
||||
26, // [26:26] is the sub-list for extension extendee
|
||||
0, // [0:26] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_proto_mcp_v1_mcp_proto_init() }
|
||||
@@ -2656,7 +3385,7 @@ func file_proto_mcp_v1_mcp_proto_init() {
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_mcp_v1_mcp_proto_rawDesc), len(file_proto_mcp_v1_mcp_proto_rawDesc)),
|
||||
NumEnums: 0,
|
||||
NumMessages: 41,
|
||||
NumMessages: 53,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
|
||||
@@ -33,6 +33,10 @@ const (
|
||||
McpAgentService_PushFile_FullMethodName = "/mcp.v1.McpAgentService/PushFile"
|
||||
McpAgentService_PullFile_FullMethodName = "/mcp.v1.McpAgentService/PullFile"
|
||||
McpAgentService_NodeStatus_FullMethodName = "/mcp.v1.McpAgentService/NodeStatus"
|
||||
McpAgentService_ListDNSRecords_FullMethodName = "/mcp.v1.McpAgentService/ListDNSRecords"
|
||||
McpAgentService_ListProxyRoutes_FullMethodName = "/mcp.v1.McpAgentService/ListProxyRoutes"
|
||||
McpAgentService_AddProxyRoute_FullMethodName = "/mcp.v1.McpAgentService/AddProxyRoute"
|
||||
McpAgentService_RemoveProxyRoute_FullMethodName = "/mcp.v1.McpAgentService/RemoveProxyRoute"
|
||||
McpAgentService_Logs_FullMethodName = "/mcp.v1.McpAgentService/Logs"
|
||||
)
|
||||
|
||||
@@ -61,6 +65,12 @@ type McpAgentServiceClient interface {
|
||||
PullFile(ctx context.Context, in *PullFileRequest, opts ...grpc.CallOption) (*PullFileResponse, error)
|
||||
// Node
|
||||
NodeStatus(ctx context.Context, in *NodeStatusRequest, opts ...grpc.CallOption) (*NodeStatusResponse, error)
|
||||
// DNS (query MCNS)
|
||||
ListDNSRecords(ctx context.Context, in *ListDNSRecordsRequest, opts ...grpc.CallOption) (*ListDNSRecordsResponse, error)
|
||||
// Proxy routes (query mc-proxy)
|
||||
ListProxyRoutes(ctx context.Context, in *ListProxyRoutesRequest, opts ...grpc.CallOption) (*ListProxyRoutesResponse, error)
|
||||
AddProxyRoute(ctx context.Context, in *AddProxyRouteRequest, opts ...grpc.CallOption) (*AddProxyRouteResponse, error)
|
||||
RemoveProxyRoute(ctx context.Context, in *RemoveProxyRouteRequest, opts ...grpc.CallOption) (*RemoveProxyRouteResponse, error)
|
||||
// Logs
|
||||
Logs(ctx context.Context, in *LogsRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[LogsResponse], error)
|
||||
}
|
||||
@@ -213,6 +223,46 @@ func (c *mcpAgentServiceClient) NodeStatus(ctx context.Context, in *NodeStatusRe
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *mcpAgentServiceClient) ListDNSRecords(ctx context.Context, in *ListDNSRecordsRequest, opts ...grpc.CallOption) (*ListDNSRecordsResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ListDNSRecordsResponse)
|
||||
err := c.cc.Invoke(ctx, McpAgentService_ListDNSRecords_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *mcpAgentServiceClient) ListProxyRoutes(ctx context.Context, in *ListProxyRoutesRequest, opts ...grpc.CallOption) (*ListProxyRoutesResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ListProxyRoutesResponse)
|
||||
err := c.cc.Invoke(ctx, McpAgentService_ListProxyRoutes_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *mcpAgentServiceClient) AddProxyRoute(ctx context.Context, in *AddProxyRouteRequest, opts ...grpc.CallOption) (*AddProxyRouteResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(AddProxyRouteResponse)
|
||||
err := c.cc.Invoke(ctx, McpAgentService_AddProxyRoute_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *mcpAgentServiceClient) RemoveProxyRoute(ctx context.Context, in *RemoveProxyRouteRequest, opts ...grpc.CallOption) (*RemoveProxyRouteResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(RemoveProxyRouteResponse)
|
||||
err := c.cc.Invoke(ctx, McpAgentService_RemoveProxyRoute_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *mcpAgentServiceClient) Logs(ctx context.Context, in *LogsRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[LogsResponse], error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
stream, err := c.cc.NewStream(ctx, &McpAgentService_ServiceDesc.Streams[0], McpAgentService_Logs_FullMethodName, cOpts...)
|
||||
@@ -257,6 +307,12 @@ type McpAgentServiceServer interface {
|
||||
PullFile(context.Context, *PullFileRequest) (*PullFileResponse, error)
|
||||
// Node
|
||||
NodeStatus(context.Context, *NodeStatusRequest) (*NodeStatusResponse, error)
|
||||
// DNS (query MCNS)
|
||||
ListDNSRecords(context.Context, *ListDNSRecordsRequest) (*ListDNSRecordsResponse, error)
|
||||
// Proxy routes (query mc-proxy)
|
||||
ListProxyRoutes(context.Context, *ListProxyRoutesRequest) (*ListProxyRoutesResponse, error)
|
||||
AddProxyRoute(context.Context, *AddProxyRouteRequest) (*AddProxyRouteResponse, error)
|
||||
RemoveProxyRoute(context.Context, *RemoveProxyRouteRequest) (*RemoveProxyRouteResponse, error)
|
||||
// Logs
|
||||
Logs(*LogsRequest, grpc.ServerStreamingServer[LogsResponse]) error
|
||||
mustEmbedUnimplementedMcpAgentServiceServer()
|
||||
@@ -311,6 +367,18 @@ func (UnimplementedMcpAgentServiceServer) PullFile(context.Context, *PullFileReq
|
||||
func (UnimplementedMcpAgentServiceServer) NodeStatus(context.Context, *NodeStatusRequest) (*NodeStatusResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method NodeStatus not implemented")
|
||||
}
|
||||
func (UnimplementedMcpAgentServiceServer) ListDNSRecords(context.Context, *ListDNSRecordsRequest) (*ListDNSRecordsResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListDNSRecords not implemented")
|
||||
}
|
||||
func (UnimplementedMcpAgentServiceServer) ListProxyRoutes(context.Context, *ListProxyRoutesRequest) (*ListProxyRoutesResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method ListProxyRoutes not implemented")
|
||||
}
|
||||
func (UnimplementedMcpAgentServiceServer) AddProxyRoute(context.Context, *AddProxyRouteRequest) (*AddProxyRouteResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method AddProxyRoute not implemented")
|
||||
}
|
||||
func (UnimplementedMcpAgentServiceServer) RemoveProxyRoute(context.Context, *RemoveProxyRouteRequest) (*RemoveProxyRouteResponse, error) {
|
||||
return nil, status.Error(codes.Unimplemented, "method RemoveProxyRoute not implemented")
|
||||
}
|
||||
func (UnimplementedMcpAgentServiceServer) Logs(*LogsRequest, grpc.ServerStreamingServer[LogsResponse]) error {
|
||||
return status.Error(codes.Unimplemented, "method Logs not implemented")
|
||||
}
|
||||
@@ -587,6 +655,78 @@ func _McpAgentService_NodeStatus_Handler(srv interface{}, ctx context.Context, d
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _McpAgentService_ListDNSRecords_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ListDNSRecordsRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(McpAgentServiceServer).ListDNSRecords(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: McpAgentService_ListDNSRecords_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(McpAgentServiceServer).ListDNSRecords(ctx, req.(*ListDNSRecordsRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _McpAgentService_ListProxyRoutes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ListProxyRoutesRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(McpAgentServiceServer).ListProxyRoutes(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: McpAgentService_ListProxyRoutes_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(McpAgentServiceServer).ListProxyRoutes(ctx, req.(*ListProxyRoutesRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _McpAgentService_AddProxyRoute_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(AddProxyRouteRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(McpAgentServiceServer).AddProxyRoute(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: McpAgentService_AddProxyRoute_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(McpAgentServiceServer).AddProxyRoute(ctx, req.(*AddProxyRouteRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _McpAgentService_RemoveProxyRoute_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(RemoveProxyRouteRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(McpAgentServiceServer).RemoveProxyRoute(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: McpAgentService_RemoveProxyRoute_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(McpAgentServiceServer).RemoveProxyRoute(ctx, req.(*RemoveProxyRouteRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _McpAgentService_Logs_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(LogsRequest)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
@@ -661,6 +801,22 @@ var McpAgentService_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "NodeStatus",
|
||||
Handler: _McpAgentService_NodeStatus_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ListDNSRecords",
|
||||
Handler: _McpAgentService_ListDNSRecords_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ListProxyRoutes",
|
||||
Handler: _McpAgentService_ListProxyRoutes_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "AddProxyRoute",
|
||||
Handler: _McpAgentService_AddProxyRoute_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "RemoveProxyRoute",
|
||||
Handler: _McpAgentService_RemoveProxyRoute_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
|
||||
@@ -35,11 +35,12 @@ type Agent struct {
|
||||
Proxy *ProxyRouter
|
||||
Certs *CertProvisioner
|
||||
DNS *DNSRegistrar
|
||||
Version string
|
||||
}
|
||||
|
||||
// Run starts the agent: opens the database, sets up the gRPC server with
|
||||
// TLS and auth, and blocks until SIGINT/SIGTERM.
|
||||
func Run(cfg *config.AgentConfig) error {
|
||||
func Run(cfg *config.AgentConfig, version string) error {
|
||||
logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{
|
||||
Level: parseLogLevel(cfg.Log.Level),
|
||||
}))
|
||||
@@ -79,6 +80,7 @@ func Run(cfg *config.AgentConfig) error {
|
||||
Proxy: proxy,
|
||||
Certs: certs,
|
||||
DNS: dns,
|
||||
Version: version,
|
||||
}
|
||||
|
||||
tlsCert, err := tls.LoadX509KeyPair(cfg.Server.TLSCert, cfg.Server.TLSKey)
|
||||
|
||||
@@ -134,7 +134,8 @@ func (a *Agent) deployComponent(ctx context.Context, serviceName string, cs *mcp
|
||||
Error: fmt.Sprintf("allocate route ports: %v", err),
|
||||
}
|
||||
}
|
||||
runSpec.Ports = ports
|
||||
// Merge explicit ports from the spec with route-allocated ports.
|
||||
runSpec.Ports = append(cs.GetPorts(), ports...)
|
||||
runSpec.Env = append(runSpec.Env, env...)
|
||||
} else {
|
||||
// Legacy: use ports directly from the spec.
|
||||
|
||||
@@ -26,8 +26,8 @@ type DNSRegistrar struct {
|
||||
logger *slog.Logger
|
||||
}
|
||||
|
||||
// dnsRecord is the JSON representation of an MCNS record.
|
||||
type dnsRecord struct {
|
||||
// DNSRecord is the JSON representation of an MCNS record.
|
||||
type DNSRecord struct {
|
||||
ID int `json:"ID"`
|
||||
Name string `json:"Name"`
|
||||
Type string `json:"Type"`
|
||||
@@ -136,8 +136,87 @@ func (d *DNSRegistrar) RemoveRecord(ctx context.Context, serviceName string) err
|
||||
return nil
|
||||
}
|
||||
|
||||
// DNSZone is the JSON representation of an MCNS zone.
|
||||
type DNSZone struct {
|
||||
Name string `json:"Name"`
|
||||
}
|
||||
|
||||
// ListZones returns all zones from MCNS.
|
||||
func (d *DNSRegistrar) ListZones(ctx context.Context) ([]DNSZone, error) {
|
||||
if d == nil {
|
||||
return nil, fmt.Errorf("DNS registrar not configured")
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("%s/v1/zones", d.serverURL)
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create list zones request: %w", err)
|
||||
}
|
||||
req.Header.Set("Authorization", "Bearer "+d.token)
|
||||
|
||||
resp, err := d.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("list zones: %w", err)
|
||||
}
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("read list zones response: %w", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("list zones: mcns returned %d: %s", resp.StatusCode, string(body))
|
||||
}
|
||||
|
||||
var envelope struct {
|
||||
Zones []DNSZone `json:"zones"`
|
||||
}
|
||||
if err := json.Unmarshal(body, &envelope); err != nil {
|
||||
return nil, fmt.Errorf("parse list zones response: %w", err)
|
||||
}
|
||||
return envelope.Zones, nil
|
||||
}
|
||||
|
||||
// ListZoneRecords returns all records in the given zone (no filters).
|
||||
func (d *DNSRegistrar) ListZoneRecords(ctx context.Context, zone string) ([]DNSRecord, error) {
|
||||
if d == nil {
|
||||
return nil, fmt.Errorf("DNS registrar not configured")
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("%s/v1/zones/%s/records", d.serverURL, zone)
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create list zone records request: %w", err)
|
||||
}
|
||||
req.Header.Set("Authorization", "Bearer "+d.token)
|
||||
|
||||
resp, err := d.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("list zone records: %w", err)
|
||||
}
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("read list zone records response: %w", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("list zone records: mcns returned %d: %s", resp.StatusCode, string(body))
|
||||
}
|
||||
|
||||
var envelope struct {
|
||||
Records []DNSRecord `json:"records"`
|
||||
}
|
||||
if err := json.Unmarshal(body, &envelope); err != nil {
|
||||
return nil, fmt.Errorf("parse list zone records response: %w", err)
|
||||
}
|
||||
return envelope.Records, nil
|
||||
}
|
||||
|
||||
// listRecords returns A records matching the service name in the zone.
|
||||
func (d *DNSRegistrar) listRecords(ctx context.Context, serviceName string) ([]dnsRecord, error) {
|
||||
func (d *DNSRegistrar) listRecords(ctx context.Context, serviceName string) ([]DNSRecord, error) {
|
||||
url := fmt.Sprintf("%s/v1/zones/%s/records?name=%s&type=A", d.serverURL, d.zone, serviceName)
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
@@ -161,7 +240,7 @@ func (d *DNSRegistrar) listRecords(ctx context.Context, serviceName string) ([]d
|
||||
}
|
||||
|
||||
var envelope struct {
|
||||
Records []dnsRecord `json:"records"`
|
||||
Records []DNSRecord `json:"records"`
|
||||
}
|
||||
if err := json.Unmarshal(body, &envelope); err != nil {
|
||||
return nil, fmt.Errorf("parse list response: %w", err)
|
||||
|
||||
40
internal/agent/dns_rpc.go
Normal file
40
internal/agent/dns_rpc.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
mcpv1 "git.wntrmute.dev/mc/mcp/gen/mcp/v1"
|
||||
)
|
||||
|
||||
// ListDNSRecords queries MCNS for all zones and their records.
|
||||
func (a *Agent) ListDNSRecords(ctx context.Context, _ *mcpv1.ListDNSRecordsRequest) (*mcpv1.ListDNSRecordsResponse, error) {
|
||||
a.Logger.Debug("ListDNSRecords called")
|
||||
|
||||
zones, err := a.DNS.ListZones(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("list zones: %w", err)
|
||||
}
|
||||
|
||||
resp := &mcpv1.ListDNSRecordsResponse{}
|
||||
for _, z := range zones {
|
||||
records, err := a.DNS.ListZoneRecords(ctx, z.Name)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("list records for zone %q: %w", z.Name, err)
|
||||
}
|
||||
|
||||
zone := &mcpv1.DNSZone{Name: z.Name}
|
||||
for _, r := range records {
|
||||
zone.Records = append(zone.Records, &mcpv1.DNSRecord{
|
||||
Id: int64(r.ID),
|
||||
Name: r.Name,
|
||||
Type: r.Type,
|
||||
Value: r.Value,
|
||||
Ttl: int32(r.TTL), //nolint:gosec // TTL is bounded
|
||||
})
|
||||
}
|
||||
resp.Zones = append(resp.Zones, zone)
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
@@ -90,7 +90,7 @@ func TestEnsureRecordSkipsWhenExists(t *testing.T) {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == http.MethodGet {
|
||||
// Return an existing record with the correct value.
|
||||
resp := map[string][]dnsRecord{"records": {{ID: 1, Name: "myservice", Type: "A", Value: "192.168.88.181", TTL: 300}}}
|
||||
resp := map[string][]DNSRecord{"records": {{ID: 1, Name: "myservice", Type: "A", Value: "192.168.88.181", TTL: 300}}}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_ = json.NewEncoder(w).Encode(resp)
|
||||
return
|
||||
@@ -124,7 +124,7 @@ func TestEnsureRecordUpdatesWrongValue(t *testing.T) {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == http.MethodGet {
|
||||
// Return a record with a stale value.
|
||||
resp := map[string][]dnsRecord{"records": {{ID: 42, Name: "myservice", Type: "A", Value: "10.0.0.1", TTL: 300}}}
|
||||
resp := map[string][]DNSRecord{"records": {{ID: 42, Name: "myservice", Type: "A", Value: "10.0.0.1", TTL: 300}}}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_ = json.NewEncoder(w).Encode(resp)
|
||||
return
|
||||
@@ -160,7 +160,7 @@ func TestRemoveRecordDeletes(t *testing.T) {
|
||||
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == http.MethodGet {
|
||||
resp := map[string][]dnsRecord{"records": {{ID: 7, Name: "myservice", Type: "A", Value: "192.168.88.181", TTL: 300}}}
|
||||
resp := map[string][]DNSRecord{"records": {{ID: 7, Name: "myservice", Type: "A", Value: "192.168.88.181", TTL: 300}}}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_ = json.NewEncoder(w).Encode(resp)
|
||||
return
|
||||
|
||||
@@ -31,6 +31,7 @@ func (a *Agent) NodeStatus(ctx context.Context, _ *mcpv1.NodeStatusRequest) (*mc
|
||||
Runtime: a.Config.Agent.ContainerRuntime,
|
||||
ServiceCount: uint32(len(services)), //nolint:gosec // bounded
|
||||
ComponentCount: componentCount,
|
||||
AgentVersion: a.Version,
|
||||
}
|
||||
|
||||
// Runtime version.
|
||||
|
||||
@@ -48,6 +48,30 @@ func (p *ProxyRouter) Close() error {
|
||||
return p.client.Close()
|
||||
}
|
||||
|
||||
// GetStatus returns the mc-proxy server status.
|
||||
func (p *ProxyRouter) GetStatus(ctx context.Context) (*mcproxy.Status, error) {
|
||||
if p == nil {
|
||||
return nil, fmt.Errorf("mc-proxy not configured")
|
||||
}
|
||||
return p.client.GetStatus(ctx)
|
||||
}
|
||||
|
||||
// AddRoute adds a single route to mc-proxy.
|
||||
func (p *ProxyRouter) AddRoute(ctx context.Context, listenerAddr string, route mcproxy.Route) error {
|
||||
if p == nil {
|
||||
return fmt.Errorf("mc-proxy not configured")
|
||||
}
|
||||
return p.client.AddRoute(ctx, listenerAddr, route)
|
||||
}
|
||||
|
||||
// RemoveRoute removes a single route from mc-proxy.
|
||||
func (p *ProxyRouter) RemoveRoute(ctx context.Context, listenerAddr, hostname string) error {
|
||||
if p == nil {
|
||||
return fmt.Errorf("mc-proxy not configured")
|
||||
}
|
||||
return p.client.RemoveRoute(ctx, listenerAddr, hostname)
|
||||
}
|
||||
|
||||
// RegisterRoutes registers all routes for a service component with mc-proxy.
|
||||
// It uses the assigned host ports from the registry.
|
||||
func (p *ProxyRouter) RegisterRoutes(ctx context.Context, serviceName string, routes []registry.Route, hostPorts map[string]int) error {
|
||||
|
||||
111
internal/agent/proxy_rpc.go
Normal file
111
internal/agent/proxy_rpc.go
Normal file
@@ -0,0 +1,111 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"git.wntrmute.dev/mc/mc-proxy/client/mcproxy"
|
||||
mcpv1 "git.wntrmute.dev/mc/mcp/gen/mcp/v1"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
// ListProxyRoutes queries mc-proxy for its current status and routes.
|
||||
func (a *Agent) ListProxyRoutes(ctx context.Context, _ *mcpv1.ListProxyRoutesRequest) (*mcpv1.ListProxyRoutesResponse, error) {
|
||||
a.Logger.Debug("ListProxyRoutes called")
|
||||
|
||||
status, err := a.Proxy.GetStatus(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get mc-proxy status: %w", err)
|
||||
}
|
||||
|
||||
resp := &mcpv1.ListProxyRoutesResponse{
|
||||
Version: status.Version,
|
||||
TotalConnections: status.TotalConnections,
|
||||
}
|
||||
if !status.StartedAt.IsZero() {
|
||||
resp.StartedAt = timestamppb.New(status.StartedAt)
|
||||
}
|
||||
|
||||
for _, ls := range status.Listeners {
|
||||
listener := &mcpv1.ProxyListenerInfo{
|
||||
Addr: ls.Addr,
|
||||
RouteCount: int32(ls.RouteCount), //nolint:gosec // bounded
|
||||
ActiveConnections: ls.ActiveConnections,
|
||||
}
|
||||
for _, r := range ls.Routes {
|
||||
listener.Routes = append(listener.Routes, &mcpv1.ProxyRouteInfo{
|
||||
Hostname: r.Hostname,
|
||||
Backend: r.Backend,
|
||||
Mode: r.Mode,
|
||||
BackendTls: r.BackendTLS,
|
||||
})
|
||||
}
|
||||
resp.Listeners = append(resp.Listeners, listener)
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// AddProxyRoute adds a route to mc-proxy.
|
||||
func (a *Agent) AddProxyRoute(ctx context.Context, req *mcpv1.AddProxyRouteRequest) (*mcpv1.AddProxyRouteResponse, error) {
|
||||
if req.GetListenerAddr() == "" {
|
||||
return nil, status.Error(codes.InvalidArgument, "listener_addr is required")
|
||||
}
|
||||
if req.GetHostname() == "" {
|
||||
return nil, status.Error(codes.InvalidArgument, "hostname is required")
|
||||
}
|
||||
if req.GetBackend() == "" {
|
||||
return nil, status.Error(codes.InvalidArgument, "backend is required")
|
||||
}
|
||||
|
||||
if a.Proxy == nil {
|
||||
return nil, status.Error(codes.FailedPrecondition, "mc-proxy not configured")
|
||||
}
|
||||
|
||||
route := mcproxy.Route{
|
||||
Hostname: req.GetHostname(),
|
||||
Backend: req.GetBackend(),
|
||||
Mode: req.GetMode(),
|
||||
BackendTLS: req.GetBackendTls(),
|
||||
}
|
||||
|
||||
if err := a.Proxy.AddRoute(ctx, req.GetListenerAddr(), route); err != nil {
|
||||
return nil, fmt.Errorf("add route: %w", err)
|
||||
}
|
||||
|
||||
a.Logger.Info("route added",
|
||||
"listener", req.GetListenerAddr(),
|
||||
"hostname", req.GetHostname(),
|
||||
"backend", req.GetBackend(),
|
||||
"mode", req.GetMode(),
|
||||
)
|
||||
|
||||
return &mcpv1.AddProxyRouteResponse{}, nil
|
||||
}
|
||||
|
||||
// RemoveProxyRoute removes a route from mc-proxy.
|
||||
func (a *Agent) RemoveProxyRoute(ctx context.Context, req *mcpv1.RemoveProxyRouteRequest) (*mcpv1.RemoveProxyRouteResponse, error) {
|
||||
if req.GetListenerAddr() == "" {
|
||||
return nil, status.Error(codes.InvalidArgument, "listener_addr is required")
|
||||
}
|
||||
if req.GetHostname() == "" {
|
||||
return nil, status.Error(codes.InvalidArgument, "hostname is required")
|
||||
}
|
||||
|
||||
if a.Proxy == nil {
|
||||
return nil, status.Error(codes.FailedPrecondition, "mc-proxy not configured")
|
||||
}
|
||||
|
||||
if err := a.Proxy.RemoveRoute(ctx, req.GetListenerAddr(), req.GetHostname()); err != nil {
|
||||
return nil, fmt.Errorf("remove route: %w", err)
|
||||
}
|
||||
|
||||
a.Logger.Info("route removed",
|
||||
"listener", req.GetListenerAddr(),
|
||||
"hostname", req.GetHostname(),
|
||||
)
|
||||
|
||||
return &mcpv1.RemoveProxyRouteResponse{}, nil
|
||||
}
|
||||
@@ -180,36 +180,33 @@ func (p *Podman) Inspect(ctx context.Context, name string) (ContainerInfo, error
|
||||
}
|
||||
|
||||
// Logs returns an exec.Cmd that streams container logs. For containers
|
||||
// using the journald log driver, it uses journalctl (podman logs can't
|
||||
// read journald outside the originating user session). For k8s-file or
|
||||
// other drivers, it uses podman logs directly.
|
||||
// using the journald log driver, it tries journalctl first (podman logs
|
||||
// can't read journald outside the originating user session). If journalctl
|
||||
// can't access the journal, it falls back to podman logs.
|
||||
func (p *Podman) Logs(ctx context.Context, containerName string, tail int, follow, timestamps bool, since string) *exec.Cmd {
|
||||
// Check if this container uses the journald log driver.
|
||||
inspectCmd := exec.CommandContext(ctx, p.command(), "inspect", "--format", "{{.HostConfig.LogConfig.Type}}", containerName) //nolint:gosec
|
||||
if out, err := inspectCmd.Output(); err == nil && strings.TrimSpace(string(out)) == "journald" {
|
||||
return p.journalLogs(ctx, containerName, tail, follow, since)
|
||||
if p.journalAccessible(ctx, containerName) {
|
||||
return p.journalLogs(ctx, containerName, tail, follow, since)
|
||||
}
|
||||
}
|
||||
|
||||
args := []string{"logs"}
|
||||
if tail > 0 {
|
||||
args = append(args, "--tail", fmt.Sprintf("%d", tail))
|
||||
return p.podmanLogs(ctx, containerName, tail, follow, timestamps, since)
|
||||
}
|
||||
|
||||
// journalAccessible probes whether journalctl can read logs for the container.
|
||||
func (p *Podman) journalAccessible(ctx context.Context, containerName string) bool {
|
||||
args := []string{"--no-pager", "-n", "0"}
|
||||
if os.Getuid() != 0 {
|
||||
args = append(args, "--user")
|
||||
}
|
||||
if follow {
|
||||
args = append(args, "--follow")
|
||||
}
|
||||
if timestamps {
|
||||
args = append(args, "--timestamps")
|
||||
}
|
||||
if since != "" {
|
||||
args = append(args, "--since", since)
|
||||
}
|
||||
args = append(args, containerName)
|
||||
return exec.CommandContext(ctx, p.command(), args...) //nolint:gosec // args built programmatically
|
||||
args = append(args, "CONTAINER_NAME="+containerName)
|
||||
cmd := exec.CommandContext(ctx, "journalctl", args...) //nolint:gosec
|
||||
return cmd.Run() == nil
|
||||
}
|
||||
|
||||
// journalLogs returns a journalctl command filtered by container name.
|
||||
// For rootless podman, container logs go to the user journal, so we
|
||||
// need --user to read them.
|
||||
func (p *Podman) journalLogs(ctx context.Context, containerName string, tail int, follow bool, since string) *exec.Cmd {
|
||||
args := []string{"--no-pager", "--output", "cat"}
|
||||
if os.Getuid() != 0 {
|
||||
@@ -228,6 +225,25 @@ func (p *Podman) journalLogs(ctx context.Context, containerName string, tail int
|
||||
return exec.CommandContext(ctx, "journalctl", args...) //nolint:gosec // args built programmatically
|
||||
}
|
||||
|
||||
// podmanLogs returns a podman logs command.
|
||||
func (p *Podman) podmanLogs(ctx context.Context, containerName string, tail int, follow, timestamps bool, since string) *exec.Cmd {
|
||||
args := []string{"logs"}
|
||||
if tail > 0 {
|
||||
args = append(args, "--tail", fmt.Sprintf("%d", tail))
|
||||
}
|
||||
if follow {
|
||||
args = append(args, "--follow")
|
||||
}
|
||||
if timestamps {
|
||||
args = append(args, "--timestamps")
|
||||
}
|
||||
if since != "" {
|
||||
args = append(args, "--since", since)
|
||||
}
|
||||
args = append(args, containerName)
|
||||
return exec.CommandContext(ctx, p.command(), args...) //nolint:gosec // args built programmatically
|
||||
}
|
||||
|
||||
// Login authenticates to a container registry using the given token as
|
||||
// the password. This enables non-interactive push with service account
|
||||
// tokens (MCR accepts MCIAS JWTs as passwords).
|
||||
|
||||
@@ -34,6 +34,14 @@ service McpAgentService {
|
||||
// Node
|
||||
rpc NodeStatus(NodeStatusRequest) returns (NodeStatusResponse);
|
||||
|
||||
// DNS (query MCNS)
|
||||
rpc ListDNSRecords(ListDNSRecordsRequest) returns (ListDNSRecordsResponse);
|
||||
|
||||
// Proxy routes (query mc-proxy)
|
||||
rpc ListProxyRoutes(ListProxyRoutesRequest) returns (ListProxyRoutesResponse);
|
||||
rpc AddProxyRoute(AddProxyRouteRequest) returns (AddProxyRouteResponse);
|
||||
rpc RemoveProxyRoute(RemoveProxyRouteRequest) returns (RemoveProxyRouteResponse);
|
||||
|
||||
// Logs
|
||||
rpc Logs(LogsRequest) returns (stream LogsResponse);
|
||||
}
|
||||
@@ -257,6 +265,7 @@ message NodeStatusResponse {
|
||||
uint64 memory_free_bytes = 9;
|
||||
double cpu_usage_percent = 10;
|
||||
google.protobuf.Timestamp uptime_since = 11;
|
||||
string agent_version = 12;
|
||||
}
|
||||
|
||||
// --- Purge ---
|
||||
@@ -300,3 +309,66 @@ message LogsRequest {
|
||||
message LogsResponse {
|
||||
bytes data = 1;
|
||||
}
|
||||
|
||||
// --- DNS ---
|
||||
|
||||
message ListDNSRecordsRequest {}
|
||||
|
||||
message DNSZone {
|
||||
string name = 1;
|
||||
repeated DNSRecord records = 2;
|
||||
}
|
||||
|
||||
message DNSRecord {
|
||||
int64 id = 1;
|
||||
string name = 2;
|
||||
string type = 3;
|
||||
string value = 4;
|
||||
int32 ttl = 5;
|
||||
}
|
||||
|
||||
message ListDNSRecordsResponse {
|
||||
repeated DNSZone zones = 1;
|
||||
}
|
||||
|
||||
// --- Proxy routes ---
|
||||
|
||||
message ListProxyRoutesRequest {}
|
||||
|
||||
message ProxyRouteInfo {
|
||||
string hostname = 1;
|
||||
string backend = 2;
|
||||
string mode = 3;
|
||||
bool backend_tls = 4;
|
||||
}
|
||||
|
||||
message ProxyListenerInfo {
|
||||
string addr = 1;
|
||||
int32 route_count = 2;
|
||||
int64 active_connections = 3;
|
||||
repeated ProxyRouteInfo routes = 4;
|
||||
}
|
||||
|
||||
message ListProxyRoutesResponse {
|
||||
string version = 1;
|
||||
int64 total_connections = 2;
|
||||
google.protobuf.Timestamp started_at = 3;
|
||||
repeated ProxyListenerInfo listeners = 4;
|
||||
}
|
||||
|
||||
message AddProxyRouteRequest {
|
||||
string listener_addr = 1; // e.g. ":443"
|
||||
string hostname = 2;
|
||||
string backend = 3;
|
||||
string mode = 4; // "l4" or "l7"
|
||||
bool backend_tls = 5;
|
||||
}
|
||||
|
||||
message AddProxyRouteResponse {}
|
||||
|
||||
message RemoveProxyRouteRequest {
|
||||
string listener_addr = 1; // e.g. ":443"
|
||||
string hostname = 2;
|
||||
}
|
||||
|
||||
message RemoveProxyRouteResponse {}
|
||||
|
||||
Reference in New Issue
Block a user