generated from cloudoperators/repository-template
/
plugindefinition_types.go
212 lines (184 loc) · 6.86 KB
/
plugindefinition_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
// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Greenhouse contributors
// SPDX-License-Identifier: Apache-2.0
package v1alpha1
import (
"encoding/json"
"fmt"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// PluginDefinitionSpec defines the desired state of PluginDefinitionSpec
type PluginDefinitionSpec struct {
// Description provides additional details of the pluginDefinition.
Description string `json:"description,omitempty"`
// HelmChart specifies where the Helm Chart for this pluginDefinition can be found.
HelmChart *HelmChartReference `json:"helmChart,omitempty"`
// UIApplication specifies a reference to a UI application
UIApplication *UIApplicationReference `json:"uiApplication,omitempty"`
// RequiredValues is a list of values required to create an instance of this PluginDefinition.
Options []PluginOption `json:"options,omitempty"`
// Version of this pluginDefinition
Version string `json:"version"`
// Weight configures the order in which Plugins are shown in the Greenhouse UI.
// Defaults to alphabetical sorting if not provided or on conflict.
Weight *int32 `json:"weight,omitempty"`
}
// PluginOptionType specifies the type of PluginOption.
// +kubebuilder:validation:Enum=string;secret;bool;int;list;map
type PluginOptionType string
const (
// PluginOptionTypeString is a valid value for PluginOptionType.
PluginOptionTypeString PluginOptionType = "string"
// PluginOptionTypeSecret is a valid value for PluginOptionType.
PluginOptionTypeSecret PluginOptionType = "secret"
// PluginOptionTypeBool is a valid value for PluginOptionType.
PluginOptionTypeBool PluginOptionType = "bool"
// PluginOptionTypeInt is a valid value for PluginOptionType.
PluginOptionTypeInt PluginOptionType = "int"
// PluginOptionTypeList is a valid value for PluginOptionType.
PluginOptionTypeList PluginOptionType = "list"
// PluginOptionTypeMap is a valid value for PluginOptionType.
PluginOptionTypeMap PluginOptionType = "map"
)
type PluginOption struct {
// Name/Key of the config option.
Name string `json:"name"`
// Default provides a default value for the option
// +optional
Default *apiextensionsv1.JSON `json:"default,omitempty"`
// Description provides a human-readable text for the value as shown in the UI.
Description string `json:"description,omitempty"`
// DisplayName provides a human-readable label for the configuration option
DisplayName string `json:"displayName,omitempty"`
// Required indicates that this config option is required
Required bool `json:"required"`
// Type of this configuration option.
Type PluginOptionType `json:"type"`
// Regex specifies a match rule for validating configuration options.
Regex string `json:"regex,omitempty"`
}
// IsValid returns nil if the PluginOption is valid.
// An error is returned for unknown types or if type and value of the option do not match.
func (p *PluginOption) IsValid() error {
if p.Default == nil {
return nil
}
switch p.Type {
case PluginOptionTypeBool:
var b bool
return json.Unmarshal(p.Default.Raw, &b)
case PluginOptionTypeInt:
var i int
return json.Unmarshal(p.Default.Raw, &i)
case PluginOptionTypeString, PluginOptionTypeSecret:
var s string
return json.Unmarshal(p.Default.Raw, &s)
case PluginOptionTypeList:
var l []any
return json.Unmarshal(p.Default.Raw, &l)
case PluginOptionTypeMap:
var m map[string]any
return json.Unmarshal(p.Default.Raw, &m)
default:
return fmt.Errorf("unknown type %s", p.Type)
}
}
// IsValidValue returns nil if the given value is valid for this PluginOption.
// An error is returned if val does not match the type of the PluginOption.
func (p *PluginOption) IsValidValue(val *apiextensionsv1.JSON) error {
var actVal any
if err := json.Unmarshal(val.Raw, &actVal); err != nil {
return err
}
switch p.Type {
case PluginOptionTypeBool:
if _, ok := actVal.(bool); !ok {
return fmt.Errorf("option %s is a bool value, got %T", p.Name, actVal)
}
case PluginOptionTypeInt:
switch actVal.(type) {
case int, float64:
// json.Decoder unmarshals numbers as float64, so we need to check for float64 as well
// known Bug in k8s & helm: e.g. https://github.com/kubernetes-sigs/yaml/issues/45
return nil
default:
return fmt.Errorf("option %s is an int value, got %T", p.Name, actVal)
}
case PluginOptionTypeString:
if _, ok := actVal.(string); !ok {
return fmt.Errorf("option %s is a string value, got %T", p.Name, actVal)
}
case PluginOptionTypeList:
if _, ok := actVal.([]any); !ok {
return fmt.Errorf("option %s is a list value, got %T", p.Name, actVal)
}
case PluginOptionTypeMap:
if _, ok := actVal.(map[string]any); !ok {
return fmt.Errorf("option %s is a map value, got %T", p.Name, actVal)
}
case PluginOptionTypeSecret:
return fmt.Errorf("option %s is a secret value, that should be derived from a secret reference", p.Name)
default:
return fmt.Errorf("option %s has unknown type, got %T", p.Name, actVal)
}
return nil
}
// GetDefault returns the default value for this option.
func (p *PluginOption) DefaultValue() (any, error) {
if p == nil {
return nil, nil
}
switch p.Type {
case PluginOptionTypeBool:
var b bool
if err := json.Unmarshal(p.Default.Raw, &b); err != nil {
return nil, err
}
return b, nil
case PluginOptionTypeInt:
var i int
if err := json.Unmarshal(p.Default.Raw, &i); err != nil {
return nil, err
}
return i, nil
case PluginOptionTypeSecret, PluginOptionTypeString:
var s string
if err := json.Unmarshal(p.Default.Raw, &s); err != nil {
return nil, err
}
return s, nil
case PluginOptionTypeList:
var l []any
if err := json.Unmarshal(p.Default.Raw, &l); err != nil {
return nil, err
}
return l, nil
default:
return nil, fmt.Errorf("unknown type %s", p.Type)
}
}
// PluginDefinitionStatus defines the observed state of PluginDefinition
type PluginDefinitionStatus struct{}
//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
//+kubebuilder:resource:scope=Cluster
//+kubebuilder:printcolumn:name="Version",type=string,JSONPath=`.spec.version`
//+kubebuilder:printcolumn:name="Description",type=string,JSONPath=`.spec.description`
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
// PluginDefinition is the Schema for the PluginDefinitions API
type PluginDefinition struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec PluginDefinitionSpec `json:"spec,omitempty"`
Status PluginDefinitionStatus `json:"status,omitempty"`
}
//+kubebuilder:object:root=true
// PluginDefinitionList contains a list of PluginDefinition
type PluginDefinitionList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []PluginDefinition `json:"items"`
}
func init() {
SchemeBuilder.Register(&PluginDefinition{}, &PluginDefinitionList{})
}