From 81d3cf276e673acb3e8954634a5935c30707e845 Mon Sep 17 00:00:00 2001 From: Daniil Loktev Date: Tue, 2 Sep 2025 15:57:36 +0300 Subject: [PATCH 1/9] wip Signed-off-by: Daniil Loktev --- .../validator/spec_changes_validator.go | 51 +++++++++++++++++++ .../pkg/controller/vi/vi_webhook.go | 20 ++++++++ 2 files changed, 71 insertions(+) diff --git a/images/virtualization-artifact/pkg/controller/vd/internal/validator/spec_changes_validator.go b/images/virtualization-artifact/pkg/controller/vd/internal/validator/spec_changes_validator.go index 300737d25b..d2c6a59d9f 100644 --- a/images/virtualization-artifact/pkg/controller/vd/internal/validator/spec_changes_validator.go +++ b/images/virtualization-artifact/pkg/controller/vd/internal/validator/spec_changes_validator.go @@ -56,6 +56,31 @@ func (v *SpecChangesValidator) ValidateCreate(ctx context.Context, newVD *virtv2 *newVD.Spec.PersistentVolumeClaim.StorageClass, ) } + if !v.scService.IsStorageClassAllowed(*newVD.Spec.PersistentVolumeClaim.StorageClass) { + return nil, fmt.Errorf( + "the storage class %q is not allowed; please check the module settings", + *newVD.Spec.PersistentVolumeClaim.StorageClass, + ) + } + } else { + mcDefaultStorageClass, err := v.scService.GetModuleStorageClass(ctx) + if err != nil && !errors.Is(err, intsvc.ErrStorageClassNotFound) { + return nil, fmt.Errorf("failed to fetch a default storage class from module config: %w", err) + } + + if mcDefaultStorageClass == nil { + defaultStorageClass, err := v.scService.GetDefaultStorageClass(ctx) + if err != nil && !errors.Is(err, intsvc.ErrStorageClassNotFound) { + return nil, fmt.Errorf("failed to fetch default storage class: %w", err) + } + + if defaultStorageClass != nil && !v.scService.IsStorageClassAllowed(defaultStorageClass.Name) { + return nil, fmt.Errorf( + "the default storage class %q is not allowed; please check the module settings or specify a storage class name explicitly in the spec", + defaultStorageClass.Name, + ) + } + } } return nil, nil @@ -92,6 +117,32 @@ func (v *SpecChangesValidator) ValidateUpdate(ctx context.Context, oldVD, newVD *newVD.Spec.PersistentVolumeClaim.StorageClass, ) } + if !v.scService.IsStorageClassAllowed(*newVD.Spec.PersistentVolumeClaim.StorageClass) { + return nil, fmt.Errorf( + "the storage class %q is not allowed; please check the module settings", + *newVD.Spec.PersistentVolumeClaim.StorageClass, + ) + } + } else { + // Check if default storage class is allowed when no storage class is specified + mcDefaultStorageClass, err := v.scService.GetModuleStorageClass(ctx) + if err != nil && !errors.Is(err, intsvc.ErrStorageClassNotFound) { + return nil, fmt.Errorf("failed to fetch a default storage class from module config: %w", err) + } + + if mcDefaultStorageClass == nil { + defaultStorageClass, err := v.scService.GetDefaultStorageClass(ctx) + if err != nil && !errors.Is(err, intsvc.ErrStorageClassNotFound) { + return nil, fmt.Errorf("failed to fetch default storage class: %w", err) + } + + if defaultStorageClass != nil && !v.scService.IsStorageClassAllowed(defaultStorageClass.Name) { + return nil, fmt.Errorf( + "the default storage class %q is not allowed; please check the module settings or specify a storage class name explicitly in the spec", + defaultStorageClass.Name, + ) + } + } } } diff --git a/images/virtualization-artifact/pkg/controller/vi/vi_webhook.go b/images/virtualization-artifact/pkg/controller/vi/vi_webhook.go index feae28f1b5..1d0f00159e 100644 --- a/images/virtualization-artifact/pkg/controller/vi/vi_webhook.go +++ b/images/virtualization-artifact/pkg/controller/vi/vi_webhook.go @@ -86,6 +86,13 @@ func (v *Validator) ValidateCreate(ctx context.Context, obj runtime.Object) (adm ) } + if !v.scService.IsStorageClassAllowed(*vi.Spec.PersistentVolumeClaim.StorageClass) { + return nil, fmt.Errorf( + "the storage class %q is not allowed; please check the module settings", + *vi.Spec.PersistentVolumeClaim.StorageClass, + ) + } + if sc != nil { sp, err := v.scService.GetStorageProfile(ctx, sc.Name) if err != nil { @@ -157,6 +164,13 @@ func (v *Validator) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.O ) } + if !v.scService.IsStorageClassAllowed(*newVI.Spec.PersistentVolumeClaim.StorageClass) { + return nil, fmt.Errorf( + "the storage class %q is not allowed; please check the module settings", + *newVI.Spec.PersistentVolumeClaim.StorageClass, + ) + } + if sc != nil { sp, err := v.scService.GetStorageProfile(ctx, sc.Name) if err != nil { @@ -213,6 +227,12 @@ func (v *Validator) validateDefaultStorageClass(ctx context.Context) error { if defaultStorageClass != nil { sc = defaultStorageClass + if !v.scService.IsStorageClassAllowed(sc.Name) { + return fmt.Errorf( + "the default storage class %q is not allowed; please check the module settings or specify a storage class name explicitly in the spec", + sc.Name, + ) + } } } From 687fb6e10073ada3378a58ec14aa8446f2c2210c Mon Sep 17 00:00:00 2001 From: Daniil Loktev Date: Tue, 2 Sep 2025 16:21:24 +0300 Subject: [PATCH 2/9] wip Signed-off-by: Daniil Loktev --- .../validator/spec_changes_validator.go | 49 ++++++++++--------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/images/virtualization-artifact/pkg/controller/vd/internal/validator/spec_changes_validator.go b/images/virtualization-artifact/pkg/controller/vd/internal/validator/spec_changes_validator.go index d2c6a59d9f..b536eef5f1 100644 --- a/images/virtualization-artifact/pkg/controller/vd/internal/validator/spec_changes_validator.go +++ b/images/virtualization-artifact/pkg/controller/vd/internal/validator/spec_changes_validator.go @@ -67,19 +67,20 @@ func (v *SpecChangesValidator) ValidateCreate(ctx context.Context, newVD *virtv2 if err != nil && !errors.Is(err, intsvc.ErrStorageClassNotFound) { return nil, fmt.Errorf("failed to fetch a default storage class from module config: %w", err) } + if mcDefaultStorageClass != nil { + return nil, nil + } - if mcDefaultStorageClass == nil { - defaultStorageClass, err := v.scService.GetDefaultStorageClass(ctx) - if err != nil && !errors.Is(err, intsvc.ErrStorageClassNotFound) { - return nil, fmt.Errorf("failed to fetch default storage class: %w", err) - } + defaultStorageClass, err := v.scService.GetDefaultStorageClass(ctx) + if err != nil && !errors.Is(err, intsvc.ErrStorageClassNotFound) { + return nil, fmt.Errorf("failed to fetch default storage class: %w", err) + } - if defaultStorageClass != nil && !v.scService.IsStorageClassAllowed(defaultStorageClass.Name) { - return nil, fmt.Errorf( - "the default storage class %q is not allowed; please check the module settings or specify a storage class name explicitly in the spec", - defaultStorageClass.Name, - ) - } + if defaultStorageClass != nil && !v.scService.IsStorageClassAllowed(defaultStorageClass.Name) { + return nil, fmt.Errorf( + "the default storage class %q is not allowed; please check the module settings or specify a storage class name explicitly in the spec", + defaultStorageClass.Name, + ) } } @@ -124,24 +125,24 @@ func (v *SpecChangesValidator) ValidateUpdate(ctx context.Context, oldVD, newVD ) } } else { - // Check if default storage class is allowed when no storage class is specified mcDefaultStorageClass, err := v.scService.GetModuleStorageClass(ctx) if err != nil && !errors.Is(err, intsvc.ErrStorageClassNotFound) { return nil, fmt.Errorf("failed to fetch a default storage class from module config: %w", err) } + if mcDefaultStorageClass != nil { + return nil, nil + } - if mcDefaultStorageClass == nil { - defaultStorageClass, err := v.scService.GetDefaultStorageClass(ctx) - if err != nil && !errors.Is(err, intsvc.ErrStorageClassNotFound) { - return nil, fmt.Errorf("failed to fetch default storage class: %w", err) - } - - if defaultStorageClass != nil && !v.scService.IsStorageClassAllowed(defaultStorageClass.Name) { - return nil, fmt.Errorf( - "the default storage class %q is not allowed; please check the module settings or specify a storage class name explicitly in the spec", - defaultStorageClass.Name, - ) - } + defaultStorageClass, err := v.scService.GetDefaultStorageClass(ctx) + if err != nil && !errors.Is(err, intsvc.ErrStorageClassNotFound) { + return nil, fmt.Errorf("failed to fetch default storage class: %w", err) + } + + if defaultStorageClass != nil && !v.scService.IsStorageClassAllowed(defaultStorageClass.Name) { + return nil, fmt.Errorf( + "the default storage class %q is not allowed; please check the module settings or specify a storage class name explicitly in the spec", + defaultStorageClass.Name, + ) } } } From 6d4c369ed46f9862ca9bd00d109bce002a8d8572 Mon Sep 17 00:00:00 2001 From: Daniil Loktev Date: Thu, 4 Sep 2025 17:01:41 +0300 Subject: [PATCH 3/9] wip Signed-off-by: Daniil Loktev --- .../validator/spec_changes_validator.go | 58 +------------------ .../pkg/controller/vi/vi_webhook.go | 13 ----- openapi/config-values.yaml | 2 + 3 files changed, 5 insertions(+), 68 deletions(-) diff --git a/images/virtualization-artifact/pkg/controller/vd/internal/validator/spec_changes_validator.go b/images/virtualization-artifact/pkg/controller/vd/internal/validator/spec_changes_validator.go index b536eef5f1..59e6c0145c 100644 --- a/images/virtualization-artifact/pkg/controller/vd/internal/validator/spec_changes_validator.go +++ b/images/virtualization-artifact/pkg/controller/vd/internal/validator/spec_changes_validator.go @@ -27,17 +27,17 @@ import ( "sigs.k8s.io/controller-runtime/pkg/webhook/admission" "github.com/deckhouse/virtualization-controller/pkg/controller/conditions" - intsvc "github.com/deckhouse/virtualization-controller/pkg/controller/vd/internal/service" + "github.com/deckhouse/virtualization-controller/pkg/controller/vd/internal/service" virtv2 "github.com/deckhouse/virtualization/api/core/v1alpha2" "github.com/deckhouse/virtualization/api/core/v1alpha2/vdcondition" ) type SpecChangesValidator struct { client client.Client - scService *intsvc.VirtualDiskStorageClassService + scService *service.VirtualDiskStorageClassService } -func NewSpecChangesValidator(client client.Client, scService *intsvc.VirtualDiskStorageClassService) *SpecChangesValidator { +func NewSpecChangesValidator(client client.Client, scService *service.VirtualDiskStorageClassService) *SpecChangesValidator { return &SpecChangesValidator{ client: client, scService: scService, @@ -56,32 +56,6 @@ func (v *SpecChangesValidator) ValidateCreate(ctx context.Context, newVD *virtv2 *newVD.Spec.PersistentVolumeClaim.StorageClass, ) } - if !v.scService.IsStorageClassAllowed(*newVD.Spec.PersistentVolumeClaim.StorageClass) { - return nil, fmt.Errorf( - "the storage class %q is not allowed; please check the module settings", - *newVD.Spec.PersistentVolumeClaim.StorageClass, - ) - } - } else { - mcDefaultStorageClass, err := v.scService.GetModuleStorageClass(ctx) - if err != nil && !errors.Is(err, intsvc.ErrStorageClassNotFound) { - return nil, fmt.Errorf("failed to fetch a default storage class from module config: %w", err) - } - if mcDefaultStorageClass != nil { - return nil, nil - } - - defaultStorageClass, err := v.scService.GetDefaultStorageClass(ctx) - if err != nil && !errors.Is(err, intsvc.ErrStorageClassNotFound) { - return nil, fmt.Errorf("failed to fetch default storage class: %w", err) - } - - if defaultStorageClass != nil && !v.scService.IsStorageClassAllowed(defaultStorageClass.Name) { - return nil, fmt.Errorf( - "the default storage class %q is not allowed; please check the module settings or specify a storage class name explicitly in the spec", - defaultStorageClass.Name, - ) - } } return nil, nil @@ -118,32 +92,6 @@ func (v *SpecChangesValidator) ValidateUpdate(ctx context.Context, oldVD, newVD *newVD.Spec.PersistentVolumeClaim.StorageClass, ) } - if !v.scService.IsStorageClassAllowed(*newVD.Spec.PersistentVolumeClaim.StorageClass) { - return nil, fmt.Errorf( - "the storage class %q is not allowed; please check the module settings", - *newVD.Spec.PersistentVolumeClaim.StorageClass, - ) - } - } else { - mcDefaultStorageClass, err := v.scService.GetModuleStorageClass(ctx) - if err != nil && !errors.Is(err, intsvc.ErrStorageClassNotFound) { - return nil, fmt.Errorf("failed to fetch a default storage class from module config: %w", err) - } - if mcDefaultStorageClass != nil { - return nil, nil - } - - defaultStorageClass, err := v.scService.GetDefaultStorageClass(ctx) - if err != nil && !errors.Is(err, intsvc.ErrStorageClassNotFound) { - return nil, fmt.Errorf("failed to fetch default storage class: %w", err) - } - - if defaultStorageClass != nil && !v.scService.IsStorageClassAllowed(defaultStorageClass.Name) { - return nil, fmt.Errorf( - "the default storage class %q is not allowed; please check the module settings or specify a storage class name explicitly in the spec", - defaultStorageClass.Name, - ) - } } } diff --git a/images/virtualization-artifact/pkg/controller/vi/vi_webhook.go b/images/virtualization-artifact/pkg/controller/vi/vi_webhook.go index 1d0f00159e..acfccad993 100644 --- a/images/virtualization-artifact/pkg/controller/vi/vi_webhook.go +++ b/images/virtualization-artifact/pkg/controller/vi/vi_webhook.go @@ -86,13 +86,6 @@ func (v *Validator) ValidateCreate(ctx context.Context, obj runtime.Object) (adm ) } - if !v.scService.IsStorageClassAllowed(*vi.Spec.PersistentVolumeClaim.StorageClass) { - return nil, fmt.Errorf( - "the storage class %q is not allowed; please check the module settings", - *vi.Spec.PersistentVolumeClaim.StorageClass, - ) - } - if sc != nil { sp, err := v.scService.GetStorageProfile(ctx, sc.Name) if err != nil { @@ -227,12 +220,6 @@ func (v *Validator) validateDefaultStorageClass(ctx context.Context) error { if defaultStorageClass != nil { sc = defaultStorageClass - if !v.scService.IsStorageClassAllowed(sc.Name) { - return fmt.Errorf( - "the default storage class %q is not allowed; please check the module settings or specify a storage class name explicitly in the spec", - sc.Name, - ) - } } } diff --git a/openapi/config-values.yaml b/openapi/config-values.yaml index bfe927b4d3..c3c6b2b19c 100644 --- a/openapi/config-values.yaml +++ b/openapi/config-values.yaml @@ -213,6 +213,7 @@ properties: type: array items: type: string + minLength: 1 x-examples: ["sc-1", "sc-2"] virtualDisks: type: object @@ -232,6 +233,7 @@ properties: type: array items: type: string + minLength: 1 x-examples: ["sc-1", "sc-2"] logLevel: type: string From 0b6c18f45c557a078a9965f428289037f33b3ff5 Mon Sep 17 00:00:00 2001 From: Daniil Loktev Date: Thu, 4 Sep 2025 17:04:56 +0300 Subject: [PATCH 4/9] wip Signed-off-by: Daniil Loktev --- .../vd/internal/validator/spec_changes_validator.go | 6 +++--- .../pkg/controller/vi/vi_webhook.go | 7 ------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/images/virtualization-artifact/pkg/controller/vd/internal/validator/spec_changes_validator.go b/images/virtualization-artifact/pkg/controller/vd/internal/validator/spec_changes_validator.go index 59e6c0145c..300737d25b 100644 --- a/images/virtualization-artifact/pkg/controller/vd/internal/validator/spec_changes_validator.go +++ b/images/virtualization-artifact/pkg/controller/vd/internal/validator/spec_changes_validator.go @@ -27,17 +27,17 @@ import ( "sigs.k8s.io/controller-runtime/pkg/webhook/admission" "github.com/deckhouse/virtualization-controller/pkg/controller/conditions" - "github.com/deckhouse/virtualization-controller/pkg/controller/vd/internal/service" + intsvc "github.com/deckhouse/virtualization-controller/pkg/controller/vd/internal/service" virtv2 "github.com/deckhouse/virtualization/api/core/v1alpha2" "github.com/deckhouse/virtualization/api/core/v1alpha2/vdcondition" ) type SpecChangesValidator struct { client client.Client - scService *service.VirtualDiskStorageClassService + scService *intsvc.VirtualDiskStorageClassService } -func NewSpecChangesValidator(client client.Client, scService *service.VirtualDiskStorageClassService) *SpecChangesValidator { +func NewSpecChangesValidator(client client.Client, scService *intsvc.VirtualDiskStorageClassService) *SpecChangesValidator { return &SpecChangesValidator{ client: client, scService: scService, diff --git a/images/virtualization-artifact/pkg/controller/vi/vi_webhook.go b/images/virtualization-artifact/pkg/controller/vi/vi_webhook.go index acfccad993..feae28f1b5 100644 --- a/images/virtualization-artifact/pkg/controller/vi/vi_webhook.go +++ b/images/virtualization-artifact/pkg/controller/vi/vi_webhook.go @@ -157,13 +157,6 @@ func (v *Validator) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.O ) } - if !v.scService.IsStorageClassAllowed(*newVI.Spec.PersistentVolumeClaim.StorageClass) { - return nil, fmt.Errorf( - "the storage class %q is not allowed; please check the module settings", - *newVI.Spec.PersistentVolumeClaim.StorageClass, - ) - } - if sc != nil { sp, err := v.scService.GetStorageProfile(ctx, sc.Name) if err != nil { From 5f476542348be6525251162478426272e3e3a1f7 Mon Sep 17 00:00:00 2001 From: Daniil Loktev Date: Thu, 4 Sep 2025 17:24:16 +0300 Subject: [PATCH 5/9] wip Signed-off-by: Daniil Loktev --- .../cmd/virtualization-controller/main.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/images/virtualization-artifact/cmd/virtualization-controller/main.go b/images/virtualization-artifact/cmd/virtualization-controller/main.go index 3609029a02..82601946b2 100644 --- a/images/virtualization-artifact/cmd/virtualization-controller/main.go +++ b/images/virtualization-artifact/cmd/virtualization-controller/main.go @@ -189,6 +189,15 @@ func main() { viStorageClassSettings := appconfig.LoadVirtualImageStorageClassSettings() vdStorageClassSettings := appconfig.LoadVirtualDiskStorageClassSettings() + if vdAllowed, exists := os.LookupEnv(appconfig.VirtualDiskAllowedStorageClasses); exists && vdAllowed == "" { + log.Error("%s is empty. Specify valid StorageClass names or remove the restriction.", appconfig.VirtualDiskAllowedStorageClasses) + os.Exit(1) + } + if viAllowed, exists := os.LookupEnv(appconfig.VirtualImageAllowedStorageClasses); exists && viAllowed == "" { + log.Error("%s is empty. Specify valid StorageClass names or remove the restriction.", appconfig.VirtualImageAllowedStorageClasses) + os.Exit(1) + } + // Get a config to talk to the apiserver cfg, err := config.GetConfig() if err != nil { From 5d36394eabd1f928e7e8cf4287eae91cdf358567 Mon Sep 17 00:00:00 2001 From: Daniil Loktev Date: Thu, 4 Sep 2025 17:47:03 +0300 Subject: [PATCH 6/9] wip Signed-off-by: Daniil Loktev --- .../cmd/virtualization-controller/main.go | 16 +++++++++------- .../pkg/config/load_vd_storage_class_settings.go | 10 +++++++--- .../pkg/config/load_vi_storage_class_settings.go | 10 +++++++--- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/images/virtualization-artifact/cmd/virtualization-controller/main.go b/images/virtualization-artifact/cmd/virtualization-controller/main.go index 82601946b2..f08bd85fdd 100644 --- a/images/virtualization-artifact/cmd/virtualization-controller/main.go +++ b/images/virtualization-artifact/cmd/virtualization-controller/main.go @@ -186,15 +186,17 @@ func main() { os.Exit(1) } - viStorageClassSettings := appconfig.LoadVirtualImageStorageClassSettings() - vdStorageClassSettings := appconfig.LoadVirtualDiskStorageClassSettings() - - if vdAllowed, exists := os.LookupEnv(appconfig.VirtualDiskAllowedStorageClasses); exists && vdAllowed == "" { - log.Error("%s is empty. Specify valid StorageClass names or remove the restriction.", appconfig.VirtualDiskAllowedStorageClasses) + _, exists := os.LookupEnv(appconfig.VirtualDiskAllowedStorageClasses) + log.Error("test: %v", exists) + viStorageClassSettings, err := appconfig.LoadVirtualImageStorageClassSettings() + if err != nil { + log.Error(err.Error()) os.Exit(1) } - if viAllowed, exists := os.LookupEnv(appconfig.VirtualImageAllowedStorageClasses); exists && viAllowed == "" { - log.Error("%s is empty. Specify valid StorageClass names or remove the restriction.", appconfig.VirtualImageAllowedStorageClasses) + + vdStorageClassSettings, err := appconfig.LoadVirtualDiskStorageClassSettings() + if err != nil { + log.Error(err.Error()) os.Exit(1) } diff --git a/images/virtualization-artifact/pkg/config/load_vd_storage_class_settings.go b/images/virtualization-artifact/pkg/config/load_vd_storage_class_settings.go index b6d7691956..7837785e7c 100644 --- a/images/virtualization-artifact/pkg/config/load_vd_storage_class_settings.go +++ b/images/virtualization-artifact/pkg/config/load_vd_storage_class_settings.go @@ -17,6 +17,7 @@ limitations under the License. package config import ( + "fmt" "os" "strings" ) @@ -33,9 +34,12 @@ type VirtualDiskStorageClassSettings struct { DefaultStorageClassName string } -func LoadVirtualDiskStorageClassSettings() VirtualDiskStorageClassSettings { +func LoadVirtualDiskStorageClassSettings() (VirtualDiskStorageClassSettings, error) { var allowedStorageClassNames []string - allowedStorageClassNamesRaw := os.Getenv(VirtualDiskAllowedStorageClasses) + allowedStorageClassNamesRaw, exists := os.LookupEnv(VirtualDiskAllowedStorageClasses) + if exists && allowedStorageClassNamesRaw == "" { + return VirtualDiskStorageClassSettings{}, fmt.Errorf("%s is empty. Specify valid StorageClass names or remove the restriction", VirtualDiskAllowedStorageClasses) + } if allowedStorageClassNamesRaw != "" { allowedStorageClassNames = strings.Split(allowedStorageClassNamesRaw, ",") } @@ -43,5 +47,5 @@ func LoadVirtualDiskStorageClassSettings() VirtualDiskStorageClassSettings { return VirtualDiskStorageClassSettings{ AllowedStorageClassNames: allowedStorageClassNames, DefaultStorageClassName: os.Getenv(VirtualDiskDefaultStorageClass), - } + }, nil } diff --git a/images/virtualization-artifact/pkg/config/load_vi_storage_class_settings.go b/images/virtualization-artifact/pkg/config/load_vi_storage_class_settings.go index d8fed5ea56..b38af47352 100644 --- a/images/virtualization-artifact/pkg/config/load_vi_storage_class_settings.go +++ b/images/virtualization-artifact/pkg/config/load_vi_storage_class_settings.go @@ -17,6 +17,7 @@ limitations under the License. package config import ( + "fmt" "os" "strings" ) @@ -36,9 +37,12 @@ type VirtualImageStorageClassSettings struct { StorageClassName string } -func LoadVirtualImageStorageClassSettings() VirtualImageStorageClassSettings { +func LoadVirtualImageStorageClassSettings() (VirtualImageStorageClassSettings, error) { var allowedStorageClassNames []string - allowedStorageClassNamesRaw := os.Getenv(VirtualImageAllowedStorageClasses) + allowedStorageClassNamesRaw, exists := os.LookupEnv(VirtualImageAllowedStorageClasses) + if exists && allowedStorageClassNamesRaw == "" { + return VirtualImageStorageClassSettings{}, fmt.Errorf("%s is empty. Specify valid StorageClass names or remove the restriction", VirtualImageAllowedStorageClasses) + } if allowedStorageClassNamesRaw != "" { allowedStorageClassNames = strings.Split(allowedStorageClassNamesRaw, ",") } @@ -47,5 +51,5 @@ func LoadVirtualImageStorageClassSettings() VirtualImageStorageClassSettings { AllowedStorageClassNames: allowedStorageClassNames, DefaultStorageClassName: os.Getenv(VirtualImageDefaultStorageClass), StorageClassName: os.Getenv(VirtualImageStorageClass), - } + }, nil } From 8c0bb5865f7aba52181969c7ce731b992885a6ef Mon Sep 17 00:00:00 2001 From: Daniil Loktev Date: Thu, 4 Sep 2025 18:02:51 +0300 Subject: [PATCH 7/9] wip Signed-off-by: Daniil Loktev --- .../cmd/virtualization-controller/main.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/images/virtualization-artifact/cmd/virtualization-controller/main.go b/images/virtualization-artifact/cmd/virtualization-controller/main.go index f08bd85fdd..5858a2b8c7 100644 --- a/images/virtualization-artifact/cmd/virtualization-controller/main.go +++ b/images/virtualization-artifact/cmd/virtualization-controller/main.go @@ -186,8 +186,6 @@ func main() { os.Exit(1) } - _, exists := os.LookupEnv(appconfig.VirtualDiskAllowedStorageClasses) - log.Error("test: %v", exists) viStorageClassSettings, err := appconfig.LoadVirtualImageStorageClassSettings() if err != nil { log.Error(err.Error()) From 7c85b6939838e0740c9ea4e305ab1957bb40c81a Mon Sep 17 00:00:00 2001 From: Daniil Loktev Date: Fri, 5 Sep 2025 08:12:47 +0300 Subject: [PATCH 8/9] wip Signed-off-by: Daniil Loktev --- openapi/doc-ru-config-values.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openapi/doc-ru-config-values.yaml b/openapi/doc-ru-config-values.yaml index 3d9f0f02b2..92c964dabf 100644 --- a/openapi/doc-ru-config-values.yaml +++ b/openapi/doc-ru-config-values.yaml @@ -114,6 +114,7 @@ properties: type: array items: type: string + minLength: 1 virtualDisks: type: object description: | @@ -132,6 +133,7 @@ properties: type: array items: type: string + minLength: 1 audit: type: object description: | From c3484729d9cc96caa60c85244b5123cd678d42fb Mon Sep 17 00:00:00 2001 From: Daniil Loktev Date: Wed, 10 Sep 2025 11:19:50 +0300 Subject: [PATCH 9/9] wip Signed-off-by: Daniil Loktev --- openapi/config-values.yaml | 4 ++++ openapi/doc-ru-config-values.yaml | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/openapi/config-values.yaml b/openapi/config-values.yaml index c3c6b2b19c..5cf5baae25 100644 --- a/openapi/config-values.yaml +++ b/openapi/config-values.yaml @@ -208,9 +208,11 @@ properties: type: object description: | Selector for allowed storage classes to be used for virtual images on PVC. + minProperties: 1 properties: matchNames: type: array + minItems: 1 items: type: string minLength: 1 @@ -228,9 +230,11 @@ properties: type: object description: | Selector for allowed storage classes to be used for virtual disks. + minProperties: 1 properties: matchNames: type: array + minItems: 1 items: type: string minLength: 1 diff --git a/openapi/doc-ru-config-values.yaml b/openapi/doc-ru-config-values.yaml index 92c964dabf..041db60763 100644 --- a/openapi/doc-ru-config-values.yaml +++ b/openapi/doc-ru-config-values.yaml @@ -109,9 +109,11 @@ properties: type: object description: | Селектор разрешенных классов хранения, которые можно использовать для виртуальных образов на PVC. + minProperties: 1 properties: matchNames: type: array + minItems: 1 items: type: string minLength: 1 @@ -128,9 +130,11 @@ properties: type: object description: | Селектор разрешенных классов хранения, используемых для виртуальных дисков. + minProperties: 1 properties: matchNames: type: array + minItems: 1 items: type: string minLength: 1