Skip to content

Commit

Permalink
Merge pull request containers#9125 from ashley-cui/secretswiring
Browse files Browse the repository at this point in the history
Implement Secrets
  • Loading branch information
openshift-merge-robot authored Feb 9, 2021
2 parents 9da4169 + 832a69b commit f98605e
Show file tree
Hide file tree
Showing 58 changed files with 2,962 additions and 7 deletions.
37 changes: 37 additions & 0 deletions cmd/podman/common/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,28 @@ func getImages(cmd *cobra.Command, toComplete string) ([]string, cobra.ShellComp
return suggestions, cobra.ShellCompDirectiveNoFileComp
}

func getSecrets(cmd *cobra.Command, toComplete string) ([]string, cobra.ShellCompDirective) {
suggestions := []string{}

engine, err := setupContainerEngine(cmd)
if err != nil {
cobra.CompErrorln(err.Error())
return nil, cobra.ShellCompDirectiveNoFileComp
}
secrets, err := engine.SecretList(registry.GetContext())
if err != nil {
cobra.CompErrorln(err.Error())
return nil, cobra.ShellCompDirectiveNoFileComp
}

for _, s := range secrets {
if strings.HasPrefix(s.Spec.Name, toComplete) {
suggestions = append(suggestions, s.Spec.Name)
}
}
return suggestions, cobra.ShellCompDirectiveNoFileComp
}

func getRegistries() ([]string, cobra.ShellCompDirective) {
regs, err := registries.GetRegistries()
if err != nil {
Expand Down Expand Up @@ -412,6 +434,21 @@ func AutocompleteVolumes(cmd *cobra.Command, args []string, toComplete string) (
return getVolumes(cmd, toComplete)
}

// AutocompleteSecrets - Autocomplete secrets.
func AutocompleteSecrets(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if !validCurrentCmdLine(cmd, args, toComplete) {
return nil, cobra.ShellCompDirectiveNoFileComp
}
return getSecrets(cmd, toComplete)
}

func AutocompleteSecretCreate(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if len(args) == 1 {
return nil, cobra.ShellCompDirectiveDefault
}
return nil, cobra.ShellCompDirectiveNoFileComp
}

// AutocompleteImages - Autocomplete images.
func AutocompleteImages(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if !validCurrentCmdLine(cmd, args, toComplete) {
Expand Down
8 changes: 8 additions & 0 deletions cmd/podman/common/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,14 @@ func DefineCreateFlags(cmd *cobra.Command, cf *ContainerCLIOpts) {
)
_ = cmd.RegisterFlagCompletionFunc(sdnotifyFlagName, AutocompleteSDNotify)

secretFlagName := "secret"
createFlags.StringArrayVar(
&cf.Secrets,
secretFlagName, []string{},
"Add secret to container",
)
_ = cmd.RegisterFlagCompletionFunc(secretFlagName, AutocompleteSecrets)

securityOptFlagName := "security-opt"
createFlags.StringArrayVar(
&cf.SecurityOpt,
Expand Down
1 change: 1 addition & 0 deletions cmd/podman/common/create_opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ type ContainerCLIOpts struct {
Replace bool
Rm bool
RootFS bool
Secrets []string
SecurityOpt []string
SdNotifyMode string
ShmSize string
Expand Down
1 change: 1 addition & 0 deletions cmd/podman/common/specgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,7 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string
s.StopTimeout = &c.StopTimeout
s.Timezone = c.Timezone
s.Umask = c.Umask
s.Secrets = c.Secrets

return nil
}
Expand Down
1 change: 1 addition & 0 deletions cmd/podman/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
_ "github.com/containers/podman/v2/cmd/podman/play"
_ "github.com/containers/podman/v2/cmd/podman/pods"
"github.com/containers/podman/v2/cmd/podman/registry"
_ "github.com/containers/podman/v2/cmd/podman/secrets"
_ "github.com/containers/podman/v2/cmd/podman/system"
_ "github.com/containers/podman/v2/cmd/podman/system/connection"
_ "github.com/containers/podman/v2/cmd/podman/volumes"
Expand Down
80 changes: 80 additions & 0 deletions cmd/podman/secrets/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package secrets

import (
"context"
"errors"
"fmt"
"io"
"os"

"github.com/containers/common/pkg/completion"
"github.com/containers/podman/v2/cmd/podman/common"
"github.com/containers/podman/v2/cmd/podman/registry"
"github.com/containers/podman/v2/pkg/domain/entities"
"github.com/spf13/cobra"
)

var (
createCmd = &cobra.Command{
Use: "create [options] SECRET FILE|-",
Short: "Create a new secret",
Long: "Create a secret. Input can be a path to a file or \"-\" (read from stdin). Default driver is file (unencrypted).",
RunE: create,
Args: cobra.ExactArgs(2),
Example: `podman secret create mysecret /path/to/secret
printf "secretdata" | podman secret create mysecret -`,
ValidArgsFunction: common.AutocompleteSecretCreate,
}
)

var (
createOpts = entities.SecretCreateOptions{}
)

func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
Command: createCmd,
Parent: secretCmd,
})

flags := createCmd.Flags()

driverFlagName := "driver"
flags.StringVar(&createOpts.Driver, driverFlagName, "file", "Specify secret driver")
_ = createCmd.RegisterFlagCompletionFunc(driverFlagName, completion.AutocompleteNone)
}

func create(cmd *cobra.Command, args []string) error {
name := args[0]

var err error
path := args[1]

var reader io.Reader
if path == "-" || path == "/dev/stdin" {
stat, err := os.Stdin.Stat()
if err != nil {
return err
}
if (stat.Mode() & os.ModeNamedPipe) == 0 {
return errors.New("if `-` is used, data must be passed into stdin")

}
reader = os.Stdin
} else {
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
reader = file
}

report, err := registry.ContainerEngine().SecretCreate(context.Background(), name, reader, createOpts)
if err != nil {
return err
}
fmt.Println(report.ID)
return nil
}
82 changes: 82 additions & 0 deletions cmd/podman/secrets/inspect.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package secrets

import (
"context"
"encoding/json"
"fmt"
"html/template"
"os"
"text/tabwriter"

"github.com/containers/common/pkg/report"
"github.com/containers/podman/v2/cmd/podman/common"
"github.com/containers/podman/v2/cmd/podman/parse"
"github.com/containers/podman/v2/cmd/podman/registry"
"github.com/containers/podman/v2/pkg/domain/entities"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)

var (
inspectCmd = &cobra.Command{
Use: "inspect [options] SECRET [SECRET...]",
Short: "Inspect a secret",
Long: "Display detail information on one or more secrets",
RunE: inspect,
Example: "podman secret inspect MYSECRET",
Args: cobra.MinimumNArgs(1),
ValidArgsFunction: common.AutocompleteSecrets,
}
)

var format string

func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
Command: inspectCmd,
Parent: secretCmd,
})
flags := inspectCmd.Flags()
formatFlagName := "format"
flags.StringVar(&format, formatFlagName, "", "Format volume output using Go template")
_ = inspectCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteJSONFormat)
}

