Skip to content

Commit 0d5ae2b

Browse files
authored
Merge pull request #140 from null93/main
Implemented Rain::Env for pkg command
2 parents c2bec1f + 276d0a4 commit 0d5ae2b

File tree

9 files changed

+95
-3
lines changed

9 files changed

+95
-3
lines changed

cft/pkg/pkg.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// or as one-property objects, much as AWS instrinsic functions are used, e.g. "Fn::Join"
66
//
77
// `Rain::Include`: insert the content of the file into the template directly. The file must be in YAML or JSON format.
8+
// `Rain::Env`: inserts environmental variable value into the template as a string. Variable must be set.
89
// `Rain::Embed`: insert the content of the file as a string
910
// `Rain::S3Http`: uploads the file or directory (zipping it first) to S3 and returns the HTTP URI (i.e. `https://bucket.s3.region.amazonaws.com/key`)
1011
// `Rain::S3`: a string value uploads the file or directory (zipping it first) to S3 and returns the S3 URI (i.e. `s3://bucket/key`)

cft/pkg/pkg_test.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,28 @@ func TestInclude(t *testing.T) {
110110
"Rain::Include": fileName,
111111
},
112112
})
113-
114113
compare(t, in, "Test", map[string]interface{}{"This": "is a test"})
115114
}
116115

