-
Notifications
You must be signed in to change notification settings - Fork 272
/
cloudstackdatacenterconfig_types.go
322 lines (285 loc) Β· 12.2 KB
/
cloudstackdatacenterconfig_types.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
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v1alpha1
import (
"fmt"
"strings"
"github.com/pkg/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/validation"
)
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
const DefaultCloudStackAZPrefix = "default-az"
// CloudStackDatacenterConfigSpec defines the desired state of CloudStackDatacenterConfig.
type CloudStackDatacenterConfigSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file
// Domain contains a grouping of accounts. Domains usually contain multiple accounts that have some logical relationship to each other and a set of delegated administrators with some authority over the domain and its subdomains
// This field is considered as a fully qualified domain name which is the same as the domain path without "ROOT/" prefix. For example, if "foo" is specified then a domain with "ROOT/foo" domain path is picked.
// The value "ROOT" is a special case that points to "the" ROOT domain of the CloudStack. That is, a domain with a path "ROOT/ROOT" is not allowed.
// +optional
// Deprecated: Please use AvailabilityZones instead
Domain string `json:"domain,omitempty"`
// Zones is a list of one or more zones that are managed by a single CloudStack management endpoint.
// +optional
// Deprecated: Please use AvailabilityZones instead
Zones []CloudStackZone `json:"zones,omitempty"`
// Account typically represents a customer of the service provider or a department in a large organization. Multiple users can exist in an account, and all CloudStack resources belong to an account. Accounts have users and users have credentials to operate on resources within that account. If an account name is provided, a domain must also be provided.
// +optional
// Deprecated: Please use AvailabilityZones instead
Account string `json:"account,omitempty"`
// CloudStack Management API endpoint's IP. It is added to VM's noproxy list
// +optional
// Deprecated: Please use AvailabilityZones instead
ManagementApiEndpoint string `json:"managementApiEndpoint,omitempty"`
// AvailabilityZones list of different partitions to distribute VMs across - corresponds to a list of CAPI failure domains
AvailabilityZones []CloudStackAvailabilityZone `json:"availabilityZones,omitempty"`
}
type CloudStackResourceIdentifier struct {
// Id of a resource in the CloudStack environment. Mutually exclusive with Name
// +optional
Id string `json:"id,omitempty"`
// Name of a resource in the CloudStack environment. Mutually exclusive with Id
// +optional
Name string `json:"name,omitempty"`
}
func (r *CloudStackResourceIdentifier) Equal(o *CloudStackResourceIdentifier) bool {
if r == o {
return true
}
if r == nil || o == nil {
return false
}
if r.Id != o.Id {
return false
}
return r.Id == "" && o.Id == "" && r.Name == o.Name
}
// CloudStackZone is an organizational construct typically used to represent a single datacenter, and all its physical and virtual resources exist inside that zone. It can either be specified as a UUID or name.
type CloudStackZone struct {
// Zone is the name or UUID of the CloudStack zone in which clusters should be created. Zones should be managed by a single CloudStack Management endpoint.
Id string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
// Network is the name or UUID of the CloudStack network in which clusters should be created. It can either be an isolated or shared network. If it doesnβt already exist in CloudStack, itβll automatically be created by CAPC as an isolated network. It can either be specified as a UUID or name
// In multiple-zones situation, only 'Shared' network is supported.
Network CloudStackResourceIdentifier `json:"network"`
}
// CloudStackAvailabilityZone maps to a CAPI failure domain to distribute machines across Cloudstack infrastructure.
type CloudStackAvailabilityZone struct {
// Name is used as a unique identifier for each availability zone
Name string `json:"name"`
// CredentialRef is used to reference a secret in the eksa-system namespace
CredentialsRef string `json:"credentialsRef"`
// Zone represents the properties of the CloudStack zone in which clusters should be created, like the network.
Zone CloudStackZone `json:"zone"`
// Domain contains a grouping of accounts. Domains usually contain multiple accounts that have some logical relationship to each other and a set of delegated administrators with some authority over the domain and its subdomains
// This field is considered as a fully qualified domain name which is the same as the domain path without "ROOT/" prefix. For example, if "foo" is specified then a domain with "ROOT/foo" domain path is picked.
// The value "ROOT" is a special case that points to "the" ROOT domain of the CloudStack. That is, a domain with a path "ROOT/ROOT" is not allowed.
Domain string `json:"domain"`
// Account typically represents a customer of the service provider or a department in a large organization. Multiple users can exist in an account, and all CloudStack resources belong to an account. Accounts have users and users have credentials to operate on resources within that account. If an account name is provided, a domain must also be provided.
Account string `json:"account,omitempty"`
// CloudStack Management API endpoint's IP. It is added to VM's noproxy list
ManagementApiEndpoint string `json:"managementApiEndpoint"`
}
// CloudStackDatacenterConfigStatus defines the observed state of CloudStackDatacenterConfig.
type CloudStackDatacenterConfigStatus struct { // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// SpecValid is set to true if cloudstackdatacenterconfig is validated.
SpecValid bool `json:"specValid,omitempty"`
// ObservedGeneration is the latest generation observed by the controller.
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
// FailureMessage indicates that there is a fatal problem reconciling the
// state, and will be set to a descriptive error message.
FailureMessage *string `json:"failureMessage,omitempty"`
// Important: Run "make" to regenerate code after modifying this file
}
//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
// CloudStackDatacenterConfig is the Schema for the cloudstackdatacenterconfigs API.
type CloudStackDatacenterConfig struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec CloudStackDatacenterConfigSpec `json:"spec,omitempty"`
Status CloudStackDatacenterConfigStatus `json:"status,omitempty"`
}
func (v *CloudStackDatacenterConfig) Kind() string {
return v.TypeMeta.Kind
}
func (v *CloudStackDatacenterConfig) ExpectedKind() string {
return CloudStackDatacenterKind
}
func (v *CloudStackDatacenterConfig) PauseReconcile() {
if v.Annotations == nil {
v.Annotations = map[string]string{}
}
v.Annotations[pausedAnnotation] = "true"
}
func (v *CloudStackDatacenterConfig) IsReconcilePaused() bool {
if s, ok := v.Annotations[pausedAnnotation]; ok {
return s == "true"
}
return false
}
func (v *CloudStackDatacenterConfig) ClearPauseAnnotation() {
if v.Annotations != nil {
delete(v.Annotations, pausedAnnotation)
}
}
func (v *CloudStackDatacenterConfig) ConvertConfigToConfigGenerateStruct() *CloudStackDatacenterConfigGenerate {
namespace := defaultEksaNamespace
if v.Namespace != "" {
namespace = v.Namespace
}
config := &CloudStackDatacenterConfigGenerate{
TypeMeta: v.TypeMeta,
ObjectMeta: ObjectMeta{
Name: v.Name,
Annotations: v.Annotations,
Namespace: namespace,
},
Spec: v.Spec,
}
return config
}
func (v *CloudStackDatacenterConfig) Marshallable() Marshallable {
return v.ConvertConfigToConfigGenerateStruct()
}
func (v *CloudStackDatacenterConfig) Validate() error {
if v.Spec.Account != "" {
return errors.New("account must be empty")
}
if v.Spec.Domain != "" {
return errors.New("domain must be empty")
}
if v.Spec.ManagementApiEndpoint != "" {
return errors.New("managementApiEndpoint must be empty")
}
if len(v.Spec.Zones) > 0 {
return errors.New("zones must be empty")
}
if len(v.Spec.AvailabilityZones) == 0 {
return errors.New("availabilityZones must not be empty")
}
azSet := make(map[string]bool)
for _, az := range v.Spec.AvailabilityZones {
errorMessages := validation.IsValidLabelValue(az.Name)
if len(errorMessages) > 0 {
return fmt.Errorf("availabilityZone names must be a valid label value since it is used to label nodes: %s",
strings.Join(errorMessages, ";"))
}
if exists := azSet[az.Name]; exists {
return fmt.Errorf("availabilityZone names must be unique. Duplicate name: %s", az.Name)
}
azSet[az.Name] = true
}
return nil
}
func (v *CloudStackDatacenterConfig) SetDefaults() {
if v.Spec.AvailabilityZones == nil || len(v.Spec.AvailabilityZones) == 0 {
v.Spec.AvailabilityZones = make([]CloudStackAvailabilityZone, 0, len(v.Spec.Zones))
for index, csZone := range v.Spec.Zones {
az := CloudStackAvailabilityZone{
Name: fmt.Sprintf("%s-%d", DefaultCloudStackAZPrefix, index),
Zone: csZone,
Account: v.Spec.Account,
Domain: v.Spec.Domain,
ManagementApiEndpoint: v.Spec.ManagementApiEndpoint,
CredentialsRef: "global",
}
v.Spec.AvailabilityZones = append(v.Spec.AvailabilityZones, az)
}
}
v.Spec.Zones = nil
v.Spec.Domain = ""
v.Spec.Account = ""
v.Spec.ManagementApiEndpoint = ""
}
func (s *CloudStackDatacenterConfigSpec) Equal(o *CloudStackDatacenterConfigSpec) bool {
if s == o {
return true
}
if s == nil || o == nil {
return false
}
if len(s.Zones) != len(o.Zones) {
return false
}
for i, z := range s.Zones {
if !z.Equal(&o.Zones[i]) {
return false
}
}
if len(s.AvailabilityZones) != len(o.AvailabilityZones) {
return false
}
oAzsMap := map[string]CloudStackAvailabilityZone{}
for _, oAz := range o.AvailabilityZones {
oAzsMap[oAz.Name] = oAz
}
for _, sAz := range s.AvailabilityZones {
oAz, found := oAzsMap[sAz.Name]
if !found || !sAz.Equal(&oAz) {
return false
}
}
return s.ManagementApiEndpoint == o.ManagementApiEndpoint &&
s.Domain == o.Domain &&
s.Account == o.Account
}
func (z *CloudStackZone) Equal(o *CloudStackZone) bool {
if z == o {
return true
}
if z == nil || o == nil {
return false
}
if z.Id == o.Id &&
z.Name == o.Name &&
z.Network.Id == o.Network.Id &&
z.Network.Name == o.Network.Name {
return true
}
return false
}
func (az *CloudStackAvailabilityZone) Equal(o *CloudStackAvailabilityZone) bool {
if az == o {
return true
}
if az == nil || o == nil {
return false
}
return az.Zone.Equal(&o.Zone) &&
az.Name == o.Name &&
az.CredentialsRef == o.CredentialsRef &&
az.Account == o.Account &&
az.Domain == o.Domain &&
az.ManagementApiEndpoint == o.ManagementApiEndpoint
}
// +kubebuilder:object:generate=false
// Same as CloudStackDatacenterConfig except stripped down for generation of yaml file during generate clusterconfig.
type CloudStackDatacenterConfigGenerate struct {
metav1.TypeMeta `json:",inline"`
ObjectMeta `json:"metadata,omitempty"`
Spec CloudStackDatacenterConfigSpec `json:"spec,omitempty"`
}
//+kubebuilder:object:root=true
// CloudStackDatacenterConfigList contains a list of CloudStackDatacenterConfig.
type CloudStackDatacenterConfigList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []CloudStackDatacenterConfig `json:"items"`
}
func init() {
SchemeBuilder.Register(&CloudStackDatacenterConfig{}, &CloudStackDatacenterConfigList{})
}