-
Notifications
You must be signed in to change notification settings - Fork 100
/
phase1_verifying.go
156 lines (136 loc) · 4.84 KB
/
phase1_verifying.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
package system
import (
"fmt"
"os"
"github.com/asaskevich/govalidator"
semver "github.com/coreos/go-semver/semver"
dockerref "github.com/docker/distribution/reference"
nbv1 "github.com/noobaa/noobaa-operator/v2/pkg/apis/noobaa/v1alpha1"
"github.com/noobaa/noobaa-operator/v2/pkg/options"
"github.com/noobaa/noobaa-operator/v2/pkg/util"
)
// ReconcilePhaseVerifying runs the reconcile verify phase
func (r *Reconciler) ReconcilePhaseVerifying() error {
r.SetPhase(
nbv1.SystemPhaseVerifying,
"SystemPhaseVerifying",
"noobaa operator started phase 1/4 - \"Verifying\"",
)
if err := r.CheckSystemCR(); err != nil {
return err
}
if r.JoinSecret != nil {
if err := r.CheckJoinSecret(); err != nil {
return err
}
}
return nil
}
// CheckSystemCR checks the validity of the system CR
// (i.e system.metadata.name and system.spec.image)
// and updates the status accordingly
func (r *Reconciler) CheckSystemCR() error {
log := r.Logger.WithField("func", "CheckSystemCR")
// we assume a single system per ns here
if r.NooBaa.Name != options.SystemName {
return util.NewPersistentError("InvalidSystemName",
fmt.Sprintf("Invalid system name %q expected %q", r.NooBaa.Name, options.SystemName))
}
specImage := options.ContainerImage
if os.Getenv("NOOBAA_CORE_IMAGE") != "" {
specImage = os.Getenv("NOOBAA_CORE_IMAGE")
}
if r.NooBaa.Spec.Image != nil {
specImage = *r.NooBaa.Spec.Image
}
// Parse the image spec as a docker image url
imageRef, err := dockerref.Parse(specImage)
// If the image cannot be parsed log the incident and mark as persistent error
// since we don't need to retry until the spec is updated.
if err != nil {
return util.NewPersistentError("InvalidImage",
fmt.Sprintf(`Invalid image requested %q %v`, specImage, err))
}
// Get the image name and tag
imageName := ""
imageTag := ""
switch image := imageRef.(type) {
case dockerref.NamedTagged:
log.Infof("Parsed image (NamedTagged) %v", image)
imageName = image.Name()
imageTag = image.Tag()
case dockerref.Tagged:
log.Infof("Parsed image (Tagged) %v", image)
imageTag = image.Tag()
case dockerref.Named:
log.Infof("Parsed image (Named) %v", image)
imageName = image.Name()
default:
log.Infof("Parsed image (unstructured) %v", image)
}
if imageName == options.ContainerImageName {
version, err := semver.NewVersion(imageTag)
if err == nil {
log.Infof("Parsed version %q from image tag %q", version.String(), imageTag)
minver := semver.New(options.ContainerImageSemverLowerBound)
maxver := semver.New(options.ContainerImageSemverUpperBound)
if version.Compare(*minver) != 1 || version.Compare(*maxver) != -1 {
return util.NewPersistentError("InvalidImageVersion",
fmt.Sprintf(`Invalid image version %q not matching version constraints: >=%v, <%v`,
imageRef, minver, maxver))
}
} else {
log.Infof("Using custom image %q", imageRef.String())
}
} else {
log.Infof("Using custom image name %q the default is %q", imageRef.String(), options.ContainerImageName)
}
// Set ActualImage to be updated in the noobaa status
r.NooBaa.Status.ActualImage = specImage
// Verfify the endpoints spec
endpointsSpec := r.NooBaa.Spec.Endpoints
if endpointsSpec != nil {
if endpointsSpec.MinCount <= 0 {
return util.NewPersistentError("InvalidEndpointsConfiguration",
"Invalid endpoint min count (must be greater than 0)")
}
// Validate bounds on endpoint counts
if endpointsSpec.MinCount > endpointsSpec.MaxCount {
return util.NewPersistentError("InvalidEndpointsConfiguration",
"Invalid endpoint maximum count (must be higher than or equal to minimum count)")
}
// Validate that all virtual hosts are in FQDN format
for _, virtualHost := range endpointsSpec.AdditionalVirtualHosts {
if !govalidator.IsDNSName(virtualHost) {
return util.NewPersistentError("InvalidEndpointsConfiguration",
fmt.Sprintf(`Invalid virtual host %s, not a fully qualified DNS name`, virtualHost))
}
}
}
return nil
}
// CheckJoinSecret checks that all need information to allow to join
// another noobaa clauster is specified in the join secret
func (r *Reconciler) CheckJoinSecret() error {
if r.JoinSecret.StringData["mgmt_addr"] == "" {
return util.NewPersistentError("InvalidJoinSecert",
"JoinSecret is missing mgmt_addr")
}
if r.JoinSecret.StringData["bg_addr"] == "" {
return util.NewPersistentError("InvalidJoinSecert",
"JoinSecret is missing bg_addr")
}
if r.JoinSecret.StringData["md_addr"] == "" {
return util.NewPersistentError("InvalidJoinSecert",
"JoinSecret is missing md_addr")
}
if r.JoinSecret.StringData["hosted_agents_addr"] == "" {
return util.NewPersistentError("InvalidJoinSecert",
"JoinSecret is missing hosted_agents_addr")
}
if r.JoinSecret.StringData["auth_token"] == "" {
return util.NewPersistentError("InvalidJoinSecert",
"JoinSecret is missing auth_token")
}
return nil
}