Skip to content

Commit

Permalink
Merge pull request #19256 from ygalblum/quadlet-working-dir
Browse files Browse the repository at this point in the history
Quadlet - Allow setting Service WorkingDirectory for Kube units
  • Loading branch information
openshift-merge-robot authored Jul 19, 2023
2 parents e5faed7 + 8d19070 commit d98978a
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 10 deletions.
31 changes: 21 additions & 10 deletions docs/source/markdown/podman-systemd.unit.5.md
Original file line number Diff line number Diff line change
Expand Up @@ -517,16 +517,17 @@ There is only one required key, `Yaml`, which defines the path to the Kubernetes

Valid options for `[Kube]` are listed below:

| **[Kube] options** | **podman kube play equivalent** |
| ----------------------------------- | ------------------------------------------------ |
| AutoUpdate=registry | --annotation "io.containers.autoupdate=registry" |
| ConfigMap=/tmp/config.map | --config-map /tmp/config.map |
| LogDriver=journald | --log-driver journald |
| Network=host | --net host |
| PodmanArgs=\-\-annotation=key=value | --annotation=key=value |
| PublishPort=59-60 | --publish=59-60 |
| UserNS=keep-id:uid=200,gid=210 | --userns keep-id:uid=200,gid=210 |
| Yaml=/tmp/kube.yaml | podman kube play /tmp/kube.yaml |
| **[Kube] options** | **podman kube play equivalent** |
| ----------------------------------- | -----------------------------------------------------------------|
| AutoUpdate=registry | --annotation "io.containers.autoupdate=registry" |
| ConfigMap=/tmp/config.map | --config-map /tmp/config.map |
| LogDriver=journald | --log-driver journald |
| Network=host | --net host |
| PodmanArgs=\-\-annotation=key=value | --annotation=key=value |
| PublishPort=59-60 | --publish=59-60 |
| SetWorkingDirectory=yaml | Set `WorkingDirectory` of unit file to location of the YAML file |
| UserNS=keep-id:uid=200,gid=210 | --userns keep-id:uid=200,gid=210 |
| Yaml=/tmp/kube.yaml | podman kube play /tmp/kube.yaml |

Supported keys in the `[Kube]` section are:

Expand Down Expand Up @@ -609,6 +610,16 @@ entry from the unit file takes precedence

This key can be listed multiple times.

### `SetWorkingDirectory=`

Set the `WorkingDirectory` field of the `Service` group of the Systemd service unit file.
Used to allow `podman kube play` to correctly resolve relative paths.
Supported values are `yaml` and `unit` to set the working directory to that of the YAML or Quadlet Unit file respectively.

Alternatively, users can explicitly set the `WorkingDirectory` field of the `Service` group in the `.kube` file.
Please note that if the `WorkingDirectory` field of the `Service` group is set,
Quadlet will not set it even if `SetWorkingDirectory` is set

### `Unmask=`

