summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/generate/systemd.go1
-rw-r--r--docs/source/markdown/podman-generate-systemd.1.md4
-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.go16
-rw-r--r--pkg/domain/entities/generate.go2
-rw-r--r--pkg/domain/infra/tunnel/generate.go2
-rw-r--r--pkg/systemd/generate/common.go2
-rw-r--r--pkg/systemd/generate/containers.go10
-rw-r--r--pkg/systemd/generate/containers_test.go59
-rw-r--r--pkg/systemd/generate/pods.go8
-rw-r--r--pkg/systemd/generate/pods_test.go47
-rw-r--r--test/e2e/generate_systemd_test.go36
14 files changed, 175 insertions, 21 deletions
diff --git a/cmd/podman/generate/systemd.go b/cmd/podman/generate/systemd.go
index 7b2d9ebb7..54ee1f051 100644
--- a/cmd/podman/generate/systemd.go
+++ b/cmd/podman/generate/systemd.go
@@ -52,6 +52,7 @@ func init() {
flags.UintVarP(&systemdTimeout, timeFlagName, "t", containerConfig.Engine.StopTimeout, "Stop timeout override")
_ = systemdCmd.RegisterFlagCompletionFunc(timeFlagName, completion.AutocompleteNone)
flags.BoolVarP(&systemdOptions.New, "new", "", false, "Create a new container instead of starting an existing one")
+ flags.BoolVarP(&systemdOptions.NoHeader, "no-header", "", false, "Skip header generation")
containerPrefixFlagName := "container-prefix"
flags.StringVar(&systemdOptions.ContainerPrefix, containerPrefixFlagName, "container", "Systemd unit name prefix for containers")
diff --git a/docs/source/markdown/podman-generate-systemd.1.md b/docs/source/markdown/podman-generate-systemd.1.md
index a59dbc7f0..f75f77d79 100644
--- a/docs/source/markdown/podman-generate-systemd.1.md
+++ b/docs/source/markdown/podman-generate-systemd.1.md
@@ -32,6 +32,10 @@ Use the name of the container for the start, stop, and description in the unit f
Using this flag will yield unit files that do not expect containers and pods to exist. Instead, new containers and pods are created based on their configuration files. The unit files are created best effort and may need to be further edited; please review the generated files carefully before using them in production.
+#### **--no-header**
+
+Do not generate the header including meta data such as the Podman version and the timestamp.
+
#### **--time**, **-t**=*value*
Override the default stop timeout for the container with the given value.
diff --git a/pkg/api/handlers/libpod/generate.go b/pkg/api/handlers/libpod/generate.go
index b3b8c1f16..fc22d0120 100644
--- a/pkg/api/handlers/libpod/generate.go
+++ b/pkg/api/handlers/libpod/generate.go
@@ -18,6 +18,7 @@ func GenerateSystemd(w http.ResponseWriter, r *http.Request) {
query := struct {
Name bool `schema:"useName"`
New bool `schema:"new"`
+ NoHeader bool `schema:"noHeader"`
RestartPolicy string `schema:"restartPolicy"`
StopTimeout uint `schema:"stopTimeout"`
ContainerPrefix string `schema:"containerPrefix"`
@@ -41,6 +42,7 @@ func GenerateSystemd(w http.ResponseWriter, r *http.Request) {
options := entities.GenerateSystemdOptions{
Name: query.Name,
New: query.New,
+ NoHeader: query.NoHeader,
RestartPolicy: query.RestartPolicy,
StopTimeout: &query.StopTimeout,
ContainerPrefix: query.ContainerPrefix,
diff --git a/pkg/api/server/register_generate.go b/pkg/api/server/register_generate.go
index bce5484ab..bbab0ad5f 100644
--- a/pkg/api/server/register_generate.go
+++ b/pkg/api/server/register_generate.go
@@ -32,6 +32,11 @@ func (s *APIServer) registerGenerateHandlers(r *mux.Router) error {
// default: false
// description: Create a new container instead of starting an existing one.
// - in: query
+ // name: noHeader
+ // type: boolean
+ // default: false
+ // description: Do not generate the header including the Podman version and the timestamp.
+ // - in: query
// name: time
// type: integer
// default: 10
diff --git a/pkg/bindings/generate/types.go b/pkg/bindings/generate/types.go
index 4e9d7a0ff..3c9ea87d4 100644
--- a/pkg/bindings/generate/types.go
+++ b/pkg/bindings/generate/types.go
@@ -14,6 +14,8 @@ type SystemdOptions struct {
UseName *bool
// New - create a new container instead of starting a new one.
New *bool
+ // NoHeader - Removes autogenerated by Podman and timestamp if set to true
+ NoHeader *bool
// RestartPolicy - systemd restart policy.
RestartPolicy *string
// 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 dc7378888..25ed446aa 100644
--- a/pkg/bindings/generate/types_systemd_options.go
+++ b/pkg/bindings/generate/types_systemd_options.go
@@ -52,6 +52,22 @@ func (o *SystemdOptions) GetNew() bool {
return *o.New
}
+// WithNoHeader
+func (o *SystemdOptions) WithNoHeader(value bool) *SystemdOptions {
+ v := &value
+ o.NoHeader = v
+ return o
+}
+
+// GetNoHeader
+func (o *SystemdOptions) GetNoHeader() bool {
+ var noHeader bool
+ if o.NoHeader == nil {
+ return noHeader
+ }
+ return *o.NoHeader
+}
+
// WithRestartPolicy
func (o *SystemdOptions) WithRestartPolicy(value string) *SystemdOptions {
v := &value
diff --git a/pkg/domain/entities/generate.go b/pkg/domain/entities/generate.go
index 4a0d7537e..3ec713edf 100644
--- a/pkg/domain/entities/generate.go
+++ b/pkg/domain/entities/generate.go
@@ -18,6 +18,8 @@ type GenerateSystemdOptions struct {
PodPrefix string
// Separator - systemd unit name separator between name/id and prefix
Separator string
+ // NoHeader - skip header generation
+ NoHeader bool
}
// GenerateSystemdReport
diff --git a/pkg/domain/infra/tunnel/generate.go b/pkg/domain/infra/tunnel/generate.go
index 6d68157c1..a9196adaa 100644
--- a/pkg/domain/infra/tunnel/generate.go
+++ b/pkg/domain/infra/tunnel/generate.go
@@ -8,7 +8,7 @@ import (
)
func (ic *ContainerEngine) GenerateSystemd(ctx context.Context, nameOrID string, opts entities.GenerateSystemdOptions) (*entities.GenerateSystemdReport, error) {
- options := new(generate.SystemdOptions).WithUseName(opts.Name).WithContainerPrefix(opts.ContainerPrefix).WithNew(opts.New)
+ options := new(generate.SystemdOptions).WithUseName(opts.Name).WithContainerPrefix(opts.ContainerPrefix).WithNew(opts.New).WithNoHeader(opts.NoHeader)
options.WithPodPrefix(opts.PodPrefix).WithRestartPolicy(opts.RestartPolicy).WithSeparator(opts.Separator)
if to := opts.StopTimeout; to != nil {
options.WithStopTimeout(*opts.StopTimeout)
diff --git a/pkg/systemd/generate/common.go b/pkg/systemd/generate/common.go
index e9902319c..bbd1a5f92 100644
--- a/pkg/systemd/generate/common.go
+++ b/pkg/systemd/generate/common.go
@@ -31,10 +31,12 @@ func validateRestartPolicy(restart string) error {
}
const headerTemplate = `# {{{{.ServiceName}}}}.service
+{{{{- if (eq .GenerateNoHeader false) }}}}
# autogenerated by Podman {{{{.PodmanVersion}}}}
{{{{- if .TimeStamp}}}}
# {{{{.TimeStamp}}}}
{{{{- end}}}}
+{{{{- end}}}}
[Unit]
Description=Podman {{{{.ServiceName}}}}.service
diff --git a/pkg/systemd/generate/containers.go b/pkg/systemd/generate/containers.go
index acee7be65..8fbbc727b 100644
--- a/pkg/systemd/generate/containers.go
+++ b/pkg/systemd/generate/containers.go
@@ -65,7 +65,8 @@ type containerInfo struct {
ExecStop string
// ExecStopPost of the unit.
ExecStopPost string
-
+ // Removes autogenerated by Podman and timestamp if set to true
+ GenerateNoHeader bool
// If not nil, the container is part of the pod. We can use the
// podInfo to extract the relevant data.
Pod *podInfo
@@ -292,10 +293,15 @@ func executeContainerTemplate(info *containerInfo, options entities.GenerateSyst
if info.PodmanVersion == "" {
info.PodmanVersion = version.Version.String()
}
+
+ if options.NoHeader {
+ info.GenerateNoHeader = true
+ info.GenerateTimestamp = false
+ }
+
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)
diff --git a/pkg/systemd/generate/containers_test.go b/pkg/systemd/generate/containers_test.go
index dad14ece9..2ba73ef8d 100644
--- a/pkg/systemd/generate/containers_test.go
+++ b/pkg/systemd/generate/containers_test.go
@@ -37,9 +37,11 @@ func TestValidateRestartPolicyContainer(t *testing.T) {
}
func TestCreateContainerSystemdUnit(t *testing.T) {
- goodID := `# container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401.service
-# autogenerated by Podman CI
-
+ serviceInfo := `# container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401.service
+`
+ headerInfo := `# autogenerated by Podman CI
+`
+ goodIDContent := `
[Unit]
Description=Podman container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401.service
Documentation=man:podman-generate-systemd(1)
@@ -59,6 +61,8 @@ Type=forking
[Install]
WantedBy=multi-user.target default.target
`
+ goodID := serviceInfo + headerInfo + goodIDContent
+ goodIDNoHeaderInfo := serviceInfo + goodIDContent
goodName := `# container-foobar.service
# autogenerated by Podman CI
@@ -377,11 +381,12 @@ Type=forking
WantedBy=multi-user.target default.target
`
tests := []struct {
- name string
- info containerInfo
- want string
- new bool
- wantErr bool
+ name string
+ info containerInfo
+ want string
+ new bool
+ noHeader bool
+ wantErr bool
}{
{"good with id",
@@ -398,6 +403,23 @@ WantedBy=multi-user.target default.target
goodID,
false,
false,
+ false,
+ },
+ {"good with noHeader",
+ containerInfo{
+ Executable: "/usr/bin/podman",
+ ServiceName: "container-639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401",
+ ContainerNameOrID: "639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401",
+ RestartPolicy: "always",
+ PIDFile: "/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ StopTimeout: 22,
+ PodmanVersion: "CI",
+ EnvVariable: EnvVariable,
+ },
+ goodIDNoHeaderInfo,
+ false,
+ true,
+ false,
},
{"good with name",
containerInfo{
@@ -413,6 +435,7 @@ WantedBy=multi-user.target default.target
goodName,
false,
false,
+ false,
},
{"good with name and bound to",
containerInfo{
@@ -429,6 +452,7 @@ WantedBy=multi-user.target default.target
goodNameBoundTo,
false,
false,
+ false,
},
{"bad restart policy",
containerInfo{
@@ -442,6 +466,7 @@ WantedBy=multi-user.target default.target
},
"",
false,
+ false,
true,
},
{"good with name and generic",
@@ -459,6 +484,7 @@ WantedBy=multi-user.target default.target
goodWithNameAndGeneric,
true,
false,
+ false,
},
{"good with explicit short detach param",
containerInfo{
@@ -475,6 +501,7 @@ WantedBy=multi-user.target default.target
goodWithExplicitShortDetachParam,
true,
false,
+ false,
},
{"good with explicit short detach param and podInfo",
containerInfo{
@@ -494,6 +521,7 @@ WantedBy=multi-user.target default.target
goodNameNewWithPodFile,
true,
false,
+ false,
},
{"good with explicit full detach param",
containerInfo{
@@ -510,6 +538,7 @@ WantedBy=multi-user.target default.target
goodNameNewDetach,
true,
false,
+ false,
},
{"good with id and no param",
containerInfo{
@@ -526,6 +555,7 @@ WantedBy=multi-user.target default.target
goodIDNew,
true,
false,
+ false,
},
{"good with explicit detach=true param",
containerInfo{
@@ -542,6 +572,7 @@ WantedBy=multi-user.target default.target
genGoodNewDetach("--detach=true"),
true,
false,
+ false,
},
{"good with explicit detach=false param",
containerInfo{
@@ -558,6 +589,7 @@ WantedBy=multi-user.target default.target
genGoodNewDetach("-d"),
true,
false,
+ false,
},
{"good with explicit detach=false param",
containerInfo{
@@ -574,6 +606,7 @@ WantedBy=multi-user.target default.target
goodNameNewDetachFalseWithCmd,
true,
false,
+ false,
},
{"good with multiple detach=false params",
containerInfo{
@@ -590,6 +623,7 @@ WantedBy=multi-user.target default.target
goodNameNewDetachFalseWithCmd,
true,
false,
+ false,
},
{"good with multiple shorthand params detach first",
containerInfo{
@@ -606,6 +640,7 @@ WantedBy=multi-user.target default.target
genGoodNewDetach("-dti"),
true,
false,
+ false,
},
{"good with multiple shorthand params detach last",
containerInfo{
@@ -622,6 +657,7 @@ WantedBy=multi-user.target default.target
genGoodNewDetach("-tid"),
true,
false,
+ false,
},
{"good with root flags",
containerInfo{
@@ -638,6 +674,7 @@ WantedBy=multi-user.target default.target
goodNewRootFlags,
true,
false,
+ false,
},
{"good with container create",
containerInfo{
@@ -654,6 +691,7 @@ WantedBy=multi-user.target default.target
goodContainerCreate,
true,
false,
+ false,
},
{"good with journald log tag (see #9034)",
containerInfo{
@@ -670,6 +708,7 @@ WantedBy=multi-user.target default.target
goodNewWithJournaldTag,
true,
false,
+ false,
},
{"good with special chars",
containerInfo{
@@ -686,13 +725,15 @@ WantedBy=multi-user.target default.target
goodNewWithSpecialChars,
true,
false,
+ false,
},
}
for _, tt := range tests {
test := tt
t.Run(tt.name, func(t *testing.T) {
opts := entities.GenerateSystemdOptions{
- New: test.new,
+ New: test.new,
+ NoHeader: test.noHeader,
}
got, err := executeContainerTemplate(&test.info, opts)
if (err != nil) != test.wantErr {
diff --git a/pkg/systemd/generate/pods.go b/pkg/systemd/generate/pods.go
index ff8ce3a03..14b1b7a89 100644
--- a/pkg/systemd/generate/pods.go
+++ b/pkg/systemd/generate/pods.go
@@ -70,6 +70,8 @@ type podInfo struct {
ExecStop string
// ExecStopPost of the unit.
ExecStopPost string
+ // Removes autogenerated by Podman and timestamp if set to true
+ GenerateNoHeader bool
}
const podTemplate = headerTemplate + `Requires={{{{- range $index, $value := .RequiredServices -}}}}{{{{if $index}}}} {{{{end}}}}{{{{ $value }}}}.service{{{{end}}}}
@@ -319,6 +321,12 @@ func executePodTemplate(info *podInfo, options entities.GenerateSystemdOptions)
if info.PodmanVersion == "" {
info.PodmanVersion = version.Version.String()
}
+
+ if options.NoHeader {
+ info.GenerateNoHeader = true
+ info.GenerateTimestamp = false
+ }
+
if info.GenerateTimestamp {
info.TimeStamp = fmt.Sprintf("%v", time.Now().Format(time.UnixDate))
}
diff --git a/pkg/systemd/generate/pods_test.go b/pkg/systemd/generate/pods_test.go
index 2b430226b..f6ca9bced 100644
--- a/pkg/systemd/generate/pods_test.go
+++ b/pkg/systemd/generate/pods_test.go
@@ -37,9 +37,11 @@ func TestValidateRestartPolicyPod(t *testing.T) {
}
func TestCreatePodSystemdUnit(t *testing.T) {
- podGood := `# pod-123abc.service
-# autogenerated by Podman CI
-
+ serviceInfo := `# pod-123abc.service
+`
+ headerInfo := `# autogenerated by Podman CI
+`
+ podContent := `
[Unit]
Description=Podman pod-123abc.service
Documentation=man:podman-generate-systemd(1)
@@ -61,6 +63,8 @@ Type=forking
[Install]
WantedBy=multi-user.target default.target
`
+ podGood := serviceInfo + headerInfo + podContent
+ podGoodNoHeaderInfo := serviceInfo + podContent
podGoodNamedNew := `# pod-123abc.service
# autogenerated by Podman CI
@@ -171,11 +175,12 @@ WantedBy=multi-user.target default.target
`
tests := []struct {
- name string
- info podInfo
- want string
- new bool
- wantErr bool
+ name string
+ info podInfo
+ want string
+ new bool
+ noHeader bool
+ wantErr bool
}{
{"pod",
podInfo{
@@ -192,6 +197,24 @@ WantedBy=multi-user.target default.target
podGood,
false,
false,
+ false,
+ },
+ {"pod noHeader",
+ podInfo{
+ Executable: "/usr/bin/podman",
+ ServiceName: "pod-123abc",
+ InfraNameOrID: "jadda-jadda-infra",
+ RestartPolicy: "always",
+ PIDFile: "/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
+ StopTimeout: 42,
+ PodmanVersion: "CI",
+ RequiredServices: []string{"container-1", "container-2"},
+ CreateCommand: []string{"podman", "pod", "create", "--name", "foo", "bar=arg with space"},
+ },
+ podGoodNoHeaderInfo,
+ false,
+ true,
+ false,
},
{"pod with root args",
podInfo{
@@ -208,6 +231,7 @@ WantedBy=multi-user.target default.target
podGood,
false,
false,
+ false,
},
{"pod --new",
podInfo{
@@ -224,6 +248,7 @@ WantedBy=multi-user.target default.target
podGoodNamedNew,
true,
false,
+ false,
},
{"pod --new with root args",
podInfo{
@@ -240,6 +265,7 @@ WantedBy=multi-user.target default.target
podGoodNamedNewWithRootArgs,
true,
false,
+ false,
},
{"pod --new with --replace=false",
podInfo{
@@ -256,6 +282,7 @@ WantedBy=multi-user.target default.target
podGoodNamedNewWithReplaceFalse,
true,
false,
+ false,
},
{"pod --new with double curly braces",
podInfo{
@@ -272,6 +299,7 @@ WantedBy=multi-user.target default.target
podNewLabelWithCurlyBraces,
true,
false,
+ false,
},
}
@@ -279,7 +307,8 @@ WantedBy=multi-user.target default.target
test := tt
t.Run(tt.name, func(t *testing.T) {
opts := entities.GenerateSystemdOptions{
- New: test.new,
+ New: test.new,
+ NoHeader: test.noHeader,
}
got, err := executePodTemplate(&test.info, opts)
if (err != nil) != test.wantErr {
diff --git a/test/e2e/generate_systemd_test.go b/test/e2e/generate_systemd_test.go
index 606d756b0..7c43e6e35 100644
--- a/test/e2e/generate_systemd_test.go
+++ b/test/e2e/generate_systemd_test.go
@@ -62,6 +62,42 @@ var _ = Describe("Podman generate systemd", func() {
Expect(session.ErrorToString()).To(ContainSubstring("bogus is not a valid restart policy"))
})
+ It("podman generate systemd with --no-header=true", func() {
+ session := podmanTest.Podman([]string{"create", "--name", "foobar", "alpine", "top"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"generate", "systemd", "foobar", "--no-header=true"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ Expect(session.OutputToString()).NotTo(ContainSubstring("autogenerated by"))
+ })
+
+ It("podman generate systemd with --no-header", func() {
+ session := podmanTest.Podman([]string{"create", "--name", "foobar", "alpine", "top"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"generate", "systemd", "foobar", "--no-header"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ Expect(session.OutputToString()).NotTo(ContainSubstring("autogenerated by"))
+ })
+
+ It("podman generate systemd with --no-header=false", func() {
+ session := podmanTest.Podman([]string{"create", "--name", "foobar", "alpine", "top"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"generate", "systemd", "foobar", "--no-header=false"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ Expect(session.OutputToString()).To(ContainSubstring("autogenerated by"))
+ })
+
It("podman generate systemd good timeout value", func() {
session := podmanTest.Podman([]string{"create", "--name", "foobar", "alpine", "top"})
session.WaitWithDefaultTimeout()