mirror of
https://github.com/containers/podman.git
synced 2026-01-25 22:39:51 -05:00
Signed-off-by: Jhon Honce <jhonce@redhat.com> Create service command Use cd cmd/service && go build . $ systemd-socket-activate -l 8081 cmd/service/service & $ curl http://localhost:8081/v1.24/images/json Signed-off-by: Jhon Honce <jhonce@redhat.com> Correct Makefile Signed-off-by: Jhon Honce <jhonce@redhat.com> Two more stragglers Signed-off-by: Jhon Honce <jhonce@redhat.com> Report errors back as http headers Signed-off-by: Jhon Honce <jhonce@redhat.com> Split out handlers, updated output Output aligned to docker structures Signed-off-by: Jhon Honce <jhonce@redhat.com> Refactored routing, added more endpoints and types * Encapsulated all the routing information in the handler_* files. * Added more serviceapi/types, including podman additions. See Info Signed-off-by: Jhon Honce <jhonce@redhat.com> Cleaned up code, implemented info content * Move Content-Type check into serviceHandler * Custom 404 handler showing the url, mostly for debugging * Refactored images: better method names and explicit http codes * Added content to /info * Added podman fields to Info struct * Added Container struct Signed-off-by: Jhon Honce <jhonce@redhat.com> Add a bunch of endpoints containers: stop, pause, unpause, wait, rm images: tag, rmi, create (pull only) Signed-off-by: baude <bbaude@redhat.com> Add even more handlers * Add serviceapi/Error() to improve error handling * Better support for API return payloads * Renamed unimplemented to unsupported these are generic endpoints we don't intend to ever support. Swarm broken out since it uses different HTTP codes to signal that the node is not in a swarm. * Added more types * API Version broken out so it can be validated in the future Signed-off-by: Jhon Honce <jhonce@redhat.com> Refactor to introduce ServiceWriter Signed-off-by: Jhon Honce <jhonce@redhat.com> populate pods endpoints /libpod/pods/.. exists, kill, pause, prune, restart, remove, start, stop, unpause Signed-off-by: baude <bbaude@redhat.com> Add components to Version, fix Error body Signed-off-by: Jhon Honce <jhonce@redhat.com> Add images pull output, fix swarm routes * docker-py tests/integration/api_client_test.py pass 100% * docker-py tests/integration/api_image_test.py pass 4/16 + Test failures include services podman does not support Signed-off-by: Jhon Honce <jhonce@redhat.com> pods endpoint submission 2 add create and others; only top and stats is left. Signed-off-by: baude <bbaude@redhat.com> Update pull image to work from empty registry Signed-off-by: Jhon Honce <jhonce@redhat.com> pod create and container create first pass at pod and container create. the container create does not quite work yet but it is very close. pod create needs a partial rewrite. also broken off the DELETE (rm/rmi) to specific handler funcs. Signed-off-by: baude <bbaude@redhat.com> Add docker-py demos, GET .../containers/json * Update serviceapi/types to reflect libpod not podman * Refactored removeImage() to provide non-streaming return Signed-off-by: Jhon Honce <jhonce@redhat.com> create container part2 finished minimal config needed for create container. started demo.py for upcoming talk Signed-off-by: baude <bbaude@redhat.com> Stop server after honoring request * Remove casting for method calls * Improve WriteResponse() * Update Container API type to match docker API Signed-off-by: Jhon Honce <jhonce@redhat.com> fix namespace assumptions cleaned up namespace issues with libpod. Signed-off-by: baude <bbaude@redhat.com> wip Signed-off-by: baude <bbaude@redhat.com> Add sliding window when shutting down server * Added a Timeout rather than closing down service on each call * Added gorilla/schema dependency for Decode'ing query parameters * Improved error handling * Container logs returned and multiplexed for stdout and stderr * .../containers/{name}/logs?stdout=True&stderr=True * Container stats * .../containers/{name}/stats Signed-off-by: Jhon Honce <jhonce@redhat.com> Improve error handling * Add check for at least one std stream required for /containers/{id}/logs * Add check for state in /containers/{id}/top * Fill in more fields for /info * Fixed error checking in service start code Signed-off-by: Jhon Honce <jhonce@redhat.com> get rest of image tests for pass Signed-off-by: baude <bbaude@redhat.com> linting our content Signed-off-by: baude <bbaude@redhat.com> more linting Signed-off-by: baude <bbaude@redhat.com> more linting Signed-off-by: baude <bbaude@redhat.com> pruning Signed-off-by: baude <bbaude@redhat.com> [CI:DOCS]apiv2 pods migrate from using args in the url to using a json struct in body for pod create. Signed-off-by: baude <bbaude@redhat.com> fix handler_images prune prune's api changed slightly to deal with filters. Signed-off-by: baude <bbaude@redhat.com> [CI:DOCS]enabled base container create tests enabling the base container create tests which allow us to get more into the stop, kill, etc tests. many new tests now pass. Signed-off-by: baude <bbaude@redhat.com> serviceapi errors: append error message to API message I dearly hope this is not breaking any other tests but debugging "Internal Server Error" is not helpful to any user. In case, it breaks tests, we can rever the commit - that's why it's a small one. Signed-off-by: Valentin Rothberg <rothberg@redhat.com> serviceAPI: add containers/prune endpoint Signed-off-by: Valentin Rothberg <rothberg@redhat.com> add `service` make target Also remove the non-functional sub-Makefile. Signed-off-by: Valentin Rothberg <rothberg@redhat.com> add make targets for testing the service * `sudo make run-service` for running the service. * `DOCKERPY_TEST="tests/integration/api_container_test.py::ListContainersTest" \ make run-docker-py-tests` for running a specific tests. Run all tests by leaving the env variable empty. Signed-off-by: Valentin Rothberg <rothberg@redhat.com> Split handlers and server packages The files were split to help contain bloat. The api/server package will contain all code related to the functioning of the server while api/handlers will have all the code related to implementing the end points. api/server/register_* will contain the methods for registering endpoints. Additionally, they will have the comments for generating the swagger spec file. See api/handlers/version.go for a small example handler, api/handlers/containers.go contains much more complex handlers. Signed-off-by: Jhon Honce <jhonce@redhat.com> [CI:DOCS]enabled more tests Signed-off-by: baude <bbaude@redhat.com> [CI:DOCS]libpod endpoints small refactor for libpod inclusion and began adding endpoints. Signed-off-by: baude <bbaude@redhat.com> Implement /build and /events * Include crypto libraries for future ssh work Signed-off-by: Jhon Honce <jhonce@redhat.com> [CI:DOCS]more image implementations convert from using for to query structs among other changes including new endpoints. Signed-off-by: baude <bbaude@redhat.com> [CI:DOCS]add bindings for golang Signed-off-by: baude <bbaude@redhat.com> [CI:DOCS]add volume endpoints for libpod create, inspect, ls, prune, and rm Signed-off-by: baude <bbaude@redhat.com> [CI:DOCS]apiv2 healthcheck enablement wire up container healthchecks for the api. Signed-off-by: baude <bbaude@redhat.com> [CI:DOCS]Add mount endpoints via the api, allow ability to mount a container and list container mounts. Signed-off-by: baude <bbaude@redhat.com> [CI:DOCS]Add search endpoint add search endpoint with golang bindings Signed-off-by: baude <bbaude@redhat.com> [CI:DOCS]more apiv2 development misc population of methods, etc Signed-off-by: baude <bbaude@redhat.com> rebase cleanup and epoch reset Signed-off-by: baude <bbaude@redhat.com> [CI:DOCS]add more network endpoints also, add some initial error handling and convenience functions for standard endpoints. Signed-off-by: baude <bbaude@redhat.com> [CI:DOCS]use helper funcs for bindings use the methods developed to make writing bindings less duplicative and easier to use. Signed-off-by: baude <bbaude@redhat.com> [CI:DOCS]add return info for prereview begin to add return info and status codes for errors so that we can review the apiv2 Signed-off-by: baude <bbaude@redhat.com> [CI:DOCS]first pass at adding swagger docs for api Signed-off-by: baude <bbaude@redhat.com>
477 lines
14 KiB
Go
477 lines
14 KiB
Go
// +build !remoteclient
|
|
|
|
package adapter
|
|
|
|
import (
|
|
"bufio"
|
|
"context"
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
"text/template"
|
|
|
|
"github.com/containers/buildah"
|
|
"github.com/containers/buildah/imagebuildah"
|
|
"github.com/containers/buildah/pkg/formats"
|
|
"github.com/containers/buildah/pkg/parse"
|
|
"github.com/containers/image/v5/docker/reference"
|
|
"github.com/containers/image/v5/types"
|
|
"github.com/containers/libpod/cmd/podman/cliconfig"
|
|
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
|
"github.com/containers/libpod/cmd/podman/shared"
|
|
"github.com/containers/libpod/libpod"
|
|
"github.com/containers/libpod/libpod/define"
|
|
"github.com/containers/libpod/libpod/events"
|
|
"github.com/containers/libpod/libpod/image"
|
|
"github.com/containers/libpod/pkg/rootless"
|
|
"github.com/containers/libpod/pkg/util"
|
|
"github.com/containers/storage/pkg/archive"
|
|
"github.com/pkg/errors"
|
|
v1 "k8s.io/api/core/v1"
|
|
)
|
|
|
|
// LocalRuntime describes a typical libpod runtime
|
|
type LocalRuntime struct {
|
|
*libpod.Runtime
|
|
Remote bool
|
|
}
|
|
|
|
// ContainerImage ...
|
|
type ContainerImage struct {
|
|
*image.Image
|
|
}
|
|
|
|
// Container ...
|
|
type Container struct {
|
|
*libpod.Container
|
|
}
|
|
|
|
// Pod encapsulates the libpod.Pod structure, helps with remote vs. local
|
|
type Pod struct {
|
|
*libpod.Pod
|
|
}
|
|
|
|
// Volume ...
|
|
type Volume struct {
|
|
*libpod.Volume
|
|
}
|
|
|
|
// VolumeFilter is for filtering volumes on the client
|
|
type VolumeFilter func(*Volume) bool
|
|
|
|
// GetRuntimeNoStore returns a localruntime struct wit an embedded runtime but
|
|
// without a configured storage.
|
|
func GetRuntimeNoStore(ctx context.Context, c *cliconfig.PodmanCommand) (*LocalRuntime, error) {
|
|
runtime, err := libpodruntime.GetRuntimeNoStore(ctx, c)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return getRuntime(runtime)
|
|
}
|
|
|
|
// GetRuntime returns a LocalRuntime struct with the actual runtime embedded in it
|
|
func GetRuntime(ctx context.Context, c *cliconfig.PodmanCommand) (*LocalRuntime, error) {
|
|
runtime, err := libpodruntime.GetRuntime(ctx, c)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return getRuntime(runtime)
|
|
}
|
|
|
|
func getRuntime(runtime *libpod.Runtime) (*LocalRuntime, error) {
|
|
return &LocalRuntime{
|
|
Runtime: runtime,
|
|
}, nil
|
|
}
|
|
|
|
// GetFilteredImages returns a slice of images in containerimages that are "filtered"
|
|
func (r *LocalRuntime) GetFilteredImages(filters []string, rwOnly bool) ([]*ContainerImage, error) {
|
|
images, err := r.ImageRuntime().GetImagesWithFilters(filters)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return r.ImagestoContainerImages(images, rwOnly)
|
|
}
|
|
|
|
// GetImages returns a slice of images in containerimages
|
|
func (r *LocalRuntime) GetImages() ([]*ContainerImage, error) {
|
|
return r.getImages(false)
|
|
}
|
|
|
|
// GetRWImages returns a slice of read/write images in containerimages
|
|
func (r *LocalRuntime) GetRWImages() ([]*ContainerImage, error) {
|
|
return r.getImages(true)
|
|
}
|
|
|
|
func (r *LocalRuntime) getImages(rwOnly bool) ([]*ContainerImage, error) {
|
|
images, err := r.Runtime.ImageRuntime().GetImages()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return r.ImagestoContainerImages(images, rwOnly)
|
|
}
|
|
|
|
// ImagestoContainerImages converts the slice of *image.Image to a slice of
|
|
// *ContainerImage. ReadOnly images are skipped when rwOnly is set.
|
|
func (r *LocalRuntime) ImagestoContainerImages(images []*image.Image, rwOnly bool) ([]*ContainerImage, error) {
|
|
var containerImages []*ContainerImage
|
|
for _, i := range images {
|
|
if rwOnly && i.IsReadOnly() {
|
|
continue
|
|
}
|
|
containerImages = append(containerImages, &ContainerImage{i})
|
|
}
|
|
return containerImages, nil
|
|
}
|
|
|
|
// NewImageFromLocal returns a containerimage representation of a image from local storage
|
|
func (r *LocalRuntime) NewImageFromLocal(name string) (*ContainerImage, error) {
|
|
img, err := r.Runtime.ImageRuntime().NewFromLocal(name)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &ContainerImage{img}, nil
|
|
}
|
|
|
|
// LoadFromArchiveReference calls into local storage to load an image from an archive
|
|
func (r *LocalRuntime) LoadFromArchiveReference(ctx context.Context, srcRef types.ImageReference, signaturePolicyPath string, writer io.Writer) ([]*ContainerImage, error) {
|
|
var containerImages []*ContainerImage
|
|
imgs, err := r.Runtime.ImageRuntime().LoadFromArchiveReference(ctx, srcRef, signaturePolicyPath, writer)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, i := range imgs {
|
|
ci := ContainerImage{i}
|
|
containerImages = append(containerImages, &ci)
|
|
}
|
|
return containerImages, nil
|
|
}
|
|
|
|
// New calls into local storage to look for an image in local storage or to pull it
|
|
func (r *LocalRuntime) New(ctx context.Context, name, signaturePolicyPath, authfile string, writer io.Writer, dockeroptions *image.DockerRegistryOptions, signingoptions image.SigningOptions, label *string, pullType util.PullType) (*ContainerImage, error) {
|
|
img, err := r.Runtime.ImageRuntime().New(ctx, name, signaturePolicyPath, authfile, writer, dockeroptions, signingoptions, label, pullType)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &ContainerImage{img}, nil
|
|
}
|
|
|
|
// RemoveImage calls into local storage and removes an image
|
|
func (r *LocalRuntime) RemoveImage(ctx context.Context, img *ContainerImage, force bool) (*image.ImageDeleteResponse, error) {
|
|
return r.Runtime.RemoveImage(ctx, img.Image, force)
|
|
}
|
|
|
|
// PruneImages is wrapper into PruneImages within the image pkg
|
|
func (r *LocalRuntime) PruneImages(ctx context.Context, all bool, filter []string) ([]string, error) {
|
|
return r.ImageRuntime().PruneImages(ctx, all, filter)
|
|
}
|
|
|
|
// Export is a wrapper to container export to a tarfile
|
|
func (r *LocalRuntime) Export(name string, path string) error {
|
|
ctr, err := r.Runtime.LookupContainer(name)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "error looking up container %q", name)
|
|
}
|
|
return ctr.Export(path)
|
|
}
|
|
|
|
// Import is a wrapper to import a container image
|
|
func (r *LocalRuntime) Import(ctx context.Context, source, reference string, changes []string, history string, quiet bool) (string, error) {
|
|
return r.Runtime.Import(ctx, source, reference, changes, history, quiet)
|
|
}
|
|
|
|
// CreateVolume is a wrapper to create volumes
|
|
func (r *LocalRuntime) CreateVolume(ctx context.Context, c *cliconfig.VolumeCreateValues, labels, opts map[string]string) (string, error) {
|
|
var (
|
|
options []libpod.VolumeCreateOption
|
|
volName string
|
|
)
|
|
|
|
if len(c.InputArgs) > 0 {
|
|
volName = c.InputArgs[0]
|
|
options = append(options, libpod.WithVolumeName(volName))
|
|
}
|
|
|
|
if c.Flag("driver").Changed {
|
|
options = append(options, libpod.WithVolumeDriver(c.Driver))
|
|
}
|
|
|
|
if len(labels) != 0 {
|
|
options = append(options, libpod.WithVolumeLabels(labels))
|
|
}
|
|
|
|
if len(opts) != 0 {
|
|
// We need to process -o for uid, gid
|
|
parsedOptions, err := shared.ParseVolumeOptions(opts)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
options = append(options, parsedOptions...)
|
|
}
|
|
newVolume, err := r.NewVolume(ctx, options...)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return newVolume.Name(), nil
|
|
}
|
|
|
|
// RemoveVolumes is a wrapper to remove volumes
|
|
func (r *LocalRuntime) RemoveVolumes(ctx context.Context, c *cliconfig.VolumeRmValues) ([]string, map[string]error, error) {
|
|
return shared.SharedRemoveVolumes(ctx, r.Runtime, c.InputArgs, c.All, c.Force)
|
|
}
|
|
|
|
// Push is a wrapper to push an image to a registry
|
|
func (r *LocalRuntime) Push(ctx context.Context, srcName, destination, manifestMIMEType, authfile, digestfile, signaturePolicyPath string, writer io.Writer, forceCompress bool, signingOptions image.SigningOptions, dockerRegistryOptions *image.DockerRegistryOptions, additionalDockerArchiveTags []reference.NamedTagged) error {
|
|
newImage, err := r.ImageRuntime().NewFromLocal(srcName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return newImage.PushImageToHeuristicDestination(ctx, destination, manifestMIMEType, authfile, digestfile, signaturePolicyPath, writer, forceCompress, signingOptions, dockerRegistryOptions, nil)
|
|
}
|
|
|
|
// InspectVolumes returns a slice of volumes based on an arg list or --all
|
|
func (r *LocalRuntime) InspectVolumes(ctx context.Context, c *cliconfig.VolumeInspectValues) ([]*libpod.InspectVolumeData, error) {
|
|
var (
|
|
volumes []*libpod.Volume
|
|
err error
|
|
)
|
|
|
|
if c.All {
|
|
volumes, err = r.GetAllVolumes()
|
|
} else {
|
|
for _, v := range c.InputArgs {
|
|
vol, err := r.LookupVolume(v)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
volumes = append(volumes, vol)
|
|
}
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
inspectVols := make([]*libpod.InspectVolumeData, 0, len(volumes))
|
|
for _, vol := range volumes {
|
|
inspectOut, err := vol.Inspect()
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "error inspecting volume %s", vol.Name())
|
|
}
|
|
inspectVols = append(inspectVols, inspectOut)
|
|
}
|
|
|
|
return inspectVols, nil
|
|
}
|
|
|
|
// Volumes returns a slice of localruntime volumes
|
|
func (r *LocalRuntime) Volumes(ctx context.Context) ([]*Volume, error) {
|
|
vols, err := r.GetAllVolumes()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return libpodVolumeToVolume(vols), nil
|
|
}
|
|
|
|
// libpodVolumeToVolume converts a slice of libpod volumes to a slice
|
|
// of localruntime volumes (same as libpod)
|
|
func libpodVolumeToVolume(volumes []*libpod.Volume) []*Volume {
|
|
var vols []*Volume
|
|
for _, v := range volumes {
|
|
newVol := Volume{
|
|
v,
|
|
}
|
|
vols = append(vols, &newVol)
|
|
}
|
|
return vols
|
|
}
|
|
|
|
// Build is the wrapper to build images
|
|
func (r *LocalRuntime) Build(ctx context.Context, c *cliconfig.BuildValues, options imagebuildah.BuildOptions, dockerfiles []string) (string, reference.Canonical, error) {
|
|
namespaceOptions, networkPolicy, err := parse.NamespaceOptions(c.PodmanCommand.Command)
|
|
if err != nil {
|
|
return "", nil, errors.Wrapf(err, "error parsing namespace-related options")
|
|
}
|
|
usernsOption, idmappingOptions, err := parse.IDMappingOptions(c.PodmanCommand.Command, options.Isolation)
|
|
if err != nil {
|
|
return "", nil, errors.Wrapf(err, "error parsing ID mapping options")
|
|
}
|
|
namespaceOptions.AddOrReplace(usernsOption...)
|
|
|
|
systemContext, err := parse.SystemContextFromOptions(c.PodmanCommand.Command)
|
|
if err != nil {
|
|
return "", nil, errors.Wrapf(err, "error building system context")
|
|
}
|
|
|
|
authfile := c.Authfile
|
|
if len(c.Authfile) == 0 {
|
|
authfile = os.Getenv("REGISTRY_AUTH_FILE")
|
|
}
|
|
|
|
systemContext.AuthFilePath = authfile
|
|
commonOpts, err := parse.CommonBuildOptions(c.PodmanCommand.Command)
|
|
if err != nil {
|
|
return "", nil, err
|
|
}
|
|
|
|
options.NamespaceOptions = namespaceOptions
|
|
options.ConfigureNetwork = networkPolicy
|
|
options.IDMappingOptions = idmappingOptions
|
|
options.CommonBuildOpts = commonOpts
|
|
options.SystemContext = systemContext
|
|
|
|
if c.GlobalFlags.Runtime != "" {
|
|
options.Runtime = c.GlobalFlags.Runtime
|
|
} else {
|
|
options.Runtime = r.GetOCIRuntimePath()
|
|
}
|
|
|
|
if c.Quiet {
|
|
options.ReportWriter = ioutil.Discard
|
|
}
|
|
|
|
if rootless.IsRootless() {
|
|
options.Isolation = buildah.IsolationOCIRootless
|
|
}
|
|
|
|
return r.Runtime.Build(ctx, options, dockerfiles...)
|
|
}
|
|
|
|
// PruneVolumes is a wrapper function for libpod PruneVolumes
|
|
func (r *LocalRuntime) PruneVolumes(ctx context.Context) ([]string, []error) {
|
|
return r.Runtime.PruneVolumes(ctx)
|
|
}
|
|
|
|
// SaveImage is a wrapper function for saving an image to the local filesystem
|
|
func (r *LocalRuntime) SaveImage(ctx context.Context, c *cliconfig.SaveValues) error {
|
|
source := c.InputArgs[0]
|
|
additionalTags := c.InputArgs[1:]
|
|
|
|
newImage, err := r.Runtime.ImageRuntime().NewFromLocal(source)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return newImage.Save(ctx, source, c.Format, c.Output, additionalTags, c.Quiet, c.Compress)
|
|
}
|
|
|
|
// LoadImage is a wrapper function for libpod LoadImage
|
|
func (r *LocalRuntime) LoadImage(ctx context.Context, name string, cli *cliconfig.LoadValues) (string, error) {
|
|
var (
|
|
writer io.Writer
|
|
)
|
|
if !cli.Quiet {
|
|
writer = os.Stderr
|
|
}
|
|
return r.Runtime.LoadImage(ctx, name, cli.Input, writer, cli.SignaturePolicy)
|
|
}
|
|
|
|
// IsImageNotFound checks if the error indicates that no image was found.
|
|
func IsImageNotFound(err error) bool {
|
|
return errors.Cause(err) == image.ErrNoSuchImage
|
|
}
|
|
|
|
// HealthCheck is a wrapper to same named function in libpod
|
|
func (r *LocalRuntime) HealthCheck(c *cliconfig.HealthCheckValues) (string, error) {
|
|
output := "unhealthy"
|
|
status, err := r.Runtime.HealthCheck(c.InputArgs[0])
|
|
if status == libpod.HealthCheckSuccess {
|
|
output = "healthy"
|
|
}
|
|
return output, err
|
|
}
|
|
|
|
// Events is a wrapper to libpod to obtain libpod/podman events
|
|
func (r *LocalRuntime) Events(c *cliconfig.EventValues) error {
|
|
var (
|
|
fromStart bool
|
|
eventsError error
|
|
)
|
|
var tmpl *template.Template
|
|
if c.Format != formats.JSONString {
|
|
template, err := template.New("events").Parse(c.Format)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
tmpl = template
|
|
}
|
|
if len(c.Since) > 0 || len(c.Until) > 0 {
|
|
fromStart = true
|
|
}
|
|
eventChannel := make(chan *events.Event)
|
|
go func() {
|
|
readOpts := events.ReadOptions{FromStart: fromStart, Stream: c.Stream, Filters: c.Filter, EventChannel: eventChannel, Since: c.Since, Until: c.Until}
|
|
eventsError = r.Runtime.Events(readOpts)
|
|
}()
|
|
|
|
if eventsError != nil {
|
|
return eventsError
|
|
}
|
|
w := bufio.NewWriter(os.Stdout)
|
|
for event := range eventChannel {
|
|
if c.Format == formats.JSONString {
|
|
jsonStr, err := event.ToJSONString()
|
|
if err != nil {
|
|
return errors.Wrapf(err, "unable to format json")
|
|
}
|
|
if _, err := w.Write([]byte(jsonStr)); err != nil {
|
|
return err
|
|
}
|
|
} else if len(c.Format) > 0 {
|
|
if err := tmpl.Execute(w, event); err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
if _, err := w.Write([]byte(event.ToHumanReadable())); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if _, err := w.Write([]byte("\n")); err != nil {
|
|
return err
|
|
}
|
|
if err := w.Flush(); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Diff shows the difference in two objects
|
|
func (r *LocalRuntime) Diff(c *cliconfig.DiffValues, to string) ([]archive.Change, error) {
|
|
return r.Runtime.GetDiff("", to)
|
|
}
|
|
|
|
// GenerateKube creates kubernetes email from containers and pods
|
|
func (r *LocalRuntime) GenerateKube(c *cliconfig.GenerateKubeValues) (*v1.Pod, *v1.Service, error) {
|
|
return shared.GenerateKube(c.InputArgs[0], c.Service, r.Runtime)
|
|
}
|
|
|
|
// GetPodsByStatus returns a slice of pods filtered by a libpod status
|
|
func (r *LocalRuntime) GetPodsByStatus(statuses []string) ([]*libpod.Pod, error) {
|
|
|
|
filterFunc := func(p *libpod.Pod) bool {
|
|
state, _ := shared.GetPodStatus(p)
|
|
for _, status := range statuses {
|
|
if state == status {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
pods, err := r.Runtime.Pods(filterFunc)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return pods, nil
|
|
}
|
|
|
|
// GetVersion is an alias to satisfy interface{}
|
|
func (r *LocalRuntime) GetVersion() (define.Version, error) {
|
|
return define.GetVersion()
|
|
}
|
|
|
|
// RemoteEndpoint resolve interface requirement
|
|
func (r *LocalRuntime) RemoteEndpoint() (*Endpoint, error) {
|
|
return nil, errors.New("RemoteEndpoint() not implemented for local connection")
|
|
}
|