github.com/codeready-toolchain/api@v0.0.0-20240507023248-73662d6db2c5/api/v1alpha1/toolchainconfig_types.go (about) 1 package v1alpha1 2 3 import ( 4 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 5 ) 6 7 // These are valid conditions of a ToolchainConfig 8 const ( 9 ToolchainConfigSyncComplete ConditionType = "SyncComplete" 10 ToolchainConfigRegServiceDeploy ConditionType = "RegServiceDeploy" 11 12 // Status condition reasons 13 // ToolchainConfigSyncedReason when the MemberOperatorConfigs were successfully synced to the member clusters 14 ToolchainConfigSyncedReason = "Synced" 15 // ToolchainConfigSyncFailedReason when there were failures while syncing MemberOperatorConfigs to the member clusters 16 ToolchainConfigSyncFailedReason = "SyncFailed" 17 // ToolchainConfigRegServiceDeployingReason when the registration service is being deployed 18 ToolchainConfigRegServiceDeployingReason = "Deploying" 19 // ToolchainConfigRegServiceDeployedReason when the registration service has deployed successfully 20 ToolchainConfigRegServiceDeployedReason = "Deployed" 21 // ToolchainConfigRegServiceDeployFailedReason when there were failures while deploying the registration service 22 ToolchainConfigRegServiceDeployFailedReason = "DeployFailed" 23 ) 24 25 // ToolchainConfigSpec contains all configuration for host and member operators 26 // +k8s:openapi-gen=true 27 type ToolchainConfigSpec struct { 28 // Contains all host operator configuration 29 // +optional 30 Host HostConfig `json:"host,omitempty"` 31 32 // Contains all member operator configurations for all member clusters 33 // +optional 34 Members Members `json:"members,omitempty"` 35 } 36 37 // HostConfig contains all configuration parameters of the host operator 38 // +k8s:openapi-gen=true 39 type HostConfig struct { 40 // Environment specifies the host-operator environment such as prod, stage, unit-tests, e2e-tests, dev, etc 41 // +optional 42 Environment *string `json:"environment,omitempty"` 43 44 // Keeps parameters necessary for automatic approval 45 // +optional 46 AutomaticApproval AutomaticApprovalConfig `json:"automaticApproval,omitempty"` 47 48 // Keeps parameters concerned with user deactivation 49 // +optional 50 Deactivation DeactivationConfig `json:"deactivation,omitempty"` 51 52 // Keeps parameters concerned with metrics 53 // +optional 54 Metrics MetricsConfig `json:"metrics,omitempty"` 55 56 // Keeps parameters concerned with notifications 57 // +optional 58 Notifications NotificationsConfig `json:"notifications,omitempty"` 59 60 // Keeps parameters necessary for the registration service 61 // +optional 62 RegistrationService RegistrationServiceConfig `json:"registrationService,omitempty"` 63 64 // Keeps parameters concerned with tiers 65 // +optional 66 Tiers TiersConfig `json:"tiers,omitempty"` 67 68 // Keeps parameters concerned with the toolchainstatus 69 // +optional 70 ToolchainStatus ToolchainStatusConfig `json:"toolchainStatus,omitempty"` 71 72 // Keeps parameters concerned with user management 73 // +optional 74 Users UsersConfig `json:"users,omitempty"` 75 76 // Keeps parameters necessary for configuring Space provisioning functionality 77 // +optional 78 SpaceConfig SpaceConfig `json:"spaceConfig,omitempty"` 79 } 80 81 // Members contains all configuration for member operators 82 // +k8s:openapi-gen=true 83 type Members struct { 84 // Defines default configuration to be applied to all member clusters 85 // +optional 86 Default MemberOperatorConfigSpec `json:"default,omitempty"` 87 88 // A map of cluster-specific member operator configurations indexed by member toolchaincluster name 89 // +optional 90 // +mapType=atomic 91 SpecificPerMemberCluster map[string]MemberOperatorConfigSpec `json:"specificPerMemberCluster,omitempty"` 92 } 93 94 // Defines all parameters necessary for automatic approval 95 // +k8s:openapi-gen=true 96 type AutomaticApprovalConfig struct { 97 // Defines if the automatic approval is enabled or not 98 // +optional 99 Enabled *bool `json:"enabled,omitempty"` 100 101 // Comma-separated email domains to consider for auto-approval. 102 // For example: "domain.com,anotherdomain.org" 103 // If domains is not set and enabled is true, it will default to auto approving all authenticated emails. 104 // If domains is set and enabled is true, it will allow auto approving only for authenticated emails under 105 // the domains entered. If enabled is false domains will be ignored. 106 // +optional 107 Domains *string `json:"domains,omitempty"` 108 } 109 110 // DeactivationConfig contains all configuration parameters related to deactivation 111 // +k8s:openapi-gen=true 112 type DeactivationConfig struct { 113 // DeactivatingNotificationDays is the number of days after a pre-deactivating notification is sent that actual 114 // deactivation occurs. If this parameter is set to zero, then there will be no delay 115 // +optional 116 DeactivatingNotificationDays *int `json:"deactivatingNotificationDays,omitempty"` 117 118 // DeactivationDomainsExcluded is a string of comma-separated domains that should be excluded from automatic user deactivation 119 // For example: "@redhat.com,@ibm.com" 120 // +optional 121 DeactivationDomainsExcluded *string `json:"deactivationDomainsExcluded,omitempty"` 122 123 // UserSignupDeactivatedRetentionDays is used to configure how many days we should keep deactivated UserSignup 124 // resources before deleting them. This parameter value should reflect an extended period of time sufficient for 125 // gathering user metrics before removing the resources from the cluster. 126 // +optional 127 UserSignupDeactivatedRetentionDays *int `json:"userSignupDeactivatedRetentionDays,omitempty"` 128 129 // UserSignupUnverifiedRetentionDays is used to configure how many days we should keep unverified (i.e. the user 130 // hasn't completed the user verification process via the registration service) UserSignup resources before deleting 131 // them. It is intended for this parameter to define an aggressive cleanup schedule for unverified user signups, 132 // and the default configuration value for this parameter reflects this. 133 // +optional 134 UserSignupUnverifiedRetentionDays *int `json:"userSignupUnverifiedRetentionDays,omitempty"` 135 } 136 137 // ToolchainSecret defines a reference to a secret, this type should be included inline in any structs that contain secrets eg. NotificationSecret 138 // +k8s:openapi-gen=true 139 type ToolchainSecret struct { 140 // Reference is the name of the secret resource to look up 141 // +optional 142 Ref *string `json:"ref,omitempty"` 143 } 144 145 // MetricsConfig contains all configuration parameters related to metrics gathering 146 // +k8s:openapi-gen=true 147 type MetricsConfig struct { 148 // ForceSynchronization is a flag used to trigger synchronization of the metrics 149 // based on the resources rather than on the content of `ToolchainStatus.status.metrics` 150 // +optional 151 ForceSynchronization *bool `json:"forceSynchronization,omitempty"` 152 } 153 154 // NotificationsConfig contains all configuration parameters related to notifications 155 // +k8s:openapi-gen=true 156 type NotificationsConfig struct { 157 // NotificationDeliveryService is notification delivery service to use for notifications 158 // +optional 159 NotificationDeliveryService *string `json:"notificationDeliveryService,omitempty"` 160 161 // DurationBeforeNotificationDeletion is notification delivery service to use for notifications 162 // +optional 163 DurationBeforeNotificationDeletion *string `json:"durationBeforeNotificationDeletion,omitempty"` 164 165 // The administrator email address for system notifications 166 // +optional 167 AdminEmail *string `json:"adminEmail,omitempty"` 168 169 // TemplateSetName defines the set of notification templates. Different Sandbox instances can use different notification templates. For example Dev Sandbox and AppStudio instances use different templates. By default, the "sandbox" template set name is used. 170 // +optional 171 TemplateSetName *string `json:"templateSetName,omitempty"` 172 173 // Defines all secrets related to notification configuration 174 // +optional 175 Secret NotificationSecret `json:"secret,omitempty"` 176 } 177 178 // Defines all secrets related to notification configuration 179 // +k8s:openapi-gen=true 180 type NotificationSecret struct { 181 // The reference to the secret that is expected to contain the keys below 182 // +optional 183 ToolchainSecret `json:",inline"` 184 185 // The key for the host operator mailgun domain used for creating an instance of mailgun 186 // +optional 187 MailgunDomain *string `json:"mailgunDomain,omitempty"` 188 189 // The key for the host operator mailgun api key used for creating an instance of mailgun 190 // +optional 191 MailgunAPIKey *string `json:"mailgunAPIKey,omitempty"` 192 193 // The key for the host operator mailgun senders email 194 // +optional 195 MailgunSenderEmail *string `json:"mailgunSenderEmail,omitempty"` 196 197 // The key for the reply-to email address that will be set in sent notifications 198 // +optional 199 MailgunReplyToEmail *string `json:"mailgunReplyToEmail,omitempty"` 200 } 201 202 // RegistrationServiceConfig contains all configuration parameters related to the registration service 203 // +k8s:openapi-gen=true 204 type RegistrationServiceConfig struct { 205 // Keeps parameters necessary for the registration service analytics config 206 // +optional 207 Analytics RegistrationServiceAnalyticsConfig `json:"analytics,omitempty"` 208 209 // Keeps parameters necessary for the registration service authentication config 210 // +optional 211 Auth RegistrationServiceAuthConfig `json:"auth,omitempty"` 212 213 // Environment specifies the environment such as prod, stage, unit-tests, e2e-tests, dev, etc 214 // +optional 215 Environment *string `json:"environment,omitempty"` 216 217 // LogLevel specifies the logging level 218 // +optional 219 LogLevel *string `json:"logLevel,omitempty"` 220 221 // Namespace specifies the namespace in which the registration service and host operator is running 222 // Consumed by host operator and set as env var on registration-service deployment 223 // +optional 224 Namespace *string `json:"namespace,omitempty"` 225 226 // RegistrationServiceURL is the URL used to a ccess the registration service 227 // +optional 228 RegistrationServiceURL *string `json:"registrationServiceURL,omitempty"` 229 230 // Replicas specifies the number of replicas to use for the registration service deployment 231 // +optional 232 Replicas *int32 `json:"replicas,omitempty"` 233 234 // Keeps parameters necessary for the registration service verification config 235 // +optional 236 Verification RegistrationServiceVerificationConfig `json:"verification,omitempty"` 237 } 238 239 // RegistrationServiceAnalyticsConfig contains the subset of registration service configuration parameters related to analytics 240 // +k8s:openapi-gen=true 241 type RegistrationServiceAnalyticsConfig struct { 242 // DevSpaces contains the analytics configuration parameters for devspaces 243 // +optional 244 DevSpaces DevSpaces `json:"devSpaces,omitempty"` 245 246 // SegmentWriteKey specifies the segment write key for sandbox 247 // +optional 248 SegmentWriteKey *string `json:"segmentWriteKey,omitempty"` 249 } 250 251 type DevSpaces struct { 252 // SegmentWriteKey specifies the segment write key 253 // +optional 254 SegmentWriteKey *string `json:"segmentWriteKey,omitempty"` 255 } 256 257 // RegistrationServiceAuthConfig contains the subset of registration service configuration parameters related to authentication 258 // +k8s:openapi-gen=true 259 type RegistrationServiceAuthConfig struct { 260 // AuthClientLibraryURL specifies the auth library location 261 // +optional 262 AuthClientLibraryURL *string `json:"authClientLibraryURL,omitempty"` 263 264 // AuthClientConfigContentType specifies the auth config content type 265 // +optional 266 AuthClientConfigContentType *string `json:"authClientConfigContentType,omitempty"` 267 268 // AuthClientConfigRaw specifies the URL used to access the registration service 269 // +optional 270 AuthClientConfigRaw *string `json:"authClientConfigRaw,omitempty"` 271 272 // AuthClientPublicKeysURL specifies the public keys URL 273 // +optional 274 AuthClientPublicKeysURL *string `json:"authClientPublicKeysURL,omitempty"` 275 276 // SSOBaseURL specifies the SSO base URL such as https://sso.redhat.com 277 // +optional 278 SSOBaseURL *string `json:"ssoBaseURL,omitempty"` 279 280 // SSORealm specifies the SSO realm name 281 // +optional 282 SSORealm *string `json:"ssoRealm,omitempty"` 283 } 284 285 // RegistrationServiceVerificationConfig contains the subset of registration service configuration parameters related to verification 286 // +k8s:openapi-gen=true 287 type RegistrationServiceVerificationConfig struct { 288 // Defines all secrets related to the registration service verification configuration 289 // +optional 290 Secret RegistrationServiceVerificationSecret `json:"secret,omitempty"` 291 292 // VerificationEnabled specifies whether verification is enabled or not 293 // Verification enablement works in the following way: 294 // 1. verification.enabled == false 295 // No verification during the signup process at all. (no phone, no captcha) 296 // 2. verification.enabled == true && verification.captcha.enabled == true 297 // Captcha is enabled and will bypass phone verification if the score is above the threshold but if the score is 298 // below the threshold then phone verification kicks in. 299 // 3. verification.enabled == true && verification.captcha.enabled == false 300 // Only phone verification is effect. 301 // +optional 302 Enabled *bool `json:"enabled,omitempty"` 303 304 // Captcha defines any configuration related to captcha verification 305 // +optional 306 Captcha CaptchaConfig `json:"captcha,omitempty"` 307 308 // VerificationDailyLimit specifies the number of times a user may initiate a phone verification request within a 309 // 24 hour period 310 // +optional 311 DailyLimit *int `json:"dailyLimit,omitempty"` 312 313 // VerificationAttemptsAllowed specifies the number of times a user may attempt to correctly enter a verification code, 314 // if they fail then they must request another code 315 // +optional 316 AttemptsAllowed *int `json:"attemptsAllowed,omitempty"` 317 318 // VerificationMessageTemplate specifies the message template used to generate the content sent to users via SMS for 319 // phone verification 320 // +optional 321 MessageTemplate *string `json:"messageTemplate,omitempty"` 322 323 // VerificationExcludedEmailDomains specifies the list of email address domains for which phone verification 324 // is not required 325 // +optional 326 ExcludedEmailDomains *string `json:"excludedEmailDomains,omitempty"` 327 328 // VerificationCodeExpiresInMin specifies an int representing the number of minutes before a verification code should 329 // be expired 330 // +optional 331 CodeExpiresInMin *int `json:"codeExpiresInMin,omitempty"` 332 333 // NotificationSender is used to specify which service should be used to send verification notifications. Allowed 334 // values are "twilio", "aws". If not specified, the Twilio sender will be used. 335 // +optional 336 NotificationSender *string `json:"notificationSender,omitempty"` 337 338 // AWSRegion to use when sending notification SMS 339 // +optional 340 AWSRegion *string `json:"awsRegion,omitempty"` 341 342 // AWSSenderID the Alphanumeric Sender ID to use, e.g. "DevSandbox" 343 // +optional 344 AWSSenderID *string `json:"awsSenderID,omitempty"` 345 346 // AWSSMSType is the type of SMS message to send, either `Promotional` or `Transactional` 347 // See https://docs.aws.amazon.com/sns/latest/dg/sms_publish-to-phone.html for details 348 // +optional 349 AWSSMSType *string `json:"awsSMSType,omitempty"` 350 351 // TwilioSenderConfigs is an array of TwilioSenderConfig objects 352 // +optional 353 // +listType=atomic 354 TwilioSenderConfigs []TwilioSenderConfig `json:"twilioSenderConfigs,omitempty"` 355 } 356 357 // TwilioSenderConfig is used to associate a particular sender ID (a sender ID is a text value that appears instead of 358 // a phone number when receiving an SMS message), for example "RED HAT", with an array of country 359 // code values for which the Sender ID value will be set via the Twilio API when sending a verification code to a user in 360 // any of the country codes specified. 361 // 362 // Since some countries are starting to block long form phone numbers (i.e. SMS messages from international phone numbers) 363 // the Sender ID may be an acceptable alternative to requiring the verification message to be sent from a local phone number. 364 // 365 // +k8s:openapi-gen=true 366 type TwilioSenderConfig struct { 367 // SenderID 368 SenderID string `json:"senderID"` 369 370 // CountryCodes 371 // +optional 372 // +listType=set 373 CountryCodes []string `json:"countryCodes,omitempty"` 374 } 375 376 // Defines all secrets related to registration service verification configuration 377 // +k8s:openapi-gen=true 378 type RegistrationServiceVerificationSecret struct { 379 // The reference to the secret that is expected to contain the keys below 380 // +optional 381 ToolchainSecret `json:",inline"` 382 383 // TwilioAccountSID specifies the Twilio account identifier, used for sending phone verification messages 384 // +optional 385 TwilioAccountSID *string `json:"twilioAccountSID,omitempty"` 386 387 // TwilioAuthToken specifies the Twilio authentication token, used for sending phone verification messages 388 // +optional 389 TwilioAuthToken *string `json:"twilioAuthToken,omitempty"` 390 391 // TwilioFromNumber specifies the phone number or alphanumeric "Sender ID" for sending phone verification messages 392 // +optional 393 TwilioFromNumber *string `json:"twilioFromNumber,omitempty"` 394 395 // AWSAccessKeyId is the AWS Access Key used to authenticate in order to access AWS services 396 // +optional 397 AWSAccessKeyID *string `json:"awsAccessKeyID,omitempty"` 398 399 // AWSSecretAccessKey is the AWS credential used to authenticate in order to access AWS services 400 // +optional 401 AWSSecretAccessKey *string `json:"awsSecretAccessKey,omitempty"` 402 403 // RecaptchaServiceAccountFile is the GCP service account file contents encoded in base64, it is 404 // to be used with the recaptcha client for authentication 405 // +optional 406 RecaptchaServiceAccountFile *string `json:"recaptchaServiceAccountFile,omitempty"` 407 } 408 409 // CaptchaConfig defines any configuration related to captcha verification 410 // +k8s:openapi-gen=true 411 type CaptchaConfig struct { 412 // Enabled specifies whether the captcha verification feature is enabled or not 413 // +optional 414 Enabled *bool `json:"enabled,omitempty"` 415 416 // ScoreThreshold defines the captcha assessment score threshold. A score equal to or above the threshold means the user is most likely human and 417 // can proceed signing up but a score below the threshold means the score is suspicious and further verification may be required. 418 // +optional 419 ScoreThreshold *string `json:"scoreThreshold,omitempty"` 420 421 // RequiredScore defines the lowest captcha score, below this score the user cannot proceed with the signup process at all. 422 // Users with captcha score lower than the required one can still be approved manually. 423 // +optional 424 RequiredScore *string `json:"requiredScore,omitempty"` 425 426 // AllowLowScoreReactivation specifies whether the reactivation for users with low captcha score (below the RequiredScore) is enabled without the need for manual approval. 427 // +optional 428 AllowLowScoreReactivation *bool `json:"allowLowScoreReactivation,omitempty"` 429 430 // SiteKey defines the recaptcha site key to use when making recaptcha requests. There can be different ones for different environments. eg. dev, stage, prod 431 // +optional 432 SiteKey *string `json:"siteKey,omitempty"` 433 434 // ProjectID defines the GCP project ID that has the recaptcha service enabled. 435 // +optional 436 ProjectID *string `json:"projectID,omitempty"` 437 } 438 439 // ToolchainStatusConfig contains all configuration parameters related to the toolchain status component 440 // +k8s:openapi-gen=true 441 type ToolchainStatusConfig struct { 442 // ToolchainStatusRefreshTime specifies how often the ToolchainStatus should load and refresh the current hosted-toolchain status 443 // +optional 444 ToolchainStatusRefreshTime *string `json:"toolchainStatusRefreshTime,omitempty"` 445 446 // Defines all secrets related to GitHub authentication/integration 447 // +optional 448 GitHubSecret GitHubSecret `json:"gitHubSecret,omitempty"` 449 } 450 451 // TiersConfig contains all configuration parameters related to tiers 452 // +k8s:openapi-gen=true 453 type TiersConfig struct { 454 // DefaultUserTier specifies the default tier to assign for new users 455 // +optional 456 DefaultUserTier *string `json:"defaultUserTier,omitempty"` 457 458 // DefaultSpaceTier specifies the default tier to assign for new spaces 459 // +optional 460 DefaultSpaceTier *string `json:"defaultSpaceTier,omitempty"` 461 462 // DurationBeforeChangeTierRequestDeletion specifies the duration before a ChangeTierRequest resource is deleted 463 // +optional 464 DurationBeforeChangeTierRequestDeletion *string `json:"durationBeforeChangeTierRequestDeletion,omitempty"` 465 466 // TemplateUpdateRequestMaxPoolSize specifies the maximum number of concurrent TemplateUpdateRequests 467 // when updating MasterUserRecords 468 // +optional 469 TemplateUpdateRequestMaxPoolSize *int `json:"templateUpdateRequestMaxPoolSize,omitempty"` 470 } 471 472 // UsersConfig contains all configuration parameters related to users 473 // +k8s:openapi-gen=true 474 type UsersConfig struct { 475 // MasterUserRecordUpdateFailureThreshold specifies the number of allowed failures before stopping attempts to update a MasterUserRecord 476 // +optional 477 MasterUserRecordUpdateFailureThreshold *int `json:"masterUserRecordUpdateFailureThreshold,omitempty"` 478 479 // ForbiddenUsernamePrefixes is a comma-separated string that defines the prefixes that a username may not have when signing up. 480 // If a username has a forbidden prefix, then the username compliance prefix is added to the username 481 // +optional 482 ForbiddenUsernamePrefixes *string `json:"forbiddenUsernamePrefixes,omitempty"` 483 484 // ForbiddenUsernameSuffixes is a comma-separated string that defines the suffixes that a username may not have when signing up. If a 485 // username has a forbidden suffix, then the username compliance suffix is added to the username 486 // +optional 487 ForbiddenUsernameSuffixes *string `json:"forbiddenUsernameSuffixes,omitempty"` 488 } 489 490 // ToolchainConfigStatus defines the observed state of ToolchainConfig 491 // +k8s:openapi-gen=true 492 type ToolchainConfigStatus struct { 493 // SyncErrors is a map of sync errors indexed by toolchaincluster name that indicates whether 494 // an attempt to sync configuration to a member cluster failed 495 // +optional 496 // +mapType=atomic 497 SyncErrors map[string]string `json:"syncErrors,omitempty"` 498 499 // Conditions is an array of the current ToolchainConfig conditions 500 // Supported condition types: ConditionReady 501 // +optional 502 // +patchMergeKey=type 503 // +patchStrategy=merge 504 // +listType=map 505 // +listMapKey=type 506 Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"` 507 } 508 509 // SpaceConfig allows to configure Space provisioning related functionality. 510 // +k8s:openapi-gen=true 511 type SpaceConfig struct { 512 // SpaceRequestEnabled specifies whether the SpaceRequest controller should start or not. 513 // This is specifically useful in order to enable/disable this functionality from configuration (e.g. disabled by default in Sandbox and enabled only for AppStudio stage/prod ...). 514 // +optional 515 SpaceRequestEnabled *bool `json:"spaceRequestEnabled,omitempty"` 516 517 // SpaceBindingRequestEnabled specifies whether the SpaceBindingRequest controller should start or not. 518 // This is specifically useful in order to enable/disable this functionality from configuration (e.g. disabled by default in Sandbox and enabled only for AppStudio stage/prod ...). 519 // +optional 520 SpaceBindingRequestEnabled *bool `json:"spaceBindingRequestEnabled,omitempty"` 521 } 522 523 //+kubebuilder:object:root=true 524 //+kubebuilder:subresource:status 525 526 // ToolchainConfig keeps all configuration parameters needed for host and member operators 527 // +kubebuilder:subresource:status 528 // +kubebuilder:resource:path=toolchainconfigs,scope=Namespaced 529 // +kubebuilder:printcolumn:name="AutomaticApproval",type="boolean",JSONPath=`.spec.host.automaticApproval.enabled` 530 // +kubebuilder:validation:XPreserveUnknownFields 531 // +operator-sdk:gen-csv:customresourcedefinitions.displayName="Toolchain Operator Config" 532 type ToolchainConfig struct { 533 metav1.TypeMeta `json:",inline"` 534 metav1.ObjectMeta `json:"metadata,omitempty"` 535 536 Spec ToolchainConfigSpec `json:"spec,omitempty"` 537 Status ToolchainConfigStatus `json:"status,omitempty"` 538 } 539 540 //+kubebuilder:object:root=true 541 542 // ToolchainConfigList contains a list of ToolchainConfig 543 type ToolchainConfigList struct { 544 metav1.TypeMeta `json:",inline"` 545 metav1.ListMeta `json:"metadata,omitempty"` 546 Items []ToolchainConfig `json:"items"` 547 } 548 549 func init() { 550 SchemeBuilder.Register(&ToolchainConfig{}, &ToolchainConfigList{}) 551 }