Skip to content

Fix GetDeployment function when Devfile SchemaVersion is less than 2.1.0 #161

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
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
13 changes: 9 additions & 4 deletions pkg/devfile/generator/generators.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ package generator
import (
"fmt"

"github.com/devfile/api/v2/pkg/attributes"
"github.com/devfile/library/v2/pkg/devfile/parser/data"

v1 "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
"github.com/devfile/library/v2/pkg/devfile/parser"
"github.com/devfile/library/v2/pkg/devfile/parser/data/v2/common"
Expand Down Expand Up @@ -185,10 +188,12 @@ func GetDeployment(devfileObj parser.DevfileObj, deployParams DeploymentParams)
Containers: deployParams.Containers,
Volumes: deployParams.Volumes,
}

globalAttributes, err := devfileObj.Data.GetAttributes()
if err != nil {
return nil, err
var globalAttributes attributes.Attributes
// attributes is not supported in versions less than 2.1.0, so we skip it
if devfileObj.Data.GetSchemaVersion() > string(data.APISchemaVersion200) {
// the only time GetAttributes will return an error is if DevfileSchemaVersion is 2.0.0, a case we've already covered;
// so we'll skip checking for error here
globalAttributes, _ = devfileObj.Data.GetAttributes()
}
components, err := devfileObj.Data.GetDevfileContainerComponents(common.DevfileOptions{})
if err != nil {
Expand Down
101 changes: 87 additions & 14 deletions pkg/devfile/generator/generators_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@ package generator

import (
"fmt"
apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"reflect"
"strings"
"testing"

apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"

"github.com/stretchr/testify/assert"
appsv1 "k8s.io/api/apps/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -1081,6 +1082,7 @@ func TestGetDeployment(t *testing.T) {
expected *appsv1.Deployment
attributes attributes.Attributes
wantErr bool
devObj func(ctrl *gomock.Controller, containerComponents []v1.Component) parser.DevfileObj
}{
{
// Currently dedicatedPod can only filter out annotations
Expand Down Expand Up @@ -1248,26 +1250,97 @@ func TestGetDeployment(t *testing.T) {
expected: nil,
wantErr: trueBool,
},
{
name: "skip getting global attributes for SchemaVersion less than 2.1.0",
containerComponents: []v1.Component{
testingutil.GenerateDummyContainerComponent("container1", nil, []v1.Endpoint{
{
Name: "http-8080",
TargetPort: 8080,
},
}, nil, v1.Annotation{
Deployment: map[string]string{
"key1": "value1",
},
}, nil),
testingutil.GenerateDummyContainerComponent("container2", nil, nil, nil, v1.Annotation{
Deployment: map[string]string{
"key2": "value2",
},
}, nil),
},
deploymentParams: DeploymentParams{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
"preserved-key": "preserved-value",
},
},
Containers: containers,
},
expected: &appsv1.Deployment{
ObjectMeta: objectMeta,
Spec: appsv1.DeploymentSpec{
Strategy: appsv1.DeploymentStrategy{
Type: appsv1.RecreateDeploymentStrategyType,
},
Selector: &metav1.LabelSelector{
MatchLabels: nil,
},
Template: corev1.PodTemplateSpec{
ObjectMeta: objectMeta,
Spec: corev1.PodSpec{
Containers: containers,
},
},
},
},
attributes: nil,
wantErr: false,
devObj: func(ctrl *gomock.Controller, containerComponents []v1.Component) parser.DevfileObj {
mockDevfileData := data.NewMockDevfileData(ctrl)

options := common.DevfileOptions{
ComponentOptions: common.ComponentOptions{
ComponentType: v1.ContainerComponentType,
},
}
// set up the mock data
mockDevfileData.EXPECT().GetSchemaVersion().Return("2.0.0")
mockDevfileData.EXPECT().GetDevfileContainerComponents(common.DevfileOptions{}).Return(containerComponents, nil).AnyTimes()
mockDevfileData.EXPECT().GetComponents(options).Return(containerComponents, nil).AnyTimes()

devObj := parser.DevfileObj{
Data: mockDevfileData,
}
return devObj
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockDevfileData := data.NewMockDevfileData(ctrl)

options := common.DevfileOptions{
ComponentOptions: common.ComponentOptions{
ComponentType: v1.ContainerComponentType,
},
}
// set up the mock data
mockDevfileData.EXPECT().GetAttributes().Return(tt.attributes, nil).AnyTimes()
mockDevfileData.EXPECT().GetDevfileContainerComponents(common.DevfileOptions{}).Return(tt.containerComponents, nil).AnyTimes()
mockDevfileData.EXPECT().GetComponents(options).Return(tt.containerComponents, nil).AnyTimes()
var devObj parser.DevfileObj
if tt.devObj != nil {
devObj = tt.devObj(ctrl, tt.containerComponents)
} else {
mockDevfileData := data.NewMockDevfileData(ctrl)

devObj := parser.DevfileObj{
Data: mockDevfileData,
options := common.DevfileOptions{
ComponentOptions: common.ComponentOptions{
ComponentType: v1.ContainerComponentType,
},
}
// set up the mock data
mockDevfileData.EXPECT().GetSchemaVersion().Return("2.1.0")
mockDevfileData.EXPECT().GetAttributes().Return(tt.attributes, nil).AnyTimes()
mockDevfileData.EXPECT().GetDevfileContainerComponents(common.DevfileOptions{}).Return(tt.containerComponents, nil).AnyTimes()
mockDevfileData.EXPECT().GetComponents(options).Return(tt.containerComponents, nil).AnyTimes()

devObj = parser.DevfileObj{
Data: mockDevfileData,
}
}
deploy, err := GetDeployment(devObj, tt.deploymentParams)
// Checks for unexpected error cases
Expand Down
3 changes: 1 addition & 2 deletions pkg/devfile/generator/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,7 @@ func getPodTemplateSpec(globalAttributes attributes.Attributes, components []v1.
Volumes: podTemplateSpecParams.Volumes,
},
}

if needsPodOverrides(globalAttributes, components) {
if len(globalAttributes) != 0 && needsPodOverrides(globalAttributes, components) {
patchedPodTemplateSpec, err := applyPodOverrides(globalAttributes, components, podTemplateSpec)
if err != nil {
return nil, err
Expand Down
21 changes: 19 additions & 2 deletions pkg/devfile/generator/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package generator

import (
"fmt"

"github.com/hashicorp/go-multierror"
"github.com/stretchr/testify/assert"
"k8s.io/utils/pointer"
Expand All @@ -37,6 +38,7 @@ import (
v1 "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"

corev1 "k8s.io/api/core/v1"
apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -640,15 +642,27 @@ func TestGetPodTemplateSpec(t *testing.T) {
namespace string
serviceAccount string
labels map[string]string
attributes attributes.Attributes
}{
{
podName: "podSpecTest",
namespace: "default",
labels: map[string]string{
"app": "app",
"component": "frontend",
},
},
{
podName: "podSpecTest",
namespace: "default",
serviceAccount: "default",
serviceAccount: "new-service-account",
labels: map[string]string{
"app": "app",
"component": "frontend",
},
attributes: attributes.Attributes{
PodOverridesAttribute: apiext.JSON{Raw: []byte("{\"spec\": {\"serviceAccountName\": \"new-service-account\"}}")},
},
},
}

Expand All @@ -663,7 +677,7 @@ func TestGetPodTemplateSpec(t *testing.T) {
InitContainers: container,
}

podTemplateSpec, err := getPodTemplateSpec(nil, nil, podTemplateSpecParams)
podTemplateSpec, err := getPodTemplateSpec(tt.attributes, nil, podTemplateSpecParams)
if err != nil {
t.Errorf("TestGetPodTemplateSpec() error: %s", err.Error())
}
Expand All @@ -674,6 +688,9 @@ func TestGetPodTemplateSpec(t *testing.T) {
if podTemplateSpec.Namespace != tt.namespace {
t.Errorf("TestGetPodTemplateSpec() error: expected namespace %s, actual %s", tt.namespace, podTemplateSpec.Namespace)
}
if tt.serviceAccount != "" && podTemplateSpec.Spec.ServiceAccountName != tt.serviceAccount {
t.Errorf("TestGetPodTemplateSpec() error: expected serviceAccountName %s, actual %s", tt.serviceAccount, podTemplateSpec.Spec.ServiceAccountName)
}
if !hasVolumeWithName("vol1", podTemplateSpec.Spec.Volumes) {
t.Errorf("TestGetPodTemplateSpec() error: volume with name: %s not found", "vol1")
}
Expand Down