diff options
24 files changed, 202 insertions, 33 deletions
@@ -808,7 +808,7 @@ ifneq (,$(findstring systemd,$(BUILDTAGS))) PODMAN_UNIT_FILES = contrib/systemd/auto-update/podman-auto-update.service \ contrib/systemd/system/podman.service \ contrib/systemd/system/podman-restart.service \ - contrib/systemd/system/podman-play-kube@.service + contrib/systemd/system/podman-kube@.service %.service: %.service.in sed -e 's;@@PODMAN@@;$(BINDIR)/podman;g' $< >$@.tmp.$$ \ @@ -822,14 +822,14 @@ install.systemd: $(PODMAN_UNIT_FILES) install ${SELINUXOPT} -m 644 contrib/systemd/system/podman.socket ${DESTDIR}${USERSYSTEMDDIR}/podman.socket install ${SELINUXOPT} -m 644 contrib/systemd/system/podman.service ${DESTDIR}${USERSYSTEMDDIR}/podman.service install ${SELINUXOPT} -m 644 contrib/systemd/system/podman-restart.service ${DESTDIR}${USERSYSTEMDDIR}/podman-restart.service - install ${SELINUXOPT} -m 644 contrib/systemd/system/podman-play-kube@.service ${DESTDIR}${USERSYSTEMDDIR}/podman-play-kube@.service + install ${SELINUXOPT} -m 644 contrib/systemd/system/podman-kube@.service ${DESTDIR}${USERSYSTEMDDIR}/podman-kube@.service # System services install ${SELINUXOPT} -m 644 contrib/systemd/auto-update/podman-auto-update.service ${DESTDIR}${SYSTEMDDIR}/podman-auto-update.service install ${SELINUXOPT} -m 644 contrib/systemd/auto-update/podman-auto-update.timer ${DESTDIR}${SYSTEMDDIR}/podman-auto-update.timer install ${SELINUXOPT} -m 644 contrib/systemd/system/podman.socket ${DESTDIR}${SYSTEMDDIR}/podman.socket install ${SELINUXOPT} -m 644 contrib/systemd/system/podman.service ${DESTDIR}${SYSTEMDDIR}/podman.service install ${SELINUXOPT} -m 644 contrib/systemd/system/podman-restart.service ${DESTDIR}${SYSTEMDDIR}/podman-restart.service - install ${SELINUXOPT} -m 644 contrib/systemd/system/podman-play-kube@.service ${DESTDIR}${SYSTEMDDIR}/podman-play-kube@.service + install ${SELINUXOPT} -m 644 contrib/systemd/system/podman-kube@.service ${DESTDIR}${SYSTEMDDIR}/podman-kube@.service rm -f $(PODMAN_UNIT_FILES) else install.systemd: diff --git a/cmd/podman/inspect/inspect.go b/cmd/podman/inspect/inspect.go index b736b3477..edddf026e 100644 --- a/cmd/podman/inspect/inspect.go +++ b/cmd/podman/inspect/inspect.go @@ -41,7 +41,7 @@ func AddInspectFlagSet(cmd *cobra.Command) *entities.InspectOptions { return &opts } -// Inspect inspects the specified container/image names or IDs. +// Inspect inspects the specified container/image/pod/volume names or IDs. func Inspect(namesOrIDs []string, options entities.InspectOptions) error { inspector, err := newInspector(options) if err != nil { diff --git a/cmd/podman/machine/machine.go b/cmd/podman/machine/machine.go index d3d44b45e..5a8a06b9d 100644 --- a/cmd/podman/machine/machine.go +++ b/cmd/podman/machine/machine.go @@ -5,7 +5,6 @@ package machine import ( "errors" - "fmt" "net" "os" "path/filepath" @@ -18,7 +17,6 @@ import ( "github.com/containers/podman/v4/cmd/podman/validate" "github.com/containers/podman/v4/libpod/events" "github.com/containers/podman/v4/pkg/machine" - "github.com/containers/podman/v4/pkg/rootless" "github.com/containers/podman/v4/pkg/util" "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -164,10 +162,3 @@ func closeMachineEvents(cmd *cobra.Command, _ []string) error { } return nil } - -func rootlessOnly(cmd *cobra.Command, args []string) error { - if !rootless.IsRootless() { - return fmt.Errorf("cannot run command %q as root", cmd.CommandPath()) - } - return nil -} diff --git a/cmd/podman/machine/machine_unix.go b/cmd/podman/machine/machine_unix.go index b56d081ec..a2d9b9d8e 100644 --- a/cmd/podman/machine/machine_unix.go +++ b/cmd/podman/machine/machine_unix.go @@ -4,9 +4,20 @@ package machine import ( + "fmt" "os" + + "github.com/containers/podman/v4/pkg/rootless" + "github.com/spf13/cobra" ) func isUnixSocket(file os.DirEntry) bool { return file.Type()&os.ModeSocket != 0 } + +func rootlessOnly(cmd *cobra.Command, args []string) error { + if !rootless.IsRootless() { + return fmt.Errorf("cannot run command %q as root", cmd.CommandPath()) + } + return nil +} diff --git a/cmd/podman/machine/machine_windows.go b/cmd/podman/machine/machine_windows.go index ffd5d8827..bf1240868 100644 --- a/cmd/podman/machine/machine_windows.go +++ b/cmd/podman/machine/machine_windows.go @@ -3,9 +3,18 @@ package machine import ( "os" "strings" + + "github.com/spf13/cobra" ) func isUnixSocket(file os.DirEntry) bool { // Assume a socket on Windows, since sock mode is not supported yet https://github.com/golang/go/issues/33357 return !file.Type().IsDir() && strings.HasSuffix(file.Name(), ".sock") } + +func rootlessOnly(cmd *cobra.Command, args []string) error { + // Rootless is not relevant on Windows. In the future rootless.IsRootless + // could be switched to return true on Windows, and other codepaths migrated + + return nil +} diff --git a/contrib/systemd/system/podman-play-kube@.service.in b/contrib/systemd/system/podman-kube@.service.in index 824f71eb0..824f71eb0 100644 --- a/contrib/systemd/system/podman-play-kube@.service.in +++ b/contrib/systemd/system/podman-kube@.service.in diff --git a/docs/source/markdown/podman-generate-systemd.1.md b/docs/source/markdown/podman-generate-systemd.1.md index 8c3c32d04..56ad4e446 100644 --- a/docs/source/markdown/podman-generate-systemd.1.md +++ b/docs/source/markdown/podman-generate-systemd.1.md @@ -14,6 +14,17 @@ Generating unit files for a pod requires the pod to be created with an infra con _Note: If you use this command with the remote client, including Mac and Windows (excluding WSL2) machines, you would still have to place the generated units on the remote system. Moreover, please make sure that the XDG_RUNTIME_DIR environment variable is set. If unset, you may set it via `export XDG_RUNTIME_DIR=/run/user/$(id -u)`._ +### Kubernetes Integration + +A Kubernetes YAML can be executed in systemd via the `podman-kube@.service` systemd template. The template's argument is the path to the YAML file. Given a `workload.yaml` file in the home directory, it can be executed as follows: + +``` +$ escaped=$(systemd-escape ~/sysadmin.yaml) +$ systemctl --user start podman-kube@$escaped.service +$ systemctl --user is-active podman-kube@$escaped.service +active +``` + ## OPTIONS #### **--after**=*dependency_name* diff --git a/docs/source/markdown/podman-play-kube.1.md b/docs/source/markdown/podman-play-kube.1.md index 1c7fc99a2..92cb694b0 100644 --- a/docs/source/markdown/podman-play-kube.1.md +++ b/docs/source/markdown/podman-play-kube.1.md @@ -103,6 +103,19 @@ spec: and as a result environment variable `FOO` will be set to `bar` for container `container-1`. +### Systemd Integration + +A Kubernetes YAML can be executed in systemd via the `podman-kube@.service` systemd template. The template's argument is the path to the YAML file. Given a `workload.yaml` file in the home directory, it can be executed as follows: + +``` +$ escaped=$(systemd-escape ~/sysadmin.yaml) +$ systemctl --user start podman-kube@$escaped.service +$ systemctl --user is-active podman-kube@$escaped.service +active +``` + +Note that the path to the YAML file must be escaped via `systemd-escape`. + ## OPTIONS #### **--annotation**=*key=value* diff --git a/docs/source/markdown/podman-volume-create.1.md b/docs/source/markdown/podman-volume-create.1.md index 32b10da84..f43e647bf 100644 --- a/docs/source/markdown/podman-volume-create.1.md +++ b/docs/source/markdown/podman-volume-create.1.md @@ -40,8 +40,8 @@ The `o` option sets options for the mount, and is equivalent to the `-o` flag to - The `o` option supports `uid` and `gid` options to set the UID and GID of the created volume that are not normally supported by **mount(8)**. - The `o` option supports the `size` option to set the maximum size of the created volume, the `inodes` option to set the maximum number of inodes for the volume and `noquota` to completely disable quota support even for tracking of disk usage. Currently these flags are only supported on "xfs" file system mounted with the `prjquota` flag described in the **xfs_quota(8)** man page. - - The `o` option supports . - - Using volume options other then the UID/GID options with the **local** driver requires root privileges. + - The `o` option supports using volume options other than the UID/GID options with the **local** driver and requires root privileges. + - The `o` options supports the `timeout` option which allows users to set a driver specific timeout in seconds before volume creation fails. For example, **--opts=o=timeout=10** sets a driver timeout of 10 seconds. When not using the **local** driver, the given options are passed directly to the volume plugin. In this case, supported options are dictated by the plugin in question, not Podman. diff --git a/libpod/boltdb_state_internal.go b/libpod/boltdb_state_internal.go index edba78d6d..11b4aa049 100644 --- a/libpod/boltdb_state_internal.go +++ b/libpod/boltdb_state_internal.go @@ -530,7 +530,7 @@ func (s *BoltState) getVolumeFromDB(name []byte, volume *Volume, volBkt *bolt.Bu // Retrieve volume driver if volume.UsesVolumeDriver() { - plugin, err := s.runtime.getVolumePlugin(volume.config.Driver) + plugin, err := s.runtime.getVolumePlugin(volume.config) if err != nil { // We want to fail gracefully here, to ensure that we // can still remove volumes even if their plugin is diff --git a/libpod/define/volume_inspect.go b/libpod/define/volume_inspect.go index aaa23b4fc..f731a8735 100644 --- a/libpod/define/volume_inspect.go +++ b/libpod/define/volume_inspect.go @@ -56,6 +56,8 @@ type InspectVolumeData struct { // a container, the container will chown the volume to the container process // UID/GID. NeedsChown bool `json:"NeedsChown,omitempty"` + // Timeout is the specified driver timeout if given + Timeout int `json:"Timeout,omitempty"` } type VolumeReload struct { diff --git a/libpod/options.go b/libpod/options.go index 9a29fb279..3f9a0424a 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -1693,6 +1693,18 @@ func withSetAnon() VolumeCreateOption { } } +// WithVolumeDriverTimeout sets the volume creation timeout period +func WithVolumeDriverTimeout(timeout int) VolumeCreateOption { + return func(volume *Volume) error { + if volume.valid { + return define.ErrVolumeFinalized + } + + volume.config.Timeout = timeout + return nil + } +} + // WithTimezone sets the timezone in the container func WithTimezone(path string) CtrCreateOption { return func(ctr *Container) error { diff --git a/libpod/plugin/volume_api.go b/libpod/plugin/volume_api.go index 2de7db32c..332ab912b 100644 --- a/libpod/plugin/volume_api.go +++ b/libpod/plugin/volume_api.go @@ -127,7 +127,7 @@ func validatePlugin(newPlugin *VolumePlugin) error { // GetVolumePlugin gets a single volume plugin, with the given name, at the // given path. -func GetVolumePlugin(name string, path string) (*VolumePlugin, error) { +func GetVolumePlugin(name string, path string, timeout int) (*VolumePlugin, error) { pluginsLock.Lock() defer pluginsLock.Unlock() @@ -151,6 +151,13 @@ func GetVolumePlugin(name string, path string) (*VolumePlugin, error) { // And since we can reuse it, might as well cache it. client := new(http.Client) client.Timeout = defaultTimeout + // if the user specified a non-zero timeout, use their value. Else, keep the default. + if timeout != 0 { + if time.Duration(timeout)*time.Second < defaultTimeout { + logrus.Warnf("the default timeout for volume creation is %d seconds, setting a time less than that may break this feature.", defaultTimeout) + } + client.Timeout = time.Duration(timeout) * time.Second + } // This bit borrowed from pkg/bindings/connection.go client.Transport = &http.Transport{ DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) { diff --git a/libpod/runtime.go b/libpod/runtime.go index 11ec750b1..da57c20c7 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -1194,9 +1194,11 @@ func (r *Runtime) reloadStorageConf() error { return nil } -// getVolumePlugin gets a specific volume plugin given its name. -func (r *Runtime) getVolumePlugin(name string) (*plugin.VolumePlugin, error) { +// getVolumePlugin gets a specific volume plugin. +func (r *Runtime) getVolumePlugin(volConfig *VolumeConfig) (*plugin.VolumePlugin, error) { // There is no plugin for local. + name := volConfig.Driver + timeout := volConfig.Timeout if name == define.VolumeDriverLocal || name == "" { return nil, nil } @@ -1206,7 +1208,7 @@ func (r *Runtime) getVolumePlugin(name string) (*plugin.VolumePlugin, error) { return nil, errors.Wrapf(define.ErrMissingPlugin, "no volume plugin with name %s available", name) } - return plugin.GetVolumePlugin(name, pluginPath) + return plugin.GetVolumePlugin(name, pluginPath, timeout) } // GetSecretsStorageDir returns the directory that the secrets manager should take diff --git a/libpod/runtime_volume_linux.go b/libpod/runtime_volume_linux.go index 17a48be86..4fd4f7301 100644 --- a/libpod/runtime_volume_linux.go +++ b/libpod/runtime_volume_linux.go @@ -59,7 +59,7 @@ func (r *Runtime) newVolume(noCreatePluginVolume bool, options ...VolumeCreateOp // Plugin can be nil if driver is local, but that's OK - superfluous // assignment doesn't hurt much. - plugin, err := r.getVolumePlugin(volume.config.Driver) + plugin, err := r.getVolumePlugin(volume.config) if err != nil { return nil, errors.Wrapf(err, "volume %s uses volume plugin %s but it could not be retrieved", volume.config.Name, volume.config.Driver) } diff --git a/libpod/volume.go b/libpod/volume.go index ab461a37f..2e8cd77a5 100644 --- a/libpod/volume.go +++ b/libpod/volume.go @@ -55,6 +55,8 @@ type VolumeConfig struct { // DisableQuota indicates that the volume should completely disable using any // quota tracking. DisableQuota bool `json:"disableQuota,omitempty"` + // Timeout allows users to override the default driver timeout of 5 seconds + Timeout int } // VolumeState holds the volume's mutable state. diff --git a/libpod/volume_inspect.go b/libpod/volume_inspect.go index 3d721410b..2182f04e6 100644 --- a/libpod/volume_inspect.go +++ b/libpod/volume_inspect.go @@ -63,6 +63,7 @@ func (v *Volume) Inspect() (*define.InspectVolumeData, error) { data.MountCount = v.state.MountCount data.NeedsCopyUp = v.state.NeedsCopyUp data.NeedsChown = v.state.NeedsChown + data.Timeout = v.config.Timeout return data, nil } diff --git a/pkg/domain/infra/abi/parse/parse.go b/pkg/domain/infra/abi/parse/parse.go index 66794e592..4e8c2e508 100644 --- a/pkg/domain/infra/abi/parse/parse.go +++ b/pkg/domain/infra/abi/parse/parse.go @@ -78,6 +78,16 @@ func VolumeOptions(opts map[string]string) ([]libpod.VolumeCreateOption, error) libpodOptions = append(libpodOptions, libpod.WithVolumeDisableQuota()) // set option "NOQUOTA": "true" volumeOptions["NOQUOTA"] = "true" + case "timeout": + if len(splitO) != 2 { + return nil, errors.Wrapf(define.ErrInvalidArg, "timeout option must provide a valid timeout in seconds") + } + intTimeout, err := strconv.Atoi(splitO[1]) + if err != nil { + return nil, errors.Wrapf(err, "cannot convert Timeout %s to an integer", splitO[1]) + } + logrus.Debugf("Removing timeout from options and adding WithTimeout for Timeout %d", intTimeout) + libpodOptions = append(libpodOptions, libpod.WithVolumeDriverTimeout(intTimeout)) default: finalVal = append(finalVal, o) } diff --git a/pkg/specgenutil/specgen.go b/pkg/specgenutil/specgen.go index ab45a8d47..8ad0a92e7 100644 --- a/pkg/specgenutil/specgen.go +++ b/pkg/specgenutil/specgen.go @@ -1134,17 +1134,21 @@ func parseLinuxResourcesDeviceAccess(device string) (specs.LinuxDeviceCgroup, er } number := strings.SplitN(value[1], ":", 2) - i, err := strconv.ParseInt(number[0], 10, 64) - if err != nil { - return specs.LinuxDeviceCgroup{}, err + if number[0] != "*" { + i, err := strconv.ParseUint(number[0], 10, 64) + if err != nil { + return specs.LinuxDeviceCgroup{}, err + } + m := int64(i) + major = &m } - major = &i if len(number) == 2 && number[1] != "*" { - i, err := strconv.ParseInt(number[1], 10, 64) + i, err := strconv.ParseUint(number[1], 10, 64) if err != nil { return specs.LinuxDeviceCgroup{}, err } - minor = &i + m := int64(i) + minor = &m } access = value[2] for _, c := range strings.Split(access, "") { diff --git a/pkg/specgenutil/specgenutil_test.go b/pkg/specgenutil/specgenutil_test.go index 5867b0ae0..fb2743f17 100644 --- a/pkg/specgenutil/specgenutil_test.go +++ b/pkg/specgenutil/specgenutil_test.go @@ -75,3 +75,82 @@ func TestWinPath(t *testing.T) { } } } + +func TestParseLinuxResourcesDeviceAccess(t *testing.T) { + d, err := parseLinuxResourcesDeviceAccess("a *:* rwm") + assert.Nil(t, err, "err is nil") + assert.True(t, d.Allow, "allow is true") + assert.Equal(t, d.Type, "a", "type is 'a'") + assert.Nil(t, d.Minor, "minor is nil") + assert.Nil(t, d.Major, "major is nil") + + d, err = parseLinuxResourcesDeviceAccess("b 3:* rwm") + assert.Nil(t, err, "err is nil") + assert.True(t, d.Allow, "allow is true") + assert.Equal(t, d.Type, "b", "type is 'b'") + assert.Nil(t, d.Minor, "minor is nil") + assert.NotNil(t, d.Major, "major is not nil") + assert.Equal(t, *d.Major, int64(3), "major is 3") + + d, err = parseLinuxResourcesDeviceAccess("a *:3 rwm") + assert.Nil(t, err, "err is nil") + assert.True(t, d.Allow, "allow is true") + assert.Equal(t, d.Type, "a", "type is 'a'") + assert.Nil(t, d.Major, "major is nil") + assert.NotNil(t, d.Minor, "minor is not nil") + assert.Equal(t, *d.Minor, int64(3), "minor is 3") + + d, err = parseLinuxResourcesDeviceAccess("c 1:2 rwm") + assert.Nil(t, err, "err is nil") + assert.True(t, d.Allow, "allow is true") + assert.Equal(t, d.Type, "c", "type is 'c'") + assert.NotNil(t, d.Major, "minor is not nil") + assert.Equal(t, *d.Major, int64(1), "minor is 1") + assert.NotNil(t, d.Minor, "minor is not nil") + assert.Equal(t, *d.Minor, int64(2), "minor is 2") + + _, err = parseLinuxResourcesDeviceAccess("q *:* rwm") + assert.NotNil(t, err, "err is not nil") + + _, err = parseLinuxResourcesDeviceAccess("a a:* rwm") + assert.NotNil(t, err, "err is not nil") + + _, err = parseLinuxResourcesDeviceAccess("a *:a rwm") + assert.NotNil(t, err, "err is not nil") + + _, err = parseLinuxResourcesDeviceAccess("a *:* abc") + assert.NotNil(t, err, "err is not nil") + + _, err = parseLinuxResourcesDeviceAccess("* *:* *") + assert.NotNil(t, err, "err is not nil") + + _, err = parseLinuxResourcesDeviceAccess("* *:a2 *") + assert.NotNil(t, err, "err is not nil") + + _, err = parseLinuxResourcesDeviceAccess("*") + assert.NotNil(t, err, "err is not nil") + + _, err = parseLinuxResourcesDeviceAccess("*:*") + assert.NotNil(t, err, "err is not nil") + + _, err = parseLinuxResourcesDeviceAccess("a *:*") + assert.NotNil(t, err, "err is not nil") + + _, err = parseLinuxResourcesDeviceAccess("a *:*") + assert.NotNil(t, err, "err is not nil") + + _, err = parseLinuxResourcesDeviceAccess("a 12a:* r") + assert.NotNil(t, err, "err is not nil") + + _, err = parseLinuxResourcesDeviceAccess("a a12:* r") + assert.NotNil(t, err, "err is not nil") + + _, err = parseLinuxResourcesDeviceAccess("a 0x1:* r") + assert.NotNil(t, err, "err is not nil") + + _, err = parseLinuxResourcesDeviceAccess("a -2:* r") + assert.NotNil(t, err, "err is not nil") + + _, err = parseLinuxResourcesDeviceAccess("a *:-3 r") + assert.NotNil(t, err, "err is not nil") +} diff --git a/podman.spec.rpkg b/podman.spec.rpkg index c9127c2d9..30653b658 100644 --- a/podman.spec.rpkg +++ b/podman.spec.rpkg @@ -226,13 +226,13 @@ done %{_unitdir}/%{name}.service %{_unitdir}/%{name}.socket %{_unitdir}/%{name}-restart.service -%{_unitdir}/%{name}-play-kube@.service +%{_unitdir}/%{name}-kube@.service %{_userunitdir}/%{name}-auto-update.service %{_userunitdir}/%{name}-auto-update.timer %{_userunitdir}/%{name}.service %{_userunitdir}/%{name}.socket %{_userunitdir}/%{name}-restart.service -%{_userunitdir}/%{name}-play-kube@.service +%{_userunitdir}/%{name}-kube@.service %{_tmpfilesdir}/%{name}.conf %if 0%{?fedora} >= 36 %{_modulesloaddir}/%{name}-iptables.conf diff --git a/test/e2e/volume_create_test.go b/test/e2e/volume_create_test.go index 499283cab..7a975f6a5 100644 --- a/test/e2e/volume_create_test.go +++ b/test/e2e/volume_create_test.go @@ -162,4 +162,19 @@ var _ = Describe("Podman volume create", func() { Expect(inspectOpts).Should(Exit(0)) Expect(inspectOpts.OutputToString()).To(Equal(optionStrFormatExpect)) }) + + It("podman create volume with o=timeout", func() { + volName := "testVol" + timeout := 10 + timeoutStr := "10" + session := podmanTest.Podman([]string{"volume", "create", "--opt", fmt.Sprintf("o=timeout=%d", timeout), volName}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + inspectTimeout := podmanTest.Podman([]string{"volume", "inspect", "--format", "{{ .Timeout }}", volName}) + inspectTimeout.WaitWithDefaultTimeout() + Expect(inspectTimeout).Should(Exit(0)) + Expect(inspectTimeout.OutputToString()).To(Equal(timeoutStr)) + + }) }) diff --git a/test/system/030-run.bats b/test/system/030-run.bats index 56cf4f266..b3e3cef00 100644 --- a/test/system/030-run.bats +++ b/test/system/030-run.bats @@ -730,7 +730,7 @@ EOF run_podman 125 run --device-cgroup-rule="x 7:* rmw" --rm $IMAGE is "$output" "Error: invalid device type in device-access-add: x" run_podman 125 run --device-cgroup-rule="a a:* rmw" --rm $IMAGE - is "$output" "Error: strconv.ParseInt: parsing \"a\": invalid syntax" + is "$output" "Error: strconv.ParseUint: parsing \"a\": invalid syntax" } @test "podman run closes stdin" { diff --git a/test/system/250-systemd.bats b/test/system/250-systemd.bats index e251e8a6d..fc3c33975 100644 --- a/test/system/250-systemd.bats +++ b/test/system/250-systemd.bats @@ -295,12 +295,12 @@ LISTEN_FDNAMES=listen_fdnames" | sort) run_podman network rm -f $netname } -@test "podman-play-kube@.service template" { +@test "podman-kube@.service template" { skip_if_remote "systemd units do not work with remote clients" # If running from a podman source directory, build and use the source # version of the play-kube-@ unit file - unit_name="podman-play-kube@.service" + unit_name="podman-kube@.service" unit_file="contrib/systemd/system/${unit_name}" if [[ -e ${unit_file}.in ]]; then echo "# [Building & using $unit_name from source]" >&3 @@ -329,7 +329,7 @@ spec: EOF # Dispatch the YAML file - service_name="podman-play-kube@$(systemd-escape $yaml_source).service" + service_name="podman-kube@$(systemd-escape $yaml_source).service" systemctl start $service_name systemctl is-active $service_name |