github.com/kyma-project/kyma-environment-broker@v0.0.1/internal/broker/plans_schema.go (about) 1 package broker 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "strings" 7 8 "github.com/kyma-project/kyma-environment-broker/internal/networking" 9 ) 10 11 type RootSchema struct { 12 Schema string `json:"$schema"` 13 Type 14 Properties interface{} `json:"properties"` 15 Required []string `json:"required"` 16 17 // Specified to true enables form view on website 18 ShowFormView bool `json:"_show_form_view"` 19 // Specifies in what order properties will be displayed on the form 20 ControlsOrder []string `json:"_controlsOrder"` 21 } 22 23 type ProvisioningProperties struct { 24 UpdateProperties 25 26 Name NameType `json:"name"` 27 ShootName *Type `json:"shootName,omitempty"` 28 ShootDomain *Type `json:"shootDomain,omitempty"` 29 Region *Type `json:"region,omitempty"` 30 Networking *NetworkingType `json:"networking,omitempty"` 31 Modules *Modules `json:"modules,omitempty"` 32 } 33 34 type UpdateProperties struct { 35 Kubeconfig *Type `json:"kubeconfig,omitempty"` 36 AutoScalerMin *Type `json:"autoScalerMin,omitempty"` 37 AutoScalerMax *Type `json:"autoScalerMax,omitempty"` 38 OIDC *OIDCType `json:"oidc,omitempty"` 39 Administrators *Type `json:"administrators,omitempty"` 40 MachineType *Type `json:"machineType,omitempty"` 41 } 42 43 func (up *UpdateProperties) IncludeAdditional() { 44 up.OIDC = NewOIDCSchema() 45 up.Administrators = AdministratorsProperty() 46 } 47 48 type NetworkingProperties struct { 49 Nodes Type `json:"nodes"` 50 } 51 52 type NetworkingType struct { 53 Type 54 Properties NetworkingProperties `json:"properties"` 55 Required []string `json:"required"` 56 } 57 58 type OIDCProperties struct { 59 ClientID Type `json:"clientID"` 60 GroupsClaim Type `json:"groupsClaim"` 61 IssuerURL Type `json:"issuerURL"` 62 SigningAlgs Type `json:"signingAlgs"` 63 UsernameClaim Type `json:"usernameClaim"` 64 UsernamePrefix Type `json:"usernamePrefix"` 65 } 66 67 type OIDCType struct { 68 Type 69 Properties OIDCProperties `json:"properties"` 70 Required []string `json:"required"` 71 } 72 73 type Type struct { 74 Type string `json:"type"` 75 Title string `json:"title,omitempty"` 76 Description string `json:"description,omitempty"` 77 Minimum int `json:"minimum,omitempty"` 78 Maximum int `json:"maximum,omitempty"` 79 MinLength int `json:"minLength,omitempty"` 80 MaxLength int `json:"maxLength,omitempty"` 81 82 // Regex pattern to match against string type of fields. 83 // If not specified for strings user can pass empty string with whitespaces only. 84 Pattern string `json:"pattern,omitempty"` 85 Default interface{} `json:"default,omitempty"` 86 Example interface{} `json:"example,omitempty"` 87 Enum []interface{} `json:"enum,omitempty"` 88 EnumDisplayName map[string]string `json:"_enumDisplayName,omitempty"` 89 Items *Type `json:"items,omitempty"` 90 AdditionalItems interface{} `json:"additionalItems,omitempty"` 91 UniqueItems interface{} `json:"uniqueItems,omitempty"` 92 ReadOnly interface{} `json:"readOnly,omitempty"` 93 AdditionalProperties interface{} `json:"additionalProperties,omitempty"` 94 } 95 96 type NameType struct { 97 Type 98 BTPdefaultTemplate BTPdefaultTemplate `json:"_BTPdefaultTemplate,omitempty"` 99 } 100 101 type BTPdefaultTemplate struct { 102 Elements []string `json:"elements,omitempty"` 103 Separator string `json:"separator,omitempty"` 104 } 105 106 type Modules struct { 107 Type 108 ControlsOrder []string `json:"_controlsOrder,omitempty"` 109 OneOf []interface{} `json:"oneOf,omitempty"` 110 } 111 112 type ModulesDefault struct { 113 Type 114 Properties ModulesDefaultProperties `json:"properties,omitempty"` 115 } 116 117 type ModulesDefaultProperties struct { 118 Default Type `json:"default,omitempty"` 119 } 120 121 type ModulesCustom struct { 122 Type 123 Properties ModulesCustomProperties `json:"properties,omitempty"` 124 } 125 126 type ModulesCustomProperties struct { 127 List ModulesCustomList `json:"list,omitempty"` 128 } 129 130 type ModulesCustomList struct { 131 Type 132 Items ModulesCustomListItems `json:"items,omitempty"` 133 } 134 135 type ModulesCustomListItems struct { 136 Type 137 ControlsOrder []string `json:"_controlsOrder,omitempty"` 138 Properties ModulesCustomListItemsProperties `json:"properties,omitempty"` 139 } 140 141 type ModulesCustomListItemsProperties struct { 142 Name Type `json:"name,omitempty"` 143 Channel Type `json:"channel,omitempty"` 144 CustomResourcePolicy Type `json:"customResourcePolicy,omitempty"` 145 } 146 147 func NewModulesSchema(modulesEnabled bool) *Modules { 148 if !modulesEnabled { 149 return nil 150 } 151 return &Modules{ 152 Type: Type{ 153 Type: "object", 154 Description: "Use default modules or provide your custom list of modules.", 155 }, 156 ControlsOrder: []string{"default", "list"}, 157 OneOf: []any{ 158 ModulesDefault{ 159 Type: Type{ 160 Type: "object", 161 Title: "Default", 162 Description: "Default modules", 163 AdditionalProperties: false, 164 }, 165 Properties: ModulesDefaultProperties{ 166 Type{ 167 Type: "boolean", 168 Title: "Use Default", 169 Description: "Check the default modules at: https://help.sap.com/docs/btp/sap-business-technology-platform/kyma-modules?version=Cloud.", 170 Default: true, 171 ReadOnly: true, 172 }, 173 }, 174 }, 175 ModulesCustom{ 176 Type: Type{ 177 Type: "object", 178 Title: "Custom", 179 Description: "Define custom module list", 180 AdditionalProperties: false, 181 }, 182 Properties: ModulesCustomProperties{ 183 ModulesCustomList{ 184 Type: Type{ 185 Type: "array", 186 UniqueItems: true, 187 Description: "Select a module technical name from the list available at: https://help.sap.com/docs/btp/sap-business-technology-platform/kyma-modules?version=Cloud. You can only use a module technical name once.", 188 }, 189 Items: ModulesCustomListItems{ 190 ControlsOrder: []string{"name", "channel", "customResourcePolicy"}, 191 Type: Type{ 192 Type: "object", 193 }, 194 Properties: ModulesCustomListItemsProperties{ 195 Name: Type{ 196 Type: "string", 197 Title: "Name", 198 MinLength: 1, 199 Description: "Select a module technical name from the list available at: https://help.sap.com/docs/btp/sap-business-technology-platform/kyma-modules?version=Cloud. You can only use a module technical name once.", 200 }, 201 Channel: Type{ 202 Type: "string", 203 Default: "regular", 204 Description: "Select your preferred release channel.", 205 Enum: ToInterfaceSlice([]string{"regular", "fast"}), 206 EnumDisplayName: map[string]string{ 207 "regular": "Regular - default version", 208 "fast": "Fast - latest version", 209 }, 210 }, 211 CustomResourcePolicy: Type{ 212 Type: "string", 213 Description: "Select your preferred CustomResourcePolicy setting.", 214 Default: "CreateAndDelete", 215 Enum: ToInterfaceSlice([]string{"CreateAndDelete", "Ignore"}), 216 EnumDisplayName: map[string]string{ 217 "CreateAndDelete": "CreateAndDelete - default module resource is created or deleted.", 218 "Ignore": "Ignore - module resource is not created.", 219 }, 220 }, 221 }, 222 }, 223 }}, 224 }}, 225 } 226 } 227 228 func NameProperty() NameType { 229 return NameType{ 230 Type: Type{ 231 Type: "string", 232 Title: "Cluster Name", 233 // Allows for all alphanumeric characters and '-' 234 Pattern: "^[a-zA-Z0-9-]*$", 235 MinLength: 1, 236 }, 237 BTPdefaultTemplate: BTPdefaultTemplate{ 238 Elements: []string{"saSubdomain"}, 239 }, 240 } 241 } 242 243 func KubeconfigProperty() *Type { 244 return &Type{ 245 Type: "string", 246 Title: "Kubeconfig contents", 247 } 248 } 249 250 func ShootNameProperty() *Type { 251 return &Type{ 252 Type: "string", 253 Title: "Shoot name", 254 Pattern: "^[a-zA-Z0-9-]*$", 255 MinLength: 1, 256 } 257 } 258 259 func ShootDomainProperty() *Type { 260 return &Type{ 261 Type: "string", 262 Title: "Shoot domain", 263 Pattern: "^[a-zA-Z0-9-\\.]*$", 264 MinLength: 1, 265 } 266 } 267 268 // NewProvisioningProperties creates a new properties for different plans 269 // Note that the order of properties will be the same in the form on the website 270 func NewProvisioningProperties(machineTypesDisplay map[string]string, machineTypes, regions []string, update, modulesEnabled bool) ProvisioningProperties { 271 272 properties := ProvisioningProperties{ 273 UpdateProperties: UpdateProperties{ 274 AutoScalerMin: &Type{ 275 Type: "integer", 276 Minimum: 2, 277 Default: 3, 278 Description: "Specifies the minimum number of virtual machines to create", 279 }, 280 AutoScalerMax: &Type{ 281 Type: "integer", 282 Minimum: 2, 283 Maximum: 80, 284 Default: 20, 285 Description: "Specifies the maximum number of virtual machines to create", 286 }, 287 MachineType: &Type{ 288 Type: "string", 289 Enum: ToInterfaceSlice(machineTypes), 290 EnumDisplayName: machineTypesDisplay, 291 }, 292 }, 293 Name: NameProperty(), 294 Region: &Type{ 295 Type: "string", 296 Enum: ToInterfaceSlice(regions), 297 }, 298 Networking: NewNetworkingSchema(), 299 Modules: NewModulesSchema(modulesEnabled), 300 } 301 302 if update { 303 properties.AutoScalerMax.Default = nil 304 properties.AutoScalerMin.Default = nil 305 } 306 307 return properties 308 } 309 310 func NewNetworkingSchema() *NetworkingType { 311 seedCIDRs := strings.Join(networking.GardenerSeedCIDRs, ", ") 312 return &NetworkingType{ 313 Type: Type{Type: "object", Description: "Networking configuration. These values are immutable and cannot be updated later."}, 314 Properties: NetworkingProperties{ 315 Nodes: Type{Type: "string", Title: "CIDR range for nodes", Description: fmt.Sprintf("CIDR range for nodes, must not overlap with the following CIDRs: %s, %s, %s", networking.DefaultPodsCIDR, networking.DefaultServicesCIDR, seedCIDRs), 316 Default: networking.DefaultNodesCIDR}, 317 }, 318 Required: []string{"nodes"}, 319 } 320 } 321 322 func NewOIDCSchema() *OIDCType { 323 return &OIDCType{ 324 Type: Type{Type: "object", Description: "OIDC configuration"}, 325 Properties: OIDCProperties{ 326 ClientID: Type{Type: "string", Description: "The client ID for the OpenID Connect client."}, 327 IssuerURL: Type{Type: "string", Description: "The URL of the OpenID issuer, only HTTPS scheme will be accepted."}, 328 GroupsClaim: Type{Type: "string", Description: "If provided, the name of a custom OpenID Connect claim for specifying user groups."}, 329 UsernameClaim: Type{Type: "string", Description: "The OpenID claim to use as the user name."}, 330 UsernamePrefix: Type{Type: "string", Description: "If provided, all usernames will be prefixed with this value. If not provided, username claims other than 'email' are prefixed by the issuer URL to avoid clashes. To skip any prefixing, provide the value '-' (dash character without additional characters)."}, 331 SigningAlgs: Type{ 332 Type: "array", 333 Items: &Type{ 334 Type: "string", 335 }, 336 Description: "Comma separated list of allowed JOSE asymmetric signing algorithms, for example, RS256, ES256", 337 }, 338 }, 339 Required: []string{"clientID", "issuerURL"}, 340 } 341 } 342 343 func NewSchema(properties interface{}, update bool, required []string) *RootSchema { 344 schema := &RootSchema{ 345 Schema: "http://json-schema.org/draft-04/schema#", 346 Type: Type{ 347 Type: "object", 348 }, 349 Properties: properties, 350 ShowFormView: true, 351 Required: required, 352 } 353 354 if update { 355 schema.Required = []string{} 356 } 357 358 return schema 359 } 360 361 func unmarshalOrPanic(from, to interface{}) interface{} { 362 if from != nil { 363 marshaled := Marshal(from) 364 err := json.Unmarshal(marshaled, to) 365 if err != nil { 366 panic(err) 367 } 368 } 369 return to 370 } 371 372 func DefaultControlsOrder() []string { 373 return []string{"name", "kubeconfig", "shootName", "shootDomain", "region", "machineType", "autoScalerMin", "autoScalerMax", "zonesCount", "modules", "networking", "oidc", "administrators"} 374 } 375 376 func ToInterfaceSlice(input []string) []interface{} { 377 interfaces := make([]interface{}, len(input)) 378 for i, item := range input { 379 interfaces[i] = item 380 } 381 return interfaces 382 } 383 384 func AdministratorsProperty() *Type { 385 return &Type{ 386 Type: "array", 387 Title: "Administrators", 388 Description: "Specifies the list of runtime administrators", 389 Items: &Type{ 390 Type: "string", 391 }, 392 } 393 }