github.com/serbaut/terraform@v0.6.12-0.20160607213102-ac2d195cc560/command/format_state.go (about)

     1  package command
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"sort"
     7  	"strings"
     8  
     9  	"github.com/hashicorp/terraform/terraform"
    10  	"github.com/mitchellh/colorstring"
    11  )
    12  
    13  // FormatStateOpts are the options for formatting a state.
    14  type FormatStateOpts struct {
    15  	// State is the state to format. This is required.
    16  	State *terraform.State
    17  
    18  	// Color is the colorizer. This is optional.
    19  	Color *colorstring.Colorize
    20  
    21  	// ModuleDepth is the depth of the modules to expand. By default this
    22  	// is zero which will not expand modules at all.
    23  	ModuleDepth int
    24  }
    25  
    26  // FormatState takes a state and returns a string
    27  func FormatState(opts *FormatStateOpts) string {
    28  	if opts.Color == nil {
    29  		panic("colorize not given")
    30  	}
    31  
    32  	s := opts.State
    33  	if len(s.Modules) == 0 {
    34  		return "The state file is empty. No resources are represented."
    35  	}
    36  
    37  	var buf bytes.Buffer
    38  	buf.WriteString("[reset]")
    39  
    40  	// Format all the modules
    41  	for _, m := range s.Modules {
    42  		if len(m.Path)-1 <= opts.ModuleDepth || opts.ModuleDepth == -1 {
    43  			formatStateModuleExpand(&buf, m, opts)
    44  		} else {
    45  			formatStateModuleSingle(&buf, m, opts)
    46  		}
    47  	}
    48  
    49  	// Write the outputs for the root module
    50  	m := s.RootModule()
    51  	if len(m.Outputs) > 0 {
    52  		buf.WriteString("\nOutputs:\n\n")
    53  
    54  		// Sort the outputs
    55  		ks := make([]string, 0, len(m.Outputs))
    56  		for k, _ := range m.Outputs {
    57  			ks = append(ks, k)
    58  		}
    59  		sort.Strings(ks)
    60  
    61  		// Output each output k/v pair
    62  		for _, k := range ks {
    63  			v := m.Outputs[k]
    64  			switch output := v.Value.(type) {
    65  			case string:
    66  				buf.WriteString(fmt.Sprintf("%s = %s", k, output))
    67  				buf.WriteString("\n")
    68  			case []interface{}:
    69  				buf.WriteString(formatListOutput("", k, output))
    70  				buf.WriteString("\n")
    71  			case map[string]interface{}:
    72  				buf.WriteString(formatMapOutput("", k, output))
    73  				buf.WriteString("\n")
    74  			}
    75  		}
    76  	}
    77  
    78  	return opts.Color.Color(strings.TrimSpace(buf.String()))
    79  }
    80  
    81  func formatStateModuleExpand(
    82  	buf *bytes.Buffer, m *terraform.ModuleState, opts *FormatStateOpts) {
    83  	var moduleName string
    84  	if !m.IsRoot() {
    85  		moduleName = fmt.Sprintf("module.%s", strings.Join(m.Path[1:], "."))
    86  	}
    87  
    88  	// First get the names of all the resources so we can show them
    89  	// in alphabetical order.
    90  	names := make([]string, 0, len(m.Resources))
    91  	for name, _ := range m.Resources {
    92  		names = append(names, name)
    93  	}
    94  	sort.Strings(names)
    95  
    96  	// Go through each resource and begin building up the output.
    97  	for _, k := range names {
    98  		name := k
    99  		if moduleName != "" {
   100  			name = moduleName + "." + name
   101  		}
   102  
   103  		rs := m.Resources[k]
   104  		is := rs.Primary
   105  		var id string
   106  		if is != nil {
   107  			id = is.ID
   108  		}
   109  		if id == "" {
   110  			id = "<not created>"
   111  		}
   112  
   113  		taintStr := ""
   114  		if rs.Primary.Tainted {
   115  			taintStr = " (tainted)"
   116  		}
   117  
   118  		buf.WriteString(fmt.Sprintf("%s:%s\n", name, taintStr))
   119  		buf.WriteString(fmt.Sprintf("  id = %s\n", id))
   120  
   121  		if is != nil {
   122  			// Sort the attributes
   123  			attrKeys := make([]string, 0, len(is.Attributes))
   124  			for ak, _ := range is.Attributes {
   125  				// Skip the id attribute since we just show the id directly
   126  				if ak == "id" {
   127  					continue
   128  				}
   129  
   130  				attrKeys = append(attrKeys, ak)
   131  			}
   132  			sort.Strings(attrKeys)
   133  
   134  			// Output each attribute
   135  			for _, ak := range attrKeys {
   136  				av := is.Attributes[ak]
   137  				buf.WriteString(fmt.Sprintf("  %s = %s\n", ak, av))
   138  			}
   139  		}
   140  	}
   141  
   142  	buf.WriteString("[reset]\n")
   143  }
   144  
   145  func formatStateModuleSingle(
   146  	buf *bytes.Buffer, m *terraform.ModuleState, opts *FormatStateOpts) {
   147  	// Header with the module name
   148  	buf.WriteString(fmt.Sprintf("module.%s\n", strings.Join(m.Path[1:], ".")))
   149  
   150  	// Now just write how many resources are in here.
   151  	buf.WriteString(fmt.Sprintf("  %d resource(s)\n", len(m.Resources)))
   152  }