@@ -931,6 +931,311 @@ func TestDeployParam(t *testing.T) {
931931 assert .Equal (t , "5" , appInstance .Status .AppSpec .Containers ["foo" ].Environment [0 ].Value )
932932}
933933
934+ func TestMultipleDefaultComputeClass (t * testing.T ) {
935+ helper .StartController (t )
936+ cfg := helper .StartAPI (t )
937+ project := helper .TempProjectWithRegions (t , helper .MustReturn (kclient .Default ), []string {apiv1 .LocalRegion , "local2" })
938+ kclient := helper .MustReturn (kclient .Default )
939+ c , err := client .New (cfg , "" , project .Name )
940+ if err != nil {
941+ t .Fatal (err )
942+ }
943+
944+ ctx := helper .GetCTX (t )
945+
946+ checks := []struct {
947+ name string
948+ noComputeClass bool
949+ testDataDirectory string
950+ region string
951+ computeClasses []adminv1.ProjectComputeClassInstance
952+ expected map [string ]v1.Scheduling
953+ waitFor func (obj * v1.AppInstance ) bool
954+ fail bool
955+ }{
956+ {
957+ name : "local-default" ,
958+ testDataDirectory : "./testdata/simple" ,
959+ region : apiv1 .LocalRegion ,
960+ computeClasses : []adminv1.ProjectComputeClassInstance {
961+ {
962+ ObjectMeta : metav1.ObjectMeta {
963+ Name : "acorn-test-custom" ,
964+ Namespace : c .GetNamespace (),
965+ },
966+ Default : true ,
967+ Memory : adminv1.ComputeClassMemory {
968+ Default : "512Mi" ,
969+ Max : "1Gi" ,
970+ Min : "512Mi" ,
971+ },
972+ SupportedRegions : []string {apiv1 .LocalRegion },
973+ },
974+ {
975+ ObjectMeta : metav1.ObjectMeta {
976+ Name : "acorn-test-custom-2" ,
977+ Namespace : c .GetNamespace (),
978+ },
979+ Default : true ,
980+ Memory : adminv1.ComputeClassMemory {
981+ Default : "513Mi" ,
982+ Max : "1Gi" ,
983+ Min : "512Mi" ,
984+ },
985+ SupportedRegions : []string {"local2" },
986+ },
987+ },
988+ expected : map [string ]v1.Scheduling {"simple" : {
989+ Requirements : corev1.ResourceRequirements {
990+ Limits : corev1.ResourceList {
991+ corev1 .ResourceMemory : resource .MustParse ("512Mi" )},
992+ Requests : corev1.ResourceList {
993+ corev1 .ResourceMemory : resource .MustParse ("512Mi" ),
994+ },
995+ },
996+ Tolerations : []corev1.Toleration {
997+ {
998+ Key : tolerations .WorkloadTolerationKey ,
999+ Operator : corev1 .TolerationOpExists ,
1000+ },
1001+ }},
1002+ },
1003+ waitFor : func (obj * v1.AppInstance ) bool {
1004+ return obj .Status .Condition (v1 .AppInstanceConditionParsed ).Success &&
1005+ obj .Status .Condition (v1 .AppInstanceConditionScheduling ).Success
1006+ },
1007+ },
1008+ {
1009+ name : "local2-default" ,
1010+ testDataDirectory : "./testdata/simple" ,
1011+ region : "local2" ,
1012+ computeClasses : []adminv1.ProjectComputeClassInstance {
1013+ {
1014+ ObjectMeta : metav1.ObjectMeta {
1015+ Name : "acorn-test-custom" ,
1016+ Namespace : c .GetNamespace (),
1017+ },
1018+ Default : true ,
1019+ Memory : adminv1.ComputeClassMemory {
1020+ Default : "512Mi" ,
1021+ Max : "1Gi" ,
1022+ Min : "512Mi" ,
1023+ },
1024+ SupportedRegions : []string {apiv1 .LocalRegion },
1025+ },
1026+ {
1027+ ObjectMeta : metav1.ObjectMeta {
1028+ Name : "acorn-test-custom-2" ,
1029+ Namespace : c .GetNamespace (),
1030+ },
1031+ Default : true ,
1032+ Memory : adminv1.ComputeClassMemory {
1033+ Default : "513Mi" ,
1034+ Max : "1Gi" ,
1035+ Min : "512Mi" ,
1036+ },
1037+ SupportedRegions : []string {"local2" },
1038+ },
1039+ },
1040+ expected : map [string ]v1.Scheduling {"simple" : {
1041+ Requirements : corev1.ResourceRequirements {
1042+ Limits : corev1.ResourceList {
1043+ corev1 .ResourceMemory : resource .MustParse ("513Mi" )},
1044+ Requests : corev1.ResourceList {
1045+ corev1 .ResourceMemory : resource .MustParse ("513Mi" ),
1046+ },
1047+ },
1048+ Tolerations : []corev1.Toleration {
1049+ {
1050+ Key : tolerations .WorkloadTolerationKey ,
1051+ Operator : corev1 .TolerationOpExists ,
1052+ },
1053+ }},
1054+ },
1055+ waitFor : func (obj * v1.AppInstance ) bool {
1056+ return obj .Status .Condition (v1 .AppInstanceConditionParsed ).Success &&
1057+ obj .Status .Condition (v1 .AppInstanceConditionScheduling ).Success
1058+ },
1059+ },
1060+ {
1061+ name : "acornfile-computeclass" ,
1062+ testDataDirectory : "./testdata/computeclass" ,
1063+ region : apiv1 .LocalRegion ,
1064+ computeClasses : []adminv1.ProjectComputeClassInstance {
1065+ {
1066+ ObjectMeta : metav1.ObjectMeta {
1067+ Name : "acorn-test-custom" ,
1068+ Namespace : c .GetNamespace (),
1069+ },
1070+ Default : true ,
1071+ Memory : adminv1.ComputeClassMemory {
1072+ Default : "512Mi" ,
1073+ Max : "1Gi" ,
1074+ Min : "512Mi" ,
1075+ },
1076+ SupportedRegions : []string {apiv1 .LocalRegion },
1077+ },
1078+ {
1079+ ObjectMeta : metav1.ObjectMeta {
1080+ Name : "acorn-test-custom-2" ,
1081+ Namespace : c .GetNamespace (),
1082+ },
1083+ Default : true ,
1084+ Memory : adminv1.ComputeClassMemory {
1085+ Default : "513Mi" ,
1086+ Max : "1Gi" ,
1087+ Min : "512Mi" ,
1088+ },
1089+ SupportedRegions : []string {"local2" },
1090+ },
1091+ },
1092+ expected : map [string ]v1.Scheduling {"simple" : {
1093+ Requirements : corev1.ResourceRequirements {
1094+ Limits : corev1.ResourceList {
1095+ corev1 .ResourceMemory : resource .MustParse ("512Mi" )},
1096+ Requests : corev1.ResourceList {
1097+ corev1 .ResourceMemory : resource .MustParse ("512Mi" ),
1098+ },
1099+ },
1100+ Tolerations : []corev1.Toleration {
1101+ {
1102+ Key : tolerations .WorkloadTolerationKey ,
1103+ Operator : corev1 .TolerationOpExists ,
1104+ },
1105+ }},
1106+ },
1107+ waitFor : func (obj * v1.AppInstance ) bool {
1108+ return obj .Status .Condition (v1 .AppInstanceConditionParsed ).Success &&
1109+ obj .Status .Condition (v1 .AppInstanceConditionScheduling ).Success
1110+ },
1111+ },
1112+ {
1113+ name : "acornfile-computeclass-wrong-region" ,
1114+ testDataDirectory : "./testdata/computeclass" ,
1115+ region : apiv1 .LocalRegion ,
1116+ computeClasses : []adminv1.ProjectComputeClassInstance {
1117+ {
1118+ ObjectMeta : metav1.ObjectMeta {
1119+ Name : "acorn-test-custom-2" ,
1120+ Namespace : c .GetNamespace (),
1121+ },
1122+ Default : true ,
1123+ Memory : adminv1.ComputeClassMemory {
1124+ Default : "512Mi" ,
1125+ Max : "1Gi" ,
1126+ Min : "512Mi" ,
1127+ },
1128+ SupportedRegions : []string {apiv1 .LocalRegion },
1129+ },
1130+ {
1131+ ObjectMeta : metav1.ObjectMeta {
1132+ Name : "acorn-test-custom" ,
1133+ Namespace : c .GetNamespace (),
1134+ },
1135+ Default : true ,
1136+ Memory : adminv1.ComputeClassMemory {
1137+ Default : "513Mi" ,
1138+ Max : "1Gi" ,
1139+ Min : "512Mi" ,
1140+ },
1141+ SupportedRegions : []string {"local2" },
1142+ },
1143+ },
1144+ fail : true ,
1145+ },
1146+ }
1147+
1148+ for _ , tt := range checks {
1149+ clusterObjects := make ([]crClient.Object , 0 , len (tt .computeClasses ))
1150+ for _ , pcc := range tt .computeClasses {
1151+ cc := adminv1 .ClusterComputeClassInstance (pcc )
1152+ clusterObjects = append (clusterObjects , cc .DeepCopy ())
1153+ }
1154+ projectObjects := make ([]crClient.Object , 0 , len (tt .computeClasses ))
1155+ for _ , cc := range tt .computeClasses {
1156+ projectObjects = append (projectObjects , cc .DeepCopy ())
1157+ }
1158+ // Perform the same test cases on both Project and Cluster ComputeClasses
1159+ for kind , computeClasses := range map [string ][]crClient.Object {"projectcomputeclass" : projectObjects , "clustercomputeclass" : clusterObjects } {
1160+ testcase := fmt .Sprintf ("%v-%v" , kind , tt .name )
1161+ t .Run (testcase , func (t * testing.T ) {
1162+ if ! tt .noComputeClass {
1163+ for _ , computeClass := range computeClasses {
1164+ if err := kclient .Create (ctx , computeClass ); err != nil {
1165+ t .Fatal (err )
1166+ }
1167+ }
1168+
1169+ // Clean-up and guarantee the computeclass doesn't exist after this test run
1170+ t .Cleanup (func () {
1171+ for _ , computeClass := range computeClasses {
1172+ if err = kclient .Delete (context .Background (), computeClass ); err != nil && ! apierrors .IsNotFound (err ) {
1173+ t .Fatal (err )
1174+ }
1175+ err := helper .EnsureDoesNotExist (ctx , func () (crClient.Object , error ) {
1176+ lookingFor := computeClass
1177+ err := kclient .Get (ctx , router .Key (computeClass .GetNamespace (), computeClass .GetName ()), lookingFor )
1178+ return lookingFor , err
1179+ })
1180+ if err != nil {
1181+ t .Fatal (err )
1182+ }
1183+ }
1184+ })
1185+ }
1186+
1187+ image , err := c .AcornImageBuild (ctx , tt .testDataDirectory + "/Acornfile" , & client.AcornImageBuildOptions {
1188+ Cwd : tt .testDataDirectory ,
1189+ })
1190+ if err != nil {
1191+ t .Fatal (err )
1192+ }
1193+
1194+ // Assign a name for the test case so no collisions occur
1195+ app , err := c .AppRun (ctx , image .ID , & client.AppRunOptions {
1196+ Name : testcase ,
1197+ Region : tt .region ,
1198+ })
1199+ if err == nil && tt .fail {
1200+ t .Fatal ("expected error, got nil" )
1201+ } else if err != nil {
1202+ if ! tt .fail {
1203+ t .Fatal (err )
1204+ }
1205+ }
1206+
1207+ // Clean-up and gurantee the app doesn't exist after this test run
1208+ if app != nil {
1209+ t .Cleanup (func () {
1210+ if err = kclient .Delete (context .Background (), app ); err != nil && ! apierrors .IsNotFound (err ) {
1211+ t .Fatal (err )
1212+ }
1213+ err := helper .EnsureDoesNotExist (ctx , func () (crClient.Object , error ) {
1214+ lookingFor := app
1215+ err := kclient .Get (ctx , router .Key (app .GetName (), app .GetNamespace ()), lookingFor )
1216+ return lookingFor , err
1217+ })
1218+ if err != nil {
1219+ t .Fatal (err )
1220+ }
1221+ })
1222+ }
1223+
1224+ if tt .waitFor != nil {
1225+ appInstance := & v1.AppInstance {
1226+ ObjectMeta : metav1.ObjectMeta {
1227+ Name : app .Name ,
1228+ Namespace : app .Namespace ,
1229+ },
1230+ }
1231+ appInstance = helper .WaitForObject (t , kclient .Watch , new (v1.AppInstanceList ), appInstance , tt .waitFor )
1232+ assert .EqualValues (t , appInstance .Status .Scheduling , tt .expected , "generated scheduling rules are incorrect" )
1233+ }
1234+ })
1235+ }
1236+ }
1237+ }
1238+
9341239func TestUsingComputeClasses (t * testing.T ) {
9351240 helper .StartController (t )
9361241 c , _ := helper .ClientAndProject (t )
@@ -1132,7 +1437,7 @@ func TestUsingComputeClasses(t *testing.T) {
11321437 },
11331438 {
11341439 name : "unsupported-region" ,
1135- testDataDirectory : "./testdata/simple " ,
1440+ testDataDirectory : "./testdata/computeclass " ,
11361441 computeClass : adminv1.ProjectComputeClassInstance {
11371442 ObjectMeta : metav1.ObjectMeta {
11381443 Name : "acorn-test-custom" ,
@@ -1160,7 +1465,7 @@ func TestUsingComputeClasses(t *testing.T) {
11601465 for _ , tt := range checks {
11611466 asClusterComputeClass := adminv1 .ClusterComputeClassInstance (tt .computeClass )
11621467 // Perform the same test cases on both Project and Cluster ComputeClasses
1163- for kind , computeClass := range map [string ]crClient.Object {"projectcomputeclass" : & tt .computeClass , "clustercomputeclass" : & asClusterComputeClass } {
1468+ for kind , computeClass := range map [string ]crClient.Object {"projectcomputeclass" : & tt .computeClass , "clustercomputeclass" : asClusterComputeClass . DeepCopy () } {
11641469 testcase := fmt .Sprintf ("%v-%v" , kind , tt .name )
11651470 t .Run (testcase , func (t * testing.T ) {
11661471 if ! tt .noComputeClass {
0 commit comments