/
setupContext.go
238 lines (200 loc) · 8.9 KB
/
setupContext.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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
package context
import (
"context"
"fmt"
"os"
"github.com/cloudogu/cesapp-lib/core"
"github.com/cloudogu/k8s-apply-lib/apply"
componentOpConfig "github.com/cloudogu/k8s-component-operator/pkg/config"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"github.com/sirupsen/logrus"
)
const (
// SecretDoguRegistry is the name of the secret containing the dogu registry credentials.
SecretDoguRegistry = "k8s-dogu-operator-dogu-registry"
// SecretDoguRegistryDevPath is the path to the secret containing the dogu registry credentials. This is used for development.
SecretDoguRegistryDevPath = "k8s/dev-resources/dogu-registry-secret.yaml"
// SecretDockerRegistry is the name of the secret containing the docker registry credentials.
SecretDockerRegistry = "k8s-dogu-operator-docker-registry"
// HelmRepositoryConfigMapName is the name of the configMap containing the endpoint of the HelmRepository.
HelmRepositoryConfigMapName = "component-operator-helm-repository"
// HelmRepositoryDevPath is the path to the config containing the endpoint of the HelmRepository. This is used for development.
HelmRepositoryDevPath = "k8s/dev-resources/helm-repository.yaml"
// SetupConfigConfigmap is the name of the config map containing the setup config.
SetupConfigConfigmap = "k8s-ces-setup-config"
// SetupConfigConfigmapDevPath is the path to the config map containing the setup config. This is used for development.
SetupConfigConfigmapDevPath = "k8s/dev-resources/k8s-ces-setup.yaml"
// SetupStartUpConfigMap is the name of the config map containing the setup.json.
SetupStartUpConfigMap = "k8s-ces-setup-json"
// SetupStartUpConfigMapDevPath is the path to the config map containing the setup.json. This is used for development.
SetupStartUpConfigMapDevPath = "k8s/dev-resources/setup.json"
// SetupStateConfigMap is the name of the config map containing the setup state.
SetupStateConfigMap = "k8s-setup-config"
// SetupStateKey is the key by which the setup state can be referenced.
SetupStateKey = "state"
// SetupStateInstalled means the setup installed the Cloudogu EcoSystem successfully.
SetupStateInstalled = "installed"
// SetupStateInstalling means the setup is currently installing the Cloudogu EcoSystem.
SetupStateInstalling = "installing"
// EnvironmentVariableStage is the name of the environment variable by which the development stage can be set.
EnvironmentVariableStage = "STAGE"
// StageDevelopment is the value that EnvironmentVariableStage must have in order to start the setup in development mode.
StageDevelopment = "development"
// EnvironmentVariableTargetNamespace is the name of the environment variable which discerns where the setup should deploy the Cloudogu EcoSystem.
EnvironmentVariableTargetNamespace = "POD_NAMESPACE"
)
// SetupContext contains all context information provided by the setup.
type SetupContext struct {
AppVersion string
Stage string
AppConfig *Config
SetupJsonConfiguration *SetupJsonConfiguration
DoguRegistryConfiguration *DoguRegistrySecret
HelmRepositoryData *componentOpConfig.HelmRepositoryData
}
// SetupContextBuilder contains information to create a setup context
type SetupContextBuilder struct {
version string
stage string
DevSetupConfigPath string
DevStartupConfigPath string
DevDoguRegistrySecretPath string
DevHelmRepositoryDataPath string
}
// NewSetupContextBuilder creates a new builder to create a setup context. Default dev resources paths are used.
func NewSetupContextBuilder(version string) *SetupContextBuilder {
return &SetupContextBuilder{
version: version,
stage: os.Getenv(EnvironmentVariableStage),
DevSetupConfigPath: SetupConfigConfigmapDevPath,
DevStartupConfigPath: SetupStartUpConfigMapDevPath,
DevDoguRegistrySecretPath: SecretDoguRegistryDevPath,
DevHelmRepositoryDataPath: HelmRepositoryDevPath,
}
}
// NewSetupContext creates a new setup context.
func (scb *SetupContextBuilder) NewSetupContext(ctx context.Context, clientSet kubernetes.Interface) (*SetupContext, error) {
logrus.Print("Reading configuration file...")
targetNamespace, err := GetEnvVar(EnvironmentVariableTargetNamespace)
if err != nil {
return nil, fmt.Errorf("could not read current namespace: %w", err)
}
config, setupJson, doguRegistrySecret, helmRepositoryData, err := scb.getConfigurations(ctx, clientSet, targetNamespace)
if err != nil {
return nil, err
}
config.TargetNamespace = targetNamespace
keyProvider := config.KeyProvider
if keyProvider != "pkcs1v15" && config.KeyProvider != "oaesp" {
return nil, fmt.Errorf("invalid key provider: %s", keyProvider)
}
configureLogger(config)
return &SetupContext{
AppVersion: scb.version,
Stage: scb.stage,
AppConfig: config,
SetupJsonConfiguration: setupJson,
DoguRegistryConfiguration: doguRegistrySecret,
HelmRepositoryData: helmRepositoryData,
}, nil
}
func (scb *SetupContextBuilder) getConfigurations(ctx context.Context, clientSet kubernetes.Interface, targetNamespace string) (*Config, *SetupJsonConfiguration, *DoguRegistrySecret, *componentOpConfig.HelmRepositoryData, error) {
if IsDevelopmentStage(scb.stage) {
return scb.getDevConfig()
}
return scb.getConfigFromCluster(ctx, clientSet, targetNamespace)
}
func (scb *SetupContextBuilder) getDevConfig() (*Config, *SetupJsonConfiguration, *DoguRegistrySecret, *componentOpConfig.HelmRepositoryData, error) {
config, err := ReadConfigFromFile(scb.DevSetupConfigPath)
if err != nil {
return nil, nil, nil, nil, err
}
setupJson, err := ReadSetupConfigFromFile(scb.DevStartupConfigPath)
if err != nil {
return nil, nil, nil, nil, err
}
doguRegistrySecret, err := ReadDoguRegistrySecretFromFile(scb.DevDoguRegistrySecretPath)
if err != nil {
return nil, nil, nil, nil, err
}
helmRepositoryData, err := componentOpConfig.NewHelmRepoDataFromFile(scb.DevHelmRepositoryDataPath)
if err != nil {
return nil, nil, nil, nil, err
}
return config, setupJson, doguRegistrySecret, helmRepositoryData, nil
}
func (scb *SetupContextBuilder) getConfigFromCluster(ctx context.Context, clientSet kubernetes.Interface, targetNamespace string) (*Config, *SetupJsonConfiguration, *DoguRegistrySecret, *componentOpConfig.HelmRepositoryData, error) {
config, err := ReadConfigFromCluster(ctx, clientSet, targetNamespace)
if err != nil {
return nil, nil, nil, nil, err
}
setupJson, err := ReadSetupConfigFromCluster(ctx, clientSet, targetNamespace)
if err != nil {
return nil, nil, nil, nil, err
}
doguRegistrySecret, err := ReadDoguRegistrySecretFromCluster(ctx, clientSet, targetNamespace)
if err != nil {
return nil, nil, nil, nil, err
}
configMapClient := clientSet.CoreV1().ConfigMaps(targetNamespace)
helmRepositoryData, err := componentOpConfig.NewHelmRepoDataFromCluster(ctx, configMapClient)
if err != nil {
return nil, nil, nil, nil, err
}
return config, setupJson, doguRegistrySecret, helmRepositoryData, err
}
func IsDevelopmentStage(stage string) bool {
return stage == StageDevelopment
}
// GetSetupStateConfigMap returns or creates if it does not exist the configmap map for presenting the state of the setup process
func GetSetupStateConfigMap(ctx context.Context, client kubernetes.Interface, namespace string) (*corev1.ConfigMap, error) {
configMap, err := client.CoreV1().ConfigMaps(namespace).Get(ctx, SetupStateConfigMap, metav1.GetOptions{})
if errors.IsNotFound(err) {
setupConfigMap := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: SetupStateConfigMap,
Namespace: namespace,
Labels: map[string]string{"app": "ces", "app.kubernetes.io/name": "k8s-ces-setup"},
},
}
configMap, err = client.CoreV1().ConfigMaps(namespace).Create(ctx, setupConfigMap, metav1.CreateOptions{})
if err != nil {
return nil, fmt.Errorf("failed to create configmap [%s]: %w", SetupStateConfigMap, err)
}
} else if err != nil {
return nil, fmt.Errorf("failed to get configmap [%s]: %w", SetupConfigConfigmap, err)
}
if configMap.Data == nil {
configMap.Data = map[string]string{}
}
return configMap, nil
}
// GetEnvVar returns an arbitrary environment variable; otherwise it returns an error
func GetEnvVar(name string) (string, error) {
ns, found := os.LookupEnv(name)
if !found {
return "", fmt.Errorf("%s must be set", name)
}
return ns, nil
}
func configureLogger(config *Config) {
logLevel := config.LogLevel
if logLevel == nil {
infoLevel := logrus.InfoLevel
logLevel = &infoLevel
logrus.Print(fmt.Sprintf("Setting default loglevel: %s", infoLevel))
}
logrus.SetLevel(*logLevel)
logrus.SetFormatter(&logrus.TextFormatter{
DisableTimestamp: true,
})
core.GetLogger = func() core.Logger {
return logrus.StandardLogger()
}
apply.GetLogger = func() apply.Logger {
return logrus.StandardLogger()
}
}