11package serverless
22
33import (
4- "crypto/sha256"
5- "encoding/hex"
6- "encoding/json"
7- "fmt"
8- "os/exec"
9- "path/filepath"
10- "runtime"
4+ "errors"
115 "strings"
126
13- "golang.org/x/mod/sumdb/dirhash"
14-
157 "github.com/aws/aws-sdk-go/aws"
168 "github.com/aws/aws-sdk-go/aws/awserr"
179 "github.com/aws/aws-sdk-go/aws/session"
@@ -20,104 +12,6 @@ import (
2012 "github.com/hashicorp/terraform-plugin-sdk/helper/schema"
2113)
2214
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-
12115func resourceDeployment () * schema.Resource {
12216 return & schema.Resource {
12317 Create : resourceDeploymentCreate ,
@@ -167,66 +61,46 @@ func resourceDeployment() *schema.Resource {
16761 },
16862
16963 // 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
17165 // we only deploy after the user has run `sls package` again.
17266 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 )
17768
178- configJson , err := getServerlessConfig (configDir , serverlessBinDir )
17969 if err != nil {
18070 return false
18171 }
18272
183- hash , err := hashServerlessDir (configDir , packageDir , d .Id (), configJson )
73+ changed , err := serverless .Hash ()
74+
18475 if err != nil {
18576 return false
18677 }
18778
188- return hash != currentHash
79+ return changed
18980 }),
19081 }
19182}
19283
19384func 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 )
19986
200- configJson , err := getServerlessConfig (configDir , serverlessBinDir )
20187 if err != nil {
20288 return err
20389 }
20490
205- id , err := getServiceName (configJson )
206- if err != nil {
207- return err
208- }
209- d .SetId (id )
91+ serviceName , ok := serverless .config ["service" ].(string )
21092
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" )
21495 }
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 {
217100 return err
218101 }
219102
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 {
230104 return err
231105 }
232106
@@ -273,24 +147,16 @@ func resourceDeploymentUpdate(d *schema.ResourceData, m interface{}) error {
273147}
274148
275149func 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 )
281151
282- err := runServerless (& serverlessParams {
283- command : "remove" ,
284- serverlessBinDir : serverlessBinDir ,
285- configDir : configDir ,
286- packageDir : packageDir ,
287- stage : stage ,
288- args : args ,
289- })
290152 if err != nil {
291153 return err
292154 }
293155
156+ if err := serverless .Remove (); err != nil {
157+ return err
158+ }
159+
294160 d .SetId ("" )
295161
296162 return nil
0 commit comments