aboutsummaryrefslogtreecommitdiff
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 913b0c7ed..693506725 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 2e139a0a9..0e6e9100a 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 ccb29fed0..abbad1485 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 368484e51..3e28bd0f1 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 2484574a7..0e768b30b 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 4fb437d08..92c6d8865 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 c007c6eb4..747c54699 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 343b3c902..8c0401278 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 068df38d9..50c8d4556 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 d164b6021..3a1da5d8c 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()