Skip to content
This repository has been archived by the owner on Jan 8, 2024. It is now read-only.

Inspecting boolean env var values. #1699

Merged
merged 14 commits into from
Jun 30, 2021
4 changes: 4 additions & 0 deletions .changelog/1699.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
```release-note:improvement
core: Correct parsing of boolean environment variables
```

27 changes: 23 additions & 4 deletions internal/ceb/ceb.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"

"github.com/hashicorp/waypoint/internal/env"
"github.com/hashicorp/waypoint/internal/pkg/gatedwriter"
"github.com/hashicorp/waypoint/internal/plugin"
"github.com/hashicorp/waypoint/internal/server"
Expand Down Expand Up @@ -299,11 +300,29 @@ func WithEnvDefaults() Option {

cfg.URLServicePort = port
cfg.ServerAddr = os.Getenv(envServerAddr)
cfg.ServerRequired = os.Getenv(envCEBServerRequired) != ""
cfg.ServerTls = os.Getenv(envServerTls) != ""
cfg.ServerTlsSkipVerify = os.Getenv(envServerTlsSkipVerify) != ""

var err error
cfg.ServerRequired, err = env.GetBool(envCEBServerRequired, false)
if err != nil {
return err
}

cfg.ServerTls, err = env.GetBool(envServerTls, false)
if err != nil {
return err
}

cfg.ServerTlsSkipVerify, err = env.GetBool(envServerTlsSkipVerify, false)
if err != nil {
return err
}

cfg.InviteToken = os.Getenv(envCEBToken)
cfg.disable = os.Getenv(envCEBDisable) != ""

cfg.disable, err = env.GetBool(envCEBDisable, false)
if err != nil {
return err
}

ceb.deploymentId = os.Getenv(envDeploymentId)

Expand Down
7 changes: 6 additions & 1 deletion internal/cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/mitchellh/go-glint"

"github.com/hashicorp/waypoint-plugin-sdk/terminal"
"github.com/hashicorp/waypoint/internal/env"
"github.com/hashicorp/waypoint/internal/pkg/signalcontext"
"github.com/hashicorp/waypoint/internal/version"
)
Expand Down Expand Up @@ -139,7 +140,11 @@ func Commands(
}

