mirror of
https://github.com/edgelesssys/constellation.git
synced 2024-10-01 01:36:09 -04:00
debugd: implement upload of multiple binaries
This commit is contained in:
parent
e6ac8e2a91
commit
6f56ed69f8
@ -14,7 +14,6 @@ import (
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/bootstrapper"
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/debugd/deploy"
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/debugd/info"
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/debugd/logcollector"
|
||||
@ -22,6 +21,8 @@ import (
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/debugd/metadata/cloudprovider"
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/debugd/metadata/fallback"
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/debugd/server"
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/filetransfer"
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/filetransfer/streamer"
|
||||
awscloud "github.com/edgelesssys/constellation/v2/internal/cloud/aws"
|
||||
azurecloud "github.com/edgelesssys/constellation/v2/internal/cloud/azure"
|
||||
platform "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
|
||||
@ -45,7 +46,8 @@ func main() {
|
||||
|
||||
log := logger.New(logger.JSONLog, logger.VerbosityFromInt(*verbosity))
|
||||
fs := afero.NewOsFs()
|
||||
streamer := bootstrapper.NewFileStreamer(fs)
|
||||
streamer := streamer.New(fs)
|
||||
filetransferer := filetransfer.New(log.Named("filetransfer"), streamer, filetransfer.DontShowProgress)
|
||||
serviceManager := deploy.NewServiceManager(log.Named("serviceManager"))
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
@ -92,13 +94,10 @@ func main() {
|
||||
logcollector.NewStartTrigger(ctx, wg, platform.FromString(csp), fetcher, log.Named("logcollector")),
|
||||
)
|
||||
|
||||
download := deploy.New(log.Named("download"), &net.Dialer{}, serviceManager, streamer, infoMap)
|
||||
download := deploy.New(log.Named("download"), &net.Dialer{}, serviceManager, filetransferer, infoMap)
|
||||
|
||||
sched := metadata.NewScheduler(log.Named("scheduler"), fetcher, download)
|
||||
serv := server.New(log.Named("server"), serviceManager, streamer, infoMap)
|
||||
if err := deploy.DefaultServiceUnit(ctx, serviceManager); err != nil {
|
||||
log.With(zap.Error(err)).Fatalf("Failed to create default service unit")
|
||||
}
|
||||
serv := server.New(log.Named("server"), serviceManager, filetransferer, infoMap)
|
||||
|
||||
writeDebugBanner(log)
|
||||
|
||||
|
@ -10,18 +10,19 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/bootstrapper"
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/debugd"
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/debugd/logcollector"
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/filetransfer"
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/filetransfer/streamer"
|
||||
pb "github.com/edgelesssys/constellation/v2/debugd/service"
|
||||
"github.com/edgelesssys/constellation/v2/internal/config"
|
||||
"github.com/edgelesssys/constellation/v2/internal/constants"
|
||||
"github.com/edgelesssys/constellation/v2/internal/file"
|
||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
||||
"github.com/spf13/afero"
|
||||
"github.com/spf13/cobra"
|
||||
"google.golang.org/grpc"
|
||||
@ -41,38 +42,52 @@ func newDeployCmd() *cobra.Command {
|
||||
}
|
||||
deployCmd.Flags().StringSlice("ips", nil, "override the ips that the bootstrapper will be uploaded to (defaults to ips from constellation config)")
|
||||
deployCmd.Flags().String("bootstrapper", "./bootstrapper", "override the path to the bootstrapper binary uploaded to instances")
|
||||
deployCmd.Flags().String("upgrade-agent", "./upgrade-agent", "override the path to the upgrade-agent binary uploaded to instances")
|
||||
deployCmd.Flags().StringToString("info", nil, "additional info to be passed to the debugd, in the form --info key1=value1,key2=value2")
|
||||
deployCmd.Flags().Int("verbosity", 0, logger.CmdLineVerbosityDescription)
|
||||
return deployCmd
|
||||
}
|
||||
|
||||
func runDeploy(cmd *cobra.Command, args []string) error {
|
||||
verbosity, err := cmd.Flags().GetInt("verbosity")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log := logger.New(logger.PlainLog, logger.VerbosityFromInt(verbosity))
|
||||
configName, err := cmd.Flags().GetString("config")
|
||||
if err != nil {
|
||||
return fmt.Errorf("parsing config path argument: %w", err)
|
||||
}
|
||||
fileHandler := file.NewHandler(afero.NewOsFs())
|
||||
fs := afero.NewOsFs()
|
||||
fileHandler := file.NewHandler(fs)
|
||||
streamer := streamer.New(fs)
|
||||
transfer := filetransfer.New(log, streamer, filetransfer.ShowProgress)
|
||||
constellationConfig, err := config.FromFile(fileHandler, configName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return deploy(cmd, fileHandler, constellationConfig, bootstrapper.NewFileStreamer(afero.NewOsFs()))
|
||||
return deploy(cmd, fileHandler, constellationConfig, transfer, log)
|
||||
}
|
||||
|
||||
func deploy(cmd *cobra.Command, fileHandler file.Handler, constellationConfig *config.Config, reader fileToStreamReader) error {
|
||||
func deploy(cmd *cobra.Command, fileHandler file.Handler, constellationConfig *config.Config, transfer fileTransferer, log *logger.Logger) error {
|
||||
bootstrapperPath, err := cmd.Flags().GetString("bootstrapper")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
upgradeAgentPath, err := cmd.Flags().GetString("upgrade-agent")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if constellationConfig.IsReleaseImage() {
|
||||
log.Println("WARNING: Constellation image does not look like a debug image. Are you using a debug image?")
|
||||
log.Infof("WARNING: Constellation image does not look like a debug image. Are you using a debug image?")
|
||||
}
|
||||
|
||||
if !constellationConfig.IsDebugCluster() {
|
||||
log.Println("WARNING: The Constellation config has debugCluster set to false.")
|
||||
log.Println("cdbg will likely not work unless you manually adjust the firewall / load balancing rules.")
|
||||
log.Println("If you create the cluster with a debug image, you should also set debugCluster to true.")
|
||||
log.Infof("WARNING: The Constellation config has debugCluster set to false.")
|
||||
log.Infof("cdbg will likely not work unless you manually adjust the firewall / load balancing rules.")
|
||||
log.Infof("If you create the cluster with a debug image, you should also set debugCluster to true.")
|
||||
}
|
||||
|
||||
ips, err := cmd.Flags().GetStringSlice("ips")
|
||||
@ -95,13 +110,28 @@ func deploy(cmd *cobra.Command, fileHandler file.Handler, constellationConfig *c
|
||||
return err
|
||||
}
|
||||
|
||||
for _, ip := range ips {
|
||||
files := []filetransfer.FileStat{
|
||||
{
|
||||
SourcePath: bootstrapperPath,
|
||||
TargetPath: debugd.BootstrapperDeployFilename,
|
||||
Mode: debugd.BinaryAccessMode,
|
||||
OverrideServiceUnit: "constellation-bootstrapper",
|
||||
},
|
||||
{
|
||||
SourcePath: upgradeAgentPath,
|
||||
TargetPath: debugd.UpgradeAgentDeployFilename,
|
||||
Mode: debugd.BinaryAccessMode,
|
||||
OverrideServiceUnit: "constellation-upgrade-agent",
|
||||
},
|
||||
}
|
||||
|
||||
for _, ip := range ips {
|
||||
input := deployOnEndpointInput{
|
||||
debugdEndpoint: ip,
|
||||
infos: info,
|
||||
bootstrapperPath: bootstrapperPath,
|
||||
reader: reader,
|
||||
debugdEndpoint: ip,
|
||||
infos: info,
|
||||
files: files,
|
||||
transfer: transfer,
|
||||
log: log,
|
||||
}
|
||||
if err := deployOnEndpoint(cmd.Context(), input); err != nil {
|
||||
return err
|
||||
@ -112,15 +142,16 @@ func deploy(cmd *cobra.Command, fileHandler file.Handler, constellationConfig *c
|
||||
}
|
||||
|
||||
type deployOnEndpointInput struct {
|
||||
debugdEndpoint string
|
||||
bootstrapperPath string
|
||||
infos map[string]string
|
||||
reader fileToStreamReader
|
||||
debugdEndpoint string
|
||||
files []filetransfer.FileStat
|
||||
infos map[string]string
|
||||
transfer fileTransferer
|
||||
log *logger.Logger
|
||||
}
|
||||
|
||||
// deployOnEndpoint deploys a custom built bootstrapper binary to a debugd endpoint.
|
||||
func deployOnEndpoint(ctx context.Context, in deployOnEndpointInput) error {
|
||||
log.Printf("Deploying on %v\n", in.debugdEndpoint)
|
||||
in.log.Infof("Deploying on %v", in.debugdEndpoint)
|
||||
|
||||
client, closer, err := newDebugdClient(ctx, in.debugdEndpoint)
|
||||
if err != nil {
|
||||
@ -128,11 +159,11 @@ func deployOnEndpoint(ctx context.Context, in deployOnEndpointInput) error {
|
||||
}
|
||||
defer closer.Close()
|
||||
|
||||
if err := setInfo(ctx, client, in.infos); err != nil {
|
||||
if err := setInfo(ctx, in.log, client, in.infos); err != nil {
|
||||
return fmt.Errorf("sending info: %w", err)
|
||||
}
|
||||
|
||||
if err := uploadBootstrapper(ctx, client, in); err != nil {
|
||||
if err := uploadFiles(ctx, client, in); err != nil {
|
||||
return fmt.Errorf("uploading bootstrapper: %w", err)
|
||||
}
|
||||
|
||||
@ -152,8 +183,8 @@ func newDebugdClient(ctx context.Context, ip string) (pb.DebugdClient, io.Closer
|
||||
return pb.NewDebugdClient(conn), conn, nil
|
||||
}
|
||||
|
||||
func setInfo(ctx context.Context, client pb.DebugdClient, infos map[string]string) error {
|
||||
log.Printf("Setting info with length %d", len(infos))
|
||||
func setInfo(ctx context.Context, log *logger.Logger, client pb.DebugdClient, infos map[string]string) error {
|
||||
log.Infof("Setting info with length %d", len(infos))
|
||||
|
||||
var infosPb []*pb.Info
|
||||
for key, value := range infos {
|
||||
@ -162,36 +193,52 @@ func setInfo(ctx context.Context, client pb.DebugdClient, infos map[string]strin
|
||||
|
||||
req := &pb.SetInfoRequest{Info: infosPb}
|
||||
|
||||
if _, err := client.SetInfo(ctx, req, grpc.WaitForReady(true)); err != nil {
|
||||
status, err := client.SetInfo(ctx, req, grpc.WaitForReady(true))
|
||||
if err != nil {
|
||||
return fmt.Errorf("setting info: %w", err)
|
||||
}
|
||||
|
||||
log.Println("Info set")
|
||||
switch status.Status {
|
||||
case pb.SetInfoStatus_SET_INFO_SUCCESS:
|
||||
log.Infof("Info set")
|
||||
case pb.SetInfoStatus_SET_INFO_ALREADY_SET:
|
||||
log.Infof("Info already set")
|
||||
default:
|
||||
log.Warnf("Unknown status %v", status.Status)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func uploadBootstrapper(ctx context.Context, client pb.DebugdClient, in deployOnEndpointInput) error {
|
||||
log.Println("Uploading bootstrapper")
|
||||
func uploadFiles(ctx context.Context, client pb.DebugdClient, in deployOnEndpointInput) error {
|
||||
in.log.Infof("Uploading files")
|
||||
|
||||
stream, err := client.UploadBootstrapper(ctx, grpc.WaitForReady(true))
|
||||
stream, err := client.UploadFiles(ctx, grpc.WaitForReady(true))
|
||||
if err != nil {
|
||||
return fmt.Errorf("starting bootstrapper upload to instance %v: %w", in.debugdEndpoint, err)
|
||||
}
|
||||
streamErr := in.reader.ReadStream(in.bootstrapperPath, stream, debugd.Chunksize, true)
|
||||
|
||||
in.transfer.SetFiles(in.files)
|
||||
if err := in.transfer.SendFiles(stream); err != nil {
|
||||
return fmt.Errorf("sending files to %v: %w", in.debugdEndpoint, err)
|
||||
}
|
||||
|
||||
uploadResponse, closeErr := stream.CloseAndRecv()
|
||||
if closeErr != nil {
|
||||
return fmt.Errorf("closing upload stream after uploading bootstrapper to %v: %w", in.debugdEndpoint, closeErr)
|
||||
return fmt.Errorf("closing upload stream after uploading files to %v: %w", in.debugdEndpoint, closeErr)
|
||||
}
|
||||
if uploadResponse.Status == pb.UploadBootstrapperStatus_UPLOAD_BOOTSTRAPPER_FILE_EXISTS {
|
||||
log.Println("Bootstrapper was already uploaded")
|
||||
return nil
|
||||
}
|
||||
if uploadResponse.Status != pb.UploadBootstrapperStatus_UPLOAD_BOOTSTRAPPER_SUCCESS || streamErr != nil {
|
||||
return fmt.Errorf("uploading bootstrapper to instance %v failed: %v / %w", in.debugdEndpoint, uploadResponse, streamErr)
|
||||
switch uploadResponse.Status {
|
||||
case pb.UploadFilesStatus_UPLOAD_FILES_SUCCESS:
|
||||
in.log.Infof("Upload successful")
|
||||
case pb.UploadFilesStatus_UPLOAD_FILES_ALREADY_FINISHED:
|
||||
in.log.Infof("Files already uploaded")
|
||||
case pb.UploadFilesStatus_UPLOAD_FILES_UPLOAD_FAILED:
|
||||
return fmt.Errorf("uploading files to %v failed: %v", in.debugdEndpoint, uploadResponse)
|
||||
case pb.UploadFilesStatus_UPLOAD_FILES_ALREADY_STARTED:
|
||||
return fmt.Errorf("upload already started on %v", in.debugdEndpoint)
|
||||
default:
|
||||
return fmt.Errorf("unknown upload status %v", uploadResponse.Status)
|
||||
}
|
||||
|
||||
log.Println("Uploaded bootstrapper")
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -211,8 +258,9 @@ func checkInfoMap(info map[string]string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type fileToStreamReader interface {
|
||||
ReadStream(filename string, stream bootstrapper.WriteChunkStream, chunksize uint, showProgress bool) error
|
||||
type fileTransferer interface {
|
||||
SendFiles(stream filetransfer.SendFilesStream) error
|
||||
SetFiles(files []filetransfer.FileStat)
|
||||
}
|
||||
|
||||
type clusterIDsFile struct {
|
||||
|
@ -14,7 +14,9 @@ const (
|
||||
GRPCTimeout = 5 * time.Minute
|
||||
DiscoverDebugdInterval = 30 * time.Second
|
||||
DownloadRetryBackoff = 1 * time.Minute
|
||||
BinaryAccessMode = 0o755 // -rwxr-xr-x
|
||||
BootstrapperDeployFilename = "/run/state/bin/bootstrapper"
|
||||
UpgradeAgentDeployFilename = "/run/state/bin/upgrade-agent"
|
||||
Chunksize = 1024
|
||||
BootstrapperSystemdUnitName = "bootstrapper.service"
|
||||
BootstrapperSystemdUnitContents = `[Unit]
|
||||
|
@ -8,13 +8,13 @@ package deploy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"strconv"
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/bootstrapper"
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/debugd"
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/filetransfer"
|
||||
pb "github.com/edgelesssys/constellation/v2/debugd/service"
|
||||
"github.com/edgelesssys/constellation/v2/internal/constants"
|
||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
||||
@ -27,19 +27,19 @@ import (
|
||||
type Download struct {
|
||||
log *logger.Logger
|
||||
dialer NetDialer
|
||||
writer streamToFileWriter
|
||||
transfer fileTransferer
|
||||
serviceManager serviceManager
|
||||
info infoSetter
|
||||
}
|
||||
|
||||
// New creates a new Download.
|
||||
func New(log *logger.Logger, dialer NetDialer, serviceManager serviceManager,
|
||||
writer streamToFileWriter, info infoSetter,
|
||||
transfer fileTransferer, info infoSetter,
|
||||
) *Download {
|
||||
return &Download{
|
||||
log: log,
|
||||
dialer: dialer,
|
||||
writer: writer,
|
||||
transfer: transfer,
|
||||
info: info,
|
||||
serviceManager: serviceManager,
|
||||
}
|
||||
@ -47,6 +47,10 @@ func New(log *logger.Logger, dialer NetDialer, serviceManager serviceManager,
|
||||
|
||||
// DownloadInfo will try to download the info from another instance.
|
||||
func (d *Download) DownloadInfo(ctx context.Context, ip string) error {
|
||||
if d.info.Received() {
|
||||
return nil
|
||||
}
|
||||
|
||||
log := d.log.With(zap.String("ip", ip))
|
||||
serverAddr := net.JoinHostPort(ip, strconv.Itoa(constants.DebugdPort))
|
||||
|
||||
@ -66,7 +70,7 @@ func (d *Download) DownloadInfo(ctx context.Context, ip string) error {
|
||||
return d.info.SetProto(resp.Info)
|
||||
}
|
||||
|
||||
// DownloadDeployment will open a new grpc connection to another instance, attempting to download a bootstrapper from that instance.
|
||||
// DownloadDeployment will open a new grpc connection to another instance, attempting to download files from that instance.
|
||||
func (d *Download) DownloadDeployment(ctx context.Context, ip string) error {
|
||||
log := d.log.With(zap.String("ip", ip))
|
||||
serverAddr := net.JoinHostPort(ip, strconv.Itoa(constants.DebugdPort))
|
||||
@ -77,23 +81,38 @@ func (d *Download) DownloadDeployment(ctx context.Context, ip string) error {
|
||||
}
|
||||
defer closer.Close()
|
||||
|
||||
log.Infof("Trying to download bootstrapper")
|
||||
stream, err := client.DownloadBootstrapper(ctx, &pb.DownloadBootstrapperRequest{})
|
||||
log.Infof("Trying to download files")
|
||||
stream, err := client.DownloadFiles(ctx, &pb.DownloadFilesRequest{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("starting bootstrapper download from other instance: %w", err)
|
||||
return fmt.Errorf("starting file download from other instance: %w", err)
|
||||
}
|
||||
if err := d.writer.WriteStream(debugd.BootstrapperDeployFilename, stream, true); err != nil {
|
||||
return fmt.Errorf("streaming bootstrapper from other instance: %w", err)
|
||||
}
|
||||
log.Infof("Successfully downloaded bootstrapper")
|
||||
|
||||
// after the upload succeeds, try to restart the bootstrapper
|
||||
restartAction := ServiceManagerRequest{
|
||||
Unit: debugd.BootstrapperSystemdUnitName,
|
||||
Action: Restart,
|
||||
err = d.transfer.RecvFiles(stream)
|
||||
switch {
|
||||
case err == nil:
|
||||
d.log.Infof("Downloading files succeeded")
|
||||
case errors.Is(err, filetransfer.ErrReceiveRunning):
|
||||
d.log.Warnf("Download already in progress")
|
||||
return err
|
||||
case errors.Is(err, filetransfer.ErrReceiveFinished):
|
||||
d.log.Warnf("Download already finished")
|
||||
return nil
|
||||
default:
|
||||
d.log.With(zap.Error(err)).Errorf("Downloading files failed")
|
||||
return err
|
||||
}
|
||||
if err := d.serviceManager.SystemdAction(ctx, restartAction); err != nil {
|
||||
return fmt.Errorf("restarting bootstrapper: %w", err)
|
||||
|
||||
files := d.transfer.GetFiles()
|
||||
for _, file := range files {
|
||||
if file.OverrideServiceUnit == "" {
|
||||
continue
|
||||
}
|
||||
if err := d.serviceManager.OverrideServiceUnitExecStart(
|
||||
ctx, file.OverrideServiceUnit, file.TargetPath,
|
||||
); err != nil {
|
||||
// continue on error to allow other units to be overridden
|
||||
d.log.With(zap.Error(err)).Errorf("Failed to override service unit %s", file.OverrideServiceUnit)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -123,14 +142,17 @@ func (d *Download) grpcWithDialer() grpc.DialOption {
|
||||
|
||||
type infoSetter interface {
|
||||
SetProto(infos []*pb.Info) error
|
||||
Received() bool
|
||||
}
|
||||
|
||||
type serviceManager interface {
|
||||
SystemdAction(ctx context.Context, request ServiceManagerRequest) error
|
||||
OverrideServiceUnitExecStart(ctx context.Context, unitName string, execStart string) error
|
||||
}
|
||||
|
||||
type streamToFileWriter interface {
|
||||
WriteStream(filename string, stream bootstrapper.ReadChunkStream, showProgress bool) error
|
||||
type fileTransferer interface {
|
||||
RecvFiles(stream filetransfer.RecvFilesStream) error
|
||||
GetFiles() []filetransfer.FileStat
|
||||
}
|
||||
|
||||
// NetDialer can open a net.Conn.
|
||||
|
@ -9,14 +9,11 @@ package deploy
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/bootstrapper"
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/debugd"
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/filetransfer"
|
||||
pb "github.com/edgelesssys/constellation/v2/debugd/service"
|
||||
"github.com/edgelesssys/constellation/v2/internal/constants"
|
||||
"github.com/edgelesssys/constellation/v2/internal/grpc/testdialer"
|
||||
@ -33,41 +30,72 @@ func TestMain(m *testing.M) {
|
||||
)
|
||||
}
|
||||
|
||||
func TestDownloadBootstrapper(t *testing.T) {
|
||||
filename := "/run/state/bin/bootstrapper"
|
||||
someErr := errors.New("failed")
|
||||
|
||||
func TestDownloadDeployment(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
server fakeDownloadServer
|
||||
serviceManager stubServiceManager
|
||||
wantChunks [][]byte
|
||||
wantDownloadErr bool
|
||||
wantFile bool
|
||||
wantSystemdAction bool
|
||||
wantDeployed bool
|
||||
files []filetransfer.FileStat
|
||||
recvFilesErr error
|
||||
overrideServiceUnitErr error
|
||||
wantErr bool
|
||||
wantOverrideCalls []struct{ UnitName, ExecStart string }
|
||||
}{
|
||||
"download works": {
|
||||
server: fakeDownloadServer{
|
||||
chunks: [][]byte{[]byte("test")},
|
||||
files: []filetransfer.FileStat{
|
||||
{
|
||||
SourcePath: "source/testfileA",
|
||||
TargetPath: "target/testfileA",
|
||||
Mode: 0o644,
|
||||
OverrideServiceUnit: "unitA",
|
||||
},
|
||||
{
|
||||
SourcePath: "source/testfileB",
|
||||
TargetPath: "target/testfileB",
|
||||
Mode: 0o644,
|
||||
},
|
||||
},
|
||||
wantOverrideCalls: []struct{ UnitName, ExecStart string }{
|
||||
{"unitA", "target/testfileA"},
|
||||
},
|
||||
wantChunks: [][]byte{[]byte("test")},
|
||||
wantDownloadErr: false,
|
||||
wantFile: true,
|
||||
wantSystemdAction: true,
|
||||
wantDeployed: true,
|
||||
},
|
||||
"download rpc call error is detected": {
|
||||
server: fakeDownloadServer{downladErr: someErr},
|
||||
wantDownloadErr: true,
|
||||
"recv files error is detected": {
|
||||
recvFilesErr: errors.New("some error"),
|
||||
wantErr: true,
|
||||
},
|
||||
"service restart error is detected": {
|
||||
server: fakeDownloadServer{chunks: [][]byte{[]byte("test")}},
|
||||
serviceManager: stubServiceManager{systemdActionErr: someErr},
|
||||
wantChunks: [][]byte{[]byte("test")},
|
||||
wantDownloadErr: true,
|
||||
wantFile: true,
|
||||
wantDeployed: true,
|
||||
wantSystemdAction: false,
|
||||
"recv already running": {
|
||||
recvFilesErr: filetransfer.ErrReceiveRunning,
|
||||
wantErr: true,
|
||||
},
|
||||
"recv already finished": {
|
||||
files: []filetransfer.FileStat{
|
||||
{
|
||||
SourcePath: "source/testfileA",
|
||||
TargetPath: "target/testfileA",
|
||||
Mode: 0o644,
|
||||
OverrideServiceUnit: "unitA",
|
||||
},
|
||||
},
|
||||
recvFilesErr: filetransfer.ErrReceiveFinished,
|
||||
wantErr: false,
|
||||
},
|
||||
"service unit fail does not stop further tries": {
|
||||
files: []filetransfer.FileStat{
|
||||
{
|
||||
SourcePath: "source/testfileA",
|
||||
TargetPath: "target/testfileA",
|
||||
Mode: 0o644,
|
||||
OverrideServiceUnit: "unitA",
|
||||
},
|
||||
{
|
||||
SourcePath: "source/testfileB",
|
||||
TargetPath: "target/testfileB",
|
||||
Mode: 0o644,
|
||||
OverrideServiceUnit: "unitB",
|
||||
},
|
||||
},
|
||||
overrideServiceUnitErr: errors.New("some error"),
|
||||
wantOverrideCalls: []struct{ UnitName, ExecStart string }{
|
||||
{"unitA", "target/testfileA"},
|
||||
{"unitB", "target/testfileB"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@ -76,11 +104,13 @@ func TestDownloadBootstrapper(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
ip := "192.0.2.0"
|
||||
writer := &fakeStreamToFileWriter{}
|
||||
transfer := &stubTransfer{recvFilesErr: tc.recvFilesErr, files: tc.files}
|
||||
serviceMgr := &stubServiceManager{overrideServiceUnitExecStartErr: tc.overrideServiceUnitErr}
|
||||
dialer := testdialer.NewBufconnDialer()
|
||||
|
||||
server := &stubDownloadServer{}
|
||||
grpcServ := grpc.NewServer()
|
||||
pb.RegisterDebugdServer(grpcServ, &tc.server)
|
||||
pb.RegisterDebugdServer(grpcServ, server)
|
||||
lis := dialer.GetListener(net.JoinHostPort(ip, strconv.Itoa(constants.DebugdPort)))
|
||||
go grpcServ.Serve(lis)
|
||||
defer grpcServ.GracefulStop()
|
||||
@ -88,30 +118,19 @@ func TestDownloadBootstrapper(t *testing.T) {
|
||||
download := &Download{
|
||||
log: logger.NewTest(t),
|
||||
dialer: dialer,
|
||||
writer: writer,
|
||||
serviceManager: &tc.serviceManager,
|
||||
transfer: transfer,
|
||||
serviceManager: serviceMgr,
|
||||
}
|
||||
|
||||
err := download.DownloadDeployment(context.Background(), ip)
|
||||
|
||||
if tc.wantDownloadErr {
|
||||
if tc.wantErr {
|
||||
assert.Error(err)
|
||||
} else {
|
||||
assert.NoError(err)
|
||||
}
|
||||
|
||||
if tc.wantFile {
|
||||
assert.Equal(tc.wantChunks, writer.chunks)
|
||||
assert.Equal(filename, writer.filename)
|
||||
}
|
||||
if tc.wantSystemdAction {
|
||||
assert.ElementsMatch(
|
||||
[]ServiceManagerRequest{
|
||||
{Unit: debugd.BootstrapperSystemdUnitName, Action: Restart},
|
||||
},
|
||||
tc.serviceManager.requests,
|
||||
)
|
||||
}
|
||||
assert.Equal(tc.wantOverrideCalls, serviceMgr.overrideCalls)
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -189,6 +208,9 @@ func TestDownloadInfo(t *testing.T) {
|
||||
type stubServiceManager struct {
|
||||
requests []ServiceManagerRequest
|
||||
systemdActionErr error
|
||||
|
||||
overrideCalls []struct{ UnitName, ExecStart string }
|
||||
overrideServiceUnitExecStartErr error
|
||||
}
|
||||
|
||||
func (s *stubServiceManager) SystemdAction(ctx context.Context, request ServiceManagerRequest) error {
|
||||
@ -196,39 +218,34 @@ func (s *stubServiceManager) SystemdAction(ctx context.Context, request ServiceM
|
||||
return s.systemdActionErr
|
||||
}
|
||||
|
||||
type fakeStreamToFileWriter struct {
|
||||
chunks [][]byte
|
||||
filename string
|
||||
func (s *stubServiceManager) OverrideServiceUnitExecStart(ctx context.Context, unitName string, execStart string) error {
|
||||
s.overrideCalls = append(s.overrideCalls, struct {
|
||||
UnitName, ExecStart string
|
||||
}{UnitName: unitName, ExecStart: execStart})
|
||||
return s.overrideServiceUnitExecStartErr
|
||||
}
|
||||
|
||||
func (f *fakeStreamToFileWriter) WriteStream(filename string, stream bootstrapper.ReadChunkStream, showProgress bool) error {
|
||||
f.filename = filename
|
||||
for {
|
||||
chunk, err := stream.Recv()
|
||||
if err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("reading stream: %w", err)
|
||||
}
|
||||
f.chunks = append(f.chunks, chunk.Content)
|
||||
}
|
||||
type stubTransfer struct {
|
||||
recvFilesErr error
|
||||
files []filetransfer.FileStat
|
||||
}
|
||||
|
||||
// fakeDownloadServer implements DebugdServer; only fakes DownloadBootstrapper, panics on every other rpc.
|
||||
type fakeDownloadServer struct {
|
||||
chunks [][]byte
|
||||
func (t *stubTransfer) RecvFiles(_ filetransfer.RecvFilesStream) error {
|
||||
return t.recvFilesErr
|
||||
}
|
||||
|
||||
func (t *stubTransfer) GetFiles() []filetransfer.FileStat {
|
||||
return t.files
|
||||
}
|
||||
|
||||
// stubDownloadServer implements DebugdServer; only stubs DownloadFiles, panics on every other rpc.
|
||||
type stubDownloadServer struct {
|
||||
downladErr error
|
||||
|
||||
pb.UnimplementedDebugdServer
|
||||
}
|
||||
|
||||
func (s *fakeDownloadServer) DownloadBootstrapper(request *pb.DownloadBootstrapperRequest, stream pb.Debugd_DownloadBootstrapperServer) error {
|
||||
for _, chunk := range s.chunks {
|
||||
if err := stream.Send(&pb.Chunk{Content: chunk}); err != nil {
|
||||
return fmt.Errorf("sending chunk: %w", err)
|
||||
}
|
||||
}
|
||||
func (s *stubDownloadServer) DownloadFiles(request *pb.DownloadFilesRequest, stream pb.Debugd_DownloadFilesServer) error {
|
||||
return s.downladErr
|
||||
}
|
||||
|
||||
@ -244,6 +261,7 @@ func (s *stubDebugdServer) GetInfo(ctx context.Context, request *pb.GetInfoReque
|
||||
|
||||
type stubInfoSetter struct {
|
||||
info []*pb.Info
|
||||
received bool
|
||||
setProtoErr error
|
||||
}
|
||||
|
||||
@ -251,3 +269,7 @@ func (s *stubInfoSetter) SetProto(infos []*pb.Info) error {
|
||||
s.info = infos
|
||||
return s.setProtoErr
|
||||
}
|
||||
|
||||
func (s *stubInfoSetter) Received() bool {
|
||||
return s.received
|
||||
}
|
||||
|
@ -9,9 +9,12 @@ package deploy
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/debugd"
|
||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
||||
"github.com/spf13/afero"
|
||||
"go.uber.org/zap"
|
||||
@ -21,6 +24,10 @@ const (
|
||||
systemdUnitFolder = "/run/systemd/system"
|
||||
)
|
||||
|
||||
// systemdUnitNameRegexp is a regular expression that matches valid systemd unit names.
|
||||
// This is only the unit name, without the .service suffix.
|
||||
var systemdUnitNameRegexp = regexp.MustCompile(`^[a-zA-Z0-9@._\-\\]+$`)
|
||||
|
||||
// SystemdAction encodes the available actions.
|
||||
//
|
||||
//go:generate stringer -type=SystemdAction
|
||||
@ -73,7 +80,7 @@ func NewServiceManager(log *logger.Logger) *ServiceManager {
|
||||
type dbusClient interface {
|
||||
// NewSystemConnectionContext establishes a connection to the system bus and authenticates.
|
||||
// Callers should call Close() when done with the connection.
|
||||
NewSystemdConnectionContext(ctx context.Context) (dbusConn, error)
|
||||
NewSystemConnectionContext(ctx context.Context) (dbusConn, error)
|
||||
}
|
||||
|
||||
type dbusConn interface {
|
||||
@ -89,15 +96,18 @@ type dbusConn interface {
|
||||
// ReloadContext instructs systemd to scan for and reload unit files. This is
|
||||
// an equivalent to systemctl daemon-reload.
|
||||
ReloadContext(ctx context.Context) error
|
||||
// Close closes the connection.
|
||||
Close()
|
||||
}
|
||||
|
||||
// SystemdAction will perform a systemd action on a service unit (start, stop, restart, reload).
|
||||
func (s *ServiceManager) SystemdAction(ctx context.Context, request ServiceManagerRequest) error {
|
||||
log := s.log.With(zap.String("unit", request.Unit), zap.String("action", request.Action.String()))
|
||||
conn, err := s.dbus.NewSystemdConnectionContext(ctx)
|
||||
conn, err := s.dbus.NewSystemConnectionContext(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("establishing systemd connection: %w", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
resultChan := make(chan string, 1)
|
||||
switch request.Action {
|
||||
@ -149,28 +159,41 @@ func (s *ServiceManager) WriteSystemdUnitFile(ctx context.Context, unit SystemdU
|
||||
}
|
||||
|
||||
log.Infof("Wrote systemd unit file and performed daemon-reload")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DefaultServiceUnit will write the default "bootstrapper.service" unit file.
|
||||
func DefaultServiceUnit(ctx context.Context, serviceManager *ServiceManager) error {
|
||||
if err := serviceManager.WriteSystemdUnitFile(ctx, SystemdUnit{
|
||||
Name: debugd.BootstrapperSystemdUnitName,
|
||||
Contents: debugd.BootstrapperSystemdUnitContents,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("writing systemd unit file %q: %w", debugd.BootstrapperSystemdUnitName, err)
|
||||
}
|
||||
|
||||
// try to start the default service if the binary exists but ignore failure.
|
||||
// this is meant to start the bootstrapper after a reboot
|
||||
// if a bootstrapper binary was uploaded before.
|
||||
if ok, err := afero.Exists(serviceManager.fs, debugd.BootstrapperDeployFilename); ok && err == nil {
|
||||
_ = serviceManager.SystemdAction(ctx, ServiceManagerRequest{
|
||||
Unit: debugd.BootstrapperSystemdUnitName,
|
||||
Action: Start,
|
||||
})
|
||||
// OverrideServiceUnitExecStart will override the ExecStart of a systemd unit.
|
||||
func (s *ServiceManager) OverrideServiceUnitExecStart(ctx context.Context, unitName, execStart string) error {
|
||||
log := s.log.With(zap.String("unitFile", fmt.Sprintf("%s/%s", systemdUnitFolder, unitName)))
|
||||
log.Infof("Overriding systemd unit file execStart")
|
||||
if !systemdUnitNameRegexp.MatchString(unitName) {
|
||||
return fmt.Errorf("unit name %q is invalid", unitName)
|
||||
}
|
||||
// validate execStart (no newlines)
|
||||
if strings.Contains(execStart, "\n") || strings.Contains(execStart, "\r") {
|
||||
return fmt.Errorf("execStart must not contain newlines")
|
||||
}
|
||||
overrideUnitContents := fmt.Sprintf("[Service]\nExecStart=\nExecStart=%s\n", execStart)
|
||||
s.systemdUnitFilewriteLock.Lock()
|
||||
defer s.systemdUnitFilewriteLock.Unlock()
|
||||
path := filepath.Join(systemdUnitFolder, unitName+".service.d", "override.conf")
|
||||
if err := s.fs.MkdirAll(filepath.Dir(path), os.ModePerm); err != nil {
|
||||
return fmt.Errorf("creating systemd unit file override directory %q: %w", filepath.Dir(path), err)
|
||||
}
|
||||
if err := afero.WriteFile(s.fs, path, []byte(overrideUnitContents), 0o644); err != nil {
|
||||
return fmt.Errorf("writing systemd unit override file %q: %w", unitName, err)
|
||||
}
|
||||
if err := s.SystemdAction(ctx, ServiceManagerRequest{Unit: unitName, Action: Reload}); err != nil {
|
||||
// do not return early here
|
||||
// the "daemon-reload" command may return an unrelated error
|
||||
// and there is no way to know if the override was successful
|
||||
log.Warnf("Failed to perform systemd daemon-reload: %v", err)
|
||||
}
|
||||
if err := s.SystemdAction(ctx, ServiceManagerRequest{Unit: unitName + ".service", Action: Restart}); err != nil {
|
||||
log.Warnf("Failed to perform unit restart: %v", err)
|
||||
return fmt.Errorf("performing systemd unit restart: %w", err)
|
||||
}
|
||||
|
||||
log.Infof("Overrode systemd unit file execStart, performed daemon-reload and restarted unit %v", unitName)
|
||||
return nil
|
||||
}
|
||||
|
@ -158,7 +158,7 @@ func TestWriteSystemdUnitFile(t *testing.T) {
|
||||
"systemd reload fails": {
|
||||
dbus: stubDbus{
|
||||
conn: &fakeDbusConn{
|
||||
actionErr: errors.New("reload error"),
|
||||
reloadErr: errors.New("reload error"),
|
||||
},
|
||||
},
|
||||
unit: SystemdUnit{
|
||||
@ -200,12 +200,127 @@ func TestWriteSystemdUnitFile(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestOverrideServiceUnitExecStart(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
dbus stubDbus
|
||||
unitName, execStart string
|
||||
readonly bool
|
||||
wantErr bool
|
||||
wantFileContents string
|
||||
wantActionCalls []dbusConnActionInput
|
||||
wantReloads int
|
||||
}{
|
||||
"override works": {
|
||||
dbus: stubDbus{
|
||||
conn: &fakeDbusConn{
|
||||
result: "done",
|
||||
},
|
||||
},
|
||||
unitName: "test",
|
||||
execStart: "/run/state/bin/test",
|
||||
wantFileContents: "[Service]\nExecStart=\nExecStart=/run/state/bin/test\n",
|
||||
wantActionCalls: []dbusConnActionInput{
|
||||
{name: "test.service", mode: "replace"},
|
||||
},
|
||||
wantReloads: 1,
|
||||
},
|
||||
"unit name invalid": {
|
||||
dbus: stubDbus{
|
||||
conn: &fakeDbusConn{
|
||||
result: "done",
|
||||
},
|
||||
},
|
||||
unitName: "invalid name",
|
||||
execStart: "/run/state/bin/test",
|
||||
wantErr: true,
|
||||
},
|
||||
"exec start invalid": {
|
||||
dbus: stubDbus{
|
||||
conn: &fakeDbusConn{
|
||||
result: "done",
|
||||
},
|
||||
},
|
||||
unitName: "test",
|
||||
execStart: "/run/state/bin/\r\ntest",
|
||||
wantErr: true,
|
||||
},
|
||||
"write fails": {
|
||||
dbus: stubDbus{
|
||||
conn: &fakeDbusConn{
|
||||
result: "done",
|
||||
},
|
||||
},
|
||||
unitName: "test",
|
||||
execStart: "/run/state/bin/test",
|
||||
readonly: true,
|
||||
wantErr: true,
|
||||
},
|
||||
"reload fails but restart is still attempted": {
|
||||
dbus: stubDbus{
|
||||
conn: &fakeDbusConn{
|
||||
result: "done",
|
||||
reloadErr: errors.New("reload error"),
|
||||
},
|
||||
},
|
||||
unitName: "test",
|
||||
execStart: "/run/state/bin/test",
|
||||
wantFileContents: "[Service]\nExecStart=\nExecStart=/run/state/bin/test\n",
|
||||
wantActionCalls: []dbusConnActionInput{
|
||||
{name: "test.service", mode: "replace"},
|
||||
},
|
||||
wantReloads: 1,
|
||||
},
|
||||
"restart fails": {
|
||||
dbus: stubDbus{
|
||||
conn: &fakeDbusConn{
|
||||
result: "done",
|
||||
actionErr: errors.New("action error"),
|
||||
},
|
||||
},
|
||||
unitName: "test",
|
||||
execStart: "/run/state/bin/test",
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
require := require.New(t)
|
||||
|
||||
fs := afero.NewMemMapFs()
|
||||
assert.NoError(fs.MkdirAll(systemdUnitFolder, 0o755))
|
||||
if tc.readonly {
|
||||
fs = afero.NewReadOnlyFs(fs)
|
||||
}
|
||||
manager := ServiceManager{
|
||||
log: logger.NewTest(t),
|
||||
dbus: &tc.dbus,
|
||||
fs: fs,
|
||||
systemdUnitFilewriteLock: sync.Mutex{},
|
||||
}
|
||||
err := manager.OverrideServiceUnitExecStart(context.Background(), tc.unitName, tc.execStart)
|
||||
|
||||
if tc.wantErr {
|
||||
assert.Error(err)
|
||||
return
|
||||
}
|
||||
require.NoError(err)
|
||||
fileContents, err := afero.ReadFile(fs, "/run/systemd/system/test.service.d/override.conf")
|
||||
assert.NoError(err)
|
||||
assert.Equal(tc.wantFileContents, string(fileContents))
|
||||
assert.Equal(tc.wantActionCalls, tc.dbus.conn.(*fakeDbusConn).inputs)
|
||||
assert.Equal(tc.wantReloads, tc.dbus.conn.(*fakeDbusConn).reloadCalls)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type stubDbus struct {
|
||||
conn dbusConn
|
||||
connErr error
|
||||
}
|
||||
|
||||
func (s *stubDbus) NewSystemdConnectionContext(ctx context.Context) (dbusConn, error) {
|
||||
func (s *stubDbus) NewSystemConnectionContext(ctx context.Context) (dbusConn, error) {
|
||||
return s.conn, s.connErr
|
||||
}
|
||||
|
||||
@ -215,11 +330,13 @@ type dbusConnActionInput struct {
|
||||
}
|
||||
|
||||
type fakeDbusConn struct {
|
||||
inputs []dbusConnActionInput
|
||||
result string
|
||||
inputs []dbusConnActionInput
|
||||
result string
|
||||
reloadCalls int
|
||||
|
||||
jobID int
|
||||
actionErr error
|
||||
reloadErr error
|
||||
}
|
||||
|
||||
func (c *fakeDbusConn) StartUnitContext(ctx context.Context, name string, mode string, ch chan<- string) (int, error) {
|
||||
@ -244,5 +361,9 @@ func (c *fakeDbusConn) RestartUnitContext(ctx context.Context, name string, mode
|
||||
}
|
||||
|
||||
func (c *fakeDbusConn) ReloadContext(ctx context.Context) error {
|
||||
return c.actionErr
|
||||
c.reloadCalls++
|
||||
|
||||
return c.reloadErr
|
||||
}
|
||||
|
||||
func (c *fakeDbusConn) Close() {}
|
||||
|
@ -15,8 +15,8 @@ import (
|
||||
// wraps go-systemd dbus.
|
||||
type dbusWrapper struct{}
|
||||
|
||||
func (d *dbusWrapper) NewSystemdConnectionContext(ctx context.Context) (dbusConn, error) {
|
||||
conn, err := dbus.NewSystemdConnectionContext(ctx)
|
||||
func (d *dbusWrapper) NewSystemConnectionContext(ctx context.Context) (dbusConn, error) {
|
||||
conn, err := dbus.NewSystemConnectionContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -44,3 +44,7 @@ func (c *dbusConnWrapper) RestartUnitContext(ctx context.Context, name string, m
|
||||
func (c *dbusConnWrapper) ReloadContext(ctx context.Context) error {
|
||||
return c.conn.ReloadContext(ctx)
|
||||
}
|
||||
|
||||
func (c *dbusConnWrapper) Close() {
|
||||
c.conn.Close()
|
||||
}
|
||||
|
@ -29,6 +29,13 @@ func NewMap() *Map {
|
||||
}
|
||||
}
|
||||
|
||||
// Received returns true if the info map has been set.
|
||||
func (i *Map) Received() bool {
|
||||
i.mux.RLock()
|
||||
defer i.mux.RUnlock()
|
||||
return i.received
|
||||
}
|
||||
|
||||
// Get returns the value of the info with the given key.
|
||||
func (i *Map) Get(key string) (string, bool, error) {
|
||||
i.mux.RLock()
|
||||
@ -67,7 +74,7 @@ func (i *Map) SetProto(infos []*servicepb.Info) error {
|
||||
defer i.mux.Unlock()
|
||||
|
||||
if i.received {
|
||||
return errors.New("info already set")
|
||||
return ErrInfoAlreadySet
|
||||
}
|
||||
|
||||
infoMap := make(map[string]string)
|
||||
@ -114,3 +121,6 @@ func (i *Map) GetProto() ([]*servicepb.Info, error) {
|
||||
}
|
||||
return infos, nil
|
||||
}
|
||||
|
||||
// ErrInfoAlreadySet is returned if the info map has already been set.
|
||||
var ErrInfoAlreadySet = errors.New("info already set")
|
||||
|
@ -284,6 +284,10 @@ func TestConcurrency(t *testing.T) {
|
||||
_, _ = i.GetProto()
|
||||
}
|
||||
|
||||
received := func() {
|
||||
_ = i.Received()
|
||||
}
|
||||
|
||||
go get()
|
||||
go get()
|
||||
go get()
|
||||
@ -300,4 +304,8 @@ func TestConcurrency(t *testing.T) {
|
||||
go getProto()
|
||||
go getProto()
|
||||
go getProto()
|
||||
go received()
|
||||
go received()
|
||||
go received()
|
||||
go received()
|
||||
}
|
||||
|
@ -9,20 +9,18 @@ package server
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"net"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/bootstrapper"
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/debugd"
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/debugd/deploy"
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/debugd/info"
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/filetransfer"
|
||||
pb "github.com/edgelesssys/constellation/v2/debugd/service"
|
||||
"github.com/edgelesssys/constellation/v2/internal/constants"
|
||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
||||
"go.uber.org/multierr"
|
||||
"go.uber.org/zap"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/keepalive"
|
||||
@ -31,18 +29,18 @@ import (
|
||||
type debugdServer struct {
|
||||
log *logger.Logger
|
||||
serviceManager serviceManager
|
||||
streamer streamer
|
||||
transfer fileTransferer
|
||||
info *info.Map
|
||||
|
||||
pb.UnimplementedDebugdServer
|
||||
}
|
||||
|
||||
// New creates a new debugdServer according to the gRPC spec.
|
||||
func New(log *logger.Logger, serviceManager serviceManager, streamer streamer, infos *info.Map) pb.DebugdServer {
|
||||
func New(log *logger.Logger, serviceManager serviceManager, transfer fileTransferer, infos *info.Map) pb.DebugdServer {
|
||||
return &debugdServer{
|
||||
log: log,
|
||||
serviceManager: serviceManager,
|
||||
streamer: streamer,
|
||||
transfer: transfer,
|
||||
info: infos,
|
||||
}
|
||||
}
|
||||
@ -55,13 +53,23 @@ func (s *debugdServer) SetInfo(ctx context.Context, req *pb.SetInfoRequest) (*pb
|
||||
s.log.Infof("Info is empty")
|
||||
}
|
||||
|
||||
if err := s.info.SetProto(req.Info); err != nil {
|
||||
s.log.With(zap.Error(err)).Errorf("Setting info failed")
|
||||
return &pb.SetInfoResponse{}, err
|
||||
setProtoErr := s.info.SetProto(req.Info)
|
||||
if errors.Is(setProtoErr, info.ErrInfoAlreadySet) {
|
||||
s.log.Warnf("Setting info failed (already set)")
|
||||
return &pb.SetInfoResponse{
|
||||
Status: pb.SetInfoStatus_SET_INFO_ALREADY_SET,
|
||||
}, nil
|
||||
}
|
||||
|
||||
if setProtoErr != nil {
|
||||
s.log.With(zap.Error(setProtoErr)).Errorf("Setting info failed")
|
||||
return nil, setProtoErr
|
||||
}
|
||||
s.log.Infof("Info set")
|
||||
|
||||
return &pb.SetInfoResponse{}, nil
|
||||
return &pb.SetInfoResponse{
|
||||
Status: pb.SetInfoStatus_SET_INFO_SUCCESS,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetInfo returns the info of the debugd instance.
|
||||
@ -76,46 +84,66 @@ func (s *debugdServer) GetInfo(ctx context.Context, req *pb.GetInfoRequest) (*pb
|
||||
return &pb.GetInfoResponse{Info: info}, nil
|
||||
}
|
||||
|
||||
// UploadBootstrapper receives a bootstrapper binary in a stream of chunks and writes to a file.
|
||||
func (s *debugdServer) UploadBootstrapper(stream pb.Debugd_UploadBootstrapperServer) error {
|
||||
startAction := deploy.ServiceManagerRequest{
|
||||
Unit: debugd.BootstrapperSystemdUnitName,
|
||||
Action: deploy.Start,
|
||||
}
|
||||
var responseStatus pb.UploadBootstrapperStatus
|
||||
defer func() {
|
||||
if err := s.serviceManager.SystemdAction(stream.Context(), startAction); err != nil {
|
||||
s.log.With(zap.Error(err)).Errorf("Starting uploaded bootstrapper failed")
|
||||
if responseStatus == pb.UploadBootstrapperStatus_UPLOAD_BOOTSTRAPPER_SUCCESS {
|
||||
responseStatus = pb.UploadBootstrapperStatus_UPLOAD_BOOTSTRAPPER_START_FAILED
|
||||
}
|
||||
}
|
||||
stream.SendAndClose(&pb.UploadBootstrapperResponse{
|
||||
Status: responseStatus,
|
||||
// UploadFiles receives a stream of files (each consisting of a header and a stream of chunks) and writes them to the filesystem.
|
||||
func (s *debugdServer) UploadFiles(stream pb.Debugd_UploadFilesServer) error {
|
||||
s.log.Infof("Received UploadFiles request")
|
||||
err := s.transfer.RecvFiles(stream)
|
||||
switch {
|
||||
case err == nil:
|
||||
s.log.Infof("Uploading files succeeded")
|
||||
case errors.Is(err, filetransfer.ErrReceiveRunning):
|
||||
s.log.Warnf("Upload already in progress")
|
||||
return stream.SendAndClose(&pb.UploadFilesResponse{
|
||||
Status: pb.UploadFilesStatus_UPLOAD_FILES_ALREADY_STARTED,
|
||||
})
|
||||
case errors.Is(err, filetransfer.ErrReceiveFinished):
|
||||
s.log.Warnf("Upload already finished")
|
||||
return stream.SendAndClose(&pb.UploadFilesResponse{
|
||||
Status: pb.UploadFilesStatus_UPLOAD_FILES_ALREADY_FINISHED,
|
||||
})
|
||||
default:
|
||||
s.log.With(zap.Error(err)).Errorf("Uploading files failed")
|
||||
return stream.SendAndClose(&pb.UploadFilesResponse{
|
||||
Status: pb.UploadFilesStatus_UPLOAD_FILES_UPLOAD_FAILED,
|
||||
})
|
||||
}()
|
||||
s.log.Infof("Starting bootstrapper upload")
|
||||
if err := s.streamer.WriteStream(debugd.BootstrapperDeployFilename, stream, true); err != nil {
|
||||
if errors.Is(err, fs.ErrExist) {
|
||||
// bootstrapper was already uploaded
|
||||
s.log.Warnf("Bootstrapper already uploaded")
|
||||
responseStatus = pb.UploadBootstrapperStatus_UPLOAD_BOOTSTRAPPER_FILE_EXISTS
|
||||
return nil
|
||||
}
|
||||
s.log.With(zap.Error(err)).Errorf("Uploading bootstrapper failed")
|
||||
responseStatus = pb.UploadBootstrapperStatus_UPLOAD_BOOTSTRAPPER_UPLOAD_FAILED
|
||||
return fmt.Errorf("uploading bootstrapper: %w", err)
|
||||
}
|
||||
|
||||
s.log.Infof("Successfully uploaded bootstrapper")
|
||||
responseStatus = pb.UploadBootstrapperStatus_UPLOAD_BOOTSTRAPPER_SUCCESS
|
||||
return nil
|
||||
files := s.transfer.GetFiles()
|
||||
var overrideUnitErr error
|
||||
for _, file := range files {
|
||||
if file.OverrideServiceUnit == "" {
|
||||
continue
|
||||
}
|
||||
// continue on error to allow other units to be overridden
|
||||
// TODO: switch to native go multierror once 1.20 is released
|
||||
// err = s.serviceManager.OverrideServiceUnitExecStart(stream.Context(), file.OverrideServiceUnit, file.TargetPath)
|
||||
// if err != nil {
|
||||
// overrideUnitErr = errors.Join(overrideUnitErr, err)
|
||||
// }
|
||||
err = s.serviceManager.OverrideServiceUnitExecStart(stream.Context(), file.OverrideServiceUnit, file.TargetPath)
|
||||
if err != nil {
|
||||
overrideUnitErr = multierr.Append(overrideUnitErr, err)
|
||||
}
|
||||
}
|
||||
|
||||
if overrideUnitErr != nil {
|
||||
s.log.With(zap.Error(overrideUnitErr)).Errorf("Overriding service units failed")
|
||||
return stream.SendAndClose(&pb.UploadFilesResponse{
|
||||
Status: pb.UploadFilesStatus_UPLOAD_FILES_START_FAILED,
|
||||
})
|
||||
}
|
||||
return stream.SendAndClose(&pb.UploadFilesResponse{
|
||||
Status: pb.UploadFilesStatus_UPLOAD_FILES_SUCCESS,
|
||||
})
|
||||
}
|
||||
|
||||
// DownloadBootstrapper streams the local bootstrapper binary to other instances.
|
||||
func (s *debugdServer) DownloadBootstrapper(request *pb.DownloadBootstrapperRequest, stream pb.Debugd_DownloadBootstrapperServer) error {
|
||||
s.log.Infof("Sending bootstrapper to other instance")
|
||||
return s.streamer.ReadStream(debugd.BootstrapperDeployFilename, stream, debugd.Chunksize, true)
|
||||
// DownloadFiles streams the previously received files to other instances.
|
||||
func (s *debugdServer) DownloadFiles(request *pb.DownloadFilesRequest, stream pb.Debugd_DownloadFilesServer) error {
|
||||
s.log.Infof("Sending files to other instance")
|
||||
if !s.transfer.CanSend() {
|
||||
return errors.New("cannot send files at this time")
|
||||
}
|
||||
return s.transfer.SendFiles(stream)
|
||||
}
|
||||
|
||||
// UploadSystemServiceUnits receives systemd service units, writes them to a service file and schedules a daemon-reload.
|
||||
@ -157,9 +185,12 @@ func Start(log *logger.Logger, wg *sync.WaitGroup, serv pb.DebugdServer) {
|
||||
type serviceManager interface {
|
||||
SystemdAction(ctx context.Context, request deploy.ServiceManagerRequest) error
|
||||
WriteSystemdUnitFile(ctx context.Context, unit deploy.SystemdUnit) error
|
||||
OverrideServiceUnitExecStart(ctx context.Context, unitName string, execStart string) error
|
||||
}
|
||||
|
||||
type streamer interface {
|
||||
WriteStream(filename string, stream bootstrapper.ReadChunkStream, showProgress bool) error
|
||||
ReadStream(filename string, stream bootstrapper.WriteChunkStream, chunksize uint, showProgress bool) error
|
||||
type fileTransferer interface {
|
||||
RecvFiles(stream filetransfer.RecvFilesStream) error
|
||||
SendFiles(stream filetransfer.SendFilesStream) error
|
||||
GetFiles() []filetransfer.FileStat
|
||||
CanSend() bool
|
||||
}
|
||||
|
@ -9,15 +9,14 @@ package server
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/bootstrapper"
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/debugd/deploy"
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/debugd/info"
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/filetransfer"
|
||||
pb "github.com/edgelesssys/constellation/v2/debugd/service"
|
||||
"github.com/edgelesssys/constellation/v2/internal/constants"
|
||||
"github.com/edgelesssys/constellation/v2/internal/grpc/testdialer"
|
||||
@ -40,21 +39,23 @@ func TestSetInfo(t *testing.T) {
|
||||
info *info.Map
|
||||
infoReceived bool
|
||||
setInfo []*pb.Info
|
||||
wantErr bool
|
||||
wantStatus pb.SetInfoStatus
|
||||
}{
|
||||
"set info works": {
|
||||
setInfo: []*pb.Info{{Key: "foo", Value: "bar"}},
|
||||
info: info.NewMap(),
|
||||
setInfo: []*pb.Info{{Key: "foo", Value: "bar"}},
|
||||
info: info.NewMap(),
|
||||
wantStatus: pb.SetInfoStatus_SET_INFO_SUCCESS,
|
||||
},
|
||||
"set empty info works": {
|
||||
setInfo: []*pb.Info{},
|
||||
info: info.NewMap(),
|
||||
setInfo: []*pb.Info{},
|
||||
info: info.NewMap(),
|
||||
wantStatus: pb.SetInfoStatus_SET_INFO_SUCCESS,
|
||||
},
|
||||
"set fails when info already set": {
|
||||
info: info.NewMap(),
|
||||
infoReceived: true,
|
||||
setInfo: []*pb.Info{{Key: "foo", Value: "bar"}},
|
||||
wantErr: true,
|
||||
wantStatus: pb.SetInfoStatus_SET_INFO_ALREADY_SET,
|
||||
},
|
||||
}
|
||||
|
||||
@ -78,19 +79,16 @@ func TestSetInfo(t *testing.T) {
|
||||
defer conn.Close()
|
||||
client := pb.NewDebugdClient(conn)
|
||||
|
||||
_, err = client.SetInfo(context.Background(), &pb.SetInfoRequest{Info: tc.setInfo})
|
||||
setInfoStatus, err := client.SetInfo(context.Background(), &pb.SetInfoRequest{Info: tc.setInfo})
|
||||
grpcServ.GracefulStop()
|
||||
|
||||
if tc.wantErr {
|
||||
assert.Error(err)
|
||||
} else {
|
||||
assert.NoError(err)
|
||||
assert.Equal(tc.wantStatus, setInfoStatus.Status)
|
||||
for i := range tc.setInfo {
|
||||
value, ok, err := tc.info.Get(tc.setInfo[i].Key)
|
||||
assert.NoError(err)
|
||||
for i := range tc.setInfo {
|
||||
value, ok, err := tc.info.Get(tc.setInfo[i].Key)
|
||||
assert.NoError(err)
|
||||
assert.True(ok)
|
||||
assert.Equal(tc.setInfo[i].Value, value)
|
||||
}
|
||||
assert.True(ok)
|
||||
assert.Equal(tc.setInfo[i].Value, value)
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -152,35 +150,36 @@ func TestGetInfo(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestUploadBootstrapper(t *testing.T) {
|
||||
func TestUploadFiles(t *testing.T) {
|
||||
endpoint := "192.0.2.1:" + strconv.Itoa(constants.DebugdPort)
|
||||
|
||||
testCases := map[string]struct {
|
||||
serviceManager stubServiceManager
|
||||
streamer fakeStreamer
|
||||
uploadChunks [][]byte
|
||||
wantErr bool
|
||||
wantResponseStatus pb.UploadBootstrapperStatus
|
||||
wantFile bool
|
||||
wantChunks [][]byte
|
||||
files []filetransfer.FileStat
|
||||
recvFilesErr error
|
||||
wantResponseStatus pb.UploadFilesStatus
|
||||
wantOverrideCalls []struct{ UnitName, ExecStart string }
|
||||
}{
|
||||
"upload works": {
|
||||
uploadChunks: [][]byte{[]byte("test")},
|
||||
wantFile: true,
|
||||
wantChunks: [][]byte{[]byte("test")},
|
||||
wantResponseStatus: pb.UploadBootstrapperStatus_UPLOAD_BOOTSTRAPPER_SUCCESS,
|
||||
files: []filetransfer.FileStat{
|
||||
{SourcePath: "source/testA", TargetPath: "target/testA", Mode: 0o644, OverrideServiceUnit: "testA"},
|
||||
{SourcePath: "source/testB", TargetPath: "target/testB", Mode: 0o644},
|
||||
},
|
||||
wantOverrideCalls: []struct{ UnitName, ExecStart string }{
|
||||
{"testA", "target/testA"},
|
||||
},
|
||||
wantResponseStatus: pb.UploadFilesStatus_UPLOAD_FILES_SUCCESS,
|
||||
},
|
||||
"recv fails": {
|
||||
streamer: fakeStreamer{writeStreamErr: errors.New("recv error")},
|
||||
wantResponseStatus: pb.UploadBootstrapperStatus_UPLOAD_BOOTSTRAPPER_UPLOAD_FAILED,
|
||||
wantErr: true,
|
||||
recvFilesErr: errors.New("recv error"),
|
||||
wantResponseStatus: pb.UploadFilesStatus_UPLOAD_FILES_UPLOAD_FAILED,
|
||||
},
|
||||
"starting bootstrapper fails": {
|
||||
uploadChunks: [][]byte{[]byte("test")},
|
||||
serviceManager: stubServiceManager{systemdActionErr: errors.New("starting bootstrapper error")},
|
||||
wantFile: true,
|
||||
wantChunks: [][]byte{[]byte("test")},
|
||||
wantResponseStatus: pb.UploadBootstrapperStatus_UPLOAD_BOOTSTRAPPER_START_FAILED,
|
||||
"upload in progress": {
|
||||
recvFilesErr: filetransfer.ErrReceiveRunning,
|
||||
wantResponseStatus: pb.UploadFilesStatus_UPLOAD_FILES_ALREADY_STARTED,
|
||||
},
|
||||
"upload already finished": {
|
||||
recvFilesErr: filetransfer.ErrReceiveFinished,
|
||||
wantResponseStatus: pb.UploadFilesStatus_UPLOAD_FILES_ALREADY_FINISHED,
|
||||
},
|
||||
}
|
||||
|
||||
@ -189,60 +188,49 @@ func TestUploadBootstrapper(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
require := require.New(t)
|
||||
|
||||
serviceMgr := &stubServiceManager{}
|
||||
transfer := &stubTransfer{files: tc.files, recvFilesErr: tc.recvFilesErr}
|
||||
|
||||
serv := debugdServer{
|
||||
log: logger.NewTest(t),
|
||||
serviceManager: &tc.serviceManager,
|
||||
streamer: &tc.streamer,
|
||||
serviceManager: serviceMgr,
|
||||
transfer: transfer,
|
||||
}
|
||||
|
||||
grpcServ, conn, err := setupServerWithConn(endpoint, &serv)
|
||||
require.NoError(err)
|
||||
defer conn.Close()
|
||||
client := pb.NewDebugdClient(conn)
|
||||
stream, err := client.UploadBootstrapper(context.Background())
|
||||
stream, err := client.UploadFiles(context.Background())
|
||||
require.NoError(err)
|
||||
require.NoError(fakeWrite(stream, tc.uploadChunks))
|
||||
resp, err := stream.CloseAndRecv()
|
||||
|
||||
grpcServ.GracefulStop()
|
||||
|
||||
if tc.wantErr {
|
||||
assert.Error(err)
|
||||
return
|
||||
}
|
||||
require.NoError(err)
|
||||
assert.Equal(tc.wantResponseStatus, resp.Status)
|
||||
if tc.wantFile {
|
||||
assert.Equal(tc.wantChunks, tc.streamer.writeStreamChunks)
|
||||
assert.Equal("/run/state/bin/bootstrapper", tc.streamer.writeStreamFilename)
|
||||
} else {
|
||||
assert.Empty(tc.streamer.writeStreamChunks)
|
||||
assert.Empty(tc.streamer.writeStreamFilename)
|
||||
}
|
||||
assert.Equal(tc.wantOverrideCalls, serviceMgr.overrideCalls)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDownloadBootstrapper(t *testing.T) {
|
||||
func TestDownloadFiles(t *testing.T) {
|
||||
endpoint := "192.0.2.1:" + strconv.Itoa(constants.DebugdPort)
|
||||
|
||||
testCases := map[string]struct {
|
||||
serviceManager stubServiceManager
|
||||
request *pb.DownloadBootstrapperRequest
|
||||
streamer fakeStreamer
|
||||
wantErr bool
|
||||
wantChunks [][]byte
|
||||
request *pb.DownloadFilesRequest
|
||||
canSend bool
|
||||
wantRecvErr bool
|
||||
wantSendFileCalls int
|
||||
}{
|
||||
"download works": {
|
||||
request: &pb.DownloadBootstrapperRequest{},
|
||||
streamer: fakeStreamer{readStreamChunks: [][]byte{[]byte("test")}},
|
||||
wantErr: false,
|
||||
wantChunks: [][]byte{[]byte("test")},
|
||||
request: &pb.DownloadFilesRequest{},
|
||||
canSend: true,
|
||||
wantSendFileCalls: 1,
|
||||
},
|
||||
"download fails": {
|
||||
request: &pb.DownloadBootstrapperRequest{},
|
||||
streamer: fakeStreamer{readStreamErr: errors.New("read bootstrapper fails")},
|
||||
wantErr: true,
|
||||
"transfer is not ready for sending": {
|
||||
request: &pb.DownloadFilesRequest{},
|
||||
wantRecvErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
@ -251,28 +239,29 @@ func TestDownloadBootstrapper(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
require := require.New(t)
|
||||
|
||||
transfer := &stubTransfer{canSend: tc.canSend}
|
||||
serv := debugdServer{
|
||||
log: logger.NewTest(t),
|
||||
serviceManager: &tc.serviceManager,
|
||||
streamer: &tc.streamer,
|
||||
log: logger.NewTest(t),
|
||||
transfer: transfer,
|
||||
}
|
||||
|
||||
grpcServ, conn, err := setupServerWithConn(endpoint, &serv)
|
||||
require.NoError(err)
|
||||
defer conn.Close()
|
||||
client := pb.NewDebugdClient(conn)
|
||||
stream, err := client.DownloadBootstrapper(context.Background(), tc.request)
|
||||
stream, err := client.DownloadFiles(context.Background(), tc.request)
|
||||
require.NoError(err)
|
||||
chunks, err := fakeRead(stream)
|
||||
grpcServ.GracefulStop()
|
||||
|
||||
if tc.wantErr {
|
||||
assert.Error(err)
|
||||
return
|
||||
_, recvErr := stream.Recv()
|
||||
if tc.wantRecvErr {
|
||||
require.Error(recvErr)
|
||||
} else {
|
||||
require.ErrorIs(recvErr, io.EOF)
|
||||
}
|
||||
require.NoError(stream.CloseSend())
|
||||
grpcServ.GracefulStop()
|
||||
require.NoError(err)
|
||||
assert.Equal(tc.wantChunks, chunks)
|
||||
assert.Equal("/run/state/bin/bootstrapper", tc.streamer.readStreamFilename)
|
||||
|
||||
assert.Equal(tc.wantSendFileCalls, transfer.sendFilesCount)
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -334,7 +323,6 @@ func TestUploadSystemServiceUnits(t *testing.T) {
|
||||
serv := debugdServer{
|
||||
log: logger.NewTest(t),
|
||||
serviceManager: &tc.serviceManager,
|
||||
streamer: &fakeStreamer{},
|
||||
}
|
||||
grpcServ, conn, err := setupServerWithConn(endpoint, &serv)
|
||||
require.NoError(err)
|
||||
@ -357,10 +345,13 @@ func TestUploadSystemServiceUnits(t *testing.T) {
|
||||
}
|
||||
|
||||
type stubServiceManager struct {
|
||||
requests []deploy.ServiceManagerRequest
|
||||
unitFiles []deploy.SystemdUnit
|
||||
systemdActionErr error
|
||||
writeSystemdUnitFileErr error
|
||||
requests []deploy.ServiceManagerRequest
|
||||
unitFiles []deploy.SystemdUnit
|
||||
overrideCalls []struct{ UnitName, ExecStart string }
|
||||
|
||||
systemdActionErr error
|
||||
writeSystemdUnitFileErr error
|
||||
overrideServiceUnitExecStartErr error
|
||||
}
|
||||
|
||||
func (s *stubServiceManager) SystemdAction(ctx context.Context, request deploy.ServiceManagerRequest) error {
|
||||
@ -373,6 +364,13 @@ func (s *stubServiceManager) WriteSystemdUnitFile(ctx context.Context, unit depl
|
||||
return s.writeSystemdUnitFileErr
|
||||
}
|
||||
|
||||
func (s *stubServiceManager) OverrideServiceUnitExecStart(ctx context.Context, unitName string, execStart string) error {
|
||||
s.overrideCalls = append(s.overrideCalls, struct {
|
||||
UnitName, ExecStart string
|
||||
}{UnitName: unitName, ExecStart: execStart})
|
||||
return s.overrideServiceUnitExecStartErr
|
||||
}
|
||||
|
||||
type netDialer interface {
|
||||
DialContext(ctx context.Context, network, address string) (net.Conn, error)
|
||||
}
|
||||
@ -386,37 +384,31 @@ func dial(ctx context.Context, dialer netDialer, target string) (*grpc.ClientCon
|
||||
)
|
||||
}
|
||||
|
||||
type fakeStreamer struct {
|
||||
writeStreamChunks [][]byte
|
||||
writeStreamFilename string
|
||||
writeStreamErr error
|
||||
readStreamChunks [][]byte
|
||||
readStreamFilename string
|
||||
readStreamErr error
|
||||
type stubTransfer struct {
|
||||
recvFilesCount int
|
||||
sendFilesCount int
|
||||
files []filetransfer.FileStat
|
||||
canSend bool
|
||||
recvFilesErr error
|
||||
sendFilesErr error
|
||||
}
|
||||
|
||||
func (f *fakeStreamer) WriteStream(filename string, stream bootstrapper.ReadChunkStream, showProgress bool) error {
|
||||
f.writeStreamFilename = filename
|
||||
for {
|
||||
chunk, err := stream.Recv()
|
||||
if err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
return f.writeStreamErr
|
||||
}
|
||||
return fmt.Errorf("reading stream: %w", err)
|
||||
}
|
||||
f.writeStreamChunks = append(f.writeStreamChunks, chunk.Content)
|
||||
}
|
||||
func (t *stubTransfer) RecvFiles(_ filetransfer.RecvFilesStream) error {
|
||||
t.recvFilesCount++
|
||||
return t.recvFilesErr
|
||||
}
|
||||
|
||||
func (f *fakeStreamer) ReadStream(filename string, stream bootstrapper.WriteChunkStream, chunksize uint, showProgress bool) error {
|
||||
f.readStreamFilename = filename
|
||||
for _, chunk := range f.readStreamChunks {
|
||||
if err := stream.Send(&pb.Chunk{Content: chunk}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
return f.readStreamErr
|
||||
func (t *stubTransfer) SendFiles(_ filetransfer.SendFilesStream) error {
|
||||
t.sendFilesCount++
|
||||
return t.sendFilesErr
|
||||
}
|
||||
|
||||
func (t *stubTransfer) GetFiles() []filetransfer.FileStat {
|
||||
return t.files
|
||||
}
|
||||
|
||||
func (t *stubTransfer) CanSend() bool {
|
||||
return t.canSend
|
||||
}
|
||||
|
||||
func setupServerWithConn(endpoint string, serv *debugdServer) (*grpc.Server, *grpc.ClientConn, error) {
|
||||
@ -433,29 +425,3 @@ func setupServerWithConn(endpoint string, serv *debugdServer) (*grpc.Server, *gr
|
||||
|
||||
return grpcServ, conn, nil
|
||||
}
|
||||
|
||||
func fakeWrite(stream bootstrapper.WriteChunkStream, chunks [][]byte) error {
|
||||
for _, chunk := range chunks {
|
||||
err := stream.Send(&pb.Chunk{
|
||||
Content: chunk,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func fakeRead(stream bootstrapper.ReadChunkStream) ([][]byte, error) {
|
||||
var chunks [][]byte
|
||||
for {
|
||||
chunk, err := stream.Recv()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return chunks, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
chunks = append(chunks, chunk.Content)
|
||||
}
|
||||
}
|
||||
|
47
debugd/internal/filetransfer/chunkstream.go
Normal file
47
debugd/internal/filetransfer/chunkstream.go
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
Copyright (c) Edgeless Systems GmbH
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package filetransfer
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
pb "github.com/edgelesssys/constellation/v2/debugd/service"
|
||||
)
|
||||
|
||||
// recvChunkStream is a wrapper around a RecvFilesStream that only returns chunks.
|
||||
type recvChunkStream struct {
|
||||
stream RecvFilesStream
|
||||
}
|
||||
|
||||
// Recv receives a FileTransferMessage and returns the chunk.
|
||||
func (s *recvChunkStream) Recv() (*pb.Chunk, error) {
|
||||
msg, err := s.stream.Recv()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
chunk := msg.GetChunk()
|
||||
if chunk == nil {
|
||||
return nil, errors.New("expected chunk")
|
||||
}
|
||||
return chunk, nil
|
||||
}
|
||||
|
||||
// sendChunkStream is a wrapper around a SendFilesStream that wraps chunks for every message.
|
||||
type sendChunkStream struct {
|
||||
stream SendFilesStream
|
||||
}
|
||||
|
||||
// Send wraps the given chunk in a FileTransferMessage and sends it.
|
||||
func (s *sendChunkStream) Send(chunk *pb.Chunk) error {
|
||||
chunkMessage := &pb.FileTransferMessage_Chunk{
|
||||
Chunk: chunk,
|
||||
}
|
||||
message := &pb.FileTransferMessage{
|
||||
Kind: chunkMessage,
|
||||
}
|
||||
return s.stream.Send(message)
|
||||
}
|
134
debugd/internal/filetransfer/chunkstream_test.go
Normal file
134
debugd/internal/filetransfer/chunkstream_test.go
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
Copyright (c) Edgeless Systems GmbH
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package filetransfer
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
pb "github.com/edgelesssys/constellation/v2/debugd/service"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestRecv(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
stream stubRecvFilesStream
|
||||
wantChunk *pb.Chunk
|
||||
wantErr bool
|
||||
}{
|
||||
"chunk is received": {
|
||||
stream: stubRecvFilesStream{
|
||||
msg: &pb.FileTransferMessage{
|
||||
Kind: &pb.FileTransferMessage_Chunk{
|
||||
Chunk: &pb.Chunk{
|
||||
Content: []byte("test"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantChunk: &pb.Chunk{
|
||||
Content: []byte("test"),
|
||||
},
|
||||
},
|
||||
"wrong type": {
|
||||
stream: stubRecvFilesStream{
|
||||
msg: &pb.FileTransferMessage{
|
||||
Kind: &pb.FileTransferMessage_Header{},
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
"empty msg": {
|
||||
stream: stubRecvFilesStream{},
|
||||
wantErr: true,
|
||||
},
|
||||
"recv fails": {
|
||||
stream: stubRecvFilesStream{
|
||||
recvErr: errors.New("someErr"),
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
require := require.New(t)
|
||||
|
||||
stream := recvChunkStream{stream: &tc.stream}
|
||||
chunk, err := stream.Recv()
|
||||
|
||||
if tc.wantErr {
|
||||
assert.Error(err)
|
||||
return
|
||||
}
|
||||
require.NoError(err)
|
||||
assert.Equal(tc.wantChunk, chunk)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSend(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
stream stubSendFilesStream
|
||||
chunk *pb.Chunk
|
||||
wantMsgs []*pb.FileTransferMessage
|
||||
wantErr bool
|
||||
}{
|
||||
"chunk is wrapped correctly": {
|
||||
chunk: &pb.Chunk{
|
||||
Content: []byte("test"),
|
||||
},
|
||||
wantMsgs: []*pb.FileTransferMessage{
|
||||
{
|
||||
Kind: &pb.FileTransferMessage_Chunk{
|
||||
Chunk: &pb.Chunk{
|
||||
Content: []byte("test"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
require := require.New(t)
|
||||
|
||||
stream := sendChunkStream{stream: &tc.stream}
|
||||
err := stream.Send(tc.chunk)
|
||||
|
||||
if tc.wantErr {
|
||||
assert.Error(err)
|
||||
return
|
||||
}
|
||||
require.NoError(err)
|
||||
assert.EqualValues(tc.wantMsgs, tc.stream.msgs)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type stubRecvFilesStream struct {
|
||||
msg *pb.FileTransferMessage
|
||||
recvErr error
|
||||
}
|
||||
|
||||
func (s *stubRecvFilesStream) Recv() (*pb.FileTransferMessage, error) {
|
||||
return s.msg, s.recvErr
|
||||
}
|
||||
|
||||
type stubSendFilesStream struct {
|
||||
msgs []*pb.FileTransferMessage
|
||||
sendErr error
|
||||
}
|
||||
|
||||
func (s *stubSendFilesStream) Send(msg *pb.FileTransferMessage) error {
|
||||
s.msgs = append(s.msgs, msg)
|
||||
return s.sendErr
|
||||
}
|
233
debugd/internal/filetransfer/filetransfer.go
Normal file
233
debugd/internal/filetransfer/filetransfer.go
Normal file
@ -0,0 +1,233 @@
|
||||
/*
|
||||
Copyright (c) Edgeless Systems GmbH
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package filetransfer
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"io/fs"
|
||||
"sync"
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/debugd"
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/filetransfer/streamer"
|
||||
pb "github.com/edgelesssys/constellation/v2/debugd/service"
|
||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// RecvFilesStream is a stream that receives FileTransferMessages.
|
||||
type RecvFilesStream interface {
|
||||
Recv() (*pb.FileTransferMessage, error)
|
||||
}
|
||||
|
||||
// SendFilesStream is a stream that sends FileTransferMessages.
|
||||
type SendFilesStream interface {
|
||||
Send(*pb.FileTransferMessage) error
|
||||
}
|
||||
|
||||
// FileTransferer manages sending and receiving of files.
|
||||
type FileTransferer struct {
|
||||
mux sync.RWMutex
|
||||
log *logger.Logger
|
||||
receiveStarted bool
|
||||
receiveFinished bool
|
||||
files []FileStat
|
||||
streamer streamReadWriter
|
||||
showProgress bool
|
||||
}
|
||||
|
||||
// New creates a new FileTransferer.
|
||||
func New(log *logger.Logger, streamer streamReadWriter, showProgress bool) *FileTransferer {
|
||||
return &FileTransferer{
|
||||
log: log,
|
||||
streamer: streamer,
|
||||
showProgress: showProgress,
|
||||
}
|
||||
}
|
||||
|
||||
// SendFiles sends files to the given stream.
|
||||
func (s *FileTransferer) SendFiles(stream SendFilesStream) error {
|
||||
s.mux.RLock()
|
||||
defer s.mux.RUnlock()
|
||||
if !s.receiveFinished {
|
||||
return errors.New("cannot send files before receiving them")
|
||||
}
|
||||
for _, file := range s.files {
|
||||
if err := s.handleFileSend(stream, file); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RecvFiles receives files from the given stream.
|
||||
func (s *FileTransferer) RecvFiles(stream RecvFilesStream) (err error) {
|
||||
if err := s.startRecv(); err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
s.abortRecv()
|
||||
} else {
|
||||
s.finishRecv()
|
||||
}
|
||||
}()
|
||||
var done bool
|
||||
for !done && err == nil {
|
||||
done, err = s.handleFileRecv(stream)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// GetFiles returns the a copy of the list of files that have been received.
|
||||
func (s *FileTransferer) GetFiles() []FileStat {
|
||||
s.mux.RLock()
|
||||
defer s.mux.RUnlock()
|
||||
res := make([]FileStat, len(s.files))
|
||||
copy(res, s.files)
|
||||
return res
|
||||
}
|
||||
|
||||
// SetFiles sets the list of files that can be sent.
|
||||
func (s *FileTransferer) SetFiles(files []FileStat) {
|
||||
s.mux.Lock()
|
||||
defer s.mux.Unlock()
|
||||
res := make([]FileStat, len(files))
|
||||
copy(res, files)
|
||||
s.files = res
|
||||
s.receiveFinished = true
|
||||
}
|
||||
|
||||
// CanSend returns true if the file receive has finished.
|
||||
// This is called to determine if a debugd instance can request files from this server.
|
||||
func (s *FileTransferer) CanSend() bool {
|
||||
s.mux.RLock()
|
||||
defer s.mux.RUnlock()
|
||||
ret := s.receiveFinished
|
||||
return ret
|
||||
}
|
||||
|
||||
func (s *FileTransferer) handleFileSend(stream SendFilesStream, file FileStat) error {
|
||||
header := &pb.FileTransferMessage_Header{
|
||||
Header: &pb.FileTransferHeader{
|
||||
TargetPath: file.TargetPath,
|
||||
Mode: uint32(file.Mode),
|
||||
},
|
||||
}
|
||||
if file.OverrideServiceUnit != "" {
|
||||
header.Header.OverrideServiceUnit = &file.OverrideServiceUnit
|
||||
}
|
||||
if err := stream.Send(&pb.FileTransferMessage{Kind: header}); err != nil {
|
||||
return err
|
||||
}
|
||||
sendChunkStream := &sendChunkStream{stream: stream}
|
||||
return s.streamer.ReadStream(file.SourcePath, sendChunkStream, debugd.Chunksize, s.showProgress)
|
||||
}
|
||||
|
||||
// handleFileRecv handles the file receive of a single file.
|
||||
// It returns true if the stream is finished (all of the file consumed) and false otherwise.
|
||||
func (s *FileTransferer) handleFileRecv(stream RecvFilesStream) (bool, error) {
|
||||
// first message must be a header message
|
||||
msg, err := stream.Recv()
|
||||
switch {
|
||||
case err == nil:
|
||||
// nop
|
||||
case errors.Is(err, io.EOF):
|
||||
return true, nil // stream is finished
|
||||
default:
|
||||
return false, err
|
||||
}
|
||||
header := msg.GetHeader()
|
||||
if header == nil {
|
||||
return false, errors.New("first message must be a header message")
|
||||
}
|
||||
s.log.Infof("Starting file receive of %q", header.TargetPath)
|
||||
s.addFile(FileStat{
|
||||
SourcePath: header.TargetPath,
|
||||
TargetPath: header.TargetPath,
|
||||
Mode: fs.FileMode(header.Mode),
|
||||
OverrideServiceUnit: func() string {
|
||||
if header.OverrideServiceUnit != nil {
|
||||
return *header.OverrideServiceUnit
|
||||
}
|
||||
return ""
|
||||
}(),
|
||||
})
|
||||
recvChunkStream := &recvChunkStream{stream: stream}
|
||||
if err := s.streamer.WriteStream(header.TargetPath, recvChunkStream, s.showProgress); err != nil {
|
||||
s.log.With(zap.Error(err)).Errorf("Receive of file %q failed", header.TargetPath)
|
||||
return false, err
|
||||
}
|
||||
s.log.Infof("Finished file receive of %q", header.TargetPath)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// startRecv marks the file receive as started. It returns an error if receiving has already started.
|
||||
func (s *FileTransferer) startRecv() error {
|
||||
s.mux.Lock()
|
||||
defer s.mux.Unlock()
|
||||
switch {
|
||||
case s.receiveFinished:
|
||||
return ErrReceiveFinished
|
||||
case s.receiveStarted:
|
||||
return ErrReceiveRunning
|
||||
}
|
||||
s.receiveStarted = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// abortRecv marks the file receive as failed.
|
||||
// This allows for a retry of the file receive.
|
||||
func (s *FileTransferer) abortRecv() {
|
||||
s.mux.Lock()
|
||||
defer s.mux.Unlock()
|
||||
s.receiveStarted = false
|
||||
s.files = nil
|
||||
}
|
||||
|
||||
// finishRecv marks the file receive as completed.
|
||||
// This allows other debugd instances to request files from this server.
|
||||
func (s *FileTransferer) finishRecv() {
|
||||
s.mux.Lock()
|
||||
defer s.mux.Unlock()
|
||||
s.receiveStarted = false
|
||||
s.receiveFinished = true
|
||||
}
|
||||
|
||||
// addFile adds a file to the list of received files.
|
||||
func (s *FileTransferer) addFile(file FileStat) {
|
||||
s.mux.Lock()
|
||||
defer s.mux.Unlock()
|
||||
s.files = append(s.files, file)
|
||||
}
|
||||
|
||||
// FileStat contains the metadata of a file that can be up/downloaded.
|
||||
type FileStat struct {
|
||||
SourcePath string
|
||||
TargetPath string
|
||||
Mode fs.FileMode
|
||||
OverrideServiceUnit string // optional name of the service unit to override
|
||||
}
|
||||
|
||||
var (
|
||||
// ErrReceiveRunning is returned if a file receive is already running.
|
||||
ErrReceiveRunning = errors.New("receive already running")
|
||||
// ErrReceiveFinished is returned if a file receive has already finished.
|
||||
ErrReceiveFinished = errors.New("receive finished")
|
||||
)
|
||||
|
||||
const (
|
||||
// ShowProgress indicates that progress should be shown.
|
||||
ShowProgress = true
|
||||
// DontShowProgress indicates that progress should not be shown.
|
||||
DontShowProgress = false
|
||||
)
|
||||
|
||||
type streamReadWriter interface {
|
||||
WriteStream(filename string, stream streamer.ReadChunkStream, showProgress bool) error
|
||||
ReadStream(filename string, stream streamer.WriteChunkStream, chunksize uint, showProgress bool) error
|
||||
}
|
411
debugd/internal/filetransfer/filetransfer_test.go
Normal file
411
debugd/internal/filetransfer/filetransfer_test.go
Normal file
@ -0,0 +1,411 @@
|
||||
/*
|
||||
Copyright (c) Edgeless Systems GmbH
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package filetransfer
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/debugd/internal/filetransfer/streamer"
|
||||
pb "github.com/edgelesssys/constellation/v2/debugd/service"
|
||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/goleak"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
goleak.VerifyTestMain(m)
|
||||
}
|
||||
|
||||
func TestSendFiles(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
files *[]FileStat
|
||||
sendErr error
|
||||
readStreamErr error
|
||||
wantHeaders []*pb.FileTransferMessage
|
||||
wantErr bool
|
||||
}{
|
||||
"can send files": {
|
||||
files: &[]FileStat{
|
||||
{
|
||||
TargetPath: "testfileA",
|
||||
Mode: 0o644,
|
||||
OverrideServiceUnit: "somesvcA",
|
||||
},
|
||||
{
|
||||
TargetPath: "testfileB",
|
||||
Mode: 0o644,
|
||||
OverrideServiceUnit: "somesvcB",
|
||||
},
|
||||
},
|
||||
wantHeaders: []*pb.FileTransferMessage{
|
||||
{
|
||||
Kind: &pb.FileTransferMessage_Header{
|
||||
Header: &pb.FileTransferHeader{
|
||||
TargetPath: "testfileA",
|
||||
Mode: 0o644,
|
||||
OverrideServiceUnit: func() *string { s := "somesvcA"; return &s }(),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Kind: &pb.FileTransferMessage_Header{
|
||||
Header: &pb.FileTransferHeader{
|
||||
TargetPath: "testfileB",
|
||||
Mode: 0o644,
|
||||
OverrideServiceUnit: func() *string { s := "somesvcB"; return &s }(),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"no files set": {
|
||||
wantErr: true,
|
||||
},
|
||||
"send fails": {
|
||||
files: &[]FileStat{
|
||||
{
|
||||
TargetPath: "testfileA",
|
||||
Mode: 0o644,
|
||||
OverrideServiceUnit: "somesvcA",
|
||||
},
|
||||
},
|
||||
sendErr: errors.New("send failed"),
|
||||
wantErr: true,
|
||||
},
|
||||
"read stream fails": {
|
||||
files: &[]FileStat{
|
||||
{
|
||||
TargetPath: "testfileA",
|
||||
Mode: 0o644,
|
||||
OverrideServiceUnit: "somesvcA",
|
||||
},
|
||||
},
|
||||
readStreamErr: errors.New("read stream failed"),
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
require := require.New(t)
|
||||
|
||||
streamer := &stubStreamReadWriter{readStreamErr: tc.readStreamErr}
|
||||
stream := &stubSendFilesStream{sendErr: tc.sendErr}
|
||||
transfer := New(logger.NewTest(t), streamer, false)
|
||||
if tc.files != nil {
|
||||
transfer.SetFiles(*tc.files)
|
||||
}
|
||||
err := transfer.SendFiles(stream)
|
||||
|
||||
if tc.wantErr {
|
||||
assert.Error(err)
|
||||
return
|
||||
}
|
||||
require.NoError(err)
|
||||
assert.Equal(tc.wantHeaders, stream.msgs)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRecvFiles(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
msgs []*pb.FileTransferMessage
|
||||
recvAlreadyStarted bool
|
||||
recvAlreadyFinished bool
|
||||
recvErr error
|
||||
writeStreamErr error
|
||||
wantFiles []FileStat
|
||||
wantErr bool
|
||||
}{
|
||||
"can recv files": {
|
||||
msgs: []*pb.FileTransferMessage{
|
||||
{
|
||||
Kind: &pb.FileTransferMessage_Header{
|
||||
Header: &pb.FileTransferHeader{
|
||||
TargetPath: "testfileA",
|
||||
Mode: 0o644,
|
||||
OverrideServiceUnit: func() *string { s := "somesvcA"; return &s }(),
|
||||
},
|
||||
},
|
||||
},
|
||||
// Chunk messages left out since they would be consumed by the streamReadWriter
|
||||
{
|
||||
Kind: &pb.FileTransferMessage_Header{
|
||||
Header: &pb.FileTransferHeader{
|
||||
TargetPath: "testfileB",
|
||||
Mode: 0o644,
|
||||
},
|
||||
},
|
||||
},
|
||||
// Chunk messages left out since they would be consumed by the streamReadWriter
|
||||
},
|
||||
wantFiles: []FileStat{
|
||||
{
|
||||
SourcePath: "testfileA",
|
||||
TargetPath: "testfileA",
|
||||
Mode: 0o644,
|
||||
OverrideServiceUnit: "somesvcA",
|
||||
},
|
||||
{
|
||||
SourcePath: "testfileB",
|
||||
TargetPath: "testfileB",
|
||||
Mode: 0o644,
|
||||
},
|
||||
},
|
||||
},
|
||||
"no messages": {},
|
||||
"recv fails": {
|
||||
recvErr: errors.New("recv failed"),
|
||||
wantErr: true,
|
||||
},
|
||||
"first recv does not yield file header": {
|
||||
msgs: []*pb.FileTransferMessage{
|
||||
{
|
||||
Kind: &pb.FileTransferMessage_Chunk{},
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
"write stream fails": {
|
||||
msgs: []*pb.FileTransferMessage{
|
||||
{
|
||||
Kind: &pb.FileTransferMessage_Header{
|
||||
Header: &pb.FileTransferHeader{
|
||||
TargetPath: "testfileA",
|
||||
Mode: 0o644,
|
||||
OverrideServiceUnit: func() *string { s := "somesvcA"; return &s }(),
|
||||
},
|
||||
},
|
||||
},
|
||||
// Chunk messages left out since they would be consumed by the streamReadWriter
|
||||
},
|
||||
writeStreamErr: errors.New("write stream failed"),
|
||||
wantErr: true,
|
||||
},
|
||||
"recv has already started": {
|
||||
msgs: []*pb.FileTransferMessage{
|
||||
{
|
||||
Kind: &pb.FileTransferMessage_Header{
|
||||
Header: &pb.FileTransferHeader{
|
||||
TargetPath: "testfileA",
|
||||
Mode: 0o644,
|
||||
OverrideServiceUnit: func() *string { s := "somesvcA"; return &s }(),
|
||||
},
|
||||
},
|
||||
},
|
||||
// Chunk messages left out since they would be consumed by the streamReadWriter
|
||||
},
|
||||
recvAlreadyStarted: true,
|
||||
wantErr: true,
|
||||
},
|
||||
"recv has already finished": {
|
||||
msgs: []*pb.FileTransferMessage{
|
||||
{
|
||||
Kind: &pb.FileTransferMessage_Header{
|
||||
Header: &pb.FileTransferHeader{
|
||||
TargetPath: "testfileA",
|
||||
Mode: 0o644,
|
||||
OverrideServiceUnit: func() *string { s := "somesvcA"; return &s }(),
|
||||
},
|
||||
},
|
||||
},
|
||||
// Chunk messages left out since they would be consumed by the streamReadWriter
|
||||
},
|
||||
recvAlreadyFinished: true,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
require := require.New(t)
|
||||
|
||||
streamer := &stubStreamReadWriter{writeStreamErr: tc.writeStreamErr}
|
||||
stream := &fakeRecvFilesStream{msgs: tc.msgs, recvErr: tc.recvErr}
|
||||
transfer := New(logger.NewTest(t), streamer, false)
|
||||
if tc.recvAlreadyStarted {
|
||||
transfer.receiveStarted = true
|
||||
}
|
||||
if tc.recvAlreadyFinished {
|
||||
transfer.receiveFinished = true
|
||||
}
|
||||
err := transfer.RecvFiles(stream)
|
||||
|
||||
if tc.wantErr {
|
||||
assert.Error(err)
|
||||
return
|
||||
}
|
||||
require.NoError(err)
|
||||
assert.Equal(tc.wantFiles, transfer.files)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetSetFiles(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
setFiles *[]FileStat
|
||||
wantFiles []FileStat
|
||||
wantErr bool
|
||||
}{
|
||||
"no files": {
|
||||
wantFiles: []FileStat{},
|
||||
},
|
||||
"files": {
|
||||
setFiles: &[]FileStat{
|
||||
{
|
||||
SourcePath: "testfileA",
|
||||
TargetPath: "testfileA",
|
||||
Mode: 0o644,
|
||||
OverrideServiceUnit: "somesvcA",
|
||||
},
|
||||
},
|
||||
wantFiles: []FileStat{
|
||||
{
|
||||
SourcePath: "testfileA",
|
||||
TargetPath: "testfileA",
|
||||
Mode: 0o644,
|
||||
OverrideServiceUnit: "somesvcA",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
streamer := &dummyStreamReadWriter{}
|
||||
transfer := New(logger.NewTest(t), streamer, false)
|
||||
if tc.setFiles != nil {
|
||||
transfer.SetFiles(*tc.setFiles)
|
||||
}
|
||||
gotFiles := transfer.GetFiles()
|
||||
assert.Equal(tc.wantFiles, gotFiles)
|
||||
assert.Equal(tc.setFiles != nil, transfer.receiveFinished)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCanSend(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
streamer := &stubStreamReadWriter{}
|
||||
stream := &stubRecvFilesStream{recvErr: io.EOF}
|
||||
transfer := New(logger.NewTest(t), streamer, false)
|
||||
assert.False(transfer.CanSend())
|
||||
|
||||
// manual set
|
||||
transfer.SetFiles(nil)
|
||||
assert.True(transfer.CanSend())
|
||||
|
||||
// reset
|
||||
transfer.receiveStarted = false
|
||||
transfer.receiveFinished = false
|
||||
transfer.files = nil
|
||||
assert.False(transfer.CanSend())
|
||||
|
||||
// receive files (empty)
|
||||
assert.NoError(transfer.RecvFiles(stream))
|
||||
assert.True(transfer.CanSend())
|
||||
}
|
||||
|
||||
func TestConcurrency(t *testing.T) {
|
||||
ft := New(logger.NewTest(t), &stubStreamReadWriter{}, false)
|
||||
|
||||
sendFiles := func() {
|
||||
_ = ft.SendFiles(&stubSendFilesStream{})
|
||||
}
|
||||
|
||||
recvFiles := func() {
|
||||
_ = ft.RecvFiles(&stubRecvFilesStream{})
|
||||
}
|
||||
|
||||
getFiles := func() {
|
||||
_ = ft.GetFiles()
|
||||
}
|
||||
|
||||
setFiles := func() {
|
||||
ft.SetFiles([]FileStat{{SourcePath: "file", TargetPath: "file", Mode: 0o644}})
|
||||
}
|
||||
|
||||
canSend := func() {
|
||||
_ = ft.CanSend()
|
||||
}
|
||||
|
||||
go sendFiles()
|
||||
go sendFiles()
|
||||
go sendFiles()
|
||||
go sendFiles()
|
||||
go recvFiles()
|
||||
go recvFiles()
|
||||
go recvFiles()
|
||||
go recvFiles()
|
||||
go getFiles()
|
||||
go getFiles()
|
||||
go getFiles()
|
||||
go getFiles()
|
||||
go setFiles()
|
||||
go setFiles()
|
||||
go setFiles()
|
||||
go setFiles()
|
||||
go canSend()
|
||||
go canSend()
|
||||
go canSend()
|
||||
go canSend()
|
||||
}
|
||||
|
||||
type stubStreamReadWriter struct {
|
||||
readStreamFilename string
|
||||
readStreamErr error
|
||||
|
||||
writeStreamFilename string
|
||||
writeStreamErr error
|
||||
}
|
||||
|
||||
func (s *stubStreamReadWriter) ReadStream(filename string, _ streamer.WriteChunkStream, _ uint, _ bool) error {
|
||||
s.readStreamFilename = filename
|
||||
return s.readStreamErr
|
||||
}
|
||||
|
||||
func (s *stubStreamReadWriter) WriteStream(filename string, _ streamer.ReadChunkStream, _ bool) error {
|
||||
s.writeStreamFilename = filename
|
||||
return s.writeStreamErr
|
||||
}
|
||||
|
||||
type fakeRecvFilesStream struct {
|
||||
msgs []*pb.FileTransferMessage
|
||||
pos int
|
||||
recvErr error
|
||||
}
|
||||
|
||||
func (s *fakeRecvFilesStream) Recv() (*pb.FileTransferMessage, error) {
|
||||
if s.recvErr != nil {
|
||||
return nil, s.recvErr
|
||||
}
|
||||
|
||||
if s.pos < len(s.msgs) {
|
||||
s.pos++
|
||||
return s.msgs[s.pos-1], nil
|
||||
}
|
||||
|
||||
return nil, io.EOF
|
||||
}
|
||||
|
||||
type dummyStreamReadWriter struct{}
|
||||
|
||||
func (s *dummyStreamReadWriter) ReadStream(_ string, _ streamer.WriteChunkStream, _ uint, _ bool) error {
|
||||
panic("dummy")
|
||||
}
|
||||
|
||||
func (s *dummyStreamReadWriter) WriteStream(_ string, _ streamer.ReadChunkStream, _ bool) error {
|
||||
panic("dummy")
|
||||
}
|
@ -4,7 +4,7 @@ Copyright (c) Edgeless Systems GmbH
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package bootstrapper
|
||||
package streamer
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@ -34,8 +34,8 @@ type WriteChunkStream interface {
|
||||
Send(chunk *pb.Chunk) error
|
||||
}
|
||||
|
||||
// NewFileStreamer creates a new FileStreamer.
|
||||
func NewFileStreamer(fs afero.Fs) *FileStreamer {
|
||||
// New creates a new FileStreamer.
|
||||
func New(fs afero.Fs) *FileStreamer {
|
||||
return &FileStreamer{
|
||||
fs: fs,
|
||||
mux: sync.RWMutex{},
|
||||
@ -44,52 +44,25 @@ func NewFileStreamer(fs afero.Fs) *FileStreamer {
|
||||
|
||||
// WriteStream opens a file to write to and streams chunks from a gRPC stream into the file.
|
||||
func (f *FileStreamer) WriteStream(filename string, stream ReadChunkStream, showProgress bool) error {
|
||||
// try to read from stream once before acquiring write lock
|
||||
chunk, err := stream.Recv()
|
||||
if err != nil {
|
||||
return fmt.Errorf("reading stream: %w", err)
|
||||
}
|
||||
|
||||
f.mux.Lock()
|
||||
defer f.mux.Unlock()
|
||||
file, err := f.fs.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0o755)
|
||||
file, err := f.fs.OpenFile(filename, os.O_WRONLY|os.O_CREATE, os.ModePerm)
|
||||
if err != nil {
|
||||
return fmt.Errorf("open %v for writing: %w", filename, err)
|
||||
}
|
||||
defer file.Close()
|
||||
stat, err := file.Stat()
|
||||
if err != nil {
|
||||
return fmt.Errorf("performing stat on %v to get the file size: %w", filename, err)
|
||||
}
|
||||
|
||||
var bar *progressbar.ProgressBar
|
||||
if showProgress {
|
||||
bar = progressbar.NewOptions64(
|
||||
-1,
|
||||
progressbar.OptionSetDescription("receiving bootstrapper"),
|
||||
progressbar.OptionShowBytes(true),
|
||||
progressbar.OptionClearOnFinish(),
|
||||
)
|
||||
bar = newProgressBar(stat.Size())
|
||||
defer bar.Close()
|
||||
}
|
||||
|
||||
for {
|
||||
if err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
break
|
||||
}
|
||||
_ = file.Close()
|
||||
_ = f.fs.Remove(filename)
|
||||
return fmt.Errorf("reading stream: %w", err)
|
||||
}
|
||||
if _, err := file.Write(chunk.Content); err != nil {
|
||||
_ = file.Close()
|
||||
_ = f.fs.Remove(filename)
|
||||
return fmt.Errorf("writing chunk to disk: %w", err)
|
||||
}
|
||||
if showProgress {
|
||||
_ = bar.Add(len(chunk.Content))
|
||||
}
|
||||
chunk, err = stream.Recv()
|
||||
}
|
||||
|
||||
return nil
|
||||
return writeInner(file, stream, bar)
|
||||
}
|
||||
|
||||
// ReadStream opens a file to read from and streams its contents chunkwise over gRPC.
|
||||
@ -101,44 +74,73 @@ func (f *FileStreamer) ReadStream(filename string, stream WriteChunkStream, chun
|
||||
if f.mux.TryRLock() {
|
||||
defer f.mux.RUnlock()
|
||||
} else {
|
||||
return errors.New("file is opened for writing cannot be read at this time")
|
||||
return errors.New("a file is opened for writing so cannot read at this time")
|
||||
}
|
||||
file, err := f.fs.OpenFile(filename, os.O_RDONLY, 0o755)
|
||||
if err != nil {
|
||||
return fmt.Errorf("open %v for reading: %w", filename, err)
|
||||
}
|
||||
defer file.Close()
|
||||
stat, err := file.Stat()
|
||||
if err != nil {
|
||||
return fmt.Errorf("performing stat on %v to get the file size: %w", filename, err)
|
||||
}
|
||||
|
||||
var bar *progressbar.ProgressBar
|
||||
if showProgress {
|
||||
stat, err := file.Stat()
|
||||
if err != nil {
|
||||
return fmt.Errorf("performing stat on %v to get the file size: %w", filename, err)
|
||||
}
|
||||
bar = progressbar.NewOptions64(
|
||||
stat.Size(),
|
||||
progressbar.OptionSetDescription("uploading bootstrapper"),
|
||||
progressbar.OptionShowBytes(true),
|
||||
progressbar.OptionClearOnFinish(),
|
||||
)
|
||||
bar = newProgressBar(stat.Size())
|
||||
defer bar.Close()
|
||||
}
|
||||
|
||||
return readInner(file, stream, chunksize, bar)
|
||||
}
|
||||
|
||||
// readInner reads from a an io.Reader and sends chunks over a gRPC stream.
|
||||
func readInner(fp io.Reader, stream WriteChunkStream, chunksize uint, bar *progressbar.ProgressBar) error {
|
||||
buf := make([]byte, chunksize)
|
||||
for {
|
||||
n, err := file.Read(buf)
|
||||
if err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("reading file chunk: %w", err)
|
||||
n, readErr := fp.Read(buf)
|
||||
isLast := errors.Is(readErr, io.EOF)
|
||||
if readErr != nil && !isLast {
|
||||
return fmt.Errorf("reading file chunk: %w", readErr)
|
||||
}
|
||||
|
||||
if err = stream.Send(&pb.Chunk{Content: buf[:n]}); err != nil {
|
||||
if err := stream.Send(&pb.Chunk{Content: buf[:n], Last: isLast}); err != nil {
|
||||
return fmt.Errorf("sending chunk: %w", err)
|
||||
}
|
||||
if showProgress {
|
||||
if bar != nil {
|
||||
_ = bar.Add(n)
|
||||
}
|
||||
if isLast {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// writeInner writes chunks from a gRPC stream to an io.Writer.
|
||||
func writeInner(fp io.Writer, stream ReadChunkStream, bar *progressbar.ProgressBar) error {
|
||||
for {
|
||||
chunk, recvErr := stream.Recv()
|
||||
if recvErr != nil {
|
||||
return fmt.Errorf("reading stream: %w", recvErr)
|
||||
}
|
||||
if _, err := fp.Write(chunk.Content); err != nil {
|
||||
return fmt.Errorf("writing chunk to disk: %w", err)
|
||||
}
|
||||
if bar != nil {
|
||||
_ = bar.Add(len(chunk.Content))
|
||||
}
|
||||
if chunk.Last {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// newProgressBar creates a new progress bar.
|
||||
func newProgressBar(size int64) *progressbar.ProgressBar {
|
||||
return progressbar.NewOptions64(
|
||||
size,
|
||||
progressbar.OptionSetDescription("transferring file"),
|
||||
progressbar.OptionShowBytes(true),
|
||||
progressbar.OptionClearOnFinish(),
|
||||
)
|
||||
}
|
@ -4,7 +4,7 @@ Copyright (c) Edgeless Systems GmbH
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package bootstrapper
|
||||
package streamer
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@ -82,7 +82,7 @@ func TestWriteStream(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
require := require.New(t)
|
||||
|
||||
writer := NewFileStreamer(tc.fs)
|
||||
writer := New(tc.fs)
|
||||
err := writer.WriteStream(filename, &tc.readChunkStream, tc.showProgress)
|
||||
|
||||
if tc.wantErr {
|
||||
@ -99,6 +99,7 @@ func TestWriteStream(t *testing.T) {
|
||||
|
||||
func TestReadStream(t *testing.T) {
|
||||
correctFilename := "testfile"
|
||||
eof := []byte{}
|
||||
|
||||
testCases := map[string]struct {
|
||||
writeChunkStream stubWriteChunkStream
|
||||
@ -114,6 +115,7 @@ func TestReadStream(t *testing.T) {
|
||||
chunksize: 4,
|
||||
wantChunks: [][]byte{
|
||||
[]byte("test"),
|
||||
eof,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
@ -124,6 +126,7 @@ func TestReadStream(t *testing.T) {
|
||||
wantChunks: [][]byte{
|
||||
[]byte("te"),
|
||||
[]byte("st"),
|
||||
eof,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
@ -140,6 +143,7 @@ func TestReadStream(t *testing.T) {
|
||||
showProgress: true,
|
||||
wantChunks: [][]byte{
|
||||
[]byte("test"),
|
||||
eof,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
@ -165,7 +169,7 @@ func TestReadStream(t *testing.T) {
|
||||
|
||||
fs := afero.NewMemMapFs()
|
||||
assert.NoError(afero.WriteFile(fs, correctFilename, []byte("test"), 0o755))
|
||||
reader := NewFileStreamer(fs)
|
||||
reader := New(fs)
|
||||
err := reader.ReadStream(tc.filename, &tc.writeChunkStream, tc.chunksize, tc.showProgress)
|
||||
|
||||
if tc.wantErr {
|
||||
@ -189,8 +193,10 @@ func (s *fakeReadChunkStream) Recv() (*pb.Chunk, error) {
|
||||
return nil, s.recvErr
|
||||
}
|
||||
|
||||
isLastChunk := s.pos == len(s.chunks)-1
|
||||
|
||||
if s.pos < len(s.chunks) {
|
||||
result := &pb.Chunk{Content: s.chunks[s.pos]}
|
||||
result := &pb.Chunk{Content: s.chunks[s.pos], Last: isLastChunk}
|
||||
s.pos++
|
||||
return result, nil
|
||||
}
|
@ -20,58 +20,107 @@ const (
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type UploadBootstrapperStatus int32
|
||||
type SetInfoStatus int32
|
||||
|
||||
const (
|
||||
UploadBootstrapperStatus_UPLOAD_BOOTSTRAPPER_SUCCESS UploadBootstrapperStatus = 0
|
||||
UploadBootstrapperStatus_UPLOAD_BOOTSTRAPPER_UPLOAD_FAILED UploadBootstrapperStatus = 1
|
||||
UploadBootstrapperStatus_UPLOAD_BOOTSTRAPPER_START_FAILED UploadBootstrapperStatus = 2
|
||||
UploadBootstrapperStatus_UPLOAD_BOOTSTRAPPER_FILE_EXISTS UploadBootstrapperStatus = 3
|
||||
SetInfoStatus_SET_INFO_SUCCESS SetInfoStatus = 0
|
||||
SetInfoStatus_SET_INFO_ALREADY_SET SetInfoStatus = 1
|
||||
)
|
||||
|
||||
// Enum value maps for UploadBootstrapperStatus.
|
||||
// Enum value maps for SetInfoStatus.
|
||||
var (
|
||||
UploadBootstrapperStatus_name = map[int32]string{
|
||||
0: "UPLOAD_BOOTSTRAPPER_SUCCESS",
|
||||
1: "UPLOAD_BOOTSTRAPPER_UPLOAD_FAILED",
|
||||
2: "UPLOAD_BOOTSTRAPPER_START_FAILED",
|
||||
3: "UPLOAD_BOOTSTRAPPER_FILE_EXISTS",
|
||||
SetInfoStatus_name = map[int32]string{
|
||||
0: "SET_INFO_SUCCESS",
|
||||
1: "SET_INFO_ALREADY_SET",
|
||||
}
|
||||
UploadBootstrapperStatus_value = map[string]int32{
|
||||
"UPLOAD_BOOTSTRAPPER_SUCCESS": 0,
|
||||
"UPLOAD_BOOTSTRAPPER_UPLOAD_FAILED": 1,
|
||||
"UPLOAD_BOOTSTRAPPER_START_FAILED": 2,
|
||||
"UPLOAD_BOOTSTRAPPER_FILE_EXISTS": 3,
|
||||
SetInfoStatus_value = map[string]int32{
|
||||
"SET_INFO_SUCCESS": 0,
|
||||
"SET_INFO_ALREADY_SET": 1,
|
||||
}
|
||||
)
|
||||
|
||||
func (x UploadBootstrapperStatus) Enum() *UploadBootstrapperStatus {
|
||||
p := new(UploadBootstrapperStatus)
|
||||
func (x SetInfoStatus) Enum() *SetInfoStatus {
|
||||
p := new(SetInfoStatus)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
|
||||
func (x UploadBootstrapperStatus) String() string {
|
||||
func (x SetInfoStatus) String() string {
|
||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||
}
|
||||
|
||||
func (UploadBootstrapperStatus) Descriptor() protoreflect.EnumDescriptor {
|
||||
func (SetInfoStatus) Descriptor() protoreflect.EnumDescriptor {
|
||||
return file_debugd_proto_enumTypes[0].Descriptor()
|
||||
}
|
||||
|
||||
func (UploadBootstrapperStatus) Type() protoreflect.EnumType {
|
||||
func (SetInfoStatus) Type() protoreflect.EnumType {
|
||||
return &file_debugd_proto_enumTypes[0]
|
||||
}
|
||||
|
||||
func (x UploadBootstrapperStatus) Number() protoreflect.EnumNumber {
|
||||
func (x SetInfoStatus) Number() protoreflect.EnumNumber {
|
||||
return protoreflect.EnumNumber(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use UploadBootstrapperStatus.Descriptor instead.
|
||||
func (UploadBootstrapperStatus) EnumDescriptor() ([]byte, []int) {
|
||||
// Deprecated: Use SetInfoStatus.Descriptor instead.
|
||||
func (SetInfoStatus) EnumDescriptor() ([]byte, []int) {
|
||||
return file_debugd_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
type UploadFilesStatus int32
|
||||
|
||||
const (
|
||||
UploadFilesStatus_UPLOAD_FILES_SUCCESS UploadFilesStatus = 0
|
||||
UploadFilesStatus_UPLOAD_FILES_UPLOAD_FAILED UploadFilesStatus = 1
|
||||
UploadFilesStatus_UPLOAD_FILES_ALREADY_STARTED UploadFilesStatus = 2
|
||||
UploadFilesStatus_UPLOAD_FILES_ALREADY_FINISHED UploadFilesStatus = 3
|
||||
UploadFilesStatus_UPLOAD_FILES_START_FAILED UploadFilesStatus = 4
|
||||
)
|
||||
|
||||
// Enum value maps for UploadFilesStatus.
|
||||
var (
|
||||
UploadFilesStatus_name = map[int32]string{
|
||||
0: "UPLOAD_FILES_SUCCESS",
|
||||
1: "UPLOAD_FILES_UPLOAD_FAILED",
|
||||
2: "UPLOAD_FILES_ALREADY_STARTED",
|
||||
3: "UPLOAD_FILES_ALREADY_FINISHED",
|
||||
4: "UPLOAD_FILES_START_FAILED",
|
||||
}
|
||||
UploadFilesStatus_value = map[string]int32{
|
||||
"UPLOAD_FILES_SUCCESS": 0,
|
||||
"UPLOAD_FILES_UPLOAD_FAILED": 1,
|
||||
"UPLOAD_FILES_ALREADY_STARTED": 2,
|
||||
"UPLOAD_FILES_ALREADY_FINISHED": 3,
|
||||
"UPLOAD_FILES_START_FAILED": 4,
|
||||
}
|
||||
)
|
||||
|
||||
func (x UploadFilesStatus) Enum() *UploadFilesStatus {
|
||||
p := new(UploadFilesStatus)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
|
||||
func (x UploadFilesStatus) String() string {
|
||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||
}
|
||||
|
||||
func (UploadFilesStatus) Descriptor() protoreflect.EnumDescriptor {
|
||||
return file_debugd_proto_enumTypes[1].Descriptor()
|
||||
}
|
||||
|
||||
func (UploadFilesStatus) Type() protoreflect.EnumType {
|
||||
return &file_debugd_proto_enumTypes[1]
|
||||
}
|
||||
|
||||
func (x UploadFilesStatus) Number() protoreflect.EnumNumber {
|
||||
return protoreflect.EnumNumber(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use UploadFilesStatus.Descriptor instead.
|
||||
func (UploadFilesStatus) EnumDescriptor() ([]byte, []int) {
|
||||
return file_debugd_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
type UploadSystemdServiceUnitsStatus int32
|
||||
|
||||
const (
|
||||
@ -102,11 +151,11 @@ func (x UploadSystemdServiceUnitsStatus) String() string {
|
||||
}
|
||||
|
||||
func (UploadSystemdServiceUnitsStatus) Descriptor() protoreflect.EnumDescriptor {
|
||||
return file_debugd_proto_enumTypes[1].Descriptor()
|
||||
return file_debugd_proto_enumTypes[2].Descriptor()
|
||||
}
|
||||
|
||||
func (UploadSystemdServiceUnitsStatus) Type() protoreflect.EnumType {
|
||||
return &file_debugd_proto_enumTypes[1]
|
||||
return &file_debugd_proto_enumTypes[2]
|
||||
}
|
||||
|
||||
func (x UploadSystemdServiceUnitsStatus) Number() protoreflect.EnumNumber {
|
||||
@ -115,7 +164,7 @@ func (x UploadSystemdServiceUnitsStatus) Number() protoreflect.EnumNumber {
|
||||
|
||||
// Deprecated: Use UploadSystemdServiceUnitsStatus.Descriptor instead.
|
||||
func (UploadSystemdServiceUnitsStatus) EnumDescriptor() ([]byte, []int) {
|
||||
return file_debugd_proto_rawDescGZIP(), []int{1}
|
||||
return file_debugd_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
type SetInfoRequest struct {
|
||||
@ -169,6 +218,8 @@ type SetInfoResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Status SetInfoStatus `protobuf:"varint,1,opt,name=status,proto3,enum=debugd.SetInfoStatus" json:"status,omitempty"`
|
||||
}
|
||||
|
||||
func (x *SetInfoResponse) Reset() {
|
||||
@ -203,6 +254,13 @@ func (*SetInfoResponse) Descriptor() ([]byte, []int) {
|
||||
return file_debugd_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *SetInfoResponse) GetStatus() SetInfoStatus {
|
||||
if x != nil {
|
||||
return x.Status
|
||||
}
|
||||
return SetInfoStatus_SET_INFO_SUCCESS
|
||||
}
|
||||
|
||||
type GetInfoRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@ -343,14 +401,14 @@ func (x *Info) GetValue() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
type DownloadBootstrapperRequest struct {
|
||||
type DownloadFilesRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
}
|
||||
|
||||
func (x *DownloadBootstrapperRequest) Reset() {
|
||||
*x = DownloadBootstrapperRequest{}
|
||||
func (x *DownloadFilesRequest) Reset() {
|
||||
*x = DownloadFilesRequest{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_debugd_proto_msgTypes[5]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
@ -358,13 +416,13 @@ func (x *DownloadBootstrapperRequest) Reset() {
|
||||
}
|
||||
}
|
||||
|
||||
func (x *DownloadBootstrapperRequest) String() string {
|
||||
func (x *DownloadFilesRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*DownloadBootstrapperRequest) ProtoMessage() {}
|
||||
func (*DownloadFilesRequest) ProtoMessage() {}
|
||||
|
||||
func (x *DownloadBootstrapperRequest) ProtoReflect() protoreflect.Message {
|
||||
func (x *DownloadFilesRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_debugd_proto_msgTypes[5]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
@ -376,23 +434,168 @@ func (x *DownloadBootstrapperRequest) ProtoReflect() protoreflect.Message {
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use DownloadBootstrapperRequest.ProtoReflect.Descriptor instead.
|
||||
func (*DownloadBootstrapperRequest) Descriptor() ([]byte, []int) {
|
||||
// Deprecated: Use DownloadFilesRequest.ProtoReflect.Descriptor instead.
|
||||
func (*DownloadFilesRequest) Descriptor() ([]byte, []int) {
|
||||
return file_debugd_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
type FileTransferMessage struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Types that are assignable to Kind:
|
||||
//
|
||||
// *FileTransferMessage_Header
|
||||
// *FileTransferMessage_Chunk
|
||||
Kind isFileTransferMessage_Kind `protobuf_oneof:"kind"`
|
||||
}
|
||||
|
||||
func (x *FileTransferMessage) Reset() {
|
||||
*x = FileTransferMessage{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_debugd_proto_msgTypes[6]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *FileTransferMessage) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*FileTransferMessage) ProtoMessage() {}
|
||||
|
||||
func (x *FileTransferMessage) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_debugd_proto_msgTypes[6]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use FileTransferMessage.ProtoReflect.Descriptor instead.
|
||||
func (*FileTransferMessage) Descriptor() ([]byte, []int) {
|
||||
return file_debugd_proto_rawDescGZIP(), []int{6}
|
||||
}
|
||||
|
||||
func (m *FileTransferMessage) GetKind() isFileTransferMessage_Kind {
|
||||
if m != nil {
|
||||
return m.Kind
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *FileTransferMessage) GetHeader() *FileTransferHeader {
|
||||
if x, ok := x.GetKind().(*FileTransferMessage_Header); ok {
|
||||
return x.Header
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *FileTransferMessage) GetChunk() *Chunk {
|
||||
if x, ok := x.GetKind().(*FileTransferMessage_Chunk); ok {
|
||||
return x.Chunk
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type isFileTransferMessage_Kind interface {
|
||||
isFileTransferMessage_Kind()
|
||||
}
|
||||
|
||||
type FileTransferMessage_Header struct {
|
||||
Header *FileTransferHeader `protobuf:"bytes,1,opt,name=header,proto3,oneof"` // start of transfer
|
||||
}
|
||||
|
||||
type FileTransferMessage_Chunk struct {
|
||||
Chunk *Chunk `protobuf:"bytes,2,opt,name=chunk,proto3,oneof"` // file content as chunks
|
||||
}
|
||||
|
||||
func (*FileTransferMessage_Header) isFileTransferMessage_Kind() {}
|
||||
|
||||
func (*FileTransferMessage_Chunk) isFileTransferMessage_Kind() {}
|
||||
|
||||
type FileTransferHeader struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
TargetPath string `protobuf:"bytes,1,opt,name=targetPath,proto3" json:"targetPath,omitempty"`
|
||||
Mode uint32 `protobuf:"varint,3,opt,name=mode,proto3" json:"mode,omitempty"`
|
||||
OverrideServiceUnit *string `protobuf:"bytes,4,opt,name=overrideServiceUnit,proto3,oneof" json:"overrideServiceUnit,omitempty"`
|
||||
}
|
||||
|
||||
func (x *FileTransferHeader) Reset() {
|
||||
*x = FileTransferHeader{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_debugd_proto_msgTypes[7]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *FileTransferHeader) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*FileTransferHeader) ProtoMessage() {}
|
||||
|
||||
func (x *FileTransferHeader) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_debugd_proto_msgTypes[7]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use FileTransferHeader.ProtoReflect.Descriptor instead.
|
||||
func (*FileTransferHeader) Descriptor() ([]byte, []int) {
|
||||
return file_debugd_proto_rawDescGZIP(), []int{7}
|
||||
}
|
||||
|
||||
func (x *FileTransferHeader) GetTargetPath() string {
|
||||
if x != nil {
|
||||
return x.TargetPath
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *FileTransferHeader) GetMode() uint32 {
|
||||
if x != nil {
|
||||
return x.Mode
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *FileTransferHeader) GetOverrideServiceUnit() string {
|
||||
if x != nil && x.OverrideServiceUnit != nil {
|
||||
return *x.OverrideServiceUnit
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Chunk struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Content []byte `protobuf:"bytes,1,opt,name=content,proto3" json:"content,omitempty"`
|
||||
Last bool `protobuf:"varint,2,opt,name=last,proto3" json:"last,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Chunk) Reset() {
|
||||
*x = Chunk{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_debugd_proto_msgTypes[6]
|
||||
mi := &file_debugd_proto_msgTypes[8]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@ -405,7 +608,7 @@ func (x *Chunk) String() string {
|
||||
func (*Chunk) ProtoMessage() {}
|
||||
|
||||
func (x *Chunk) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_debugd_proto_msgTypes[6]
|
||||
mi := &file_debugd_proto_msgTypes[8]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@ -418,7 +621,7 @@ func (x *Chunk) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use Chunk.ProtoReflect.Descriptor instead.
|
||||
func (*Chunk) Descriptor() ([]byte, []int) {
|
||||
return file_debugd_proto_rawDescGZIP(), []int{6}
|
||||
return file_debugd_proto_rawDescGZIP(), []int{8}
|
||||
}
|
||||
|
||||
func (x *Chunk) GetContent() []byte {
|
||||
@ -428,31 +631,38 @@ func (x *Chunk) GetContent() []byte {
|
||||
return nil
|
||||
}
|
||||
|
||||
type UploadBootstrapperResponse struct {
|
||||
func (x *Chunk) GetLast() bool {
|
||||
if x != nil {
|
||||
return x.Last
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type UploadFilesResponse struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Status UploadBootstrapperStatus `protobuf:"varint,1,opt,name=status,proto3,enum=debugd.UploadBootstrapperStatus" json:"status,omitempty"`
|
||||
Status UploadFilesStatus `protobuf:"varint,1,opt,name=status,proto3,enum=debugd.UploadFilesStatus" json:"status,omitempty"`
|
||||
}
|
||||
|
||||
func (x *UploadBootstrapperResponse) Reset() {
|
||||
*x = UploadBootstrapperResponse{}
|
||||
func (x *UploadFilesResponse) Reset() {
|
||||
*x = UploadFilesResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_debugd_proto_msgTypes[7]
|
||||
mi := &file_debugd_proto_msgTypes[9]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *UploadBootstrapperResponse) String() string {
|
||||
func (x *UploadFilesResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*UploadBootstrapperResponse) ProtoMessage() {}
|
||||
func (*UploadFilesResponse) ProtoMessage() {}
|
||||
|
||||
func (x *UploadBootstrapperResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_debugd_proto_msgTypes[7]
|
||||
func (x *UploadFilesResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_debugd_proto_msgTypes[9]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@ -463,16 +673,16 @@ func (x *UploadBootstrapperResponse) ProtoReflect() protoreflect.Message {
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use UploadBootstrapperResponse.ProtoReflect.Descriptor instead.
|
||||
func (*UploadBootstrapperResponse) Descriptor() ([]byte, []int) {
|
||||
return file_debugd_proto_rawDescGZIP(), []int{7}
|
||||
// Deprecated: Use UploadFilesResponse.ProtoReflect.Descriptor instead.
|
||||
func (*UploadFilesResponse) Descriptor() ([]byte, []int) {
|
||||
return file_debugd_proto_rawDescGZIP(), []int{9}
|
||||
}
|
||||
|
||||
func (x *UploadBootstrapperResponse) GetStatus() UploadBootstrapperStatus {
|
||||
func (x *UploadFilesResponse) GetStatus() UploadFilesStatus {
|
||||
if x != nil {
|
||||
return x.Status
|
||||
}
|
||||
return UploadBootstrapperStatus_UPLOAD_BOOTSTRAPPER_SUCCESS
|
||||
return UploadFilesStatus_UPLOAD_FILES_SUCCESS
|
||||
}
|
||||
|
||||
type ServiceUnit struct {
|
||||
@ -487,7 +697,7 @@ type ServiceUnit struct {
|
||||
func (x *ServiceUnit) Reset() {
|
||||
*x = ServiceUnit{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_debugd_proto_msgTypes[8]
|
||||
mi := &file_debugd_proto_msgTypes[10]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@ -500,7 +710,7 @@ func (x *ServiceUnit) String() string {
|
||||
func (*ServiceUnit) ProtoMessage() {}
|
||||
|
||||
func (x *ServiceUnit) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_debugd_proto_msgTypes[8]
|
||||
mi := &file_debugd_proto_msgTypes[10]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@ -513,7 +723,7 @@ func (x *ServiceUnit) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use ServiceUnit.ProtoReflect.Descriptor instead.
|
||||
func (*ServiceUnit) Descriptor() ([]byte, []int) {
|
||||
return file_debugd_proto_rawDescGZIP(), []int{8}
|
||||
return file_debugd_proto_rawDescGZIP(), []int{10}
|
||||
}
|
||||
|
||||
func (x *ServiceUnit) GetName() string {
|
||||
@ -541,7 +751,7 @@ type UploadSystemdServiceUnitsRequest struct {
|
||||
func (x *UploadSystemdServiceUnitsRequest) Reset() {
|
||||
*x = UploadSystemdServiceUnitsRequest{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_debugd_proto_msgTypes[9]
|
||||
mi := &file_debugd_proto_msgTypes[11]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@ -554,7 +764,7 @@ func (x *UploadSystemdServiceUnitsRequest) String() string {
|
||||
func (*UploadSystemdServiceUnitsRequest) ProtoMessage() {}
|
||||
|
||||
func (x *UploadSystemdServiceUnitsRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_debugd_proto_msgTypes[9]
|
||||
mi := &file_debugd_proto_msgTypes[11]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@ -567,7 +777,7 @@ func (x *UploadSystemdServiceUnitsRequest) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use UploadSystemdServiceUnitsRequest.ProtoReflect.Descriptor instead.
|
||||
func (*UploadSystemdServiceUnitsRequest) Descriptor() ([]byte, []int) {
|
||||
return file_debugd_proto_rawDescGZIP(), []int{9}
|
||||
return file_debugd_proto_rawDescGZIP(), []int{11}
|
||||
}
|
||||
|
||||
func (x *UploadSystemdServiceUnitsRequest) GetUnits() []*ServiceUnit {
|
||||
@ -588,7 +798,7 @@ type UploadSystemdServiceUnitsResponse struct {
|
||||
func (x *UploadSystemdServiceUnitsResponse) Reset() {
|
||||
*x = UploadSystemdServiceUnitsResponse{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_debugd_proto_msgTypes[10]
|
||||
mi := &file_debugd_proto_msgTypes[12]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@ -601,7 +811,7 @@ func (x *UploadSystemdServiceUnitsResponse) String() string {
|
||||
func (*UploadSystemdServiceUnitsResponse) ProtoMessage() {}
|
||||
|
||||
func (x *UploadSystemdServiceUnitsResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_debugd_proto_msgTypes[10]
|
||||
mi := &file_debugd_proto_msgTypes[12]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@ -614,7 +824,7 @@ func (x *UploadSystemdServiceUnitsResponse) ProtoReflect() protoreflect.Message
|
||||
|
||||
// Deprecated: Use UploadSystemdServiceUnitsResponse.ProtoReflect.Descriptor instead.
|
||||
func (*UploadSystemdServiceUnitsResponse) Descriptor() ([]byte, []int) {
|
||||
return file_debugd_proto_rawDescGZIP(), []int{10}
|
||||
return file_debugd_proto_rawDescGZIP(), []int{12}
|
||||
}
|
||||
|
||||
func (x *UploadSystemdServiceUnitsResponse) GetStatus() UploadSystemdServiceUnitsStatus {
|
||||
@ -631,89 +841,113 @@ var file_debugd_proto_rawDesc = []byte{
|
||||
0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x22, 0x32, 0x0a, 0x0e, 0x53, 0x65, 0x74, 0x49, 0x6e, 0x66,
|
||||
0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f,
|
||||
0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e,
|
||||
0x49, 0x6e, 0x66, 0x6f, 0x52, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x22, 0x11, 0x0a, 0x0f, 0x53, 0x65,
|
||||
0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x10, 0x0a,
|
||||
0x0e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22,
|
||||
0x33, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x12, 0x20, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
|
||||
0x32, 0x0c, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x04,
|
||||
0x69, 0x6e, 0x66, 0x6f, 0x22, 0x2e, 0x0a, 0x04, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x10, 0x0a, 0x03,
|
||||
0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14,
|
||||
0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76,
|
||||
0x61, 0x6c, 0x75, 0x65, 0x22, 0x1d, 0x0a, 0x1b, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64,
|
||||
0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x22, 0x21, 0x0a, 0x05, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x18, 0x0a, 0x07,
|
||||
0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63,
|
||||
0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x56, 0x0a, 0x1a, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64,
|
||||
0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70,
|
||||
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x55, 0x70,
|
||||
0x6c, 0x6f, 0x61, 0x64, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72,
|
||||
0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x3d,
|
||||
0x0a, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x6e, 0x69, 0x74, 0x12, 0x12, 0x0a,
|
||||
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
|
||||
0x65, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x4d, 0x0a,
|
||||
0x20, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x53, 0x65,
|
||||
0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x6e, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x12, 0x29, 0x0a, 0x05, 0x75, 0x6e, 0x69, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
|
||||
0x32, 0x13, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
|
||||
0x65, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x05, 0x75, 0x6e, 0x69, 0x74, 0x73, 0x22, 0x64, 0x0a, 0x21,
|
||||
0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x53, 0x65, 0x72,
|
||||
0x76, 0x69, 0x63, 0x65, 0x55, 0x6e, 0x69, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x12, 0x3f, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x0e, 0x32, 0x27, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61,
|
||||
0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55,
|
||||
0x6e, 0x69, 0x74, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74,
|
||||
0x75, 0x73, 0x2a, 0xad, 0x01, 0x0a, 0x18, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x42, 0x6f, 0x6f,
|
||||
0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12,
|
||||
0x1f, 0x0a, 0x1b, 0x55, 0x50, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x42, 0x4f, 0x4f, 0x54, 0x53, 0x54,
|
||||
0x52, 0x41, 0x50, 0x50, 0x45, 0x52, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x00,
|
||||
0x12, 0x25, 0x0a, 0x21, 0x55, 0x50, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x42, 0x4f, 0x4f, 0x54, 0x53,
|
||||
0x54, 0x52, 0x41, 0x50, 0x50, 0x45, 0x52, 0x5f, 0x55, 0x50, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x46,
|
||||
0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, 0x24, 0x0a, 0x20, 0x55, 0x50, 0x4c, 0x4f, 0x41,
|
||||
0x44, 0x5f, 0x42, 0x4f, 0x4f, 0x54, 0x53, 0x54, 0x52, 0x41, 0x50, 0x50, 0x45, 0x52, 0x5f, 0x53,
|
||||
0x54, 0x41, 0x52, 0x54, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x02, 0x12, 0x23, 0x0a,
|
||||
0x1f, 0x55, 0x50, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x42, 0x4f, 0x4f, 0x54, 0x53, 0x54, 0x52, 0x41,
|
||||
0x50, 0x50, 0x45, 0x52, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x5f, 0x45, 0x58, 0x49, 0x53, 0x54, 0x53,
|
||||
0x10, 0x03, 0x2a, 0x75, 0x0a, 0x1f, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x79, 0x73, 0x74,
|
||||
0x65, 0x6d, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x6e, 0x69, 0x74, 0x73, 0x53,
|
||||
0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x0a, 0x24, 0x55, 0x50, 0x4c, 0x4f, 0x41, 0x44, 0x5f,
|
||||
0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, 0x44, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x5f,
|
||||
0x55, 0x4e, 0x49, 0x54, 0x53, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x00, 0x12,
|
||||
0x28, 0x0a, 0x24, 0x55, 0x50, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d,
|
||||
0x44, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x55, 0x4e, 0x49, 0x54, 0x53, 0x5f,
|
||||
0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x10, 0x01, 0x32, 0x94, 0x03, 0x0a, 0x06, 0x44, 0x65,
|
||||
0x62, 0x75, 0x67, 0x64, 0x12, 0x3c, 0x0a, 0x07, 0x53, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12,
|
||||
0x16, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64,
|
||||
0x2e, 0x53, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x22, 0x00, 0x12, 0x3c, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e,
|
||||
0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x47,
|
||||
0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00,
|
||||
0x12, 0x4b, 0x0a, 0x12, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74,
|
||||
0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x12, 0x0d, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e,
|
||||
0x43, 0x68, 0x75, 0x6e, 0x6b, 0x1a, 0x22, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x55,
|
||||
0x70, 0x6c, 0x6f, 0x61, 0x64, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x70, 0x65,
|
||||
0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, 0x01, 0x12, 0x4e, 0x0a,
|
||||
0x14, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72,
|
||||
0x61, 0x70, 0x70, 0x65, 0x72, 0x12, 0x23, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x44,
|
||||
0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70,
|
||||
0x70, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0d, 0x2e, 0x64, 0x65, 0x62,
|
||||
0x75, 0x67, 0x64, 0x2e, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x22, 0x00, 0x30, 0x01, 0x12, 0x71, 0x0a,
|
||||
0x18, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x65, 0x72,
|
||||
0x76, 0x69, 0x63, 0x65, 0x55, 0x6e, 0x69, 0x74, 0x73, 0x12, 0x28, 0x2e, 0x64, 0x65, 0x62, 0x75,
|
||||
0x67, 0x64, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64,
|
||||
0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x6e, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x55, 0x70, 0x6c,
|
||||
0x6f, 0x61, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
|
||||
0x65, 0x55, 0x6e, 0x69, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00,
|
||||
0x42, 0x38, 0x5a, 0x36, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65,
|
||||
0x64, 0x67, 0x65, 0x6c, 0x65, 0x73, 0x73, 0x73, 0x79, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x74,
|
||||
0x65, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x32, 0x2f, 0x64, 0x65, 0x62, 0x75,
|
||||
0x67, 0x64, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x33,
|
||||
0x49, 0x6e, 0x66, 0x6f, 0x52, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x22, 0x40, 0x0a, 0x0f, 0x53, 0x65,
|
||||
0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a,
|
||||
0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e,
|
||||
0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x53, 0x74,
|
||||
0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x10, 0x0a, 0x0e,
|
||||
0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x33,
|
||||
0x0a, 0x0f, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x12, 0x20, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
|
||||
0x0c, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x04, 0x69,
|
||||
0x6e, 0x66, 0x6f, 0x22, 0x2e, 0x0a, 0x04, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x6b,
|
||||
0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a,
|
||||
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61,
|
||||
0x6c, 0x75, 0x65, 0x22, 0x16, 0x0a, 0x14, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x46,
|
||||
0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x7a, 0x0a, 0x13, 0x46,
|
||||
0x69, 0x6c, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61,
|
||||
0x67, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x46, 0x69, 0x6c, 0x65,
|
||||
0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x48, 0x00,
|
||||
0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x25, 0x0a, 0x05, 0x63, 0x68, 0x75, 0x6e,
|
||||
0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64,
|
||||
0x2e, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x48, 0x00, 0x52, 0x05, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x42,
|
||||
0x06, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x22, 0x97, 0x01, 0x0a, 0x12, 0x46, 0x69, 0x6c, 0x65,
|
||||
0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x1e,
|
||||
0x0a, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x12, 0x12,
|
||||
0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x6d, 0x6f,
|
||||
0x64, 0x65, 0x12, 0x35, 0x0a, 0x13, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x53, 0x65,
|
||||
0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x6e, 0x69, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48,
|
||||
0x00, 0x52, 0x13, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69,
|
||||
0x63, 0x65, 0x55, 0x6e, 0x69, 0x74, 0x88, 0x01, 0x01, 0x42, 0x16, 0x0a, 0x14, 0x5f, 0x6f, 0x76,
|
||||
0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x6e, 0x69,
|
||||
0x74, 0x22, 0x35, 0x0a, 0x05, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f,
|
||||
0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x6f, 0x6e,
|
||||
0x74, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x61, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x08, 0x52, 0x04, 0x6c, 0x61, 0x73, 0x74, 0x22, 0x48, 0x0a, 0x13, 0x55, 0x70, 0x6c, 0x6f,
|
||||
0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
||||
0x31, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32,
|
||||
0x19, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x46,
|
||||
0x69, 0x6c, 0x65, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74,
|
||||
0x75, 0x73, 0x22, 0x3d, 0x0a, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x6e, 0x69,
|
||||
0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,
|
||||
0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,
|
||||
0x73, 0x22, 0x4d, 0x0a, 0x20, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65,
|
||||
0x6d, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x6e, 0x69, 0x74, 0x73, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x05, 0x75, 0x6e, 0x69, 0x74, 0x73, 0x18, 0x01,
|
||||
0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x53, 0x65,
|
||||
0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x05, 0x75, 0x6e, 0x69, 0x74, 0x73,
|
||||
0x22, 0x64, 0x0a, 0x21, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d,
|
||||
0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x6e, 0x69, 0x74, 0x73, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x55,
|
||||
0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x53, 0x65, 0x72, 0x76,
|
||||
0x69, 0x63, 0x65, 0x55, 0x6e, 0x69, 0x74, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06,
|
||||
0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2a, 0x3f, 0x0a, 0x0d, 0x53, 0x65, 0x74, 0x49, 0x6e, 0x66,
|
||||
0x6f, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x45, 0x54, 0x5f, 0x49,
|
||||
0x4e, 0x46, 0x4f, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x00, 0x12, 0x18, 0x0a,
|
||||
0x14, 0x53, 0x45, 0x54, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x5f, 0x41, 0x4c, 0x52, 0x45, 0x41, 0x44,
|
||||
0x59, 0x5f, 0x53, 0x45, 0x54, 0x10, 0x01, 0x2a, 0xb1, 0x01, 0x0a, 0x11, 0x55, 0x70, 0x6c, 0x6f,
|
||||
0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a,
|
||||
0x14, 0x55, 0x50, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x5f, 0x53, 0x55,
|
||||
0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x00, 0x12, 0x1e, 0x0a, 0x1a, 0x55, 0x50, 0x4c, 0x4f, 0x41,
|
||||
0x44, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x5f, 0x55, 0x50, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x46,
|
||||
0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, 0x20, 0x0a, 0x1c, 0x55, 0x50, 0x4c, 0x4f, 0x41,
|
||||
0x44, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x5f, 0x41, 0x4c, 0x52, 0x45, 0x41, 0x44, 0x59, 0x5f,
|
||||
0x53, 0x54, 0x41, 0x52, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x21, 0x0a, 0x1d, 0x55, 0x50, 0x4c,
|
||||
0x4f, 0x41, 0x44, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x5f, 0x41, 0x4c, 0x52, 0x45, 0x41, 0x44,
|
||||
0x59, 0x5f, 0x46, 0x49, 0x4e, 0x49, 0x53, 0x48, 0x45, 0x44, 0x10, 0x03, 0x12, 0x1d, 0x0a, 0x19,
|
||||
0x55, 0x50, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x5f, 0x53, 0x54, 0x41,
|
||||
0x52, 0x54, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x04, 0x2a, 0x75, 0x0a, 0x1f, 0x55,
|
||||
0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x53, 0x65, 0x72, 0x76,
|
||||
0x69, 0x63, 0x65, 0x55, 0x6e, 0x69, 0x74, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28,
|
||||
0x0a, 0x24, 0x55, 0x50, 0x4c, 0x4f, 0x41, 0x44, 0x5f, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, 0x44,
|
||||
0x5f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x55, 0x4e, 0x49, 0x54, 0x53, 0x5f, 0x53,
|
||||
0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, 0x00, 0x12, 0x28, 0x0a, 0x24, 0x55, 0x50, 0x4c, 0x4f,
|
||||
0x41, 0x44, 0x5f, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, 0x44, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x49,
|
||||
0x43, 0x45, 0x5f, 0x55, 0x4e, 0x49, 0x54, 0x53, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45,
|
||||
0x10, 0x01, 0x32, 0x94, 0x03, 0x0a, 0x06, 0x44, 0x65, 0x62, 0x75, 0x67, 0x64, 0x12, 0x3c, 0x0a,
|
||||
0x07, 0x53, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67,
|
||||
0x64, 0x2e, 0x53, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x1a, 0x17, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x53, 0x65, 0x74, 0x49, 0x6e, 0x66,
|
||||
0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3c, 0x0a, 0x07, 0x47,
|
||||
0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e,
|
||||
0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17,
|
||||
0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x0b, 0x55, 0x70, 0x6c,
|
||||
0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x1b, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67,
|
||||
0x64, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x4d, 0x65,
|
||||
0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1b, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x55,
|
||||
0x70, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x22, 0x00, 0x28, 0x01, 0x12, 0x4e, 0x0a, 0x0d, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f,
|
||||
0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x1c, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64,
|
||||
0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x46,
|
||||
0x69, 0x6c, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61,
|
||||
0x67, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x71, 0x0a, 0x18, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64,
|
||||
0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x6e, 0x69,
|
||||
0x74, 0x73, 0x12, 0x28, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x55, 0x70, 0x6c, 0x6f,
|
||||
0x61, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
|
||||
0x55, 0x6e, 0x69, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x64,
|
||||
0x65, 0x62, 0x75, 0x67, 0x64, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x79, 0x73, 0x74,
|
||||
0x65, 0x6d, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x6e, 0x69, 0x74, 0x73, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x38, 0x5a, 0x36, 0x67, 0x69, 0x74,
|
||||
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x64, 0x67, 0x65, 0x6c, 0x65, 0x73, 0x73,
|
||||
0x73, 0x79, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x65, 0x6c, 0x6c, 0x61, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x2f, 0x76, 0x32, 0x2f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x64, 0x2f, 0x73, 0x65, 0x72, 0x76,
|
||||
0x69, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
@ -728,44 +962,50 @@ func file_debugd_proto_rawDescGZIP() []byte {
|
||||
return file_debugd_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_debugd_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
|
||||
var file_debugd_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
|
||||
var file_debugd_proto_enumTypes = make([]protoimpl.EnumInfo, 3)
|
||||
var file_debugd_proto_msgTypes = make([]protoimpl.MessageInfo, 13)
|
||||
var file_debugd_proto_goTypes = []interface{}{
|
||||
(UploadBootstrapperStatus)(0), // 0: debugd.UploadBootstrapperStatus
|
||||
(UploadSystemdServiceUnitsStatus)(0), // 1: debugd.UploadSystemdServiceUnitsStatus
|
||||
(*SetInfoRequest)(nil), // 2: debugd.SetInfoRequest
|
||||
(*SetInfoResponse)(nil), // 3: debugd.SetInfoResponse
|
||||
(*GetInfoRequest)(nil), // 4: debugd.GetInfoRequest
|
||||
(*GetInfoResponse)(nil), // 5: debugd.GetInfoResponse
|
||||
(*Info)(nil), // 6: debugd.Info
|
||||
(*DownloadBootstrapperRequest)(nil), // 7: debugd.DownloadBootstrapperRequest
|
||||
(*Chunk)(nil), // 8: debugd.Chunk
|
||||
(*UploadBootstrapperResponse)(nil), // 9: debugd.UploadBootstrapperResponse
|
||||
(*ServiceUnit)(nil), // 10: debugd.ServiceUnit
|
||||
(*UploadSystemdServiceUnitsRequest)(nil), // 11: debugd.UploadSystemdServiceUnitsRequest
|
||||
(*UploadSystemdServiceUnitsResponse)(nil), // 12: debugd.UploadSystemdServiceUnitsResponse
|
||||
(SetInfoStatus)(0), // 0: debugd.SetInfoStatus
|
||||
(UploadFilesStatus)(0), // 1: debugd.UploadFilesStatus
|
||||
(UploadSystemdServiceUnitsStatus)(0), // 2: debugd.UploadSystemdServiceUnitsStatus
|
||||
(*SetInfoRequest)(nil), // 3: debugd.SetInfoRequest
|
||||
(*SetInfoResponse)(nil), // 4: debugd.SetInfoResponse
|
||||
(*GetInfoRequest)(nil), // 5: debugd.GetInfoRequest
|
||||
(*GetInfoResponse)(nil), // 6: debugd.GetInfoResponse
|
||||
(*Info)(nil), // 7: debugd.Info
|
||||
(*DownloadFilesRequest)(nil), // 8: debugd.DownloadFilesRequest
|
||||
(*FileTransferMessage)(nil), // 9: debugd.FileTransferMessage
|
||||
(*FileTransferHeader)(nil), // 10: debugd.FileTransferHeader
|
||||
(*Chunk)(nil), // 11: debugd.Chunk
|
||||
(*UploadFilesResponse)(nil), // 12: debugd.UploadFilesResponse
|
||||
(*ServiceUnit)(nil), // 13: debugd.ServiceUnit
|
||||
(*UploadSystemdServiceUnitsRequest)(nil), // 14: debugd.UploadSystemdServiceUnitsRequest
|
||||
(*UploadSystemdServiceUnitsResponse)(nil), // 15: debugd.UploadSystemdServiceUnitsResponse
|
||||
}
|
||||
var file_debugd_proto_depIdxs = []int32{
|
||||
6, // 0: debugd.SetInfoRequest.info:type_name -> debugd.Info
|
||||
6, // 1: debugd.GetInfoResponse.info:type_name -> debugd.Info
|
||||
0, // 2: debugd.UploadBootstrapperResponse.status:type_name -> debugd.UploadBootstrapperStatus
|
||||
10, // 3: debugd.UploadSystemdServiceUnitsRequest.units:type_name -> debugd.ServiceUnit
|
||||
1, // 4: debugd.UploadSystemdServiceUnitsResponse.status:type_name -> debugd.UploadSystemdServiceUnitsStatus
|
||||
2, // 5: debugd.Debugd.SetInfo:input_type -> debugd.SetInfoRequest
|
||||
4, // 6: debugd.Debugd.GetInfo:input_type -> debugd.GetInfoRequest
|
||||
8, // 7: debugd.Debugd.UploadBootstrapper:input_type -> debugd.Chunk
|
||||
7, // 8: debugd.Debugd.DownloadBootstrapper:input_type -> debugd.DownloadBootstrapperRequest
|
||||
11, // 9: debugd.Debugd.UploadSystemServiceUnits:input_type -> debugd.UploadSystemdServiceUnitsRequest
|
||||
3, // 10: debugd.Debugd.SetInfo:output_type -> debugd.SetInfoResponse
|
||||
5, // 11: debugd.Debugd.GetInfo:output_type -> debugd.GetInfoResponse
|
||||
9, // 12: debugd.Debugd.UploadBootstrapper:output_type -> debugd.UploadBootstrapperResponse
|
||||
8, // 13: debugd.Debugd.DownloadBootstrapper:output_type -> debugd.Chunk
|
||||
12, // 14: debugd.Debugd.UploadSystemServiceUnits:output_type -> debugd.UploadSystemdServiceUnitsResponse
|
||||
10, // [10:15] is the sub-list for method output_type
|
||||
5, // [5:10] is the sub-list for method input_type
|
||||
5, // [5:5] is the sub-list for extension type_name
|
||||
5, // [5:5] is the sub-list for extension extendee
|
||||
0, // [0:5] is the sub-list for field type_name
|
||||
7, // 0: debugd.SetInfoRequest.info:type_name -> debugd.Info
|
||||
0, // 1: debugd.SetInfoResponse.status:type_name -> debugd.SetInfoStatus
|
||||
7, // 2: debugd.GetInfoResponse.info:type_name -> debugd.Info
|
||||
10, // 3: debugd.FileTransferMessage.header:type_name -> debugd.FileTransferHeader
|
||||
11, // 4: debugd.FileTransferMessage.chunk:type_name -> debugd.Chunk
|
||||
1, // 5: debugd.UploadFilesResponse.status:type_name -> debugd.UploadFilesStatus
|
||||
13, // 6: debugd.UploadSystemdServiceUnitsRequest.units:type_name -> debugd.ServiceUnit
|
||||
2, // 7: debugd.UploadSystemdServiceUnitsResponse.status:type_name -> debugd.UploadSystemdServiceUnitsStatus
|
||||
3, // 8: debugd.Debugd.SetInfo:input_type -> debugd.SetInfoRequest
|
||||
5, // 9: debugd.Debugd.GetInfo:input_type -> debugd.GetInfoRequest
|
||||
9, // 10: debugd.Debugd.UploadFiles:input_type -> debugd.FileTransferMessage
|
||||
8, // 11: debugd.Debugd.DownloadFiles:input_type -> debugd.DownloadFilesRequest
|
||||
14, // 12: debugd.Debugd.UploadSystemServiceUnits:input_type -> debugd.UploadSystemdServiceUnitsRequest
|
||||
4, // 13: debugd.Debugd.SetInfo:output_type -> debugd.SetInfoResponse
|
||||
6, // 14: debugd.Debugd.GetInfo:output_type -> debugd.GetInfoResponse
|
||||
12, // 15: debugd.Debugd.UploadFiles:output_type -> debugd.UploadFilesResponse
|
||||
9, // 16: debugd.Debugd.DownloadFiles:output_type -> debugd.FileTransferMessage
|
||||
15, // 17: debugd.Debugd.UploadSystemServiceUnits:output_type -> debugd.UploadSystemdServiceUnitsResponse
|
||||
13, // [13:18] is the sub-list for method output_type
|
||||
8, // [8:13] is the sub-list for method input_type
|
||||
8, // [8:8] is the sub-list for extension type_name
|
||||
8, // [8:8] is the sub-list for extension extendee
|
||||
0, // [0:8] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_debugd_proto_init() }
|
||||
@ -835,7 +1075,7 @@ func file_debugd_proto_init() {
|
||||
}
|
||||
}
|
||||
file_debugd_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*DownloadBootstrapperRequest); i {
|
||||
switch v := v.(*DownloadFilesRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
@ -847,7 +1087,7 @@ func file_debugd_proto_init() {
|
||||
}
|
||||
}
|
||||
file_debugd_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Chunk); i {
|
||||
switch v := v.(*FileTransferMessage); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
@ -859,7 +1099,7 @@ func file_debugd_proto_init() {
|
||||
}
|
||||
}
|
||||
file_debugd_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*UploadBootstrapperResponse); i {
|
||||
switch v := v.(*FileTransferHeader); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
@ -871,7 +1111,7 @@ func file_debugd_proto_init() {
|
||||
}
|
||||
}
|
||||
file_debugd_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ServiceUnit); i {
|
||||
switch v := v.(*Chunk); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
@ -883,7 +1123,7 @@ func file_debugd_proto_init() {
|
||||
}
|
||||
}
|
||||
file_debugd_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*UploadSystemdServiceUnitsRequest); i {
|
||||
switch v := v.(*UploadFilesResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
@ -895,6 +1135,30 @@ func file_debugd_proto_init() {
|
||||
}
|
||||
}
|
||||
file_debugd_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ServiceUnit); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_debugd_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*UploadSystemdServiceUnitsRequest); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_debugd_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*UploadSystemdServiceUnitsResponse); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
@ -907,13 +1171,18 @@ func file_debugd_proto_init() {
|
||||
}
|
||||
}
|
||||
}
|
||||
file_debugd_proto_msgTypes[6].OneofWrappers = []interface{}{
|
||||
(*FileTransferMessage_Header)(nil),
|
||||
(*FileTransferMessage_Chunk)(nil),
|
||||
}
|
||||
file_debugd_proto_msgTypes[7].OneofWrappers = []interface{}{}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_debugd_proto_rawDesc,
|
||||
NumEnums: 2,
|
||||
NumMessages: 11,
|
||||
NumEnums: 3,
|
||||
NumMessages: 13,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
|
@ -7,8 +7,8 @@ package debugd;
|
||||
service Debugd {
|
||||
rpc SetInfo (SetInfoRequest) returns (SetInfoResponse) {}
|
||||
rpc GetInfo (GetInfoRequest) returns (GetInfoResponse) {}
|
||||
rpc UploadBootstrapper(stream Chunk) returns (UploadBootstrapperResponse) {}
|
||||
rpc DownloadBootstrapper(DownloadBootstrapperRequest) returns (stream Chunk) {}
|
||||
rpc UploadFiles(stream FileTransferMessage) returns (UploadFilesResponse) {}
|
||||
rpc DownloadFiles(DownloadFilesRequest) returns (stream FileTransferMessage) {}
|
||||
rpc UploadSystemServiceUnits(UploadSystemdServiceUnitsRequest) returns (UploadSystemdServiceUnitsResponse) {}
|
||||
}
|
||||
|
||||
@ -16,7 +16,14 @@ message SetInfoRequest {
|
||||
repeated Info info = 1;
|
||||
}
|
||||
|
||||
message SetInfoResponse {}
|
||||
message SetInfoResponse {
|
||||
SetInfoStatus status = 1;
|
||||
}
|
||||
|
||||
enum SetInfoStatus {
|
||||
SET_INFO_SUCCESS = 0;
|
||||
SET_INFO_ALREADY_SET = 1;
|
||||
}
|
||||
|
||||
message GetInfoRequest {}
|
||||
|
||||
@ -29,22 +36,36 @@ message Info {
|
||||
string value = 2;
|
||||
}
|
||||
|
||||
message DownloadFilesRequest {}
|
||||
|
||||
message DownloadBootstrapperRequest {}
|
||||
message FileTransferMessage {
|
||||
oneof kind {
|
||||
FileTransferHeader header = 1; // start of transfer
|
||||
Chunk chunk = 2; // file content as chunks
|
||||
}
|
||||
}
|
||||
|
||||
message FileTransferHeader {
|
||||
string targetPath = 1;
|
||||
uint32 mode = 3;
|
||||
optional string overrideServiceUnit = 4;
|
||||
}
|
||||
|
||||
message Chunk {
|
||||
bytes content = 1;
|
||||
bool last = 2;
|
||||
}
|
||||
|
||||
message UploadBootstrapperResponse {
|
||||
UploadBootstrapperStatus status = 1;
|
||||
message UploadFilesResponse {
|
||||
UploadFilesStatus status = 1;
|
||||
}
|
||||
|
||||
enum UploadBootstrapperStatus {
|
||||
UPLOAD_BOOTSTRAPPER_SUCCESS = 0;
|
||||
UPLOAD_BOOTSTRAPPER_UPLOAD_FAILED = 1;
|
||||
UPLOAD_BOOTSTRAPPER_START_FAILED = 2;
|
||||
UPLOAD_BOOTSTRAPPER_FILE_EXISTS = 3;
|
||||
enum UploadFilesStatus {
|
||||
UPLOAD_FILES_SUCCESS = 0;
|
||||
UPLOAD_FILES_UPLOAD_FAILED = 1;
|
||||
UPLOAD_FILES_ALREADY_STARTED = 2;
|
||||
UPLOAD_FILES_ALREADY_FINISHED = 3;
|
||||
UPLOAD_FILES_START_FAILED = 4;
|
||||
}
|
||||
|
||||
message ServiceUnit {
|
||||
|
@ -24,8 +24,8 @@ const _ = grpc.SupportPackageIsVersion7
|
||||
type DebugdClient interface {
|
||||
SetInfo(ctx context.Context, in *SetInfoRequest, opts ...grpc.CallOption) (*SetInfoResponse, error)
|
||||
GetInfo(ctx context.Context, in *GetInfoRequest, opts ...grpc.CallOption) (*GetInfoResponse, error)
|
||||
UploadBootstrapper(ctx context.Context, opts ...grpc.CallOption) (Debugd_UploadBootstrapperClient, error)
|
||||
DownloadBootstrapper(ctx context.Context, in *DownloadBootstrapperRequest, opts ...grpc.CallOption) (Debugd_DownloadBootstrapperClient, error)
|
||||
UploadFiles(ctx context.Context, opts ...grpc.CallOption) (Debugd_UploadFilesClient, error)
|
||||
DownloadFiles(ctx context.Context, in *DownloadFilesRequest, opts ...grpc.CallOption) (Debugd_DownloadFilesClient, error)
|
||||
UploadSystemServiceUnits(ctx context.Context, in *UploadSystemdServiceUnitsRequest, opts ...grpc.CallOption) (*UploadSystemdServiceUnitsResponse, error)
|
||||
}
|
||||
|
||||
@ -55,46 +55,46 @@ func (c *debugdClient) GetInfo(ctx context.Context, in *GetInfoRequest, opts ...
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *debugdClient) UploadBootstrapper(ctx context.Context, opts ...grpc.CallOption) (Debugd_UploadBootstrapperClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &Debugd_ServiceDesc.Streams[0], "/debugd.Debugd/UploadBootstrapper", opts...)
|
||||
func (c *debugdClient) UploadFiles(ctx context.Context, opts ...grpc.CallOption) (Debugd_UploadFilesClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &Debugd_ServiceDesc.Streams[0], "/debugd.Debugd/UploadFiles", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &debugdUploadBootstrapperClient{stream}
|
||||
x := &debugdUploadFilesClient{stream}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type Debugd_UploadBootstrapperClient interface {
|
||||
Send(*Chunk) error
|
||||
CloseAndRecv() (*UploadBootstrapperResponse, error)
|
||||
type Debugd_UploadFilesClient interface {
|
||||
Send(*FileTransferMessage) error
|
||||
CloseAndRecv() (*UploadFilesResponse, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type debugdUploadBootstrapperClient struct {
|
||||
type debugdUploadFilesClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *debugdUploadBootstrapperClient) Send(m *Chunk) error {
|
||||
func (x *debugdUploadFilesClient) Send(m *FileTransferMessage) error {
|
||||
return x.ClientStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *debugdUploadBootstrapperClient) CloseAndRecv() (*UploadBootstrapperResponse, error) {
|
||||
func (x *debugdUploadFilesClient) CloseAndRecv() (*UploadFilesResponse, error) {
|
||||
if err := x.ClientStream.CloseSend(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m := new(UploadBootstrapperResponse)
|
||||
m := new(UploadFilesResponse)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (c *debugdClient) DownloadBootstrapper(ctx context.Context, in *DownloadBootstrapperRequest, opts ...grpc.CallOption) (Debugd_DownloadBootstrapperClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &Debugd_ServiceDesc.Streams[1], "/debugd.Debugd/DownloadBootstrapper", opts...)
|
||||
func (c *debugdClient) DownloadFiles(ctx context.Context, in *DownloadFilesRequest, opts ...grpc.CallOption) (Debugd_DownloadFilesClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &Debugd_ServiceDesc.Streams[1], "/debugd.Debugd/DownloadFiles", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
x := &debugdDownloadBootstrapperClient{stream}
|
||||
x := &debugdDownloadFilesClient{stream}
|
||||
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -104,17 +104,17 @@ func (c *debugdClient) DownloadBootstrapper(ctx context.Context, in *DownloadBoo
|
||||
return x, nil
|
||||
}
|
||||
|
||||
type Debugd_DownloadBootstrapperClient interface {
|
||||
Recv() (*Chunk, error)
|
||||
type Debugd_DownloadFilesClient interface {
|
||||
Recv() (*FileTransferMessage, error)
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
type debugdDownloadBootstrapperClient struct {
|
||||
type debugdDownloadFilesClient struct {
|
||||
grpc.ClientStream
|
||||
}
|
||||
|
||||
func (x *debugdDownloadBootstrapperClient) Recv() (*Chunk, error) {
|
||||
m := new(Chunk)
|
||||
func (x *debugdDownloadFilesClient) Recv() (*FileTransferMessage, error) {
|
||||
m := new(FileTransferMessage)
|
||||
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -136,8 +136,8 @@ func (c *debugdClient) UploadSystemServiceUnits(ctx context.Context, in *UploadS
|
||||
type DebugdServer interface {
|
||||
SetInfo(context.Context, *SetInfoRequest) (*SetInfoResponse, error)
|
||||
GetInfo(context.Context, *GetInfoRequest) (*GetInfoResponse, error)
|
||||
UploadBootstrapper(Debugd_UploadBootstrapperServer) error
|
||||
DownloadBootstrapper(*DownloadBootstrapperRequest, Debugd_DownloadBootstrapperServer) error
|
||||
UploadFiles(Debugd_UploadFilesServer) error
|
||||
DownloadFiles(*DownloadFilesRequest, Debugd_DownloadFilesServer) error
|
||||
UploadSystemServiceUnits(context.Context, *UploadSystemdServiceUnitsRequest) (*UploadSystemdServiceUnitsResponse, error)
|
||||
mustEmbedUnimplementedDebugdServer()
|
||||
}
|
||||
@ -152,11 +152,11 @@ func (UnimplementedDebugdServer) SetInfo(context.Context, *SetInfoRequest) (*Set
|
||||
func (UnimplementedDebugdServer) GetInfo(context.Context, *GetInfoRequest) (*GetInfoResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetInfo not implemented")
|
||||
}
|
||||
func (UnimplementedDebugdServer) UploadBootstrapper(Debugd_UploadBootstrapperServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method UploadBootstrapper not implemented")
|
||||
func (UnimplementedDebugdServer) UploadFiles(Debugd_UploadFilesServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method UploadFiles not implemented")
|
||||
}
|
||||
func (UnimplementedDebugdServer) DownloadBootstrapper(*DownloadBootstrapperRequest, Debugd_DownloadBootstrapperServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method DownloadBootstrapper not implemented")
|
||||
func (UnimplementedDebugdServer) DownloadFiles(*DownloadFilesRequest, Debugd_DownloadFilesServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method DownloadFiles not implemented")
|
||||
}
|
||||
func (UnimplementedDebugdServer) UploadSystemServiceUnits(context.Context, *UploadSystemdServiceUnitsRequest) (*UploadSystemdServiceUnitsResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method UploadSystemServiceUnits not implemented")
|
||||
@ -210,50 +210,50 @@ func _Debugd_GetInfo_Handler(srv interface{}, ctx context.Context, dec func(inte
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Debugd_UploadBootstrapper_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(DebugdServer).UploadBootstrapper(&debugdUploadBootstrapperServer{stream})
|
||||
func _Debugd_UploadFiles_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
return srv.(DebugdServer).UploadFiles(&debugdUploadFilesServer{stream})
|
||||
}
|
||||
|
||||
type Debugd_UploadBootstrapperServer interface {
|
||||
SendAndClose(*UploadBootstrapperResponse) error
|
||||
Recv() (*Chunk, error)
|
||||
type Debugd_UploadFilesServer interface {
|
||||
SendAndClose(*UploadFilesResponse) error
|
||||
Recv() (*FileTransferMessage, error)
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type debugdUploadBootstrapperServer struct {
|
||||
type debugdUploadFilesServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *debugdUploadBootstrapperServer) SendAndClose(m *UploadBootstrapperResponse) error {
|
||||
func (x *debugdUploadFilesServer) SendAndClose(m *UploadFilesResponse) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
func (x *debugdUploadBootstrapperServer) Recv() (*Chunk, error) {
|
||||
m := new(Chunk)
|
||||
func (x *debugdUploadFilesServer) Recv() (*FileTransferMessage, error) {
|
||||
m := new(FileTransferMessage)
|
||||
if err := x.ServerStream.RecvMsg(m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func _Debugd_DownloadBootstrapper_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(DownloadBootstrapperRequest)
|
||||
func _Debugd_DownloadFiles_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
m := new(DownloadFilesRequest)
|
||||
if err := stream.RecvMsg(m); err != nil {
|
||||
return err
|
||||
}
|
||||
return srv.(DebugdServer).DownloadBootstrapper(m, &debugdDownloadBootstrapperServer{stream})
|
||||
return srv.(DebugdServer).DownloadFiles(m, &debugdDownloadFilesServer{stream})
|
||||
}
|
||||
|
||||
type Debugd_DownloadBootstrapperServer interface {
|
||||
Send(*Chunk) error
|
||||
type Debugd_DownloadFilesServer interface {
|
||||
Send(*FileTransferMessage) error
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
type debugdDownloadBootstrapperServer struct {
|
||||
type debugdDownloadFilesServer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (x *debugdDownloadBootstrapperServer) Send(m *Chunk) error {
|
||||
func (x *debugdDownloadFilesServer) Send(m *FileTransferMessage) error {
|
||||
return x.ServerStream.SendMsg(m)
|
||||
}
|
||||
|
||||
@ -297,13 +297,13 @@ var Debugd_ServiceDesc = grpc.ServiceDesc{
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "UploadBootstrapper",
|
||||
Handler: _Debugd_UploadBootstrapper_Handler,
|
||||
StreamName: "UploadFiles",
|
||||
Handler: _Debugd_UploadFiles_Handler,
|
||||
ClientStreams: true,
|
||||
},
|
||||
{
|
||||
StreamName: "DownloadBootstrapper",
|
||||
Handler: _Debugd_DownloadBootstrapper_Handler,
|
||||
StreamName: "DownloadFiles",
|
||||
Handler: _Debugd_DownloadFiles_Handler,
|
||||
ServerStreams: true,
|
||||
},
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user