Skip to content

Commit

Permalink
Allow specifying of Cloudformation template parameters (#123)
Browse files Browse the repository at this point in the history
* Use correct type for body response

* Use correct type for statusCode

* Return 502 if status code is malformed

* Update Goformation to latest version

* Allow specifying of Cloudformation template parameters
  • Loading branch information
resios authored and sanathkr committed Sep 20, 2017
1 parent 79dcd37 commit 8624aae
Show file tree
Hide file tree
Showing 660 changed files with 2,399 additions and 3,332 deletions.
5 changes: 4 additions & 1 deletion invoke.go
Expand Up @@ -12,6 +12,7 @@ import (
"sync"

"github.com/awslabs/goformation"
"github.com/awslabs/goformation/intrinsics"
"github.com/codegangsta/cli"
)

Expand All @@ -33,7 +34,9 @@ func invoke(c *cli.Context) {
}

filename := getTemplateFilename(c.String("template"))
template, err := goformation.Open(filename)
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)
}
Expand Down
30 changes: 30 additions & 0 deletions main.go
Expand Up @@ -4,6 +4,8 @@ import (
"fmt"
"os"
"path/filepath"
"regexp"
"strings"

"github.com/codegangsta/cli"
"github.com/fatih/color"
Expand Down Expand Up @@ -62,6 +64,11 @@ func main() {
Usage: "AWS SAM template file",
EnvVar: "SAM_TEMPLATE_FILE",
},
cli.StringFlag{
Name: "parameter-values",
Usage: "Optional. A string that contains CloudFormation parameter overrides encoded as key-value pairs. Use the same format as the AWS CLI, e.g. 'ParameterKey=KeyPairName,ParameterValue=MyKey ParameterKey=InstanceType,ParameterValue=t1.micro'. In case of parsing errors all values are ignored",
EnvVar: "SAM_TEMPLATE_PARAM_ARG",
},
cli.StringFlag{
Name: "log-file, l",
Usage: "Optional logfile to send runtime logs to",
Expand Down Expand Up @@ -124,6 +131,11 @@ func main() {
Usage: "AWS SAM template file",
EnvVar: "SAM_TEMPLATE_FILE",
},
cli.StringFlag{
Name: "parameter-values",
Usage: "Optional. A string that contains CloudFormation parameter overrides encoded as key-value pairs. Use the same format as the AWS CLI, e.g. 'ParameterKey=KeyPairName,ParameterValue=MyKey ParameterKey=InstanceType,ParameterValue=t1.micro'. In case of parsing errors all values are ignored",
EnvVar: "SAM_TEMPLATE_PARAM_ARG",
},
cli.StringFlag{
Name: "log-file, l",
Usage: "Optional. Logfile to send runtime logs to",
Expand Down Expand Up @@ -351,6 +363,24 @@ func main() {

}

// regexp that parses Cloudformation paramter key-value pair: https://regex101.com/r/hruxlg/3
var paramRe = regexp.MustCompile(`(?:ParameterKey)=("(?:\\.|[^"\\]+)*"|(?:\\.|[^, "\\]+)*),(?:ParameterValue)=("(?:\\.|[^"\\]+)*"|(?:\\.|[^ ,"\\]+)*)`)

// parseParameters parses the Cloudformation parameters like string and converts
// it into a map of key-value pairs.
func parseParameters(arg string) (overrides map[string]interface{}) {
overrides = make(map[string]interface{})

unquote := func(orig string) string {
return strings.Replace(strings.TrimSuffix(strings.TrimPrefix(orig, `"`), `"`), `\ `, ` `, -1)
}

for _, match := range paramRe.FindAllStringSubmatch(arg, -1) {
overrides[unquote(match[1])] = unquote(match[2])
}
return
}

// getTemplateFilename allows SAM Local to default to either template.yaml
// or template.yml for the --template/-t parameter. This is helpful, as there
// isn't a hard definition for the filename suffix and usage tends to be mixed
Expand Down
47 changes: 47 additions & 0 deletions params_test.go
@@ -0,0 +1,47 @@
package main

import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)

var _ = Describe("Parse Cloudformation parameters", func() {

Context("with normal input", func() {

It("returns empty map when input is missing", func() {
p := parseParameters("")
Expect(p).To(BeEmpty())
})

It("returns expected values when input is correct", func() {
p := parseParameters("ParameterKey=KeyPairName,ParameterValue=MyKey ParameterKey=InstanceType,ParameterValue=t1.micro")
Expect(p).To(HaveLen(2))
Expect(p).To(HaveKeyWithValue("KeyPairName", "MyKey"))
Expect(p).To(HaveKeyWithValue("InstanceType", "t1.micro"))
})

It("returns partial values when input is malformed", func() {
p := parseParameters("ParameterKey=KeyPairName,ParameterValue=MyKey Para")
Expect(p).To(HaveLen(1))
Expect(p).To(HaveKeyWithValue("KeyPairName", "MyKey"))
})
})

Context("with escaped input", func() {

It("returns expected values when keys or values are quoted", func() {
p := parseParameters(`ParameterKey="KeyPairName",ParameterValue="MyKey " ParameterKey=InstanceType,ParameterValue=t1\ mic\ ro`)
Expect(p).To(HaveLen(2))
Expect(p).To(HaveKeyWithValue("KeyPairName", "MyKey "))
Expect(p).To(HaveKeyWithValue("InstanceType", "t1 mic ro"))
})

It("handles wrong quotings", func() {
p := parseParameters(`ParameterKey="KeyPairName,ParameterValue="MyKey" ParameterKey=InstanceType,ParameterValue=t1\ micro`)
Expect(p).To(HaveLen(1))
Expect(p).To(HaveKeyWithValue("InstanceType", "t1 micro"))
})

})
})
6 changes: 5 additions & 1 deletion start.go
Expand Up @@ -8,6 +8,8 @@ import (
"os"
"path/filepath"

"github.com/awslabs/goformation/intrinsics"

"github.com/awslabs/aws-sam-local/router"
"github.com/awslabs/goformation"
"github.com/codegangsta/cli"
Expand All @@ -29,7 +31,9 @@ func start(c *cli.Context) {
}

filename := getTemplateFilename(c.String("template"))
template, err := goformation.Open(filename)
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)
}
Expand Down
153 changes: 77 additions & 76 deletions vendor/github.com/awslabs/goformation/README.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 8624aae

Please sign in to comment.