From 6f0c365d44f1757903841c0ec13c99de5484781b Mon Sep 17 00:00:00 2001 From: pptx704 Date: Tue, 10 Mar 2026 03:54:53 +0600 Subject: [PATCH] Add host agent RPC server with sandbox lifecycle management Implement the host agent as a Connect RPC server that orchestrates sandbox creation, destruction, pause/resume, and command execution. Includes sandbox manager with TTL-based reaper, network slot allocator, rootfs cloning, hostagent proto definition with generated stubs, and test/debug scripts. Fix Firecracker process lifetime bug where VM was tied to HTTP request context instead of background context. --- CLAUDE.md | 4 +- Makefile | 3 +- cmd/host-agent/main.go | 154 +- envd/internal/services/spec/filesystem.pb.go | 1444 ++++++++++++ envd/internal/services/spec/process.pb.go | 1970 +++++++++++++++++ .../spec/specconnect/filesystem.connect.go | 337 +++ .../spec/specconnect/process.connect.go | 310 +++ images/envd.service | 12 - internal/filesystem/clone.go | 16 + internal/filesystem/images.go | 1 + internal/hostagent/server.go | 125 ++ internal/id/id.go | 16 + internal/models/host.go | 1 + internal/models/sandbox.go | 32 + internal/network/allocator.go | 40 + internal/sandbox/manager.go | 356 +++ internal/vm/jailer.go | 5 +- proto/hostagent/buf.gen.yaml | 13 + proto/hostagent/buf.yaml | 3 + proto/hostagent/gen/hostagent.pb.go | 848 +++++++ .../hostagentv1connect/hostagent.connect.go | 265 +++ proto/hostagent/hostagent.proto | 96 + scripts/test-host.sh | 233 ++ scripts/update-debug-rootfs.sh | 73 + 24 files changed, 6236 insertions(+), 121 deletions(-) create mode 100644 envd/internal/services/spec/filesystem.pb.go create mode 100644 envd/internal/services/spec/process.pb.go create mode 100644 envd/internal/services/spec/specconnect/filesystem.connect.go create mode 100644 envd/internal/services/spec/specconnect/process.connect.go delete mode 100644 images/envd.service create mode 100644 internal/hostagent/server.go create mode 100644 internal/sandbox/manager.go create mode 100644 proto/hostagent/buf.gen.yaml create mode 100644 proto/hostagent/buf.yaml create mode 100644 proto/hostagent/gen/hostagent.pb.go create mode 100644 proto/hostagent/gen/hostagentv1connect/hostagent.connect.go create mode 100755 scripts/test-host.sh create mode 100755 scripts/update-debug-rootfs.sh diff --git a/CLAUDE.md b/CLAUDE.md index 4bfe192..c265f8e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -770,8 +770,8 @@ open http://localhost:8000/admin/ 1. Write `internal/network/` — TAP + NAT per sandbox 2. Write `internal/filesystem/` — CoW rootfs clones 3. Define hostagent.proto, generate stubs -4. Write host agent gRPC server -5. Test: grpcurl to create/exec/destroy +4. Write host agent rpc server +5. Test: curl to create/exec/destroy ### Phase 3: Control Plane 1. Set up PostgreSQL, write goose migrations diff --git a/Makefile b/Makefile index 5574f74..0fc5ef0 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ build-agent: build-envd: cd $(ENVD_DIR) && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \ - go build -ldflags="$(LDFLAGS)" -o ../$(GOBIN)/envd . + go build -ldflags="$(LDFLAGS)" -o $(GOBIN)/envd . @file $(GOBIN)/envd | grep -q "statically linked" || \ (echo "ERROR: envd is not statically linked!" && exit 1) @@ -85,6 +85,7 @@ generate: proto sqlc proto: cd proto/envd && buf generate + cd proto/hostagent && buf generate cd $(ENVD_DIR)/spec && buf generate sqlc: diff --git a/cmd/host-agent/main.go b/cmd/host-agent/main.go index 290cdda..17569c7 100644 --- a/cmd/host-agent/main.go +++ b/cmd/host-agent/main.go @@ -2,26 +2,16 @@ package main import ( "context" - "fmt" "log/slog" + "net/http" "os" - "os/exec" "os/signal" - "path/filepath" "syscall" "time" - "git.omukk.dev/wrenn/sandbox/internal/envdclient" - "git.omukk.dev/wrenn/sandbox/internal/network" - "git.omukk.dev/wrenn/sandbox/internal/vm" -) - -const ( - kernelPath = "/var/lib/wrenn/kernels/vmlinux" - baseRootfs = "/var/lib/wrenn/sandboxes/rootfs.ext4" - sandboxesDir = "/var/lib/wrenn/sandboxes" - sandboxID = "sb-demo0001" - slotIndex = 1 + "git.omukk.dev/wrenn/sandbox/internal/hostagent" + "git.omukk.dev/wrenn/sandbox/internal/sandbox" + "git.omukk.dev/wrenn/sandbox/proto/hostagent/gen/hostagentv1connect" ) func main() { @@ -39,112 +29,66 @@ func main() { slog.Warn("failed to enable ip_forward", "error", err) } + listenAddr := envOrDefault("AGENT_LISTEN_ADDR", ":50051") + kernelPath := envOrDefault("AGENT_KERNEL_PATH", "/var/lib/wrenn/kernels/vmlinux") + imagesPath := envOrDefault("AGENT_IMAGES_PATH", "/var/lib/wrenn/images") + sandboxesPath := envOrDefault("AGENT_SANDBOXES_PATH", "/var/lib/wrenn/sandboxes") + + cfg := sandbox.Config{ + KernelPath: kernelPath, + ImagesDir: imagesPath, + SandboxesDir: sandboxesPath, + } + + mgr := sandbox.New(cfg) + ctx, cancel := context.WithCancel(context.Background()) defer cancel() - // Handle signals for clean shutdown. + mgr.StartTTLReaper(ctx) + + srv := hostagent.NewServer(mgr) + path, handler := hostagentv1connect.NewHostAgentServiceHandler(srv) + + mux := http.NewServeMux() + mux.Handle(path, handler) + + httpServer := &http.Server{ + Addr: listenAddr, + Handler: mux, + } + + // Graceful shutdown on signal. sigCh := make(chan os.Signal, 1) signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM) go func() { sig := <-sigCh slog.Info("received signal, shutting down", "signal", sig) cancel() + + shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 30*time.Second) + defer shutdownCancel() + + mgr.Shutdown(shutdownCtx) + + if err := httpServer.Shutdown(shutdownCtx); err != nil { + slog.Error("http server shutdown error", "error", err) + } }() - if err := run(ctx); err != nil { - slog.Error("fatal error", "error", err) + slog.Info("host agent starting", "addr", listenAddr) + if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed { + slog.Error("http server error", "error", err) os.Exit(1) } + + slog.Info("host agent stopped") } -func run(ctx context.Context) error { - // Step 1: Clone rootfs for this sandbox. - sandboxRootfs := filepath.Join(sandboxesDir, fmt.Sprintf("%s-rootfs.ext4", sandboxID)) - slog.Info("cloning rootfs", "src", baseRootfs, "dst", sandboxRootfs) - - if err := cloneRootfs(baseRootfs, sandboxRootfs); err != nil { - return fmt.Errorf("clone rootfs: %w", err) +func envOrDefault(key, def string) string { + if v := os.Getenv(key); v != "" { + return v } - defer os.Remove(sandboxRootfs) - - // Step 2: Set up network. - slot := network.NewSlot(slotIndex) - - slog.Info("setting up network", "slot", slotIndex) - if err := network.CreateNetwork(slot); err != nil { - return fmt.Errorf("create network: %w", err) - } - defer func() { - slog.Info("tearing down network") - network.RemoveNetwork(slot) - }() - - // Step 3: Boot the VM. - mgr := vm.NewManager() - - cfg := vm.VMConfig{ - SandboxID: sandboxID, - KernelPath: kernelPath, - RootfsPath: sandboxRootfs, - VCPUs: 1, - MemoryMB: 512, - NetworkNamespace: slot.NamespaceID, - TapDevice: slot.TapName, - TapMAC: slot.TapMAC, - GuestIP: slot.GuestIP, - GatewayIP: slot.TapIP, - NetMask: slot.GuestNetMask, - } - - vmInstance, err := mgr.Create(ctx, cfg) - if err != nil { - return fmt.Errorf("create VM: %w", err) - } - _ = vmInstance - defer func() { - slog.Info("destroying VM") - mgr.Destroy(context.Background(), sandboxID) - }() - - // Step 4: Wait for envd to be ready. - client := envdclient.New(slot.HostIP.String()) - - waitCtx, waitCancel := context.WithTimeout(ctx, 30*time.Second) - defer waitCancel() - - if err := client.WaitUntilReady(waitCtx); err != nil { - return fmt.Errorf("wait for envd: %w", err) - } - - // Step 5: Run "echo hello" inside the sandbox. - slog.Info("executing command", "cmd", "echo hello") - - result, err := client.Exec(ctx, "/bin/sh", "-c", "echo hello") - if err != nil { - return fmt.Errorf("exec: %w", err) - } - - fmt.Printf("\n=== Command Output ===\n") - fmt.Printf("stdout: %s", string(result.Stdout)) - if len(result.Stderr) > 0 { - fmt.Printf("stderr: %s", string(result.Stderr)) - } - fmt.Printf("exit code: %d\n", result.ExitCode) - fmt.Printf("======================\n\n") - - // Step 6: Clean shutdown. - slog.Info("demo complete, cleaning up") - - return nil + return def } -// cloneRootfs creates a copy-on-write clone of the base rootfs image. -// Uses reflink if supported by the filesystem, falls back to regular copy. -func cloneRootfs(src, dst string) error { - // Try reflink first (instant, CoW). - cmd := exec.Command("cp", "--reflink=auto", src, dst) - if err := cmd.Run(); err != nil { - return fmt.Errorf("cp --reflink=auto: %w", err) - } - return nil -} diff --git a/envd/internal/services/spec/filesystem.pb.go b/envd/internal/services/spec/filesystem.pb.go new file mode 100644 index 0000000..0c654fb --- /dev/null +++ b/envd/internal/services/spec/filesystem.pb.go @@ -0,0 +1,1444 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: filesystem.proto + +package spec + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + 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 FileType int32 + +const ( + FileType_FILE_TYPE_UNSPECIFIED FileType = 0 + FileType_FILE_TYPE_FILE FileType = 1 + FileType_FILE_TYPE_DIRECTORY FileType = 2 + FileType_FILE_TYPE_SYMLINK FileType = 3 +) + +// Enum value maps for FileType. +var ( + FileType_name = map[int32]string{ + 0: "FILE_TYPE_UNSPECIFIED", + 1: "FILE_TYPE_FILE", + 2: "FILE_TYPE_DIRECTORY", + 3: "FILE_TYPE_SYMLINK", + } + FileType_value = map[string]int32{ + "FILE_TYPE_UNSPECIFIED": 0, + "FILE_TYPE_FILE": 1, + "FILE_TYPE_DIRECTORY": 2, + "FILE_TYPE_SYMLINK": 3, + } +) + +func (x FileType) Enum() *FileType { + p := new(FileType) + *p = x + return p +} + +func (x FileType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (FileType) Descriptor() protoreflect.EnumDescriptor { + return file_filesystem_proto_enumTypes[0].Descriptor() +} + +func (FileType) Type() protoreflect.EnumType { + return &file_filesystem_proto_enumTypes[0] +} + +func (x FileType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use FileType.Descriptor instead. +func (FileType) EnumDescriptor() ([]byte, []int) { + return file_filesystem_proto_rawDescGZIP(), []int{0} +} + +type EventType int32 + +const ( + EventType_EVENT_TYPE_UNSPECIFIED EventType = 0 + EventType_EVENT_TYPE_CREATE EventType = 1 + EventType_EVENT_TYPE_WRITE EventType = 2 + EventType_EVENT_TYPE_REMOVE EventType = 3 + EventType_EVENT_TYPE_RENAME EventType = 4 + EventType_EVENT_TYPE_CHMOD EventType = 5 +) + +// Enum value maps for EventType. +var ( + EventType_name = map[int32]string{ + 0: "EVENT_TYPE_UNSPECIFIED", + 1: "EVENT_TYPE_CREATE", + 2: "EVENT_TYPE_WRITE", + 3: "EVENT_TYPE_REMOVE", + 4: "EVENT_TYPE_RENAME", + 5: "EVENT_TYPE_CHMOD", + } + EventType_value = map[string]int32{ + "EVENT_TYPE_UNSPECIFIED": 0, + "EVENT_TYPE_CREATE": 1, + "EVENT_TYPE_WRITE": 2, + "EVENT_TYPE_REMOVE": 3, + "EVENT_TYPE_RENAME": 4, + "EVENT_TYPE_CHMOD": 5, + } +) + +func (x EventType) Enum() *EventType { + p := new(EventType) + *p = x + return p +} + +func (x EventType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (EventType) Descriptor() protoreflect.EnumDescriptor { + return file_filesystem_proto_enumTypes[1].Descriptor() +} + +func (EventType) Type() protoreflect.EnumType { + return &file_filesystem_proto_enumTypes[1] +} + +func (x EventType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use EventType.Descriptor instead. +func (EventType) EnumDescriptor() ([]byte, []int) { + return file_filesystem_proto_rawDescGZIP(), []int{1} +} + +type MoveRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Source string `protobuf:"bytes,1,opt,name=source,proto3" json:"source,omitempty"` + Destination string `protobuf:"bytes,2,opt,name=destination,proto3" json:"destination,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *MoveRequest) Reset() { + *x = MoveRequest{} + mi := &file_filesystem_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *MoveRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MoveRequest) ProtoMessage() {} + +func (x *MoveRequest) ProtoReflect() protoreflect.Message { + mi := &file_filesystem_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 MoveRequest.ProtoReflect.Descriptor instead. +func (*MoveRequest) Descriptor() ([]byte, []int) { + return file_filesystem_proto_rawDescGZIP(), []int{0} +} + +func (x *MoveRequest) GetSource() string { + if x != nil { + return x.Source + } + return "" +} + +func (x *MoveRequest) GetDestination() string { + if x != nil { + return x.Destination + } + return "" +} + +type MoveResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Entry *EntryInfo `protobuf:"bytes,1,opt,name=entry,proto3" json:"entry,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *MoveResponse) Reset() { + *x = MoveResponse{} + mi := &file_filesystem_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *MoveResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MoveResponse) ProtoMessage() {} + +func (x *MoveResponse) ProtoReflect() protoreflect.Message { + mi := &file_filesystem_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 MoveResponse.ProtoReflect.Descriptor instead. +func (*MoveResponse) Descriptor() ([]byte, []int) { + return file_filesystem_proto_rawDescGZIP(), []int{1} +} + +func (x *MoveResponse) GetEntry() *EntryInfo { + if x != nil { + return x.Entry + } + return nil +} + +type MakeDirRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *MakeDirRequest) Reset() { + *x = MakeDirRequest{} + mi := &file_filesystem_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *MakeDirRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MakeDirRequest) ProtoMessage() {} + +func (x *MakeDirRequest) ProtoReflect() protoreflect.Message { + mi := &file_filesystem_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 MakeDirRequest.ProtoReflect.Descriptor instead. +func (*MakeDirRequest) Descriptor() ([]byte, []int) { + return file_filesystem_proto_rawDescGZIP(), []int{2} +} + +func (x *MakeDirRequest) GetPath() string { + if x != nil { + return x.Path + } + return "" +} + +type MakeDirResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Entry *EntryInfo `protobuf:"bytes,1,opt,name=entry,proto3" json:"entry,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *MakeDirResponse) Reset() { + *x = MakeDirResponse{} + mi := &file_filesystem_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *MakeDirResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MakeDirResponse) ProtoMessage() {} + +func (x *MakeDirResponse) ProtoReflect() protoreflect.Message { + mi := &file_filesystem_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 MakeDirResponse.ProtoReflect.Descriptor instead. +func (*MakeDirResponse) Descriptor() ([]byte, []int) { + return file_filesystem_proto_rawDescGZIP(), []int{3} +} + +func (x *MakeDirResponse) GetEntry() *EntryInfo { + if x != nil { + return x.Entry + } + return nil +} + +type RemoveRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RemoveRequest) Reset() { + *x = RemoveRequest{} + mi := &file_filesystem_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RemoveRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveRequest) ProtoMessage() {} + +func (x *RemoveRequest) ProtoReflect() protoreflect.Message { + mi := &file_filesystem_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 RemoveRequest.ProtoReflect.Descriptor instead. +func (*RemoveRequest) Descriptor() ([]byte, []int) { + return file_filesystem_proto_rawDescGZIP(), []int{4} +} + +func (x *RemoveRequest) GetPath() string { + if x != nil { + return x.Path + } + return "" +} + +type RemoveResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RemoveResponse) Reset() { + *x = RemoveResponse{} + mi := &file_filesystem_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RemoveResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveResponse) ProtoMessage() {} + +func (x *RemoveResponse) ProtoReflect() protoreflect.Message { + mi := &file_filesystem_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 RemoveResponse.ProtoReflect.Descriptor instead. +func (*RemoveResponse) Descriptor() ([]byte, []int) { + return file_filesystem_proto_rawDescGZIP(), []int{5} +} + +type StatRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *StatRequest) Reset() { + *x = StatRequest{} + mi := &file_filesystem_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StatRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StatRequest) ProtoMessage() {} + +func (x *StatRequest) ProtoReflect() protoreflect.Message { + mi := &file_filesystem_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 StatRequest.ProtoReflect.Descriptor instead. +func (*StatRequest) Descriptor() ([]byte, []int) { + return file_filesystem_proto_rawDescGZIP(), []int{6} +} + +func (x *StatRequest) GetPath() string { + if x != nil { + return x.Path + } + return "" +} + +type StatResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Entry *EntryInfo `protobuf:"bytes,1,opt,name=entry,proto3" json:"entry,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *StatResponse) Reset() { + *x = StatResponse{} + mi := &file_filesystem_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StatResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StatResponse) ProtoMessage() {} + +func (x *StatResponse) ProtoReflect() protoreflect.Message { + mi := &file_filesystem_proto_msgTypes[7] + 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 StatResponse.ProtoReflect.Descriptor instead. +func (*StatResponse) Descriptor() ([]byte, []int) { + return file_filesystem_proto_rawDescGZIP(), []int{7} +} + +func (x *StatResponse) GetEntry() *EntryInfo { + if x != nil { + return x.Entry + } + return nil +} + +type EntryInfo struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Type FileType `protobuf:"varint,2,opt,name=type,proto3,enum=filesystem.FileType" json:"type,omitempty"` + Path string `protobuf:"bytes,3,opt,name=path,proto3" json:"path,omitempty"` + Size int64 `protobuf:"varint,4,opt,name=size,proto3" json:"size,omitempty"` + Mode uint32 `protobuf:"varint,5,opt,name=mode,proto3" json:"mode,omitempty"` + Permissions string `protobuf:"bytes,6,opt,name=permissions,proto3" json:"permissions,omitempty"` + Owner string `protobuf:"bytes,7,opt,name=owner,proto3" json:"owner,omitempty"` + Group string `protobuf:"bytes,8,opt,name=group,proto3" json:"group,omitempty"` + ModifiedTime *timestamppb.Timestamp `protobuf:"bytes,9,opt,name=modified_time,json=modifiedTime,proto3" json:"modified_time,omitempty"` + // If the entry is a symlink, this field contains the target of the symlink. + SymlinkTarget *string `protobuf:"bytes,10,opt,name=symlink_target,json=symlinkTarget,proto3,oneof" json:"symlink_target,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *EntryInfo) Reset() { + *x = EntryInfo{} + mi := &file_filesystem_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *EntryInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EntryInfo) ProtoMessage() {} + +func (x *EntryInfo) ProtoReflect() protoreflect.Message { + mi := &file_filesystem_proto_msgTypes[8] + 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 EntryInfo.ProtoReflect.Descriptor instead. +func (*EntryInfo) Descriptor() ([]byte, []int) { + return file_filesystem_proto_rawDescGZIP(), []int{8} +} + +func (x *EntryInfo) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *EntryInfo) GetType() FileType { + if x != nil { + return x.Type + } + return FileType_FILE_TYPE_UNSPECIFIED +} + +func (x *EntryInfo) GetPath() string { + if x != nil { + return x.Path + } + return "" +} + +func (x *EntryInfo) GetSize() int64 { + if x != nil { + return x.Size + } + return 0 +} + +func (x *EntryInfo) GetMode() uint32 { + if x != nil { + return x.Mode + } + return 0 +} + +func (x *EntryInfo) GetPermissions() string { + if x != nil { + return x.Permissions + } + return "" +} + +func (x *EntryInfo) GetOwner() string { + if x != nil { + return x.Owner + } + return "" +} + +func (x *EntryInfo) GetGroup() string { + if x != nil { + return x.Group + } + return "" +} + +func (x *EntryInfo) GetModifiedTime() *timestamppb.Timestamp { + if x != nil { + return x.ModifiedTime + } + return nil +} + +func (x *EntryInfo) GetSymlinkTarget() string { + if x != nil && x.SymlinkTarget != nil { + return *x.SymlinkTarget + } + return "" +} + +type ListDirRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` + Depth uint32 `protobuf:"varint,2,opt,name=depth,proto3" json:"depth,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListDirRequest) Reset() { + *x = ListDirRequest{} + mi := &file_filesystem_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListDirRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListDirRequest) ProtoMessage() {} + +func (x *ListDirRequest) ProtoReflect() protoreflect.Message { + mi := &file_filesystem_proto_msgTypes[9] + 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 ListDirRequest.ProtoReflect.Descriptor instead. +func (*ListDirRequest) Descriptor() ([]byte, []int) { + return file_filesystem_proto_rawDescGZIP(), []int{9} +} + +func (x *ListDirRequest) GetPath() string { + if x != nil { + return x.Path + } + return "" +} + +func (x *ListDirRequest) GetDepth() uint32 { + if x != nil { + return x.Depth + } + return 0 +} + +type ListDirResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Entries []*EntryInfo `protobuf:"bytes,1,rep,name=entries,proto3" json:"entries,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListDirResponse) Reset() { + *x = ListDirResponse{} + mi := &file_filesystem_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListDirResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListDirResponse) ProtoMessage() {} + +func (x *ListDirResponse) ProtoReflect() protoreflect.Message { + mi := &file_filesystem_proto_msgTypes[10] + 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 ListDirResponse.ProtoReflect.Descriptor instead. +func (*ListDirResponse) Descriptor() ([]byte, []int) { + return file_filesystem_proto_rawDescGZIP(), []int{10} +} + +func (x *ListDirResponse) GetEntries() []*EntryInfo { + if x != nil { + return x.Entries + } + return nil +} + +type WatchDirRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` + Recursive bool `protobuf:"varint,2,opt,name=recursive,proto3" json:"recursive,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WatchDirRequest) Reset() { + *x = WatchDirRequest{} + mi := &file_filesystem_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WatchDirRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WatchDirRequest) ProtoMessage() {} + +func (x *WatchDirRequest) ProtoReflect() protoreflect.Message { + mi := &file_filesystem_proto_msgTypes[11] + 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 WatchDirRequest.ProtoReflect.Descriptor instead. +func (*WatchDirRequest) Descriptor() ([]byte, []int) { + return file_filesystem_proto_rawDescGZIP(), []int{11} +} + +func (x *WatchDirRequest) GetPath() string { + if x != nil { + return x.Path + } + return "" +} + +func (x *WatchDirRequest) GetRecursive() bool { + if x != nil { + return x.Recursive + } + return false +} + +type FilesystemEvent struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Type EventType `protobuf:"varint,2,opt,name=type,proto3,enum=filesystem.EventType" json:"type,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *FilesystemEvent) Reset() { + *x = FilesystemEvent{} + mi := &file_filesystem_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *FilesystemEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FilesystemEvent) ProtoMessage() {} + +func (x *FilesystemEvent) ProtoReflect() protoreflect.Message { + mi := &file_filesystem_proto_msgTypes[12] + 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 FilesystemEvent.ProtoReflect.Descriptor instead. +func (*FilesystemEvent) Descriptor() ([]byte, []int) { + return file_filesystem_proto_rawDescGZIP(), []int{12} +} + +func (x *FilesystemEvent) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *FilesystemEvent) GetType() EventType { + if x != nil { + return x.Type + } + return EventType_EVENT_TYPE_UNSPECIFIED +} + +type WatchDirResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Types that are valid to be assigned to Event: + // + // *WatchDirResponse_Start + // *WatchDirResponse_Filesystem + // *WatchDirResponse_Keepalive + Event isWatchDirResponse_Event `protobuf_oneof:"event"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WatchDirResponse) Reset() { + *x = WatchDirResponse{} + mi := &file_filesystem_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WatchDirResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WatchDirResponse) ProtoMessage() {} + +func (x *WatchDirResponse) ProtoReflect() protoreflect.Message { + mi := &file_filesystem_proto_msgTypes[13] + 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 WatchDirResponse.ProtoReflect.Descriptor instead. +func (*WatchDirResponse) Descriptor() ([]byte, []int) { + return file_filesystem_proto_rawDescGZIP(), []int{13} +} + +func (x *WatchDirResponse) GetEvent() isWatchDirResponse_Event { + if x != nil { + return x.Event + } + return nil +} + +func (x *WatchDirResponse) GetStart() *WatchDirResponse_StartEvent { + if x != nil { + if x, ok := x.Event.(*WatchDirResponse_Start); ok { + return x.Start + } + } + return nil +} + +func (x *WatchDirResponse) GetFilesystem() *FilesystemEvent { + if x != nil { + if x, ok := x.Event.(*WatchDirResponse_Filesystem); ok { + return x.Filesystem + } + } + return nil +} + +func (x *WatchDirResponse) GetKeepalive() *WatchDirResponse_KeepAlive { + if x != nil { + if x, ok := x.Event.(*WatchDirResponse_Keepalive); ok { + return x.Keepalive + } + } + return nil +} + +type isWatchDirResponse_Event interface { + isWatchDirResponse_Event() +} + +type WatchDirResponse_Start struct { + Start *WatchDirResponse_StartEvent `protobuf:"bytes,1,opt,name=start,proto3,oneof"` +} + +type WatchDirResponse_Filesystem struct { + Filesystem *FilesystemEvent `protobuf:"bytes,2,opt,name=filesystem,proto3,oneof"` +} + +type WatchDirResponse_Keepalive struct { + Keepalive *WatchDirResponse_KeepAlive `protobuf:"bytes,3,opt,name=keepalive,proto3,oneof"` +} + +func (*WatchDirResponse_Start) isWatchDirResponse_Event() {} + +func (*WatchDirResponse_Filesystem) isWatchDirResponse_Event() {} + +func (*WatchDirResponse_Keepalive) isWatchDirResponse_Event() {} + +type CreateWatcherRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` + Recursive bool `protobuf:"varint,2,opt,name=recursive,proto3" json:"recursive,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreateWatcherRequest) Reset() { + *x = CreateWatcherRequest{} + mi := &file_filesystem_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateWatcherRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateWatcherRequest) ProtoMessage() {} + +func (x *CreateWatcherRequest) ProtoReflect() protoreflect.Message { + mi := &file_filesystem_proto_msgTypes[14] + 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 CreateWatcherRequest.ProtoReflect.Descriptor instead. +func (*CreateWatcherRequest) Descriptor() ([]byte, []int) { + return file_filesystem_proto_rawDescGZIP(), []int{14} +} + +func (x *CreateWatcherRequest) GetPath() string { + if x != nil { + return x.Path + } + return "" +} + +func (x *CreateWatcherRequest) GetRecursive() bool { + if x != nil { + return x.Recursive + } + return false +} + +type CreateWatcherResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + WatcherId string `protobuf:"bytes,1,opt,name=watcher_id,json=watcherId,proto3" json:"watcher_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreateWatcherResponse) Reset() { + *x = CreateWatcherResponse{} + mi := &file_filesystem_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateWatcherResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateWatcherResponse) ProtoMessage() {} + +func (x *CreateWatcherResponse) ProtoReflect() protoreflect.Message { + mi := &file_filesystem_proto_msgTypes[15] + 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 CreateWatcherResponse.ProtoReflect.Descriptor instead. +func (*CreateWatcherResponse) Descriptor() ([]byte, []int) { + return file_filesystem_proto_rawDescGZIP(), []int{15} +} + +func (x *CreateWatcherResponse) GetWatcherId() string { + if x != nil { + return x.WatcherId + } + return "" +} + +type GetWatcherEventsRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + WatcherId string `protobuf:"bytes,1,opt,name=watcher_id,json=watcherId,proto3" json:"watcher_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetWatcherEventsRequest) Reset() { + *x = GetWatcherEventsRequest{} + mi := &file_filesystem_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetWatcherEventsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetWatcherEventsRequest) ProtoMessage() {} + +func (x *GetWatcherEventsRequest) ProtoReflect() protoreflect.Message { + mi := &file_filesystem_proto_msgTypes[16] + 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 GetWatcherEventsRequest.ProtoReflect.Descriptor instead. +func (*GetWatcherEventsRequest) Descriptor() ([]byte, []int) { + return file_filesystem_proto_rawDescGZIP(), []int{16} +} + +func (x *GetWatcherEventsRequest) GetWatcherId() string { + if x != nil { + return x.WatcherId + } + return "" +} + +type GetWatcherEventsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Events []*FilesystemEvent `protobuf:"bytes,1,rep,name=events,proto3" json:"events,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetWatcherEventsResponse) Reset() { + *x = GetWatcherEventsResponse{} + mi := &file_filesystem_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetWatcherEventsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetWatcherEventsResponse) ProtoMessage() {} + +func (x *GetWatcherEventsResponse) ProtoReflect() protoreflect.Message { + mi := &file_filesystem_proto_msgTypes[17] + 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 GetWatcherEventsResponse.ProtoReflect.Descriptor instead. +func (*GetWatcherEventsResponse) Descriptor() ([]byte, []int) { + return file_filesystem_proto_rawDescGZIP(), []int{17} +} + +func (x *GetWatcherEventsResponse) GetEvents() []*FilesystemEvent { + if x != nil { + return x.Events + } + return nil +} + +type RemoveWatcherRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + WatcherId string `protobuf:"bytes,1,opt,name=watcher_id,json=watcherId,proto3" json:"watcher_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RemoveWatcherRequest) Reset() { + *x = RemoveWatcherRequest{} + mi := &file_filesystem_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RemoveWatcherRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveWatcherRequest) ProtoMessage() {} + +func (x *RemoveWatcherRequest) ProtoReflect() protoreflect.Message { + mi := &file_filesystem_proto_msgTypes[18] + 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 RemoveWatcherRequest.ProtoReflect.Descriptor instead. +func (*RemoveWatcherRequest) Descriptor() ([]byte, []int) { + return file_filesystem_proto_rawDescGZIP(), []int{18} +} + +func (x *RemoveWatcherRequest) GetWatcherId() string { + if x != nil { + return x.WatcherId + } + return "" +} + +type RemoveWatcherResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RemoveWatcherResponse) Reset() { + *x = RemoveWatcherResponse{} + mi := &file_filesystem_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RemoveWatcherResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveWatcherResponse) ProtoMessage() {} + +func (x *RemoveWatcherResponse) ProtoReflect() protoreflect.Message { + mi := &file_filesystem_proto_msgTypes[19] + 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 RemoveWatcherResponse.ProtoReflect.Descriptor instead. +func (*RemoveWatcherResponse) Descriptor() ([]byte, []int) { + return file_filesystem_proto_rawDescGZIP(), []int{19} +} + +type WatchDirResponse_StartEvent struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WatchDirResponse_StartEvent) Reset() { + *x = WatchDirResponse_StartEvent{} + mi := &file_filesystem_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WatchDirResponse_StartEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WatchDirResponse_StartEvent) ProtoMessage() {} + +func (x *WatchDirResponse_StartEvent) ProtoReflect() protoreflect.Message { + mi := &file_filesystem_proto_msgTypes[20] + 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 WatchDirResponse_StartEvent.ProtoReflect.Descriptor instead. +func (*WatchDirResponse_StartEvent) Descriptor() ([]byte, []int) { + return file_filesystem_proto_rawDescGZIP(), []int{13, 0} +} + +type WatchDirResponse_KeepAlive struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WatchDirResponse_KeepAlive) Reset() { + *x = WatchDirResponse_KeepAlive{} + mi := &file_filesystem_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WatchDirResponse_KeepAlive) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WatchDirResponse_KeepAlive) ProtoMessage() {} + +func (x *WatchDirResponse_KeepAlive) ProtoReflect() protoreflect.Message { + mi := &file_filesystem_proto_msgTypes[21] + 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 WatchDirResponse_KeepAlive.ProtoReflect.Descriptor instead. +func (*WatchDirResponse_KeepAlive) Descriptor() ([]byte, []int) { + return file_filesystem_proto_rawDescGZIP(), []int{13, 1} +} + +var File_filesystem_proto protoreflect.FileDescriptor + +const file_filesystem_proto_rawDesc = "" + + "\n" + + "\x10filesystem.proto\x12\n" + + "filesystem\x1a\x1fgoogle/protobuf/timestamp.proto\"G\n" + + "\vMoveRequest\x12\x16\n" + + "\x06source\x18\x01 \x01(\tR\x06source\x12 \n" + + "\vdestination\x18\x02 \x01(\tR\vdestination\";\n" + + "\fMoveResponse\x12+\n" + + "\x05entry\x18\x01 \x01(\v2\x15.filesystem.EntryInfoR\x05entry\"$\n" + + "\x0eMakeDirRequest\x12\x12\n" + + "\x04path\x18\x01 \x01(\tR\x04path\">\n" + + "\x0fMakeDirResponse\x12+\n" + + "\x05entry\x18\x01 \x01(\v2\x15.filesystem.EntryInfoR\x05entry\"#\n" + + "\rRemoveRequest\x12\x12\n" + + "\x04path\x18\x01 \x01(\tR\x04path\"\x10\n" + + "\x0eRemoveResponse\"!\n" + + "\vStatRequest\x12\x12\n" + + "\x04path\x18\x01 \x01(\tR\x04path\";\n" + + "\fStatResponse\x12+\n" + + "\x05entry\x18\x01 \x01(\v2\x15.filesystem.EntryInfoR\x05entry\"\xd3\x02\n" + + "\tEntryInfo\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x12(\n" + + "\x04type\x18\x02 \x01(\x0e2\x14.filesystem.FileTypeR\x04type\x12\x12\n" + + "\x04path\x18\x03 \x01(\tR\x04path\x12\x12\n" + + "\x04size\x18\x04 \x01(\x03R\x04size\x12\x12\n" + + "\x04mode\x18\x05 \x01(\rR\x04mode\x12 \n" + + "\vpermissions\x18\x06 \x01(\tR\vpermissions\x12\x14\n" + + "\x05owner\x18\a \x01(\tR\x05owner\x12\x14\n" + + "\x05group\x18\b \x01(\tR\x05group\x12?\n" + + "\rmodified_time\x18\t \x01(\v2\x1a.google.protobuf.TimestampR\fmodifiedTime\x12*\n" + + "\x0esymlink_target\x18\n" + + " \x01(\tH\x00R\rsymlinkTarget\x88\x01\x01B\x11\n" + + "\x0f_symlink_target\":\n" + + "\x0eListDirRequest\x12\x12\n" + + "\x04path\x18\x01 \x01(\tR\x04path\x12\x14\n" + + "\x05depth\x18\x02 \x01(\rR\x05depth\"B\n" + + "\x0fListDirResponse\x12/\n" + + "\aentries\x18\x01 \x03(\v2\x15.filesystem.EntryInfoR\aentries\"C\n" + + "\x0fWatchDirRequest\x12\x12\n" + + "\x04path\x18\x01 \x01(\tR\x04path\x12\x1c\n" + + "\trecursive\x18\x02 \x01(\bR\trecursive\"P\n" + + "\x0fFilesystemEvent\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x12)\n" + + "\x04type\x18\x02 \x01(\x0e2\x15.filesystem.EventTypeR\x04type\"\xfe\x01\n" + + "\x10WatchDirResponse\x12?\n" + + "\x05start\x18\x01 \x01(\v2'.filesystem.WatchDirResponse.StartEventH\x00R\x05start\x12=\n" + + "\n" + + "filesystem\x18\x02 \x01(\v2\x1b.filesystem.FilesystemEventH\x00R\n" + + "filesystem\x12F\n" + + "\tkeepalive\x18\x03 \x01(\v2&.filesystem.WatchDirResponse.KeepAliveH\x00R\tkeepalive\x1a\f\n" + + "\n" + + "StartEvent\x1a\v\n" + + "\tKeepAliveB\a\n" + + "\x05event\"H\n" + + "\x14CreateWatcherRequest\x12\x12\n" + + "\x04path\x18\x01 \x01(\tR\x04path\x12\x1c\n" + + "\trecursive\x18\x02 \x01(\bR\trecursive\"6\n" + + "\x15CreateWatcherResponse\x12\x1d\n" + + "\n" + + "watcher_id\x18\x01 \x01(\tR\twatcherId\"8\n" + + "\x17GetWatcherEventsRequest\x12\x1d\n" + + "\n" + + "watcher_id\x18\x01 \x01(\tR\twatcherId\"O\n" + + "\x18GetWatcherEventsResponse\x123\n" + + "\x06events\x18\x01 \x03(\v2\x1b.filesystem.FilesystemEventR\x06events\"5\n" + + "\x14RemoveWatcherRequest\x12\x1d\n" + + "\n" + + "watcher_id\x18\x01 \x01(\tR\twatcherId\"\x17\n" + + "\x15RemoveWatcherResponse*i\n" + + "\bFileType\x12\x19\n" + + "\x15FILE_TYPE_UNSPECIFIED\x10\x00\x12\x12\n" + + "\x0eFILE_TYPE_FILE\x10\x01\x12\x17\n" + + "\x13FILE_TYPE_DIRECTORY\x10\x02\x12\x15\n" + + "\x11FILE_TYPE_SYMLINK\x10\x03*\x98\x01\n" + + "\tEventType\x12\x1a\n" + + "\x16EVENT_TYPE_UNSPECIFIED\x10\x00\x12\x15\n" + + "\x11EVENT_TYPE_CREATE\x10\x01\x12\x14\n" + + "\x10EVENT_TYPE_WRITE\x10\x02\x12\x15\n" + + "\x11EVENT_TYPE_REMOVE\x10\x03\x12\x15\n" + + "\x11EVENT_TYPE_RENAME\x10\x04\x12\x14\n" + + "\x10EVENT_TYPE_CHMOD\x10\x052\x9f\x05\n" + + "\n" + + "Filesystem\x129\n" + + "\x04Stat\x12\x17.filesystem.StatRequest\x1a\x18.filesystem.StatResponse\x12B\n" + + "\aMakeDir\x12\x1a.filesystem.MakeDirRequest\x1a\x1b.filesystem.MakeDirResponse\x129\n" + + "\x04Move\x12\x17.filesystem.MoveRequest\x1a\x18.filesystem.MoveResponse\x12B\n" + + "\aListDir\x12\x1a.filesystem.ListDirRequest\x1a\x1b.filesystem.ListDirResponse\x12?\n" + + "\x06Remove\x12\x19.filesystem.RemoveRequest\x1a\x1a.filesystem.RemoveResponse\x12G\n" + + "\bWatchDir\x12\x1b.filesystem.WatchDirRequest\x1a\x1c.filesystem.WatchDirResponse0\x01\x12T\n" + + "\rCreateWatcher\x12 .filesystem.CreateWatcherRequest\x1a!.filesystem.CreateWatcherResponse\x12]\n" + + "\x10GetWatcherEvents\x12#.filesystem.GetWatcherEventsRequest\x1a$.filesystem.GetWatcherEventsResponse\x12T\n" + + "\rRemoveWatcher\x12 .filesystem.RemoveWatcherRequest\x1a!.filesystem.RemoveWatcherResponseB\xa2\x01\n" + + "\x0ecom.filesystemB\x0fFilesystemProtoP\x01Z7git.omukk.dev/wrenn/sandbox/envd/internal/services/spec\xa2\x02\x03FXX\xaa\x02\n" + + "Filesystem\xca\x02\n" + + "Filesystem\xe2\x02\x16Filesystem\\GPBMetadata\xea\x02\n" + + "Filesystemb\x06proto3" + +var ( + file_filesystem_proto_rawDescOnce sync.Once + file_filesystem_proto_rawDescData []byte +) + +func file_filesystem_proto_rawDescGZIP() []byte { + file_filesystem_proto_rawDescOnce.Do(func() { + file_filesystem_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_filesystem_proto_rawDesc), len(file_filesystem_proto_rawDesc))) + }) + return file_filesystem_proto_rawDescData +} + +var file_filesystem_proto_enumTypes = make([]protoimpl.EnumInfo, 2) +var file_filesystem_proto_msgTypes = make([]protoimpl.MessageInfo, 22) +var file_filesystem_proto_goTypes = []any{ + (FileType)(0), // 0: filesystem.FileType + (EventType)(0), // 1: filesystem.EventType + (*MoveRequest)(nil), // 2: filesystem.MoveRequest + (*MoveResponse)(nil), // 3: filesystem.MoveResponse + (*MakeDirRequest)(nil), // 4: filesystem.MakeDirRequest + (*MakeDirResponse)(nil), // 5: filesystem.MakeDirResponse + (*RemoveRequest)(nil), // 6: filesystem.RemoveRequest + (*RemoveResponse)(nil), // 7: filesystem.RemoveResponse + (*StatRequest)(nil), // 8: filesystem.StatRequest + (*StatResponse)(nil), // 9: filesystem.StatResponse + (*EntryInfo)(nil), // 10: filesystem.EntryInfo + (*ListDirRequest)(nil), // 11: filesystem.ListDirRequest + (*ListDirResponse)(nil), // 12: filesystem.ListDirResponse + (*WatchDirRequest)(nil), // 13: filesystem.WatchDirRequest + (*FilesystemEvent)(nil), // 14: filesystem.FilesystemEvent + (*WatchDirResponse)(nil), // 15: filesystem.WatchDirResponse + (*CreateWatcherRequest)(nil), // 16: filesystem.CreateWatcherRequest + (*CreateWatcherResponse)(nil), // 17: filesystem.CreateWatcherResponse + (*GetWatcherEventsRequest)(nil), // 18: filesystem.GetWatcherEventsRequest + (*GetWatcherEventsResponse)(nil), // 19: filesystem.GetWatcherEventsResponse + (*RemoveWatcherRequest)(nil), // 20: filesystem.RemoveWatcherRequest + (*RemoveWatcherResponse)(nil), // 21: filesystem.RemoveWatcherResponse + (*WatchDirResponse_StartEvent)(nil), // 22: filesystem.WatchDirResponse.StartEvent + (*WatchDirResponse_KeepAlive)(nil), // 23: filesystem.WatchDirResponse.KeepAlive + (*timestamppb.Timestamp)(nil), // 24: google.protobuf.Timestamp +} +var file_filesystem_proto_depIdxs = []int32{ + 10, // 0: filesystem.MoveResponse.entry:type_name -> filesystem.EntryInfo + 10, // 1: filesystem.MakeDirResponse.entry:type_name -> filesystem.EntryInfo + 10, // 2: filesystem.StatResponse.entry:type_name -> filesystem.EntryInfo + 0, // 3: filesystem.EntryInfo.type:type_name -> filesystem.FileType + 24, // 4: filesystem.EntryInfo.modified_time:type_name -> google.protobuf.Timestamp + 10, // 5: filesystem.ListDirResponse.entries:type_name -> filesystem.EntryInfo + 1, // 6: filesystem.FilesystemEvent.type:type_name -> filesystem.EventType + 22, // 7: filesystem.WatchDirResponse.start:type_name -> filesystem.WatchDirResponse.StartEvent + 14, // 8: filesystem.WatchDirResponse.filesystem:type_name -> filesystem.FilesystemEvent + 23, // 9: filesystem.WatchDirResponse.keepalive:type_name -> filesystem.WatchDirResponse.KeepAlive + 14, // 10: filesystem.GetWatcherEventsResponse.events:type_name -> filesystem.FilesystemEvent + 8, // 11: filesystem.Filesystem.Stat:input_type -> filesystem.StatRequest + 4, // 12: filesystem.Filesystem.MakeDir:input_type -> filesystem.MakeDirRequest + 2, // 13: filesystem.Filesystem.Move:input_type -> filesystem.MoveRequest + 11, // 14: filesystem.Filesystem.ListDir:input_type -> filesystem.ListDirRequest + 6, // 15: filesystem.Filesystem.Remove:input_type -> filesystem.RemoveRequest + 13, // 16: filesystem.Filesystem.WatchDir:input_type -> filesystem.WatchDirRequest + 16, // 17: filesystem.Filesystem.CreateWatcher:input_type -> filesystem.CreateWatcherRequest + 18, // 18: filesystem.Filesystem.GetWatcherEvents:input_type -> filesystem.GetWatcherEventsRequest + 20, // 19: filesystem.Filesystem.RemoveWatcher:input_type -> filesystem.RemoveWatcherRequest + 9, // 20: filesystem.Filesystem.Stat:output_type -> filesystem.StatResponse + 5, // 21: filesystem.Filesystem.MakeDir:output_type -> filesystem.MakeDirResponse + 3, // 22: filesystem.Filesystem.Move:output_type -> filesystem.MoveResponse + 12, // 23: filesystem.Filesystem.ListDir:output_type -> filesystem.ListDirResponse + 7, // 24: filesystem.Filesystem.Remove:output_type -> filesystem.RemoveResponse + 15, // 25: filesystem.Filesystem.WatchDir:output_type -> filesystem.WatchDirResponse + 17, // 26: filesystem.Filesystem.CreateWatcher:output_type -> filesystem.CreateWatcherResponse + 19, // 27: filesystem.Filesystem.GetWatcherEvents:output_type -> filesystem.GetWatcherEventsResponse + 21, // 28: filesystem.Filesystem.RemoveWatcher:output_type -> filesystem.RemoveWatcherResponse + 20, // [20:29] is the sub-list for method output_type + 11, // [11:20] is the sub-list for method input_type + 11, // [11:11] is the sub-list for extension type_name + 11, // [11:11] is the sub-list for extension extendee + 0, // [0:11] is the sub-list for field type_name +} + +func init() { file_filesystem_proto_init() } +func file_filesystem_proto_init() { + if File_filesystem_proto != nil { + return + } + file_filesystem_proto_msgTypes[8].OneofWrappers = []any{} + file_filesystem_proto_msgTypes[13].OneofWrappers = []any{ + (*WatchDirResponse_Start)(nil), + (*WatchDirResponse_Filesystem)(nil), + (*WatchDirResponse_Keepalive)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_filesystem_proto_rawDesc), len(file_filesystem_proto_rawDesc)), + NumEnums: 2, + NumMessages: 22, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_filesystem_proto_goTypes, + DependencyIndexes: file_filesystem_proto_depIdxs, + EnumInfos: file_filesystem_proto_enumTypes, + MessageInfos: file_filesystem_proto_msgTypes, + }.Build() + File_filesystem_proto = out.File + file_filesystem_proto_goTypes = nil + file_filesystem_proto_depIdxs = nil +} diff --git a/envd/internal/services/spec/process.pb.go b/envd/internal/services/spec/process.pb.go new file mode 100644 index 0000000..711d34f --- /dev/null +++ b/envd/internal/services/spec/process.pb.go @@ -0,0 +1,1970 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: process.proto + +package spec + +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 Signal int32 + +const ( + Signal_SIGNAL_UNSPECIFIED Signal = 0 + Signal_SIGNAL_SIGTERM Signal = 15 + Signal_SIGNAL_SIGKILL Signal = 9 +) + +// Enum value maps for Signal. +var ( + Signal_name = map[int32]string{ + 0: "SIGNAL_UNSPECIFIED", + 15: "SIGNAL_SIGTERM", + 9: "SIGNAL_SIGKILL", + } + Signal_value = map[string]int32{ + "SIGNAL_UNSPECIFIED": 0, + "SIGNAL_SIGTERM": 15, + "SIGNAL_SIGKILL": 9, + } +) + +func (x Signal) Enum() *Signal { + p := new(Signal) + *p = x + return p +} + +func (x Signal) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Signal) Descriptor() protoreflect.EnumDescriptor { + return file_process_proto_enumTypes[0].Descriptor() +} + +func (Signal) Type() protoreflect.EnumType { + return &file_process_proto_enumTypes[0] +} + +func (x Signal) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Signal.Descriptor instead. +func (Signal) EnumDescriptor() ([]byte, []int) { + return file_process_proto_rawDescGZIP(), []int{0} +} + +type PTY struct { + state protoimpl.MessageState `protogen:"open.v1"` + Size *PTY_Size `protobuf:"bytes,1,opt,name=size,proto3" json:"size,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PTY) Reset() { + *x = PTY{} + mi := &file_process_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PTY) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PTY) ProtoMessage() {} + +func (x *PTY) ProtoReflect() protoreflect.Message { + mi := &file_process_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 PTY.ProtoReflect.Descriptor instead. +func (*PTY) Descriptor() ([]byte, []int) { + return file_process_proto_rawDescGZIP(), []int{0} +} + +func (x *PTY) GetSize() *PTY_Size { + if x != nil { + return x.Size + } + return nil +} + +type ProcessConfig struct { + state protoimpl.MessageState `protogen:"open.v1"` + Cmd string `protobuf:"bytes,1,opt,name=cmd,proto3" json:"cmd,omitempty"` + Args []string `protobuf:"bytes,2,rep,name=args,proto3" json:"args,omitempty"` + Envs map[string]string `protobuf:"bytes,3,rep,name=envs,proto3" json:"envs,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Cwd *string `protobuf:"bytes,4,opt,name=cwd,proto3,oneof" json:"cwd,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ProcessConfig) Reset() { + *x = ProcessConfig{} + mi := &file_process_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ProcessConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ProcessConfig) ProtoMessage() {} + +func (x *ProcessConfig) ProtoReflect() protoreflect.Message { + mi := &file_process_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 ProcessConfig.ProtoReflect.Descriptor instead. +func (*ProcessConfig) Descriptor() ([]byte, []int) { + return file_process_proto_rawDescGZIP(), []int{1} +} + +func (x *ProcessConfig) GetCmd() string { + if x != nil { + return x.Cmd + } + return "" +} + +func (x *ProcessConfig) GetArgs() []string { + if x != nil { + return x.Args + } + return nil +} + +func (x *ProcessConfig) GetEnvs() map[string]string { + if x != nil { + return x.Envs + } + return nil +} + +func (x *ProcessConfig) GetCwd() string { + if x != nil && x.Cwd != nil { + return *x.Cwd + } + return "" +} + +type ListRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListRequest) Reset() { + *x = ListRequest{} + mi := &file_process_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListRequest) ProtoMessage() {} + +func (x *ListRequest) ProtoReflect() protoreflect.Message { + mi := &file_process_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 ListRequest.ProtoReflect.Descriptor instead. +func (*ListRequest) Descriptor() ([]byte, []int) { + return file_process_proto_rawDescGZIP(), []int{2} +} + +type ProcessInfo struct { + state protoimpl.MessageState `protogen:"open.v1"` + Config *ProcessConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + Pid uint32 `protobuf:"varint,2,opt,name=pid,proto3" json:"pid,omitempty"` + Tag *string `protobuf:"bytes,3,opt,name=tag,proto3,oneof" json:"tag,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ProcessInfo) Reset() { + *x = ProcessInfo{} + mi := &file_process_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ProcessInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ProcessInfo) ProtoMessage() {} + +func (x *ProcessInfo) ProtoReflect() protoreflect.Message { + mi := &file_process_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 ProcessInfo.ProtoReflect.Descriptor instead. +func (*ProcessInfo) Descriptor() ([]byte, []int) { + return file_process_proto_rawDescGZIP(), []int{3} +} + +func (x *ProcessInfo) GetConfig() *ProcessConfig { + if x != nil { + return x.Config + } + return nil +} + +func (x *ProcessInfo) GetPid() uint32 { + if x != nil { + return x.Pid + } + return 0 +} + +func (x *ProcessInfo) GetTag() string { + if x != nil && x.Tag != nil { + return *x.Tag + } + return "" +} + +type ListResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Processes []*ProcessInfo `protobuf:"bytes,1,rep,name=processes,proto3" json:"processes,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListResponse) Reset() { + *x = ListResponse{} + mi := &file_process_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListResponse) ProtoMessage() {} + +func (x *ListResponse) ProtoReflect() protoreflect.Message { + mi := &file_process_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 ListResponse.ProtoReflect.Descriptor instead. +func (*ListResponse) Descriptor() ([]byte, []int) { + return file_process_proto_rawDescGZIP(), []int{4} +} + +func (x *ListResponse) GetProcesses() []*ProcessInfo { + if x != nil { + return x.Processes + } + return nil +} + +type StartRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Process *ProcessConfig `protobuf:"bytes,1,opt,name=process,proto3" json:"process,omitempty"` + Pty *PTY `protobuf:"bytes,2,opt,name=pty,proto3,oneof" json:"pty,omitempty"` + Tag *string `protobuf:"bytes,3,opt,name=tag,proto3,oneof" json:"tag,omitempty"` + // This is optional for backwards compatibility. + // We default to true. New SDK versions will set this to false by default. + Stdin *bool `protobuf:"varint,4,opt,name=stdin,proto3,oneof" json:"stdin,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *StartRequest) Reset() { + *x = StartRequest{} + mi := &file_process_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StartRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StartRequest) ProtoMessage() {} + +func (x *StartRequest) ProtoReflect() protoreflect.Message { + mi := &file_process_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 StartRequest.ProtoReflect.Descriptor instead. +func (*StartRequest) Descriptor() ([]byte, []int) { + return file_process_proto_rawDescGZIP(), []int{5} +} + +func (x *StartRequest) GetProcess() *ProcessConfig { + if x != nil { + return x.Process + } + return nil +} + +func (x *StartRequest) GetPty() *PTY { + if x != nil { + return x.Pty + } + return nil +} + +func (x *StartRequest) GetTag() string { + if x != nil && x.Tag != nil { + return *x.Tag + } + return "" +} + +func (x *StartRequest) GetStdin() bool { + if x != nil && x.Stdin != nil { + return *x.Stdin + } + return false +} + +type UpdateRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Process *ProcessSelector `protobuf:"bytes,1,opt,name=process,proto3" json:"process,omitempty"` + Pty *PTY `protobuf:"bytes,2,opt,name=pty,proto3,oneof" json:"pty,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpdateRequest) Reset() { + *x = UpdateRequest{} + mi := &file_process_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateRequest) ProtoMessage() {} + +func (x *UpdateRequest) ProtoReflect() protoreflect.Message { + mi := &file_process_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 UpdateRequest.ProtoReflect.Descriptor instead. +func (*UpdateRequest) Descriptor() ([]byte, []int) { + return file_process_proto_rawDescGZIP(), []int{6} +} + +func (x *UpdateRequest) GetProcess() *ProcessSelector { + if x != nil { + return x.Process + } + return nil +} + +func (x *UpdateRequest) GetPty() *PTY { + if x != nil { + return x.Pty + } + return nil +} + +type UpdateResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpdateResponse) Reset() { + *x = UpdateResponse{} + mi := &file_process_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateResponse) ProtoMessage() {} + +func (x *UpdateResponse) ProtoReflect() protoreflect.Message { + mi := &file_process_proto_msgTypes[7] + 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 UpdateResponse.ProtoReflect.Descriptor instead. +func (*UpdateResponse) Descriptor() ([]byte, []int) { + return file_process_proto_rawDescGZIP(), []int{7} +} + +type ProcessEvent struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Types that are valid to be assigned to Event: + // + // *ProcessEvent_Start + // *ProcessEvent_Data + // *ProcessEvent_End + // *ProcessEvent_Keepalive + Event isProcessEvent_Event `protobuf_oneof:"event"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ProcessEvent) Reset() { + *x = ProcessEvent{} + mi := &file_process_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ProcessEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ProcessEvent) ProtoMessage() {} + +func (x *ProcessEvent) ProtoReflect() protoreflect.Message { + mi := &file_process_proto_msgTypes[8] + 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 ProcessEvent.ProtoReflect.Descriptor instead. +func (*ProcessEvent) Descriptor() ([]byte, []int) { + return file_process_proto_rawDescGZIP(), []int{8} +} + +func (x *ProcessEvent) GetEvent() isProcessEvent_Event { + if x != nil { + return x.Event + } + return nil +} + +func (x *ProcessEvent) GetStart() *ProcessEvent_StartEvent { + if x != nil { + if x, ok := x.Event.(*ProcessEvent_Start); ok { + return x.Start + } + } + return nil +} + +func (x *ProcessEvent) GetData() *ProcessEvent_DataEvent { + if x != nil { + if x, ok := x.Event.(*ProcessEvent_Data); ok { + return x.Data + } + } + return nil +} + +func (x *ProcessEvent) GetEnd() *ProcessEvent_EndEvent { + if x != nil { + if x, ok := x.Event.(*ProcessEvent_End); ok { + return x.End + } + } + return nil +} + +func (x *ProcessEvent) GetKeepalive() *ProcessEvent_KeepAlive { + if x != nil { + if x, ok := x.Event.(*ProcessEvent_Keepalive); ok { + return x.Keepalive + } + } + return nil +} + +type isProcessEvent_Event interface { + isProcessEvent_Event() +} + +type ProcessEvent_Start struct { + Start *ProcessEvent_StartEvent `protobuf:"bytes,1,opt,name=start,proto3,oneof"` +} + +type ProcessEvent_Data struct { + Data *ProcessEvent_DataEvent `protobuf:"bytes,2,opt,name=data,proto3,oneof"` +} + +type ProcessEvent_End struct { + End *ProcessEvent_EndEvent `protobuf:"bytes,3,opt,name=end,proto3,oneof"` +} + +type ProcessEvent_Keepalive struct { + Keepalive *ProcessEvent_KeepAlive `protobuf:"bytes,4,opt,name=keepalive,proto3,oneof"` +} + +func (*ProcessEvent_Start) isProcessEvent_Event() {} + +func (*ProcessEvent_Data) isProcessEvent_Event() {} + +func (*ProcessEvent_End) isProcessEvent_Event() {} + +func (*ProcessEvent_Keepalive) isProcessEvent_Event() {} + +type StartResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Event *ProcessEvent `protobuf:"bytes,1,opt,name=event,proto3" json:"event,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *StartResponse) Reset() { + *x = StartResponse{} + mi := &file_process_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StartResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StartResponse) ProtoMessage() {} + +func (x *StartResponse) ProtoReflect() protoreflect.Message { + mi := &file_process_proto_msgTypes[9] + 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 StartResponse.ProtoReflect.Descriptor instead. +func (*StartResponse) Descriptor() ([]byte, []int) { + return file_process_proto_rawDescGZIP(), []int{9} +} + +func (x *StartResponse) GetEvent() *ProcessEvent { + if x != nil { + return x.Event + } + return nil +} + +type ConnectResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Event *ProcessEvent `protobuf:"bytes,1,opt,name=event,proto3" json:"event,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ConnectResponse) Reset() { + *x = ConnectResponse{} + mi := &file_process_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ConnectResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ConnectResponse) ProtoMessage() {} + +func (x *ConnectResponse) ProtoReflect() protoreflect.Message { + mi := &file_process_proto_msgTypes[10] + 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 ConnectResponse.ProtoReflect.Descriptor instead. +func (*ConnectResponse) Descriptor() ([]byte, []int) { + return file_process_proto_rawDescGZIP(), []int{10} +} + +func (x *ConnectResponse) GetEvent() *ProcessEvent { + if x != nil { + return x.Event + } + return nil +} + +type SendInputRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Process *ProcessSelector `protobuf:"bytes,1,opt,name=process,proto3" json:"process,omitempty"` + Input *ProcessInput `protobuf:"bytes,2,opt,name=input,proto3" json:"input,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SendInputRequest) Reset() { + *x = SendInputRequest{} + mi := &file_process_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SendInputRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SendInputRequest) ProtoMessage() {} + +func (x *SendInputRequest) ProtoReflect() protoreflect.Message { + mi := &file_process_proto_msgTypes[11] + 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 SendInputRequest.ProtoReflect.Descriptor instead. +func (*SendInputRequest) Descriptor() ([]byte, []int) { + return file_process_proto_rawDescGZIP(), []int{11} +} + +func (x *SendInputRequest) GetProcess() *ProcessSelector { + if x != nil { + return x.Process + } + return nil +} + +func (x *SendInputRequest) GetInput() *ProcessInput { + if x != nil { + return x.Input + } + return nil +} + +type SendInputResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SendInputResponse) Reset() { + *x = SendInputResponse{} + mi := &file_process_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SendInputResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SendInputResponse) ProtoMessage() {} + +func (x *SendInputResponse) ProtoReflect() protoreflect.Message { + mi := &file_process_proto_msgTypes[12] + 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 SendInputResponse.ProtoReflect.Descriptor instead. +func (*SendInputResponse) Descriptor() ([]byte, []int) { + return file_process_proto_rawDescGZIP(), []int{12} +} + +type ProcessInput struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Types that are valid to be assigned to Input: + // + // *ProcessInput_Stdin + // *ProcessInput_Pty + Input isProcessInput_Input `protobuf_oneof:"input"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ProcessInput) Reset() { + *x = ProcessInput{} + mi := &file_process_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ProcessInput) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ProcessInput) ProtoMessage() {} + +func (x *ProcessInput) ProtoReflect() protoreflect.Message { + mi := &file_process_proto_msgTypes[13] + 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 ProcessInput.ProtoReflect.Descriptor instead. +func (*ProcessInput) Descriptor() ([]byte, []int) { + return file_process_proto_rawDescGZIP(), []int{13} +} + +func (x *ProcessInput) GetInput() isProcessInput_Input { + if x != nil { + return x.Input + } + return nil +} + +func (x *ProcessInput) GetStdin() []byte { + if x != nil { + if x, ok := x.Input.(*ProcessInput_Stdin); ok { + return x.Stdin + } + } + return nil +} + +func (x *ProcessInput) GetPty() []byte { + if x != nil { + if x, ok := x.Input.(*ProcessInput_Pty); ok { + return x.Pty + } + } + return nil +} + +type isProcessInput_Input interface { + isProcessInput_Input() +} + +type ProcessInput_Stdin struct { + Stdin []byte `protobuf:"bytes,1,opt,name=stdin,proto3,oneof"` +} + +type ProcessInput_Pty struct { + Pty []byte `protobuf:"bytes,2,opt,name=pty,proto3,oneof"` +} + +func (*ProcessInput_Stdin) isProcessInput_Input() {} + +func (*ProcessInput_Pty) isProcessInput_Input() {} + +type StreamInputRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Types that are valid to be assigned to Event: + // + // *StreamInputRequest_Start + // *StreamInputRequest_Data + // *StreamInputRequest_Keepalive + Event isStreamInputRequest_Event `protobuf_oneof:"event"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *StreamInputRequest) Reset() { + *x = StreamInputRequest{} + mi := &file_process_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StreamInputRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StreamInputRequest) ProtoMessage() {} + +func (x *StreamInputRequest) ProtoReflect() protoreflect.Message { + mi := &file_process_proto_msgTypes[14] + 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 StreamInputRequest.ProtoReflect.Descriptor instead. +func (*StreamInputRequest) Descriptor() ([]byte, []int) { + return file_process_proto_rawDescGZIP(), []int{14} +} + +func (x *StreamInputRequest) GetEvent() isStreamInputRequest_Event { + if x != nil { + return x.Event + } + return nil +} + +func (x *StreamInputRequest) GetStart() *StreamInputRequest_StartEvent { + if x != nil { + if x, ok := x.Event.(*StreamInputRequest_Start); ok { + return x.Start + } + } + return nil +} + +func (x *StreamInputRequest) GetData() *StreamInputRequest_DataEvent { + if x != nil { + if x, ok := x.Event.(*StreamInputRequest_Data); ok { + return x.Data + } + } + return nil +} + +func (x *StreamInputRequest) GetKeepalive() *StreamInputRequest_KeepAlive { + if x != nil { + if x, ok := x.Event.(*StreamInputRequest_Keepalive); ok { + return x.Keepalive + } + } + return nil +} + +type isStreamInputRequest_Event interface { + isStreamInputRequest_Event() +} + +type StreamInputRequest_Start struct { + Start *StreamInputRequest_StartEvent `protobuf:"bytes,1,opt,name=start,proto3,oneof"` +} + +type StreamInputRequest_Data struct { + Data *StreamInputRequest_DataEvent `protobuf:"bytes,2,opt,name=data,proto3,oneof"` +} + +type StreamInputRequest_Keepalive struct { + Keepalive *StreamInputRequest_KeepAlive `protobuf:"bytes,3,opt,name=keepalive,proto3,oneof"` +} + +func (*StreamInputRequest_Start) isStreamInputRequest_Event() {} + +func (*StreamInputRequest_Data) isStreamInputRequest_Event() {} + +func (*StreamInputRequest_Keepalive) isStreamInputRequest_Event() {} + +type StreamInputResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *StreamInputResponse) Reset() { + *x = StreamInputResponse{} + mi := &file_process_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StreamInputResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StreamInputResponse) ProtoMessage() {} + +func (x *StreamInputResponse) ProtoReflect() protoreflect.Message { + mi := &file_process_proto_msgTypes[15] + 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 StreamInputResponse.ProtoReflect.Descriptor instead. +func (*StreamInputResponse) Descriptor() ([]byte, []int) { + return file_process_proto_rawDescGZIP(), []int{15} +} + +type SendSignalRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Process *ProcessSelector `protobuf:"bytes,1,opt,name=process,proto3" json:"process,omitempty"` + Signal Signal `protobuf:"varint,2,opt,name=signal,proto3,enum=process.Signal" json:"signal,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SendSignalRequest) Reset() { + *x = SendSignalRequest{} + mi := &file_process_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SendSignalRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SendSignalRequest) ProtoMessage() {} + +func (x *SendSignalRequest) ProtoReflect() protoreflect.Message { + mi := &file_process_proto_msgTypes[16] + 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 SendSignalRequest.ProtoReflect.Descriptor instead. +func (*SendSignalRequest) Descriptor() ([]byte, []int) { + return file_process_proto_rawDescGZIP(), []int{16} +} + +func (x *SendSignalRequest) GetProcess() *ProcessSelector { + if x != nil { + return x.Process + } + return nil +} + +func (x *SendSignalRequest) GetSignal() Signal { + if x != nil { + return x.Signal + } + return Signal_SIGNAL_UNSPECIFIED +} + +type SendSignalResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SendSignalResponse) Reset() { + *x = SendSignalResponse{} + mi := &file_process_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SendSignalResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SendSignalResponse) ProtoMessage() {} + +func (x *SendSignalResponse) ProtoReflect() protoreflect.Message { + mi := &file_process_proto_msgTypes[17] + 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 SendSignalResponse.ProtoReflect.Descriptor instead. +func (*SendSignalResponse) Descriptor() ([]byte, []int) { + return file_process_proto_rawDescGZIP(), []int{17} +} + +type CloseStdinRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Process *ProcessSelector `protobuf:"bytes,1,opt,name=process,proto3" json:"process,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CloseStdinRequest) Reset() { + *x = CloseStdinRequest{} + mi := &file_process_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CloseStdinRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CloseStdinRequest) ProtoMessage() {} + +func (x *CloseStdinRequest) ProtoReflect() protoreflect.Message { + mi := &file_process_proto_msgTypes[18] + 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 CloseStdinRequest.ProtoReflect.Descriptor instead. +func (*CloseStdinRequest) Descriptor() ([]byte, []int) { + return file_process_proto_rawDescGZIP(), []int{18} +} + +func (x *CloseStdinRequest) GetProcess() *ProcessSelector { + if x != nil { + return x.Process + } + return nil +} + +type CloseStdinResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CloseStdinResponse) Reset() { + *x = CloseStdinResponse{} + mi := &file_process_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CloseStdinResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CloseStdinResponse) ProtoMessage() {} + +func (x *CloseStdinResponse) ProtoReflect() protoreflect.Message { + mi := &file_process_proto_msgTypes[19] + 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 CloseStdinResponse.ProtoReflect.Descriptor instead. +func (*CloseStdinResponse) Descriptor() ([]byte, []int) { + return file_process_proto_rawDescGZIP(), []int{19} +} + +type ConnectRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Process *ProcessSelector `protobuf:"bytes,1,opt,name=process,proto3" json:"process,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ConnectRequest) Reset() { + *x = ConnectRequest{} + mi := &file_process_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ConnectRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ConnectRequest) ProtoMessage() {} + +func (x *ConnectRequest) ProtoReflect() protoreflect.Message { + mi := &file_process_proto_msgTypes[20] + 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 ConnectRequest.ProtoReflect.Descriptor instead. +func (*ConnectRequest) Descriptor() ([]byte, []int) { + return file_process_proto_rawDescGZIP(), []int{20} +} + +func (x *ConnectRequest) GetProcess() *ProcessSelector { + if x != nil { + return x.Process + } + return nil +} + +type ProcessSelector struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Types that are valid to be assigned to Selector: + // + // *ProcessSelector_Pid + // *ProcessSelector_Tag + Selector isProcessSelector_Selector `protobuf_oneof:"selector"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ProcessSelector) Reset() { + *x = ProcessSelector{} + mi := &file_process_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ProcessSelector) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ProcessSelector) ProtoMessage() {} + +func (x *ProcessSelector) ProtoReflect() protoreflect.Message { + mi := &file_process_proto_msgTypes[21] + 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 ProcessSelector.ProtoReflect.Descriptor instead. +func (*ProcessSelector) Descriptor() ([]byte, []int) { + return file_process_proto_rawDescGZIP(), []int{21} +} + +func (x *ProcessSelector) GetSelector() isProcessSelector_Selector { + if x != nil { + return x.Selector + } + return nil +} + +func (x *ProcessSelector) GetPid() uint32 { + if x != nil { + if x, ok := x.Selector.(*ProcessSelector_Pid); ok { + return x.Pid + } + } + return 0 +} + +func (x *ProcessSelector) GetTag() string { + if x != nil { + if x, ok := x.Selector.(*ProcessSelector_Tag); ok { + return x.Tag + } + } + return "" +} + +type isProcessSelector_Selector interface { + isProcessSelector_Selector() +} + +type ProcessSelector_Pid struct { + Pid uint32 `protobuf:"varint,1,opt,name=pid,proto3,oneof"` +} + +type ProcessSelector_Tag struct { + Tag string `protobuf:"bytes,2,opt,name=tag,proto3,oneof"` +} + +func (*ProcessSelector_Pid) isProcessSelector_Selector() {} + +func (*ProcessSelector_Tag) isProcessSelector_Selector() {} + +type PTY_Size struct { + state protoimpl.MessageState `protogen:"open.v1"` + Cols uint32 `protobuf:"varint,1,opt,name=cols,proto3" json:"cols,omitempty"` + Rows uint32 `protobuf:"varint,2,opt,name=rows,proto3" json:"rows,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PTY_Size) Reset() { + *x = PTY_Size{} + mi := &file_process_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PTY_Size) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PTY_Size) ProtoMessage() {} + +func (x *PTY_Size) ProtoReflect() protoreflect.Message { + mi := &file_process_proto_msgTypes[22] + 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 PTY_Size.ProtoReflect.Descriptor instead. +func (*PTY_Size) Descriptor() ([]byte, []int) { + return file_process_proto_rawDescGZIP(), []int{0, 0} +} + +func (x *PTY_Size) GetCols() uint32 { + if x != nil { + return x.Cols + } + return 0 +} + +func (x *PTY_Size) GetRows() uint32 { + if x != nil { + return x.Rows + } + return 0 +} + +type ProcessEvent_StartEvent struct { + state protoimpl.MessageState `protogen:"open.v1"` + Pid uint32 `protobuf:"varint,1,opt,name=pid,proto3" json:"pid,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ProcessEvent_StartEvent) Reset() { + *x = ProcessEvent_StartEvent{} + mi := &file_process_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ProcessEvent_StartEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ProcessEvent_StartEvent) ProtoMessage() {} + +func (x *ProcessEvent_StartEvent) ProtoReflect() protoreflect.Message { + mi := &file_process_proto_msgTypes[24] + 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 ProcessEvent_StartEvent.ProtoReflect.Descriptor instead. +func (*ProcessEvent_StartEvent) Descriptor() ([]byte, []int) { + return file_process_proto_rawDescGZIP(), []int{8, 0} +} + +func (x *ProcessEvent_StartEvent) GetPid() uint32 { + if x != nil { + return x.Pid + } + return 0 +} + +type ProcessEvent_DataEvent struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Types that are valid to be assigned to Output: + // + // *ProcessEvent_DataEvent_Stdout + // *ProcessEvent_DataEvent_Stderr + // *ProcessEvent_DataEvent_Pty + Output isProcessEvent_DataEvent_Output `protobuf_oneof:"output"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ProcessEvent_DataEvent) Reset() { + *x = ProcessEvent_DataEvent{} + mi := &file_process_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ProcessEvent_DataEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ProcessEvent_DataEvent) ProtoMessage() {} + +func (x *ProcessEvent_DataEvent) ProtoReflect() protoreflect.Message { + mi := &file_process_proto_msgTypes[25] + 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 ProcessEvent_DataEvent.ProtoReflect.Descriptor instead. +func (*ProcessEvent_DataEvent) Descriptor() ([]byte, []int) { + return file_process_proto_rawDescGZIP(), []int{8, 1} +} + +func (x *ProcessEvent_DataEvent) GetOutput() isProcessEvent_DataEvent_Output { + if x != nil { + return x.Output + } + return nil +} + +func (x *ProcessEvent_DataEvent) GetStdout() []byte { + if x != nil { + if x, ok := x.Output.(*ProcessEvent_DataEvent_Stdout); ok { + return x.Stdout + } + } + return nil +} + +func (x *ProcessEvent_DataEvent) GetStderr() []byte { + if x != nil { + if x, ok := x.Output.(*ProcessEvent_DataEvent_Stderr); ok { + return x.Stderr + } + } + return nil +} + +func (x *ProcessEvent_DataEvent) GetPty() []byte { + if x != nil { + if x, ok := x.Output.(*ProcessEvent_DataEvent_Pty); ok { + return x.Pty + } + } + return nil +} + +type isProcessEvent_DataEvent_Output interface { + isProcessEvent_DataEvent_Output() +} + +type ProcessEvent_DataEvent_Stdout struct { + Stdout []byte `protobuf:"bytes,1,opt,name=stdout,proto3,oneof"` +} + +type ProcessEvent_DataEvent_Stderr struct { + Stderr []byte `protobuf:"bytes,2,opt,name=stderr,proto3,oneof"` +} + +type ProcessEvent_DataEvent_Pty struct { + Pty []byte `protobuf:"bytes,3,opt,name=pty,proto3,oneof"` +} + +func (*ProcessEvent_DataEvent_Stdout) isProcessEvent_DataEvent_Output() {} + +func (*ProcessEvent_DataEvent_Stderr) isProcessEvent_DataEvent_Output() {} + +func (*ProcessEvent_DataEvent_Pty) isProcessEvent_DataEvent_Output() {} + +type ProcessEvent_EndEvent struct { + state protoimpl.MessageState `protogen:"open.v1"` + ExitCode int32 `protobuf:"zigzag32,1,opt,name=exit_code,json=exitCode,proto3" json:"exit_code,omitempty"` + Exited bool `protobuf:"varint,2,opt,name=exited,proto3" json:"exited,omitempty"` + Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` + Error *string `protobuf:"bytes,4,opt,name=error,proto3,oneof" json:"error,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ProcessEvent_EndEvent) Reset() { + *x = ProcessEvent_EndEvent{} + mi := &file_process_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ProcessEvent_EndEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ProcessEvent_EndEvent) ProtoMessage() {} + +func (x *ProcessEvent_EndEvent) ProtoReflect() protoreflect.Message { + mi := &file_process_proto_msgTypes[26] + 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 ProcessEvent_EndEvent.ProtoReflect.Descriptor instead. +func (*ProcessEvent_EndEvent) Descriptor() ([]byte, []int) { + return file_process_proto_rawDescGZIP(), []int{8, 2} +} + +func (x *ProcessEvent_EndEvent) GetExitCode() int32 { + if x != nil { + return x.ExitCode + } + return 0 +} + +func (x *ProcessEvent_EndEvent) GetExited() bool { + if x != nil { + return x.Exited + } + return false +} + +func (x *ProcessEvent_EndEvent) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *ProcessEvent_EndEvent) GetError() string { + if x != nil && x.Error != nil { + return *x.Error + } + return "" +} + +type ProcessEvent_KeepAlive struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ProcessEvent_KeepAlive) Reset() { + *x = ProcessEvent_KeepAlive{} + mi := &file_process_proto_msgTypes[27] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ProcessEvent_KeepAlive) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ProcessEvent_KeepAlive) ProtoMessage() {} + +func (x *ProcessEvent_KeepAlive) ProtoReflect() protoreflect.Message { + mi := &file_process_proto_msgTypes[27] + 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 ProcessEvent_KeepAlive.ProtoReflect.Descriptor instead. +func (*ProcessEvent_KeepAlive) Descriptor() ([]byte, []int) { + return file_process_proto_rawDescGZIP(), []int{8, 3} +} + +type StreamInputRequest_StartEvent struct { + state protoimpl.MessageState `protogen:"open.v1"` + Process *ProcessSelector `protobuf:"bytes,1,opt,name=process,proto3" json:"process,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *StreamInputRequest_StartEvent) Reset() { + *x = StreamInputRequest_StartEvent{} + mi := &file_process_proto_msgTypes[28] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StreamInputRequest_StartEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StreamInputRequest_StartEvent) ProtoMessage() {} + +func (x *StreamInputRequest_StartEvent) ProtoReflect() protoreflect.Message { + mi := &file_process_proto_msgTypes[28] + 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 StreamInputRequest_StartEvent.ProtoReflect.Descriptor instead. +func (*StreamInputRequest_StartEvent) Descriptor() ([]byte, []int) { + return file_process_proto_rawDescGZIP(), []int{14, 0} +} + +func (x *StreamInputRequest_StartEvent) GetProcess() *ProcessSelector { + if x != nil { + return x.Process + } + return nil +} + +type StreamInputRequest_DataEvent struct { + state protoimpl.MessageState `protogen:"open.v1"` + Input *ProcessInput `protobuf:"bytes,2,opt,name=input,proto3" json:"input,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *StreamInputRequest_DataEvent) Reset() { + *x = StreamInputRequest_DataEvent{} + mi := &file_process_proto_msgTypes[29] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StreamInputRequest_DataEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StreamInputRequest_DataEvent) ProtoMessage() {} + +func (x *StreamInputRequest_DataEvent) ProtoReflect() protoreflect.Message { + mi := &file_process_proto_msgTypes[29] + 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 StreamInputRequest_DataEvent.ProtoReflect.Descriptor instead. +func (*StreamInputRequest_DataEvent) Descriptor() ([]byte, []int) { + return file_process_proto_rawDescGZIP(), []int{14, 1} +} + +func (x *StreamInputRequest_DataEvent) GetInput() *ProcessInput { + if x != nil { + return x.Input + } + return nil +} + +type StreamInputRequest_KeepAlive struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *StreamInputRequest_KeepAlive) Reset() { + *x = StreamInputRequest_KeepAlive{} + mi := &file_process_proto_msgTypes[30] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StreamInputRequest_KeepAlive) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StreamInputRequest_KeepAlive) ProtoMessage() {} + +func (x *StreamInputRequest_KeepAlive) ProtoReflect() protoreflect.Message { + mi := &file_process_proto_msgTypes[30] + 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 StreamInputRequest_KeepAlive.ProtoReflect.Descriptor instead. +func (*StreamInputRequest_KeepAlive) Descriptor() ([]byte, []int) { + return file_process_proto_rawDescGZIP(), []int{14, 2} +} + +var File_process_proto protoreflect.FileDescriptor + +const file_process_proto_rawDesc = "" + + "\n" + + "\rprocess.proto\x12\aprocess\"\\\n" + + "\x03PTY\x12%\n" + + "\x04size\x18\x01 \x01(\v2\x11.process.PTY.SizeR\x04size\x1a.\n" + + "\x04Size\x12\x12\n" + + "\x04cols\x18\x01 \x01(\rR\x04cols\x12\x12\n" + + "\x04rows\x18\x02 \x01(\rR\x04rows\"\xc3\x01\n" + + "\rProcessConfig\x12\x10\n" + + "\x03cmd\x18\x01 \x01(\tR\x03cmd\x12\x12\n" + + "\x04args\x18\x02 \x03(\tR\x04args\x124\n" + + "\x04envs\x18\x03 \x03(\v2 .process.ProcessConfig.EnvsEntryR\x04envs\x12\x15\n" + + "\x03cwd\x18\x04 \x01(\tH\x00R\x03cwd\x88\x01\x01\x1a7\n" + + "\tEnvsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01B\x06\n" + + "\x04_cwd\"\r\n" + + "\vListRequest\"n\n" + + "\vProcessInfo\x12.\n" + + "\x06config\x18\x01 \x01(\v2\x16.process.ProcessConfigR\x06config\x12\x10\n" + + "\x03pid\x18\x02 \x01(\rR\x03pid\x12\x15\n" + + "\x03tag\x18\x03 \x01(\tH\x00R\x03tag\x88\x01\x01B\x06\n" + + "\x04_tag\"B\n" + + "\fListResponse\x122\n" + + "\tprocesses\x18\x01 \x03(\v2\x14.process.ProcessInfoR\tprocesses\"\xb1\x01\n" + + "\fStartRequest\x120\n" + + "\aprocess\x18\x01 \x01(\v2\x16.process.ProcessConfigR\aprocess\x12#\n" + + "\x03pty\x18\x02 \x01(\v2\f.process.PTYH\x00R\x03pty\x88\x01\x01\x12\x15\n" + + "\x03tag\x18\x03 \x01(\tH\x01R\x03tag\x88\x01\x01\x12\x19\n" + + "\x05stdin\x18\x04 \x01(\bH\x02R\x05stdin\x88\x01\x01B\x06\n" + + "\x04_ptyB\x06\n" + + "\x04_tagB\b\n" + + "\x06_stdin\"p\n" + + "\rUpdateRequest\x122\n" + + "\aprocess\x18\x01 \x01(\v2\x18.process.ProcessSelectorR\aprocess\x12#\n" + + "\x03pty\x18\x02 \x01(\v2\f.process.PTYH\x00R\x03pty\x88\x01\x01B\x06\n" + + "\x04_pty\"\x10\n" + + "\x0eUpdateResponse\"\x87\x04\n" + + "\fProcessEvent\x128\n" + + "\x05start\x18\x01 \x01(\v2 .process.ProcessEvent.StartEventH\x00R\x05start\x125\n" + + "\x04data\x18\x02 \x01(\v2\x1f.process.ProcessEvent.DataEventH\x00R\x04data\x122\n" + + "\x03end\x18\x03 \x01(\v2\x1e.process.ProcessEvent.EndEventH\x00R\x03end\x12?\n" + + "\tkeepalive\x18\x04 \x01(\v2\x1f.process.ProcessEvent.KeepAliveH\x00R\tkeepalive\x1a\x1e\n" + + "\n" + + "StartEvent\x12\x10\n" + + "\x03pid\x18\x01 \x01(\rR\x03pid\x1a]\n" + + "\tDataEvent\x12\x18\n" + + "\x06stdout\x18\x01 \x01(\fH\x00R\x06stdout\x12\x18\n" + + "\x06stderr\x18\x02 \x01(\fH\x00R\x06stderr\x12\x12\n" + + "\x03pty\x18\x03 \x01(\fH\x00R\x03ptyB\b\n" + + "\x06output\x1a|\n" + + "\bEndEvent\x12\x1b\n" + + "\texit_code\x18\x01 \x01(\x11R\bexitCode\x12\x16\n" + + "\x06exited\x18\x02 \x01(\bR\x06exited\x12\x16\n" + + "\x06status\x18\x03 \x01(\tR\x06status\x12\x19\n" + + "\x05error\x18\x04 \x01(\tH\x00R\x05error\x88\x01\x01B\b\n" + + "\x06_error\x1a\v\n" + + "\tKeepAliveB\a\n" + + "\x05event\"<\n" + + "\rStartResponse\x12+\n" + + "\x05event\x18\x01 \x01(\v2\x15.process.ProcessEventR\x05event\">\n" + + "\x0fConnectResponse\x12+\n" + + "\x05event\x18\x01 \x01(\v2\x15.process.ProcessEventR\x05event\"s\n" + + "\x10SendInputRequest\x122\n" + + "\aprocess\x18\x01 \x01(\v2\x18.process.ProcessSelectorR\aprocess\x12+\n" + + "\x05input\x18\x02 \x01(\v2\x15.process.ProcessInputR\x05input\"\x13\n" + + "\x11SendInputResponse\"C\n" + + "\fProcessInput\x12\x16\n" + + "\x05stdin\x18\x01 \x01(\fH\x00R\x05stdin\x12\x12\n" + + "\x03pty\x18\x02 \x01(\fH\x00R\x03ptyB\a\n" + + "\x05input\"\xea\x02\n" + + "\x12StreamInputRequest\x12>\n" + + "\x05start\x18\x01 \x01(\v2&.process.StreamInputRequest.StartEventH\x00R\x05start\x12;\n" + + "\x04data\x18\x02 \x01(\v2%.process.StreamInputRequest.DataEventH\x00R\x04data\x12E\n" + + "\tkeepalive\x18\x03 \x01(\v2%.process.StreamInputRequest.KeepAliveH\x00R\tkeepalive\x1a@\n" + + "\n" + + "StartEvent\x122\n" + + "\aprocess\x18\x01 \x01(\v2\x18.process.ProcessSelectorR\aprocess\x1a8\n" + + "\tDataEvent\x12+\n" + + "\x05input\x18\x02 \x01(\v2\x15.process.ProcessInputR\x05input\x1a\v\n" + + "\tKeepAliveB\a\n" + + "\x05event\"\x15\n" + + "\x13StreamInputResponse\"p\n" + + "\x11SendSignalRequest\x122\n" + + "\aprocess\x18\x01 \x01(\v2\x18.process.ProcessSelectorR\aprocess\x12'\n" + + "\x06signal\x18\x02 \x01(\x0e2\x0f.process.SignalR\x06signal\"\x14\n" + + "\x12SendSignalResponse\"G\n" + + "\x11CloseStdinRequest\x122\n" + + "\aprocess\x18\x01 \x01(\v2\x18.process.ProcessSelectorR\aprocess\"\x14\n" + + "\x12CloseStdinResponse\"D\n" + + "\x0eConnectRequest\x122\n" + + "\aprocess\x18\x01 \x01(\v2\x18.process.ProcessSelectorR\aprocess\"E\n" + + "\x0fProcessSelector\x12\x12\n" + + "\x03pid\x18\x01 \x01(\rH\x00R\x03pid\x12\x12\n" + + "\x03tag\x18\x02 \x01(\tH\x00R\x03tagB\n" + + "\n" + + "\bselector*H\n" + + "\x06Signal\x12\x16\n" + + "\x12SIGNAL_UNSPECIFIED\x10\x00\x12\x12\n" + + "\x0eSIGNAL_SIGTERM\x10\x0f\x12\x12\n" + + "\x0eSIGNAL_SIGKILL\x10\t2\x91\x04\n" + + "\aProcess\x123\n" + + "\x04List\x12\x14.process.ListRequest\x1a\x15.process.ListResponse\x12>\n" + + "\aConnect\x12\x17.process.ConnectRequest\x1a\x18.process.ConnectResponse0\x01\x128\n" + + "\x05Start\x12\x15.process.StartRequest\x1a\x16.process.StartResponse0\x01\x129\n" + + "\x06Update\x12\x16.process.UpdateRequest\x1a\x17.process.UpdateResponse\x12J\n" + + "\vStreamInput\x12\x1b.process.StreamInputRequest\x1a\x1c.process.StreamInputResponse(\x01\x12B\n" + + "\tSendInput\x12\x19.process.SendInputRequest\x1a\x1a.process.SendInputResponse\x12E\n" + + "\n" + + "SendSignal\x12\x1a.process.SendSignalRequest\x1a\x1b.process.SendSignalResponse\x12E\n" + + "\n" + + "CloseStdin\x12\x1a.process.CloseStdinRequest\x1a\x1b.process.CloseStdinResponseB\x90\x01\n" + + "\vcom.processB\fProcessProtoP\x01Z7git.omukk.dev/wrenn/sandbox/envd/internal/services/spec\xa2\x02\x03PXX\xaa\x02\aProcess\xca\x02\aProcess\xe2\x02\x13Process\\GPBMetadata\xea\x02\aProcessb\x06proto3" + +var ( + file_process_proto_rawDescOnce sync.Once + file_process_proto_rawDescData []byte +) + +func file_process_proto_rawDescGZIP() []byte { + file_process_proto_rawDescOnce.Do(func() { + file_process_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_process_proto_rawDesc), len(file_process_proto_rawDesc))) + }) + return file_process_proto_rawDescData +} + +var file_process_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_process_proto_msgTypes = make([]protoimpl.MessageInfo, 31) +var file_process_proto_goTypes = []any{ + (Signal)(0), // 0: process.Signal + (*PTY)(nil), // 1: process.PTY + (*ProcessConfig)(nil), // 2: process.ProcessConfig + (*ListRequest)(nil), // 3: process.ListRequest + (*ProcessInfo)(nil), // 4: process.ProcessInfo + (*ListResponse)(nil), // 5: process.ListResponse + (*StartRequest)(nil), // 6: process.StartRequest + (*UpdateRequest)(nil), // 7: process.UpdateRequest + (*UpdateResponse)(nil), // 8: process.UpdateResponse + (*ProcessEvent)(nil), // 9: process.ProcessEvent + (*StartResponse)(nil), // 10: process.StartResponse + (*ConnectResponse)(nil), // 11: process.ConnectResponse + (*SendInputRequest)(nil), // 12: process.SendInputRequest + (*SendInputResponse)(nil), // 13: process.SendInputResponse + (*ProcessInput)(nil), // 14: process.ProcessInput + (*StreamInputRequest)(nil), // 15: process.StreamInputRequest + (*StreamInputResponse)(nil), // 16: process.StreamInputResponse + (*SendSignalRequest)(nil), // 17: process.SendSignalRequest + (*SendSignalResponse)(nil), // 18: process.SendSignalResponse + (*CloseStdinRequest)(nil), // 19: process.CloseStdinRequest + (*CloseStdinResponse)(nil), // 20: process.CloseStdinResponse + (*ConnectRequest)(nil), // 21: process.ConnectRequest + (*ProcessSelector)(nil), // 22: process.ProcessSelector + (*PTY_Size)(nil), // 23: process.PTY.Size + nil, // 24: process.ProcessConfig.EnvsEntry + (*ProcessEvent_StartEvent)(nil), // 25: process.ProcessEvent.StartEvent + (*ProcessEvent_DataEvent)(nil), // 26: process.ProcessEvent.DataEvent + (*ProcessEvent_EndEvent)(nil), // 27: process.ProcessEvent.EndEvent + (*ProcessEvent_KeepAlive)(nil), // 28: process.ProcessEvent.KeepAlive + (*StreamInputRequest_StartEvent)(nil), // 29: process.StreamInputRequest.StartEvent + (*StreamInputRequest_DataEvent)(nil), // 30: process.StreamInputRequest.DataEvent + (*StreamInputRequest_KeepAlive)(nil), // 31: process.StreamInputRequest.KeepAlive +} +var file_process_proto_depIdxs = []int32{ + 23, // 0: process.PTY.size:type_name -> process.PTY.Size + 24, // 1: process.ProcessConfig.envs:type_name -> process.ProcessConfig.EnvsEntry + 2, // 2: process.ProcessInfo.config:type_name -> process.ProcessConfig + 4, // 3: process.ListResponse.processes:type_name -> process.ProcessInfo + 2, // 4: process.StartRequest.process:type_name -> process.ProcessConfig + 1, // 5: process.StartRequest.pty:type_name -> process.PTY + 22, // 6: process.UpdateRequest.process:type_name -> process.ProcessSelector + 1, // 7: process.UpdateRequest.pty:type_name -> process.PTY + 25, // 8: process.ProcessEvent.start:type_name -> process.ProcessEvent.StartEvent + 26, // 9: process.ProcessEvent.data:type_name -> process.ProcessEvent.DataEvent + 27, // 10: process.ProcessEvent.end:type_name -> process.ProcessEvent.EndEvent + 28, // 11: process.ProcessEvent.keepalive:type_name -> process.ProcessEvent.KeepAlive + 9, // 12: process.StartResponse.event:type_name -> process.ProcessEvent + 9, // 13: process.ConnectResponse.event:type_name -> process.ProcessEvent + 22, // 14: process.SendInputRequest.process:type_name -> process.ProcessSelector + 14, // 15: process.SendInputRequest.input:type_name -> process.ProcessInput + 29, // 16: process.StreamInputRequest.start:type_name -> process.StreamInputRequest.StartEvent + 30, // 17: process.StreamInputRequest.data:type_name -> process.StreamInputRequest.DataEvent + 31, // 18: process.StreamInputRequest.keepalive:type_name -> process.StreamInputRequest.KeepAlive + 22, // 19: process.SendSignalRequest.process:type_name -> process.ProcessSelector + 0, // 20: process.SendSignalRequest.signal:type_name -> process.Signal + 22, // 21: process.CloseStdinRequest.process:type_name -> process.ProcessSelector + 22, // 22: process.ConnectRequest.process:type_name -> process.ProcessSelector + 22, // 23: process.StreamInputRequest.StartEvent.process:type_name -> process.ProcessSelector + 14, // 24: process.StreamInputRequest.DataEvent.input:type_name -> process.ProcessInput + 3, // 25: process.Process.List:input_type -> process.ListRequest + 21, // 26: process.Process.Connect:input_type -> process.ConnectRequest + 6, // 27: process.Process.Start:input_type -> process.StartRequest + 7, // 28: process.Process.Update:input_type -> process.UpdateRequest + 15, // 29: process.Process.StreamInput:input_type -> process.StreamInputRequest + 12, // 30: process.Process.SendInput:input_type -> process.SendInputRequest + 17, // 31: process.Process.SendSignal:input_type -> process.SendSignalRequest + 19, // 32: process.Process.CloseStdin:input_type -> process.CloseStdinRequest + 5, // 33: process.Process.List:output_type -> process.ListResponse + 11, // 34: process.Process.Connect:output_type -> process.ConnectResponse + 10, // 35: process.Process.Start:output_type -> process.StartResponse + 8, // 36: process.Process.Update:output_type -> process.UpdateResponse + 16, // 37: process.Process.StreamInput:output_type -> process.StreamInputResponse + 13, // 38: process.Process.SendInput:output_type -> process.SendInputResponse + 18, // 39: process.Process.SendSignal:output_type -> process.SendSignalResponse + 20, // 40: process.Process.CloseStdin:output_type -> process.CloseStdinResponse + 33, // [33:41] is the sub-list for method output_type + 25, // [25:33] is the sub-list for method input_type + 25, // [25:25] is the sub-list for extension type_name + 25, // [25:25] is the sub-list for extension extendee + 0, // [0:25] is the sub-list for field type_name +} + +func init() { file_process_proto_init() } +func file_process_proto_init() { + if File_process_proto != nil { + return + } + file_process_proto_msgTypes[1].OneofWrappers = []any{} + file_process_proto_msgTypes[3].OneofWrappers = []any{} + file_process_proto_msgTypes[5].OneofWrappers = []any{} + file_process_proto_msgTypes[6].OneofWrappers = []any{} + file_process_proto_msgTypes[8].OneofWrappers = []any{ + (*ProcessEvent_Start)(nil), + (*ProcessEvent_Data)(nil), + (*ProcessEvent_End)(nil), + (*ProcessEvent_Keepalive)(nil), + } + file_process_proto_msgTypes[13].OneofWrappers = []any{ + (*ProcessInput_Stdin)(nil), + (*ProcessInput_Pty)(nil), + } + file_process_proto_msgTypes[14].OneofWrappers = []any{ + (*StreamInputRequest_Start)(nil), + (*StreamInputRequest_Data)(nil), + (*StreamInputRequest_Keepalive)(nil), + } + file_process_proto_msgTypes[21].OneofWrappers = []any{ + (*ProcessSelector_Pid)(nil), + (*ProcessSelector_Tag)(nil), + } + file_process_proto_msgTypes[25].OneofWrappers = []any{ + (*ProcessEvent_DataEvent_Stdout)(nil), + (*ProcessEvent_DataEvent_Stderr)(nil), + (*ProcessEvent_DataEvent_Pty)(nil), + } + file_process_proto_msgTypes[26].OneofWrappers = []any{} + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_process_proto_rawDesc), len(file_process_proto_rawDesc)), + NumEnums: 1, + NumMessages: 31, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_process_proto_goTypes, + DependencyIndexes: file_process_proto_depIdxs, + EnumInfos: file_process_proto_enumTypes, + MessageInfos: file_process_proto_msgTypes, + }.Build() + File_process_proto = out.File + file_process_proto_goTypes = nil + file_process_proto_depIdxs = nil +} diff --git a/envd/internal/services/spec/specconnect/filesystem.connect.go b/envd/internal/services/spec/specconnect/filesystem.connect.go new file mode 100644 index 0000000..f405b3d --- /dev/null +++ b/envd/internal/services/spec/specconnect/filesystem.connect.go @@ -0,0 +1,337 @@ +// Code generated by protoc-gen-connect-go. DO NOT EDIT. +// +// Source: filesystem.proto + +package specconnect + +import ( + connect "connectrpc.com/connect" + context "context" + errors "errors" + spec "git.omukk.dev/wrenn/sandbox/envd/internal/services/spec" + http "net/http" + strings "strings" +) + +// This is a compile-time assertion to ensure that this generated file and the connect package are +// compatible. If you get a compiler error that this constant is not defined, this code was +// generated with a version of connect newer than the one compiled into your binary. You can fix the +// problem by either regenerating this code with an older version of connect or updating the connect +// version compiled into your binary. +const _ = connect.IsAtLeastVersion1_13_0 + +const ( + // FilesystemName is the fully-qualified name of the Filesystem service. + FilesystemName = "filesystem.Filesystem" +) + +// These constants are the fully-qualified names of the RPCs defined in this package. They're +// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route. +// +// Note that these are different from the fully-qualified method names used by +// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to +// reflection-formatted method names, remove the leading slash and convert the remaining slash to a +// period. +const ( + // FilesystemStatProcedure is the fully-qualified name of the Filesystem's Stat RPC. + FilesystemStatProcedure = "/filesystem.Filesystem/Stat" + // FilesystemMakeDirProcedure is the fully-qualified name of the Filesystem's MakeDir RPC. + FilesystemMakeDirProcedure = "/filesystem.Filesystem/MakeDir" + // FilesystemMoveProcedure is the fully-qualified name of the Filesystem's Move RPC. + FilesystemMoveProcedure = "/filesystem.Filesystem/Move" + // FilesystemListDirProcedure is the fully-qualified name of the Filesystem's ListDir RPC. + FilesystemListDirProcedure = "/filesystem.Filesystem/ListDir" + // FilesystemRemoveProcedure is the fully-qualified name of the Filesystem's Remove RPC. + FilesystemRemoveProcedure = "/filesystem.Filesystem/Remove" + // FilesystemWatchDirProcedure is the fully-qualified name of the Filesystem's WatchDir RPC. + FilesystemWatchDirProcedure = "/filesystem.Filesystem/WatchDir" + // FilesystemCreateWatcherProcedure is the fully-qualified name of the Filesystem's CreateWatcher + // RPC. + FilesystemCreateWatcherProcedure = "/filesystem.Filesystem/CreateWatcher" + // FilesystemGetWatcherEventsProcedure is the fully-qualified name of the Filesystem's + // GetWatcherEvents RPC. + FilesystemGetWatcherEventsProcedure = "/filesystem.Filesystem/GetWatcherEvents" + // FilesystemRemoveWatcherProcedure is the fully-qualified name of the Filesystem's RemoveWatcher + // RPC. + FilesystemRemoveWatcherProcedure = "/filesystem.Filesystem/RemoveWatcher" +) + +// FilesystemClient is a client for the filesystem.Filesystem service. +type FilesystemClient interface { + Stat(context.Context, *connect.Request[spec.StatRequest]) (*connect.Response[spec.StatResponse], error) + MakeDir(context.Context, *connect.Request[spec.MakeDirRequest]) (*connect.Response[spec.MakeDirResponse], error) + Move(context.Context, *connect.Request[spec.MoveRequest]) (*connect.Response[spec.MoveResponse], error) + ListDir(context.Context, *connect.Request[spec.ListDirRequest]) (*connect.Response[spec.ListDirResponse], error) + Remove(context.Context, *connect.Request[spec.RemoveRequest]) (*connect.Response[spec.RemoveResponse], error) + WatchDir(context.Context, *connect.Request[spec.WatchDirRequest]) (*connect.ServerStreamForClient[spec.WatchDirResponse], error) + // Non-streaming versions of WatchDir + CreateWatcher(context.Context, *connect.Request[spec.CreateWatcherRequest]) (*connect.Response[spec.CreateWatcherResponse], error) + GetWatcherEvents(context.Context, *connect.Request[spec.GetWatcherEventsRequest]) (*connect.Response[spec.GetWatcherEventsResponse], error) + RemoveWatcher(context.Context, *connect.Request[spec.RemoveWatcherRequest]) (*connect.Response[spec.RemoveWatcherResponse], error) +} + +// NewFilesystemClient constructs a client for the filesystem.Filesystem service. By default, it +// uses the Connect protocol with the binary Protobuf Codec, asks for gzipped responses, and sends +// uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the connect.WithGRPC() or +// connect.WithGRPCWeb() options. +// +// The URL supplied here should be the base URL for the Connect or gRPC server (for example, +// http://api.acme.com or https://acme.com/grpc). +func NewFilesystemClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) FilesystemClient { + baseURL = strings.TrimRight(baseURL, "/") + filesystemMethods := spec.File_filesystem_proto.Services().ByName("Filesystem").Methods() + return &filesystemClient{ + stat: connect.NewClient[spec.StatRequest, spec.StatResponse]( + httpClient, + baseURL+FilesystemStatProcedure, + connect.WithSchema(filesystemMethods.ByName("Stat")), + connect.WithClientOptions(opts...), + ), + makeDir: connect.NewClient[spec.MakeDirRequest, spec.MakeDirResponse]( + httpClient, + baseURL+FilesystemMakeDirProcedure, + connect.WithSchema(filesystemMethods.ByName("MakeDir")), + connect.WithClientOptions(opts...), + ), + move: connect.NewClient[spec.MoveRequest, spec.MoveResponse]( + httpClient, + baseURL+FilesystemMoveProcedure, + connect.WithSchema(filesystemMethods.ByName("Move")), + connect.WithClientOptions(opts...), + ), + listDir: connect.NewClient[spec.ListDirRequest, spec.ListDirResponse]( + httpClient, + baseURL+FilesystemListDirProcedure, + connect.WithSchema(filesystemMethods.ByName("ListDir")), + connect.WithClientOptions(opts...), + ), + remove: connect.NewClient[spec.RemoveRequest, spec.RemoveResponse]( + httpClient, + baseURL+FilesystemRemoveProcedure, + connect.WithSchema(filesystemMethods.ByName("Remove")), + connect.WithClientOptions(opts...), + ), + watchDir: connect.NewClient[spec.WatchDirRequest, spec.WatchDirResponse]( + httpClient, + baseURL+FilesystemWatchDirProcedure, + connect.WithSchema(filesystemMethods.ByName("WatchDir")), + connect.WithClientOptions(opts...), + ), + createWatcher: connect.NewClient[spec.CreateWatcherRequest, spec.CreateWatcherResponse]( + httpClient, + baseURL+FilesystemCreateWatcherProcedure, + connect.WithSchema(filesystemMethods.ByName("CreateWatcher")), + connect.WithClientOptions(opts...), + ), + getWatcherEvents: connect.NewClient[spec.GetWatcherEventsRequest, spec.GetWatcherEventsResponse]( + httpClient, + baseURL+FilesystemGetWatcherEventsProcedure, + connect.WithSchema(filesystemMethods.ByName("GetWatcherEvents")), + connect.WithClientOptions(opts...), + ), + removeWatcher: connect.NewClient[spec.RemoveWatcherRequest, spec.RemoveWatcherResponse]( + httpClient, + baseURL+FilesystemRemoveWatcherProcedure, + connect.WithSchema(filesystemMethods.ByName("RemoveWatcher")), + connect.WithClientOptions(opts...), + ), + } +} + +// filesystemClient implements FilesystemClient. +type filesystemClient struct { + stat *connect.Client[spec.StatRequest, spec.StatResponse] + makeDir *connect.Client[spec.MakeDirRequest, spec.MakeDirResponse] + move *connect.Client[spec.MoveRequest, spec.MoveResponse] + listDir *connect.Client[spec.ListDirRequest, spec.ListDirResponse] + remove *connect.Client[spec.RemoveRequest, spec.RemoveResponse] + watchDir *connect.Client[spec.WatchDirRequest, spec.WatchDirResponse] + createWatcher *connect.Client[spec.CreateWatcherRequest, spec.CreateWatcherResponse] + getWatcherEvents *connect.Client[spec.GetWatcherEventsRequest, spec.GetWatcherEventsResponse] + removeWatcher *connect.Client[spec.RemoveWatcherRequest, spec.RemoveWatcherResponse] +} + +// Stat calls filesystem.Filesystem.Stat. +func (c *filesystemClient) Stat(ctx context.Context, req *connect.Request[spec.StatRequest]) (*connect.Response[spec.StatResponse], error) { + return c.stat.CallUnary(ctx, req) +} + +// MakeDir calls filesystem.Filesystem.MakeDir. +func (c *filesystemClient) MakeDir(ctx context.Context, req *connect.Request[spec.MakeDirRequest]) (*connect.Response[spec.MakeDirResponse], error) { + return c.makeDir.CallUnary(ctx, req) +} + +// Move calls filesystem.Filesystem.Move. +func (c *filesystemClient) Move(ctx context.Context, req *connect.Request[spec.MoveRequest]) (*connect.Response[spec.MoveResponse], error) { + return c.move.CallUnary(ctx, req) +} + +// ListDir calls filesystem.Filesystem.ListDir. +func (c *filesystemClient) ListDir(ctx context.Context, req *connect.Request[spec.ListDirRequest]) (*connect.Response[spec.ListDirResponse], error) { + return c.listDir.CallUnary(ctx, req) +} + +// Remove calls filesystem.Filesystem.Remove. +func (c *filesystemClient) Remove(ctx context.Context, req *connect.Request[spec.RemoveRequest]) (*connect.Response[spec.RemoveResponse], error) { + return c.remove.CallUnary(ctx, req) +} + +// WatchDir calls filesystem.Filesystem.WatchDir. +func (c *filesystemClient) WatchDir(ctx context.Context, req *connect.Request[spec.WatchDirRequest]) (*connect.ServerStreamForClient[spec.WatchDirResponse], error) { + return c.watchDir.CallServerStream(ctx, req) +} + +// CreateWatcher calls filesystem.Filesystem.CreateWatcher. +func (c *filesystemClient) CreateWatcher(ctx context.Context, req *connect.Request[spec.CreateWatcherRequest]) (*connect.Response[spec.CreateWatcherResponse], error) { + return c.createWatcher.CallUnary(ctx, req) +} + +// GetWatcherEvents calls filesystem.Filesystem.GetWatcherEvents. +func (c *filesystemClient) GetWatcherEvents(ctx context.Context, req *connect.Request[spec.GetWatcherEventsRequest]) (*connect.Response[spec.GetWatcherEventsResponse], error) { + return c.getWatcherEvents.CallUnary(ctx, req) +} + +// RemoveWatcher calls filesystem.Filesystem.RemoveWatcher. +func (c *filesystemClient) RemoveWatcher(ctx context.Context, req *connect.Request[spec.RemoveWatcherRequest]) (*connect.Response[spec.RemoveWatcherResponse], error) { + return c.removeWatcher.CallUnary(ctx, req) +} + +// FilesystemHandler is an implementation of the filesystem.Filesystem service. +type FilesystemHandler interface { + Stat(context.Context, *connect.Request[spec.StatRequest]) (*connect.Response[spec.StatResponse], error) + MakeDir(context.Context, *connect.Request[spec.MakeDirRequest]) (*connect.Response[spec.MakeDirResponse], error) + Move(context.Context, *connect.Request[spec.MoveRequest]) (*connect.Response[spec.MoveResponse], error) + ListDir(context.Context, *connect.Request[spec.ListDirRequest]) (*connect.Response[spec.ListDirResponse], error) + Remove(context.Context, *connect.Request[spec.RemoveRequest]) (*connect.Response[spec.RemoveResponse], error) + WatchDir(context.Context, *connect.Request[spec.WatchDirRequest], *connect.ServerStream[spec.WatchDirResponse]) error + // Non-streaming versions of WatchDir + CreateWatcher(context.Context, *connect.Request[spec.CreateWatcherRequest]) (*connect.Response[spec.CreateWatcherResponse], error) + GetWatcherEvents(context.Context, *connect.Request[spec.GetWatcherEventsRequest]) (*connect.Response[spec.GetWatcherEventsResponse], error) + RemoveWatcher(context.Context, *connect.Request[spec.RemoveWatcherRequest]) (*connect.Response[spec.RemoveWatcherResponse], error) +} + +// NewFilesystemHandler builds an HTTP handler from the service implementation. It returns the path +// on which to mount the handler and the handler itself. +// +// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf +// and JSON codecs. They also support gzip compression. +func NewFilesystemHandler(svc FilesystemHandler, opts ...connect.HandlerOption) (string, http.Handler) { + filesystemMethods := spec.File_filesystem_proto.Services().ByName("Filesystem").Methods() + filesystemStatHandler := connect.NewUnaryHandler( + FilesystemStatProcedure, + svc.Stat, + connect.WithSchema(filesystemMethods.ByName("Stat")), + connect.WithHandlerOptions(opts...), + ) + filesystemMakeDirHandler := connect.NewUnaryHandler( + FilesystemMakeDirProcedure, + svc.MakeDir, + connect.WithSchema(filesystemMethods.ByName("MakeDir")), + connect.WithHandlerOptions(opts...), + ) + filesystemMoveHandler := connect.NewUnaryHandler( + FilesystemMoveProcedure, + svc.Move, + connect.WithSchema(filesystemMethods.ByName("Move")), + connect.WithHandlerOptions(opts...), + ) + filesystemListDirHandler := connect.NewUnaryHandler( + FilesystemListDirProcedure, + svc.ListDir, + connect.WithSchema(filesystemMethods.ByName("ListDir")), + connect.WithHandlerOptions(opts...), + ) + filesystemRemoveHandler := connect.NewUnaryHandler( + FilesystemRemoveProcedure, + svc.Remove, + connect.WithSchema(filesystemMethods.ByName("Remove")), + connect.WithHandlerOptions(opts...), + ) + filesystemWatchDirHandler := connect.NewServerStreamHandler( + FilesystemWatchDirProcedure, + svc.WatchDir, + connect.WithSchema(filesystemMethods.ByName("WatchDir")), + connect.WithHandlerOptions(opts...), + ) + filesystemCreateWatcherHandler := connect.NewUnaryHandler( + FilesystemCreateWatcherProcedure, + svc.CreateWatcher, + connect.WithSchema(filesystemMethods.ByName("CreateWatcher")), + connect.WithHandlerOptions(opts...), + ) + filesystemGetWatcherEventsHandler := connect.NewUnaryHandler( + FilesystemGetWatcherEventsProcedure, + svc.GetWatcherEvents, + connect.WithSchema(filesystemMethods.ByName("GetWatcherEvents")), + connect.WithHandlerOptions(opts...), + ) + filesystemRemoveWatcherHandler := connect.NewUnaryHandler( + FilesystemRemoveWatcherProcedure, + svc.RemoveWatcher, + connect.WithSchema(filesystemMethods.ByName("RemoveWatcher")), + connect.WithHandlerOptions(opts...), + ) + return "/filesystem.Filesystem/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case FilesystemStatProcedure: + filesystemStatHandler.ServeHTTP(w, r) + case FilesystemMakeDirProcedure: + filesystemMakeDirHandler.ServeHTTP(w, r) + case FilesystemMoveProcedure: + filesystemMoveHandler.ServeHTTP(w, r) + case FilesystemListDirProcedure: + filesystemListDirHandler.ServeHTTP(w, r) + case FilesystemRemoveProcedure: + filesystemRemoveHandler.ServeHTTP(w, r) + case FilesystemWatchDirProcedure: + filesystemWatchDirHandler.ServeHTTP(w, r) + case FilesystemCreateWatcherProcedure: + filesystemCreateWatcherHandler.ServeHTTP(w, r) + case FilesystemGetWatcherEventsProcedure: + filesystemGetWatcherEventsHandler.ServeHTTP(w, r) + case FilesystemRemoveWatcherProcedure: + filesystemRemoveWatcherHandler.ServeHTTP(w, r) + default: + http.NotFound(w, r) + } + }) +} + +// UnimplementedFilesystemHandler returns CodeUnimplemented from all methods. +type UnimplementedFilesystemHandler struct{} + +func (UnimplementedFilesystemHandler) Stat(context.Context, *connect.Request[spec.StatRequest]) (*connect.Response[spec.StatResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("filesystem.Filesystem.Stat is not implemented")) +} + +func (UnimplementedFilesystemHandler) MakeDir(context.Context, *connect.Request[spec.MakeDirRequest]) (*connect.Response[spec.MakeDirResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("filesystem.Filesystem.MakeDir is not implemented")) +} + +func (UnimplementedFilesystemHandler) Move(context.Context, *connect.Request[spec.MoveRequest]) (*connect.Response[spec.MoveResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("filesystem.Filesystem.Move is not implemented")) +} + +func (UnimplementedFilesystemHandler) ListDir(context.Context, *connect.Request[spec.ListDirRequest]) (*connect.Response[spec.ListDirResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("filesystem.Filesystem.ListDir is not implemented")) +} + +func (UnimplementedFilesystemHandler) Remove(context.Context, *connect.Request[spec.RemoveRequest]) (*connect.Response[spec.RemoveResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("filesystem.Filesystem.Remove is not implemented")) +} + +func (UnimplementedFilesystemHandler) WatchDir(context.Context, *connect.Request[spec.WatchDirRequest], *connect.ServerStream[spec.WatchDirResponse]) error { + return connect.NewError(connect.CodeUnimplemented, errors.New("filesystem.Filesystem.WatchDir is not implemented")) +} + +func (UnimplementedFilesystemHandler) CreateWatcher(context.Context, *connect.Request[spec.CreateWatcherRequest]) (*connect.Response[spec.CreateWatcherResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("filesystem.Filesystem.CreateWatcher is not implemented")) +} + +func (UnimplementedFilesystemHandler) GetWatcherEvents(context.Context, *connect.Request[spec.GetWatcherEventsRequest]) (*connect.Response[spec.GetWatcherEventsResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("filesystem.Filesystem.GetWatcherEvents is not implemented")) +} + +func (UnimplementedFilesystemHandler) RemoveWatcher(context.Context, *connect.Request[spec.RemoveWatcherRequest]) (*connect.Response[spec.RemoveWatcherResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("filesystem.Filesystem.RemoveWatcher is not implemented")) +} diff --git a/envd/internal/services/spec/specconnect/process.connect.go b/envd/internal/services/spec/specconnect/process.connect.go new file mode 100644 index 0000000..effd57b --- /dev/null +++ b/envd/internal/services/spec/specconnect/process.connect.go @@ -0,0 +1,310 @@ +// Code generated by protoc-gen-connect-go. DO NOT EDIT. +// +// Source: process.proto + +package specconnect + +import ( + connect "connectrpc.com/connect" + context "context" + errors "errors" + spec "git.omukk.dev/wrenn/sandbox/envd/internal/services/spec" + http "net/http" + strings "strings" +) + +// This is a compile-time assertion to ensure that this generated file and the connect package are +// compatible. If you get a compiler error that this constant is not defined, this code was +// generated with a version of connect newer than the one compiled into your binary. You can fix the +// problem by either regenerating this code with an older version of connect or updating the connect +// version compiled into your binary. +const _ = connect.IsAtLeastVersion1_13_0 + +const ( + // ProcessName is the fully-qualified name of the Process service. + ProcessName = "process.Process" +) + +// These constants are the fully-qualified names of the RPCs defined in this package. They're +// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route. +// +// Note that these are different from the fully-qualified method names used by +// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to +// reflection-formatted method names, remove the leading slash and convert the remaining slash to a +// period. +const ( + // ProcessListProcedure is the fully-qualified name of the Process's List RPC. + ProcessListProcedure = "/process.Process/List" + // ProcessConnectProcedure is the fully-qualified name of the Process's Connect RPC. + ProcessConnectProcedure = "/process.Process/Connect" + // ProcessStartProcedure is the fully-qualified name of the Process's Start RPC. + ProcessStartProcedure = "/process.Process/Start" + // ProcessUpdateProcedure is the fully-qualified name of the Process's Update RPC. + ProcessUpdateProcedure = "/process.Process/Update" + // ProcessStreamInputProcedure is the fully-qualified name of the Process's StreamInput RPC. + ProcessStreamInputProcedure = "/process.Process/StreamInput" + // ProcessSendInputProcedure is the fully-qualified name of the Process's SendInput RPC. + ProcessSendInputProcedure = "/process.Process/SendInput" + // ProcessSendSignalProcedure is the fully-qualified name of the Process's SendSignal RPC. + ProcessSendSignalProcedure = "/process.Process/SendSignal" + // ProcessCloseStdinProcedure is the fully-qualified name of the Process's CloseStdin RPC. + ProcessCloseStdinProcedure = "/process.Process/CloseStdin" +) + +// ProcessClient is a client for the process.Process service. +type ProcessClient interface { + List(context.Context, *connect.Request[spec.ListRequest]) (*connect.Response[spec.ListResponse], error) + Connect(context.Context, *connect.Request[spec.ConnectRequest]) (*connect.ServerStreamForClient[spec.ConnectResponse], error) + Start(context.Context, *connect.Request[spec.StartRequest]) (*connect.ServerStreamForClient[spec.StartResponse], error) + Update(context.Context, *connect.Request[spec.UpdateRequest]) (*connect.Response[spec.UpdateResponse], error) + // Client input stream ensures ordering of messages + StreamInput(context.Context) *connect.ClientStreamForClient[spec.StreamInputRequest, spec.StreamInputResponse] + SendInput(context.Context, *connect.Request[spec.SendInputRequest]) (*connect.Response[spec.SendInputResponse], error) + SendSignal(context.Context, *connect.Request[spec.SendSignalRequest]) (*connect.Response[spec.SendSignalResponse], error) + // Close stdin to signal EOF to the process. + // Only works for non-PTY processes. For PTY, send Ctrl+D (0x04) instead. + CloseStdin(context.Context, *connect.Request[spec.CloseStdinRequest]) (*connect.Response[spec.CloseStdinResponse], error) +} + +// NewProcessClient constructs a client for the process.Process service. By default, it uses the +// Connect protocol with the binary Protobuf Codec, asks for gzipped responses, and sends +// uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the connect.WithGRPC() or +// connect.WithGRPCWeb() options. +// +// The URL supplied here should be the base URL for the Connect or gRPC server (for example, +// http://api.acme.com or https://acme.com/grpc). +func NewProcessClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) ProcessClient { + baseURL = strings.TrimRight(baseURL, "/") + processMethods := spec.File_process_proto.Services().ByName("Process").Methods() + return &processClient{ + list: connect.NewClient[spec.ListRequest, spec.ListResponse]( + httpClient, + baseURL+ProcessListProcedure, + connect.WithSchema(processMethods.ByName("List")), + connect.WithClientOptions(opts...), + ), + connect: connect.NewClient[spec.ConnectRequest, spec.ConnectResponse]( + httpClient, + baseURL+ProcessConnectProcedure, + connect.WithSchema(processMethods.ByName("Connect")), + connect.WithClientOptions(opts...), + ), + start: connect.NewClient[spec.StartRequest, spec.StartResponse]( + httpClient, + baseURL+ProcessStartProcedure, + connect.WithSchema(processMethods.ByName("Start")), + connect.WithClientOptions(opts...), + ), + update: connect.NewClient[spec.UpdateRequest, spec.UpdateResponse]( + httpClient, + baseURL+ProcessUpdateProcedure, + connect.WithSchema(processMethods.ByName("Update")), + connect.WithClientOptions(opts...), + ), + streamInput: connect.NewClient[spec.StreamInputRequest, spec.StreamInputResponse]( + httpClient, + baseURL+ProcessStreamInputProcedure, + connect.WithSchema(processMethods.ByName("StreamInput")), + connect.WithClientOptions(opts...), + ), + sendInput: connect.NewClient[spec.SendInputRequest, spec.SendInputResponse]( + httpClient, + baseURL+ProcessSendInputProcedure, + connect.WithSchema(processMethods.ByName("SendInput")), + connect.WithClientOptions(opts...), + ), + sendSignal: connect.NewClient[spec.SendSignalRequest, spec.SendSignalResponse]( + httpClient, + baseURL+ProcessSendSignalProcedure, + connect.WithSchema(processMethods.ByName("SendSignal")), + connect.WithClientOptions(opts...), + ), + closeStdin: connect.NewClient[spec.CloseStdinRequest, spec.CloseStdinResponse]( + httpClient, + baseURL+ProcessCloseStdinProcedure, + connect.WithSchema(processMethods.ByName("CloseStdin")), + connect.WithClientOptions(opts...), + ), + } +} + +// processClient implements ProcessClient. +type processClient struct { + list *connect.Client[spec.ListRequest, spec.ListResponse] + connect *connect.Client[spec.ConnectRequest, spec.ConnectResponse] + start *connect.Client[spec.StartRequest, spec.StartResponse] + update *connect.Client[spec.UpdateRequest, spec.UpdateResponse] + streamInput *connect.Client[spec.StreamInputRequest, spec.StreamInputResponse] + sendInput *connect.Client[spec.SendInputRequest, spec.SendInputResponse] + sendSignal *connect.Client[spec.SendSignalRequest, spec.SendSignalResponse] + closeStdin *connect.Client[spec.CloseStdinRequest, spec.CloseStdinResponse] +} + +// List calls process.Process.List. +func (c *processClient) List(ctx context.Context, req *connect.Request[spec.ListRequest]) (*connect.Response[spec.ListResponse], error) { + return c.list.CallUnary(ctx, req) +} + +// Connect calls process.Process.Connect. +func (c *processClient) Connect(ctx context.Context, req *connect.Request[spec.ConnectRequest]) (*connect.ServerStreamForClient[spec.ConnectResponse], error) { + return c.connect.CallServerStream(ctx, req) +} + +// Start calls process.Process.Start. +func (c *processClient) Start(ctx context.Context, req *connect.Request[spec.StartRequest]) (*connect.ServerStreamForClient[spec.StartResponse], error) { + return c.start.CallServerStream(ctx, req) +} + +// Update calls process.Process.Update. +func (c *processClient) Update(ctx context.Context, req *connect.Request[spec.UpdateRequest]) (*connect.Response[spec.UpdateResponse], error) { + return c.update.CallUnary(ctx, req) +} + +// StreamInput calls process.Process.StreamInput. +func (c *processClient) StreamInput(ctx context.Context) *connect.ClientStreamForClient[spec.StreamInputRequest, spec.StreamInputResponse] { + return c.streamInput.CallClientStream(ctx) +} + +// SendInput calls process.Process.SendInput. +func (c *processClient) SendInput(ctx context.Context, req *connect.Request[spec.SendInputRequest]) (*connect.Response[spec.SendInputResponse], error) { + return c.sendInput.CallUnary(ctx, req) +} + +// SendSignal calls process.Process.SendSignal. +func (c *processClient) SendSignal(ctx context.Context, req *connect.Request[spec.SendSignalRequest]) (*connect.Response[spec.SendSignalResponse], error) { + return c.sendSignal.CallUnary(ctx, req) +} + +// CloseStdin calls process.Process.CloseStdin. +func (c *processClient) CloseStdin(ctx context.Context, req *connect.Request[spec.CloseStdinRequest]) (*connect.Response[spec.CloseStdinResponse], error) { + return c.closeStdin.CallUnary(ctx, req) +} + +// ProcessHandler is an implementation of the process.Process service. +type ProcessHandler interface { + List(context.Context, *connect.Request[spec.ListRequest]) (*connect.Response[spec.ListResponse], error) + Connect(context.Context, *connect.Request[spec.ConnectRequest], *connect.ServerStream[spec.ConnectResponse]) error + Start(context.Context, *connect.Request[spec.StartRequest], *connect.ServerStream[spec.StartResponse]) error + Update(context.Context, *connect.Request[spec.UpdateRequest]) (*connect.Response[spec.UpdateResponse], error) + // Client input stream ensures ordering of messages + StreamInput(context.Context, *connect.ClientStream[spec.StreamInputRequest]) (*connect.Response[spec.StreamInputResponse], error) + SendInput(context.Context, *connect.Request[spec.SendInputRequest]) (*connect.Response[spec.SendInputResponse], error) + SendSignal(context.Context, *connect.Request[spec.SendSignalRequest]) (*connect.Response[spec.SendSignalResponse], error) + // Close stdin to signal EOF to the process. + // Only works for non-PTY processes. For PTY, send Ctrl+D (0x04) instead. + CloseStdin(context.Context, *connect.Request[spec.CloseStdinRequest]) (*connect.Response[spec.CloseStdinResponse], error) +} + +// NewProcessHandler builds an HTTP handler from the service implementation. It returns the path on +// which to mount the handler and the handler itself. +// +// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf +// and JSON codecs. They also support gzip compression. +func NewProcessHandler(svc ProcessHandler, opts ...connect.HandlerOption) (string, http.Handler) { + processMethods := spec.File_process_proto.Services().ByName("Process").Methods() + processListHandler := connect.NewUnaryHandler( + ProcessListProcedure, + svc.List, + connect.WithSchema(processMethods.ByName("List")), + connect.WithHandlerOptions(opts...), + ) + processConnectHandler := connect.NewServerStreamHandler( + ProcessConnectProcedure, + svc.Connect, + connect.WithSchema(processMethods.ByName("Connect")), + connect.WithHandlerOptions(opts...), + ) + processStartHandler := connect.NewServerStreamHandler( + ProcessStartProcedure, + svc.Start, + connect.WithSchema(processMethods.ByName("Start")), + connect.WithHandlerOptions(opts...), + ) + processUpdateHandler := connect.NewUnaryHandler( + ProcessUpdateProcedure, + svc.Update, + connect.WithSchema(processMethods.ByName("Update")), + connect.WithHandlerOptions(opts...), + ) + processStreamInputHandler := connect.NewClientStreamHandler( + ProcessStreamInputProcedure, + svc.StreamInput, + connect.WithSchema(processMethods.ByName("StreamInput")), + connect.WithHandlerOptions(opts...), + ) + processSendInputHandler := connect.NewUnaryHandler( + ProcessSendInputProcedure, + svc.SendInput, + connect.WithSchema(processMethods.ByName("SendInput")), + connect.WithHandlerOptions(opts...), + ) + processSendSignalHandler := connect.NewUnaryHandler( + ProcessSendSignalProcedure, + svc.SendSignal, + connect.WithSchema(processMethods.ByName("SendSignal")), + connect.WithHandlerOptions(opts...), + ) + processCloseStdinHandler := connect.NewUnaryHandler( + ProcessCloseStdinProcedure, + svc.CloseStdin, + connect.WithSchema(processMethods.ByName("CloseStdin")), + connect.WithHandlerOptions(opts...), + ) + return "/process.Process/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case ProcessListProcedure: + processListHandler.ServeHTTP(w, r) + case ProcessConnectProcedure: + processConnectHandler.ServeHTTP(w, r) + case ProcessStartProcedure: + processStartHandler.ServeHTTP(w, r) + case ProcessUpdateProcedure: + processUpdateHandler.ServeHTTP(w, r) + case ProcessStreamInputProcedure: + processStreamInputHandler.ServeHTTP(w, r) + case ProcessSendInputProcedure: + processSendInputHandler.ServeHTTP(w, r) + case ProcessSendSignalProcedure: + processSendSignalHandler.ServeHTTP(w, r) + case ProcessCloseStdinProcedure: + processCloseStdinHandler.ServeHTTP(w, r) + default: + http.NotFound(w, r) + } + }) +} + +// UnimplementedProcessHandler returns CodeUnimplemented from all methods. +type UnimplementedProcessHandler struct{} + +func (UnimplementedProcessHandler) List(context.Context, *connect.Request[spec.ListRequest]) (*connect.Response[spec.ListResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("process.Process.List is not implemented")) +} + +func (UnimplementedProcessHandler) Connect(context.Context, *connect.Request[spec.ConnectRequest], *connect.ServerStream[spec.ConnectResponse]) error { + return connect.NewError(connect.CodeUnimplemented, errors.New("process.Process.Connect is not implemented")) +} + +func (UnimplementedProcessHandler) Start(context.Context, *connect.Request[spec.StartRequest], *connect.ServerStream[spec.StartResponse]) error { + return connect.NewError(connect.CodeUnimplemented, errors.New("process.Process.Start is not implemented")) +} + +func (UnimplementedProcessHandler) Update(context.Context, *connect.Request[spec.UpdateRequest]) (*connect.Response[spec.UpdateResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("process.Process.Update is not implemented")) +} + +func (UnimplementedProcessHandler) StreamInput(context.Context, *connect.ClientStream[spec.StreamInputRequest]) (*connect.Response[spec.StreamInputResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("process.Process.StreamInput is not implemented")) +} + +func (UnimplementedProcessHandler) SendInput(context.Context, *connect.Request[spec.SendInputRequest]) (*connect.Response[spec.SendInputResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("process.Process.SendInput is not implemented")) +} + +func (UnimplementedProcessHandler) SendSignal(context.Context, *connect.Request[spec.SendSignalRequest]) (*connect.Response[spec.SendSignalResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("process.Process.SendSignal is not implemented")) +} + +func (UnimplementedProcessHandler) CloseStdin(context.Context, *connect.Request[spec.CloseStdinRequest]) (*connect.Response[spec.CloseStdinResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("process.Process.CloseStdin is not implemented")) +} diff --git a/images/envd.service b/images/envd.service deleted file mode 100644 index ca70b22..0000000 --- a/images/envd.service +++ /dev/null @@ -1,12 +0,0 @@ -[Unit] -Description=Wrenn envd guest agent -After=network.target - -[Service] -Type=simple -ExecStart=/usr/local/bin/envd -Restart=on-failure -RestartSec=1 - -[Install] -WantedBy=multi-user.target diff --git a/internal/filesystem/clone.go b/internal/filesystem/clone.go index e69de29..28abedb 100644 --- a/internal/filesystem/clone.go +++ b/internal/filesystem/clone.go @@ -0,0 +1,16 @@ +package filesystem + +import ( + "fmt" + "os/exec" +) + +// CloneRootfs creates a copy-on-write clone of the base rootfs image. +// Uses reflink if supported by the filesystem, falls back to regular copy. +func CloneRootfs(src, dst string) error { + cmd := exec.Command("cp", "--reflink=auto", src, dst) + if out, err := cmd.CombinedOutput(); err != nil { + return fmt.Errorf("cp --reflink=auto: %s: %w", string(out), err) + } + return nil +} diff --git a/internal/filesystem/images.go b/internal/filesystem/images.go index e69de29..e4b5af9 100644 --- a/internal/filesystem/images.go +++ b/internal/filesystem/images.go @@ -0,0 +1 @@ +package filesystem diff --git a/internal/hostagent/server.go b/internal/hostagent/server.go new file mode 100644 index 0000000..717b509 --- /dev/null +++ b/internal/hostagent/server.go @@ -0,0 +1,125 @@ +package hostagent + +import ( + "context" + "fmt" + "time" + + "connectrpc.com/connect" + + pb "git.omukk.dev/wrenn/sandbox/proto/hostagent/gen" + "git.omukk.dev/wrenn/sandbox/proto/hostagent/gen/hostagentv1connect" + + "git.omukk.dev/wrenn/sandbox/internal/sandbox" +) + +// Server implements the HostAgentService Connect RPC handler. +type Server struct { + hostagentv1connect.UnimplementedHostAgentServiceHandler + mgr *sandbox.Manager +} + +// NewServer creates a new host agent RPC server. +func NewServer(mgr *sandbox.Manager) *Server { + return &Server{mgr: mgr} +} + +func (s *Server) CreateSandbox( + ctx context.Context, + req *connect.Request[pb.CreateSandboxRequest], +) (*connect.Response[pb.CreateSandboxResponse], error) { + msg := req.Msg + + sb, err := s.mgr.Create(ctx, msg.Template, int(msg.Vcpus), int(msg.MemoryMb), int(msg.TimeoutSec)) + if err != nil { + return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("create sandbox: %w", err)) + } + + return connect.NewResponse(&pb.CreateSandboxResponse{ + SandboxId: sb.ID, + Status: string(sb.Status), + HostIp: sb.HostIP.String(), + }), nil +} + +func (s *Server) DestroySandbox( + ctx context.Context, + req *connect.Request[pb.DestroySandboxRequest], +) (*connect.Response[pb.DestroySandboxResponse], error) { + if err := s.mgr.Destroy(ctx, req.Msg.SandboxId); err != nil { + return nil, connect.NewError(connect.CodeNotFound, err) + } + return connect.NewResponse(&pb.DestroySandboxResponse{}), nil +} + +func (s *Server) PauseSandbox( + ctx context.Context, + req *connect.Request[pb.PauseSandboxRequest], +) (*connect.Response[pb.PauseSandboxResponse], error) { + if err := s.mgr.Pause(ctx, req.Msg.SandboxId); err != nil { + return nil, connect.NewError(connect.CodeInternal, err) + } + return connect.NewResponse(&pb.PauseSandboxResponse{}), nil +} + +func (s *Server) ResumeSandbox( + ctx context.Context, + req *connect.Request[pb.ResumeSandboxRequest], +) (*connect.Response[pb.ResumeSandboxResponse], error) { + if err := s.mgr.Resume(ctx, req.Msg.SandboxId); err != nil { + return nil, connect.NewError(connect.CodeInternal, err) + } + return connect.NewResponse(&pb.ResumeSandboxResponse{}), nil +} + +func (s *Server) Exec( + ctx context.Context, + req *connect.Request[pb.ExecRequest], +) (*connect.Response[pb.ExecResponse], error) { + msg := req.Msg + + timeout := 30 * time.Second + if msg.TimeoutSec > 0 { + timeout = time.Duration(msg.TimeoutSec) * time.Second + } + + execCtx, cancel := context.WithTimeout(ctx, timeout) + defer cancel() + + result, err := s.mgr.Exec(execCtx, msg.SandboxId, msg.Cmd, msg.Args...) + if err != nil { + return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("exec: %w", err)) + } + + return connect.NewResponse(&pb.ExecResponse{ + Stdout: result.Stdout, + Stderr: result.Stderr, + ExitCode: result.ExitCode, + }), nil +} + +func (s *Server) ListSandboxes( + ctx context.Context, + req *connect.Request[pb.ListSandboxesRequest], +) (*connect.Response[pb.ListSandboxesResponse], error) { + sandboxes := s.mgr.List() + + infos := make([]*pb.SandboxInfo, len(sandboxes)) + for i, sb := range sandboxes { + infos[i] = &pb.SandboxInfo{ + SandboxId: sb.ID, + Status: string(sb.Status), + Template: sb.Template, + Vcpus: int32(sb.VCPUs), + MemoryMb: int32(sb.MemoryMB), + HostIp: sb.HostIP.String(), + CreatedAtUnix: sb.CreatedAt.Unix(), + LastActiveAtUnix: sb.LastActiveAt.Unix(), + TimeoutSec: int32(sb.TimeoutSec), + } + } + + return connect.NewResponse(&pb.ListSandboxesResponse{ + Sandboxes: infos, + }), nil +} diff --git a/internal/id/id.go b/internal/id/id.go index e69de29..1b306f7 100644 --- a/internal/id/id.go +++ b/internal/id/id.go @@ -0,0 +1,16 @@ +package id + +import ( + "crypto/rand" + "encoding/hex" + "fmt" +) + +// NewSandboxID generates a new sandbox ID in the format "sb-" + 8 hex chars. +func NewSandboxID() string { + b := make([]byte, 4) + if _, err := rand.Read(b); err != nil { + panic(fmt.Sprintf("crypto/rand failed: %v", err)) + } + return "sb-" + hex.EncodeToString(b) +} diff --git a/internal/models/host.go b/internal/models/host.go index e69de29..2640e7f 100644 --- a/internal/models/host.go +++ b/internal/models/host.go @@ -0,0 +1 @@ +package models diff --git a/internal/models/sandbox.go b/internal/models/sandbox.go index e69de29..b99bd6b 100644 --- a/internal/models/sandbox.go +++ b/internal/models/sandbox.go @@ -0,0 +1,32 @@ +package models + +import ( + "net" + "time" +) + +// SandboxStatus represents the current state of a sandbox. +type SandboxStatus string + +const ( + StatusPending SandboxStatus = "pending" + StatusRunning SandboxStatus = "running" + StatusPaused SandboxStatus = "paused" + StatusStopped SandboxStatus = "stopped" + StatusError SandboxStatus = "error" +) + +// Sandbox holds all state for a running sandbox on this host. +type Sandbox struct { + ID string + Status SandboxStatus + Template string + VCPUs int + MemoryMB int + TimeoutSec int + SlotIndex int + HostIP net.IP + RootfsPath string + CreatedAt time.Time + LastActiveAt time.Time +} diff --git a/internal/network/allocator.go b/internal/network/allocator.go index 1ae2e9d..b7265e6 100644 --- a/internal/network/allocator.go +++ b/internal/network/allocator.go @@ -1 +1,41 @@ package network + +import ( + "fmt" + "sync" +) + +// SlotAllocator manages network slot indices for sandboxes. +// Each sandbox needs a unique slot index for its network addressing. +type SlotAllocator struct { + mu sync.Mutex + inUse map[int]bool +} + +// NewSlotAllocator creates a new slot allocator. +func NewSlotAllocator() *SlotAllocator { + return &SlotAllocator{ + inUse: make(map[int]bool), + } +} + +// Allocate returns the next available slot index (1-based). +func (a *SlotAllocator) Allocate() (int, error) { + a.mu.Lock() + defer a.mu.Unlock() + + for i := 1; i <= 65534; i++ { + if !a.inUse[i] { + a.inUse[i] = true + return i, nil + } + } + return 0, fmt.Errorf("no free network slots") +} + +// Release frees a slot index for reuse. +func (a *SlotAllocator) Release(index int) { + a.mu.Lock() + defer a.mu.Unlock() + delete(a.inUse, index) +} diff --git a/internal/sandbox/manager.go b/internal/sandbox/manager.go new file mode 100644 index 0000000..b9ca420 --- /dev/null +++ b/internal/sandbox/manager.go @@ -0,0 +1,356 @@ +package sandbox + +import ( + "context" + "fmt" + "log/slog" + "os" + "path/filepath" + "sync" + "time" + + "git.omukk.dev/wrenn/sandbox/internal/envdclient" + "git.omukk.dev/wrenn/sandbox/internal/filesystem" + "git.omukk.dev/wrenn/sandbox/internal/id" + "git.omukk.dev/wrenn/sandbox/internal/models" + "git.omukk.dev/wrenn/sandbox/internal/network" + "git.omukk.dev/wrenn/sandbox/internal/vm" +) + +// Config holds the paths and defaults for the sandbox manager. +type Config struct { + KernelPath string + ImagesDir string // directory containing base rootfs images (e.g., /var/lib/wrenn/images/minimal.ext4) + SandboxesDir string // directory for per-sandbox rootfs clones (e.g., /var/lib/wrenn/sandboxes) + EnvdTimeout time.Duration +} + +// Manager orchestrates sandbox lifecycle: VM, network, filesystem, envd. +type Manager struct { + cfg Config + vm *vm.Manager + slots *network.SlotAllocator + mu sync.RWMutex + boxes map[string]*sandboxState + stopCh chan struct{} +} + +// sandboxState holds the runtime state for a single sandbox. +type sandboxState struct { + models.Sandbox + slot *network.Slot + client *envdclient.Client +} + +// New creates a new sandbox manager. +func New(cfg Config) *Manager { + if cfg.EnvdTimeout == 0 { + cfg.EnvdTimeout = 30 * time.Second + } + return &Manager{ + cfg: cfg, + vm: vm.NewManager(), + slots: network.NewSlotAllocator(), + boxes: make(map[string]*sandboxState), + stopCh: make(chan struct{}), + } +} + +// Create boots a new sandbox: clone rootfs, set up network, start VM, wait for envd. +func (m *Manager) Create(ctx context.Context, template string, vcpus, memoryMB, timeoutSec int) (*models.Sandbox, error) { + sandboxID := id.NewSandboxID() + + if vcpus <= 0 { + vcpus = 1 + } + if memoryMB <= 0 { + memoryMB = 512 + } + + if template == "" { + template = "minimal" + } + + // Resolve base rootfs image: /var/lib/wrenn/images/{template}.ext4 + baseRootfs := filepath.Join(m.cfg.ImagesDir, template+".ext4") + if _, err := os.Stat(baseRootfs); err != nil { + return nil, fmt.Errorf("base rootfs not found at %s: %w", baseRootfs, err) + } + + // Clone rootfs. + rootfsPath := filepath.Join(m.cfg.SandboxesDir, fmt.Sprintf("%s-%s.ext4", sandboxID, template)) + if err := filesystem.CloneRootfs(baseRootfs, rootfsPath); err != nil { + return nil, fmt.Errorf("clone rootfs: %w", err) + } + + // Allocate network slot. + slotIdx, err := m.slots.Allocate() + if err != nil { + os.Remove(rootfsPath) + return nil, fmt.Errorf("allocate network slot: %w", err) + } + slot := network.NewSlot(slotIdx) + + // Set up network. + if err := network.CreateNetwork(slot); err != nil { + m.slots.Release(slotIdx) + os.Remove(rootfsPath) + return nil, fmt.Errorf("create network: %w", err) + } + + // Boot VM. + vmCfg := vm.VMConfig{ + SandboxID: sandboxID, + KernelPath: m.cfg.KernelPath, + RootfsPath: rootfsPath, + VCPUs: vcpus, + MemoryMB: memoryMB, + NetworkNamespace: slot.NamespaceID, + TapDevice: slot.TapName, + TapMAC: slot.TapMAC, + GuestIP: slot.GuestIP, + GatewayIP: slot.TapIP, + NetMask: slot.GuestNetMask, + } + + if _, err := m.vm.Create(ctx, vmCfg); err != nil { + network.RemoveNetwork(slot) + m.slots.Release(slotIdx) + os.Remove(rootfsPath) + return nil, fmt.Errorf("create VM: %w", err) + } + + // Wait for envd to be ready. + client := envdclient.New(slot.HostIP.String()) + waitCtx, waitCancel := context.WithTimeout(ctx, m.cfg.EnvdTimeout) + defer waitCancel() + + if err := client.WaitUntilReady(waitCtx); err != nil { + m.vm.Destroy(context.Background(), sandboxID) + network.RemoveNetwork(slot) + m.slots.Release(slotIdx) + os.Remove(rootfsPath) + return nil, fmt.Errorf("wait for envd: %w", err) + } + + now := time.Now() + sb := &sandboxState{ + Sandbox: models.Sandbox{ + ID: sandboxID, + Status: models.StatusRunning, + Template: template, + VCPUs: vcpus, + MemoryMB: memoryMB, + TimeoutSec: timeoutSec, + SlotIndex: slotIdx, + HostIP: slot.HostIP, + RootfsPath: rootfsPath, + CreatedAt: now, + LastActiveAt: now, + }, + slot: slot, + client: client, + } + + m.mu.Lock() + m.boxes[sandboxID] = sb + m.mu.Unlock() + + slog.Info("sandbox created", + "id", sandboxID, + "template", template, + "host_ip", slot.HostIP.String(), + ) + + return &sb.Sandbox, nil +} + +// Destroy stops and cleans up a sandbox. +func (m *Manager) Destroy(ctx context.Context, sandboxID string) error { + m.mu.Lock() + sb, ok := m.boxes[sandboxID] + if !ok { + m.mu.Unlock() + return fmt.Errorf("sandbox not found: %s", sandboxID) + } + delete(m.boxes, sandboxID) + m.mu.Unlock() + + m.cleanup(ctx, sb) + + slog.Info("sandbox destroyed", "id", sandboxID) + return nil +} + +// cleanup tears down all resources for a sandbox. +func (m *Manager) cleanup(ctx context.Context, sb *sandboxState) { + if err := m.vm.Destroy(ctx, sb.ID); err != nil { + slog.Warn("vm destroy error", "id", sb.ID, "error", err) + } + if err := network.RemoveNetwork(sb.slot); err != nil { + slog.Warn("network cleanup error", "id", sb.ID, "error", err) + } + m.slots.Release(sb.SlotIndex) + os.Remove(sb.RootfsPath) +} + +// Pause pauses a running sandbox. +func (m *Manager) Pause(ctx context.Context, sandboxID string) error { + sb, err := m.get(sandboxID) + if err != nil { + return err + } + + if sb.Status != models.StatusRunning { + return fmt.Errorf("sandbox %s is not running (status: %s)", sandboxID, sb.Status) + } + + if err := m.vm.Pause(ctx, sandboxID); err != nil { + return fmt.Errorf("pause VM: %w", err) + } + + m.mu.Lock() + sb.Status = models.StatusPaused + m.mu.Unlock() + + slog.Info("sandbox paused", "id", sandboxID) + return nil +} + +// Resume resumes a paused sandbox. +func (m *Manager) Resume(ctx context.Context, sandboxID string) error { + sb, err := m.get(sandboxID) + if err != nil { + return err + } + + if sb.Status != models.StatusPaused { + return fmt.Errorf("sandbox %s is not paused (status: %s)", sandboxID, sb.Status) + } + + if err := m.vm.Resume(ctx, sandboxID); err != nil { + return fmt.Errorf("resume VM: %w", err) + } + + m.mu.Lock() + sb.Status = models.StatusRunning + sb.LastActiveAt = time.Now() + m.mu.Unlock() + + slog.Info("sandbox resumed", "id", sandboxID) + return nil +} + +// Exec runs a command inside a sandbox. +func (m *Manager) Exec(ctx context.Context, sandboxID string, cmd string, args ...string) (*envdclient.ExecResult, error) { + sb, err := m.get(sandboxID) + if err != nil { + return nil, err + } + + if sb.Status != models.StatusRunning { + return nil, fmt.Errorf("sandbox %s is not running (status: %s)", sandboxID, sb.Status) + } + + m.mu.Lock() + sb.LastActiveAt = time.Now() + m.mu.Unlock() + + return sb.client.Exec(ctx, cmd, args...) +} + +// List returns all sandboxes. +func (m *Manager) List() []models.Sandbox { + m.mu.RLock() + defer m.mu.RUnlock() + + result := make([]models.Sandbox, 0, len(m.boxes)) + for _, sb := range m.boxes { + result = append(result, sb.Sandbox) + } + return result +} + +// Get returns a sandbox by ID. +func (m *Manager) Get(sandboxID string) (*models.Sandbox, error) { + sb, err := m.get(sandboxID) + if err != nil { + return nil, err + } + return &sb.Sandbox, nil +} + +func (m *Manager) get(sandboxID string) (*sandboxState, error) { + m.mu.RLock() + defer m.mu.RUnlock() + + sb, ok := m.boxes[sandboxID] + if !ok { + return nil, fmt.Errorf("sandbox not found: %s", sandboxID) + } + return sb, nil +} + +// StartTTLReaper starts a background goroutine that destroys sandboxes +// that have exceeded their TTL (timeout_sec of inactivity). +func (m *Manager) StartTTLReaper(ctx context.Context) { + go func() { + ticker := time.NewTicker(10 * time.Second) + defer ticker.Stop() + + for { + select { + case <-ctx.Done(): + return + case <-m.stopCh: + return + case <-ticker.C: + m.reapExpired(ctx) + } + } + }() +} + +func (m *Manager) reapExpired(ctx context.Context) { + m.mu.RLock() + var expired []string + now := time.Now() + for id, sb := range m.boxes { + if sb.TimeoutSec <= 0 { + continue + } + if sb.Status != models.StatusRunning && sb.Status != models.StatusPaused { + continue + } + if now.Sub(sb.LastActiveAt) > time.Duration(sb.TimeoutSec)*time.Second { + expired = append(expired, id) + } + } + m.mu.RUnlock() + + for _, id := range expired { + slog.Info("TTL expired, destroying sandbox", "id", id) + if err := m.Destroy(ctx, id); err != nil { + slog.Warn("TTL reap failed", "id", id, "error", err) + } + } +} + +// Shutdown destroys all sandboxes and stops the TTL reaper. +func (m *Manager) Shutdown(ctx context.Context) { + close(m.stopCh) + + m.mu.Lock() + ids := make([]string, 0, len(m.boxes)) + for id := range m.boxes { + ids = append(ids, id) + } + m.mu.Unlock() + + for _, sbID := range ids { + slog.Info("shutdown: destroying sandbox", "id", sbID) + if err := m.Destroy(ctx, sbID); err != nil { + slog.Warn("shutdown destroy failed", "id", sbID, "error", err) + } + } +} diff --git a/internal/vm/jailer.go b/internal/vm/jailer.go index 6def11f..e528540 100644 --- a/internal/vm/jailer.go +++ b/internal/vm/jailer.go @@ -30,7 +30,10 @@ type process struct { // 5. ip netns exec : enters the network namespace where TAP is configured // 6. exec firecracker with the API socket path func startProcess(ctx context.Context, cfg *VMConfig) (*process, error) { - execCtx, cancel := context.WithCancel(ctx) + // Use a background context for the long-lived Firecracker process. + // The request context (ctx) is only used for the startup phase — we must + // not tie the VM's lifetime to the HTTP request that created it. + execCtx, cancel := context.WithCancel(context.Background()) script := buildStartScript(cfg) diff --git a/proto/hostagent/buf.gen.yaml b/proto/hostagent/buf.gen.yaml new file mode 100644 index 0000000..acba972 --- /dev/null +++ b/proto/hostagent/buf.gen.yaml @@ -0,0 +1,13 @@ +version: v2 +plugins: + - protoc_builtin: go + out: gen + opt: paths=source_relative + - local: protoc-gen-connect-go + out: gen + opt: paths=source_relative +managed: + enabled: true + override: + - file_option: go_package_prefix + value: git.omukk.dev/wrenn/sandbox/proto/hostagent/gen diff --git a/proto/hostagent/buf.yaml b/proto/hostagent/buf.yaml new file mode 100644 index 0000000..b869981 --- /dev/null +++ b/proto/hostagent/buf.yaml @@ -0,0 +1,3 @@ +version: v2 +modules: + - path: . diff --git a/proto/hostagent/gen/hostagent.pb.go b/proto/hostagent/gen/hostagent.pb.go new file mode 100644 index 0000000..0907329 --- /dev/null +++ b/proto/hostagent/gen/hostagent.pb.go @@ -0,0 +1,848 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: hostagent.proto + +package hostagentv1 + +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 CreateSandboxRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Template name (e.g., "minimal", "python311"). Determines base rootfs. + Template string `protobuf:"bytes,1,opt,name=template,proto3" json:"template,omitempty"` + // Number of virtual CPUs (default: 1). + Vcpus int32 `protobuf:"varint,2,opt,name=vcpus,proto3" json:"vcpus,omitempty"` + // Memory in MB (default: 512). + MemoryMb int32 `protobuf:"varint,3,opt,name=memory_mb,json=memoryMb,proto3" json:"memory_mb,omitempty"` + // TTL in seconds. Sandbox is auto-destroyed after this duration of + // inactivity. 0 means no auto-destroy. + TimeoutSec int32 `protobuf:"varint,4,opt,name=timeout_sec,json=timeoutSec,proto3" json:"timeout_sec,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreateSandboxRequest) Reset() { + *x = CreateSandboxRequest{} + mi := &file_hostagent_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateSandboxRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateSandboxRequest) ProtoMessage() {} + +func (x *CreateSandboxRequest) ProtoReflect() protoreflect.Message { + mi := &file_hostagent_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 CreateSandboxRequest.ProtoReflect.Descriptor instead. +func (*CreateSandboxRequest) Descriptor() ([]byte, []int) { + return file_hostagent_proto_rawDescGZIP(), []int{0} +} + +func (x *CreateSandboxRequest) GetTemplate() string { + if x != nil { + return x.Template + } + return "" +} + +func (x *CreateSandboxRequest) GetVcpus() int32 { + if x != nil { + return x.Vcpus + } + return 0 +} + +func (x *CreateSandboxRequest) GetMemoryMb() int32 { + if x != nil { + return x.MemoryMb + } + return 0 +} + +func (x *CreateSandboxRequest) GetTimeoutSec() int32 { + if x != nil { + return x.TimeoutSec + } + return 0 +} + +type CreateSandboxResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + SandboxId string `protobuf:"bytes,1,opt,name=sandbox_id,json=sandboxId,proto3" json:"sandbox_id,omitempty"` + Status string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"` + HostIp string `protobuf:"bytes,3,opt,name=host_ip,json=hostIp,proto3" json:"host_ip,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreateSandboxResponse) Reset() { + *x = CreateSandboxResponse{} + mi := &file_hostagent_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateSandboxResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateSandboxResponse) ProtoMessage() {} + +func (x *CreateSandboxResponse) ProtoReflect() protoreflect.Message { + mi := &file_hostagent_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 CreateSandboxResponse.ProtoReflect.Descriptor instead. +func (*CreateSandboxResponse) Descriptor() ([]byte, []int) { + return file_hostagent_proto_rawDescGZIP(), []int{1} +} + +func (x *CreateSandboxResponse) GetSandboxId() string { + if x != nil { + return x.SandboxId + } + return "" +} + +func (x *CreateSandboxResponse) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *CreateSandboxResponse) GetHostIp() string { + if x != nil { + return x.HostIp + } + return "" +} + +type DestroySandboxRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + SandboxId string `protobuf:"bytes,1,opt,name=sandbox_id,json=sandboxId,proto3" json:"sandbox_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DestroySandboxRequest) Reset() { + *x = DestroySandboxRequest{} + mi := &file_hostagent_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DestroySandboxRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DestroySandboxRequest) ProtoMessage() {} + +func (x *DestroySandboxRequest) ProtoReflect() protoreflect.Message { + mi := &file_hostagent_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 DestroySandboxRequest.ProtoReflect.Descriptor instead. +func (*DestroySandboxRequest) Descriptor() ([]byte, []int) { + return file_hostagent_proto_rawDescGZIP(), []int{2} +} + +func (x *DestroySandboxRequest) GetSandboxId() string { + if x != nil { + return x.SandboxId + } + return "" +} + +type DestroySandboxResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DestroySandboxResponse) Reset() { + *x = DestroySandboxResponse{} + mi := &file_hostagent_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DestroySandboxResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DestroySandboxResponse) ProtoMessage() {} + +func (x *DestroySandboxResponse) ProtoReflect() protoreflect.Message { + mi := &file_hostagent_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 DestroySandboxResponse.ProtoReflect.Descriptor instead. +func (*DestroySandboxResponse) Descriptor() ([]byte, []int) { + return file_hostagent_proto_rawDescGZIP(), []int{3} +} + +type PauseSandboxRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + SandboxId string `protobuf:"bytes,1,opt,name=sandbox_id,json=sandboxId,proto3" json:"sandbox_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PauseSandboxRequest) Reset() { + *x = PauseSandboxRequest{} + mi := &file_hostagent_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PauseSandboxRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PauseSandboxRequest) ProtoMessage() {} + +func (x *PauseSandboxRequest) ProtoReflect() protoreflect.Message { + mi := &file_hostagent_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 PauseSandboxRequest.ProtoReflect.Descriptor instead. +func (*PauseSandboxRequest) Descriptor() ([]byte, []int) { + return file_hostagent_proto_rawDescGZIP(), []int{4} +} + +func (x *PauseSandboxRequest) GetSandboxId() string { + if x != nil { + return x.SandboxId + } + return "" +} + +type PauseSandboxResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *PauseSandboxResponse) Reset() { + *x = PauseSandboxResponse{} + mi := &file_hostagent_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PauseSandboxResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PauseSandboxResponse) ProtoMessage() {} + +func (x *PauseSandboxResponse) ProtoReflect() protoreflect.Message { + mi := &file_hostagent_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 PauseSandboxResponse.ProtoReflect.Descriptor instead. +func (*PauseSandboxResponse) Descriptor() ([]byte, []int) { + return file_hostagent_proto_rawDescGZIP(), []int{5} +} + +type ResumeSandboxRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + SandboxId string `protobuf:"bytes,1,opt,name=sandbox_id,json=sandboxId,proto3" json:"sandbox_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResumeSandboxRequest) Reset() { + *x = ResumeSandboxRequest{} + mi := &file_hostagent_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResumeSandboxRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResumeSandboxRequest) ProtoMessage() {} + +func (x *ResumeSandboxRequest) ProtoReflect() protoreflect.Message { + mi := &file_hostagent_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 ResumeSandboxRequest.ProtoReflect.Descriptor instead. +func (*ResumeSandboxRequest) Descriptor() ([]byte, []int) { + return file_hostagent_proto_rawDescGZIP(), []int{6} +} + +func (x *ResumeSandboxRequest) GetSandboxId() string { + if x != nil { + return x.SandboxId + } + return "" +} + +type ResumeSandboxResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ResumeSandboxResponse) Reset() { + *x = ResumeSandboxResponse{} + mi := &file_hostagent_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ResumeSandboxResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResumeSandboxResponse) ProtoMessage() {} + +func (x *ResumeSandboxResponse) ProtoReflect() protoreflect.Message { + mi := &file_hostagent_proto_msgTypes[7] + 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 ResumeSandboxResponse.ProtoReflect.Descriptor instead. +func (*ResumeSandboxResponse) Descriptor() ([]byte, []int) { + return file_hostagent_proto_rawDescGZIP(), []int{7} +} + +type ExecRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + SandboxId string `protobuf:"bytes,1,opt,name=sandbox_id,json=sandboxId,proto3" json:"sandbox_id,omitempty"` + Cmd string `protobuf:"bytes,2,opt,name=cmd,proto3" json:"cmd,omitempty"` + Args []string `protobuf:"bytes,3,rep,name=args,proto3" json:"args,omitempty"` + // Timeout for the command in seconds (default: 30). + TimeoutSec int32 `protobuf:"varint,4,opt,name=timeout_sec,json=timeoutSec,proto3" json:"timeout_sec,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ExecRequest) Reset() { + *x = ExecRequest{} + mi := &file_hostagent_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ExecRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExecRequest) ProtoMessage() {} + +func (x *ExecRequest) ProtoReflect() protoreflect.Message { + mi := &file_hostagent_proto_msgTypes[8] + 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 ExecRequest.ProtoReflect.Descriptor instead. +func (*ExecRequest) Descriptor() ([]byte, []int) { + return file_hostagent_proto_rawDescGZIP(), []int{8} +} + +func (x *ExecRequest) GetSandboxId() string { + if x != nil { + return x.SandboxId + } + return "" +} + +func (x *ExecRequest) GetCmd() string { + if x != nil { + return x.Cmd + } + return "" +} + +func (x *ExecRequest) GetArgs() []string { + if x != nil { + return x.Args + } + return nil +} + +func (x *ExecRequest) GetTimeoutSec() int32 { + if x != nil { + return x.TimeoutSec + } + return 0 +} + +type ExecResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Stdout []byte `protobuf:"bytes,1,opt,name=stdout,proto3" json:"stdout,omitempty"` + Stderr []byte `protobuf:"bytes,2,opt,name=stderr,proto3" json:"stderr,omitempty"` + ExitCode int32 `protobuf:"varint,3,opt,name=exit_code,json=exitCode,proto3" json:"exit_code,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ExecResponse) Reset() { + *x = ExecResponse{} + mi := &file_hostagent_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ExecResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExecResponse) ProtoMessage() {} + +func (x *ExecResponse) ProtoReflect() protoreflect.Message { + mi := &file_hostagent_proto_msgTypes[9] + 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 ExecResponse.ProtoReflect.Descriptor instead. +func (*ExecResponse) Descriptor() ([]byte, []int) { + return file_hostagent_proto_rawDescGZIP(), []int{9} +} + +func (x *ExecResponse) GetStdout() []byte { + if x != nil { + return x.Stdout + } + return nil +} + +func (x *ExecResponse) GetStderr() []byte { + if x != nil { + return x.Stderr + } + return nil +} + +func (x *ExecResponse) GetExitCode() int32 { + if x != nil { + return x.ExitCode + } + return 0 +} + +type ListSandboxesRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListSandboxesRequest) Reset() { + *x = ListSandboxesRequest{} + mi := &file_hostagent_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListSandboxesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListSandboxesRequest) ProtoMessage() {} + +func (x *ListSandboxesRequest) ProtoReflect() protoreflect.Message { + mi := &file_hostagent_proto_msgTypes[10] + 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 ListSandboxesRequest.ProtoReflect.Descriptor instead. +func (*ListSandboxesRequest) Descriptor() ([]byte, []int) { + return file_hostagent_proto_rawDescGZIP(), []int{10} +} + +type ListSandboxesResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Sandboxes []*SandboxInfo `protobuf:"bytes,1,rep,name=sandboxes,proto3" json:"sandboxes,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListSandboxesResponse) Reset() { + *x = ListSandboxesResponse{} + mi := &file_hostagent_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListSandboxesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListSandboxesResponse) ProtoMessage() {} + +func (x *ListSandboxesResponse) ProtoReflect() protoreflect.Message { + mi := &file_hostagent_proto_msgTypes[11] + 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 ListSandboxesResponse.ProtoReflect.Descriptor instead. +func (*ListSandboxesResponse) Descriptor() ([]byte, []int) { + return file_hostagent_proto_rawDescGZIP(), []int{11} +} + +func (x *ListSandboxesResponse) GetSandboxes() []*SandboxInfo { + if x != nil { + return x.Sandboxes + } + return nil +} + +type SandboxInfo struct { + state protoimpl.MessageState `protogen:"open.v1"` + SandboxId string `protobuf:"bytes,1,opt,name=sandbox_id,json=sandboxId,proto3" json:"sandbox_id,omitempty"` + Status string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"` + Template string `protobuf:"bytes,3,opt,name=template,proto3" json:"template,omitempty"` + Vcpus int32 `protobuf:"varint,4,opt,name=vcpus,proto3" json:"vcpus,omitempty"` + MemoryMb int32 `protobuf:"varint,5,opt,name=memory_mb,json=memoryMb,proto3" json:"memory_mb,omitempty"` + HostIp string `protobuf:"bytes,6,opt,name=host_ip,json=hostIp,proto3" json:"host_ip,omitempty"` + CreatedAtUnix int64 `protobuf:"varint,7,opt,name=created_at_unix,json=createdAtUnix,proto3" json:"created_at_unix,omitempty"` + LastActiveAtUnix int64 `protobuf:"varint,8,opt,name=last_active_at_unix,json=lastActiveAtUnix,proto3" json:"last_active_at_unix,omitempty"` + TimeoutSec int32 `protobuf:"varint,9,opt,name=timeout_sec,json=timeoutSec,proto3" json:"timeout_sec,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SandboxInfo) Reset() { + *x = SandboxInfo{} + mi := &file_hostagent_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SandboxInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SandboxInfo) ProtoMessage() {} + +func (x *SandboxInfo) ProtoReflect() protoreflect.Message { + mi := &file_hostagent_proto_msgTypes[12] + 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 SandboxInfo.ProtoReflect.Descriptor instead. +func (*SandboxInfo) Descriptor() ([]byte, []int) { + return file_hostagent_proto_rawDescGZIP(), []int{12} +} + +func (x *SandboxInfo) GetSandboxId() string { + if x != nil { + return x.SandboxId + } + return "" +} + +func (x *SandboxInfo) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *SandboxInfo) GetTemplate() string { + if x != nil { + return x.Template + } + return "" +} + +func (x *SandboxInfo) GetVcpus() int32 { + if x != nil { + return x.Vcpus + } + return 0 +} + +func (x *SandboxInfo) GetMemoryMb() int32 { + if x != nil { + return x.MemoryMb + } + return 0 +} + +func (x *SandboxInfo) GetHostIp() string { + if x != nil { + return x.HostIp + } + return "" +} + +func (x *SandboxInfo) GetCreatedAtUnix() int64 { + if x != nil { + return x.CreatedAtUnix + } + return 0 +} + +func (x *SandboxInfo) GetLastActiveAtUnix() int64 { + if x != nil { + return x.LastActiveAtUnix + } + return 0 +} + +func (x *SandboxInfo) GetTimeoutSec() int32 { + if x != nil { + return x.TimeoutSec + } + return 0 +} + +var File_hostagent_proto protoreflect.FileDescriptor + +const file_hostagent_proto_rawDesc = "" + + "\n" + + "\x0fhostagent.proto\x12\fhostagent.v1\"\x86\x01\n" + + "\x14CreateSandboxRequest\x12\x1a\n" + + "\btemplate\x18\x01 \x01(\tR\btemplate\x12\x14\n" + + "\x05vcpus\x18\x02 \x01(\x05R\x05vcpus\x12\x1b\n" + + "\tmemory_mb\x18\x03 \x01(\x05R\bmemoryMb\x12\x1f\n" + + "\vtimeout_sec\x18\x04 \x01(\x05R\n" + + "timeoutSec\"g\n" + + "\x15CreateSandboxResponse\x12\x1d\n" + + "\n" + + "sandbox_id\x18\x01 \x01(\tR\tsandboxId\x12\x16\n" + + "\x06status\x18\x02 \x01(\tR\x06status\x12\x17\n" + + "\ahost_ip\x18\x03 \x01(\tR\x06hostIp\"6\n" + + "\x15DestroySandboxRequest\x12\x1d\n" + + "\n" + + "sandbox_id\x18\x01 \x01(\tR\tsandboxId\"\x18\n" + + "\x16DestroySandboxResponse\"4\n" + + "\x13PauseSandboxRequest\x12\x1d\n" + + "\n" + + "sandbox_id\x18\x01 \x01(\tR\tsandboxId\"\x16\n" + + "\x14PauseSandboxResponse\"5\n" + + "\x14ResumeSandboxRequest\x12\x1d\n" + + "\n" + + "sandbox_id\x18\x01 \x01(\tR\tsandboxId\"\x17\n" + + "\x15ResumeSandboxResponse\"s\n" + + "\vExecRequest\x12\x1d\n" + + "\n" + + "sandbox_id\x18\x01 \x01(\tR\tsandboxId\x12\x10\n" + + "\x03cmd\x18\x02 \x01(\tR\x03cmd\x12\x12\n" + + "\x04args\x18\x03 \x03(\tR\x04args\x12\x1f\n" + + "\vtimeout_sec\x18\x04 \x01(\x05R\n" + + "timeoutSec\"[\n" + + "\fExecResponse\x12\x16\n" + + "\x06stdout\x18\x01 \x01(\fR\x06stdout\x12\x16\n" + + "\x06stderr\x18\x02 \x01(\fR\x06stderr\x12\x1b\n" + + "\texit_code\x18\x03 \x01(\x05R\bexitCode\"\x16\n" + + "\x14ListSandboxesRequest\"P\n" + + "\x15ListSandboxesResponse\x127\n" + + "\tsandboxes\x18\x01 \x03(\v2\x19.hostagent.v1.SandboxInfoR\tsandboxes\"\xa4\x02\n" + + "\vSandboxInfo\x12\x1d\n" + + "\n" + + "sandbox_id\x18\x01 \x01(\tR\tsandboxId\x12\x16\n" + + "\x06status\x18\x02 \x01(\tR\x06status\x12\x1a\n" + + "\btemplate\x18\x03 \x01(\tR\btemplate\x12\x14\n" + + "\x05vcpus\x18\x04 \x01(\x05R\x05vcpus\x12\x1b\n" + + "\tmemory_mb\x18\x05 \x01(\x05R\bmemoryMb\x12\x17\n" + + "\ahost_ip\x18\x06 \x01(\tR\x06hostIp\x12&\n" + + "\x0fcreated_at_unix\x18\a \x01(\x03R\rcreatedAtUnix\x12-\n" + + "\x13last_active_at_unix\x18\b \x01(\x03R\x10lastActiveAtUnix\x12\x1f\n" + + "\vtimeout_sec\x18\t \x01(\x05R\n" + + "timeoutSec2\x93\x04\n" + + "\x10HostAgentService\x12X\n" + + "\rCreateSandbox\x12\".hostagent.v1.CreateSandboxRequest\x1a#.hostagent.v1.CreateSandboxResponse\x12[\n" + + "\x0eDestroySandbox\x12#.hostagent.v1.DestroySandboxRequest\x1a$.hostagent.v1.DestroySandboxResponse\x12U\n" + + "\fPauseSandbox\x12!.hostagent.v1.PauseSandboxRequest\x1a\".hostagent.v1.PauseSandboxResponse\x12X\n" + + "\rResumeSandbox\x12\".hostagent.v1.ResumeSandboxRequest\x1a#.hostagent.v1.ResumeSandboxResponse\x12=\n" + + "\x04Exec\x12\x19.hostagent.v1.ExecRequest\x1a\x1a.hostagent.v1.ExecResponse\x12X\n" + + "\rListSandboxes\x12\".hostagent.v1.ListSandboxesRequest\x1a#.hostagent.v1.ListSandboxesResponseB\xb0\x01\n" + + "\x10com.hostagent.v1B\x0eHostagentProtoP\x01Z;git.omukk.dev/wrenn/sandbox/proto/hostagent/gen;hostagentv1\xa2\x02\x03HXX\xaa\x02\fHostagent.V1\xca\x02\fHostagent\\V1\xe2\x02\x18Hostagent\\V1\\GPBMetadata\xea\x02\rHostagent::V1b\x06proto3" + +var ( + file_hostagent_proto_rawDescOnce sync.Once + file_hostagent_proto_rawDescData []byte +) + +func file_hostagent_proto_rawDescGZIP() []byte { + file_hostagent_proto_rawDescOnce.Do(func() { + file_hostagent_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_hostagent_proto_rawDesc), len(file_hostagent_proto_rawDesc))) + }) + return file_hostagent_proto_rawDescData +} + +var file_hostagent_proto_msgTypes = make([]protoimpl.MessageInfo, 13) +var file_hostagent_proto_goTypes = []any{ + (*CreateSandboxRequest)(nil), // 0: hostagent.v1.CreateSandboxRequest + (*CreateSandboxResponse)(nil), // 1: hostagent.v1.CreateSandboxResponse + (*DestroySandboxRequest)(nil), // 2: hostagent.v1.DestroySandboxRequest + (*DestroySandboxResponse)(nil), // 3: hostagent.v1.DestroySandboxResponse + (*PauseSandboxRequest)(nil), // 4: hostagent.v1.PauseSandboxRequest + (*PauseSandboxResponse)(nil), // 5: hostagent.v1.PauseSandboxResponse + (*ResumeSandboxRequest)(nil), // 6: hostagent.v1.ResumeSandboxRequest + (*ResumeSandboxResponse)(nil), // 7: hostagent.v1.ResumeSandboxResponse + (*ExecRequest)(nil), // 8: hostagent.v1.ExecRequest + (*ExecResponse)(nil), // 9: hostagent.v1.ExecResponse + (*ListSandboxesRequest)(nil), // 10: hostagent.v1.ListSandboxesRequest + (*ListSandboxesResponse)(nil), // 11: hostagent.v1.ListSandboxesResponse + (*SandboxInfo)(nil), // 12: hostagent.v1.SandboxInfo +} +var file_hostagent_proto_depIdxs = []int32{ + 12, // 0: hostagent.v1.ListSandboxesResponse.sandboxes:type_name -> hostagent.v1.SandboxInfo + 0, // 1: hostagent.v1.HostAgentService.CreateSandbox:input_type -> hostagent.v1.CreateSandboxRequest + 2, // 2: hostagent.v1.HostAgentService.DestroySandbox:input_type -> hostagent.v1.DestroySandboxRequest + 4, // 3: hostagent.v1.HostAgentService.PauseSandbox:input_type -> hostagent.v1.PauseSandboxRequest + 6, // 4: hostagent.v1.HostAgentService.ResumeSandbox:input_type -> hostagent.v1.ResumeSandboxRequest + 8, // 5: hostagent.v1.HostAgentService.Exec:input_type -> hostagent.v1.ExecRequest + 10, // 6: hostagent.v1.HostAgentService.ListSandboxes:input_type -> hostagent.v1.ListSandboxesRequest + 1, // 7: hostagent.v1.HostAgentService.CreateSandbox:output_type -> hostagent.v1.CreateSandboxResponse + 3, // 8: hostagent.v1.HostAgentService.DestroySandbox:output_type -> hostagent.v1.DestroySandboxResponse + 5, // 9: hostagent.v1.HostAgentService.PauseSandbox:output_type -> hostagent.v1.PauseSandboxResponse + 7, // 10: hostagent.v1.HostAgentService.ResumeSandbox:output_type -> hostagent.v1.ResumeSandboxResponse + 9, // 11: hostagent.v1.HostAgentService.Exec:output_type -> hostagent.v1.ExecResponse + 11, // 12: hostagent.v1.HostAgentService.ListSandboxes:output_type -> hostagent.v1.ListSandboxesResponse + 7, // [7:13] is the sub-list for method output_type + 1, // [1:7] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_hostagent_proto_init() } +func file_hostagent_proto_init() { + if File_hostagent_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_hostagent_proto_rawDesc), len(file_hostagent_proto_rawDesc)), + NumEnums: 0, + NumMessages: 13, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_hostagent_proto_goTypes, + DependencyIndexes: file_hostagent_proto_depIdxs, + MessageInfos: file_hostagent_proto_msgTypes, + }.Build() + File_hostagent_proto = out.File + file_hostagent_proto_goTypes = nil + file_hostagent_proto_depIdxs = nil +} diff --git a/proto/hostagent/gen/hostagentv1connect/hostagent.connect.go b/proto/hostagent/gen/hostagentv1connect/hostagent.connect.go new file mode 100644 index 0000000..5a14275 --- /dev/null +++ b/proto/hostagent/gen/hostagentv1connect/hostagent.connect.go @@ -0,0 +1,265 @@ +// Code generated by protoc-gen-connect-go. DO NOT EDIT. +// +// Source: hostagent.proto + +package hostagentv1connect + +import ( + connect "connectrpc.com/connect" + context "context" + errors "errors" + gen "git.omukk.dev/wrenn/sandbox/proto/hostagent/gen" + http "net/http" + strings "strings" +) + +// This is a compile-time assertion to ensure that this generated file and the connect package are +// compatible. If you get a compiler error that this constant is not defined, this code was +// generated with a version of connect newer than the one compiled into your binary. You can fix the +// problem by either regenerating this code with an older version of connect or updating the connect +// version compiled into your binary. +const _ = connect.IsAtLeastVersion1_13_0 + +const ( + // HostAgentServiceName is the fully-qualified name of the HostAgentService service. + HostAgentServiceName = "hostagent.v1.HostAgentService" +) + +// These constants are the fully-qualified names of the RPCs defined in this package. They're +// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route. +// +// Note that these are different from the fully-qualified method names used by +// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to +// reflection-formatted method names, remove the leading slash and convert the remaining slash to a +// period. +const ( + // HostAgentServiceCreateSandboxProcedure is the fully-qualified name of the HostAgentService's + // CreateSandbox RPC. + HostAgentServiceCreateSandboxProcedure = "/hostagent.v1.HostAgentService/CreateSandbox" + // HostAgentServiceDestroySandboxProcedure is the fully-qualified name of the HostAgentService's + // DestroySandbox RPC. + HostAgentServiceDestroySandboxProcedure = "/hostagent.v1.HostAgentService/DestroySandbox" + // HostAgentServicePauseSandboxProcedure is the fully-qualified name of the HostAgentService's + // PauseSandbox RPC. + HostAgentServicePauseSandboxProcedure = "/hostagent.v1.HostAgentService/PauseSandbox" + // HostAgentServiceResumeSandboxProcedure is the fully-qualified name of the HostAgentService's + // ResumeSandbox RPC. + HostAgentServiceResumeSandboxProcedure = "/hostagent.v1.HostAgentService/ResumeSandbox" + // HostAgentServiceExecProcedure is the fully-qualified name of the HostAgentService's Exec RPC. + HostAgentServiceExecProcedure = "/hostagent.v1.HostAgentService/Exec" + // HostAgentServiceListSandboxesProcedure is the fully-qualified name of the HostAgentService's + // ListSandboxes RPC. + HostAgentServiceListSandboxesProcedure = "/hostagent.v1.HostAgentService/ListSandboxes" +) + +// HostAgentServiceClient is a client for the hostagent.v1.HostAgentService service. +type HostAgentServiceClient interface { + // CreateSandbox boots a new microVM with the given configuration. + CreateSandbox(context.Context, *connect.Request[gen.CreateSandboxRequest]) (*connect.Response[gen.CreateSandboxResponse], error) + // DestroySandbox stops and cleans up a sandbox (VM, network, rootfs). + DestroySandbox(context.Context, *connect.Request[gen.DestroySandboxRequest]) (*connect.Response[gen.DestroySandboxResponse], error) + // PauseSandbox pauses a running sandbox's VM. + PauseSandbox(context.Context, *connect.Request[gen.PauseSandboxRequest]) (*connect.Response[gen.PauseSandboxResponse], error) + // ResumeSandbox resumes a paused sandbox's VM. + ResumeSandbox(context.Context, *connect.Request[gen.ResumeSandboxRequest]) (*connect.Response[gen.ResumeSandboxResponse], error) + // Exec runs a command inside a sandbox and returns the collected output. + Exec(context.Context, *connect.Request[gen.ExecRequest]) (*connect.Response[gen.ExecResponse], error) + // ListSandboxes returns all sandboxes managed by this host agent. + ListSandboxes(context.Context, *connect.Request[gen.ListSandboxesRequest]) (*connect.Response[gen.ListSandboxesResponse], error) +} + +// NewHostAgentServiceClient constructs a client for the hostagent.v1.HostAgentService service. By +// default, it uses the Connect protocol with the binary Protobuf Codec, asks for gzipped responses, +// and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the +// connect.WithGRPC() or connect.WithGRPCWeb() options. +// +// The URL supplied here should be the base URL for the Connect or gRPC server (for example, +// http://api.acme.com or https://acme.com/grpc). +func NewHostAgentServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) HostAgentServiceClient { + baseURL = strings.TrimRight(baseURL, "/") + hostAgentServiceMethods := gen.File_hostagent_proto.Services().ByName("HostAgentService").Methods() + return &hostAgentServiceClient{ + createSandbox: connect.NewClient[gen.CreateSandboxRequest, gen.CreateSandboxResponse]( + httpClient, + baseURL+HostAgentServiceCreateSandboxProcedure, + connect.WithSchema(hostAgentServiceMethods.ByName("CreateSandbox")), + connect.WithClientOptions(opts...), + ), + destroySandbox: connect.NewClient[gen.DestroySandboxRequest, gen.DestroySandboxResponse]( + httpClient, + baseURL+HostAgentServiceDestroySandboxProcedure, + connect.WithSchema(hostAgentServiceMethods.ByName("DestroySandbox")), + connect.WithClientOptions(opts...), + ), + pauseSandbox: connect.NewClient[gen.PauseSandboxRequest, gen.PauseSandboxResponse]( + httpClient, + baseURL+HostAgentServicePauseSandboxProcedure, + connect.WithSchema(hostAgentServiceMethods.ByName("PauseSandbox")), + connect.WithClientOptions(opts...), + ), + resumeSandbox: connect.NewClient[gen.ResumeSandboxRequest, gen.ResumeSandboxResponse]( + httpClient, + baseURL+HostAgentServiceResumeSandboxProcedure, + connect.WithSchema(hostAgentServiceMethods.ByName("ResumeSandbox")), + connect.WithClientOptions(opts...), + ), + exec: connect.NewClient[gen.ExecRequest, gen.ExecResponse]( + httpClient, + baseURL+HostAgentServiceExecProcedure, + connect.WithSchema(hostAgentServiceMethods.ByName("Exec")), + connect.WithClientOptions(opts...), + ), + listSandboxes: connect.NewClient[gen.ListSandboxesRequest, gen.ListSandboxesResponse]( + httpClient, + baseURL+HostAgentServiceListSandboxesProcedure, + connect.WithSchema(hostAgentServiceMethods.ByName("ListSandboxes")), + connect.WithClientOptions(opts...), + ), + } +} + +// hostAgentServiceClient implements HostAgentServiceClient. +type hostAgentServiceClient struct { + createSandbox *connect.Client[gen.CreateSandboxRequest, gen.CreateSandboxResponse] + destroySandbox *connect.Client[gen.DestroySandboxRequest, gen.DestroySandboxResponse] + pauseSandbox *connect.Client[gen.PauseSandboxRequest, gen.PauseSandboxResponse] + resumeSandbox *connect.Client[gen.ResumeSandboxRequest, gen.ResumeSandboxResponse] + exec *connect.Client[gen.ExecRequest, gen.ExecResponse] + listSandboxes *connect.Client[gen.ListSandboxesRequest, gen.ListSandboxesResponse] +} + +// CreateSandbox calls hostagent.v1.HostAgentService.CreateSandbox. +func (c *hostAgentServiceClient) CreateSandbox(ctx context.Context, req *connect.Request[gen.CreateSandboxRequest]) (*connect.Response[gen.CreateSandboxResponse], error) { + return c.createSandbox.CallUnary(ctx, req) +} + +// DestroySandbox calls hostagent.v1.HostAgentService.DestroySandbox. +func (c *hostAgentServiceClient) DestroySandbox(ctx context.Context, req *connect.Request[gen.DestroySandboxRequest]) (*connect.Response[gen.DestroySandboxResponse], error) { + return c.destroySandbox.CallUnary(ctx, req) +} + +// PauseSandbox calls hostagent.v1.HostAgentService.PauseSandbox. +func (c *hostAgentServiceClient) PauseSandbox(ctx context.Context, req *connect.Request[gen.PauseSandboxRequest]) (*connect.Response[gen.PauseSandboxResponse], error) { + return c.pauseSandbox.CallUnary(ctx, req) +} + +// ResumeSandbox calls hostagent.v1.HostAgentService.ResumeSandbox. +func (c *hostAgentServiceClient) ResumeSandbox(ctx context.Context, req *connect.Request[gen.ResumeSandboxRequest]) (*connect.Response[gen.ResumeSandboxResponse], error) { + return c.resumeSandbox.CallUnary(ctx, req) +} + +// Exec calls hostagent.v1.HostAgentService.Exec. +func (c *hostAgentServiceClient) Exec(ctx context.Context, req *connect.Request[gen.ExecRequest]) (*connect.Response[gen.ExecResponse], error) { + return c.exec.CallUnary(ctx, req) +} + +// ListSandboxes calls hostagent.v1.HostAgentService.ListSandboxes. +func (c *hostAgentServiceClient) ListSandboxes(ctx context.Context, req *connect.Request[gen.ListSandboxesRequest]) (*connect.Response[gen.ListSandboxesResponse], error) { + return c.listSandboxes.CallUnary(ctx, req) +} + +// HostAgentServiceHandler is an implementation of the hostagent.v1.HostAgentService service. +type HostAgentServiceHandler interface { + // CreateSandbox boots a new microVM with the given configuration. + CreateSandbox(context.Context, *connect.Request[gen.CreateSandboxRequest]) (*connect.Response[gen.CreateSandboxResponse], error) + // DestroySandbox stops and cleans up a sandbox (VM, network, rootfs). + DestroySandbox(context.Context, *connect.Request[gen.DestroySandboxRequest]) (*connect.Response[gen.DestroySandboxResponse], error) + // PauseSandbox pauses a running sandbox's VM. + PauseSandbox(context.Context, *connect.Request[gen.PauseSandboxRequest]) (*connect.Response[gen.PauseSandboxResponse], error) + // ResumeSandbox resumes a paused sandbox's VM. + ResumeSandbox(context.Context, *connect.Request[gen.ResumeSandboxRequest]) (*connect.Response[gen.ResumeSandboxResponse], error) + // Exec runs a command inside a sandbox and returns the collected output. + Exec(context.Context, *connect.Request[gen.ExecRequest]) (*connect.Response[gen.ExecResponse], error) + // ListSandboxes returns all sandboxes managed by this host agent. + ListSandboxes(context.Context, *connect.Request[gen.ListSandboxesRequest]) (*connect.Response[gen.ListSandboxesResponse], error) +} + +// NewHostAgentServiceHandler builds an HTTP handler from the service implementation. It returns the +// path on which to mount the handler and the handler itself. +// +// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf +// and JSON codecs. They also support gzip compression. +func NewHostAgentServiceHandler(svc HostAgentServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) { + hostAgentServiceMethods := gen.File_hostagent_proto.Services().ByName("HostAgentService").Methods() + hostAgentServiceCreateSandboxHandler := connect.NewUnaryHandler( + HostAgentServiceCreateSandboxProcedure, + svc.CreateSandbox, + connect.WithSchema(hostAgentServiceMethods.ByName("CreateSandbox")), + connect.WithHandlerOptions(opts...), + ) + hostAgentServiceDestroySandboxHandler := connect.NewUnaryHandler( + HostAgentServiceDestroySandboxProcedure, + svc.DestroySandbox, + connect.WithSchema(hostAgentServiceMethods.ByName("DestroySandbox")), + connect.WithHandlerOptions(opts...), + ) + hostAgentServicePauseSandboxHandler := connect.NewUnaryHandler( + HostAgentServicePauseSandboxProcedure, + svc.PauseSandbox, + connect.WithSchema(hostAgentServiceMethods.ByName("PauseSandbox")), + connect.WithHandlerOptions(opts...), + ) + hostAgentServiceResumeSandboxHandler := connect.NewUnaryHandler( + HostAgentServiceResumeSandboxProcedure, + svc.ResumeSandbox, + connect.WithSchema(hostAgentServiceMethods.ByName("ResumeSandbox")), + connect.WithHandlerOptions(opts...), + ) + hostAgentServiceExecHandler := connect.NewUnaryHandler( + HostAgentServiceExecProcedure, + svc.Exec, + connect.WithSchema(hostAgentServiceMethods.ByName("Exec")), + connect.WithHandlerOptions(opts...), + ) + hostAgentServiceListSandboxesHandler := connect.NewUnaryHandler( + HostAgentServiceListSandboxesProcedure, + svc.ListSandboxes, + connect.WithSchema(hostAgentServiceMethods.ByName("ListSandboxes")), + connect.WithHandlerOptions(opts...), + ) + return "/hostagent.v1.HostAgentService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case HostAgentServiceCreateSandboxProcedure: + hostAgentServiceCreateSandboxHandler.ServeHTTP(w, r) + case HostAgentServiceDestroySandboxProcedure: + hostAgentServiceDestroySandboxHandler.ServeHTTP(w, r) + case HostAgentServicePauseSandboxProcedure: + hostAgentServicePauseSandboxHandler.ServeHTTP(w, r) + case HostAgentServiceResumeSandboxProcedure: + hostAgentServiceResumeSandboxHandler.ServeHTTP(w, r) + case HostAgentServiceExecProcedure: + hostAgentServiceExecHandler.ServeHTTP(w, r) + case HostAgentServiceListSandboxesProcedure: + hostAgentServiceListSandboxesHandler.ServeHTTP(w, r) + default: + http.NotFound(w, r) + } + }) +} + +// UnimplementedHostAgentServiceHandler returns CodeUnimplemented from all methods. +type UnimplementedHostAgentServiceHandler struct{} + +func (UnimplementedHostAgentServiceHandler) CreateSandbox(context.Context, *connect.Request[gen.CreateSandboxRequest]) (*connect.Response[gen.CreateSandboxResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("hostagent.v1.HostAgentService.CreateSandbox is not implemented")) +} + +func (UnimplementedHostAgentServiceHandler) DestroySandbox(context.Context, *connect.Request[gen.DestroySandboxRequest]) (*connect.Response[gen.DestroySandboxResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("hostagent.v1.HostAgentService.DestroySandbox is not implemented")) +} + +func (UnimplementedHostAgentServiceHandler) PauseSandbox(context.Context, *connect.Request[gen.PauseSandboxRequest]) (*connect.Response[gen.PauseSandboxResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("hostagent.v1.HostAgentService.PauseSandbox is not implemented")) +} + +func (UnimplementedHostAgentServiceHandler) ResumeSandbox(context.Context, *connect.Request[gen.ResumeSandboxRequest]) (*connect.Response[gen.ResumeSandboxResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("hostagent.v1.HostAgentService.ResumeSandbox is not implemented")) +} + +func (UnimplementedHostAgentServiceHandler) Exec(context.Context, *connect.Request[gen.ExecRequest]) (*connect.Response[gen.ExecResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("hostagent.v1.HostAgentService.Exec is not implemented")) +} + +func (UnimplementedHostAgentServiceHandler) ListSandboxes(context.Context, *connect.Request[gen.ListSandboxesRequest]) (*connect.Response[gen.ListSandboxesResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("hostagent.v1.HostAgentService.ListSandboxes is not implemented")) +} diff --git a/proto/hostagent/hostagent.proto b/proto/hostagent/hostagent.proto index e69de29..f23c8a0 100644 --- a/proto/hostagent/hostagent.proto +++ b/proto/hostagent/hostagent.proto @@ -0,0 +1,96 @@ +syntax = "proto3"; + +package hostagent.v1; + +// HostAgentService manages sandbox VMs on a single physical host. +// The control plane calls these RPCs to orchestrate sandbox lifecycle. +service HostAgentService { + // CreateSandbox boots a new microVM with the given configuration. + rpc CreateSandbox(CreateSandboxRequest) returns (CreateSandboxResponse); + + // DestroySandbox stops and cleans up a sandbox (VM, network, rootfs). + rpc DestroySandbox(DestroySandboxRequest) returns (DestroySandboxResponse); + + // PauseSandbox pauses a running sandbox's VM. + rpc PauseSandbox(PauseSandboxRequest) returns (PauseSandboxResponse); + + // ResumeSandbox resumes a paused sandbox's VM. + rpc ResumeSandbox(ResumeSandboxRequest) returns (ResumeSandboxResponse); + + // Exec runs a command inside a sandbox and returns the collected output. + rpc Exec(ExecRequest) returns (ExecResponse); + + // ListSandboxes returns all sandboxes managed by this host agent. + rpc ListSandboxes(ListSandboxesRequest) returns (ListSandboxesResponse); +} + +message CreateSandboxRequest { + // Template name (e.g., "minimal", "python311"). Determines base rootfs. + string template = 1; + + // Number of virtual CPUs (default: 1). + int32 vcpus = 2; + + // Memory in MB (default: 512). + int32 memory_mb = 3; + + // TTL in seconds. Sandbox is auto-destroyed after this duration of + // inactivity. 0 means no auto-destroy. + int32 timeout_sec = 4; +} + +message CreateSandboxResponse { + string sandbox_id = 1; + string status = 2; + string host_ip = 3; +} + +message DestroySandboxRequest { + string sandbox_id = 1; +} + +message DestroySandboxResponse {} + +message PauseSandboxRequest { + string sandbox_id = 1; +} + +message PauseSandboxResponse {} + +message ResumeSandboxRequest { + string sandbox_id = 1; +} + +message ResumeSandboxResponse {} + +message ExecRequest { + string sandbox_id = 1; + string cmd = 2; + repeated string args = 3; + // Timeout for the command in seconds (default: 30). + int32 timeout_sec = 4; +} + +message ExecResponse { + bytes stdout = 1; + bytes stderr = 2; + int32 exit_code = 3; +} + +message ListSandboxesRequest {} + +message ListSandboxesResponse { + repeated SandboxInfo sandboxes = 1; +} + +message SandboxInfo { + string sandbox_id = 1; + string status = 2; + string template = 3; + int32 vcpus = 4; + int32 memory_mb = 5; + string host_ip = 6; + int64 created_at_unix = 7; + int64 last_active_at_unix = 8; + int32 timeout_sec = 9; +} diff --git a/scripts/test-host.sh b/scripts/test-host.sh new file mode 100755 index 0000000..1cd61e7 --- /dev/null +++ b/scripts/test-host.sh @@ -0,0 +1,233 @@ +#!/usr/bin/env bash +# +# test-host.sh — Integration test for the Wrenn host agent. +# +# Prerequisites: +# - Host agent running: sudo ./builds/wrenn-agent +# - Firecracker installed at /usr/local/bin/firecracker +# - Kernel at /var/lib/wrenn/kernels/vmlinux +# - Base rootfs at /var/lib/wrenn/images/minimal.ext4 (with envd + wrenn-init baked in) +# +# Usage: +# ./scripts/test-host.sh [agent_url] +# +# The agent URL defaults to http://localhost:50051. + +set -euo pipefail + +AGENT="${1:-http://localhost:50051}" +BASE="/hostagent.v1.HostAgentService" +SANDBOX_ID="" + +# Colors for output. +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +NC='\033[0m' + +pass() { echo -e "${GREEN}PASS${NC}: $1"; } +fail() { echo -e "${RED}FAIL${NC}: $1"; exit 1; } +info() { echo -e "${YELLOW}----${NC}: $1"; } + +rpc() { + local method="$1" + local body="$2" + curl -s -X POST \ + -H "Content-Type: application/json" \ + "${AGENT}${BASE}/${method}" \ + -d "${body}" +} + +# ────────────────────────────────────────────────── +# Test 1: List sandboxes (should be empty) +# ────────────────────────────────────────────────── +info "Test 1: List sandboxes (expect empty)" + +RESULT=$(rpc "ListSandboxes" '{}') +echo " Response: ${RESULT}" + +echo "${RESULT}" | grep -q '"sandboxes"' || echo "${RESULT}" | grep -q '{}' && \ + pass "ListSandboxes returned" || \ + fail "ListSandboxes failed" + +# ────────────────────────────────────────────────── +# Test 2: Create a sandbox +# ────────────────────────────────────────────────── +info "Test 2: Create a sandbox" + +RESULT=$(rpc "CreateSandbox" '{ + "template": "minimal", + "vcpus": 1, + "memoryMb": 512, + "timeoutSec": 300 +}') +echo " Response: ${RESULT}" + +SANDBOX_ID=$(echo "${RESULT}" | python3 -c "import sys,json; print(json.load(sys.stdin)['sandboxId'])" 2>/dev/null) || \ + fail "CreateSandbox did not return sandboxId" + +echo " Sandbox ID: ${SANDBOX_ID}" +pass "Sandbox created: ${SANDBOX_ID}" + +# ────────────────────────────────────────────────── +# Test 3: List sandboxes (should have one) +# ────────────────────────────────────────────────── +info "Test 3: List sandboxes (expect one)" + +RESULT=$(rpc "ListSandboxes" '{}') +echo " Response: ${RESULT}" + +echo "${RESULT}" | grep -q "${SANDBOX_ID}" && \ + pass "Sandbox ${SANDBOX_ID} found in list" || \ + fail "Sandbox not found in list" + +# ────────────────────────────────────────────────── +# Test 4: Execute a command +# ────────────────────────────────────────────────── +info "Test 4: Execute 'echo hello world'" + +RESULT=$(rpc "Exec" "{ + \"sandboxId\": \"${SANDBOX_ID}\", + \"cmd\": \"/bin/sh\", + \"args\": [\"-c\", \"echo hello world\"], + \"timeoutSec\": 10 +}") +echo " Response: ${RESULT}" + +# stdout is base64-encoded in Connect RPC JSON. +STDOUT=$(echo "${RESULT}" | python3 -c " +import sys, json, base64 +r = json.load(sys.stdin) +print(base64.b64decode(r['stdout']).decode().strip()) +" 2>/dev/null) || fail "Exec did not return stdout" + +[ "${STDOUT}" = "hello world" ] && \ + pass "Exec returned correct output: '${STDOUT}'" || \ + fail "Expected 'hello world', got '${STDOUT}'" + +# ────────────────────────────────────────────────── +# Test 5: Execute a multi-line command +# ────────────────────────────────────────────────── +info "Test 5: Execute multi-line command" + +RESULT=$(rpc "Exec" "{ + \"sandboxId\": \"${SANDBOX_ID}\", + \"cmd\": \"/bin/sh\", + \"args\": [\"-c\", \"echo line1; echo line2; echo line3\"], + \"timeoutSec\": 10 +}") +echo " Response: ${RESULT}" + +LINE_COUNT=$(echo "${RESULT}" | python3 -c " +import sys, json, base64 +r = json.load(sys.stdin) +lines = base64.b64decode(r['stdout']).decode().strip().split('\n') +print(len(lines)) +" 2>/dev/null) + +[ "${LINE_COUNT}" = "3" ] && \ + pass "Multi-line output: ${LINE_COUNT} lines" || \ + fail "Expected 3 lines, got ${LINE_COUNT}" + +# ────────────────────────────────────────────────── +# Test 6: Pause the sandbox +# ────────────────────────────────────────────────── +info "Test 6: Pause sandbox" + +RESULT=$(rpc "PauseSandbox" "{\"sandboxId\": \"${SANDBOX_ID}\"}") +echo " Response: ${RESULT}" + +# Verify status is paused. +LIST=$(rpc "ListSandboxes" '{}') +echo "${LIST}" | grep -q '"paused"' && \ + pass "Sandbox paused" || \ + fail "Sandbox not in paused state" + +# ────────────────────────────────────────────────── +# Test 7: Exec should fail while paused +# ────────────────────────────────────────────────── +info "Test 7: Exec while paused (expect error)" + +RESULT=$(rpc "Exec" "{ + \"sandboxId\": \"${SANDBOX_ID}\", + \"cmd\": \"/bin/echo\", + \"args\": [\"should fail\"] +}") +echo " Response: ${RESULT}" + +echo "${RESULT}" | grep -qi "not running\|error\|code" && \ + pass "Exec correctly rejected while paused" || \ + fail "Exec should have failed while paused" + +# ────────────────────────────────────────────────── +# Test 8: Resume the sandbox +# ────────────────────────────────────────────────── +info "Test 8: Resume sandbox" + +RESULT=$(rpc "ResumeSandbox" "{\"sandboxId\": \"${SANDBOX_ID}\"}") +echo " Response: ${RESULT}" + +# Verify status is running. +LIST=$(rpc "ListSandboxes" '{}') +echo "${LIST}" | grep -q '"running"' && \ + pass "Sandbox resumed" || \ + fail "Sandbox not in running state" + +# ────────────────────────────────────────────────── +# Test 9: Exec after resume +# ────────────────────────────────────────────────── +info "Test 9: Exec after resume" + +RESULT=$(rpc "Exec" "{ + \"sandboxId\": \"${SANDBOX_ID}\", + \"cmd\": \"/bin/sh\", + \"args\": [\"-c\", \"echo resumed ok\"], + \"timeoutSec\": 10 +}") +echo " Response: ${RESULT}" + +STDOUT=$(echo "${RESULT}" | python3 -c " +import sys, json, base64 +r = json.load(sys.stdin) +print(base64.b64decode(r['stdout']).decode().strip()) +" 2>/dev/null) || fail "Exec after resume failed" + +[ "${STDOUT}" = "resumed ok" ] && \ + pass "Exec after resume works: '${STDOUT}'" || \ + fail "Expected 'resumed ok', got '${STDOUT}'" + +# ────────────────────────────────────────────────── +# Test 10: Destroy the sandbox +# ────────────────────────────────────────────────── +info "Test 10: Destroy sandbox" + +RESULT=$(rpc "DestroySandbox" "{\"sandboxId\": \"${SANDBOX_ID}\"}") +echo " Response: ${RESULT}" +pass "Sandbox destroyed" + +# ────────────────────────────────────────────────── +# Test 11: List sandboxes (should be empty again) +# ────────────────────────────────────────────────── +info "Test 11: List sandboxes (expect empty)" + +RESULT=$(rpc "ListSandboxes" '{}') +echo " Response: ${RESULT}" + +echo "${RESULT}" | grep -q "${SANDBOX_ID}" && \ + fail "Destroyed sandbox still in list" || \ + pass "Sandbox list is clean" + +# ────────────────────────────────────────────────── +# Test 12: Destroy non-existent sandbox (expect error) +# ────────────────────────────────────────────────── +info "Test 12: Destroy non-existent sandbox (expect error)" + +RESULT=$(rpc "DestroySandbox" '{"sandboxId": "sb-nonexist"}') +echo " Response: ${RESULT}" + +echo "${RESULT}" | grep -qi "not found\|error\|code" && \ + pass "Correctly rejected non-existent sandbox" || \ + fail "Should have returned error for non-existent sandbox" + +echo "" +echo -e "${GREEN}All tests passed!${NC}" diff --git a/scripts/update-debug-rootfs.sh b/scripts/update-debug-rootfs.sh new file mode 100755 index 0000000..f8487c6 --- /dev/null +++ b/scripts/update-debug-rootfs.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash +# +# update-debug-rootfs.sh — Build envd and inject it (plus wrenn-init) into the debug rootfs. +# +# This script: +# 1. Builds a fresh envd static binary via make +# 2. Mounts the rootfs image +# 3. Copies envd and wrenn-init into the image +# 4. Unmounts cleanly +# +# Usage: +# bash scripts/update-debug-rootfs.sh [rootfs_path] +# +# Defaults to /var/lib/wrenn/images/minimal.ext4 + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" +ROOTFS="${1:-/var/lib/wrenn/images/minimal.ext4}" +MOUNT_DIR="/tmp/wrenn-rootfs-update" + +if [ ! -f "${ROOTFS}" ]; then + echo "ERROR: Rootfs not found at ${ROOTFS}" + exit 1 +fi + +# Step 1: Build envd. +echo "==> Building envd..." +cd "${PROJECT_ROOT}" +make build-envd +ENVD_BIN="${PROJECT_ROOT}/builds/envd" + +if [ ! -f "${ENVD_BIN}" ]; then + echo "ERROR: envd binary not found at ${ENVD_BIN}" + exit 1 +fi + +# Verify it's statically linked. +if ! file "${ENVD_BIN}" | grep -q "statically linked"; then + echo "ERROR: envd is not statically linked!" + exit 1 +fi + +# Step 2: Mount the rootfs. +echo "==> Mounting rootfs at ${MOUNT_DIR}..." +mkdir -p "${MOUNT_DIR}" +sudo mount -o loop "${ROOTFS}" "${MOUNT_DIR}" + +cleanup() { + echo "==> Unmounting rootfs..." + sudo umount "${MOUNT_DIR}" 2>/dev/null || true + rmdir "${MOUNT_DIR}" 2>/dev/null || true +} +trap cleanup EXIT + +# Step 3: Copy files into rootfs. +echo "==> Installing envd..." +sudo mkdir -p "${MOUNT_DIR}/usr/local/bin" +sudo cp "${ENVD_BIN}" "${MOUNT_DIR}/usr/local/bin/envd" +sudo chmod 755 "${MOUNT_DIR}/usr/local/bin/envd" + +echo "==> Installing wrenn-init..." +sudo cp "${PROJECT_ROOT}/images/wrenn-init.sh" "${MOUNT_DIR}/usr/local/bin/wrenn-init" +sudo chmod 755 "${MOUNT_DIR}/usr/local/bin/wrenn-init" + +# Step 4: Verify. +echo "" +echo "==> Installed files:" +ls -la "${MOUNT_DIR}/usr/local/bin/envd" "${MOUNT_DIR}/usr/local/bin/wrenn-init" + +echo "" +echo "==> Done. Rootfs updated: ${ROOTFS}"