Skip to content

Commit ff2c1df

Browse files
RHOAIENG-63118 - Add upgrade tests for Kueue resource management
This commit introduces new tests for validating the upgrade process of Kueue resource flavors and cluster queues. The tests ensure that resource specifications and generation numbers are correctly maintained during upgrades. Key functions include `AddUpgradeResourceBaseline`, `StoreUpgradeBaseline`, and `VerifyUpgradeResourceSpecIntegrity`, which handle the storage and verification of resource specifications in ConfigMaps. Additionally, the tests set up necessary Kueue resources and validate their state before and after the upgrade process, ensuring the integrity of the resource management system. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent f5c3de9 commit ff2c1df

3 files changed

Lines changed: 446 additions & 0 deletions

File tree

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
Copyright 2026.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package support
18+
19+
import (
20+
"encoding/json"
21+
"fmt"
22+
23+
"github.com/onsi/gomega"
24+
25+
corev1 "k8s.io/api/core/v1"
26+
"k8s.io/apimachinery/pkg/api/resource"
27+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28+
kueuev1beta2 "sigs.k8s.io/kueue/apis/kueue/v1beta2"
29+
)
30+
31+
const UpgradeRHOAIVersionKey = "rhoai-version"
32+
33+
func AddUpgradeResourceBaseline(data map[string]string, genKey, specKey string, generation int64, spec interface{}) error {
34+
specJSON, err := json.Marshal(spec)
35+
if err != nil {
36+
return err
37+
}
38+
data[genKey] = fmt.Sprintf("%d", generation)
39+
data[specKey] = string(specJSON)
40+
return nil
41+
}
42+
43+
func StoreUpgradeBaseline(test Test, namespace, configMapName string, data map[string]string) {
44+
test.T().Helper()
45+
46+
data[UpgradeRHOAIVersionKey] = GetRHOAIVersionFromDSCI(test)
47+
configMap := &corev1.ConfigMap{
48+
ObjectMeta: metav1.ObjectMeta{
49+
Name: configMapName,
50+
Namespace: namespace,
51+
},
52+
Data: data,
53+
}
54+
_ = test.Client().Core().CoreV1().ConfigMaps(namespace).Delete(test.Ctx(), configMapName, metav1.DeleteOptions{})
55+
_, err := test.Client().Core().CoreV1().ConfigMaps(namespace).Create(test.Ctx(), configMap, metav1.CreateOptions{})
56+
test.Expect(err).NotTo(gomega.HaveOccurred())
57+
test.T().Logf("Stored upgrade baseline in ConfigMap %s/%s", namespace, configMapName)
58+
}
59+
60+
func VerifyUpgradeResourceSpecIntegrity(test Test, resourceName string, generation int64, spec interface{},
61+
configMap *corev1.ConfigMap, genKey, specKey string) {
62+
test.T().Helper()
63+
64+
expectedGen := configMap.Data[genKey]
65+
actualGen := fmt.Sprintf("%d", generation)
66+
if actualGen != expectedGen {
67+
currentSpecJSON, _ := json.Marshal(spec)
68+
test.T().Logf("%s generation changed during upgrade (%s to %s)", resourceName, expectedGen, actualGen)
69+
test.T().Logf("Pre-upgrade %s spec: %s", resourceName, configMap.Data[specKey])
70+
test.T().Logf("Post-upgrade %s spec: %s", resourceName, currentSpecJSON)
71+
}
72+
test.Expect(actualGen).To(gomega.Equal(expectedGen),
73+
"%s spec should be unchanged after upgrade (generation %s, expected %s)", resourceName, actualGen, expectedGen)
74+
test.T().Logf("%s generation unchanged after upgrade: %s", resourceName, actualGen)
75+
}
76+
77+
func ClusterQueueNominalGPUQuota(clusterQueue *kueuev1beta2.ClusterQueue, gpuResourceLabel string) resource.Quantity {
78+
for _, resourceGroup := range clusterQueue.Spec.ResourceGroups {
79+
for _, flavor := range resourceGroup.Flavors {
80+
for _, quota := range flavor.Resources {
81+
if string(quota.Name) == gpuResourceLabel {
82+
return quota.NominalQuota
83+
}
84+
}
85+
}
86+
}
87+
return resource.Quantity{}
88+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*
2+
Copyright 2026.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package support
18+
19+
import (
20+
"encoding/json"
21+
"testing"
22+
23+
"github.com/onsi/gomega"
24+
25+
corev1 "k8s.io/api/core/v1"
26+
"k8s.io/apimachinery/pkg/api/resource"
27+
kueuev1beta2 "sigs.k8s.io/kueue/apis/kueue/v1beta2"
28+
)
29+
30+
func TestAddUpgradeResourceBaseline(t *testing.T) {
31+
test := NewTest(t)
32+
33+
data := map[string]string{}
34+
spec := kueuev1beta2.ClusterQueueSpec{
35+
ResourceGroups: []kueuev1beta2.ResourceGroup{
36+
{
37+
CoveredResources: []corev1.ResourceName{corev1.ResourceName(NVIDIA.ResourceLabel)},
38+
Flavors: []kueuev1beta2.FlavorQuotas{
39+
{
40+
Resources: []kueuev1beta2.ResourceQuota{
41+
{
42+
Name: corev1.ResourceName(NVIDIA.ResourceLabel),
43+
NominalQuota: resource.MustParse("1"),
44+
},
45+
},
46+
},
47+
},
48+
},
49+
},
50+
}
51+
52+
err := AddUpgradeResourceBaseline(data, "generation-key", "spec-key", 3, spec)
53+
test.Expect(err).NotTo(gomega.HaveOccurred())
54+
test.Expect(data["generation-key"]).To(gomega.Equal("3"))
55+
56+
var restored kueuev1beta2.ClusterQueueSpec
57+
err = json.Unmarshal([]byte(data["spec-key"]), &restored)
58+
test.Expect(err).NotTo(gomega.HaveOccurred())
59+
test.Expect(restored.ResourceGroups).To(gomega.HaveLen(1))
60+
test.Expect(restored.ResourceGroups[0].Flavors[0].Resources[0].NominalQuota).To(gomega.Equal(resource.MustParse("1")))
61+
}
62+
63+
func TestClusterQueueNominalGPUQuota(t *testing.T) {
64+
test := NewTest(t)
65+
66+
clusterQueue := &kueuev1beta2.ClusterQueue{
67+
Spec: kueuev1beta2.ClusterQueueSpec{
68+
ResourceGroups: []kueuev1beta2.ResourceGroup{
69+
{
70+
Flavors: []kueuev1beta2.FlavorQuotas{
71+
{
72+
Resources: []kueuev1beta2.ResourceQuota{
73+
{
74+
Name: corev1.ResourceName(NVIDIA.ResourceLabel),
75+
NominalQuota: resource.MustParse("2"),
76+
},
77+
},
78+
},
79+
},
80+
},
81+
},
82+
},
83+
}
84+
85+
quota := ClusterQueueNominalGPUQuota(clusterQueue, NVIDIA.ResourceLabel)
86+
test.Expect(quota).To(gomega.Equal(resource.MustParse("2")))
87+
test.Expect(ClusterQueueNominalGPUQuota(clusterQueue, "missing")).To(gomega.Equal(resource.Quantity{}))
88+
}
89+
90+
func TestVerifyUpgradeResourceSpecIntegrity(t *testing.T) {
91+
test := NewTest(t)
92+
configMap := &corev1.ConfigMap{
93+
Data: map[string]string{
94+
"gen-key": "5",
95+
"spec-key": `{"nodeLabels":{"nvidia.com/gpu.present":"true"}}`,
96+
UpgradeRHOAIVersionKey: "3.4.0",
97+
},
98+
}
99+
spec := kueuev1beta2.ResourceFlavorSpec{
100+
NodeLabels: map[string]string{
101+
"nvidia.com/gpu.present": "true",
102+
},
103+
}
104+
105+
VerifyUpgradeResourceSpecIntegrity(test, "ResourceFlavor", 5, spec, configMap, "gen-key", "spec-key")
106+
}

0 commit comments

Comments
 (0)