Skip to content

Commit 94ab5db

Browse files
authored
Merge pull request #71 from maysunfaisal/newFilter
Update Devfile Library Get Options
2 parents eb1cd3b + 55a1b83 commit 94ab5db

14 files changed

+978
-103
lines changed

README.md

+46-23
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Devfile Parser Library
1+
# Devfile Library
22

33
## About
44

@@ -8,25 +8,43 @@ The Devfile Parser library is a Golang module that:
88
3. generates Kubernetes objects for the various devfile resources.
99
4. defines util functions for the devfile.
1010

11+
## Usage
12+
1113
The function documentation can be accessed via [pkg.go.dev](https://pkg.go.dev/github.com/devfile/library).
1214
1. To parse a devfile, visit pkg/devfile/parse.go
13-
```
14-
// Parses the devfile and validates the devfile data
15-
devfile, err := devfilePkg.ParseAndValidate(devfileLocation)
16-
17-
// To get all the components from the devfile
18-
components, err := devfile.Data.GetComponents(DevfileOptions{})
19-
20-
// To get all the components from the devfile with attributes tagged - tool: console-import & import: {strategy: Dockerfile}
21-
components, err := devfile.Data.GetComponents(DevfileOptions{
22-
Filter: map[string]interface{}{
23-
"tool": "console-import",
24-
"import": map[string]interface{}{
25-
"strategy": "Dockerfile",
26-
},
15+
```
16+
// Parses the devfile and validates the devfile data
17+
devfile, err := devfilePkg.ParseAndValidate(devfileLocation)
18+
19+
// To get all the components from the devfile
20+
components, err := devfile.Data.GetComponents(DevfileOptions{})
21+
22+
// To get all the components from the devfile with attributes tagged - tool: console-import
23+
// & import: {strategy: Dockerfile}
24+
components, err := devfile.Data.GetComponents(DevfileOptions{
25+
Filter: map[string]interface{}{
26+
"tool": "console-import",
27+
"import": map[string]interface{}{
28+
"strategy": "Dockerfile",
2729
},
28-
})
29-
```
30+
},
31+
})
32+
33+
// To get all the volume components
34+
components, err := devfile.Data.GetComponents(DevfileOptions{
35+
ComponentOptions: ComponentOptions{
36+
ComponentType: v1.VolumeComponentType,
37+
},
38+
})
39+
40+
// To get all the exec commands that belong to the build group
41+
commands, err := devfile.Data.GetCommands(DevfileOptions{
42+
CommandOptions: CommandOptions{
43+
CommandType: v1.ExecCommandType,
44+
CommandGroupKind: v1.BuildCommandGroupKind,
45+
},
46+
})
47+
```
3048
2. To get the Kubernetes objects from the devfile, visit pkg/devfile/generator/generators.go
3149
```
3250
// To get a slice of Kubernetes containers of type corev1.Container from the devfile component containers
@@ -43,8 +61,9 @@ The function documentation can be accessed via [pkg.go.dev](https://pkg.go.dev/g
4361
}
4462
deployment := generator.GetDeployment(deployParams)
4563
```
46-
47-
<br></br>
64+
65+
## Updating Library Schema
66+
4867
Run `updateApi.sh` can update to use latest `github.com/devfile/api` and update the schema saved under `pkg/devfile/parser/data`
4968

5069
The script also accepts version number as an argument to update devfile schema for a specific devfile version.
@@ -54,15 +73,19 @@ For example, run the following command will update devfile schema for 2.0.0
5473
```
5574
Running the script with no arguments will default to update the latest devfile version
5675

76+
## Projects using devfile/library
5777

58-
## Usage
59-
60-
In the future, the following projects will be consuming this library as a Golang dependency
78+
The following projects are consuming this library as a Golang dependency
6179

62-
* [Workspace Operator](https://github.com/devfile/devworkspace-operator)
6380
* [odo](https://github.com/openshift/odo)
6481
* [OpenShift Console](https://github.com/openshift/console)
6582

83+
In the future, [Workspace Operator](https://github.com/devfile/devworkspace-operator) will be the next consumer of devfile/library.
84+
6685
## Issues
6786

6887
Issues are tracked in the [devfile/api](https://github.com/devfile/api) repo with the label [area/library](https://github.com/devfile/api/issues?q=is%3Aopen+is%3Aissue+label%3Aarea%2Flibrary)
88+
89+
## Releases
90+
91+
For devfile/library releases, please check the release [page](https://github.com/devfile/library/releases).

pkg/devfile/parser/data/interface.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ type DevfileData interface {
5555
GetDevfileWorkspace() *v1.DevWorkspaceTemplateSpecContent
5656
SetDevfileWorkspace(content v1.DevWorkspaceTemplateSpecContent)
5757

58-
//utils
58+
// utils
5959
GetDevfileContainerComponents(common.DevfileOptions) ([]v1.Component, error)
6060
GetDevfileVolumeComponents(common.DevfileOptions) ([]v1.Component, error)
6161
}

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

+24-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package v2
22

33
import (
4+
"reflect"
45
"strings"
56

67
v1 "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
@@ -9,21 +10,40 @@ import (
910

1011
// GetCommands returns the slice of Command objects parsed from the Devfile
1112
func (d *DevfileV2) GetCommands(options common.DevfileOptions) ([]v1.Command, error) {
12-
if len(options.Filter) == 0 {
13+
14+
if reflect.DeepEqual(options, common.DevfileOptions{}) {
1315
return d.Commands, nil
1416
}
1517

1618
var commands []v1.Command
1719
for _, command := range d.Commands {
20+
// Filter Command Attributes
1821
filterIn, err := common.FilterDevfileObject(command.Attributes, options)
1922
if err != nil {
2023
return nil, err
24+
} else if !filterIn {
25+
continue
2126
}
2227

23-
if filterIn {
24-
command.Id = strings.ToLower(command.Id)
25-
commands = append(commands, command)
28+
// Filter Command Type - Exec, Composite, etc.
29+
commandType, err := common.GetCommandType(command)
30+
if err != nil {
31+
return nil, err
32+
}
33+
if options.CommandOptions.CommandType != "" && commandType != options.CommandOptions.CommandType {
34+
continue
2635
}
36+
37+
// Filter Command Group Kind - Run, Build, etc.
38+
commandGroup := common.GetGroup(command)
39+
// exclude conditions:
40+
// 1. options group is present and command group is present but does not match
41+
// 2. options group is present and command group is not present
42+
if options.CommandOptions.CommandGroupKind != "" && ((commandGroup != nil && options.CommandOptions.CommandGroupKind != commandGroup.Kind) || commandGroup == nil) {
43+
continue
44+
}
45+
46+
commands = append(commands, command)
2747
}
2848

2949
return commands, nil

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

+110-32
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@ import (
1212

1313
func TestDevfile200_GetCommands(t *testing.T) {
1414

15-
type args struct {
16-
name string
17-
}
1815
tests := []struct {
1916
name string
2017
currentCommands []v1.Command
@@ -23,7 +20,7 @@ func TestDevfile200_GetCommands(t *testing.T) {
2320
wantErr bool
2421
}{
2522
{
26-
name: "case 1: get the necessary commands",
23+
name: "Get all the commands",
2724
currentCommands: []v1.Command{
2825
{
2926
Id: "command1",
@@ -38,12 +35,11 @@ func TestDevfile200_GetCommands(t *testing.T) {
3835
},
3936
},
4037
},
41-
filterOptions: common.DevfileOptions{},
42-
wantCommands: []string{"command1", "command2"},
43-
wantErr: false,
38+
wantCommands: []string{"command1", "command2"},
39+
wantErr: false,
4440
},
4541
{
46-
name: "case 2: get the filtered commands",
42+
name: "Get the filtered commands",
4743
currentCommands: []v1.Command{
4844
{
4945
Id: "command1",
@@ -52,7 +48,15 @@ func TestDevfile200_GetCommands(t *testing.T) {
5248
"secondString": "secondStringValue",
5349
}),
5450
CommandUnion: v1.CommandUnion{
55-
Exec: &v1.ExecCommand{},
51+
Exec: &v1.ExecCommand{
52+
LabeledCommand: v1.LabeledCommand{
53+
BaseCommand: v1.BaseCommand{
54+
Group: &v1.CommandGroup{
55+
Kind: v1.BuildCommandGroupKind,
56+
},
57+
},
58+
},
59+
},
5660
},
5761
},
5862
{
@@ -65,18 +69,74 @@ func TestDevfile200_GetCommands(t *testing.T) {
6569
Composite: &v1.CompositeCommand{},
6670
},
6771
},
72+
{
73+
Id: "command3",
74+
Attributes: attributes.Attributes{}.FromStringMap(map[string]string{
75+
"firstString": "firstStringValue",
76+
"thirdString": "thirdStringValue",
77+
}),
78+
CommandUnion: v1.CommandUnion{
79+
Composite: &v1.CompositeCommand{
80+
LabeledCommand: v1.LabeledCommand{
81+
BaseCommand: v1.BaseCommand{
82+
Group: &v1.CommandGroup{
83+
Kind: v1.BuildCommandGroupKind,
84+
},
85+
},
86+
},
87+
},
88+
},
89+
},
90+
{
91+
Id: "command4",
92+
Attributes: attributes.Attributes{}.FromStringMap(map[string]string{
93+
"thirdString": "thirdStringValue",
94+
}),
95+
CommandUnion: v1.CommandUnion{
96+
Apply: &v1.ApplyCommand{
97+
LabeledCommand: v1.LabeledCommand{
98+
BaseCommand: v1.BaseCommand{
99+
Group: &v1.CommandGroup{
100+
Kind: v1.BuildCommandGroupKind,
101+
},
102+
},
103+
},
104+
},
105+
},
106+
},
107+
{
108+
Id: "command5",
109+
Attributes: attributes.Attributes{}.FromStringMap(map[string]string{
110+
"firstString": "firstStringValue",
111+
"thirdString": "thirdStringValue",
112+
}),
113+
CommandUnion: v1.CommandUnion{
114+
Composite: &v1.CompositeCommand{
115+
LabeledCommand: v1.LabeledCommand{
116+
BaseCommand: v1.BaseCommand{
117+
Group: &v1.CommandGroup{
118+
Kind: v1.RunCommandGroupKind,
119+
},
120+
},
121+
},
122+
},
123+
},
124+
},
68125
},
69126
filterOptions: common.DevfileOptions{
70127
Filter: map[string]interface{}{
71-
"firstString": "firstStringValue",
72-
"secondString": "secondStringValue",
128+
"firstString": "firstStringValue",
129+
},
130+
CommandOptions: common.CommandOptions{
131+
CommandGroupKind: v1.BuildCommandGroupKind,
132+
CommandType: v1.CompositeCommandType,
73133
},
74134
},
75-
wantCommands: []string{"command1"},
135+
wantCommands: []string{"command3"},
76136
wantErr: false,
77137
},
78138
{
79-
name: "case 3: get the wrong filtered commands",
139+
name: "Wrong filter for commands",
80140
currentCommands: []v1.Command{
81141
{
82142
Id: "command1",
@@ -104,8 +164,25 @@ func TestDevfile200_GetCommands(t *testing.T) {
104164
"firstStringIsWrong": "firstStringValue",
105165
},
106166
},
107-
wantCommands: []string{},
108-
wantErr: false,
167+
wantErr: false,
168+
},
169+
{
170+
name: "Invalid command type",
171+
currentCommands: []v1.Command{
172+
{
173+
Id: "command1",
174+
Attributes: attributes.Attributes{}.FromStringMap(map[string]string{
175+
"firstString": "firstStringValue",
176+
}),
177+
CommandUnion: v1.CommandUnion{},
178+
},
179+
},
180+
filterOptions: common.DevfileOptions{
181+
Filter: map[string]interface{}{
182+
"firstString": "firstStringValue",
183+
},
184+
},
185+
wantErr: true,
109186
},
110187
}
111188
for _, tt := range tests {
@@ -121,26 +198,27 @@ func TestDevfile200_GetCommands(t *testing.T) {
121198
}
122199

123200
commands, err := d.GetCommands(tt.filterOptions)
124-
if !tt.wantErr && err != nil {
125-
t.Errorf("TestDevfile200_GetCommands() unexpected error - %v", err)
126-
return
127-
} else if tt.wantErr && err == nil {
128-
t.Errorf("TestDevfile200_GetCommands() expected an error but got nil %v", commands)
129-
return
130-
} else if tt.wantErr && err != nil {
131-
return
132-
}
201+
if (err != nil) != tt.wantErr {
202+
t.Errorf("TestDevfile200_GetCommands() error = %v, wantErr %v", err, tt.wantErr)
203+
} else if err == nil {
204+
// confirm the length of actual vs expected
205+
if len(commands) != len(tt.wantCommands) {
206+
t.Errorf("TestDevfile200_GetCommands() error - length of expected commands is not the same as the length of actual commands")
207+
return
208+
}
133209

134-
for _, wantCommand := range tt.wantCommands {
135-
matched := false
136-
for _, devfileCommand := range commands {
137-
if wantCommand == devfileCommand.Id {
138-
matched = true
210+
// compare the command slices for content
211+
for _, wantCommand := range tt.wantCommands {
212+
matched := false
213+
for _, command := range commands {
214+
if wantCommand == command.Id {
215+
matched = true
216+
}
139217
}
140-
}
141218

142-
if !matched {
143-
t.Errorf("TestDevfile200_GetCommands() error - command %s not found in the devfile", wantCommand)
219+
if !matched {
220+
t.Errorf("TestDevfile200_GetCommands() error - command %s not found in the devfile", wantCommand)
221+
}
144222
}
145223
}
146224
})

pkg/devfile/parser/data/v2/common/command_helper.go

+19
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package common
22

33
import (
4+
"fmt"
5+
46
v1 "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
57
)
68

@@ -47,3 +49,20 @@ func GetExecWorkingDir(dc v1.Command) string {
4749

4850
return ""
4951
}
52+
53+
// GetCommandType returns the command type of a given command
54+
func GetCommandType(command v1.Command) (v1.CommandType, error) {
55+
switch {
56+
case command.Apply != nil:
57+
return v1.ApplyCommandType, nil
58+
case command.Composite != nil:
59+
return v1.CompositeCommandType, nil
60+
case command.Exec != nil:
61+
return v1.ExecCommandType, nil
62+
case command.Custom != nil:
63+
return v1.CustomCommandType, nil
64+
65+
default:
66+
return "", fmt.Errorf("unknown command type")
67+
}
68+
}

0 commit comments

Comments
 (0)