mirror of https://github.com/containers/podman.git
Separator is no longer prepended when prefix is empty on podman generate systemd
When podman generate systemd is invoked, it previously did not check if container-prefix or pod-prefix are empty. When these are empty, the file name starts with the separator, which is hyphen by default. This results in files like '-containername.service'. The code now checks if these prefixes are empty. If they are, the filename no longer adds a separator. Instead, it uses name or ID of the container or pod. Closes #13272 Signed-off-by: Nirmal Patel <npate012@gmail.com>
This commit is contained in:
parent
b1d37a7e21
commit
714e5a13d9
|
@ -25,18 +25,15 @@ func GenerateSystemd(w http.ResponseWriter, r *http.Request) {
|
||||||
RestartSec uint `schema:"restartSec"`
|
RestartSec uint `schema:"restartSec"`
|
||||||
StopTimeout uint `schema:"stopTimeout"`
|
StopTimeout uint `schema:"stopTimeout"`
|
||||||
StartTimeout uint `schema:"startTimeout"`
|
StartTimeout uint `schema:"startTimeout"`
|
||||||
ContainerPrefix string `schema:"containerPrefix"`
|
ContainerPrefix *string `schema:"containerPrefix"`
|
||||||
PodPrefix string `schema:"podPrefix"`
|
PodPrefix *string `schema:"podPrefix"`
|
||||||
Separator string `schema:"separator"`
|
Separator *string `schema:"separator"`
|
||||||
Wants []string `schema:"wants"`
|
Wants []string `schema:"wants"`
|
||||||
After []string `schema:"after"`
|
After []string `schema:"after"`
|
||||||
Requires []string `schema:"requires"`
|
Requires []string `schema:"requires"`
|
||||||
}{
|
}{
|
||||||
StartTimeout: 0,
|
StartTimeout: 0,
|
||||||
StopTimeout: util.DefaultContainerConfig().Engine.StopTimeout,
|
StopTimeout: util.DefaultContainerConfig().Engine.StopTimeout,
|
||||||
ContainerPrefix: "container",
|
|
||||||
PodPrefix: "pod",
|
|
||||||
Separator: "-",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
|
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
|
||||||
|
@ -44,6 +41,21 @@ func GenerateSystemd(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ContainerPrefix = "container"
|
||||||
|
if query.ContainerPrefix != nil {
|
||||||
|
ContainerPrefix = *query.ContainerPrefix
|
||||||
|
}
|
||||||
|
|
||||||
|
var PodPrefix = "pod"
|
||||||
|
if query.PodPrefix != nil {
|
||||||
|
PodPrefix = *query.PodPrefix
|
||||||
|
}
|
||||||
|
|
||||||
|
var Separator = "-"
|
||||||
|
if query.Separator != nil {
|
||||||
|
Separator = *query.Separator
|
||||||
|
}
|
||||||
|
|
||||||
containerEngine := abi.ContainerEngine{Libpod: runtime}
|
containerEngine := abi.ContainerEngine{Libpod: runtime}
|
||||||
options := entities.GenerateSystemdOptions{
|
options := entities.GenerateSystemdOptions{
|
||||||
Name: query.Name,
|
Name: query.Name,
|
||||||
|
@ -53,9 +65,9 @@ func GenerateSystemd(w http.ResponseWriter, r *http.Request) {
|
||||||
RestartPolicy: query.RestartPolicy,
|
RestartPolicy: query.RestartPolicy,
|
||||||
StartTimeout: &query.StartTimeout,
|
StartTimeout: &query.StartTimeout,
|
||||||
StopTimeout: &query.StopTimeout,
|
StopTimeout: &query.StopTimeout,
|
||||||
ContainerPrefix: query.ContainerPrefix,
|
ContainerPrefix: ContainerPrefix,
|
||||||
PodPrefix: query.PodPrefix,
|
PodPrefix: PodPrefix,
|
||||||
Separator: query.Separator,
|
Separator: Separator,
|
||||||
RestartSec: &query.RestartSec,
|
RestartSec: &query.RestartSec,
|
||||||
Wants: query.Wants,
|
Wants: query.Wants,
|
||||||
After: query.After,
|
After: query.After,
|
||||||
|
|
|
@ -137,3 +137,17 @@ func removeArg(arg string, args []string) []string {
|
||||||
}
|
}
|
||||||
return newArgs
|
return newArgs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This function is used to get name of systemd service from prefix, separator, and
|
||||||
|
// container/pod name. If prefix is empty, the service name does not include the
|
||||||
|
// separator. This is to avoid a situation where service name starts with the separator
|
||||||
|
// which is usually hyphen.
|
||||||
|
func getServiceName(prefix string, separator string, name string) string {
|
||||||
|
serviceName := name
|
||||||
|
|
||||||
|
if len(prefix) > 0 {
|
||||||
|
serviceName = prefix + separator + name
|
||||||
|
}
|
||||||
|
|
||||||
|
return serviceName
|
||||||
|
}
|
||||||
|
|
|
@ -236,7 +236,9 @@ func containerServiceName(ctr *libpod.Container, options entities.GenerateSystem
|
||||||
if options.Name {
|
if options.Name {
|
||||||
nameOrID = ctr.Name()
|
nameOrID = ctr.Name()
|
||||||
}
|
}
|
||||||
serviceName := fmt.Sprintf("%s%s%s", options.ContainerPrefix, options.Separator, nameOrID)
|
|
||||||
|
serviceName := getServiceName(options.ContainerPrefix, options.Separator, nameOrID)
|
||||||
|
|
||||||
return nameOrID, serviceName
|
return nameOrID, serviceName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,6 +87,30 @@ ExecStopPost=/usr/bin/podman stop -t 10 foobar
|
||||||
PIDFile=/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
|
PIDFile=/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
|
||||||
Type=forking
|
Type=forking
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=default.target
|
||||||
|
`
|
||||||
|
|
||||||
|
goodNameEmptyContainerPrefix := `# foobar.service
|
||||||
|
# autogenerated by Podman CI
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=Podman foobar.service
|
||||||
|
Documentation=man:podman-generate-systemd(1)
|
||||||
|
Wants=network-online.target
|
||||||
|
After=network-online.target
|
||||||
|
RequiresMountsFor=/var/run/containers/storage
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Environment=PODMAN_SYSTEMD_UNIT=%n
|
||||||
|
Restart=on-failure
|
||||||
|
TimeoutStopSec=70
|
||||||
|
ExecStart=/usr/bin/podman start foobar
|
||||||
|
ExecStop=/usr/bin/podman stop -t 10 foobar
|
||||||
|
ExecStopPost=/usr/bin/podman stop -t 10 foobar
|
||||||
|
PIDFile=/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid
|
||||||
|
Type=forking
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=default.target
|
WantedBy=default.target
|
||||||
`
|
`
|
||||||
|
@ -1206,6 +1230,24 @@ WantedBy=default.target
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
|
{"good with name and empty container-prefix",
|
||||||
|
containerInfo{
|
||||||
|
Executable: "/usr/bin/podman",
|
||||||
|
ServiceName: "foobar",
|
||||||
|
ContainerNameOrID: "foobar",
|
||||||
|
PIDFile: "/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
|
||||||
|
StopTimeout: 10,
|
||||||
|
PodmanVersion: "CI",
|
||||||
|
EnvVariable: define.EnvVariable,
|
||||||
|
GraphRoot: "/var/lib/containers/storage",
|
||||||
|
RunRoot: "/var/run/containers/storage",
|
||||||
|
},
|
||||||
|
goodNameEmptyContainerPrefix,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
test := tt
|
test := tt
|
||||||
|
|
|
@ -242,7 +242,8 @@ func generatePodInfo(pod *libpod.Pod, options entities.GenerateSystemdOptions) (
|
||||||
nameOrID = pod.Name()
|
nameOrID = pod.Name()
|
||||||
ctrNameOrID = infraCtr.Name()
|
ctrNameOrID = infraCtr.Name()
|
||||||
}
|
}
|
||||||
serviceName := fmt.Sprintf("%s%s%s", options.PodPrefix, options.Separator, nameOrID)
|
|
||||||
|
serviceName := getServiceName(options.PodPrefix, options.Separator, nameOrID)
|
||||||
|
|
||||||
info := podInfo{
|
info := podInfo{
|
||||||
ServiceName: serviceName,
|
ServiceName: serviceName,
|
||||||
|
|
|
@ -67,6 +67,32 @@ WantedBy=default.target
|
||||||
podGood := serviceInfo + headerInfo + podContent
|
podGood := serviceInfo + headerInfo + podContent
|
||||||
podGoodNoHeaderInfo := serviceInfo + podContent
|
podGoodNoHeaderInfo := serviceInfo + podContent
|
||||||
|
|
||||||
|
podGoodWithEmptyPrefix := `# 123abc.service
|
||||||
|
# autogenerated by Podman CI
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=Podman 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
|
||||||
|
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
|
||||||
|
`
|
||||||
|
|
||||||
podGoodCustomWants := `# pod-123abc.service
|
podGoodCustomWants := `# pod-123abc.service
|
||||||
# autogenerated by Podman CI
|
# autogenerated by Podman CI
|
||||||
|
|
||||||
|
@ -580,6 +606,24 @@ WantedBy=default.target
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
|
{"pod with empty pod-prefix",
|
||||||
|
podInfo{
|
||||||
|
Executable: "/usr/bin/podman",
|
||||||
|
ServiceName: "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"},
|
||||||
|
},
|
||||||
|
podGoodWithEmptyPrefix,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
|
|
@ -423,6 +423,20 @@ var _ = Describe("Podman generate systemd", func() {
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("podman generate systemd --container-prefix ''", func() {
|
||||||
|
n := podmanTest.Podman([]string{"create", "--name", "foo", "alpine", "top"})
|
||||||
|
n.WaitWithDefaultTimeout()
|
||||||
|
Expect(n).Should(Exit(0))
|
||||||
|
|
||||||
|
session := podmanTest.Podman([]string{"generate", "systemd", "--name", "--container-prefix", "", "foo"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session).Should(Exit(0))
|
||||||
|
|
||||||
|
// Grepping the output (in addition to unit tests)
|
||||||
|
Expect(session.OutputToString()).To(ContainSubstring("# foo.service"))
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
It("podman generate systemd --separator _", func() {
|
It("podman generate systemd --separator _", func() {
|
||||||
n := podmanTest.Podman([]string{"create", "--name", "foo", "alpine", "top"})
|
n := podmanTest.Podman([]string{"create", "--name", "foo", "alpine", "top"})
|
||||||
n.WaitWithDefaultTimeout()
|
n.WaitWithDefaultTimeout()
|
||||||
|
@ -485,6 +499,44 @@ var _ = Describe("Podman generate systemd", func() {
|
||||||
Expect(session.OutputToString()).To(ContainSubstring("BindsTo=p_foo.service"))
|
Expect(session.OutputToString()).To(ContainSubstring("BindsTo=p_foo.service"))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("podman generate systemd pod --pod-prefix '' --container-prefix '' --separator _ change all prefixes/separator", func() {
|
||||||
|
n := podmanTest.Podman([]string{"pod", "create", "--name", "foo"})
|
||||||
|
n.WaitWithDefaultTimeout()
|
||||||
|
Expect(n).Should(Exit(0))
|
||||||
|
|
||||||
|
n = podmanTest.Podman([]string{"create", "--pod", "foo", "--name", "foo-1", "alpine", "top"})
|
||||||
|
n.WaitWithDefaultTimeout()
|
||||||
|
Expect(n).Should(Exit(0))
|
||||||
|
|
||||||
|
n = podmanTest.Podman([]string{"create", "--pod", "foo", "--name", "foo-2", "alpine", "top"})
|
||||||
|
n.WaitWithDefaultTimeout()
|
||||||
|
Expect(n).Should(Exit(0))
|
||||||
|
|
||||||
|
// test systemd generate with empty pod prefix
|
||||||
|
session1 := podmanTest.Podman([]string{"generate", "systemd", "--pod-prefix", "", "--name", "foo"})
|
||||||
|
session1.WaitWithDefaultTimeout()
|
||||||
|
Expect(session1).Should(Exit(0))
|
||||||
|
|
||||||
|
// Grepping the output (in addition to unit tests)
|
||||||
|
Expect(session1.OutputToString()).To(ContainSubstring("# foo.service"))
|
||||||
|
Expect(session1.OutputToString()).To(ContainSubstring("Requires=container-foo-1.service container-foo-2.service"))
|
||||||
|
Expect(session1.OutputToString()).To(ContainSubstring("# container-foo-1.service"))
|
||||||
|
Expect(session1.OutputToString()).To(ContainSubstring("BindsTo=foo.service"))
|
||||||
|
|
||||||
|
// test systemd generate with empty container and pod prefix
|
||||||
|
session2 := podmanTest.Podman([]string{"generate", "systemd", "--container-prefix", "", "--pod-prefix", "", "--separator", "_", "--name", "foo"})
|
||||||
|
session2.WaitWithDefaultTimeout()
|
||||||
|
Expect(session2).Should(Exit(0))
|
||||||
|
|
||||||
|
// Grepping the output (in addition to unit tests)
|
||||||
|
Expect(session2.OutputToString()).To(ContainSubstring("# foo.service"))
|
||||||
|
Expect(session2.OutputToString()).To(ContainSubstring("Requires=foo-1.service foo-2.service"))
|
||||||
|
Expect(session2.OutputToString()).To(ContainSubstring("# foo-1.service"))
|
||||||
|
Expect(session2.OutputToString()).To(ContainSubstring("# foo-2.service"))
|
||||||
|
Expect(session2.OutputToString()).To(ContainSubstring("BindsTo=foo.service"))
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
It("podman generate systemd pod with containers --new", func() {
|
It("podman generate systemd pod with containers --new", func() {
|
||||||
tmpDir, err := ioutil.TempDir("", "")
|
tmpDir, err := ioutil.TempDir("", "")
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
|
|
Loading…
Reference in New Issue