Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/ws-daemon/pkg/controller/workspace_provider.go
2500 views
1
// Copyright (c) 2023 Gitpod GmbH. All rights reserved.
2
// Licensed under the GNU Affero General Public License (AGPL).
3
// See License.AGPL.txt in the project root for license information.
4
5
package controller
6
7
import (
8
"context"
9
"fmt"
10
"path/filepath"
11
"sync"
12
13
"github.com/gitpod-io/gitpod/common-go/log"
14
"github.com/gitpod-io/gitpod/common-go/tracing"
15
"github.com/opentracing/opentracing-go"
16
17
"github.com/gitpod-io/gitpod/ws-daemon/pkg/internal/session"
18
)
19
20
type WorkspaceFactory func(ctx context.Context, instanceID string) (ws *session.Workspace, err error)
21
22
type WorkspaceProvider struct {
23
Location string
24
hooks map[session.WorkspaceState][]session.WorkspaceLivecycleHook
25
workspaces sync.Map
26
}
27
28
func NewWorkspaceProvider(location string, hooks map[session.WorkspaceState][]session.WorkspaceLivecycleHook) *WorkspaceProvider {
29
return &WorkspaceProvider{
30
Location: location,
31
hooks: hooks,
32
}
33
}
34
35
func (wf *WorkspaceProvider) NewWorkspace(ctx context.Context, instanceID, location string, create WorkspaceFactory) (ws *session.Workspace, err error) {
36
span, ctx := opentracing.StartSpanFromContext(ctx, "WorkspaceProvider.NewWorkspace")
37
tracing.ApplyOWI(span, log.OWI("", "", instanceID))
38
defer tracing.FinishSpan(span, &err)
39
40
ws, err = create(ctx, location)
41
if err != nil {
42
return nil, err
43
}
44
45
if ws.NonPersistentAttrs == nil {
46
ws.NonPersistentAttrs = make(map[string]interface{})
47
}
48
49
err = wf.runLifecycleHooks(ctx, ws, session.WorkspaceInitializing)
50
if err != nil {
51
return nil, err
52
}
53
54
wf.workspaces.Store(instanceID, ws)
55
56
return ws, nil
57
}
58
59
func (wf *WorkspaceProvider) Remove(ctx context.Context, instanceID string) {
60
span, _ := opentracing.StartSpanFromContext(ctx, "WorkspaceProvider.Remove")
61
tracing.ApplyOWI(span, log.OWI("", "", instanceID))
62
defer tracing.FinishSpan(span, nil)
63
64
wf.workspaces.Delete(instanceID)
65
}
66
67
func (wf *WorkspaceProvider) GetAndConnect(ctx context.Context, instanceID string) (*session.Workspace, error) {
68
ws, ok := wf.workspaces.Load(instanceID)
69
if !ok {
70
// if the workspace is not in memory ws-daemon probabably has been restarted
71
// in that case we reload it from disk
72
path := filepath.Join(wf.Location, fmt.Sprintf("%s.workspace.json", instanceID))
73
loadWs, err := session.LoadWorkspace(ctx, path)
74
if err != nil {
75
return nil, err
76
}
77
78
ws = loadWs
79
}
80
81
err := wf.runLifecycleHooks(ctx, ws.(*session.Workspace), session.WorkspaceReady)
82
if err != nil {
83
return nil, err
84
}
85
wf.workspaces.Store(instanceID, ws)
86
87
return ws.(*session.Workspace), nil
88
}
89
90
func (s *WorkspaceProvider) runLifecycleHooks(ctx context.Context, ws *session.Workspace, state session.WorkspaceState) error {
91
hooks := s.hooks[state]
92
93
for _, h := range hooks {
94
err := h(ctx, ws)
95
if err != nil {
96
return err
97
}
98
}
99
return nil
100
}
101
102