Skip to content

Commit

Permalink
Readme file
Browse files Browse the repository at this point in the history
  • Loading branch information
alexandrst88 committed May 12, 2018
2 parents cf636e0 + 90737e5 commit d33d29f
Show file tree
Hide file tree
Showing 9 changed files with 324 additions and 1 deletion.
9 changes: 9 additions & 0 deletions .gitignore
@@ -0,0 +1,9 @@
*.tf
.DS_Store
.DS_Store?
*.swp
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
13 changes: 13 additions & 0 deletions .travis.yml
@@ -0,0 +1,13 @@
language: go
go:
- 1.9
# Don't email me the results of the test runs.
notifications:
email: false
before_script:
- go get github.com/golang/lint/golint # Linter

script:
- go test -v -race ./... # Run all the tests with the race detector enabled
- go vet ./... # go vet is the official Go static analyzer
- golint -set_exit_status $(go list ./...) # one last linter
76 changes: 75 additions & 1 deletion README.md
@@ -1,2 +1,76 @@
# terraform-variables-generator
Simple Tool for Generate Variables file from Terraform Configuration

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.

## Build

```bash
go build .
```

## Usage

```bash
./terraform-variables-generator
```

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.

### Example

```text
resource "aws_vpc" "vpc" {
cidr_block = "${var.cidr}"
enable_dns_hostnames = "${var.enable_dns_hostnames}"
enable_dns_support = "${var.enable_dns_support}"
tags {
Name = "${var.name}"
}
}
resource "aws_internet_gateway" "vpc" {
vpc_id = "${aws_vpc.vpc.id}"
tags {
Name = "${var.name}-igw"
}
}
```

Will generate

```text
variable "ami" {
description = ""
}
variable "instance_type" {
description = ""
}
variable "cidr" {
description = ""
}
variable "enable_dns_hostnames" {
description = ""
}
variable "enable_dns_support" {
description = ""
}
variable "name" {
description = ""
}
```

## Tests

Run tests and linter

```bash
go test -v -race ./...
golint -set_exit_status $(go list ./...)
```
11 changes: 11 additions & 0 deletions configuration.mock
@@ -0,0 +1,11 @@
//Mock Terraform Configuration File
resource "aws_eip" "nat" {
vpc = true
count = "${length(var.public_subnets)}"
}

resource "aws_nat_gateway" "nat" {
allocation_id = "${element(aws_eip.nat.*.id, count.index)}"
subnet_id = "${element(aws_subnet.public.*.id, count.index)}"
count = "${length(var.public_subnets)}"
}
29 changes: 29 additions & 0 deletions file_utils.go
@@ -0,0 +1,29 @@
package main

import (
"os"
"path/filepath"

log "github.com/sirupsen/logrus"
)

func getAllFiles(ext string) ([]string, error) {
dir, err := os.Getwd()
checkError(err)
var files []string
log.Infof("Finding files in %q directory", dir)
files, err = filepath.Glob(ext)
checkError(err)

if len(files) == 0 {
log.Infof("No files with %q extensions found in %q", ext, dir)
}
return files, nil
}

func fileExists(name string) bool {
if _, err := os.Stat(name); err == nil {
return true
}
return false
}
79 changes: 79 additions & 0 deletions generator.go
@@ -0,0 +1,79 @@
package main

import (
"bufio"
"html/template"
"os"
"strings"
"sync"

log "github.com/sirupsen/logrus"
)

var replacer *strings.Replacer
var varPrefix = "var."
var tfFileExt = "*.tf"

var dstFile = "./variables.tf"
var varTemplate = template.Must(template.New("var_file").Parse(`{{range .}}
variable "{{ . }}" {
description = ""
}
{{end}}
`))

func init() {
replacer = strings.NewReplacer(":", ".",
"]", "",
"}", "",
"{", "",
"\"", "",
")", "",
"(", "",
"[", "",
",", "",
"var.", "",
" ", "",
)
}
func main() {
if fileExists(dstFile) {
userPromt()
}

tfFiles, err := getAllFiles(tfFileExt)
if len(tfFiles) == 0 {
log.Warn("No terraform files to proceed, exiting")
os.Exit(0)
}
checkError(err)
var wg sync.WaitGroup
messages := make(chan string)
wg.Add(len(tfFiles))
t := &terraformVars{}

for _, file := range tfFiles {
go func(file string) {
defer wg.Done()
fileHandle, _ := os.Open(file)
defer fileHandle.Close()
fileScanner := bufio.NewScanner(fileHandle)
for fileScanner.Scan() {
messages <- fileScanner.Text()
}
}(file)
}
go func() {
for text := range messages {
t.matchVarPref(text, varPrefix)
}
}()
wg.Wait()
f, err := os.Create(dstFile)
checkError(err)

err = varTemplate.Execute(f, t.Variables)
checkError(err)
log.Infof("Variables are generated to %q file", dstFile)

}
48 changes: 48 additions & 0 deletions generator_test.go
@@ -0,0 +1,48 @@
package main

import (
"bufio"
"os"
"testing"
)

var mockFile = "tf_configuration.mock"
var testExtFile = "*.mock"

func TestContainsElement(t *testing.T) {
testSlice := []string{"Terraform", "Puppet", "Ansible"}
if containsElement(testSlice, "Chef") {
t.Error("Should return false, but return true")
}
}

func TestGetAllFiles(t *testing.T) {
files, err := getAllFiles(testExtFile)
checkError(err)
if len(files) == 0 {
t.Error("Should found at least one file")
}
}

func TestMatchVariable(t *testing.T) {
ter := &terraformVars{}
var messages []string

file, err := getAllFiles(testExtFile)
checkError(err)

fileHandle, _ := os.Open(file[0])
defer fileHandle.Close()

fileScanner := bufio.NewScanner(fileHandle)
for fileScanner.Scan() {
messages = append(messages, fileScanner.Text())
}
for _, text := range messages {
ter.matchVarPref(text, varPrefix)
}
if len(ter.Variables) != 1 {
t.Errorf("Should return one variable. but returned %d", len(ter.Variables))
}

}
37 changes: 37 additions & 0 deletions helpers.go
@@ -0,0 +1,37 @@
package main

import (
"fmt"
"os"

log "github.com/sirupsen/logrus"
)

func checkError(e error) {
if e != nil {
log.Fatal(e)
}
}

func containsElement(slice []string, value string) bool {
if len(slice) == 0 {
return false
}
for _, s := range slice {
if value == s {
return true
}
}
return false
}

func userPromt() {
var response string
log.Warnf("File %q already exists, type yes if you want replace", dstFile)
fmt.Print("-> ")
_, err := fmt.Scanln(&response)
checkError(err)
if response != "yes" {
os.Exit(0)
}
}
23 changes: 23 additions & 0 deletions terraform.go
@@ -0,0 +1,23 @@
package main

import (
"regexp"
"strings"
)

type terraformVars struct {
Variables []string
}

func (t *terraformVars) matchVarPref(row, varPrefix string) {
if strings.Contains(row, varPrefix) {
pattern := regexp.MustCompile(`var.([a-z?_]+)`)
match := pattern.FindAllStringSubmatch(row, 1)
if len(match) != 0 {
res := replacer.Replace(match[0][0])
if !containsElement(t.Variables, res) {
t.Variables = append(t.Variables, res)
}
}
}
}

0 comments on commit d33d29f

Please sign in to comment.