Skip to content

Commit faef587

Browse files
committed
Add unit tests for GetPodTemplateSpec
Signed-off-by: Philippe Martin <[email protected]>
1 parent e342737 commit faef587

File tree

2 files changed

+372
-77
lines changed

2 files changed

+372
-77
lines changed

pkg/devfile/generator/generators_test.go

+366-7
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,7 @@ import (
2121
"strings"
2222
"testing"
2323

24-
"github.com/stretchr/testify/assert"
25-
appsv1 "k8s.io/api/apps/v1"
26-
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27-
"k8s.io/apimachinery/pkg/util/intstr"
28-
"k8s.io/utils/pointer"
29-
24+
"github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
3025
v1 "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
3126
"github.com/devfile/api/v2/pkg/attributes"
3227
"github.com/devfile/library/v2/pkg/devfile/parser"
@@ -35,8 +30,14 @@ import (
3530
"github.com/devfile/library/v2/pkg/testingutil"
3631
"github.com/devfile/library/v2/pkg/util"
3732
"github.com/golang/mock/gomock"
38-
33+
"github.com/google/go-cmp/cmp"
34+
"github.com/stretchr/testify/assert"
35+
appsv1 "k8s.io/api/apps/v1"
3936
corev1 "k8s.io/api/core/v1"
37+
apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
38+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
39+
"k8s.io/apimachinery/pkg/util/intstr"
40+
"k8s.io/utils/pointer"
4041
)
4142

4243
var fakeResources corev1.ResourceRequirements
@@ -1267,3 +1268,361 @@ func TestGetDeployment(t *testing.T) {
12671268
})
12681269
}
12691270
}
1271+
1272+
func TestGetPodTemplateSpec(t *testing.T) {
1273+
type args struct {
1274+
devfileObj func(ctrl *gomock.Controller) parser.DevfileObj
1275+
podTemplateParams PodTemplateParams
1276+
}
1277+
tests := []struct {
1278+
name string
1279+
args args
1280+
want *corev1.PodTemplateSpec
1281+
wantErr bool
1282+
}{
1283+
{
1284+
name: "Devfile with wrong container-override",
1285+
args: args{
1286+
devfileObj: func(ctrl *gomock.Controller) parser.DevfileObj {
1287+
containers := []v1alpha2.Component{
1288+
{
1289+
Name: "main",
1290+
ComponentUnion: v1.ComponentUnion{
1291+
Container: &v1.ContainerComponent{
1292+
Container: v1.Container{
1293+
Image: "an-image",
1294+
},
1295+
},
1296+
},
1297+
Attributes: attributes.Attributes{
1298+
ContainerOverridesAttribute: apiext.JSON{Raw: []byte("{\"spec\": \"serviceAccountName\": \"new-service-account\"}")},
1299+
},
1300+
},
1301+
}
1302+
events := v1alpha2.Events{}
1303+
mockDevfileData := data.NewMockDevfileData(ctrl)
1304+
mockDevfileData.EXPECT().GetComponents(gomock.Any()).Return(containers, nil).AnyTimes()
1305+
mockDevfileData.EXPECT().GetDevfileContainerComponents(gomock.Any()).Return(containers, nil).AnyTimes()
1306+
mockDevfileData.EXPECT().GetEvents().Return(events).AnyTimes()
1307+
mockDevfileData.EXPECT().GetProjects(gomock.Any()).Return(nil, nil).AnyTimes()
1308+
mockDevfileData.EXPECT().GetAttributes().Return(attributes.Attributes{}, nil)
1309+
mockDevfileData.EXPECT().GetSchemaVersion().Return("2.1.0").AnyTimes()
1310+
return parser.DevfileObj{
1311+
Data: mockDevfileData,
1312+
}
1313+
},
1314+
},
1315+
wantErr: true,
1316+
},
1317+
{
1318+
name: "Devfile with local container-override on the first container only",
1319+
args: args{
1320+
devfileObj: func(ctrl *gomock.Controller) parser.DevfileObj {
1321+
containers := []v1alpha2.Component{
1322+
{
1323+
Name: "main",
1324+
ComponentUnion: v1.ComponentUnion{
1325+
Container: &v1.ContainerComponent{
1326+
Container: v1.Container{
1327+
Image: "an-image",
1328+
},
1329+
},
1330+
},
1331+
Attributes: attributes.Attributes{}.FromMap(map[string]interface{}{
1332+
"container-overrides": map[string]interface{}{"securityContext": map[string]int64{"runAsGroup": 3000}},
1333+
}, nil),
1334+
},
1335+
{
1336+
Name: "tools",
1337+
ComponentUnion: v1.ComponentUnion{
1338+
Container: &v1.ContainerComponent{
1339+
Container: v1.Container{
1340+
Image: "a-tool-image",
1341+
},
1342+
},
1343+
},
1344+
},
1345+
}
1346+
events := v1alpha2.Events{}
1347+
mockDevfileData := data.NewMockDevfileData(ctrl)
1348+
mockDevfileData.EXPECT().GetComponents(gomock.Any()).Return(containers, nil).AnyTimes()
1349+
mockDevfileData.EXPECT().GetDevfileContainerComponents(gomock.Any()).Return(containers, nil).AnyTimes()
1350+
mockDevfileData.EXPECT().GetEvents().Return(events).AnyTimes()
1351+
mockDevfileData.EXPECT().GetProjects(gomock.Any()).Return(nil, nil).AnyTimes()
1352+
mockDevfileData.EXPECT().GetAttributes().Return(attributes.Attributes{
1353+
PodOverridesAttribute: apiext.JSON{Raw: []byte("{\"spec\": {\"serviceAccountName\": \"new-service-account\"}}")}}, nil)
1354+
mockDevfileData.EXPECT().GetSchemaVersion().Return("2.1.0").AnyTimes()
1355+
return parser.DevfileObj{
1356+
Data: mockDevfileData,
1357+
}
1358+
},
1359+
},
1360+
want: &corev1.PodTemplateSpec{
1361+
Spec: corev1.PodSpec{
1362+
ServiceAccountName: "new-service-account",
1363+
Containers: []corev1.Container{
1364+
{
1365+
Name: "main",
1366+
Image: "an-image",
1367+
Env: []corev1.EnvVar{
1368+
{Name: "PROJECTS_ROOT", Value: "/projects"},
1369+
{Name: "PROJECT_SOURCE", Value: "/projects"},
1370+
},
1371+
ImagePullPolicy: corev1.PullAlways,
1372+
SecurityContext: &corev1.SecurityContext{
1373+
RunAsGroup: pointer.Int64(3000),
1374+
},
1375+
},
1376+
{
1377+
Name: "tools",
1378+
Image: "a-tool-image",
1379+
Env: []corev1.EnvVar{
1380+
{Name: "PROJECTS_ROOT", Value: "/projects"},
1381+
{Name: "PROJECT_SOURCE", Value: "/projects"},
1382+
},
1383+
ImagePullPolicy: corev1.PullAlways,
1384+
Ports: []corev1.ContainerPort{},
1385+
},
1386+
},
1387+
InitContainers: []corev1.Container{},
1388+
},
1389+
},
1390+
},
1391+
{
1392+
name: "Devfile with local container-override and global pod-override",
1393+
args: args{
1394+
devfileObj: func(ctrl *gomock.Controller) parser.DevfileObj {
1395+
containers := []v1alpha2.Component{
1396+
{
1397+
Name: "main",
1398+
ComponentUnion: v1.ComponentUnion{
1399+
Container: &v1.ContainerComponent{
1400+
Container: v1.Container{
1401+
Image: "an-image",
1402+
},
1403+
},
1404+
},
1405+
Attributes: attributes.Attributes{}.FromMap(map[string]interface{}{
1406+
"container-overrides": map[string]interface{}{"securityContext": map[string]int64{"runAsGroup": 3000}},
1407+
}, nil),
1408+
},
1409+
}
1410+
events := v1alpha2.Events{}
1411+
mockDevfileData := data.NewMockDevfileData(ctrl)
1412+
mockDevfileData.EXPECT().GetComponents(gomock.Any()).Return(containers, nil).AnyTimes()
1413+
mockDevfileData.EXPECT().GetDevfileContainerComponents(gomock.Any()).Return(containers, nil).AnyTimes()
1414+
mockDevfileData.EXPECT().GetEvents().Return(events).AnyTimes()
1415+
mockDevfileData.EXPECT().GetProjects(gomock.Any()).Return(nil, nil).AnyTimes()
1416+
mockDevfileData.EXPECT().GetAttributes().Return(attributes.Attributes{
1417+
PodOverridesAttribute: apiext.JSON{Raw: []byte("{\"spec\": {\"serviceAccountName\": \"new-service-account\"}}")}}, nil)
1418+
mockDevfileData.EXPECT().GetSchemaVersion().Return("2.1.0").AnyTimes()
1419+
return parser.DevfileObj{
1420+
Data: mockDevfileData,
1421+
}
1422+
},
1423+
},
1424+
want: &corev1.PodTemplateSpec{
1425+
Spec: corev1.PodSpec{
1426+
ServiceAccountName: "new-service-account",
1427+
Containers: []corev1.Container{
1428+
{
1429+
Name: "main",
1430+
Image: "an-image",
1431+
Env: []corev1.EnvVar{
1432+
{Name: "PROJECTS_ROOT", Value: "/projects"},
1433+
{Name: "PROJECT_SOURCE", Value: "/projects"},
1434+
},
1435+
ImagePullPolicy: corev1.PullAlways,
1436+
SecurityContext: &corev1.SecurityContext{
1437+
RunAsGroup: pointer.Int64(3000),
1438+
},
1439+
},
1440+
},
1441+
InitContainers: []corev1.Container{},
1442+
},
1443+
},
1444+
},
1445+
{
1446+
name: "Devfile with local container-override and local pod-override",
1447+
args: args{
1448+
devfileObj: func(ctrl *gomock.Controller) parser.DevfileObj {
1449+
containers := []v1alpha2.Component{
1450+
{
1451+
Name: "main",
1452+
ComponentUnion: v1.ComponentUnion{
1453+
Container: &v1.ContainerComponent{
1454+
Container: v1.Container{
1455+
Image: "an-image",
1456+
},
1457+
},
1458+
},
1459+
Attributes: attributes.Attributes{
1460+
ContainerOverridesAttribute: apiext.JSON{Raw: []byte("{\"securityContext\": {\"runAsGroup\": 3000}}")},
1461+
PodOverridesAttribute: apiext.JSON{Raw: []byte("{\"spec\": {\"serviceAccountName\": \"new-service-account\"}}")},
1462+
},
1463+
},
1464+
}
1465+
events := v1alpha2.Events{}
1466+
mockDevfileData := data.NewMockDevfileData(ctrl)
1467+
mockDevfileData.EXPECT().GetComponents(gomock.Any()).Return(containers, nil).AnyTimes()
1468+
mockDevfileData.EXPECT().GetDevfileContainerComponents(gomock.Any()).Return(containers, nil).AnyTimes()
1469+
mockDevfileData.EXPECT().GetEvents().Return(events).AnyTimes()
1470+
mockDevfileData.EXPECT().GetProjects(gomock.Any()).Return(nil, nil).AnyTimes()
1471+
mockDevfileData.EXPECT().GetAttributes().Return(attributes.Attributes{}, nil)
1472+
mockDevfileData.EXPECT().GetSchemaVersion().Return("2.1.0").AnyTimes()
1473+
return parser.DevfileObj{
1474+
Data: mockDevfileData,
1475+
}
1476+
},
1477+
},
1478+
want: &corev1.PodTemplateSpec{
1479+
Spec: corev1.PodSpec{
1480+
ServiceAccountName: "new-service-account",
1481+
Containers: []corev1.Container{
1482+
{
1483+
Name: "main",
1484+
Image: "an-image",
1485+
Env: []corev1.EnvVar{
1486+
{Name: "PROJECTS_ROOT", Value: "/projects"},
1487+
{Name: "PROJECT_SOURCE", Value: "/projects"},
1488+
},
1489+
ImagePullPolicy: corev1.PullAlways,
1490+
SecurityContext: &corev1.SecurityContext{
1491+
RunAsGroup: pointer.Int64(3000),
1492+
},
1493+
},
1494+
},
1495+
InitContainers: []corev1.Container{},
1496+
},
1497+
},
1498+
},
1499+
{
1500+
name: "Devfile with pod-override at local ang global level",
1501+
args: args{
1502+
devfileObj: func(ctrl *gomock.Controller) parser.DevfileObj {
1503+
containers := []v1alpha2.Component{
1504+
{
1505+
Name: "main",
1506+
ComponentUnion: v1.ComponentUnion{
1507+
Container: &v1.ContainerComponent{
1508+
Container: v1.Container{
1509+
Image: "an-image",
1510+
},
1511+
},
1512+
},
1513+
Attributes: attributes.Attributes{
1514+
PodOverridesAttribute: apiext.JSON{Raw: []byte("{\"spec\": {\"schedulerName\": \"new-scheduler\"}}")},
1515+
},
1516+
},
1517+
}
1518+
events := v1alpha2.Events{}
1519+
mockDevfileData := data.NewMockDevfileData(ctrl)
1520+
mockDevfileData.EXPECT().GetComponents(gomock.Any()).Return(containers, nil).AnyTimes()
1521+
mockDevfileData.EXPECT().GetDevfileContainerComponents(gomock.Any()).Return(containers, nil).AnyTimes()
1522+
mockDevfileData.EXPECT().GetEvents().Return(events).AnyTimes()
1523+
mockDevfileData.EXPECT().GetProjects(gomock.Any()).Return(nil, nil).AnyTimes()
1524+
mockDevfileData.EXPECT().GetAttributes().Return(attributes.Attributes{
1525+
PodOverridesAttribute: apiext.JSON{Raw: []byte("{\"spec\": {\"serviceAccountName\": \"new-service-account\"}}")},
1526+
}, nil)
1527+
mockDevfileData.EXPECT().GetSchemaVersion().Return("2.1.0").AnyTimes()
1528+
return parser.DevfileObj{
1529+
Data: mockDevfileData,
1530+
}
1531+
},
1532+
},
1533+
want: &corev1.PodTemplateSpec{
1534+
Spec: corev1.PodSpec{
1535+
ServiceAccountName: "new-service-account",
1536+
SchedulerName: "new-scheduler",
1537+
Containers: []corev1.Container{
1538+
{
1539+
Name: "main",
1540+
Image: "an-image",
1541+
Env: []corev1.EnvVar{
1542+
{Name: "PROJECTS_ROOT", Value: "/projects"},
1543+
{Name: "PROJECT_SOURCE", Value: "/projects"},
1544+
},
1545+
ImagePullPolicy: corev1.PullAlways,
1546+
Ports: []corev1.ContainerPort{},
1547+
},
1548+
},
1549+
InitContainers: []corev1.Container{},
1550+
},
1551+
},
1552+
},
1553+
{
1554+
name: "Devfile with global container-override and pod-override",
1555+
args: args{
1556+
devfileObj: func(ctrl *gomock.Controller) parser.DevfileObj {
1557+
containers := []v1alpha2.Component{
1558+
{
1559+
Name: "main",
1560+
ComponentUnion: v1.ComponentUnion{
1561+
Container: &v1.ContainerComponent{
1562+
Container: v1.Container{
1563+
Image: "an-image",
1564+
},
1565+
},
1566+
},
1567+
Attributes: attributes.Attributes{}.FromMap(map[string]interface{}{
1568+
"container-overrides": map[string]interface{}{"securityContext": map[string]int64{"runAsGroup": 3000}},
1569+
}, nil),
1570+
},
1571+
}
1572+
events := v1alpha2.Events{}
1573+
mockDevfileData := data.NewMockDevfileData(ctrl)
1574+
mockDevfileData.EXPECT().GetComponents(gomock.Any()).Return(containers, nil).AnyTimes()
1575+
mockDevfileData.EXPECT().GetDevfileContainerComponents(gomock.Any()).Return(containers, nil).AnyTimes()
1576+
mockDevfileData.EXPECT().GetEvents().Return(events).AnyTimes()
1577+
mockDevfileData.EXPECT().GetProjects(gomock.Any()).Return(nil, nil).AnyTimes()
1578+
mockDevfileData.EXPECT().GetAttributes().Return(attributes.Attributes{
1579+
PodOverridesAttribute: apiext.JSON{Raw: []byte("{\"spec\": {\"serviceAccountName\": \"new-service-account\"}}")},
1580+
ContainerOverridesAttribute: apiext.JSON{Raw: []byte("{\"securityContext\": {\"runAsGroup\": 3000}}")},
1581+
}, nil)
1582+
mockDevfileData.EXPECT().GetSchemaVersion().Return("2.1.0").AnyTimes()
1583+
return parser.DevfileObj{
1584+
Data: mockDevfileData,
1585+
}
1586+
},
1587+
},
1588+
want: &corev1.PodTemplateSpec{
1589+
Spec: corev1.PodSpec{
1590+
ServiceAccountName: "new-service-account",
1591+
Containers: []corev1.Container{
1592+
{
1593+
Name: "main",
1594+
Image: "an-image",
1595+
Env: []corev1.EnvVar{
1596+
{Name: "PROJECTS_ROOT", Value: "/projects"},
1597+
{Name: "PROJECT_SOURCE", Value: "/projects"},
1598+
},
1599+
ImagePullPolicy: corev1.PullAlways,
1600+
SecurityContext: &corev1.SecurityContext{
1601+
RunAsGroup: pointer.Int64(3000),
1602+
},
1603+
},
1604+
},
1605+
InitContainers: []corev1.Container{},
1606+
},
1607+
},
1608+
},
1609+
}
1610+
for _, tt := range tests {
1611+
t.Run(tt.name, func(t *testing.T) {
1612+
1613+
ctrl := gomock.NewController(t)
1614+
defer ctrl.Finish()
1615+
1616+
devObj := tt.args.devfileObj(ctrl)
1617+
1618+
got, err := GetPodTemplateSpec(devObj, tt.args.podTemplateParams)
1619+
if (err != nil) != tt.wantErr {
1620+
t.Errorf("GetPodTemplateSpec() error = %v, wantErr %v", err, tt.wantErr)
1621+
return
1622+
}
1623+
if diff := cmp.Diff(tt.want, got); diff != "" {
1624+
t.Errorf("GetPodTemplateSpec() mismatch (-want +got): %s\n", diff)
1625+
}
1626+
})
1627+
}
1628+
}

0 commit comments

Comments
 (0)