-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
storage.go
182 lines (154 loc) · 4.98 KB
/
storage.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
// Copyright (c) 2021 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.
package common
import (
"fmt"
"path/filepath"
storageconfig "github.com/gitpod-io/gitpod/content-service/api/config"
"github.com/gitpod-io/gitpod/installer/pkg/config/v1/experimental"
"k8s.io/utils/pointer"
corev1 "k8s.io/api/core/v1"
)
const storageMount = "/mnt/secrets/storage"
// StorageConfig produces config service configuration from the installer config
func useMinio(context *RenderContext) bool {
// Minio is used for in-cluster storage and as a facade to non-GCP providers
if pointer.BoolDeref(context.Config.ObjectStorage.InCluster, false) {
return true
}
if context.Config.ObjectStorage.Azure != nil {
return true
}
return false
}
func StorageConfig(context *RenderContext) storageconfig.StorageConfig {
var res *storageconfig.StorageConfig
if context.Config.ObjectStorage.CloudStorage != nil {
maximumBackupCount := 3
if context.Config.ObjectStorage.MaximumBackupCount != nil {
maximumBackupCount = *context.Config.ObjectStorage.MaximumBackupCount
}
res = &storageconfig.StorageConfig{
Kind: storageconfig.GCloudStorage,
GCloudConfig: storageconfig.GCPConfig{
Region: context.Config.Metadata.Region,
Project: context.Config.ObjectStorage.CloudStorage.Project,
CredentialsFile: filepath.Join(storageMount, "service-account.json"),
MaximumBackupCount: maximumBackupCount,
},
}
}
if context.Config.ObjectStorage.S3 != nil {
res = &storageconfig.StorageConfig{
Kind: storageconfig.MinIOStorage,
MinIOConfig: storageconfig.MinIOConfig{
Endpoint: context.Config.ObjectStorage.S3.Endpoint,
AccessKeyIdFile: filepath.Join(storageMount, "accessKeyId"),
SecretAccessKeyFile: filepath.Join(storageMount, "secretAccessKey"),
Secure: true,
Region: context.Config.Metadata.Region,
ParallelUpload: 100,
},
}
}
if useMinio(context) {
res = &storageconfig.StorageConfig{
Kind: storageconfig.MinIOStorage,
MinIOConfig: storageconfig.MinIOConfig{
Endpoint: fmt.Sprintf("minio.%s.svc.cluster.local:%d", context.Namespace, MinioServiceAPIPort),
AccessKeyID: context.Values.StorageAccessKey,
SecretAccessKey: context.Values.StorageSecretKey,
Secure: false,
Region: "local", // Local Minio requires this value - workspace allocation fails if not set to this
ParallelUpload: 6,
},
}
}
if res == nil {
panic("no valid storage configuration set")
}
// todo(sje): create exportable type
res.BackupTrail = struct {
Enabled bool `json:"enabled"`
MaxLength int `json:"maxLength"`
}{
Enabled: true,
MaxLength: 3,
}
// 5 GiB
res.BlobQuota = 5 * 1024 * 1024 * 1024
if context.Config.ObjectStorage.BlobQuota != nil {
res.BlobQuota = *context.Config.ObjectStorage.BlobQuota
}
_ = context.WithExperimental(func(ucfg *experimental.Config) error {
if ucfg.Workspace != nil {
res.Stage = storageconfig.Stage(ucfg.Workspace.Stage)
}
return nil
})
return *res
}
// mountStorage performs the actual storage mount, which is common across all providers
func mountStorage(pod *corev1.PodSpec, secret string, container ...string) {
volumeName := "storage-volume"
pod.Volumes = append(pod.Volumes,
corev1.Volume{
Name: volumeName,
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: secret,
},
},
},
)
idx := make(map[string]struct{}, len(container))
if len(container) == 0 {
for _, c := range pod.Containers {
idx[c.Name] = struct{}{}
}
} else {
for _, c := range container {
idx[c] = struct{}{}
}
}
for i := range pod.Containers {
if _, ok := idx[pod.Containers[i].Name]; !ok {
continue
}
pod.Containers[i].VolumeMounts = append(pod.Containers[i].VolumeMounts,
corev1.VolumeMount{
Name: volumeName,
ReadOnly: true,
MountPath: storageMount,
},
)
}
}
// AddStorageMounts adds mounts and volumes to a pod which are required for
// the storage configuration to function. If a list of containers is provided,
// the mounts are only added to those containers. If the list is empty, they're
// added to all containers.
func AddStorageMounts(ctx *RenderContext, pod *corev1.PodSpec, container ...string) error {
if ctx.Config.ObjectStorage.CloudStorage != nil {
mountStorage(pod, ctx.Config.ObjectStorage.CloudStorage.ServiceAccount.Name, container...)
return nil
}
if ctx.Config.ObjectStorage.S3 != nil {
mountStorage(pod, ctx.Config.ObjectStorage.S3.Credentials.Name, container...)
return nil
}
if useMinio(ctx) {
// builtin storage needs no extra mounts
return nil
}
return fmt.Errorf("no valid storage configuration set")
}
func NewEmptyDirVolume(name string) *corev1.Volume {
return &corev1.Volume{
Name: name,
VolumeSource: corev1.VolumeSource{
EmptyDir: &corev1.EmptyDirVolumeSource{},
},
}
}