1
1
package serverless
2
2
3
3
import (
4
- "crypto/sha256"
5
- "encoding/hex"
6
- "encoding/json"
7
- "fmt"
8
- "os/exec"
9
- "path/filepath"
10
- "runtime"
4
+ "errors"
11
5
"strings"
12
6
13
- "golang.org/x/mod/sumdb/dirhash"
14
-
15
7
"github.com/aws/aws-sdk-go/aws"
16
8
"github.com/aws/aws-sdk-go/aws/awserr"
17
9
"github.com/aws/aws-sdk-go/aws/session"
@@ -20,104 +12,6 @@ import (
20
12
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
21
13
)
22
14
23
- type serverlessConfig struct {
24
- Service string
25
- }
26
-
27
- func getServerlessConfig (configDir string , serverlessBinDir string ) ([]byte , error ) {
28
- cmd := exec .Command (getServerlessBin (configDir , serverlessBinDir ), "print" , "--format" , "json" )
29
- cmd .Dir = configDir
30
-
31
- output , err := cmd .CombinedOutput ()
32
- if err != nil {
33
- return []byte {}, fmt .Errorf ("%v\n %w" , string (output ), err )
34
- }
35
-
36
- return output , nil
37
- }
38
-
39
- func getServiceName (configJson []byte ) (string , error ) {
40
- config := serverlessConfig {}
41
- err := json .Unmarshal ([]byte (configJson ), & config )
42
-
43
- return config .Service , err
44
- }
45
-
46
- // Create a hash of the Serverless config and the Serverless zip archive.
47
- // Note that dirhash.HashZip ignores all zip metadata and correctly hashes
48
- // contents of the archive.
49
- func hashServerlessDir (
50
- configDir string ,
51
- packagePath string ,
52
- serviceName string ,
53
- configJson []byte ,
54
- ) (string , error ) {
55
- absolutePackagePath := filepath .Join (configDir , packagePath )
56
- zipPath := filepath .Join (absolutePackagePath , fmt .Sprintf ("%s.zip" , serviceName ))
57
-
58
- zipHash , err := dirhash .HashZip (zipPath , dirhash .Hash1 )
59
- if err != nil {
60
- return "" , err
61
- }
62
-
63
- configHashBytes := sha256 .Sum256 (configJson )
64
- configHash := hex .EncodeToString (configHashBytes [:])
65
-
66
- return strings .Join ([]string {zipHash , configHash }, "-" ), nil
67
- }
68
-
69
- func getServerlessBin (configDir string , binPath string ) string {
70
- if binPath == "" {
71
- binPath = filepath .Join (configDir , "node_modules" , ".bin" )
72
- }
73
- suffix := ""
74
- if runtime .GOOS == "windows" {
75
- suffix = ".cmd"
76
- }
77
- return filepath .Join (binPath , fmt .Sprintf ("serverless%s" , suffix ))
78
- }
79
-
80
- type serverlessParams struct {
81
- command string
82
- serverlessBinDir string
83
- configDir string
84
- packageDir string
85
- stage string
86
- args []interface {}
87
- }
88
-
89
- func runServerless (params * serverlessParams ) error {
90
- stringArgs := make ([]string , len (params .args ))
91
- for i , v := range stringArgs {
92
- stringArgs [i ] = fmt .Sprint (v )
93
- }
94
-
95
- requiredArgs := []string {
96
- params .command ,
97
- "-s" ,
98
- params .stage ,
99
- }
100
-
101
- if params .command == "deploy" || params .command == "package" {
102
- requiredArgs = append (requiredArgs , "-p" , params .packageDir )
103
- }
104
-
105
- stringArgs = append (
106
- requiredArgs ,
107
- stringArgs ... ,
108
- )
109
-
110
- cmd := exec .Command (getServerlessBin (params .configDir , params .serverlessBinDir ), stringArgs ... )
111
- cmd .Dir = params .configDir
112
-
113
- output , err := cmd .CombinedOutput ()
114
- if err != nil {
115
- return fmt .Errorf ("%v\n %w" , string (output ), err )
116
- }
117
-
118
- return nil
119
- }
120
-
121
15
func resourceDeployment () * schema.Resource {
122
16
return & schema.Resource {
123
17
Create : resourceDeploymentCreate ,
@@ -167,66 +61,46 @@ func resourceDeployment() *schema.Resource {
167
61
},
168
62
169
63
// Only trigger a deploy if either the Serverless config or Serverless zip archive has changed.
170
- // `sls package` isn't deterministic according to experiments, so in practive this means that
64
+ // `sls package` isn't deterministic according to experiments, so in practice this means that
171
65
// we only deploy after the user has run `sls package` again.
172
66
CustomizeDiff : customdiff .ComputedIf ("package_hash" , func (d * schema.ResourceDiff , meta interface {}) bool {
173
- configDir := d .Get ("config_dir" ).(string )
174
- packageDir := d .Get ("package_dir" ).(string )
175
- serverlessBinDir := d .Get ("serverless_bin_dir" ).(string )
176
- currentHash := d .Get ("package_hash" ).(string )
67
+ serverless , err := NewServerless (d )
177
68
178
- configJson , err := getServerlessConfig (configDir , serverlessBinDir )
179
69
if err != nil {
180
70
return false
181
71
}
182
72
183
- hash , err := hashServerlessDir (configDir , packageDir , d .Id (), configJson )
73
+ changed , err := serverless .Hash ()
74
+
184
75
if err != nil {
185
76
return false
186
77
}
187
78
188
- return hash != currentHash
79
+ return changed
189
80
}),
190
81
}
191
82
}
192
83
193
84
func resourceDeploymentCreate (d * schema.ResourceData , m interface {}) error {
194
- configDir := d .Get ("config_dir" ).(string )
195
- serverlessBinDir := d .Get ("serverless_bin_dir" ).(string )
196
- packageDir := d .Get ("package_dir" ).(string )
197
- stage := d .Get ("stage" ).(string )
198
- args := d .Get ("args" ).([]interface {})
85
+ serverless , err := NewServerless (d )
199
86
200
- configJson , err := getServerlessConfig (configDir , serverlessBinDir )
201
87
if err != nil {
202
88
return err
203
89
}
204
90
205
- id , err := getServiceName (configJson )
206
- if err != nil {
207
- return err
208
- }
209
- d .SetId (id )
91
+ serviceName , ok := serverless .config ["service" ].(string )
210
92
211
- hash , err := hashServerlessDir (configDir , packageDir , id , configJson )
212
- if err != nil {
213
- return err
93
+ if ! ok {
94
+ return errors .New ("service name was not found in serverless config" )
214
95
}
215
- err = d .Set ("package_hash" , hash )
216
- if err != nil {
96
+
97
+ d .SetId (serviceName )
98
+
99
+ if err := d .Set ("package_hash" , serverless .hash ); err != nil {
217
100
return err
218
101
}
219
102
220
- err = runServerless (& serverlessParams {
221
- command : "deploy" ,
222
- serverlessBinDir : serverlessBinDir ,
223
- configDir : configDir ,
224
- packageDir : packageDir ,
225
- stage : stage ,
226
- args : args ,
227
- })
228
-
229
- if err != nil {
103
+ if err := serverless .Deploy (); err != nil {
230
104
return err
231
105
}
232
106
@@ -273,24 +147,16 @@ func resourceDeploymentUpdate(d *schema.ResourceData, m interface{}) error {
273
147
}
274
148
275
149
func resourceDeploymentDelete (d * schema.ResourceData , m interface {}) error {
276
- configDir := d .Get ("config_dir" ).(string )
277
- serverlessBinDir := d .Get ("serverless_bin_dir" ).(string )
278
- packageDir := d .Get ("package_dir" ).(string )
279
- stage := d .Get ("stage" ).(string )
280
- args := d .Get ("args" ).([]interface {})
150
+ serverless , err := NewServerless (d )
281
151
282
- err := runServerless (& serverlessParams {
283
- command : "remove" ,
284
- serverlessBinDir : serverlessBinDir ,
285
- configDir : configDir ,
286
- packageDir : packageDir ,
287
- stage : stage ,
288
- args : args ,
289
- })
290
152
if err != nil {
291
153
return err
292
154
}
293
155
156
+ if err := serverless .Remove (); err != nil {
157
+ return err
158
+ }
159
+
294
160
d .SetId ("" )
295
161
296
162
return nil
0 commit comments