From 96565017724ba8ef6f1dc1feaa06c461aa9d5c5f Mon Sep 17 00:00:00 2001 From: Matt Weagle Date: Fri, 30 Sep 2016 20:00:28 -0700 Subject: [PATCH] Fn::ImportValue support Add support for Fn::ImportValue intrinsic. @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html --- func.go | 5 +++++ func_importvalue.go | 43 ++++++++++++++++++++++++++++++++++++++++ func_importvalue_test.go | 41 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 func_importvalue.go create mode 100644 func_importvalue_test.go diff --git a/func.go b/func.go index 29c66d6..1490e1a 100644 --- a/func.go +++ b/func.go @@ -99,6 +99,11 @@ func unmarshalFunc(data []byte) (Func, error) { if err := json.Unmarshal(data, &f); err == nil { return f, nil } + case "Fn::ImportValue": + f := ImportValueFunc{} + if err := json.Unmarshal(data, &f); err == nil { + return f, nil + } default: return nil, UnknownFunctionError{Name: key} } diff --git a/func_importvalue.go b/func_importvalue.go new file mode 100644 index 0000000..a4f9422 --- /dev/null +++ b/func_importvalue.go @@ -0,0 +1,43 @@ +package cloudformation + +// ImportValue returns a new instance of ImportValue that imports valueToImport. +func ImportValue(valueToImport string) ImportValueFunc { + return ImportValueFunc{ValueToImport: valueToImport} +} + +// ImportValueFunc represents an invocation of the Fn::ImportValue intrinsic. +// The intrinsic function Fn::ImportValue returns the value of an output exported by +// another stack. You typically use this function to create cross-stack references. +// In the following example template snippets, Stack A exports VPC security group +// values and Stack B imports them. +// +// Note +// The following restrictions apply to cross-stack references: +// For each AWS account, Export names must be unique within a region. +// You can't create cross-stack references across different regions. You can +// use the intrinsic function Fn::ImportValue only to import values that +// have been exported within the same region. +// For outputs, the value of the Name property of an Export can't use +// functions (Ref or GetAtt) that depend on a resource. +// Similarly, the ImportValue function can't include functions (Ref or GetAtt) +// that depend on a resource. +// You can't delete a stack if another stack references one of its outputs. +// You can't modify or remove the output value as long as it's referenced by another stack. +// +// See http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html +type ImportValueFunc struct { + ValueToImport string `json:"Fn::ImportValue"` +} + +// String returns this reference as a StringExpr +func (r ImportValueFunc) String() *StringExpr { + return &StringExpr{Func: r} +} + +// StringList returns this reference as a StringListExpr +func (r ImportValueFunc) StringList() *StringListExpr { + return &StringListExpr{Func: r} +} + +var _ StringFunc = ImportValueFunc{} +var _ StringListFunc = ImportValueFunc{} diff --git a/func_importvalue_test.go b/func_importvalue_test.go new file mode 100644 index 0000000..08a3dfe --- /dev/null +++ b/func_importvalue_test.go @@ -0,0 +1,41 @@ +package cloudformation + +import ( + "encoding/json" + + . "gopkg.in/check.v1" +) + +type ImportValueFuncTest struct{} + +var _ = Suite(&ImportValueFuncTest{}) + +func (testSuite *ImportValueFuncTest) TestRef(c *C) { + inputBuf := `{"Fn::ImportValue" : "sharedValueToImport"}` + f, err := unmarshalFunc([]byte(inputBuf)) + c.Assert(err, IsNil) + c.Assert(f.(StringFunc).String(), DeepEquals, ImportValue("sharedValueToImport").String()) + + // tidy the JSON input + inputStruct := map[string]interface{}{} + _ = json.Unmarshal([]byte(inputBuf), &inputStruct) + expectedBuf, _ := json.Marshal(inputStruct) + + buf, err := json.Marshal(f) + c.Assert(err, IsNil) + c.Assert(string(buf), Equals, string(expectedBuf)) +} + +func (testSuite *ImportValueFuncTest) TestFailures(c *C) { + inputBuf := `{"Fn::ImportValue": {"Fn::ImportValue": "foo"}}` + _, err := unmarshalFunc([]byte(inputBuf)) + c.Assert(err, ErrorMatches, "cannot decode function") + + inputBuf = `{"Fn::ImportValue": ["1"]}` + _, err = unmarshalFunc([]byte(inputBuf)) + c.Assert(err, ErrorMatches, "cannot decode function") + + inputBuf = `{"Fn::ImportValue": true}` + _, err = unmarshalFunc([]byte(inputBuf)) + c.Assert(err, ErrorMatches, "cannot decode function") +}