Skip to content

Commit 34f8567

Browse files
authoredMar 11, 2021
Merge pull request #65 from maysunfaisal/357-1
Add Delete Comp, Command, Proj, StarterProj
2 parents 813456e + 5e32c06 commit 34f8567

14 files changed

+597
-362
lines changed
 

‎go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ require (
1515
github.com/openshift/api v0.0.0-20200930075302-db52bc4ef99f
1616
github.com/pkg/errors v0.9.1
1717
github.com/spf13/afero v1.2.2
18-
github.com/stretchr/testify v1.6.1 // indirect
18+
github.com/stretchr/testify v1.6.1
1919
github.com/xeipuuv/gojsonschema v1.2.0
2020
k8s.io/api v0.19.0
2121
k8s.io/apimachinery v0.19.0

‎go.sum

+1
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,7 @@ gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
494494
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
495495
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
496496
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
497+
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
497498
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
498499
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
499500
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

‎pkg/devfile/parser/data/interface.go

+9-5
Original file line numberDiff line numberDiff line change
@@ -26,26 +26,30 @@ type DevfileData interface {
2626
GetComponents(common.DevfileOptions) ([]v1.Component, error)
2727
AddComponents(components []v1.Component) error
2828
UpdateComponent(component v1.Component)
29+
DeleteComponent(name string) error
2930

3031
// project related methods
3132
GetProjects(common.DevfileOptions) ([]v1.Project, error)
3233
AddProjects(projects []v1.Project) error
3334
UpdateProject(project v1.Project)
35+
DeleteProject(name string) error
3436

3537
// starter projects related commands
3638
GetStarterProjects(common.DevfileOptions) ([]v1.StarterProject, error)
3739
AddStarterProjects(projects []v1.StarterProject) error
3840
UpdateStarterProject(project v1.StarterProject)
41+
DeleteStarterProject(name string) error
3942

4043
// command related methods
4144
GetCommands(common.DevfileOptions) ([]v1.Command, error)
42-
AddCommands(commands ...v1.Command) error
45+
AddCommands(commands []v1.Command) error
4346
UpdateCommand(command v1.Command)
47+
DeleteCommand(id string) error
4448

45-
// volume related methods
46-
AddVolume(volume v1.Component, path string) error
47-
DeleteVolume(name string) error
48-
GetVolumeMountPath(name string) (string, error)
49+
// volume mount related methods
50+
AddVolumeMounts(componentName string, volumeMounts []v1.VolumeMount) error
51+
DeleteVolumeMount(name string) error
52+
GetVolumeMountPath(mountName, componentName string) (string, error)
4953

5054
// workspace related methods
5155
GetDevfileWorkspace() *v1.DevWorkspaceTemplateSpecContent

‎pkg/devfile/parser/data/v2/commands.go

+18-6
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,10 @@ func (d *DevfileV2) GetCommands(options common.DevfileOptions) ([]v1.Command, er
3131

3232
// AddCommands adds the slice of Command objects to the Devfile's commands
3333
// if a command is already defined, error out
34-
func (d *DevfileV2) AddCommands(commands ...v1.Command) error {
35-
devfileCommands, err := d.GetCommands(common.DevfileOptions{})
36-
if err != nil {
37-
return err
38-
}
34+
func (d *DevfileV2) AddCommands(commands []v1.Command) error {
3935

4036
for _, command := range commands {
41-
for _, devfileCommand := range devfileCommands {
37+
for _, devfileCommand := range d.Commands {
4238
if command.Id == devfileCommand.Id {
4339
return &common.FieldAlreadyExistError{Name: command.Id, Field: "command"}
4440
}
@@ -57,3 +53,19 @@ func (d *DevfileV2) UpdateCommand(command v1.Command) {
5753
}
5854
}
5955
}
56+
57+
// DeleteCommand removes the specified command
58+
func (d *DevfileV2) DeleteCommand(id string) error {
59+
60+
for i := range d.Commands {
61+
if d.Commands[i].Id == id {
62+
d.Commands = append(d.Commands[:i], d.Commands[i+1:]...)
63+
return nil
64+
}
65+
}
66+
67+
return &common.FieldNotFoundError{
68+
Field: "command",
69+
Name: id,
70+
}
71+
}

‎pkg/devfile/parser/data/v2/commands_test.go

+82-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
v1 "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
88
"github.com/devfile/api/v2/pkg/attributes"
99
"github.com/devfile/library/pkg/devfile/parser/data/v2/common"
10+
"github.com/stretchr/testify/assert"
1011
)
1112

1213
func TestDevfile200_GetCommands(t *testing.T) {
@@ -216,7 +217,7 @@ func TestDevfile200_AddCommands(t *testing.T) {
216217
},
217218
}
218219

219-
got := d.AddCommands(tt.newCommands...)
220+
got := d.AddCommands(tt.newCommands)
220221
if !tt.wantErr && got != nil {
221222
t.Errorf("TestDevfile200_AddCommands() unexpected error - %v", got)
222223
} else if tt.wantErr && got == nil {
@@ -300,3 +301,83 @@ func TestDevfile200_UpdateCommands(t *testing.T) {
300301
})
301302
}
302303
}
304+
305+
func TestDeleteCommands(t *testing.T) {
306+
307+
d := &DevfileV2{
308+
v1.Devfile{
309+
DevWorkspaceTemplateSpec: v1.DevWorkspaceTemplateSpec{
310+
DevWorkspaceTemplateSpecContent: v1.DevWorkspaceTemplateSpecContent{
311+
Commands: []v1.Command{
312+
{
313+
Id: "command1",
314+
CommandUnion: v1.CommandUnion{
315+
Exec: &v1.ExecCommand{},
316+
},
317+
},
318+
{
319+
Id: "command2",
320+
CommandUnion: v1.CommandUnion{
321+
Exec: &v1.ExecCommand{},
322+
},
323+
},
324+
{
325+
Id: "command3",
326+
CommandUnion: v1.CommandUnion{
327+
Composite: &v1.CompositeCommand{
328+
Commands: []string{"command1", "command2", "command1"},
329+
},
330+
},
331+
},
332+
},
333+
},
334+
},
335+
},
336+
}
337+
338+
tests := []struct {
339+
name string
340+
commandToDelete string
341+
wantCommands []v1.Command
342+
wantErr bool
343+
}{
344+
{
345+
name: "Successfully delete command",
346+
commandToDelete: "command1",
347+
wantCommands: []v1.Command{
348+
{
349+
Id: "command2",
350+
CommandUnion: v1.CommandUnion{
351+
Exec: &v1.ExecCommand{},
352+
},
353+
},
354+
{
355+
Id: "command3",
356+
CommandUnion: v1.CommandUnion{
357+
Composite: &v1.CompositeCommand{
358+
Commands: []string{"command1", "command2", "command1"},
359+
},
360+
},
361+
},
362+
},
363+
wantErr: false,
364+
},
365+
{
366+
name: "Missing Command",
367+
commandToDelete: "command34",
368+
wantErr: true,
369+
},
370+
}
371+
for _, tt := range tests {
372+
t.Run(tt.name, func(t *testing.T) {
373+
err := d.DeleteCommand(tt.commandToDelete)
374+
if (err != nil) != tt.wantErr {
375+
t.Errorf("DeleteCommand() error = %v, wantErr %v", err, tt.wantErr)
376+
return
377+
} else if err == nil {
378+
assert.Equal(t, tt.wantCommands, d.Commands, "The two values should be the same.")
379+
}
380+
})
381+
}
382+
383+
}

‎pkg/devfile/parser/data/v2/components.go

+21-9
Original file line numberDiff line numberDiff line change
@@ -60,17 +60,13 @@ func (d *DevfileV2) GetDevfileVolumeComponents(options common.DevfileOptions) ([
6060
// if a component is already defined, error out
6161
func (d *DevfileV2) AddComponents(components []v1.Component) error {
6262

63-
componentMap := make(map[string]bool)
64-
65-
for _, component := range d.Components {
66-
componentMap[component.Name] = true
67-
}
6863
for _, component := range components {
69-
if _, ok := componentMap[component.Name]; !ok {
70-
d.Components = append(d.Components, component)
71-
} else {
72-
return &common.FieldAlreadyExistError{Name: component.Name, Field: "component"}
64+
for _, devfileComponent := range d.Components {
65+
if component.Name == devfileComponent.Name {
66+
return &common.FieldAlreadyExistError{Name: component.Name, Field: "component"}
67+
}
7368
}
69+
d.Components = append(d.Components, component)
7470
}
7571
return nil
7672
}
@@ -88,3 +84,19 @@ func (d *DevfileV2) UpdateComponent(component v1.Component) {
8884
d.Components[index] = component
8985
}
9086
}
87+
88+
// DeleteComponent removes the specified component
89+
func (d *DevfileV2) DeleteComponent(name string) error {
90+
91+
for i := range d.Components {
92+
if d.Components[i].Name == name {
93+
d.Components = append(d.Components[:i], d.Components[i+1:]...)
94+
return nil
95+
}
96+
}
97+
98+
return &common.FieldNotFoundError{
99+
Field: "component",
100+
Name: name,
101+
}
102+
}

‎pkg/devfile/parser/data/v2/components_test.go

+92
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/devfile/api/v2/pkg/attributes"
99
"github.com/devfile/library/pkg/devfile/parser/data/v2/common"
1010
"github.com/devfile/library/pkg/testingutil"
11+
"github.com/stretchr/testify/assert"
1112
)
1213

1314
func TestDevfile200_AddComponent(t *testing.T) {
@@ -403,3 +404,94 @@ func TestGetDevfileVolumeComponents(t *testing.T) {
403404
}
404405

405406
}
407+
408+
func TestDeleteComponents(t *testing.T) {
409+
410+
d := &DevfileV2{
411+
v1.Devfile{
412+
DevWorkspaceTemplateSpec: v1.DevWorkspaceTemplateSpec{
413+
DevWorkspaceTemplateSpecContent: v1.DevWorkspaceTemplateSpecContent{
414+
Components: []v1.Component{
415+
{
416+
Name: "comp2",
417+
ComponentUnion: v1.ComponentUnion{
418+
Container: &v1.ContainerComponent{
419+
Container: v1.Container{
420+
VolumeMounts: []v1.VolumeMount{
421+
testingutil.GetFakeVolumeMount("comp2", "/path"),
422+
testingutil.GetFakeVolumeMount("comp2", "/path2"),
423+
testingutil.GetFakeVolumeMount("comp3", "/path"),
424+
},
425+
},
426+
},
427+
},
428+
},
429+
{
430+
Name: "comp2",
431+
ComponentUnion: v1.ComponentUnion{
432+
Volume: &v1.VolumeComponent{},
433+
},
434+
},
435+
{
436+
Name: "comp3",
437+
ComponentUnion: v1.ComponentUnion{
438+
Volume: &v1.VolumeComponent{},
439+
},
440+
},
441+
},
442+
},
443+
},
444+
},
445+
}
446+
447+
tests := []struct {
448+
name string
449+
componentToDelete string
450+
wantComponents []v1.Component
451+
wantErr bool
452+
}{
453+
{
454+
name: "Successfully delete a Component",
455+
componentToDelete: "comp3",
456+
wantComponents: []v1.Component{
457+
{
458+
Name: "comp2",
459+
ComponentUnion: v1.ComponentUnion{
460+
Container: &v1.ContainerComponent{
461+
Container: v1.Container{
462+
VolumeMounts: []v1.VolumeMount{
463+
testingutil.GetFakeVolumeMount("comp2", "/path"),
464+
testingutil.GetFakeVolumeMount("comp2", "/path2"),
465+
testingutil.GetFakeVolumeMount("comp3", "/path"),
466+
},
467+
},
468+
},
469+
},
470+
},
471+
{
472+
Name: "comp2",
473+
ComponentUnion: v1.ComponentUnion{
474+
Volume: &v1.VolumeComponent{},
475+
},
476+
},
477+
},
478+
wantErr: false,
479+
},
480+
{
481+
name: "Missing Component",
482+
componentToDelete: "comp12",
483+
wantErr: true,
484+
},
485+
}
486+
for _, tt := range tests {
487+
t.Run(tt.name, func(t *testing.T) {
488+
err := d.DeleteComponent(tt.componentToDelete)
489+
if (err != nil) != tt.wantErr {
490+
t.Errorf("DeleteComponent() error = %v, wantErr %v", err, tt.wantErr)
491+
} else if err == nil {
492+
assert.Equal(t, tt.wantComponents, d.Components, "The two values should be the same.")
493+
}
494+
})
495+
}
496+
497+
}

‎pkg/devfile/parser/data/v2/events.go

+14-4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ func (d *DevfileV2) GetEvents() v1.Events {
1616
// AddEvents adds the Events Object to the devfile's events
1717
// if the event is already defined in the devfile, error out
1818
func (d *DevfileV2) AddEvents(events v1.Events) error {
19+
20+
if d.Events == nil {
21+
d.Events = &v1.Events{}
22+
}
23+
1924
if len(events.PreStop) > 0 {
2025
if len(d.Events.PreStop) > 0 {
2126
return &common.FieldAlreadyExistError{Field: "pre stop"}
@@ -50,16 +55,21 @@ func (d *DevfileV2) AddEvents(events v1.Events) error {
5055
// UpdateEvents updates the devfile's events
5156
// it only updates the events passed to it
5257
func (d *DevfileV2) UpdateEvents(postStart, postStop, preStart, preStop []string) {
53-
if len(postStart) != 0 {
58+
59+
if d.Events == nil {
60+
d.Events = &v1.Events{}
61+
}
62+
63+
if postStart != nil {
5464
d.Events.PostStart = postStart
5565
}
56-
if len(postStop) != 0 {
66+
if postStop != nil {
5767
d.Events.PostStop = postStop
5868
}
59-
if len(preStart) != 0 {
69+
if preStart != nil {
6070
d.Events.PreStart = preStart
6171
}
62-
if len(preStop) != 0 {
72+
if preStop != nil {
6373
d.Events.PreStop = preStop
6474
}
6575
}

‎pkg/devfile/parser/data/v2/events_test.go

+46-15
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ func TestDevfile200_AddEvents(t *testing.T) {
1111

1212
tests := []struct {
1313
name string
14-
currentEvents v1.Events
14+
currentEvents *v1.Events
1515
newEvents v1.Events
1616
wantErr bool
1717
}{
1818
{
19-
name: "case 1: successfully add the events",
20-
currentEvents: v1.Events{
19+
name: "successfully add the events",
20+
currentEvents: &v1.Events{
2121
WorkspaceEvents: v1.WorkspaceEvents{
2222
PreStart: []string{"preStart1"},
2323
},
@@ -30,8 +30,18 @@ func TestDevfile200_AddEvents(t *testing.T) {
3030
wantErr: false,
3131
},
3232
{
33-
name: "case 2: event already present",
34-
currentEvents: v1.Events{
33+
name: "successfully add the events to empty devfile event",
34+
currentEvents: nil,
35+
newEvents: v1.Events{
36+
WorkspaceEvents: v1.WorkspaceEvents{
37+
PostStart: []string{"postStart1"},
38+
},
39+
},
40+
wantErr: false,
41+
},
42+
{
43+
name: "event already present",
44+
currentEvents: &v1.Events{
3545
WorkspaceEvents: v1.WorkspaceEvents{
3646
PreStart: []string{"preStart1"},
3747
},
@@ -50,18 +60,16 @@ func TestDevfile200_AddEvents(t *testing.T) {
5060
v1.Devfile{
5161
DevWorkspaceTemplateSpec: v1.DevWorkspaceTemplateSpec{
5262
DevWorkspaceTemplateSpecContent: v1.DevWorkspaceTemplateSpecContent{
53-
Events: &tt.currentEvents,
63+
Events: tt.currentEvents,
5464
},
5565
},
5666
},
5767
}
5868

59-
got := d.AddEvents(tt.newEvents)
69+
err := d.AddEvents(tt.newEvents)
6070

61-
if !tt.wantErr && got != nil {
62-
t.Errorf("TestDevfile200_AddEvents() unexpected error - %+v", got)
63-
} else if tt.wantErr && got == nil {
64-
t.Errorf("TestDevfile200_AddEvents() expected error but got nil")
71+
if (err != nil) != tt.wantErr {
72+
t.Errorf("DeleteCommand() error = %v, wantErr %v", err, tt.wantErr)
6573
}
6674

6775
})
@@ -72,16 +80,39 @@ func TestDevfile200_UpdateEvents(t *testing.T) {
7280

7381
tests := []struct {
7482
name string
75-
currentEvents v1.Events
83+
currentEvents *v1.Events
7684
newEvents v1.Events
7785
}{
7886
{
79-
name: "case 1: successfully add the events",
80-
currentEvents: v1.Events{
87+
name: "successfully add/update the events",
88+
currentEvents: &v1.Events{
89+
WorkspaceEvents: v1.WorkspaceEvents{
90+
PreStart: []string{"preStart1"},
91+
},
92+
},
93+
newEvents: v1.Events{
94+
WorkspaceEvents: v1.WorkspaceEvents{
95+
PreStart: []string{"preStart2"},
96+
PostStart: []string{"postStart2"},
97+
},
98+
},
99+
},
100+
{
101+
name: "successfully update the events to empty",
102+
currentEvents: &v1.Events{
81103
WorkspaceEvents: v1.WorkspaceEvents{
82104
PreStart: []string{"preStart1"},
83105
},
84106
},
107+
newEvents: v1.Events{
108+
WorkspaceEvents: v1.WorkspaceEvents{
109+
PreStart: []string{""},
110+
},
111+
},
112+
},
113+
{
114+
name: "successfully add the events to empty devfile events",
115+
currentEvents: nil,
85116
newEvents: v1.Events{
86117
WorkspaceEvents: v1.WorkspaceEvents{
87118
PreStart: []string{"preStart2"},
@@ -96,7 +127,7 @@ func TestDevfile200_UpdateEvents(t *testing.T) {
96127
v1.Devfile{
97128
DevWorkspaceTemplateSpec: v1.DevWorkspaceTemplateSpec{
98129
DevWorkspaceTemplateSpecContent: v1.DevWorkspaceTemplateSpecContent{
99-
Events: &tt.currentEvents,
130+
Events: tt.currentEvents,
100131
},
101132
},
102133
},

‎pkg/devfile/parser/data/v2/projects.go

+32
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,22 @@ func (d *DevfileV2) UpdateProject(project v1.Project) {
5555
}
5656
}
5757

58+
// DeleteProject removes the specified project
59+
func (d *DevfileV2) DeleteProject(name string) error {
60+
61+
for i := range d.Projects {
62+
if d.Projects[i].Name == name {
63+
d.Projects = append(d.Projects[:i], d.Projects[i+1:]...)
64+
return nil
65+
}
66+
}
67+
68+
return &common.FieldNotFoundError{
69+
Field: "project",
70+
Name: name,
71+
}
72+
}
73+
5874
//GetStarterProjects returns the DevfileStarterProject parsed from devfile
5975
func (d *DevfileV2) GetStarterProjects(options common.DevfileOptions) ([]v1.StarterProject, error) {
6076
if len(options.Filter) == 0 {
@@ -102,3 +118,19 @@ func (d *DevfileV2) UpdateStarterProject(project v1.StarterProject) {
102118
}
103119
}
104120
}
121+
122+
// DeleteStarterProject removes the specified starter project
123+
func (d *DevfileV2) DeleteStarterProject(name string) error {
124+
125+
for i := range d.StarterProjects {
126+
if d.StarterProjects[i].Name == name {
127+
d.StarterProjects = append(d.StarterProjects[:i], d.StarterProjects[i+1:]...)
128+
return nil
129+
}
130+
}
131+
132+
return &common.FieldNotFoundError{
133+
Field: "starter project",
134+
Name: name,
135+
}
136+
}

‎pkg/devfile/parser/data/v2/projects_test.go

+115
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66

77
v1 "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
88
"github.com/kylelemons/godebug/pretty"
9+
"github.com/stretchr/testify/assert"
910
)
1011

1112
func TestDevfile200_AddProjects(t *testing.T) {
@@ -188,6 +189,63 @@ func TestDevfile200_UpdateProject(t *testing.T) {
188189
}
189190
}
190191

192+
func TestDevfile200_DeleteProject(t *testing.T) {
193+
194+
d := &DevfileV2{
195+
v1.Devfile{
196+
DevWorkspaceTemplateSpec: v1.DevWorkspaceTemplateSpec{
197+
DevWorkspaceTemplateSpecContent: v1.DevWorkspaceTemplateSpecContent{
198+
Projects: []v1.Project{
199+
{
200+
Name: "nodejs",
201+
ClonePath: "/project",
202+
},
203+
{
204+
Name: "java",
205+
ClonePath: "/project2",
206+
},
207+
},
208+
},
209+
},
210+
},
211+
}
212+
213+
tests := []struct {
214+
name string
215+
projectToDelete string
216+
wantProjects []v1.Project
217+
wantErr bool
218+
}{
219+
{
220+
name: "Project successfully deleted",
221+
projectToDelete: "nodejs",
222+
wantProjects: []v1.Project{
223+
{
224+
Name: "java",
225+
ClonePath: "/project2",
226+
},
227+
},
228+
wantErr: false,
229+
},
230+
{
231+
name: "Project not found",
232+
projectToDelete: "nodejs1",
233+
wantErr: true,
234+
},
235+
}
236+
for _, tt := range tests {
237+
t.Run(tt.name, func(t *testing.T) {
238+
err := d.DeleteProject(tt.projectToDelete)
239+
if (err != nil) != tt.wantErr {
240+
t.Errorf("DeleteProject() error = %v, wantErr %v", err, tt.wantErr)
241+
} else if err == nil {
242+
assert.Equal(t, tt.wantProjects, d.Projects, "The two values should be the same.")
243+
}
244+
})
245+
}
246+
247+
}
248+
191249
func TestDevfile200_AddStarterProjects(t *testing.T) {
192250
currentProject := []v1.StarterProject{
193251
{
@@ -370,3 +428,60 @@ func TestDevfile200_UpdateStarterProject(t *testing.T) {
370428
})
371429
}
372430
}
431+
432+
func TestDevfile200_DeleteStarterProject(t *testing.T) {
433+
434+
d := &DevfileV2{
435+
v1.Devfile{
436+
DevWorkspaceTemplateSpec: v1.DevWorkspaceTemplateSpec{
437+
DevWorkspaceTemplateSpecContent: v1.DevWorkspaceTemplateSpecContent{
438+
StarterProjects: []v1.StarterProject{
439+
{
440+
Name: "nodejs",
441+
SubDir: "/project",
442+
},
443+
{
444+
Name: "java",
445+
SubDir: "/project2",
446+
},
447+
},
448+
},
449+
},
450+
},
451+
}
452+
453+
tests := []struct {
454+
name string
455+
starterProjectToDelete string
456+
wantStarterProjects []v1.StarterProject
457+
wantErr bool
458+
}{
459+
{
460+
name: "Starter Project successfully deleted",
461+
starterProjectToDelete: "nodejs",
462+
wantStarterProjects: []v1.StarterProject{
463+
{
464+
Name: "java",
465+
SubDir: "/project2",
466+
},
467+
},
468+
wantErr: false,
469+
},
470+
{
471+
name: "Starter Project not found",
472+
starterProjectToDelete: "nodejs1",
473+
wantErr: true,
474+
},
475+
}
476+
for _, tt := range tests {
477+
t.Run(tt.name, func(t *testing.T) {
478+
err := d.DeleteStarterProject(tt.starterProjectToDelete)
479+
if (err != nil) != tt.wantErr {
480+
t.Errorf("DeleteStarterProject() error = %v, wantErr %v", err, tt.wantErr)
481+
} else if err == nil {
482+
assert.Equal(t, tt.wantStarterProjects, d.StarterProjects, "The two values should be the same.")
483+
}
484+
})
485+
}
486+
487+
}

‎pkg/devfile/parser/data/v2/volumes.go

+46-56
Original file line numberDiff line numberDiff line change
@@ -8,99 +8,89 @@ import (
88
"github.com/devfile/library/pkg/devfile/parser/data/v2/common"
99
)
1010

11-
// AddVolume adds the volume to the devFile and mounts it to all the container components
12-
func (d *DevfileV2) AddVolume(volumeComponent v1.Component, path string) error {
13-
volumeExists := false
11+
// AddVolumeMounts adds the volume mounts to the specified container component
12+
func (d *DevfileV2) AddVolumeMounts(componentName string, volumeMounts []v1.VolumeMount) error {
1413
var pathErrorContainers []string
14+
found := false
1515
for _, component := range d.Components {
16-
if component.Container != nil {
17-
for _, volumeMount := range component.Container.VolumeMounts {
18-
if volumeMount.Path == path {
19-
var err = fmt.Errorf("another volume, %s, is mounted to the same path: %s, on the container: %s", volumeMount.Name, path, component.Name)
20-
pathErrorContainers = append(pathErrorContainers, err.Error())
16+
if component.Container != nil && component.Name == componentName {
17+
found = true
18+
for _, devfileVolumeMount := range component.Container.VolumeMounts {
19+
for _, volumeMount := range volumeMounts {
20+
if devfileVolumeMount.Path == volumeMount.Path {
21+
pathErrorContainers = append(pathErrorContainers, fmt.Sprintf("unable to mount volume %s, as another volume %s is mounted to the same path %s in the container %s", volumeMount.Name, devfileVolumeMount.Name, volumeMount.Path, component.Name))
22+
}
2123
}
2224
}
23-
component.Container.VolumeMounts = append(component.Container.VolumeMounts, v1.VolumeMount{
24-
Name: volumeComponent.Name,
25-
Path: path,
26-
})
27-
} else if component.Volume != nil && component.Name == volumeComponent.Name {
28-
volumeExists = true
29-
break
25+
if len(pathErrorContainers) == 0 {
26+
component.Container.VolumeMounts = append(component.Container.VolumeMounts, volumeMounts...)
27+
}
3028
}
3129
}
3230

33-
if volumeExists {
34-
return &common.FieldAlreadyExistError{
35-
Field: "volume",
36-
Name: volumeComponent.Name,
31+
if !found {
32+
return &common.FieldNotFoundError{
33+
Field: "container component",
34+
Name: componentName,
3735
}
3836
}
3937

4038
if len(pathErrorContainers) > 0 {
41-
return fmt.Errorf("errors while creating volume:\n%s", strings.Join(pathErrorContainers, "\n"))
39+
return fmt.Errorf("errors while adding volume mounts:\n%s", strings.Join(pathErrorContainers, "\n"))
4240
}
4341

44-
d.Components = append(d.Components, volumeComponent)
45-
4642
return nil
4743
}
4844

49-
// DeleteVolume removes the volume from the devFile and removes all the related volume mounts
50-
func (d *DevfileV2) DeleteVolume(name string) error {
45+
// DeleteVolumeMount deletes the volume mount from container components
46+
func (d *DevfileV2) DeleteVolumeMount(name string) error {
5147
found := false
52-
for i := len(d.Components) - 1; i >= 0; i-- {
53-
if d.Components[i].Container != nil {
54-
var tmp []v1.VolumeMount
55-
for _, volumeMount := range d.Components[i].Container.VolumeMounts {
56-
if volumeMount.Name != name {
57-
tmp = append(tmp, volumeMount)
48+
for i := range d.Components {
49+
if d.Components[i].Container != nil && d.Components[i].Name != name {
50+
// Volume Mounts can have multiple instances of a volume mounted at different paths
51+
// As arrays are rearraged/shifted for deletion, we lose one element every time there is a match
52+
// Looping backward is efficient, otherwise we would have to manually decrement counter
53+
// if we looped forward
54+
for j := len(d.Components[i].Container.VolumeMounts) - 1; j >= 0; j-- {
55+
if d.Components[i].Container.VolumeMounts[j].Name == name {
56+
found = true
57+
d.Components[i].Container.VolumeMounts = append(d.Components[i].Container.VolumeMounts[:j], d.Components[i].Container.VolumeMounts[j+1:]...)
5858
}
5959
}
60-
d.Components[i].Container.VolumeMounts = tmp
61-
} else if d.Components[i].Volume != nil {
62-
if d.Components[i].Name == name {
63-
found = true
64-
d.Components = append(d.Components[:i], d.Components[i+1:]...)
65-
}
6660
}
6761
}
6862

6963
if !found {
7064
return &common.FieldNotFoundError{
71-
Field: "volume",
65+
Field: "volume mount",
7266
Name: name,
7367
}
7468
}
7569

7670
return nil
7771
}
7872

79-
// GetVolumeMountPath gets the mount path of the required volume
80-
func (d *DevfileV2) GetVolumeMountPath(name string) (string, error) {
81-
volumeFound := false
82-
mountFound := false
83-
path := ""
73+
// GetVolumeMountPath gets the mount path of the specified volume mount from the specified container component
74+
func (d *DevfileV2) GetVolumeMountPath(mountName, componentName string) (string, error) {
75+
componentFound := false
8476

8577
for _, component := range d.Components {
86-
if component.Container != nil {
78+
if component.Container != nil && component.Name == componentName {
79+
componentFound = true
8780
for _, volumeMount := range component.Container.VolumeMounts {
88-
if volumeMount.Name == name {
89-
mountFound = true
90-
path = volumeMount.Path
81+
if volumeMount.Name == mountName {
82+
return volumeMount.Path, nil
9183
}
9284
}
93-
} else if component.Volume != nil {
94-
volumeFound = true
9585
}
9686
}
97-
if volumeFound && mountFound {
98-
return path, nil
99-
} else if !mountFound && volumeFound {
100-
return "", fmt.Errorf("volume not mounted to any component")
101-
}
102-
return "", &common.FieldNotFoundError{
103-
Field: "volume",
104-
Name: "name",
87+
88+
if !componentFound {
89+
return "", &common.FieldNotFoundError{
90+
Field: "container component",
91+
Name: componentName,
92+
}
10593
}
94+
95+
return "", fmt.Errorf("volume %s not mounted to component %s", mountName, componentName)
10696
}

‎pkg/devfile/parser/data/v2/volumes_test.go

+119-264
Large diffs are not rendered by default.

‎tests/v2/utils/library/test_utils.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ type DevfileFollower struct {
5555

5656
// AddCommand adds the specified command to the library data
5757
func (devfileFollower DevfileFollower) AddCommand(command schema.Command) error {
58-
return devfileFollower.LibraryData.AddCommands(command)
58+
return devfileFollower.LibraryData.AddCommands([]schema.Command{command})
5959
}
6060

6161
// UpdateCommand updates the specified command in the library data

0 commit comments

Comments
 (0)
Please sign in to comment.