summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/api/handlers/compat/images_push.go10
-rw-r--r--pkg/api/handlers/libpod/generate.go2
-rw-r--r--pkg/api/server/register_generate.go5
-rw-r--r--pkg/bindings/generate/types.go2
-rw-r--r--pkg/bindings/generate/types_systemd_options.go15
-rw-r--r--pkg/domain/entities/generate.go2
-rw-r--r--pkg/domain/infra/abi/images.go12
-rw-r--r--pkg/domain/infra/abi/play.go71
-rw-r--r--pkg/domain/infra/tunnel/generate.go3
-rw-r--r--pkg/specgen/generate/kube/kube.go12
-rw-r--r--pkg/specgen/generate/kube/volume.go64
-rw-r--r--pkg/systemd/generate/pods.go9
-rw-r--r--pkg/systemd/generate/pods_test.go46
13 files changed, 221 insertions, 32 deletions
diff --git a/pkg/api/handlers/compat/images_push.go b/pkg/api/handlers/compat/images_push.go
index 5ecb429ae..3a84b5799 100644
--- a/pkg/api/handlers/compat/images_push.go
+++ b/pkg/api/handlers/compat/images_push.go
@@ -74,10 +74,16 @@ func PushImage(w http.ResponseWriter, r *http.Request) {
return
}
imageName = possiblyNormalizedName
- if _, _, err := runtime.LibimageRuntime().LookupImage(possiblyNormalizedName, nil); err != nil {
+ localImage, _, err := runtime.LibimageRuntime().LookupImage(possiblyNormalizedName, nil)
+ if err != nil {
utils.ImageNotFound(w, imageName, errors.Wrapf(err, "failed to find image %s", imageName))
return
}
+ rawManifest, _, err := localImage.Manifest(r.Context())
+ if err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusBadRequest, err)
+ return
+ }
authconf, authfile, key, err := auth.GetCredentials(r)
if err != nil {
@@ -196,7 +202,7 @@ loop: // break out of for/select infinite loop
if tag == "" {
tag = "latest"
}
- report.Status = fmt.Sprintf("%s: digest: %s", tag, string(digestBytes))
+ report.Status = fmt.Sprintf("%s: digest: %s size: %d", tag, string(digestBytes), len(rawManifest))
if err := enc.Encode(report); err != nil {
logrus.Warnf("Failed to json encode error %q", err.Error())
}
diff --git a/pkg/api/handlers/libpod/generate.go b/pkg/api/handlers/libpod/generate.go
index 1411c680e..88fd69d45 100644
--- a/pkg/api/handlers/libpod/generate.go
+++ b/pkg/api/handlers/libpod/generate.go
@@ -22,6 +22,7 @@ func GenerateSystemd(w http.ResponseWriter, r *http.Request) {
NoHeader bool `schema:"noHeader"`
TemplateUnitFile bool `schema:"templateUnitFile"`
RestartPolicy *string `schema:"restartPolicy"`
+ RestartSec uint `schema:"restartSec"`
StopTimeout uint `schema:"stopTimeout"`
StartTimeout uint `schema:"startTimeout"`
ContainerPrefix string `schema:"containerPrefix"`
@@ -53,6 +54,7 @@ func GenerateSystemd(w http.ResponseWriter, r *http.Request) {
ContainerPrefix: query.ContainerPrefix,
PodPrefix: query.PodPrefix,
Separator: query.Separator,
+ RestartSec: &query.RestartSec,
}
report, err := containerEngine.GenerateSystemd(r.Context(), utils.GetName(r), options)
diff --git a/pkg/api/server/register_generate.go b/pkg/api/server/register_generate.go
index 0e36394cf..65340bf56 100644
--- a/pkg/api/server/register_generate.go
+++ b/pkg/api/server/register_generate.go
@@ -67,6 +67,11 @@ func (s *APIServer) registerGenerateHandlers(r *mux.Router) error {
// type: string
// default: "-"
// description: Systemd unit name separator between name/id and prefix.
+ // - in: query
+ // name: restartSec
+ // type: integer
+ // default: 0
+ // description: Configures the time to sleep before restarting a service.
// produces:
// - application/json
// responses:
diff --git a/pkg/bindings/generate/types.go b/pkg/bindings/generate/types.go
index 092474e4a..ce560c547 100644
--- a/pkg/bindings/generate/types.go
+++ b/pkg/bindings/generate/types.go
@@ -20,6 +20,8 @@ type SystemdOptions struct {
TemplateUnitFile *bool
// RestartPolicy - systemd restart policy.
RestartPolicy *string
+ // RestartSec - systemd service restartsec. Configures the time to sleep before restarting a service.
+ RestartSec *uint
// StartTimeout - time when starting the container.
StartTimeout *uint
// StopTimeout - time when stopping the container.
diff --git a/pkg/bindings/generate/types_systemd_options.go b/pkg/bindings/generate/types_systemd_options.go
index d60f1d70e..504d4da7f 100644
--- a/pkg/bindings/generate/types_systemd_options.go
+++ b/pkg/bindings/generate/types_systemd_options.go
@@ -92,6 +92,21 @@ func (o *SystemdOptions) GetRestartPolicy() string {
return *o.RestartPolicy
}
+// WithRestartSec set field RestartSec to given value
+func (o *SystemdOptions) WithRestartSec(value uint) *SystemdOptions {
+ o.RestartSec = &value
+ return o
+}
+
+// GetRestartSec returns value of field RestartSec
+func (o *SystemdOptions) GetRestartSec() uint {
+ if o.RestartSec == nil {
+ var z uint
+ return z
+ }
+ return *o.RestartSec
+}
+
// WithStartTimeout set field StartTimeout to given value
func (o *SystemdOptions) WithStartTimeout(value uint) *SystemdOptions {
o.StartTimeout = &value
diff --git a/pkg/domain/entities/generate.go b/pkg/domain/entities/generate.go
index 7e80e5d2d..e431a70af 100644
--- a/pkg/domain/entities/generate.go
+++ b/pkg/domain/entities/generate.go
@@ -10,6 +10,8 @@ type GenerateSystemdOptions struct {
New bool
// RestartPolicy - systemd restart policy.
RestartPolicy *string
+ // RestartSec - systemd service restartsec. Configures the time to sleep before restarting a service.
+ RestartSec *uint
// StartTimeout - time when starting the container.
StartTimeout *uint
// StopTimeout - time when stopping the container.
diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go
index 7a3451a7d..4346182d6 100644
--- a/pkg/domain/infra/abi/images.go
+++ b/pkg/domain/infra/abi/images.go
@@ -306,8 +306,16 @@ func (ir *ImageEngine) Push(ctx context.Context, source string, destination stri
pushOptions.SignBy = options.SignBy
pushOptions.InsecureSkipTLSVerify = options.SkipTLSVerify
- if options.CompressionFormat != "" {
- algo, err := compression.AlgorithmByName(options.CompressionFormat)
+ compressionFormat := options.CompressionFormat
+ if compressionFormat == "" {
+ config, err := ir.Libpod.GetConfigNoCopy()
+ if err != nil {
+ return err
+ }
+ compressionFormat = config.Engine.CompressionFormat
+ }
+ if compressionFormat != "" {
+ algo, err := compression.AlgorithmByName(compressionFormat)
if err != nil {
return err
}
diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go
index bdf22cf0c..ab52fad64 100644
--- a/pkg/domain/infra/abi/play.go
+++ b/pkg/domain/infra/abi/play.go
@@ -239,27 +239,6 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
return nil, err
}
podSpec := entities.PodSpec{PodSpecGen: *p}
- volumes, err := kube.InitializeVolumes(podYAML.Spec.Volumes)
- if err != nil {
- return nil, err
- }
-
- seccompPaths, err := kube.InitializeSeccompPaths(podYAML.ObjectMeta.Annotations, options.SeccompProfileRoot)
- if err != nil {
- return nil, err
- }
-
- var ctrRestartPolicy string
- switch podYAML.Spec.RestartPolicy {
- case v1.RestartPolicyAlways:
- ctrRestartPolicy = define.RestartPolicyAlways
- case v1.RestartPolicyOnFailure:
- ctrRestartPolicy = define.RestartPolicyOnFailure
- case v1.RestartPolicyNever:
- ctrRestartPolicy = define.RestartPolicyNo
- default: // Default to Always
- ctrRestartPolicy = define.RestartPolicyAlways
- }
configMapIndex := make(map[string]struct{})
for _, configMap := range configMaps {
@@ -284,6 +263,56 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
configMaps = append(configMaps, cm)
}
+ volumes, err := kube.InitializeVolumes(podYAML.Spec.Volumes, configMaps)
+ if err != nil {
+ return nil, err
+ }
+
+ // Go through the volumes and create a podman volume for all volumes that have been
+ // defined by a configmap
+ for _, v := range volumes {
+ if v.Type == kube.KubeVolumeTypeConfigMap && !v.Optional {
+ vol, err := ic.Libpod.NewVolume(ctx, libpod.WithVolumeName(v.Source))
+ if err != nil {
+ return nil, errors.Wrapf(err, "cannot create a local volume for volume from configmap %q", v.Source)
+ }
+ mountPoint, err := vol.MountPoint()
+ if err != nil || mountPoint == "" {
+ return nil, errors.Wrapf(err, "unable to get mountpoint of volume %q", vol.Name())
+ }
+ // Create files and add data to the volume mountpoint based on the Items in the volume
+ for k, v := range v.Items {
+ dataPath := filepath.Join(mountPoint, k)
+ f, err := os.Create(dataPath)
+ if err != nil {
+ return nil, errors.Wrapf(err, "cannot create file %q at volume mountpoint %q", k, mountPoint)
+ }
+ defer f.Close()
+ _, err = f.WriteString(v)
+ if err != nil {
+ return nil, err
+ }
+ }
+ }
+ }
+
+ seccompPaths, err := kube.InitializeSeccompPaths(podYAML.ObjectMeta.Annotations, options.SeccompProfileRoot)
+ if err != nil {
+ return nil, err
+ }
+
+ var ctrRestartPolicy string
+ switch podYAML.Spec.RestartPolicy {
+ case v1.RestartPolicyAlways:
+ ctrRestartPolicy = define.RestartPolicyAlways
+ case v1.RestartPolicyOnFailure:
+ ctrRestartPolicy = define.RestartPolicyOnFailure
+ case v1.RestartPolicyNever:
+ ctrRestartPolicy = define.RestartPolicyNo
+ default: // Default to Always
+ ctrRestartPolicy = define.RestartPolicyAlways
+ }
+
if podOpt.Infra {
infraImage := util.DefaultContainerConfig().Engine.InfraImage
infraOptions := entities.NewInfraContainerCreateOptions()
diff --git a/pkg/domain/infra/tunnel/generate.go b/pkg/domain/infra/tunnel/generate.go
index d62a318d6..dd895b61f 100644
--- a/pkg/domain/infra/tunnel/generate.go
+++ b/pkg/domain/infra/tunnel/generate.go
@@ -19,6 +19,9 @@ func (ic *ContainerEngine) GenerateSystemd(ctx context.Context, nameOrID string,
if opts.RestartPolicy != nil {
options.WithRestartPolicy(*opts.RestartPolicy)
}
+ if opts.RestartSec != nil {
+ options.WithRestartSec(*opts.RestartSec)
+ }
return generate.Systemd(ic.ClientCtx, nameOrID, options)
}
diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go
index c502a6e62..6d9f598c9 100644
--- a/pkg/specgen/generate/kube/kube.go
+++ b/pkg/specgen/generate/kube/kube.go
@@ -310,6 +310,11 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
if !exists {
return nil, errors.Errorf("Volume mount %s specified for container but not configured in volumes", volume.Name)
}
+ // Skip if the volume is optional. This means that a configmap for a configmap volume was not found but it was
+ // optional so we can move on without throwing an error
+ if exists && volumeSource.Optional {
+ continue
+ }
dest, options, err := parseMountPath(volume.MountPath, volume.ReadOnly)
if err != nil {
@@ -341,6 +346,13 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
Options: options,
}
s.Volumes = append(s.Volumes, &namedVolume)
+ case KubeVolumeTypeConfigMap:
+ cmVolume := specgen.NamedVolume{
+ Dest: volume.MountPath,
+ Name: volumeSource.Source,
+ Options: options,
+ }
+ s.Volumes = append(s.Volumes, &cmVolume)
default:
return nil, errors.Errorf("Unsupported volume source type")
}
diff --git a/pkg/specgen/generate/kube/volume.go b/pkg/specgen/generate/kube/volume.go
index a8042b532..76ec0a390 100644
--- a/pkg/specgen/generate/kube/volume.go
+++ b/pkg/specgen/generate/kube/volume.go
@@ -23,6 +23,7 @@ type KubeVolumeType int
const (
KubeVolumeTypeBindMount KubeVolumeType = iota
KubeVolumeTypeNamed KubeVolumeType = iota
+ KubeVolumeTypeConfigMap KubeVolumeType = iota
)
// nolint:golint
@@ -31,6 +32,14 @@ type KubeVolume struct {
Type KubeVolumeType
// Path for bind mount or volume name for named volume
Source string
+ // Items to add to a named volume created where the key is the file name and the value is the data
+ // This is only used when there are volumes in the yaml that refer to a configmap
+ // Example: if configmap has data "SPECIAL_LEVEL: very" then the file name is "SPECIAL_LEVEL" and the
+ // data in that file is "very".
+ Items map[string]string
+ // If the volume is optional, we can move on if it is not found
+ // Only used when there are volumes in a yaml that refer to a configmap
+ Optional bool
}
// Create a KubeVolume from an HostPathVolumeSource
@@ -98,23 +107,64 @@ func VolumeFromPersistentVolumeClaim(claim *v1.PersistentVolumeClaimVolumeSource
}, nil
}
+func VolumeFromConfigMap(configMapVolumeSource *v1.ConfigMapVolumeSource, configMaps []v1.ConfigMap) (*KubeVolume, error) {
+ var configMap *v1.ConfigMap
+ kv := &KubeVolume{Type: KubeVolumeTypeConfigMap, Items: map[string]string{}}
+ for _, cm := range configMaps {
+ if cm.Name == configMapVolumeSource.Name {
+ matchedCM := cm
+ // Set the source to the config map name
+ kv.Source = cm.Name
+ configMap = &matchedCM
+ break
+ }
+ }
+
+ if configMap == nil {
+ // If the volumeSource was optional, move on even if a matching configmap wasn't found
+ if *configMapVolumeSource.Optional {
+ kv.Source = configMapVolumeSource.Name
+ kv.Optional = *configMapVolumeSource.Optional
+ return kv, nil
+ }
+ return nil, errors.Errorf("no such ConfigMap %q", configMapVolumeSource.Name)
+ }
+
+ // If there are Items specified in the volumeSource, that overwrites the Data from the configmap
+ if len(configMapVolumeSource.Items) > 0 {
+ for _, item := range configMapVolumeSource.Items {
+ if val, ok := configMap.Data[item.Key]; ok {
+ kv.Items[item.Path] = val
+ }
+ }
+ } else {
+ for k, v := range configMap.Data {
+ kv.Items[k] = v
+ }
+ }
+ return kv, nil
+}
+
// Create a KubeVolume from one of the supported VolumeSource
-func VolumeFromSource(volumeSource v1.VolumeSource) (*KubeVolume, error) {
- if volumeSource.HostPath != nil {
+func VolumeFromSource(volumeSource v1.VolumeSource, configMaps []v1.ConfigMap) (*KubeVolume, error) {
+ switch {
+ case volumeSource.HostPath != nil:
return VolumeFromHostPath(volumeSource.HostPath)
- } else if volumeSource.PersistentVolumeClaim != nil {
+ case volumeSource.PersistentVolumeClaim != nil:
return VolumeFromPersistentVolumeClaim(volumeSource.PersistentVolumeClaim)
- } else {
- return nil, errors.Errorf("HostPath and PersistentVolumeClaim are currently the only supported VolumeSource")
+ case volumeSource.ConfigMap != nil:
+ return VolumeFromConfigMap(volumeSource.ConfigMap, configMaps)
+ default:
+ return nil, errors.Errorf("HostPath, ConfigMap, and PersistentVolumeClaim are currently the only supported VolumeSource")
}
}
// Create a map of volume name to KubeVolume
-func InitializeVolumes(specVolumes []v1.Volume) (map[string]*KubeVolume, error) {
+func InitializeVolumes(specVolumes []v1.Volume, configMaps []v1.ConfigMap) (map[string]*KubeVolume, error) {
volumes := make(map[string]*KubeVolume)
for _, specVolume := range specVolumes {
- volume, err := VolumeFromSource(specVolume.VolumeSource)
+ volume, err := VolumeFromSource(specVolume.VolumeSource, configMaps)
if err != nil {
return nil, errors.Wrapf(err, "failed to create volume %q", specVolume.Name)
}
diff --git a/pkg/systemd/generate/pods.go b/pkg/systemd/generate/pods.go
index 48252c737..f2d04dadc 100644
--- a/pkg/systemd/generate/pods.go
+++ b/pkg/systemd/generate/pods.go
@@ -30,6 +30,8 @@ type podInfo struct {
StopTimeout uint
// RestartPolicy of the systemd unit (e.g., no, on-failure, always).
RestartPolicy string
+ // RestartSec of the systemd unit. Configures the time to sleep before restarting a service.
+ RestartSec uint
// PIDFile of the service. Required for forking services. Must point to the
// PID of the associated conmon process.
PIDFile string
@@ -89,6 +91,9 @@ Before={{{{- range $index, $value := .RequiredServices -}}}}{{{{if $index}}}} {{
[Service]
Environment={{{{.EnvVariable}}}}=%n
Restart={{{{.RestartPolicy}}}}
+{{{{- if .RestartSec}}}}
+RestartSec={{{{.RestartSec}}}}
+{{{{- end}}}}
TimeoutStopSec={{{{.TimeoutStopSec}}}}
{{{{- if .ExecStartPre1}}}}
ExecStartPre={{{{.ExecStartPre1}}}}
@@ -242,6 +247,10 @@ func executePodTemplate(info *podInfo, options entities.GenerateSystemdOptions)
info.RestartPolicy = *options.RestartPolicy
}
+ if options.RestartSec != nil {
+ info.RestartSec = *options.RestartSec
+ }
+
// Make sure the executable is set.
if info.Executable == "" {
executable, err := os.Executable()
diff --git a/pkg/systemd/generate/pods_test.go b/pkg/systemd/generate/pods_test.go
index 612908991..0889507a5 100644
--- a/pkg/systemd/generate/pods_test.go
+++ b/pkg/systemd/generate/pods_test.go
@@ -67,6 +67,33 @@ WantedBy=default.target
podGood := serviceInfo + headerInfo + podContent
podGoodNoHeaderInfo := serviceInfo + podContent
+ podGoodRestartSec := `# pod-123abc.service
+# autogenerated by Podman CI
+
+[Unit]
+Description=Podman pod-123abc.service
+Documentation=man:podman-generate-systemd(1)
+Wants=network-online.target
+After=network-online.target
+RequiresMountsFor=/var/run/containers/storage
+Requires=container-1.service container-2.service
+Before=container-1.service container-2.service
+
+[Service]
+Environment=PODMAN_SYSTEMD_UNIT=%n
+Restart=on-failure
+RestartSec=15
+TimeoutStopSec=102
+ExecStart=/usr/bin/podman start jadda-jadda-infra
+ExecStop=/usr/bin/podman stop -t 42 jadda-jadda-infra
+ExecStopPost=/usr/bin/podman stop -t 42 jadda-jadda-infra
+PIDFile=/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
+Type=forking
+
+[Install]
+WantedBy=default.target
+`
+
podGoodNamedNew := `# pod-123abc.service
# autogenerated by Podman CI
@@ -205,6 +232,25 @@ WantedBy=default.target
false,
false,
},
+ {"pod restartSec",
+ podInfo{
+ Executable: "/usr/bin/podman",
+ ServiceName: "pod-123abc",
+ InfraNameOrID: "jadda-jadda-infra",
+ PIDFile: "/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ StopTimeout: 42,
+ PodmanVersion: "CI",
+ GraphRoot: "/var/lib/containers/storage",
+ RunRoot: "/var/run/containers/storage",
+ RequiredServices: []string{"container-1", "container-2"},
+ CreateCommand: []string{"podman", "pod", "create", "--name", "foo", "bar=arg with space"},
+ RestartSec: 15,
+ },
+ podGoodRestartSec,
+ false,
+ false,
+ false,
+ },
{"pod noHeader",
podInfo{
Executable: "/usr/bin/podman",