Commit Graph

23 Commits

Author SHA1 Message Date
James Bardin ef8ed1e275 coalesce the backened interrupt code
Moves the nested select statements for backend operations into a single
function. The only difference in this part was that apply called
PersistState, which should be harmless regardless of the type of
operation being run.
2018-02-12 11:56:54 -05:00
James Bardin 7cba68326a always wait for a RunningOperation to return
If the user wishes to interrupt the running operation, only the first
interrupt was communicated to the operation by canceling the provided
context. A second interrupt would start the shutdown process, but not
communicate this to the running operation. This order of event could
cause partial writes of state.

What would happen is that once the command returns, the plugin system
would stop the provider processes. Once the provider processes dies, all
pending Eval operations would return return with an error, and quickly
cause the operation to complete. Since the backend code didn't know that
the process was shutting down imminently, it would continue by
attempting to write out the last known state. Under the right
conditions, the process would exit part way through the writing of the
state file.

Add Stop and Cancel CancelFuncs to the RunningOperation, to allow it to
easily differentiate between the two signals. The backend will then be
able to detect a shutdown and abort more gracefully.

In order to ensure that the backend is not in the process of writing the
state out, the command will always attempt to wait for the process to
complete after cancellation.
2018-02-12 11:56:03 -05:00
James Bardin 85295e5c23 watch for cancellation in plan and refresh
Cancellation in the local backend was only implemented for apply.
2017-12-05 10:17:20 -05:00
Martin Atkins 83414beb8f command: various adjustments to the diff presentation
The previous diff presentation was rather "wordy", and not very friendly
to those who can't see color either because they have color-blindness or
because they don't have a color-supporting terminal.

This new presentation uses the actual symbols used in the plan output
and tries to be more concise. It also uses some framing characters to
try to separate the different stages of "terraform plan" to make it
easier to visually navigate.

The apply command also adopts this new plan presentation, in preparation
for "terraform apply" (with interactive plan confirmation) becoming the
primary, safe workflow in the next major release.

Finally, we standardize on the terminology "perform" and "actions" rather
than "execute" and "changes" to reflect the fact that reading is now an
action and that isn't actually a _change_.
2017-09-01 17:55:05 -07:00
Martin Atkins 3ea159297c command/format: improve consistency of plan results
Previously the rendered plan output was constructed directly from the
core plan and then annotated with counts derived from the count hook.
At various places we applied little adjustments to deal with the fact that
the user-facing diff model is not identical to the internal diff model,
including the special handling of data source reads and destroys. Since
this logic was just muddled into the rendering code, it behaved
inconsistently with the tally of adds, updates and deletes.

This change reworks the plan formatter so that it happens in two stages:
- First, we produce a specialized Plan object that is tailored for use
  in the UI. This applies all the relevant logic to transform the
  physical model into the user model.
- Second, we do a straightforward visual rendering of the display-oriented
  plan object.

For the moment this is slightly overkill since there's only one rendering
path, but it does give us the benefit of letting the counts be derived
from the same data as the full detailed diff, ensuring that they'll stay
consistent.

Later we may choose to have other UIs for plans, such as a
machine-readable output intended to drive a web UI. In that case, we'd
want the web UI to consume a serialization of the _display-oriented_ plan
so that it doesn't need to re-implement all of these UI special cases.

This introduces to core a new diff action type for "refresh". Currently
this is used _only_ in the UI layer, to represent data source reads.
Later it would be good to use this type for the core diff as well, to
improve consistency, but that is left for another day to keep this change
focused on the UI.
2017-09-01 17:55:05 -07:00
James Bardin 3fb76f3ebb only show state path help if state is local 2017-06-29 15:30:44 -04:00
Martin Atkins 6afa72f6ca command: minor adjustments to the -auto-approve=false UX
Some tweaks to the messaging and presentation.
2017-06-27 11:22:35 -07:00
David Glasser 14af879fe0 command: also print plan for destroy 2017-06-27 11:22:31 -07:00
David Glasser 039d36bf91 command: add "apply -auto-approve=false" flag
A common reason to want to use `terraform plan` is to have a chance to
review and confirm a plan before running it.  If in fact that is the
only reason you are running plan, this new `terraform apply -auto-approve=false`
flag provides an easier alternative to

    P=$(mktemp -t plan)
    terraform refresh
    terraform plan -refresh=false -out=$P
    terraform apply $P
    rm $P