func inspect(cmd *cobra.Command, args []string) error {
inspected, errs, _ := registry.ContainerEngine().SecretInspect(context.Background(), args)

// always print valid list
if len(inspected) == 0 {
inspected = []*entities.SecretInfoReport{}
}

if cmd.Flags().Changed("format") {
row := report.NormalizeFormat(format)
formatted := parse.EnforceRange(row)

tmpl, err := template.New("inspect secret").Parse(formatted)
if err != nil {
return err
}
w := tabwriter.NewWriter(os.Stdout, 12, 2, 2, ' ', 0)
defer w.Flush()
tmpl.Execute(w, inspected)
} else {
buf, err := json.MarshalIndent(inspected, "", " ")
if err != nil {
return err
}
fmt.Println(string(buf))
}

if len(errs) > 0 {
if len(errs) > 1 {
for _, err := range errs[1:] {
fmt.Fprintf(os.Stderr, "error inspecting secret: %v\n", err)
}
}
return errors.Errorf("error inspecting secret: %v", errs[0])
}
return nil
}
99 changes: 99 additions & 0 deletions cmd/podman/secrets/list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package secrets

import (
"context"
"html/template"
"os"
"text/tabwriter"
"time"

"github.com/containers/common/pkg/completion"
"github.com/containers/common/pkg/report"
"github.com/containers/podman/v2/cmd/podman/common"
"github.com/containers/podman/v2/cmd/podman/parse"
"github.com/containers/podman/v2/cmd/podman/registry"
"github.com/containers/podman/v2/cmd/podman/validate"
"github.com/containers/podman/v2/pkg/domain/entities"
"github.com/docker/go-units"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)

var (
lsCmd = &cobra.Command{
Use: "ls [options]",
Aliases: []string{"list"},
Short: "List secrets",
RunE: ls,
Example: "podman secret ls",
Args: validate.NoArgs,
ValidArgsFunction: completion.AutocompleteNone,
}
listFlag = listFlagType{}
)

type listFlagType struct {
format string
noHeading bool
}

func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
Command: lsCmd,
Parent: secretCmd,
})

flags := lsCmd.Flags()
formatFlagName := "format"
flags.StringVar(&listFlag.format, formatFlagName, "{{.ID}}\t{{.Name}}\t{{.Driver}}\t{{.CreatedAt}}\t{{.UpdatedAt}}\t\n", "Format volume output using Go template")
_ = lsCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteJSONFormat)

}

func ls(cmd *cobra.Command, args []string) error {
responses, err := registry.ContainerEngine().SecretList(context.Background())
if err != nil {
return err
}
listed := make([]*entities.SecretListReport, 0, len(responses))
for _, response := range responses {
listed = append(listed, &entities.SecretListReport{
ID: response.ID,
Name: response.Spec.Name,
CreatedAt: units.HumanDuration(time.Since(response.CreatedAt)) + " ago",
UpdatedAt: units.HumanDuration(time.Since(response.UpdatedAt)) + " ago",
Driver: response.Spec.Driver.Name,
})

}
return outputTemplate(cmd, listed)
}

func outputTemplate(cmd *cobra.Command, responses []*entities.SecretListReport) error {
headers := report.Headers(entities.SecretListReport{}, map[string]string{
"CreatedAt": "CREATED",
"UpdatedAt": "UPDATED",
})

row := report.NormalizeFormat(listFlag.format)
format := parse.EnforceRange(row)

tmpl, err := template.New("list secret").Parse(format)
if err != nil {
return err
}
w := tabwriter.NewWriter(os.Stdout, 12, 2, 2, ' ', 0)
defer w.Flush()

if cmd.Flags().Changed("format") && !parse.HasTable(listFlag.format) {
listFlag.noHeading = true
}

if !listFlag.noHeading {
if err := tmpl.Execute(w, headers); err != nil {
return errors.Wrapf(err, "failed to write report column headers")
}
}
return tmpl.Execute(w, responses)
}
Loading

0 comments on commit f98605e

Please sign in to comment.