github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/command/jsonformat/renderer.go (about) 1 package jsonformat 2 3 import ( 4 "fmt" 5 6 "github.com/mitchellh/colorstring" 7 8 "github.com/hashicorp/terraform/internal/command/format" 9 "github.com/hashicorp/terraform/internal/command/jsonformat/computed" 10 "github.com/hashicorp/terraform/internal/command/jsonformat/differ" 11 "github.com/hashicorp/terraform/internal/command/jsonplan" 12 "github.com/hashicorp/terraform/internal/command/jsonprovider" 13 "github.com/hashicorp/terraform/internal/command/jsonstate" 14 viewsjson "github.com/hashicorp/terraform/internal/command/views/json" 15 "github.com/hashicorp/terraform/internal/plans" 16 "github.com/hashicorp/terraform/internal/terminal" 17 ctyjson "github.com/zclconf/go-cty/cty/json" 18 ) 19 20 type JSONLogType string 21 22 type JSONLog struct { 23 Message string `json:"@message"` 24 Type JSONLogType `json:"type"` 25 Diagnostic *viewsjson.Diagnostic `json:"diagnostic"` 26 Outputs viewsjson.Outputs `json:"outputs"` 27 Hook map[string]interface{} `json:"hook"` 28 } 29 30 const ( 31 LogVersion JSONLogType = "version" 32 LogDiagnostic JSONLogType = "diagnostic" 33 LogPlannedChange JSONLogType = "planned_change" 34 LogRefreshStart JSONLogType = "refresh_start" 35 LogRefreshComplete JSONLogType = "refresh_complete" 36 LogApplyStart JSONLogType = "apply_start" 37 LogApplyErrored JSONLogType = "apply_errored" 38 LogApplyComplete JSONLogType = "apply_complete" 39 LogChangeSummary JSONLogType = "change_summary" 40 LogProvisionStart JSONLogType = "provision_start" 41 LogProvisionProgress JSONLogType = "provision_progress" 42 LogProvisionComplete JSONLogType = "provision_complete" 43 LogProvisionErrored JSONLogType = "provision_errored" 44 LogOutputs JSONLogType = "outputs" 45 ) 46 47 type Renderer struct { 48 Streams *terminal.Streams 49 Colorize *colorstring.Colorize 50 51 RunningInAutomation bool 52 } 53 54 func (renderer Renderer) RenderHumanPlan(plan Plan, mode plans.Mode, opts ...PlanRendererOpt) { 55 // TODO(liamcervante): Tidy up this detection of version differences, we 56 // should only report warnings when the plan is generated using a newer 57 // version then we are executing. We could also look into major vs minor 58 // version differences. This should work for alpha testing in the meantime. 59 if plan.PlanFormatVersion != jsonplan.FormatVersion || plan.ProviderFormatVersion != jsonprovider.FormatVersion { 60 renderer.Streams.Println(format.WordWrap( 61 renderer.Colorize.Color("\n[bold][red]Warning:[reset][bold] This plan was generated using a different version of Terraform, the diff presented here maybe missing representations of recent features."), 62 renderer.Streams.Stdout.Columns())) 63 } 64 65 plan.renderHuman(renderer, mode, opts...) 66 } 67 68 func (renderer Renderer) RenderHumanState(state State) { 69 // TODO(liamcervante): Tidy up this detection of version differences, we 70 // should only report warnings when the plan is generated using a newer 71 // version then we are executing. We could also look into major vs minor 72 // version differences. This should work for alpha testing in the meantime. 73 if state.StateFormatVersion != jsonstate.FormatVersion || state.ProviderFormatVersion != jsonprovider.FormatVersion { 74 renderer.Streams.Println(format.WordWrap( 75 renderer.Colorize.Color("\n[bold][red]Warning:[reset][bold] This state was retrieved using a different version of Terraform, the state presented here maybe missing representations of recent features."), 76 renderer.Streams.Stdout.Columns())) 77 } 78 79 if state.Empty() { 80 renderer.Streams.Println("The state file is empty. No resources are represented.") 81 return 82 } 83 84 opts := computed.NewRenderHumanOpts(renderer.Colorize) 85 opts.ShowUnchangedChildren = true 86 opts.HideDiffActionSymbols = true 87 88 state.renderHumanStateModule(renderer, state.RootModule, opts, true) 89 state.renderHumanStateOutputs(renderer, opts) 90 } 91 92 func (r Renderer) RenderLog(log *JSONLog) error { 93 switch log.Type { 94 case LogRefreshComplete, 95 LogVersion, 96 LogPlannedChange, 97 LogProvisionComplete, 98 LogProvisionErrored, 99 LogApplyErrored: 100 // We won't display these types of logs 101 return nil 102 103 case LogApplyStart, LogApplyComplete, LogRefreshStart, LogProvisionStart: 104 msg := fmt.Sprintf(r.Colorize.Color("[bold]%s[reset]"), log.Message) 105 r.Streams.Println(msg) 106 107 case LogDiagnostic: 108 diag := format.DiagnosticFromJSON(log.Diagnostic, r.Colorize, 78) 109 r.Streams.Print(diag) 110 111 case LogOutputs: 112 if len(log.Outputs) > 0 { 113 r.Streams.Println(r.Colorize.Color("[bold][green]Outputs:[reset]")) 114 for name, output := range log.Outputs { 115 change := differ.FromJsonViewsOutput(output) 116 ctype, err := ctyjson.UnmarshalType(output.Type) 117 if err != nil { 118 return err 119 } 120 121 opts := computed.NewRenderHumanOpts(r.Colorize) 122 opts.ShowUnchangedChildren = true 123 124 outputDiff := change.ComputeDiffForType(ctype) 125 outputStr := outputDiff.RenderHuman(0, opts) 126 127 msg := fmt.Sprintf("%s = %s", name, outputStr) 128 r.Streams.Println(msg) 129 } 130 } 131 132 case LogProvisionProgress: 133 provisioner := log.Hook["provisioner"].(string) 134 output := log.Hook["output"].(string) 135 resource := log.Hook["resource"].(map[string]interface{}) 136 resourceAddr := resource["addr"].(string) 137 138 msg := fmt.Sprintf(r.Colorize.Color("[bold]%s: (%s):[reset] %s"), 139 resourceAddr, provisioner, output) 140 r.Streams.Println(msg) 141 142 case LogChangeSummary: 143 // Normally, we will only render the apply change summary since the renderer 144 // generates a plan change summary for us 145 msg := fmt.Sprintf(r.Colorize.Color("[bold][green]%s[reset]"), log.Message) 146 r.Streams.Println("\n" + msg + "\n") 147 148 default: 149 // If the log type is not a known log type, we will just print the log message 150 r.Streams.Println(log.Message) 151 } 152 153 return nil 154 }