Skip to content

Commit

Permalink
Add dev mode to Terraplate
Browse files Browse the repository at this point in the history
Significant refactoring needed, in order or dev mode to also be able to perform
runs, and therefore made the build step another task in a run.
  • Loading branch information
jlarfors committed Aug 18, 2022
1 parent 5112fc5 commit acdbbd8
Show file tree
Hide file tree
Showing 44 changed files with 2,202 additions and 385 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
restore-keys: |
${{ runner.os }}-go-
- name: Test
run: go test -failfast ./...
run: go test -v -failfast ./...
# Build with GoReleaser (but don't release!).
# This verifies that the GoReleaser config is valid and can build
- name: Run GoReleaser
Expand Down
46 changes: 23 additions & 23 deletions builder/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,44 @@ package builder

import (
"fmt"
"io"
"os"
"path/filepath"
"reflect"
"sort"

"github.com/hashicorp/go-multierror"
"github.com/fatih/color"
"github.com/hashicorp/hcl/v2/hclwrite"
"github.com/verifa/terraplate/parser"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/gocty"
)

// Build takes a TerraConfig as input and builds all the templates and terraform
// files
func Build(config *parser.TerraConfig) error {
var buildErrs error
for _, terrafile := range config.RootModules() {
var errorColor = color.New(color.FgRed, color.Bold)

if err := buildTerraplate(terrafile, config); err != nil {
buildErrs = multierror.Append(buildErrs, fmt.Errorf("building Terraplate Terraform file: %w", err))
continue
}

if err := buildTemplates(terrafile); err != nil {
buildErrs = multierror.Append(buildErrs, fmt.Errorf("building templates: %w", err))
continue
}

fmt.Printf("%s: Built %d templates\n", terrafile.RelativeDir(), len(terrafile.Templates))
// BuildTerrafile takes an input Terrafile and builds it, writing any output
// to the provided io.Writer
func BuildTerrafile(tf *parser.Terrafile, out io.Writer) error {
if err := buildTerraplate(tf, out); err != nil {
buildErr := fmt.Errorf("building Terraplate Terraform file: %w", err)
fmt.Fprintf(out, "\n%s: %v", errorColor.Sprint("Error"), buildErr)
return buildErr
}

if buildErrs != nil {
return fmt.Errorf("building root modules: %s", buildErrs)
if err := buildTemplates(tf, out); err != nil {
buildErr := fmt.Errorf("building templates: %w", err)
fmt.Fprintf(out, "\n%s: %v", errorColor.Sprint("Error"), buildErr)
return buildErr
}

return nil
}

// buildTemplates builds the templates associated with the given terrafile
func buildTemplates(tf *parser.Terrafile) error {
func buildTemplates(tf *parser.Terrafile, out io.Writer) error {
for _, tmpl := range tf.Templates {
target := filepath.Join(tf.Dir, tmpl.Target)
fmt.Fprintf(out, "Building template %s to %s\n", tmpl.Name, target)

data, dataErr := tf.BuildData()
if dataErr != nil {
return fmt.Errorf("getting build data for %s: %w", tf.Path, dataErr)
Expand All @@ -56,7 +53,7 @@ func buildTemplates(tf *parser.Terrafile) error {
continue
}
}
target := filepath.Join(tf.Dir, tmpl.Target)

content := defaultTemplateHeader(tf, tmpl) + tmpl.Contents
if err := parser.TemplateWrite(data, tmpl.Name, content, target); err != nil {
return fmt.Errorf("creating template %s in terrafile %s: %w", tmpl.Name, tf.RelativePath(), err)
Expand All @@ -67,8 +64,11 @@ func buildTemplates(tf *parser.Terrafile) error {

// buildTerraplate builds the terraplate terraform file which contains the
// variables (with defaults) and terraform block
func buildTerraplate(terrafile *parser.Terrafile, config *parser.TerraConfig) error {
func buildTerraplate(terrafile *parser.Terrafile, out io.Writer) error {

path := filepath.Join(terrafile.Dir, "terraplate.tf")
fmt.Fprintf(out, "Building terraplate.tf file to %s\n", path)

// Create the Terraform file
tfFile := hclwrite.NewEmptyFile()

Expand Down
23 changes: 9 additions & 14 deletions cmd/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (
"fmt"

"github.com/spf13/cobra"
"github.com/verifa/terraplate/builder"
"github.com/verifa/terraplate/parser"
"github.com/verifa/terraplate/runner"
)
Expand All @@ -40,23 +39,19 @@ templates and configurations detected.`,
return fmt.Errorf("parsing terraplate: %w", err)
}

if err := builder.Build(config); err != nil {
return fmt.Errorf("building terraplate: %w", err)
runOpts := []func(r *runner.TerraRunOpts){
runner.RunBuild(),
}

fmt.Print(buildSuccessMessage)

if doValidate {
runner := runner.Run(config, runner.RunInit(), runner.RunValidate())
// Print log
fmt.Println(runner.Log())

if runner.HasError() {
return runner.Errors()
}
runOpts = append(runOpts, runner.RunValidate())
}
runOpts = append(runOpts, runner.ExtraArgs(args))
runner := runner.Run(config, runOpts...)

fmt.Println(runner.Log())
fmt.Println(runner.Summary())

return nil
return runner.Errors()
},
}

Expand Down
72 changes: 72 additions & 0 deletions cmd/dev.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
Copyright © 2021 Verifa <[email protected]>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd

import (
"fmt"
"io"
"os"

tea "github.com/charmbracelet/bubbletea"
"github.com/spf13/cobra"
"github.com/verifa/terraplate/parser"
"github.com/verifa/terraplate/runner"
"github.com/verifa/terraplate/tui"
)

// devCmd represents the plan command
var devCmd = &cobra.Command{
Use: "dev",
Short: "Enters dev mode which launches a Terminal UI for Terraplate",
Long: `Enters dev mode which launches a Terminal UI for building and running Terraplate root modules.`,
RunE: func(cmd *cobra.Command, args []string) error {
// Parse
config, err := parser.Parse(&config.ParserConfig)
if err != nil {
return fmt.Errorf("parsing terraplate: %w", err)
}

// Dev mode
fmt.Print(devStartMessage)
runOpts := []func(r *runner.TerraRunOpts){
runner.RunBuild(),
runner.RunPlan(),
runner.RunShowPlan(),
runner.Jobs(planJobs),
// Discard any output from the runner itself.
// This does not discard the Terraform output.
runner.Output(io.Discard),
}
runOpts = append(runOpts, runner.ExtraArgs(args))
runner := runner.New(config, runOpts...)

p := tea.NewProgram(
tui.New(runner),
tea.WithAltScreen(),
tea.WithMouseCellMotion(),
)
if err := p.Start(); err != nil {
fmt.Printf("Alas, there's been an error: %v", err)
os.Exit(1)
}
return nil
},
}

func init() {
RootCmd.AddCommand(devCmd)
devCmd.Flags().IntVarP(&planJobs, "jobs", "j", runner.DefaultJobs, "Number of concurrent terraform jobs to run at one time")
}
10 changes: 2 additions & 8 deletions cmd/drift.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (
"fmt"

"github.com/spf13/cobra"
"github.com/verifa/terraplate/builder"
"github.com/verifa/terraplate/notify"
"github.com/verifa/terraplate/parser"
"github.com/verifa/terraplate/runner"
Expand Down Expand Up @@ -58,15 +57,10 @@ var driftCmd = &cobra.Command{
if err != nil {
return fmt.Errorf("parsing terraplate: %w", err)
}
// Build
fmt.Print(buildStartMessage)
if err := builder.Build(config); err != nil {
return err
}
fmt.Print(buildSuccessMessage)
// Plan
fmt.Print(terraformStartMessage)
runOpts := []func(r *runner.TerraRunOpts){
runner.RunBuild(),
runner.RunInit(),
runner.RunPlan(),
runner.RunShowPlan(),
Expand All @@ -92,7 +86,7 @@ var driftCmd = &cobra.Command{
}
}

fmt.Print(runner.PlanSummary())
fmt.Print(runner.Summary())
return nil
},
}
Expand Down
26 changes: 23 additions & 3 deletions cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ import (
"github.com/verifa/terraplate/runner"
)

var initJobs int
var (
initJobs int
initSkipBuild bool
initUpgrade bool
)

// initCmd represents the init command
var initCmd = &cobra.Command{
Expand All @@ -35,9 +39,23 @@ var initCmd = &cobra.Command{
if err != nil {
return fmt.Errorf("parsing terraplate: %w", err)
}
runner := runner.Run(config, runner.RunInit(), runner.Jobs(initJobs), runner.ExtraArgs(args))
// Print log
runOpts := []func(r *runner.TerraRunOpts){
runner.RunInit(),
runner.Jobs(initJobs),
runner.ExtraArgs(args),
}

if !initSkipBuild {
runOpts = append(runOpts, runner.RunBuild())
}
if initUpgrade {
runOpts = append(runOpts, runner.RunInitUpgrade())
}

runOpts = append(runOpts, runner.ExtraArgs(args))
runner := runner.Run(config, runOpts...)
fmt.Println(runner.Log())
fmt.Println(runner.Summary())

return runner.Errors()
},
Expand All @@ -46,5 +64,7 @@ var initCmd = &cobra.Command{
func init() {
RootCmd.AddCommand(initCmd)

initCmd.Flags().BoolVar(&initSkipBuild, "skip-build", false, "Skip build process (default: false)")
initCmd.Flags().BoolVarP(&initUpgrade, "upgrade", "u", false, "Perform upgrade when initializing")
initCmd.Flags().IntVarP(&initJobs, "jobs", "j", runner.DefaultJobs, "Number of concurrent terraform jobs to run at one time")
}
6 changes: 1 addition & 5 deletions cmd/messages.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
package cmd

import (
"fmt"

"github.com/fatih/color"
)

var (
successColor = color.New(color.FgGreen, color.Bold)
errorColor = color.New(color.FgRed, color.Bold)
boldText = color.New(color.Bold)
buildStartMessage = boldText.Sprint("\nBuilding root modules...\n\n")
buildSuccessMessage = fmt.Sprintf("\n%s All root modules built\n\n", successColor.Sprint("Success!"))
terraformStartMessage = boldText.Sprint("\nTerraforming root modules...\n\n")
devStartMessage = boldText.Sprint("\nStarting dev mode...\n\n")
)
Loading

0 comments on commit acdbbd8

Please sign in to comment.