Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/install/installer/pkg/config/loader.go
2499 views
1
// Copyright (c) 2021 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 config
6
7
import (
8
"fmt"
9
10
"github.com/gitpod-io/gitpod/installer/pkg/cluster"
11
"github.com/gitpod-io/gitpod/installer/pkg/yq"
12
"github.com/go-playground/validator/v10"
13
14
"sigs.k8s.io/yaml"
15
)
16
17
// CurrentVersion points to the latest config version
18
const CurrentVersion = "v1"
19
20
// NewDefaultConfig returns a new instance of the current config struct,
21
// with all defaults filled in.
22
func NewDefaultConfig() (interface{}, error) {
23
v, ok := versions[CurrentVersion]
24
if !ok {
25
return nil, fmt.Errorf("current config version is invalid - this should never happen")
26
}
27
28
cfg := v.Factory()
29
err := v.Defaults(cfg)
30
if err != nil {
31
return nil, err
32
}
33
34
return cfg, nil
35
}
36
37
type ConfigVersion interface {
38
// Factory provides a new instance of the config struct
39
Factory() interface{}
40
41
// Defaults fills in the defaults for this version.
42
// obj is expected to be the return value of Factory()
43
Defaults(obj interface{}) error
44
45
// LoadValidationFuncs loads the custom validation functions
46
LoadValidationFuncs(*validator.Validate) error
47
48
// ClusterValidation introduces configuration specific cluster validation checks
49
ClusterValidation(cfg interface{}) cluster.ValidationChecks
50
51
// CheckDeprecated checks for deprecated config params.
52
// Returns key/value pair of deprecated params/values and any error messages (used for conflicting params)
53
CheckDeprecated(cfg interface{}) (map[string]interface{}, []string)
54
}
55
56
// AddVersion adds a new version.
57
// Expected to be called from the init package of a config package.
58
func AddVersion(version string, v ConfigVersion) {
59
if versions == nil {
60
versions = make(map[string]ConfigVersion)
61
}
62
versions[version] = v
63
}
64
65
var (
66
ErrInvalidType = fmt.Errorf("invalid type")
67
)
68
69
var versions map[string]ConfigVersion
70
71
func LoadConfigVersion(version string) (ConfigVersion, error) {
72
v, ok := versions[version]
73
if !ok {
74
return nil, fmt.Errorf("unsupprted API version: %s", version)
75
}
76
77
return v, nil
78
}
79
80
// Load takes a config string and overrides that onto the default
81
// config for that version (passed in the config). If no config version
82
// is passed, It overrides it onto the default CurrentVersion of the binary
83
func Load(overrideConfig string, strict bool) (cfg interface{}, version string, err error) {
84
var overrideVS struct {
85
APIVersion string `json:"apiVersion"`
86
}
87
err = yaml.Unmarshal([]byte(overrideConfig), &overrideVS)
88
if err != nil {
89
return
90
}
91
92
apiVersion := overrideVS.APIVersion
93
// fall-back to default CurrentVersion if no apiVersion was passed
94
if version == "" {
95
apiVersion = CurrentVersion
96
}
97
98
v, err := LoadConfigVersion(apiVersion)
99
if err != nil {
100
return
101
}
102
103
// Load default configuration
104
cfg = v.Factory()
105
err = v.Defaults(cfg)
106
if err != nil {
107
return
108
}
109
110
// Remove the apiVersion from the config as this has already been parsed
111
// Use yq to make processing reliable
112
output, err := yq.Process(overrideConfig, "del(.apiVersion)")
113
if err != nil {
114
return
115
}
116
117
// Override passed configuration onto the default
118
if strict {
119
err = yaml.UnmarshalStrict([]byte(*output), cfg)
120
} else {
121
err = yaml.Unmarshal([]byte(*output), cfg)
122
}
123
if err != nil {
124
return
125
}
126
127
return cfg, apiVersion, nil
128
}
129
130
func Marshal(version string, cfg interface{}) ([]byte, error) {
131
if _, ok := versions[version]; !ok {
132
return nil, fmt.Errorf("unsupported API version: %s", version)
133
}
134
135
b, err := yaml.Marshal(cfg)
136
if err != nil {
137
return nil, err
138
}
139
140
return []byte(fmt.Sprintf("apiVersion: %s\n%s", version, string(b))), nil
141
}
142
143