mirror of
https://github.com/opentofu/opentofu.git
synced 2025-01-12 09:01:58 -06:00
Fix for no json output of state locking actions for --json flag (#32451)
* Add viewType to Meta object and use it at the call sites * Assign viewType passed from flags to state-locking cli commands * Remove temp files * Set correct mode for statelocker depending on json flag passed to commands * Add StateLocker interface conformation check for StateLockerJSON * Remove empty line at end of comment * Pass correct ViewType to StateLocker from Backend call chain * Pass viewType to backend migration and initialization functions * Remove json processing info in process comment * Restore documentation style of backendMigrateOpts
This commit is contained in:
parent
5264510c79
commit
c70244426a
@ -94,7 +94,7 @@ func (c *ApplyCommand) Run(rawArgs []string) int {
|
||||
|
||||
// Prepare the backend, passing the plan file if present, and the
|
||||
// backend-specific arguments
|
||||
be, beDiags := c.PrepareBackend(planFile, args.State)
|
||||
be, beDiags := c.PrepareBackend(planFile, args.State, args.ViewType)
|
||||
diags = diags.Append(beDiags)
|
||||
if diags.HasErrors() {
|
||||
view.Diagnostics(diags)
|
||||
@ -102,7 +102,7 @@ func (c *ApplyCommand) Run(rawArgs []string) int {
|
||||
}
|
||||
|
||||
// Build the operation request
|
||||
opReq, opDiags := c.OperationRequest(be, view, planFile, args.Operation, args.AutoApprove)
|
||||
opReq, opDiags := c.OperationRequest(be, view, args.ViewType, planFile, args.Operation, args.AutoApprove)
|
||||
diags = diags.Append(opDiags)
|
||||
|
||||
// Collect variable value and add them to the operation request
|
||||
@ -191,7 +191,7 @@ func (c *ApplyCommand) LoadPlanFile(path string) (*planfile.Reader, tfdiags.Diag
|
||||
return planFile, diags
|
||||
}
|
||||
|
||||
func (c *ApplyCommand) PrepareBackend(planFile *planfile.Reader, args *arguments.State) (backend.Enhanced, tfdiags.Diagnostics) {
|
||||
func (c *ApplyCommand) PrepareBackend(planFile *planfile.Reader, args *arguments.State, viewType arguments.ViewType) (backend.Enhanced, tfdiags.Diagnostics) {
|
||||
var diags tfdiags.Diagnostics
|
||||
|
||||
// FIXME: we need to apply the state arguments to the meta object here
|
||||
@ -211,7 +211,8 @@ func (c *ApplyCommand) PrepareBackend(planFile *planfile.Reader, args *arguments
|
||||
}
|
||||
|
||||
be, beDiags = c.Backend(&BackendOpts{
|
||||
Config: backendConfig,
|
||||
Config: backendConfig,
|
||||
ViewType: viewType,
|
||||
})
|
||||
} else {
|
||||
plan, err := planFile.ReadPlan()
|
||||
@ -245,6 +246,7 @@ func (c *ApplyCommand) PrepareBackend(planFile *planfile.Reader, args *arguments
|
||||
func (c *ApplyCommand) OperationRequest(
|
||||
be backend.Enhanced,
|
||||
view views.Apply,
|
||||
viewType arguments.ViewType,
|
||||
planFile *planfile.Reader,
|
||||
args *arguments.Operation,
|
||||
autoApprove bool,
|
||||
@ -257,7 +259,7 @@ func (c *ApplyCommand) OperationRequest(
|
||||
diags = diags.Append(c.providerDevOverrideRuntimeWarnings())
|
||||
|
||||
// Build the operation
|
||||
opReq := c.Operation(be)
|
||||
opReq := c.Operation(be, viewType)
|
||||
opReq.AutoApprove = autoApprove
|
||||
opReq.ConfigDir = "."
|
||||
opReq.PlanMode = args.PlanMode
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/hashicorp/terraform/internal/addrs"
|
||||
"github.com/hashicorp/terraform/internal/backend"
|
||||
"github.com/hashicorp/terraform/internal/command/arguments"
|
||||
"github.com/hashicorp/terraform/internal/repl"
|
||||
"github.com/hashicorp/terraform/internal/terraform"
|
||||
"github.com/hashicorp/terraform/internal/tfdiags"
|
||||
@ -75,7 +76,7 @@ func (c *ConsoleCommand) Run(args []string) int {
|
||||
c.ignoreRemoteVersionConflict(b)
|
||||
|
||||
// Build the operation
|
||||
opReq := c.Operation(b)
|
||||
opReq := c.Operation(b, arguments.ViewHuman)
|
||||
opReq.ConfigDir = configPath
|
||||
opReq.ConfigLoader, err = c.initConfigLoader()
|
||||
opReq.AllowUnsetVariables = true // we'll just evaluate them as unknown
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform/internal/backend"
|
||||
"github.com/hashicorp/terraform/internal/command/arguments"
|
||||
"github.com/hashicorp/terraform/internal/dag"
|
||||
"github.com/hashicorp/terraform/internal/plans"
|
||||
"github.com/hashicorp/terraform/internal/plans/planfile"
|
||||
@ -91,7 +92,7 @@ func (c *GraphCommand) Run(args []string) int {
|
||||
c.ignoreRemoteVersionConflict(b)
|
||||
|
||||
// Build the operation
|
||||
opReq := c.Operation(b)
|
||||
opReq := c.Operation(b, arguments.ViewHuman)
|
||||
opReq.ConfigDir = configPath
|
||||
opReq.ConfigLoader, err = c.initConfigLoader()
|
||||
opReq.PlanFile = planFile
|
||||
|
@ -182,7 +182,7 @@ func (c *ImportCommand) Run(args []string) int {
|
||||
}
|
||||
|
||||
// Build the operation
|
||||
opReq := c.Operation(b)
|
||||
opReq := c.Operation(b, arguments.ViewHuman)
|
||||
opReq.ConfigDir = configPath
|
||||
opReq.ConfigLoader, err = c.initConfigLoader()
|
||||
if err != nil {
|
||||
|
@ -53,6 +53,10 @@ type BackendOpts struct {
|
||||
// ForceLocal will force a purely local backend, including state.
|
||||
// You probably don't want to set this.
|
||||
ForceLocal bool
|
||||
|
||||
// ViewType will set console output format for the
|
||||
// initialization operation (JSON or human-readable).
|
||||
ViewType arguments.ViewType
|
||||
}
|
||||
|
||||
// BackendWithRemoteTerraformVersion is a shared interface between the 'remote' and 'cloud' backends
|
||||
@ -391,7 +395,7 @@ func (m *Meta) backendCLIOpts() (*backend.CLIOpts, error) {
|
||||
// This prepares the operation. After calling this, the caller is expected
|
||||
// to modify fields of the operation such as Sequence to specify what will
|
||||
// be called.
|
||||
func (m *Meta) Operation(b backend.Backend) *backend.Operation {
|
||||
func (m *Meta) Operation(b backend.Backend, vt arguments.ViewType) *backend.Operation {
|
||||
schema := b.ConfigSchema()
|
||||
workspace, err := m.Workspace()
|
||||
if err != nil {
|
||||
@ -411,7 +415,7 @@ func (m *Meta) Operation(b backend.Backend) *backend.Operation {
|
||||
|
||||
stateLocker := clistate.NewNoopLocker()
|
||||
if m.stateLock {
|
||||
view := views.NewStateLocker(arguments.ViewHuman, m.View)
|
||||
view := views.NewStateLocker(vt, m.View)
|
||||
stateLocker = clistate.NewLocker(m.stateLockTimeout, view)
|
||||
}
|
||||
|
||||
@ -611,7 +615,7 @@ func (m *Meta) backendFromConfig(opts *BackendOpts) (backend.Backend, tfdiags.Di
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
return m.backend_c_r_S(c, cHash, sMgr, true)
|
||||
return m.backend_c_r_S(c, cHash, sMgr, true, opts)
|
||||
|
||||
// Configuring a backend for the first time or -reconfigure flag was used
|
||||
case c != nil && s.Backend.Empty():
|
||||
@ -845,9 +849,18 @@ func (m *Meta) backendFromState() (backend.Backend, tfdiags.Diagnostics) {
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
// Unconfiguring a backend (moving from backend => local).
|
||||
func (m *Meta) backend_c_r_S(c *configs.Backend, cHash int, sMgr *clistate.LocalState, output bool) (backend.Backend, tfdiags.Diagnostics) {
|
||||
func (m *Meta) backend_c_r_S(
|
||||
c *configs.Backend, cHash int, sMgr *clistate.LocalState, output bool, opts *BackendOpts) (backend.Backend, tfdiags.Diagnostics) {
|
||||
|
||||
var diags tfdiags.Diagnostics
|
||||
|
||||
vt := arguments.ViewJSON
|
||||
// Set default viewtype if none was set as the StateLocker needs to know exactly
|
||||
// what viewType we want to have.
|
||||
if opts == nil || opts.ViewType != vt {
|
||||
vt = arguments.ViewHuman
|
||||
}
|
||||
|
||||
s := sMgr.State()
|
||||
|
||||
cloudMode := cloud.DetectConfigChangeType(s.Backend, c, false)
|
||||
@ -885,6 +898,7 @@ func (m *Meta) backend_c_r_S(c *configs.Backend, cHash int, sMgr *clistate.Local
|
||||
DestinationType: "local",
|
||||
Source: b,
|
||||
Destination: localB,
|
||||
ViewType: vt,
|
||||
})
|
||||
if err != nil {
|
||||
diags = diags.Append(err)
|
||||
@ -916,6 +930,13 @@ func (m *Meta) backend_c_r_S(c *configs.Backend, cHash int, sMgr *clistate.Local
|
||||
func (m *Meta) backend_C_r_s(c *configs.Backend, cHash int, sMgr *clistate.LocalState, opts *BackendOpts) (backend.Backend, tfdiags.Diagnostics) {
|
||||
var diags tfdiags.Diagnostics
|
||||
|
||||
vt := arguments.ViewJSON
|
||||
// Set default viewtype if none was set as the StateLocker needs to know exactly
|
||||
// what viewType we want to have.
|
||||
if opts == nil || opts.ViewType != vt {
|
||||
vt = arguments.ViewHuman
|
||||
}
|
||||
|
||||
// Grab a purely local backend to get the local state if it exists
|
||||
localB, localBDiags := m.Backend(&BackendOpts{ForceLocal: true, Init: true})
|
||||
if localBDiags.HasErrors() {
|
||||
@ -970,6 +991,7 @@ func (m *Meta) backend_C_r_s(c *configs.Backend, cHash int, sMgr *clistate.Local
|
||||
DestinationType: c.Type,
|
||||
Source: localB,
|
||||
Destination: b,
|
||||
ViewType: vt,
|
||||
})
|
||||
if err != nil {
|
||||
diags = diags.Append(err)
|
||||
@ -1007,7 +1029,7 @@ func (m *Meta) backend_C_r_s(c *configs.Backend, cHash int, sMgr *clistate.Local
|
||||
}
|
||||
|
||||
if m.stateLock {
|
||||
view := views.NewStateLocker(arguments.ViewHuman, m.View)
|
||||
view := views.NewStateLocker(vt, m.View)
|
||||
stateLocker := clistate.NewLocker(m.stateLockTimeout, view)
|
||||
if err := stateLocker.Lock(sMgr, "backend from plan"); err != nil {
|
||||
diags = diags.Append(fmt.Errorf("Error locking state: %s", err))
|
||||
@ -1077,6 +1099,13 @@ func (m *Meta) backend_C_r_s(c *configs.Backend, cHash int, sMgr *clistate.Local
|
||||
func (m *Meta) backend_C_r_S_changed(c *configs.Backend, cHash int, sMgr *clistate.LocalState, output bool, opts *BackendOpts) (backend.Backend, tfdiags.Diagnostics) {
|
||||
var diags tfdiags.Diagnostics
|
||||
|
||||
vt := arguments.ViewJSON
|
||||
// Set default viewtype if none was set as the StateLocker needs to know exactly
|
||||
// what viewType we want to have.
|
||||
if opts == nil || opts.ViewType != vt {
|
||||
vt = arguments.ViewHuman
|
||||
}
|
||||
|
||||
// Get the old state
|
||||
s := sMgr.State()
|
||||
|
||||
@ -1136,6 +1165,7 @@ func (m *Meta) backend_C_r_S_changed(c *configs.Backend, cHash int, sMgr *clista
|
||||
DestinationType: c.Type,
|
||||
Source: oldB,
|
||||
Destination: b,
|
||||
ViewType: vt,
|
||||
})
|
||||
if err != nil {
|
||||
diags = diags.Append(err)
|
||||
@ -1143,7 +1173,7 @@ func (m *Meta) backend_C_r_S_changed(c *configs.Backend, cHash int, sMgr *clista
|
||||
}
|
||||
|
||||
if m.stateLock {
|
||||
view := views.NewStateLocker(arguments.ViewHuman, m.View)
|
||||
view := views.NewStateLocker(vt, m.View)
|
||||
stateLocker := clistate.NewLocker(m.stateLockTimeout, view)
|
||||
if err := stateLocker.Lock(sMgr, "backend from plan"); err != nil {
|
||||
diags = diags.Append(fmt.Errorf("Error locking state: %s", err))
|
||||
|
@ -26,6 +26,7 @@ import (
|
||||
type backendMigrateOpts struct {
|
||||
SourceType, DestinationType string
|
||||
Source, Destination backend.Backend
|
||||
ViewType arguments.ViewType
|
||||
|
||||
// Fields below are set internally when migrate is called
|
||||
|
||||
@ -339,8 +340,13 @@ func (m *Meta) backendMigrateState_s_s(opts *backendMigrateOpts) error {
|
||||
|
||||
if m.stateLock {
|
||||
lockCtx := context.Background()
|
||||
|
||||
view := views.NewStateLocker(arguments.ViewHuman, m.View)
|
||||
vt := arguments.ViewJSON
|
||||
// Set default viewtype if none was set as the StateLocker needs to know exactly
|
||||
// what viewType we want to have.
|
||||
if opts == nil || opts.ViewType != vt {
|
||||
vt = arguments.ViewHuman
|
||||
}
|
||||
view := views.NewStateLocker(vt, m.View)
|
||||
locker := clistate.NewLocker(m.stateLockTimeout, view)
|
||||
|
||||
lockerSource := locker.WithContext(lockCtx)
|
||||
|
@ -64,7 +64,7 @@ func (c *PlanCommand) Run(rawArgs []string) int {
|
||||
diags = diags.Append(c.providerDevOverrideRuntimeWarnings())
|
||||
|
||||
// Prepare the backend with the backend-specific arguments
|
||||
be, beDiags := c.PrepareBackend(args.State)
|
||||
be, beDiags := c.PrepareBackend(args.State, args.ViewType)
|
||||
diags = diags.Append(beDiags)
|
||||
if diags.HasErrors() {
|
||||
view.Diagnostics(diags)
|
||||
@ -72,7 +72,7 @@ func (c *PlanCommand) Run(rawArgs []string) int {
|
||||
}
|
||||
|
||||
// Build the operation request
|
||||
opReq, opDiags := c.OperationRequest(be, view, args.Operation, args.OutPath)
|
||||
opReq, opDiags := c.OperationRequest(be, view, args.ViewType, args.Operation, args.OutPath)
|
||||
diags = diags.Append(opDiags)
|
||||
if diags.HasErrors() {
|
||||
view.Diagnostics(diags)
|
||||
@ -110,7 +110,7 @@ func (c *PlanCommand) Run(rawArgs []string) int {
|
||||
return op.Result.ExitStatus()
|
||||
}
|
||||
|
||||
func (c *PlanCommand) PrepareBackend(args *arguments.State) (backend.Enhanced, tfdiags.Diagnostics) {
|
||||
func (c *PlanCommand) PrepareBackend(args *arguments.State, viewType arguments.ViewType) (backend.Enhanced, tfdiags.Diagnostics) {
|
||||
// FIXME: we need to apply the state arguments to the meta object here
|
||||
// because they are later used when initializing the backend. Carving a
|
||||
// path to pass these arguments to the functions that need them is
|
||||
@ -124,7 +124,8 @@ func (c *PlanCommand) PrepareBackend(args *arguments.State) (backend.Enhanced, t
|
||||
|
||||
// Load the backend
|
||||
be, beDiags := c.Backend(&BackendOpts{
|
||||
Config: backendConfig,
|
||||
Config: backendConfig,
|
||||
ViewType: viewType,
|
||||
})
|
||||
diags = diags.Append(beDiags)
|
||||
if beDiags.HasErrors() {
|
||||
@ -137,13 +138,14 @@ func (c *PlanCommand) PrepareBackend(args *arguments.State) (backend.Enhanced, t
|
||||
func (c *PlanCommand) OperationRequest(
|
||||
be backend.Enhanced,
|
||||
view views.Plan,
|
||||
viewType arguments.ViewType,
|
||||
args *arguments.Operation,
|
||||
planOutPath string,
|
||||
) (*backend.Operation, tfdiags.Diagnostics) {
|
||||
var diags tfdiags.Diagnostics
|
||||
|
||||
// Build the operation
|
||||
opReq := c.Operation(be)
|
||||
opReq := c.Operation(be, viewType)
|
||||
opReq.ConfigDir = "."
|
||||
opReq.PlanMode = args.PlanMode
|
||||
opReq.Hooks = view.Hooks()
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/hashicorp/terraform/internal/backend"
|
||||
"github.com/hashicorp/terraform/internal/command/arguments"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonprovider"
|
||||
"github.com/hashicorp/terraform/internal/tfdiags"
|
||||
)
|
||||
@ -78,7 +79,7 @@ func (c *ProvidersSchemaCommand) Run(args []string) int {
|
||||
}
|
||||
|
||||
// Build the operation
|
||||
opReq := c.Operation(b)
|
||||
opReq := c.Operation(b, arguments.ViewJSON)
|
||||
opReq.ConfigDir = cwd
|
||||
opReq.ConfigLoader, err = c.initConfigLoader()
|
||||
opReq.AllowUnsetVariables = true
|
||||
|
@ -64,7 +64,7 @@ func (c *RefreshCommand) Run(rawArgs []string) int {
|
||||
c.Meta.parallelism = args.Operation.Parallelism
|
||||
|
||||
// Prepare the backend with the backend-specific arguments
|
||||
be, beDiags := c.PrepareBackend(args.State)
|
||||
be, beDiags := c.PrepareBackend(args.State, args.ViewType)
|
||||
diags = diags.Append(beDiags)
|
||||
if diags.HasErrors() {
|
||||
view.Diagnostics(diags)
|
||||
@ -72,7 +72,7 @@ func (c *RefreshCommand) Run(rawArgs []string) int {
|
||||
}
|
||||
|
||||
// Build the operation request
|
||||
opReq, opDiags := c.OperationRequest(be, view, args.Operation)
|
||||
opReq, opDiags := c.OperationRequest(be, view, args.ViewType, args.Operation)
|
||||
diags = diags.Append(opDiags)
|
||||
if diags.HasErrors() {
|
||||
view.Diagnostics(diags)
|
||||
@ -107,7 +107,7 @@ func (c *RefreshCommand) Run(rawArgs []string) int {
|
||||
return op.Result.ExitStatus()
|
||||
}
|
||||
|
||||
func (c *RefreshCommand) PrepareBackend(args *arguments.State) (backend.Enhanced, tfdiags.Diagnostics) {
|
||||
func (c *RefreshCommand) PrepareBackend(args *arguments.State, viewType arguments.ViewType) (backend.Enhanced, tfdiags.Diagnostics) {
|
||||
// FIXME: we need to apply the state arguments to the meta object here
|
||||
// because they are later used when initializing the backend. Carving a
|
||||
// path to pass these arguments to the functions that need them is
|
||||
@ -121,7 +121,8 @@ func (c *RefreshCommand) PrepareBackend(args *arguments.State) (backend.Enhanced
|
||||
|
||||
// Load the backend
|
||||
be, beDiags := c.Backend(&BackendOpts{
|
||||
Config: backendConfig,
|
||||
Config: backendConfig,
|
||||
ViewType: viewType,
|
||||
})
|
||||
diags = diags.Append(beDiags)
|
||||
if beDiags.HasErrors() {
|
||||
@ -131,12 +132,12 @@ func (c *RefreshCommand) PrepareBackend(args *arguments.State) (backend.Enhanced
|
||||
return be, diags
|
||||
}
|
||||
|
||||
func (c *RefreshCommand) OperationRequest(be backend.Enhanced, view views.Refresh, args *arguments.Operation,
|
||||
func (c *RefreshCommand) OperationRequest(be backend.Enhanced, view views.Refresh, viewType arguments.ViewType, args *arguments.Operation,
|
||||
) (*backend.Operation, tfdiags.Diagnostics) {
|
||||
var diags tfdiags.Diagnostics
|
||||
|
||||
// Build the operation
|
||||
opReq := c.Operation(be)
|
||||
opReq := c.Operation(be, viewType)
|
||||
opReq.ConfigDir = "."
|
||||
opReq.Hooks = view.Hooks()
|
||||
opReq.Targets = args.Targets
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/hashicorp/terraform/internal/addrs"
|
||||
"github.com/hashicorp/terraform/internal/backend"
|
||||
"github.com/hashicorp/terraform/internal/command/arguments"
|
||||
"github.com/hashicorp/terraform/internal/command/format"
|
||||
"github.com/hashicorp/terraform/internal/states"
|
||||
"github.com/mitchellh/cli"
|
||||
@ -71,7 +72,7 @@ func (c *StateShowCommand) Run(args []string) int {
|
||||
}
|
||||
|
||||
// Build the operation (required to get the schemas)
|
||||
opReq := c.Operation(b)
|
||||
opReq := c.Operation(b, arguments.ViewHuman)
|
||||
opReq.AllowUnsetVariables = true
|
||||
opReq.ConfigDir = cwd
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
package views
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/terraform/internal/command/arguments"
|
||||
)
|
||||
@ -18,6 +20,8 @@ func NewStateLocker(vt arguments.ViewType, view *View) StateLocker {
|
||||
switch vt {
|
||||
case arguments.ViewHuman:
|
||||
return &StateLockerHuman{view: view}
|
||||
case arguments.ViewJSON:
|
||||
return &StateLockerJSON{view: view}
|
||||
default:
|
||||
panic(fmt.Sprintf("unknown view type %v", vt))
|
||||
}
|
||||
@ -30,6 +34,7 @@ type StateLockerHuman struct {
|
||||
}
|
||||
|
||||
var _ StateLocker = (*StateLockerHuman)(nil)
|
||||
var _ StateLocker = (*StateLockerJSON)(nil)
|
||||
|
||||
func (v *StateLockerHuman) Locking() {
|
||||
v.view.streams.Println("Acquiring state lock. This may take a few moments...")
|
||||
@ -38,3 +43,37 @@ func (v *StateLockerHuman) Locking() {
|
||||
func (v *StateLockerHuman) Unlocking() {
|
||||
v.view.streams.Println("Releasing state lock. This may take a few moments...")
|
||||
}
|
||||
|
||||
// StateLockerJSON is an implementation of StateLocker which prints the state lock status
|
||||
// to a terminal in machine-readable JSON form.
|
||||
type StateLockerJSON struct {
|
||||
view *View
|
||||
}
|
||||
|
||||
func (v *StateLockerJSON) Locking() {
|
||||
current_timestamp := time.Now().Format(time.RFC3339)
|
||||
|
||||
json_data := map[string]string{
|
||||
"@level": "info",
|
||||
"@message": "Acquiring state lock. This may take a few moments...",
|
||||
"@module": "terraform.ui",
|
||||
"@timestamp": current_timestamp,
|
||||
"type": "state_lock_acquire"}
|
||||
|
||||
lock_info_message, _ := json.Marshal(json_data)
|
||||
v.view.streams.Println(string(lock_info_message))
|
||||
}
|
||||
|
||||
func (v *StateLockerJSON) Unlocking() {
|
||||
current_timestamp := time.Now().Format(time.RFC3339)
|
||||
|
||||
json_data := map[string]string{
|
||||
"@level": "info",
|
||||
"@message": "Releasing state lock. This may take a few moments...",
|
||||
"@module": "terraform.ui",
|
||||
"@timestamp": current_timestamp,
|
||||
"type": "state_lock_release"}
|
||||
|
||||
lock_info_message, _ := json.Marshal(json_data)
|
||||
v.view.streams.Println(string(lock_info_message))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user