Add 'kpod history' command
Signed-off-by: umohnani8 <umohnani@redhat.com>
This commit is contained in:
parent
b4973e1006
commit
ad490708a4
6 changed files with 518 additions and 1 deletions
|
@ -41,6 +41,7 @@ It is currently in active development in the Kubernetes community through the [d
|
||||||
| ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
|
| ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
|
||||||
| [crio(8)](/docs/crio.8.md) | Enable OCI Kubernetes Container Runtime daemon |
|
| [crio(8)](/docs/crio.8.md) | Enable OCI Kubernetes Container Runtime daemon |
|
||||||
| [kpod(1)](/docs/kpod.1.md) | Simple management tool for pods and images |
|
| [kpod(1)](/docs/kpod.1.md) | Simple management tool for pods and images |
|
||||||
|
| [kpod-history(1)](/docs/kpod-history.1.md)] | Shows the history of an image |
|
||||||
| [kpod-images(1)](/docs/kpod-images.1.md) | List images in local storage |
|
| [kpod-images(1)](/docs/kpod-images.1.md) | List images in local storage |
|
||||||
| [kpod-pull(1)](/docs/kpod-pull.1.md) | Pull an image from a registry |
|
| [kpod-pull(1)](/docs/kpod-pull.1.md) | Pull an image from a registry |
|
||||||
| [kpod-rmi(1)](/docs/kpod-rmi.1.md) | Removes one or more images |
|
| [kpod-rmi(1)](/docs/kpod-rmi.1.md) | Removes one or more images |
|
||||||
|
|
353
cmd/kpod/history.go
Normal file
353
cmd/kpod/history.go
Normal file
|
@ -0,0 +1,353 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/Sirupsen/logrus"
|
||||||
|
is "github.com/containers/image/storage"
|
||||||
|
"github.com/containers/storage"
|
||||||
|
units "github.com/docker/go-units"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
createdByTruncLength = 45
|
||||||
|
idTruncLength = 13
|
||||||
|
)
|
||||||
|
|
||||||
|
// historyOutputParams stores info about each layer
|
||||||
|
type historyOutputParams struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Created *time.Time `json:"created"`
|
||||||
|
CreatedBy string `json:"createdby"`
|
||||||
|
Size int64 `json:"size"`
|
||||||
|
Comment string `json:"comment"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// historyOptions stores cli flag values
|
||||||
|
type historyOptions struct {
|
||||||
|
image string
|
||||||
|
human bool
|
||||||
|
noTrunc bool
|
||||||
|
quiet bool
|
||||||
|
format string
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
historyFlags = []cli.Flag{
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "human, H",
|
||||||
|
Usage: "Display sizes and dates in human readable format",
|
||||||
|
},
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "no-trunc",
|
||||||
|
Usage: "Do not truncate the output",
|
||||||
|
},
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "quiet, q",
|
||||||
|
Usage: "Display the numeric IDs only",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "format",
|
||||||
|
Usage: "Pretty-print history of the image using a Go template",
|
||||||
|
},
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "json",
|
||||||
|
Usage: "Print the history in JSON format",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
historyDescription = "Displays the history of an image. The information can be printed out in an easy to read, " +
|
||||||
|
"or user specified format, and can be truncated."
|
||||||
|
historyCommand = cli.Command{
|
||||||
|
Name: "history",
|
||||||
|
Usage: "Show history of a specified image",
|
||||||
|
Description: historyDescription,
|
||||||
|
Flags: historyFlags,
|
||||||
|
Action: historyCmd,
|
||||||
|
ArgsUsage: "",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func historyCmd(c *cli.Context) error {
|
||||||
|
store, err := getStore(c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
human := true
|
||||||
|
if c.IsSet("human") {
|
||||||
|
human = c.Bool("human")
|
||||||
|
}
|
||||||
|
noTruncate := false
|
||||||
|
if c.IsSet("no-trunc") {
|
||||||
|
noTruncate = c.Bool("no-trunc")
|
||||||
|
}
|
||||||
|
quiet := false
|
||||||
|
if c.IsSet("quiet") {
|
||||||
|
quiet = c.Bool("quiet")
|
||||||
|
}
|
||||||
|
json := false
|
||||||
|
if c.IsSet("json") {
|
||||||
|
json = c.Bool("json")
|
||||||
|
}
|
||||||
|
format := ""
|
||||||
|
if c.IsSet("format") {
|
||||||
|
format = c.String("format")
|
||||||
|
}
|
||||||
|
|
||||||
|
args := c.Args()
|
||||||
|
if len(args) == 0 {
|
||||||
|
logrus.Errorf("an image name must be specified")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if len(args) > 1 {
|
||||||
|
logrus.Errorf("Kpod history takes at most 1 argument")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
imgName := args[0]
|
||||||
|
|
||||||
|
opts := historyOptions{
|
||||||
|
image: imgName,
|
||||||
|
human: human,
|
||||||
|
noTrunc: noTruncate,
|
||||||
|
quiet: quiet,
|
||||||
|
format: format,
|
||||||
|
}
|
||||||
|
|
||||||
|
var history []byte
|
||||||
|
if json {
|
||||||
|
history, err = createJSON(store, opts)
|
||||||
|
fmt.Println(string(history))
|
||||||
|
} else {
|
||||||
|
if format == "" && !quiet {
|
||||||
|
outputHeading(noTruncate)
|
||||||
|
}
|
||||||
|
err = outputHistory(store, opts)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// outputHeader outputs the heading
|
||||||
|
func outputHeading(noTrunc bool) {
|
||||||
|
if !noTrunc {
|
||||||
|
fmt.Printf("%-12s\t\t%-16s\t\t%-45s\t\t", "IMAGE", "CREATED", "CREATED BY")
|
||||||
|
fmt.Printf("%-16s\t\t%s\n", "SIZE", "COMMENT")
|
||||||
|
} else {
|
||||||
|
fmt.Printf("%-64s\t%-18s\t%-60s\t", "IMAGE", "CREATED", "CREATED BY")
|
||||||
|
fmt.Printf("%-16s\t%s\n", "SIZE", "COMMENT")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// outputString outputs the information in historyOutputParams
|
||||||
|
func outputString(noTrunc, human bool, params historyOutputParams) {
|
||||||
|
var (
|
||||||
|
createdTime string
|
||||||
|
outputSize string
|
||||||
|
)
|
||||||
|
|
||||||
|
if human {
|
||||||
|
createdTime = outputHumanTime(params.Created) + " ago"
|
||||||
|
outputSize = units.HumanSize(float64(params.Size))
|
||||||
|
} else {
|
||||||
|
createdTime = outputTime(params.Created)
|
||||||
|
outputSize = strconv.FormatInt(params.Size, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !noTrunc {
|
||||||
|
fmt.Printf("%-12.12s\t\t%-16s\t\t%-45.45s\t\t", params.ID, createdTime, params.CreatedBy)
|
||||||
|
fmt.Printf("%-16s\t\t%s\n", outputSize, params.Comment)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("%-64s\t%-18s\t%-60s\t", params.ID, createdTime, params.CreatedBy)
|
||||||
|
fmt.Printf("%-16s\t%s\n\n", outputSize, params.Comment)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// outputWithTemplate is called when --format is given a template
|
||||||
|
func outputWithTemplate(format string, params historyOutputParams, human bool) error {
|
||||||
|
templ, err := template.New("history").Parse(format)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "error parsing template")
|
||||||
|
}
|
||||||
|
|
||||||
|
createdTime := outputTime(params.Created)
|
||||||
|
outputSize := strconv.FormatInt(params.Size, 10)
|
||||||
|
|
||||||
|
if human {
|
||||||
|
createdTime = outputHumanTime(params.Created) + " ago"
|
||||||
|
outputSize = units.HumanSize(float64(params.Size))
|
||||||
|
}
|
||||||
|
|
||||||
|
// templParams is used to store the info from params and the time and
|
||||||
|
// size that have been converted to type string for when the human flag
|
||||||
|
// is set
|
||||||
|
templParams := struct {
|
||||||
|
ID string
|
||||||
|
Created string
|
||||||
|
CreatedBy string
|
||||||
|
Size string
|
||||||
|
Comment string
|
||||||
|
}{
|
||||||
|
params.ID,
|
||||||
|
createdTime,
|
||||||
|
params.CreatedBy,
|
||||||
|
outputSize,
|
||||||
|
params.Comment,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = templ.Execute(os.Stdout, templParams); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// outputTime displays the time stamp in "2017-06-20T20:24:10Z" format
|
||||||
|
func outputTime(tm *time.Time) string {
|
||||||
|
return tm.Format(time.RFC3339)
|
||||||
|
}
|
||||||
|
|
||||||
|
// outputHumanTime displays the time elapsed since creation
|
||||||
|
func outputHumanTime(tm *time.Time) string {
|
||||||
|
return units.HumanDuration(time.Since(*tm))
|
||||||
|
}
|
||||||
|
|
||||||
|
// createJSON retrieves the history of the image and returns a JSON object
|
||||||
|
func createJSON(store storage.Store, opts historyOptions) ([]byte, error) {
|
||||||
|
var (
|
||||||
|
size int64
|
||||||
|
img *storage.Image
|
||||||
|
imageID string
|
||||||
|
layerAll []historyOutputParams
|
||||||
|
)
|
||||||
|
|
||||||
|
ref, err := is.Transport.ParseStoreReference(store, opts.image)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Errorf("error parsing reference to image %q: %v", opts.image, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
img, err = is.Transport.GetStoreImage(store, ref)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Errorf("no such image %q: %v", opts.image, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
systemContext := getSystemContext("")
|
||||||
|
|
||||||
|
src, err := ref.NewImage(systemContext)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Errorf("error instantiating image %q: %v", opts.image, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
oci, err := src.OCIConfig()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
history := oci.History
|
||||||
|
layers := src.LayerInfos()
|
||||||
|
count := 1
|
||||||
|
// iterating backwards to get newwest to oldest
|
||||||
|
for i := len(history) - 1; i >= 0; i-- {
|
||||||
|
if i == len(history)-1 {
|
||||||
|
imageID = img.ID
|
||||||
|
} else {
|
||||||
|
imageID = "<missing>"
|
||||||
|
}
|
||||||
|
|
||||||
|
if !history[i].EmptyLayer {
|
||||||
|
size = layers[len(layers)-count].Size
|
||||||
|
count++
|
||||||
|
} else {
|
||||||
|
size = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
params := historyOutputParams{
|
||||||
|
ID: imageID,
|
||||||
|
Created: history[i].Created,
|
||||||
|
CreatedBy: history[i].CreatedBy,
|
||||||
|
Size: size,
|
||||||
|
Comment: history[i].Comment,
|
||||||
|
}
|
||||||
|
|
||||||
|
layerAll = append(layerAll, params)
|
||||||
|
}
|
||||||
|
|
||||||
|
output, err := json.MarshalIndent(layerAll, "", "\t\t")
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Errorf("error marshalling to JSON: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = src.Close(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return output, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// outputHistory gets the history of the image from the JSON object
|
||||||
|
// and pretty prints it to the screen
|
||||||
|
func outputHistory(store storage.Store, opts historyOptions) error {
|
||||||
|
var (
|
||||||
|
outputCreatedBy string
|
||||||
|
imageID string
|
||||||
|
history []historyOutputParams
|
||||||
|
)
|
||||||
|
|
||||||
|
raw, err := createJSON(store, opts)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Errorf("error creating JSON: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = json.Unmarshal(raw, &history); err != nil {
|
||||||
|
return errors.Errorf("error Unmarshalling JSON: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(history); i++ {
|
||||||
|
imageID = history[i].ID
|
||||||
|
|
||||||
|
outputCreatedBy = strings.Join(strings.Fields(history[i].CreatedBy), " ")
|
||||||
|
if !opts.noTrunc && len(outputCreatedBy) > createdByTruncLength {
|
||||||
|
outputCreatedBy = outputCreatedBy[:createdByTruncLength-3] + "..."
|
||||||
|
}
|
||||||
|
|
||||||
|
if !opts.noTrunc && i == 0 {
|
||||||
|
imageID = history[i].ID[:idTruncLength]
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.quiet {
|
||||||
|
if !opts.noTrunc {
|
||||||
|
fmt.Printf("%-12.12s\n", imageID)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("%-s\n", imageID)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
params := historyOutputParams{
|
||||||
|
ID: imageID,
|
||||||
|
Created: history[i].Created,
|
||||||
|
CreatedBy: outputCreatedBy,
|
||||||
|
Size: history[i].Size,
|
||||||
|
Comment: history[i].Comment,
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(opts.format) > 0 {
|
||||||
|
if err = outputWithTemplate(opts.format, params, opts.human); err != nil {
|
||||||
|
return errors.Errorf("error outputing with template: %v", err)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
outputString(opts.noTrunc, opts.human, params)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -28,6 +28,7 @@ func main() {
|
||||||
tagCommand,
|
tagCommand,
|
||||||
versionCommand,
|
versionCommand,
|
||||||
pullCommand,
|
pullCommand,
|
||||||
|
historyCommand,
|
||||||
}
|
}
|
||||||
app.Flags = []cli.Flag{
|
app.Flags = []cli.Flag{
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
|
|
|
@ -93,6 +93,28 @@ _kpod_pull() {
|
||||||
_complete_ "$options_with_args" "$boolean_options"
|
_complete_ "$options_with_args" "$boolean_options"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_kpod_history() {
|
||||||
|
local options_with_args="
|
||||||
|
--format
|
||||||
|
"
|
||||||
|
local boolean_options="
|
||||||
|
--human -H
|
||||||
|
--no-trunc
|
||||||
|
--quiet -q
|
||||||
|
--json
|
||||||
|
"
|
||||||
|
_complete_ "$options_with_args" "$boolean_options"
|
||||||
|
|
||||||
|
case "$cur" in
|
||||||
|
-*)
|
||||||
|
COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
__kpod_list_images
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
_kpod_kpod() {
|
_kpod_kpod() {
|
||||||
local options_with_args="
|
local options_with_args="
|
||||||
"
|
"
|
||||||
|
@ -106,6 +128,7 @@ _kpod_kpod() {
|
||||||
tag
|
tag
|
||||||
version
|
version
|
||||||
pull
|
pull
|
||||||
|
history
|
||||||
"
|
"
|
||||||
|
|
||||||
case "$prev" in
|
case "$prev" in
|
||||||
|
|
69
docs/kpod-history.1.md
Normal file
69
docs/kpod-history.1.md
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
% kpod(8) # kpod-history - Simple tool to view the history of an image
|
||||||
|
% Urvashi Mohnani
|
||||||
|
% JULY 2017
|
||||||
|
# NAME
|
||||||
|
kpod-history - Shows the history of an image.
|
||||||
|
|
||||||
|
# SYNOPSIS
|
||||||
|
**kpod history [OPTIONS] IMAGE[:TAG|DIGEST]**
|
||||||
|
|
||||||
|
# DESCRIPTION
|
||||||
|
**kpod history** displays the history of an image by printing out information
|
||||||
|
about each layer used in the image. The information printed out for each layer
|
||||||
|
include Created (time and date), Created By, Size, and Comment. The output can
|
||||||
|
be truncated or not using the **--no-trunc** flag. If the **--human** flag is
|
||||||
|
set, the time of creation and size are printed out in a human readable format.
|
||||||
|
The **--quiet** flag displays the ID of the image only when set and the **--format**
|
||||||
|
flag is used to print the information using the Go template provided by the user.
|
||||||
|
|
||||||
|
Valid placeholders for the Go template are listed below:
|
||||||
|
| **Placeholder** | **Description** |
|
||||||
|
|-----------------|------------------------------------------------------------------------------|
|
||||||
|
| .ID | Image ID |
|
||||||
|
| .Created | if **--human**, time elapsed since creation, otherwise time stamp of creation|
|
||||||
|
| .CreatedBy | Command used to create the layer |
|
||||||
|
| .Size | Size of layer on disk |
|
||||||
|
| .Comment | Comment for the layer |
|
||||||
|
|
||||||
|
**kpod [GLOBAL OPTIONS]**
|
||||||
|
|
||||||
|
**kpod [GLOBAL OPTIONS] history [OPTIONS]**
|
||||||
|
|
||||||
|
# GLOBAL OPTIONS
|
||||||
|
|
||||||
|
**--help, -h**
|
||||||
|
Print usage statement
|
||||||
|
|
||||||
|
# OPTIONS
|
||||||
|
|
||||||
|
**--human, -H**
|
||||||
|
Display sizes and dates in human readable format
|
||||||
|
|
||||||
|
**--no-trunc**
|
||||||
|
Do not truncate the output
|
||||||
|
|
||||||
|
**--quiet, -q**
|
||||||
|
Print the numeric IDs only
|
||||||
|
|
||||||
|
**--format**
|
||||||
|
Pretty-print history of the image using a Go template
|
||||||
|
|
||||||
|
**--json**
|
||||||
|
Print the history in JSON form
|
||||||
|
|
||||||
|
# COMMANDS
|
||||||
|
|
||||||
|
**kpod history debian**
|
||||||
|
|
||||||
|
**kpod history --no-trunc=true --human=false debian**
|
||||||
|
|
||||||
|
**kpod history --format "{{.ID}} {{.Created}}" debian**
|
||||||
|
|
||||||
|
## history
|
||||||
|
Show the history of an image
|
||||||
|
|
||||||
|
# SEE ALSO
|
||||||
|
kpod(1), crio(8), crio.conf(5)
|
||||||
|
|
||||||
|
# HISTORY
|
||||||
|
July 2017, Originally compiled by Urvashi Mohnani <umohnani@redhat.com>
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
load helpers
|
load helpers
|
||||||
|
|
||||||
|
IMAGE="alpine"
|
||||||
ROOT="$TESTDIR/crio"
|
ROOT="$TESTDIR/crio"
|
||||||
RUNROOT="$TESTDIR/crio-run"
|
RUNROOT="$TESTDIR/crio-run"
|
||||||
KPOD_OPTIONS="--root $ROOT --runroot $RUNROOT --storage-driver vfs"
|
KPOD_OPTIONS="--root $ROOT --runroot $RUNROOT --storage-driver vfs"
|
||||||
|
@ -16,30 +17,40 @@ KPOD_OPTIONS="--root $ROOT --runroot $RUNROOT --storage-driver vfs"
|
||||||
run ${KPOD_BINARY} $KPOD_OPTIONS pull debian:6.0.10
|
run ${KPOD_BINARY} $KPOD_OPTIONS pull debian:6.0.10
|
||||||
echo "$output"
|
echo "$output"
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
|
run ${KPOD_BINARY} $KPOD_OPTIONS rmi debian:6.0.10
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "kpod pull from docker without tag" {
|
@test "kpod pull from docker without tag" {
|
||||||
run ${KPOD_BINARY} $KPOD_OPTIONS pull debian
|
run ${KPOD_BINARY} $KPOD_OPTIONS pull debian
|
||||||
echo "$output"
|
echo "$output"
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
|
run ${KPOD_BINARY} $KPOD_OPTIONS rmi debian
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "kpod pull from a non-docker registry with tag" {
|
@test "kpod pull from a non-docker registry with tag" {
|
||||||
run ${KPOD_BINARY} $KPOD_OPTIONS pull registry.fedoraproject.org/fedora:rawhide
|
run ${KPOD_BINARY} $KPOD_OPTIONS pull registry.fedoraproject.org/fedora:rawhide
|
||||||
echo "$output"
|
echo "$output"
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
|
run ${KPOD_BINARY} $KPOD_OPTIONS rmi registry.fedoraproject.org/fedora:rawhide
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "kpod pull from a non-docker registry without tag" {
|
@test "kpod pull from a non-docker registry without tag" {
|
||||||
run ${KPOD_BINARY} $KPOD_OPTIONS pull registry.fedoraproject.org/fedora
|
run ${KPOD_BINARY} $KPOD_OPTIONS pull registry.fedoraproject.org/fedora
|
||||||
echo "$output"
|
echo "$output"
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
|
run ${KPOD_BINARY} $KPOD_OPTIONS rmi registry.fedoraproject.org/fedora
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "kpod pull using digest" {
|
@test "kpod pull using digest" {
|
||||||
run ${KPOD_BINARY} $KPOD_OPTIONS pull debian@sha256:7d067f77d2ae5a23fe6920f8fbc2936c4b0d417e9d01b26372561860750815f0
|
run ${KPOD_BINARY} $KPOD_OPTIONS pull alpine@sha256:1072e499f3f655a032e88542330cf75b02e7bdf673278f701d7ba61629ee3ebe
|
||||||
echo "$output"
|
echo "$output"
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
|
run ${KPOD_BINARY} $KPOD_OPTIONS rmi alpine:latest
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "kpod pull from a non existent image" {
|
@test "kpod pull from a non existent image" {
|
||||||
|
@ -47,3 +58,62 @@ KPOD_OPTIONS="--root $ROOT --runroot $RUNROOT --storage-driver vfs"
|
||||||
echo "$output"
|
echo "$output"
|
||||||
[ "$status" -ne 0 ]
|
[ "$status" -ne 0 ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "kpod history default" {
|
||||||
|
run ${KPOD_BINARY} ${KPOD_OPTIONS} pull $IMAGE
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
run ${KPOD_BINARY} ${KPOD_OPTIONS} history $IMAGE
|
||||||
|
echo "$output"
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
run ${KPOD_BINARY} $KPOD_OPTIONS rmi $IMAGE
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "kpod history with format" {
|
||||||
|
run ${KPOD_BINARY} ${KPOD_OPTIONS} pull $IMAGE
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
run ${KPOD_BINARY} ${KPOD_OPTIONS} history --format "{{.ID}} {{.Created}}" $IMAGE
|
||||||
|
echo "$output"
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
run ${KPOD_BINARY} $KPOD_OPTIONS rmi $IMAGE
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "kpod history human flag" {
|
||||||
|
run ${KPOD_BINARY} ${KPOD_OPTIONS} pull $IMAGE
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
run ${KPOD_BINARY} ${KPOD_OPTIONS} history --human=false $IMAGE
|
||||||
|
echo "$output"
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
run ${KPOD_BINARY} $KPOD_OPTIONS rmi $IMAGE
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "kpod history quiet flag" {
|
||||||
|
run ${KPOD_BINARY} ${KPOD_OPTIONS} pull $IMAGE
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
run ${KPOD_BINARY} ${KPOD_OPTIONS} history -q $IMAGE
|
||||||
|
echo "$output"
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
run ${KPOD_BINARY} $KPOD_OPTIONS rmi $IMAGE
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "kpod history no-trunc flag" {
|
||||||
|
run ${KPOD_BINARY} ${KPOD_OPTIONS} pull $IMAGE
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
run ${KPOD_BINARY} ${KPOD_OPTIONS} history --no-trunc $IMAGE
|
||||||
|
echo "$output"
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
run ${KPOD_BINARY} $KPOD_OPTIONS rmi $IMAGE
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "kpod history json flag" {
|
||||||
|
run ${KPOD_BINARY} ${KPOD_OPTIONS} pull $IMAGE
|
||||||
|
run bash -c "${KPOD_BINARY} ${KPOD_OPTIONS} history --json $IMAGE | python -m json.tool"
|
||||||
|
echo "$output"
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
run ${KPOD_BINARY} $KPOD_OPTIONS rmi $IMAGE
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue