-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
343 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ | |
*.dll | ||
*.so | ||
*.dylib | ||
gotlet | ||
|
||
# Test binary, built with `go test -c` | ||
*.test | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,138 @@ | ||
# gotlet | ||
Simple Templating command line tool using go template engine | ||
|
||
## Instalation | ||
``` | ||
chmod +x ./gotlet | ||
mv ./gotlet /usr/local/bin/gotlet | ||
``` | ||
|
||
## Example usage: | ||
|
||
``` | ||
./gotlet -t deployment.yaml -d data.yaml -v | ||
``` | ||
|
||
## Flags: | ||
- `-t` Specify the template file path (required) | ||
- `-d` Specify the data file path containing the variables in Yaml (optional, if not specified you have only environment variables to include) | ||
- `-p` A prefix for filtering which env variables to include | ||
- `-o` Output file path (default: result.yaml) | ||
- `-v` Print out the result in stdout | ||
|
||
## Template Engine Reference: | ||
To use a variable, eighter from environment variables or the specified use the following syntax which is standard go template syntax. | ||
|
||
``` | ||
statictext {{ .variable_name }} static text | ||
``` | ||
Nested variables: | ||
``` | ||
statictext {{ .variable_name.sub_var_name }} static text | ||
``` | ||
Environment variables: | ||
``` | ||
statictext {{ .USER }} static text | ||
``` | ||
Iterate in a key-value dictionary | ||
``` | ||
env: | ||
{{range $key, $value := .environment_variables}} | ||
- name: {{ $key }} | ||
value: {{ $value }} | ||
{{end}} | ||
``` | ||
|
||
Read more at [official go documents](https://pkg.go.dev/text/template) | ||
|
||
## Sample | ||
This is a basic variable file: | ||
> Note that variables root element is required and MUST be `variables` | ||
```yaml | ||
variables: | ||
service_name: nginx | ||
version: 2 | ||
component: front-end | ||
port: 80 | ||
frontend_max_replicas: 3 | ||
frontend_image: "nginx:latest" | ||
environment_variables: | ||
environment: production | ||
api_url: "https://api.url.com" | ||
project_name: website | ||
``` | ||
This is a sample template file which is a kubernetes deployment | ||
```yaml | ||
apiVersion: apps/v1 | ||
kind: Deployment | ||
metadata: | ||
name: {{.service_name}}-{{.component}}-{{.version}} | ||
labels: | ||
app: {{.service_name}} | ||
component: {{.component}} | ||
version: {{.version}} | ||
spec: | ||
strategy: | ||
type: RollingUpdate | ||
rollingUpdate: | ||
maxUnavailable: 2 | ||
maxSurge: {{ .frontend_max_replicas }} | ||
spec: | ||
containers: | ||
- name: {{.service_name}} | ||
image: {{.frontend_image}} | ||
imagePullPolicy: IfNotPresent | ||
ports: | ||
- containerPort: {{.ops_port}} | ||
env: {{range $key, $value := .environment_variables}} | ||
- name: {{ $key }} | ||
value: {{ $value }} {{end}} | ||
|
||
``` | ||
|
||
running this command would generate this file: | ||
``` | ||
./gotlet -t ./examples/template.yaml -d ./examples/variables.yaml -o export.yaml | ||
``` | ||
```yaml | ||
apiVersion: apps/v1 | ||
kind: Deployment | ||
metadata: | ||
name: nginx-front-end-2 | ||
labels: | ||
app: nginx | ||
component: front-end | ||
version: 2 | ||
spec: | ||
strategy: | ||
type: RollingUpdate | ||
rollingUpdate: | ||
maxUnavailable: 2 | ||
maxSurge: 3 | ||
spec: | ||
containers: | ||
- name: nginx | ||
image: nginx:latest | ||
imagePullPolicy: IfNotPresent | ||
ports: | ||
- containerPort: <no value> | ||
env: | ||
- name: api_url | ||
value: https://api.url.com | ||
- name: environment | ||
value: production | ||
- name: project_name | ||
value: website | ||
|
||
``` | ||
|
||
## Build from source | ||
To run on your local machine (you need go 1.18+ installed) | ||
``` | ||
go build . | ||
``` | ||
|
||
To run on a linux server or a linux pipeline runner: | ||
``` | ||
GOOS=linux GOARCH=amd64 go build -o gotlet-amd64-linux main.go | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
apiVersion: apps/v1 | ||
kind: Deployment | ||
metadata: | ||
name: {{.service_name}}-{{.component}}-{{.version}} | ||
labels: | ||
app: {{.service_name}} | ||
component: {{.component}} | ||
version: {{.version}} | ||
spec: | ||
strategy: | ||
type: RollingUpdate | ||
rollingUpdate: | ||
maxUnavailable: 2 | ||
maxSurge: {{ .frontend_max_replicas }} | ||
spec: | ||
containers: | ||
- name: {{.service_name}} | ||
image: {{.frontend_image}} | ||
imagePullPolicy: IfNotPresent | ||
ports: | ||
- containerPort: {{.ops_port}} | ||
env: {{range $key, $value := .environment_variables}} | ||
- name: {{ $key }} | ||
value: {{ $value }} {{end}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
variables: | ||
service_name: nginx | ||
version: 2 | ||
component: front-end | ||
port: 80 | ||
frontend_max_replicas: 3 | ||
frontend_image: "nginx:latest" | ||
environment_variables: | ||
environment: production | ||
api_url: "https://api.url.com" | ||
project_name: website |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
module gotlet | ||
|
||
go 1.18 | ||
|
||
require gopkg.in/yaml.v3 v3.0.1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package main | ||
|
||
import ( | ||
"flag" | ||
"fmt" | ||
"gotlet/pkg/colors" | ||
"io/ioutil" | ||
"os" | ||
) | ||
|
||
func main() { | ||
if len(flag.Args()) == 0 { | ||
fmt.Println("gotlet renders your variables into a template file.") | ||
} | ||
|
||
templateFile := flag.String("t", "", "Specify the template file path") | ||
envPrefix := flag.String("p", "", "A prefix for filtering which env variables to include") | ||
dataFile := flag.String("d", "", "Specify the data file containing the variables in Yaml") | ||
outputPath := flag.String("o", "result.yaml", "Output file path") | ||
printOutput := flag.Bool("v", false, "Print out the result in stdout") | ||
|
||
flag.Parse() | ||
|
||
if *templateFile == "" { | ||
fmt.Println(colors.Red + "- The template file path is required, use -t flag") | ||
os.Exit(1) | ||
} | ||
|
||
if *envPrefix == "" { | ||
fmt.Println(colors.Yellow, "- No env variable prefix specified, loading all env variables.\n"+ | ||
"\tThis is not recommended, use -p flag to specify", colors.Reset) | ||
} | ||
|
||
data := &Model{ | ||
Variables: make(map[string]any), | ||
} | ||
|
||
err := getVariables(data, *dataFile) | ||
if err != nil { | ||
fmt.Println(err) | ||
os.Exit(1) | ||
} | ||
|
||
addEnvVariables(data, *envPrefix) | ||
|
||
result, err := renderTemplate(*templateFile, data) | ||
if err != nil { | ||
fmt.Println(err) | ||
os.Exit(1) | ||
} | ||
|
||
if *outputPath != "" { | ||
err = ioutil.WriteFile(*outputPath, result, 0644) | ||
if err != nil { | ||
fmt.Println(err) | ||
os.Exit(1) | ||
} | ||
} | ||
|
||
if *printOutput { | ||
fmt.Println(string(result)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package colors | ||
|
||
var Reset = "\033[0m" | ||
var Red = "\033[31m" | ||
var Green = "\033[32m" | ||
var Yellow = "\033[33m" | ||
var Blue = "\033[34m" | ||
var Purple = "\033[35m" | ||
var Cyan = "\033[36m" | ||
var Gray = "\033[37m" | ||
var White = "\033[97m" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package main | ||
|
||
import ( | ||
"bytes" | ||
"io/ioutil" | ||
"text/template" | ||
) | ||
|
||
type Model struct { | ||
Variables map[string]any | ||
} | ||
|
||
func renderTemplate(templateFile string, data *Model) ([]byte, error) { | ||
originalContent, err := ioutil.ReadFile(templateFile) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
tmpl := template.New(templateFile) | ||
|
||
t, err := tmpl.Parse(string(originalContent)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
renderedContent := new(bytes.Buffer) | ||
err = t.Execute(renderedContent, data.Variables) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return renderedContent.Bytes(), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"io/ioutil" | ||
"os" | ||
"strings" | ||
|
||
"gopkg.in/yaml.v3" | ||
) | ||
|
||
func getVariables(data *Model, variablesFile string) error { | ||
if variablesFile != "" { | ||
err := readVariables(data, variablesFile) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func addEnvVariables(data *Model, envPrefix string) { | ||
envs := envToMap() | ||
for k, v := range envs { | ||
if strings.HasPrefix(k, envPrefix) { | ||
data.Variables[k] = v | ||
} | ||
} | ||
} | ||
|
||
func readVariables(m *Model, variables string) error { | ||
yamlFile, err := ioutil.ReadFile(variables) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
err = yaml.Unmarshal(yamlFile, m) | ||
if err != nil { | ||
return fmt.Errorf("yamlFile.Unmarshal error #%w ", err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func envToMap() map[string]string { | ||
envMap := make(map[string]string) | ||
|
||
for _, v := range os.Environ() { | ||
splitV := strings.SplitN(v, "=", 2) | ||
envMap[splitV[0]] = splitV[1] | ||
} | ||
|
||
return envMap | ||
} |