github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/command/views/json/hook.go (about) 1 package json 2 3 import ( 4 "fmt" 5 "time" 6 7 "github.com/hashicorp/terraform/internal/addrs" 8 "github.com/hashicorp/terraform/internal/plans" 9 ) 10 11 type Hook interface { 12 HookType() MessageType 13 String() string 14 } 15 16 // ApplyStart: triggered by PreApply hook 17 type applyStart struct { 18 Resource ResourceAddr `json:"resource"` 19 Action ChangeAction `json:"action"` 20 IDKey string `json:"id_key,omitempty"` 21 IDValue string `json:"id_value,omitempty"` 22 actionVerb string 23 } 24 25 var _ Hook = (*applyStart)(nil) 26 27 func (h *applyStart) HookType() MessageType { 28 return MessageApplyStart 29 } 30 31 func (h *applyStart) String() string { 32 var id string 33 if h.IDKey != "" && h.IDValue != "" { 34 id = fmt.Sprintf(" [%s=%s]", h.IDKey, h.IDValue) 35 } 36 return fmt.Sprintf("%s: %s...%s", h.Resource.Addr, h.actionVerb, id) 37 } 38 39 func NewApplyStart(addr addrs.AbsResourceInstance, action plans.Action, idKey string, idValue string) Hook { 40 hook := &applyStart{ 41 Resource: newResourceAddr(addr), 42 Action: changeAction(action), 43 IDKey: idKey, 44 IDValue: idValue, 45 actionVerb: startActionVerb(action), 46 } 47 48 return hook 49 } 50 51 // ApplyProgress: currently triggered by a timer started on PreApply. In 52 // future, this might also be triggered by provider progress reporting. 53 type applyProgress struct { 54 Resource ResourceAddr `json:"resource"` 55 Action ChangeAction `json:"action"` 56 Elapsed float64 `json:"elapsed_seconds"` 57 actionVerb string 58 elapsed time.Duration 59 } 60 61 var _ Hook = (*applyProgress)(nil) 62 63 func (h *applyProgress) HookType() MessageType { 64 return MessageApplyProgress 65 } 66 67 func (h *applyProgress) String() string { 68 return fmt.Sprintf("%s: Still %s... [%s elapsed]", h.Resource.Addr, h.actionVerb, h.elapsed) 69 } 70 71 func NewApplyProgress(addr addrs.AbsResourceInstance, action plans.Action, elapsed time.Duration) Hook { 72 return &applyProgress{ 73 Resource: newResourceAddr(addr), 74 Action: changeAction(action), 75 Elapsed: elapsed.Seconds(), 76 actionVerb: progressActionVerb(action), 77 elapsed: elapsed, 78 } 79 } 80 81 // ApplyComplete: triggered by PostApply hook 82 type applyComplete struct { 83 Resource ResourceAddr `json:"resource"` 84 Action ChangeAction `json:"action"` 85 IDKey string `json:"id_key,omitempty"` 86 IDValue string `json:"id_value,omitempty"` 87 Elapsed float64 `json:"elapsed_seconds"` 88 actionNoun string 89 elapsed time.Duration 90 } 91 92 var _ Hook = (*applyComplete)(nil) 93 94 func (h *applyComplete) HookType() MessageType { 95 return MessageApplyComplete 96 } 97 98 func (h *applyComplete) String() string { 99 var id string 100 if h.IDKey != "" && h.IDValue != "" { 101 id = fmt.Sprintf(" [%s=%s]", h.IDKey, h.IDValue) 102 } 103 return fmt.Sprintf("%s: %s complete after %s%s", h.Resource.Addr, h.actionNoun, h.elapsed, id) 104 } 105 106 func NewApplyComplete(addr addrs.AbsResourceInstance, action plans.Action, idKey, idValue string, elapsed time.Duration) Hook { 107 return &applyComplete{ 108 Resource: newResourceAddr(addr), 109 Action: changeAction(action), 110 IDKey: idKey, 111 IDValue: idValue, 112 Elapsed: elapsed.Seconds(), 113 actionNoun: actionNoun(action), 114 elapsed: elapsed, 115 } 116 } 117 118 // ApplyErrored: triggered by PostApply hook on failure. This will be followed 119 // by diagnostics when the apply finishes. 120 type applyErrored struct { 121 Resource ResourceAddr `json:"resource"` 122 Action ChangeAction `json:"action"` 123 Elapsed float64 `json:"elapsed_seconds"` 124 actionNoun string 125 elapsed time.Duration 126 } 127 128 var _ Hook = (*applyErrored)(nil) 129 130 func (h *applyErrored) HookType() MessageType { 131 return MessageApplyErrored 132 } 133 134 func (h *applyErrored) String() string { 135 return fmt.Sprintf("%s: %s errored after %s", h.Resource.Addr, h.actionNoun, h.elapsed) 136 } 137 138 func NewApplyErrored(addr addrs.AbsResourceInstance, action plans.Action, elapsed time.Duration) Hook { 139 return &applyErrored{ 140 Resource: newResourceAddr(addr), 141 Action: changeAction(action), 142 Elapsed: elapsed.Seconds(), 143 actionNoun: actionNoun(action), 144 elapsed: elapsed, 145 } 146 } 147 148 // ProvisionStart: triggered by PreProvisionInstanceStep hook 149 type provisionStart struct { 150 Resource ResourceAddr `json:"resource"` 151 Provisioner string `json:"provisioner"` 152 } 153 154 var _ Hook = (*provisionStart)(nil) 155 156 func (h *provisionStart) HookType() MessageType { 157 return MessageProvisionStart 158 } 159 160 func (h *provisionStart) String() string { 161 return fmt.Sprintf("%s: Provisioning with '%s'...", h.Resource.Addr, h.Provisioner) 162 } 163 164 func NewProvisionStart(addr addrs.AbsResourceInstance, provisioner string) Hook { 165 return &provisionStart{ 166 Resource: newResourceAddr(addr), 167 Provisioner: provisioner, 168 } 169 } 170 171 // ProvisionProgress: triggered by ProvisionOutput hook 172 type provisionProgress struct { 173 Resource ResourceAddr `json:"resource"` 174 Provisioner string `json:"provisioner"` 175 Output string `json:"output"` 176 } 177 178 var _ Hook = (*provisionProgress)(nil) 179 180 func (h *provisionProgress) HookType() MessageType { 181 return MessageProvisionProgress 182 } 183 184 func (h *provisionProgress) String() string { 185 return fmt.Sprintf("%s: (%s): %s", h.Resource.Addr, h.Provisioner, h.Output) 186 } 187 188 func NewProvisionProgress(addr addrs.AbsResourceInstance, provisioner string, output string) Hook { 189 return &provisionProgress{ 190 Resource: newResourceAddr(addr), 191 Provisioner: provisioner, 192 Output: output, 193 } 194 } 195 196 // ProvisionComplete: triggered by PostProvisionInstanceStep hook 197 type provisionComplete struct { 198 Resource ResourceAddr `json:"resource"` 199 Provisioner string `json:"provisioner"` 200 } 201 202 var _ Hook = (*provisionComplete)(nil) 203 204 func (h *provisionComplete) HookType() MessageType { 205 return MessageProvisionComplete 206 } 207 208 func (h *provisionComplete) String() string { 209 return fmt.Sprintf("%s: (%s) Provisioning complete", h.Resource.Addr, h.Provisioner) 210 } 211 212 func NewProvisionComplete(addr addrs.AbsResourceInstance, provisioner string) Hook { 213 return &provisionComplete{ 214 Resource: newResourceAddr(addr), 215 Provisioner: provisioner, 216 } 217 } 218 219 // ProvisionErrored: triggered by PostProvisionInstanceStep hook on failure. 220 // This will be followed by diagnostics when the apply finishes. 221 type provisionErrored struct { 222 Resource ResourceAddr `json:"resource"` 223 Provisioner string `json:"provisioner"` 224 } 225 226 var _ Hook = (*provisionErrored)(nil) 227 228 func (h *provisionErrored) HookType() MessageType { 229 return MessageProvisionErrored 230 } 231 232 func (h *provisionErrored) String() string { 233 return fmt.Sprintf("%s: (%s) Provisioning errored", h.Resource.Addr, h.Provisioner) 234 } 235 236 func NewProvisionErrored(addr addrs.AbsResourceInstance, provisioner string) Hook { 237 return &provisionErrored{ 238 Resource: newResourceAddr(addr), 239 Provisioner: provisioner, 240 } 241 } 242 243 // RefreshStart: triggered by PreRefresh hook 244 type refreshStart struct { 245 Resource ResourceAddr `json:"resource"` 246 IDKey string `json:"id_key,omitempty"` 247 IDValue string `json:"id_value,omitempty"` 248 } 249 250 var _ Hook = (*refreshStart)(nil) 251 252 func (h *refreshStart) HookType() MessageType { 253 return MessageRefreshStart 254 } 255 256 func (h *refreshStart) String() string { 257 var id string 258 if h.IDKey != "" && h.IDValue != "" { 259 id = fmt.Sprintf(" [%s=%s]", h.IDKey, h.IDValue) 260 } 261 return fmt.Sprintf("%s: Refreshing state...%s", h.Resource.Addr, id) 262 } 263 264 func NewRefreshStart(addr addrs.AbsResourceInstance, idKey, idValue string) Hook { 265 return &refreshStart{ 266 Resource: newResourceAddr(addr), 267 IDKey: idKey, 268 IDValue: idValue, 269 } 270 } 271 272 // RefreshComplete: triggered by PostRefresh hook 273 type refreshComplete struct { 274 Resource ResourceAddr `json:"resource"` 275 IDKey string `json:"id_key,omitempty"` 276 IDValue string `json:"id_value,omitempty"` 277 } 278 279 var _ Hook = (*refreshComplete)(nil) 280 281 func (h *refreshComplete) HookType() MessageType { 282 return MessageRefreshComplete 283 } 284 285 func (h *refreshComplete) String() string { 286 var id string 287 if h.IDKey != "" && h.IDValue != "" { 288 id = fmt.Sprintf(" [%s=%s]", h.IDKey, h.IDValue) 289 } 290 return fmt.Sprintf("%s: Refresh complete%s", h.Resource.Addr, id) 291 } 292 293 func NewRefreshComplete(addr addrs.AbsResourceInstance, idKey, idValue string) Hook { 294 return &refreshComplete{ 295 Resource: newResourceAddr(addr), 296 IDKey: idKey, 297 IDValue: idValue, 298 } 299 } 300 301 // Convert the subset of plans.Action values we expect to receive into a 302 // present-tense verb for the applyStart hook message. 303 func startActionVerb(action plans.Action) string { 304 switch action { 305 case plans.Create: 306 return "Creating" 307 case plans.Update: 308 return "Modifying" 309 case plans.Delete: 310 return "Destroying" 311 case plans.Read: 312 return "Refreshing" 313 case plans.CreateThenDelete, plans.DeleteThenCreate: 314 // This is not currently possible to reach, as we receive separate 315 // passes for create and delete 316 return "Replacing" 317 case plans.NoOp: 318 // This should never be possible: a no-op planned change should not 319 // be applied. We'll fall back to "Applying". 320 fallthrough 321 default: 322 return "Applying" 323 } 324 } 325 326 // Convert the subset of plans.Action values we expect to receive into a 327 // present-tense verb for the applyProgress hook message. This will be 328 // prefixed with "Still ", so it is lower-case. 329 func progressActionVerb(action plans.Action) string { 330 switch action { 331 case plans.Create: 332 return "creating" 333 case plans.Update: 334 return "modifying" 335 case plans.Delete: 336 return "destroying" 337 case plans.Read: 338 return "refreshing" 339 case plans.CreateThenDelete, plans.DeleteThenCreate: 340 // This is not currently possible to reach, as we receive separate 341 // passes for create and delete 342 return "replacing" 343 case plans.NoOp: 344 // This should never be possible: a no-op planned change should not 345 // be applied. We'll fall back to "applying". 346 fallthrough 347 default: 348 return "applying" 349 } 350 } 351 352 // Convert the subset of plans.Action values we expect to receive into a 353 // noun for the applyComplete and applyErrored hook messages. This will be 354 // combined into a phrase like "Creation complete after 1m4s". 355 func actionNoun(action plans.Action) string { 356 switch action { 357 case plans.Create: 358 return "Creation" 359 case plans.Update: 360 return "Modifications" 361 case plans.Delete: 362 return "Destruction" 363 case plans.Read: 364 return "Refresh" 365 case plans.CreateThenDelete, plans.DeleteThenCreate: 366 // This is not currently possible to reach, as we receive separate 367 // passes for create and delete 368 return "Replacement" 369 case plans.NoOp: 370 // This should never be possible: a no-op planned change should not 371 // be applied. We'll fall back to "Apply". 372 fallthrough 373 default: 374 return "Apply" 375 } 376 }