-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
platform.go
163 lines (147 loc) · 7.21 KB
/
platform.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
package validation
import (
"fmt"
"regexp"
"sort"
"k8s.io/apimachinery/pkg/util/validation/field"
"github.com/openshift/installer/pkg/types"
"github.com/openshift/installer/pkg/types/gcp"
)
var (
// Regions is a map of known GCP regions. The key of the map is
// the short name of the region. The value of the map is the long
// name of the region.
Regions = map[string]string{
// List from: https://cloud.google.com/compute/docs/regions-zones/
"africa-south1": "Johannesburg, South Africa",
"asia-east1": "Changhua County, Taiwan",
"asia-east2": "Hong Kong",
"asia-northeast1": "Tokyo, Japan",
"asia-northeast2": "Osaka, Japan",
"asia-northeast3": "Seoul, South Korea",
"asia-south1": "Mumbai, India",
"asia-south2": "Delhi, India",
"asia-southeast1": "Jurong West, Singapore",
"asia-southeast2": "Jakarta, Indonesia",
"australia-southeast1": "Sydney, Australia",
"australia-southeast2": "Melbourne, Australia",
"europe-central2": "Warsaw, Poland",
"europe-north1": "Hamina, Finland",
"europe-west1": "St. Ghislain, Belgium",
"europe-west2": "London, England, UK",
"europe-west3": "Frankfurt, Germany",
"europe-west4": "Eemshaven, Netherlands",
"europe-west6": "Zürich, Switzerland",
"europe-west8": "Milan, Italy",
"europe-west9": "Paris, France",
"europe-west12": "Turin, Italy",
"europe-southwest1": "Madrid, Spain",
"me-central1": "Doha, Qatar, Middle East",
"me-central2": "Dammam, Saudi Arabia, Middle East",
"me-west1": "Tel Aviv, Israel",
"northamerica-northeast1": "Montréal, Québec, Canada",
"northamerica-northeast2": "Toronto, Ontario, Canada",
"southamerica-east1": "São Paulo, Brazil",
"southamerica-west1": "Santiago, Chile",
"us-central1": "Council Bluffs, Iowa, USA",
"us-east1": "Moncks Corner, South Carolina, USA",
"us-east4": "Ashburn, Virginia, USA",
"us-east5": "Columbus, Ohio, USA",
"us-south1": "Dallas, Texas, USA",
"us-west1": "The Dalles, Oregon, USA",
"us-west2": "Los Angeles, California, USA",
"us-west3": "Salt Lake City, Utah, USA",
"us-west4": "Las Vegas, Nevada, USA",
}
validRegionValues = func() []string {
validValues := make([]string, len(Regions))
i := 0
for r := range Regions {
validValues[i] = r
i++
}
sort.Strings(validValues)
return validValues
}()
// userLabelKeyRegex is for verifying that the label key contains only allowed characters.
userLabelKeyRegex = regexp.MustCompile(`^[a-z][0-9a-z_-]{0,62}$`)
// userLabelValueRegex is for verifying that the label value contains only allowed characters.
userLabelValueRegex = regexp.MustCompile(`^[0-9a-z_-]{1,63}$`)
// userLabelKeyPrefixRegex is for verifying that the label key does not contain restricted prefixes.
userLabelKeyPrefixRegex = regexp.MustCompile(`^(?i)(kubernetes\-io|openshift\-io)`)
)
const (
// maxUserLabelLimit is the maximum userLabels that can be configured as defined in openshift/api.
// https://github.com/openshift/api/commit/ae73a19d05c35068af16c9aeff375d0b7c936a8a#diff-07b264a49084976b670fb699badaca1795027d6ea732a99226a5388104f6174fR592-R602
maxUserLabelLimit = 32
)
// ValidatePlatform checks that the specified platform is valid.
func ValidatePlatform(p *gcp.Platform, fldPath *field.Path, ic *types.InstallConfig) field.ErrorList {
allErrs := field.ErrorList{}
if p.Region == "" {
allErrs = append(allErrs, field.Required(fldPath.Child("region"), "must provide a region"))
}
if p.DefaultMachinePlatform != nil {
allErrs = append(allErrs, ValidateMachinePool(p, p.DefaultMachinePlatform, fldPath.Child("defaultMachinePlatform"))...)
allErrs = append(allErrs, ValidateDefaultDiskType(p.DefaultMachinePlatform, fldPath.Child("defaultMachinePlatform"))...)
}
if p.NetworkProjectID != "" {
if p.Network == "" {
allErrs = append(allErrs, field.Required(fldPath.Child("network"), "must provide a network when a networkProjectID is specified"))
}
if ic.CredentialsMode != types.ManualCredentialsMode && ic.CredentialsMode != types.PassthroughCredentialsMode {
allErrs = append(allErrs, field.NotSupported(fldPath.Child("credentialsMode"),
ic.CredentialsMode, []string{string(types.ManualCredentialsMode), string(types.PassthroughCredentialsMode)}))
}
}
if p.Network != "" {
if p.ComputeSubnet == "" {
allErrs = append(allErrs, field.Required(fldPath.Child("computeSubnet"), "must provide a compute subnet when a network is specified"))
}
if p.ControlPlaneSubnet == "" {
allErrs = append(allErrs, field.Required(fldPath.Child("controlPlaneSubnet"), "must provide a control plane subnet when a network is specified"))
}
}
if (p.ComputeSubnet != "" || p.ControlPlaneSubnet != "") && p.Network == "" {
allErrs = append(allErrs, field.Required(fldPath.Child("network"), "must provide a VPC network when supplying subnets"))
}
// check if configured userLabels are valid.
allErrs = append(allErrs, validateUserLabels(p.UserLabels, fldPath.Child("userLabels"))...)
return allErrs
}
// validateUserLabels verifies if configured number of UserLabels is not more than
// allowed limit and the label keys and values are valid.
func validateUserLabels(labels []gcp.UserLabel, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if len(labels) == 0 {
return allErrs
}
if len(labels) > maxUserLabelLimit {
allErrs = append(allErrs, field.TooMany(fldPath, len(labels), maxUserLabelLimit))
}
for _, label := range labels {
if err := validateLabel(label.Key, label.Value); err != nil {
allErrs = append(allErrs, field.Invalid(fldPath.Key(label.Key), label.Value, err.Error()))
}
}
return allErrs
}
// validateLabel checks the following to ensure that the label configured is acceptable.
// - The key and value contain only allowed characters.
// - The key is not empty and at most 63 characters and starts with a lowercase letter.
// - The value is not empty and at most 63 characters.
// - The key and value must contain only lowercase letters, numeric characters,
// underscores, and dashes.
// - The key cannot be Name or have kubernetes.io, openshift.io prefixes.
func validateLabel(key, value string) error {
if !userLabelKeyRegex.MatchString(key) {
return fmt.Errorf("label key is invalid or contains invalid characters. Label key can have a maximum of 63 characters and cannot be empty. Label key must begin with a lowercase letter, and must contain only lowercase letters, numeric characters, and the following special characters `_-`")
}
if !userLabelValueRegex.MatchString(value) {
return fmt.Errorf("label value is invalid or contains invalid characters. Label value can have a maximum of 63 characters and cannot be empty. Value must contain only lowercase letters, numeric characters, and the following special characters `_-`")
}
if userLabelKeyPrefixRegex.MatchString(key) {
return fmt.Errorf("label key contains restricted prefix. Label key cannot have `kubernetes-io`, `openshift-io` prefixes")
}
return nil
}