Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions assets/active/descheduler/recommended.yaml.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ spec:
{{- end }}
{{- end }}
evictionLimits:
{{- $migTotal := dig "spec" "liveMigrationConfig" "parallelMigrationsPerCluster" 5 .HCO.Object }}
{{- $migTotal := dig "spec" "virtualization" "liveMigrationConfig" "parallelMigrationsPerCluster" 5 .HCO.Object }}
total: {{ $migTotal }}
{{- $migNode := dig "spec" "liveMigrationConfig" "parallelOutboundMigrationsPerNode" 2 .HCO.Object }}
{{- $migNode := dig "spec" "virtualization" "liveMigrationConfig" "parallelOutboundMigrationsPerNode" 2 .HCO.Object }}
node: {{ $migNode }}
2 changes: 1 addition & 1 deletion assets/active/hco/golden-config.yaml.tpl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
apiVersion: hco.kubevirt.io/v1beta1
apiVersion: hco.kubevirt.io/v1
kind: HyperConverged
metadata:
name: kubevirt-hyperconverged
Expand Down
2 changes: 1 addition & 1 deletion assets/active/kubelet/perf-settings.yaml.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ spec:
# Prevent uneven scheduling based on image count (BZ#1984442)
# according to https://access.redhat.com/articles/6994974
nodeStatusMaxImages: -1
{{- $maxPods := dig "spec" "infra" "nodePlacement" "maxPods" 500 .HCO.Object }}
{{- $maxPods := dig "spec" "deployment" "nodePlacements" "infra" "maxPods" 500 .HCO.Object }}
maxPods: {{ $maxPods }}
# Auto-size kubelet reserved resources (will be OCP default per RFE-8045)
autoSizingReserved: true
Expand Down
2 changes: 1 addition & 1 deletion cmd/csv-generator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ through the existing HyperConverged resource.`,
Required: []CRDDescription{
{
Name: "hyperconvergeds.hco.kubevirt.io",
Version: "v1beta1",
Version: "v1",
Kind: "HyperConverged",
DisplayName: "HyperConverged",
Description: "HyperConverged is the configuration API for the KubeVirt ecosystem.",
Expand Down
2 changes: 1 addition & 1 deletion cmd/render/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ func loadHCOFromCluster(ctx context.Context, kubeconfigPath string) (*unstructur

hcoList := &unstructured.UnstructuredList{}
hcoList.SetGroupVersionKind(pkgcontext.HCOGVK)
hcoList.SetAPIVersion("hco.kubevirt.io/v1beta1")
hcoList.SetAPIVersion("hco.kubevirt.io/v1")

if err := k8sClient.List(ctx, hcoList); err != nil {
return nil, fmt.Errorf("failed to list HCO: %w", err)
Expand Down
5 changes: 3 additions & 2 deletions cmd/render/render_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,15 @@ import (

func TestLoadHCOFromFile(t *testing.T) {
// Create temp HCO file
hcoYAML := `apiVersion: hco.kubevirt.io/v1beta1
hcoYAML := `apiVersion: hco.kubevirt.io/v1
kind: HyperConverged
metadata:
name: kubevirt-hyperconverged
namespace: openshift-cnv
spec:
featureGates:
deployKubeSecondaryDNS: true
- name: deployKubeSecondaryDNS
state: Enabled
`

