diff options
-rwxr-xr-x | API.md | 36 | ||||
-rw-r--r-- | cmd/podman/inspect.go | 39 | ||||
-rw-r--r-- | cmd/podman/shared/container.go | 16 | ||||
-rw-r--r-- | cmd/podman/varlink/io.podman.varlink | 16 | ||||
-rw-r--r-- | libpod/adapter/containers_remote.go | 50 | ||||
-rw-r--r-- | libpod/adapter/images_remote.go | 19 | ||||
-rw-r--r-- | libpod/adapter/runtime_remote.go | 98 | ||||
-rw-r--r-- | libpod/boltdb_state.go | 12 | ||||
-rw-r--r-- | libpod/boltdb_state_linux.go | 2 | ||||
-rw-r--r-- | libpod/boltdb_state_unsupported.go | 2 | ||||
-rw-r--r-- | libpod/common_test.go | 8 | ||||
-rw-r--r-- | libpod/container.go | 21 | ||||
-rw-r--r-- | libpod/container_internal.go | 2 | ||||
-rw-r--r-- | libpod/container_internal_test.go | 2 | ||||
-rw-r--r-- | libpod/runtime_ctr.go | 2 | ||||
-rw-r--r-- | pkg/varlinkapi/containers.go | 86 | ||||
-rw-r--r-- | test/e2e/common_test.go | 19 | ||||
-rw-r--r-- | test/e2e/inspect_test.go | 6 | ||||
-rw-r--r-- | test/e2e/libpod_suite_remoteclient_test.go | 8 | ||||
-rw-r--r-- | test/e2e/libpod_suite_test.go | 9 |
20 files changed, 343 insertions, 110 deletions
@@ -9,14 +9,22 @@ in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in [func Commit(name: string, image_name: string, changes: []string, author: string, message: string, pause: bool, manifestType: string) string](#Commit) +[func ContainerArtifacts(name: string, artifactName: string) string](#ContainerArtifacts) + [func ContainerCheckpoint(name: string, keep: bool, leaveRunning: bool, tcpEstablished: bool) string](#ContainerCheckpoint) +[func ContainerConfig(name: string) string](#ContainerConfig) + [func ContainerExists(name: string) int](#ContainerExists) +[func ContainerInspectData(name: string) string](#ContainerInspectData) + [func ContainerRestore(name: string, keep: bool, tcpEstablished: bool) string](#ContainerRestore) [func ContainerRunlabel(runlabel: Runlabel) ](#ContainerRunlabel) +[func ContainerStateData(name: string) string](#ContainerStateData) + [func CreateContainer(create: Create) string](#CreateContainer) [func CreateImage() NotImplemented](#CreateImage) @@ -239,12 +247,24 @@ attributes: _CMD, ENTRYPOINT, ENV, EXPOSE, LABEL, ONBUILD, STOPSIGNAL, USER, VOL container while it is being committed, pass a _true_ bool for the pause argument. If the container cannot be found by the ID or name provided, a (ContainerNotFound)[#ContainerNotFound] error will be returned; otherwise, the resulting image's ID will be returned as a string. +### <a name="ContainerArtifacts"></a>func ContainerArtifacts +<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;"> + +method ContainerArtifacts(name: [string](https://godoc.org/builtin#string), artifactName: [string](https://godoc.org/builtin#string)) [string](https://godoc.org/builtin#string)</div> +ContainerArtifacts returns a container's artifacts in string form. This call is for +development of Podman only and generally should not be used. ### <a name="ContainerCheckpoint"></a>func ContainerCheckpoint <div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;"> method ContainerCheckpoint(name: [string](https://godoc.org/builtin#string), keep: [bool](https://godoc.org/builtin#bool), leaveRunning: [bool](https://godoc.org/builtin#bool), tcpEstablished: [bool](https://godoc.org/builtin#bool)) [string](https://godoc.org/builtin#string)</div> ContainerCheckPoint performs a checkpopint on a container by its name or full/partial container ID. On successful checkpoint, the id of the checkpointed container is returned. +### <a name="ContainerConfig"></a>func ContainerConfig +<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;"> + +method ContainerConfig(name: [string](https://godoc.org/builtin#string)) [string](https://godoc.org/builtin#string)</div> +ContainerConfig returns a container's config in string form. This call is for +development of Podman only and generally should not be used. ### <a name="ContainerExists"></a>func ContainerExists <div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;"> @@ -258,6 +278,12 @@ $ varlink call -m unix:/run/podman/io.podman/io.podman.ContainerExists '{"name": "exists": 0 } ~~~ +### <a name="ContainerInspectData"></a>func ContainerInspectData +<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;"> + +method ContainerInspectData(name: [string](https://godoc.org/builtin#string)) [string](https://godoc.org/builtin#string)</div> +ContainerInspectData returns a container's inspect data in string form. This call is for +development of Podman only and generally should not be used. ### <a name="ContainerRestore"></a>func ContainerRestore <div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;"> @@ -270,6 +296,12 @@ of the container's ID. method ContainerRunlabel(runlabel: [Runlabel](#Runlabel)) </div> ContainerRunlabel runs executes a command as described by a given container image label. +### <a name="ContainerStateData"></a>func ContainerStateData +<div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;"> + +method ContainerStateData(name: [string](https://godoc.org/builtin#string)) [string](https://godoc.org/builtin#string)</div> +ContainerStateData returns a container's state config in string form. This call is for +development of Podman only and generally should not be used. ### <a name="CreateContainer"></a>func CreateContainer <div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;"> @@ -1373,6 +1405,8 @@ virtualSize [int](https://godoc.org/builtin#int) containers [int](https://godoc.org/builtin#int) labels [map[string]](#map[string]) + +isParent [bool](https://godoc.org/builtin#bool) ### <a name="ImageSearch"></a>type ImageSearch ImageSearch is the returned structure for SearchImage. It is returned @@ -1460,7 +1494,7 @@ graph_status [InfoGraphStatus](#InfoGraphStatus) run_root [string](https://godoc.org/builtin#string) ### <a name="ListContainerData"></a>type ListContainerData -ListContainer is the returned struct for an individual container +ListContainerData is the returned struct for an individual container id [string](https://godoc.org/builtin#string) diff --git a/cmd/podman/inspect.go b/cmd/podman/inspect.go index 2f1e97c6c..3ef740463 100644 --- a/cmd/podman/inspect.go +++ b/cmd/podman/inspect.go @@ -2,12 +2,13 @@ package main import ( "context" + "encoding/json" "strings" "github.com/containers/libpod/cmd/podman/formats" - "github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/cmd/podman/shared" - "github.com/containers/libpod/libpod" + "github.com/containers/libpod/libpod/adapter" + cc "github.com/containers/libpod/pkg/spec" "github.com/containers/libpod/pkg/util" "github.com/pkg/errors" "github.com/urfave/cli" @@ -63,7 +64,7 @@ func inspectCmd(c *cli.Context) error { return err } - runtime, err := libpodruntime.GetRuntime(c) + runtime, err := adapter.GetRuntime(c) if err != nil { return errors.Wrapf(err, "error creating libpod runtime") } @@ -104,7 +105,7 @@ func inspectCmd(c *cli.Context) error { } // func iterateInput iterates the images|containers the user has requested and returns the inspect data and error -func iterateInput(ctx context.Context, c *cli.Context, args []string, runtime *libpod.Runtime, inspectType string) ([]interface{}, error) { +func iterateInput(ctx context.Context, c *cli.Context, args []string, runtime *adapter.LocalRuntime, inspectType string) ([]interface{}, error) { var ( data interface{} inspectedItems []interface{} @@ -124,13 +125,18 @@ func iterateInput(ctx context.Context, c *cli.Context, args []string, runtime *l inspectError = errors.Wrapf(err, "error getting libpod container inspect data %s", ctr.ID()) break } - data, err = shared.GetCtrInspectInfo(ctr, libpodInspectData) + artifact, err := getArtifact(ctr) + if inspectError != nil { + inspectError = err + break + } + data, err = shared.GetCtrInspectInfo(ctr.Config(), libpodInspectData, artifact) if err != nil { inspectError = errors.Wrapf(err, "error parsing container data %q", ctr.ID()) break } case inspectTypeImage: - image, err := runtime.ImageRuntime().NewFromLocal(input) + image, err := runtime.NewImageFromLocal(input) if err != nil { inspectError = errors.Wrapf(err, "error getting image %q", input) break @@ -143,7 +149,7 @@ func iterateInput(ctx context.Context, c *cli.Context, args []string, runtime *l case inspectAll: ctr, err := runtime.LookupContainer(input) if err != nil { - image, err := runtime.ImageRuntime().NewFromLocal(input) + image, err := runtime.NewImageFromLocal(input) if err != nil { inspectError = errors.Wrapf(err, "error getting image %q", input) break @@ -159,7 +165,12 @@ func iterateInput(ctx context.Context, c *cli.Context, args []string, runtime *l inspectError = errors.Wrapf(err, "error getting libpod container inspect data %s", ctr.ID()) break } - data, err = shared.GetCtrInspectInfo(ctr, libpodInspectData) + artifact, inspectError := getArtifact(ctr) + if inspectError != nil { + inspectError = err + break + } + data, err = shared.GetCtrInspectInfo(ctr.Config(), libpodInspectData, artifact) if err != nil { inspectError = errors.Wrapf(err, "error parsing container data %s", ctr.ID()) break @@ -172,3 +183,15 @@ func iterateInput(ctx context.Context, c *cli.Context, args []string, runtime *l } return inspectedItems, inspectError } + +func getArtifact(ctr *adapter.Container) (*cc.CreateConfig, error) { + var createArtifact cc.CreateConfig + artifact, err := ctr.GetArtifact("create-config") + if err != nil { + return nil, err + } + if err := json.Unmarshal(artifact, &createArtifact); err != nil { + return nil, err + } + return &createArtifact, nil +} diff --git a/cmd/podman/shared/container.go b/cmd/podman/shared/container.go index a904ef75a..9040c4a5c 100644 --- a/cmd/podman/shared/container.go +++ b/cmd/podman/shared/container.go @@ -2,7 +2,6 @@ package shared import ( "context" - "encoding/json" "fmt" "github.com/google/shlex" "io" @@ -446,8 +445,7 @@ func getStrFromSquareBrackets(cmd string) string { // GetCtrInspectInfo takes container inspect data and collects all its info into a ContainerData // structure for inspection related methods -func GetCtrInspectInfo(ctr *libpod.Container, ctrInspectData *inspect.ContainerInspectData) (*inspect.ContainerData, error) { - config := ctr.Config() +func GetCtrInspectInfo(config *libpod.ContainerConfig, ctrInspectData *inspect.ContainerInspectData, createArtifact *cc.CreateConfig) (*inspect.ContainerData, error) { spec := config.Spec cpus, mems, period, quota, realtimePeriod, realtimeRuntime, shares := getCPUInfo(spec) @@ -456,16 +454,6 @@ func GetCtrInspectInfo(ctr *libpod.Container, ctrInspectData *inspect.ContainerI pidsLimit := getPidsInfo(spec) cgroup := getCgroup(spec) - var createArtifact cc.CreateConfig - artifact, err := ctr.GetArtifact("create-config") - if err == nil { - if err := json.Unmarshal(artifact, &createArtifact); err != nil { - return nil, err - } - } else { - logrus.Errorf("couldn't get some inspect information, error getting artifact %q: %v", ctr.ID(), err) - } - data := &inspect.ContainerData{ ctrInspectData, &inspect.HostConfig{ @@ -493,7 +481,7 @@ func GetCtrInspectInfo(ctr *libpod.Container, ctrInspectData *inspect.ContainerI PidsLimit: pidsLimit, Privileged: config.Privileged, ReadonlyRootfs: spec.Root.Readonly, - Runtime: ctr.RuntimeName(), + Runtime: config.OCIRuntime, NetworkMode: string(createArtifact.NetMode), IpcMode: string(createArtifact.IpcMode), Cgroup: cgroup, diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink index c6f1d3f1b..79300f9bc 100644 --- a/cmd/podman/varlink/io.podman.varlink +++ b/cmd/podman/varlink/io.podman.varlink @@ -1035,6 +1035,22 @@ method GenerateKubeService() -> (notimplemented: NotImplemented) # like that created by GenerateKube. See also [GenerateKube](GenerateKube). method ReplayKube() -> (notimplemented: NotImplemented) +# ContainerConfig returns a container's config in string form. This call is for +# development of Podman only and generally should not be used. +method ContainerConfig(name: string) -> (config: string) + +# ContainerArtifacts returns a container's artifacts in string form. This call is for +# development of Podman only and generally should not be used. +method ContainerArtifacts(name: string, artifactName: string) -> (config: string) + +# ContainerInspectData returns a container's inspect data in string form. This call is for +# development of Podman only and generally should not be used. +method ContainerInspectData(name: string) -> (config: string) + +# ContainerStateData returns a container's state config in string form. This call is for +# development of Podman only and generally should not be used. +method ContainerStateData(name: string) -> (config: string) + # ImageNotFound means the image could not be found by the provided name or ID in local storage. error ImageNotFound (name: string) diff --git a/libpod/adapter/containers_remote.go b/libpod/adapter/containers_remote.go new file mode 100644 index 000000000..9623304e5 --- /dev/null +++ b/libpod/adapter/containers_remote.go @@ -0,0 +1,50 @@ +// +build remoteclient + +package adapter + +import ( + "encoding/json" + + iopodman "github.com/containers/libpod/cmd/podman/varlink" + "github.com/containers/libpod/libpod" + "github.com/containers/libpod/pkg/inspect" +) + +// Inspect returns an inspect struct from varlink +func (c *Container) Inspect(size bool) (*inspect.ContainerInspectData, error) { + reply, err := iopodman.ContainerInspectData().Call(c.Runtime.Conn, c.ID()) + if err != nil { + return nil, err + } + data := inspect.ContainerInspectData{} + if err := json.Unmarshal([]byte(reply), &data); err != nil { + return nil, err + } + return &data, err +} + +// ID returns the ID of the container +func (c *Container) ID() string { + return c.config.ID +} + +// GetArtifact returns a container's artifacts +func (c *Container) GetArtifact(name string) ([]byte, error) { + var data []byte + reply, err := iopodman.ContainerArtifacts().Call(c.Runtime.Conn, c.ID(), name) + if err != nil { + return nil, err + } + if err := json.Unmarshal([]byte(reply), &data); err != nil { + return nil, err + } + return data, err +} + +// Config returns a container's Config ... same as ctr.Config() +func (c *Container) Config() *libpod.ContainerConfig { + if c.config != nil { + return c.config + } + return c.Runtime.Config(c.ID()) +} diff --git a/libpod/adapter/images_remote.go b/libpod/adapter/images_remote.go index 77b0629a7..e7b38dccc 100644 --- a/libpod/adapter/images_remote.go +++ b/libpod/adapter/images_remote.go @@ -3,15 +3,22 @@ package adapter import ( - "github.com/containers/libpod/libpod" + "context" + "encoding/json" + + iopodman "github.com/containers/libpod/cmd/podman/varlink" + "github.com/containers/libpod/pkg/inspect" ) -// Images returns information for the host system and its components -func (r RemoteRuntime) Images() ([]libpod.InfoData, error) { - conn, err := r.Connect() +// Inspect returns returns an ImageData struct from over a varlink connection +func (i *ContainerImage) Inspect(ctx context.Context) (*inspect.ImageData, error) { + reply, err := iopodman.InspectImage().Call(i.Runtime.Conn, i.ID()) if err != nil { return nil, err } - _ = conn - return nil, nil + data := inspect.ImageData{} + if err := json.Unmarshal([]byte(reply), &data); err != nil { + return nil, err + } + return &data, nil } diff --git a/libpod/adapter/runtime_remote.go b/libpod/adapter/runtime_remote.go index 8ef8fe167..7189348bc 100644 --- a/libpod/adapter/runtime_remote.go +++ b/libpod/adapter/runtime_remote.go @@ -4,15 +4,18 @@ package adapter import ( "context" + "encoding/json" "fmt" "io" "strings" "time" "github.com/containers/image/types" - iopodman "github.com/containers/libpod/cmd/podman/varlink" + "github.com/containers/libpod/cmd/podman/varlink" + "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/image" - digest "github.com/opencontainers/go-digest" + "github.com/opencontainers/go-digest" + "github.com/sirupsen/logrus" "github.com/urfave/cli" "github.com/varlink/go/varlink" ) @@ -80,21 +83,9 @@ type Container struct { // remoteContainer .... type remoteContainer struct { - ID string - Image string - ImageID string - Command []string - Created time.Time - RunningFor string - Status string - //Ports []ocicni.PortMapping - RootFsSize int64 - RWSize int64 - Names string - Labels []map[string]string - // Mounts []string - // ContainerRunning bool - //Namespaces []LinuxNameSpace + Runtime *LocalRuntime + config *libpod.ContainerConfig + state *libpod.ContainerState } // GetImages returns a slice of containerimages over a varlink connection @@ -272,39 +263,60 @@ func (ci *ContainerImage) History(ctx context.Context) ([]*image.History, error) // LookupContainer gets basic information about container over a varlink // connection and then translates it to a *Container -func (r *RemoteRuntime) LookupContainer(idOrName string) (*Container, error) { - container, err := iopodman.GetContainer().Call(r.Conn, idOrName) +func (r *LocalRuntime) LookupContainer(idOrName string) (*Container, error) { + state, err := r.ContainerState(idOrName) if err != nil { return nil, err } - return listContainerDataToContainer(container) + config := r.Config(idOrName) + if err != nil { + return nil, err + } + + rc := remoteContainer{ + r, + config, + state, + } + + c := Container{ + rc, + } + return &c, nil +} + +func (r *LocalRuntime) GetLatestContainer() (*Container, error) { + return nil, libpod.ErrNotImplemented } -// listContainerDataToContainer takes a varlink listcontainerData struct and makes -// an "adapted" Container -func listContainerDataToContainer(listData iopodman.ListContainerData) (*Container, error) { - created, err := splitStringDate(listData.Createdat) +// ContainerState returns the "state" of the container. +func (r *LocalRuntime) ContainerState(name string) (*libpod.ContainerState, error) { //no-lint + reply, err := iopodman.ContainerStateData().Call(r.Conn, name) if err != nil { return nil, err } - rc := remoteContainer{ - // TODO commented out attributes will be populated when podman-remote ps - // is implemented. They are not needed yet for basic container operations. - ID: listData.Id, - Image: listData.Image, - ImageID: listData.Imageid, - Command: listData.Command, - Created: created, - RunningFor: listData.Runningfor, - Status: listData.Status, - //ports: - RootFsSize: listData.Rootfssize, - RWSize: listData.Rwsize, - Names: listData.Names, - //Labels: - //Mounts - //ContainerRunning: - //namespaces: + data := libpod.ContainerState{} + if err := json.Unmarshal([]byte(reply), &data); err != nil { + return nil, err } - return &Container{rc}, nil + return &data, err + +} + +// Config returns a container config +func (r *LocalRuntime) Config(name string) *libpod.ContainerConfig { + // TODO the Spec being returned is not populated. Matt and I could not figure out why. Will defer + // further looking into it for after devconf. + // The libpod function for this has no errors so we are kind of in a tough + // spot here. Logging the errors for now. + reply, err := iopodman.ContainerConfig().Call(r.Conn, name) + if err != nil { + logrus.Error("call to container.config failed") + } + data := libpod.ContainerConfig{} + if err := json.Unmarshal([]byte(reply), &data); err != nil { + logrus.Error("failed to unmarshal container inspect data") + } + return &data + } diff --git a/libpod/boltdb_state.go b/libpod/boltdb_state.go index e7a07a9a8..5bc15dd7f 100644 --- a/libpod/boltdb_state.go +++ b/libpod/boltdb_state.go @@ -205,7 +205,7 @@ func (s *BoltState) Refresh() error { return errors.Wrapf(ErrInternal, "container %s missing state in DB", string(id)) } - state := new(containerState) + state := new(ContainerState) if err := json.Unmarshal(stateBytes, state); err != nil { return errors.Wrapf(err, "error unmarshalling state for container %s", string(id)) @@ -325,7 +325,7 @@ func (s *BoltState) Container(id string) (*Container, error) { ctr := new(Container) ctr.config = new(ContainerConfig) - ctr.state = new(containerState) + ctr.state = new(ContainerState) db, err := s.getDBCon() if err != nil { @@ -361,7 +361,7 @@ func (s *BoltState) LookupContainer(idOrName string) (*Container, error) { ctr := new(Container) ctr.config = new(ContainerConfig) - ctr.state = new(containerState) + ctr.state = new(ContainerState) db, err := s.getDBCon() if err != nil { @@ -542,7 +542,7 @@ func (s *BoltState) UpdateContainer(ctr *Container) error { return errors.Wrapf(ErrNSMismatch, "container %s is in namespace %q, does not match our namespace %q", ctr.ID(), ctr.config.Namespace, s.namespace) } - newState := new(containerState) + newState := new(ContainerState) netNSPath := "" ctrID := []byte(ctr.ID()) @@ -754,7 +754,7 @@ func (s *BoltState) AllContainers() ([]*Container, error) { ctr := new(Container) ctr.config = new(ContainerConfig) - ctr.state = new(containerState) + ctr.state = new(ContainerState) if err := s.getContainerFromDB(id, ctr, ctrBucket); err != nil { // If the error is a namespace mismatch, we can @@ -1140,7 +1140,7 @@ func (s *BoltState) PodContainers(pod *Pod) ([]*Container, error) { err = podCtrs.ForEach(func(id, val []byte) error { newCtr := new(Container) newCtr.config = new(ContainerConfig) - newCtr.state = new(containerState) + newCtr.state = new(ContainerState) ctrs = append(ctrs, newCtr) return s.getContainerFromDB(id, newCtr, ctrBkt) diff --git a/libpod/boltdb_state_linux.go b/libpod/boltdb_state_linux.go index d91f311e5..09a9be606 100644 --- a/libpod/boltdb_state_linux.go +++ b/libpod/boltdb_state_linux.go @@ -8,7 +8,7 @@ import ( // replaceNetNS handle network namespace transitions after updating a // container's state. -func replaceNetNS(netNSPath string, ctr *Container, newState *containerState) error { +func replaceNetNS(netNSPath string, ctr *Container, newState *ContainerState) error { if netNSPath != "" { // Check if the container's old state has a good netns if ctr.state.NetNS != nil && netNSPath == ctr.state.NetNS.Path() { diff --git a/libpod/boltdb_state_unsupported.go b/libpod/boltdb_state_unsupported.go index 64610d304..244dc51a0 100644 --- a/libpod/boltdb_state_unsupported.go +++ b/libpod/boltdb_state_unsupported.go @@ -3,7 +3,7 @@ package libpod // replaceNetNS is exclusive to the Linux platform and is a no-op elsewhere -func replaceNetNS(netNSPath string, ctr *Container, newState *containerState) error { +func replaceNetNS(netNSPath string, ctr *Container, newState *ContainerState) error { return nil } diff --git a/libpod/common_test.go b/libpod/common_test.go index 4af68a040..df730098e 100644 --- a/libpod/common_test.go +++ b/libpod/common_test.go @@ -48,7 +48,7 @@ func getTestContainer(id, name string, manager lock.Manager) (*Container, error) }, }, }, - state: &containerState{ + state: &ContainerState{ State: ContainerStateRunning, ConfigPath: "/does/not/exist/specs/" + id, RunDir: "/does/not/exist/tmp/", @@ -166,10 +166,10 @@ func testContainersEqual(t *testing.T, a, b *Container, allowedEmpty bool) { aConfig := new(ContainerConfig) bConfig := new(ContainerConfig) - aState := new(containerState) - bState := new(containerState) + aState := new(ContainerState) + bState := new(ContainerState) - blankState := new(containerState) + blankState := new(ContainerState) assert.Equal(t, a.valid, b.valid) diff --git a/libpod/container.go b/libpod/container.go index b5f6a29ba..b0589be3b 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -116,7 +116,7 @@ func (ns LinuxNS) String() string { type Container struct { config *ContainerConfig - state *containerState + state *ContainerState // Batched indicates that a container has been locked as part of a // Batch() operation @@ -136,10 +136,10 @@ type Container struct { requestedIP net.IP } -// containerState contains the current state of the container +// ContainerState contains the current state of the container // It is stored on disk in a tmpfs and recreated on reboot // easyjson:json -type containerState struct { +type ContainerState struct { // The current state of the running container State ContainerStatus `json:"state"` // The path to the JSON OCI runtime spec for this container @@ -1063,3 +1063,18 @@ func networkDisabled(c *Container) (bool, error) { } return false, nil } + +// ContainerState returns containerstate struct +func (c *Container) ContainerState() (*ContainerState, error) { + if !c.batched { + c.lock.Lock() + defer c.lock.Unlock() + + if err := c.syncContainer(); err != nil { + return nil, err + } + } + returnConfig := new(ContainerState) + deepcopier.Copy(c.state).To(returnConfig) + return c.state, nil +} diff --git a/libpod/container_internal.go b/libpod/container_internal.go index ce8791f08..39c1501da 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -388,7 +388,7 @@ func (c *Container) teardownStorage() error { // Reset resets state fields to default values // It is performed before a refresh and clears the state after a reboot // It does not save the results - assumes the database will do that for us -func resetState(state *containerState) error { +func resetState(state *ContainerState) error { state.PID = 0 state.Mountpoint = "" state.Mounted = false diff --git a/libpod/container_internal_test.go b/libpod/container_internal_test.go index 124f1d20e..f1e2b70a7 100644 --- a/libpod/container_internal_test.go +++ b/libpod/container_internal_test.go @@ -37,7 +37,7 @@ func TestPostDeleteHooks(t *testing.T) { }, StaticDir: dir, // not the bundle, but good enough for this test }, - state: &containerState{ + state: &ContainerState{ ExtensionStageHooks: map[string][]rspec.Hook{ "poststop": { rspec.Hook{ diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go index 68599fe6d..6d5ce5a7e 100644 --- a/libpod/runtime_ctr.go +++ b/libpod/runtime_ctr.go @@ -48,7 +48,7 @@ func (r *Runtime) newContainer(ctx context.Context, rSpec *spec.Spec, options .. ctr := new(Container) ctr.config = new(ContainerConfig) - ctr.state = new(containerState) + ctr.state = new(ContainerState) ctr.config.ID = stringid.GenerateNonCryptoID() diff --git a/pkg/varlinkapi/containers.go b/pkg/varlinkapi/containers.go index 07d981786..a01e3cc2b 100644 --- a/pkg/varlinkapi/containers.go +++ b/pkg/varlinkapi/containers.go @@ -12,6 +12,7 @@ import ( "github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/cmd/podman/varlink" "github.com/containers/libpod/libpod" + cc "github.com/containers/libpod/pkg/spec" "github.com/containers/storage/pkg/archive" "github.com/pkg/errors" ) @@ -68,7 +69,12 @@ func (i *LibpodAPI) InspectContainer(call iopodman.VarlinkCall, name string) err if err != nil { return call.ReplyErrorOccurred(err.Error()) } - data, err := shared.GetCtrInspectInfo(ctr, inspectInfo) + artifact, err := getArtifact(ctr) + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + + data, err := shared.GetCtrInspectInfo(ctr.Config(), inspectInfo, artifact) if err != nil { return call.ReplyErrorOccurred(err.Error()) } @@ -462,3 +468,81 @@ func (i *LibpodAPI) ContainerRestore(call iopodman.VarlinkCall, name string, kee } return call.ReplyContainerRestore(ctr.ID()) } + +func getArtifact(ctr *libpod.Container) (*cc.CreateConfig, error) { + var createArtifact cc.CreateConfig + artifact, err := ctr.GetArtifact("create-config") + if err != nil { + return nil, err + } + if err := json.Unmarshal(artifact, &createArtifact); err != nil { + return nil, err + } + return &createArtifact, nil +} + +// ContainerConfig returns just the container.config struct +func (i *LibpodAPI) ContainerConfig(call iopodman.VarlinkCall, name string) error { + ctr, err := i.Runtime.LookupContainer(name) + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + config := ctr.Config() + b, err := json.Marshal(config) + if err != nil { + return call.ReplyErrorOccurred("unable to serialize container config") + } + return call.ReplyContainerConfig(string(b)) +} + +// ContainerArtifacts returns an untouched container's artifact in string format +func (i *LibpodAPI) ContainerArtifacts(call iopodman.VarlinkCall, name, artifactName string) error { + ctr, err := i.Runtime.LookupContainer(name) + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + artifacts, err := ctr.GetArtifact(artifactName) + if err != nil { + return call.ReplyErrorOccurred("unable to get container artifacts") + } + b, err := json.Marshal(artifacts) + if err != nil { + return call.ReplyErrorOccurred("unable to serialize container artifacts") + } + return call.ReplyContainerArtifacts(string(b)) +} + +// ContainerInspectData returns the inspect data of a container in string format +func (i *LibpodAPI) ContainerInspectData(call iopodman.VarlinkCall, name string) error { + ctr, err := i.Runtime.LookupContainer(name) + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + data, err := ctr.Inspect(true) + if err != nil { + return call.ReplyErrorOccurred("unable to inspect container") + } + b, err := json.Marshal(data) + if err != nil { + return call.ReplyErrorOccurred("unable to serialize container inspect data") + } + return call.ReplyContainerInspectData(string(b)) + +} + +// ContainerStateData returns a container's state data in string format +func (i *LibpodAPI) ContainerStateData(call iopodman.VarlinkCall, name string) error { + ctr, err := i.Runtime.LookupContainer(name) + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + data, err := ctr.ContainerState() + if err != nil { + return call.ReplyErrorOccurred("unable to obtain container state") + } + b, err := json.Marshal(data) + if err != nil { + return call.ReplyErrorOccurred("unable to serialize container inspect data") + } + return call.ReplyContainerStateData(string(b)) +} diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go index e00a59b7f..a75601b65 100644 --- a/test/e2e/common_test.go +++ b/test/e2e/common_test.go @@ -1,17 +1,19 @@ package integration import ( + "encoding/json" "fmt" - . "github.com/containers/libpod/test/utils" "os" "os/exec" + "path/filepath" + "strings" + "testing" + "github.com/containers/libpod/pkg/inspect" + . "github.com/containers/libpod/test/utils" "github.com/containers/storage/pkg/reexec" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "path/filepath" - "strings" - "testing" ) var ( @@ -227,3 +229,12 @@ func (p *PodmanTestIntegration) CreateArtifact(image string) error { } return nil } + +// InspectImageJSON takes the session output of an inspect +// image and returns json +func (s *PodmanSessionIntegration) InspectImageJSON() []inspect.ImageData { + var i []inspect.ImageData + err := json.Unmarshal(s.Out.Contents(), &i) + Expect(err).To(BeNil()) + return i +} diff --git a/test/e2e/inspect_test.go b/test/e2e/inspect_test.go index 38c50da14..e5c471bf9 100644 --- a/test/e2e/inspect_test.go +++ b/test/e2e/inspect_test.go @@ -1,5 +1,3 @@ -// +build !remoteclient - package integration import ( @@ -45,6 +43,7 @@ var _ = Describe("Podman inspect", func() { }) It("podman inspect bogus container", func() { + SkipIfRemote() session := podmanTest.Podman([]string{"inspect", "foobar4321"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Not(Equal(0))) @@ -68,6 +67,7 @@ var _ = Describe("Podman inspect", func() { }) It("podman inspect container with size", func() { + SkipIfRemote() _, ec, _ := podmanTest.RunLsContainer("") Expect(ec).To(Equal(0)) @@ -79,6 +79,7 @@ var _ = Describe("Podman inspect", func() { }) It("podman inspect container and image", func() { + SkipIfRemote() ls, ec, _ := podmanTest.RunLsContainer("") Expect(ec).To(Equal(0)) cid := ls.OutputToString() @@ -90,6 +91,7 @@ var _ = Describe("Podman inspect", func() { }) It("podman inspect -l with additional input should fail", func() { + SkipIfRemote() result := podmanTest.Podman([]string{"inspect", "-l", "1234foobar"}) result.WaitWithDefaultTimeout() Expect(result.ExitCode()).To(Equal(125)) diff --git a/test/e2e/libpod_suite_remoteclient_test.go b/test/e2e/libpod_suite_remoteclient_test.go index cad4401f8..660c2f639 100644 --- a/test/e2e/libpod_suite_remoteclient_test.go +++ b/test/e2e/libpod_suite_remoteclient_test.go @@ -55,10 +55,10 @@ func (p *PodmanTestIntegration) RunLsContainer(name string) (*PodmanSessionInteg // InspectImageJSON takes the session output of an inspect // image and returns json -func (s *PodmanSessionIntegration) InspectImageJSON() []inspect.ImageData { - // TODO - return nil -} +//func (s *PodmanSessionIntegration) InspectImageJSON() []inspect.ImageData { +// // TODO +// return nil +//} func (p *PodmanTestIntegration) setDefaultRegistriesConfigEnv() { defaultFile := filepath.Join(INTEGRATION_ROOT, "test/registries.conf") diff --git a/test/e2e/libpod_suite_test.go b/test/e2e/libpod_suite_test.go index a7ce14239..48304af7f 100644 --- a/test/e2e/libpod_suite_test.go +++ b/test/e2e/libpod_suite_test.go @@ -118,15 +118,6 @@ func (s *PodmanSessionIntegration) InspectPodToJSON() libpod.PodInspect { return i } -// InspectImageJSON takes the session output of an inspect -// image and returns json -func (s *PodmanSessionIntegration) InspectImageJSON() []inspect.ImageData { - var i []inspect.ImageData - err := json.Unmarshal(s.Out.Contents(), &i) - Expect(err).To(BeNil()) - return i -} - // CreatePod creates a pod with no infra container // it optionally takes a pod name func (p *PodmanTestIntegration) CreatePod(name string) (*PodmanSessionIntegration, int, string) { |