diff --git a/components/supervisor/.gitignore b/components/supervisor/.gitignore new file mode 100644 index 00000000000000..bd452240480f68 --- /dev/null +++ b/components/supervisor/.gitignore @@ -0,0 +1 @@ +supervisor diff --git a/components/supervisor/cmd/run.go b/components/supervisor/cmd/run.go index 070713ba172023..1d14bb07037651 100644 --- a/components/supervisor/cmd/run.go +++ b/components/supervisor/cmd/run.go @@ -23,7 +23,7 @@ var runCmd = &cobra.Command{ Short: "starts the supervisor", Run: func(cmd *cobra.Command, args []string) { - log.Init(ServiceName, Version, true, os.Getenv("SUPERVISOR_DEBUG_ENABLE") == "true") + log.Init(ServiceName, Version, !runOpts.RunGP, os.Getenv("SUPERVISOR_DEBUG_ENABLE") == "true") common_grpc.SetupLogging() supervisor.Version = Version supervisor.Run(supervisor.WithRunGP(runOpts.RunGP)) diff --git a/components/supervisor/hot-swap.sh b/components/supervisor/hot-swap.sh new file mode 100755 index 00000000000000..3a79a82c1ada27 --- /dev/null +++ b/components/supervisor/hot-swap.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# Copyright (c) 2022 Gitpod GmbH. All rights reserved. +# Licensed under the GNU Affero General Public License (AGPL). +# See License.AGPL.txt in the project root for license information. + +set -Eeuo pipefail + +# This script swaps the backend startup endpoint with a built one +# in a workspace and restarts the JB backend. + +component=${PWD##*/} +workspaceUrl=$(echo "${1}" |sed -e "s/\/$//") +echo "URL: $workspaceUrl" + +workspaceDesc=$(gpctl workspaces describe "$workspaceUrl" -o=json) + +podName=$(echo "$workspaceDesc" | jq .runtime.pod_name -r) +echo "Pod: $podName" + +workspaceId=$(echo "$workspaceDesc" | jq .metadata.meta_id -r) +echo "ID: $workspaceId" + +clusterHost=$(kubectl exec -it "$podName" -- printenv GITPOD_WORKSPACE_CLUSTER_HOST |sed -e "s/\s//g") +echo "Cluster Host: $clusterHost" + +# prepare ssh +ownerToken=$(kubectl get pod "$podName" -o=json | jq ".metadata.annotations.\"gitpod\/ownerToken\"" -r) +sshConfig="./ssh-config" +echo "Host $workspaceId" > "$sshConfig" +echo " Hostname \"$workspaceId.ssh.$clusterHost\"" >> "$sshConfig" +echo " User \"$workspaceId#$ownerToken\"" >> "$sshConfig" + +# build +go build . +echo "$component built" + +# upload +uploadDest="/.supervisor/$component" +echo "Upload Dest: $uploadDest" +ssh -F "$sshConfig" "$workspaceId" "sudo chmod 777 $uploadDest && sudo rm $uploadDest" +scp -F "$sshConfig" -r "./supervisor" "$workspaceId":"$uploadDest" +echo "Swap complete" diff --git a/components/supervisor/local-hot-swap.sh b/components/supervisor/local-hot-swap.sh new file mode 100755 index 00000000000000..eb0fde3f888742 --- /dev/null +++ b/components/supervisor/local-hot-swap.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# Copyright (c) 2022 Gitpod GmbH. All rights reserved. +# Licensed under the GNU Affero General Public License (AGPL). +# See License.AGPL.txt in the project root for license information. + +set -Eeuo pipefail + +# This script swaps the backend startup endpoint with a built one +# in a workspace and restarts the JB backend. + +component=${PWD##*/} + +# build +go build . +echo "$component built" + +sudo rm /.supervisor/supervisor +sudo mv ./"$component" /.supervisor +echo "Local Swap complete" diff --git a/components/supervisor/pkg/supervisor/supervisor.go b/components/supervisor/pkg/supervisor/supervisor.go index 175bdd83d8b72d..ee04eee817451e 100644 --- a/components/supervisor/pkg/supervisor/supervisor.go +++ b/components/supervisor/pkg/supervisor/supervisor.go @@ -191,15 +191,18 @@ func Run(options ...RunOption) { configureGit(cfg, childProcEnvvars) tokenService := NewInMemoryTokenService() - tkns, err := cfg.GetTokens(true) - if err != nil { - log.WithError(err).Warn("cannot prepare tokens") - } - for i := range tkns { - _, err = tokenService.SetToken(context.Background(), &tkns[i].SetTokenRequest) + + if !opts.RunGP { + tkns, err := cfg.GetTokens(true) if err != nil { log.WithError(err).Warn("cannot prepare tokens") } + for i := range tkns { + _, err = tokenService.SetToken(context.Background(), &tkns[i].SetTokenRequest) + if err != nil { + log.WithError(err).Warn("cannot prepare tokens") + } + } } tunneledPortsService := ports.NewTunneledPortsService(cfg.DebugEnable) @@ -238,6 +241,12 @@ func Run(options ...RunOption) { desktopIdeReady *ideReadyState = nil cstate = NewInMemoryContentState(cfg.RepoRoot) + gitpodService serverapi.APIInterface + + notificationService = NewNotificationService() + ) + + if !opts.RunGP { gitpodService = serverapi.NewServerApiService(ctx, &serverapi.ServiceConfig{ Host: host, Endpoint: endpoint, @@ -245,13 +254,12 @@ func Run(options ...RunOption) { WorkspaceID: cfg.WorkspaceID, SupervisorVersion: Version, }, tokenService) + } - notificationService = NewNotificationService() - ) if cfg.DesktopIDE != nil { desktopIdeReady = &ideReadyState{cond: sync.NewCond(&sync.Mutex{})} } - if !cfg.isHeadless() { + if !cfg.isHeadless() && !opts.RunGP { go trackReadiness(ctx, gitpodService, cfg, cstate, ideReady, desktopIdeReady) } tokenService.provider[KindGit] = []tokenProvider{NewGitTokenProvider(gitpodService, cfg.WorkspaceConfig, notificationService)} @@ -259,8 +267,15 @@ func Run(options ...RunOption) { gitpodConfigService := config.NewConfigService(cfg.RepoRoot+"/.gitpod.yml", cstate.ContentReady(), log.Log) go gitpodConfigService.Watch(ctx) + var exposedPorts ports.ExposedPortsInterface + + if !opts.RunGP { + exposedPorts = createExposedPortsImpl(cfg, gitpodService) + } + + // createExposedPortsImpl(cfg, gitpodService) portMgmt := ports.NewManager( - createExposedPortsImpl(cfg, gitpodService), + exposedPorts, &ports.PollingServedPortsObserver{ RefreshInterval: 2 * time.Second, }, @@ -270,7 +285,10 @@ func Run(options ...RunOption) { ) topService := NewTopService() - topService.Observe(ctx) + + if !opts.RunGP { + topService.Observe(ctx) + } supervisorMetrics := metrics.NewMetrics() var metricsReporter *metrics.GrpcMetricsReporter @@ -355,17 +373,28 @@ func Run(options ...RunOption) { wg sync.WaitGroup shutdown = make(chan ShutdownReason, 1) ) - wg.Add(1) - go startContentInit(ctx, cfg, &wg, cstate, supervisorMetrics) + + if !opts.RunGP { + wg.Add(1) + go startContentInit(ctx, cfg, &wg, cstate, supervisorMetrics) + } + wg.Add(1) go startAPIEndpoint(ctx, cfg, &wg, apiServices, tunneledPortsService, metricsReporter, apiEndpointOpts...) - wg.Add(1) - go startSSHServer(ctx, cfg, &wg, childProcEnvvars) + + if !opts.RunGP { + wg.Add(1) + go startSSHServer(ctx, cfg, &wg, childProcEnvvars) + } + wg.Add(1) tasksSuccessChan := make(chan taskSuccess, 1) go taskManager.Run(ctx, &wg, tasksSuccessChan) - wg.Add(1) - go socketActivationForDocker(ctx, &wg, termMux) + + if !opts.RunGP { + wg.Add(1) + go socketActivationForDocker(ctx, &wg, termMux) + } if cfg.isHeadless() { wg.Add(1) @@ -899,7 +928,7 @@ func prepareIDELaunch(cfg *Config, ideConfig *IDEConfig, childProcEnvvars []stri // of envvars. If envvars is nil, os.Environ() is used. // // Beware: if config contains an OTS URL the results may differ on subsequent calls. -func buildChildProcEnv(cfg *Config, envvars []string) []string { +func buildChildProcEnv(cfg *Config, envvars []string, runGP bool) []string { if envvars == nil { envvars = os.Environ() } @@ -919,7 +948,10 @@ func buildChildProcEnv(cfg *Config, envvars []string) []string { envs[nme] = val } - envs["SUPERVISOR_ADDR"] = fmt.Sprintf("localhost:%d", cfg.APIEndpointPort) + + if !runGP { + envs["SUPERVISOR_ADDR"] = fmt.Sprintf("localhost:%d", cfg.APIEndpointPort) + } if cfg.EnvvarOTS != "" { es, err := downloadEnvvarOTS(cfg.EnvvarOTS)