forked from aws/aws-sam-cli
-
Notifications
You must be signed in to change notification settings - Fork 0
/
invoke.go
149 lines (124 loc) · 3.8 KB
/
invoke.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package main
import (
"fmt"
"log"
"os"
"path/filepath"
"io/ioutil"
"io"
"sync"
"github.com/awslabs/goformation"
"github.com/awslabs/goformation/intrinsics"
"github.com/codegangsta/cli"
)
func invoke(c *cli.Context) {
// Setup the logger
stdout := io.Writer(os.Stdout)
stderr := io.Writer(os.Stderr)
logarg := c.String("log-file") // matches the definition in main.go
if len(logarg) > 0 {
if logFile, err := os.Create(logarg); err == nil {
stderr = io.Writer(logFile)
stdout = io.Writer(logFile)
log.SetOutput(stderr)
} else {
log.Fatalf("Failed to open log file %s: %s\n", c.String("log"), err)
}
}
filename := getTemplateFilename(c.String("template"))
template, err := goformation.OpenWithOptions(filename, &intrinsics.ProcessorOptions{
ParameterOverrides: parseParameters(c.String("parameter-values")),
})
if err != nil {
log.Fatalf("Failed to parse template: %s\n", err)
}
log.Printf("Successfully parsed %s\n", filename)
name := c.Args().First()
// Find the specified function in the SAM template. Either check for a function whose
// logical ID matches the first CLI argument, or if they only have a single function
// defined, and don't specify a name, then just use that function.
functions := template.GetAllAWSServerlessFunctionResources()
addCloudformationLambdaFunctions(template, functions)
function, found := functions[name]
if !found {
if len(functions) == 1 && name == "" {
for _, f := range functions {
function = f
}
} else {
if name == "" {
fmt.Fprintf(os.Stderr, "ERROR: You must provide a function identifier (function's Logical ID in the SAM template) as the first argument.\n")
} else {
fmt.Fprintf(os.Stderr, "ERROR: Could not find a AWS::Serverless::Function with logical ID '%s'\n", name)
}
// If have functions defined in the template, be helpful and suggest them
if len(functions) > 0 {
fmt.Fprintf(os.Stderr, "Possible options in your template:\n")
for resourceName := range functions {
fmt.Fprintf(os.Stderr, " * %s\n", resourceName)
}
}
os.Exit(1)
}
}
// Check connectivity to docker
dockerVersion, err := getDockerVersion()
if err != nil {
log.Printf("Running AWS SAM projects locally requires Docker. Have you got it installed?\n")
log.Printf("%s\n", err)
os.Exit(1)
}
log.Printf("Connected to Docker %s", dockerVersion)
cwd := filepath.Dir(filename)
if c.String("docker-volume-basedir") != "" {
cwd = c.String("docker-volume-basedir")
}
runt, err := NewRuntime(NewRuntimeOpt{
Cwd: cwd,
LogicalID: name,
Function: function,
Logger: stderr,
EnvOverrideFile: c.String("env-vars"),
DebugPort: c.String("debug-port"),
SkipPullImage: c.Bool("skip-pull-image"),
DockerNetwork: c.String("docker-network"),
})
if err != nil {
log.Fatalf("Could not initiate %s runtime: %s\n", function.Runtime, err)
}
eventFile := c.String("event")
event := ""
if eventFile == "" {
// The event payload wasn't provided with --event, so read from stdin
log.Printf("Reading invoke payload from stdin (you can also pass it from file with --event)\n")
pb, err := ioutil.ReadAll(os.Stdin)
if err != nil {
log.Fatalf("Could not read event from stdin: %s\n", err)
}
event = string(pb)
} else {
// The event payload should be read from the file provided
pb, err := ioutil.ReadFile(eventFile)
if err != nil {
log.Fatalf("Could not read event from file: %s\n", err)
}
event = string(pb)
}
stdoutTxt, stderrTxt, err := runt.Invoke(event, c.String("profile"))
if err != nil {
log.Fatalf("Could not invoke function: %s\n", err)
}
var wg sync.WaitGroup
wg.Add(2)
go func() {
io.Copy(stderr, stderrTxt)
wg.Done()
}()
go func() {
io.Copy(stdout, stdoutTxt)
wg.Done()
}()
wg.Wait()
fmt.Fprintf(stderr, "\n")
runt.CleanUp()
}