fleet-manager: checkpoint 2 — gRPC agent plane (bidi mTLS stream)
The steady-state host<->manager transport, resolving the design's OPEN FORK to bespoke gRPC (not OTLP+Wazuh). One long-lived, host-dialed, mTLS bidi stream: health/metrics up, desired-state/commands down — no polling, real-time control, still no inbound host port. - proto/fleet_agent.proto: FleetAgent.Session(stream AgentUp) -> stream ManagerDown. AgentUp = Hello | HealthSnapshot | CommandResult; ManagerDown = DesiredState | Command(reboot/drain/resync). int64 unix times (no well-known-type dep). Generated stubs committed (CI needs no protoc). - agent.go: gRPC server with mTLS verified by the FLEET CA (the host's reused TPM identity cert — distinct from the admin plane's admin CA). Identity is the peer cert SERIAL, taken from the verified cert = inventory key, never self-asserted; an unenrolled serial is refused (enrolment gates the stream). Per-conn send channel decouples admin pushes from stream.Send. Stream registry (serial->conn) with reconnect eviction. On connect + on change, desired-state is pushed live; inventory stays authoritative so offline hosts reconcile on reconnect. Metrics go through a MetricsSink seam (no-op now; InfluxDB in ckpt 4). - main.go: agent plane starts only when its cert/key/CA are set; admin can run standalone. Lifecycle PUT now live-pushes and reports pushed_live. Full mTLS integration test (in-process fleet CA + host client cert): initial desired-state on connect, Hello+snapshot -> inventory + online presence, live desired-state push, and unenrolled-serial rejection. go build/test/vet/gofmt clean. Deps (server-side only): google.golang.org/grpc + protobuf.
This commit is contained in:
@@ -0,0 +1,810 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.36.11
|
||||
// protoc v3.21.12
|
||||
// source: proto/fleet_agent.proto
|
||||
|
||||
// The steady-state contract between the on-host fleet agent and the
|
||||
// fleet-manager. ONE long-lived, host-dialed, mTLS bidi stream (health/metrics
|
||||
// up, desired-state down) — the design's resolved transport fork (bespoke gRPC,
|
||||
// not OTLP+Wazuh). See docs/fleet-management-design.md + tpm-enrolment-design.md.
|
||||
//
|
||||
// Identity is the mTLS peer cert (the host's reused TPM identity cert, fleet CA);
|
||||
// the manager derives the cert serial (= inventory key) from it, so AgentUp
|
||||
// messages carry NO self-asserted identity — a host can only ever be itself.
|
||||
|
||||
package fleetpb
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
unsafe "unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type Command_Kind int32
|
||||
|
||||
const (
|
||||
Command_KIND_UNSPECIFIED Command_Kind = 0
|
||||
Command_REBOOT Command_Kind = 1 // reboot now (into desired target_version)
|
||||
Command_DRAIN Command_Kind = 2 // stop taking work / prepare for maintenance
|
||||
Command_RESYNC Command_Kind = 3 // re-fetch + re-apply desired-state now
|
||||
)
|
||||
|
||||
// Enum value maps for Command_Kind.
|
||||
var (
|
||||
Command_Kind_name = map[int32]string{
|
||||
0: "KIND_UNSPECIFIED",
|
||||
1: "REBOOT",
|
||||
2: "DRAIN",
|
||||
3: "RESYNC",
|
||||
}
|
||||
Command_Kind_value = map[string]int32{
|
||||
"KIND_UNSPECIFIED": 0,
|
||||
"REBOOT": 1,
|
||||
"DRAIN": 2,
|
||||
"RESYNC": 3,
|
||||
}
|
||||
)
|
||||
|
||||
func (x Command_Kind) Enum() *Command_Kind {
|
||||
p := new(Command_Kind)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
|
||||
func (x Command_Kind) String() string {
|
||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||
}
|
||||
|
||||
func (Command_Kind) Descriptor() protoreflect.EnumDescriptor {
|
||||
return file_proto_fleet_agent_proto_enumTypes[0].Descriptor()
|
||||
}
|
||||
|
||||
func (Command_Kind) Type() protoreflect.EnumType {
|
||||
return &file_proto_fleet_agent_proto_enumTypes[0]
|
||||
}
|
||||
|
||||
func (x Command_Kind) Number() protoreflect.EnumNumber {
|
||||
return protoreflect.EnumNumber(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Command_Kind.Descriptor instead.
|
||||
func (Command_Kind) EnumDescriptor() ([]byte, []int) {
|
||||
return file_proto_fleet_agent_proto_rawDescGZIP(), []int{6, 0}
|
||||
}
|
||||
|
||||
type AgentUp struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// Types that are valid to be assigned to Msg:
|
||||
//
|
||||
// *AgentUp_Hello
|
||||
// *AgentUp_Snapshot
|
||||
// *AgentUp_Result
|
||||
Msg isAgentUp_Msg `protobuf_oneof:"msg"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *AgentUp) Reset() {
|
||||
*x = AgentUp{}
|
||||
mi := &file_proto_fleet_agent_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *AgentUp) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*AgentUp) ProtoMessage() {}
|
||||
|
||||
func (x *AgentUp) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_fleet_agent_proto_msgTypes[0]
|
||||
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 AgentUp.ProtoReflect.Descriptor instead.
|
||||
func (*AgentUp) Descriptor() ([]byte, []int) {
|
||||
return file_proto_fleet_agent_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *AgentUp) GetMsg() isAgentUp_Msg {
|
||||
if x != nil {
|
||||
return x.Msg
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *AgentUp) GetHello() *Hello {
|
||||
if x != nil {
|
||||
if x, ok := x.Msg.(*AgentUp_Hello); ok {
|
||||
return x.Hello
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *AgentUp) GetSnapshot() *HealthSnapshot {
|
||||
if x != nil {
|
||||
if x, ok := x.Msg.(*AgentUp_Snapshot); ok {
|
||||
return x.Snapshot
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *AgentUp) GetResult() *CommandResult {
|
||||
if x != nil {
|
||||
if x, ok := x.Msg.(*AgentUp_Result); ok {
|
||||
return x.Result
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type isAgentUp_Msg interface {
|
||||
isAgentUp_Msg()
|
||||
}
|
||||
|
||||
type AgentUp_Hello struct {
|
||||
Hello *Hello `protobuf:"bytes,1,opt,name=hello,proto3,oneof"` // first frame after connect
|
||||
}
|
||||
|
||||
type AgentUp_Snapshot struct {
|
||||
Snapshot *HealthSnapshot `protobuf:"bytes,2,opt,name=snapshot,proto3,oneof"` // periodic telemetry (also written to InfluxDB)
|
||||
}
|
||||
|
||||
type AgentUp_Result struct {
|
||||
Result *CommandResult `protobuf:"bytes,3,opt,name=result,proto3,oneof"` // outcome of a ManagerDown.Command
|
||||
}
|
||||
|
||||
func (*AgentUp_Hello) isAgentUp_Msg() {}
|
||||
|
||||
func (*AgentUp_Snapshot) isAgentUp_Msg() {}
|
||||
|
||||
func (*AgentUp_Result) isAgentUp_Msg() {}
|
||||
|
||||
// Hello — what the host is running, sent once on connect so the manager can
|
||||
// reconcile version drift immediately.
|
||||
type Hello struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
ImageVersion string `protobuf:"bytes,1,opt,name=image_version,json=imageVersion,proto3" json:"image_version,omitempty"`
|
||||
RootfsDigest string `protobuf:"bytes,2,opt,name=rootfs_digest,json=rootfsDigest,proto3" json:"rootfs_digest,omitempty"`
|
||||
Kernel string `protobuf:"bytes,3,opt,name=kernel,proto3" json:"kernel,omitempty"`
|
||||
KioskUrl string `protobuf:"bytes,4,opt,name=kiosk_url,json=kioskUrl,proto3" json:"kiosk_url,omitempty"`
|
||||
StarshipName string `protobuf:"bytes,5,opt,name=starship_name,json=starshipName,proto3" json:"starship_name,omitempty"` // advisory; manager already knows it from inventory
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *Hello) Reset() {
|
||||
*x = Hello{}
|
||||
mi := &file_proto_fleet_agent_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *Hello) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Hello) ProtoMessage() {}
|
||||
|
||||
func (x *Hello) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_fleet_agent_proto_msgTypes[1]
|
||||
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 Hello.ProtoReflect.Descriptor instead.
|
||||
func (*Hello) Descriptor() ([]byte, []int) {
|
||||
return file_proto_fleet_agent_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *Hello) GetImageVersion() string {
|
||||
if x != nil {
|
||||
return x.ImageVersion
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Hello) GetRootfsDigest() string {
|
||||
if x != nil {
|
||||
return x.RootfsDigest
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Hello) GetKernel() string {
|
||||
if x != nil {
|
||||
return x.Kernel
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Hello) GetKioskUrl() string {
|
||||
if x != nil {
|
||||
return x.KioskUrl
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Hello) GetStarshipName() string {
|
||||
if x != nil {
|
||||
return x.StarshipName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// HealthSnapshot — one telemetry sample. Cached as the latest value in inventory
|
||||
// AND written as a time-series point to InfluxDB (tagged with the authenticated
|
||||
// cert serial / hostnqn).
|
||||
type HealthSnapshot struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
AtUnix int64 `protobuf:"varint,1,opt,name=at_unix,json=atUnix,proto3" json:"at_unix,omitempty"` // sample time, unix seconds (0 = manager stamps now)
|
||||
LoadAvg float64 `protobuf:"fixed64,2,opt,name=load_avg,json=loadAvg,proto3" json:"load_avg,omitempty"`
|
||||
CpuPct float64 `protobuf:"fixed64,3,opt,name=cpu_pct,json=cpuPct,proto3" json:"cpu_pct,omitempty"`
|
||||
TempC float64 `protobuf:"fixed64,4,opt,name=temp_c,json=tempC,proto3" json:"temp_c,omitempty"`
|
||||
MemUsedPct float64 `protobuf:"fixed64,5,opt,name=mem_used_pct,json=memUsedPct,proto3" json:"mem_used_pct,omitempty"`
|
||||
TmpfsUsedPct float64 `protobuf:"fixed64,6,opt,name=tmpfs_used_pct,json=tmpfsUsedPct,proto3" json:"tmpfs_used_pct,omitempty"` // overlay RAM pressure
|
||||
NvmeRoot string `protobuf:"bytes,7,opt,name=nvme_root,json=nvmeRoot,proto3" json:"nvme_root,omitempty"` // ok|degraded|down
|
||||
Auth string `protobuf:"bytes,8,opt,name=auth,proto3" json:"auth,omitempty"` // 802.1x/macsec: up|down
|
||||
Selinux string `protobuf:"bytes,9,opt,name=selinux,proto3" json:"selinux,omitempty"` // enforcing|permissive
|
||||
Chrony string `protobuf:"bytes,10,opt,name=chrony,proto3" json:"chrony,omitempty"` // synced|unsynced
|
||||
KioskActive bool `protobuf:"varint,11,opt,name=kiosk_active,json=kioskActive,proto3" json:"kiosk_active,omitempty"`
|
||||
SessionUptime string `protobuf:"bytes,12,opt,name=session_uptime,json=sessionUptime,proto3" json:"session_uptime,omitempty"`
|
||||
ChromiumCrashes int32 `protobuf:"varint,13,opt,name=chromium_crashes,json=chromiumCrashes,proto3" json:"chromium_crashes,omitempty"`
|
||||
Display string `protobuf:"bytes,14,opt,name=display,proto3" json:"display,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *HealthSnapshot) Reset() {
|
||||
*x = HealthSnapshot{}
|
||||
mi := &file_proto_fleet_agent_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *HealthSnapshot) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*HealthSnapshot) ProtoMessage() {}
|
||||
|
||||
func (x *HealthSnapshot) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_fleet_agent_proto_msgTypes[2]
|
||||
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 HealthSnapshot.ProtoReflect.Descriptor instead.
|
||||
func (*HealthSnapshot) Descriptor() ([]byte, []int) {
|
||||
return file_proto_fleet_agent_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *HealthSnapshot) GetAtUnix() int64 {
|
||||
if x != nil {
|
||||
return x.AtUnix
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *HealthSnapshot) GetLoadAvg() float64 {
|
||||
if x != nil {
|
||||
return x.LoadAvg
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *HealthSnapshot) GetCpuPct() float64 {
|
||||
if x != nil {
|
||||
return x.CpuPct
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *HealthSnapshot) GetTempC() float64 {
|
||||
if x != nil {
|
||||
return x.TempC
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *HealthSnapshot) GetMemUsedPct() float64 {
|
||||
if x != nil {
|
||||
return x.MemUsedPct
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *HealthSnapshot) GetTmpfsUsedPct() float64 {
|
||||
if x != nil {
|
||||
return x.TmpfsUsedPct
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *HealthSnapshot) GetNvmeRoot() string {
|
||||
if x != nil {
|
||||
return x.NvmeRoot
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *HealthSnapshot) GetAuth() string {
|
||||
if x != nil {
|
||||
return x.Auth
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *HealthSnapshot) GetSelinux() string {
|
||||
if x != nil {
|
||||
return x.Selinux
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *HealthSnapshot) GetChrony() string {
|
||||
if x != nil {
|
||||
return x.Chrony
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *HealthSnapshot) GetKioskActive() bool {
|
||||
if x != nil {
|
||||
return x.KioskActive
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *HealthSnapshot) GetSessionUptime() string {
|
||||
if x != nil {
|
||||
return x.SessionUptime
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *HealthSnapshot) GetChromiumCrashes() int32 {
|
||||
if x != nil {
|
||||
return x.ChromiumCrashes
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *HealthSnapshot) GetDisplay() string {
|
||||
if x != nil {
|
||||
return x.Display
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type CommandResult struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"`
|
||||
Ok bool `protobuf:"varint,2,opt,name=ok,proto3" json:"ok,omitempty"`
|
||||
Detail string `protobuf:"bytes,3,opt,name=detail,proto3" json:"detail,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *CommandResult) Reset() {
|
||||
*x = CommandResult{}
|
||||
mi := &file_proto_fleet_agent_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *CommandResult) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*CommandResult) ProtoMessage() {}
|
||||
|
||||
func (x *CommandResult) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_fleet_agent_proto_msgTypes[3]
|
||||
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 CommandResult.ProtoReflect.Descriptor instead.
|
||||
func (*CommandResult) Descriptor() ([]byte, []int) {
|
||||
return file_proto_fleet_agent_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *CommandResult) GetCommandId() string {
|
||||
if x != nil {
|
||||
return x.CommandId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *CommandResult) GetOk() bool {
|
||||
if x != nil {
|
||||
return x.Ok
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *CommandResult) GetDetail() string {
|
||||
if x != nil {
|
||||
return x.Detail
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type ManagerDown struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// Types that are valid to be assigned to Msg:
|
||||
//
|
||||
// *ManagerDown_Desired
|
||||
// *ManagerDown_Command
|
||||
Msg isManagerDown_Msg `protobuf_oneof:"msg"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ManagerDown) Reset() {
|
||||
*x = ManagerDown{}
|
||||
mi := &file_proto_fleet_agent_proto_msgTypes[4]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ManagerDown) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ManagerDown) ProtoMessage() {}
|
||||
|
||||
func (x *ManagerDown) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_fleet_agent_proto_msgTypes[4]
|
||||
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 ManagerDown.ProtoReflect.Descriptor instead.
|
||||
func (*ManagerDown) Descriptor() ([]byte, []int) {
|
||||
return file_proto_fleet_agent_proto_rawDescGZIP(), []int{4}
|
||||
}
|
||||
|
||||
func (x *ManagerDown) GetMsg() isManagerDown_Msg {
|
||||
if x != nil {
|
||||
return x.Msg
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ManagerDown) GetDesired() *DesiredState {
|
||||
if x != nil {
|
||||
if x, ok := x.Msg.(*ManagerDown_Desired); ok {
|
||||
return x.Desired
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ManagerDown) GetCommand() *Command {
|
||||
if x != nil {
|
||||
if x, ok := x.Msg.(*ManagerDown_Command); ok {
|
||||
return x.Command
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type isManagerDown_Msg interface {
|
||||
isManagerDown_Msg()
|
||||
}
|
||||
|
||||
type ManagerDown_Desired struct {
|
||||
Desired *DesiredState `protobuf:"bytes,1,opt,name=desired,proto3,oneof"` // full desired-state: sent on connect + on change
|
||||
}
|
||||
|
||||
type ManagerDown_Command struct {
|
||||
Command *Command `protobuf:"bytes,2,opt,name=command,proto3,oneof"` // imperative action
|
||||
}
|
||||
|
||||
func (*ManagerDown_Desired) isManagerDown_Msg() {}
|
||||
|
||||
func (*ManagerDown_Command) isManagerDown_Msg() {}
|
||||
|
||||
// DesiredState — server-authoritative target the agent reconciles toward.
|
||||
type DesiredState struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
TargetVersion string `protobuf:"bytes,1,opt,name=target_version,json=targetVersion,proto3" json:"target_version,omitempty"`
|
||||
KioskUrl string `protobuf:"bytes,2,opt,name=kiosk_url,json=kioskUrl,proto3" json:"kiosk_url,omitempty"`
|
||||
RebootAtUnix int64 `protobuf:"varint,3,opt,name=reboot_at_unix,json=rebootAtUnix,proto3" json:"reboot_at_unix,omitempty"` // 0 = no scheduled reboot
|
||||
Drain bool `protobuf:"varint,4,opt,name=drain,proto3" json:"drain,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *DesiredState) Reset() {
|
||||
*x = DesiredState{}
|
||||
mi := &file_proto_fleet_agent_proto_msgTypes[5]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *DesiredState) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*DesiredState) ProtoMessage() {}
|
||||
|
||||
func (x *DesiredState) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_fleet_agent_proto_msgTypes[5]
|
||||
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 DesiredState.ProtoReflect.Descriptor instead.
|
||||
func (*DesiredState) Descriptor() ([]byte, []int) {
|
||||
return file_proto_fleet_agent_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
func (x *DesiredState) GetTargetVersion() string {
|
||||
if x != nil {
|
||||
return x.TargetVersion
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *DesiredState) GetKioskUrl() string {
|
||||
if x != nil {
|
||||
return x.KioskUrl
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *DesiredState) GetRebootAtUnix() int64 {
|
||||
if x != nil {
|
||||
return x.RebootAtUnix
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *DesiredState) GetDrain() bool {
|
||||
if x != nil {
|
||||
return x.Drain
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Command — an imperative action pushed live (admin clicked a button in the SPA).
|
||||
type Command struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"`
|
||||
Kind Command_Kind `protobuf:"varint,2,opt,name=kind,proto3,enum=fleet.agent.v1.Command_Kind" json:"kind,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *Command) Reset() {
|
||||
*x = Command{}
|
||||
mi := &file_proto_fleet_agent_proto_msgTypes[6]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *Command) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Command) ProtoMessage() {}
|
||||
|
||||
func (x *Command) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_fleet_agent_proto_msgTypes[6]
|
||||
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 Command.ProtoReflect.Descriptor instead.
|
||||
func (*Command) Descriptor() ([]byte, []int) {
|
||||
return file_proto_fleet_agent_proto_rawDescGZIP(), []int{6}
|
||||
}
|
||||
|
||||
func (x *Command) GetCommandId() string {
|
||||
if x != nil {
|
||||
return x.CommandId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Command) GetKind() Command_Kind {
|
||||
if x != nil {
|
||||
return x.Kind
|
||||
}
|
||||
return Command_KIND_UNSPECIFIED
|
||||
}
|
||||
|
||||
var File_proto_fleet_agent_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_proto_fleet_agent_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\x17proto/fleet_agent.proto\x12\x0efleet.agent.v1\"\xb6\x01\n" +
|
||||
"\aAgentUp\x12-\n" +
|
||||
"\x05hello\x18\x01 \x01(\v2\x15.fleet.agent.v1.HelloH\x00R\x05hello\x12<\n" +
|
||||
"\bsnapshot\x18\x02 \x01(\v2\x1e.fleet.agent.v1.HealthSnapshotH\x00R\bsnapshot\x127\n" +
|
||||
"\x06result\x18\x03 \x01(\v2\x1d.fleet.agent.v1.CommandResultH\x00R\x06resultB\x05\n" +
|
||||
"\x03msg\"\xab\x01\n" +
|
||||
"\x05Hello\x12#\n" +
|
||||
"\rimage_version\x18\x01 \x01(\tR\fimageVersion\x12#\n" +
|
||||
"\rrootfs_digest\x18\x02 \x01(\tR\frootfsDigest\x12\x16\n" +
|
||||
"\x06kernel\x18\x03 \x01(\tR\x06kernel\x12\x1b\n" +
|
||||
"\tkiosk_url\x18\x04 \x01(\tR\bkioskUrl\x12#\n" +
|
||||
"\rstarship_name\x18\x05 \x01(\tR\fstarshipName\"\xae\x03\n" +
|
||||
"\x0eHealthSnapshot\x12\x17\n" +
|
||||
"\aat_unix\x18\x01 \x01(\x03R\x06atUnix\x12\x19\n" +
|
||||
"\bload_avg\x18\x02 \x01(\x01R\aloadAvg\x12\x17\n" +
|
||||
"\acpu_pct\x18\x03 \x01(\x01R\x06cpuPct\x12\x15\n" +
|
||||
"\x06temp_c\x18\x04 \x01(\x01R\x05tempC\x12 \n" +
|
||||
"\fmem_used_pct\x18\x05 \x01(\x01R\n" +
|
||||
"memUsedPct\x12$\n" +
|
||||
"\x0etmpfs_used_pct\x18\x06 \x01(\x01R\ftmpfsUsedPct\x12\x1b\n" +
|
||||
"\tnvme_root\x18\a \x01(\tR\bnvmeRoot\x12\x12\n" +
|
||||
"\x04auth\x18\b \x01(\tR\x04auth\x12\x18\n" +
|
||||
"\aselinux\x18\t \x01(\tR\aselinux\x12\x16\n" +
|
||||
"\x06chrony\x18\n" +
|
||||
" \x01(\tR\x06chrony\x12!\n" +
|
||||
"\fkiosk_active\x18\v \x01(\bR\vkioskActive\x12%\n" +
|
||||
"\x0esession_uptime\x18\f \x01(\tR\rsessionUptime\x12)\n" +
|
||||
"\x10chromium_crashes\x18\r \x01(\x05R\x0fchromiumCrashes\x12\x18\n" +
|
||||
"\adisplay\x18\x0e \x01(\tR\adisplay\"V\n" +
|
||||
"\rCommandResult\x12\x1d\n" +
|
||||
"\n" +
|
||||
"command_id\x18\x01 \x01(\tR\tcommandId\x12\x0e\n" +
|
||||
"\x02ok\x18\x02 \x01(\bR\x02ok\x12\x16\n" +
|
||||
"\x06detail\x18\x03 \x01(\tR\x06detail\"\x83\x01\n" +
|
||||
"\vManagerDown\x128\n" +
|
||||
"\adesired\x18\x01 \x01(\v2\x1c.fleet.agent.v1.DesiredStateH\x00R\adesired\x123\n" +
|
||||
"\acommand\x18\x02 \x01(\v2\x17.fleet.agent.v1.CommandH\x00R\acommandB\x05\n" +
|
||||
"\x03msg\"\x8e\x01\n" +
|
||||
"\fDesiredState\x12%\n" +
|
||||
"\x0etarget_version\x18\x01 \x01(\tR\rtargetVersion\x12\x1b\n" +
|
||||
"\tkiosk_url\x18\x02 \x01(\tR\bkioskUrl\x12$\n" +
|
||||
"\x0ereboot_at_unix\x18\x03 \x01(\x03R\frebootAtUnix\x12\x14\n" +
|
||||
"\x05drain\x18\x04 \x01(\bR\x05drain\"\x9b\x01\n" +
|
||||
"\aCommand\x12\x1d\n" +
|
||||
"\n" +
|
||||
"command_id\x18\x01 \x01(\tR\tcommandId\x120\n" +
|
||||
"\x04kind\x18\x02 \x01(\x0e2\x1c.fleet.agent.v1.Command.KindR\x04kind\"?\n" +
|
||||
"\x04Kind\x12\x14\n" +
|
||||
"\x10KIND_UNSPECIFIED\x10\x00\x12\n" +
|
||||
"\n" +
|
||||
"\x06REBOOT\x10\x01\x12\t\n" +
|
||||
"\x05DRAIN\x10\x02\x12\n" +
|
||||
"\n" +
|
||||
"\x06RESYNC\x10\x032Q\n" +
|
||||
"\n" +
|
||||
"FleetAgent\x12C\n" +
|
||||
"\aSession\x12\x17.fleet.agent.v1.AgentUp\x1a\x1b.fleet.agent.v1.ManagerDown(\x010\x01B\x1dZ\x1bfleet-manager/proto;fleetpbb\x06proto3"
|
||||
|
||||
var (
|
||||
file_proto_fleet_agent_proto_rawDescOnce sync.Once
|
||||
file_proto_fleet_agent_proto_rawDescData []byte
|
||||
)
|
||||
|
||||
func file_proto_fleet_agent_proto_rawDescGZIP() []byte {
|
||||
file_proto_fleet_agent_proto_rawDescOnce.Do(func() {
|
||||
file_proto_fleet_agent_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_proto_fleet_agent_proto_rawDesc), len(file_proto_fleet_agent_proto_rawDesc)))
|
||||
})
|
||||
return file_proto_fleet_agent_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_proto_fleet_agent_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||
var file_proto_fleet_agent_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
|
||||
var file_proto_fleet_agent_proto_goTypes = []any{
|
||||
(Command_Kind)(0), // 0: fleet.agent.v1.Command.Kind
|
||||
(*AgentUp)(nil), // 1: fleet.agent.v1.AgentUp
|
||||
(*Hello)(nil), // 2: fleet.agent.v1.Hello
|
||||
(*HealthSnapshot)(nil), // 3: fleet.agent.v1.HealthSnapshot
|
||||
(*CommandResult)(nil), // 4: fleet.agent.v1.CommandResult
|
||||
(*ManagerDown)(nil), // 5: fleet.agent.v1.ManagerDown
|
||||
(*DesiredState)(nil), // 6: fleet.agent.v1.DesiredState
|
||||
(*Command)(nil), // 7: fleet.agent.v1.Command
|
||||
}
|
||||
var file_proto_fleet_agent_proto_depIdxs = []int32{
|
||||
2, // 0: fleet.agent.v1.AgentUp.hello:type_name -> fleet.agent.v1.Hello
|
||||
3, // 1: fleet.agent.v1.AgentUp.snapshot:type_name -> fleet.agent.v1.HealthSnapshot
|
||||
4, // 2: fleet.agent.v1.AgentUp.result:type_name -> fleet.agent.v1.CommandResult
|
||||
6, // 3: fleet.agent.v1.ManagerDown.desired:type_name -> fleet.agent.v1.DesiredState
|
||||
7, // 4: fleet.agent.v1.ManagerDown.command:type_name -> fleet.agent.v1.Command
|
||||
0, // 5: fleet.agent.v1.Command.kind:type_name -> fleet.agent.v1.Command.Kind
|
||||
1, // 6: fleet.agent.v1.FleetAgent.Session:input_type -> fleet.agent.v1.AgentUp
|
||||
5, // 7: fleet.agent.v1.FleetAgent.Session:output_type -> fleet.agent.v1.ManagerDown
|
||||
7, // [7:8] is the sub-list for method output_type
|
||||
6, // [6:7] is the sub-list for method input_type
|
||||
6, // [6:6] is the sub-list for extension type_name
|
||||
6, // [6:6] is the sub-list for extension extendee
|
||||
0, // [0:6] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_proto_fleet_agent_proto_init() }
|
||||
func file_proto_fleet_agent_proto_init() {
|
||||
if File_proto_fleet_agent_proto != nil {
|
||||
return
|
||||
}
|
||||
file_proto_fleet_agent_proto_msgTypes[0].OneofWrappers = []any{
|
||||
(*AgentUp_Hello)(nil),
|
||||
(*AgentUp_Snapshot)(nil),
|
||||
(*AgentUp_Result)(nil),
|
||||
}
|
||||
file_proto_fleet_agent_proto_msgTypes[4].OneofWrappers = []any{
|
||||
(*ManagerDown_Desired)(nil),
|
||||
(*ManagerDown_Command)(nil),
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_fleet_agent_proto_rawDesc), len(file_proto_fleet_agent_proto_rawDesc)),
|
||||
NumEnums: 1,
|
||||
NumMessages: 7,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
GoTypes: file_proto_fleet_agent_proto_goTypes,
|
||||
DependencyIndexes: file_proto_fleet_agent_proto_depIdxs,
|
||||
EnumInfos: file_proto_fleet_agent_proto_enumTypes,
|
||||
MessageInfos: file_proto_fleet_agent_proto_msgTypes,
|
||||
}.Build()
|
||||
File_proto_fleet_agent_proto = out.File
|
||||
file_proto_fleet_agent_proto_goTypes = nil
|
||||
file_proto_fleet_agent_proto_depIdxs = nil
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
syntax = "proto3";
|
||||
|
||||
// The steady-state contract between the on-host fleet agent and the
|
||||
// fleet-manager. ONE long-lived, host-dialed, mTLS bidi stream (health/metrics
|
||||
// up, desired-state down) — the design's resolved transport fork (bespoke gRPC,
|
||||
// not OTLP+Wazuh). See docs/fleet-management-design.md + tpm-enrolment-design.md.
|
||||
//
|
||||
// Identity is the mTLS peer cert (the host's reused TPM identity cert, fleet CA);
|
||||
// the manager derives the cert serial (= inventory key) from it, so AgentUp
|
||||
// messages carry NO self-asserted identity — a host can only ever be itself.
|
||||
package fleet.agent.v1;
|
||||
|
||||
option go_package = "fleet-manager/proto;fleetpb";
|
||||
|
||||
service FleetAgent {
|
||||
// Session: the single bidirectional stream. The host opens it (dials out, no
|
||||
// inbound host port); the manager pushes desired-state/commands back over the
|
||||
// same connection. Closing/keepalive-timeout = the host's offline signal.
|
||||
rpc Session(stream AgentUp) returns (stream ManagerDown);
|
||||
}
|
||||
|
||||
// ---- host -> manager ------------------------------------------------------
|
||||
|
||||
message AgentUp {
|
||||
oneof msg {
|
||||
Hello hello = 1; // first frame after connect
|
||||
HealthSnapshot snapshot = 2; // periodic telemetry (also written to InfluxDB)
|
||||
CommandResult result = 3; // outcome of a ManagerDown.Command
|
||||
}
|
||||
}
|
||||
|
||||
// Hello — what the host is running, sent once on connect so the manager can
|
||||
// reconcile version drift immediately.
|
||||
message Hello {
|
||||
string image_version = 1;
|
||||
string rootfs_digest = 2;
|
||||
string kernel = 3;
|
||||
string kiosk_url = 4;
|
||||
string starship_name = 5; // advisory; manager already knows it from inventory
|
||||
}
|
||||
|
||||
// HealthSnapshot — one telemetry sample. Cached as the latest value in inventory
|
||||
// AND written as a time-series point to InfluxDB (tagged with the authenticated
|
||||
// cert serial / hostnqn).
|
||||
message HealthSnapshot {
|
||||
int64 at_unix = 1; // sample time, unix seconds (0 = manager stamps now)
|
||||
double load_avg = 2;
|
||||
double cpu_pct = 3;
|
||||
double temp_c = 4;
|
||||
double mem_used_pct = 5;
|
||||
double tmpfs_used_pct = 6; // overlay RAM pressure
|
||||
string nvme_root = 7; // ok|degraded|down
|
||||
string auth = 8; // 802.1x/macsec: up|down
|
||||
string selinux = 9; // enforcing|permissive
|
||||
string chrony = 10; // synced|unsynced
|
||||
bool kiosk_active = 11;
|
||||
string session_uptime = 12;
|
||||
int32 chromium_crashes = 13;
|
||||
string display = 14;
|
||||
}
|
||||
|
||||
message CommandResult {
|
||||
string command_id = 1;
|
||||
bool ok = 2;
|
||||
string detail = 3;
|
||||
}
|
||||
|
||||
// ---- manager -> host ------------------------------------------------------
|
||||
|
||||
message ManagerDown {
|
||||
oneof msg {
|
||||
DesiredState desired = 1; // full desired-state: sent on connect + on change
|
||||
Command command = 2; // imperative action
|
||||
}
|
||||
}
|
||||
|
||||
// DesiredState — server-authoritative target the agent reconciles toward.
|
||||
message DesiredState {
|
||||
string target_version = 1;
|
||||
string kiosk_url = 2;
|
||||
int64 reboot_at_unix = 3; // 0 = no scheduled reboot
|
||||
bool drain = 4;
|
||||
}
|
||||
|
||||
// Command — an imperative action pushed live (admin clicked a button in the SPA).
|
||||
message Command {
|
||||
string command_id = 1;
|
||||
Kind kind = 2;
|
||||
|
||||
enum Kind {
|
||||
KIND_UNSPECIFIED = 0;
|
||||
REBOOT = 1; // reboot now (into desired target_version)
|
||||
DRAIN = 2; // stop taking work / prepare for maintenance
|
||||
RESYNC = 3; // re-fetch + re-apply desired-state now
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.6.2
|
||||
// - protoc v3.21.12
|
||||
// source: proto/fleet_agent.proto
|
||||
|
||||
// The steady-state contract between the on-host fleet agent and the
|
||||
// fleet-manager. ONE long-lived, host-dialed, mTLS bidi stream (health/metrics
|
||||
// up, desired-state down) — the design's resolved transport fork (bespoke gRPC,
|
||||
// not OTLP+Wazuh). See docs/fleet-management-design.md + tpm-enrolment-design.md.
|
||||
//
|
||||
// Identity is the mTLS peer cert (the host's reused TPM identity cert, fleet CA);
|
||||
// the manager derives the cert serial (= inventory key) from it, so AgentUp
|
||||
// messages carry NO self-asserted identity — a host can only ever be itself.
|
||||
|
||||
package fleetpb
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.64.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
FleetAgent_Session_FullMethodName = "/fleet.agent.v1.FleetAgent/Session"
|
||||
)
|
||||
|
||||
// FleetAgentClient is the client API for FleetAgent service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type FleetAgentClient interface {
|
||||
// Session: the single bidirectional stream. The host opens it (dials out, no
|
||||
// inbound host port); the manager pushes desired-state/commands back over the
|
||||
// same connection. Closing/keepalive-timeout = the host's offline signal.
|
||||
Session(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[AgentUp, ManagerDown], error)
|
||||
}
|
||||
|
||||
type fleetAgentClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewFleetAgentClient(cc grpc.ClientConnInterface) FleetAgentClient {
|
||||
return &fleetAgentClient{cc}
|
||||
}
|
||||
|
||||
func (c *fleetAgentClient) Session(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[AgentUp, ManagerDown], error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
stream, err := c.cc.NewStream(ctx, &FleetAgent_ServiceDesc.Streams[0], FleetAgent_Session_FullMethodName, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &grpc.GenericClientStream[AgentUp, ManagerDown]{ClientStream: stream}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type FleetAgent_SessionClient = grpc.BidiStreamingClient[AgentUp, ManagerDown]
|
||||
|
||||
// FleetAgentServer is the server API for FleetAgent service.
|
||||
// All implementations must embed UnimplementedFleetAgentServer
|
||||
// for forward compatibility.
|
||||
type FleetAgentServer interface {
|
||||
// Session: the single bidirectional stream. The host opens it (dials out, no
|
||||
// inbound host port); the manager pushes desired-state/commands back over the
|
||||
// same connection. Closing/keepalive-timeout = the host's offline signal.
|
||||
Session(grpc.BidiStreamingServer[AgentUp, ManagerDown]) error
|
||||
mustEmbedUnimplementedFleetAgentServer()
|
||||
}
|
||||
|
||||
// UnimplementedFleetAgentServer must be embedded to have
|
||||
// forward compatible implementations.
|
||||
//
|
||||
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||
// pointer dereference when methods are called.
|
||||
type UnimplementedFleetAgentServer struct{}
|
||||
|
||||
func (UnimplementedFleetAgentServer) Session(grpc.BidiStreamingServer[AgentUp, ManagerDown]) error {
|
||||
return status.Error(codes.Unimplemented, "method Session not implemented")
|
||||
}
|
||||
func (UnimplementedFleetAgentServer) mustEmbedUnimplementedFleetAgentServer() {}
|
||||
func (UnimplementedFleetAgentServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeFleetAgentServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to FleetAgentServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeFleetAgentServer interface {
|
||||
mustEmbedUnimplementedFleetAgentServer()
|
||||
}
|
||||
|
||||
func RegisterFleetAgentServer(s grpc.ServiceRegistrar, srv FleetAgentServer) {
|
||||
// If the following call panics, it indicates UnimplementedFleetAgentServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||
t.testEmbeddedByValue()
|
||||
}
|
||||
s.RegisterService(&FleetAgent_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _FleetAgent_Session_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(FleetAgentServer).Session(&grpc.GenericServerStream[AgentUp, ManagerDown]{ServerStream: stream})
|
||||
}
|
||||
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type FleetAgent_SessionServer = grpc.BidiStreamingServer[AgentUp, ManagerDown]
|
||||
|
||||
// FleetAgent_ServiceDesc is the grpc.ServiceDesc for FleetAgent service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var FleetAgent_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "fleet.agent.v1.FleetAgent",
|
||||
HandlerType: (*FleetAgentServer)(nil),
|
||||
Methods: []grpc.MethodDesc{},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "Session",
|
||||
Handler: _FleetAgent_Session_Handler,
|
||||
ServerStreams: true,
|
||||
ClientStreams: true,
|
||||
},
|
||||
},
|
||||
Metadata: "proto/fleet_agent.proto",
|
||||
}
|
||||
Reference in New Issue
Block a user