Skip to content

Commit

Permalink
Add autocompletions to be shared between buildah and podman
Browse files Browse the repository at this point in the history
When attempting to port podman secrets to buildah secrets, I found
these autocompletions which could be shared between the projects.

Moving them to containers/common to allow sharing.

Signed-off-by: Daniel J Walsh <[email protected]>
  • Loading branch information
rhatdan committed Feb 19, 2021
1 parent ff21341 commit 7cfa80b
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 45 deletions.
14 changes: 14 additions & 0 deletions pkg/completion/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,17 @@ func AutocompleteOS(cmd *cobra.Command, args []string, toComplete string) ([]str
completions := []string{"linux", "windows"}
return completions, cobra.ShellCompDirectiveNoFileComp
}

// AutocompleteJSONFormat - Autocomplete format flag option.
// -> "json"
func AutocompleteJSONFormat(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return []string{"json"}, cobra.ShellCompDirectiveNoFileComp
}

// AutocompleteOneArg - Autocomplete one random arg
func AutocompleteOneArg(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) == 1 {
return nil, cobra.ShellCompDirectiveDefault
}
return nil, cobra.ShellCompDirectiveNoFileComp
}
58 changes: 28 additions & 30 deletions pkg/secrets/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,38 +19,36 @@ const maxSecretSize = 512000
// secretIDLength is the character length of a secret ID - 25
const secretIDLength = 25

var (
// ErrInvalidPath indicates that the secrets path is invalid
ErrInvalidPath = errors.New("invalid secrets path")
// errInvalidPath indicates that the secrets path is invalid
var errInvalidPath = errors.New("invalid secrets path")

// ErrNoSuchSecret indicates that the secret does not exist
ErrNoSuchSecret = errors.New("no such secret")
// errNoSuchSecret indicates that the secret does not exist
var errNoSuchSecret = errors.New("no such secret")

// ErrSecretNameInUse indicates that the secret name is already in use
ErrSecretNameInUse = errors.New("secret name in use")
// errSecretNameInUse indicates that the secret name is already in use
var errSecretNameInUse = errors.New("secret name in use")

// ErrInvalidSecretName indicates that the secret name is invalid
ErrInvalidSecretName = errors.New("invalid secret name")
// errInvalidSecretName indicates that the secret name is invalid
var errInvalidSecretName = errors.New("invalid secret name")

// ErrInvalidDriver indicates that the driver type is invalid
ErrInvalidDriver = errors.New("invalid driver")
// errInvalidDriver indicates that the driver type is invalid
var errInvalidDriver = errors.New("invalid driver")

// ErrInvalidDriverOpt indicates that a driver option is invalid
ErrInvalidDriverOpt = errors.New("invalid driver option")
// errInvalidDriverOpt indicates that a driver option is invalid
var errInvalidDriverOpt = errors.New("invalid driver option")

// ErrAmbiguous indicates that a secret is ambiguous
ErrAmbiguous = errors.New("secret is ambiguous")
// errAmbiguous indicates that a secret is ambiguous
var errAmbiguous = errors.New("secret is ambiguous")

// ErrDataSize indicates that the secret data is too large or too small
ErrDataSize = errors.New("secret data must be larger than 0 and less than 512000 bytes")
// errDataSize indicates that the secret data is too large or too small
var errDataSize = errors.New("secret data must be larger than 0 and less than 512000 bytes")

// secretsFile is the name of the file that the secrets database will be stored in
secretsFile = "secrets.json"
// secretsFile is the name of the file that the secrets database will be stored in
var secretsFile = "secrets.json"

// secretNameRegexp matches valid secret names
// Allowed: 64 [a-zA-Z0-9-_.] characters, and the start and end character must be [a-zA-Z0-9]
secretNameRegexp = regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9_.-]*$`)
)
// secretNameRegexp matches valid secret names
// Allowed: 64 [a-zA-Z0-9-_.] characters, and the start and end character must be [a-zA-Z0-9]
var secretNameRegexp = regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9_.-]*$`)