tmpDir := t.TempDir()
Expand Down
4 changes: 2 additions & 2 deletions pkg/assets/tombstone_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ var _ = Describe("Tombstone Loader", func() {
Describe("TombstoneMetadata", func() {
It("should correctly extract GVK from tombstone object", func() {
obj := &unstructured.Unstructured{}
obj.SetAPIVersion("hco.kubevirt.io/v1beta1")
obj.SetAPIVersion("hco.kubevirt.io/v1")
obj.SetKind("HyperConverged")
obj.SetName("test")
obj.SetLabels(map[string]string{
Expand All @@ -181,7 +181,7 @@ var _ = Describe("Tombstone Loader", func() {
}

Expect(ts.GVK.Group).To(Equal("hco.kubevirt.io"))
Expect(ts.GVK.Version).To(Equal("v1beta1"))
Expect(ts.GVK.Version).To(Equal("v1"))
Expect(ts.GVK.Kind).To(Equal("HyperConverged"))
Expect(ts.Name).To(Equal("test"))
})
Expand Down
2 changes: 1 addition & 1 deletion pkg/context/render_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const (
HCOGroup = "hco.kubevirt.io"

// HCOVersion is the API version for HyperConverged
HCOVersion = "v1beta1"
HCOVersion = "v1"

// HCOKind is the kind for HyperConverged
HCOKind = "HyperConverged"
Expand Down
2 changes: 1 addition & 1 deletion pkg/controller/hco_context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,7 @@ func TestRenderContextBuilder_Build(t *testing.T) {

hco := &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "hco.kubevirt.io/v1beta1",
"apiVersion": "hco.kubevirt.io/v1",
"kind": "HyperConverged",
"metadata": map[string]interface{}{
"name": "test-hco",
Expand Down
17 changes: 13 additions & 4 deletions pkg/controller/platform_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -363,17 +363,26 @@ func (r *PlatformReconciler) updateConditionEvaluator(hco *unstructured.Unstruct
r.conditionEvaluator.Annotations = hco.GetAnnotations()
}

// extractFeatureGates extracts feature gates from HCO spec
// extractFeatureGates extracts feature gates from HCO v1 spec.
// In v1 the field is an array of {name: string, state: "Enabled"|"Disabled"} objects.
func extractFeatureGates(hco *unstructured.Unstructured) map[string]bool {
gates := make(map[string]bool)

featureGates, found, err := unstructured.NestedStringSlice(hco.Object, "spec", "featureGates")
featureGates, found, err := unstructured.NestedSlice(hco.Object, "spec", "featureGates")
if err != nil || !found {
return gates
}

for _, gate := range featureGates {
gates[gate] = true
for _, item := range featureGates {
gate, ok := item.(map[string]any)
if !ok {
continue
}
name, _ := gate["name"].(string)
state, _ := gate["state"].(string)
if name != "" {
gates[name] = (state != "Disabled")
}
}

return gates
Expand Down
70 changes: 51 additions & 19 deletions pkg/controller/platform_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@ func TestExtractFeatureGates(t *testing.T) {
{
name: "with feature gates",
hco: &unstructured.Unstructured{
Object: map[string]interface{}{
"spec": map[string]interface{}{
"featureGates": []interface{}{
"FeatureGate1",
"FeatureGate2",
"ExperimentalFeature",
Object: map[string]any{
"spec": map[string]any{
"featureGates": []any{
map[string]any{"name": "FeatureGate1"},
map[string]any{"name": "FeatureGate2"},
map[string]any{"name": "ExperimentalFeature"},
},
},
},
Expand All @@ -56,12 +56,44 @@ func TestExtractFeatureGates(t *testing.T) {
"ExperimentalFeature": true,
},
},
{
name: "disabled feature gate",
hco: &unstructured.Unstructured{
Object: map[string]any{
"spec": map[string]any{
"featureGates": []any{
map[string]any{"name": "EnabledGate"},
map[string]any{"name": "DisabledGate", "state": "Disabled"},
},
},
},
},
want: map[string]bool{
"EnabledGate": true,
"DisabledGate": false,
},
},
{
name: "feature gate with no state defaults to enabled",
hco: &unstructured.Unstructured{
Object: map[string]any{
"spec": map[string]any{
"featureGates": []any{
map[string]any{"name": "NoStateGate"},
},
},
},
},
want: map[string]bool{
"NoStateGate": true,
},
},
{
name: "empty feature gates",
hco: &unstructured.Unstructured{
Object: map[string]interface{}{
"spec": map[string]interface{}{
"featureGates": []interface{}{},
Object: map[string]any{
"spec": map[string]any{
"featureGates": []any{},
},
},
},
Expand All @@ -70,26 +102,26 @@ func TestExtractFeatureGates(t *testing.T) {
{
name: "no feature gates field",
hco: &unstructured.Unstructured{
Object: map[string]interface{}{
"spec": map[string]interface{}{},
Object: map[string]any{
"spec": map[string]any{},
},
},
want: map[string]bool{},
},
{
name: "no spec field",
hco: &unstructured.Unstructured{
Object: map[string]interface{}{},
Object: map[string]any{},
},
want: map[string]bool{},
},
{
name: "single feature gate",
hco: &unstructured.Unstructured{
Object: map[string]interface{}{
"spec": map[string]interface{}{
"featureGates": []interface{}{
"SingleFeature",
Object: map[string]any{
"spec": map[string]any{
"featureGates": []any{
map[string]any{"name": "SingleFeature"},
},
},
},
Expand Down Expand Up @@ -605,9 +637,9 @@ func TestAssetSelectionWithAutopilotAnnotation(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
hco := &unstructured.Unstructured{
Object: map[string]interface{}{
"metadata": map[string]interface{}{
"annotations": map[string]interface{}{
Object: map[string]any{
"metadata": map[string]any{
"annotations": map[string]any{
overrides.AnnotationAutopilotEnabled: tt.annotationValue,
},
},
Expand Down
2 changes: 1 addition & 1 deletion pkg/debug/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ func (s *Server) handleHealth(w http.ResponseWriter, r *http.Request) {
func (s *Server) getRenderContext(ctx context.Context) (*pkgcontext.RenderContext, error) {
hcoList := &unstructured.UnstructuredList{}
hcoList.SetGroupVersionKind(pkgcontext.HCOGVK)
hcoList.SetAPIVersion("hco.kubevirt.io/v1beta1")
hcoList.SetAPIVersion("hco.kubevirt.io/v1")

if err := s.client.List(ctx, hcoList); err != nil {
return nil, fmt.Errorf("failed to list HCO: %w", err)
Expand Down
8 changes: 4 additions & 4 deletions pkg/engine/renderer_perf_tuning_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func renderHCOAsset(t *testing.T, assetName string) (*unstructured.Unstructured,
renderer := NewRenderer(loader)

hco := &unstructured.Unstructured{}
hco.SetAPIVersion("hco.kubevirt.io/v1beta1")
hco.SetAPIVersion("hco.kubevirt.io/v1")
hco.SetKind("HyperConverged")
hco.SetName("kubevirt-hyperconverged")
hco.SetNamespace("openshift-cnv")
Expand Down Expand Up @@ -72,7 +72,7 @@ func TestHCOGoldenConfigPreservesCertConfig(t *testing.T) {
renderer := NewRenderer(loader)

hco := &unstructured.Unstructured{}
hco.SetAPIVersion("hco.kubevirt.io/v1beta1")
hco.SetAPIVersion("hco.kubevirt.io/v1")
hco.SetKind("HyperConverged")
hco.SetName("kubevirt-hyperconverged")
hco.SetNamespace("openshift-cnv")
Expand Down Expand Up @@ -173,13 +173,13 @@ func TestKubeletPerfSettingsMaxPodsCustom(t *testing.T) {
renderer := NewRenderer(loader)

hco := &unstructured.Unstructured{}
hco.SetAPIVersion("hco.kubevirt.io/v1beta1")
hco.SetAPIVersion("hco.kubevirt.io/v1")
hco.SetKind("HyperConverged")
hco.SetName("kubevirt-hyperconverged")
hco.SetNamespace("openshift-cnv")

// Set custom maxPods
err = unstructured.SetNestedField(hco.Object, int64(250), "spec", "infra", "nodePlacement", "maxPods")
err = unstructured.SetNestedField(hco.Object, int64(250), "spec", "deployment", "nodePlacements", "infra", "maxPods")
if err != nil {
t.Fatalf("Failed to set maxPods in HCO: %v", err)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/engine/tombstone_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ var _ = Describe("Tombstone Reconciler", func() {
hco = &unstructured.Unstructured{}
hco.SetGroupVersionKind(schema.GroupVersionKind{
Group: "hco.kubevirt.io",
Version: "v1beta1",
Version: "v1",
Kind: "HyperConverged",
})
hco.SetName("kubevirt-hyperconverged")
Expand Down
2 changes: 1 addition & 1 deletion pkg/util/crd_checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ func (c *CRDChecker) updateDependencyMetric(crdName string, missing bool) {

// Use a default version for metrics (doesn't affect functionality)
// The actual version doesn't matter for our "is this CRD missing?" metric
version := "v1beta1"
version := "v1"

observability.SetMissingDependency(group, version, kind, missing)
}
Expand Down
14 changes: 8 additions & 6 deletions test/controller_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ var _ = Describe("Platform Controller Integration", func() {

hco := &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "hco.kubevirt.io/v1beta1",
"apiVersion": "hco.kubevirt.io/v1",
"kind": "HyperConverged",
"metadata": map[string]interface{}{
"name": "kubevirt-hyperconverged", // HCO CRD requires this exact name
Expand Down Expand Up @@ -312,16 +312,18 @@ var _ = Describe("Platform Controller Integration", func() {
By("creating an HCO without the managed-by label")
hco := &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "hco.kubevirt.io/v1beta1",
"apiVersion": "hco.kubevirt.io/v1",
"kind": "HyperConverged",
"metadata": map[string]interface{}{
"name": "kubevirt-hyperconverged",
"namespace": testNs,
},
"spec": map[string]interface{}{
"liveMigrationConfig": map[string]interface{}{
"parallelMigrationsPerCluster": 5,
"parallelOutboundMigrationsPerNode": 2,
"virtualization": map[string]interface{}{
"liveMigrationConfig": map[string]interface{}{
"parallelMigrationsPerCluster": 5,
"parallelOutboundMigrationsPerNode": 2,
},
},
},
},
Expand All @@ -333,7 +335,7 @@ var _ = Describe("Platform Controller Integration", func() {
created := &unstructured.Unstructured{}
created.SetGroupVersionKind(schema.GroupVersionKind{
Group: "hco.kubevirt.io",
Version: "v1beta1",
Version: "v1",
Kind: "HyperConverged",
})
Expect(k8sClient.Get(ctx, key, created)).To(Succeed())
Expand Down
18 changes: 11 additions & 7 deletions test/descheduler_crd_versions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,13 @@ var _ = Describe("Descheduler CRD Version Compatibility", func() {

// Create mock HCO with custom eviction limits
hco = pkgcontext.NewMockHCO("kubevirt-hyperconverged", ns.GetName())
// Set custom eviction limits to verify they're extracted correctly
// Set custom eviction limits to verify they're extracted correctly (v1 paths)
hcoSpec := map[string]interface{}{
"liveMigrationConfig": map[string]interface{}{
"parallelMigrationsPerCluster": int64(45),
"parallelOutboundMigrationsPerNode": int64(20),
"virtualization": map[string]interface{}{
"liveMigrationConfig": map[string]interface{}{
"parallelMigrationsPerCluster": int64(45),
"parallelOutboundMigrationsPerNode": int64(20),
},
},
}
hco.Object["spec"] = hcoSpec
Expand Down Expand Up @@ -265,9 +267,11 @@ var _ = Describe("Descheduler CRD Version Compatibility", func() {
// Create HCO with only total limit set
partialHCO := pkgcontext.NewMockHCO("test-hco", ns.GetName())
partialHCO.Object["spec"] = map[string]interface{}{
"liveMigrationConfig": map[string]interface{}{
"parallelMigrationsPerCluster": int64(100),
// parallelOutboundMigrationsPerNode omitted
"virtualization": map[string]interface{}{
"liveMigrationConfig": map[string]interface{}{
"parallelMigrationsPerCluster": int64(100),
// parallelOutboundMigrationsPerNode omitted
},
},
}
partialHCO.SetAnnotations(map[string]string{
Expand Down
Loading