// Set plain mode if set
if os.Getenv(EnvPlain) != "" {
outputModeBool, err := env.GetBool(EnvPlain, false)
if err != nil {
log.Warn(err.Error())
}
if outputModeBool {
baseCommand.globalOptions = append(baseCommand.globalOptions,
WithUI(terminal.NonInteractiveUI(ctx)))
}
Expand Down
22 changes: 22 additions & 0 deletions internal/env/env.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package env

import (
"fmt"
"os"
"strconv"
"strings"
)

// GetBool Extracts a boolean from an env var. Falls back to the default
// if the key is unset or not a valid boolean.
func GetBool(key string, defaultValue bool) (bool, error) {
envVal := os.Getenv(key)
if envVal == "" {
return defaultValue, nil
}
value, err := strconv.ParseBool(strings.ToLower(envVal))
if err != nil {
return defaultValue, fmt.Errorf("failed to parse a boolean from environment variable %s=%s", key, envVal)
}
return value, nil
}
88 changes: 88 additions & 0 deletions internal/env/env_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package env

import (
"os"
"testing"
)

func TestGetBool(t *testing.T) {
envVarTestKey := "WAYPOINT_GET_ENV_BOOL_TEST"

tests := []struct {
name string
defaultVal bool
envVal string
want bool
wantErr bool
}{
{
name: "Empty env var returns default 1",
defaultVal: true,
envVal: "",
want: true,
wantErr: false,
},
{
name: "Empty env var returns default 2",
defaultVal: false,
envVal: "",
want: false,
wantErr: false,
},
{
name: "Non-truthy env var returns err",
defaultVal: false,
envVal: "unparseable",
want: false,
wantErr: true,
},
{
name: "'true' is true",
defaultVal: false,
envVal: "true",
want: true,
wantErr: false,
},
{
name: "'false' is true",
defaultVal: true,
envVal: "false",
want: false,
wantErr: false,
},
{
name: "1 is true",
defaultVal: false,
envVal: "1",
want: true,
wantErr: false,
},
{
name: "0 is false",
defaultVal: true,
envVal: "0",
want: false,
wantErr: false,
},
{
name: "Boolean parsing ignores capitalization",
defaultVal: false,
envVal: "tRuE",
want: true,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
os.Setenv(envVarTestKey, tt.envVal)
got, err := GetBool(envVarTestKey, tt.defaultVal)
if (err != nil) != tt.wantErr {
t.Errorf("GetBool() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("GetBool() got = %v, want %v", got, tt.want)
}
})
}
}
15 changes: 13 additions & 2 deletions internal/serverclient/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"google.golang.org/grpc/credentials"

"github.com/hashicorp/waypoint/internal/clicontext"
"github.com/hashicorp/waypoint/internal/env"
"github.com/hashicorp/waypoint/internal/protocolversion"
"github.com/hashicorp/waypoint/internal/serverconfig"
)
Expand Down Expand Up @@ -126,8 +127,18 @@ func FromEnv() ConnectOption {
return func(c *connectConfig) error {
if v := os.Getenv(EnvServerAddr); v != "" {
c.Addr = v
c.Tls = os.Getenv(EnvServerTls) != ""
c.TlsSkipVerify = os.Getenv(EnvServerTlsSkipVerify) != ""

var err error
c.Tls, err = env.GetBool(EnvServerTls, false)
if err != nil {
return err
}

c.TlsSkipVerify, err = env.GetBool(EnvServerTlsSkipVerify, false)
if err != nil {
return err
}

c.Auth = os.Getenv(EnvServerToken) != ""
}

Expand Down
6 changes: 3 additions & 3 deletions website/content/docs/automating-execution/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ configure the Waypoint CLI for communication with the Waypoint server.
- `WAYPOINT_SERVER_TOKEN`. Must be set to a Waypoint token, created with [`waypoint token new`](/commands/token-new)
- `WAYPOINT_SERVER_ADDR`. The address to the Waypoint server gRPC address. This must
be accessible from the network that the client is running on.
- `WAYPOINT_SERVER_TLS`. Should be set to `1` to configure the client to use TLS when
- `WAYPOINT_SERVER_TLS`. Should be set to a truthy value (e.g. "1") to configure the client to use TLS when
connecting to the server.
- `WAYPOINT_SERVER_TLS_SKIP_VERIFY`. Current must be set to `1` to disable TLS verification
- `WAYPOINT_SERVER_TLS_SKIP_VERIFY`. Current must be set to a truthy value (e.g. "1") to disable TLS verification
when communicating with the server.

~> The Waypoint server token is sensitive and should be
Expand All @@ -71,7 +71,7 @@ If Waypoint detects that the terminal does not support interactivity it will out
simpler "non-interactive" output mode. This output is easier to consume in
a CI/CD systems logging views, or through log archiving systems. This is automatic
and does not need to be explicitly configured, but can be forced by setting
the environment variable `WAYPOINT_PLAIN` to `1`.
the environment variable `WAYPOINT_PLAIN` to a truthy value (e.g. "1").

## Workspaces

Expand Down
4 changes: 2 additions & 2 deletions website/content/docs/entrypoint/disable.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ deployments and apps.
## Disable at Runtime

You can disable the entrypoint at runtime by setting the `WAYPOINT_CEB_DISABLE`
environment variable to any non-empty value.
environment variable to a truthy value (e.g. "1").

This environment variable is checked immediately on entrypoint startup. If
it is present and non-empty then the entrypoint will immediately execute the
the value is true, then the entrypoint will immediately execute the
child process. The entrypoint **will not** attempt to even connect to the
server and will not use any network or disk resources.

Expand Down
8 changes: 5 additions & 3 deletions website/content/docs/runner/run-manual.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,11 @@ The environment variables specify how to connect to the server:
that the runner can reach. The port should be for the gRPC API, and
is typically 9701.

- `WAYPOINT_SERVER_TLS` should be set to "true" if the server is listening
on TLS. You may additionally set `WAYPOINT_SERVER_TLS_SKIP_VERIFY` to
a non-empty value if the TLS cert is invalid and can be safely ignored
- `WAYPOINT_SERVER_TLS` should be set to a truthy value (e.g. "1") if
the server is listening on TLS.

- `WAYPOINT_SERVER_TLS_SKIP_VERIFY` should be set to a truthy value
(e.g. "1") if the TLS cert is invalid and can be safely ignored,
such as in a development environment.

- `WAYPOINT_SERVER_TOKEN` should be an [auth token](/docs/server/auth)
Expand Down