Skip to content
This repository was archived by the owner on Aug 30, 2024. It is now read-only.

Environment subcommands #89

Closed
wants to merge 14 commits into from
Prev Previous commit
Next Next commit
fixup! Migrate envs
  • Loading branch information
cmoog committed Jul 31, 2020
commit 8f4a73c155b73354d4c80a6245e381f16d18e580
2 changes: 1 addition & 1 deletion ci/integration/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func TestCoderCLI(t *testing.T) {
tcli.StderrEmpty(),
)

c.Run(ctx, "coder version").Assert(t,
c.Run(ctx, "coder --version").Assert(t,
tcli.StderrEmpty(),
tcli.Success(),
tcli.StdoutMatches("linux"),
Expand Down
25 changes: 1 addition & 24 deletions cmd/coder/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,39 +9,15 @@ import (
"runtime"

"cdr.dev/coder-cli/internal/x/xterminal"
"github.com/spf13/pflag"
"github.com/urfave/cli"

cdrcli "go.coder.com/cli"
"go.coder.com/flog"
)

var (
version string = "unknown"
)

type rootCmd struct{}

func (r *rootCmd) Run(fl *pflag.FlagSet) {

fl.Usage()
}

func (r *rootCmd) Spec() cdrcli.CommandSpec {
return cdrcli.CommandSpec{
Name: "coder",
Usage: "[subcommand] [flags]",
Desc: "coder provides a CLI for working with an existing Coder Enterprise installation.",
}
}

func (r *rootCmd) Subcommands() []cdrcli.Command {
return []cdrcli.Command{
&syncCmd{},
&urlsCmd{},
}
}

func main() {
if os.Getenv("PPROF") != "" {
go func() {
Expand All @@ -67,6 +43,7 @@ func main() {
makeConfigSSHCmd(),
makeSecretsCmd(),
makeEnvsCommand(),
makeSyncCmd(),
}
err = app.Run(os.Args)
if err != nil {
Expand Down
11 changes: 6 additions & 5 deletions cmd/coder/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ func makeSecretsCmd() cli.Command {
return cli.Command{
Name: "secrets",
Usage: "",
Description: "interact with secrets",
Description: "Interact with secrets objects owned by the active user.",
Subcommands: []cli.Command{
{
Name: "ls",
Usage: "",
Description: "",
Description: "list all secrets owned by the active user",
Action: listSecrets,
},
makeCreateSecret(),
Expand Down Expand Up @@ -54,11 +54,12 @@ func makeCreateSecret() cli.Command {

return cli.Command{
Name: "create",
Usage: "",
Description: "",
Usage: "create a new secret",
Description: "Create a new secret object to store application secrets and access them securely from within your environments.",
ArgsUsage: "[secret_name]",
Before: func(c *cli.Context) error {
if c.Args().First() == "" {
return xerrors.Errorf("[name] is a required field argument")
return xerrors.Errorf("[secret_name] is a required argument")
}
if fromPrompt && (fromLiteral != "" || fromFile != "") {
return xerrors.Errorf("--from-prompt cannot be set along with --from-file or --from-literal")
Expand Down
155 changes: 80 additions & 75 deletions cmd/coder/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,37 @@ import (
"path/filepath"
"strings"

"github.com/spf13/pflag"
"cdr.dev/coder-cli/internal/sync"
"github.com/urfave/cli"
"golang.org/x/xerrors"

"go.coder.com/cli"
"go.coder.com/flog"

"cdr.dev/coder-cli/internal/sync"
)

type syncCmd struct {
init bool
}

func (cmd *syncCmd) Spec() cli.CommandSpec {
return cli.CommandSpec{
Name: "sync",
Usage: "[local directory] [<env name>:<remote directory>]",
Desc: "establish a one way directory sync to a remote environment",
func makeSyncCmd() cli.Command {
var init bool
return cli.Command{
Name: "sync",
Usage: "synchronize local files to a Coder environment",
Description: "Establish a one way directory sync to a Coder environment.",
ArgsUsage: "[local directory] [<env name>:<remote directory>]",
Before: func(c *cli.Context) error {
if c.Args().Get(0) == "" || c.Args().Get(1) == "" {
return xerrors.Errorf("[local] and [remote] arguments are required")
}
return nil
},
Action: makeRunSync(&init),
Flags: []cli.Flag{
cli.BoolFlag{
Name: "init",
Usage: "do initial transfer and exit",
Destination: &init,
},
},
}
}

func (cmd *syncCmd) RegisterFlags(fl *pflag.FlagSet) {
fl.BoolVarP(&cmd.init, "init", "i", false, "do initial transfer and exit")
}

// version returns local rsync protocol version as a string.
func rsyncVersion() string {
cmd := exec.Command("rsync", "--version")
Expand All @@ -49,63 +56,61 @@ func rsyncVersion() string {
return versionString[1]
}

func (cmd *syncCmd) Run(fl *pflag.FlagSet) {
var (
local = fl.Arg(0)
remote = fl.Arg(1)
)
if local == "" || remote == "" {
exitUsage(fl)
}

entClient := requireAuth()

info, err := os.Stat(local)
if err != nil {
flog.Fatal("%v", err)
}
if !info.IsDir() {
flog.Fatal("%s must be a directory", local)
}

remoteTokens := strings.SplitN(remote, ":", 2)
if len(remoteTokens) != 2 {
flog.Fatal("remote misformatted")
}
var (
envName = remoteTokens[0]
remoteDir = remoteTokens[1]
)

env := findEnv(entClient, envName)

absLocal, err := filepath.Abs(local)
if err != nil {
flog.Fatal("make abs path out of %v: %v", local, absLocal)
}

s := sync.Sync{
Init: cmd.init,
Env: env,
RemoteDir: remoteDir,
LocalDir: absLocal,
Client: entClient,
}

localVersion := rsyncVersion()
remoteVersion, rsyncErr := s.Version()

if rsyncErr != nil {
flog.Info("Unable to determine remote rsync version. Proceeding cautiously.")
} else if localVersion != remoteVersion {
flog.Fatal("rsync protocol mismatch: local = %v, remote = %v", localVersion, rsyncErr)
}

for err == nil || err == sync.ErrRestartSync {
err = s.Run()
}

if err != nil {
flog.Fatal("%v", err)
func makeRunSync(init *bool) func(c *cli.Context) {
return func(c *cli.Context) {
var (
local = c.Args().Get(0)
remote = c.Args().Get(1)
)

entClient := requireAuth()

info, err := os.Stat(local)
if err != nil {
flog.Fatal("%v", err)
}
if !info.IsDir() {
flog.Fatal("%s must be a directory", local)
}

remoteTokens := strings.SplitN(remote, ":", 2)
if len(remoteTokens) != 2 {
flog.Fatal("remote misformatted")
}
var (
envName = remoteTokens[0]
remoteDir = remoteTokens[1]
)

env := findEnv(entClient, envName)

absLocal, err := filepath.Abs(local)
if err != nil {
flog.Fatal("make abs path out of %v: %v", local, absLocal)
}

s := sync.Sync{
Init: *init,
Env: env,
RemoteDir: remoteDir,
LocalDir: absLocal,
Client: entClient,
}

localVersion := rsyncVersion()
remoteVersion, rsyncErr := s.Version()

if rsyncErr != nil {
flog.Info("Unable to determine remote rsync version. Proceeding cautiously.")
} else if localVersion != remoteVersion {
flog.Fatal("rsync protocol mismatch: local = %v, remote = %v", localVersion, rsyncErr)
}

for err == nil || err == sync.ErrRestartSync {
err = s.Run()
}
if err != nil {
flog.Fatal("%v", err)
}
}
}
101 changes: 0 additions & 101 deletions internal/x/xvalidate/errors.go

This file was deleted.