commit
e1c0508fec
7 changed files with 194 additions and 0 deletions
47
cmd/kpod/common.go
Normal file
47
cmd/kpod/common.go
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
is "github.com/containers/image/storage"
|
||||||
|
"github.com/containers/storage"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getStore(c *cli.Context) (storage.Store, error) {
|
||||||
|
options := storage.DefaultStoreOptions
|
||||||
|
if c.GlobalIsSet("storage-driver") {
|
||||||
|
options.GraphDriverName = c.GlobalString("storage-driver")
|
||||||
|
}
|
||||||
|
if c.GlobalIsSet("storage-opt") {
|
||||||
|
opts := c.GlobalStringSlice("storage-opt")
|
||||||
|
if len(opts) > 0 {
|
||||||
|
options.GraphDriverOptions = opts
|
||||||
|
}
|
||||||
|
}
|
||||||
|
store, err := storage.GetStore(options)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
is.Transport.SetStore(store)
|
||||||
|
return store, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func findImage(store storage.Store, image string) (*storage.Image, error) {
|
||||||
|
var img *storage.Image
|
||||||
|
ref, err := is.Transport.ParseStoreReference(store, image)
|
||||||
|
if err == nil {
|
||||||
|
img, err = is.Transport.GetStoreImage(store, ref)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
img2, err2 := store.Image(image)
|
||||||
|
if err2 != nil {
|
||||||
|
if ref == nil {
|
||||||
|
return nil, errors.Wrapf(err, "error parsing reference to image %q", image)
|
||||||
|
}
|
||||||
|
return nil, errors.Wrapf(err, "unable to locate image %q", image)
|
||||||
|
}
|
||||||
|
img = img2
|
||||||
|
}
|
||||||
|
return img, nil
|
||||||
|
|
||||||
|
}
|
32
cmd/kpod/common_test.go
Normal file
32
cmd/kpod/common_test.go
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/user"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"flag"
|
||||||
|
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetStore(t *testing.T) {
|
||||||
|
u, err := user.Current()
|
||||||
|
if err != nil {
|
||||||
|
t.Log("Could not determine user. Running as root may cause tests to fail")
|
||||||
|
} else if u.Uid != "0" {
|
||||||
|
t.Fatal("tests will fail unless run as root")
|
||||||
|
}
|
||||||
|
|
||||||
|
set := flag.NewFlagSet("test", 0)
|
||||||
|
globalSet := flag.NewFlagSet("test", 0)
|
||||||
|
globalSet.String("root", "", "path to the root directory in which data, including images, is stored")
|
||||||
|
globalCtx := cli.NewContext(nil, globalSet, nil)
|
||||||
|
command := cli.Command{Name: "imagesCommand"}
|
||||||
|
c := cli.NewContext(nil, set, globalCtx)
|
||||||
|
c.Command = command
|
||||||
|
|
||||||
|
_, err = getStore(c)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,6 +18,7 @@ func main() {
|
||||||
|
|
||||||
app.Commands = []cli.Command{
|
app.Commands = []cli.Command{
|
||||||
launchCommand,
|
launchCommand,
|
||||||
|
tagCommand,
|
||||||
versionCommand,
|
versionCommand,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
73
cmd/kpod/tag.go
Normal file
73
cmd/kpod/tag.go
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/containers/image/docker/reference"
|
||||||
|
"github.com/containers/storage"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
tagDescription = "Adds one or more additional names to locally-stored image"
|
||||||
|
tagCommand = cli.Command{
|
||||||
|
Name: "tag",
|
||||||
|
Usage: "Add an additional name to a local image",
|
||||||
|
Description: tagDescription,
|
||||||
|
Action: tagCmd,
|
||||||
|
ArgsUsage: "IMAGE-NAME [IMAGE-NAME ...]",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func tagCmd(c *cli.Context) error {
|
||||||
|
args := c.Args()
|
||||||
|
if len(args) < 2 {
|
||||||
|
return errors.Errorf("image name and at least one new name must be specified")
|
||||||
|
}
|
||||||
|
store, err := getStore(c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
img, err := findImage(store, args[0])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if img == nil {
|
||||||
|
return errors.New("null image")
|
||||||
|
}
|
||||||
|
err = addImageNames(store, img, args[1:])
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "error adding names %v to image %q", args[1:], args[0])
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func addImageNames(store storage.Store, image *storage.Image, addNames []string) error {
|
||||||
|
// Add tags to the names if applicable
|
||||||
|
names, err := expandedTags(addNames)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = store.SetNames(image.ID, append(image.Names, names...))
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "error adding names (%v) to image %q", names, image.ID)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func expandedTags(tags []string) ([]string, error) {
|
||||||
|
expandedNames := []string{}
|
||||||
|
for _, tag := range tags {
|
||||||
|
name, err := reference.ParseNormalizedNamed(tag)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "error parsing tag %q", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
name = reference.TagNameOnly(name)
|
||||||
|
newTag := ""
|
||||||
|
if tagged, ok := name.(reference.NamedTagged); ok {
|
||||||
|
newTag = tagged.Tag()
|
||||||
|
}
|
||||||
|
expandedNames = append(expandedNames, name.Name()+":"+newTag)
|
||||||
|
}
|
||||||
|
return expandedNames, nil
|
||||||
|
}
|
|
@ -35,6 +35,14 @@ _kpod_version() {
|
||||||
_complete_ "$options_with_args" "$boolean_options"
|
_complete_ "$options_with_args" "$boolean_options"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kpod_tag() {
|
||||||
|
local options_with_args="
|
||||||
|
"
|
||||||
|
local boolean_options="
|
||||||
|
"
|
||||||
|
_complete_ "$options_with_args" "$boolean_options"
|
||||||
|
}
|
||||||
|
|
||||||
_kpod_kpod() {
|
_kpod_kpod() {
|
||||||
local options_with_args="
|
local options_with_args="
|
||||||
"
|
"
|
||||||
|
@ -44,6 +52,7 @@ _kpod_kpod() {
|
||||||
"
|
"
|
||||||
commands="
|
commands="
|
||||||
launch
|
launch
|
||||||
|
tag
|
||||||
version
|
version
|
||||||
"
|
"
|
||||||
|
|
||||||
|
|
29
docs/kpod-tag.1.md
Normal file
29
docs/kpod-tag.1.md
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
## kpod-tag "1" "June 2017" "kpod"
|
||||||
|
|
||||||
|
# NAME
|
||||||
|
kpod tag - add tags to an image
|
||||||
|
|
||||||
|
# SYNOPSIS
|
||||||
|
**kpod tag**
|
||||||
|
[**--help**|**-h**]
|
||||||
|
|
||||||
|
# DESCRIPTION
|
||||||
|
Assigns a new alias to an image in a registry. An alias refers to the entire image name, including the optional **TAG** after the ':'
|
||||||
|
|
||||||
|
**kpod [GLOBAL OPTIONS]**
|
||||||
|
|
||||||
|
**kpod [GLOBAL OPTIONS] launch [OPTIONS]**
|
||||||
|
|
||||||
|
# GLOBAL OPTIONS
|
||||||
|
|
||||||
|
**--help, -h**
|
||||||
|
Print usage statement
|
||||||
|
|
||||||
|
# EXAMPLES
|
||||||
|
|
||||||
|
kpod tag 0e3bbc2 fedora:latest
|
||||||
|
|
||||||
|
kpod tag httpd myregistryhost:5000/fedora/httpd:v2
|
||||||
|
|
||||||
|
# SEE ALSO
|
||||||
|
kpod(1), crio(8), crio.conf(5)
|
|
@ -32,6 +32,9 @@ has the capability to debug pods/images created by crio.
|
||||||
## launch
|
## launch
|
||||||
Launch a pod
|
Launch a pod
|
||||||
|
|
||||||
|
## tag
|
||||||
|
Add one or more additional names to locally-stored image
|
||||||
|
|
||||||
# SEE ALSO
|
# SEE ALSO
|
||||||
crio(8), crio.conf(5)
|
crio(8), crio.conf(5)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue