-
Notifications
You must be signed in to change notification settings - Fork 67
/
clusterinstallation_utils.go
275 lines (242 loc) · 9.5 KB
/
clusterinstallation_utils.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
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
package v1alpha1
import (
"errors"
"fmt"
"strings"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
)
const (
// OperatorName is the name of the Mattermost operator
OperatorName = "mattermost-operator"
// DefaultMattermostImage is the default Mattermost docker image
DefaultMattermostImage = "mattermost/mattermost-enterprise-edition"
// DefaultMattermostVersion is the default Mattermost docker tag
DefaultMattermostVersion = "7.5.1"
// DefaultMattermostSize is the default number of users
DefaultMattermostSize = "5000users"
// DefaultMattermostDatabaseType is the default Mattermost database
DefaultMattermostDatabaseType = "mysql"
// DefaultMinioStorageSize is the default Storage size for Minio
DefaultMinioStorageSize = "50Gi"
// DefaultStorageSize is the default Storage size for the Database
DefaultStorageSize = "50Gi"
// DefaultPullPolicy is ifNotPresent
DefaultPullPolicy = corev1.PullIfNotPresent
// DefaultMysqlDatabaseVersion
// https://github.com/bitpoke/mysql-operator/blob/master/pkg/util/constants/constants.go#L87
DefaultMysqlDatabaseVersion = "8.0"
// ClusterLabel is the label applied across all compoments
ClusterLabel = "v1alpha1.mattermost.com/installation"
// ClusterResourceLabel is the label applied to a given Mattermost
// as well as all other resources created to support it.
ClusterResourceLabel = "v1alpha1.mattermost.com/resource"
// BlueName is the name of the blue Mattermost installation in a blue/green
// deployment type.
BlueName = "blue"
// GreenName is the name of the green Mattermost installation in a blue/green
// deployment type.
GreenName = "green"
// MattermostAppContainerName is the name of the container which runs the
// Mattermost application
MattermostAppContainerName = "mattermost"
)
// SetDefaults set the missing values in the manifest to the default ones
func (mattermost *ClusterInstallation) SetDefaults() error {
if mattermost.Spec.IngressName == "" {
return errors.New("IngressName required, but not set")
}
if mattermost.Spec.Image == "" {
mattermost.Spec.Image = DefaultMattermostImage
}
if mattermost.Spec.Version == "" {
mattermost.Spec.Version = DefaultMattermostVersion
}
if mattermost.Spec.ImagePullPolicy == "" {
mattermost.Spec.ImagePullPolicy = DefaultPullPolicy
}
mattermost.Spec.Minio.SetDefaults()
mattermost.Spec.Database.SetDefaults()
err := mattermost.Spec.BlueGreen.SetDefaults(mattermost)
if err != nil {
return err
}
err = mattermost.Spec.Canary.SetDefaults(mattermost)
return err
}
// SetDefaults sets the missing values in Canary to the default ones
func (canary *Canary) SetDefaults(mattermost *ClusterInstallation) error {
if canary.Enable {
if canary.Deployment.Version == "" {
return errors.New("Canary version required, but not set")
}
if canary.Deployment.Image == "" {
return errors.New("Canary deployment image required, but not set")
}
if canary.Deployment.Name == "" {
canary.Deployment.Name = fmt.Sprintf("%s-canary", mattermost.Name)
}
}
return nil
}
// SetDefaults sets the missing values in BlueGreen to the default ones
func (bg *BlueGreen) SetDefaults(mattermost *ClusterInstallation) error {
if bg.Enable {
bg.ProductionDeployment = strings.ToLower(bg.ProductionDeployment)
if bg.ProductionDeployment != BlueName && bg.ProductionDeployment != GreenName {
return fmt.Errorf("%s is not a valid ProductionDeployment value, must be 'blue' or 'green'", bg.ProductionDeployment)
}
if bg.Green.Version == "" || bg.Blue.Version == "" {
return errors.New("Both Blue and Green deployment versions required, but not set")
}
if bg.Blue.Image == "" || bg.Green.Image == "" {
return errors.New("Both Blue and Green deployment images required, but not set")
}
if bg.Green.Name == "" {
bg.Green.Name = fmt.Sprintf("%s-green", mattermost.Name)
}
if bg.Blue.Name == "" {
bg.Blue.Name = fmt.Sprintf("%s-blue", mattermost.Name)
}
if bg.Green.IngressName == "" {
bg.Green.IngressName = fmt.Sprintf("green.%s", mattermost.Spec.IngressName)
}
if bg.Blue.IngressName == "" {
bg.Blue.IngressName = fmt.Sprintf("blue.%s", mattermost.Spec.IngressName)
}
}
return nil
}
// SetDefaults sets the missing values in Minio to the default ones
func (mi *Minio) SetDefaults() {
if mi.StorageSize == "" {
mi.StorageSize = DefaultMinioStorageSize
}
}
// IsExternal returns true if the MinIO/S3 instance is external
func (mi *Minio) IsExternal() bool {
return mi.ExternalURL != ""
}
// SetDefaults sets the missing values in Database to the default ones
func (db *Database) SetDefaults() {
if len(db.Type) == 0 {
db.Type = DefaultMattermostDatabaseType
}
if db.StorageSize == "" {
db.StorageSize = DefaultStorageSize
}
if db.Type == DefaultMattermostDatabaseType && db.Version == "" {
db.Version = DefaultMysqlDatabaseVersion
}
}
// getDeploymentContainerByName gets container from a deployment by name
func (mattermost *ClusterInstallation) getDeploymentContainerByName(deployment *appsv1.Deployment, containerName string) *corev1.Container {
return getContainerByName(deployment.Spec.Template.Spec.Containers, containerName)
}
// getContainerByName gets container from a slice of containers by name
func getContainerByName(containers []corev1.Container, containerName string) *corev1.Container {
for _, container := range containers {
if container.Name == containerName {
return &container
}
}
return nil
}
// GetMattermostAppContainerFromDeployment gets container which runs Mattermost application from a deployment.
func (mattermost *ClusterInstallation) GetMattermostAppContainerFromDeployment(deployment *appsv1.Deployment) *corev1.Container {
// Check new-style - fixed name
container := mattermost.getDeploymentContainerByName(deployment, MattermostAppContainerName)
if container == nil {
// Check old-style - name of the container == name of the deployment
container = mattermost.getDeploymentContainerByName(deployment, deployment.Name)
}
return container
}
// GetMattermostAppContainer gets container from PodSpec which runs Mattermost application
// from a deployment.
func (mattermost *ClusterInstallation) GetMattermostAppContainer(containers []corev1.Container) *corev1.Container {
container := getContainerByName(containers, MattermostAppContainerName)
if container == nil {
// Check old-style - name of the container == name of the deployment
container = getContainerByName(containers, mattermost.Name)
}
return container
}
// GetImageName returns the container image name that matches the spec of the
// ClusterInstallation.
func (mattermost *ClusterInstallation) GetImageName() string {
// if user set the version using the Digest instead of tag like
// sha256:dd15a51ac7dafd213744d1ef23394e7532f71a90f477c969b94600e46da5a0cf
// we need to set the @ instead of : to split the image name and "tag"
if strings.Contains(mattermost.Spec.Version, "sha256:") {
return fmt.Sprintf("%s@%s", mattermost.Spec.Image, mattermost.Spec.Version)
}
return fmt.Sprintf("%s:%s", mattermost.Spec.Image, mattermost.Spec.Version)
}
// GetProductionDeploymentName returns the name of the deployment that is
// currently designated as production.
func (mattermost *ClusterInstallation) GetProductionDeploymentName() string {
if mattermost.Spec.BlueGreen.Enable {
if mattermost.Spec.BlueGreen.ProductionDeployment == BlueName {
return mattermost.Spec.BlueGreen.Blue.Name
}
if mattermost.Spec.BlueGreen.ProductionDeployment == GreenName {
return mattermost.Spec.BlueGreen.Green.Name
}
}
return mattermost.Name
}
// GetDeploymentImageName returns the container image name that matches the spec
// of the deployment.
func (d *AppDeployment) GetDeploymentImageName() string {
if strings.Contains(d.Version, "sha256:") {
return fmt.Sprintf("%s@%s", d.Image, d.Version)
}
return fmt.Sprintf("%s:%s", d.Image, d.Version)
}
// ClusterInstallationSelectorLabels returns the selector labels for selecting the resources
// belonging to the given mattermost clusterinstallation.
func ClusterInstallationSelectorLabels(name string) map[string]string {
l := ClusterInstallationResourceLabels(name)
l[ClusterLabel] = name
l["app"] = MattermostAppContainerName
return l
}
// ClusterInstallationLabels returns the labels for selecting the resources
// belonging to the given mattermost clusterinstallation.
func (mattermost *ClusterInstallation) ClusterInstallationLabels(name string) map[string]string {
l := ClusterInstallationResourceLabels(name)
l[ClusterLabel] = name
l["app"] = MattermostAppContainerName
labels := map[string]string{}
if mattermost.Spec.BlueGreen.Enable {
if mattermost.Spec.BlueGreen.ProductionDeployment == BlueName {
labels = mattermost.Spec.BlueGreen.Blue.ResourceLabels
}
if mattermost.Spec.BlueGreen.ProductionDeployment == GreenName {
labels = mattermost.Spec.BlueGreen.Green.ResourceLabels
}
} else {
labels = mattermost.Spec.ResourceLabels
}
for k, v := range labels {
l[k] = v
}
return l
}
// MySQLLabels returns the labels for selecting the resources belonging to the
// given mysql cluster.
func MySQLLabels() map[string]string {
return map[string]string{
"app.kubernetes.io/component": "database",
"app.kubernetes.io/instance": "db",
"app.kubernetes.io/managed-by": "mysql.presslabs.org",
"app.kubernetes.io/name": "mysql",
}
}
// ClusterInstallationResourceLabels returns the labels for selecting a given
// ClusterInstallation as well as any external dependency resources that were
// created for the installation.
func ClusterInstallationResourceLabels(name string) map[string]string {
return map[string]string{ClusterResourceLabel: name}
}