Skip to content

Commit d33d29f

Browse files
committed
Readme file
2 parents cf636e0 + 90737e5 commit d33d29f

File tree

9 files changed

+324
-1
lines changed

9 files changed

+324
-1
lines changed

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
*.tf
2+
.DS_Store
3+
.DS_Store?
4+
*.swp
5+
.vscode/*
6+
!.vscode/settings.json
7+
!.vscode/tasks.json
8+
!.vscode/launch.json
9+
!.vscode/extensions.json

.travis.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
language: go
2+
go:
3+
- 1.9
4+
# Don't email me the results of the test runs.
5+
notifications:
6+
email: false
7+
before_script:
8+
- go get github.com/golang/lint/golint # Linter
9+
10+
script:
11+
- go test -v -race ./... # Run all the tests with the race detector enabled
12+
- go vet ./... # go vet is the official Go static analyzer
13+
- golint -set_exit_status $(go list ./...) # one last linter

README.md

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,76 @@
11
# terraform-variables-generator
2-
Simple Tool for Generate Variables file from Terraform Configuration
2+
3+
Simple Tool for Generate Variables file from Terraform Configuration. It will find all *.tf files in current directory, and generate varibales.tf file, if you already have this file, it will ask to override it.
4+
5+
## Build
6+
7+
```bash
8+
go build .
9+
```
10+
11+
## Usage
12+
13+
```bash
14+
./terraform-variables-generator
15+
```
16+
17+
It will find all *.tf files in current directory, and generate varibales.tf file, if you already have this file, it will ask to override it.
18+
19+
### Example
20+
21+
```text
22+
resource "aws_vpc" "vpc" {
23+
cidr_block = "${var.cidr}"
24+
enable_dns_hostnames = "${var.enable_dns_hostnames}"
25+
enable_dns_support = "${var.enable_dns_support}"
26+
27+
tags {
28+
Name = "${var.name}"
29+
}
30+
}
31+
32+
resource "aws_internet_gateway" "vpc" {
33+
vpc_id = "${aws_vpc.vpc.id}"
34+
35+
tags {
36+
Name = "${var.name}-igw"
37+
}
38+
}
39+
```
40+
41+
Will generate
42+
43+
```text
44+
variable "ami" {
45+
description = ""
46+
}
47+
48+
variable "instance_type" {
49+
description = ""
50+
}
51+
52+
variable "cidr" {
53+
description = ""
54+
}
55+
56+
variable "enable_dns_hostnames" {
57+
description = ""
58+
}
59+
60+
variable "enable_dns_support" {
61+
description = ""
62+
}
63+
64+
variable "name" {
65+
description = ""
66+
}
67+
```
68+
69+
## Tests
70+
71+
Run tests and linter
72+
73+
```bash
74+
go test -v -race ./...
75+
golint -set_exit_status $(go list ./...)
76+
```

configuration.mock

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//Mock Terraform Configuration File
2+
resource "aws_eip" "nat" {
3+
vpc = true
4+
count = "${length(var.public_subnets)}"
5+
}
6+
7+
resource "aws_nat_gateway" "nat" {
8+
allocation_id = "${element(aws_eip.nat.*.id, count.index)}"
9+
subnet_id = "${element(aws_subnet.public.*.id, count.index)}"
10+
count = "${length(var.public_subnets)}"
11+
}

file_utils.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package main
2+
3+
import (
4+
"os"
5+
"path/filepath"
6+
7+
log "github.com/sirupsen/logrus"
8+
)
9+
10+
func getAllFiles(ext string) ([]string, error) {
11+
dir, err := os.Getwd()
12+
checkError(err)
13+
var files []string
14+
log.Infof("Finding files in %q directory", dir)
15+
files, err = filepath.Glob(ext)
16+
checkError(err)
17+
18+
if len(files) == 0 {
19+
log.Infof("No files with %q extensions found in %q", ext, dir)
20+
}
21+
return files, nil
22+
}
23+
24+
func fileExists(name string) bool {
25+
if _, err := os.Stat(name); err == nil {
26+
return true
27+
}
28+
return false
29+
}

generator.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package main
2+
3+
import (
4+
"bufio"
5+
"html/template"
6+
"os"
7+
"strings"
8+
"sync"
9+
10+
log "github.com/sirupsen/logrus"
11+
)
12+
13+
var replacer *strings.Replacer
14+
var varPrefix = "var."
15+
var tfFileExt = "*.tf"
16+
17+
var dstFile = "./variables.tf"
18+
var varTemplate = template.Must(template.New("var_file").Parse(`{{range .}}
19+
variable "{{ . }}" {
20+
description = ""
21+
}
22+
{{end}}
23+
`))
24+
25+
func init() {
26+
replacer = strings.NewReplacer(":", ".",
27+
"]", "",
28+
"}", "",
29+
"{", "",
30+
"\"", "",
31+
")", "",
32+
"(", "",
33+
"[", "",
34+
",", "",
35+
"var.", "",
36+
" ", "",
37+
)
38+
}
39+
func main() {
40+
if fileExists(dstFile) {
41+
userPromt()
42+
}
43+
44+
tfFiles, err := getAllFiles(tfFileExt)
45+
if len(tfFiles) == 0 {
46+
log.Warn("No terraform files to proceed, exiting")
47+
os.Exit(0)
48+
}
49+
checkError(err)
50+
var wg sync.WaitGroup
51+
messages := make(chan string)
52+
wg.Add(len(tfFiles))
53+
t := &terraformVars{}
54+
55+
for _, file := range tfFiles {
56+
go func(file string) {
57+
defer wg.Done()
58+
fileHandle, _ := os.Open(file)
59+
defer fileHandle.Close()
60+
fileScanner := bufio.NewScanner(fileHandle)
61+
for fileScanner.Scan() {
62+
messages <- fileScanner.Text()
63+
}
64+
}(file)
65+
}
66+
go func() {
67+
for text := range messages {
68+
t.matchVarPref(text, varPrefix)
69+
}
70+
}()
71+
wg.Wait()
72+
f, err := os.Create(dstFile)
73+
checkError(err)
74+
75+
err = varTemplate.Execute(f, t.Variables)
76+
checkError(err)
77+
log.Infof("Variables are generated to %q file", dstFile)
78+
79+
}

generator_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package main
2+
3+
import (
4+
"bufio"
5+
"os"
6+
"testing"
7+
)
8+
9+
var mockFile = "tf_configuration.mock"
10+
var testExtFile = "*.mock"
11+
12+
func TestContainsElement(t *testing.T) {
13+
testSlice := []string{"Terraform", "Puppet", "Ansible"}
14+
if containsElement(testSlice, "Chef") {
15+
t.Error("Should return false, but return true")
16+
}
17+
}
18+
19+
func TestGetAllFiles(t *testing.T) {
20+
files, err := getAllFiles(testExtFile)
21+
checkError(err)
22+
if len(files) == 0 {
23+
t.Error("Should found at least one file")
24+
}
25+
}
26+
27+
func TestMatchVariable(t *testing.T) {
28+
ter := &terraformVars{}
29+
var messages []string
30+
31+
file, err := getAllFiles(testExtFile)
32+
checkError(err)
33+
34+
fileHandle, _ := os.Open(file[0])
35+
defer fileHandle.Close()
36+
37+
fileScanner := bufio.NewScanner(fileHandle)
38+
for fileScanner.Scan() {
39+
messages = append(messages, fileScanner.Text())
40+
}
41+
for _, text := range messages {
42+
ter.matchVarPref(text, varPrefix)
43+
}
44+
if len(ter.Variables) != 1 {
45+
t.Errorf("Should return one variable. but returned %d", len(ter.Variables))
46+
}
47+
48+
}

helpers.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
log "github.com/sirupsen/logrus"
8+
)
9+
10+
func checkError(e error) {
11+
if e != nil {
12+
log.Fatal(e)
13+
}
14+
}
15+
16+
func containsElement(slice []string, value string) bool {
17+
if len(slice) == 0 {
18+
return false
19+
}
20+
for _, s := range slice {
21+
if value == s {
22+
return true
23+
}
24+
}
25+
return false
26+
}
27+
28+
func userPromt() {
29+
var response string
30+
log.Warnf("File %q already exists, type yes if you want replace", dstFile)
31+
fmt.Print("-> ")
32+
_, err := fmt.Scanln(&response)
33+
checkError(err)
34+
if response != "yes" {
35+
os.Exit(0)
36+
}
37+
}

terraform.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package main
2+
3+
import (
4+
"regexp"
5+
"strings"
6+
)
7+
8+
type terraformVars struct {
9+
Variables []string
10+
}
11+
12+
func (t *terraformVars) matchVarPref(row, varPrefix string) {
13+
if strings.Contains(row, varPrefix) {
14+
pattern := regexp.MustCompile(`var.([a-z?_]+)`)
15+
match := pattern.FindAllStringSubmatch(row, 1)
16+
if len(match) != 0 {
17+
res := replacer.Replace(match[0][0])
18+
if !containsElement(t.Variables, res) {
19+
t.Variables = append(t.Variables, res)
20+
}
21+
}
22+
}
23+
}

0 commit comments

Comments
 (0)