7
7
logger "github.com/sirupsen/logrus"
8
8
"gopkg.in/yaml.v3"
9
9
"path"
10
- "sort "
10
+ "strconv "
11
11
"strings"
12
12
"time"
13
13
@@ -37,7 +37,7 @@ var ValidateStackHeadVersionTask = Task{
37
37
38
38
var PrepareProjectTask = func (projectDefinition * project.Project ) Task {
39
39
return Task {
40
- Name : fmt .Sprintf ("Preparing project structure " ),
40
+ Name : fmt .Sprintf ("Preparing deployment " ),
41
41
Run : func (r * Task ) error {
42
42
r .PrintLn ("Create project directory if not exists" )
43
43
if err := xfs .CreateFolder ("ssh://" + projectDefinition .GetDirectoryPath ()); err != nil {
@@ -47,40 +47,25 @@ var PrepareProjectTask = func(projectDefinition *project.Project) Task {
47
47
return err
48
48
}
49
49
50
+ r .PrintLn ("Lookup previous deployments" )
50
51
// Find latest deployment
51
- files , err := xfs . ListFolders ( "ssh://" + projectDefinition . GetDeploymentsPath () )
52
+ latestDeployment , err := system . GetLatestDeployment ( projectDefinition )
52
53
if err != nil {
53
54
return err
54
55
}
55
- if files != nil {
56
- // newest files at the top
57
- sort .Slice (files , func (i , j int ) bool {
58
- return files [i ].ModTime ().After (files [j ].ModTime ())
59
- })
60
- for _ , file := range files {
61
- if file .IsDir () && system .MatchDeploymentNaming (file .Name ()) {
62
- fullPath := path .Join (projectDefinition .GetDeploymentsPath (), file .Name ())
63
- latestDeployment , err := system .GetDeploymentByPath (fullPath )
64
- if err != nil {
65
- return err
66
- }
67
- if ! latestDeployment .RolledBack {
68
- latestDeployment .Project = system .Context .Project
69
- system .Context .LatestDeployment = latestDeployment
70
- break
71
- }
72
- }
73
- }
74
- }
56
+ system .Context .LatestDeployment = latestDeployment
57
+ oldVersion := "N/A"
75
58
newVersion := 1
76
59
if system .Context .LatestDeployment != nil {
60
+ oldVersion = "v" + strconv .Itoa (system .Context .LatestDeployment .Version )
77
61
newVersion = system .Context .LatestDeployment .Version + 1
78
62
}
79
63
system .Context .CurrentDeployment = system.Deployment {
80
64
Version : newVersion ,
81
65
DateStart : time .Now (),
82
66
Project : system .Context .Project ,
83
67
}
68
+ r .PrintLn (fmt .Sprintf ("Previous deployment: %s, new deployment: v%d" , oldVersion , newVersion ))
84
69
85
70
// Create folder for new deployment
86
71
if err := xfs .CreateFolder ("ssh://" + system .Context .CurrentDeployment .GetPath ()); err != nil {
@@ -104,6 +89,7 @@ var CollectResourcesTask = func(projectDefinition *project.Project) Task {
104
89
if module .GetConfig ().Type == "plugin" {
105
90
continue
106
91
}
92
+ r .PrintLn ("Collecting from " + module .GetConfig ().Name )
107
93
moduleSettings := system .GetModuleSettings (module .GetConfig ().Name )
108
94
if err := module .Deploy (moduleSettings ); err != nil {
109
95
return err
@@ -132,7 +118,7 @@ var RollbackResources = Task{
132
118
}
133
119
for _ , resource := range resourceGroup .Resources {
134
120
spinner := r .TaskRunner .GetNewSubtaskSpinner (resource .ToString (true ))
135
- matched , err := system .RollbackResourceOperation (resource )
121
+ matched , err := system .RollbackResourceOperation (resource , false )
136
122
if ! matched || err == nil {
137
123
if spinner != nil {
138
124
spinner .Complete ()
@@ -156,28 +142,22 @@ var RollbackResources = Task{
156
142
return fmt .Errorf ("The following errors occurred:\n " + strings .Join (system .Context .CurrentDeployment .RollbackErrors , "\n " ))
157
143
}
158
144
159
- // Delete deployment version
160
- //if err := xfs.DeleteFolder("ssh://"+system.Context.CurrentDeployment.GetPath(), true); err != nil {
161
- // return fmt.Errorf("unable to remove deployment folder: " + err.Error())
162
- //}
163
-
164
145
return nil
165
146
},
166
147
}
167
148
168
149
var CreateResources = Task {
169
150
Name : "Creating resources" ,
170
151
Run : func (r * Task ) error {
171
- var errors []error
152
+ var errors []string
172
153
var uncompletedSpinners []* ysmrr.Spinner
173
154
174
155
for _ , resourceGroup := range system .Context .CurrentDeployment .ResourceGroups {
175
156
for _ , resource := range resourceGroup .Resources {
176
157
spinner := r .TaskRunner .GetNewSubtaskSpinner (resource .ToString (false ))
177
- processed , err := system .ApplyResourceOperation (resource )
158
+ processed , err := system .ApplyResourceOperation (resource , false )
178
159
if err != nil {
179
160
rollback = true
180
- errors = append (errors , err )
181
161
if spinner != nil {
182
162
spinner .UpdateMessage (err .Error ())
183
163
spinner .Error ()
@@ -201,7 +181,7 @@ var CreateResources = Task{
201
181
spinner .Error ()
202
182
}
203
183
rollback = true
204
- errors = append (errors , fmt .Errorf ("Unable to complete resource creation: %s" , err ))
184
+ errors = append (errors , fmt .Sprintf ("Unable to complete resource creation: %s" , err ))
205
185
}
206
186
}
207
187
if ! rollback {
@@ -219,24 +199,80 @@ var CreateResources = Task{
219
199
}
220
200
errorMessages := []string {"The following errors occurred:" }
221
201
for _ , err2 := range errors {
222
- errorMessages = append (errorMessages , "- " + err2 . Error () )
202
+ errorMessages = append (errorMessages , "- " + err2 )
223
203
}
224
204
return fmt .Errorf (strings .Join (errorMessages , "\n " ))
225
205
},
226
206
}
227
207
208
+ func reverse [S ~ []E , E any ](s S ) {
209
+ for i , j := 0 , len (s )- 1 ; i < j ; i , j = i + 1 , j - 1 {
210
+ s [i ], s [j ] = s [j ], s [i ]
211
+ }
212
+ }
213
+
214
+ var RemoveResources = func (latestDeployment * system.Deployment ) Task {
215
+ return Task {
216
+ Name : "Removing project resources" ,
217
+ Run : func (r * Task ) error {
218
+ var uncompletedSpinners []* ysmrr.Spinner
219
+
220
+ reverse (latestDeployment .ResourceGroups )
221
+ for _ , group := range latestDeployment .ResourceGroups {
222
+ reverse (group .Resources )
223
+ for _ , resource := range group .Resources {
224
+ if resource .ExternalResource {
225
+ resource .Operation = system .OperationDelete
226
+ spinner := r .TaskRunner .GetNewSubtaskSpinner (resource .ToString (false ))
227
+ if processed , err := system .PerformOperation (resource , true ); err != nil {
228
+ if err != nil {
229
+ if spinner != nil {
230
+ spinner .UpdateMessage (err .Error ())
231
+ spinner .Error ()
232
+ }
233
+ return err
234
+ }
235
+ if spinner != nil {
236
+ if processed {
237
+ spinner .Complete ()
238
+ } else {
239
+ // uncompleted spinners are resolved when resource group finishes
240
+ uncompletedSpinners = append (uncompletedSpinners , spinner )
241
+ }
242
+ }
243
+ }
244
+ }
245
+ }
246
+ for _ , spinner := range uncompletedSpinners {
247
+ spinner .Complete ()
248
+ }
249
+ }
250
+ return nil
251
+ },
252
+ }
253
+ }
254
+
228
255
var FinalizeDeployment = Task {
229
256
Name : "Finalizing deployment" ,
230
257
Run : func (r * Task ) error {
258
+ // set deployment end date
231
259
system .Context .CurrentDeployment .DateEnd = time .Now ()
232
- resourcesPath := path .Join (system .Context .CurrentDeployment .GetPath (), "deployment.yaml" )
260
+
261
+ // save deployment.yaml file
233
262
yamlString , err := yaml .Marshal (system .Context .CurrentDeployment )
234
263
if err != nil {
235
264
return err
236
265
}
237
- if err = xfs .WriteFile ("ssh://" + resourcesPath , string (yamlString )); err != nil {
266
+ if err = xfs .WriteFile ("ssh://" + path . Join ( system . Context . CurrentDeployment . GetPath (), "deployment.yaml" ) , string (yamlString )); err != nil {
238
267
return err
239
268
}
269
+
270
+ // update current symlink if deployment was successful
271
+ if ! system .Context .CurrentDeployment .RolledBack {
272
+ if _ , err := system .SimpleRemoteRun ("ln" , system.RemoteRunOpts {Args : []string {"-sfn " + system .Context .CurrentDeployment .GetPath () + " " + path .Join (system .Context .CurrentDeployment .Project .GetDeploymentsPath (), "current" )}}); err != nil {
273
+ return fmt .Errorf ("Unable to symlink current deployment: " + err .Error ())
274
+ }
275
+ }
240
276
return nil
241
277
},
242
278
}
0 commit comments