summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/api/handlers/compat/containers.go4
-rw-r--r--pkg/api/handlers/compat/containers_create.go8
-rw-r--r--pkg/api/handlers/compat/images.go4
-rw-r--r--pkg/api/handlers/compat/images_build.go12
-rw-r--r--pkg/api/handlers/compat/images_history.go2
-rw-r--r--pkg/api/handlers/compat/info.go4
-rw-r--r--pkg/api/handlers/compat/networks.go10
-rw-r--r--pkg/api/handlers/compat/ping.go4
-rw-r--r--pkg/api/handlers/compat/version.go4
-rw-r--r--pkg/api/handlers/decoder.go6
-rw-r--r--pkg/api/handlers/libpod/pods.go31
-rw-r--r--pkg/api/handlers/libpod/system.go2
-rw-r--r--pkg/api/handlers/libpod/volumes.go14
-rw-r--r--pkg/api/handlers/types.go17
-rw-r--r--pkg/api/handlers/utils/containers.go2
-rw-r--r--pkg/api/handlers/utils/handler.go24
-rw-r--r--pkg/api/handlers/utils/handler_test.go4
-rw-r--r--pkg/api/handlers/utils/images.go7
-rw-r--r--pkg/api/handlers/utils/pods.go10
-rw-r--r--pkg/api/server/docs.go25
-rw-r--r--pkg/api/server/handler_api.go6
-rw-r--r--pkg/api/server/server.go2
-rw-r--r--pkg/bindings/bindings.go3
-rw-r--r--pkg/bindings/connection.go23
-rw-r--r--pkg/bindings/containers/attach.go16
-rw-r--r--pkg/bindings/containers/checkpoint.go14
-rw-r--r--pkg/bindings/containers/commit.go6
-rw-r--r--pkg/bindings/containers/diff.go4
-rw-r--r--pkg/bindings/containers/types.go2
-rw-r--r--pkg/bindings/generate/generate.go2
-rw-r--r--pkg/bindings/images/diff.go4
-rw-r--r--pkg/bindings/images/images.go6
-rw-r--r--pkg/bindings/play/play.go2
-rw-r--r--pkg/bindings/system/system.go1
-rw-r--r--pkg/bindings/test/containers_test.go19
-rw-r--r--pkg/cgroups/cgroups.go4
-rw-r--r--pkg/cgroups/cpu.go3
-rw-r--r--pkg/domain/entities/container_ps.go6
-rw-r--r--pkg/domain/entities/containers.go36
-rw-r--r--pkg/domain/entities/engine.go4
-rw-r--r--pkg/domain/entities/engine_container.go24
-rw-r--r--pkg/domain/entities/engine_image.go14
-rw-r--r--pkg/domain/entities/filters.go24
-rw-r--r--pkg/domain/entities/generate.go2
-rw-r--r--pkg/domain/entities/images.go10
-rw-r--r--pkg/domain/entities/play.go14
-rw-r--r--pkg/domain/entities/pods.go46
-rw-r--r--pkg/domain/entities/set.go16
-rw-r--r--pkg/domain/entities/types.go4
-rw-r--r--pkg/domain/entities/volumes.go8
-rw-r--r--pkg/domain/infra/abi/containers.go182
-rw-r--r--pkg/domain/infra/abi/containers_runlabel.go12
-rw-r--r--pkg/domain/infra/abi/cp.go6
-rw-r--r--pkg/domain/infra/abi/generate.go161
-rw-r--r--pkg/domain/infra/abi/healthcheck.go4
-rw-r--r--pkg/domain/infra/abi/images.go41
-rw-r--r--pkg/domain/infra/abi/images_list.go9
-rw-r--r--pkg/domain/infra/abi/manifest.go4
-rw-r--r--pkg/domain/infra/abi/network.go7
-rw-r--r--pkg/domain/infra/abi/parse/parse.go2
-rw-r--r--pkg/domain/infra/abi/play.go109
-rw-r--r--pkg/domain/infra/abi/pods.go47
-rw-r--r--pkg/domain/infra/abi/system.go26
-rw-r--r--pkg/domain/infra/abi/trust.go8
-rw-r--r--pkg/domain/infra/abi/volumes.go23
-rw-r--r--pkg/domain/infra/runtime_abi.go4
-rw-r--r--pkg/domain/infra/runtime_tunnel.go4
-rw-r--r--pkg/domain/infra/tunnel/containers.go96
-rw-r--r--pkg/domain/infra/tunnel/generate.go2
-rw-r--r--pkg/domain/infra/tunnel/healthcheck.go4
-rw-r--r--pkg/domain/infra/tunnel/helpers.go16
-rw-r--r--pkg/domain/infra/tunnel/images.go36
-rw-r--r--pkg/domain/infra/tunnel/network.go4
-rw-r--r--pkg/domain/infra/tunnel/play.go2
-rw-r--r--pkg/domain/infra/tunnel/pods.go34
-rw-r--r--pkg/domain/infra/tunnel/volumes.go13
-rw-r--r--pkg/domain/utils/utils.go2
-rw-r--r--pkg/hooks/exec/runtimeconfigfilter_test.go54
-rw-r--r--pkg/lookup/lookup.go2
-rw-r--r--pkg/network/files.go11
-rw-r--r--pkg/network/network.go6
-rw-r--r--pkg/parallel/parallel_linux.go6
-rw-r--r--pkg/ps/ps.go2
-rw-r--r--pkg/signal/signal_linux.go2
-rw-r--r--pkg/spec/createconfig.go2
-rw-r--r--pkg/specgen/container_validate.go2
-rw-r--r--pkg/specgen/generate/container_create.go2
-rw-r--r--pkg/specgen/generate/namespaces.go4
-rw-r--r--pkg/specgen/generate/pod_create.go4
-rw-r--r--pkg/specgen/pod_validate.go2
-rw-r--r--pkg/specgen/podspecgen.go3
-rw-r--r--pkg/systemd/generate/common.go50
-rw-r--r--pkg/systemd/generate/common_test.go25
-rw-r--r--pkg/systemd/generate/containers.go307
-rw-r--r--pkg/systemd/generate/containers_test.go390
-rw-r--r--pkg/systemd/generate/pods.go356
-rw-r--r--pkg/systemd/generate/pods_test.go145
-rw-r--r--pkg/systemd/generate/systemdgen.go237
-rw-r--r--pkg/systemd/generate/systemdgen_test.go347
-rw-r--r--pkg/trust/config.go4
-rw-r--r--pkg/util/mountOpts.go3
-rw-r--r--pkg/varlinkapi/create.go4
-rw-r--r--pkg/varlinkapi/volumes.go2
103 files changed, 1974 insertions, 1375 deletions
diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go
index 1fd068ba6..8ce2180ab 100644
--- a/pkg/api/handlers/compat/containers.go
+++ b/pkg/api/handlers/compat/containers.go
@@ -348,7 +348,7 @@ func LogsFromContainer(w http.ResponseWriter, r *http.Request) {
}
func LibpodToContainer(l *libpod.Container, sz bool) (*handlers.Container, error) {
- imageId, imageName := l.Image()
+ imageID, imageName := l.Image()
var (
err error
@@ -378,7 +378,7 @@ func LibpodToContainer(l *libpod.Container, sz bool) (*handlers.Container, error
ID: l.ID(),
Names: []string{fmt.Sprintf("/%s", l.Name())},
Image: imageName,
- ImageID: imageId,
+ ImageID: imageID,
Command: strings.Join(l.Command(), " "),
Created: l.CreatedTime().Unix(),
Ports: nil,
diff --git a/pkg/api/handlers/compat/containers_create.go b/pkg/api/handlers/compat/containers_create.go
index 3d4bd4fb5..3ae9d9ab3 100644
--- a/pkg/api/handlers/compat/containers_create.go
+++ b/pkg/api/handlers/compat/containers_create.go
@@ -62,10 +62,8 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
func makeCreateConfig(containerConfig *config.Config, input handlers.CreateContainerConfig, newImage *image2.Image) (createconfig.CreateConfig, error) {
var (
- err error
- init bool
- tmpfs []string
- volumes []string
+ err error
+ init bool
)
env := make(map[string]string)
stopSignal := unix.SIGTERM
@@ -137,6 +135,7 @@ func makeCreateConfig(containerConfig *config.Config, input handlers.CreateConta
User: input.User,
}
pidConfig := createconfig.PidConfig{PidMode: namespaces.PidMode(input.HostConfig.PidMode)}
+ volumes := make([]string, 0, len(input.Volumes))
for k := range input.Volumes {
volumes = append(volumes, k)
}
@@ -158,6 +157,7 @@ func makeCreateConfig(containerConfig *config.Config, input handlers.CreateConta
}
// format the tmpfs mounts into a []string from map
+ tmpfs := make([]string, 0, len(input.HostConfig.Tmpfs))
for k, v := range input.HostConfig.Tmpfs {
tmpfs = append(tmpfs, fmt.Sprintf("%s:%s", k, v))
}
diff --git a/pkg/api/handlers/compat/images.go b/pkg/api/handlers/compat/images.go
index b64ed0036..ce9ff1b19 100644
--- a/pkg/api/handlers/compat/images.go
+++ b/pkg/api/handlers/compat/images.go
@@ -224,7 +224,7 @@ func CreateImageFromSrc(w http.ResponseWriter, r *http.Request) {
Status string `json:"status"`
Progress string `json:"progress"`
ProgressDetail map[string]string `json:"progressDetail"`
- Id string `json:"id"`
+ Id string `json:"id"` //nolint
}{
Status: iid,
ProgressDetail: map[string]string{},
@@ -289,7 +289,7 @@ func CreateImageFromImage(w http.ResponseWriter, r *http.Request) {
Error string `json:"error"`
Progress string `json:"progress"`
ProgressDetail map[string]string `json:"progressDetail"`
- Id string `json:"id"`
+ Id string `json:"id"` //nolint
}{
Status: fmt.Sprintf("pulling image (%s) from %s", img.Tag, strings.Join(img.Names(), ", ")),
ProgressDetail: map[string]string{},
diff --git a/pkg/api/handlers/compat/images_build.go b/pkg/api/handlers/compat/images_build.go
index e9d8fd719..399c104e9 100644
--- a/pkg/api/handlers/compat/images_build.go
+++ b/pkg/api/handlers/compat/images_build.go
@@ -36,6 +36,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
if hdr[0] != "application/x-tar" {
utils.BadRequest(w, "Content-Type", hdr[0],
fmt.Errorf("Content-Type: %s is not supported. Should be \"application/x-tar\"", hdr[0]))
+ return
}
}
@@ -59,10 +60,10 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
ForceRm bool `schema:"forcerm"`
Memory int64 `schema:"memory"`
MemSwap int64 `schema:"memswap"`
- CpuShares uint64 `schema:"cpushares"`
- CpuSetCpus string `schema:"cpusetcpus"`
- CpuPeriod uint64 `schema:"cpuperiod"`
- CpuQuota int64 `schema:"cpuquota"`
+ CpuShares uint64 `schema:"cpushares"` //nolint
+ CpuSetCpus string `schema:"cpusetcpus"` //nolint
+ CpuPeriod uint64 `schema:"cpuperiod"` //nolint
+ CpuQuota int64 `schema:"cpuquota"` //nolint
BuildArgs string `schema:"buildargs"`
ShmSize int `schema:"shmsize"`
Squash bool `schema:"squash"`
@@ -260,8 +261,7 @@ func extractTarFile(r *http.Request, w http.ResponseWriter) (string, error) {
r.Body.Close()
if err != nil {
- utils.InternalServerError(w,
- fmt.Errorf("failed Request: Unable to copy tar file from request body %s", r.RequestURI))
+ return "", fmt.Errorf("failed Request: Unable to copy tar file from request body %s", r.RequestURI)
}
_, _ = tarBall.Seek(0, 0)
diff --git a/pkg/api/handlers/compat/images_history.go b/pkg/api/handlers/compat/images_history.go
index afadf4c48..7c0bbf828 100644
--- a/pkg/api/handlers/compat/images_history.go
+++ b/pkg/api/handlers/compat/images_history.go
@@ -12,7 +12,6 @@ import (
func HistoryImage(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value("runtime").(*libpod.Runtime)
name := utils.GetName(r)
- var allHistory []handlers.HistoryResponse
newImage, err := runtime.ImageRuntime().NewFromLocal(name)
if err != nil {
@@ -25,6 +24,7 @@ func HistoryImage(w http.ResponseWriter, r *http.Request) {
utils.InternalServerError(w, err)
return
}
+ allHistory := make([]handlers.HistoryResponse, 0, len(history))
for _, h := range history {
l := handlers.HistoryResponse{
ID: h.ID,
diff --git a/pkg/api/handlers/compat/info.go b/pkg/api/handlers/compat/info.go
index e9756a03f..5c3f610a4 100644
--- a/pkg/api/handlers/compat/info.go
+++ b/pkg/api/handlers/compat/info.go
@@ -129,7 +129,7 @@ func GetInfo(w http.ResponseWriter, r *http.Request) {
}
func getGraphStatus(storeInfo map[string]string) [][2]string {
- var graphStatus [][2]string
+ graphStatus := make([][2]string, 0, len(storeInfo))
for k, v := range storeInfo {
graphStatus = append(graphStatus, [2]string{k, v})
}
@@ -177,7 +177,7 @@ func getContainersState(r *libpod.Runtime) map[define.ContainerStatus]int {
if err != nil {
continue
}
- states[state] += 1
+ states[state]++
}
}
return states
diff --git a/pkg/api/handlers/compat/networks.go b/pkg/api/handlers/compat/networks.go
index c52ca093f..0f1eca5e5 100644
--- a/pkg/api/handlers/compat/networks.go
+++ b/pkg/api/handlers/compat/networks.go
@@ -20,10 +20,6 @@ import (
"github.com/pkg/errors"
)
-type CompatInspectNetwork struct {
- types.NetworkResource
-}
-
func InspectNetwork(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value("runtime").(*libpod.Runtime)
@@ -166,9 +162,6 @@ func findPluginByName(plugins []*libcni.NetworkConfig, pluginType string) ([]byt
}
func ListNetworks(w http.ResponseWriter, r *http.Request) {
- var (
- reports []*types.NetworkResource
- )
runtime := r.Context().Value("runtime").(*libpod.Runtime)
decoder := r.Context().Value("decoder").(*schema.Decoder)
query := struct {
@@ -195,6 +188,7 @@ func ListNetworks(w http.ResponseWriter, r *http.Request) {
utils.InternalServerError(w, err)
return
}
+ reports := make([]*types.NetworkResource, 0, len(netNames))
for _, name := range netNames {
report, err := getNetworkResourceByName(name, runtime)
if err != nil {
@@ -219,7 +213,7 @@ func CreateNetwork(w http.ResponseWriter, r *http.Request) {
if len(networkCreate.Name) > 0 {
name = networkCreate.Name
}
- // At present I think we should just suport the bridge driver
+ // At present I think we should just support the bridge driver
// and allow demand to make us consider more
if networkCreate.Driver != network.DefaultNetworkDriver {
utils.InternalServerError(w, errors.New("network create only supports the bridge driver"))
diff --git a/pkg/api/handlers/compat/ping.go b/pkg/api/handlers/compat/ping.go
index abee3d8e8..d275c4a02 100644
--- a/pkg/api/handlers/compat/ping.go
+++ b/pkg/api/handlers/compat/ping.go
@@ -14,13 +14,13 @@ import (
// Clients will use the Header availability to test which backend engine is in use.
// Note: Additionally handler supports GET and HEAD methods
func Ping(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("API-Version", utils.ApiVersion[utils.CompatTree][utils.CurrentApiVersion].String())
+ w.Header().Set("API-Version", utils.APIVersion[utils.CompatTree][utils.CurrentAPIVersion].String())
w.Header().Set("BuildKit-Version", "")
w.Header().Set("Docker-Experimental", "true")
w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Pragma", "no-cache")
- w.Header().Set("Libpod-API-Version", utils.ApiVersion[utils.LibpodTree][utils.CurrentApiVersion].String())
+ w.Header().Set("Libpod-API-Version", utils.APIVersion[utils.LibpodTree][utils.CurrentAPIVersion].String())
w.Header().Set("Libpod-Buildha-Version", buildah.Version)
w.WriteHeader(http.StatusOK)
diff --git a/pkg/api/handlers/compat/version.go b/pkg/api/handlers/compat/version.go
index bfc226bb8..3164b16b9 100644
--- a/pkg/api/handlers/compat/version.go
+++ b/pkg/api/handlers/compat/version.go
@@ -34,14 +34,14 @@ func VersionHandler(w http.ResponseWriter, r *http.Request) {
Name: "Podman Engine",
Version: versionInfo.Version,
Details: map[string]string{
- "APIVersion": utils.ApiVersion[utils.LibpodTree][utils.CurrentApiVersion].String(),
+ "APIVersion": utils.APIVersion[utils.LibpodTree][utils.CurrentAPIVersion].String(),
"Arch": goRuntime.GOARCH,
"BuildTime": time.Unix(versionInfo.Built, 0).Format(time.RFC3339),
"Experimental": "true",
"GitCommit": versionInfo.GitCommit,
"GoVersion": versionInfo.GoVersion,
"KernelVersion": infoData.Host.Kernel,
- "MinAPIVersion": utils.ApiVersion[utils.LibpodTree][utils.MinimalApiVersion].String(),
+ "MinAPIVersion": utils.APIVersion[utils.LibpodTree][utils.MinimalAPIVersion].String(),
"Os": goRuntime.GOOS,
},
}}
diff --git a/pkg/api/handlers/decoder.go b/pkg/api/handlers/decoder.go
index 03b86275d..e46cd8837 100644
--- a/pkg/api/handlers/decoder.go
+++ b/pkg/api/handlers/decoder.go
@@ -17,7 +17,7 @@ func NewAPIDecoder() *schema.Decoder {
d := schema.NewDecoder()
d.IgnoreUnknownKeys(true)
- d.RegisterConverter(map[string][]string{}, convertUrlValuesString)
+ d.RegisterConverter(map[string][]string{}, convertURLValuesString)
d.RegisterConverter(time.Time{}, convertTimeString)
var Signal syscall.Signal
@@ -35,12 +35,12 @@ func NewAPIDecoder() *schema.Decoder {
// panic(err)
// }
// payload = url.QueryEscape(payload)
-func convertUrlValuesString(query string) reflect.Value {
+func convertURLValuesString(query string) reflect.Value {
f := map[string][]string{}
err := json.Unmarshal([]byte(query), &f)
if err != nil {
- logrus.Infof("convertUrlValuesString: Failed to Unmarshal %s: %s", query, err.Error())
+ logrus.Infof("convertURLValuesString: Failed to Unmarshal %s: %s", query, err.Error())
}
return reflect.ValueOf(f)
diff --git a/pkg/api/handlers/libpod/pods.go b/pkg/api/handlers/libpod/pods.go
index c3f8d5d66..4b57ef26a 100644
--- a/pkg/api/handlers/libpod/pods.go
+++ b/pkg/api/handlers/libpod/pods.go
@@ -17,6 +17,7 @@ import (
"github.com/containers/libpod/pkg/util"
"github.com/gorilla/schema"
"github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
)
func PodCreate(w http.ResponseWriter, r *http.Request) {
@@ -31,11 +32,11 @@ func PodCreate(w http.ResponseWriter, r *http.Request) {
}
pod, err := generate.MakePod(&psg, runtime)
if err != nil {
- http_code := http.StatusInternalServerError
+ httpCode := http.StatusInternalServerError
if errors.Cause(err) == define.ErrPodExists {
- http_code = http.StatusConflict
+ httpCode = http.StatusConflict
}
- utils.Error(w, "Something went wrong.", http_code, err)
+ utils.Error(w, "Something went wrong.", httpCode, err)
return
}
utils.WriteResponse(w, http.StatusCreated, handlers.IDResponse{ID: pod.ID()})
@@ -88,7 +89,6 @@ func PodStop(w http.ResponseWriter, r *http.Request) {
runtime = r.Context().Value("runtime").(*libpod.Runtime)
decoder = r.Context().Value("decoder").(*schema.Decoder)
responses map[string]error
- errs []error
)
query := struct {
Timeout int `schema:"t"`
@@ -127,6 +127,7 @@ func PodStop(w http.ResponseWriter, r *http.Request) {
utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
return
}
+ var errs []error //nolint
for _, err := range responses {
errs = append(errs, err)
}
@@ -138,9 +139,7 @@ func PodStop(w http.ResponseWriter, r *http.Request) {
}
func PodStart(w http.ResponseWriter, r *http.Request) {
- var (
- errs []error
- )
+ var errs []error //nolint
runtime := r.Context().Value("runtime").(*libpod.Runtime)
name := utils.GetName(r)
pod, err := runtime.LookupPod(name)
@@ -205,9 +204,7 @@ func PodDelete(w http.ResponseWriter, r *http.Request) {
}
func PodRestart(w http.ResponseWriter, r *http.Request) {
- var (
- errs []error
- )
+ var errs []error //nolint
runtime := r.Context().Value("runtime").(*libpod.Runtime)
name := utils.GetName(r)
pod, err := runtime.LookupPod(name)
@@ -242,12 +239,12 @@ func PodPrune(w http.ResponseWriter, r *http.Request) {
func PodPruneHelper(w http.ResponseWriter, r *http.Request) ([]*entities.PodPruneReport, error) {
var (
runtime = r.Context().Value("runtime").(*libpod.Runtime)
- reports []*entities.PodPruneReport
)
responses, err := runtime.PrunePods(r.Context())
if err != nil {
return nil, err
}
+ reports := make([]*entities.PodPruneReport, 0, len(responses))
for k, v := range responses {
reports = append(reports, &entities.PodPruneReport{
Err: v,
@@ -258,9 +255,7 @@ func PodPruneHelper(w http.ResponseWriter, r *http.Request) ([]*entities.PodPrun
}
func PodPause(w http.ResponseWriter, r *http.Request) {
- var (
- errs []error
- )
+ var errs []error //nolint
runtime := r.Context().Value("runtime").(*libpod.Runtime)
name := utils.GetName(r)
pod, err := runtime.LookupPod(name)
@@ -284,9 +279,7 @@ func PodPause(w http.ResponseWriter, r *http.Request) {
}
func PodUnpause(w http.ResponseWriter, r *http.Request) {
- var (
- errs []error
- )
+ var errs []error //nolint
runtime := r.Context().Value("runtime").(*libpod.Runtime)
name := utils.GetName(r)
pod, err := runtime.LookupPod(name)
@@ -356,7 +349,7 @@ func PodKill(w http.ResponseWriter, r *http.Request) {
runtime = r.Context().Value("runtime").(*libpod.Runtime)
decoder = r.Context().Value("decoder").(*schema.Decoder)
signal = "SIGKILL"
- errs []error
+ errs []error //nolint
)
query := struct {
Signal string `schema:"signal"`
@@ -375,6 +368,7 @@ func PodKill(w http.ResponseWriter, r *http.Request) {
sig, err := util.ParseSignal(signal)
if err != nil {
utils.InternalServerError(w, errors.Wrapf(err, "unable to parse signal value"))
+ return
}
name := utils.GetName(r)
pod, err := runtime.LookupPod(name)
@@ -382,6 +376,7 @@ func PodKill(w http.ResponseWriter, r *http.Request) {
utils.PodNotFound(w, name, err)
return
}
+ logrus.Debugf("Killing pod %s with signal %d", pod.ID(), sig)
podStates, err := pod.Status()
if err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
diff --git a/pkg/api/handlers/libpod/system.go b/pkg/api/handlers/libpod/system.go
index f575546c9..52d3b91ab 100644
--- a/pkg/api/handlers/libpod/system.go
+++ b/pkg/api/handlers/libpod/system.go
@@ -61,7 +61,7 @@ func SystemPrune(w http.ResponseWriter, r *http.Request) {
systemPruneReport.ImagePruneReport = &report
if query.Volumes {
- volumePruneReport, err := pruneVolumesHelper(w, r)
+ volumePruneReport, err := pruneVolumesHelper(r)
if err != nil {
utils.InternalServerError(w, err)
return
diff --git a/pkg/api/handlers/libpod/volumes.go b/pkg/api/handlers/libpod/volumes.go
index c42ca407b..ea035fc4d 100644
--- a/pkg/api/handlers/libpod/volumes.go
+++ b/pkg/api/handlers/libpod/volumes.go
@@ -46,7 +46,7 @@ func CreateVolume(w http.ResponseWriter, r *http.Request) {
volumeOptions = append(volumeOptions, libpod.WithVolumeLabels(input.Label))
}
if len(input.Options) > 0 {
- parsedOptions, err := parse.ParseVolumeOptions(input.Options)
+ parsedOptions, err := parse.VolumeOptions(input.Options)
if err != nil {
utils.InternalServerError(w, err)
return
@@ -102,9 +102,8 @@ func InspectVolume(w http.ResponseWriter, r *http.Request) {
func ListVolumes(w http.ResponseWriter, r *http.Request) {
var (
- decoder = r.Context().Value("decoder").(*schema.Decoder)
- runtime = r.Context().Value("runtime").(*libpod.Runtime)
- volumeConfigs []*entities.VolumeListReport
+ decoder = r.Context().Value("decoder").(*schema.Decoder)
+ runtime = r.Context().Value("runtime").(*libpod.Runtime)
)
query := struct {
Filters map[string][]string `schema:"filters"`
@@ -129,6 +128,7 @@ func ListVolumes(w http.ResponseWriter, r *http.Request) {
utils.InternalServerError(w, err)
return
}
+ volumeConfigs := make([]*entities.VolumeListReport, 0, len(vols))
for _, v := range vols {
config := entities.VolumeConfigResponse{
Name: v.Name(),
@@ -147,7 +147,7 @@ func ListVolumes(w http.ResponseWriter, r *http.Request) {
}
func PruneVolumes(w http.ResponseWriter, r *http.Request) {
- reports, err := pruneVolumesHelper(w, r)
+ reports, err := pruneVolumesHelper(r)
if err != nil {
utils.InternalServerError(w, err)
return
@@ -155,15 +155,15 @@ func PruneVolumes(w http.ResponseWriter, r *http.Request) {
utils.WriteResponse(w, http.StatusOK, reports)
}
-func pruneVolumesHelper(w http.ResponseWriter, r *http.Request) ([]*entities.VolumePruneReport, error) {
+func pruneVolumesHelper(r *http.Request) ([]*entities.VolumePruneReport, error) {
var (
runtime = r.Context().Value("runtime").(*libpod.Runtime)
- reports []*entities.VolumePruneReport
)
pruned, err := runtime.PruneVolumes(r.Context())
if err != nil {
return nil, err
}
+ reports := make([]*entities.VolumePruneReport, 0, len(pruned))
for k, v := range pruned {
reports = append(reports, &entities.VolumePruneReport{
Err: v,
diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go
index 79aeff2f8..c1e84ab5a 100644
--- a/pkg/api/handlers/types.go
+++ b/pkg/api/handlers/types.go
@@ -247,6 +247,7 @@ func ImageDataToImageInspect(ctx context.Context, l *libpodImage.Image) (*ImageI
if err != nil {
return nil, err
}
+
// TODO the rest of these still need wiring!
config := dockerContainer.Config{
// Hostname: "",
@@ -261,17 +262,17 @@ func ImageDataToImageInspect(ctx context.Context, l *libpodImage.Image) (*ImageI
// StdinOnce: false,
Env: info.Config.Env,
Cmd: info.Config.Cmd,
- // Healthcheck: nil,
+ //Healthcheck: l.ImageData.HealthCheck,
// ArgsEscaped: false,
// Image: "",
- // Volumes: nil,
- // WorkingDir: "",
- // Entrypoint: nil,
+ Volumes: info.Config.Volumes,
+ WorkingDir: info.Config.WorkingDir,
+ Entrypoint: info.Config.Entrypoint,
// NetworkDisabled: false,
// MacAddress: "",
- // OnBuild: nil,
- Labels: info.Labels,
- // StopSignal: "",
+ //OnBuild: info.Config.OnBuild,
+ Labels: info.Labels,
+ StopSignal: info.Config.StopSignal,
// StopTimeout: nil,
// Shell: nil,
}
@@ -285,7 +286,7 @@ func ImageDataToImageInspect(ctx context.Context, l *libpodImage.Image) (*ImageI
Comment: info.Comment,
Config: &config,
Created: l.Created().Format(time.RFC3339Nano),
- DockerVersion: "",
+ DockerVersion: info.Version,
GraphDriver: docker.GraphDriverData{},
ID: fmt.Sprintf("sha256:%s", l.ID()),
Metadata: docker.ImageMetadata{},
diff --git a/pkg/api/handlers/utils/containers.go b/pkg/api/handlers/utils/containers.go
index a46b308b5..4bcac6e72 100644
--- a/pkg/api/handlers/utils/containers.go
+++ b/pkg/api/handlers/utils/containers.go
@@ -62,7 +62,7 @@ func WaitContainer(w http.ResponseWriter, r *http.Request) (int32, error) {
func CreateContainer(ctx context.Context, w http.ResponseWriter, runtime *libpod.Runtime, cc *createconfig.CreateConfig) {
var pod *libpod.Pod
- ctr, err := createconfig.CreateContainerFromCreateConfig(runtime, cc, ctx, pod)
+ ctr, err := createconfig.CreateContainerFromCreateConfig(ctx, runtime, cc, pod)
if err != nil {
Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "CreateContainerFromCreateConfig()"))
return
diff --git a/pkg/api/handlers/utils/handler.go b/pkg/api/handlers/utils/handler.go
index 2f4a54b98..62fdc05dd 100644
--- a/pkg/api/handlers/utils/handler.go
+++ b/pkg/api/handlers/utils/handler.go
@@ -28,27 +28,27 @@ const (
// CompatTree supports Libpod endpoints
CompatTree
- // CurrentApiVersion announces what is the current API level
- CurrentApiVersion = VersionLevel(iota)
- // MinimalApiVersion announces what is the oldest API level supported
- MinimalApiVersion
+ // CurrentAPIVersion announces what is the current API level
+ CurrentAPIVersion = VersionLevel(iota)
+ // MinimalAPIVersion announces what is the oldest API level supported
+ MinimalAPIVersion
)
var (
// See https://docs.docker.com/engine/api/v1.40/
// libpod compat handlers are expected to honor docker API versions
- // ApiVersion provides the current and minimal API versions for compat and libpod endpoint trees
+ // APIVersion provides the current and minimal API versions for compat and libpod endpoint trees
// Note: GET|HEAD /_ping is never versioned and provides the API-Version and Libpod-API-Version headers to allow
// clients to shop for the Version they wish to support
- ApiVersion = map[VersionTree]map[VersionLevel]semver.Version{
+ APIVersion = map[VersionTree]map[VersionLevel]semver.Version{
LibpodTree: {
- CurrentApiVersion: semver.MustParse("1.0.0"),
- MinimalApiVersion: semver.MustParse("1.0.0"),
+ CurrentAPIVersion: semver.MustParse("1.0.0"),
+ MinimalAPIVersion: semver.MustParse("1.0.0"),
},
CompatTree: {
- CurrentApiVersion: semver.MustParse("1.40.0"),
- MinimalApiVersion: semver.MustParse("1.24.0"),
+ CurrentAPIVersion: semver.MustParse("1.40.0"),
+ MinimalAPIVersion: semver.MustParse("1.24.0"),
},
}
@@ -103,8 +103,8 @@ func SupportedVersionWithDefaults(r *http.Request) (semver.Version, error) {
}
return SupportedVersion(r,
- fmt.Sprintf(">=%s <=%s", ApiVersion[tree][MinimalApiVersion].String(),
- ApiVersion[tree][CurrentApiVersion].String()))
+ fmt.Sprintf(">=%s <=%s", APIVersion[tree][MinimalAPIVersion].String(),
+ APIVersion[tree][CurrentAPIVersion].String()))
}
// WriteResponse encodes the given value as JSON or string and renders it for http client
diff --git a/pkg/api/handlers/utils/handler_test.go b/pkg/api/handlers/utils/handler_test.go
index 6009432b5..d9fd22b80 100644
--- a/pkg/api/handlers/utils/handler_test.go
+++ b/pkg/api/handlers/utils/handler_test.go
@@ -12,12 +12,12 @@ import (
func TestSupportedVersion(t *testing.T) {
req, err := http.NewRequest("GET",
- fmt.Sprintf("/v%s/libpod/testing/versions", ApiVersion[LibpodTree][CurrentApiVersion]),
+ fmt.Sprintf("/v%s/libpod/testing/versions", APIVersion[LibpodTree][CurrentAPIVersion]),
nil)
if err != nil {
t.Fatal(err)
}
- req = mux.SetURLVars(req, map[string]string{"version": ApiVersion[LibpodTree][CurrentApiVersion].String()})
+ req = mux.SetURLVars(req, map[string]string{"version": APIVersion[LibpodTree][CurrentAPIVersion].String()})
rr := httptest.NewRecorder()
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
diff --git a/pkg/api/handlers/utils/images.go b/pkg/api/handlers/utils/images.go
index 7fb31a177..521f727be 100644
--- a/pkg/api/handlers/utils/images.go
+++ b/pkg/api/handlers/utils/images.go
@@ -3,6 +3,7 @@ package utils
import (
"fmt"
"net/http"
+ "strings"
"github.com/containers/image/v5/docker"
"github.com/containers/image/v5/storage"
@@ -77,9 +78,7 @@ func GetImages(w http.ResponseWriter, r *http.Request) ([]*image.Image, error) {
if len(query.Filters) > 0 {
for k, v := range query.Filters {
- for _, val := range v {
- filters = append(filters, fmt.Sprintf("%s=%s", k, val))
- }
+ filters = append(filters, fmt.Sprintf("%s=%s", k, strings.Join(v, "=")))
}
images, err = runtime.ImageRuntime().GetImagesWithFilters(filters)
if err != nil {
@@ -94,7 +93,7 @@ func GetImages(w http.ResponseWriter, r *http.Request) ([]*image.Image, error) {
if query.All {
return images, nil
}
- var returnImages []*image.Image
+ returnImages := []*image.Image{}
for _, img := range images {
if len(img.Names()) == 0 {
parent, err := img.IsParent(r.Context())
diff --git a/pkg/api/handlers/utils/pods.go b/pkg/api/handlers/utils/pods.go
index 5b6f6d34d..0bb818c1c 100644
--- a/pkg/api/handlers/utils/pods.go
+++ b/pkg/api/handlers/utils/pods.go
@@ -11,7 +11,6 @@ import (
func GetPods(w http.ResponseWriter, r *http.Request) ([]*entities.ListPodsReport, error) {
var (
- lps []*entities.ListPodsReport
pods []*libpod.Pod
filters []libpod.PodFilter
)
@@ -45,6 +44,11 @@ func GetPods(w http.ResponseWriter, r *http.Request) ([]*entities.ListPodsReport
return nil, err
}
+ if len(pods) == 0 {
+ return nil, nil
+ }
+
+ lps := make([]*entities.ListPodsReport, 0, len(pods))
for _, pod := range pods {
status, err := pod.GetPodStatus()
if err != nil {
@@ -54,7 +58,7 @@ func GetPods(w http.ResponseWriter, r *http.Request) ([]*entities.ListPodsReport
if err != nil {
return nil, err
}
- infraId, err := pod.InfraContainerID()
+ infraID, err := pod.InfraContainerID()
if err != nil {
return nil, err
}
@@ -65,7 +69,7 @@ func GetPods(w http.ResponseWriter, r *http.Request) ([]*entities.ListPodsReport
Name: pod.Name(),
Namespace: pod.Namespace(),
Status: status,
- InfraId: infraId,
+ InfraId: infraID,
Labels: pod.Labels(),
}
for _, ctr := range ctrs {
diff --git a/pkg/api/server/docs.go b/pkg/api/server/docs.go
index c989c7927..124c16092 100644
--- a/pkg/api/server/docs.go
+++ b/pkg/api/server/docs.go
@@ -4,6 +4,31 @@
// only as experimental as this point. The endpoints, parameters, inputs, and
// return values can all change.
//
+// To start the service and keep it running for 5,000 seconds (-t 0 runs forever):
+//
+// podman system service -t 5000 &
+//
+// You can then use cURL on the socket using requests documented below.
+//
+// NOTE: if you install the package podman-docker, it will create a symbolic
+// link for /var/run/docker.sock to /run/podman/podman.sock
+//
+// See podman-service(1) for more information.
+//
+// Quick Examples:
+//
+// 'podman info'
+//
+// curl --unix-socket /run/podman/podman.sock http://d/v1.0.0/libpod/info
+//
+// 'podman pull quay.io/containers/podman'
+//
+// curl -XPOST --unix-socket /run/podman/podman.sock -v 'http://d/v1.0.0/images/create?fromImage=quay.io%2Fcontainers%2Fpodman'
+//
+// 'podman list images'
+//
+// curl --unix-socket /run/podman/podman.sock -v 'http://d/v1.0.0/libpod/images/json' | jq
+//
// Terms Of Service:
//
// Schemes: http, https
diff --git a/pkg/api/server/handler_api.go b/pkg/api/server/handler_api.go
index 7a7db12f3..dbdb7f17b 100644
--- a/pkg/api/server/handler_api.go
+++ b/pkg/api/server/handler_api.go
@@ -34,9 +34,9 @@ func (s *APIServer) APIHandler(h http.HandlerFunc) http.HandlerFunc {
}
// TODO: Use r.ConnContext when ported to go 1.13
- c := context.WithValue(r.Context(), "decoder", s.Decoder)
- c = context.WithValue(c, "runtime", s.Runtime)
- c = context.WithValue(c, "shutdownFunc", s.Shutdown)
+ c := context.WithValue(r.Context(), "decoder", s.Decoder) //nolint
+ c = context.WithValue(c, "runtime", s.Runtime) //nolint
+ c = context.WithValue(c, "shutdownFunc", s.Shutdown) //nolint
r = r.WithContext(c)
h(w, r)
diff --git a/pkg/api/server/server.go b/pkg/api/server/server.go
index 499a4c58a..bd6a99b96 100644
--- a/pkg/api/server/server.go
+++ b/pkg/api/server/server.go
@@ -257,7 +257,7 @@ func (t *IdleTracker) ConnState(conn net.Conn, state http.ConnState) {
if oldActive == 0 {
t.timer.Stop()
}
- t.total += 1
+ t.total++
case http.StateIdle, http.StateClosed:
delete(t.active, conn)
// Restart the timer if we've become idle
diff --git a/pkg/bindings/bindings.go b/pkg/bindings/bindings.go
index da47ea713..94f7a45d0 100644
--- a/pkg/bindings/bindings.go
+++ b/pkg/bindings/bindings.go
@@ -5,7 +5,6 @@
// This package exposes a series of methods that allow users to firstly
// create their connection with the API endpoints. Once the connection
// is established, users can then manage the Podman container runtime.
-
package bindings
import (
@@ -28,7 +27,7 @@ var (
pFalse = false
PFalse = &pFalse
- // _*YES*- podman will fail to run if this value is wrong
+ // APIVersion - podman will fail to run if this value is wrong
APIVersion = semver.MustParse("1.0.0")
)
diff --git a/pkg/bindings/connection.go b/pkg/bindings/connection.go
index b130b9598..a9c61e5ae 100644
--- a/pkg/bindings/connection.go
+++ b/pkg/bindings/connection.go
@@ -41,7 +41,7 @@ type APIResponse struct {
}
type Connection struct {
- Uri *url.URL
+ URI *url.URL
Client *http.Client
}
@@ -115,12 +115,12 @@ func NewConnectionWithIdentity(ctx context.Context, uri string, passPhrase strin
_url.Path = JoinURL(_url.Host, _url.Path)
_url.Host = ""
}
- connection, err = unixClient(_url)
+ connection = unixClient(_url)
case "tcp":
if !strings.HasPrefix(uri, "tcp://") {
return nil, errors.New("tcp URIs should begin with tcp://")
}
- connection, err = tcpClient(_url)
+ connection = tcpClient(_url)
default:
return nil, errors.Errorf("'%s' is not a supported schema", _url.Scheme)
}
@@ -135,9 +135,9 @@ func NewConnectionWithIdentity(ctx context.Context, uri string, passPhrase strin
return ctx, nil
}
-func tcpClient(_url *url.URL) (Connection, error) {
+func tcpClient(_url *url.URL) Connection {
connection := Connection{
- Uri: _url,
+ URI: _url,
}
connection.Client = &http.Client{
Transport: &http.Transport{
@@ -147,7 +147,7 @@ func tcpClient(_url *url.URL) (Connection, error) {
DisableCompression: true,
},
}
- return connection, nil
+ return connection
}
// pingNewConnection pings to make sure the RESTFUL service is up
@@ -186,8 +186,7 @@ func pingNewConnection(ctx context.Context) error {
}
func sshClient(_url *url.URL, secure bool, passPhrase string, identities ...string) (Connection, error) {
- var authMethods []ssh.AuthMethod
-
+ authMethods := []ssh.AuthMethod{}
for _, i := range identities {
auth, err := publicKey(i, []byte(passPhrase))
if err != nil {
@@ -246,7 +245,7 @@ func sshClient(_url *url.URL, secure bool, passPhrase string, identities ...stri
return Connection{}, errors.Wrapf(err, "Connection to bastion host (%s) failed.", _url.String())
}
- connection := Connection{Uri: _url}
+ connection := Connection{URI: _url}
connection.Client = &http.Client{
Transport: &http.Transport{
DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
@@ -256,8 +255,8 @@ func sshClient(_url *url.URL, secure bool, passPhrase string, identities ...stri
return connection, nil
}
-func unixClient(_url *url.URL) (Connection, error) {
- connection := Connection{Uri: _url}
+func unixClient(_url *url.URL) Connection {
+ connection := Connection{URI: _url}
connection.Client = &http.Client{
Transport: &http.Transport{
DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
@@ -266,7 +265,7 @@ func unixClient(_url *url.URL) (Connection, error) {
DisableCompression: true,
},
}
- return connection, nil
+ return connection
}
// DoRequest assembles the http request and returns the response
diff --git a/pkg/bindings/containers/attach.go b/pkg/bindings/containers/attach.go
index b7f35c30d..44c7f4002 100644
--- a/pkg/bindings/containers/attach.go
+++ b/pkg/bindings/containers/attach.go
@@ -25,7 +25,7 @@ import (
)
// Attach attaches to a running container
-func Attach(ctx context.Context, nameOrId string, detachKeys *string, logs, stream *bool, stdin io.Reader, stdout io.Writer, stderr io.Writer, attachReady chan bool) error {
+func Attach(ctx context.Context, nameOrID string, detachKeys *string, logs, stream *bool, stdin io.Reader, stdout io.Writer, stderr io.Writer, attachReady chan bool) error {
isSet := struct {
stdin bool
stdout bool
@@ -52,7 +52,7 @@ func Attach(ctx context.Context, nameOrId string, detachKeys *string, logs, stre
}
// Do we need to wire in stdin?
- ctnr, err := Inspect(ctx, nameOrId, bindings.PFalse)
+ ctnr, err := Inspect(ctx, nameOrID, bindings.PFalse)
if err != nil {
return err
}
@@ -115,7 +115,7 @@ func Attach(ctx context.Context, nameOrId string, detachKeys *string, logs, stre
IdleConnTimeout: time.Duration(0),
}
conn.Client.Transport = t
- response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/attach", params, headers, nameOrId)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/attach", params, headers, nameOrID)
if err != nil {
return err
}
@@ -129,7 +129,7 @@ func Attach(ctx context.Context, nameOrId string, detachKeys *string, logs, stre
winCtx, winCancel := context.WithCancel(ctx)
defer winCancel()
- go attachHandleResize(ctx, winCtx, winChange, false, nameOrId, file)
+ go attachHandleResize(ctx, winCtx, winChange, false, nameOrID, file)
}
// If we are attaching around a start, we need to "signal"
@@ -243,13 +243,13 @@ func DemuxFrame(r io.Reader, buffer []byte, length int) (frame []byte, err error
}
// ResizeContainerTTY sets container's TTY height and width in characters
-func ResizeContainerTTY(ctx context.Context, nameOrId string, height *int, width *int) error {
- return resizeTTY(ctx, bindings.JoinURL("containers", nameOrId, "resize"), height, width)
+func ResizeContainerTTY(ctx context.Context, nameOrID string, height *int, width *int) error {
+ return resizeTTY(ctx, bindings.JoinURL("containers", nameOrID, "resize"), height, width)
}
// ResizeExecTTY sets session's TTY height and width in characters
-func ResizeExecTTY(ctx context.Context, nameOrId string, height *int, width *int) error {
- return resizeTTY(ctx, bindings.JoinURL("exec", nameOrId, "resize"), height, width)
+func ResizeExecTTY(ctx context.Context, nameOrID string, height *int, width *int) error {
+ return resizeTTY(ctx, bindings.JoinURL("exec", nameOrID, "resize"), height, width)
}
// resizeTTY set size of TTY of container
diff --git a/pkg/bindings/containers/checkpoint.go b/pkg/bindings/containers/checkpoint.go
index f483a9297..8a3932e80 100644
--- a/pkg/bindings/containers/checkpoint.go
+++ b/pkg/bindings/containers/checkpoint.go
@@ -10,9 +10,9 @@ import (
"github.com/containers/libpod/pkg/domain/entities"
)
-// Checkpoint checkpoints the given container (identified by nameOrId). All additional
+// Checkpoint checkpoints the given container (identified by nameOrID). All additional
// options are options and allow for more fine grained control of the checkpoint process.
-func Checkpoint(ctx context.Context, nameOrId string, keep, leaveRunning, tcpEstablished, ignoreRootFS *bool, export *string) (*entities.CheckpointReport, error) {
+func Checkpoint(ctx context.Context, nameOrID string, keep, leaveRunning, tcpEstablished, ignoreRootFS *bool, export *string) (*entities.CheckpointReport, error) {
var report entities.CheckpointReport
conn, err := bindings.GetClient(ctx)
if err != nil {
@@ -34,16 +34,16 @@ func Checkpoint(ctx context.Context, nameOrId string, keep, leaveRunning, tcpEst
if export != nil {
params.Set("export", *export)
}
- response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/checkpoint", params, nil, nameOrId)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/checkpoint", params, nil, nameOrID)
if err != nil {
return nil, err
}
return &report, response.Process(&report)
}
-// Restore restores a checkpointed container to running. The container is identified by the nameOrId option. All
-// additional options are optional and allow finer control of the restore processs.
-func Restore(ctx context.Context, nameOrId string, keep, tcpEstablished, ignoreRootFS, ignoreStaticIP, ignoreStaticMAC *bool, name, importArchive *string) (*entities.RestoreReport, error) {
+// Restore restores a checkpointed container to running. The container is identified by the nameOrID option. All
+// additional options are optional and allow finer control of the restore process.
+func Restore(ctx context.Context, nameOrID string, keep, tcpEstablished, ignoreRootFS, ignoreStaticIP, ignoreStaticMAC *bool, name, importArchive *string) (*entities.RestoreReport, error) {
var report entities.RestoreReport
conn, err := bindings.GetClient(ctx)
if err != nil {
@@ -71,7 +71,7 @@ func Restore(ctx context.Context, nameOrId string, keep, tcpEstablished, ignoreR
if importArchive != nil {
params.Set("import", *importArchive)
}
- response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/restore", params, nil, nameOrId)
+ response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/restore", params, nil, nameOrID)
if err != nil {
return nil, err
}
diff --git a/pkg/bindings/containers/commit.go b/pkg/bindings/containers/commit.go
index 780d42272..1a9ddc970 100644
--- a/pkg/bindings/containers/commit.go
+++ b/pkg/bindings/containers/commit.go
@@ -10,16 +10,16 @@ import (
"github.com/containers/libpod/pkg/bindings"
)
-// Commit creates a container image from a container. The container is defined by nameOrId. Use
+// Commit creates a container image from a container. The container is defined by nameOrID. Use
// the CommitOptions for finer grain control on characteristics of the resulting image.
-func Commit(ctx context.Context, nameOrId string, options CommitOptions) (handlers.IDResponse, error) {
+func Commit(ctx context.Context, nameOrID string, options CommitOptions) (handlers.IDResponse, error) {
id := handlers.IDResponse{}
conn, err := bindings.GetClient(ctx)
if err != nil {
return id, err
}
params := url.Values{}
- params.Set("container", nameOrId)
+ params.Set("container", nameOrID)
if options.Author != nil {
params.Set("author", *options.Author)
}
diff --git a/pkg/bindings/containers/diff.go b/pkg/bindings/containers/diff.go
index 06a828c30..e7a50248a 100644
--- a/pkg/bindings/containers/diff.go
+++ b/pkg/bindings/containers/diff.go
@@ -9,13 +9,13 @@ import (
)
// Diff provides the changes between two container layers
-func Diff(ctx context.Context, nameOrId string) ([]archive.Change, error) {
+func Diff(ctx context.Context, nameOrID string) ([]archive.Change, error) {
conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
}
- response, err := conn.DoRequest(nil, http.MethodGet, "/containers/%s/changes", nil, nil, nameOrId)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/containers/%s/changes", nil, nil, nameOrID)
if err != nil {
return nil, err
}
diff --git a/pkg/bindings/containers/types.go b/pkg/bindings/containers/types.go
index 31daaf565..f288c2944 100644
--- a/pkg/bindings/containers/types.go
+++ b/pkg/bindings/containers/types.go
@@ -12,7 +12,7 @@ type LogOptions struct {
Until *string
}
-// CommitOptions describe details about the resulting commited
+// CommitOptions describe details about the resulting committed
// image as defined by repo and tag. None of these options
// are required.
type CommitOptions struct {
diff --git a/pkg/bindings/generate/generate.go b/pkg/bindings/generate/generate.go
index 161b722f3..5e4be4896 100644
--- a/pkg/bindings/generate/generate.go
+++ b/pkg/bindings/generate/generate.go
@@ -10,7 +10,7 @@ import (
"github.com/containers/libpod/pkg/domain/entities"
)
-func GenerateKube(ctx context.Context, nameOrID string, options entities.GenerateKubeOptions) (*entities.GenerateKubeReport, error) {
+func Kube(ctx context.Context, nameOrID string, options entities.GenerateKubeOptions) (*entities.GenerateKubeReport, error) {
conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
diff --git a/pkg/bindings/images/diff.go b/pkg/bindings/images/diff.go
index e2d344ea0..25cbde188 100644
--- a/pkg/bindings/images/diff.go
+++ b/pkg/bindings/images/diff.go
@@ -9,13 +9,13 @@ import (
)
// Diff provides the changes between two container layers
-func Diff(ctx context.Context, nameOrId string) ([]archive.Change, error) {
+func Diff(ctx context.Context, nameOrID string) ([]archive.Change, error) {
conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
}
- response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/changes", nil, nil, nameOrId)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/changes", nil, nil, nameOrID)
if err != nil {
return nil, err
}
diff --git a/pkg/bindings/images/images.go b/pkg/bindings/images/images.go
index e0802a6e1..9cb6a0ac5 100644
--- a/pkg/bindings/images/images.go
+++ b/pkg/bindings/images/images.go
@@ -80,7 +80,7 @@ func GetImage(ctx context.Context, nameOrID string, size *bool) (*entities.Image
}
// Tree retrieves a "tree" based representation of the given image
-func Tree(ctx context.Context, nameOrId string, whatRequires *bool) (*entities.ImageTreeReport, error) {
+func Tree(ctx context.Context, nameOrID string, whatRequires *bool) (*entities.ImageTreeReport, error) {
var report entities.ImageTreeReport
conn, err := bindings.GetClient(ctx)
if err != nil {
@@ -90,7 +90,7 @@ func Tree(ctx context.Context, nameOrId string, whatRequires *bool) (*entities.I
if whatRequires != nil {
params.Set("size", strconv.FormatBool(*whatRequires))
}
- response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/tree", params, nil, nameOrId)
+ response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/tree", params, nil, nameOrID)
if err != nil {
return nil, err
}
@@ -394,7 +394,7 @@ func Pull(ctx context.Context, rawImage string, options entities.ImagePullOption
}
// Push is the binding for libpod's v2 endpoints for push images. Note that
-// `source` must be a refering to an image in the remote's container storage.
+// `source` must be a referring to an image in the remote's container storage.
// The destination must be a reference to a registry (i.e., of docker transport
// or be normalized to one). Other transports are rejected as they do not make
// sense in a remote context.
diff --git a/pkg/bindings/play/play.go b/pkg/bindings/play/play.go
index 288cca454..9a4f56b6d 100644
--- a/pkg/bindings/play/play.go
+++ b/pkg/bindings/play/play.go
@@ -13,7 +13,7 @@ import (
"github.com/containers/libpod/pkg/domain/entities"
)
-func PlayKube(ctx context.Context, path string, options entities.PlayKubeOptions) (*entities.PlayKubeReport, error) {
+func Kube(ctx context.Context, path string, options entities.PlayKubeOptions) (*entities.PlayKubeReport, error) {
var report entities.PlayKubeReport
conn, err := bindings.GetClient(ctx)
if err != nil {
diff --git a/pkg/bindings/system/system.go b/pkg/bindings/system/system.go
index 010762bef..b2ee3951b 100644
--- a/pkg/bindings/system/system.go
+++ b/pkg/bindings/system/system.go
@@ -125,6 +125,7 @@ func Version(ctx context.Context) (*entities.SystemVersionReport, error) {
Version: component.Version.Version,
GoVersion: component.GoVersion,
GitCommit: component.GitCommit,
+ BuiltTime: time.Unix(b.Unix(), 0).Format(time.ANSIC),
Built: b.Unix(),
OsArch: fmt.Sprintf("%s/%s", component.Os, component.Arch),
}
diff --git a/pkg/bindings/test/containers_test.go b/pkg/bindings/test/containers_test.go
index 3b94b10eb..b987f0442 100644
--- a/pkg/bindings/test/containers_test.go
+++ b/pkg/bindings/test/containers_test.go
@@ -739,4 +739,23 @@ var _ = Describe("Podman containers ", func() {
//Expect(code).To(BeNumerically("==", http.StatusInternalServerError))
})
+ It("List containers with filters", func() {
+ var name = "top"
+ var name2 = "top2"
+ cid, err := bt.RunTopContainer(&name, bindings.PFalse, nil)
+ Expect(err).To(BeNil())
+ _, err = bt.RunTopContainer(&name2, bindings.PFalse, nil)
+ Expect(err).To(BeNil())
+ s := specgen.NewSpecGenerator(alpine.name, false)
+ s.Terminal = true
+ s.Command = []string{"date", "-R"}
+ _, err = containers.CreateWithSpec(bt.conn, s)
+ Expect(err).To(BeNil())
+ // Validate list container with id filter
+ filters := make(map[string][]string)
+ filters["id"] = []string{cid}
+ c, err := containers.List(bt.conn, filters, bindings.PTrue, nil, nil, nil, nil)
+ Expect(err).To(BeNil())
+ Expect(len(c)).To(Equal(1))
+ })
})
diff --git a/pkg/cgroups/cgroups.go b/pkg/cgroups/cgroups.go
index 3b56f944f..399072108 100644
--- a/pkg/cgroups/cgroups.go
+++ b/pkg/cgroups/cgroups.go
@@ -133,7 +133,7 @@ func getAvailableControllers(exclude map[string]controllerHandler, cgroup2 bool)
if err != nil {
return nil, errors.Wrapf(err, "read directory %s", cgroupRoot)
}
- var controllers []controller
+ controllers := []controller{}
for _, i := range infos {
name := i.Name()
if _, found := exclude[name]; found {
@@ -505,7 +505,7 @@ func (c *CgroupControl) AddPid(pid int) error {
return nil
}
- var names []string
+ names := make([]string, 0, len(handlers))
for n := range handlers {
names = append(names, n)
}
diff --git a/pkg/cgroups/cpu.go b/pkg/cgroups/cpu.go
index 5f0a18031..3745c6e50 100644
--- a/pkg/cgroups/cpu.go
+++ b/pkg/cgroups/cpu.go
@@ -29,13 +29,12 @@ func readAcct(ctr *CgroupControl, name string) (uint64, error) {
}
func readAcctList(ctr *CgroupControl, name string) ([]uint64, error) {
- var r []uint64
-
p := filepath.Join(ctr.getCgroupv1Path(CPUAcct), name)
data, err := ioutil.ReadFile(p)
if err != nil {
return nil, errors.Wrapf(err, "reading %s", p)
}
+ r := []uint64{}
for _, s := range strings.Split(string(data), " ") {
s = cleanString(s)
if s == "" {
diff --git a/pkg/domain/entities/container_ps.go b/pkg/domain/entities/container_ps.go
index fd94d93be..c5e11f188 100644
--- a/pkg/domain/entities/container_ps.go
+++ b/pkg/domain/entities/container_ps.go
@@ -85,9 +85,9 @@ func (a psSortedCommand) Less(i, j int) bool {
return strings.Join(a.SortListContainers[i].Command, " ") < strings.Join(a.SortListContainers[j].Command, " ")
}
-type psSortedId struct{ SortListContainers }
+type psSortedID struct{ SortListContainers }
-func (a psSortedId) Less(i, j int) bool {
+func (a psSortedID) Less(i, j int) bool {
return a.SortListContainers[i].ID < a.SortListContainers[j].ID
}
@@ -139,7 +139,7 @@ func (a PsSortedCreateTime) Less(i, j int) bool {
func SortPsOutput(sortBy string, psOutput SortListContainers) (SortListContainers, error) {
switch sortBy {
case "id":
- sort.Sort(psSortedId{psOutput})
+ sort.Sort(psSortedID{psOutput})
case "image":
sort.Sort(psSortedImage{psOutput})
case "command":
diff --git a/pkg/domain/entities/containers.go b/pkg/domain/entities/containers.go
index 8d85a9b23..b4d8e6c29 100644
--- a/pkg/domain/entities/containers.go
+++ b/pkg/domain/entities/containers.go
@@ -56,7 +56,7 @@ type WaitOptions struct {
}
type WaitReport struct {
- Id string
+ Id string //nolint
Error error
ExitCode int32
}
@@ -76,7 +76,7 @@ type PauseUnPauseOptions struct {
type PauseUnpauseReport struct {
Err error
- Id string
+ Id string //nolint
}
type StopOptions struct {
@@ -84,12 +84,12 @@ type StopOptions struct {
CIDFiles []string
Ignore bool
Latest bool
- Timeout uint
+ Timeout *uint
}
type StopReport struct {
Err error
- Id string
+ Id string //nolint
}
type TopOptions struct {
@@ -110,7 +110,7 @@ type KillOptions struct {
type KillReport struct {
Err error
- Id string
+ Id string //nolint
}
type RestartOptions struct {
@@ -122,7 +122,7 @@ type RestartOptions struct {
type RestartReport struct {
Err error
- Id string
+ Id string //nolint
}
type RmOptions struct {
@@ -137,7 +137,7 @@ type RmOptions struct {
type RmReport struct {
Err error
- Id string
+ Id string //nolint
}
type ContainerInspectReport struct {
@@ -157,7 +157,7 @@ type CommitOptions struct {
}
type CommitReport struct {
- Id string
+ Id string //nolint
}
type ContainerExportOptions struct {
@@ -176,7 +176,7 @@ type CheckpointOptions struct {
type CheckpointReport struct {
Err error
- Id string
+ Id string //nolint
}
type RestoreOptions struct {
@@ -193,11 +193,11 @@ type RestoreOptions struct {
type RestoreReport struct {
Err error
- Id string
+ Id string //nolint
}
type ContainerCreateReport struct {
- Id string
+ Id string //nolint
}
// AttachOptions describes the cli and other values
@@ -263,7 +263,7 @@ type ContainerStartOptions struct {
// ContainerStartReport describes the response from starting
// containers from the cli
type ContainerStartReport struct {
- Id string
+ Id string //nolint
RawInput string
Err error
ExitCode int
@@ -303,7 +303,7 @@ type ContainerRunOptions struct {
// a container
type ContainerRunReport struct {
ExitCode int
- Id string
+ Id string //nolint
}
// ContainerCleanupOptions are the CLI values for the
@@ -320,7 +320,7 @@ type ContainerCleanupOptions struct {
// container cleanup
type ContainerCleanupReport struct {
CleanErr error
- Id string
+ Id string //nolint
RmErr error
RmiErr error
}
@@ -336,7 +336,7 @@ type ContainerInitOptions struct {
// container init
type ContainerInitReport struct {
Err error
- Id string
+ Id string //nolint
}
//ContainerMountOptions describes the input values for mounting containers
@@ -358,7 +358,7 @@ type ContainerUnmountOptions struct {
// ContainerMountReport describes the response from container mount
type ContainerMountReport struct {
Err error
- Id string
+ Id string //nolint
Name string
Path string
}
@@ -366,7 +366,7 @@ type ContainerMountReport struct {
// ContainerUnmountReport describes the response from umounting a container
type ContainerUnmountReport struct {
Err error
- Id string
+ Id string //nolint
}
// ContainerPruneOptions describes the options needed
@@ -392,7 +392,7 @@ type ContainerPortOptions struct {
// ContainerPortReport describes the output needed for
// the CLI to output ports
type ContainerPortReport struct {
- Id string
+ Id string //nolint
Ports []ocicni.PortMapping
}
diff --git a/pkg/domain/entities/engine.go b/pkg/domain/entities/engine.go
index b2bef0eea..1f056bad7 100644
--- a/pkg/domain/entities/engine.go
+++ b/pkg/domain/entities/engine.go
@@ -39,7 +39,7 @@ type PodmanConfig struct {
CGroupUsage string // rootless code determines Usage message
ConmonPath string // --conmon flag will set Engine.ConmonPath
- CpuProfile string // Hidden: Should CPU profile be taken
+ CPUProfile string // Hidden: Should CPU profile be taken
EngineMode EngineMode // ABI or Tunneling mode
Identities []string // ssh identities for connecting to server
MaxWorks int // maximum number of parallel threads
@@ -52,7 +52,7 @@ type PodmanConfig struct {
SpanCtx context.Context // context to use when tracing
Syslog bool // write to StdOut and Syslog, not supported when tunneling
Trace bool // Hidden: Trace execution
- Uri string // URI to RESTful API Service
+ URI string // URI to RESTful API Service
Runroot string
StorageDriver string
diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go
index 3d5161745..979df7581 100644
--- a/pkg/domain/entities/engine_container.go
+++ b/pkg/domain/entities/engine_container.go
@@ -12,25 +12,25 @@ import (
type ContainerEngine interface {
AutoUpdate(ctx context.Context, options AutoUpdateOptions) (*AutoUpdateReport, []error)
Config(ctx context.Context) (*config.Config, error)
- ContainerAttach(ctx context.Context, nameOrId string, options AttachOptions) error
+ ContainerAttach(ctx context.Context, nameOrID string, options AttachOptions) error
ContainerCheckpoint(ctx context.Context, namesOrIds []string, options CheckpointOptions) ([]*CheckpointReport, error)
ContainerCleanup(ctx context.Context, namesOrIds []string, options ContainerCleanupOptions) ([]*ContainerCleanupReport, error)
- ContainerCommit(ctx context.Context, nameOrId string, options CommitOptions) (*CommitReport, error)
+ ContainerCommit(ctx context.Context, nameOrID string, options CommitOptions) (*CommitReport, error)
ContainerCp(ctx context.Context, source, dest string, options ContainerCpOptions) (*ContainerCpReport, error)
ContainerCreate(ctx context.Context, s *specgen.SpecGenerator) (*ContainerCreateReport, error)
- ContainerDiff(ctx context.Context, nameOrId string, options DiffOptions) (*DiffReport, error)
- ContainerExec(ctx context.Context, nameOrId string, options ExecOptions, streams define.AttachStreams) (int, error)
+ ContainerDiff(ctx context.Context, nameOrID string, options DiffOptions) (*DiffReport, error)
+ ContainerExec(ctx context.Context, nameOrID string, options ExecOptions, streams define.AttachStreams) (int, error)
ContainerExecDetached(ctx context.Context, nameOrID string, options ExecOptions) (string, error)
- ContainerExists(ctx context.Context, nameOrId string) (*BoolReport, error)
- ContainerExport(ctx context.Context, nameOrId string, options ContainerExportOptions) error
+ ContainerExists(ctx context.Context, nameOrID string) (*BoolReport, error)
+ ContainerExport(ctx context.Context, nameOrID string, options ContainerExportOptions) error
ContainerInit(ctx context.Context, namesOrIds []string, options ContainerInitOptions) ([]*ContainerInitReport, error)
ContainerInspect(ctx context.Context, namesOrIds []string, options InspectOptions) ([]*ContainerInspectReport, error)
ContainerKill(ctx context.Context, namesOrIds []string, options KillOptions) ([]*KillReport, error)
ContainerList(ctx context.Context, options ContainerListOptions) ([]ListContainer, error)
ContainerLogs(ctx context.Context, containers []string, options ContainerLogsOptions) error
- ContainerMount(ctx context.Context, nameOrIds []string, options ContainerMountOptions) ([]*ContainerMountReport, error)
+ ContainerMount(ctx context.Context, nameOrIDs []string, options ContainerMountOptions) ([]*ContainerMountReport, error)
ContainerPause(ctx context.Context, namesOrIds []string, options PauseUnPauseOptions) ([]*PauseUnpauseReport, error)
- ContainerPort(ctx context.Context, nameOrId string, options ContainerPortOptions) ([]*ContainerPortReport, error)
+ ContainerPort(ctx context.Context, nameOrID string, options ContainerPortOptions) ([]*ContainerPortReport, error)
ContainerPrune(ctx context.Context, options ContainerPruneOptions) (*ContainerPruneReport, error)
ContainerRestart(ctx context.Context, namesOrIds []string, options RestartOptions) ([]*RestartReport, error)
ContainerRestore(ctx context.Context, namesOrIds []string, options RestoreOptions) ([]*RestoreReport, error)
@@ -41,14 +41,14 @@ type ContainerEngine interface {
ContainerStats(ctx context.Context, namesOrIds []string, options ContainerStatsOptions) error
ContainerStop(ctx context.Context, namesOrIds []string, options StopOptions) ([]*StopReport, error)
ContainerTop(ctx context.Context, options TopOptions) (*StringSliceReport, error)
- ContainerUnmount(ctx context.Context, nameOrIds []string, options ContainerUnmountOptions) ([]*ContainerUnmountReport, error)
+ ContainerUnmount(ctx context.Context, nameOrIDs []string, options ContainerUnmountOptions) ([]*ContainerUnmountReport, error)
ContainerUnpause(ctx context.Context, namesOrIds []string, options PauseUnPauseOptions) ([]*PauseUnpauseReport, error)
ContainerWait(ctx context.Context, namesOrIds []string, options WaitOptions) ([]WaitReport, error)
Events(ctx context.Context, opts EventsOptions) error
GenerateSystemd(ctx context.Context, nameOrID string, opts GenerateSystemdOptions) (*GenerateSystemdReport, error)
GenerateKube(ctx context.Context, nameOrID string, opts GenerateKubeOptions) (*GenerateKubeReport, error)
SystemPrune(ctx context.Context, options SystemPruneOptions) (*SystemPruneReport, error)
- HealthCheckRun(ctx context.Context, nameOrId string, options HealthCheckOptions) (*define.HealthCheckResults, error)
+ HealthCheckRun(ctx context.Context, nameOrID string, options HealthCheckOptions) (*define.HealthCheckResults, error)
Info(ctx context.Context) (*define.Info, error)
NetworkCreate(ctx context.Context, name string, options NetworkCreateOptions) (*NetworkCreateReport, error)
NetworkInspect(ctx context.Context, namesOrIds []string, options NetworkInspectOptions) ([]NetworkInspectReport, error)
@@ -56,7 +56,7 @@ type ContainerEngine interface {
NetworkRm(ctx context.Context, namesOrIds []string, options NetworkRmOptions) ([]*NetworkRmReport, error)
PlayKube(ctx context.Context, path string, opts PlayKubeOptions) (*PlayKubeReport, error)
PodCreate(ctx context.Context, opts PodCreateOptions) (*PodCreateReport, error)
- PodExists(ctx context.Context, nameOrId string) (*BoolReport, error)
+ PodExists(ctx context.Context, nameOrID string) (*BoolReport, error)
PodInspect(ctx context.Context, options PodInspectOptions) (*PodInspectReport, error)
PodKill(ctx context.Context, namesOrIds []string, options PodKillOptions) ([]*PodKillReport, error)
PodPause(ctx context.Context, namesOrIds []string, options PodPauseOptions) ([]*PodPauseReport, error)
@@ -75,7 +75,7 @@ type ContainerEngine interface {
Unshare(ctx context.Context, args []string) error
VarlinkService(ctx context.Context, opts ServiceOptions) error
Version(ctx context.Context) (*SystemVersionReport, error)
- VolumeCreate(ctx context.Context, opts VolumeCreateOptions) (*IdOrNameResponse, error)
+ VolumeCreate(ctx context.Context, opts VolumeCreateOptions) (*IDOrNameResponse, error)
VolumeInspect(ctx context.Context, namesOrIds []string, opts VolumeInspectOptions) ([]*VolumeInspectReport, error)
VolumeList(ctx context.Context, opts VolumeListOptions) ([]*VolumeListReport, error)
VolumePrune(ctx context.Context, opts VolumePruneOptions) ([]*VolumePruneReport, error)
diff --git a/pkg/domain/entities/engine_image.go b/pkg/domain/entities/engine_image.go
index 7d7099838..60fb20b6e 100644
--- a/pkg/domain/entities/engine_image.go
+++ b/pkg/domain/entities/engine_image.go
@@ -9,9 +9,9 @@ import (
type ImageEngine interface {
Build(ctx context.Context, containerFiles []string, opts BuildOptions) (*BuildReport, error)
Config(ctx context.Context) (*config.Config, error)
- Diff(ctx context.Context, nameOrId string, options DiffOptions) (*DiffReport, error)
- Exists(ctx context.Context, nameOrId string) (*BoolReport, error)
- History(ctx context.Context, nameOrId string, opts ImageHistoryOptions) (*ImageHistoryReport, error)
+ Diff(ctx context.Context, nameOrID string, options DiffOptions) (*DiffReport, error)
+ Exists(ctx context.Context, nameOrID string) (*BoolReport, error)
+ History(ctx context.Context, nameOrID string, opts ImageHistoryOptions) (*ImageHistoryReport, error)
Import(ctx context.Context, opts ImageImportOptions) (*ImageImportReport, error)
Inspect(ctx context.Context, namesOrIDs []string, opts InspectOptions) ([]*ImageInspectReport, error)
List(ctx context.Context, opts ImageListOptions) ([]*ImageSummary, error)
@@ -20,14 +20,14 @@ type ImageEngine interface {
Pull(ctx context.Context, rawImage string, opts ImagePullOptions) (*ImagePullReport, error)
Push(ctx context.Context, source string, destination string, opts ImagePushOptions) error
Remove(ctx context.Context, images []string, opts ImageRemoveOptions) (*ImageRemoveReport, []error)
- Save(ctx context.Context, nameOrId string, tags []string, options ImageSaveOptions) error
+ Save(ctx context.Context, nameOrID string, tags []string, options ImageSaveOptions) error
Search(ctx context.Context, term string, opts ImageSearchOptions) ([]ImageSearchReport, error)
SetTrust(ctx context.Context, args []string, options SetTrustOptions) error
ShowTrust(ctx context.Context, args []string, options ShowTrustOptions) (*ShowTrustReport, error)
Shutdown(ctx context.Context)
- Tag(ctx context.Context, nameOrId string, tags []string, options ImageTagOptions) error
- Tree(ctx context.Context, nameOrId string, options ImageTreeOptions) (*ImageTreeReport, error)
- Untag(ctx context.Context, nameOrId string, tags []string, options ImageUntagOptions) error
+ Tag(ctx context.Context, nameOrID string, tags []string, options ImageTagOptions) error
+ Tree(ctx context.Context, nameOrID string, options ImageTreeOptions) (*ImageTreeReport, error)
+ Untag(ctx context.Context, nameOrID string, tags []string, options ImageUntagOptions) error
ManifestCreate(ctx context.Context, names, images []string, opts ManifestCreateOptions) (string, error)
ManifestInspect(ctx context.Context, name string) ([]byte, error)
ManifestAdd(ctx context.Context, opts ManifestAddOptions) (string, error)
diff --git a/pkg/domain/entities/filters.go b/pkg/domain/entities/filters.go
index c7e227244..2ddbffbcd 100644
--- a/pkg/domain/entities/filters.go
+++ b/pkg/domain/entities/filters.go
@@ -20,14 +20,14 @@ type Names interface {
Names() []string
}
-// IdOrName interface allows filters to access ID() or Name() of object
-type IdOrNamed interface {
+// IDOrName interface allows filters to access ID() or Name() of object
+type IDOrNamed interface {
Identifier
Named
}
-// IdOrName interface allows filters to access ID() or Names() of object
-type IdOrNames interface {
+// IDOrName interface allows filters to access ID() or Names() of object
+type IDOrNames interface {
Identifier
Names
}
@@ -42,11 +42,11 @@ func CompileImageFilters(filters url.Values) ImageFilter {
for name, targets := range filters {
switch name {
case "id":
- fns = append(fns, FilterIdFn(targets))
+ fns = append(fns, FilterIDFn(targets))
case "name":
fns = append(fns, FilterNamesFn(targets))
case "idOrName":
- fns = append(fns, FilterIdOrNameFn(targets))
+ fns = append(fns, FilterIDOrNameFn(targets))
}
}
@@ -66,11 +66,11 @@ func CompileContainerFilters(filters url.Values) ContainerFilter {
for name, targets := range filters {
switch name {
case "id":
- fns = append(fns, FilterIdFn(targets))
+ fns = append(fns, FilterIDFn(targets))
case "name":
fns = append(fns, FilterNameFn(targets))
case "idOrName":
- fns = append(fns, FilterIdOrNameFn(targets))
+ fns = append(fns, FilterIDOrNameFn(targets))
}
}
@@ -89,7 +89,7 @@ func CompileVolumeFilters(filters url.Values) VolumeFilter {
for name, targets := range filters {
if name == "id" {
- fns = append(fns, FilterIdFn(targets))
+ fns = append(fns, FilterIDFn(targets))
}
}
@@ -103,7 +103,7 @@ func CompileVolumeFilters(filters url.Values) VolumeFilter {
}
}
-func FilterIdFn(id []string) func(Identifier) bool {
+func FilterIDFn(id []string) func(Identifier) bool {
return func(obj Identifier) bool {
for _, v := range id {
if strings.Contains(obj.Id(), v) {
@@ -138,8 +138,8 @@ func FilterNamesFn(name []string) func(Names) bool {
}
}
-func FilterIdOrNameFn(id []string) func(IdOrNamed) bool {
- return func(obj IdOrNamed) bool {
+func FilterIDOrNameFn(id []string) func(IDOrNamed) bool {
+ return func(obj IDOrNamed) bool {
for _, v := range id {
if strings.Contains(obj.Id(), v) || strings.Contains(obj.Name(), v) {
return true
diff --git a/pkg/domain/entities/generate.go b/pkg/domain/entities/generate.go
index 68a42d897..a8ad13705 100644
--- a/pkg/domain/entities/generate.go
+++ b/pkg/domain/entities/generate.go
@@ -18,7 +18,7 @@ type GenerateSystemdOptions struct {
ContainerPrefix string
// PodPrefix - systemd unit name prefix for pods
PodPrefix string
- // Separator - systemd unit name seperator between name/id and prefix
+ // Separator - systemd unit name separator between name/id and prefix
Separator string
}
diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go
index 19a2c87f5..81f52fef5 100644
--- a/pkg/domain/entities/images.go
+++ b/pkg/domain/entities/images.go
@@ -45,13 +45,13 @@ type Image struct {
HealthCheck *manifest.Schema2HealthConfig `json:",omitempty"`
}
-func (i *Image) Id() string {
+func (i *Image) Id() string { //nolint
return i.ID
}
type ImageSummary struct {
ID string `json:"Id"`
- ParentId string `json:",omitempty"`
+ ParentId string `json:",omitempty"` // nolint
RepoTags []string `json:",omitempty"`
Created time.Time `json:",omitempty"`
Size int64 `json:",omitempty"`
@@ -70,7 +70,7 @@ type ImageSummary struct {
History []string `json:",omitempty"`
}
-func (i *ImageSummary) Id() string {
+func (i *ImageSummary) Id() string { //nolint
return i.ID
}
@@ -266,7 +266,7 @@ type ImageImportOptions struct {
}
type ImageImportReport struct {
- Id string
+ Id string //nolint
}
type ImageSaveOptions struct {
@@ -299,7 +299,7 @@ type ShowTrustReport struct {
Raw []byte
SystemRegistriesDirPath string
JSONOutput []byte
- Policies []*trust.TrustPolicy
+ Policies []*trust.Policy
}
// SetTrustOptions describes the CLI options for setting trust
diff --git a/pkg/domain/entities/play.go b/pkg/domain/entities/play.go
index 4f485cbee..0823bc64e 100644
--- a/pkg/domain/entities/play.go
+++ b/pkg/domain/entities/play.go
@@ -26,12 +26,18 @@ type PlayKubeOptions struct {
SeccompProfileRoot string
}
-// PlayKubeReport contains the results of running play kube.
-type PlayKubeReport struct {
- // Pod - the ID of the created pod.
- Pod string
+// PlayKubePod represents a single pod and associated containers created by play kube
+type PlayKubePod struct {
+ // ID - ID of the pod created as a result of play kube.
+ ID string
// Containers - the IDs of the containers running in the created pod.
Containers []string
// Logs - non-fatal erros and log messages while processing.
Logs []string
}
+
+// PlayKubeReport contains the results of running play kube.
+type PlayKubeReport struct {
+ // Pods - pods created by play kube.
+ Pods []PlayKubePod
+}
diff --git a/pkg/domain/entities/pods.go b/pkg/domain/entities/pods.go
index 37acba6e6..fc76ddd41 100644
--- a/pkg/domain/entities/pods.go
+++ b/pkg/domain/entities/pods.go
@@ -17,15 +17,15 @@ type PodKillOptions struct {
type PodKillReport struct {
Errs []error
- Id string
+ Id string //nolint
}
type ListPodsReport struct {
Cgroup string
Containers []*ListPodContainer
Created time.Time
- Id string
- InfraId string
+ Id string //nolint
+ InfraId string //nolint
Name string
Namespace string
Status string
@@ -33,7 +33,7 @@ type ListPodsReport struct {
}
type ListPodContainer struct {
- Id string
+ Id string //nolint
Names string
Status string
}
@@ -45,7 +45,7 @@ type PodPauseOptions struct {
type PodPauseReport struct {
Errs []error
- Id string
+ Id string //nolint
}
type PodunpauseOptions struct {
@@ -55,7 +55,7 @@ type PodunpauseOptions struct {
type PodUnpauseReport struct {
Errs []error
- Id string
+ Id string //nolint
}
type PodStopOptions struct {
@@ -67,7 +67,7 @@ type PodStopOptions struct {
type PodStopReport struct {
Errs []error
- Id string
+ Id string //nolint
}
type PodRestartOptions struct {
@@ -77,7 +77,7 @@ type PodRestartOptions struct {
type PodRestartReport struct {
Errs []error
- Id string
+ Id string //nolint
}
type PodStartOptions struct {
@@ -87,7 +87,7 @@ type PodStartOptions struct {
type PodStartReport struct {
Errs []error
- Id string
+ Id string //nolint
}
type PodRmOptions struct {
@@ -99,23 +99,24 @@ type PodRmOptions struct {
type PodRmReport struct {
Err error
- Id string
+ Id string //nolint
}
type PodCreateOptions struct {
- CGroupParent string
- Hostname string
- Infra bool
- InfraImage string
- InfraCommand string
- Labels map[string]string
- Name string
- Net *NetOptions
- Share []string
+ CGroupParent string
+ Hostname string
+ Infra bool
+ InfraImage string
+ InfraCommand string
+ InfraConmonPidFile string
+ Labels map[string]string
+ Name string
+ Net *NetOptions
+ Share []string
}
type PodCreateReport struct {
- Id string
+ Id string //nolint
}
func (p PodCreateOptions) ToPodSpecGen(s *specgen.PodSpecGenerator) {
@@ -127,6 +128,9 @@ func (p PodCreateOptions) ToPodSpecGen(s *specgen.PodSpecGenerator) {
if len(p.InfraCommand) > 0 {
s.InfraCommand = strings.Split(p.InfraCommand, " ")
}
+ if len(p.InfraConmonPidFile) > 0 {
+ s.InfraConmonPidFile = p.InfraConmonPidFile
+ }
s.InfraImage = p.InfraImage
s.SharedNamespaces = p.Share
@@ -155,7 +159,7 @@ type PodPruneOptions struct {
type PodPruneReport struct {
Err error
- Id string
+ Id string //nolint
}
type PodTopOptions struct {
diff --git a/pkg/domain/entities/set.go b/pkg/domain/entities/set.go
index c8d6cb1a9..1d31d82f9 100644
--- a/pkg/domain/entities/set.go
+++ b/pkg/domain/entities/set.go
@@ -4,12 +4,12 @@ import (
"strings"
)
-type stringSet struct {
+type StringSet struct {
m map[string]struct{}
}
-func NewStringSet(elem ...string) *stringSet {
- s := &stringSet{}
+func NewStringSet(elem ...string) *StringSet {
+ s := &StringSet{}
s.m = make(map[string]struct{}, len(elem))
for _, e := range elem {
s.Add(e)
@@ -17,20 +17,20 @@ func NewStringSet(elem ...string) *stringSet {
return s
}
-func (s *stringSet) Add(elem string) {
+func (s *StringSet) Add(elem string) {
s.m[elem] = struct{}{}
}
-func (s *stringSet) Remove(elem string) {
+func (s *StringSet) Remove(elem string) {
delete(s.m, elem)
}
-func (s *stringSet) Contains(elem string) bool {
+func (s *StringSet) Contains(elem string) bool {
_, ok := s.m[elem]
return ok
}
-func (s *stringSet) Elements() []string {
+func (s *StringSet) Elements() []string {
keys := make([]string, len(s.m))
i := 0
for k := range s.m {
@@ -40,6 +40,6 @@ func (s *stringSet) Elements() []string {
return keys
}
-func (s *stringSet) String() string {
+func (s *StringSet) String() string {
return strings.Join(s.Elements(), ", ")
}
diff --git a/pkg/domain/entities/types.go b/pkg/domain/entities/types.go
index 21ab025de..622f74838 100644
--- a/pkg/domain/entities/types.go
+++ b/pkg/domain/entities/types.go
@@ -11,7 +11,7 @@ import (
)
type Container struct {
- IdOrNamed
+ IDOrNamed
}
type Volume struct {
@@ -19,7 +19,7 @@ type Volume struct {
}
type Report struct {
- Id []string
+ Id []string //nolint
Err map[string]error
}
diff --git a/pkg/domain/entities/volumes.go b/pkg/domain/entities/volumes.go
index 23c066083..7cf7d82a2 100644
--- a/pkg/domain/entities/volumes.go
+++ b/pkg/domain/entities/volumes.go
@@ -16,9 +16,9 @@ type VolumeCreateOptions struct {
Options map[string]string `schema:"opts"`
}
-type IdOrNameResponse struct {
+type IDOrNameResponse struct {
// The Id or Name of an object
- IdOrName string
+ IDOrName string
}
type VolumeConfigResponse struct {
@@ -63,7 +63,7 @@ type VolumeRmOptions struct {
type VolumeRmReport struct {
Err error
- Id string
+ Id string //nolint
}
type VolumeInspectOptions struct {
@@ -80,7 +80,7 @@ type VolumePruneOptions struct {
type VolumePruneReport struct {
Err error
- Id string
+ Id string //nolint
}
type VolumeListOptions struct {
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go
index eb45d4630..d2c8aefdc 100644
--- a/pkg/domain/infra/abi/containers.go
+++ b/pkg/domain/infra/abi/containers.go
@@ -75,8 +75,8 @@ func getContainersByContext(all, latest bool, names []string, runtime *libpod.Ru
}
// TODO: Should return *entities.ContainerExistsReport, error
-func (ic *ContainerEngine) ContainerExists(ctx context.Context, nameOrId string) (*entities.BoolReport, error) {
- _, err := ic.Libpod.LookupContainer(nameOrId)
+func (ic *ContainerEngine) ContainerExists(ctx context.Context, nameOrID string) (*entities.BoolReport, error) {
+ _, err := ic.Libpod.LookupContainer(nameOrID)
if err != nil && errors.Cause(err) != define.ErrNoSuchCtr {
return nil, err
}
@@ -84,13 +84,11 @@ func (ic *ContainerEngine) ContainerExists(ctx context.Context, nameOrId string)
}
func (ic *ContainerEngine) ContainerWait(ctx context.Context, namesOrIds []string, options entities.WaitOptions) ([]entities.WaitReport, error) {
- var (
- responses []entities.WaitReport
- )
ctrs, err := getContainersByContext(false, options.Latest, namesOrIds, ic.Libpod)
if err != nil {
return nil, err
}
+ responses := make([]entities.WaitReport, 0, len(ctrs))
for _, c := range ctrs {
response := entities.WaitReport{Id: c.ID()}
exitCode, err := c.WaitForConditionWithInterval(options.Interval, options.Condition)
@@ -106,10 +104,9 @@ func (ic *ContainerEngine) ContainerWait(ctx context.Context, namesOrIds []strin
func (ic *ContainerEngine) ContainerPause(ctx context.Context, namesOrIds []string, options entities.PauseUnPauseOptions) ([]*entities.PauseUnpauseReport, error) {
var (
- ctrs []*libpod.Container
- err error
- report []*entities.PauseUnpauseReport
+ err error
)
+ ctrs := []*libpod.Container{} //nolint
if options.All {
ctrs, err = ic.Libpod.GetAllContainers()
} else {
@@ -118,6 +115,7 @@ func (ic *ContainerEngine) ContainerPause(ctx context.Context, namesOrIds []stri
if err != nil {
return nil, err
}
+ report := make([]*entities.PauseUnpauseReport, 0, len(ctrs))
for _, c := range ctrs {
err := c.Pause()
report = append(report, &entities.PauseUnpauseReport{Id: c.ID(), Err: err})
@@ -127,10 +125,9 @@ func (ic *ContainerEngine) ContainerPause(ctx context.Context, namesOrIds []stri
func (ic *ContainerEngine) ContainerUnpause(ctx context.Context, namesOrIds []string, options entities.PauseUnPauseOptions) ([]*entities.PauseUnpauseReport, error) {
var (
- ctrs []*libpod.Container
- err error
- report []*entities.PauseUnpauseReport
+ err error
)
+ ctrs := []*libpod.Container{} //nolint
if options.All {
ctrs, err = ic.Libpod.GetAllContainers()
} else {
@@ -139,6 +136,7 @@ func (ic *ContainerEngine) ContainerUnpause(ctx context.Context, namesOrIds []st
if err != nil {
return nil, err
}
+ report := make([]*entities.PauseUnpauseReport, 0, len(ctrs))
for _, c := range ctrs {
err := c.Unpause()
report = append(report, &entities.PauseUnpauseReport{Id: c.ID(), Err: err})
@@ -146,9 +144,6 @@ func (ic *ContainerEngine) ContainerUnpause(ctx context.Context, namesOrIds []st
return report, nil
}
func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []string, options entities.StopOptions) ([]*entities.StopReport, error) {
- var (
- reports []*entities.StopReport
- )
names := namesOrIds
for _, cidFile := range options.CIDFiles {
content, err := ioutil.ReadFile(cidFile)
@@ -162,32 +157,34 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin
if err != nil && !(options.Ignore && errors.Cause(err) == define.ErrNoSuchCtr) {
return nil, err
}
- for _, con := range ctrs {
- report := entities.StopReport{Id: con.ID()}
- err = con.StopWithTimeout(options.Timeout)
+ errMap, err := parallel.ContainerOp(ctx, ctrs, func(c *libpod.Container) error {
+ var err error
+ if options.Timeout != nil {
+ err = c.StopWithTimeout(*options.Timeout)
+ } else {
+ err = c.Stop()
+ }
if err != nil {
- // These first two are considered non-fatal under the right conditions
- if errors.Cause(err) == define.ErrCtrStopped {
- logrus.Debugf("Container %s is already stopped", con.ID())
- reports = append(reports, &report)
- continue
-
- } else if options.All && errors.Cause(err) == define.ErrCtrStateInvalid {
- logrus.Debugf("Container %s is not running, could not stop", con.ID())
- reports = append(reports, &report)
- continue
+ switch {
+ case errors.Cause(err) == define.ErrCtrStopped:
+ logrus.Debugf("Container %s is already stopped", c.ID())
+ case options.All && errors.Cause(err) == define.ErrCtrStateInvalid:
+ logrus.Debugf("Container %s is not running, could not stop", c.ID())
+ default:
+ return err
}
- report.Err = err
- reports = append(reports, &report)
- continue
- } else if err := con.Cleanup(ctx); err != nil {
- // Only if no error, proceed to cleanup to ensure all
- // mounts are removed before we exit.
- report.Err = err
- reports = append(reports, &report)
- continue
}
- reports = append(reports, &report)
+ return c.Cleanup(ctx)
+ })
+ if err != nil {
+ return nil, err
+ }
+ reports := make([]*entities.StopReport, 0, len(errMap))
+ for ctr, err := range errMap {
+ report := new(entities.StopReport)
+ report.Id = ctr.ID()
+ report.Err = err
+ reports = append(reports, report)
}
return reports, nil
}
@@ -203,10 +200,10 @@ func (ic *ContainerEngine) ContainerPrune(ctx context.Context, options entities.
filterFuncs = append(filterFuncs, generatedFunc)
}
}
- return ic.pruneContainersHelper(ctx, filterFuncs)
+ return ic.pruneContainersHelper(filterFuncs)
}
-func (ic *ContainerEngine) pruneContainersHelper(ctx context.Context, filterFuncs []libpod.ContainerFilter) (*entities.ContainerPruneReport, error) {
+func (ic *ContainerEngine) pruneContainersHelper(filterFuncs []libpod.ContainerFilter) (*entities.ContainerPruneReport, error) {
prunedContainers, pruneErrors, err := ic.Libpod.PruneContainers(filterFuncs)
if err != nil {
return nil, err
@@ -219,9 +216,6 @@ func (ic *ContainerEngine) pruneContainersHelper(ctx context.Context, filterFunc
}
func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []string, options entities.KillOptions) ([]*entities.KillReport, error) {
- var (
- reports []*entities.KillReport
- )
sig, err := signal.ParseSignalNameOrNumber(options.Signal)
if err != nil {
return nil, err
@@ -230,6 +224,7 @@ func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []strin
if err != nil {
return nil, err
}
+ reports := make([]*entities.KillReport, 0, len(ctrs))
for _, con := range ctrs {
reports = append(reports, &entities.KillReport{
Id: con.ID(),
@@ -240,9 +235,8 @@ func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []strin
}
func (ic *ContainerEngine) ContainerRestart(ctx context.Context, namesOrIds []string, options entities.RestartOptions) ([]*entities.RestartReport, error) {
var (
- ctrs []*libpod.Container
- err error
- reports []*entities.RestartReport
+ ctrs []*libpod.Container
+ err error
)
if options.Running {
@@ -257,6 +251,7 @@ func (ic *ContainerEngine) ContainerRestart(ctx context.Context, namesOrIds []st
}
}
+ reports := make([]*entities.RestartReport, 0, len(ctrs))
for _, con := range ctrs {
timeout := con.StopTimeout()
if options.Timeout != nil {
@@ -271,9 +266,7 @@ func (ic *ContainerEngine) ContainerRestart(ctx context.Context, namesOrIds []st
}
func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string, options entities.RmOptions) ([]*entities.RmReport, error) {
- var (
- reports []*entities.RmReport
- )
+ reports := []*entities.RmReport{}
if options.Storage {
for _, ctr := range namesOrIds {
report := entities.RmReport{Id: ctr}
@@ -322,7 +315,7 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string,
return reports, nil
}
- errMap, err := parallel.ParallelContainerOp(ctx, ctrs, func(c *libpod.Container) error {
+ errMap, err := parallel.ContainerOp(ctx, ctrs, func(c *libpod.Container) error {
err := ic.Libpod.RemoveContainer(ctx, c, options.Force, options.Volumes)
if err != nil {
if options.Ignore && errors.Cause(err) == define.ErrNoSuchCtr {
@@ -346,11 +339,11 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string,
}
func (ic *ContainerEngine) ContainerInspect(ctx context.Context, namesOrIds []string, options entities.InspectOptions) ([]*entities.ContainerInspectReport, error) {
- var reports []*entities.ContainerInspectReport
ctrs, err := getContainersByContext(false, options.Latest, namesOrIds, ic.Libpod)
if err != nil {
return nil, err
}
+ reports := make([]*entities.ContainerInspectReport, 0, len(ctrs))
for _, c := range ctrs {
data, err := c.Inspect(options.Size)
if err != nil {
@@ -383,11 +376,11 @@ func (ic *ContainerEngine) ContainerTop(ctx context.Context, options entities.To
return report, err
}
-func (ic *ContainerEngine) ContainerCommit(ctx context.Context, nameOrId string, options entities.CommitOptions) (*entities.CommitReport, error) {
+func (ic *ContainerEngine) ContainerCommit(ctx context.Context, nameOrID string, options entities.CommitOptions) (*entities.CommitReport, error) {
var (
mimeType string
)
- ctr, err := ic.Libpod.LookupContainer(nameOrId)
+ ctr, err := ic.Libpod.LookupContainer(nameOrID)
if err != nil {
return nil, err
}
@@ -428,8 +421,8 @@ func (ic *ContainerEngine) ContainerCommit(ctx context.Context, nameOrId string,
return &entities.CommitReport{Id: newImage.ID()}, nil
}
-func (ic *ContainerEngine) ContainerExport(ctx context.Context, nameOrId string, options entities.ContainerExportOptions) error {
- ctr, err := ic.Libpod.LookupContainer(nameOrId)
+func (ic *ContainerEngine) ContainerExport(ctx context.Context, nameOrID string, options entities.ContainerExportOptions) error {
+ ctr, err := ic.Libpod.LookupContainer(nameOrID)
if err != nil {
return err
}
@@ -438,9 +431,8 @@ func (ic *ContainerEngine) ContainerExport(ctx context.Context, nameOrId string,
func (ic *ContainerEngine) ContainerCheckpoint(ctx context.Context, namesOrIds []string, options entities.CheckpointOptions) ([]*entities.CheckpointReport, error) {
var (
- err error
- cons []*libpod.Container
- reports []*entities.CheckpointReport
+ err error
+ cons []*libpod.Container
)
checkOpts := libpod.ContainerCheckpointOptions{
Keep: options.Keep,
@@ -462,6 +454,7 @@ func (ic *ContainerEngine) ContainerCheckpoint(ctx context.Context, namesOrIds [
if err != nil {
return nil, err
}
+ reports := make([]*entities.CheckpointReport, 0, len(cons))
for _, con := range cons {
err = con.Checkpoint(ctx, checkOpts)
reports = append(reports, &entities.CheckpointReport{
@@ -474,10 +467,8 @@ func (ic *ContainerEngine) ContainerCheckpoint(ctx context.Context, namesOrIds [
func (ic *ContainerEngine) ContainerRestore(ctx context.Context, namesOrIds []string, options entities.RestoreOptions) ([]*entities.RestoreReport, error) {
var (
- cons []*libpod.Container
- err error
- filterFuncs []libpod.ContainerFilter
- reports []*entities.RestoreReport
+ cons []*libpod.Container
+ err error
)
restoreOptions := libpod.ContainerCheckpointOptions{
@@ -490,10 +481,12 @@ func (ic *ContainerEngine) ContainerRestore(ctx context.Context, namesOrIds []st
IgnoreStaticMAC: options.IgnoreStaticMAC,
}
- filterFuncs = append(filterFuncs, func(c *libpod.Container) bool {
- state, _ := c.State()
- return state == define.ContainerStateExited
- })
+ filterFuncs := []libpod.ContainerFilter{
+ func(c *libpod.Container) bool {
+ state, _ := c.State()
+ return state == define.ContainerStateExited
+ },
+ }
switch {
case options.Import != "":
@@ -506,6 +499,7 @@ func (ic *ContainerEngine) ContainerRestore(ctx context.Context, namesOrIds []st
if err != nil {
return nil, err
}
+ reports := make([]*entities.RestoreReport, 0, len(cons))
for _, con := range cons {
err := con.Restore(ctx, restoreOptions)
reports = append(reports, &entities.RestoreReport{
@@ -527,8 +521,8 @@ func (ic *ContainerEngine) ContainerCreate(ctx context.Context, s *specgen.SpecG
return &entities.ContainerCreateReport{Id: ctr.ID()}, nil
}
-func (ic *ContainerEngine) ContainerAttach(ctx context.Context, nameOrId string, options entities.AttachOptions) error {
- ctrs, err := getContainersByContext(false, options.Latest, []string{nameOrId}, ic.Libpod)
+func (ic *ContainerEngine) ContainerAttach(ctx context.Context, nameOrID string, options entities.AttachOptions) error {
+ ctrs, err := getContainersByContext(false, options.Latest, []string{nameOrID}, ic.Libpod)
if err != nil {
return err
}
@@ -564,38 +558,38 @@ func makeExecConfig(options entities.ExecOptions) *libpod.ExecConfig {
return execConfig
}
-func checkExecPreserveFDs(options entities.ExecOptions) (int, error) {
- ec := define.ExecErrorCodeGeneric
+func checkExecPreserveFDs(options entities.ExecOptions) error {
if options.PreserveFDs > 0 {
entries, err := ioutil.ReadDir("/proc/self/fd")
if err != nil {
- return ec, errors.Wrapf(err, "unable to read /proc/self/fd")
+ return errors.Wrapf(err, "unable to read /proc/self/fd")
}
m := make(map[int]bool)
for _, e := range entries {
i, err := strconv.Atoi(e.Name())
if err != nil {
- return ec, errors.Wrapf(err, "cannot parse %s in /proc/self/fd", e.Name())
+ return errors.Wrapf(err, "cannot parse %s in /proc/self/fd", e.Name())
}
m[i] = true
}
for i := 3; i < 3+int(options.PreserveFDs); i++ {
if _, found := m[i]; !found {
- return ec, errors.New("invalid --preserve-fds=N specified. Not enough FDs available")
+ return errors.New("invalid --preserve-fds=N specified. Not enough FDs available")
}
}
}
- return ec, nil
+ return nil
}
-func (ic *ContainerEngine) ContainerExec(ctx context.Context, nameOrId string, options entities.ExecOptions, streams define.AttachStreams) (int, error) {
- ec, err := checkExecPreserveFDs(options)
+func (ic *ContainerEngine) ContainerExec(ctx context.Context, nameOrID string, options entities.ExecOptions, streams define.AttachStreams) (int, error) {
+ ec := define.ExecErrorCodeGeneric
+ err := checkExecPreserveFDs(options)
if err != nil {
return ec, err
}
- ctrs, err := getContainersByContext(false, options.Latest, []string{nameOrId}, ic.Libpod)
+ ctrs, err := getContainersByContext(false, options.Latest, []string{nameOrID}, ic.Libpod)
if err != nil {
return ec, err
}
@@ -607,12 +601,12 @@ func (ic *ContainerEngine) ContainerExec(ctx context.Context, nameOrId string, o
return define.TranslateExecErrorToExitCode(ec, err), err
}
-func (ic *ContainerEngine) ContainerExecDetached(ctx context.Context, nameOrId string, options entities.ExecOptions) (string, error) {
- _, err := checkExecPreserveFDs(options)
+func (ic *ContainerEngine) ContainerExecDetached(ctx context.Context, nameOrID string, options entities.ExecOptions) (string, error) {
+ err := checkExecPreserveFDs(options)
if err != nil {
return "", err
}
- ctrs, err := getContainersByContext(false, options.Latest, []string{nameOrId}, ic.Libpod)
+ ctrs, err := getContainersByContext(false, options.Latest, []string{nameOrID}, ic.Libpod)
if err != nil {
return "", err
}
@@ -647,7 +641,7 @@ func (ic *ContainerEngine) ContainerExecDetached(ctx context.Context, nameOrId s
}
func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []string, options entities.ContainerStartOptions) ([]*entities.ContainerStartReport, error) {
- var reports []*entities.ContainerStartReport
+ reports := []*entities.ContainerStartReport{}
var exitCode = define.ExecErrorCodeGeneric
ctrs, rawInputs, err := getContainersAndInputByContext(false, options.Latest, namesOrIds, ic.Libpod)
if err != nil {
@@ -766,15 +760,15 @@ func (ic *ContainerEngine) ContainerList(ctx context.Context, options entities.C
}
// ContainerDiff provides changes to given container
-func (ic *ContainerEngine) ContainerDiff(ctx context.Context, nameOrId string, opts entities.DiffOptions) (*entities.DiffReport, error) {
+func (ic *ContainerEngine) ContainerDiff(ctx context.Context, nameOrID string, opts entities.DiffOptions) (*entities.DiffReport, error) {
if opts.Latest {
ctnr, err := ic.Libpod.GetLatestContainer()
if err != nil {
return nil, errors.Wrap(err, "unable to get latest container")
}
- nameOrId = ctnr.ID()
+ nameOrID = ctnr.ID()
}
- changes, err := ic.Libpod.GetDiff("", nameOrId)
+ changes, err := ic.Libpod.GetDiff("", nameOrID)
return &entities.DiffReport{Changes: changes}, err
}
@@ -906,7 +900,7 @@ func (ic *ContainerEngine) ContainerLogs(ctx context.Context, containers []strin
}
func (ic *ContainerEngine) ContainerCleanup(ctx context.Context, namesOrIds []string, options entities.ContainerCleanupOptions) ([]*entities.ContainerCleanupReport, error) {
- var reports []*entities.ContainerCleanupReport
+ reports := []*entities.ContainerCleanupReport{}
ctrs, err := getContainersByContext(options.All, options.Latest, namesOrIds, ic.Libpod)
if err != nil {
return nil, err
@@ -957,11 +951,11 @@ func (ic *ContainerEngine) ContainerCleanup(ctx context.Context, namesOrIds []st
}
func (ic *ContainerEngine) ContainerInit(ctx context.Context, namesOrIds []string, options entities.ContainerInitOptions) ([]*entities.ContainerInitReport, error) {
- var reports []*entities.ContainerInitReport
ctrs, err := getContainersByContext(options.All, options.Latest, namesOrIds, ic.Libpod)
if err != nil {
return nil, err
}
+ reports := make([]*entities.ContainerInitReport, 0, len(ctrs))
for _, ctr := range ctrs {
report := entities.ContainerInitReport{Id: ctr.ID()}
err := ctr.Init(ctx)
@@ -976,7 +970,7 @@ func (ic *ContainerEngine) ContainerInit(ctx context.Context, namesOrIds []strin
return reports, nil
}
-func (ic *ContainerEngine) ContainerMount(ctx context.Context, nameOrIds []string, options entities.ContainerMountOptions) ([]*entities.ContainerMountReport, error) {
+func (ic *ContainerEngine) ContainerMount(ctx context.Context, nameOrIDs []string, options entities.ContainerMountOptions) ([]*entities.ContainerMountReport, error) {
if os.Geteuid() != 0 {
if driver := ic.Libpod.StorageConfig().GraphDriverName; driver != "vfs" {
// Do not allow to mount a graphdriver that is not vfs if we are creating the userns as part
@@ -992,11 +986,11 @@ func (ic *ContainerEngine) ContainerMount(ctx context.Context, nameOrIds []strin
os.Exit(ret)
}
}
- var reports []*entities.ContainerMountReport
- ctrs, err := getContainersByContext(options.All, options.Latest, nameOrIds, ic.Libpod)
+ ctrs, err := getContainersByContext(options.All, options.Latest, nameOrIDs, ic.Libpod)
if err != nil {
return nil, err
}
+ reports := make([]*entities.ContainerMountReport, 0, len(ctrs))
for _, ctr := range ctrs {
report := entities.ContainerMountReport{Id: ctr.ID()}
report.Path, report.Err = ctr.Mount()
@@ -1028,12 +1022,12 @@ func (ic *ContainerEngine) ContainerMount(ctx context.Context, nameOrIds []strin
return reports, nil
}
-func (ic *ContainerEngine) ContainerUnmount(ctx context.Context, nameOrIds []string, options entities.ContainerUnmountOptions) ([]*entities.ContainerUnmountReport, error) {
- var reports []*entities.ContainerUnmountReport
- ctrs, err := getContainersByContext(options.All, options.Latest, nameOrIds, ic.Libpod)
+func (ic *ContainerEngine) ContainerUnmount(ctx context.Context, nameOrIDs []string, options entities.ContainerUnmountOptions) ([]*entities.ContainerUnmountReport, error) {
+ ctrs, err := getContainersByContext(options.All, options.Latest, nameOrIDs, ic.Libpod)
if err != nil {
return nil, err
}
+ reports := []*entities.ContainerUnmountReport{}
for _, ctr := range ctrs {
state, err := ctr.State()
if err != nil {
@@ -1063,12 +1057,12 @@ func (ic *ContainerEngine) Config(_ context.Context) (*config.Config, error) {
return ic.Libpod.GetConfig()
}
-func (ic *ContainerEngine) ContainerPort(ctx context.Context, nameOrId string, options entities.ContainerPortOptions) ([]*entities.ContainerPortReport, error) {
- var reports []*entities.ContainerPortReport
- ctrs, err := getContainersByContext(options.All, options.Latest, []string{nameOrId}, ic.Libpod)
+func (ic *ContainerEngine) ContainerPort(ctx context.Context, nameOrID string, options entities.ContainerPortOptions) ([]*entities.ContainerPortReport, error) {
+ ctrs, err := getContainersByContext(options.All, options.Latest, []string{nameOrID}, ic.Libpod)
if err != nil {
return nil, err
}
+ reports := []*entities.ContainerPortReport{}
for _, con := range ctrs {
state, err := con.State()
if err != nil {
diff --git a/pkg/domain/infra/abi/containers_runlabel.go b/pkg/domain/infra/abi/containers_runlabel.go
index 41f4444d5..37422aac5 100644
--- a/pkg/domain/infra/abi/containers_runlabel.go
+++ b/pkg/domain/infra/abi/containers_runlabel.go
@@ -116,7 +116,7 @@ func generateRunlabelCommand(runlabel string, img *image.Image, args []string, o
err error
name, imageName string
globalOpts string
- cmd, env []string
+ cmd []string
)
// TODO: How do we get global opts as done in v1?
@@ -149,7 +149,7 @@ func generateRunlabelCommand(runlabel string, img *image.Image, args []string, o
return nil, nil, err
}
- env = generateRunEnvironment(name, imageName, options)
+ env := generateRunEnvironment(options)
env = append(env, "PODMAN_RUNLABEL_NESTED=1")
envmap, err := envLib.ParseSlice(env)
if err != nil {
@@ -185,9 +185,6 @@ func generateRunlabelCommand(runlabel string, img *image.Image, args []string, o
// generateCommand takes a label (string) and converts it to an executable command
func generateCommand(command, imageName, name, globalOpts string) ([]string, error) {
- var (
- newCommand []string
- )
if name == "" {
name = imageName
}
@@ -201,8 +198,7 @@ func generateCommand(command, imageName, name, globalOpts string) ([]string, err
if err != nil {
return nil, err
}
- newCommand = append(newCommand, prog)
-
+ newCommand := []string{prog}
for _, arg := range cmd[1:] {
var newArg string
switch arg {
@@ -234,7 +230,7 @@ func generateCommand(command, imageName, name, globalOpts string) ([]string, err
// GenerateRunEnvironment merges the current environment variables with optional
// environment variables provided by the user
-func generateRunEnvironment(name, imageName string, options entities.ContainerRunlabelOptions) []string {
+func generateRunEnvironment(options entities.ContainerRunlabelOptions) []string {
newEnv := os.Environ()
if options.Optional1 != "" {
newEnv = append(newEnv, fmt.Sprintf("OPT1=%s", options.Optional1))
diff --git a/pkg/domain/infra/abi/cp.go b/pkg/domain/infra/abi/cp.go
index 542813394..82b07e2e1 100644
--- a/pkg/domain/infra/abi/cp.go
+++ b/pkg/domain/infra/abi/cp.go
@@ -92,7 +92,7 @@ func (ic *ContainerEngine) ContainerCp(ctx context.Context, source, dest string,
if isFromHostToCtr {
if isVol, volDestName, volName := isVolumeDestName(destPath, ctr); isVol { //nolint(gocritic)
- path, err := pathWithVolumeMount(ctr, ic.Libpod, volDestName, volName, destPath)
+ path, err := pathWithVolumeMount(ic.Libpod, volDestName, volName, destPath)
if err != nil {
return nil, errors.Wrapf(err, "error getting destination path from volume %s", volDestName)
}
@@ -126,7 +126,7 @@ func (ic *ContainerEngine) ContainerCp(ctx context.Context, source, dest string,
} else {
destOwner = idtools.IDPair{UID: os.Getuid(), GID: os.Getgid()}
if isVol, volDestName, volName := isVolumeDestName(srcPath, ctr); isVol { //nolint(gocritic)
- path, err := pathWithVolumeMount(ctr, ic.Libpod, volDestName, volName, srcPath)
+ path, err := pathWithVolumeMount(ic.Libpod, volDestName, volName, srcPath)
if err != nil {
return nil, errors.Wrapf(err, "error getting source path from volume %s", volDestName)
}
@@ -396,7 +396,7 @@ func isVolumeDestName(path string, ctr *libpod.Container) (bool, string, string)
}
// if SRCPATH or DESTPATH is from volume mount's destination -v or --mount type=volume, generates the path with volume mount point
-func pathWithVolumeMount(ctr *libpod.Container, runtime *libpod.Runtime, volDestName, volName, path string) (string, error) {
+func pathWithVolumeMount(runtime *libpod.Runtime, volDestName, volName, path string) (string, error) {
destVolume, err := runtime.GetVolume(volName)
if err != nil {
return "", errors.Wrapf(err, "error getting volume destination %s", volName)
diff --git a/pkg/domain/infra/abi/generate.go b/pkg/domain/infra/abi/generate.go
index abb5e2911..8853303d5 100644
--- a/pkg/domain/infra/abi/generate.go
+++ b/pkg/domain/infra/abi/generate.go
@@ -4,7 +4,6 @@ import (
"bytes"
"context"
"fmt"
- "strings"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/define"
@@ -16,165 +15,29 @@ import (
)
func (ic *ContainerEngine) GenerateSystemd(ctx context.Context, nameOrID string, options entities.GenerateSystemdOptions) (*entities.GenerateSystemdReport, error) {
- opts := generate.Options{
- Files: options.Files,
- New: options.New,
- }
-
// First assume it's a container.
- if info, found, err := ic.generateSystemdgenContainerInfo(nameOrID, nil, options); found && err != nil {
- return nil, err
- } else if found && err == nil {
- output, err := generate.CreateContainerSystemdUnit(info, opts)
- if err != nil {
- return nil, err
+ ctr, ctrErr := ic.Libpod.LookupContainer(nameOrID)
+ if ctrErr == nil {
+ // Generate the unit for the container.
+ s, err := generate.ContainerUnit(ctr, options)
+ if err == nil {
+ return &entities.GenerateSystemdReport{Output: s}, nil
}
- return &entities.GenerateSystemdReport{Output: output}, nil
- }
-
- // --new does not support pods.
- if options.New {
- return nil, errors.Errorf("error generating systemd unit files: cannot generate generic files for a pod")
}
- // We're either having a pod or garbage.
+ // If it's not a container, we either have a pod or garbage.
pod, err := ic.Libpod.LookupPod(nameOrID)
if err != nil {
- return nil, err
- }
-
- // Error out if the pod has no infra container, which we require to be the
- // main service.
- if !pod.HasInfraContainer() {
- return nil, fmt.Errorf("error generating systemd unit files: Pod %q has no infra container", pod.Name())
+ err = errors.Wrap(ctrErr, err.Error())
+ return nil, errors.Wrapf(err, "%s does not refer to a container or pod", nameOrID)
}
- // Generate a systemdgen.ContainerInfo for the infra container. This
- // ContainerInfo acts as the main service of the pod.
- infraID, err := pod.InfraContainerID()
- if err != nil {
- return nil, nil
- }
- podInfo, _, err := ic.generateSystemdgenContainerInfo(infraID, pod, options)
+ // Generate the units for the pod and all its containers.
+ s, err := generate.PodUnits(pod, options)
if err != nil {
return nil, err
}
-
- // Compute the container-dependency graph for the Pod.
- containers, err := pod.AllContainers()
- if err != nil {
- return nil, err
- }
- if len(containers) == 0 {
- return nil, fmt.Errorf("error generating systemd unit files: Pod %q has no containers", pod.Name())
- }
- graph, err := libpod.BuildContainerGraph(containers)
- if err != nil {
- return nil, err
- }
-
- // Traverse the dependency graph and create systemdgen.ContainerInfo's for
- // each container.
- containerInfos := []*generate.ContainerInfo{podInfo}
- for ctr, dependencies := range graph.DependencyMap() {
- // Skip the infra container as we already generated it.
- if ctr.ID() == infraID {
- continue
- }
- ctrInfo, _, err := ic.generateSystemdgenContainerInfo(ctr.ID(), nil, options)
- if err != nil {
- return nil, err
- }
- // Now add the container's dependencies and at the container as a
- // required service of the infra container.
- for _, dep := range dependencies {
- if dep.ID() == infraID {
- ctrInfo.BoundToServices = append(ctrInfo.BoundToServices, podInfo.ServiceName)
- } else {
- _, serviceName := generateServiceName(dep, nil, options)
- ctrInfo.BoundToServices = append(ctrInfo.BoundToServices, serviceName)
- }
- }
- podInfo.RequiredServices = append(podInfo.RequiredServices, ctrInfo.ServiceName)
- containerInfos = append(containerInfos, ctrInfo)
- }
-
- // Now generate the systemd service for all containers.
- builder := strings.Builder{}
- for i, info := range containerInfos {
- if i > 0 {
- builder.WriteByte('\n')
- }
- out, err := generate.CreateContainerSystemdUnit(info, opts)
- if err != nil {
- return nil, err
- }
- builder.WriteString(out)
- }
-
- return &entities.GenerateSystemdReport{Output: builder.String()}, nil
-}
-
-// generateSystemdgenContainerInfo is a helper to generate a
-// systemdgen.ContainerInfo for `GenerateSystemd`.
-func (ic *ContainerEngine) generateSystemdgenContainerInfo(nameOrID string, pod *libpod.Pod, options entities.GenerateSystemdOptions) (*generate.ContainerInfo, bool, error) {
- ctr, err := ic.Libpod.LookupContainer(nameOrID)
- if err != nil {
- return nil, false, err
- }
-
- timeout := ctr.StopTimeout()
- if options.StopTimeout != nil {
- timeout = *options.StopTimeout
- }
-
- config := ctr.Config()
- conmonPidFile := config.ConmonPidFile
- if conmonPidFile == "" {
- return nil, true, errors.Errorf("conmon PID file path is empty, try to recreate the container with --conmon-pidfile flag")
- }
-
- createCommand := []string{}
- if config.CreateCommand != nil {
- createCommand = config.CreateCommand
- } else if options.New {
- return nil, true, errors.Errorf("cannot use --new on container %q: no create command found", nameOrID)
- }
-
- name, serviceName := generateServiceName(ctr, pod, options)
- info := &generate.ContainerInfo{
- ServiceName: serviceName,
- ContainerName: name,
- RestartPolicy: options.RestartPolicy,
- PIDFile: conmonPidFile,
- StopTimeout: timeout,
- GenerateTimestamp: true,
- CreateCommand: createCommand,
- }
-
- return info, true, nil
-}
-
-// generateServiceName generates the container name and the service name for systemd service.
-func generateServiceName(ctr *libpod.Container, pod *libpod.Pod, options entities.GenerateSystemdOptions) (string, string) {
- var kind, name, ctrName string
- if pod == nil {
- kind = options.ContainerPrefix //defaults to container
- name = ctr.ID()
- if options.Name {
- name = ctr.Name()
- }
- ctrName = name
- } else {
- kind = options.PodPrefix //defaults to pod
- name = pod.ID()
- ctrName = ctr.ID()
- if options.Name {
- name = pod.Name()
- ctrName = ctr.Name()
- }
- }
- return ctrName, fmt.Sprintf("%s%s%s", kind, options.Separator, name)
+ return &entities.GenerateSystemdReport{Output: s}, nil
}
func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrID string, options entities.GenerateKubeOptions) (*entities.GenerateKubeReport, error) {
diff --git a/pkg/domain/infra/abi/healthcheck.go b/pkg/domain/infra/abi/healthcheck.go
index 4e925ef56..dfa9a6fa5 100644
--- a/pkg/domain/infra/abi/healthcheck.go
+++ b/pkg/domain/infra/abi/healthcheck.go
@@ -7,8 +7,8 @@ import (
"github.com/containers/libpod/pkg/domain/entities"
)
-func (ic *ContainerEngine) HealthCheckRun(ctx context.Context, nameOrId string, options entities.HealthCheckOptions) (*define.HealthCheckResults, error) {
- status, err := ic.Libpod.HealthCheck(nameOrId)
+func (ic *ContainerEngine) HealthCheckRun(ctx context.Context, nameOrID string, options entities.HealthCheckOptions) (*define.HealthCheckResults, error) {
+ status, err := ic.Libpod.HealthCheck(nameOrID)
if err != nil {
return nil, err
}
diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go
index d8af4d339..e630d9bc8 100644
--- a/pkg/domain/infra/abi/images.go
+++ b/pkg/domain/infra/abi/images.go
@@ -38,8 +38,8 @@ import (
// SignatureStoreDir defines default directory to store signatures
const SignatureStoreDir = "/var/lib/containers/sigstore"
-func (ir *ImageEngine) Exists(_ context.Context, nameOrId string) (*entities.BoolReport, error) {
- _, err := ir.Libpod.ImageRuntime().NewFromLocal(nameOrId)
+func (ir *ImageEngine) Exists(_ context.Context, nameOrID string) (*entities.BoolReport, error) {
+ _, err := ir.Libpod.ImageRuntime().NewFromLocal(nameOrID)
if err != nil && errors.Cause(err) != define.ErrNoSuchImage {
return nil, err
}
@@ -65,8 +65,8 @@ func (ir *ImageEngine) pruneImagesHelper(ctx context.Context, all bool, filters
return &report, nil
}
-func (ir *ImageEngine) History(ctx context.Context, nameOrId string, opts entities.ImageHistoryOptions) (*entities.ImageHistoryReport, error) {
- image, err := ir.Libpod.ImageRuntime().NewFromLocal(nameOrId)
+func (ir *ImageEngine) History(ctx context.Context, nameOrID string, opts entities.ImageHistoryOptions) (*entities.ImageHistoryReport, error) {
+ image, err := ir.Libpod.ImageRuntime().NewFromLocal(nameOrID)
if err != nil {
return nil, err
}
@@ -167,7 +167,7 @@ func (ir *ImageEngine) Pull(ctx context.Context, rawImage string, options entiti
return nil, errors.Wrapf(err, "error getting repository tags")
}
- var foundIDs []string
+ foundIDs := []string{}
for _, tag := range tags {
name := rawImage + ":" + tag
newImage, err := ir.Libpod.ImageRuntime().New(ctx, name, options.SignaturePolicy, options.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, nil, util.PullImageAlways)
@@ -261,8 +261,8 @@ func (ir *ImageEngine) Push(ctx context.Context, source string, destination stri
nil)
}
-// func (r *imageRuntime) Delete(ctx context.Context, nameOrId string, opts entities.ImageDeleteOptions) (*entities.ImageDeleteReport, error) {
-// image, err := r.libpod.ImageEngine().NewFromLocal(nameOrId)
+// func (r *imageRuntime) Delete(ctx context.Context, nameOrID string, opts entities.ImageDeleteOptions) (*entities.ImageDeleteReport, error) {
+// image, err := r.libpod.ImageEngine().NewFromLocal(nameOrID)
// if err != nil {
// return nil, err
// }
@@ -292,8 +292,8 @@ func (ir *ImageEngine) Push(ctx context.Context, source string, destination stri
// return &report, nil
// }
-func (ir *ImageEngine) Tag(ctx context.Context, nameOrId string, tags []string, options entities.ImageTagOptions) error {
- newImage, err := ir.Libpod.ImageRuntime().NewFromLocal(nameOrId)
+func (ir *ImageEngine) Tag(ctx context.Context, nameOrID string, tags []string, options entities.ImageTagOptions) error {
+ newImage, err := ir.Libpod.ImageRuntime().NewFromLocal(nameOrID)
if err != nil {
return err
}
@@ -305,8 +305,8 @@ func (ir *ImageEngine) Tag(ctx context.Context, nameOrId string, tags []string,
return nil
}
-func (ir *ImageEngine) Untag(ctx context.Context, nameOrId string, tags []string, options entities.ImageUntagOptions) error {
- newImage, err := ir.Libpod.ImageRuntime().NewFromLocal(nameOrId)
+func (ir *ImageEngine) Untag(ctx context.Context, nameOrID string, tags []string, options entities.ImageUntagOptions) error {
+ newImage, err := ir.Libpod.ImageRuntime().NewFromLocal(nameOrID)
if err != nil {
return err
}
@@ -356,16 +356,16 @@ func (ir *ImageEngine) Import(ctx context.Context, opts entities.ImageImportOpti
return &entities.ImageImportReport{Id: id}, nil
}
-func (ir *ImageEngine) Save(ctx context.Context, nameOrId string, tags []string, options entities.ImageSaveOptions) error {
- newImage, err := ir.Libpod.ImageRuntime().NewFromLocal(nameOrId)
+func (ir *ImageEngine) Save(ctx context.Context, nameOrID string, tags []string, options entities.ImageSaveOptions) error {
+ newImage, err := ir.Libpod.ImageRuntime().NewFromLocal(nameOrID)
if err != nil {
return err
}
- return newImage.Save(ctx, nameOrId, options.Format, options.Output, tags, options.Quiet, options.Compress)
+ return newImage.Save(ctx, nameOrID, options.Format, options.Output, tags, options.Quiet, options.Compress)
}
-func (ir *ImageEngine) Diff(_ context.Context, nameOrId string, _ entities.DiffOptions) (*entities.DiffReport, error) {
- changes, err := ir.Libpod.GetDiff("", nameOrId)
+func (ir *ImageEngine) Diff(_ context.Context, nameOrID string, _ entities.DiffOptions) (*entities.DiffReport, error) {
+ changes, err := ir.Libpod.GetDiff("", nameOrID)
if err != nil {
return nil, err
}
@@ -420,8 +420,8 @@ func (ir *ImageEngine) Build(ctx context.Context, containerFiles []string, opts
return &entities.BuildReport{ID: id}, nil
}
-func (ir *ImageEngine) Tree(ctx context.Context, nameOrId string, opts entities.ImageTreeOptions) (*entities.ImageTreeReport, error) {
- img, err := ir.Libpod.ImageRuntime().NewFromLocal(nameOrId)
+func (ir *ImageEngine) Tree(ctx context.Context, nameOrID string, opts entities.ImageTreeOptions) (*entities.ImageTreeReport, error) {
+ img, err := ir.Libpod.ImageRuntime().NewFromLocal(nameOrID)
if err != nil {
return nil, err
}
@@ -443,7 +443,7 @@ func removeErrorsToExitCode(rmErrors []error) int {
// container.
inUseErrors bool
// otherErrors indicates that at least one error other than the two
- // above occured.
+ // above occurred.
otherErrors bool
)
@@ -549,8 +549,7 @@ func (ir *ImageEngine) Remove(ctx context.Context, images []string, opts entitie
rmErrors = append(rmErrors, err)
}
}
-
- return
+ return //nolint
}
// Shutdown Libpod engine
diff --git a/pkg/domain/infra/abi/images_list.go b/pkg/domain/infra/abi/images_list.go
index 3034e36ec..98c041c15 100644
--- a/pkg/domain/infra/abi/images_list.go
+++ b/pkg/domain/infra/abi/images_list.go
@@ -8,17 +8,12 @@ import (
)
func (ir *ImageEngine) List(ctx context.Context, opts entities.ImageListOptions) ([]*entities.ImageSummary, error) {
- var (
- images []*libpodImage.Image
- err error
- )
-
- images, err = ir.Libpod.ImageRuntime().GetImagesWithFilters(opts.Filter)
+ images, err := ir.Libpod.ImageRuntime().GetImagesWithFilters(opts.Filter)
if err != nil {
return nil, err
}
- var summaries []*entities.ImageSummary
+ summaries := []*entities.ImageSummary{}
for _, img := range images {
var repoTags []string
if opts.All {
diff --git a/pkg/domain/infra/abi/manifest.go b/pkg/domain/infra/abi/manifest.go
index a2b5fc0fc..a6f5bab6b 100644
--- a/pkg/domain/infra/abi/manifest.go
+++ b/pkg/domain/infra/abi/manifest.go
@@ -153,7 +153,7 @@ func (ir *ImageEngine) ManifestRemove(ctx context.Context, names []string) (stri
}
listImage, err := ir.Libpod.ImageRuntime().NewFromLocal(names[0])
if err != nil {
- return "", errors.Wrapf(err, "error retriving local image from image name %s", names[0])
+ return "", errors.Wrapf(err, "error retrieving local image from image name %s", names[0])
}
updatedListID, err := listImage.RemoveManifest(instanceDigest)
if err == nil {
@@ -166,7 +166,7 @@ func (ir *ImageEngine) ManifestRemove(ctx context.Context, names []string) (stri
func (ir *ImageEngine) ManifestPush(ctx context.Context, names []string, opts entities.ManifestPushOptions) error {
listImage, err := ir.Libpod.ImageRuntime().NewFromLocal(names[0])
if err != nil {
- return errors.Wrapf(err, "error retriving local image from image name %s", names[0])
+ return errors.Wrapf(err, "error retrieving local image from image name %s", names[0])
}
dest, err := alltransports.ParseImageName(names[1])
if err != nil {
diff --git a/pkg/domain/infra/abi/network.go b/pkg/domain/infra/abi/network.go
index 8e3515824..eba1af362 100644
--- a/pkg/domain/infra/abi/network.go
+++ b/pkg/domain/infra/abi/network.go
@@ -48,15 +48,12 @@ func (ic *ContainerEngine) NetworkList(ctx context.Context, options entities.Net
}
func (ic *ContainerEngine) NetworkInspect(ctx context.Context, namesOrIds []string, options entities.NetworkInspectOptions) ([]entities.NetworkInspectReport, error) {
- var (
- rawCNINetworks []entities.NetworkInspectReport
- )
-
config, err := ic.Libpod.GetConfig()
if err != nil {
return nil, err
}
+ rawCNINetworks := make([]entities.NetworkInspectReport, 0, len(namesOrIds))
for _, name := range namesOrIds {
rawList, err := network.InspectNetwork(config, name)
if err != nil {
@@ -68,7 +65,7 @@ func (ic *ContainerEngine) NetworkInspect(ctx context.Context, namesOrIds []stri
}
func (ic *ContainerEngine) NetworkRm(ctx context.Context, namesOrIds []string, options entities.NetworkRmOptions) ([]*entities.NetworkRmReport, error) {
- var reports []*entities.NetworkRmReport
+ reports := []*entities.NetworkRmReport{}
config, err := ic.Libpod.GetConfig()
if err != nil {
diff --git a/pkg/domain/infra/abi/parse/parse.go b/pkg/domain/infra/abi/parse/parse.go
index 6c0e1ee55..2320c6a32 100644
--- a/pkg/domain/infra/abi/parse/parse.go
+++ b/pkg/domain/infra/abi/parse/parse.go
@@ -12,7 +12,7 @@ import (
// Handle volume options from CLI.
// Parse "o" option to find UID, GID.
-func ParseVolumeOptions(opts map[string]string) ([]libpod.VolumeCreateOption, error) {
+func VolumeOptions(opts map[string]string) ([]libpod.VolumeCreateOption, error) {
libpodOptions := []libpod.VolumeCreateOption{}
volumeOptions := make(map[string]string)
diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go
index 6d0919d2b..7053cec9e 100644
--- a/pkg/domain/infra/abi/play.go
+++ b/pkg/domain/infra/abi/play.go
@@ -26,6 +26,7 @@ import (
"github.com/ghodss/yaml"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
+ v1apps "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
)
@@ -38,13 +39,7 @@ const (
func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options entities.PlayKubeOptions) (*entities.PlayKubeReport, error) {
var (
- containers []*libpod.Container
- pod *libpod.Pod
- podOptions []libpod.PodCreateOption
- podYAML v1.Pod
- registryCreds *types.DockerAuthConfig
- writer io.Writer
- report entities.PlayKubeReport
+ kubeObject v1.ObjectReference
)
content, err := ioutil.ReadFile(path)
@@ -52,32 +47,91 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en
return nil, err
}
- if err := yaml.Unmarshal(content, &podYAML); err != nil {
+ if err := yaml.Unmarshal(content, &kubeObject); err != nil {
return nil, errors.Wrapf(err, "unable to read %q as YAML", path)
}
// NOTE: pkg/bindings/play is also parsing the file.
// A pkg/kube would be nice to refactor and abstract
// parts of the K8s-related code.
- if podYAML.Kind != "Pod" {
- return nil, errors.Errorf("invalid YAML kind: %q. Pod is the only supported Kubernetes YAML kind", podYAML.Kind)
+ switch kubeObject.Kind {
+ case "Pod":
+ var podYAML v1.Pod
+ var podTemplateSpec v1.PodTemplateSpec
+ if err := yaml.Unmarshal(content, &podYAML); err != nil {
+ return nil, errors.Wrapf(err, "unable to read YAML %q as Kube Pod", path)
+ }
+ podTemplateSpec.ObjectMeta = podYAML.ObjectMeta
+ podTemplateSpec.Spec = podYAML.Spec
+ return ic.playKubePod(ctx, podTemplateSpec.ObjectMeta.Name, &podTemplateSpec, options)
+ case "Deployment":
+ var deploymentYAML v1apps.Deployment
+ if err := yaml.Unmarshal(content, &deploymentYAML); err != nil {
+ return nil, errors.Wrapf(err, "unable to read YAML %q as Kube Deployment", path)
+ }
+ return ic.playKubeDeployment(ctx, &deploymentYAML, options)
+ default:
+ return nil, errors.Errorf("invalid YAML kind: %q. [Pod|Deployment] are the only supported Kubernetes Kinds", kubeObject.Kind)
+ }
+
+}
+
+func (ic *ContainerEngine) playKubeDeployment(ctx context.Context, deploymentYAML *v1apps.Deployment, options entities.PlayKubeOptions) (*entities.PlayKubeReport, error) {
+ var (
+ deploymentName string
+ podSpec v1.PodTemplateSpec
+ numReplicas int32
+ i int32
+ report entities.PlayKubeReport
+ )
+
+ deploymentName = deploymentYAML.ObjectMeta.Name
+ if deploymentName == "" {
+ return nil, errors.Errorf("Deployment does not have a name")
+ }
+ numReplicas = 1
+ if deploymentYAML.Spec.Replicas != nil {
+ numReplicas = *deploymentYAML.Spec.Replicas
+ }
+ podSpec = deploymentYAML.Spec.Template
+
+ // create "replicas" number of pods
+ for i = 0; i < numReplicas; i++ {
+ podName := fmt.Sprintf("%s-pod-%d", deploymentName, i)
+ podReport, err := ic.playKubePod(ctx, podName, &podSpec, options)
+ if err != nil {
+ return nil, errors.Wrapf(err, "Error encountered while bringing up pod %s", podName)
+ }
+ report.Pods = append(report.Pods, podReport.Pods...)
}
+ return &report, nil
+}
+
+func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podYAML *v1.PodTemplateSpec, options entities.PlayKubeOptions) (*entities.PlayKubeReport, error) {
+ var (
+ pod *libpod.Pod
+ registryCreds *types.DockerAuthConfig
+ writer io.Writer
+ playKubePod entities.PlayKubePod
+ report entities.PlayKubeReport
+ )
// check for name collision between pod and container
- podName := podYAML.ObjectMeta.Name
if podName == "" {
return nil, errors.Errorf("pod does not have a name")
}
for _, n := range podYAML.Spec.Containers {
if n.Name == podName {
- report.Logs = append(report.Logs,
+ playKubePod.Logs = append(playKubePod.Logs,
fmt.Sprintf("a container exists with the same name (%q) as the pod in your YAML file; changing pod name to %s_pod\n", podName, podName))
podName = fmt.Sprintf("%s_pod", podName)
}
}
- podOptions = append(podOptions, libpod.WithInfraContainer())
- podOptions = append(podOptions, libpod.WithPodName(podName))
+ podOptions := []libpod.PodCreateOption{
+ libpod.WithInfraContainer(),
+ libpod.WithPodName(podName),
+ }
// TODO for now we just used the default kernel namespaces; we need to add/subtract this from yaml
hostname := podYAML.Spec.Hostname
@@ -217,6 +271,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en
return nil, err
}
+ containers := make([]*libpod.Container, 0, len(podYAML.Spec.Containers))
for _, container := range podYAML.Spec.Containers {
pullPolicy := util.PullImageMissing
if len(container.ImagePullPolicy) > 0 {
@@ -239,11 +294,11 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en
if err != nil {
return nil, err
}
- conf, err := kubeContainerToCreateConfig(ctx, container, ic.Libpod, newImage, namespaces, volumes, pod.ID(), podInfraID, seccompPaths)
+ conf, err := kubeContainerToCreateConfig(ctx, container, newImage, namespaces, volumes, pod.ID(), podName, podInfraID, seccompPaths)
if err != nil {
return nil, err
}
- ctr, err := createconfig.CreateContainerFromCreateConfig(ic.Libpod, conf, ctx, pod)
+ ctr, err := createconfig.CreateContainerFromCreateConfig(ctx, ic.Libpod, conf, pod)
if err != nil {
return nil, err
}
@@ -259,11 +314,13 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options en
}
}
- report.Pod = pod.ID()
+ playKubePod.ID = pod.ID()
for _, ctr := range containers {
- report.Containers = append(report.Containers, ctr.ID())
+ playKubePod.Containers = append(playKubePod.Containers, ctr.ID())
}
+ report.Pods = append(report.Pods, playKubePod)
+
return &report, nil
}
@@ -351,7 +408,7 @@ func setupSecurityContext(securityConfig *createconfig.SecurityConfig, userConfi
}
// kubeContainerToCreateConfig takes a v1.Container and returns a createconfig describing a container
-func kubeContainerToCreateConfig(ctx context.Context, containerYAML v1.Container, runtime *libpod.Runtime, newImage *image.Image, namespaces map[string]string, volumes map[string]string, podID, infraID string, seccompPaths *kubeSeccompPaths) (*createconfig.CreateConfig, error) {
+func kubeContainerToCreateConfig(ctx context.Context, containerYAML v1.Container, newImage *image.Image, namespaces map[string]string, volumes map[string]string, podID, podName, infraID string, seccompPaths *kubeSeccompPaths) (*createconfig.CreateConfig, error) {
var (
containerConfig createconfig.CreateConfig
pidConfig createconfig.PidConfig
@@ -368,7 +425,14 @@ func kubeContainerToCreateConfig(ctx context.Context, containerYAML v1.Container
containerConfig.Image = containerYAML.Image
containerConfig.ImageID = newImage.ID()
- containerConfig.Name = containerYAML.Name
+
+ // podName should be non-empty for Deployment objects to be able to create
+ // multiple pods having containers with unique names
+ if podName == "" {
+ return nil, errors.Errorf("kubeContainerToCreateConfig got empty podName")
+ }
+ containerConfig.Name = fmt.Sprintf("%s-%s", podName, containerYAML.Name)
+
containerConfig.Tty = containerYAML.TTY
containerConfig.Pod = podID
@@ -382,7 +446,10 @@ func kubeContainerToCreateConfig(ctx context.Context, containerYAML v1.Container
setupSecurityContext(&securityConfig, &userConfig, containerYAML)
- securityConfig.SeccompProfilePath = seccompPaths.findForContainer(containerConfig.Name)
+ // Since we prefix the container name with pod name to work-around the uniqueness requirement,
+ // the seccom profile should reference the actual container name from the YAML
+ // but apply to the containers with the prefixed name
+ securityConfig.SeccompProfilePath = seccompPaths.findForContainer(containerYAML.Name)
containerConfig.Command = []string{}
if imageData != nil && imageData.Config != nil {
diff --git a/pkg/domain/infra/abi/pods.go b/pkg/domain/infra/abi/pods.go
index 320880920..4a122f54d 100644
--- a/pkg/domain/infra/abi/pods.go
+++ b/pkg/domain/infra/abi/pods.go
@@ -45,8 +45,8 @@ func getPodsByContext(all, latest bool, pods []string, runtime *libpod.Runtime)
return outpods, err
}
-func (ic *ContainerEngine) PodExists(ctx context.Context, nameOrId string) (*entities.BoolReport, error) {
- _, err := ic.Libpod.LookupPod(nameOrId)
+func (ic *ContainerEngine) PodExists(ctx context.Context, nameOrID string) (*entities.BoolReport, error) {
+ _, err := ic.Libpod.LookupPod(nameOrID)
if err != nil && errors.Cause(err) != define.ErrNoSuchPod {
return nil, err
}
@@ -54,9 +54,7 @@ func (ic *ContainerEngine) PodExists(ctx context.Context, nameOrId string) (*ent
}
func (ic *ContainerEngine) PodKill(ctx context.Context, namesOrIds []string, options entities.PodKillOptions) ([]*entities.PodKillReport, error) {
- var (
- reports []*entities.PodKillReport
- )
+ reports := []*entities.PodKillReport{}
sig, err := signal.ParseSignalNameOrNumber(options.Signal)
if err != nil {
return nil, err
@@ -87,9 +85,7 @@ func (ic *ContainerEngine) PodKill(ctx context.Context, namesOrIds []string, opt
}
func (ic *ContainerEngine) PodPause(ctx context.Context, namesOrIds []string, options entities.PodPauseOptions) ([]*entities.PodPauseReport, error) {
- var (
- reports []*entities.PodPauseReport
- )
+ reports := []*entities.PodPauseReport{}
pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod)
if err != nil {
return nil, err
@@ -114,9 +110,7 @@ func (ic *ContainerEngine) PodPause(ctx context.Context, namesOrIds []string, op
}
func (ic *ContainerEngine) PodUnpause(ctx context.Context, namesOrIds []string, options entities.PodunpauseOptions) ([]*entities.PodUnpauseReport, error) {
- var (
- reports []*entities.PodUnpauseReport
- )
+ reports := []*entities.PodUnpauseReport{}
pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod)
if err != nil {
return nil, err
@@ -141,9 +135,7 @@ func (ic *ContainerEngine) PodUnpause(ctx context.Context, namesOrIds []string,
}
func (ic *ContainerEngine) PodStop(ctx context.Context, namesOrIds []string, options entities.PodStopOptions) ([]*entities.PodStopReport, error) {
- var (
- reports []*entities.PodStopReport
- )
+ reports := []*entities.PodStopReport{}
pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod)
if err != nil && !(options.Ignore && errors.Cause(err) == define.ErrNoSuchPod) {
return nil, err
@@ -168,9 +160,7 @@ func (ic *ContainerEngine) PodStop(ctx context.Context, namesOrIds []string, opt
}
func (ic *ContainerEngine) PodRestart(ctx context.Context, namesOrIds []string, options entities.PodRestartOptions) ([]*entities.PodRestartReport, error) {
- var (
- reports []*entities.PodRestartReport
- )
+ reports := []*entities.PodRestartReport{}
pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod)
if err != nil {
return nil, err
@@ -196,13 +186,12 @@ func (ic *ContainerEngine) PodRestart(ctx context.Context, namesOrIds []string,
}
func (ic *ContainerEngine) PodStart(ctx context.Context, namesOrIds []string, options entities.PodStartOptions) ([]*entities.PodStartReport, error) {
- var (
- reports []*entities.PodStartReport
- )
+ reports := []*entities.PodStartReport{}
pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod)
if err != nil {
return nil, err
}
+
for _, p := range pods {
report := entities.PodStartReport{Id: p.ID()}
errs, err := p.Start(ctx)
@@ -224,13 +213,11 @@ func (ic *ContainerEngine) PodStart(ctx context.Context, namesOrIds []string, op
}
func (ic *ContainerEngine) PodRm(ctx context.Context, namesOrIds []string, options entities.PodRmOptions) ([]*entities.PodRmReport, error) {
- var (
- reports []*entities.PodRmReport
- )
pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod)
if err != nil && !(options.Ignore && errors.Cause(err) == define.ErrNoSuchPod) {
return nil, err
}
+ reports := make([]*entities.PodRmReport, 0, len(pods))
for _, p := range pods {
report := entities.PodRmReport{Id: p.ID()}
err := ic.Libpod.RemovePod(ctx, p, true, options.Force)
@@ -247,13 +234,11 @@ func (ic *ContainerEngine) PodPrune(ctx context.Context, options entities.PodPru
}
func (ic *ContainerEngine) prunePodHelper(ctx context.Context) ([]*entities.PodPruneReport, error) {
- var (
- reports []*entities.PodPruneReport
- )
response, err := ic.Libpod.PrunePods(ctx)
if err != nil {
return nil, err
}
+ reports := make([]*entities.PodPruneReport, 0, len(response))
for k, v := range response {
reports = append(reports, &entities.PodPruneReport{
Err: v,
@@ -298,9 +283,8 @@ func (ic *ContainerEngine) PodTop(ctx context.Context, options entities.PodTopOp
func (ic *ContainerEngine) PodPs(ctx context.Context, options entities.PodPSOptions) ([]*entities.ListPodsReport, error) {
var (
err error
- filters []libpod.PodFilter
- pds []*libpod.Pod
- reports []*entities.ListPodsReport
+ filters = []libpod.PodFilter{}
+ pds = []*libpod.Pod{}
)
for k, v := range options.Filters {
@@ -326,6 +310,7 @@ func (ic *ContainerEngine) PodPs(ctx context.Context, options entities.PodPSOpti
}
}
+ reports := make([]*entities.ListPodsReport, 0, len(pds))
for _, p := range pds {
var lpcs []*entities.ListPodContainer
status, err := p.GetPodStatus()
@@ -347,7 +332,7 @@ func (ic *ContainerEngine) PodPs(ctx context.Context, options entities.PodPSOpti
Status: state.String(),
})
}
- infraId, err := p.InfraContainerID()
+ infraID, err := p.InfraContainerID()
if err != nil {
return nil, err
}
@@ -356,7 +341,7 @@ func (ic *ContainerEngine) PodPs(ctx context.Context, options entities.PodPSOpti
Containers: lpcs,
Created: p.CreatedTime(),
Id: p.ID(),
- InfraId: infraId,
+ InfraId: infraID,
Name: p.Name(),
Namespace: p.Namespace(),
Status: status,
diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go
index 9b538b301..90002326e 100644
--- a/pkg/domain/infra/abi/system.go
+++ b/pkg/domain/infra/abi/system.go
@@ -72,11 +72,9 @@ func (ic *ContainerEngine) SetupRootless(_ context.Context, cmd *cobra.Command)
return err
}
unitName := fmt.Sprintf("podman-%d.scope", os.Getpid())
- if err := utils.RunUnderSystemdScope(os.Getpid(), "user.slice", unitName); err != nil {
- if conf.Engine.CgroupManager == config.SystemdCgroupsManager {
+ if conf.Engine.CgroupManager == config.SystemdCgroupsManager {
+ if err := utils.RunUnderSystemdScope(os.Getpid(), "user.slice", unitName); err != nil {
logrus.Warnf("Failed to add podman to systemd sandbox cgroup: %v", err)
- } else {
- logrus.Debugf("Failed to add podman to systemd sandbox cgroup: %v", err)
}
}
}
@@ -174,7 +172,7 @@ func checkInput() error { // nolint:deadcode,unused
return nil
}
-// SystemPrune removes unsed data from the system. Pruning pods, containers, volumes and images.
+// SystemPrune removes unused data from the system. Pruning pods, containers, volumes and images.
func (ic *ContainerEngine) SystemPrune(ctx context.Context, options entities.SystemPruneOptions) (*entities.SystemPruneReport, error) {
var systemPruneReport = new(entities.SystemPruneReport)
podPruneReport, err := ic.prunePodHelper(ctx)
@@ -183,7 +181,7 @@ func (ic *ContainerEngine) SystemPrune(ctx context.Context, options entities.Sys
}
systemPruneReport.PodPruneReport = podPruneReport
- containerPruneReport, err := ic.pruneContainersHelper(ctx, nil)
+ containerPruneReport, err := ic.pruneContainersHelper(nil)
if err != nil {
return nil, err
}
@@ -214,10 +212,7 @@ func (ic *ContainerEngine) SystemPrune(ctx context.Context, options entities.Sys
func (ic *ContainerEngine) SystemDf(ctx context.Context, options entities.SystemDfOptions) (*entities.SystemDfReport, error) {
var (
- dfImages []*entities.SystemDfImageReport
- dfContainers []*entities.SystemDfContainerReport
- dfVolumes []*entities.SystemDfVolumeReport
- runningContainers []string
+ dfImages = []*entities.SystemDfImageReport{}
)
// Get Images and iterate them
@@ -284,6 +279,7 @@ func (ic *ContainerEngine) SystemDf(ctx context.Context, options entities.System
if err != nil {
return nil, err
}
+ dfContainers := make([]*entities.SystemDfContainerReport, 0, len(cons))
for _, c := range cons {
iid, _ := c.Image()
conSize, err := c.RootFsSize()
@@ -322,10 +318,12 @@ func (ic *ContainerEngine) SystemDf(ctx context.Context, options entities.System
if err != nil {
return nil, err
}
+ runningContainers := make([]string, 0, len(running))
for _, c := range running {
runningContainers = append(runningContainers, c.ID())
}
+ dfVolumes := make([]*entities.SystemDfVolumeReport, 0, len(vols))
for _, v := range vols {
var consInUse int
volSize, err := sizeOfPath(v.MountPoint())
@@ -338,7 +336,7 @@ func (ic *ContainerEngine) SystemDf(ctx context.Context, options entities.System
}
for _, viu := range inUse {
if util.StringInSlice(viu, runningContainers) {
- consInUse += 1
+ consInUse++
}
}
report := entities.SystemDfVolumeReport{
@@ -376,12 +374,12 @@ func (se *SystemEngine) Renumber(ctx context.Context, flags *pflag.FlagSet, conf
return nil
}
-func (s SystemEngine) Migrate(ctx context.Context, flags *pflag.FlagSet, config *entities.PodmanConfig, options entities.SystemMigrateOptions) error {
+func (se SystemEngine) Migrate(ctx context.Context, flags *pflag.FlagSet, config *entities.PodmanConfig, options entities.SystemMigrateOptions) error {
return nil
}
-func (s SystemEngine) Shutdown(ctx context.Context) {
- if err := s.Libpod.Shutdown(false); err != nil {
+func (se SystemEngine) Shutdown(ctx context.Context) {
+ if err := se.Libpod.Shutdown(false); err != nil {
logrus.Error(err)
}
}
diff --git a/pkg/domain/infra/abi/trust.go b/pkg/domain/infra/abi/trust.go
index 5b89c91d9..03986ad0e 100644
--- a/pkg/domain/infra/abi/trust.go
+++ b/pkg/domain/infra/abi/trust.go
@@ -112,8 +112,8 @@ func (ir *ImageEngine) SetTrust(ctx context.Context, args []string, options enti
return ioutil.WriteFile(policyPath, data, 0644)
}
-func getPolicyShowOutput(policyContentStruct trust.PolicyContent, systemRegistriesDirPath string) ([]*trust.TrustPolicy, error) {
- var output []*trust.TrustPolicy
+func getPolicyShowOutput(policyContentStruct trust.PolicyContent, systemRegistriesDirPath string) ([]*trust.Policy, error) {
+ var output []*trust.Policy
registryConfigs, err := trust.LoadAndMergeConfig(systemRegistriesDirPath)
if err != nil {
@@ -121,7 +121,7 @@ func getPolicyShowOutput(policyContentStruct trust.PolicyContent, systemRegistri
}
if len(policyContentStruct.Default) > 0 {
- defaultPolicyStruct := trust.TrustPolicy{
+ defaultPolicyStruct := trust.Policy{
Name: "* (default)",
RepoName: "default",
Type: trustTypeDescription(policyContentStruct.Default[0].Type),
@@ -130,7 +130,7 @@ func getPolicyShowOutput(policyContentStruct trust.PolicyContent, systemRegistri
}
for _, transval := range policyContentStruct.Transports {
for repo, repoval := range transval {
- tempTrustShowOutput := trust.TrustPolicy{
+ tempTrustShowOutput := trust.Policy{
Name: repo,
RepoName: repo,
Type: repoval[0].Type,
diff --git a/pkg/domain/infra/abi/volumes.go b/pkg/domain/infra/abi/volumes.go
index 91b2440df..702e11003 100644
--- a/pkg/domain/infra/abi/volumes.go
+++ b/pkg/domain/infra/abi/volumes.go
@@ -10,7 +10,7 @@ import (
"github.com/pkg/errors"
)
-func (ic *ContainerEngine) VolumeCreate(ctx context.Context, opts entities.VolumeCreateOptions) (*entities.IdOrNameResponse, error) {
+func (ic *ContainerEngine) VolumeCreate(ctx context.Context, opts entities.VolumeCreateOptions) (*entities.IDOrNameResponse, error) {
var (
volumeOptions []libpod.VolumeCreateOption
)
@@ -24,7 +24,7 @@ func (ic *ContainerEngine) VolumeCreate(ctx context.Context, opts entities.Volum
volumeOptions = append(volumeOptions, libpod.WithVolumeLabels(opts.Label))
}
if len(opts.Options) > 0 {
- parsedOptions, err := parse.ParseVolumeOptions(opts.Options)
+ parsedOptions, err := parse.VolumeOptions(opts.Options)
if err != nil {
return nil, err
}
@@ -34,15 +34,16 @@ func (ic *ContainerEngine) VolumeCreate(ctx context.Context, opts entities.Volum
if err != nil {
return nil, err
}
- return &entities.IdOrNameResponse{IdOrName: vol.Name()}, nil
+ return &entities.IDOrNameResponse{IDOrName: vol.Name()}, nil
}
func (ic *ContainerEngine) VolumeRm(ctx context.Context, namesOrIds []string, opts entities.VolumeRmOptions) ([]*entities.VolumeRmReport, error) {
var (
err error
- reports []*entities.VolumeRmReport
vols []*libpod.Volume
+ reports = []*entities.VolumeRmReport{}
)
+
if opts.All {
vols, err = ic.Libpod.Volumes()
if err != nil {
@@ -72,9 +73,8 @@ func (ic *ContainerEngine) VolumeRm(ctx context.Context, namesOrIds []string, op
func (ic *ContainerEngine) VolumeInspect(ctx context.Context, namesOrIds []string, opts entities.VolumeInspectOptions) ([]*entities.VolumeInspectReport, error) {
var (
- err error
- reports []*entities.VolumeInspectReport
- vols []*libpod.Volume
+ err error
+ vols []*libpod.Volume
)
// Note: as with previous implementation, a single failure here
@@ -93,6 +93,7 @@ func (ic *ContainerEngine) VolumeInspect(ctx context.Context, namesOrIds []strin
vols = append(vols, vol)
}
}
+ reports := make([]*entities.VolumeInspectReport, 0, len(vols))
for _, v := range vols {
config := entities.VolumeConfigResponse{
Name: v.Name(),
@@ -115,13 +116,11 @@ func (ic *ContainerEngine) VolumePrune(ctx context.Context, opts entities.Volume
}
func (ic *ContainerEngine) pruneVolumesHelper(ctx context.Context) ([]*entities.VolumePruneReport, error) {
- var (
- reports []*entities.VolumePruneReport
- )
pruned, err := ic.Libpod.PruneVolumes(ctx)
if err != nil {
return nil, err
}
+ reports := make([]*entities.VolumePruneReport, 0, len(pruned))
for k, v := range pruned {
reports = append(reports, &entities.VolumePruneReport{
Err: v,
@@ -132,9 +131,6 @@ func (ic *ContainerEngine) pruneVolumesHelper(ctx context.Context) ([]*entities.
}
func (ic *ContainerEngine) VolumeList(ctx context.Context, opts entities.VolumeListOptions) ([]*entities.VolumeListReport, error) {
- var (
- reports []*entities.VolumeListReport
- )
volumeFilters, err := filters.GenerateVolumeFilters(opts.Filter)
if err != nil {
return nil, err
@@ -143,6 +139,7 @@ func (ic *ContainerEngine) VolumeList(ctx context.Context, opts entities.VolumeL
if err != nil {
return nil, err
}
+ reports := make([]*entities.VolumeListReport, 0, len(vols))
for _, v := range vols {
config := entities.VolumeConfigResponse{
Name: v.Name(),
diff --git a/pkg/domain/infra/runtime_abi.go b/pkg/domain/infra/runtime_abi.go
index 0a82b9a6b..60d0c6e86 100644
--- a/pkg/domain/infra/runtime_abi.go
+++ b/pkg/domain/infra/runtime_abi.go
@@ -20,7 +20,7 @@ func NewContainerEngine(facts *entities.PodmanConfig) (entities.ContainerEngine,
r, err := NewLibpodRuntime(facts.FlagSet, facts)
return r, err
case entities.TunnelMode:
- ctx, err := bindings.NewConnectionWithIdentity(context.Background(), facts.Uri, facts.PassPhrase, facts.Identities...)
+ ctx, err := bindings.NewConnectionWithIdentity(context.Background(), facts.URI, facts.PassPhrase, facts.Identities...)
return &tunnel.ContainerEngine{ClientCxt: ctx}, err
}
return nil, fmt.Errorf("runtime mode '%v' is not supported", facts.EngineMode)
@@ -33,7 +33,7 @@ func NewImageEngine(facts *entities.PodmanConfig) (entities.ImageEngine, error)
r, err := NewLibpodImageRuntime(facts.FlagSet, facts)
return r, err
case entities.TunnelMode:
- ctx, err := bindings.NewConnectionWithIdentity(context.Background(), facts.Uri, facts.PassPhrase, facts.Identities...)
+ ctx, err := bindings.NewConnectionWithIdentity(context.Background(), facts.URI, facts.PassPhrase, facts.Identities...)
return &tunnel.ImageEngine{ClientCxt: ctx}, err
}
return nil, fmt.Errorf("runtime mode '%v' is not supported", facts.EngineMode)
diff --git a/pkg/domain/infra/runtime_tunnel.go b/pkg/domain/infra/runtime_tunnel.go
index bba7d2c0c..24a93b888 100644
--- a/pkg/domain/infra/runtime_tunnel.go
+++ b/pkg/domain/infra/runtime_tunnel.go
@@ -16,7 +16,7 @@ func NewContainerEngine(facts *entities.PodmanConfig) (entities.ContainerEngine,
case entities.ABIMode:
return nil, fmt.Errorf("direct runtime not supported")
case entities.TunnelMode:
- ctx, err := bindings.NewConnectionWithIdentity(context.Background(), facts.Uri, facts.PassPhrase, facts.Identities...)
+ ctx, err := bindings.NewConnectionWithIdentity(context.Background(), facts.URI, facts.PassPhrase, facts.Identities...)
return &tunnel.ContainerEngine{ClientCxt: ctx}, err
}
return nil, fmt.Errorf("runtime mode '%v' is not supported", facts.EngineMode)
@@ -28,7 +28,7 @@ func NewImageEngine(facts *entities.PodmanConfig) (entities.ImageEngine, error)
case entities.ABIMode:
return nil, fmt.Errorf("direct image runtime not supported")
case entities.TunnelMode:
- ctx, err := bindings.NewConnectionWithIdentity(context.Background(), facts.Uri, facts.PassPhrase, facts.Identities...)
+ ctx, err := bindings.NewConnectionWithIdentity(context.Background(), facts.URI, facts.PassPhrase, facts.Identities...)
return &tunnel.ImageEngine{ClientCxt: ctx}, err
}
return nil, fmt.Errorf("runtime mode '%v' is not supported", facts.EngineMode)
diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go
index 36b7bf535..4bd813847 100644
--- a/pkg/domain/infra/tunnel/containers.go
+++ b/pkg/domain/infra/tunnel/containers.go
@@ -26,19 +26,17 @@ func (ic *ContainerEngine) ContainerRunlabel(ctx context.Context, label string,
return errors.New("not implemented")
}
-func (ic *ContainerEngine) ContainerExists(ctx context.Context, nameOrId string) (*entities.BoolReport, error) {
- exists, err := containers.Exists(ic.ClientCxt, nameOrId)
+func (ic *ContainerEngine) ContainerExists(ctx context.Context, nameOrID string) (*entities.BoolReport, error) {
+ exists, err := containers.Exists(ic.ClientCxt, nameOrID)
return &entities.BoolReport{Value: exists}, err
}
func (ic *ContainerEngine) ContainerWait(ctx context.Context, namesOrIds []string, options entities.WaitOptions) ([]entities.WaitReport, error) {
- var (
- responses []entities.WaitReport
- )
cons, err := getContainersByContext(ic.ClientCxt, false, namesOrIds)
if err != nil {
return nil, err
}
+ responses := make([]entities.WaitReport, 0, len(cons))
for _, c := range cons {
response := entities.WaitReport{Id: c.ID}
exitCode, err := containers.Wait(ic.ClientCxt, c.ID, &options.Condition)
@@ -53,13 +51,11 @@ func (ic *ContainerEngine) ContainerWait(ctx context.Context, namesOrIds []strin
}
func (ic *ContainerEngine) ContainerPause(ctx context.Context, namesOrIds []string, options entities.PauseUnPauseOptions) ([]*entities.PauseUnpauseReport, error) {
- var (
- reports []*entities.PauseUnpauseReport
- )
ctrs, err := getContainersByContext(ic.ClientCxt, options.All, namesOrIds)
if err != nil {
return nil, err
}
+ reports := make([]*entities.PauseUnpauseReport, 0, len(ctrs))
for _, c := range ctrs {
err := containers.Pause(ic.ClientCxt, c.ID)
reports = append(reports, &entities.PauseUnpauseReport{Id: c.ID, Err: err})
@@ -68,13 +64,11 @@ func (ic *ContainerEngine) ContainerPause(ctx context.Context, namesOrIds []stri
}
func (ic *ContainerEngine) ContainerUnpause(ctx context.Context, namesOrIds []string, options entities.PauseUnPauseOptions) ([]*entities.PauseUnpauseReport, error) {
- var (
- reports []*entities.PauseUnpauseReport
- )
ctrs, err := getContainersByContext(ic.ClientCxt, options.All, namesOrIds)
if err != nil {
return nil, err
}
+ reports := make([]*entities.PauseUnpauseReport, 0, len(ctrs))
for _, c := range ctrs {
err := containers.Unpause(ic.ClientCxt, c.ID)
reports = append(reports, &entities.PauseUnpauseReport{Id: c.ID, Err: err})
@@ -83,9 +77,7 @@ func (ic *ContainerEngine) ContainerUnpause(ctx context.Context, namesOrIds []st
}
func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []string, options entities.StopOptions) ([]*entities.StopReport, error) {
- var (
- reports []*entities.StopReport
- )
+ reports := []*entities.StopReport{}
for _, cidFile := range options.CIDFiles {
content, err := ioutil.ReadFile(cidFile)
if err != nil {
@@ -100,7 +92,7 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin
}
for _, c := range ctrs {
report := entities.StopReport{Id: c.ID}
- if err = containers.Stop(ic.ClientCxt, c.ID, &options.Timeout); err != nil {
+ if err = containers.Stop(ic.ClientCxt, c.ID, options.Timeout); err != nil {
// These first two are considered non-fatal under the right conditions
if errors.Cause(err).Error() == define.ErrCtrStopped.Error() {
logrus.Debugf("Container %s is already stopped", c.ID)
@@ -125,13 +117,11 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin
}
func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []string, options entities.KillOptions) ([]*entities.KillReport, error) {
- var (
- reports []*entities.KillReport
- )
ctrs, err := getContainersByContext(ic.ClientCxt, options.All, namesOrIds)
if err != nil {
return nil, err
}
+ reports := make([]*entities.KillReport, 0, len(ctrs))
for _, c := range ctrs {
reports = append(reports, &entities.KillReport{
Id: c.ID,
@@ -143,7 +133,7 @@ func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []strin
func (ic *ContainerEngine) ContainerRestart(ctx context.Context, namesOrIds []string, options entities.RestartOptions) ([]*entities.RestartReport, error) {
var (
- reports []*entities.RestartReport
+ reports = []*entities.RestartReport{}
timeout *int
)
if options.Timeout != nil {
@@ -168,9 +158,6 @@ func (ic *ContainerEngine) ContainerRestart(ctx context.Context, namesOrIds []st
}
func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string, options entities.RmOptions) ([]*entities.RmReport, error) {
- var (
- reports []*entities.RmReport
- )
for _, cidFile := range options.CIDFiles {
content, err := ioutil.ReadFile(cidFile)
if err != nil {
@@ -184,6 +171,7 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string,
return nil, err
}
// TODO there is no endpoint for container eviction. Need to discuss
+ reports := make([]*entities.RmReport, 0, len(ctrs))
for _, c := range ctrs {
reports = append(reports, &entities.RmReport{
Id: c.ID,
@@ -198,13 +186,11 @@ func (ic *ContainerEngine) ContainerPrune(ctx context.Context, options entities.
}
func (ic *ContainerEngine) ContainerInspect(ctx context.Context, namesOrIds []string, options entities.InspectOptions) ([]*entities.ContainerInspectReport, error) {
- var (
- reports []*entities.ContainerInspectReport
- )
ctrs, err := getContainersByContext(ic.ClientCxt, false, namesOrIds)
if err != nil {
return nil, err
}
+ reports := make([]*entities.ContainerInspectReport, 0, len(ctrs))
for _, con := range ctrs {
data, err := containers.Inspect(ic.ClientCxt, con.ID, &options.Size)
if err != nil {
@@ -230,10 +216,10 @@ func (ic *ContainerEngine) ContainerTop(ctx context.Context, options entities.To
return &entities.StringSliceReport{Value: topOutput}, nil
}
-func (ic *ContainerEngine) ContainerCommit(ctx context.Context, nameOrId string, options entities.CommitOptions) (*entities.CommitReport, error) {
+func (ic *ContainerEngine) ContainerCommit(ctx context.Context, nameOrID string, options entities.CommitOptions) (*entities.CommitReport, error) {
var (
repo string
- tag string = "latest"
+ tag = "latest"
)
if len(options.ImageName) > 0 {
ref, err := reference.Parse(options.ImageName)
@@ -259,14 +245,14 @@ func (ic *ContainerEngine) ContainerCommit(ctx context.Context, nameOrId string,
Repo: &repo,
Tag: &tag,
}
- response, err := containers.Commit(ic.ClientCxt, nameOrId, commitOpts)
+ response, err := containers.Commit(ic.ClientCxt, nameOrID, commitOpts)
if err != nil {
return nil, err
}
return &entities.CommitReport{Id: response.ID}, nil
}
-func (ic *ContainerEngine) ContainerExport(ctx context.Context, nameOrId string, options entities.ContainerExportOptions) error {
+func (ic *ContainerEngine) ContainerExport(ctx context.Context, nameOrID string, options entities.ContainerExportOptions) error {
var (
err error
w io.Writer
@@ -277,14 +263,13 @@ func (ic *ContainerEngine) ContainerExport(ctx context.Context, nameOrId string,
return err
}
}
- return containers.Export(ic.ClientCxt, nameOrId, w)
+ return containers.Export(ic.ClientCxt, nameOrID, w)
}
func (ic *ContainerEngine) ContainerCheckpoint(ctx context.Context, namesOrIds []string, options entities.CheckpointOptions) ([]*entities.CheckpointReport, error) {
var (
- reports []*entities.CheckpointReport
- err error
- ctrs []entities.ListContainer
+ err error
+ ctrs = []entities.ListContainer{}
)
if options.All {
@@ -305,6 +290,7 @@ func (ic *ContainerEngine) ContainerCheckpoint(ctx context.Context, namesOrIds [
return nil, err
}
}
+ reports := make([]*entities.CheckpointReport, 0, len(ctrs))
for _, c := range ctrs {
report, err := containers.Checkpoint(ic.ClientCxt, c.ID, &options.Keep, &options.LeaveRunning, &options.TCPEstablished, &options.IgnoreRootFS, &options.Export)
if err != nil {
@@ -317,9 +303,8 @@ func (ic *ContainerEngine) ContainerCheckpoint(ctx context.Context, namesOrIds [
func (ic *ContainerEngine) ContainerRestore(ctx context.Context, namesOrIds []string, options entities.RestoreOptions) ([]*entities.RestoreReport, error) {
var (
- reports []*entities.RestoreReport
- err error
- ctrs []entities.ListContainer
+ err error
+ ctrs = []entities.ListContainer{}
)
if options.All {
allCtrs, err := getContainersByContext(ic.ClientCxt, true, []string{})
@@ -339,6 +324,7 @@ func (ic *ContainerEngine) ContainerRestore(ctx context.Context, namesOrIds []st
return nil, err
}
}
+ reports := make([]*entities.RestoreReport, 0, len(ctrs))
for _, c := range ctrs {
report, err := containers.Restore(ic.ClientCxt, c.ID, &options.Keep, &options.TCPEstablished, &options.IgnoreRootFS, &options.IgnoreStaticIP, &options.IgnoreStaticMAC, &options.Name, &options.Import)
if err != nil {
@@ -357,7 +343,7 @@ func (ic *ContainerEngine) ContainerCreate(ctx context.Context, s *specgen.SpecG
return &entities.ContainerCreateReport{Id: response.ID}, nil
}
-func (ic *ContainerEngine) ContainerLogs(_ context.Context, nameOrIds []string, options entities.ContainerLogsOptions) error {
+func (ic *ContainerEngine) ContainerLogs(_ context.Context, nameOrIDs []string, options entities.ContainerLogsOptions) error {
since := options.Since.Format(time.RFC3339)
tail := strconv.FormatInt(options.Tail, 10)
stdout := options.Writer != nil
@@ -375,7 +361,7 @@ func (ic *ContainerEngine) ContainerLogs(_ context.Context, nameOrIds []string,
outCh := make(chan string)
ctx, cancel := context.WithCancel(context.Background())
go func() {
- err = containers.Logs(ic.ClientCxt, nameOrIds[0], opts, outCh, outCh)
+ err = containers.Logs(ic.ClientCxt, nameOrIDs[0], opts, outCh, outCh)
cancel()
}()
@@ -389,8 +375,8 @@ func (ic *ContainerEngine) ContainerLogs(_ context.Context, nameOrIds []string,
}
}
-func (ic *ContainerEngine) ContainerAttach(ctx context.Context, nameOrId string, options entities.AttachOptions) error {
- return containers.Attach(ic.ClientCxt, nameOrId, &options.DetachKeys, nil, bindings.PTrue, options.Stdin, options.Stdout, options.Stderr, nil)
+func (ic *ContainerEngine) ContainerAttach(ctx context.Context, nameOrID string, options entities.AttachOptions) error {
+ return containers.Attach(ic.ClientCxt, nameOrID, &options.DetachKeys, nil, bindings.PTrue, options.Stdin, options.Stdout, options.Stderr, nil)
}
func makeExecConfig(options entities.ExecOptions) *handlers.ExecCreateConfig {
@@ -415,10 +401,10 @@ func makeExecConfig(options entities.ExecOptions) *handlers.ExecCreateConfig {
return createConfig
}
-func (ic *ContainerEngine) ContainerExec(ctx context.Context, nameOrId string, options entities.ExecOptions, streams define.AttachStreams) (int, error) {
+func (ic *ContainerEngine) ContainerExec(ctx context.Context, nameOrID string, options entities.ExecOptions, streams define.AttachStreams) (int, error) {
createConfig := makeExecConfig(options)
- sessionID, err := containers.ExecCreate(ic.ClientCxt, nameOrId, createConfig)
+ sessionID, err := containers.ExecCreate(ic.ClientCxt, nameOrID, createConfig)
if err != nil {
return 125, err
}
@@ -435,10 +421,10 @@ func (ic *ContainerEngine) ContainerExec(ctx context.Context, nameOrId string, o
return inspectOut.ExitCode, nil
}
-func (ic *ContainerEngine) ContainerExecDetached(ctx context.Context, nameOrId string, options entities.ExecOptions) (string, error) {
+func (ic *ContainerEngine) ContainerExecDetached(ctx context.Context, nameOrID string, options entities.ExecOptions) (string, error) {
createConfig := makeExecConfig(options)
- sessionID, err := containers.ExecCreate(ic.ClientCxt, nameOrId, createConfig)
+ sessionID, err := containers.ExecCreate(ic.ClientCxt, nameOrID, createConfig)
if err != nil {
return "", err
}
@@ -467,7 +453,7 @@ func startAndAttach(ic *ContainerEngine, name string, detachKeys *string, input,
}
func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []string, options entities.ContainerStartOptions) ([]*entities.ContainerStartReport, error) {
- var reports []*entities.ContainerStartReport
+ reports := []*entities.ContainerStartReport{}
for _, name := range namesOrIds {
report := entities.ContainerStartReport{
Id: name,
@@ -525,8 +511,8 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta
return &report, err
}
-func (ic *ContainerEngine) ContainerDiff(ctx context.Context, nameOrId string, _ entities.DiffOptions) (*entities.DiffReport, error) {
- changes, err := containers.Diff(ic.ClientCxt, nameOrId)
+func (ic *ContainerEngine) ContainerDiff(ctx context.Context, nameOrID string, _ entities.DiffOptions) (*entities.DiffReport, error) {
+ changes, err := containers.Diff(ic.ClientCxt, nameOrID)
return &entities.DiffReport{Changes: changes}, err
}
@@ -535,11 +521,11 @@ func (ic *ContainerEngine) ContainerCleanup(ctx context.Context, namesOrIds []st
}
func (ic *ContainerEngine) ContainerInit(ctx context.Context, namesOrIds []string, options entities.ContainerInitOptions) ([]*entities.ContainerInitReport, error) {
- var reports []*entities.ContainerInitReport
ctrs, err := getContainersByContext(ic.ClientCxt, options.All, namesOrIds)
if err != nil {
return nil, err
}
+ reports := make([]*entities.ContainerInitReport, 0, len(ctrs))
for _, ctr := range ctrs {
err := containers.ContainerInit(ic.ClientCxt, ctr.ID)
// When using all, it is NOT considered an error if a container
@@ -555,11 +541,11 @@ func (ic *ContainerEngine) ContainerInit(ctx context.Context, namesOrIds []strin
return reports, nil
}
-func (ic *ContainerEngine) ContainerMount(ctx context.Context, nameOrIds []string, options entities.ContainerMountOptions) ([]*entities.ContainerMountReport, error) {
+func (ic *ContainerEngine) ContainerMount(ctx context.Context, nameOrIDs []string, options entities.ContainerMountOptions) ([]*entities.ContainerMountReport, error) {
return nil, errors.New("mounting containers is not supported for remote clients")
}
-func (ic *ContainerEngine) ContainerUnmount(ctx context.Context, nameOrIds []string, options entities.ContainerUnmountOptions) ([]*entities.ContainerUnmountReport, error) {
+func (ic *ContainerEngine) ContainerUnmount(ctx context.Context, nameOrIDs []string, options entities.ContainerUnmountOptions) ([]*entities.ContainerUnmountReport, error) {
return nil, errors.New("unmounting containers is not supported for remote clients")
}
@@ -567,13 +553,13 @@ func (ic *ContainerEngine) Config(_ context.Context) (*config.Config, error) {
return config.Default()
}
-func (ic *ContainerEngine) ContainerPort(ctx context.Context, nameOrId string, options entities.ContainerPortOptions) ([]*entities.ContainerPortReport, error) {
+func (ic *ContainerEngine) ContainerPort(ctx context.Context, nameOrID string, options entities.ContainerPortOptions) ([]*entities.ContainerPortReport, error) {
var (
- reports []*entities.ContainerPortReport
- namesOrIds []string
+ reports = []*entities.ContainerPortReport{}
+ namesOrIds = []string{}
)
- if len(nameOrId) > 0 {
- namesOrIds = append(namesOrIds, nameOrId)
+ if len(nameOrID) > 0 {
+ namesOrIds = append(namesOrIds, nameOrID)
}
ctrs, err := getContainersByContext(ic.ClientCxt, options.All, namesOrIds)
if err != nil {
diff --git a/pkg/domain/infra/tunnel/generate.go b/pkg/domain/infra/tunnel/generate.go
index eb5587f89..519dc5907 100644
--- a/pkg/domain/infra/tunnel/generate.go
+++ b/pkg/domain/infra/tunnel/generate.go
@@ -13,5 +13,5 @@ func (ic *ContainerEngine) GenerateSystemd(ctx context.Context, nameOrID string,
}
func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrID string, options entities.GenerateKubeOptions) (*entities.GenerateKubeReport, error) {
- return generate.GenerateKube(ic.ClientCxt, nameOrID, options)
+ return generate.Kube(ic.ClientCxt, nameOrID, options)
}
diff --git a/pkg/domain/infra/tunnel/healthcheck.go b/pkg/domain/infra/tunnel/healthcheck.go
index e589489b3..56bdd6759 100644
--- a/pkg/domain/infra/tunnel/healthcheck.go
+++ b/pkg/domain/infra/tunnel/healthcheck.go
@@ -8,6 +8,6 @@ import (
"github.com/containers/libpod/pkg/domain/entities"
)
-func (ic *ContainerEngine) HealthCheckRun(ctx context.Context, nameOrId string, options entities.HealthCheckOptions) (*define.HealthCheckResults, error) {
- return containers.RunHealthCheck(ic.ClientCxt, nameOrId)
+func (ic *ContainerEngine) HealthCheckRun(ctx context.Context, nameOrID string, options entities.HealthCheckOptions) (*define.HealthCheckResults, error) {
+ return containers.RunHealthCheck(ic.ClientCxt, nameOrID)
}
diff --git a/pkg/domain/infra/tunnel/helpers.go b/pkg/domain/infra/tunnel/helpers.go
index 862c7a5d6..2bbc0e7a5 100644
--- a/pkg/domain/infra/tunnel/helpers.go
+++ b/pkg/domain/infra/tunnel/helpers.go
@@ -13,11 +13,11 @@ import (
"github.com/pkg/errors"
)
-func getContainersByContext(contextWithConnection context.Context, all bool, namesOrIds []string) ([]entities.ListContainer, error) {
+func getContainersByContext(contextWithConnection context.Context, all bool, namesOrIDs []string) ([]entities.ListContainer, error) {
var (
cons []entities.ListContainer
)
- if all && len(namesOrIds) > 0 {
+ if all && len(namesOrIDs) > 0 {
return nil, errors.New("cannot lookup containers and all")
}
c, err := containers.List(contextWithConnection, nil, bindings.PTrue, nil, nil, nil, bindings.PTrue)
@@ -27,7 +27,7 @@ func getContainersByContext(contextWithConnection context.Context, all bool, nam
if all {
return c, err
}
- for _, id := range namesOrIds {
+ for _, id := range namesOrIDs {
var found bool
for _, con := range c {
if id == con.ID || strings.HasPrefix(con.ID, id) || util.StringInSlice(id, con.Names) {
@@ -43,11 +43,11 @@ func getContainersByContext(contextWithConnection context.Context, all bool, nam
return cons, nil
}
-func getPodsByContext(contextWithConnection context.Context, all bool, namesOrIds []string) ([]*entities.ListPodsReport, error) {
+func getPodsByContext(contextWithConnection context.Context, all bool, namesOrIDs []string) ([]*entities.ListPodsReport, error) {
var (
sPods []*entities.ListPodsReport
)
- if all && len(namesOrIds) > 0 {
+ if all && len(namesOrIDs) > 0 {
return nil, errors.New("cannot lookup specific pods and all")
}
@@ -58,17 +58,17 @@ func getPodsByContext(contextWithConnection context.Context, all bool, namesOrId
if all {
return fPods, nil
}
- for _, nameOrId := range namesOrIds {
+ for _, nameOrID := range namesOrIDs {
var found bool
for _, f := range fPods {
- if f.Name == nameOrId || strings.HasPrefix(f.Id, nameOrId) {
+ if f.Name == nameOrID || strings.HasPrefix(f.Id, nameOrID) {
sPods = append(sPods, f)
found = true
break
}
}
if !found {
- return nil, errors.Wrapf(define.ErrNoSuchPod, "unable to find pod %q", nameOrId)
+ return nil, errors.Wrapf(define.ErrNoSuchPod, "unable to find pod %q", nameOrID)
}
}
return sPods, nil
diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go
index c300e74d0..ec2c53c4f 100644
--- a/pkg/domain/infra/tunnel/images.go
+++ b/pkg/domain/infra/tunnel/images.go
@@ -18,8 +18,8 @@ import (
"github.com/pkg/errors"
)
-func (ir *ImageEngine) Exists(_ context.Context, nameOrId string) (*entities.BoolReport, error) {
- found, err := images.Exists(ir.ClientCxt, nameOrId)
+func (ir *ImageEngine) Exists(_ context.Context, nameOrID string) (*entities.BoolReport, error) {
+ found, err := images.Exists(ir.ClientCxt, nameOrID)
return &entities.BoolReport{Value: found}, err
}
@@ -39,7 +39,7 @@ func (ir *ImageEngine) List(ctx context.Context, opts entities.ImageListOptions)
return nil, err
}
- is := make([]*entities.ImageSummary, len(images))
+ is := make([]*entities.ImageSummary, 0, len(images))
for i, img := range images {
hold := entities.ImageSummary{}
if err := utils.DeepCopy(&hold, img); err != nil {
@@ -50,8 +50,8 @@ func (ir *ImageEngine) List(ctx context.Context, opts entities.ImageListOptions)
return is, nil
}
-func (ir *ImageEngine) History(ctx context.Context, nameOrId string, opts entities.ImageHistoryOptions) (*entities.ImageHistoryReport, error) {
- results, err := images.History(ir.ClientCxt, nameOrId)
+func (ir *ImageEngine) History(ctx context.Context, nameOrID string, opts entities.ImageHistoryOptions) (*entities.ImageHistoryReport, error) {
+ results, err := images.History(ir.ClientCxt, nameOrID)
if err != nil {
return nil, err
}
@@ -98,7 +98,7 @@ func (ir *ImageEngine) Pull(ctx context.Context, rawImage string, options entiti
return &entities.ImagePullReport{Images: pulledImages}, nil
}
-func (ir *ImageEngine) Tag(ctx context.Context, nameOrId string, tags []string, options entities.ImageTagOptions) error {
+func (ir *ImageEngine) Tag(ctx context.Context, nameOrID string, tags []string, options entities.ImageTagOptions) error {
for _, newTag := range tags {
var (
tag, repo string
@@ -114,19 +114,19 @@ func (ir *ImageEngine) Tag(ctx context.Context, nameOrId string, tags []string,
repo = r.Name()
}
if len(repo) < 1 {
- return errors.Errorf("invalid image name %q", nameOrId)
+ return errors.Errorf("invalid image name %q", nameOrID)
}
- if err := images.Tag(ir.ClientCxt, nameOrId, tag, repo); err != nil {
+ if err := images.Tag(ir.ClientCxt, nameOrID, tag, repo); err != nil {
return err
}
}
return nil
}
-func (ir *ImageEngine) Untag(ctx context.Context, nameOrId string, tags []string, options entities.ImageUntagOptions) error {
+func (ir *ImageEngine) Untag(ctx context.Context, nameOrID string, tags []string, options entities.ImageUntagOptions) error {
// Remove all tags if none are provided
if len(tags) == 0 {
- newImage, err := images.GetImage(ir.ClientCxt, nameOrId, bindings.PFalse)
+ newImage, err := images.GetImage(ir.ClientCxt, nameOrID, bindings.PFalse)
if err != nil {
return err
}
@@ -148,9 +148,9 @@ func (ir *ImageEngine) Untag(ctx context.Context, nameOrId string, tags []string
repo = r.Name()
}
if len(repo) < 1 {
- return errors.Errorf("invalid image name %q", nameOrId)
+ return errors.Errorf("invalid image name %q", nameOrID)
}
- if err := images.Untag(ir.ClientCxt, nameOrId, tag, repo); err != nil {
+ if err := images.Untag(ir.ClientCxt, nameOrID, tag, repo); err != nil {
return err
}
}
@@ -199,7 +199,7 @@ func (ir *ImageEngine) Push(ctx context.Context, source string, destination stri
return images.Push(ir.ClientCxt, source, destination, options)
}
-func (ir *ImageEngine) Save(ctx context.Context, nameOrId string, tags []string, options entities.ImageSaveOptions) error {
+func (ir *ImageEngine) Save(ctx context.Context, nameOrID string, tags []string, options entities.ImageSaveOptions) error {
var (
f *os.File
err error
@@ -217,7 +217,7 @@ func (ir *ImageEngine) Save(ctx context.Context, nameOrId string, tags []string,
return err
}
- exErr := images.Export(ir.ClientCxt, nameOrId, f, &options.Format, &options.Compress)
+ exErr := images.Export(ir.ClientCxt, nameOrID, f, &options.Format, &options.Compress)
if err := f.Close(); err != nil {
return err
}
@@ -250,8 +250,8 @@ func (ir *ImageEngine) Save(ctx context.Context, nameOrId string, tags []string,
}
// Diff reports the changes to the given image
-func (ir *ImageEngine) Diff(ctx context.Context, nameOrId string, _ entities.DiffOptions) (*entities.DiffReport, error) {
- changes, err := images.Diff(ir.ClientCxt, nameOrId)
+func (ir *ImageEngine) Diff(ctx context.Context, nameOrID string, _ entities.DiffOptions) (*entities.DiffReport, error) {
+ changes, err := images.Diff(ir.ClientCxt, nameOrID)
if err != nil {
return nil, err
}
@@ -277,8 +277,8 @@ func (ir *ImageEngine) Build(ctx context.Context, containerFiles []string, opts
return images.Build(ir.ClientCxt, containerFiles, opts, tarfile)
}
-func (ir *ImageEngine) Tree(ctx context.Context, nameOrId string, opts entities.ImageTreeOptions) (*entities.ImageTreeReport, error) {
- return images.Tree(ir.ClientCxt, nameOrId, &opts.WhatRequires)
+func (ir *ImageEngine) Tree(ctx context.Context, nameOrID string, opts entities.ImageTreeOptions) (*entities.ImageTreeReport, error) {
+ return images.Tree(ir.ClientCxt, nameOrID, &opts.WhatRequires)
}
// Shutdown Libpod engine
diff --git a/pkg/domain/infra/tunnel/network.go b/pkg/domain/infra/tunnel/network.go
index 7725d8257..e7cc5fb26 100644
--- a/pkg/domain/infra/tunnel/network.go
+++ b/pkg/domain/infra/tunnel/network.go
@@ -12,7 +12,7 @@ func (ic *ContainerEngine) NetworkList(ctx context.Context, options entities.Net
}
func (ic *ContainerEngine) NetworkInspect(ctx context.Context, namesOrIds []string, options entities.NetworkInspectOptions) ([]entities.NetworkInspectReport, error) {
- var reports []entities.NetworkInspectReport
+ reports := make([]entities.NetworkInspectReport, 0, len(namesOrIds))
for _, name := range namesOrIds {
report, err := network.Inspect(ic.ClientCxt, name)
if err != nil {
@@ -24,7 +24,7 @@ func (ic *ContainerEngine) NetworkInspect(ctx context.Context, namesOrIds []stri
}
func (ic *ContainerEngine) NetworkRm(ctx context.Context, namesOrIds []string, options entities.NetworkRmOptions) ([]*entities.NetworkRmReport, error) {
- var reports []*entities.NetworkRmReport
+ reports := make([]*entities.NetworkRmReport, 0, len(namesOrIds))
for _, name := range namesOrIds {
report, err := network.Remove(ic.ClientCxt, name, &options.Force)
if err != nil {
diff --git a/pkg/domain/infra/tunnel/play.go b/pkg/domain/infra/tunnel/play.go
index 15383a703..5f6bc4a2a 100644
--- a/pkg/domain/infra/tunnel/play.go
+++ b/pkg/domain/infra/tunnel/play.go
@@ -8,5 +8,5 @@ import (
)
func (ic *ContainerEngine) PlayKube(ctx context.Context, path string, options entities.PlayKubeOptions) (*entities.PlayKubeReport, error) {
- return play.PlayKube(ic.ClientCxt, path, options)
+ return play.Kube(ic.ClientCxt, path, options)
}
diff --git a/pkg/domain/infra/tunnel/pods.go b/pkg/domain/infra/tunnel/pods.go
index b93c48aab..d18e9937c 100644
--- a/pkg/domain/infra/tunnel/pods.go
+++ b/pkg/domain/infra/tunnel/pods.go
@@ -7,22 +7,26 @@ import (
"github.com/containers/libpod/pkg/bindings/pods"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/specgen"
+ "github.com/containers/libpod/pkg/util"
"github.com/pkg/errors"
)
-func (ic *ContainerEngine) PodExists(ctx context.Context, nameOrId string) (*entities.BoolReport, error) {
- exists, err := pods.Exists(ic.ClientCxt, nameOrId)
+func (ic *ContainerEngine) PodExists(ctx context.Context, nameOrID string) (*entities.BoolReport, error) {
+ exists, err := pods.Exists(ic.ClientCxt, nameOrID)
return &entities.BoolReport{Value: exists}, err
}
func (ic *ContainerEngine) PodKill(ctx context.Context, namesOrIds []string, options entities.PodKillOptions) ([]*entities.PodKillReport, error) {
- var (
- reports []*entities.PodKillReport
- )
+ _, err := util.ParseSignal(options.Signal)
+ if err != nil {
+ return nil, err
+ }
+
foundPods, err := getPodsByContext(ic.ClientCxt, options.All, namesOrIds)
if err != nil {
return nil, err
}
+ reports := make([]*entities.PodKillReport, 0, len(foundPods))
for _, p := range foundPods {
response, err := pods.Kill(ic.ClientCxt, p.Id, &options.Signal)
if err != nil {
@@ -39,13 +43,11 @@ func (ic *ContainerEngine) PodKill(ctx context.Context, namesOrIds []string, opt
}
func (ic *ContainerEngine) PodPause(ctx context.Context, namesOrIds []string, options entities.PodPauseOptions) ([]*entities.PodPauseReport, error) {
- var (
- reports []*entities.PodPauseReport
- )
foundPods, err := getPodsByContext(ic.ClientCxt, options.All, namesOrIds)
if err != nil {
return nil, err
}
+ reports := make([]*entities.PodPauseReport, 0, len(foundPods))
for _, p := range foundPods {
response, err := pods.Pause(ic.ClientCxt, p.Id)
if err != nil {
@@ -62,13 +64,11 @@ func (ic *ContainerEngine) PodPause(ctx context.Context, namesOrIds []string, op
}
func (ic *ContainerEngine) PodUnpause(ctx context.Context, namesOrIds []string, options entities.PodunpauseOptions) ([]*entities.PodUnpauseReport, error) {
- var (
- reports []*entities.PodUnpauseReport
- )
foundPods, err := getPodsByContext(ic.ClientCxt, options.All, namesOrIds)
if err != nil {
return nil, err
}
+ reports := make([]*entities.PodUnpauseReport, 0, len(foundPods))
for _, p := range foundPods {
response, err := pods.Unpause(ic.ClientCxt, p.Id)
if err != nil {
@@ -85,10 +85,7 @@ func (ic *ContainerEngine) PodUnpause(ctx context.Context, namesOrIds []string,
}
func (ic *ContainerEngine) PodStop(ctx context.Context, namesOrIds []string, options entities.PodStopOptions) ([]*entities.PodStopReport, error) {
- var (
- reports []*entities.PodStopReport
- timeout int = -1
- )
+ timeout := -1
foundPods, err := getPodsByContext(ic.ClientCxt, options.All, namesOrIds)
if err != nil && !(options.Ignore && errors.Cause(err) == define.ErrNoSuchPod) {
return nil, err
@@ -96,6 +93,7 @@ func (ic *ContainerEngine) PodStop(ctx context.Context, namesOrIds []string, opt
if options.Timeout != -1 {
timeout = options.Timeout
}
+ reports := make([]*entities.PodStopReport, 0, len(foundPods))
for _, p := range foundPods {
response, err := pods.Stop(ic.ClientCxt, p.Id, &timeout)
if err != nil {
@@ -112,11 +110,11 @@ func (ic *ContainerEngine) PodStop(ctx context.Context, namesOrIds []string, opt
}
func (ic *ContainerEngine) PodRestart(ctx context.Context, namesOrIds []string, options entities.PodRestartOptions) ([]*entities.PodRestartReport, error) {
- var reports []*entities.PodRestartReport
foundPods, err := getPodsByContext(ic.ClientCxt, options.All, namesOrIds)
if err != nil {
return nil, err
}
+ reports := make([]*entities.PodRestartReport, 0, len(foundPods))
for _, p := range foundPods {
response, err := pods.Restart(ic.ClientCxt, p.Id)
if err != nil {
@@ -133,11 +131,11 @@ func (ic *ContainerEngine) PodRestart(ctx context.Context, namesOrIds []string,
}
func (ic *ContainerEngine) PodStart(ctx context.Context, namesOrIds []string, options entities.PodStartOptions) ([]*entities.PodStartReport, error) {
- var reports []*entities.PodStartReport
foundPods, err := getPodsByContext(ic.ClientCxt, options.All, namesOrIds)
if err != nil {
return nil, err
}
+ reports := make([]*entities.PodStartReport, 0, len(foundPods))
for _, p := range foundPods {
response, err := pods.Start(ic.ClientCxt, p.Id)
if err != nil {
@@ -154,11 +152,11 @@ func (ic *ContainerEngine) PodStart(ctx context.Context, namesOrIds []string, op
}
func (ic *ContainerEngine) PodRm(ctx context.Context, namesOrIds []string, options entities.PodRmOptions) ([]*entities.PodRmReport, error) {
- var reports []*entities.PodRmReport
foundPods, err := getPodsByContext(ic.ClientCxt, options.All, namesOrIds)
if err != nil && !(options.Ignore && errors.Cause(err) == define.ErrNoSuchPod) {
return nil, err
}
+ reports := make([]*entities.PodRmReport, 0, len(foundPods))
for _, p := range foundPods {
response, err := pods.Remove(ic.ClientCxt, p.Id, &options.Force)
if err != nil {
diff --git a/pkg/domain/infra/tunnel/volumes.go b/pkg/domain/infra/tunnel/volumes.go
index e48a7fa7c..af7273ac4 100644
--- a/pkg/domain/infra/tunnel/volumes.go
+++ b/pkg/domain/infra/tunnel/volumes.go
@@ -7,19 +7,15 @@ import (
"github.com/containers/libpod/pkg/domain/entities"
)
-func (ic *ContainerEngine) VolumeCreate(ctx context.Context, opts entities.VolumeCreateOptions) (*entities.IdOrNameResponse, error) {
+func (ic *ContainerEngine) VolumeCreate(ctx context.Context, opts entities.VolumeCreateOptions) (*entities.IDOrNameResponse, error) {
response, err := volumes.Create(ic.ClientCxt, opts)
if err != nil {
return nil, err
}
- return &entities.IdOrNameResponse{IdOrName: response.Name}, nil
+ return &entities.IDOrNameResponse{IDOrName: response.Name}, nil
}
func (ic *ContainerEngine) VolumeRm(ctx context.Context, namesOrIds []string, opts entities.VolumeRmOptions) ([]*entities.VolumeRmReport, error) {
- var (
- reports []*entities.VolumeRmReport
- )
-
if opts.All {
vols, err := volumes.List(ic.ClientCxt, nil)
if err != nil {
@@ -29,6 +25,7 @@ func (ic *ContainerEngine) VolumeRm(ctx context.Context, namesOrIds []string, op
namesOrIds = append(namesOrIds, v.Name)
}
}
+ reports := make([]*entities.VolumeRmReport, 0, len(namesOrIds))
for _, id := range namesOrIds {
reports = append(reports, &entities.VolumeRmReport{
Err: volumes.Remove(ic.ClientCxt, id, &opts.Force),
@@ -39,9 +36,6 @@ func (ic *ContainerEngine) VolumeRm(ctx context.Context, namesOrIds []string, op
}
func (ic *ContainerEngine) VolumeInspect(ctx context.Context, namesOrIds []string, opts entities.VolumeInspectOptions) ([]*entities.VolumeInspectReport, error) {
- var (
- reports []*entities.VolumeInspectReport
- )
if opts.All {
vols, err := volumes.List(ic.ClientCxt, nil)
if err != nil {
@@ -51,6 +45,7 @@ func (ic *ContainerEngine) VolumeInspect(ctx context.Context, namesOrIds []strin
namesOrIds = append(namesOrIds, v.Name)
}
}
+ reports := make([]*entities.VolumeInspectReport, 0, len(namesOrIds))
for _, id := range namesOrIds {
data, err := volumes.Inspect(ic.ClientCxt, id)
if err != nil {
diff --git a/pkg/domain/utils/utils.go b/pkg/domain/utils/utils.go
index c17769f62..ee213e1b6 100644
--- a/pkg/domain/utils/utils.go
+++ b/pkg/domain/utils/utils.go
@@ -31,7 +31,7 @@ func ToLibpodFilters(f url.Values) (filters []string) {
return
}
-func ToUrlValues(f []string) (filters url.Values) {
+func ToURLValues(f []string) (filters url.Values) {
filters = make(url.Values)
for _, v := range f {
t := strings.SplitN(v, "=", 2)
diff --git a/pkg/hooks/exec/runtimeconfigfilter_test.go b/pkg/hooks/exec/runtimeconfigfilter_test.go
index 48dd2f998..f4b6cf86a 100644
--- a/pkg/hooks/exec/runtimeconfigfilter_test.go
+++ b/pkg/hooks/exec/runtimeconfigfilter_test.go
@@ -12,21 +12,11 @@ import (
"github.com/stretchr/testify/assert"
)
-func pointerInt(value int) *int {
- return &value
-}
-
-func pointerUInt32(value uint32) *uint32 {
- return &value
-}
-
-func pointerFileMode(value os.FileMode) *os.FileMode {
- return &value
-}
-
func TestRuntimeConfigFilter(t *testing.T) {
unexpectedEndOfJSONInput := json.Unmarshal([]byte("{\n"), nil) //nolint
-
+ fileMode := os.FileMode(0600)
+ rootUint32 := uint32(0)
+ binUser := int(1)
for _, tt := range []struct {
name string
contextTimeout time.Duration
@@ -77,9 +67,9 @@ func TestRuntimeConfigFilter(t *testing.T) {
Type: "c",
Major: 10,
Minor: 229,
- FileMode: pointerFileMode(0600),
- UID: pointerUInt32(0),
- GID: pointerUInt32(0),
+ FileMode: &fileMode,
+ UID: &rootUint32,
+ GID: &rootUint32,
},
},
},
@@ -96,18 +86,18 @@ func TestRuntimeConfigFilter(t *testing.T) {
Type: "c",
Major: 10,
Minor: 229,
- FileMode: pointerFileMode(0600),
- UID: pointerUInt32(0),
- GID: pointerUInt32(0),
+ FileMode: &fileMode,
+ UID: &rootUint32,
+ GID: &rootUint32,
},
{
Path: "/dev/sda",
Type: "b",
Major: 8,
Minor: 0,
- FileMode: pointerFileMode(0600),
- UID: pointerUInt32(0),
- GID: pointerUInt32(0),
+ FileMode: &fileMode,
+ UID: &rootUint32,
+ GID: &rootUint32,
},
},
},
@@ -137,9 +127,9 @@ func TestRuntimeConfigFilter(t *testing.T) {
Type: "c",
Major: 10,
Minor: 229,
- FileMode: pointerFileMode(0600),
- UID: pointerUInt32(0),
- GID: pointerUInt32(0),
+ FileMode: &fileMode,
+ UID: &rootUint32,
+ GID: &rootUint32,
},
},
},
@@ -156,18 +146,18 @@ func TestRuntimeConfigFilter(t *testing.T) {
Type: "c",
Major: 10,
Minor: 229,
- FileMode: pointerFileMode(0600),
- UID: pointerUInt32(0),
- GID: pointerUInt32(0),
+ FileMode: &fileMode,
+ UID: &rootUint32,
+ GID: &rootUint32,
},
{
Path: "/dev/sdb",
Type: "b",
Major: 8,
Minor: 0,
- FileMode: pointerFileMode(0600),
- UID: pointerUInt32(0),
- GID: pointerUInt32(0),
+ FileMode: &fileMode,
+ UID: &rootUint32,
+ GID: &rootUint32,
},
},
},
@@ -203,7 +193,7 @@ func TestRuntimeConfigFilter(t *testing.T) {
{
Path: path,
Args: []string{"sh", "-c", "sleep 2"},
- Timeout: pointerInt(1),
+ Timeout: &binUser,
},
},
input: &spec.Spec{
diff --git a/pkg/lookup/lookup.go b/pkg/lookup/lookup.go
index dff25f74f..8f241edf2 100644
--- a/pkg/lookup/lookup.go
+++ b/pkg/lookup/lookup.go
@@ -79,7 +79,6 @@ func GetContainerGroups(groups []string, containerMount string, override *Overri
var (
groupDest string
err error
- uintgids []uint32
)
groupPath := etcgroup
@@ -96,6 +95,7 @@ func GetContainerGroups(groups []string, containerMount string, override *Overri
if err != nil {
return nil, err
}
+ uintgids := make([]uint32, 0, len(gids))
// For libpod, we want []uint32s
for _, gid := range gids {
uintgids = append(uintgids, uint32(gid))
diff --git a/pkg/network/files.go b/pkg/network/files.go
index 81c0e1a28..beb3289f3 100644
--- a/pkg/network/files.go
+++ b/pkg/network/files.go
@@ -22,13 +22,13 @@ func GetCNIConfDir(config *config.Config) string {
// LoadCNIConfsFromDir loads all the CNI configurations from a dir
func LoadCNIConfsFromDir(dir string) ([]*libcni.NetworkConfigList, error) {
- var configs []*libcni.NetworkConfigList
files, err := libcni.ConfFiles(dir, []string{".conflist"})
if err != nil {
return nil, err
}
sort.Strings(files)
+ configs := make([]*libcni.NetworkConfigList, 0, len(files))
for _, confFile := range files {
conf, err := libcni.ConfListFromFile(confFile)
if err != nil {
@@ -72,7 +72,7 @@ func ReadRawCNIConfByName(config *config.Config, name string) ([]byte, error) {
// GetCNIPlugins returns a list of plugins that a given network
// has in the form of a string
func GetCNIPlugins(list *libcni.NetworkConfigList) string {
- var plugins []string
+ plugins := make([]string, 0, len(list.Plugins))
for _, plug := range list.Plugins {
plugins = append(plugins, plug.Network.Type)
}
@@ -106,12 +106,11 @@ func GetNetworksFromFilesystem(config *config.Config) ([]*allocator.Net, error)
// GetNetworkNamesFromFileSystem gets all the names from the cni network
// configuration files
func GetNetworkNamesFromFileSystem(config *config.Config) ([]string, error) {
- var networkNames []string
-
networks, err := LoadCNIConfsFromDir(GetCNIConfDir(config))
if err != nil {
return nil, err
}
+ networkNames := []string{}
for _, n := range networks {
networkNames = append(networkNames, n.Name)
}
@@ -144,12 +143,12 @@ func GetInterfaceNameFromConfig(path string) (string, error) {
// GetBridgeNamesFromFileSystem is a convenience function to get all the bridge
// names from the configured networks
func GetBridgeNamesFromFileSystem(config *config.Config) ([]string, error) {
- var bridgeNames []string
-
networks, err := LoadCNIConfsFromDir(GetCNIConfDir(config))
if err != nil {
return nil, err
}
+
+ bridgeNames := []string{}
for _, n := range networks {
var name string
// iterate network conflists
diff --git a/pkg/network/network.go b/pkg/network/network.go
index 526ee92d8..997aaf8a2 100644
--- a/pkg/network/network.go
+++ b/pkg/network/network.go
@@ -14,7 +14,7 @@ import (
)
// DefaultNetworkDriver is the default network type used
-var DefaultNetworkDriver string = "bridge"
+var DefaultNetworkDriver = "bridge"
// SupportedNetworkDrivers describes the list of supported drivers
var SupportedNetworkDrivers = []string{DefaultNetworkDriver}
@@ -30,11 +30,11 @@ func IsSupportedDriver(driver string) error {
// GetLiveNetworks returns a slice of networks representing what the system
// has defined as network interfaces
func GetLiveNetworks() ([]*net.IPNet, error) {
- var nets []*net.IPNet
addrs, err := net.InterfaceAddrs()
if err != nil {
return nil, err
}
+ nets := make([]*net.IPNet, 0, len(addrs))
for _, address := range addrs {
_, n, err := net.ParseCIDR(address.String())
if err != nil {
@@ -47,11 +47,11 @@ func GetLiveNetworks() ([]*net.IPNet, error) {
// GetLiveNetworkNames returns a list of network interfaces on the system
func GetLiveNetworkNames() ([]string, error) {
- var interfaceNames []string
liveInterfaces, err := net.Interfaces()
if err != nil {
return nil, err
}
+ interfaceNames := make([]string, 0, len(liveInterfaces))
for _, i := range liveInterfaces {
interfaceNames = append(interfaceNames, i.Name)
}
diff --git a/pkg/parallel/parallel_linux.go b/pkg/parallel/parallel_linux.go
index e3f086c0e..472571972 100644
--- a/pkg/parallel/parallel_linux.go
+++ b/pkg/parallel/parallel_linux.go
@@ -9,11 +9,11 @@ import (
"github.com/sirupsen/logrus"
)
-// ParallelContainerOp performs the given function on the given set of
+// ContainerOp performs the given function on the given set of
// containers, using a number of parallel threads.
// If no error is returned, each container specified in ctrs will have an entry
// in the resulting map; containers with no error will be set to nil.
-func ParallelContainerOp(ctx context.Context, ctrs []*libpod.Container, applyFunc func(*libpod.Container) error) (map[*libpod.Container]error, error) {
+func ContainerOp(ctx context.Context, ctrs []*libpod.Container, applyFunc func(*libpod.Container) error) (map[*libpod.Container]error, error) {
jobControlLock.RLock()
defer jobControlLock.RUnlock()
@@ -22,7 +22,7 @@ func ParallelContainerOp(ctx context.Context, ctrs []*libpod.Container, applyFun
// The expectation is that most of the time is spent in applyFunc
// anyways.
var (
- errMap map[*libpod.Container]error = make(map[*libpod.Container]error)
+ errMap = make(map[*libpod.Container]error)
errLock sync.Mutex
allDone sync.WaitGroup
)
diff --git a/pkg/ps/ps.go b/pkg/ps/ps.go
index ec96367cb..b07eb7f9a 100644
--- a/pkg/ps/ps.go
+++ b/pkg/ps/ps.go
@@ -21,7 +21,7 @@ import (
func GetContainerLists(runtime *libpod.Runtime, options entities.ContainerListOptions) ([]entities.ListContainer, error) {
var (
filterFuncs []libpod.ContainerFilter
- pss []entities.ListContainer
+ pss = []entities.ListContainer{}
)
all := options.All || options.Last > 0
if len(options.Filters) > 0 {
diff --git a/pkg/signal/signal_linux.go b/pkg/signal/signal_linux.go
index 6eebf7e5a..72ab1b97b 100644
--- a/pkg/signal/signal_linux.go
+++ b/pkg/signal/signal_linux.go
@@ -93,7 +93,7 @@ var signalMap = map[string]syscall.Signal{
// CatchAll catches all signals and relays them to the specified channel.
func CatchAll(sigc chan os.Signal) {
- var handledSigs []os.Signal
+ handledSigs := make([]os.Signal, 0, len(signalMap))
for _, s := range signalMap {
handledSigs = append(handledSigs, s)
}
diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go
index 2cf30a59e..e19c582b5 100644
--- a/pkg/spec/createconfig.go
+++ b/pkg/spec/createconfig.go
@@ -399,7 +399,7 @@ func AddPrivilegedDevices(g *generate.Generator) error {
return addPrivilegedDevices(g)
}
-func CreateContainerFromCreateConfig(r *libpod.Runtime, createConfig *CreateConfig, ctx context.Context, pod *libpod.Pod) (*libpod.Container, error) {
+func CreateContainerFromCreateConfig(ctx context.Context, r *libpod.Runtime, createConfig *CreateConfig, pod *libpod.Pod) (*libpod.Container, error) {
runtimeSpec, options, err := createConfig.MakeContainerConfig(r, pod)
if err != nil {
return nil, err
diff --git a/pkg/specgen/container_validate.go b/pkg/specgen/container_validate.go
index 2c5891f9a..45179343b 100644
--- a/pkg/specgen/container_validate.go
+++ b/pkg/specgen/container_validate.go
@@ -10,7 +10,7 @@ import (
var (
// ErrInvalidSpecConfig describes an error that the given SpecGenerator is invalid
- ErrInvalidSpecConfig error = errors.New("invalid configuration")
+ ErrInvalidSpecConfig = errors.New("invalid configuration")
// SystemDValues describes the only values that SystemD can be
SystemDValues = []string{"true", "false", "always"}
// ImageVolumeModeValues describes the only values that ImageVolumeMode can be
diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go
index 74ae848af..33075b543 100644
--- a/pkg/specgen/generate/container_create.go
+++ b/pkg/specgen/generate/container_create.go
@@ -230,7 +230,7 @@ func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen.
options = append(options, libpod.WithPrivileged(s.Privileged))
// Get namespace related options
- namespaceOptions, err := GenerateNamespaceOptions(ctx, s, rt, pod, img)
+ namespaceOptions, err := namespaceOptions(ctx, s, rt, pod, img)
if err != nil {
return nil, err
}
diff --git a/pkg/specgen/generate/namespaces.go b/pkg/specgen/generate/namespaces.go
index ffa96a5cf..e67afe1bf 100644
--- a/pkg/specgen/generate/namespaces.go
+++ b/pkg/specgen/generate/namespaces.go
@@ -72,13 +72,13 @@ func GetDefaultNamespaceMode(nsType string, cfg *config.Config, pod *libpod.Pod)
return toReturn, errors.Wrapf(define.ErrInvalidArg, "invalid namespace type %q passed", nsType)
}
-// GenerateNamespaceOptions generates container creation options for all
+// namespaceOptions generates container creation options for all
// namespaces in a SpecGenerator.
// Pod is the pod the container will join. May be nil is the container is not
// joining a pod.
// TODO: Consider grouping options that are not directly attached to a namespace
// elsewhere.
-func GenerateNamespaceOptions(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runtime, pod *libpod.Pod, img *image.Image) ([]libpod.CtrCreateOption, error) {
+func namespaceOptions(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runtime, pod *libpod.Pod, img *image.Image) ([]libpod.CtrCreateOption, error) {
toReturn := []libpod.CtrCreateOption{}
// If pod is not nil, get infra container.
diff --git a/pkg/specgen/generate/pod_create.go b/pkg/specgen/generate/pod_create.go
index cd2d69cfb..5ccb1ba80 100644
--- a/pkg/specgen/generate/pod_create.go
+++ b/pkg/specgen/generate/pod_create.go
@@ -93,5 +93,9 @@ func createPodOptions(p *specgen.PodSpecGenerator) ([]libpod.PodCreateOption, er
options = append(options, libpod.WithInfraContainerPorts(ports))
}
options = append(options, libpod.WithPodCgroups())
+ options = append(options, libpod.WithPodCreateCommand())
+ if len(p.InfraConmonPidFile) > 0 {
+ options = append(options, libpod.WithInfraConmonPidFile(p.InfraConmonPidFile))
+ }
return options, nil
}
diff --git a/pkg/specgen/pod_validate.go b/pkg/specgen/pod_validate.go
index 640447e71..2d57cdb91 100644
--- a/pkg/specgen/pod_validate.go
+++ b/pkg/specgen/pod_validate.go
@@ -7,7 +7,7 @@ import (
var (
// ErrInvalidPodSpecConfig describes an error given when the podspecgenerator is invalid
- ErrInvalidPodSpecConfig error = errors.New("invalid pod spec")
+ ErrInvalidPodSpecConfig = errors.New("invalid pod spec")
// containerConfig has the default configurations defined in containers.conf
containerConfig = util.DefaultContainerConfig()
)
diff --git a/pkg/specgen/podspecgen.go b/pkg/specgen/podspecgen.go
index 11976233a..600d27004 100644
--- a/pkg/specgen/podspecgen.go
+++ b/pkg/specgen/podspecgen.go
@@ -25,6 +25,9 @@ type PodBasicConfig struct {
// InfraCommand and InfraImages in this struct.
// Optional.
NoInfra bool `json:"no_infra,omitempty"`
+ // InfraConmonPidFile is a custom path to store the infra container's
+ // conmon PID.
+ InfraConmonPidFile string `json:"infra_conmon_pid_file,omitempty"`
// InfraCommand sets the command that will be used to start the infra
// container.
// If not set, the default set in the Libpod configuration file will be
diff --git a/pkg/systemd/generate/common.go b/pkg/systemd/generate/common.go
new file mode 100644
index 000000000..fe56dc874
--- /dev/null
+++ b/pkg/systemd/generate/common.go
@@ -0,0 +1,50 @@
+package generate
+
+import (
+ "github.com/pkg/errors"
+)
+
+// EnvVariable "PODMAN_SYSTEMD_UNIT" is set in all generated systemd units and
+// is set to the unit's (unique) name.
+const EnvVariable = "PODMAN_SYSTEMD_UNIT"
+
+// restartPolicies includes all valid restart policies to be used in a unit
+// file.
+var restartPolicies = []string{"no", "on-success", "on-failure", "on-abnormal", "on-watchdog", "on-abort", "always"}
+
+// validateRestartPolicy checks that the user-provided policy is valid.
+func validateRestartPolicy(restart string) error {
+ for _, i := range restartPolicies {
+ if i == restart {
+ return nil
+ }
+ }
+ return errors.Errorf("%s is not a valid restart policy", restart)
+}
+
+const headerTemplate = `# {{.ServiceName}}.service
+# autogenerated by Podman {{.PodmanVersion}}
+{{- if .TimeStamp}}
+# {{.TimeStamp}}
+{{- end}}
+
+[Unit]
+Description=Podman {{.ServiceName}}.service
+Documentation=man:podman-generate-systemd(1)
+Wants=network.target
+After=network-online.target
+`
+
+// filterPodFlags removes --pod and --pod-id-file from the specified command.
+func filterPodFlags(command []string) []string {
+ processed := []string{}
+ for i := 0; i < len(command); i++ {
+ s := command[i]
+ if s == "--pod" || s == "--pod-id-file" {
+ i++
+ continue
+ }
+ processed = append(processed, s)
+ }
+ return processed
+}
diff --git a/pkg/systemd/generate/common_test.go b/pkg/systemd/generate/common_test.go
new file mode 100644
index 000000000..f53bb7828
--- /dev/null
+++ b/pkg/systemd/generate/common_test.go
@@ -0,0 +1,25 @@
+package generate
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestFilterPodFlags(t *testing.T) {
+
+ tests := []struct {
+ input []string
+ }{
+ {[]string{"podman", "pod", "create"}},
+ {[]string{"podman", "pod", "create", "--name", "foo"}},
+ {[]string{"podman", "pod", "create", "--pod-id-file", "foo"}},
+ {[]string{"podman", "run", "--pod", "foo"}},
+ }
+
+ for _, test := range tests {
+ processed := filterPodFlags(test.input)
+ assert.NotContains(t, processed, "--pod-id-file")
+ assert.NotContains(t, processed, "--pod")
+ }
+}
diff --git a/pkg/systemd/generate/containers.go b/pkg/systemd/generate/containers.go
new file mode 100644
index 000000000..4180022cb
--- /dev/null
+++ b/pkg/systemd/generate/containers.go
@@ -0,0 +1,307 @@
+package generate
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "sort"
+ "strings"
+ "text/template"
+ "time"
+
+ "github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/containers/libpod/version"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+)
+
+// containerInfo contains data required for generating a container's systemd
+// unit file.
+type containerInfo struct {
+ // ServiceName of the systemd service.
+ ServiceName string
+ // Name or ID of the container.
+ ContainerNameOrID string
+ // StopTimeout sets the timeout Podman waits before killing the container
+ // during service stop.
+ StopTimeout uint
+ // RestartPolicy of the systemd unit (e.g., no, on-failure, always).
+ RestartPolicy string
+ // PIDFile of the service. Required for forking services. Must point to the
+ // PID of the associated conmon process.
+ PIDFile string
+ // ContainerIDFile to be used in the unit.
+ ContainerIDFile string
+ // GenerateTimestamp, if set the generated unit file has a time stamp.
+ GenerateTimestamp bool
+ // BoundToServices are the services this service binds to. Note that this
+ // service runs after them.
+ BoundToServices []string
+ // PodmanVersion for the header. Will be set internally. Will be auto-filled
+ // if left empty.
+ PodmanVersion string
+ // Executable is the path to the podman executable. Will be auto-filled if
+ // left empty.
+ Executable string
+ // TimeStamp at the time of creating the unit file. Will be set internally.
+ TimeStamp string
+ // CreateCommand is the full command plus arguments of the process the
+ // container has been created with.
+ CreateCommand []string
+ // EnvVariable is generate.EnvVariable and must not be set.
+ EnvVariable string
+ // ExecStartPre of the unit.
+ ExecStartPre string
+ // ExecStart of the unit.
+ ExecStart string
+ // ExecStop of the unit.
+ ExecStop string
+ // ExecStopPost of the unit.
+ ExecStopPost string
+
+ // If not nil, the container is part of the pod. We can use the
+ // podInfo to extract the relevant data.
+ pod *podInfo
+}
+
+const containerTemplate = headerTemplate + `
+{{- if .BoundToServices}}
+RefuseManualStart=yes
+RefuseManualStop=yes
+BindsTo={{- range $index, $value := .BoundToServices -}}{{if $index}} {{end}}{{ $value }}.service{{end}}
+After={{- range $index, $value := .BoundToServices -}}{{if $index}} {{end}}{{ $value }}.service{{end}}
+{{- end}}
+
+[Service]
+Environment={{.EnvVariable}}=%n
+Restart={{.RestartPolicy}}
+{{- if .ExecStartPre}}
+ExecStartPre={{.ExecStartPre}}
+{{- end}}
+ExecStart={{.ExecStart}}
+ExecStop={{.ExecStop}}
+{{- if .ExecStopPost}}
+ExecStopPost={{.ExecStopPost}}
+{{- end}}
+PIDFile={{.PIDFile}}
+KillMode=none
+Type=forking
+
+[Install]
+WantedBy=multi-user.target default.target`
+
+// ContainerUnit generates a systemd unit for the specified container. Based
+// on the options, the return value might be the entire unit or a file it has
+// been written to.
+func ContainerUnit(ctr *libpod.Container, options entities.GenerateSystemdOptions) (string, error) {
+ info, err := generateContainerInfo(ctr, options)
+ if err != nil {
+ return "", err
+ }
+ return executeContainerTemplate(info, options)
+}
+
+func generateContainerInfo(ctr *libpod.Container, options entities.GenerateSystemdOptions) (*containerInfo, error) {
+ timeout := ctr.StopTimeout()
+ if options.StopTimeout != nil {
+ timeout = *options.StopTimeout
+ }
+
+ config := ctr.Config()
+ conmonPidFile := config.ConmonPidFile
+ if conmonPidFile == "" {
+ return nil, errors.Errorf("conmon PID file path is empty, try to recreate the container with --conmon-pidfile flag")
+ }
+
+ createCommand := []string{}
+ if config.CreateCommand != nil {
+ createCommand = config.CreateCommand
+ } else if options.New {
+ return nil, errors.Errorf("cannot use --new on container %q: no create command found", ctr.ID())
+ }
+
+ nameOrID, serviceName := containerServiceName(ctr, options)
+
+ info := containerInfo{
+ ServiceName: serviceName,
+ ContainerNameOrID: nameOrID,
+ RestartPolicy: options.RestartPolicy,
+ PIDFile: conmonPidFile,
+ StopTimeout: timeout,
+ GenerateTimestamp: true,
+ CreateCommand: createCommand,
+ }
+
+ return &info, nil
+}
+
+// containerServiceName returns the nameOrID and the service name of the
+// container.
+func containerServiceName(ctr *libpod.Container, options entities.GenerateSystemdOptions) (string, string) {
+ nameOrID := ctr.ID()
+ if options.Name {
+ nameOrID = ctr.Name()
+ }
+ serviceName := fmt.Sprintf("%s%s%s", options.ContainerPrefix, options.Separator, nameOrID)
+ return nameOrID, serviceName
+}
+
+// executeContainerTemplate executes the container template on the specified
+// containerInfo. Note that the containerInfo is also post processed and
+// completed, which allows for an easier unit testing.
+func executeContainerTemplate(info *containerInfo, options entities.GenerateSystemdOptions) (string, error) {
+ if err := validateRestartPolicy(info.RestartPolicy); err != nil {
+ return "", err
+ }
+
+ // Make sure the executable is set.
+ if info.Executable == "" {
+ executable, err := os.Executable()
+ if err != nil {
+ executable = "/usr/bin/podman"
+ logrus.Warnf("Could not obtain podman executable location, using default %s", executable)
+ }
+ info.Executable = executable
+ }
+
+ info.EnvVariable = EnvVariable
+ info.ExecStart = "{{.Executable}} start {{.ContainerNameOrID}}"
+ info.ExecStop = "{{.Executable}} stop {{if (ge .StopTimeout 0)}}-t {{.StopTimeout}}{{end}} {{.ContainerNameOrID}}"
+
+ // Assemble the ExecStart command when creating a new container.
+ //
+ // Note that we cannot catch all corner cases here such that users
+ // *must* manually check the generated files. A container might have
+ // been created via a Python script, which would certainly yield an
+ // invalid `info.CreateCommand`. Hence, we're doing a best effort unit
+ // generation and don't try aiming at completeness.
+ if options.New {
+ info.PIDFile = "%t/" + info.ServiceName + ".pid"
+ info.ContainerIDFile = "%t/" + info.ServiceName + ".ctr-id"
+ // The create command must at least have three arguments:
+ // /usr/bin/podman run $IMAGE
+ index := 2
+ if info.CreateCommand[1] == "container" {
+ index = 3
+ }
+ if len(info.CreateCommand) < index+1 {
+ return "", errors.Errorf("container's create command is too short or invalid: %v", info.CreateCommand)
+ }
+ // We're hard-coding the first five arguments and append the
+ // CreateCommand with a stripped command and subcomand.
+ startCommand := []string{
+ info.Executable,
+ "run",
+ "--conmon-pidfile", "{{.PIDFile}}",
+ "--cidfile", "{{.ContainerIDFile}}",
+ "--cgroups=no-conmon",
+ }
+ // If the container is in a pod, make sure that the
+ // --pod-id-file is set correctly.
+ if info.pod != nil {
+ podFlags := []string{"--pod-id-file", info.pod.PodIDFile}
+ startCommand = append(startCommand, podFlags...)
+ info.CreateCommand = filterPodFlags(info.CreateCommand)
+ }
+
+ // Presence check for certain flags/options.
+ hasDetachParam := false
+ hasNameParam := false
+ hasReplaceParam := false
+ for _, p := range info.CreateCommand[index:] {
+ switch p {
+ case "--detach", "-d":
+ hasDetachParam = true
+ case "--name":
+ hasNameParam = true
+ case "--replace":
+ hasReplaceParam = true
+ }
+ }
+
+ if !hasDetachParam {
+ // Enforce detaching
+ //
+ // since we use systemd `Type=forking` service @see
+ // https://www.freedesktop.org/software/systemd/man/systemd.service.html#Type=
+ // when we generated systemd service file with the
+ // --new param, `ExecStart` will have `/usr/bin/podman
+ // run ...` if `info.CreateCommand` has no `-d` or
+ // `--detach` param, podman will run the container in
+ // default attached mode, as a result, `systemd start`
+ // will wait the `podman run` command exit until failed
+ // with timeout error.
+ startCommand = append(startCommand, "-d")
+ }
+ if hasNameParam && !hasReplaceParam {
+ // Enforce --replace for named containers. This will
+ // make systemd units more robuts as it allows them to
+ // start after system crashes (see
+ // github.com/containers/libpod/issues/5485).
+ startCommand = append(startCommand, "--replace")
+ }
+ startCommand = append(startCommand, info.CreateCommand[index:]...)
+
+ info.ExecStartPre = "/usr/bin/rm -f {{.PIDFile}} {{.ContainerIDFile}}"
+ info.ExecStart = strings.Join(startCommand, " ")
+ info.ExecStop = "{{.Executable}} stop --ignore --cidfile {{.ContainerIDFile}} {{if (ge .StopTimeout 0)}}-t {{.StopTimeout}}{{end}}"
+ info.ExecStopPost = "{{.Executable}} rm --ignore -f --cidfile {{.ContainerIDFile}}"
+ }
+
+ if info.PodmanVersion == "" {
+ info.PodmanVersion = version.Version
+ }
+ if info.GenerateTimestamp {
+ info.TimeStamp = fmt.Sprintf("%v", time.Now().Format(time.UnixDate))
+ }
+
+ // Sort the slices to assure a deterministic output.
+ sort.Strings(info.BoundToServices)
+
+ // Generate the template and compile it.
+ //
+ // Note that we need a two-step generation process to allow for fields
+ // embedding other fields. This way we can replace `A -> B -> C` and
+ // make the code easier to maintain at the cost of a slightly slower
+ // generation. That's especially needed for embedding the PID and ID
+ // files in other fields which will eventually get replaced in the 2nd
+ // template execution.
+ templ, err := template.New("container_template").Parse(containerTemplate)
+ if err != nil {
+ return "", errors.Wrap(err, "error parsing systemd service template")
+ }
+
+ var buf bytes.Buffer
+ if err := templ.Execute(&buf, info); err != nil {
+ return "", err
+ }
+
+ // Now parse the generated template (i.e., buf) and execute it.
+ templ, err = template.New("container_template").Parse(buf.String())
+ if err != nil {
+ return "", errors.Wrap(err, "error parsing systemd service template")
+ }
+
+ buf = bytes.Buffer{}
+ if err := templ.Execute(&buf, info); err != nil {
+ return "", err
+ }
+
+ if !options.Files {
+ return buf.String(), nil
+ }
+
+ buf.WriteByte('\n')
+ cwd, err := os.Getwd()
+ if err != nil {
+ return "", errors.Wrap(err, "error getting current working directory")
+ }
+ path := filepath.Join(cwd, fmt.Sprintf("%s.service", info.ServiceName))
+ if err := ioutil.WriteFile(path, buf.Bytes(), 0644); err != nil {
+ return "", errors.Wrap(err, "error generating systemd unit")
+ }
+ return path, nil
+}
diff --git a/pkg/systemd/generate/containers_test.go b/pkg/systemd/generate/containers_test.go
new file mode 100644
index 000000000..8d3ea1ca0
--- /dev/null
+++ b/pkg/systemd/generate/containers_test.go
@@ -0,0 +1,390 @@
+package generate
+
+import (
+ "testing"
+
+ "github.com/containers/libpod/pkg/domain/entities"
+)
+
+func TestValidateRestartPolicyContainer(t *testing.T) {
+ type containerInfo struct {
+ restart string
+ }
+ tests := []struct {
+ name string
+ containerInfo containerInfo
+ wantErr bool
+ }{
+ {"good-on", containerInfo{restart: "no"}, false},
+ {"good-on-success", containerInfo{restart: "on-success"}, false},
+ {"good-on-failure", containerInfo{restart: "on-failure"}, false},
+ {"good-on-abnormal", containerInfo{restart: "on-abnormal"}, false},
+ {"good-on-watchdog", containerInfo{restart: "on-watchdog"}, false},
+ {"good-on-abort", containerInfo{restart: "on-abort"}, false},
+ {"good-always", containerInfo{restart: "always"}, false},
+ {"fail", containerInfo{restart: "foobar"}, true},
+ {"failblank", containerInfo{restart: ""}, true},
+ }
+ for _, tt := range tests {
+ test := tt
+ t.Run(tt.name, func(t *testing.T) {
+ if err := validateRestartPolicy(test.containerInfo.restart); (err != nil) != test.wantErr {
+ t.Errorf("ValidateRestartPolicy() error = %v, wantErr %v", err, test.wantErr)
+ }
+ })
+ }
+}
+
+func TestCreateContainerSystemdUnit(t *testing.T) {
+ goodID := `# container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401.service
+# autogenerated by Podman CI
+
+[Unit]
+Description=Podman container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401.service
+Documentation=man:podman-generate-systemd(1)
+Wants=network.target
+After=network-online.target
+
+[Service]
+Environment=PODMAN_SYSTEMD_UNIT=%n
+Restart=always
+ExecStart=/usr/bin/podman start 639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401
+ExecStop=/usr/bin/podman stop -t 10 639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401
+PIDFile=/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
+KillMode=none
+Type=forking
+
+[Install]
+WantedBy=multi-user.target default.target`
+
+ goodName := `# container-foobar.service
+# autogenerated by Podman CI
+
+[Unit]
+Description=Podman container-foobar.service
+Documentation=man:podman-generate-systemd(1)
+Wants=network.target
+After=network-online.target
+
+[Service]
+Environment=PODMAN_SYSTEMD_UNIT=%n
+Restart=always
+ExecStart=/usr/bin/podman start foobar
+ExecStop=/usr/bin/podman stop -t 10 foobar
+PIDFile=/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
+KillMode=none
+Type=forking
+
+[Install]
+WantedBy=multi-user.target default.target`
+
+ goodNameBoundTo := `# container-foobar.service
+# autogenerated by Podman CI
+
+[Unit]
+Description=Podman container-foobar.service
+Documentation=man:podman-generate-systemd(1)
+Wants=network.target
+After=network-online.target
+RefuseManualStart=yes
+RefuseManualStop=yes
+BindsTo=a.service b.service c.service pod.service
+After=a.service b.service c.service pod.service
+
+[Service]
+Environment=PODMAN_SYSTEMD_UNIT=%n
+Restart=always
+ExecStart=/usr/bin/podman start foobar
+ExecStop=/usr/bin/podman stop -t 10 foobar
+PIDFile=/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
+KillMode=none
+Type=forking
+
+[Install]
+WantedBy=multi-user.target default.target`
+
+ goodWithNameAndGeneric := `# jadda-jadda.service
+# autogenerated by Podman CI
+
+[Unit]
+Description=Podman jadda-jadda.service
+Documentation=man:podman-generate-systemd(1)
+Wants=network.target
+After=network-online.target
+
+[Service]
+Environment=PODMAN_SYSTEMD_UNIT=%n
+Restart=always
+ExecStartPre=/usr/bin/rm -f %t/jadda-jadda.pid %t/jadda-jadda.ctr-id
+ExecStart=/usr/bin/podman run --conmon-pidfile %t/jadda-jadda.pid --cidfile %t/jadda-jadda.ctr-id --cgroups=no-conmon -d --replace --name jadda-jadda --hostname hello-world awesome-image:latest command arg1 ... argN
+ExecStop=/usr/bin/podman stop --ignore --cidfile %t/jadda-jadda.ctr-id -t 42
+ExecStopPost=/usr/bin/podman rm --ignore -f --cidfile %t/jadda-jadda.ctr-id
+PIDFile=%t/jadda-jadda.pid
+KillMode=none
+Type=forking
+
+[Install]
+WantedBy=multi-user.target default.target`
+
+ goodWithExplicitShortDetachParam := `# jadda-jadda.service
+# autogenerated by Podman CI
+
+[Unit]
+Description=Podman jadda-jadda.service
+Documentation=man:podman-generate-systemd(1)
+Wants=network.target
+After=network-online.target
+
+[Service]
+Environment=PODMAN_SYSTEMD_UNIT=%n
+Restart=always
+ExecStartPre=/usr/bin/rm -f %t/jadda-jadda.pid %t/jadda-jadda.ctr-id
+ExecStart=/usr/bin/podman run --conmon-pidfile %t/jadda-jadda.pid --cidfile %t/jadda-jadda.ctr-id --cgroups=no-conmon --replace -d --name jadda-jadda --hostname hello-world awesome-image:latest command arg1 ... argN
+ExecStop=/usr/bin/podman stop --ignore --cidfile %t/jadda-jadda.ctr-id -t 42
+ExecStopPost=/usr/bin/podman rm --ignore -f --cidfile %t/jadda-jadda.ctr-id
+PIDFile=%t/jadda-jadda.pid
+KillMode=none
+Type=forking
+
+[Install]
+WantedBy=multi-user.target default.target`
+
+ goodNameNewWithPodFile := `# jadda-jadda.service
+# autogenerated by Podman CI
+
+[Unit]
+Description=Podman jadda-jadda.service
+Documentation=man:podman-generate-systemd(1)
+Wants=network.target
+After=network-online.target
+
+[Service]
+Environment=PODMAN_SYSTEMD_UNIT=%n
+Restart=always
+ExecStartPre=/usr/bin/rm -f %t/jadda-jadda.pid %t/jadda-jadda.ctr-id
+ExecStart=/usr/bin/podman run --conmon-pidfile %t/jadda-jadda.pid --cidfile %t/jadda-jadda.ctr-id --cgroups=no-conmon --pod-id-file /tmp/pod-foobar.pod-id-file --replace -d --name jadda-jadda --hostname hello-world awesome-image:latest command arg1 ... argN
+ExecStop=/usr/bin/podman stop --ignore --cidfile %t/jadda-jadda.ctr-id -t 42
+ExecStopPost=/usr/bin/podman rm --ignore -f --cidfile %t/jadda-jadda.ctr-id
+PIDFile=%t/jadda-jadda.pid
+KillMode=none
+Type=forking
+
+[Install]
+WantedBy=multi-user.target default.target`
+
+ goodNameNewDetach := `# jadda-jadda.service
+# autogenerated by Podman CI
+
+[Unit]
+Description=Podman jadda-jadda.service
+Documentation=man:podman-generate-systemd(1)
+Wants=network.target
+After=network-online.target
+
+[Service]
+Environment=PODMAN_SYSTEMD_UNIT=%n
+Restart=always
+ExecStartPre=/usr/bin/rm -f %t/jadda-jadda.pid %t/jadda-jadda.ctr-id
+ExecStart=/usr/bin/podman run --conmon-pidfile %t/jadda-jadda.pid --cidfile %t/jadda-jadda.ctr-id --cgroups=no-conmon --replace --detach --name jadda-jadda --hostname hello-world awesome-image:latest command arg1 ... argN
+ExecStop=/usr/bin/podman stop --ignore --cidfile %t/jadda-jadda.ctr-id -t 42
+ExecStopPost=/usr/bin/podman rm --ignore -f --cidfile %t/jadda-jadda.ctr-id
+PIDFile=%t/jadda-jadda.pid
+KillMode=none
+Type=forking
+
+[Install]
+WantedBy=multi-user.target default.target`
+
+ goodIDNew := `# container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401.service
+# autogenerated by Podman CI
+
+[Unit]
+Description=Podman container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401.service
+Documentation=man:podman-generate-systemd(1)
+Wants=network.target
+After=network-online.target
+
+[Service]
+Environment=PODMAN_SYSTEMD_UNIT=%n
+Restart=always
+ExecStartPre=/usr/bin/rm -f %t/container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401.pid %t/container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401.ctr-id
+ExecStart=/usr/bin/podman run --conmon-pidfile %t/container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401.pid --cidfile %t/container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401.ctr-id --cgroups=no-conmon -d awesome-image:latest
+ExecStop=/usr/bin/podman stop --ignore --cidfile %t/container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401.ctr-id -t 10
+ExecStopPost=/usr/bin/podman rm --ignore -f --cidfile %t/container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401.ctr-id
+PIDFile=%t/container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401.pid
+KillMode=none
+Type=forking
+
+[Install]
+WantedBy=multi-user.target default.target`
+
+ tests := []struct {
+ name string
+ info containerInfo
+ want string
+ new bool
+ wantErr bool
+ }{
+
+ {"good with id",
+ containerInfo{
+ Executable: "/usr/bin/podman",
+ ServiceName: "container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401",
+ ContainerNameOrID: "639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401",
+ RestartPolicy: "always",
+ PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ StopTimeout: 10,
+ PodmanVersion: "CI",
+ EnvVariable: EnvVariable,
+ },
+ goodID,
+ false,
+ false,
+ },
+ {"good with name",
+ containerInfo{
+ Executable: "/usr/bin/podman",
+ ServiceName: "container-foobar",
+ ContainerNameOrID: "foobar",
+ RestartPolicy: "always",
+ PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ StopTimeout: 10,
+ PodmanVersion: "CI",
+ EnvVariable: EnvVariable,
+ },
+ goodName,
+ false,
+ false,
+ },
+ {"good with name and bound to",
+ containerInfo{
+ Executable: "/usr/bin/podman",
+ ServiceName: "container-foobar",
+ ContainerNameOrID: "foobar",
+ RestartPolicy: "always",
+ PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ StopTimeout: 10,
+ PodmanVersion: "CI",
+ BoundToServices: []string{"pod", "a", "b", "c"},
+ EnvVariable: EnvVariable,
+ },
+ goodNameBoundTo,
+ false,
+ false,
+ },
+ {"bad restart policy",
+ containerInfo{
+ Executable: "/usr/bin/podman",
+ ServiceName: "639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401",
+ RestartPolicy: "never",
+ PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ StopTimeout: 10,
+ PodmanVersion: "CI",
+ EnvVariable: EnvVariable,
+ },
+ "",
+ false,
+ true,
+ },
+ {"good with name and generic",
+ containerInfo{
+ Executable: "/usr/bin/podman",
+ ServiceName: "jadda-jadda",
+ ContainerNameOrID: "jadda-jadda",
+ RestartPolicy: "always",
+ PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ StopTimeout: 42,
+ PodmanVersion: "CI",
+ CreateCommand: []string{"I'll get stripped", "container", "run", "--name", "jadda-jadda", "--hostname", "hello-world", "awesome-image:latest", "command", "arg1", "...", "argN"},
+ EnvVariable: EnvVariable,
+ },
+ goodWithNameAndGeneric,
+ true,
+ false,
+ },
+ {"good with explicit short detach param",
+ containerInfo{
+ Executable: "/usr/bin/podman",
+ ServiceName: "jadda-jadda",
+ ContainerNameOrID: "jadda-jadda",
+ RestartPolicy: "always",
+ PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ StopTimeout: 42,
+ PodmanVersion: "CI",
+ CreateCommand: []string{"I'll get stripped", "container", "run", "-d", "--name", "jadda-jadda", "--hostname", "hello-world", "awesome-image:latest", "command", "arg1", "...", "argN"},
+ EnvVariable: EnvVariable,
+ },
+ goodWithExplicitShortDetachParam,
+ true,
+ false,
+ },
+ {"good with explicit short detach param and podInfo",
+ containerInfo{
+ Executable: "/usr/bin/podman",
+ ServiceName: "jadda-jadda",
+ ContainerNameOrID: "jadda-jadda",
+ RestartPolicy: "always",
+ PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ StopTimeout: 42,
+ PodmanVersion: "CI",
+ CreateCommand: []string{"I'll get stripped", "container", "run", "-d", "--name", "jadda-jadda", "--hostname", "hello-world", "awesome-image:latest", "command", "arg1", "...", "argN"},
+ EnvVariable: EnvVariable,
+ pod: &podInfo{
+ PodIDFile: "/tmp/pod-foobar.pod-id-file",
+ },
+ },
+ goodNameNewWithPodFile,
+ true,
+ false,
+ },
+ {"good with explicit full detach param",
+ containerInfo{
+ Executable: "/usr/bin/podman",
+ ServiceName: "jadda-jadda",
+ ContainerNameOrID: "jadda-jadda",
+ RestartPolicy: "always",
+ PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ StopTimeout: 42,
+ PodmanVersion: "CI",
+ CreateCommand: []string{"I'll get stripped", "container", "run", "--detach", "--name", "jadda-jadda", "--hostname", "hello-world", "awesome-image:latest", "command", "arg1", "...", "argN"},
+ EnvVariable: EnvVariable,
+ },
+ goodNameNewDetach,
+ true,
+ false,
+ },
+ {"good with id and no param",
+ containerInfo{
+ Executable: "/usr/bin/podman",
+ ServiceName: "container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401",
+ ContainerNameOrID: "639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401",
+ RestartPolicy: "always",
+ PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ StopTimeout: 10,
+ PodmanVersion: "CI",
+ CreateCommand: []string{"I'll get stripped", "container", "run", "awesome-image:latest"},
+ EnvVariable: EnvVariable,
+ },
+ goodIDNew,
+ true,
+ false,
+ },
+ }
+ for _, tt := range tests {
+ test := tt
+ t.Run(tt.name, func(t *testing.T) {
+ opts := entities.GenerateSystemdOptions{
+ Files: false,
+ New: test.new,
+ }
+ got, err := executeContainerTemplate(&test.info, opts)
+ if (err != nil) != test.wantErr {
+ t.Errorf("CreateContainerSystemdUnit() error = \n%v, wantErr \n%v", err, test.wantErr)
+ return
+ }
+ if got != test.want {
+ t.Errorf("CreateContainerSystemdUnit() = \n%v\n---------> want\n%v", got, test.want)
+ }
+ })
+ }
+}
diff --git a/pkg/systemd/generate/pods.go b/pkg/systemd/generate/pods.go
new file mode 100644
index 000000000..367b8381f
--- /dev/null
+++ b/pkg/systemd/generate/pods.go
@@ -0,0 +1,356 @@
+package generate
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "sort"
+ "strings"
+ "text/template"
+ "time"
+
+ "github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/containers/libpod/version"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+)
+
+// podInfo contains data required for generating a pod's systemd
+// unit file.
+type podInfo struct {
+ // ServiceName of the systemd service.
+ ServiceName string
+ // Name or ID of the infra container.
+ InfraNameOrID string
+ // StopTimeout sets the timeout Podman waits before killing the container
+ // during service stop.
+ StopTimeout uint
+ // RestartPolicy of the systemd unit (e.g., no, on-failure, always).
+ RestartPolicy string
+ // PIDFile of the service. Required for forking services. Must point to the
+ // PID of the associated conmon process.
+ PIDFile string
+ // PodIDFile of the unit.
+ PodIDFile string
+ // GenerateTimestamp, if set the generated unit file has a time stamp.
+ GenerateTimestamp bool
+ // RequiredServices are services this service requires. Note that this
+ // service runs before them.
+ RequiredServices []string
+ // PodmanVersion for the header. Will be set internally. Will be auto-filled
+ // if left empty.
+ PodmanVersion string
+ // Executable is the path to the podman executable. Will be auto-filled if
+ // left empty.
+ Executable string
+ // TimeStamp at the time of creating the unit file. Will be set internally.
+ TimeStamp string
+ // CreateCommand is the full command plus arguments of the process the
+ // container has been created with.
+ CreateCommand []string
+ // PodCreateCommand - a post-processed variant of CreateCommand to use
+ // when creating the pod.
+ PodCreateCommand string
+ // EnvVariable is generate.EnvVariable and must not be set.
+ EnvVariable string
+ // ExecStartPre1 of the unit.
+ ExecStartPre1 string
+ // ExecStartPre2 of the unit.
+ ExecStartPre2 string
+ // ExecStart of the unit.
+ ExecStart string
+ // ExecStop of the unit.
+ ExecStop string
+ // ExecStopPost of the unit.
+ ExecStopPost string
+}
+
+const podTemplate = headerTemplate + `Requires={{- range $index, $value := .RequiredServices -}}{{if $index}} {{end}}{{ $value }}.service{{end}}
+Before={{- range $index, $value := .RequiredServices -}}{{if $index}} {{end}}{{ $value }}.service{{end}}
+
+[Service]
+Environment={{.EnvVariable}}=%n
+Restart={{.RestartPolicy}}
+{{- if .ExecStartPre1}}
+ExecStartPre={{.ExecStartPre1}}
+{{- end}}
+{{- if .ExecStartPre2}}
+ExecStartPre={{.ExecStartPre2}}
+{{- end}}
+ExecStart={{.ExecStart}}
+ExecStop={{.ExecStop}}
+{{- if .ExecStopPost}}
+ExecStopPost={{.ExecStopPost}}
+{{- end}}
+PIDFile={{.PIDFile}}
+KillMode=none
+Type=forking
+
+[Install]
+WantedBy=multi-user.target default.target`
+
+// PodUnits generates systemd units for the specified pod and its containers.
+// Based on the options, the return value might be the content of all units or
+// the files they been written to.
+func PodUnits(pod *libpod.Pod, options entities.GenerateSystemdOptions) (string, error) {
+ // Error out if the pod has no infra container, which we require to be the
+ // main service.
+ if !pod.HasInfraContainer() {
+ return "", errors.Errorf("error generating systemd unit files: Pod %q has no infra container", pod.Name())
+ }
+
+ podInfo, err := generatePodInfo(pod, options)
+ if err != nil {
+ return "", err
+ }
+
+ infraID, err := pod.InfraContainerID()
+ if err != nil {
+ return "", err
+ }
+
+ // Compute the container-dependency graph for the Pod.
+ containers, err := pod.AllContainers()
+ if err != nil {
+ return "", err
+ }
+ if len(containers) == 0 {
+ return "", errors.Errorf("error generating systemd unit files: Pod %q has no containers", pod.Name())
+ }
+ graph, err := libpod.BuildContainerGraph(containers)
+ if err != nil {
+ return "", err
+ }
+
+ // Traverse the dependency graph and create systemdgen.containerInfo's for
+ // each container.
+ containerInfos := []*containerInfo{}
+ for ctr, dependencies := range graph.DependencyMap() {
+ // Skip the infra container as we already generated it.
+ if ctr.ID() == infraID {
+ continue
+ }
+ ctrInfo, err := generateContainerInfo(ctr, options)
+ if err != nil {
+ return "", err
+ }
+ // Now add the container's dependencies and at the container as a
+ // required service of the infra container.
+ for _, dep := range dependencies {
+ if dep.ID() == infraID {
+ ctrInfo.BoundToServices = append(ctrInfo.BoundToServices, podInfo.ServiceName)
+ } else {
+ _, serviceName := containerServiceName(dep, options)
+ ctrInfo.BoundToServices = append(ctrInfo.BoundToServices, serviceName)
+ }
+ }
+ podInfo.RequiredServices = append(podInfo.RequiredServices, ctrInfo.ServiceName)
+ containerInfos = append(containerInfos, ctrInfo)
+ }
+
+ // Now generate the systemd service for all containers.
+ builder := strings.Builder{}
+ out, err := executePodTemplate(podInfo, options)
+ if err != nil {
+ return "", err
+ }
+ builder.WriteString(out)
+ for _, info := range containerInfos {
+ info.pod = podInfo
+ builder.WriteByte('\n')
+ out, err := executeContainerTemplate(info, options)
+ if err != nil {
+ return "", err
+ }
+ builder.WriteString(out)
+ }
+
+ return builder.String(), nil
+}
+
+func generatePodInfo(pod *libpod.Pod, options entities.GenerateSystemdOptions) (*podInfo, error) {
+ // Generate a systemdgen.containerInfo for the infra container. This
+ // containerInfo acts as the main service of the pod.
+ infraCtr, err := pod.InfraContainer()
+ if err != nil {
+ return nil, errors.Wrap(err, "could not find infra container")
+ }
+
+ timeout := infraCtr.StopTimeout()
+ if options.StopTimeout != nil {
+ timeout = *options.StopTimeout
+ }
+
+ config := infraCtr.Config()
+ conmonPidFile := config.ConmonPidFile
+ if conmonPidFile == "" {
+ return nil, errors.Errorf("conmon PID file path is empty, try to recreate the container with --conmon-pidfile flag")
+ }
+
+ createCommand := pod.CreateCommand()
+ if options.New && len(createCommand) == 0 {
+ return nil, errors.Errorf("cannot use --new on pod %q: no create command found", pod.ID())
+ }
+
+ nameOrID := pod.ID()
+ ctrNameOrID := infraCtr.ID()
+ if options.Name {
+ nameOrID = pod.Name()
+ ctrNameOrID = infraCtr.Name()
+ }
+ serviceName := fmt.Sprintf("%s%s%s", options.PodPrefix, options.Separator, nameOrID)
+
+ info := podInfo{
+ ServiceName: serviceName,
+ InfraNameOrID: ctrNameOrID,
+ RestartPolicy: options.RestartPolicy,
+ PIDFile: conmonPidFile,
+ StopTimeout: timeout,
+ GenerateTimestamp: true,
+ CreateCommand: createCommand,
+ }
+ return &info, nil
+}
+
+// executePodTemplate executes the pod template on the specified podInfo. Note
+// that the podInfo is also post processed and completed, which allows for an
+// easier unit testing.
+func executePodTemplate(info *podInfo, options entities.GenerateSystemdOptions) (string, error) {
+ if err := validateRestartPolicy(info.RestartPolicy); err != nil {
+ return "", err
+ }
+
+ // Make sure the executable is set.
+ if info.Executable == "" {
+ executable, err := os.Executable()
+ if err != nil {
+ executable = "/usr/bin/podman"
+ logrus.Warnf("Could not obtain podman executable location, using default %s", executable)
+ }
+ info.Executable = executable
+ }
+
+ info.EnvVariable = EnvVariable
+ info.ExecStart = "{{.Executable}} start {{.InfraNameOrID}}"
+ info.ExecStop = "{{.Executable}} stop {{if (ge .StopTimeout 0)}}-t {{.StopTimeout}}{{end}} {{.InfraNameOrID}}"
+
+ // Assemble the ExecStart command when creating a new pod.
+ //
+ // Note that we cannot catch all corner cases here such that users
+ // *must* manually check the generated files. A pod might have been
+ // created via a Python script, which would certainly yield an invalid
+ // `info.CreateCommand`. Hence, we're doing a best effort unit
+ // generation and don't try aiming at completeness.
+ if options.New {
+ info.PIDFile = "%t/" + info.ServiceName + ".pid"
+ info.PodIDFile = "%t/" + info.ServiceName + ".pod-id"
+
+ podCreateIndex := 0
+ var podRootArgs, podCreateArgs []string
+ switch len(info.CreateCommand) {
+ case 0, 1, 2:
+ return "", errors.Errorf("pod does not appear to be created via `podman pod create`: %v", info.CreateCommand)
+ default:
+ // Make sure that pod was created with `pod create` and
+ // not something else, such as `run --pod new`.
+ for i := 1; i < len(info.CreateCommand); i++ {
+ if info.CreateCommand[i-1] == "pod" && info.CreateCommand[i] == "create" {
+ podCreateIndex = i
+ break
+ }
+ }
+ if podCreateIndex == 0 {
+ return "", errors.Errorf("pod does not appear to be created via `podman pod create`: %v", info.CreateCommand)
+ }
+ podRootArgs = info.CreateCommand[0 : podCreateIndex-2]
+ podCreateArgs = filterPodFlags(info.CreateCommand[podCreateIndex+1:])
+ }
+ // We're hard-coding the first five arguments and append the
+ // CreateCommand with a stripped command and subcomand.
+ startCommand := []string{info.Executable}
+ startCommand = append(startCommand, podRootArgs...)
+ startCommand = append(startCommand,
+ []string{"pod", "create",
+ "--infra-conmon-pidfile", "{{.PIDFile}}",
+ "--pod-id-file", "{{.PodIDFile}}"}...)
+
+ // Presence check for certain flags/options.
+ hasNameParam := false
+ hasReplaceParam := false
+ for _, p := range podCreateArgs {
+ switch p {
+ case "--name":
+ hasNameParam = true
+ case "--replace":
+ hasReplaceParam = true
+ }
+ }
+ if hasNameParam && !hasReplaceParam {
+ podCreateArgs = append(podCreateArgs, "--replace")
+ }
+
+ startCommand = append(startCommand, podCreateArgs...)
+
+ info.ExecStartPre1 = "/usr/bin/rm -f {{.PIDFile}} {{.PodIDFile}}"
+ info.ExecStartPre2 = strings.Join(startCommand, " ")
+ info.ExecStart = "{{.Executable}} pod start --pod-id-file {{.PodIDFile}}"
+ info.ExecStop = "{{.Executable}} pod stop --ignore --pod-id-file {{.PodIDFile}} {{if (ge .StopTimeout 0)}}-t {{.StopTimeout}}{{end}}"
+ info.ExecStopPost = "{{.Executable}} pod rm --ignore -f --pod-id-file {{.PodIDFile}}"
+ }
+ if info.PodmanVersion == "" {
+ info.PodmanVersion = version.Version
+ }
+ if info.GenerateTimestamp {
+ info.TimeStamp = fmt.Sprintf("%v", time.Now().Format(time.UnixDate))
+ }
+
+ // Sort the slices to assure a deterministic output.
+ sort.Strings(info.RequiredServices)
+
+ // Generate the template and compile it.
+ //
+ // Note that we need a two-step generation process to allow for fields
+ // embedding other fields. This way we can replace `A -> B -> C` and
+ // make the code easier to maintain at the cost of a slightly slower
+ // generation. That's especially needed for embedding the PID and ID
+ // files in other fields which will eventually get replaced in the 2nd
+ // template execution.
+ templ, err := template.New("pod_template").Parse(podTemplate)
+ if err != nil {
+ return "", errors.Wrap(err, "error parsing systemd service template")
+ }
+
+ var buf bytes.Buffer
+ if err := templ.Execute(&buf, info); err != nil {
+ return "", err
+ }
+
+ // Now parse the generated template (i.e., buf) and execute it.
+ templ, err = template.New("pod_template").Parse(buf.String())
+ if err != nil {
+ return "", errors.Wrap(err, "error parsing systemd service template")
+ }
+
+ buf = bytes.Buffer{}
+ if err := templ.Execute(&buf, info); err != nil {
+ return "", err
+ }
+
+ if !options.Files {
+ return buf.String(), nil
+ }
+
+ buf.WriteByte('\n')
+ cwd, err := os.Getwd()
+ if err != nil {
+ return "", errors.Wrap(err, "error getting current working directory")
+ }
+ path := filepath.Join(cwd, fmt.Sprintf("%s.service", info.ServiceName))
+ if err := ioutil.WriteFile(path, buf.Bytes(), 0644); err != nil {
+ return "", errors.Wrap(err, "error generating systemd unit")
+ }
+ return path, nil
+}
diff --git a/pkg/systemd/generate/pods_test.go b/pkg/systemd/generate/pods_test.go
new file mode 100644
index 000000000..f7ce33a30
--- /dev/null
+++ b/pkg/systemd/generate/pods_test.go
@@ -0,0 +1,145 @@
+package generate
+
+import (
+ "testing"
+
+ "github.com/containers/libpod/pkg/domain/entities"
+)
+
+func TestValidateRestartPolicyPod(t *testing.T) {
+ type podInfo struct {
+ restart string
+ }
+ tests := []struct {
+ name string
+ podInfo podInfo
+ wantErr bool
+ }{
+ {"good-on", podInfo{restart: "no"}, false},
+ {"good-on-success", podInfo{restart: "on-success"}, false},
+ {"good-on-failure", podInfo{restart: "on-failure"}, false},
+ {"good-on-abnormal", podInfo{restart: "on-abnormal"}, false},
+ {"good-on-watchdog", podInfo{restart: "on-watchdog"}, false},
+ {"good-on-abort", podInfo{restart: "on-abort"}, false},
+ {"good-always", podInfo{restart: "always"}, false},
+ {"fail", podInfo{restart: "foobar"}, true},
+ {"failblank", podInfo{restart: ""}, true},
+ }
+ for _, tt := range tests {
+ test := tt
+ t.Run(tt.name, func(t *testing.T) {
+ if err := validateRestartPolicy(test.podInfo.restart); (err != nil) != test.wantErr {
+ t.Errorf("ValidateRestartPolicy() error = %v, wantErr %v", err, test.wantErr)
+ }
+ })
+ }
+}
+
+func TestCreatePodSystemdUnit(t *testing.T) {
+ podGood := `# pod-123abc.service
+# autogenerated by Podman CI
+
+[Unit]
+Description=Podman pod-123abc.service
+Documentation=man:podman-generate-systemd(1)
+Wants=network.target
+After=network-online.target
+Requires=container-1.service container-2.service
+Before=container-1.service container-2.service
+
+[Service]
+Environment=PODMAN_SYSTEMD_UNIT=%n
+Restart=always
+ExecStart=/usr/bin/podman start jadda-jadda-infra
+ExecStop=/usr/bin/podman stop -t 10 jadda-jadda-infra
+PIDFile=/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
+KillMode=none
+Type=forking
+
+[Install]
+WantedBy=multi-user.target default.target`
+
+ podGoodNamedNew := `# pod-123abc.service
+# autogenerated by Podman CI
+
+[Unit]
+Description=Podman pod-123abc.service
+Documentation=man:podman-generate-systemd(1)
+Wants=network.target
+After=network-online.target
+Requires=container-1.service container-2.service
+Before=container-1.service container-2.service
+
+[Service]
+Environment=PODMAN_SYSTEMD_UNIT=%n
+Restart=on-failure
+ExecStartPre=/usr/bin/rm -f %t/pod-123abc.pid %t/pod-123abc.pod-id
+ExecStartPre=/usr/bin/podman pod create --infra-conmon-pidfile %t/pod-123abc.pid --pod-id-file %t/pod-123abc.pod-id --name foo --replace
+ExecStart=/usr/bin/podman pod start --pod-id-file %t/pod-123abc.pod-id
+ExecStop=/usr/bin/podman pod stop --ignore --pod-id-file %t/pod-123abc.pod-id -t 10
+ExecStopPost=/usr/bin/podman pod rm --ignore -f --pod-id-file %t/pod-123abc.pod-id
+PIDFile=%t/pod-123abc.pid
+KillMode=none
+Type=forking
+
+[Install]
+WantedBy=multi-user.target default.target`
+
+ tests := []struct {
+ name string
+ info podInfo
+ want string
+ new bool
+ wantErr bool
+ }{
+ {"pod",
+ podInfo{
+ Executable: "/usr/bin/podman",
+ ServiceName: "pod-123abc",
+ InfraNameOrID: "jadda-jadda-infra",
+ RestartPolicy: "always",
+ PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ StopTimeout: 10,
+ PodmanVersion: "CI",
+ RequiredServices: []string{"container-1", "container-2"},
+ },
+ podGood,
+ false,
+ false,
+ },
+ {"pod --new",
+ podInfo{
+ Executable: "/usr/bin/podman",
+ ServiceName: "pod-123abc",
+ InfraNameOrID: "jadda-jadda-infra",
+ RestartPolicy: "on-failure",
+ PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ StopTimeout: 10,
+ PodmanVersion: "CI",
+ RequiredServices: []string{"container-1", "container-2"},
+ CreateCommand: []string{"podman", "pod", "create", "--name", "foo"},
+ },
+ podGoodNamedNew,
+ true,
+ false,
+ },
+ }
+
+ for _, tt := range tests {
+ test := tt
+ t.Run(tt.name, func(t *testing.T) {
+ opts := entities.GenerateSystemdOptions{
+ Files: false,
+ New: test.new,
+ }
+ got, err := executePodTemplate(&test.info, opts)
+ if (err != nil) != test.wantErr {
+ t.Errorf("CreatePodSystemdUnit() error = \n%v, wantErr \n%v", err, test.wantErr)
+ return
+ }
+ if got != test.want {
+ t.Errorf("CreatePodSystemdUnit() = \n%v\n---------> want\n%v", got, test.want)
+ }
+ })
+ }
+}
diff --git a/pkg/systemd/generate/systemdgen.go b/pkg/systemd/generate/systemdgen.go
deleted file mode 100644
index 73fe52c0e..000000000
--- a/pkg/systemd/generate/systemdgen.go
+++ /dev/null
@@ -1,237 +0,0 @@
-package generate
-
-import (
- "bytes"
- "fmt"
- "io/ioutil"
- "os"
- "path/filepath"
- "sort"
- "strings"
- "text/template"
- "time"
-
- "github.com/containers/libpod/version"
- "github.com/pkg/errors"
- "github.com/sirupsen/logrus"
-)
-
-// EnvVariable "PODMAN_SYSTEMD_UNIT" is set in all generated systemd units and
-// is set to the unit's (unique) name.
-const EnvVariable = "PODMAN_SYSTEMD_UNIT"
-
-// ContainerInfo contains data required for generating a container's systemd
-// unit file.
-type ContainerInfo struct {
- // ServiceName of the systemd service.
- ServiceName string
- // Name or ID of the container.
- ContainerName string
- // InfraContainer of the pod.
- InfraContainer string
- // StopTimeout sets the timeout Podman waits before killing the container
- // during service stop.
- StopTimeout uint
- // RestartPolicy of the systemd unit (e.g., no, on-failure, always).
- RestartPolicy string
- // PIDFile of the service. Required for forking services. Must point to the
- // PID of the associated conmon process.
- PIDFile string
- // GenerateTimestamp, if set the generated unit file has a time stamp.
- GenerateTimestamp bool
- // BoundToServices are the services this service binds to. Note that this
- // service runs after them.
- BoundToServices []string
- // RequiredServices are services this service requires. Note that this
- // service runs before them.
- RequiredServices []string
- // PodmanVersion for the header. Will be set internally. Will be auto-filled
- // if left empty.
- PodmanVersion string
- // Executable is the path to the podman executable. Will be auto-filled if
- // left empty.
- Executable string
- // TimeStamp at the time of creating the unit file. Will be set internally.
- TimeStamp string
- // New controls if a new container is created or if an existing one is started.
- New bool
- // CreateCommand is the full command plus arguments of the process the
- // container has been created with.
- CreateCommand []string
- // RunCommand is a post-processed variant of CreateCommand and used for
- // the ExecStart field in generic unit files.
- RunCommand string
- // EnvVariable is generate.EnvVariable and must not be set.
- EnvVariable string
-}
-
-var restartPolicies = []string{"no", "on-success", "on-failure", "on-abnormal", "on-watchdog", "on-abort", "always"}
-
-// validateRestartPolicy checks that the user-provided policy is valid.
-func validateRestartPolicy(restart string) error {
- for _, i := range restartPolicies {
- if i == restart {
- return nil
- }
- }
- return errors.Errorf("%s is not a valid restart policy", restart)
-}
-
-const containerTemplate = `# {{.ServiceName}}.service
-# autogenerated by Podman {{.PodmanVersion}}
-{{- if .TimeStamp}}
-# {{.TimeStamp}}
-{{- end}}
-
-[Unit]
-Description=Podman {{.ServiceName}}.service
-Documentation=man:podman-generate-systemd(1)
-Wants=network.target
-After=network-online.target
-{{- if .BoundToServices}}
-RefuseManualStart=yes
-RefuseManualStop=yes
-BindsTo={{- range $index, $value := .BoundToServices -}}{{if $index}} {{end}}{{ $value }}.service{{end}}
-After={{- range $index, $value := .BoundToServices -}}{{if $index}} {{end}}{{ $value }}.service{{end}}
-{{- end}}
-{{- if .RequiredServices}}
-Requires={{- range $index, $value := .RequiredServices -}}{{if $index}} {{end}}{{ $value }}.service{{end}}
-Before={{- range $index, $value := .RequiredServices -}}{{if $index}} {{end}}{{ $value }}.service{{end}}
-{{- end}}
-
-[Service]
-Environment={{.EnvVariable}}=%n
-Restart={{.RestartPolicy}}
-{{- if .New}}
-ExecStartPre=/usr/bin/rm -f %t/%n-pid %t/%n-cid
-ExecStart={{.RunCommand}}
-ExecStop={{.Executable}} stop --ignore --cidfile %t/%n-cid {{if (ge .StopTimeout 0)}}-t {{.StopTimeout}}{{end}}
-ExecStopPost={{.Executable}} rm --ignore -f --cidfile %t/%n-cid
-PIDFile=%t/%n-pid
-{{- else}}
-ExecStart={{.Executable}} start {{.ContainerName}}
-ExecStop={{.Executable}} stop {{if (ge .StopTimeout 0)}}-t {{.StopTimeout}}{{end}} {{.ContainerName}}
-PIDFile={{.PIDFile}}
-{{- end}}
-KillMode=none
-Type=forking
-
-[Install]
-WantedBy=multi-user.target default.target`
-
-// Options include different options to control the unit file generation.
-type Options struct {
- // When set, generate service files in the current working directory and
- // return the paths to these files instead of returning all contents in one
- // big string.
- Files bool
- // New controls if a new container is created or if an existing one is started.
- New bool
-}
-
-// CreateContainerSystemdUnit creates a systemd unit file for a container.
-func CreateContainerSystemdUnit(info *ContainerInfo, opts Options) (string, error) {
- if err := validateRestartPolicy(info.RestartPolicy); err != nil {
- return "", err
- }
-
- // Make sure the executable is set.
- if info.Executable == "" {
- executable, err := os.Executable()
- if err != nil {
- executable = "/usr/bin/podman"
- logrus.Warnf("Could not obtain podman executable location, using default %s", executable)
- }
- info.Executable = executable
- }
-
- info.EnvVariable = EnvVariable
-
- // Assemble the ExecStart command when creating a new container.
- //
- // Note that we cannot catch all corner cases here such that users
- // *must* manually check the generated files. A container might have
- // been created via a Python script, which would certainly yield an
- // invalid `info.CreateCommand`. Hence, we're doing a best effort unit
- // generation and don't try aiming at completeness.
- if opts.New {
- // The create command must at least have three arguments:
- // /usr/bin/podman run $IMAGE
- index := 2
- if info.CreateCommand[1] == "container" {
- index = 3
- }
- if len(info.CreateCommand) < index+1 {
- return "", errors.Errorf("container's create command is too short or invalid: %v", info.CreateCommand)
- }
- // We're hard-coding the first five arguments and append the
- // CreateCommand with a stripped command and subcomand.
- command := []string{
- info.Executable,
- "run",
- "--conmon-pidfile", "%t/%n-pid",
- "--cidfile", "%t/%n-cid",
- "--cgroups=no-conmon",
- }
-
- // Enforce detaching
- //
- // since we use systemd `Type=forking` service
- // @see https://www.freedesktop.org/software/systemd/man/systemd.service.html#Type=
- // when we generated systemd service file with the --new param,
- // `ExecStart` will have `/usr/bin/podman run ...`
- // if `info.CreateCommand` has no `-d` or `--detach` param,
- // podman will run the container in default attached mode,
- // as a result, `systemd start` will wait the `podman run` command exit until failed with timeout error.
- hasDetachParam := false
- for _, p := range info.CreateCommand[index:] {
- if p == "--detach" || p == "-d" {
- hasDetachParam = true
- }
- }
- if !hasDetachParam {
- command = append(command, "-d")
- }
-
- command = append(command, info.CreateCommand[index:]...)
- info.RunCommand = strings.Join(command, " ")
- info.New = true
- }
-
- if info.PodmanVersion == "" {
- info.PodmanVersion = version.Version
- }
- if info.GenerateTimestamp {
- info.TimeStamp = fmt.Sprintf("%v", time.Now().Format(time.UnixDate))
- }
-
- // Sort the slices to assure a deterministic output.
- sort.Strings(info.RequiredServices)
- sort.Strings(info.BoundToServices)
-
- // Generate the template and compile it.
- templ, err := template.New("systemd_service_file").Parse(containerTemplate)
- if err != nil {
- return "", errors.Wrap(err, "error parsing systemd service template")
- }
-
- var buf bytes.Buffer
- if err := templ.Execute(&buf, info); err != nil {
- return "", err
- }
-
- if !opts.Files {
- return buf.String(), nil
- }
-
- buf.WriteByte('\n')
- cwd, err := os.Getwd()
- if err != nil {
- return "", errors.Wrap(err, "error getting current working directory")
- }
- path := filepath.Join(cwd, fmt.Sprintf("%s.service", info.ServiceName))
- if err := ioutil.WriteFile(path, buf.Bytes(), 0644); err != nil {
- return "", errors.Wrap(err, "error generating systemd unit")
- }
- return path, nil
-}
diff --git a/pkg/systemd/generate/systemdgen_test.go b/pkg/systemd/generate/systemdgen_test.go
deleted file mode 100644
index 3269405a6..000000000
--- a/pkg/systemd/generate/systemdgen_test.go
+++ /dev/null
@@ -1,347 +0,0 @@
-package generate
-
-import (
- "testing"
-)
-
-func TestValidateRestartPolicy(t *testing.T) {
- type ContainerInfo struct {
- restart string
- }
- tests := []struct {
- name string
- ContainerInfo ContainerInfo
- wantErr bool
- }{
- {"good-on", ContainerInfo{restart: "no"}, false},
- {"good-on-success", ContainerInfo{restart: "on-success"}, false},
- {"good-on-failure", ContainerInfo{restart: "on-failure"}, false},
- {"good-on-abnormal", ContainerInfo{restart: "on-abnormal"}, false},
- {"good-on-watchdog", ContainerInfo{restart: "on-watchdog"}, false},
- {"good-on-abort", ContainerInfo{restart: "on-abort"}, false},
- {"good-always", ContainerInfo{restart: "always"}, false},
- {"fail", ContainerInfo{restart: "foobar"}, true},
- {"failblank", ContainerInfo{restart: ""}, true},
- }
- for _, tt := range tests {
- test := tt
- t.Run(tt.name, func(t *testing.T) {
- if err := validateRestartPolicy(test.ContainerInfo.restart); (err != nil) != test.wantErr {
- t.Errorf("ValidateRestartPolicy() error = %v, wantErr %v", err, test.wantErr)
- }
- })
- }
-}
-
-func TestCreateContainerSystemdUnit(t *testing.T) {
- goodID := `# container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401.service
-# autogenerated by Podman CI
-
-[Unit]
-Description=Podman container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401.service
-Documentation=man:podman-generate-systemd(1)
-Wants=network.target
-After=network-online.target
-
-[Service]
-Environment=PODMAN_SYSTEMD_UNIT=%n
-Restart=always
-ExecStart=/usr/bin/podman start 639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401
-ExecStop=/usr/bin/podman stop -t 10 639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401
-PIDFile=/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
-KillMode=none
-Type=forking
-
-[Install]
-WantedBy=multi-user.target default.target`
-
- goodName := `# container-foobar.service
-# autogenerated by Podman CI
-
-[Unit]
-Description=Podman container-foobar.service
-Documentation=man:podman-generate-systemd(1)
-Wants=network.target
-After=network-online.target
-
-[Service]
-Environment=PODMAN_SYSTEMD_UNIT=%n
-Restart=always
-ExecStart=/usr/bin/podman start foobar
-ExecStop=/usr/bin/podman stop -t 10 foobar
-PIDFile=/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
-KillMode=none
-Type=forking
-
-[Install]
-WantedBy=multi-user.target default.target`
-
- goodNameBoundTo := `# container-foobar.service
-# autogenerated by Podman CI
-
-[Unit]
-Description=Podman container-foobar.service
-Documentation=man:podman-generate-systemd(1)
-Wants=network.target
-After=network-online.target
-RefuseManualStart=yes
-RefuseManualStop=yes
-BindsTo=a.service b.service c.service pod.service
-After=a.service b.service c.service pod.service
-
-[Service]
-Environment=PODMAN_SYSTEMD_UNIT=%n
-Restart=always
-ExecStart=/usr/bin/podman start foobar
-ExecStop=/usr/bin/podman stop -t 10 foobar
-PIDFile=/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
-KillMode=none
-Type=forking
-
-[Install]
-WantedBy=multi-user.target default.target`
-
- podGoodName := `# pod-123abc.service
-# autogenerated by Podman CI
-
-[Unit]
-Description=Podman pod-123abc.service
-Documentation=man:podman-generate-systemd(1)
-Wants=network.target
-After=network-online.target
-Requires=container-1.service container-2.service
-Before=container-1.service container-2.service
-
-[Service]
-Environment=PODMAN_SYSTEMD_UNIT=%n
-Restart=always
-ExecStart=/usr/bin/podman start jadda-jadda-infra
-ExecStop=/usr/bin/podman stop -t 10 jadda-jadda-infra
-PIDFile=/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
-KillMode=none
-Type=forking
-
-[Install]
-WantedBy=multi-user.target default.target`
-
- goodNameNew := `# jadda-jadda.service
-# autogenerated by Podman CI
-
-[Unit]
-Description=Podman jadda-jadda.service
-Documentation=man:podman-generate-systemd(1)
-Wants=network.target
-After=network-online.target
-
-[Service]
-Environment=PODMAN_SYSTEMD_UNIT=%n
-Restart=always
-ExecStartPre=/usr/bin/rm -f %t/%n-pid %t/%n-cid
-ExecStart=/usr/bin/podman run --conmon-pidfile %t/%n-pid --cidfile %t/%n-cid --cgroups=no-conmon -d --name jadda-jadda --hostname hello-world awesome-image:latest command arg1 ... argN
-ExecStop=/usr/bin/podman stop --ignore --cidfile %t/%n-cid -t 42
-ExecStopPost=/usr/bin/podman rm --ignore -f --cidfile %t/%n-cid
-PIDFile=%t/%n-pid
-KillMode=none
-Type=forking
-
-[Install]
-WantedBy=multi-user.target default.target`
-
- goodNameNewDetach := `# jadda-jadda.service
-# autogenerated by Podman CI
-
-[Unit]
-Description=Podman jadda-jadda.service
-Documentation=man:podman-generate-systemd(1)
-Wants=network.target
-After=network-online.target
-
-[Service]
-Environment=PODMAN_SYSTEMD_UNIT=%n
-Restart=always
-ExecStartPre=/usr/bin/rm -f %t/%n-pid %t/%n-cid
-ExecStart=/usr/bin/podman run --conmon-pidfile %t/%n-pid --cidfile %t/%n-cid --cgroups=no-conmon --detach --name jadda-jadda --hostname hello-world awesome-image:latest command arg1 ... argN
-ExecStop=/usr/bin/podman stop --ignore --cidfile %t/%n-cid -t 42
-ExecStopPost=/usr/bin/podman rm --ignore -f --cidfile %t/%n-cid
-PIDFile=%t/%n-pid
-KillMode=none
-Type=forking
-
-[Install]
-WantedBy=multi-user.target default.target`
-
- goodIdNew := `# container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401.service
-# autogenerated by Podman CI
-
-[Unit]
-Description=Podman container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401.service
-Documentation=man:podman-generate-systemd(1)
-Wants=network.target
-After=network-online.target
-
-[Service]
-Environment=PODMAN_SYSTEMD_UNIT=%n
-Restart=always
-ExecStartPre=/usr/bin/rm -f %t/%n-pid %t/%n-cid
-ExecStart=/usr/bin/podman run --conmon-pidfile %t/%n-pid --cidfile %t/%n-cid --cgroups=no-conmon -d awesome-image:latest
-ExecStop=/usr/bin/podman stop --ignore --cidfile %t/%n-cid -t 10
-ExecStopPost=/usr/bin/podman rm --ignore -f --cidfile %t/%n-cid
-PIDFile=%t/%n-pid
-KillMode=none
-Type=forking
-
-[Install]
-WantedBy=multi-user.target default.target`
-
- tests := []struct {
- name string
- info ContainerInfo
- want string
- wantErr bool
- }{
-
- {"good with id",
- ContainerInfo{
- Executable: "/usr/bin/podman",
- ServiceName: "container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401",
- ContainerName: "639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401",
- RestartPolicy: "always",
- PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
- StopTimeout: 10,
- PodmanVersion: "CI",
- },
- goodID,
- false,
- },
- {"good with name",
- ContainerInfo{
- Executable: "/usr/bin/podman",
- ServiceName: "container-foobar",
- ContainerName: "foobar",
- RestartPolicy: "always",
- PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
- StopTimeout: 10,
- PodmanVersion: "CI",
- },
- goodName,
- false,
- },
- {"good with name and bound to",
- ContainerInfo{
- Executable: "/usr/bin/podman",
- ServiceName: "container-foobar",
- ContainerName: "foobar",
- RestartPolicy: "always",
- PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
- StopTimeout: 10,
- PodmanVersion: "CI",
- BoundToServices: []string{"pod", "a", "b", "c"},
- },
- goodNameBoundTo,
- false,
- },
- {"pod",
- ContainerInfo{
- Executable: "/usr/bin/podman",
- ServiceName: "pod-123abc",
- ContainerName: "jadda-jadda-infra",
- RestartPolicy: "always",
- PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
- StopTimeout: 10,
- PodmanVersion: "CI",
- RequiredServices: []string{"container-1", "container-2"},
- },
- podGoodName,
- false,
- },
- {"bad restart policy",
- ContainerInfo{
- Executable: "/usr/bin/podman",
- ServiceName: "639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401",
- RestartPolicy: "never",
- PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
- StopTimeout: 10,
- PodmanVersion: "CI",
- },
- "",
- true,
- },
- {"good with name and generic",
- ContainerInfo{
- Executable: "/usr/bin/podman",
- ServiceName: "jadda-jadda",
- ContainerName: "jadda-jadda",
- RestartPolicy: "always",
- PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
- StopTimeout: 42,
- PodmanVersion: "CI",
- New: true,
- CreateCommand: []string{"I'll get stripped", "container", "run", "--name", "jadda-jadda", "--hostname", "hello-world", "awesome-image:latest", "command", "arg1", "...", "argN"},
- },
- goodNameNew,
- false,
- },
- {"good with explicit short detach param",
- ContainerInfo{
- Executable: "/usr/bin/podman",
- ServiceName: "jadda-jadda",
- ContainerName: "jadda-jadda",
- RestartPolicy: "always",
- PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
- StopTimeout: 42,
- PodmanVersion: "CI",
- New: true,
- CreateCommand: []string{"I'll get stripped", "container", "run", "-d", "--name", "jadda-jadda", "--hostname", "hello-world", "awesome-image:latest", "command", "arg1", "...", "argN"},
- },
- goodNameNew,
- false,
- },
- {"good with explicit full detach param",
- ContainerInfo{
- Executable: "/usr/bin/podman",
- ServiceName: "jadda-jadda",
- ContainerName: "jadda-jadda",
- RestartPolicy: "always",
- PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
- StopTimeout: 42,
- PodmanVersion: "CI",
- New: true,
- CreateCommand: []string{"I'll get stripped", "container", "run", "--detach", "--name", "jadda-jadda", "--hostname", "hello-world", "awesome-image:latest", "command", "arg1", "...", "argN"},
- },
- goodNameNewDetach,
- false,
- },
- {"good with id and no param",
- ContainerInfo{
- Executable: "/usr/bin/podman",
- ServiceName: "container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401",
- ContainerName: "639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401",
- RestartPolicy: "always",
- PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
- StopTimeout: 10,
- PodmanVersion: "CI",
- New: true,
- CreateCommand: []string{"I'll get stripped", "container", "run", "awesome-image:latest"},
- },
- goodIdNew,
- false,
- },
- }
- for _, tt := range tests {
- test := tt
- t.Run(tt.name, func(t *testing.T) {
- opts := Options{
- Files: false,
- New: test.info.New,
- }
- got, err := CreateContainerSystemdUnit(&test.info, opts)
- if (err != nil) != test.wantErr {
- t.Errorf("CreateContainerSystemdUnit() error = \n%v, wantErr \n%v", err, test.wantErr)
- return
- }
- if got != test.want {
- t.Errorf("CreateContainerSystemdUnit() = \n%v\n---------> want\n%v", got, test.want)
- }
- })
- }
-}
diff --git a/pkg/trust/config.go b/pkg/trust/config.go
index 0bafc722b..164df2a90 100644
--- a/pkg/trust/config.go
+++ b/pkg/trust/config.go
@@ -1,7 +1,7 @@
package trust
-// Trust Policy describes a basic trust policy configuration
-type TrustPolicy struct {
+// Policy describes a basic trust policy configuration
+type Policy struct {
Name string `json:"name"`
RepoName string `json:"repo_name,omitempty"`
Keys []string `json:"keys,omitempty"`
diff --git a/pkg/util/mountOpts.go b/pkg/util/mountOpts.go
index 929223244..416e60728 100644
--- a/pkg/util/mountOpts.go
+++ b/pkg/util/mountOpts.go
@@ -28,8 +28,7 @@ func ProcessOptions(options []string, isTmpfs bool, sourcePath string) ([]string
foundWrite, foundSize, foundProp, foundMode, foundExec, foundSuid, foundDev, foundCopyUp, foundBind, foundZ bool
)
- var newOptions []string
-
+ newOptions := make([]string, 0, len(options))
for _, opt := range options {
// Some options have parameters - size, mode
splitOpt := strings.SplitN(opt, "=", 2)
diff --git a/pkg/varlinkapi/create.go b/pkg/varlinkapi/create.go
index 571ce6115..d921130e7 100644
--- a/pkg/varlinkapi/create.go
+++ b/pkg/varlinkapi/create.go
@@ -220,7 +220,7 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod.
}
}
- ctr, err := CreateContainerFromCreateConfig(runtime, createConfig, ctx, pod)
+ ctr, err := CreateContainerFromCreateConfig(ctx, runtime, createConfig, pod)
if err != nil {
return nil, nil, err
}
@@ -909,7 +909,7 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.
return config, nil
}
-func CreateContainerFromCreateConfig(r *libpod.Runtime, createConfig *cc.CreateConfig, ctx context.Context, pod *libpod.Pod) (*libpod.Container, error) {
+func CreateContainerFromCreateConfig(ctx context.Context, r *libpod.Runtime, createConfig *cc.CreateConfig, pod *libpod.Pod) (*libpod.Container, error) {
runtimeSpec, options, err := createConfig.MakeContainerConfig(r, pod)
if err != nil {
return nil, err
diff --git a/pkg/varlinkapi/volumes.go b/pkg/varlinkapi/volumes.go
index aa0eb1fb5..3b6276287 100644
--- a/pkg/varlinkapi/volumes.go
+++ b/pkg/varlinkapi/volumes.go
@@ -25,7 +25,7 @@ func (i *VarlinkAPI) VolumeCreate(call iopodman.VarlinkCall, options iopodman.Vo
volumeOptions = append(volumeOptions, libpod.WithVolumeLabels(options.Labels))
}
if len(options.Options) > 0 {
- parsedOptions, err := parse.ParseVolumeOptions(options.Options)
+ parsedOptions, err := parse.VolumeOptions(options.Options)
if err != nil {
return call.ReplyErrorOccurred(err.Error())
}