tofu: Context.Input now takes a context.Context

This continues our ongoing effort to get a coherent chain of
context.Context all the way from "package main" to all of our calls to
external components.

Context.Input now passes this through to the UI input implementation,
which was already written to handle cancellation. However, that
implementation currently handles interruption itself by directly watching
for the interrupt signal and so we remove the cancellation from the
context for now to avoid changing how interrupts are handled. Hopefully
in future we can remove the inline SIGINT handling from the UIInput
implementation and use its context-cancellation-handling instead.

All of the _test.go file updates here are purely mechanical additions of
the extra argument. No test is materially modified by this change, which
is intentional to get some assurance that isn't a breaking change.

Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This commit is contained in:
Martin Atkins 2024-11-12 16:10:41 -08:00
parent 9cadb097ba
commit a8b6342556
3 changed files with 22 additions and 14 deletions

View File

@ -125,7 +125,7 @@ func (b *Local) localRun(ctx context.Context, op *backend.Operation) (*backend.L
mode := tofu.InputModeProvider mode := tofu.InputModeProvider
log.Printf("[TRACE] backend/local: requesting interactive input, if necessary") log.Printf("[TRACE] backend/local: requesting interactive input, if necessary")
inputDiags := ret.Core.Input(ret.Config, mode) inputDiags := ret.Core.Input(ctx, ret.Config, mode)
diags = diags.Append(inputDiags) diags = diags.Append(inputDiags)
if inputDiags.HasErrors() { if inputDiags.HasErrors() {
return nil, nil, nil, diags return nil, nil, nil, diags

View File

@ -36,7 +36,9 @@ import (
// any other Context method with a different config, because the aforementioned // any other Context method with a different config, because the aforementioned
// modified internal state won't match. Again, this is an architectural wart // modified internal state won't match. Again, this is an architectural wart
// that we'll hopefully resolve in future. // that we'll hopefully resolve in future.
func (c *Context) Input(config *configs.Config, mode InputMode) tfdiags.Diagnostics { //
//nolint:cyclop,funlen,gocognit,nestif // Historical function predates our complexity rules
func (c *Context) Input(ctx context.Context, config *configs.Config, mode InputMode) tfdiags.Diagnostics {
// This function used to be responsible for more than it is now, so its // This function used to be responsible for more than it is now, so its
// interface is more general than its current functionality requires. // interface is more general than its current functionality requires.
// It now exists only to handle interactive prompts for provider // It now exists only to handle interactive prompts for provider
@ -61,8 +63,6 @@ func (c *Context) Input(config *configs.Config, mode InputMode) tfdiags.Diagnost
return diags return diags
} }
ctx := context.Background()
if mode&InputModeProvider != 0 { if mode&InputModeProvider != 0 {
log.Printf("[TRACE] Context.Input: Prompting for provider arguments") log.Printf("[TRACE] Context.Input: Prompting for provider arguments")
@ -165,7 +165,15 @@ func (c *Context) Input(config *configs.Config, mode InputMode) tfdiags.Diagnost
} }
log.Printf("[TRACE] Context.Input: Prompting for %s argument %s", pa, key) log.Printf("[TRACE] Context.Input: Prompting for %s argument %s", pa, key)
rawVal, err := input.Input(ctx, &InputOpts{ // NOTE: Historically we were just passing a context.Background into
// this, because we didn't have any other context.Context to use.
// We're now passing in our given context but intentionally ignoring
// its cancellation because the main UIInput implementation (in
// package command) already/ had direct SIGINT handling and we want to
// preserve that behavior.
// FIXME: Remove the UIInput's own SIGINT handling and rely on the
// cancellation of ctx instead.
rawVal, err := input.Input(context.WithoutCancel(ctx), &InputOpts{
Id: key, Id: key,
Query: key, Query: key,
Description: attrS.Description, Description: attrS.Description,

View File

@ -65,7 +65,7 @@ func TestContext2Input_provider(t *testing.T) {
return return
} }
if diags := ctx.Input(m, InputModeStd); diags.HasErrors() { if diags := ctx.Input(context.Background(), m, InputModeStd); diags.HasErrors() {
t.Fatalf("input errors: %s", diags.Err()) t.Fatalf("input errors: %s", diags.Err())
} }
@ -143,7 +143,7 @@ func TestContext2Input_providerMulti(t *testing.T) {
var actual []interface{} var actual []interface{}
var lock sync.Mutex var lock sync.Mutex
if diags := ctx.Input(m, InputModeStd); diags.HasErrors() { if diags := ctx.Input(context.Background(), m, InputModeStd); diags.HasErrors() {
t.Fatalf("input errors: %s", diags.Err()) t.Fatalf("input errors: %s", diags.Err())
} }
@ -181,7 +181,7 @@ func TestContext2Input_providerOnce(t *testing.T) {
}, },
}) })
if diags := ctx.Input(m, InputModeStd); diags.HasErrors() { if diags := ctx.Input(context.Background(), m, InputModeStd); diags.HasErrors() {
t.Fatalf("input errors: %s", diags.Err()) t.Fatalf("input errors: %s", diags.Err())
} }
} }
@ -231,7 +231,7 @@ func TestContext2Input_providerId(t *testing.T) {
"provider.aws.foo": "bar", "provider.aws.foo": "bar",
} }
if diags := ctx.Input(m, InputModeStd); diags.HasErrors() { if diags := ctx.Input(context.Background(), m, InputModeStd); diags.HasErrors() {
t.Fatalf("input errors: %s", diags.Err()) t.Fatalf("input errors: %s", diags.Err())
} }
@ -289,7 +289,7 @@ func TestContext2Input_providerOnly(t *testing.T) {
return return
} }
if err := ctx.Input(m, InputModeProvider); err != nil { if err := ctx.Input(context.Background(), m, InputModeProvider); err != nil {
t.Fatalf("err: %s", err) t.Fatalf("err: %s", err)
} }
@ -348,7 +348,7 @@ func TestContext2Input_providerVars(t *testing.T) {
actual = req.Config.GetAttr("foo").AsString() actual = req.Config.GetAttr("foo").AsString()
return return
} }
if diags := ctx.Input(m, InputModeStd); diags.HasErrors() { if diags := ctx.Input(context.Background(), m, InputModeStd); diags.HasErrors() {
t.Fatalf("input errors: %s", diags.Err()) t.Fatalf("input errors: %s", diags.Err())
} }
@ -383,7 +383,7 @@ func TestContext2Input_providerVarsModuleInherit(t *testing.T) {
UIInput: input, UIInput: input,
}) })
if diags := ctx.Input(m, InputModeStd); diags.HasErrors() { if diags := ctx.Input(context.Background(), m, InputModeStd); diags.HasErrors() {
t.Fatalf("input errors: %s", diags.Err()) t.Fatalf("input errors: %s", diags.Err())
} }
} }
@ -400,7 +400,7 @@ func TestContext2Input_submoduleTriggersInvalidCount(t *testing.T) {
UIInput: input, UIInput: input,
}) })
if diags := ctx.Input(m, InputModeStd); diags.HasErrors() { if diags := ctx.Input(context.Background(), m, InputModeStd); diags.HasErrors() {
t.Fatalf("input errors: %s", diags.Err()) t.Fatalf("input errors: %s", diags.Err())
} }
} }
@ -458,7 +458,7 @@ func TestContext2Input_dataSourceRequiresRefresh(t *testing.T) {
UIInput: input, UIInput: input,
}) })
if diags := ctx.Input(m, InputModeStd); diags.HasErrors() { if diags := ctx.Input(context.Background(), m, InputModeStd); diags.HasErrors() {
t.Fatalf("input errors: %s", diags.Err()) t.Fatalf("input errors: %s", diags.Err())
} }