diff --git a/components/content-service/pkg/layer/provider.go b/components/content-service/pkg/layer/provider.go index 851492c3280e85..82ea905e767d32 100644 --- a/components/content-service/pkg/layer/provider.go +++ b/components/content-service/pkg/layer/provider.go @@ -227,6 +227,103 @@ func (s *Provider) GetContentLayer(ctx context.Context, owner, workspaceID strin return nil, nil, xerrors.Errorf("no backup or valid initializer present") } +// GetContentLayerPVC provides the content layer for a workspace that uses PVC feature +func (s *Provider) GetContentLayerPVC(ctx context.Context, owner, workspaceID string, initializer *csapi.WorkspaceInitializer) (l []Layer, manifest *csapi.WorkspaceContentManifest, err error) { + span, ctx := tracing.FromContext(ctx, "GetContentLayerPVC") + defer tracing.FinishSpan(span, &err) + tracing.ApplyOWI(span, log.OWI(owner, workspaceID, "")) + + defer func() { + // we never return a nil manifest, just maybe an empty one + if manifest == nil { + manifest = &csapi.WorkspaceContentManifest{ + Type: csapi.TypeFullWorkspaceContentV1, + } + } + }() + + // check if workspace has an FWB + bucket := s.Storage.Bucket(owner) + span.LogKV("bucket", bucket) + + // check if legacy workspace backup is present + var layer *Layer + info, err := s.Storage.SignDownload(ctx, bucket, fmt.Sprintf(fmtLegacyBackupName, workspaceID), &storage.SignedURLOptions{}) + if err != nil && !xerrors.Is(err, storage.ErrNotFound) { + return nil, nil, err + } + if err == nil { + span.LogKV("backup found", "legacy workspace backup") + + cdesc, err := executor.PrepareFromBackup(info.URL) + if err != nil { + return nil, nil, err + } + + layer, err = contentDescriptorToLayerPVC(cdesc) + if err != nil { + return nil, nil, err + } + + l = []Layer{*layer} + return l, manifest, nil + } + + // At this point we've found neither a full-workspace-backup, nor a legacy backup. + // It's time to use the initializer. + if gis := initializer.GetSnapshot(); gis != nil { + return s.getSnapshotContentLayer(ctx, gis) + } + if pis := initializer.GetPrebuild(); pis != nil { + l, manifest, err = s.getPrebuildContentLayer(ctx, pis) + if err != nil { + log.WithError(err).WithFields(log.OWI(owner, workspaceID, "")).Warn("cannot initialize from prebuild - falling back to Git") + span.LogKV("fallback-to-git", err.Error()) + + // we failed creating a prebuild initializer, so let's try falling back to the Git part. + var init []*csapi.WorkspaceInitializer + for _, gi := range pis.Git { + init = append(init, &csapi.WorkspaceInitializer{ + Spec: &csapi.WorkspaceInitializer_Git{ + Git: gi, + }, + }) + } + initializer = &csapi.WorkspaceInitializer{ + Spec: &csapi.WorkspaceInitializer_Composite{ + Composite: &csapi.CompositeInitializer{ + Initializer: init, + }, + }, + } + } else { + // creating the initializer worked - we're done here + return + } + } + if gis := initializer.GetGit(); gis != nil { + span.LogKV("initializer", "Git") + + cdesc, err := executor.Prepare(initializer, nil) + if err != nil { + return nil, nil, err + } + + layer, err = contentDescriptorToLayerPVC(cdesc) + if err != nil { + return nil, nil, err + } + return []Layer{*layer}, nil, nil + } + if initializer.GetBackup() != nil { + // We were asked to restore a backup and have tried above. We've failed to restore the backup, + // hance the backup initializer failed. + return nil, nil, xerrors.Errorf("no backup found") + } + + return nil, nil, xerrors.Errorf("no backup or valid initializer present") +} + func (s *Provider) getSnapshotContentLayer(ctx context.Context, sp *csapi.SnapshotInitializer) (l []Layer, manifest *csapi.WorkspaceContentManifest, err error) { span, ctx := tracing.FromContext(ctx, "getSnapshotContentLayer") defer tracing.FinishSpan(span, &err) @@ -368,6 +465,17 @@ func contentDescriptorToLayer(cdesc []byte) (*Layer, error) { ) } +// version of this function for persistent volume claim feature +// we cannot use /workspace folder as when mounting /workspace folder through PVC +// it will mask anything that was in container layer, hence we are using /.workspace instead here +func contentDescriptorToLayerPVC(cdesc []byte) (*Layer, error) { + return layerFromContent( + fileInLayer{&tar.Header{Typeflag: tar.TypeDir, Name: "/.workspace", Uid: initializer.GitpodUID, Gid: initializer.GitpodGID, Mode: 0755}, nil}, + fileInLayer{&tar.Header{Typeflag: tar.TypeDir, Name: "/.workspace/.gitpod", Uid: initializer.GitpodUID, Gid: initializer.GitpodGID, Mode: 0755}, nil}, + fileInLayer{&tar.Header{Typeflag: tar.TypeReg, Name: "/.workspace/.gitpod/content.json", Uid: initializer.GitpodUID, Gid: initializer.GitpodGID, Mode: 0755, Size: int64(len(cdesc))}, cdesc}, + ) +} + func workspaceReadyLayer(src csapi.WorkspaceInitSource) (*Layer, error) { msg := csapi.WorkspaceReadyMessage{ Source: src, diff --git a/components/supervisor/pkg/supervisor/supervisor.go b/components/supervisor/pkg/supervisor/supervisor.go index 6a6ba11fd657b4..43f381b0e6df33 100644 --- a/components/supervisor/pkg/supervisor/supervisor.go +++ b/components/supervisor/pkg/supervisor/supervisor.go @@ -1221,6 +1221,12 @@ func startContentInit(ctx context.Context, cfg *Config, wg *sync.WaitGroup, cst }() fn := "/workspace/.gitpod/content.json" + fnReady := "/workspace/.gitpod/ready" + if _, err := os.Stat("/.workspace/.gitpod/content.json"); !os.IsNotExist(err) { + fn = "/.workspace/.gitpod/content.json" + fnReady = "/.workspace/.gitpod/ready" + log.Info("Detected content.json in /.workspace folder, assuming PVC feature enabled") + } f, err := os.Open(fn) if os.IsNotExist(err) { log.WithError(err).Info("no content init descriptor found - not trying to run it") @@ -1230,7 +1236,7 @@ func startContentInit(ctx context.Context, cfg *Config, wg *sync.WaitGroup, cst // TODO: rewrite using fsnotify t := time.NewTicker(100 * time.Millisecond) for range t.C { - b, err := os.ReadFile("/workspace/.gitpod/ready") + b, err := os.ReadFile(fnReady) if err != nil { if !os.IsNotExist(err) { log.WithError(err).Error("cannot read content ready file") diff --git a/components/workspacekit/cmd/rings.go b/components/workspacekit/cmd/rings.go index 15a18242b263f4..f146f51efde1fa 100644 --- a/components/workspacekit/cmd/rings.go +++ b/components/workspacekit/cmd/rings.go @@ -111,7 +111,7 @@ var ring0Cmd = &cobra.Command{ cmd.Stderr = os.Stderr cmd.Env = append(os.Environ(), "WORKSPACEKIT_FSSHIFT="+prep.FsShift.String(), - fmt.Sprintf("WORKSPACEKIT_FULL_WORKSPACE_BACKUP=%v", prep.FullWorkspaceBackup), + fmt.Sprintf("WORKSPACEKIT_NO_WORKSPACE_MOUNT=%v", prep.FullWorkspaceBackup || prep.PersistentVolumeClaim), ) if err := cmd.Start(); err != nil { @@ -303,7 +303,8 @@ var ring1Cmd = &cobra.Command{ // FWB workspaces do not require mounting /workspace // if that is done, the backup will not contain any change in the directory - if os.Getenv("WORKSPACEKIT_FULL_WORKSPACE_BACKUP") != "true" { + // same applies to persistent volume claims, we cannot mount /workspace folder when PVC is used + if os.Getenv("WORKSPACEKIT_NO_WORKSPACE_MOUNT") != "true" { mnts = append(mnts, mnte{Target: "/workspace", Flags: unix.MS_BIND | unix.MS_REC}, ) @@ -416,6 +417,7 @@ var ring1Cmd = &cobra.Command{ log.WithError(err).Error("cannot mount proc") return } + _, err = client.EvacuateCGroup(ctx, &daemonapi.EvacuateCGroupRequest{}) if err != nil { client.Close() diff --git a/components/ws-daemon-api/daemon.proto b/components/ws-daemon-api/daemon.proto index b5b5b164809469..5e8ead2d3038c3 100644 --- a/components/ws-daemon-api/daemon.proto +++ b/components/ws-daemon-api/daemon.proto @@ -55,6 +55,11 @@ message InitWorkspaceRequest { // storage_quota_bytes enforces a storage quate for the workspace if set to a value != 0 int64 storage_quota_bytes = 8; + + // persistent_volume_claim means that we use PVC instead of HostPath to mount /workspace folder and content-init + // happens inside workspacekit instead of in ws-daemon. We also use k8s Snapshots to store\restore workspace content + // instead of GCS\tar. + bool persistent_volume_claim = 9; } // WorkspaceMetadata is data associated with a workspace that's required for other parts of the system to function diff --git a/components/ws-daemon-api/go.mod b/components/ws-daemon-api/go.mod index 6d290344d12b55..86b69e9026bd2e 100644 --- a/components/ws-daemon-api/go.mod +++ b/components/ws-daemon-api/go.mod @@ -1,3 +1,5 @@ module github.com/gitpod-io/generated_code_dependencies go 1.18 + +require google.golang.org/protobuf v1.28.0 // indirect diff --git a/components/ws-daemon-api/go.sum b/components/ws-daemon-api/go.sum index e69de29bb2d1d6..e38d2e36121ca0 100644 --- a/components/ws-daemon-api/go.sum +++ b/components/ws-daemon-api/go.sum @@ -0,0 +1,6 @@ +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= diff --git a/components/ws-daemon-api/go/daemon.pb.go b/components/ws-daemon-api/go/daemon.pb.go index ec20567ff4ddcf..9ece9648f97e1e 100644 --- a/components/ws-daemon-api/go/daemon.pb.go +++ b/components/ws-daemon-api/go/daemon.pb.go @@ -108,6 +108,10 @@ type InitWorkspaceRequest struct { RemoteStorageDisabled bool `protobuf:"varint,7,opt,name=remote_storage_disabled,json=remoteStorageDisabled,proto3" json:"remoteStorageDisabled,omitempty"` // storage_quota_bytes enforces a storage quate for the workspace if set to a value != 0 StorageQuotaBytes int64 `protobuf:"varint,8,opt,name=storage_quota_bytes,json=storageQuotaBytes,proto3" json:"storageQuotaBytes,omitempty"` + // persistent_volume_claim means that we use PVC instead of HostPath to mount /workspace folder and content-init + // happens inside workspacekit instead of in ws-daemon. We also use k8s Snapshots to store\restore workspace content + // instead of GCS\tar. + PersistentVolumeClaim bool `protobuf:"varint,9,opt,name=persistent_volume_claim,json=persistentVolumeClaim,proto3" json:"persistentVolumeClaim,omitempty"` } func (x *InitWorkspaceRequest) Reset() { @@ -191,6 +195,13 @@ func (x *InitWorkspaceRequest) GetStorageQuotaBytes() int64 { return 0 } +func (x *InitWorkspaceRequest) GetPersistentVolumeClaim() bool { + if x != nil { + return x.PersistentVolumeClaim + } + return false +} + // WorkspaceMetadata is data associated with a workspace that's required for other parts of the system to function type WorkspaceMetadata struct { state protoimpl.MessageState `json:"state,omitempty"` @@ -700,7 +711,7 @@ var file_daemon_proto_rawDesc = []byte{ 0x77, 0x73, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x1a, 0x25, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2d, 0x61, 0x70, 0x69, 0x2f, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, - 0xf4, 0x02, 0x0a, 0x14, 0x49, 0x6e, 0x69, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, + 0xac, 0x03, 0x0a, 0x14, 0x49, 0x6e, 0x69, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x37, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x77, 0x73, 0x64, @@ -723,78 +734,82 @@ var file_daemon_proto_rawDesc = []byte{ 0x12, 0x2e, 0x0a, 0x13, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x71, 0x75, 0x6f, 0x74, 0x61, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x42, 0x79, 0x74, 0x65, 0x73, - 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x22, 0x42, 0x0a, 0x11, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x6f, - 0x77, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, - 0x72, 0x12, 0x17, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x61, 0x49, 0x64, 0x22, 0x17, 0x0a, 0x15, 0x49, 0x6e, - 0x69, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x24, 0x0a, 0x12, 0x57, 0x61, 0x69, 0x74, 0x46, 0x6f, 0x72, 0x49, 0x6e, - 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x15, 0x0a, 0x13, 0x57, 0x61, 0x69, - 0x74, 0x46, 0x6f, 0x72, 0x49, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x54, 0x0a, 0x13, 0x54, 0x61, 0x6b, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x2d, 0x0a, 0x12, 0x72, 0x65, 0x74, 0x75, 0x72, - 0x6e, 0x5f, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x6c, 0x79, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x11, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x49, 0x6d, 0x6d, 0x65, 0x64, - 0x69, 0x61, 0x74, 0x65, 0x6c, 0x79, 0x22, 0x28, 0x0a, 0x14, 0x54, 0x61, 0x6b, 0x65, 0x53, 0x6e, - 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, - 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, - 0x22, 0x62, 0x0a, 0x17, 0x44, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x62, - 0x61, 0x63, 0x6b, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x62, 0x61, 0x63, - 0x6b, 0x75, 0x70, 0x12, 0x1f, 0x0a, 0x0b, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x5f, 0x6c, 0x6f, - 0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, - 0x4c, 0x6f, 0x67, 0x73, 0x22, 0x54, 0x0a, 0x18, 0x44, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x65, 0x57, - 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x38, 0x0a, 0x0a, 0x67, 0x69, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, - 0x09, 0x67, 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x28, 0x0a, 0x16, 0x42, 0x61, - 0x63, 0x6b, 0x75, 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x02, 0x69, 0x64, 0x22, 0x2b, 0x0a, 0x17, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x57, 0x6f, - 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, - 0x6c, 0x2a, 0x51, 0x0a, 0x15, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, - 0x4e, 0x45, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x53, 0x45, 0x54, 0x54, 0x49, 0x4e, 0x47, 0x5f, - 0x55, 0x50, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x41, 0x56, 0x41, 0x49, 0x4c, 0x41, 0x42, 0x4c, - 0x45, 0x10, 0x02, 0x12, 0x0f, 0x0a, 0x0b, 0x57, 0x52, 0x41, 0x50, 0x50, 0x49, 0x4e, 0x47, 0x5f, - 0x55, 0x50, 0x10, 0x03, 0x32, 0xc3, 0x03, 0x0a, 0x17, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x52, 0x0a, 0x0d, 0x49, 0x6e, 0x69, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x12, 0x1e, 0x2e, 0x77, 0x73, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x49, 0x6e, 0x69, - 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1f, 0x2e, 0x77, 0x73, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x49, 0x6e, 0x69, - 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x12, 0x4c, 0x0a, 0x0b, 0x57, 0x61, 0x69, 0x74, 0x46, 0x6f, 0x72, 0x49, - 0x6e, 0x69, 0x74, 0x12, 0x1c, 0x2e, 0x77, 0x73, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x57, + 0x12, 0x36, 0x0a, 0x17, 0x70, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x76, + 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x5f, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x18, 0x09, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x15, 0x70, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x56, 0x6f, 0x6c, + 0x75, 0x6d, 0x65, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x22, 0x42, + 0x0a, 0x11, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x6d, 0x65, 0x74, + 0x61, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x61, + 0x49, 0x64, 0x22, 0x17, 0x0a, 0x15, 0x49, 0x6e, 0x69, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x0a, 0x12, 0x57, 0x61, 0x69, 0x74, 0x46, 0x6f, 0x72, 0x49, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1d, 0x2e, 0x77, 0x73, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x57, 0x61, 0x69, - 0x74, 0x46, 0x6f, 0x72, 0x49, 0x6e, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x4f, 0x0a, 0x0c, 0x54, 0x61, 0x6b, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, - 0x6f, 0x74, 0x12, 0x1d, 0x2e, 0x77, 0x73, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x54, 0x61, - 0x6b, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1e, 0x2e, 0x77, 0x73, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x54, 0x61, 0x6b, - 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x12, 0x5b, 0x0a, 0x10, 0x44, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x65, 0x57, 0x6f, - 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x21, 0x2e, 0x77, 0x73, 0x64, 0x61, 0x65, 0x6d, - 0x6f, 0x6e, 0x2e, 0x44, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x77, 0x73, 0x64, - 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x44, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x65, 0x57, 0x6f, 0x72, - 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x12, 0x58, 0x0a, 0x0f, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x12, 0x20, 0x2e, 0x77, 0x73, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x42, - 0x61, 0x63, 0x6b, 0x75, 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x77, 0x73, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, - 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x2b, 0x5a, 0x29, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2d, - 0x69, 0x6f, 0x2f, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2f, 0x77, 0x73, 0x2d, 0x64, 0x61, 0x65, - 0x6d, 0x6f, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, + 0x64, 0x22, 0x15, 0x0a, 0x13, 0x57, 0x61, 0x69, 0x74, 0x46, 0x6f, 0x72, 0x49, 0x6e, 0x69, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x54, 0x0a, 0x13, 0x54, 0x61, 0x6b, 0x65, + 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, + 0x2d, 0x0a, 0x12, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x5f, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, + 0x61, 0x74, 0x65, 0x6c, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x72, 0x65, 0x74, + 0x75, 0x72, 0x6e, 0x49, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x6c, 0x79, 0x22, 0x28, + 0x0a, 0x14, 0x54, 0x61, 0x6b, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0x62, 0x0a, 0x17, 0x44, 0x69, 0x73, 0x70, + 0x6f, 0x73, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x06, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12, 0x1f, 0x0a, 0x0b, 0x62, + 0x61, 0x63, 0x6b, 0x75, 0x70, 0x5f, 0x6c, 0x6f, 0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0a, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x4c, 0x6f, 0x67, 0x73, 0x22, 0x54, 0x0a, 0x18, + 0x44, 0x69, 0x73, 0x70, 0x6f, 0x73, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x0a, 0x67, 0x69, 0x74, 0x5f, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x69, + 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x09, 0x67, 0x69, 0x74, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x22, 0x28, 0x0a, 0x16, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x57, 0x6f, 0x72, 0x6b, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x2b, 0x0a, 0x17, + 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x2a, 0x51, 0x0a, 0x15, 0x57, 0x6f, 0x72, + 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, + 0x53, 0x45, 0x54, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x55, 0x50, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, + 0x41, 0x56, 0x41, 0x49, 0x4c, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x02, 0x12, 0x0f, 0x0a, 0x0b, 0x57, + 0x52, 0x41, 0x50, 0x50, 0x49, 0x4e, 0x47, 0x5f, 0x55, 0x50, 0x10, 0x03, 0x32, 0xc3, 0x03, 0x0a, + 0x17, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x52, 0x0a, 0x0d, 0x49, 0x6e, 0x69, 0x74, + 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1e, 0x2e, 0x77, 0x73, 0x64, 0x61, + 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x77, 0x73, 0x64, 0x61, + 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4c, 0x0a, 0x0b, + 0x57, 0x61, 0x69, 0x74, 0x46, 0x6f, 0x72, 0x49, 0x6e, 0x69, 0x74, 0x12, 0x1c, 0x2e, 0x77, 0x73, + 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x57, 0x61, 0x69, 0x74, 0x46, 0x6f, 0x72, 0x49, 0x6e, + 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x77, 0x73, 0x64, 0x61, + 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x57, 0x61, 0x69, 0x74, 0x46, 0x6f, 0x72, 0x49, 0x6e, 0x69, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4f, 0x0a, 0x0c, 0x54, 0x61, + 0x6b, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x1d, 0x2e, 0x77, 0x73, 0x64, + 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x54, 0x61, 0x6b, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, + 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x77, 0x73, 0x64, 0x61, + 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x54, 0x61, 0x6b, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5b, 0x0a, 0x10, 0x44, + 0x69, 0x73, 0x70, 0x6f, 0x73, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, + 0x21, 0x2e, 0x77, 0x73, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x44, 0x69, 0x73, 0x70, 0x6f, + 0x73, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x77, 0x73, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x44, 0x69, + 0x73, 0x70, 0x6f, 0x73, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x58, 0x0a, 0x0f, 0x42, 0x61, 0x63, 0x6b, + 0x75, 0x70, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x20, 0x2e, 0x77, 0x73, + 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x57, 0x6f, 0x72, + 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, + 0x77, 0x73, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x57, + 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x00, 0x42, 0x2b, 0x5a, 0x29, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2d, 0x69, 0x6f, 0x2f, 0x67, 0x69, 0x74, 0x70, 0x6f, + 0x64, 0x2f, 0x77, 0x73, 0x2d, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/components/ws-daemon-api/go/workspace_daemon.pb.go b/components/ws-daemon-api/go/workspace_daemon.pb.go index a51092d86d1e2d..5e67b5dd32394c 100644 --- a/components/ws-daemon-api/go/workspace_daemon.pb.go +++ b/components/ws-daemon-api/go/workspace_daemon.pb.go @@ -115,8 +115,9 @@ type PrepareForUserNSResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - FsShift FSShiftMethod `protobuf:"varint,1,opt,name=fs_shift,json=fsShift,proto3,enum=iws.FSShiftMethod" json:"fs_shift,omitempty"` - FullWorkspaceBackup bool `protobuf:"varint,2,opt,name=full_workspace_backup,json=fullWorkspaceBackup,proto3" json:"full_workspace_backup,omitempty"` + FsShift FSShiftMethod `protobuf:"varint,1,opt,name=fs_shift,json=fsShift,proto3,enum=iws.FSShiftMethod" json:"fs_shift,omitempty"` + FullWorkspaceBackup bool `protobuf:"varint,2,opt,name=full_workspace_backup,json=fullWorkspaceBackup,proto3" json:"full_workspace_backup,omitempty"` + PersistentVolumeClaim bool `protobuf:"varint,3,opt,name=persistent_volume_claim,json=persistentVolumeClaim,proto3" json:"persistent_volume_claim,omitempty"` } func (x *PrepareForUserNSResponse) Reset() { @@ -165,6 +166,13 @@ func (x *PrepareForUserNSResponse) GetFullWorkspaceBackup() bool { return false } +func (x *PrepareForUserNSResponse) GetPersistentVolumeClaim() bool { + if x != nil { + return x.PersistentVolumeClaim + } + return false +} + type WriteIDMappingResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -784,102 +792,106 @@ var file_workspace_daemon_proto_rawDesc = []byte{ 0x0a, 0x16, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x03, 0x69, 0x77, 0x73, 0x22, 0x19, 0x0a, 0x17, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x46, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x4e, - 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x7d, 0x0a, 0x18, 0x50, 0x72, 0x65, 0x70, - 0x61, 0x72, 0x65, 0x46, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x53, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x08, 0x66, 0x73, 0x5f, 0x73, 0x68, 0x69, 0x66, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x46, 0x53, 0x53, - 0x68, 0x69, 0x66, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x07, 0x66, 0x73, 0x53, 0x68, - 0x69, 0x66, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x77, 0x6f, 0x72, 0x6b, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x13, 0x66, 0x75, 0x6c, 0x6c, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x22, 0x51, 0x0a, 0x16, 0x57, 0x72, 0x69, 0x74, 0x65, - 0x49, 0x44, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x65, - 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, - 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x22, 0xd4, 0x01, 0x0a, 0x15, 0x57, - 0x72, 0x69, 0x74, 0x65, 0x49, 0x44, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x03, 0x70, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x67, 0x69, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x03, 0x67, 0x69, 0x64, 0x12, 0x3c, 0x0a, 0x07, 0x6d, 0x61, 0x70, 0x70, - 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x69, 0x77, 0x73, 0x2e, - 0x57, 0x72, 0x69, 0x74, 0x65, 0x49, 0x44, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x6d, - 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x1a, 0x59, 0x0a, 0x07, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, - 0x67, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, - 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x68, 0x6f, 0x73, 0x74, 0x49, 0x64, 0x12, 0x12, 0x0a, - 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x73, 0x69, 0x7a, - 0x65, 0x22, 0x17, 0x0a, 0x15, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x43, 0x47, 0x72, - 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x18, 0x0a, 0x16, 0x45, 0x76, - 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x43, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3c, 0x0a, 0x10, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, - 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x70, - 0x69, 0x64, 0x22, 0x13, 0x0a, 0x11, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3d, 0x0a, 0x11, 0x55, 0x6d, 0x6f, 0x75, 0x6e, - 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, - 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x14, 0x0a, 0x12, 0x55, 0x6d, 0x6f, 0x75, 0x6e, 0x74, - 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x11, 0x0a, 0x0f, - 0x54, 0x65, 0x61, 0x72, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, - 0x2c, 0x0a, 0x10, 0x54, 0x65, 0x61, 0x72, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x29, 0x0a, - 0x15, 0x53, 0x65, 0x74, 0x75, 0x70, 0x50, 0x61, 0x69, 0x72, 0x56, 0x65, 0x74, 0x68, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x18, 0x0a, 0x16, 0x53, 0x65, 0x74, 0x75, - 0x70, 0x50, 0x61, 0x69, 0x72, 0x56, 0x65, 0x74, 0x68, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x2a, 0x26, 0x0a, 0x0d, 0x46, 0x53, 0x53, 0x68, 0x69, 0x66, 0x74, 0x4d, 0x65, 0x74, - 0x68, 0x6f, 0x64, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x48, 0x49, 0x46, 0x54, 0x46, 0x53, 0x10, 0x00, - 0x12, 0x08, 0x0a, 0x04, 0x46, 0x55, 0x53, 0x45, 0x10, 0x01, 0x32, 0x89, 0x05, 0x0a, 0x12, 0x49, - 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x12, 0x51, 0x0a, 0x10, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x46, 0x6f, 0x72, 0x55, - 0x73, 0x65, 0x72, 0x4e, 0x53, 0x12, 0x1c, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x50, 0x72, 0x65, 0x70, - 0x61, 0x72, 0x65, 0x46, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x53, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, - 0x65, 0x46, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x0e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x49, 0x44, 0x4d, - 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x1a, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x57, 0x72, 0x69, - 0x74, 0x65, 0x49, 0x44, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x49, 0x44, - 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x12, 0x4b, 0x0a, 0x0e, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x43, 0x47, 0x72, - 0x6f, 0x75, 0x70, 0x12, 0x1a, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, - 0x74, 0x65, 0x43, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1b, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x43, 0x47, - 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3c, - 0x0a, 0x09, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x12, 0x15, 0x2e, 0x69, 0x77, - 0x73, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, - 0x6f, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3f, 0x0a, 0x0a, - 0x55, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x12, 0x16, 0x2e, 0x69, 0x77, 0x73, - 0x2e, 0x55, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x55, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x50, - 0x72, 0x6f, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3d, 0x0a, - 0x0a, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x79, 0x73, 0x66, 0x73, 0x12, 0x15, 0x2e, 0x69, 0x77, - 0x73, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, - 0x6f, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x40, 0x0a, 0x0b, - 0x55, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x79, 0x73, 0x66, 0x73, 0x12, 0x16, 0x2e, 0x69, 0x77, - 0x73, 0x2e, 0x55, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x55, 0x6d, 0x6f, 0x75, 0x6e, 0x74, - 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x39, - 0x0a, 0x08, 0x54, 0x65, 0x61, 0x72, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x14, 0x2e, 0x69, 0x77, 0x73, - 0x2e, 0x54, 0x65, 0x61, 0x72, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x15, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x54, 0x65, 0x61, 0x72, 0x64, 0x6f, 0x77, 0x6e, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x0e, 0x53, 0x65, 0x74, - 0x75, 0x70, 0x50, 0x61, 0x69, 0x72, 0x56, 0x65, 0x74, 0x68, 0x73, 0x12, 0x1a, 0x2e, 0x69, 0x77, - 0x73, 0x2e, 0x53, 0x65, 0x74, 0x75, 0x70, 0x50, 0x61, 0x69, 0x72, 0x56, 0x65, 0x74, 0x68, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x53, 0x65, - 0x74, 0x75, 0x70, 0x50, 0x61, 0x69, 0x72, 0x56, 0x65, 0x74, 0x68, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x2b, 0x5a, 0x29, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2d, 0x69, 0x6f, 0x2f, 0x67, - 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2f, 0x77, 0x73, 0x2d, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2f, - 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xb5, 0x01, 0x0a, 0x18, 0x50, 0x72, 0x65, + 0x70, 0x61, 0x72, 0x65, 0x46, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x53, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x08, 0x66, 0x73, 0x5f, 0x73, 0x68, 0x69, 0x66, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x46, 0x53, + 0x53, 0x68, 0x69, 0x66, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x07, 0x66, 0x73, 0x53, + 0x68, 0x69, 0x66, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x77, 0x6f, 0x72, + 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x13, 0x66, 0x75, 0x6c, 0x6c, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x12, 0x36, 0x0a, 0x17, 0x70, 0x65, 0x72, 0x73, + 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x5f, 0x63, 0x6c, + 0x61, 0x69, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x70, 0x65, 0x72, 0x73, 0x69, + 0x73, 0x74, 0x65, 0x6e, 0x74, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x43, 0x6c, 0x61, 0x69, 0x6d, + 0x22, 0x51, 0x0a, 0x16, 0x57, 0x72, 0x69, 0x74, 0x65, 0x49, 0x44, 0x4d, 0x61, 0x70, 0x70, 0x69, + 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x63, 0x6f, + 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, + 0x6f, 0x64, 0x65, 0x22, 0xd4, 0x01, 0x0a, 0x15, 0x57, 0x72, 0x69, 0x74, 0x65, 0x49, 0x44, 0x4d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, + 0x03, 0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x70, 0x69, 0x64, 0x12, + 0x10, 0x0a, 0x03, 0x67, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x67, 0x69, + 0x64, 0x12, 0x3c, 0x0a, 0x07, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x49, 0x44, + 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4d, + 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x1a, + 0x59, 0x0a, 0x07, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, + 0x07, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, + 0x68, 0x6f, 0x73, 0x74, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x22, 0x17, 0x0a, 0x15, 0x45, 0x76, + 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x43, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x22, 0x18, 0x0a, 0x16, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x43, + 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3c, 0x0a, + 0x10, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x13, 0x0a, 0x11, 0x4d, + 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x3d, 0x0a, 0x11, 0x55, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x10, 0x0a, + 0x03, 0x70, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, + 0x14, 0x0a, 0x12, 0x55, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x11, 0x0a, 0x0f, 0x54, 0x65, 0x61, 0x72, 0x64, 0x6f, 0x77, + 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2c, 0x0a, 0x10, 0x54, 0x65, 0x61, 0x72, + 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, + 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, + 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x29, 0x0a, 0x15, 0x53, 0x65, 0x74, 0x75, 0x70, 0x50, + 0x61, 0x69, 0x72, 0x56, 0x65, 0x74, 0x68, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x70, 0x69, + 0x64, 0x22, 0x18, 0x0a, 0x16, 0x53, 0x65, 0x74, 0x75, 0x70, 0x50, 0x61, 0x69, 0x72, 0x56, 0x65, + 0x74, 0x68, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0x26, 0x0a, 0x0d, 0x46, + 0x53, 0x53, 0x68, 0x69, 0x66, 0x74, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x0b, 0x0a, 0x07, + 0x53, 0x48, 0x49, 0x46, 0x54, 0x46, 0x53, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x55, 0x53, + 0x45, 0x10, 0x01, 0x32, 0x89, 0x05, 0x0a, 0x12, 0x49, 0x6e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x51, 0x0a, 0x10, 0x50, 0x72, + 0x65, 0x70, 0x61, 0x72, 0x65, 0x46, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x53, 0x12, 0x1c, + 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x46, 0x6f, 0x72, 0x55, + 0x73, 0x65, 0x72, 0x4e, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x69, + 0x77, 0x73, 0x2e, 0x50, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65, 0x46, 0x6f, 0x72, 0x55, 0x73, 0x65, + 0x72, 0x4e, 0x53, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4b, 0x0a, + 0x0e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x49, 0x44, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, + 0x1a, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x49, 0x44, 0x4d, 0x61, 0x70, + 0x70, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x69, 0x77, + 0x73, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x49, 0x44, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x0e, 0x45, 0x76, + 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x43, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x1a, 0x2e, 0x69, + 0x77, 0x73, 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x43, 0x47, 0x72, 0x6f, 0x75, + 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x45, + 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x43, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3c, 0x0a, 0x09, 0x4d, 0x6f, 0x75, 0x6e, 0x74, + 0x50, 0x72, 0x6f, 0x63, 0x12, 0x15, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, + 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x69, 0x77, + 0x73, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3f, 0x0a, 0x0a, 0x55, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x50, + 0x72, 0x6f, 0x63, 0x12, 0x16, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x55, 0x6d, 0x6f, 0x75, 0x6e, 0x74, + 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x69, 0x77, + 0x73, 0x2e, 0x55, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3d, 0x0a, 0x0a, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x53, + 0x79, 0x73, 0x66, 0x73, 0x12, 0x15, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, + 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x69, 0x77, + 0x73, 0x2e, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x40, 0x0a, 0x0b, 0x55, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x53, + 0x79, 0x73, 0x66, 0x73, 0x12, 0x16, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x55, 0x6d, 0x6f, 0x75, 0x6e, + 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x69, + 0x77, 0x73, 0x2e, 0x55, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x39, 0x0a, 0x08, 0x54, 0x65, 0x61, 0x72, 0x64, + 0x6f, 0x77, 0x6e, 0x12, 0x14, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x54, 0x65, 0x61, 0x72, 0x64, 0x6f, + 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x69, 0x77, 0x73, 0x2e, + 0x54, 0x65, 0x61, 0x72, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x0e, 0x53, 0x65, 0x74, 0x75, 0x70, 0x50, 0x61, 0x69, 0x72, 0x56, + 0x65, 0x74, 0x68, 0x73, 0x12, 0x1a, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x53, 0x65, 0x74, 0x75, 0x70, + 0x50, 0x61, 0x69, 0x72, 0x56, 0x65, 0x74, 0x68, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1b, 0x2e, 0x69, 0x77, 0x73, 0x2e, 0x53, 0x65, 0x74, 0x75, 0x70, 0x50, 0x61, 0x69, 0x72, + 0x56, 0x65, 0x74, 0x68, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, + 0x2b, 0x5a, 0x29, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x69, + 0x74, 0x70, 0x6f, 0x64, 0x2d, 0x69, 0x6f, 0x2f, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2f, 0x77, + 0x73, 0x2d, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/components/ws-daemon-api/typescript/src/daemon_pb.d.ts b/components/ws-daemon-api/typescript/src/daemon_pb.d.ts index c9533914d7ddd8..0622963e7a4af2 100644 --- a/components/ws-daemon-api/typescript/src/daemon_pb.d.ts +++ b/components/ws-daemon-api/typescript/src/daemon_pb.d.ts @@ -13,7 +13,7 @@ import * as jspb from "google-protobuf"; import * as content_service_api_initializer_pb from "@gitpod/content-service/lib"; -export class InitWorkspaceRequest extends jspb.Message { +export class InitWorkspaceRequest extends jspb.Message { getId(): string; setId(value: string): InitWorkspaceRequest; @@ -36,6 +36,8 @@ export class InitWorkspaceRequest extends jspb.Message { setRemoteStorageDisabled(value: boolean): InitWorkspaceRequest; getStorageQuotaBytes(): number; setStorageQuotaBytes(value: number): InitWorkspaceRequest; + getPersistentVolumeClaim(): boolean; + setPersistentVolumeClaim(value: boolean): InitWorkspaceRequest; serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): InitWorkspaceRequest.AsObject; @@ -56,10 +58,11 @@ export namespace InitWorkspaceRequest { contentManifest: Uint8Array | string, remoteStorageDisabled: boolean, storageQuotaBytes: number, + persistentVolumeClaim: boolean, } } -export class WorkspaceMetadata extends jspb.Message { +export class WorkspaceMetadata extends jspb.Message { getOwner(): string; setOwner(value: string): WorkspaceMetadata; getMetaId(): string; @@ -82,7 +85,7 @@ export namespace WorkspaceMetadata { } } -export class InitWorkspaceResponse extends jspb.Message { +export class InitWorkspaceResponse extends jspb.Message { serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): InitWorkspaceResponse.AsObject; @@ -99,7 +102,7 @@ export namespace InitWorkspaceResponse { } } -export class WaitForInitRequest extends jspb.Message { +export class WaitForInitRequest extends jspb.Message { getId(): string; setId(value: string): WaitForInitRequest; @@ -119,7 +122,7 @@ export namespace WaitForInitRequest { } } -export class WaitForInitResponse extends jspb.Message { +export class WaitForInitResponse extends jspb.Message { serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): WaitForInitResponse.AsObject; @@ -136,7 +139,7 @@ export namespace WaitForInitResponse { } } -export class TakeSnapshotRequest extends jspb.Message { +export class TakeSnapshotRequest extends jspb.Message { getId(): string; setId(value: string): TakeSnapshotRequest; getReturnImmediately(): boolean; @@ -159,7 +162,7 @@ export namespace TakeSnapshotRequest { } } -export class TakeSnapshotResponse extends jspb.Message { +export class TakeSnapshotResponse extends jspb.Message { getUrl(): string; setUrl(value: string): TakeSnapshotResponse; @@ -179,7 +182,7 @@ export namespace TakeSnapshotResponse { } } -export class DisposeWorkspaceRequest extends jspb.Message { +export class DisposeWorkspaceRequest extends jspb.Message { getId(): string; setId(value: string): DisposeWorkspaceRequest; getBackup(): boolean; @@ -205,7 +208,7 @@ export namespace DisposeWorkspaceRequest { } } -export class DisposeWorkspaceResponse extends jspb.Message { +export class DisposeWorkspaceResponse extends jspb.Message { hasGitStatus(): boolean; clearGitStatus(): void; @@ -228,7 +231,7 @@ export namespace DisposeWorkspaceResponse { } } -export class BackupWorkspaceRequest extends jspb.Message { +export class BackupWorkspaceRequest extends jspb.Message { getId(): string; setId(value: string): BackupWorkspaceRequest; @@ -248,7 +251,7 @@ export namespace BackupWorkspaceRequest { } } -export class BackupWorkspaceResponse extends jspb.Message { +export class BackupWorkspaceResponse extends jspb.Message { getUrl(): string; setUrl(value: string): BackupWorkspaceResponse; diff --git a/components/ws-daemon-api/typescript/src/daemon_pb.js b/components/ws-daemon-api/typescript/src/daemon_pb.js index e5a96e8ef520cc..68521ba99a3d7a 100644 --- a/components/ws-daemon-api/typescript/src/daemon_pb.js +++ b/components/ws-daemon-api/typescript/src/daemon_pb.js @@ -304,7 +304,8 @@ proto.wsdaemon.InitWorkspaceRequest.toObject = function(includeInstance, msg) { fullWorkspaceBackup: jspb.Message.getBooleanFieldWithDefault(msg, 4, false), contentManifest: msg.getContentManifest_asB64(), remoteStorageDisabled: jspb.Message.getBooleanFieldWithDefault(msg, 7, false), - storageQuotaBytes: jspb.Message.getFieldWithDefault(msg, 8, 0) + storageQuotaBytes: jspb.Message.getFieldWithDefault(msg, 8, 0), + persistentVolumeClaim: jspb.Message.getBooleanFieldWithDefault(msg, 9, false) }; if (includeInstance) { @@ -371,6 +372,10 @@ proto.wsdaemon.InitWorkspaceRequest.deserializeBinaryFromReader = function(msg, var value = /** @type {number} */ (reader.readInt64()); msg.setStorageQuotaBytes(value); break; + case 9: + var value = /** @type {boolean} */ (reader.readBool()); + msg.setPersistentVolumeClaim(value); + break; default: reader.skipField(); break; @@ -451,6 +456,13 @@ proto.wsdaemon.InitWorkspaceRequest.serializeBinaryToWriter = function(message, f ); } + f = message.getPersistentVolumeClaim(); + if (f) { + writer.writeBool( + 9, + f + ); + } }; @@ -642,6 +654,24 @@ proto.wsdaemon.InitWorkspaceRequest.prototype.setStorageQuotaBytes = function(va }; +/** + * optional bool persistent_volume_claim = 9; + * @return {boolean} + */ +proto.wsdaemon.InitWorkspaceRequest.prototype.getPersistentVolumeClaim = function() { + return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 9, false)); +}; + + +/** + * @param {boolean} value + * @return {!proto.wsdaemon.InitWorkspaceRequest} returns this + */ +proto.wsdaemon.InitWorkspaceRequest.prototype.setPersistentVolumeClaim = function(value) { + return jspb.Message.setProto3BooleanField(this, 9, value); +}; + + diff --git a/components/ws-daemon-api/typescript/src/workspace_daemon_pb.d.ts b/components/ws-daemon-api/typescript/src/workspace_daemon_pb.d.ts index c22b5b5d04fbbf..ebc614ef65de23 100644 --- a/components/ws-daemon-api/typescript/src/workspace_daemon_pb.d.ts +++ b/components/ws-daemon-api/typescript/src/workspace_daemon_pb.d.ts @@ -34,6 +34,8 @@ export class PrepareForUserNSResponse extends jspb.Message { setFsShift(value: FSShiftMethod): PrepareForUserNSResponse; getFullWorkspaceBackup(): boolean; setFullWorkspaceBackup(value: boolean): PrepareForUserNSResponse; + getPersistentVolumeClaim(): boolean; + setPersistentVolumeClaim(value: boolean): PrepareForUserNSResponse; serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): PrepareForUserNSResponse.AsObject; @@ -49,6 +51,7 @@ export namespace PrepareForUserNSResponse { export type AsObject = { fsShift: FSShiftMethod, fullWorkspaceBackup: boolean, + persistentVolumeClaim: boolean, } } diff --git a/components/ws-daemon-api/typescript/src/workspace_daemon_pb.js b/components/ws-daemon-api/typescript/src/workspace_daemon_pb.js index 79e34748746f1f..3fbb7fea7caf98 100644 --- a/components/ws-daemon-api/typescript/src/workspace_daemon_pb.js +++ b/components/ws-daemon-api/typescript/src/workspace_daemon_pb.js @@ -486,7 +486,8 @@ proto.iws.PrepareForUserNSResponse.prototype.toObject = function(opt_includeInst proto.iws.PrepareForUserNSResponse.toObject = function(includeInstance, msg) { var f, obj = { fsShift: jspb.Message.getFieldWithDefault(msg, 1, 0), - fullWorkspaceBackup: jspb.Message.getBooleanFieldWithDefault(msg, 2, false) + fullWorkspaceBackup: jspb.Message.getBooleanFieldWithDefault(msg, 2, false), + persistentVolumeClaim: jspb.Message.getBooleanFieldWithDefault(msg, 3, false) }; if (includeInstance) { @@ -531,6 +532,10 @@ proto.iws.PrepareForUserNSResponse.deserializeBinaryFromReader = function(msg, r var value = /** @type {boolean} */ (reader.readBool()); msg.setFullWorkspaceBackup(value); break; + case 3: + var value = /** @type {boolean} */ (reader.readBool()); + msg.setPersistentVolumeClaim(value); + break; default: reader.skipField(); break; @@ -574,6 +579,13 @@ proto.iws.PrepareForUserNSResponse.serializeBinaryToWriter = function(message, w f ); } + f = message.getPersistentVolumeClaim(); + if (f) { + writer.writeBool( + 3, + f + ); + } }; @@ -613,6 +625,24 @@ proto.iws.PrepareForUserNSResponse.prototype.setFullWorkspaceBackup = function(v }; +/** + * optional bool persistent_volume_claim = 3; + * @return {boolean} + */ +proto.iws.PrepareForUserNSResponse.prototype.getPersistentVolumeClaim = function() { + return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 3, false)); +}; + + +/** + * @param {boolean} value + * @return {!proto.iws.PrepareForUserNSResponse} returns this + */ +proto.iws.PrepareForUserNSResponse.prototype.setPersistentVolumeClaim = function(value) { + return jspb.Message.setProto3BooleanField(this, 3, value); +}; + + diff --git a/components/ws-daemon-api/workspace_daemon.proto b/components/ws-daemon-api/workspace_daemon.proto index 7802e5d7ee4a0a..d3ea9963d7a815 100644 --- a/components/ws-daemon-api/workspace_daemon.proto +++ b/components/ws-daemon-api/workspace_daemon.proto @@ -54,6 +54,7 @@ message PrepareForUserNSRequest {} message PrepareForUserNSResponse { FSShiftMethod fs_shift = 1; bool full_workspace_backup = 2; + bool persistent_volume_claim = 3; } // FSShiftMethod describes the means by which we establish the ID shift for diff --git a/components/ws-daemon/pkg/content/service.go b/components/ws-daemon/pkg/content/service.go index 79cce6a5308965..94a7ebcf38b10b 100644 --- a/components/ws-daemon/pkg/content/service.go +++ b/components/ws-daemon/pkg/content/service.go @@ -153,10 +153,7 @@ func (s *WorkspaceService) InitWorkspace(ctx context.Context, req *api.InitWorks var ( wsloc string ) - if req.FullWorkspaceBackup { - if s.runtime == nil { - return nil, status.Errorf(codes.FailedPrecondition, "full workspace backup is not available - not connected to container runtime") - } + if req.FullWorkspaceBackup || req.PersistentVolumeClaim { var mf csapi.WorkspaceContentManifest if len(req.ContentManifest) == 0 { return nil, status.Errorf(codes.InvalidArgument, "content manifest is required") @@ -165,6 +162,10 @@ func (s *WorkspaceService) InitWorkspace(ctx context.Context, req *api.InitWorks if err != nil { return nil, status.Errorf(codes.InvalidArgument, "invalid content manifest: %s", err.Error()) } + if req.PersistentVolumeClaim { + // todo(pavel): setting wsloc as otherwise mkdir fails later on. + wsloc = filepath.Join(s.store.Location, req.Id) + } } else { wsloc = filepath.Join(s.store.Location, req.Id) } @@ -177,7 +178,7 @@ func (s *WorkspaceService) InitWorkspace(ctx context.Context, req *api.InitWorks return nil, err } - if !req.FullWorkspaceBackup { + if !req.FullWorkspaceBackup && !req.PersistentVolumeClaim { var remoteContent map[string]storage.DownloadInfo // some workspaces don't have remote storage enabled. For those workspaces we clearly @@ -259,6 +260,7 @@ func (s *WorkspaceService) creator(req *api.InitWorkspaceRequest) session.Worksp WorkspaceID: req.Metadata.MetaId, InstanceID: req.Id, FullWorkspaceBackup: req.FullWorkspaceBackup, + PersistentVolumeClaim: req.PersistentVolumeClaim, ContentManifest: req.ContentManifest, RemoteStorageDisabled: req.RemoteStorageDisabled, StorageQuota: int(req.StorageQuotaBytes), @@ -379,6 +381,7 @@ func (s *WorkspaceService) uploadWorkspaceContent(ctx context.Context, sess *ses span.SetTag("backup", backupName) span.SetTag("manifest", mfName) span.SetTag("full", sess.FullWorkspaceBackup) + span.SetTag("pvc", sess.PersistentVolumeClaim) defer tracing.FinishSpan(span, &err) var ( @@ -387,6 +390,11 @@ func (s *WorkspaceService) uploadWorkspaceContent(ctx context.Context, sess *ses mf csapi.WorkspaceContentManifest ) + if sess.PersistentVolumeClaim { + // currently not supported (will be done differently via snapshots) + return status.Error(codes.FailedPrecondition, "uploadWorkspaceContent not supported yet when PVC feature is enabled") + } + if sess.FullWorkspaceBackup { // Backup any change located in the upper overlay directory of the workspace in the node loc = filepath.Join(sess.ServiceLocDaemon, "upper") @@ -673,6 +681,9 @@ func (s *WorkspaceService) TakeSnapshot(ctx context.Context, req *api.TakeSnapsh if sess.RemoteStorageDisabled { return nil, status.Error(codes.FailedPrecondition, "workspace has no remote storage") } + if sess.PersistentVolumeClaim { + return nil, status.Error(codes.FailedPrecondition, "snapshots are not support yet when persistent volume claim feature is enabled") + } rs, ok := sess.NonPersistentAttrs[session.AttrRemoteStorage].(storage.DirectAccess) if rs == nil || !ok { log.WithFields(sess.OWI()).WithError(err).Error("cannot upload snapshot: no remote storage configured") @@ -731,6 +742,9 @@ func (s *WorkspaceService) BackupWorkspace(ctx context.Context, req *api.BackupW if sess.RemoteStorageDisabled { return nil, status.Errorf(codes.FailedPrecondition, "workspace has no remote storage") } + if sess.PersistentVolumeClaim { + return nil, status.Errorf(codes.FailedPrecondition, "workspace backup not supported yet when persistent volume claim feature is enabled") + } rs, ok := sess.NonPersistentAttrs[session.AttrRemoteStorage].(storage.DirectAccess) if rs == nil || !ok { log.WithFields(sess.OWI()).WithError(err).Error("cannot take backup: no remote storage configured") diff --git a/components/ws-daemon/pkg/internal/session/workspace.go b/components/ws-daemon/pkg/internal/session/workspace.go index e51e0a3fe7be14..7d10f3900fdb85 100644 --- a/components/ws-daemon/pkg/internal/session/workspace.go +++ b/components/ws-daemon/pkg/internal/session/workspace.go @@ -55,14 +55,15 @@ type Workspace struct { // workspace resides. If this workspace has no Git working copy, this field is an empty string. CheckoutLocation string `json:"checkoutLocation"` - CreatedAt time.Time `json:"createdAt"` - DoBackup bool `json:"doBackup"` - Owner string `json:"owner"` - WorkspaceID string `json:"metaID"` - InstanceID string `json:"workspaceID"` - LastGitStatus *csapi.GitStatus `json:"lastGitStatus"` - FullWorkspaceBackup bool `json:"fullWorkspaceBackup"` - ContentManifest []byte `json:"contentManifest"` + CreatedAt time.Time `json:"createdAt"` + DoBackup bool `json:"doBackup"` + Owner string `json:"owner"` + WorkspaceID string `json:"metaID"` + InstanceID string `json:"workspaceID"` + LastGitStatus *csapi.GitStatus `json:"lastGitStatus"` + FullWorkspaceBackup bool `json:"fullWorkspaceBackup"` + PersistentVolumeClaim bool `json:"persistentVolumeClaim"` + ContentManifest []byte `json:"contentManifest"` ServiceLocNode string `json:"serviceLocNode"` ServiceLocDaemon string `json:"serviceLocDaemon"` @@ -216,6 +217,11 @@ func (s *Workspace) Dispose(ctx context.Context) (err error) { return err } + if s.PersistentVolumeClaim { + // nothing to dispose as files are on persistent volume claim + return nil + } + if !s.FullWorkspaceBackup { err = os.RemoveAll(s.Location) } diff --git a/components/ws-daemon/pkg/iws/iws.go b/components/ws-daemon/pkg/iws/iws.go index 54ae4f471c9a3a..e584632787a583 100644 --- a/components/ws-daemon/pkg/iws/iws.go +++ b/components/ws-daemon/pkg/iws/iws.go @@ -269,8 +269,9 @@ func (wbs *InWorkspaceServiceServer) PrepareForUserNS(ctx context.Context, req * } return &api.PrepareForUserNSResponse{ - FsShift: api.FSShiftMethod_FUSE, - FullWorkspaceBackup: wbs.Session.FullWorkspaceBackup, + FsShift: api.FSShiftMethod_FUSE, + FullWorkspaceBackup: wbs.Session.FullWorkspaceBackup, + PersistentVolumeClaim: wbs.Session.PersistentVolumeClaim, }, nil } @@ -297,8 +298,9 @@ func (wbs *InWorkspaceServiceServer) PrepareForUserNS(ctx context.Context, req * } return &api.PrepareForUserNSResponse{ - FsShift: api.FSShiftMethod_SHIFTFS, - FullWorkspaceBackup: wbs.Session.FullWorkspaceBackup, + FsShift: api.FSShiftMethod_SHIFTFS, + FullWorkspaceBackup: wbs.Session.FullWorkspaceBackup, + PersistentVolumeClaim: wbs.Session.PersistentVolumeClaim, }, nil } diff --git a/components/ws-manager-api/go/config/config.go b/components/ws-manager-api/go/config/config.go index 1a30833fc2aa54..63735767533386 100644 --- a/components/ws-manager-api/go/config/config.go +++ b/components/ws-manager-api/go/config/config.go @@ -116,6 +116,7 @@ type Configuration struct { type WorkspaceClass struct { Container ContainerConfiguration `json:"container"` Templates WorkspacePodTemplateConfiguration `json:"templates"` + PVC PVCConfiguration `json:"pvc"` } // WorkspaceTimeoutConfiguration configures the timeout behaviour of workspaces @@ -258,6 +259,20 @@ var validWorkspaceURLTemplate = validation.By(func(o interface{}) error { return err }) +// PVCConfiguration configures properties of persistent volume claim to use for workspace containers +type PVCConfiguration struct { + Size resource.Quantity `json:"size"` + StorageClass string `json:"storage-class"` +} + +// Validate validates a PVC configuration +func (c *PVCConfiguration) Validate() error { + return validation.ValidateStruct(c, + validation.Field(&c.Size, validation.Required), + validation.Field(&c.StorageClass, validation.Required), + ) +} + // ContainerConfiguration configures properties of workspace pod container type ContainerConfiguration struct { Requests *ResourceConfiguration `json:"requests,omitempty"` diff --git a/components/ws-manager/config-schema.json b/components/ws-manager/config-schema.json index 9c47e7d81e90ac..f35e1704186ac2 100644 --- a/components/ws-manager/config-schema.json +++ b/components/ws-manager/config-schema.json @@ -25,12 +25,17 @@ }, "AllContainerConfiguration": { "required": [ - "workspace" + "workspace", + "pvc" ], "properties": { "workspace": { "$schema": "http://json-schema.org/draft-04/schema#", "$ref": "#/definitions/ContainerConfiguration" + }, + "pvc": { + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/PVCConfiguration" } }, "additionalProperties": false, @@ -126,6 +131,22 @@ "additionalProperties": false, "type": "object" }, + "PVCConfiguration": { + "required": [ + "size", + "storage-class" + ], + "properties": { + "size": { + "type": "string" + }, + "storage-class": { + "type": "string" + } + }, + "additionalProperties": false, + "type": "object" + }, "InitProbeConfiguration": { "properties": { "timeout": { diff --git a/components/ws-manager/example-config.json b/components/ws-manager/example-config.json index 15d0688efd0883..217a2ab83278d5 100644 --- a/components/ws-manager/example-config.json +++ b/components/ws-manager/example-config.json @@ -15,6 +15,10 @@ "memory": "3246Mi" } }, + "pvc": { + "size": "30Gi", + "storage-class": "" + }, "sync": { "image": "eu.gcr.io/gitpod-dev/gitpod-ws-daemon:cw-ws-manager.24", "requests": { diff --git a/components/ws-manager/pkg/manager/annotations.go b/components/ws-manager/pkg/manager/annotations.go index a84b3c9705a5de..a9ef97cc60e7b2 100644 --- a/components/ws-manager/pkg/manager/annotations.go +++ b/components/ws-manager/pkg/manager/annotations.go @@ -63,6 +63,9 @@ const ( // fullWorkspaceBackupAnnotation is set on workspaces which operate using a full workspace backup fullWorkspaceBackupAnnotation = "gitpod/fullWorkspaceBackup" + // pvcWorkspaceFeatureAnnotation is set on workspaces which are using persistent_volume_claim feature + pvcWorkspaceFeatureAnnotation = "gitpod.io/pvcFeature" + // gitpodFinalizerName is the name of the Gitpod finalizer we use to clean up a workspace gitpodFinalizerName = "gitpod.io/finalizer" diff --git a/components/ws-manager/pkg/manager/create.go b/components/ws-manager/pkg/manager/create.go index b96bb74dfca597..318f6f18cab91e 100644 --- a/components/ws-manager/pkg/manager/create.go +++ b/components/ws-manager/pkg/manager/create.go @@ -217,6 +217,42 @@ func mergeProbe(dst, src reflect.Value) (err error) { return nil } +func (m *Manager) createPVCForWorkspacePod(startContext *startWorkspaceContext) (*corev1.PersistentVolumeClaim, error) { + req := startContext.Request + var prefix string + switch req.Type { + case api.WorkspaceType_PREBUILD: + prefix = "prebuild" + case api.WorkspaceType_PROBE: + prefix = "probe" + case api.WorkspaceType_IMAGEBUILD: + prefix = "imagebuild" + default: + prefix = "ws" + } + + PVCConfig := m.Config.WorkspaceClasses[""].PVC + if startContext.Class != nil { + PVCConfig = startContext.Class.PVC + } + storageClassName := PVCConfig.StorageClass + return &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("%s-%s", prefix, req.Id), + Namespace: m.Config.Namespace, + }, + Spec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce}, + StorageClassName: &storageClassName, + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceName(corev1.ResourceStorage): PVCConfig.Size, + }, + }, + }, + }, nil +} + // createDefiniteWorkspacePod creates a workspace pod without regard for any template. // The result of this function can be deployed and it would work. func (m *Manager) createDefiniteWorkspacePod(startContext *startWorkspaceContext) (*corev1.Pod, error) { @@ -421,6 +457,7 @@ func (m *Manager) createDefiniteWorkspacePod(startContext *startWorkspaceContext }, } + PodSecContext := corev1.PodSecurityContext{} pod := corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("%s-%s", prefix, req.Id), @@ -436,6 +473,7 @@ func (m *Manager) createDefiniteWorkspacePod(startContext *startWorkspaceContext SchedulerName: m.Config.SchedulerName, EnableServiceLinks: &boolFalse, Affinity: affinity, + SecurityContext: &PodSecContext, Containers: []corev1.Container{ *workspaceContainer, }, @@ -489,6 +527,27 @@ func (m *Manager) createDefiniteWorkspacePod(startContext *startWorkspaceContext case api.WorkspaceFeatureFlag_NOOP: + case api.WorkspaceFeatureFlag_PERSISTENT_VOLUME_CLAIM: + pod.Labels[pvcWorkspaceFeatureAnnotation] = "true" + + // update volume to use persistent volume claim, and name of it is the same as pod's name + pvcName := pod.ObjectMeta.Name + pod.Spec.Volumes[0].VolumeSource = corev1.VolumeSource{ + PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ + ClaimName: pvcName, + }, + } + + // SubPath so that lost+found is not visible + pod.Spec.Containers[0].VolumeMounts[0].SubPath = "workspace" + // not needed, since it is using dedicated disk + pod.Spec.Containers[0].VolumeMounts[0].MountPropagation = nil + + // pavel: 133332 is the Gitpod UID (33333) shifted by 99999. The shift happens inside the workspace container due to the user namespace use. + // We set this magical ID to make sure that gitpod user inside the workspace can write into /workspace folder mounted by PVC + gitpodGUID := int64(133332) + pod.Spec.SecurityContext.FSGroup = &gitpodGUID + default: return nil, xerrors.Errorf("unknown feature flag: %v", feature) } @@ -611,6 +670,7 @@ func (m *Manager) createWorkspaceContainer(startContext *startWorkspaceContext) TerminationMessagePolicy: corev1.TerminationMessageReadFile, }, nil } + func (m *Manager) createWorkspaceEnvironment(startContext *startWorkspaceContext) ([]corev1.EnvVar, error) { spec := startContext.Request.Spec diff --git a/components/ws-manager/pkg/manager/imagespec.go b/components/ws-manager/pkg/manager/imagespec.go index c3d9775ad07561..388b9fd6aaf7f0 100644 --- a/components/ws-manager/pkg/manager/imagespec.go +++ b/components/ws-manager/pkg/manager/imagespec.go @@ -18,6 +18,7 @@ import ( wsk8s "github.com/gitpod-io/gitpod/common-go/kubernetes" "github.com/gitpod-io/gitpod/common-go/tracing" csapi "github.com/gitpod-io/gitpod/content-service/api" + "github.com/gitpod-io/gitpod/content-service/pkg/layer" regapi "github.com/gitpod-io/gitpod/registry-facade/api" ) @@ -54,7 +55,10 @@ func (m *Manager) GetImageSpec(ctx context.Context, req *regapi.GetImageSpecRequ return nil, status.Error(codes.Internal, err.Error()) } - if _, ok := pod.Labels[fullWorkspaceBackupAnnotation]; ok { + _, fullWorkspaceBackupEnabled := pod.Labels[fullWorkspaceBackupAnnotation] + _, pvcFeatureEnabled := pod.Labels[pvcWorkspaceFeatureAnnotation] + + if fullWorkspaceBackupEnabled || pvcFeatureEnabled { owner := pod.Labels[wsk8s.OwnerLabel] workspaceID := pod.Labels[wsk8s.MetaIDLabel] initializerRaw, ok := pod.Annotations[workspaceInitializerAnnotation] @@ -70,7 +74,12 @@ func (m *Manager) GetImageSpec(ctx context.Context, req *regapi.GetImageSpecRequ if err != nil { return nil, xerrors.Errorf("cannot unmarshal init config: %w", err) } - cl, _, err := m.Content.GetContentLayer(ctx, owner, workspaceID, &initializer) + var cl []layer.Layer + if pvcFeatureEnabled { + cl, _, err = m.Content.GetContentLayerPVC(ctx, owner, workspaceID, &initializer) + } else { + cl, _, err = m.Content.GetContentLayer(ctx, owner, workspaceID, &initializer) + } if err != nil { return nil, xerrors.Errorf("cannot get content layer: %w", err) } diff --git a/components/ws-manager/pkg/manager/manager.go b/components/ws-manager/pkg/manager/manager.go index 9429ae235a9571..c58a40fe15b977 100644 --- a/components/ws-manager/pkg/manager/manager.go +++ b/components/ws-manager/pkg/manager/manager.go @@ -211,6 +211,25 @@ func (m *Manager) StartWorkspace(ctx context.Context, req *api.StartWorkspaceReq } span.LogKV("event", "pod description created") + var createPVC bool + for _, feature := range startContext.Request.Spec.FeatureFlags { + if feature == api.WorkspaceFeatureFlag_PERSISTENT_VOLUME_CLAIM { + createPVC = true + break + } + } + if createPVC { + clog.Info("PVC feature detected, creating PVC object") + pvc, err := m.createPVCForWorkspacePod(startContext) + if err != nil { + return nil, xerrors.Errorf("cannot create pvc for workspace pod: %w", err) + } + err = m.Clientset.Create(ctx, pvc) + if err != nil { + return nil, xerrors.Errorf("cannot create pvc object for workspace pod: %w", err) + } + } + // create the Pod in the cluster and wait until is scheduled // https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.22.md#workloads-that-saturate-nodes-with-pods-may-see-pods-that-fail-due-to-node-admission backoff := wait.Backoff{ diff --git a/components/ws-manager/pkg/manager/monitor.go b/components/ws-manager/pkg/manager/monitor.go index c4f26a817ab336..ea3e8325bee459 100644 --- a/components/ws-manager/pkg/manager/monitor.go +++ b/components/ws-manager/pkg/manager/monitor.go @@ -22,6 +22,7 @@ import ( grpc_status "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/watch" "sigs.k8s.io/controller-runtime/pkg/client" @@ -660,6 +661,7 @@ func (m *Monitor) probeWorkspaceReady(ctx context.Context, pod *corev1.Pod) (res // prior to this call this function returns once initialization is complete. func (m *Monitor) initializeWorkspaceContent(ctx context.Context, pod *corev1.Pod) (err error) { _, fullWorkspaceBackup := pod.Labels[fullWorkspaceBackupAnnotation] + _, pvcFeatureEnabled := pod.Labels[pvcWorkspaceFeatureAnnotation] workspaceID, ok := pod.Annotations[workspaceIDAnnotation] if !ok { @@ -713,7 +715,7 @@ func (m *Monitor) initializeWorkspaceContent(ctx context.Context, pod *corev1.Po return xerrors.Errorf("cannot unmarshal init config: %w", err) } - if fullWorkspaceBackup { + if fullWorkspaceBackup || pvcFeatureEnabled { _, mf, err := m.manager.Content.GetContentLayer(ctx, workspaceMeta.Owner, workspaceMeta.MetaId, &initializer) if err != nil { return xerrors.Errorf("cannot download workspace content manifest: %w", err) @@ -754,6 +756,7 @@ func (m *Monitor) initializeWorkspaceContent(ctx context.Context, pod *corev1.Po }, Initializer: &initializer, FullWorkspaceBackup: fullWorkspaceBackup, + PersistentVolumeClaim: pvcFeatureEnabled, ContentManifest: contentManifest, RemoteStorageDisabled: shouldDisableRemoteStorage(pod), StorageQuotaBytes: storage.Value(), @@ -867,6 +870,30 @@ func (m *Monitor) finalizeWorkspaceContent(ctx context.Context, wso *workspaceOb return false, nil, nil } + // todo(pavel): once we add snapshot objects, this will be moved to a better place + if wso.Pod != nil { + _, pvcFeatureEnabled := wso.Pod.Labels[pvcWorkspaceFeatureAnnotation] + if pvcFeatureEnabled { + // pvc name is the same as pod name + pvcName := wso.Pod.Name + log.Infof("Deleting PVC: %s", pvcName) + // todo: once we add snapshot objects, this will be changed to create snapshot object first + pvcErr := m.manager.Clientset.Delete(ctx, + &corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: pvcName, + Namespace: m.manager.Config.Namespace, + }, + }, + ) + span.LogKV("event", "pvc deleted") + + if pvcErr != nil { + log.WithError(pvcErr).Errorf("failed to delete pvc `%s`", pvcName) + } + } + } + // Maybe the workspace never made it to a phase where we actually initialized a workspace. // Assuming that once we've had a nodeName we've spoken to ws-daemon it's safe to assume that if // we don't have a nodeName we don't need to dipose the workspace. diff --git a/components/ws-manager/pkg/manager/testdata/cdwp_admission.golden b/components/ws-manager/pkg/manager/testdata/cdwp_admission.golden index 8e66b88f6547d3..63464467403c3d 100644 --- a/components/ws-manager/pkg/manager/testdata/cdwp_admission.golden +++ b/components/ws-manager/pkg/manager/testdata/cdwp_admission.golden @@ -211,6 +211,7 @@ "restartPolicy": "Never", "serviceAccountName": "workspace", "automountServiceAccountToken": false, + "securityContext": {}, "hostname": "foobar", "affinity": { "nodeAffinity": { diff --git a/components/ws-manager/pkg/manager/testdata/cdwp_affinity.golden b/components/ws-manager/pkg/manager/testdata/cdwp_affinity.golden index e5a4af9f16e08d..b4c4a9c8f286d9 100644 --- a/components/ws-manager/pkg/manager/testdata/cdwp_affinity.golden +++ b/components/ws-manager/pkg/manager/testdata/cdwp_affinity.golden @@ -203,6 +203,7 @@ "restartPolicy": "Never", "serviceAccountName": "workspace", "automountServiceAccountToken": false, + "securityContext": {}, "hostname": "foobar", "affinity": { "nodeAffinity": { diff --git a/components/ws-manager/pkg/manager/testdata/cdwp_class.golden b/components/ws-manager/pkg/manager/testdata/cdwp_class.golden index e36345f886b706..51ee3459244068 100644 --- a/components/ws-manager/pkg/manager/testdata/cdwp_class.golden +++ b/components/ws-manager/pkg/manager/testdata/cdwp_class.golden @@ -203,6 +203,7 @@ "dnsPolicy": "None", "serviceAccountName": "workspace", "automountServiceAccountToken": false, + "securityContext": {}, "imagePullSecrets": [ { "name": "dockerhub-typefox" diff --git a/components/ws-manager/pkg/manager/testdata/cdwp_customcerts.golden b/components/ws-manager/pkg/manager/testdata/cdwp_customcerts.golden index f4e856d5050bb8..08410381ddcfd7 100644 --- a/components/ws-manager/pkg/manager/testdata/cdwp_customcerts.golden +++ b/components/ws-manager/pkg/manager/testdata/cdwp_customcerts.golden @@ -225,6 +225,7 @@ "restartPolicy": "Never", "serviceAccountName": "workspace", "automountServiceAccountToken": false, + "securityContext": {}, "hostname": "foobar", "affinity": { "nodeAffinity": { diff --git a/components/ws-manager/pkg/manager/testdata/cdwp_empty_resource_req.golden b/components/ws-manager/pkg/manager/testdata/cdwp_empty_resource_req.golden index 2cada68b6ac7bc..2344bcf9eef837 100644 --- a/components/ws-manager/pkg/manager/testdata/cdwp_empty_resource_req.golden +++ b/components/ws-manager/pkg/manager/testdata/cdwp_empty_resource_req.golden @@ -205,6 +205,7 @@ "restartPolicy": "Never", "serviceAccountName": "workspace", "automountServiceAccountToken": false, + "securityContext": {}, "hostname": "foobar", "affinity": { "nodeAffinity": { diff --git a/components/ws-manager/pkg/manager/testdata/cdwp_envvars.golden b/components/ws-manager/pkg/manager/testdata/cdwp_envvars.golden index c0051239f85da5..398ebfd81b047b 100644 --- a/components/ws-manager/pkg/manager/testdata/cdwp_envvars.golden +++ b/components/ws-manager/pkg/manager/testdata/cdwp_envvars.golden @@ -240,6 +240,7 @@ "restartPolicy": "Never", "serviceAccountName": "workspace", "automountServiceAccountToken": false, + "securityContext": {}, "hostname": "foobar", "affinity": { "nodeAffinity": { diff --git a/components/ws-manager/pkg/manager/testdata/cdwp_fixedresources.golden b/components/ws-manager/pkg/manager/testdata/cdwp_fixedresources.golden index 071ece5b23d70e..1e4d05e9ca3808 100644 --- a/components/ws-manager/pkg/manager/testdata/cdwp_fixedresources.golden +++ b/components/ws-manager/pkg/manager/testdata/cdwp_fixedresources.golden @@ -208,6 +208,7 @@ "restartPolicy": "Never", "serviceAccountName": "workspace", "automountServiceAccountToken": false, + "securityContext": {}, "hostname": "foobar", "affinity": { "nodeAffinity": { diff --git a/components/ws-manager/pkg/manager/testdata/cdwp_fullworkspacebackup.golden b/components/ws-manager/pkg/manager/testdata/cdwp_fullworkspacebackup.golden index c59724952d5174..61218be7a5fc7a 100644 --- a/components/ws-manager/pkg/manager/testdata/cdwp_fullworkspacebackup.golden +++ b/components/ws-manager/pkg/manager/testdata/cdwp_fullworkspacebackup.golden @@ -197,6 +197,7 @@ "restartPolicy": "Never", "serviceAccountName": "workspace", "automountServiceAccountToken": false, + "securityContext": {}, "hostname": "foobar", "affinity": { "nodeAffinity": { diff --git a/components/ws-manager/pkg/manager/testdata/cdwp_imagebuild.golden b/components/ws-manager/pkg/manager/testdata/cdwp_imagebuild.golden index 3cc285173df670..53c72f84beb469 100644 --- a/components/ws-manager/pkg/manager/testdata/cdwp_imagebuild.golden +++ b/components/ws-manager/pkg/manager/testdata/cdwp_imagebuild.golden @@ -229,6 +229,7 @@ "restartPolicy": "Never", "serviceAccountName": "workspace", "automountServiceAccountToken": false, + "securityContext": {}, "hostname": "foobar", "affinity": { "nodeAffinity": { diff --git a/components/ws-manager/pkg/manager/testdata/cdwp_imagebuild_template.golden b/components/ws-manager/pkg/manager/testdata/cdwp_imagebuild_template.golden index 3a7b8a5d081d98..2f7dbb5474ce08 100644 --- a/components/ws-manager/pkg/manager/testdata/cdwp_imagebuild_template.golden +++ b/components/ws-manager/pkg/manager/testdata/cdwp_imagebuild_template.golden @@ -234,6 +234,7 @@ "dnsPolicy": "None", "serviceAccountName": "workspace", "automountServiceAccountToken": false, + "securityContext": {}, "imagePullSecrets": [ { "name": "dockerhub-gitpod" diff --git a/components/ws-manager/pkg/manager/testdata/cdwp_no_ideimage.golden b/components/ws-manager/pkg/manager/testdata/cdwp_no_ideimage.golden index 1bc2f7eb59f8c1..6ae2eb21a6cffa 100644 --- a/components/ws-manager/pkg/manager/testdata/cdwp_no_ideimage.golden +++ b/components/ws-manager/pkg/manager/testdata/cdwp_no_ideimage.golden @@ -205,6 +205,7 @@ "restartPolicy": "Never", "serviceAccountName": "workspace", "automountServiceAccountToken": false, + "securityContext": {}, "hostname": "foobar", "affinity": { "nodeAffinity": { diff --git a/components/ws-manager/pkg/manager/testdata/cdwp_prebuild.golden b/components/ws-manager/pkg/manager/testdata/cdwp_prebuild.golden index 84ad4ca1189988..75f6b3091cf102 100644 --- a/components/ws-manager/pkg/manager/testdata/cdwp_prebuild.golden +++ b/components/ws-manager/pkg/manager/testdata/cdwp_prebuild.golden @@ -211,6 +211,7 @@ "restartPolicy": "Never", "serviceAccountName": "workspace", "automountServiceAccountToken": false, + "securityContext": {}, "hostname": "foobar", "affinity": { "nodeAffinity": { diff --git a/components/ws-manager/pkg/manager/testdata/cdwp_prebuild_template.golden b/components/ws-manager/pkg/manager/testdata/cdwp_prebuild_template.golden index 28a98e9af64d4a..4031bd80e48f99 100644 --- a/components/ws-manager/pkg/manager/testdata/cdwp_prebuild_template.golden +++ b/components/ws-manager/pkg/manager/testdata/cdwp_prebuild_template.golden @@ -216,6 +216,7 @@ "dnsPolicy": "None", "serviceAccountName": "workspace", "automountServiceAccountToken": false, + "securityContext": {}, "imagePullSecrets": [ { "name": "dockerhub-typefox" diff --git a/components/ws-manager/pkg/manager/testdata/cdwp_prebuild_template_override_resources.golden b/components/ws-manager/pkg/manager/testdata/cdwp_prebuild_template_override_resources.golden index caa61fc8fd85f6..a99a122bc47770 100644 --- a/components/ws-manager/pkg/manager/testdata/cdwp_prebuild_template_override_resources.golden +++ b/components/ws-manager/pkg/manager/testdata/cdwp_prebuild_template_override_resources.golden @@ -216,6 +216,7 @@ "dnsPolicy": "None", "serviceAccountName": "workspace", "automountServiceAccountToken": false, + "securityContext": {}, "imagePullSecrets": [ { "name": "dockerhub-typefox" diff --git a/components/ws-manager/pkg/manager/testdata/cdwp_probe.golden b/components/ws-manager/pkg/manager/testdata/cdwp_probe.golden index 60d16e27dfcad2..d428482147b53e 100644 --- a/components/ws-manager/pkg/manager/testdata/cdwp_probe.golden +++ b/components/ws-manager/pkg/manager/testdata/cdwp_probe.golden @@ -211,6 +211,7 @@ "restartPolicy": "Never", "serviceAccountName": "workspace", "automountServiceAccountToken": false, + "securityContext": {}, "hostname": "foobar", "affinity": { "nodeAffinity": { diff --git a/components/ws-manager/pkg/manager/testdata/cdwp_readinessprobe.golden b/components/ws-manager/pkg/manager/testdata/cdwp_readinessprobe.golden index 3b5719af1179c6..501fc9e115ed21 100644 --- a/components/ws-manager/pkg/manager/testdata/cdwp_readinessprobe.golden +++ b/components/ws-manager/pkg/manager/testdata/cdwp_readinessprobe.golden @@ -207,6 +207,7 @@ "restartPolicy": "Never", "serviceAccountName": "workspace", "automountServiceAccountToken": false, + "securityContext": {}, "hostname": "foobar", "affinity": { "nodeAffinity": { diff --git a/components/ws-manager/pkg/manager/testdata/cdwp_tasks.golden b/components/ws-manager/pkg/manager/testdata/cdwp_tasks.golden index e0443ad2dcb2fa..9653d2a9f65db0 100644 --- a/components/ws-manager/pkg/manager/testdata/cdwp_tasks.golden +++ b/components/ws-manager/pkg/manager/testdata/cdwp_tasks.golden @@ -211,6 +211,7 @@ "restartPolicy": "Never", "serviceAccountName": "workspace", "automountServiceAccountToken": false, + "securityContext": {}, "hostname": "foobar", "affinity": { "nodeAffinity": { diff --git a/components/ws-manager/pkg/manager/testdata/cdwp_template.golden b/components/ws-manager/pkg/manager/testdata/cdwp_template.golden index eaf4439affb5f5..adf72e275be604 100644 --- a/components/ws-manager/pkg/manager/testdata/cdwp_template.golden +++ b/components/ws-manager/pkg/manager/testdata/cdwp_template.golden @@ -212,6 +212,7 @@ "dnsPolicy": "None", "serviceAccountName": "workspace", "automountServiceAccountToken": false, + "securityContext": {}, "imagePullSecrets": [ { "name": "dockerhub-typefox" diff --git a/components/ws-manager/pkg/manager/testdata/cdwp_timeout.golden b/components/ws-manager/pkg/manager/testdata/cdwp_timeout.golden index 5b5287ac311e9d..08349526d45967 100644 --- a/components/ws-manager/pkg/manager/testdata/cdwp_timeout.golden +++ b/components/ws-manager/pkg/manager/testdata/cdwp_timeout.golden @@ -212,6 +212,7 @@ "restartPolicy": "Never", "serviceAccountName": "workspace", "automountServiceAccountToken": false, + "securityContext": {}, "hostname": "foobar", "affinity": { "nodeAffinity": { diff --git a/components/ws-manager/pkg/manager/testdata/cdwp_userns.golden b/components/ws-manager/pkg/manager/testdata/cdwp_userns.golden index fff342f93ef530..8da8846ae9e7c5 100644 --- a/components/ws-manager/pkg/manager/testdata/cdwp_userns.golden +++ b/components/ws-manager/pkg/manager/testdata/cdwp_userns.golden @@ -207,6 +207,7 @@ "restartPolicy": "Never", "serviceAccountName": "workspace", "automountServiceAccountToken": false, + "securityContext": {}, "hostname": "foobar", "affinity": { "nodeAffinity": { diff --git a/components/ws-manager/pkg/manager/testdata/cdwp_with_ephemeral_storage.golden b/components/ws-manager/pkg/manager/testdata/cdwp_with_ephemeral_storage.golden index a6f305cd3f455b..a02817f1940e74 100644 --- a/components/ws-manager/pkg/manager/testdata/cdwp_with_ephemeral_storage.golden +++ b/components/ws-manager/pkg/manager/testdata/cdwp_with_ephemeral_storage.golden @@ -226,6 +226,7 @@ "restartPolicy": "Never", "serviceAccountName": "workspace", "automountServiceAccountToken": false, + "securityContext": {}, "hostname": "foobar", "affinity": { "nodeAffinity": { diff --git a/components/ws-manager/pkg/manager/testdata/cdwp_withaffinity_regular.golden b/components/ws-manager/pkg/manager/testdata/cdwp_withaffinity_regular.golden index 0a22087d6e1783..8e516495776ca3 100644 --- a/components/ws-manager/pkg/manager/testdata/cdwp_withaffinity_regular.golden +++ b/components/ws-manager/pkg/manager/testdata/cdwp_withaffinity_regular.golden @@ -207,6 +207,7 @@ "restartPolicy": "Never", "serviceAccountName": "workspace", "automountServiceAccountToken": false, + "securityContext": {}, "hostname": "foobar", "affinity": { "nodeAffinity": { diff --git a/components/ws-manager/pkg/manager/testdata/cdwp_withaffinityheadless.golden b/components/ws-manager/pkg/manager/testdata/cdwp_withaffinityheadless.golden index 3cc285173df670..53c72f84beb469 100644 --- a/components/ws-manager/pkg/manager/testdata/cdwp_withaffinityheadless.golden +++ b/components/ws-manager/pkg/manager/testdata/cdwp_withaffinityheadless.golden @@ -229,6 +229,7 @@ "restartPolicy": "Never", "serviceAccountName": "workspace", "automountServiceAccountToken": false, + "securityContext": {}, "hostname": "foobar", "affinity": { "nodeAffinity": { diff --git a/install/installer/example-config.yaml b/install/installer/example-config.yaml index d205d39cf51364..cc0eecca7f8849 100644 --- a/install/installer/example-config.yaml +++ b/install/installer/example-config.yaml @@ -25,6 +25,9 @@ openVSX: repository: eu.gcr.io/gitpod-core-dev/build workspace: maxLifetime: 36h0m0s + pvc: + size: 30Gi + storageClass: "" resources: requests: cpu: "1" diff --git a/install/installer/pkg/components/ws-manager/configmap.go b/install/installer/pkg/components/ws-manager/configmap.go index d8b2bdefd6c3f1..23bb74b4a5cfd3 100644 --- a/install/installer/pkg/components/ws-manager/configmap.go +++ b/install/installer/pkg/components/ws-manager/configmap.go @@ -68,6 +68,10 @@ func configmap(ctx *common.RenderContext) ([]runtime.Object, error) { }, }, Templates: templatesCfg, + PVC: config.PVCConfiguration{ + Size: ctx.Config.Workspace.PVC.Size, + StorageClass: ctx.Config.Workspace.PVC.StorageClass, + }, }, } err = ctx.WithExperimental(func(ucfg *experimental.Config) error { @@ -98,6 +102,7 @@ func configmap(ctx *common.RenderContext) ([]runtime.Object, error) { }, }, Templates: tplsCfg, + PVC: config.PVCConfiguration(c.PVC), } tpls = append(tpls, ctpls...) } diff --git a/install/installer/pkg/components/ws-manager/role.go b/install/installer/pkg/components/ws-manager/role.go index 824ca8080ed77c..4a2d14da3a67f5 100644 --- a/install/installer/pkg/components/ws-manager/role.go +++ b/install/installer/pkg/components/ws-manager/role.go @@ -33,6 +33,23 @@ func role(ctx *common.RenderContext) ([]runtime.Object, error) { "services", "endpoints", "configmaps", + "persistentvolumeclaims", + }, + Verbs: []string{ + "get", + "list", + "create", + "update", + "patch", + "watch", + "delete", + "deletecollection", + }, + }, + { + APIGroups: []string{"snapshot.storage.k8s.io"}, + Resources: []string{ + "volumesnapshots", }, Verbs: []string{ "get", diff --git a/install/installer/pkg/config/v1/config.go b/install/installer/pkg/config/v1/config.go index a8c2dc3187f713..7a946b4936f269 100644 --- a/install/installer/pkg/config/v1/config.go +++ b/install/installer/pkg/config/v1/config.go @@ -58,6 +58,8 @@ func (v version) Defaults(in interface{}) error { cfg.Workspace.Runtime.ContainerDSocket = "/run/containerd/containerd.sock" cfg.Workspace.Runtime.ContainerDRuntimeDir = "/var/lib/containerd/io.containerd.runtime.v2.task/k8s.io" cfg.Workspace.MaxLifetime = util.Duration(36 * time.Hour) + cfg.Workspace.PVC.Size = resource.MustParse("30Gi") + cfg.Workspace.PVC.StorageClass = "" cfg.OpenVSX.URL = "https://open-vsx.org" cfg.DisableDefinitelyGP = true @@ -238,11 +240,22 @@ type WorkspaceTemplates struct { Regular *corev1.Pod `json:"regular"` } +type PersistentVolumeClaim struct { + // Size is a size of persistent volume claim to use + Size resource.Quantity `json:"size" validate:"required"` + + // StorageClass is a storage class of persistent volume claim to use + StorageClass string `json:"storageClass"` +} + type Workspace struct { Runtime WorkspaceRuntime `json:"runtime" validate:"required"` Resources Resources `json:"resources" validate:"required"` Templates *WorkspaceTemplates `json:"templates,omitempty"` + // PVC is the struct that describes how to setup persistent volume claim for workspace + PVC PersistentVolumeClaim `json:"pvc" validate:"required"` + // MaxLifetime is the maximum time a workspace is allowed to run. After that, the workspace times out despite activity MaxLifetime util.Duration `json:"maxLifetime" validate:"required"` diff --git a/install/installer/pkg/config/v1/experimental/experimental.go b/install/installer/pkg/config/v1/experimental/experimental.go index b1379a9dd3a9f1..f7f2a2af9c7dd4 100644 --- a/install/installer/pkg/config/v1/experimental/experimental.go +++ b/install/installer/pkg/config/v1/experimental/experimental.go @@ -66,13 +66,23 @@ type WorkspaceConfig struct { WorkspaceClasses map[string]WorkspaceClass `json:"classes,omitempty"` } +type PersistentVolumeClaim struct { + // Size is a size of persistent volume claim to use + Size resource.Quantity `json:"size" validate:"required"` + + // StorageClass is a storage class of persistent volume claim to use + StorageClass string `json:"storageClass"` +} + type WorkspaceClass struct { Resources struct { Requests corev1.ResourceList `json:"requests" validate:"required"` Limits corev1.ResourceList `json:"limits,omitempty"` } `json:"resources" validate:"required"` - Templates WorkspaceTemplates `json:"templates,omitempty"` + Templates WorkspaceTemplates `json:"templates,omitempty"` + PVC PersistentVolumeClaim `json:"pvc" validate:"required"` } + type WorkspaceTemplates struct { Default *corev1.Pod `json:"default"` Prebuild *corev1.Pod `json:"prebuild"` diff --git a/test/tests/components/ws-manager/content_test.go b/test/tests/components/ws-manager/content_test.go index cece09f5bdbd7c..9d2a03c47f35f5 100644 --- a/test/tests/components/ws-manager/content_test.go +++ b/test/tests/components/ws-manager/content_test.go @@ -185,6 +185,7 @@ func TestMissingBackup(t *testing.T) { }{ {Name: "classic"}, {Name: "fwb", FF: []wsapi.WorkspaceFeatureFlag{wsapi.WorkspaceFeatureFlag_FULL_WORKSPACE_BACKUP}}, + {Name: "pvc", FF: []wsapi.WorkspaceFeatureFlag{wsapi.WorkspaceFeatureFlag_PERSISTENT_VOLUME_CLAIM}}, } for _, test := range tests { t.Run(test.Name+"_backup_init", func(t *testing.T) {