Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

auto-update: make output more user friendly #10880

Merged
merged 6 commits into from
Jul 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 91 additions & 6 deletions cmd/podman/auto-update.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
package main

import (
"encoding/json"
"fmt"
"os"
"strings"

"github.com/containers/common/pkg/auth"
"github.com/containers/common/pkg/completion"
"github.com/containers/common/pkg/report"
"github.com/containers/podman/v3/cmd/podman/common"
"github.com/containers/podman/v3/cmd/podman/registry"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/errorhandling"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)

type cliAutoUpdateOptions struct {
entities.AutoUpdateOptions
format string
}

var (
autoUpdateOptions = entities.AutoUpdateOptions{}
autoUpdateOptions = cliAutoUpdateOptions{}
autoUpdateDescription = `Auto update containers according to their auto-update policy.
Auto-update policies are specified with the "io.containers.autoupdate" label.
Expand Down Expand Up @@ -42,18 +52,93 @@ func init() {
authfileFlagName := "authfile"
flags.StringVar(&autoUpdateOptions.Authfile, authfileFlagName, auth.GetDefaultAuthFile(), "Path to the authentication file. Use REGISTRY_AUTH_FILE environment variable to override")
_ = autoUpdateCommand.RegisterFlagCompletionFunc(authfileFlagName, completion.AutocompleteDefault)

flags.StringVar(&autoUpdateOptions.format, "format", "", "Change the output format to JSON or a Go template")
_ = autoUpdateCommand.RegisterFlagCompletionFunc("format", common.AutocompleteFormat(autoUpdateOutput{}))
}

func autoUpdate(cmd *cobra.Command, args []string) error {
if len(args) > 0 {
// Backwards compat. System tests expect this error string.
return errors.Errorf("`%s` takes no arguments", cmd.CommandPath())
}
report, failures := registry.ContainerEngine().AutoUpdate(registry.GetContext(), autoUpdateOptions)
if report != nil {
for _, unit := range report.Units {
fmt.Println(unit)
}

allReports, failures := registry.ContainerEngine().AutoUpdate(registry.GetContext(), autoUpdateOptions.AutoUpdateOptions)
if allReports == nil {
return errorhandling.JoinErrors(failures)
}

if err := writeTemplate(allReports, autoUpdateOptions.format); err != nil {
failures = append(failures, err)
}

return errorhandling.JoinErrors(failures)
}

type autoUpdateOutput struct {
Unit string
Container string
ContainerName string
ContainerID string
Image string
Policy string
Updated string
}

func reportsToOutput(allReports []*entities.AutoUpdateReport) []autoUpdateOutput {
output := make([]autoUpdateOutput, len(allReports))
for i, r := range allReports {
output[i] = autoUpdateOutput{
Unit: r.SystemdUnit,
Container: fmt.Sprintf("%s (%s)", r.ContainerID[:12], r.ContainerName),
ContainerName: r.ContainerName,
ContainerID: r.ContainerID,
Image: r.ImageName,
Policy: r.Policy,
Updated: r.Updated,
}
}
return output
}

func writeTemplate(allReports []*entities.AutoUpdateReport, inputFormat string) error {
var format string
var printHeader bool

output := reportsToOutput(allReports)
switch inputFormat {
case "":
rows := []string{"{{.Unit}}", "{{.Container}}", "{{.Image}}", "{{.Policy}}", "{{.Updated}}"}
format = "{{range . }}" + strings.Join(rows, "\t") + "\n{{end -}}"
printHeader = true
case "json":
prettyJSON, err := json.MarshalIndent(output, "", " ")
if err != nil {
return err
}
fmt.Println(string(prettyJSON))
return nil
default:
format = "{{range . }}" + inputFormat + "\n{{end -}}"
}

tmpl, err := report.NewTemplate("auto-update").Parse(format)
if err != nil {
return err
}

w, err := report.NewWriterDefault(os.Stdout)
if err != nil {
return err
}
defer w.Flush()

if printHeader {
headers := report.Headers(autoUpdateOutput{}, nil)
if err := tmpl.Execute(w, headers); err != nil {
return err
}
}

return tmpl.Execute(w, output)
}
24 changes: 20 additions & 4 deletions docs/source/markdown/podman-auto-update.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,22 @@ If the authorization state is not found there, `$HOME/.docker/config.json` is ch

Note: There is also the option to override the default path of the authentication file by setting the `REGISTRY_AUTH_FILE` environment variable. This can be done with **export REGISTRY_AUTH_FILE=_path_**.

#### **--format**=*format*

Change the default output format. This can be of a supported type like 'json' or a Go template.
Valid placeholders for the Go template are listed below:

| **Placeholder** | **Description** |
| --------------- | -------------------------------------- |
| .Unit | Name of the systemd unit |
| .ContainerName | Name of the container |
| .ContainerID | ID of the container |
| .Container | ID and name of the container |
| .Image | Name of the image |
| .Policy | Auto-update policy of the container |
| .Updated | Update status: true,false,failed |


## EXAMPLES
Autoupdate with registry policy

Expand All @@ -53,7 +69,7 @@ bc219740a210455fa27deacc96d50a9e20516492f1417507c13ce1533dbdcd9d
### Generate a systemd unit for this container
$ podman generate systemd --new --files bc219740a210455fa27deacc96d50a9e20516492f1417507c13ce1533dbdcd9d
/home/user/containers/libpod/container-bc219740a210455fa27deacc96d50a9e20516492f1417507c13ce1533dbdcd9d.service
/home/user/container-bc219740a210455fa27deacc96d50a9e20516492f1417507c13ce1533dbdcd9d.service
### Load the new systemd unit and start it
$ mv ./container-bc219740a210455fa27deacc96d50a9e20516492f1417507c13ce1533dbdcd9d.service ~/.config/systemd/user
Expand All @@ -67,7 +83,7 @@ $ systemctl --user start container-bc219740a210455fa27deacc96d50a9e20516492f1417
### Auto-update the container
$ podman auto-update
container-bc219740a210455fa27deacc96d50a9e20516492f1417507c13ce1533dbdcd9d.service
[...]
```

Autoupdate with local policy
Expand All @@ -80,7 +96,7 @@ be0889fd06f252a2e5141b37072c6bada68563026cb2b2649f53394d87ccc338
### Generate a systemd unit for this container
$ podman generate systemd --new --files be0889fd06f252a2e5141b37072c6bada68563026cb2b2649f53394d87ccc338
/home/user/containers/libpod/container-be0889fd06f252a2e5141b37072c6bada68563026cb2b2649f53394d87ccc338.service
/home/user/container-be0889fd06f252a2e5141b37072c6bada68563026cb2b2649f53394d87ccc338.service
### Load the new systemd unit and start it
$ mv ./container-be0889fd06f252a2e5141b37072c6bada68563026cb2b2649f53394d87ccc338.service ~/.config/systemd/user
Expand All @@ -102,7 +118,7 @@ $ podman commit --change CMD=/bin/bash inspiring_galileo busybox:latest
### Auto-update the container
$ podman auto-update
container-be0889fd06f252a2e5141b37072c6bada68563026cb2b2649f53394d87ccc338.service
[...]
```

## SEE ALSO
Expand Down
Loading