func (d *debugInfo) flush() {
	d.tar.Flush()
	d.gz.Flush()
	if f, ok := d.w.(flusher); ok {
		f.Flush()
	}
	if s, ok := d.w.(syncer); ok {
		s.Sync()
	}
}
Flush the tar.Writer and the gzip.Writer. Flush() or Sync() will be called
on the output writer if they are available.
package terraform
import (
	"archive/tar"
	"bytes"
	"compress/gzip"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"sync"
	"time"
)
var dbug *debugInfo
func SetDebugInfo(path string) error {
	if os.Getenv("TF_DEBUG") == "" {
		return nil
	}
	di, err := newDebugInfoFile(path)
	if err != nil {
		return err
	}
	dbug = di
	return nil
}
func CloseDebugInfo() error {
	return dbug.Close()
}
func newDebugInfoFile(dir string) (*debugInfo, error) {
	err := os.MkdirAll(dir, 0755)
	if err != nil {
		return nil, err
	}
	name := fmt.Sprintf("debug-%s", time.Now().Format("2006-01-02-15-04-05.999999999"))
	archivePath := filepath.Join(dir, name+".tar.gz")
	f, err := os.OpenFile(archivePath, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666)
	if err != nil {
		return nil, err
	}
	return newDebugInfo(name, f)
}
func newDebugInfo(name string, w io.Writer) (*debugInfo, error) {
	gz := gzip.NewWriter(w)
	d := &debugInfo{
		name: name,
		w:    w,
		gz:   gz,
		tar:  tar.NewWriter(gz),
	}
	topHdr := &tar.Header{
		Name:     name,
		Typeflag: tar.TypeDir,
		Mode:     0755,
	}
	graphsHdr := &tar.Header{
		Name:     name + "/graphs",
		Typeflag: tar.TypeDir,
		Mode:     0755,
	}
	err := d.tar.WriteHeader(topHdr)
	err = d.tar.WriteHeader(graphsHdr)
	if err != nil {
		return nil, err
	}
	return d, nil
}
type debugInfo struct {
	sync.Mutex
	name string
	phase string
	step int
	closed bool
	w   io.Writer
	gz  *gzip.Writer
	tar *tar.Writer
}
func (d *debugInfo) SetPhase(phase string) {
	if d == nil {
		return
	}
	d.Lock()
	defer d.Unlock()
	d.phase = phase
}
func (d *debugInfo) Close() error {
	if d == nil {
		return nil
	}
	d.Lock()
	defer d.Unlock()
	if d.closed {
		return nil
	}
	d.closed = true
	d.tar.Close()
	d.gz.Close()
	if c, ok := d.w.(io.Closer); ok {
		return c.Close()
	}
	return nil
}
type debugBuffer struct {
	debugInfo *debugInfo
	name      string
	buf       bytes.Buffer
}
func (b *debugBuffer) Write(d []byte) (int, error) {
	return b.buf.Write(d)
}
func (b *debugBuffer) Close() error {
	return b.debugInfo.WriteFile(b.name, b.buf.Bytes())
}
type nopWriteCloser struct{}
func (nopWriteCloser) Write([]byte) (int, error) { return 0, nil }
func (nopWriteCloser) Close() error              { return nil }
func (d *debugInfo) NewFileWriter(name string) io.WriteCloser {
	if d == nil {
		return nopWriteCloser{}
	}
	return &debugBuffer{
		debugInfo: d,
		name:      name,
	}
}
type syncer interface {
	Sync() error
}
type flusher interface {
	Flush() error
}