// SecretsManager holds information on handling secrets
type SecretsManager struct {
Expand Down Expand Up @@ -99,7 +97,7 @@ func NewManager(rootPath string) (*SecretsManager, error) {
manager := new(SecretsManager)

if !filepath.IsAbs(rootPath) {
return nil, errors.Wrapf(ErrInvalidPath, "path must be absolute: %s", rootPath)
return nil, errors.Wrapf(errInvalidPath, "path must be absolute: %s", rootPath)
}
// the lockfile functions requre that the rootPath dir is executable
if err := os.MkdirAll(rootPath, 0700); err != nil {
Expand Down Expand Up @@ -129,7 +127,7 @@ func (s *SecretsManager) Store(name string, data []byte, driverType string, driv
}

if !(len(data) > 0 && len(data) < maxSecretSize) {
return "", ErrDataSize
return "", errDataSize
}

s.lockfile.Lock()
Expand All @@ -140,7 +138,7 @@ func (s *SecretsManager) Store(name string, data []byte, driverType string, driv
return "", err
}
if exist {
return "", errors.Wrapf(ErrSecretNameInUse, name)
return "", errors.Wrapf(errSecretNameInUse, name)
}

secr := new(Secret)
Expand All @@ -152,7 +150,7 @@ func (s *SecretsManager) Store(name string, data []byte, driverType string, driv
newID = newID[0:secretIDLength]
_, err := s.lookupSecret(newID)
if err != nil {
if errors.Cause(err) == ErrNoSuchSecret {
if errors.Cause(err) == errNoSuchSecret {
secr.ID = newID
break
} else {
Expand Down Expand Up @@ -266,7 +264,7 @@ func (s *SecretsManager) LookupSecretData(nameOrID string) (*Secret, []byte, err
// validateSecretName checks if the secret name is valid.
func validateSecretName(name string) error {
if !secretNameRegexp.MatchString(name) || len(name) > 64 || strings.HasSuffix(name, "-") || strings.HasSuffix(name, ".") {
return errors.Wrapf(ErrInvalidSecretName, "only 64 [a-zA-Z0-9-_.] characters allowed, and the start and end character must be [a-zA-Z0-9]: %s", name)
return errors.Wrapf(errInvalidSecretName, "only 64 [a-zA-Z0-9-_.] characters allowed, and the start and end character must be [a-zA-Z0-9]: %s", name)
}
return nil
}
Expand All @@ -277,8 +275,8 @@ func getDriver(name string, opts map[string]string) (SecretsDriver, error) {
if path, ok := opts["path"]; ok {
return filedriver.NewDriver(path)
} else {
return nil, errors.Wrap(ErrInvalidDriverOpt, "need path for filedriver")
return nil, errors.Wrap(errInvalidDriverOpt, "need path for filedriver")
}
}
return nil, ErrInvalidDriver
return nil, errInvalidDriver
}
8 changes: 0 additions & 8 deletions pkg/secrets/secrets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"os"
"testing"

"github.com/pkg/errors"
"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -60,15 +59,12 @@ func TestAddSecretName(t *testing.T) {
// name too short
_, err = manager.Store("", []byte("mydata"), drivertype, opts)
require.Error(t, err)
require.Equal(t, errors.Cause(err), ErrInvalidSecretName)
// name too long
_, err = manager.Store("uatqsbssrapurkuqoapubpifvsrissslzjehalxcesbhpxcvhsozlptrmngrivaiz", []byte("mydata"), drivertype, opts)
require.Error(t, err)
require.Equal(t, errors.Cause(err), ErrInvalidSecretName)
// invalid chars
_, err = manager.Store("??", []byte("mydata"), drivertype, opts)
require.Error(t, err)
require.Equal(t, errors.Cause(err), ErrInvalidSecretName)
_, err = manager.Store("-a", []byte("mydata"), drivertype, opts)
require.Error(t, err)
_, err = manager.Store("a-", []byte("mydata"), drivertype, opts)
Expand Down Expand Up @@ -123,7 +119,6 @@ func TestAddSecretDupName(t *testing.T) {

_, err = manager.Store("mysecret", []byte("mydata"), drivertype, opts)
require.Error(t, err)
require.Equal(t, errors.Cause(err), ErrSecretNameInUse)
}

func TestAddSecretPrefix(t *testing.T) {
Expand Down Expand Up @@ -156,7 +151,6 @@ func TestRemoveSecret(t *testing.T) {

_, err = manager.lookupSecret("mysecret")
require.Error(t, err)
require.Equal(t, errors.Cause(err), ErrNoSuchSecret)

_, _, err = manager.LookupSecretData("mysecret")
require.Error(t, err)
Expand All @@ -169,7 +163,6 @@ func TestRemoveSecretNoExist(t *testing.T) {

_, err = manager.Delete("mysecret")
require.Error(t, err)
require.Equal(t, errors.Cause(err), ErrNoSuchSecret)
}

func TestLookupAllSecrets(t *testing.T) {
Expand Down Expand Up @@ -216,7 +209,6 @@ func TestInspectSecretBogus(t *testing.T) {

_, err = manager.Lookup("bogus")
require.Error(t, err)
require.Equal(t, errors.Cause(err), ErrNoSuchSecret)
}

func TestSecretList(t *testing.T) {
Expand Down
14 changes: 7 additions & 7 deletions pkg/secrets/secretsdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,21 +71,21 @@ func (s *SecretsManager) getNameAndID(nameOrID string) (name, id string, err err
name, id, err = s.getExactNameAndID(nameOrID)
if err == nil {
return name, id, nil
} else if errors.Cause(err) != ErrNoSuchSecret {
} else if errors.Cause(err) != errNoSuchSecret {
return "", "", err
}

// ID prefix may have been given, iterate through all IDs.
// ID and partial ID has a max lenth of 25, so we return if its greater than that.
if len(nameOrID) > secretIDLength {
return "", "", errors.Wrapf(ErrNoSuchSecret, "no secret with name or id %q", nameOrID)
return "", "", errors.Wrapf(errNoSuchSecret, "no secret with name or id %q", nameOrID)
}
exists := false
var foundID, foundName string
for id, name := range s.db.IDToName {
if strings.HasPrefix(id, nameOrID) {
if exists {
return "", "", errors.Wrapf(ErrAmbiguous, "more than one result secret with prefix %s", nameOrID)
return "", "", errors.Wrapf(errAmbiguous, "more than one result secret with prefix %s", nameOrID)
}
exists = true
foundID = id
Expand All @@ -96,7 +96,7 @@ func (s *SecretsManager) getNameAndID(nameOrID string) (name, id string, err err
if exists {
return foundName, foundID, nil
}
return "", "", errors.Wrapf(ErrNoSuchSecret, "no secret with name or id %q", nameOrID)
return "", "", errors.Wrapf(errNoSuchSecret, "no secret with name or id %q", nameOrID)
}

// getExactNameAndID takes a secret's name or ID and returns both its name and full ID.
Expand All @@ -115,15 +115,15 @@ func (s *SecretsManager) getExactNameAndID(nameOrID string) (name, id string, er
return name, id, nil
}

return "", "", errors.Wrapf(ErrNoSuchSecret, "no secret with name or id %q", nameOrID)
return "", "", errors.Wrapf(errNoSuchSecret, "no secret with name or id %q", nameOrID)
}

// exactSecretExists checks if the secret exists, given a name or ID
// Does not match partial name or IDs
func (s *SecretsManager) exactSecretExists(nameOrID string) (bool, error) {
_, _, err := s.getExactNameAndID(nameOrID)
if err != nil {
if errors.Cause(err) == ErrNoSuchSecret {
if errors.Cause(err) == errNoSuchSecret {
return false, nil
}
return false, err
Expand Down Expand Up @@ -158,7 +158,7 @@ func (s *SecretsManager) lookupSecret(nameOrID string) (*Secret, error) {
return &secret, nil
}

return nil, errors.Wrapf(ErrNoSuchSecret, "no secret with name or id %q", nameOrID)
return nil, errors.Wrapf(errNoSuchSecret, "no secret with name or id %q", nameOrID)
}

// Store creates a new secret in the secrets database.
Expand Down

0 comments on commit 7cfa80b

Please sign in to comment.