Specify the paths to unmask separated by a colon. unmask=ALL or /path/1:/path/2, or shell expanded paths (/proc/*):
Expand Down
47 changes: 47 additions & 0 deletions pkg/systemd/quadlet/quadlet.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ const (
XVolumeGroup = "X-Volume"
)

// Systemd Unit file keys
const (
ServiceKeyWorkingDirectory = "WorkingDirectory"
)

// All the supported quadlet keys
const (
KeyAddCapability = "AddCapability"
Expand Down Expand Up @@ -103,6 +108,7 @@ const (
KeySecurityLabelNested = "SecurityLabelNested"
KeySecurityLabelType = "SecurityLabelType"
KeySecret = "Secret"
KeySetWorkingDirectory = "SetWorkingDirectory"
KeySysctl = "Sysctl"
KeyTimezone = "Timezone"
KeyTmpfs = "Tmpfs"
Expand Down Expand Up @@ -226,6 +232,7 @@ var (
KeyRemapUID: true,
KeyRemapUIDSize: true,
KeyRemapUsers: true,
KeySetWorkingDirectory: true,
KeyUserNS: true,
KeyYaml: true,
}
Expand Down Expand Up @@ -1019,6 +1026,11 @@ func ConvertKube(kube *parser.UnitFile, names map[string]string, isUser bool) (*
execStop.add(yamlPath)
service.AddCmdline(ServiceGroup, "ExecStopPost", execStop.Args)

err = handleSetWorkingDirectory(kube, service)
if err != nil {
return nil, err
}

return service, nil
}

Expand Down Expand Up @@ -1288,3 +1300,38 @@ func handlePodmanArgs(unitFile *parser.UnitFile, groupName string, podman *Podma
podman.add(podmanArgs...)
}
}

func handleSetWorkingDirectory(kube, serviceUnitFile *parser.UnitFile) error {
// If WorkingDirectory is already set in the Service section do not change it
workingDir, ok := kube.Lookup(ServiceGroup, ServiceKeyWorkingDirectory)
if ok && len(workingDir) > 0 {
return nil
}

setWorkingDirectory, ok := kube.Lookup(KubeGroup, KeySetWorkingDirectory)
if !ok || len(setWorkingDirectory) == 0 {
return nil
}

var relativeToFile string
switch strings.ToLower(setWorkingDirectory) {
case "yaml":
relativeToFile, ok = kube.Lookup(KubeGroup, KeyYaml)
if !ok {
return fmt.Errorf("no Yaml key specified")
}
case "unit":
relativeToFile = kube.Path
default:
return fmt.Errorf("unsupported value for %s: %s ", ServiceKeyWorkingDirectory, setWorkingDirectory)
}

fileInWorkingDir, err := getAbsolutePath(kube, relativeToFile)
if err != nil {
return err
}

serviceUnitFile.Add(ServiceGroup, ServiceKeyWorkingDirectory, filepath.Dir(fileInWorkingDir))

return nil
}
8 changes: 8 additions & 0 deletions test/e2e/quadlet/workingdir-service.kube
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
## assert-key-is-regex "Service" "WorkingDirectory" "/etc/containers/systemd"

[Service]
WorkingDirectory=/etc/containers/systemd

[Kube]
Yaml=deployment.yml
SetWorkingDirectory=unit
5 changes: 5 additions & 0 deletions test/e2e/quadlet/workingdir-unit.kube
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## assert-key-is-regex "Service" "WorkingDirectory" ".*/podman_test.*/quadlet"

[Kube]
Yaml=deployment.yml
SetWorkingDirectory=unit
5 changes: 5 additions & 0 deletions test/e2e/quadlet/workingdir-yaml-abs.kube
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## assert-key-is "Service" "WorkingDirectory" "/etc/containers/systemd"

[Kube]
Yaml=/etc/containers/systemd/deployment.yml
SetWorkingDirectory=yaml
5 changes: 5 additions & 0 deletions test/e2e/quadlet/workingdir-yaml-rel.kube
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## assert-key-is-regex "Service" "WorkingDirectory" ".*/podman_test.*/quadlet/myservice"

[Kube]
Yaml=./myservice/deployment.yml
SetWorkingDirectory=yaml
4 changes: 4 additions & 0 deletions test/e2e/quadlet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,10 @@ BOGUS=foo
Entry("Kube - User Remap Auto", "remap-auto.kube", 0, ""),
Entry("Kube - User Remap Manual", "remap-manual.kube", 1, "converting \"remap-manual.kube\": RemapUsers=manual is not supported"),
Entry("Syslog Identifier", "syslog.identifier.kube", 0, ""),
Entry("Kube - Working Directory YAML Absolute Path", "workingdir-yaml-abs.kube", 0, ""),
Entry("Kube - Working Directory YAML Relative Path", "workingdir-yaml-rel.kube", 0, ""),
Entry("Kube - Working Directory Unit", "workingdir-unit.kube", 0, ""),
Entry("Kube - Working Directory already in Service", "workingdir-service.kube", 0, ""),

Entry("Network - Basic", "basic.network", 0, ""),
Entry("Network - Disable DNS", "disable-dns.network", 0, ""),
Expand Down
60 changes: 60 additions & 0 deletions test/system/252-quadlet.bats
Original file line number Diff line number Diff line change
Expand Up @@ -923,4 +923,64 @@ EOF
run_podman rmi $(pause_image)
}

@test "quadlet kube - Working Directory" {
yaml_source="$PODMAN_TMPDIR/basic_$(random_string).yaml"
local_path=local_path$(random_string)
pod_name=test_pod
container_name=test

cat >$yaml_source <<EOF
apiVersion: v1
kind: Pod
metadata:
labels:
app: test
name: $pod_name
spec:
containers:
- command:
- "sh"
args:
- "-c"
- "echo STARTED CONTAINER; top -b"
image: $IMAGE
name: $container_name
volumeMounts:
- mountPath: /test
name: test-volume
volumes:
- name: test-volume
hostPath:
# directory location on host
path: ./$local_path
# this field is optional
type: DirectoryOrCreate
EOF

# Create the Quadlet file
local quadlet_file=$PODMAN_TMPDIR/basic_$(random_string).kube
cat > $quadlet_file <<EOF
[Kube]
Yaml=${yaml_source}
SetWorkingDirectory=yaml
EOF

run_quadlet "$quadlet_file"
service_setup $QUADLET_SERVICE_NAME

# Ensure we have output.
wait_for_output "STARTED CONTAINER" $pod_name-$container_name

run_podman container inspect --format "{{.State.Status}}" $pod_name-$container_name
is "$output" "running" "container should be started by systemd and hence be running"

run_podman ps

run_podman exec $pod_name-$container_name /bin/sh -c "echo hello > /test/test.txt"
is $(cat $PODMAN_TMPDIR/$local_path/test.txt) "hello"

service_cleanup $QUADLET_SERVICE_NAME inactive
run_podman rmi $(pause_image)
}

# vim: filetype=sh

0 comments on commit d98978a

Please sign in to comment.