160 lines
3.9 KiB
Go
160 lines
3.9 KiB
Go
package tfexec
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
type formatConfig struct {
|
|
recursive bool
|
|
dir string
|
|
}
|
|
|
|
var defaultFormatConfig = formatConfig{
|
|
recursive: false,
|
|
}
|
|
|
|
type FormatOption interface {
|
|
configureFormat(*formatConfig)
|
|
}
|
|
|
|
func (opt *RecursiveOption) configureFormat(conf *formatConfig) {
|
|
conf.recursive = opt.recursive
|
|
}
|
|
|
|
func (opt *DirOption) configureFormat(conf *formatConfig) {
|
|
conf.dir = opt.path
|
|
}
|
|
|
|
// FormatString formats a passed string, given a path to Terraform.
|
|
func FormatString(ctx context.Context, execPath string, content string) (string, error) {
|
|
tf, err := NewTerraform(filepath.Dir(execPath), execPath)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return tf.FormatString(ctx, content)
|
|
}
|
|
|
|
// FormatString formats a passed string.
|
|
func (tf *Terraform) FormatString(ctx context.Context, content string) (string, error) {
|
|
in := strings.NewReader(content)
|
|
var outBuf strings.Builder
|
|
err := tf.Format(ctx, in, &outBuf)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return outBuf.String(), nil
|
|
}
|
|
|
|
// Format performs formatting on the unformatted io.Reader (as stdin to the CLI) and returns
|
|
// the formatted result on the formatted io.Writer.
|
|
func (tf *Terraform) Format(ctx context.Context, unformatted io.Reader, formatted io.Writer) error {
|
|
cmd, err := tf.formatCmd(ctx, nil, Dir("-"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
cmd.Stdin = unformatted
|
|
cmd.Stdout = mergeWriters(cmd.Stdout, formatted)
|
|
|
|
return tf.runTerraformCmd(ctx, cmd)
|
|
}
|
|
|
|
// FormatWrite attempts to format and modify all config files in the working or selected (via DirOption) directory.
|
|
func (tf *Terraform) FormatWrite(ctx context.Context, opts ...FormatOption) error {
|
|
for _, o := range opts {
|
|
switch o := o.(type) {
|
|
case *DirOption:
|
|
if o.path == "-" {
|
|
return fmt.Errorf("a path of \"-\" is not supported for this method, please use FormatString")
|
|
}
|
|
}
|
|
}
|
|
|
|
cmd, err := tf.formatCmd(ctx, []string{"-write=true", "-list=false", "-diff=false"}, opts...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return tf.runTerraformCmd(ctx, cmd)
|
|
}
|
|
|
|
// FormatCheck returns true if the config files in the working or selected (via DirOption) directory are already formatted.
|
|
func (tf *Terraform) FormatCheck(ctx context.Context, opts ...FormatOption) (bool, []string, error) {
|
|
for _, o := range opts {
|
|
switch o := o.(type) {
|
|
case *DirOption:
|
|
if o.path == "-" {
|
|
return false, nil, fmt.Errorf("a path of \"-\" is not supported for this method, please use FormatString")
|
|
}
|
|
}
|
|
}
|
|
|
|
cmd, err := tf.formatCmd(ctx, []string{"-write=false", "-list=true", "-diff=false", "-check=true"}, opts...)
|
|
if err != nil {
|
|
return false, nil, err
|
|
}
|
|
|
|
var outBuf strings.Builder
|
|
cmd.Stdout = mergeWriters(cmd.Stdout, &outBuf)
|
|
|
|
err = tf.runTerraformCmd(ctx, cmd)
|
|
if err == nil {
|
|
return true, nil, nil
|
|
}
|
|
if cmd.ProcessState.ExitCode() == 3 {
|
|
// unformatted, parse the file list
|
|
|
|
files := []string{}
|
|
lines := strings.Split(strings.Replace(outBuf.String(), "\r\n", "\n", -1), "\n")
|
|
for _, l := range lines {
|
|
l = strings.TrimSpace(l)
|
|
if l == "" {
|
|
continue
|
|
}
|
|
files = append(files, l)
|
|
}
|
|
|
|
return false, files, nil
|
|
}
|
|
return false, nil, err
|
|
}
|
|
|
|
func (tf *Terraform) formatCmd(ctx context.Context, args []string, opts ...FormatOption) (*exec.Cmd, error) {
|
|
err := tf.compatible(ctx, tf0_7_7, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("fmt was first introduced in Terraform 0.7.7: %w", err)
|
|
}
|
|
|
|
c := defaultFormatConfig
|
|
|
|
for _, o := range opts {
|
|
switch o.(type) {
|
|
case *RecursiveOption:
|
|
err := tf.compatible(ctx, tf0_12_0, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("-recursive was added to fmt in Terraform 0.12: %w", err)
|
|
}
|
|
}
|
|
|
|
o.configureFormat(&c)
|
|
}
|
|
|
|
args = append([]string{"fmt", "-no-color"}, args...)
|
|
|
|
if c.recursive {
|
|
args = append(args, "-recursive")
|
|
}
|
|
|
|
if c.dir != "" {
|
|
args = append(args, c.dir)
|
|
}
|
|
|
|
return tf.buildTerraformCmd(ctx, nil, args...), nil
|
|
}
|