2023-05-02 11:33:06 -04:00
|
|
|
// Copyright IBM Corp. 2014, 2026
|
2023-08-10 18:43:27 -04:00
|
|
|
// SPDX-License-Identifier: BUSL-1.1
|
2023-05-02 11:33:06 -04:00
|
|
|
|
Upgrade to Go 1.17
This includes the addition of the new "//go:build" comment form in addition
to the legacy "// +build" notation, as produced by gofmt to ensure
consistent behavior between Go versions. The new directives are all
equivalent to what was present before, so there's no change in behavior.
Go 1.17 continues to use the Unicode 13 tables as in Go 1.16, so this
upgrade does not require also upgrading our Unicode-related dependencies.
This upgrade includes the following breaking changes which will also
appear as breaking changes for Terraform users, but that are consistent
with the Terraform v1.0 compatibility promises.
- On MacOS, Terraform now requires macOS 10.13 High Sierra or later.
This upgrade also includes the following breaking changes which will
appear as breaking changes for Terraform users that are inconsistent with
our compatibility promises, but have justified exceptions as follows:
- cidrsubnet, cidrhost, and cidrnetmask will now reject IPv4 CIDR
addresses whose decimal components have leading zeros, where previously
they would just silently ignore those leading zeros.
This is a security-motivated exception to our compatibility promises,
because some external systems interpret zero-prefixed octets as octal
numbers rather than decimal, and thus the previous lenient parsing could
lead to a different interpretation of the address between systems, and
thus potentially allow bypassing policy when configuring firewall rules
etc.
This upgrade also includes the following breaking changes which could
_potentially_ appear as breaking changes for Terraform users, but that do
not in practice for the reasons given:
- The Go net/url package no longer allows query strings with pairs
separated by semicolons instead of ampersands. This primarily affects
HTTP servers written in Go, and Terraform includes a special temporary
HTTP server as part of its implementation of OAuth for "terraform login",
but that server only needs to accept URLs created by Terraform itself
and Terraform does not generate any URLs that would be rejected.
2021-08-16 20:19:17 -04:00
|
|
|
//go:build !solaris
|
2016-11-14 03:32:01 -05:00
|
|
|
// +build !solaris
|
|
|
|
|
|
|
|
|
|
// The readline library we use doesn't currently support solaris so
|
|
|
|
|
// we just build tag it off.
|
|
|
|
|
|
|
|
|
|
package command
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
|
|
|
|
"io"
|
2021-10-27 10:28:19 -04:00
|
|
|
"os"
|
terraform console: Multi-line entry support
The console command, when running in interactive mode, will now detect if
the input seems to be an incomplete (but valid enough so far) expression,
and if so will produce another prompt to accept another line of expression
input.
This is primarily to make it easier to paste in multi-line expressions
taken from elsewhere, but it could also be used for manual input.
The support for multi-line _editing_ is limited by the fact that the
readline dependency we use doesn't support multiline input and so we're
currently doing this in spite of that library. Hopefully we'll be able to
improve on that in future either by contributing multi-line editing support
upstream or by switching to a different readline dependency.
The delimiter-counting heuristic employed here is similar to the one used
by HCL itself to decide whether a newline should end the definition of an
attribute, but this implementation is simpler because it doesn't need to
produce error messages or perform any recovery. Instead, it just bails out
if it encounters something strange so that the console session can return
a parse error.
Because some invalid input may cause a user to become "stuck" in a multi-
line sequence, we consider a blank line as intent to immediately try to
evaluate what was entered, and also interpret SIGINT (e.g. Ctrl+C) as
cancellation of multi-line input, assuming that at least one line was
already entered, extending the previous precedent that SIGINT cancels
when at least one character was already entered at the prompt.
2024-03-12 20:05:05 -04:00
|
|
|
"strings"
|
2016-11-14 03:32:01 -05:00
|
|
|
|
|
|
|
|
"github.com/chzyer/readline"
|
2023-12-20 06:04:10 -05:00
|
|
|
"github.com/hashicorp/cli"
|
terraform console: Multi-line entry support
The console command, when running in interactive mode, will now detect if
the input seems to be an incomplete (but valid enough so far) expression,
and if so will produce another prompt to accept another line of expression
input.
This is primarily to make it easier to paste in multi-line expressions
taken from elsewhere, but it could also be used for manual input.
The support for multi-line _editing_ is limited by the fact that the
readline dependency we use doesn't support multiline input and so we're
currently doing this in spite of that library. Hopefully we'll be able to
improve on that in future either by contributing multi-line editing support
upstream or by switching to a different readline dependency.
The delimiter-counting heuristic employed here is similar to the one used
by HCL itself to decide whether a newline should end the definition of an
attribute, but this implementation is simpler because it doesn't need to
produce error messages or perform any recovery. Instead, it just bails out
if it encounters something strange so that the console session can return
a parse error.
Because some invalid input may cause a user to become "stuck" in a multi-
line sequence, we consider a blank line as intent to immediately try to
evaluate what was entered, and also interpret SIGINT (e.g. Ctrl+C) as
cancellation of multi-line input, assuming that at least one line was
already entered, extending the previous precedent that SIGINT cancels
when at least one character was already entered at the prompt.
2024-03-12 20:05:05 -04:00
|
|
|
|
|
|
|
|
"github.com/hashicorp/terraform/internal/repl"
|
2016-11-14 03:32:01 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func (c *ConsoleCommand) modeInteractive(session *repl.Session, ui cli.Ui) int {
|
|
|
|
|
// Configure input
|
2021-10-26 15:54:09 -04:00
|
|
|
l, err := readline.NewEx(&readline.Config{
|
2016-11-14 03:32:01 -05:00
|
|
|
Prompt: "> ",
|
|
|
|
|
InterruptPrompt: "^C",
|
|
|
|
|
EOFPrompt: "exit",
|
|
|
|
|
HistorySearchFold: true,
|
2021-10-27 10:28:19 -04:00
|
|
|
Stdin: os.Stdin,
|
|
|
|
|
Stdout: os.Stdout,
|
|
|
|
|
Stderr: os.Stderr,
|
2021-10-26 15:54:09 -04:00
|
|
|
})
|
2016-11-14 03:32:01 -05:00
|
|
|
if err != nil {
|
|
|
|
|
c.Ui.Error(fmt.Sprintf(
|
|
|
|
|
"Error initializing console: %s",
|
|
|
|
|
err))
|
|
|
|
|
return 1
|
|
|
|
|
}
|
|
|
|
|
defer l.Close()
|
|
|
|
|
|
terraform console: Multi-line entry support
The console command, when running in interactive mode, will now detect if
the input seems to be an incomplete (but valid enough so far) expression,
and if so will produce another prompt to accept another line of expression
input.
This is primarily to make it easier to paste in multi-line expressions
taken from elsewhere, but it could also be used for manual input.
The support for multi-line _editing_ is limited by the fact that the
readline dependency we use doesn't support multiline input and so we're
currently doing this in spite of that library. Hopefully we'll be able to
improve on that in future either by contributing multi-line editing support
upstream or by switching to a different readline dependency.
The delimiter-counting heuristic employed here is similar to the one used
by HCL itself to decide whether a newline should end the definition of an
attribute, but this implementation is simpler because it doesn't need to
produce error messages or perform any recovery. Instead, it just bails out
if it encounters something strange so that the console session can return
a parse error.
Because some invalid input may cause a user to become "stuck" in a multi-
line sequence, we consider a blank line as intent to immediately try to
evaluate what was entered, and also interpret SIGINT (e.g. Ctrl+C) as
cancellation of multi-line input, assuming that at least one line was
already entered, extending the previous precedent that SIGINT cancels
when at least one character was already entered at the prompt.
2024-03-12 20:05:05 -04:00
|
|
|
// TODO: Currently we're handling multi-line input largely _in spite of_
|
|
|
|
|
// the readline library, because it doesn't support that. This means that
|
|
|
|
|
// in particular the history treats each line as a separate history entry,
|
|
|
|
|
// and doesn't allow editing of previous lines after the user's already
|
|
|
|
|
// pressed enter.
|
|
|
|
|
//
|
|
|
|
|
// Hopefully we can do better than this one day, but having some basic
|
|
|
|
|
// support for multi-line input is at least better than none at all:
|
|
|
|
|
// this is mainly helpful when pasting in expressions from elsewhere that
|
|
|
|
|
// already have newline characters in them, to avoid pre-editing it.
|
|
|
|
|
|
|
|
|
|
lines := make([]string, 0, 4)
|
2016-11-14 03:32:01 -05:00
|
|
|
for {
|
|
|
|
|
// Read a line
|
terraform console: Multi-line entry support
The console command, when running in interactive mode, will now detect if
the input seems to be an incomplete (but valid enough so far) expression,
and if so will produce another prompt to accept another line of expression
input.
This is primarily to make it easier to paste in multi-line expressions
taken from elsewhere, but it could also be used for manual input.
The support for multi-line _editing_ is limited by the fact that the
readline dependency we use doesn't support multiline input and so we're
currently doing this in spite of that library. Hopefully we'll be able to
improve on that in future either by contributing multi-line editing support
upstream or by switching to a different readline dependency.
The delimiter-counting heuristic employed here is similar to the one used
by HCL itself to decide whether a newline should end the definition of an
attribute, but this implementation is simpler because it doesn't need to
produce error messages or perform any recovery. Instead, it just bails out
if it encounters something strange so that the console session can return
a parse error.
Because some invalid input may cause a user to become "stuck" in a multi-
line sequence, we consider a blank line as intent to immediately try to
evaluate what was entered, and also interpret SIGINT (e.g. Ctrl+C) as
cancellation of multi-line input, assuming that at least one line was
already entered, extending the previous precedent that SIGINT cancels
when at least one character was already entered at the prompt.
2024-03-12 20:05:05 -04:00
|
|
|
if len(lines) == 0 {
|
|
|
|
|
l.SetPrompt("> ")
|
|
|
|
|
} else {
|
|
|
|
|
l.SetPrompt(": ")
|
|
|
|
|
}
|
2016-11-14 03:32:01 -05:00
|
|
|
line, err := l.Readline()
|
|
|
|
|
if err == readline.ErrInterrupt {
|
terraform console: Multi-line entry support
The console command, when running in interactive mode, will now detect if
the input seems to be an incomplete (but valid enough so far) expression,
and if so will produce another prompt to accept another line of expression
input.
This is primarily to make it easier to paste in multi-line expressions
taken from elsewhere, but it could also be used for manual input.
The support for multi-line _editing_ is limited by the fact that the
readline dependency we use doesn't support multiline input and so we're
currently doing this in spite of that library. Hopefully we'll be able to
improve on that in future either by contributing multi-line editing support
upstream or by switching to a different readline dependency.
The delimiter-counting heuristic employed here is similar to the one used
by HCL itself to decide whether a newline should end the definition of an
attribute, but this implementation is simpler because it doesn't need to
produce error messages or perform any recovery. Instead, it just bails out
if it encounters something strange so that the console session can return
a parse error.
Because some invalid input may cause a user to become "stuck" in a multi-
line sequence, we consider a blank line as intent to immediately try to
evaluate what was entered, and also interpret SIGINT (e.g. Ctrl+C) as
cancellation of multi-line input, assuming that at least one line was
already entered, extending the previous precedent that SIGINT cancels
when at least one character was already entered at the prompt.
2024-03-12 20:05:05 -04:00
|
|
|
if len(lines) == 0 && line == "" {
|
2016-11-14 03:32:01 -05:00
|
|
|
break
|
terraform console: Multi-line entry support
The console command, when running in interactive mode, will now detect if
the input seems to be an incomplete (but valid enough so far) expression,
and if so will produce another prompt to accept another line of expression
input.
This is primarily to make it easier to paste in multi-line expressions
taken from elsewhere, but it could also be used for manual input.
The support for multi-line _editing_ is limited by the fact that the
readline dependency we use doesn't support multiline input and so we're
currently doing this in spite of that library. Hopefully we'll be able to
improve on that in future either by contributing multi-line editing support
upstream or by switching to a different readline dependency.
The delimiter-counting heuristic employed here is similar to the one used
by HCL itself to decide whether a newline should end the definition of an
attribute, but this implementation is simpler because it doesn't need to
produce error messages or perform any recovery. Instead, it just bails out
if it encounters something strange so that the console session can return
a parse error.
Because some invalid input may cause a user to become "stuck" in a multi-
line sequence, we consider a blank line as intent to immediately try to
evaluate what was entered, and also interpret SIGINT (e.g. Ctrl+C) as
cancellation of multi-line input, assuming that at least one line was
already entered, extending the previous precedent that SIGINT cancels
when at least one character was already entered at the prompt.
2024-03-12 20:05:05 -04:00
|
|
|
} else if line != "" {
|
|
|
|
|
continue
|
2016-11-14 03:32:01 -05:00
|
|
|
} else {
|
terraform console: Multi-line entry support
The console command, when running in interactive mode, will now detect if
the input seems to be an incomplete (but valid enough so far) expression,
and if so will produce another prompt to accept another line of expression
input.
This is primarily to make it easier to paste in multi-line expressions
taken from elsewhere, but it could also be used for manual input.
The support for multi-line _editing_ is limited by the fact that the
readline dependency we use doesn't support multiline input and so we're
currently doing this in spite of that library. Hopefully we'll be able to
improve on that in future either by contributing multi-line editing support
upstream or by switching to a different readline dependency.
The delimiter-counting heuristic employed here is similar to the one used
by HCL itself to decide whether a newline should end the definition of an
attribute, but this implementation is simpler because it doesn't need to
produce error messages or perform any recovery. Instead, it just bails out
if it encounters something strange so that the console session can return
a parse error.
Because some invalid input may cause a user to become "stuck" in a multi-
line sequence, we consider a blank line as intent to immediately try to
evaluate what was entered, and also interpret SIGINT (e.g. Ctrl+C) as
cancellation of multi-line input, assuming that at least one line was
already entered, extending the previous precedent that SIGINT cancels
when at least one character was already entered at the prompt.
2024-03-12 20:05:05 -04:00
|
|
|
// Reset the entry buffer to start a new expression
|
|
|
|
|
lines = lines[:0]
|
|
|
|
|
ui.Output("(multi-line entry canceled)")
|
2016-11-14 03:32:01 -05:00
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
} else if err == io.EOF {
|
|
|
|
|
break
|
|
|
|
|
}
|
terraform console: Multi-line entry support
The console command, when running in interactive mode, will now detect if
the input seems to be an incomplete (but valid enough so far) expression,
and if so will produce another prompt to accept another line of expression
input.
This is primarily to make it easier to paste in multi-line expressions
taken from elsewhere, but it could also be used for manual input.
The support for multi-line _editing_ is limited by the fact that the
readline dependency we use doesn't support multiline input and so we're
currently doing this in spite of that library. Hopefully we'll be able to
improve on that in future either by contributing multi-line editing support
upstream or by switching to a different readline dependency.
The delimiter-counting heuristic employed here is similar to the one used
by HCL itself to decide whether a newline should end the definition of an
attribute, but this implementation is simpler because it doesn't need to
produce error messages or perform any recovery. Instead, it just bails out
if it encounters something strange so that the console session can return
a parse error.
Because some invalid input may cause a user to become "stuck" in a multi-
line sequence, we consider a blank line as intent to immediately try to
evaluate what was entered, and also interpret SIGINT (e.g. Ctrl+C) as
cancellation of multi-line input, assuming that at least one line was
already entered, extending the previous precedent that SIGINT cancels
when at least one character was already entered at the prompt.
2024-03-12 20:05:05 -04:00
|
|
|
lines = append(lines, line)
|
|
|
|
|
// The following implements a heuristic for deciding if it seems likely
|
|
|
|
|
// that the user was intending to continue entering more expression
|
|
|
|
|
// characters on a subsequent line. This should get the right answer
|
|
|
|
|
// for any valid expression, but might get confused by invalid input.
|
|
|
|
|
// The user can always hit enter one more time (entering a blank line)
|
|
|
|
|
// to break out of a multi-line sequence and force interpretation of
|
|
|
|
|
// what was already entered.
|
|
|
|
|
if repl.ExpressionEntryCouldContinue(lines) {
|
|
|
|
|
continue
|
|
|
|
|
}
|
2016-11-14 03:32:01 -05:00
|
|
|
|
terraform console: Multi-line entry support
The console command, when running in interactive mode, will now detect if
the input seems to be an incomplete (but valid enough so far) expression,
and if so will produce another prompt to accept another line of expression
input.
This is primarily to make it easier to paste in multi-line expressions
taken from elsewhere, but it could also be used for manual input.
The support for multi-line _editing_ is limited by the fact that the
readline dependency we use doesn't support multiline input and so we're
currently doing this in spite of that library. Hopefully we'll be able to
improve on that in future either by contributing multi-line editing support
upstream or by switching to a different readline dependency.
The delimiter-counting heuristic employed here is similar to the one used
by HCL itself to decide whether a newline should end the definition of an
attribute, but this implementation is simpler because it doesn't need to
produce error messages or perform any recovery. Instead, it just bails out
if it encounters something strange so that the console session can return
a parse error.
Because some invalid input may cause a user to become "stuck" in a multi-
line sequence, we consider a blank line as intent to immediately try to
evaluate what was entered, and also interpret SIGINT (e.g. Ctrl+C) as
cancellation of multi-line input, assuming that at least one line was
already entered, extending the previous precedent that SIGINT cancels
when at least one character was already entered at the prompt.
2024-03-12 20:05:05 -04:00
|
|
|
input := strings.Join(lines, "\n") + "\n"
|
|
|
|
|
lines = lines[:0] // reset for next iteration
|
|
|
|
|
out, exit, diags := session.Handle(input)
|
2018-05-03 23:44:55 -04:00
|
|
|
if diags.HasErrors() {
|
|
|
|
|
c.showDiagnostics(diags)
|
2016-11-14 03:32:01 -05:00
|
|
|
}
|
2018-05-03 23:44:55 -04:00
|
|
|
if exit {
|
|
|
|
|
break
|
2016-11-14 03:32:01 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ui.Output(out)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0
|
|
|
|
|
}
|