The flag defaults to true for now, but in a future version of Terraform it will
default to false.
2017-06-27 11:22:26 -07:00
James Bardin 9e4c0ff2ad call PersistState immediately when cancelling
When the backend operation is cancelled, immediately call PersistState.
The is a high likelihood that the user is going to terminate the process
early if the provider doesn't return in a timely manner, so persist as
much state as possible.
2017-05-25 11:20:51 -04:00
Martin Atkins 9cda37205d backend/local: create local state file if backend write fails
In the old remote state system we had the idea of a local backup, which
is actually still present for the legacy backends but no longer applies
for the new-style backends like the s3 backend.

It's problematic when an apply runs for long enough that someone's
time-limited AWS STS credentials expire and then Terraform fails and can't
persist state to S3.

To reduce the risk of lost state, here we add some extra fallback code
for the local apply operation in particular. If either state writing
or state persisting fail then we attempt to write the state to a special
backup file errored.tfstate, and produce an error message that guides the
user on how to retry uploading this state.

In the unlikely event that we can't write to local disk either (e.g.
permissions problems) we take a last-ditch attempt to dump the JSON onto
stdout and advise the user to manually copy it into a file for import.
If even that doesn't work for some reason, we assume a critical Terraform
bug (JSON-serialization problem with states?) and bail out with an
apologetic error message.

This is implemented for the apply command in particular because this is
the one command where new objects are created in real APIs that we don't
want to lose track of. For other operations it's less bad to just generate
a simple error message and have the user retry.

This fixes #14298.
2017-05-23 11:18:01 -07:00
James Bardin 7dad3f4d48 remove redundant output when interrupting apply
The backend apply operation doesn't need to output the same text as the
cli itself. Instead notify the user that we are in the process of
stopping the operation.
2017-04-25 11:44:51 -04:00
James Bardin 928e60672f context Refresh and Apply sometimes return nil
The documentation for Refresh indicates that it will always return a
valid state, but that wasn't true in the case of a graph builder error.
While this same concept wasn't documented for Apply, it was still
assumed in the terraform apply code.

Since the helper testing framework relies on the absence of a state to
determine if it can call Destroy, the Context can't can't start
returning a state in all cases. Document this, and use the State method
to fetch the correct state value after Apply.

Add a nil check to the WriteState function, so that writing a nil state
is a noop.

Make sure to init before sorting the state, to make sure we're not
attempting to sort nil values. This isn't technically needed with the
current code, but it's just safer in general.
2017-04-14 14:56:10 -04:00
James Bardin 305ef43aa6 provide contexts to clistate.Lock calls
Add fields required to create an appropriate context for all calls to
clistate.Lock.

Add missing checks for Meta.stateLock, where we would attempt to lock,
even if locking should be skipped.
2017-04-01 17:09:20 -04:00
James Bardin 3f0dcd1308 Have the clistate Lock use LockWithContext
- Have the ui Lock helper use state.LockWithContext.
- Rename the message package to clistate, since that's how it's imported
  everywhere.
- Use a more idiomatic placement of the Context in the LockWithContext
  args.
2017-04-01 17:09:20 -04:00
Mitchell Hashimoto d443bf1b56
backend/local: allow nil modules (no config) if executing a plan 2017-02-16 10:56:39 -08:00
Mitchell Hashimoto 1480d0c5b8
backend/local: check for empty config on apply
This prevents Terraform from crashing on apply/destroy with a directory
with no Terraform configuration files. We allow a destroy with no files
but not an apply.
2017-02-15 16:00:59 -08:00
James Bardin f2e496a14c Have backend operations properly unlock state
Make sure unlock is called with the correct LockID during operations
2017-02-15 14:41:55 -05:00
James Bardin 67dc16c9ca Make backend/local test pass 2017-02-15 14:41:55 -05:00
Mitchell Hashimoto 65982bd412
backend/local: use new command/state package for better UX 2017-02-14 11:17:28 -08:00
James Bardin 0d7752b0f5 Update runningOp.Err with State.Unlock error
Have the defer'ed State.Unlock call append any error to the
RunningOperation.Err field. Local error would be rare and
self-correcting, but when the backend.Local is using a remote state the
error may require user intervention.
2017-02-06 09:54:15 -05:00
James Bardin 9cdba1f199 enable local state locking for apply
Have the LocalBackend lock the state during operations, and enble this
for the apply comand.
2017-02-02 18:08:28 -05:00
Mitchell Hashimoto 397e1b3132
backend/local
The local backend implementation is an implementation of
backend.Enhanced that recreates all the behavior of the CLI but through
the backend interface.
2017-01-26 14:33:49 -08:00