116+
func TestEnv(t *testing.T) {
117+
os.Setenv("RAIN_TEST_ENV_EXISTS", "foo")
118+
in1, _ := parse.Map(map[string]interface{}{
119+
"Success": map[string]interface{}{
120+
"Rain::Env": "RAIN_TEST_ENV_EXISTS",
121+
},
122+
})
123+
in2, _ := parse.Map(map[string]interface{}{
124+
"Failure": map[string]interface{}{
125+
"Rain::Env": "RAIN_TEST_ENV_DOESNT_EXISTS",
126+
},
127+
})
128+
compare(t, in1, "Success", "foo")
129+
_, err2 := pkg.Template(in2, "./")
130+
if err2 == nil {
131+
t.Errorf("Expected error since %q environment variable doesn't exist", "RAIN_TEST_ENV_DOESNT_EXISTS")
132+
}
133+
}
134+
117135
func TestS3Http(t *testing.T) {
118136
in, _ := parse.Map(map[string]interface{}{
119137
"Test": map[string]interface{}{

cft/pkg/rain.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
package pkg
33

44
import (
5+
"os"
56
"errors"
67
"fmt"
78
"path/filepath"
@@ -37,6 +38,7 @@ var registry = make(map[string]rainFunc)
3738
func init() {
3839
registry["**/*|Rain::Embed"] = includeString
3940
registry["**/*|Rain::Include"] = includeLiteral
41+
registry["**/*|Rain::Env"] = includeEnv
4042
registry["**/*|Rain::S3Http"] = includeS3Http
4143
registry["**/*|Rain::S3"] = includeS3
4244
registry["**/*|Rain::Module"] = module
@@ -78,6 +80,24 @@ func includeLiteral(n *yaml.Node, root string, t cft.Template, parent node.NodeP
7880
return true, nil
7981
}
8082

83+
func includeEnv(n *yaml.Node, root string, t cft.Template, parent node.NodePair) (bool, error) {
84+
name, err := expectString(n)
85+
if err != nil {
86+
return false, err
87+
}
88+
val, present := os.LookupEnv( name )
89+
if !present {
90+
return false, fmt.Errorf("missing environmental variable %q", name)
91+
}
92+
var newNode yaml.Node
93+
newNode.Encode ( val )
94+
if err != nil {
95+
return false, err
96+
}
97+
*n = newNode
98+
return true, nil
99+
}
100+
81101
func handleS3(root string, options s3Options) (*yaml.Node, error) {
82102
s, err := upload(root, options.Path, options.Zip)
83103
if err != nil {

cft/pkg/util.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// or as one-property objects, much as AWS instrinsic functions are used, e.g. "Fn::Join"
66
//
77
// `Rain::Include`: insert the content of the file into the template directly. The file must be in YAML or JSON format.
8+
// `Rain::Env`: inserts environmental variable value into the template as a string. Variable must be set.
89
// `Rain::Embed`: insert the content of the file as a string
910
// `Rain::S3Http`: uploads the file or directory (zipping it first) to S3 and returns the HTTP URI (i.e. `https://bucket.s3.region.amazonaws.com/key`)
1011
// `Rain::S3`: a string value uploads the file or directory (zipping it first) to S3 and returns the S3 URI (i.e. `s3://bucket/key`)

cft/tags.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ var Tags = map[string]string{
2121
"!Condition": "Condition",
2222
"!Rain::Embed": "Rain::Embed",
2323
"!Rain::Include": "Rain::Include",
24+
"!Rain::Env": "Rain::Env",
2425
"!Rain::S3Http": "Rain::S3Http",
2526
"!Rain::S3": "Rain::S3",
2627
"!Rain::Module": "Rain::Module",

docs/rain_pkg.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ You may use the following, rain-specific directives in templates packaged with "
1212

1313
!Rain::Include <path> Reads the file at <path> as YAML/JSON and inserts the resulting object into the template
1414

15+
!Rain::Env <name> Reads the <name> environmental variable and inserts value into the template as a string
16+
1517
!Rain::S3Http <path> Uploads <path> (zipping first if it is a directory) to S3
1618
and embeds the S3 HTTP URL into the template as a string
1719

internal/aws/s3/mock.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package s3
55
import (
66
"crypto/sha256"
77
"fmt"
8+
"path/filepath"
89

910
"github.com/aws-cloudformation/rain/internal/aws"
1011
"github.com/aws-cloudformation/rain/internal/config"
@@ -32,8 +33,7 @@ func Upload(bucketName string, content []byte) (string, error) {
3233
if !isBucketExists {
3334
return "", fmt.Errorf("bucket does not exist: '%s'", bucketName)
3435
}
35-
36-
return fmt.Sprintf("%x", sha256.Sum256(content)), nil
36+
return filepath.Join ( BucketKeyPrefix, fmt.Sprintf("%x", sha256.Sum256(content)) ), nil
3737
}
3838

3939
// RainBucket returns the name of the rain deployment bucket in the current region

internal/aws/s3/s3_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
//go:build func_test
2+
3+
package s3
4+
5+
import (
6+
"fmt"
7+
"testing"
8+
9+
"github.com/aws-cloudformation/rain/internal/aws"
10+
)
11+
12+
func TestPassingBucketName(t *testing.T) {
13+
tests := [][]string {
14+
{"custom-bucket-name", "custom-bucket-name"},
15+
{"", fmt.Sprintf("rain-artifacts-1234567890-%s", aws.Config().Region) },
16+
}
17+
for _, test := range tests {
18+
BucketName = test[0]
19+
output := RainBucket(false)
20+
if output != test[1] {
21+
t.Errorf("incorrect bucket name, expecting %q but got %q", test[1], output)
22+
}
23+
}
24+
}
25+
26+
func TestPassingBucketKeyPrefix(t *testing.T) {
27+
buckets ["random-bucket"] = true
28+
content := []byte("some content")
29+
hash := "290f493c44f5d63d06b374d0a5abd292fae38b92cab2fae5efefe1b0e9347f56"
30+
tests := [][]string {
31+
{"some-prefix", fmt.Sprintf ("some-prefix/%s", hash)},
32+
{"some-prefix/", fmt.Sprintf ("some-prefix/%s", hash)},
33+
{"some-prefix/test", fmt.Sprintf ("some-prefix/test/%s", hash)},
34+
{"some-prefix/test/", fmt.Sprintf ("some-prefix/test/%s", hash)},
35+
{"", hash},
36+
}
37+
for _, test := range tests {
38+
BucketKeyPrefix = test[0]
39+
output, err := Upload("random-bucket", content)
40+
if err != nil {
41+
t.Errorf("unexpected error during upload: %v", err)
42+
}
43+
if output != test[1] {
44+
t.Errorf("incorrect key, expecting %q but got %q", test[1], output)
45+
}
46+
}
47+
}

internal/cmd/pkg/pkg.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ You may use the following, rain-specific directives in templates packaged with "
2929
3030
!Rain::Include <path> Reads the file at <path> as YAML/JSON and inserts the resulting object into the template
3131
32+
!Rain::Env <name> Reads the <name> environmental variable and inserts value into the template as a string
33+
3234
!Rain::S3Http <path> Uploads <path> (zipping first if it is a directory) to S3
3335
and embeds the S3 HTTP URL into the template as a string
3436

0 commit comments

Comments
 (0)