Skip to content

Commit

Permalink
support both s3 and local vars file
Browse files Browse the repository at this point in the history
  • Loading branch information
Matt Schurenko committed Jan 27, 2019
1 parent 3b93d22 commit c7a1f5f
Show file tree
Hide file tree
Showing 11 changed files with 114 additions and 59 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ version: 2
jobs:
build:
environment:
VERSION: &version 0.1.4
VERSION: &version 0.1.5
AWS_REGION: us-west-2
docker:
- image: &image golang:latest
Expand Down
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ test:
-e AWS_ACCESS_KEY_ID="${AWS_ACCESS_KEY_ID}" \
-e AWS_SECRET_ACCESS_KEY="${AWS_SECRET_ACCESS_KEY}" \
-w /go/src/entrypoint \
golang:latest go test -v
golang:latest go test -v -cover

test_container:
docker run --rm -ti \
-v `pwd`:/go/src/entrypoint \
-e AWS_REGION="us-west-2" \
-e AWS_ACCESS_KEY_ID="${AWS_ACCESS_KEY_ID}" \
-e AWS_SECRET_ACCESS_KEY="${AWS_SECRET_ACCESS_KEY}" \
-e ENTRYPOINT_S3_PATH="mschurenko-test/fixtures/vars.yml" \
-e ENTRYPOINT_VARS_FILE="/go/src/entrypoint/fixtures/vars-no-secret.yml" \
-e ENTRYPOINT_TEMPLATES="test1.conf.tmpl,test2.conf.tmpl" \
-w /go/src/entrypoint \
golang:latest ./test.sh
Expand All @@ -24,4 +24,4 @@ build: test test_container
-w /go/src/entrypoint \
golang:latest go install

