Skip to content

Commit 09ac1dc

Browse files
author
Samyak Rout
committed
feat: Modularize providers and add new Terraform commands
- Updated providers.tf.tmpl to include a dynamic backend block, allowing support for multiple backend types by specifying backend type and parameters in the configuration. - Enhanced main.go to remove the -backend-config flag from the Terraform init command. - Added support for new Terraform commands: validate and destroy. - Modified the build command to sequentially execute init, validate, plan, and apply. - Updated terraform-generator.json structure to accommodate dynamic backend configurations. This commit enhances the flexibility and scalability of the Terraform code generation process, allowing easier integration of various providers and backends.
1 parent 5c16337 commit 09ac1dc

File tree

3 files changed

+88
-29
lines changed

3 files changed

+88
-29
lines changed

infra_as_code/terraform_generator/backend/main.go

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,31 @@ import (
1515
)
1616

1717
func main() {
18+
// Define subcommands
1819
generateCmd := flag.NewFlagSet("generate", flag.ExitOnError)
20+
terraformCmd := flag.NewFlagSet("terraform", flag.ExitOnError)
21+
22+
// Define flags for 'generate' subcommand
1923
company := generateCmd.String("company", "", "Company name (required)")
2024
product := generateCmd.String("product", "", "Product name (required)")
2125
provider := generateCmd.String("provider", "", "Provider name (required)")
2226
modules := generateCmd.String("modules", "", "Comma-separated list of modules")
2327
customers := generateCmd.String("customers", "", "Comma-separated list of customers")
2428

25-
terraformCmd := flag.NewFlagSet("terraform", flag.ExitOnError)
26-
tfCommand := terraformCmd.String("command", "", "Terraform command to execute (init, plan, apply, build, print)")
29+
// Define flags for 'terraform' subcommand
30+
tfCommand := terraformCmd.String("command", "", "Terraform command to execute (init, validate, plan, apply, build, destroy, print)")
2731
tfCompany := terraformCmd.String("company", "", "Company name (required)")
2832
tfProduct := terraformCmd.String("product", "", "Product name (required)")
2933
tfProvider := terraformCmd.String("provider", "", "Provider name (required)")
3034
tfInfratype := terraformCmd.String("infratype", "", "Infrastructure type (prod or nonprod)")
3135

36+
// Ensure a subcommand is provided
3237
if len(os.Args) < 2 {
3338
fmt.Println("Expected 'generate' or 'terraform' subcommands")
3439
os.Exit(1)
3540
}
3641

42+
// Parse subcommands
3743
switch os.Args[1] {
3844
case "generate":
3945
generateCmd.Parse(os.Args[2:])
@@ -53,12 +59,15 @@ func main() {
5359
}
5460
}
5561

62+
// handleGenerateCommand processes the 'generate' subcommand
5663
func handleGenerateCommand(company, product, provider, modules, customers string) {
64+
// Validate required flags
5765
if company == "" || product == "" || provider == "" {
5866
fmt.Println("Error: --company, --product, and --provider are required")
5967
os.Exit(1)
6068
}
6169

70+
// Create a GenerateRequest
6271
req := models.GenerateRequest{
6372
OrganisationName: company,
6473
ProductName: product,
@@ -82,6 +91,7 @@ func handleGenerateCommand(company, product, provider, modules, customers string
8291
}
8392
}
8493

94+
// Generate Terraform code
8595
if err := services.GenerateTerraform(&req); err != nil {
8696
fmt.Printf("Error generating Terraform code: %v\n", err)
8797
os.Exit(1)
@@ -90,41 +100,51 @@ func handleGenerateCommand(company, product, provider, modules, customers string
90100
fmt.Println("Terraform code generated successfully")
91101
}
92102

103+
// handleTerraformCommand processes the 'terraform' subcommand
93104
func handleTerraformCommand(command, company, product, provider, infratype string) {
105+
// Validate required flags
94106
if command == "" || company == "" || product == "" || provider == "" {
95107
fmt.Println("Error: --command, --company, --product, and --provider are required")
96108
os.Exit(1)
97109
}
98110

99-
// 'init', 'build', and 'print' commands require '--infratype'
100-
if (command == "init" || command == "build" || command == "print") && infratype == "" {
101-
fmt.Println("Error: --infratype is required for 'init', 'build', and 'print' commands")
111+
// Certain commands require 'infratype'
112+
if (command == "init" || command == "build" || command == "print" || command == "validate") && infratype == "" {
113+
fmt.Println("Error: --infratype is required for 'init', 'build', 'print', and 'validate' commands")
102114
os.Exit(1)
103115
}
104116

117+
// Handle 'print' command separately
105118
if command == "print" {
106119
printTerraformCommands(command, company, product, provider, infratype)
107120
} else {
121+
// Execute other Terraform commands
108122
if err := runTerraformCommand(command, company, product, provider, infratype); err != nil {
109123
log.Fatalf("Error executing Terraform command: %v\n", err)
110124
}
111125
}
112126
}
113127

128+
// runTerraformCommand executes the specified Terraform command
114129
func runTerraformCommand(command, company, product, provider, infratype string) error {
115130
terraformDir := filepath.Join("output", "terraform", company, product)
116131
if _, err := os.Stat(terraformDir); os.IsNotExist(err) {
117132
return fmt.Errorf("Terraform directory %s does not exist", terraformDir)
118133
}
119134

135+
// Change to the Terraform directory
120136
if err := os.Chdir(terraformDir); err != nil {
121137
return fmt.Errorf("error changing directory to %s: %v", terraformDir, err)
122138
}
123139

124140
switch command {
125141
case "init":
126-
backendConfig := fmt.Sprintf("backend/%s_%s.tfvars", product, strings.ToLower(infratype))
127-
args := []string{"init", "-no-color", "-get=true", "-force-copy", fmt.Sprintf("-backend-config=%s", backendConfig)}
142+
// Removed -backend-config
143+
args := []string{"init", "-no-color", "-get=true", "-force-copy"}
144+
return executeCommand("terraform", args)
145+
146+
case "validate":
147+
args := []string{"validate", "-no-color"}
128148
return executeCommand("terraform", args)
129149

130150
case "plan":
@@ -135,10 +155,15 @@ func runTerraformCommand(command, company, product, provider, infratype string)
135155
args := []string{"apply", "-no-color", "-input=false", "-auto-approve=true", "-lock=true", "-lock-timeout=7200s", "-refresh=true", "-var-file=./vars.tfvars"}
136156
return executeCommand("terraform", args)
137157

158+
case "destroy":
159+
args := []string{"destroy", "-no-color", "-auto-approve=true", "-var-file=./vars.tfvars"}
160+
return executeCommand("terraform", args)
161+
138162
case "build":
139-
backendConfig := fmt.Sprintf("backend/%s_%s.tfvars", product, strings.ToLower(infratype))
163+
// Sequentially execute init, validate, plan, and apply
140164
buildCommands := [][]string{
141-
{"init", "-no-color", "-get=true", "-force-copy", fmt.Sprintf("-backend-config=%s", backendConfig)},
165+
{"init", "-no-color", "-get=true", "-force-copy"},
166+
{"validate", "-no-color"},
142167
{"plan", "-no-color", "-input=false", "-lock=true", "-refresh=true", "-var-file=./vars.tfvars"},
143168
{"apply", "-no-color", "-input=false", "-auto-approve=true", "-lock=true", "-lock-timeout=7200s", "-refresh=true", "-var-file=./vars.tfvars"},
144169
}
@@ -156,16 +181,33 @@ func runTerraformCommand(command, company, product, provider, infratype string)
156181
return nil
157182
}
158183

184+
// printTerraformCommands prints the Terraform commands without executing them
159185
func printTerraformCommands(command, company, product, provider, infratype string) {
160186
terraformDir := filepath.Join("output", "terraform", company, product)
161187
fmt.Printf("Working directory: %s\n", terraformDir)
162188

163-
backendConfig := fmt.Sprintf("backend/%s_%s.tfvars", product, strings.ToLower(infratype))
164-
fmt.Printf("terraform init -no-color -get=true -force-copy -backend-config=%s\n", backendConfig)
165-
fmt.Println("terraform plan -no-color -input=false -lock=true -refresh=true -var-file=./vars.tfvars")
166-
fmt.Println("terraform apply -no-color -input=false -auto-approve=true -lock=true -lock-timeout=7200s -refresh=true -var-file=./vars.tfvars")
189+
switch command {
190+
case "init":
191+
fmt.Println("terraform init -no-color -get=true -force-copy")
192+
case "validate":
193+
fmt.Println("terraform validate -no-color")
194+
case "plan":
195+
fmt.Println("terraform plan -no-color -input=false -lock=true -refresh=true -var-file=./vars.tfvars")
196+
case "apply":
197+
fmt.Println("terraform apply -no-color -input=false -auto-approve=true -lock=true -lock-timeout=7200s -refresh=true -var-file=./vars.tfvars")
198+
case "destroy":
199+
fmt.Println("terraform destroy -no-color -auto-approve=true -var-file=./vars.tfvars")
200+
case "build":
201+
fmt.Println("terraform init -no-color -get=true -force-copy")
202+
fmt.Println("terraform validate -no-color")
203+
fmt.Println("terraform plan -no-color -input=false -lock=true -refresh=true -var-file=./vars.tfvars")
204+
fmt.Println("terraform apply -no-color -input=false -auto-approve=true -lock=true -lock-timeout=7200s -refresh=true -var-file=./vars.tfvars")
205+
default:
206+
fmt.Printf("Unsupported command: %s\n", command)
207+
}
167208
}
168209

210+
// executeCommand runs a shell command and streams its output
169211
func executeCommand(command string, args []string) error {
170212
cmd := exec.Command(command, args...)
171213
cmd.Stdout = os.Stdout

infra_as_code/terraform_generator/backend/models/config.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,16 @@ type Provider struct {
2020
}
2121

2222
type Backend struct {
23-
ResourceGroupName string `json:"resource_group_name"`
24-
StorageAccountName string `json:"storage_account_name"`
25-
ContainerName string `json:"container_name"`
26-
Key string `json:"key"`
27-
SubscriptionId string `json:"subscription_id"`
28-
TenantID string `json:"tenant_id"`
29-
ClientID string `json:"client_id"`
30-
AccessKey string `json:"access_key"`
23+
Type string `json:"type"`
24+
Parameters map[string]string `json:"parameters"`
25+
ResourceGroupName string `json:"resource_group_name"`
26+
StorageAccountName string `json:"storage_account_name"`
27+
ContainerName string `json:"container_name"`
28+
Key string `json:"key"`
29+
SubscriptionId string `json:"subscription_id"`
30+
TenantID string `json:"tenant_id"`
31+
ClientID string `json:"client_id"`
32+
AccessKey string `json:"access_key"`
3133
}
3234

3335
type Module struct {
Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,31 @@
1-
{{- range $module := .Modules }}
2-
module "{{ $module.ModuleName }}" {
3-
source = "{{ $module.Source }}"
4-
{{- $moduleVars := index $.ModuleVariables $module.ModuleName }}
1+
terraform {
2+
backend "azurerm" {
3+
resource_group_name = "{{ .Backend.ResourceGroupName }}"
4+
storage_account_name = "{{ .Backend.StorageAccountName }}"
5+
container_name = "{{ .Backend.ContainerName }}"
6+
key = "{{ .Backend.Key }}"
7+
access_key = "{{ .Backend.AccessKey }}"
8+
subscription_id = "{{ .Backend.SubscriptionId }}"
9+
tenant_id = "{{ .Backend.TenantID }}"
10+
client_id = "{{ .Backend.ClientID }}"
11+
}
12+
}
13+
14+
{{- range .Modules }}
15+
module "{{ .ModuleName }}" {
16+
source = "{{ .Source }}"
17+
18+
{{- $moduleVars := index $.ModuleVariables .ModuleName }}
519
{{- range $varName, $var := $moduleVars }}
620
{{ $varName }} = {{ formatValue $var.Value $var.Type }}
721
{{- end }}
8-
{{- if $module.DependsOn }}
22+
23+
{{- if .DependsOn }}
924
depends_on = [
10-
{{- range $index, $dependency := $module.DependsOn }}
11-
module.{{ $dependency }}{{ if lt (add $index 1) (len $module.DependsOn) }},{{ end }}
25+
{{- range $index, $dependency := .DependsOn }}
26+
module.{{ $dependency }}{{ if lt (add $index 1) (len .DependsOn) }},{{ end }}
1227
{{- end }}
1328
]
1429
{{- end }}
1530
}
16-
{{ end }}
31+
{{- end }}

0 commit comments

Comments
 (0)