Skip to content

Commit

Permalink
fix: don't assume bash when displaying interactive CLI prompts
Browse files Browse the repository at this point in the history
  • Loading branch information
danxmoran committed Jul 14, 2021
1 parent ba8f91f commit 1a982a9
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 325 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ This release adds an embedded SQLite database for storing metadata required by t
1. [21840](https://github.com/influxdata/influxdb/pull/21840): Run migrations on restored bolt & SQLite metadata databases as part of the restore process.
1. [21844](https://github.com/influxdata/influxdb/pull/21844): Upgrade to latest version of `influxdata/cron` so that tasks can be created with interval of `every: 1w`.
1. [21849](https://github.com/influxdata/influxdb/pull/21849): Specify which fields are missing when rejecting an incomplete onboarding request.
1. [21839](https://github.com/influxdata/influxdb/pull/21839): Fix display and parsing of `influxd upgrade` CLI prompts in PowerShell.

## v2.0.7 [2021-06-04]

Expand Down
14 changes: 12 additions & 2 deletions cmd/influxd/launcher/launcher_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -482,13 +482,23 @@ func (tl *TestLauncher) TaskService(tb testing.TB) taskmodel.TaskService {

func (tl *TestLauncher) BackupService(tb testing.TB) *clibackup.Client {
tb.Helper()
return &clibackup.Client{CLI: clients.CLI{}, BackupApi: tl.APIClient(tb).BackupApi}
client := tl.APIClient(tb)
return &clibackup.Client{
CLI: clients.CLI{},
BackupApi: client.BackupApi,
HealthApi: client.HealthApi,
}
}

func (tl *TestLauncher) RestoreService(tb testing.TB) *clirestore.Client {
tb.Helper()
client := tl.APIClient(tb)
return &clirestore.Client{CLI: clients.CLI{}, RestoreApi: client.RestoreApi, OrganizationsApi: client.OrganizationsApi}
return &clirestore.Client{
CLI: clients.CLI{},
RestoreApi: client.RestoreApi,
OrganizationsApi: client.OrganizationsApi,
HealthApi: client.HealthApi,
}
}

func (tl *TestLauncher) HTTPClient(tb testing.TB) *httpc.Client {
Expand Down
18 changes: 7 additions & 11 deletions cmd/influxd/upgrade/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,17 @@ import (
"path/filepath"
"strings"

"github.com/influxdata/influxdb/v2/kit/platform"

"github.com/dustin/go-humanize"
"github.com/influxdata/influx-cli/v2/clients"
"github.com/influxdata/influxdb/v2"
"github.com/influxdata/influxdb/v2/cmd/internal"
"github.com/influxdata/influxdb/v2/kit/platform"
"github.com/influxdata/influxdb/v2/pkg/fs"
"github.com/influxdata/influxdb/v2/v1/services/meta"
"github.com/tcnksm/go-input"
"go.uber.org/zap"
)

// upgradeDatabases creates databases, buckets, retention policies and shard info according to 1.x meta and copies data
func upgradeDatabases(ctx context.Context, ui *input.UI, v1 *influxDBv1, v2 *influxDBv2, opts *options, orgID platform.ID, log *zap.Logger) (map[string][]platform.ID, error) {
func upgradeDatabases(ctx context.Context, cli clients.CLI, v1 *influxDBv1, v2 *influxDBv2, opts *options, orgID platform.ID, log *zap.Logger) (map[string][]platform.ID, error) {
v1opts := opts.source
v2opts := opts.target
db2BucketIds := make(map[string][]platform.ID)
Expand All @@ -40,7 +38,7 @@ func upgradeDatabases(ctx context.Context, ui *input.UI, v1 *influxDBv1, v2 *inf
log.Info("No database found in the 1.x meta")
return db2BucketIds, nil
}
if err := checkDiskSpace(ui, opts, log); err != nil {
if err := checkDiskSpace(cli, opts, log); err != nil {
return nil, err
}

Expand Down Expand Up @@ -199,7 +197,7 @@ func upgradeDatabases(ctx context.Context, ui *input.UI, v1 *influxDBv1, v2 *inf

// checkDiskSpace ensures there is enough room at the target path to store
// a full copy of all V1 data.
func checkDiskSpace(ui *input.UI, opts *options, log *zap.Logger) error {
func checkDiskSpace(cli clients.CLI, opts *options, log *zap.Logger) error {
log.Info("Checking available disk space")

size, err := DirSize(opts.source.dataDir)
Expand Down Expand Up @@ -227,12 +225,10 @@ func checkDiskSpace(ui *input.UI, opts *options, log *zap.Logger) error {
return fmt.Errorf("not enough space on target disk of %s: need %d, available %d", v2dir, size, diskInfo.Free)
}
if !opts.force {
if confirmed := internal.GetConfirm(ui, func() string {
return fmt.Sprintf(`Proceeding will copy all V1 data to %q
if confirmed := cli.StdIO.GetConfirm(fmt.Sprintf(`Proceeding will copy all V1 data to %q
Space available: %s
Space required: %s
`, v2dir, freeBytes, requiredBytes)
}); !confirmed {
`, v2dir, freeBytes, requiredBytes)); !confirmed {
return errors.New("upgrade was canceled")
}
}
Expand Down
101 changes: 26 additions & 75 deletions cmd/influxd/upgrade/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,12 @@ import (
"context"
"errors"
"fmt"
"math"
"path/filepath"
"strconv"
"time"

"github.com/influxdata/influx-cli/v2/clients"
"github.com/influxdata/influx-cli/v2/clients/setup"
"github.com/influxdata/influx-cli/v2/config"
"github.com/influxdata/influxdb/v2"
"github.com/influxdata/influxdb/v2/cmd/internal"
"github.com/tcnksm/go-input"
"go.uber.org/zap"
)

Expand All @@ -25,81 +22,35 @@ func setupAdmin(ctx context.Context, v2 *influxDBv2, req *influxdb.OnboardingReq
return res, nil
}

func onboardingRequest(ui *input.UI, options *options) (*influxdb.OnboardingRequest, error) {
if (options.force || len(options.target.password) > 0) && len(options.target.password) < internal.MinPasswordLen {
return nil, internal.ErrPasswordIsTooShort
}

req := &influxdb.OnboardingRequest{
User: options.target.userName,
Password: options.target.password,
Org: options.target.orgName,
Bucket: options.target.bucket,
RetentionPeriodSeconds: influxdb.InfiniteRetention,
Token: options.target.token,
}

if options.target.retention != "" {
dur, err := internal.RawDurationToTimeDuration(options.target.retention)
if err != nil {
return nil, err
}
secs, nanos := math.Modf(dur.Seconds())
if nanos > 0 {
return nil, fmt.Errorf("retention policy %q is too precise, must be divisible by 1s", options.target.retention)
}
req.RetentionPeriodSeconds = int64(secs)
}

if options.force {
return req, nil
}

fmt.Fprintln(ui.Writer, string(internal.PromptWithColor("Welcome to InfluxDB 2.0!", internal.ColorYellow)))
if req.User == "" {
req.User = internal.GetInput(ui, "Please type your primary username", "")
}
if req.Password == "" {
req.Password = internal.GetPassword(ui, false)
func onboardingRequest(cli clients.CLI, options *options) (*influxdb.OnboardingRequest, error) {
setupClient := setup.Client{CLI: cli}
cliReq, err := setupClient.OnboardingRequest(&setup.Params{
Username: options.target.userName,
Password: options.target.password,
AuthToken: options.target.token,
Org: options.target.orgName,
Bucket: options.target.bucket,
Retention: options.target.retention,
Force: options.force,
})
if err != nil {
return nil, err
}
if req.Org == "" {
req.Org = internal.GetInput(ui, "Please type your primary organization name", "")
req := influxdb.OnboardingRequest{
User: cliReq.Username,
Org: cliReq.Org,
Bucket: cliReq.Bucket,
}
if req.Bucket == "" {
req.Bucket = internal.GetInput(ui, "Please type your primary bucket name", "")
if cliReq.Password != nil {
req.Password = *cliReq.Password
}

// Check the initial opts instead of the req to distinguish not-set from explicit 0 over the CLI.
if options.target.retention == "" {
infiniteStr := strconv.Itoa(influxdb.InfiniteRetention)
for {
rpStr := internal.GetInput(ui,
"Please type your retention period in hours.\nOr press ENTER for infinite", infiniteStr)
rp, err := strconv.Atoi(rpStr)
if rp >= 0 && err == nil {
req.RetentionPeriodSeconds = int64((time.Duration(rp) * time.Hour).Seconds())
break
}
}
if cliReq.RetentionPeriodSeconds != nil {
req.RetentionPeriodSeconds = *cliReq.RetentionPeriodSeconds
}

if confirmed := internal.GetConfirm(ui, func() string {
rp := "infinite"
if req.RetentionPeriodSeconds > 0 {
rp = (time.Duration(req.RetentionPeriodSeconds) * time.Second).String()
}
return fmt.Sprintf(`
You have entered:
Username: %s
Organization: %s
Bucket: %s
Retention Period: %s
`, req.User, req.Org, req.Bucket, rp)
}); !confirmed {
return nil, errors.New("setup was canceled")
if cliReq.Token != nil {
req.Token = *cliReq.Token
}

return req, nil
return &req, nil
}

func saveLocalConfig(sourceOptions *optionsV1, targetOptions *optionsV2, log *zap.Logger) error {
Expand Down
17 changes: 8 additions & 9 deletions cmd/influxd/upgrade/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,16 @@ import (
"path/filepath"
"strings"

"github.com/influxdata/influxdb/v2/kit/platform"

"github.com/influxdata/influx-cli/v2/clients"
"github.com/influxdata/influx-cli/v2/pkg/stdio"
"github.com/influxdata/influxdb/v2"
"github.com/influxdata/influxdb/v2/authorization"
"github.com/influxdata/influxdb/v2/bolt"
"github.com/influxdata/influxdb/v2/dbrp"
"github.com/influxdata/influxdb/v2/internal/fs"
"github.com/influxdata/influxdb/v2/kit/cli"
"github.com/influxdata/influxdb/v2/kit/metric"
"github.com/influxdata/influxdb/v2/kit/platform"
"github.com/influxdata/influxdb/v2/kit/prom"
"github.com/influxdata/influxdb/v2/kv"
"github.com/influxdata/influxdb/v2/kv/migration"
Expand All @@ -31,7 +32,6 @@ import (
"github.com/influxdata/influxdb/v2/v1/services/meta/filestore"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/tcnksm/go-input"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
Expand Down Expand Up @@ -155,8 +155,7 @@ func NewCommand(ctx context.Context, v *viper.Viper) (*cobra.Command, error) {
if err != nil {
return err
}
ui := &input.UI{Writer: cmd.OutOrStdout(), Reader: cmd.InOrStdin()}
return runUpgradeE(ctx, ui, options, logger)
return runUpgradeE(ctx, clients.CLI{StdIO: stdio.TerminalStdio}, options, logger)
},
Args: cobra.NoArgs,
}
Expand Down Expand Up @@ -234,7 +233,7 @@ func NewCommand(ctx context.Context, v *viper.Viper) (*cobra.Command, error) {
DestP: &options.target.retention,
Flag: "retention",
Default: "",
Desc: "optional: duration bucket will retain data. 0 is infinite. The default is 0.",
Desc: "optional: duration bucket will retain data (i.e '1w' or '72h'). Default is infinite.",
Short: 'r',
},
{
Expand Down Expand Up @@ -351,7 +350,7 @@ func buildLogger(options *logOptions, verbose bool) (*zap.Logger, error) {
return log, nil
}

func runUpgradeE(ctx context.Context, ui *input.UI, options *options, log *zap.Logger) error {
func runUpgradeE(ctx context.Context, cli clients.CLI, options *options, log *zap.Logger) error {
if options.source.configFile != "" && options.source.dbDir != "" {
return errors.New("only one of --v1-dir or --config-file may be specified")
}
Expand Down Expand Up @@ -445,7 +444,7 @@ func runUpgradeE(ctx context.Context, ui *input.UI, options *options, log *zap.L
return errors.New("InfluxDB has been already set up")
}

req, err := onboardingRequest(ui, options)
req, err := onboardingRequest(cli, options)
if err != nil {
return err
}
Expand All @@ -463,7 +462,7 @@ func runUpgradeE(ctx context.Context, ui *input.UI, options *options, log *zap.L
return err
}

db2BucketIds, err := upgradeDatabases(ctx, ui, v1, v2, options, or.Org.ID, log)
db2BucketIds, err := upgradeDatabases(ctx, cli, v1, v2, options, or.Org.ID, log)
if err != nil {
// remove all files
log.Error("Database upgrade error, removing data", zap.Error(err))
Expand Down
7 changes: 2 additions & 5 deletions cmd/influxd/upgrade/upgrade_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package upgrade

import (
"bytes"
"context"
"fmt"
"io/ioutil"
Expand All @@ -13,6 +12,7 @@ import (
"github.com/BurntSushi/toml"
"github.com/dustin/go-humanize"
"github.com/google/go-cmp/cmp"
"github.com/influxdata/influx-cli/v2/clients"
"github.com/influxdata/influxdb/v2"
"github.com/influxdata/influxdb/v2/bolt"
"github.com/influxdata/influxdb/v2/cmd/influxd/launcher"
Expand All @@ -22,7 +22,6 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/stretchr/testify/require"
"github.com/tcnksm/go-input"
"go.uber.org/zap"
"go.uber.org/zap/zaptest"
)
Expand Down Expand Up @@ -225,10 +224,8 @@ func TestUpgradeRealDB(t *testing.T) {
}

opts := &options{source: *v1opts, target: *v2opts, force: true}
ui := &input.UI{Writer: &bytes.Buffer{}, Reader: &bytes.Buffer{}}

log := zaptest.NewLogger(t, zaptest.Level(zap.InfoLevel))
err = runUpgradeE(ctx, ui, opts, log)
err = runUpgradeE(ctx, clients.CLI{}, opts, log)
require.NoError(t, err)

v := viper.New()
Expand Down
Loading

0 comments on commit 1a982a9

Please sign in to comment.