Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/content-service-api/go/initializer.go
2498 views
1
// Copyright (c) 2022 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 api
6
7
import (
8
"fmt"
9
"strconv"
10
"strings"
11
12
"golang.org/x/xerrors"
13
)
14
15
// GetCheckoutLocationsFromInitializer returns a list of all checkout locations from the initializer
16
func GetCheckoutLocationsFromInitializer(init *WorkspaceInitializer) []string {
17
var res []string
18
_ = WalkInitializer(nil, init, func(path []string, init *WorkspaceInitializer) error {
19
switch spec := init.Spec.(type) {
20
case *WorkspaceInitializer_Git:
21
res = append(res, spec.Git.CheckoutLocation)
22
case *WorkspaceInitializer_Backup:
23
res = append(res, spec.Backup.CheckoutLocation)
24
25
case *WorkspaceInitializer_Prebuild:
26
// walkInitializer will visit the Git initializer
27
}
28
29
return nil
30
})
31
return res
32
}
33
34
const extractedSecretPrefix = "extracted-secret/"
35
36
// GatherSecretsFromInitializer collects all from an initializer. This function does not
37
// alter the initializer in any way.
38
func GatherSecretsFromInitializer(init *WorkspaceInitializer) map[string]string {
39
return extractSecretsFromInitializer(init, false)
40
}
41
42
// ExtractAndReplaceSecretsFromInitializer removes secrets to the initializer.
43
// This function alters the initializer, which only becomes useful calling InjectSecretsToInitializer.
44
// This is the counterpart of InjectSecretsToInitializer.
45
func ExtractAndReplaceSecretsFromInitializer(init *WorkspaceInitializer) map[string]string {
46
return extractSecretsFromInitializer(init, true)
47
}
48
49
func extractSecretsFromInitializer(init *WorkspaceInitializer, replaceValue bool) map[string]string {
50
res := make(map[string]string)
51
52
_ = WalkInitializer([]string{"initializer"}, init, func(path []string, init *WorkspaceInitializer) error {
53
git, ok := init.Spec.(*WorkspaceInitializer_Git)
54
if !ok {
55
return nil
56
}
57
58
pwd := git.Git.Config.AuthPassword
59
if pwd == "" || strings.HasPrefix(pwd, extractedSecretPrefix) {
60
return nil
61
}
62
63
name := strings.Join(path, ".")
64
res[name] = pwd
65
66
if replaceValue {
67
git.Git.Config.AuthPassword = extractedSecretPrefix + name
68
}
69
70
return nil
71
})
72
73
return res
74
}
75
76
// InjectSecretsToInitializer injects secrets to the initializer. This is the counterpart of ExtractSecretsFromInitializer.
77
func InjectSecretsToInitializer(init *WorkspaceInitializer, secrets map[string][]byte) error {
78
return WalkInitializer([]string{"initializer"}, init, func(path []string, init *WorkspaceInitializer) error {
79
git, ok := init.Spec.(*WorkspaceInitializer_Git)
80
if !ok {
81
return nil
82
}
83
84
pwd := git.Git.Config.AuthPassword
85
if !strings.HasPrefix(pwd, extractedSecretPrefix) {
86
return nil
87
}
88
89
name := strings.TrimPrefix(pwd, extractedSecretPrefix)
90
val, ok := secrets[name]
91
if !ok {
92
return xerrors.Errorf("secret %s not found", name)
93
}
94
95
git.Git.Config.AuthPassword = string(val)
96
97
return nil
98
})
99
}
100
101
// WalkInitializer walks the initializer structure
102
func WalkInitializer(path []string, init *WorkspaceInitializer, visitor func(path []string, init *WorkspaceInitializer) error) error {
103
if init == nil {
104
return nil
105
}
106
107
switch spec := init.Spec.(type) {
108
case *WorkspaceInitializer_Empty:
109
return visitor(append(path, "empty"), init)
110
case *WorkspaceInitializer_Git:
111
return visitor(append(path, "git"), init)
112
case *WorkspaceInitializer_Snapshot:
113
return visitor(append(path, "snapshot"), init)
114
case *WorkspaceInitializer_Prebuild:
115
child := append(path, "prebuild")
116
err := visitor(child, init)
117
if err != nil {
118
return err
119
}
120
for i, g := range spec.Prebuild.Git {
121
err = WalkInitializer(append(child, strconv.Itoa(i)), &WorkspaceInitializer{Spec: &WorkspaceInitializer_Git{Git: g}}, visitor)
122
if err != nil {
123
return err
124
}
125
}
126
return nil
127
case *WorkspaceInitializer_Composite:
128
path = append(path, "composite")
129
err := visitor(path, init)
130
if err != nil {
131
return err
132
}
133
for i, p := range spec.Composite.Initializer {
134
err := WalkInitializer(append(path, strconv.Itoa(i)), p, visitor)
135
if err != nil {
136
return err
137
}
138
}
139
return nil
140
case *WorkspaceInitializer_Download:
141
return visitor(append(path, "download"), init)
142
case *WorkspaceInitializer_Backup:
143
return visitor(append(path, "backup"), init)
144
145
default:
146
return fmt.Errorf("unsupported workspace initializer in walkInitializer - this is a bug in Gitpod")
147
}
148
}
149
150