1 package devstate
2
3 import (
4 "fmt"
5
6 "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
7 "github.com/devfile/library/v2/pkg/devfile/parser/data/v2/common"
8 . "github.com/redhat-developer/odo/pkg/apiserver-gen/go"
9 )
10
11 func (o *DevfileState) AddExecCommand(name string, component string, commandLine string, workingDir string, hotReloadCapable bool) (DevfileContent, error) {
12 command := v1alpha2.Command{
13 Id: name,
14 CommandUnion: v1alpha2.CommandUnion{
15 Exec: &v1alpha2.ExecCommand{
16 Component: component,
17 CommandLine: commandLine,
18 WorkingDir: workingDir,
19 HotReloadCapable: &hotReloadCapable,
20 },
21 },
22 }
23 err := o.Devfile.Data.AddCommands([]v1alpha2.Command{command})
24 if err != nil {
25 return DevfileContent{}, err
26 }
27 return o.GetContent()
28 }
29
30 func (o *DevfileState) PatchExecCommand(name string, component string, commandLine string, workingDir string, hotReloadCapable bool) (DevfileContent, error) {
31 found, err := o.Devfile.Data.GetCommands(common.DevfileOptions{
32 CommandOptions: common.CommandOptions{
33 CommandType: v1alpha2.ExecCommandType,
34 },
35 FilterByName: name,
36 })
37 if err != nil {
38 return DevfileContent{}, err
39 }
40 if len(found) != 1 {
41 return DevfileContent{}, fmt.Errorf("%d Exec Command found with name %q", len(found), name)
42 }
43
44 command := found[0]
45 command.Exec.Component = component
46 command.Exec.CommandLine = commandLine
47 command.Exec.WorkingDir = workingDir
48 command.Exec.HotReloadCapable = &hotReloadCapable
49 err = o.Devfile.Data.UpdateCommand(command)
50 if err != nil {
51 return DevfileContent{}, err
52 }
53 return o.GetContent()
54 }
55
56 func (o *DevfileState) AddApplyCommand(name string, component string) (DevfileContent, error) {
57 command := v1alpha2.Command{
58 Id: name,
59 CommandUnion: v1alpha2.CommandUnion{
60 Apply: &v1alpha2.ApplyCommand{
61 Component: component,
62 },
63 },
64 }
65 err := o.Devfile.Data.AddCommands([]v1alpha2.Command{command})
66 if err != nil {
67 return DevfileContent{}, err
68 }
69 return o.GetContent()
70 }
71
72 func (o *DevfileState) PatchApplyCommand(name string, component string) (DevfileContent, error) {
73 found, err := o.Devfile.Data.GetCommands(common.DevfileOptions{
74 CommandOptions: common.CommandOptions{
75 CommandType: v1alpha2.ApplyCommandType,
76 },
77 FilterByName: name,
78 })
79 if err != nil {
80 return DevfileContent{}, err
81 }
82 if len(found) != 1 {
83 return DevfileContent{}, fmt.Errorf("%d Apply Command found with name %q", len(found), name)
84 }
85
86 command := found[0]
87 command.Apply.Component = component
88 err = o.Devfile.Data.UpdateCommand(command)
89 if err != nil {
90 return DevfileContent{}, err
91 }
92 return o.GetContent()
93 }
94
95 func (o *DevfileState) AddCompositeCommand(name string, parallel bool, commands []string) (DevfileContent, error) {
96 command := v1alpha2.Command{
97 Id: name,
98 CommandUnion: v1alpha2.CommandUnion{
99 Composite: &v1alpha2.CompositeCommand{
100 Parallel: ¶llel,
101 Commands: commands,
102 },
103 },
104 }
105 err := o.Devfile.Data.AddCommands([]v1alpha2.Command{command})
106 if err != nil {
107 return DevfileContent{}, err
108 }
109 return o.GetContent()
110 }
111
112 func (o *DevfileState) PatchCompositeCommand(name string, parallel bool, commands []string) (DevfileContent, error) {
113 found, err := o.Devfile.Data.GetCommands(common.DevfileOptions{
114 CommandOptions: common.CommandOptions{
115 CommandType: v1alpha2.CompositeCommandType,
116 },
117 FilterByName: name,
118 })
119 if err != nil {
120 return DevfileContent{}, err
121 }
122 if len(found) != 1 {
123 return DevfileContent{}, fmt.Errorf("%d Composite Command found with name %q", len(found), name)
124 }
125
126 command := found[0]
127 command.Composite.Parallel = ¶llel
128 command.Composite.Commands = commands
129 err = o.Devfile.Data.UpdateCommand(command)
130 if err != nil {
131 return DevfileContent{}, err
132 }
133 return o.GetContent()
134 }
135
136 func (o *DevfileState) DeleteCommand(name string) (DevfileContent, error) {
137 err := o.checkCommandUsed(name)
138 if err != nil {
139 return DevfileContent{}, fmt.Errorf("error deleting command %q: %w", name, err)
140 }
141 err = o.Devfile.Data.DeleteCommand(name)
142 if err != nil {
143 return DevfileContent{}, err
144 }
145 return o.GetContent()
146 }
147
148 func (o *DevfileState) checkCommandUsed(name string) error {
149 commands, err := o.Devfile.Data.GetCommands(common.DevfileOptions{
150 CommandOptions: common.CommandOptions{
151 CommandType: v1alpha2.CompositeCommandType,
152 },
153 })
154 if err != nil {
155 return err
156 }
157 for _, command := range commands {
158 for _, subcommand := range command.Composite.Commands {
159 if subcommand == name {
160 return fmt.Errorf("command %q is used by composite command %q", name, command.Id)
161 }
162 }
163 }
164 return nil
165 }
166
167 func (o *DevfileState) MoveCommand(previousGroup, newGroup string, previousIndex, newIndex int) (DevfileContent, error) {
168 commands, err := o.Devfile.Data.GetCommands(common.DevfileOptions{})
169 if err != nil {
170 return DevfileContent{}, err
171 }
172
173 commandsByGroup, err := subMoveCommand(commands, previousGroup, newGroup, previousIndex, newIndex)
174 if err != nil {
175 return DevfileContent{}, err
176 }
177
178
179 for i := len(commands) - 1; i >= 0; i-- {
180 err = o.Devfile.Data.DeleteCommand(commands[i].Id)
181 if err != nil {
182 return DevfileContent{}, err
183 }
184 }
185
186 for _, group := range []string{"build", "run", "test", "debug", "deploy", ""} {
187 err := o.Devfile.Data.AddCommands(commandsByGroup[group])
188 if err != nil {
189 return DevfileContent{}, err
190 }
191 }
192 return o.GetContent()
193 }
194
195 func subMoveCommand(commands []v1alpha2.Command, previousGroup, newGroup string, previousIndex, newIndex int) (map[string][]v1alpha2.Command, error) {
196 commandsByGroup := map[string][]v1alpha2.Command{}
197
198 for _, command := range commands {
199 group := GetGroup(command)
200 commandsByGroup[group] = append(commandsByGroup[group], command)
201 }
202
203 if len(commandsByGroup[previousGroup]) <= previousIndex {
204 return nil, fmt.Errorf("unable to find command at index #%d in group %q", previousIndex, previousGroup)
205 }
206
207 commandToMove := commandsByGroup[previousGroup][previousIndex]
208 SetGroup(&commandToMove, newGroup)
209
210 commandsByGroup[previousGroup] = append(
211 commandsByGroup[previousGroup][:previousIndex],
212 commandsByGroup[previousGroup][previousIndex+1:]...,
213 )
214
215 end := append([]v1alpha2.Command{}, commandsByGroup[newGroup][newIndex:]...)
216 commandsByGroup[newGroup] = append(commandsByGroup[newGroup][:newIndex], commandToMove)
217 commandsByGroup[newGroup] = append(commandsByGroup[newGroup], end...)
218
219 return commandsByGroup, nil
220 }
221
222 func (o *DevfileState) SetDefaultCommand(commandName string, group string) (DevfileContent, error) {
223 commands, err := o.Devfile.Data.GetCommands(common.DevfileOptions{})
224 if err != nil {
225 return DevfileContent{}, err
226 }
227
228 for i, command := range commands {
229 if GetGroup(command) == group {
230 isDefault := command.Id == commandName
231 SetDefault(&commands[i], isDefault)
232 err = o.Devfile.Data.UpdateCommand(command)
233 if err != nil {
234 return DevfileContent{}, err
235 }
236 }
237 }
238 return o.GetContent()
239 }
240
241 func (o *DevfileState) UnsetDefaultCommand(commandName string) (DevfileContent, error) {
242 commands, err := o.Devfile.Data.GetCommands(common.DevfileOptions{})
243 if err != nil {
244 return DevfileContent{}, err
245 }
246
247 for i, command := range commands {
248 if command.Id == commandName {
249 SetDefault(&commands[i], false)
250 err = o.Devfile.Data.UpdateCommand(command)
251 if err != nil {
252 return DevfileContent{}, err
253 }
254 break
255 }
256 }
257 return o.GetContent()
258 }
259
View as plain text