Skip to content

Commit 239da7d

Browse files
authored
Added support for locals.tf (#12)
* Added locals support and GitHub Actions
1 parent 781fb35 commit 239da7d

File tree

8 files changed

+160
-23
lines changed

8 files changed

+160
-23
lines changed

.github/workflows/pull_requests.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: pr
2+
on:
3+
pull_request:
4+
branches:
5+
- master
6+
jobs:
7+
build:
8+
name: Build
9+
runs-on: ubuntu-latest
10+
steps:
11+
- name: Setup Go
12+
uses: actions/setup-go@v1
13+
with:
14+
go-version: 1.15
15+
id: go
16+
- name: Code checkout
17+
uses: actions/checkout@v2
18+
with:
19+
fetch-depth: 0
20+
- uses: actions/cache@v2
21+
with:
22+
path: ~/go/pkg/mod
23+
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
24+
restore-keys: |
25+
${{ runner.os }}-go-
26+
27+
- name: Test
28+
run: go test -v -race ./...
29+
30+
- name: Lint
31+
uses: golangci/golangci-lint-action@v2

.github/workflows/release.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: release
2+
on:
3+
push:
4+
tags:
5+
- '*'
6+
jobs:
7+
goreleaser:
8+
runs-on: ubuntu-latest
9+
steps:
10+
-
11+
name: Checkout
12+
uses: actions/checkout@v2
13+
with:
14+
fetch-depth: 0
15+
-
16+
name: Set up Go
17+
uses: actions/setup-go@v2
18+
with:
19+
go-version: 1.15
20+
-
21+
name: Run GoReleaser
22+
uses: goreleaser/goreleaser-action@v2
23+
with:
24+
version: latest
25+
args: release --rm-dist
26+
env:
27+
GITHUB_TOKEN: ${{ secrets.TOKEN }}

README.md

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
11
# terraform-variables-generator
22

3+
Terraform versions support ![version](https://img.shields.io/badge/version-0.11.*-blue) ![version](https://img.shields.io/badge/version-0.12.*-blue) ![version](https://img.shields.io/badge/version-0.13.*-blue)
4+
35
Simple Tool to Generate Variables file from Terraform Configuration. It will find all *.tf files in current directory, and generate variables.tf file. If you already have this file, it will ask to override it.
46

7+
| Version | Supports |
8+
|---------|----------|
9+
| 0.11.* | yes |
10+
| 0.12.* | yes |
11+
| 0.13.* | yes |
12+
13+
514
## Build
615

716
```bash
@@ -20,17 +29,17 @@ It will find all *.tf files in current directory, and generate variables.tf file
2029

2130
```text
2231
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}"
32+
cidr_block = var.cidr
33+
enable_dns_hostnames = var.enable_dns_hostnames
34+
enable_dns_support = var.enable_dns_support
2635
2736
tags {
28-
Name = "${var.name}"
37+
Name = var.name
2938
}
3039
}
3140
3241
resource "aws_internet_gateway" "vpc" {
33-
vpc_id = "${aws_vpc.vpc.id}"
42+
vpc_id = aws_vpc.vpc.id
3443
3544
tags {
3645
Name = "${var.name}-igw"
@@ -74,3 +83,7 @@ Run tests and linter
7483
go test -v -race ./...
7584
golint -set_exit_status $(go list ./...)
7685
```
86+
87+
## TO DO
88+
89+
Move Locals and Variables to Single Interface

cmd/cmd.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ const (
1919
var (
2020
generatorVersion string
2121

22-
vars bool
23-
varsFile string
22+
vars bool
23+
varsFile string
24+
localsFile string
2425
)
2526

2627
// Execute will run main logic
@@ -37,6 +38,7 @@ func Execute(version string) {
3738

3839
cmd.PersistentFlags().BoolVar(&vars, "vars", true, "generate variables")
3940
cmd.PersistentFlags().StringVar(&varsFile, "vars-file", "./variables.tf", "path to generated variables file")
41+
cmd.PersistentFlags().StringVar(&localsFile, "locals-file", "./locals.tf", "path to generated locals file")
4042

4143
if err := cmd.Execute(); err != nil {
4244
fmt.Println(err)
@@ -51,13 +53,17 @@ func runGenerator(cmd *cobra.Command, args []string) {
5153
utils.UserPromt(varsFile)
5254
}
5355

56+
if utils.FileExists(localsFile) {
57+
utils.UserPromt(localsFile)
58+
}
59+
5460
tfFiles, err := utils.GetAllFiles(tfFileExt)
5561
utils.CheckError(err)
5662
if len(tfFiles) == 0 {
5763
log.Warn("No terraform files to proceed, exiting")
5864
return
5965
}
6066

61-
generator.GenerateVars(tfFiles, varsFile)
67+
generator.Generate(tfFiles, varsFile, localsFile)
6268
}
6369
}

pkg/generator/configuration.mock

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
//Mock Terraform Configuration File
22
resource "aws_eip" "nat" {
33
vpc = true
4-
count = "${length(var.public_subnets)}"
4+
count = length(var.public_subnets)
5+
tags {
6+
Name = local.name_internal
7+
Env = "${local.env}-env"
8+
}
59
}
610

711
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)}"
12+
allocation_id = element(aws_eip.nat.*.id, count.index)
13+
subnet_id = element(aws_subnet.public.*.id, count.index)}"
1014
count = "${length(var.public_subnets)}"
1115
}
1216

1317
data "template_file" "template1" {
14-
template = "${file("${path.module}/template1.tpl")}"
18+
template = file("${path.module}/template1.tpl")
1519
vars {
1620
t1_var1 = "${var.t1_var1}"
17-
t1-var2 = "${var.t1-var2}"
21+
t1-var2 = var.t1-var2
1822
t1-var3 = "${var.t1-Var3}-${var.t1-inline}"
1923
}
2024
}

pkg/generator/terraform.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010

1111
type terraformVars struct {
1212
Variables []string
13+
Locals []string
1314
}
1415

1516
func (t *terraformVars) matchVarPref(row, varPrefix string) {
@@ -25,6 +26,19 @@ func (t *terraformVars) matchVarPref(row, varPrefix string) {
2526
}
2627
}
2728

28-
func (t *terraformVars) sortVars() {
29-
sort.Strings(t.Variables)
29+
func (t *terraformVars) matchLocalPref(row, localPrefix string) {
30+
if strings.Contains(row, localPrefix) {
31+
pattern := regexp.MustCompile(`local.([a-z?A-Z?0-9?_][a-z?A-Z?0-9?_?-]*)`)
32+
match := pattern.FindAllStringSubmatch(row, -1)
33+
for _, m := range match {
34+
res := replacer.Replace(m[0])
35+
if !utils.ContainsElement(t.Locals, res) {
36+
t.Locals = append(t.Locals, res)
37+
}
38+
}
39+
}
40+
}
41+
42+
func (t *terraformVars) sort(vars []string) {
43+
sort.Strings(vars)
3044
}

pkg/generator/vars.go

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,19 @@ import (
1414

1515
var replacer *strings.Replacer
1616
var varPrefix = "var."
17+
var localPrefix = "local."
1718

1819
var varTemplate = template.Must(template.New("var_file").Parse(`{{range .}}
1920
variable "{{ . }}" {
2021
description = ""
2122
}
2223
{{end}}`))
2324

25+
var localsTemplate = template.Must(template.New("locals_file").Parse(`locals { {{ range . }}
26+
{{ . }} ={{ end }}
27+
}
28+
`))
29+
2430
func init() {
2531
replacer = strings.NewReplacer(":", ".",
2632
"]", "",
@@ -32,12 +38,13 @@ func init() {
3238
"[", "",
3339
",", "",
3440
"var.", "",
41+
"local.", "",
3542
" ", "",
3643
)
3744
}
3845

39-
// GenerateVars will write generated vars to file
40-
func GenerateVars(tfFiles []string, dstFile string) {
46+
// Generate will write inputs to file
47+
func Generate(tfFiles []string, varsDstFile string, localsDstFile string) {
4148
var wg sync.WaitGroup
4249
messages := make(chan string)
4350
wg.Add(len(tfFiles))
@@ -57,14 +64,27 @@ func GenerateVars(tfFiles []string, dstFile string) {
5764
go func() {
5865
for text := range messages {
5966
t.matchVarPref(text, varPrefix)
67+
t.matchLocalPref(text, localPrefix)
6068
}
6169
}()
6270
wg.Wait()
63-
f, err := os.Create(dstFile)
64-
utils.CheckError(err)
6571

66-
t.sortVars()
67-
err = varTemplate.Execute(f, t.Variables)
68-
utils.CheckError(err)
69-
log.Infof("Variables are generated to %q file", dstFile)
72+
if len(t.Variables) > 0 {
73+
f, err := os.Create(varsDstFile)
74+
utils.CheckError(err)
75+
log.Infof("Variables are generated to %q file", varsDstFile)
76+
77+
t.sort(t.Variables)
78+
err = varTemplate.Execute(f, t.Variables)
79+
utils.CheckError(err)
80+
}
81+
82+
if len(t.Locals) > 0 {
83+
t.sort(t.Locals)
84+
localsFile, err := os.Create(localsDstFile)
85+
utils.CheckError(err)
86+
err = localsTemplate.Execute(localsFile, t.Locals)
87+
utils.CheckError(err)
88+
log.Infof("Locals are generated to %q file", localsDstFile)
89+
}
7090
}

pkg/generator/vars_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,27 @@ func TestMatchVariable(t *testing.T) {
4646
t.Errorf("Should return five variable. but returned %d", len(ter.Variables))
4747
t.Errorf("Variables found: %s", ter.Variables)
4848
}
49+
}
4950

51+
func TestMatchLocal(t *testing.T) {
52+
ter := &terraformVars{}
53+
var messages []string
54+
55+
file, err := utils.GetAllFiles(testExtFile)
56+
utils.CheckError(err)
57+
58+
fileHandle, _ := os.Open(file[0])
59+
defer fileHandle.Close()
60+
61+
fileScanner := bufio.NewScanner(fileHandle)
62+
for fileScanner.Scan() {
63+
messages = append(messages, fileScanner.Text())
64+
}
65+
for _, text := range messages {
66+
ter.matchLocalPref(text, localPrefix)
67+
}
68+
if len(ter.Locals) != 2 {
69+
t.Errorf("Should return two variable. but returned %d", len(ter.Locals))
70+
t.Errorf("Variables found: %s", ter.Locals)
71+
}
5072
}

0 commit comments

Comments
 (0)