Skip to content

Commit

Permalink
Merge a958b0a into 66b4691
Browse files Browse the repository at this point in the history
  • Loading branch information
MattAWright committed Jan 25, 2018
2 parents 66b4691 + a958b0a commit fd6fecb
Show file tree
Hide file tree
Showing 15 changed files with 160 additions and 48 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ _Date_
- More precise errors are returned to users when invalid usernames, org,
project, team, or policy names are submitted to a ui prompt.
- The experimental and hidden `policies test` command has been removed.
- Added spinners to represent progress. This means fewer lasting print-outs
for certain commands.

## v0.29.0

Expand Down
14 changes: 13 additions & 1 deletion Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions api/credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,25 @@ type CredentialsClient struct {
}

// Search returns all credentials at the given pathexp in an undecrypted state
func (c *CredentialsClient) Search(ctx context.Context, pathexp string) ([]apitypes.CredentialEnvelope, error) {
func (c *CredentialsClient) Search(ctx context.Context, pathexp string, p ProgressFunc) ([]apitypes.CredentialEnvelope, error) {
v := &url.Values{}
v.Set("pathexp", pathexp)
v.Set("skip-decryption", "true")

return c.listWorker(ctx, v)
return c.listWorker(ctx, v, p)
}

// Get returns all credentials at the given path.
func (c *CredentialsClient) Get(ctx context.Context, path string) ([]apitypes.CredentialEnvelope, error) {
func (c *CredentialsClient) Get(ctx context.Context, path string, p ProgressFunc) ([]apitypes.CredentialEnvelope, error) {
v := &url.Values{}
v.Set("path", path)

return c.listWorker(ctx, v)
return c.listWorker(ctx, v, p)
}

func (c *CredentialsClient) listWorker(ctx context.Context, v *url.Values) ([]apitypes.CredentialEnvelope, error) {
func (c *CredentialsClient) listWorker(ctx context.Context, v *url.Values, p ProgressFunc) ([]apitypes.CredentialEnvelope, error) {
var resp []apitypes.CredentialResp
err := c.client.DaemonRoundTrip(ctx, "GET", "/credentials", v, nil, &resp, nil)
err := c.client.DaemonRoundTrip(ctx, "GET", "/credentials", v, nil, &resp, p)
if err != nil {
return nil, err
}
Expand Down
10 changes: 10 additions & 0 deletions cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ var progress api.ProgressFunc = func(evt *api.Event, err error) {
}
}

func spinner(text string) (*ui.Spinner, api.ProgressFunc) {
s := ui.NewSpinner(text)

return s, func(evt *api.Event, err error) {
if evt != nil {
s.Update(evt.Message)
}
}
}

// NewAPIClient loads config and creates a new api client
func NewAPIClient(ctx *context.Context, client *api.Client) (context.Context, *api.Client, error) {
if client == nil {
Expand Down
8 changes: 6 additions & 2 deletions cmd/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import (
"strings"

"github.com/google/shlex"
"github.com/urfave/cli"

"github.com/manifoldco/torus-cli/apitypes"
"github.com/manifoldco/torus-cli/errs"
"github.com/manifoldco/torus-cli/hints"
"github.com/urfave/cli"
)

type secretPair struct {
Expand Down Expand Up @@ -57,7 +58,10 @@ func importCmd(ctx *cli.Context) error {
}(secret.value)
}

creds, err := setCredentials(ctx, path, makers)
s, p := spinner("Attempting to set credentials")
s.Start()
creds, err := setCredentials(ctx, path, makers, p)
s.Stop()
if err != nil {
return errs.NewErrorExitError("Could not set credentials.", err)
}
Expand Down
5 changes: 4 additions & 1 deletion cmd/invites_approve.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,10 @@ func invitesApprove(ctx *cli.Context) error {
return errs.NewExitError("Invite not found.")
}

err = client.OrgInvites.Approve(context.Background(), *targetInvite, progress)
s, p := spinner(fmt.Sprintf("Attempting to approve invite for %s", email))
s.Start()
err = client.OrgInvites.Approve(context.Background(), *targetInvite, p)
s.Stop()
if err != nil {
return err
}
Expand Down
22 changes: 17 additions & 5 deletions cmd/keypairs.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,21 +188,27 @@ func generateKeypairs(ctx *cli.Context) error {

var rErr error

s, p := spinner("Attempting to generate keypairs")
s.Start()
for orgID, name := range regenOrgs {
fmt.Println("Generating signing and encryption keypairs for org: " + name)
err := client.KeyPairs.Create(c, orgID, progress)
s.Update("Generating signing and encryption keypairs for org: " + name)
err := client.KeyPairs.Create(c, orgID, p)
if err != nil && rErr == nil {
s.Stop()
rErr = err
break
}
}
s.Stop()

if rErr != nil {
return errs.NewExitError("Error while regenerating keypairs.")
}

if len(regenOrgs) > 0 {
fmt.Println("Keypair generation successful.")
for _, name := range regenOrgs {
fmt.Printf("Successfully generated keypairs for %s org\n", name)
}
} else {
fmt.Println("No keypairs missing.")
}
Expand All @@ -228,7 +234,10 @@ func generateKeypairsForOrg(c context.Context, ctx *cli.Context, client *api.Cli
orgID = org.ID
}

err = client.KeyPairs.Create(c, orgID, progress)
s, p := spinner("Attempting to generate keypairs")
s.Start()
err = client.KeyPairs.Create(c, orgID, p)
s.Stop()
if err != nil {
return outputErr
}
Expand Down Expand Up @@ -276,7 +285,10 @@ func revokeKeypairs(ctx *cli.Context) error {
return nil
}

err = client.KeyPairs.Revoke(c, org.ID, progress)
s, p := spinner("Attempting to revoke keypairs")
s.Start()
err = client.KeyPairs.Revoke(c, org.ID, p)
s.Stop()
if err != nil {
return errs.NewErrorExitError("Error while revoking keypairs.", err)
}
Expand Down
8 changes: 4 additions & 4 deletions cmd/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ func listCmd(ctx *cli.Context) error {

go func() {
// Get credentials
credentials, cErr = client.Credentials.Search(c, filterPathExp.String())
credentials, cErr = client.Credentials.Search(c, filterPathExp.String(), nil)
getEnvsServicesCreds.Done()
}()

Expand Down Expand Up @@ -217,8 +217,8 @@ func listCmd(ctx *cli.Context) error {
if(verbose){
fmt.Println("")
projW := ansiterm.NewTabWriter(os.Stdout, 0, 0, 4, ' ', 0)
fmt.Fprintf(projW, "Org:\t" + ui.Bold(org.Body.Name) + "\t\n")
fmt.Fprintf(projW, "Project:\t" + ui.Bold(project.Body.Name) + "\t\n")
fmt.Fprintf(projW, ui.Bold("Org") + ":\t" + org.Body.Name + "\t\n")
fmt.Fprintf(projW, ui.Bold("Project") + ":\t" + project.Body.Name + "\t\n")
projW.Flush()
}

Expand Down Expand Up @@ -247,7 +247,7 @@ func listCmd(ctx *cli.Context) error {
}
w.Flush()

fmt.Printf("\n(%s) secrets found\n.", ui.Faint(strconv.Itoa(credCount)))
fmt.Printf("\n(%s) secrets found\n", ui.Faint(strconv.Itoa(credCount)))

return nil
}
Expand Down
5 changes: 4 additions & 1 deletion cmd/machines.go
Original file line number Diff line number Diff line change
Expand Up @@ -664,8 +664,11 @@ func createMachine(ctx *cli.Context) error {
func createMachineByName(c context.Context, client *api.Client,
orgID, teamID *identity.ID, name string) (*apitypes.MachineSegment, *base64.Value, error) {

s, p := spinner("Attempting to create machine.")
s.Start()
machine, tokenSecret, err := client.Machines.Create(
c, orgID, teamID, name, progress)
c, orgID, teamID, name, p)
s.Stop()
if err != nil {
if strings.Contains(err.Error(), "resource exists") {
return nil, nil, errs.NewExitError("Machine already exists")
Expand Down
11 changes: 7 additions & 4 deletions cmd/set.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,14 @@ func setCmd(ctx *cli.Context) error {
return apitypes.NewStringCredentialValue(value)
}

_, err = setCredentials(ctx, path, makers)
s, p := spinner(fmt.Sprintf("Attempting to set credential %s", name))
s.Start()
_, err = setCredentials(ctx, path, makers, p)
s.Stop()
if err != nil {
return errs.NewErrorExitError("Could not set credential.", err)
}

fmt.Printf("\nCredential %s has been set at %s/%s\n", name, path, name)

hints.Display(hints.View, hints.Run, hints.Unset, hints.Import, hints.Export)
Expand Down Expand Up @@ -158,7 +161,7 @@ func determinePathFromFlags(ctx *cli.Context) (*pathexp.PathExp, error) {
type valueMaker func() *apitypes.CredentialValue
type valueMakers map[string]valueMaker

func setCredentials(ctx *cli.Context, pe *pathexp.PathExp, makers valueMakers) ([]apitypes.CredentialEnvelope, error) {
func setCredentials(ctx *cli.Context, pe *pathexp.PathExp, makers valueMakers, p api.ProgressFunc) ([]apitypes.CredentialEnvelope, error) {
cfg, err := config.LoadConfig()
if err != nil {
return nil, err
Expand Down Expand Up @@ -207,5 +210,5 @@ func setCredentials(ctx *cli.Context, pe *pathexp.PathExp, makers valueMakers) (
})
}

return client.Credentials.Create(c, creds, progress)
return client.Credentials.Create(c, creds, p)
}
5 changes: 4 additions & 1 deletion cmd/unset.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,13 @@ func unsetCmd(ctx *cli.Context) error {
return apitypes.NewUnsetCredentialValue()
}

_, err = setCredentials(ctx, pe, makers)
s, p := spinner(fmt.Sprintf("Attempting to unset credential %s", name))
s.Start()
_, err = setCredentials(ctx, pe, makers, p)
if err != nil {
return errs.NewErrorExitError("Could not unset credential", err)
}
s.Stop()

output := fmt.Sprintf("\nCredential %s has been unset at %s/%s.", name, pe, name)
fmt.Println(output)
Expand Down
9 changes: 5 additions & 4 deletions cmd/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,9 @@ func viewCmd(ctx *cli.Context) error {
}
}

return tw.Flush()

hints.Display(hints.Link, hints.Run, hints.Export)

return err
return tw.Flush()
}

func getSecrets(ctx *cli.Context) ([]apitypes.CredentialEnvelope, string, error) {
Expand Down Expand Up @@ -120,7 +118,10 @@ func getSecrets(ctx *cli.Context) ([]apitypes.CredentialEnvelope, string, error)

path := strings.Join(parts, "/")

secrets, err := client.Credentials.Get(c, path)
s, p := spinner("Decrypting credentials")
s.Start()
secrets, err := client.Credentials.Get(c, path, p)
s.Stop()
if err != nil {
return nil, "", errs.NewErrorExitError("Error fetching secrets", err)
}
Expand Down
34 changes: 15 additions & 19 deletions docs/commands/secrets.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,6 @@ This is how all secrets are stored in Torus.
# Setting the port for the production auth service inside myorg's api project.
$ torus set -o myorg -p api -e production -s auth PORT 3000

Credentials retrieved
Keypairs retrieved
Encrypting key retrieved
Credential encrypted
Completed Operation

Credential PORT has been set at /myorg/api/production/auth/*/*/PORT
```

Expand Down Expand Up @@ -100,6 +94,16 @@ Credential PORT has been set at /myorg/api/[production|staging]/auth/*/*/PORT

`torus unset <name|path>` unsets the value for the specified name (or [path](../concepts/path.md)).

**Example**

```bash
$ torus unset port
You are about to unset "/myorg/myproject/dev-matt/default/*/*/port". This cannot be undone.
✔ Do you wish to continue? [y/N] y

Credential port has been unset at /myorg/myproject/dev-matt/default/*/*/port.
```

## import
###### Added [v0.25.0](https://github.com/manifoldco/torus-cli/blob/v0.25.0/CHANGELOG.md)

Expand All @@ -109,21 +113,13 @@ Credential PORT has been set at /myorg/api/[production|staging]/auth/*/*/PORT

```bash
$ cat prod.env
PORT=4000
DOMAIN=mydomain.co
MYSQL_URL=mysql://user:pass@host.com:4321/mydb

$ torus import -e production test.env
DOMAIN="mydomain.co"
PORT="4000"

Credentials retrieved
Keypairs retrieved
Encrypting key retrieved
Credential encrypted
Credential encrypted
Completed Operation
$ torus import -e production prod.env

Credential port has been set at /myorg/myproject/production/default/*/*/PORT
Credential mysql_url has been set at /myorg/myproject/production/default/*/*/MYSQL_URL
Credential domain has been set at /myorg/myproject/production/default/*/*/domain
Credential port has been set at /myorg/myproject/production/default/*/*/port
```

## export
Expand Down
38 changes: 38 additions & 0 deletions ui/spinner.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package ui

import (
"time"

"github.com/briandowns/spinner"
)

// Spinner struct contains the spinner struct and display text
type Spinner struct {
spinner *spinner.Spinner
text string
}

// NewSpinner creates a new Spinner struct
func NewSpinner(text string) *Spinner {
s := spinner.New(spinner.CharSets[9], 100*time.Millisecond)
s.Suffix = " " + text
return &Spinner{
s,
text,
}
}

// Start displays the Spinner and starts movement
func (s *Spinner) Start() {
s.spinner.Start()
}

// Stop halts the spiner movement and removes it from display
func (s *Spinner) Stop() {
s.spinner.Stop()
}

// Update changes the Spinner's suffix to 'text'
func (s *Spinner) Update(text string) {
s.spinner.Suffix = " " + text
}
Loading

0 comments on commit fd6fecb

Please sign in to comment.