Merge pull request #772 from 14rcole/kpod-rename

implement kpod rename
This commit is contained in:
Mrunal Patel 2017-08-17 10:04:16 -07:00 committed by GitHub
commit a5591d34b7
9 changed files with 257 additions and 1 deletions

View file

@ -53,7 +53,9 @@ func getConfig(c *cli.Context) (*libkpod.Config, error) {
if c.Bool("debug") {
logrus.SetLevel(logrus.DebugLevel)
}
if c.GlobalIsSet("runtime") {
config.Runtime = c.GlobalString("runtime")
}
return config, nil
}

View file

@ -34,6 +34,7 @@ func main() {
mountCommand,
pullCommand,
pushCommand,
renameCommand,
rmiCommand,
saveCommand,
tagCommand,
@ -57,6 +58,10 @@ func main() {
Name: "runroot",
Usage: "path to the 'run directory' where all state information is stored",
},
cli.StringFlag{
Name: "runtime",
Usage: "path to the OCI-compatible binary used to run containers, default is /usr/bin/runc",
},
cli.StringFlag{
Name: "storage-driver, s",
Usage: "select which storage driver is used to manage storage of images and containers (default is overlay2)",

45
cmd/kpod/rename.go Normal file
View file

@ -0,0 +1,45 @@
package main
import (
"github.com/kubernetes-incubator/cri-o/libkpod"
"github.com/pkg/errors"
"github.com/urfave/cli"
)
var (
renameDescription = "Rename a container. Container may be created, running, paused, or stopped"
renameFlags = []cli.Flag{}
renameCommand = cli.Command{
Name: "rename",
Usage: "rename a container",
Description: renameDescription,
Action: renameCmd,
ArgsUsage: "CONTAINER NEW-NAME",
Flags: renameFlags,
}
)
func renameCmd(c *cli.Context) error {
if len(c.Args()) != 2 {
return errors.Errorf("Rename requires a src container name/ID and a dest container name")
}
config, err := getConfig(c)
if err != nil {
return errors.Wrapf(err, "Could not get config")
}
server, err := libkpod.New(config)
if err != nil {
return errors.Wrapf(err, "could not get container server")
}
err = server.Update()
if err != nil {
return errors.Wrapf(err, "could not update list of containers")
}
err = server.ContainerRename(c.Args().Get(0), c.Args().Get(1))
if err != nil {
return errors.Wrapf(err, "could not rename container")
}
return nil
}

View file

@ -181,6 +181,26 @@ _kpod_push() {
esac
}
_kpod_rename() {
local boolean_options="
--help
-h
"
local options_with_args="
"
local all_options="$options_with_args $boolean_options"
case "$cur" in
-*)
COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
;;
*)
__kpod_list_containers
;;
esac
}
_kpod_rmi() {
local boolean_options="
--help

24
docs/kpod-rename.1.md Normal file
View file

@ -0,0 +1,24 @@
% kpod(1) kpod-rename - Rename a container
% Ryan Cole
# kpod-images "1" "March 2017" "kpod"
## NAME
kpod rename - Rename a container
## SYNOPSIS
**kpod** **rename** CONTAINER NEW-NAME
## DESCRIPTION
Rename a container. Container may be created, running, paused, or stopped
## EXAMPLE
kpod rename redis-container webserver
kpod rename a236b9a4 mycontainer
## SEE ALSO
kpod(1)
## HISTORY
March 2017, Originally compiled by Ryan Cole <rycole@redhat.com>

View file

@ -35,6 +35,9 @@ has the capability to debug pods/images created by crio.
**--runroot**=**value**
Path to the 'run directory' where all state information is stored
**--runtime**=**value**
Path to the OCI-compatible binary used to run containers
**--storage-driver, -s**=**value**
Select which storage driver is used to manage storage of images and containers (default is overlay)
@ -76,6 +79,9 @@ Pull an image from a registry
### push
Push an image from local storage to elsewhere
### rename
Rename a container
### rmi
Removes one or more locally stored images

114
libkpod/rename.go Normal file
View file

@ -0,0 +1,114 @@
package libkpod
import (
"encoding/json"
"path/filepath"
"k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
"github.com/docker/docker/pkg/ioutils"
"github.com/kubernetes-incubator/cri-o/oci"
"github.com/kubernetes-incubator/cri-o/pkg/annotations"
"github.com/opencontainers/runtime-tools/generate"
)
const configFile = "config.json"
// ContainerRename renames the given container
func (c *ContainerServer) ContainerRename(container, name string) error {
ctr, err := c.LookupContainer(container)
if err != nil {
return err
}
oldName := ctr.Name()
_, err = c.ReserveContainerName(ctr.ID(), name)
if err != nil {
return err
}
defer func() {
if err != nil {
c.ReleaseContainerName(name)
} else {
c.ReleaseContainerName(oldName)
}
}()
// Update state.json
if err = c.updateStateName(ctr, name); err != nil {
return err
}
// Update config.json
configRuntimePath := filepath.Join(ctr.BundlePath(), configFile)
if err = updateConfigName(configRuntimePath, name); err != nil {
return err
}
configStoragePath := filepath.Join(ctr.Dir(), configFile)
if err = updateConfigName(configStoragePath, name); err != nil {
return err
}
// Update containers.json
if err = c.store.SetNames(ctr.ID(), []string{name}); err != nil {
return err
}
return nil
}
func updateConfigName(configPath, name string) error {
specgen, err := generate.NewFromFile(configPath)
if err != nil {
return err
}
specgen.AddAnnotation(annotations.Name, name)
specgen.AddAnnotation(annotations.Metadata, updateMetadata(specgen.Spec().Annotations, name))
return specgen.SaveToFile(configPath, generate.ExportOptions{})
}
func (c *ContainerServer) updateStateName(ctr *oci.Container, name string) error {
ctr.State().Annotations[annotations.Name] = name
ctr.State().Annotations[annotations.Metadata] = updateMetadata(ctr.State().Annotations, name)
// This is taken directly from c.ContainerStateToDisk(), which can't be used because of the call to UpdateStatus() in the first line
jsonSource, err := ioutils.NewAtomicFileWriter(ctr.StatePath(), 0644)
if err != nil {
return err
}
defer jsonSource.Close()
enc := json.NewEncoder(jsonSource)
return enc.Encode(c.runtime.ContainerStatus(ctr))
}
// Attempts to update a metadata annotation
func updateMetadata(specAnnotations map[string]string, name string) string {
oldMetadata := specAnnotations[annotations.Metadata]
containerType := specAnnotations[annotations.ContainerType]
if containerType == "container" {
metadata := runtime.ContainerMetadata{}
err := json.Unmarshal([]byte(oldMetadata), metadata)
if err != nil {
return oldMetadata
}
metadata.Name = name
m, err := json.Marshal(metadata)
if err != nil {
return oldMetadata
}
return string(m)
} else if containerType == "sandbox" {
metadata := runtime.PodSandboxMetadata{}
err := json.Unmarshal([]byte(oldMetadata), metadata)
if err != nil {
return oldMetadata
}
metadata.Name = name
m, err := json.Marshal(metadata)
if err != nil {
return oldMetadata
}
return string(m)
} else {
return specAnnotations[annotations.Metadata]
}
}

View file

@ -160,6 +160,11 @@ func (c *Container) Sandbox() string {
return c.sandbox
}
// Dir returns the the dir of the container
func (c *Container) Dir() string {
return c.dir
}
// NetNsPath returns the path to the network namespace of the container.
func (c *Container) NetNsPath() (string, error) {
if c.state == nil {

35
test/kpod_rename.bats Normal file
View file

@ -0,0 +1,35 @@
#!/usr/bin/env bats
load helpers
IMAGE="redis:alpine"
ROOT="$TESTDIR/crio"
RUNROOT="$TESTDIR/crio-run"
KPOD_OPTIONS="--root $ROOT --runroot $RUNROOT $STORAGE_OPTS"
NEW_NAME="rename-test"
function teardown() {
cleanup_test
}
@test "kpod rename successful" {
start_crio
run ${KPOD_BINARY} ${KPOD_OPTIONS} pull $IMAGE
[ "$status" -eq 0 ]
run crioctl pod run --config "$TESTDATA"/sandbox_config.json
echo "$output"
pod_id="$output"
[ "$status" -eq 0 ]
run crioctl ctr create --config "$TESTDATA"/container_config.json --pod "$pod_id"
ctr_id="$output"
run ${KPOD_BINARY} $KPOD_OPTIONS rename "$ctr_id" "$NEW_NAME"
echo "$output"
[ "$status" -eq 0 ]
run ${KPOD_BINARY} $KPOD_OPTIONS inspect "$ctr_id" --format {{.Name}}
echo "$output"
[ "$status" -eq 0 ]
[ "$output" == "$NEW_NAME" ]
cleanup_ctrs
cleanup_pods
stop_crio
}