PHONY: test test_container build
PHONY: test test_container build
30 changes: 27 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type tmplCtx struct {
```

Which can be referenced like:
```gohtml
```gotemplate
value of MY_VAR is {{ .EnvVars["MY_VAR"] }}
```

Expand All @@ -39,8 +39,7 @@ funcMap = map[string]interface{}{
In addition to the above github.com/Masterminds/sprig are included.

## Dealing with empty values
By default `entrypoint` sets `template.Option` to `[]string{"missing=error"}`. This can be changed by setting `ENTRYPOINT_TMPL_OPTION`.

By default `entrypoint` sets `template.Option` to `"missing=error"`. This can be changed by setting `ENTRYPOINT_TMPL_OPTION`.

## Special Environment Variales
The following environment variables are specfic to `entrypoint` and will not be passed into your container:
Expand All @@ -51,3 +50,28 @@ ENTRYPOINT_TMPL_OPTION
```

## Testing templates

## Examples
# `Dockerfile`
```dockerfile
...
# entrypoint
RUN curl -L https://github.com/mschurenko/entrypoint/releases/download/0.1.4/entrypoint \
-o /entrypoint && chmod +x /entrypoint

# templates
WORKDIR /conf
COPY tmpl1.conf.tmpl .
COPY tmpl2.conf.tmpl .

ENTRYPOINT ["/entrypoint"]
```

# Template
set `ENV` and `APP` environment variables and refer to them in your template:
```gotemplate
{{- $env := .EnvVars.ENV -}}
{{- $app := .EnvVars.APP -}}
{{- $vars := index (index .Vars $env) $app -}}
http_port: {{ $vars.http_port }}
```
2 changes: 1 addition & 1 deletion fixtures/test1.conf.tmpl
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
test1 conf
my secret is {{ getSecret "/mschurenko/entrypoint/test_secret" }}
aws region: {{ getRegion }}
2 changes: 1 addition & 1 deletion fixtures/test2.conf.tmpl
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
test2 conf
my secret is {{ getSecret "/mschurenko/entrypoint/test_secret" }}
aws region: {{ getRegion }}
9 changes: 9 additions & 0 deletions fixtures/vars-no-secret.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
production:
web:
db: prod-db1
cache: prod-cache1
staging:
web:
db: stage-db1
cache: stage-cache1
3 changes: 2 additions & 1 deletion fixtures/vars.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
production:
web:
db: prod-db1
password: {{ getSecret "/mschurenko/entrypoint/test_secret" }}
cache: prod-cache1
staging:
web:
db: stage-db1
cache: stage-cache1
cache: stage-cache1
68 changes: 45 additions & 23 deletions funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ var funcMap map[string]interface{}
var templateOptions = []string{}

const tmplExt string = ".tmpl"
const s3Prefix string = "s3://"

func init() {
r := getRegion()
Expand Down Expand Up @@ -66,12 +67,12 @@ func getRegion() string {
client := &http.Client{Timeout: 5 * time.Second}
r, err := client.Get("http://169.254.169.254/latest/meta-data/placement/availability-zone")
if err != nil {
log.Fatalf("could not connect to ECS metadata: %v\n", err)
log.Fatalf("getRegion: could not connect to ECS metadata: %v\n", err)
}

bs, err := ioutil.ReadAll(r.Body)

return string(bs[0 : len(bs)-1])
return string(bs[:len(bs)-1])
}

func stripExt(f string) string {
Expand All @@ -86,17 +87,16 @@ func getSecret(name string) string {

output, err := svc.GetSecretValue(input)
if err != nil {
log.Fatal(err)
log.Fatalf("getSecret: %v", err)
}

return *output.SecretString
}

func getNumCPU() float64 {
f := "/proc/cpuinfo"
bs, err := ioutil.ReadFile(f)
bs, err := ioutil.ReadFile("/proc/cpuinfo")
if err != nil {
log.Fatal(err)
log.Fatalf("getNumCPU: %v", err)
}

lines := strings.Split(string(bs), "\n")
Expand All @@ -120,7 +120,7 @@ func getNumCPU() float64 {
func getNameServers() []string {
bs, err := ioutil.ReadFile("/etc/resolv.conf")
if err != nil {
log.Fatal(err)
log.Fatalf("getNameServers: %v", err)
}

var ns []string
Expand All @@ -139,13 +139,42 @@ func getNameServers() []string {
func getHostname() string {
s, err := os.Hostname()
if err != nil {
log.Fatal(err)
log.Fatalf("getHostname: %v", err)
}

return s
}

func getVarsFromS3(s3Path string) map[string]interface{} {
func getVarsFromFile(file string) map[string]interface{} {
var s string

if strings.HasPrefix(file, s3Prefix) {
s = getFileFromS3(file)
} else {
// assume this is a local file
bs, err := ioutil.ReadFile(file)
if err != nil {
log.Fatalf("getVarsFromFile: %v", err)
}

s = string(bs)
}

// context is nil for vars file
y := renderStr("vars", s, nil)

v := make(map[string]interface{})
err := yaml.Unmarshal([]byte(y), &v)
if err != nil {
log.Fatalf("getVarsFromFile: %v", err)
}

return v
}

func getFileFromS3(file string) string {
s3Path := strings.Split(file, s3Prefix)[1]

xs := strings.Split(s3Path, "/")

var filtered []string
Expand All @@ -156,7 +185,7 @@ func getVarsFromS3(s3Path string) map[string]interface{} {
}

if len(filtered) < 2 {
log.Fatalf("%v is not a valid path", s3Path)
log.Fatalf("getFileFromS3: %v is not a valid path", s3Path)
}
bucket := filtered[0]
path := strings.Join(filtered[1:], "/")
Expand All @@ -170,21 +199,14 @@ func getVarsFromS3(s3Path string) map[string]interface{} {

o, err := svc.GetObject(input)
if err != nil {
log.Fatal(err)
log.Fatalf("getFileFromS3: %v", err)
}

bs, err := ioutil.ReadAll(o.Body)
if err != nil {
log.Fatal(err)
log.Fatalf("getFileFromS3: %v", err)
}

d := make(map[string]interface{})
err = yaml.Unmarshal(bs, &d)
if err != nil {
log.Fatal(err)
}

return d
return string(bs)
}

func renderTmpl(tmplFile string, ctx interface{}) {
Expand All @@ -194,11 +216,11 @@ func renderTmpl(tmplFile string, ctx interface{}) {

f, err := os.Create(newFile)
if err != nil {
log.Fatal(err)
log.Fatalf("renderTmpl: %v", err)
}
err = t.Execute(f, ctx)
if err != nil {
log.Fatal(err)
log.Fatalf("renderTmpl: %v", err)
}
}

Expand All @@ -208,7 +230,7 @@ func renderStr(name, tmpl string, ctx interface{}) string {
var b bytes.Buffer
err := t.Execute(&b, ctx)
if err != nil {
log.Fatal(err)
log.Fatalf("renderStr: %v", err)
}

return b.String()
Expand Down
31 changes: 13 additions & 18 deletions funcs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,25 +157,22 @@ func TestRenderStr(t *testing.T) {

}

func TestGetVarsFromFileLocal(t *testing.T) {
f := "./fixtures/vars.yml"
getVarsFromFile(f)
}

func TestGetVarsFromFileS3(t *testing.T) {
getVarsFromFile(s3Prefix + s3Bucket + "/" + s3Key)
}

func TestRenderTmpl(t *testing.T) {
vars := getVarsFromFile(s3Prefix + s3Bucket + "/" + s3Key)
ctx := tmplCtx{
EnvVars: map[string]string{
"MY_ENV": "production",
},
Vars: map[string]interface{}{
"production": map[string]map[string]string{
"web": map[string]string{
"db": "prod-db1",
"cache": "prod-cache1",
},
},
"staging": map[string]map[string]string{
"web": map[string]string{
"db": "stage-db1",
"cache": "stage-cache1",
},
},
},
Vars: vars,
}

tmplName := "test.conf.tmpl"
Expand All @@ -186,6 +183,7 @@ func TestRenderTmpl(t *testing.T) {
production web cache is prod-cache1
value of /mschurenko/entrypoint/test_secret is mysecret
aws region is us-west-2
value of production.web.password is mysecret
`

tmplStr := `
Expand All @@ -194,6 +192,7 @@ func TestRenderTmpl(t *testing.T) {
production web cache is {{ (index .Vars .EnvVars.MY_ENV).web.cache }}
value of /mschurenko/entrypoint/test_secret is {{ getSecret "/mschurenko/entrypoint/test_secret" }}
aws region is {{ getRegion }}
value of production.web.password is {{ .Vars.production.web.password }}
`

if err := ioutil.WriteFile(tmplName, []byte(tmplStr), 0644); err != nil {
Expand All @@ -216,7 +215,3 @@ func TestRenderTmpl(t *testing.T) {
}

}

func TestGetVarsFromS3(t *testing.T) {
getVarsFromS3(s3Bucket + "/" + s3Key)
}
17 changes: 10 additions & 7 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,12 @@ type tmplCtx struct {
func main() {
usage := fmt.Sprintf("Usage: %v cmd [argN...]", os.Args[0])

fmt.Println(os.Args)

if len(os.Args) < 2 {
log.Fatal(usage)
}

execArgs := os.Args[1:]
log.Println("entrypoint arguments:", strings.Join(execArgs, " "))

cmdPath, err := exec.LookPath(execArgs[0])
if err != nil {
Expand All @@ -39,14 +38,20 @@ func main() {
}

vars := make(map[string]interface{})
if os.Getenv("ENTRYPOINT_S3_PATH") != "" {
vars = getVarsFromS3(os.Getenv("ENTRYPOINT_S3_PATH"))
if os.Getenv("ENTRYPOINT_VARS_FILE") != "" {
vars = getVarsFromFile(os.Getenv("ENTRYPOINT_VARS_FILE"))
}

var containerVars []string
var templates []string

// parse ENV vars
for k, v := range envVars {

if !strings.HasPrefix(k, "ENTRYPOINT_") {
containerVars = append(containerVars, k+"="+v)
}

matched, _ := regexp.Match(`^{{.*}}$`, []byte(v))
if matched {
var rendered string
Expand Down Expand Up @@ -82,9 +87,7 @@ func main() {

}

fmt.Println(execArgs)

err = syscall.Exec(cmdPath, execArgs, os.Environ())
err = syscall.Exec(cmdPath, execArgs, containerVars)
if err != nil {
log.Fatal(err)
}
Expand Down
3 changes: 2 additions & 1 deletion test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ go install -race

cd fixtures

entrypoint cat test1.conf test2.conf
entrypoint cat test1.conf test2.conf
# entrypoint env

0 comments on commit c7a1f5f

Please sign in to comment.