Add artifact quadlet unit type support

RFE: Add artifact quadlet unit type #25778

Signed-off-by: Odilon Sousa <osousa@redhat.com>
This commit is contained in:
Odilon Sousa
2025-09-23 14:58:09 -03:00
parent 1671029517
commit 34254cd1d0
11 changed files with 368 additions and 11 deletions

View File

@@ -396,6 +396,8 @@ func generateUnitsInfoMap(units []*parser.UnitFile) map[string]*quadlet.UnitInfo
// types), but still breaks the dependency cycle between .volume and .build ([Volume] can
// have Image=some.build, and [Build] can have Volume=some.volume:/some-volume)
resourceName = quadlet.GetBuiltImageName(unit)
case strings.HasSuffix(unit.Filename, ".artifact"):
serviceName = quadlet.GetArtifactServiceName(unit)
case strings.HasSuffix(unit.Filename, ".pod"):
containers = make([]string, 0)
// Prefill resouceNames for .pod files.
@@ -550,6 +552,9 @@ func process() bool {
service, err = quadlet.ConvertImage(unit, unitsInfoMap, isUserFlag)
case strings.HasSuffix(unit.Filename, ".build"):
service, warnings, err = quadlet.ConvertBuild(unit, unitsInfoMap, isUserFlag)
case strings.HasSuffix(unit.Filename, ".artifact"):
warnIfAmbiguousName(unit, quadlet.ArtifactGroup)
service, err = quadlet.ConvertArtifact(unit, unitsInfoMap, isUserFlag)
case strings.HasSuffix(unit.Filename, ".pod"):
service, warnings, err = quadlet.ConvertPod(unit, unit.Filename, unitsInfoMap, isUserFlag)
default:

View File

@@ -6,7 +6,7 @@ podman\-systemd.unit - systemd units using Podman Quadlet
## SYNOPSIS
*name*.container, *name*.volume, *name*.network, *name*.kube *name*.image, *name*.build *name*.pod
*name*.container, *name*.volume, *name*.network, *name*.kube *name*.image, *name*.build *name*.pod, *name*.artifact
### Podman rootful unit search path
@@ -48,7 +48,7 @@ the [Service] table and [Install] tables pass directly to systemd and are handle
See systemd.unit(5) man page for more information.
The Podman generator reads the search paths above and reads files with the extensions `.container`
`.volume`, `.network`, `.build`, `.pod` and `.kube`, and for each file generates a similarly named `.service` file. Be aware that
`.volume`, `.network`, `.build`, `.pod`, `.kube`, and `.artifact`, and for each file generates a similarly named `.service` file. Be aware that
existing vendor services (i.e., in `/usr/`) are replaced if they have the same name. The generated unit files can
be started and managed with `systemctl` like any other systemd service. `systemctl {--user} list-unit-files`
lists existing unit files on the system.
@@ -104,7 +104,7 @@ Quadlet requires the use of cgroup v2, use `podman info --format {{.Host.Cgroups
By default, the `Type` field of the `Service` section of the Quadlet file does not need to be set.
Quadlet will set it to `notify` for `.container` and `.kube` files,
`forking` for `.pod` files, and `oneshot` for `.volume`, `.network`, `.build`, and `.image` files.
`forking` for `.pod` files, and `oneshot` for `.volume`, `.network`, `.build`, `.image`, and `.artifact` files.
However, `Type` may be explicitly set to `oneshot` for `.container` and `.kube` files when no containers are expected
to run once `podman` exits.
@@ -2091,6 +2091,123 @@ Override the default architecture variant of the container image.
This is equivalent to the Podman `--variant` option.
## Artifact units [Artifact]
### WARNING: Experimental Unit
This unit is considered experimental and still in development. Inputs, options, and outputs are all subject to change.
Artifact units are named with a `.artifact` extension and contain a `[Artifact]` section describing
the container artifact pull command. The generated service is a one-time command that ensures that the artifact
exists on the host, pulling it if needed.
Using artifact units allows containers to depend on artifacts being automatically pulled. This is
particularly useful for managing artifacts that containers need to mount or access, the **Artifact** key is mandatory inside of the [Artifact] unit.
Valid options for `[Artifact]` are listed below:
| **[Artifact] options** | **podman artifact pull equivalent** |
|---------------------------------------------|--------------------------------------------------------|
| Artifact=quay\.io/foobar/artifact:special | podman artifact pull quay\.io/foobar/artifact:special |
| AuthFile=/etc/registry/auth\.json | --authfile=/etc/registry/auth\.json |
| CertDir=/etc/registry/certs | --cert-dir=/etc/registry/certs |
| ContainersConfModule=/etc/nvd\.conf | --module=/etc/nvd\.conf |
| Creds=username:password | --creds=username:password |
| DecryptionKey=/etc/registry\.key | --decryption-key=/etc/registry\.key |
| GlobalArgs=--log-level=debug | --log-level=debug |
| PodmanArgs=--pull never | --pull never |
| Quiet=true | --quiet |
| Retry=5 | --retry=5 |
| RetryDelay=10s | --retry-delay=10s |
| ServiceName=my-artifact | Set the systemd service name to my-artifact.service |
| TLSVerify=false | --tls-verify=false |
### `Artifact=`
The artifact to pull from a registry onto the local machine. This is the only required key for artifact units.
It is required to use a fully qualified artifact name rather than a short name, both for
performance and robustness reasons.
### `AuthFile=`
Path of the authentication file.
This is equivalent to the Podman `--authfile` option.
### `CertDir=`
Use certificates at path (*.crt, *.cert, *.key) to connect to the registry.
This is equivalent to the Podman `--cert-dir` option.
### `ContainersConfModule=`
Load the specified containers.conf(5) module. Equivalent to the Podman `--module` option.
This key can be listed multiple times.
### `Creds=`
The credentials to use when contacting the registry in the format `[username[:password]]`.
This is equivalent to the Podman `--creds` option.
### `DecryptionKey=`
The `[key[:passphrase]]` to be used for decryption of artifacts.
This is equivalent to the Podman `--decryption-key` option.
### `GlobalArgs=`
This key contains a list of arguments passed directly between `podman` and `artifact`
in the generated file. It can be used to access Podman features otherwise unsupported by the generator. Since the generator is unaware
of what unexpected interactions can be caused by these arguments, it is not recommended to use
this option.
The format of this is a space separated list of arguments, which can optionally be individually
escaped to allow inclusion of whitespace and other control characters.
This key can be listed multiple times.
### `PodmanArgs=`
This key contains a list of arguments passed directly to the end of the `podman artifact pull` command
in the generated file (right before the artifact name in the command line). It can be used to
access Podman features otherwise unsupported by the generator. Since the generator is unaware
of what unexpected interactions can be caused by these arguments, it is not recommended to use
this option.
The format of this is a space separated list of arguments, which can optionally be individually
escaped to allow inclusion of whitespace and other control characters.
This key can be listed multiple times.
### `Quiet=`
Suppress output information when pulling artifacts.
This is equivalent to the Podman `--quiet` option.
### `Retry=`
Number of times to retry the artifact pull when a HTTP error occurs. Equivalent to the Podman `--retry` option.
### `RetryDelay=`
Delay between retries. Equivalent to the Podman `--retry-delay` option.
### `ServiceName=`
The (optional) name of the systemd service. If this is not specified, the default value is the same name as the unit, but with a `-artifact` suffix, i.e. a `$name.artifact` file creates a `$name-artifact.service` systemd service.
### `TLSVerify=`
Require HTTPS and verification of certificates when contacting registries.
This is equivalent to the Podman `--tls-verify` option.
## Quadlet section [Quadlet]
Some quadlet specific configuration is shared between different unit types. Those settings
can be configured in the `[Quadlet]` section.
@@ -2195,6 +2312,29 @@ IPRange=172.16.0.0/28
Label=org.test.Key=value
```
Example `test.artifact` to only pull the artifact using one auth file:
```
[Artifact]
Artifact=quay.io/example/my-artifact:latest
AuthFile=/etc/registry/auth.json
TLSVerify=false
```
Example usage where a container depends on an artifact:
`my-artifact.artifact`:
```
[Artifact]
Artifact=quay.io/example/my-config:latest
```
`my-app.container`:
```
[Container]
Image=quay.io/example/my-app:latest
Mount=type=artifact,source=my-artifact.artifact,destination=/etc/config
```
Example for Container in a Pod:
`test.pod`

View File

@@ -27,6 +27,7 @@ const (
UnitDirDistro = "/usr/share/containers/systemd"
// Names of commonly used systemd/quadlet group names
ArtifactGroup = "Artifact"
ContainerGroup = "Container"
InstallGroup = "Install"
KubeGroup = "Kube"
@@ -38,6 +39,7 @@ const (
ImageGroup = "Image"
BuildGroup = "Build"
QuadletGroup = "Quadlet"
XArtifactGroup = "X-Artifact"
XContainerGroup = "X-Container"
XKubeGroup = "X-Kube"
XNetworkGroup = "X-Network"
@@ -61,6 +63,7 @@ const (
KeyAllTags = "AllTags"
KeyAnnotation = "Annotation"
KeyArch = "Arch"
KeyArtifact = "Artifact"
KeyAuthFile = "AuthFile"
KeyAutoUpdate = "AutoUpdate"
KeyCertDir = "CertDir"
@@ -141,6 +144,7 @@ const (
KeyPolicy = "Policy"
KeyPublishPort = "PublishPort"
KeyPull = "Pull"
KeyQuiet = "Quiet"
KeyReadOnly = "ReadOnly"
KeyReadOnlyTmpfs = "ReadOnlyTmpfs"
KeyReloadCmd = "ReloadCmd"
@@ -458,6 +462,25 @@ var (
KeyVolume: true,
},
},
ArtifactGroup: {
GroupName: ArtifactGroup,
XGroupName: XArtifactGroup,
SupportedKeys: map[string]bool{
KeyArtifact: true,
KeyAuthFile: true,
KeyCertDir: true,
KeyContainersConfModule: true,
KeyCreds: true,
KeyDecryptionKey: true,
KeyGlobalArgs: true,
KeyPodmanArgs: true,
KeyQuiet: true,
KeyRetry: true,
KeyRetryDelay: true,
KeyServiceName: true,
KeyTLSVerify: true,
},
},
PodGroup: {
GroupName: PodGroup,
XGroupName: XPodGroup,
@@ -1464,6 +1487,8 @@ func GetUnitServiceName(unit *parser.UnitFile) (string, error) {
return GetImageServiceName(unit), nil
case strings.HasSuffix(unit.Filename, ".build"):
return GetBuildServiceName(unit), nil
case strings.HasSuffix(unit.Filename, ".artifact"):
return GetArtifactServiceName(unit), nil
case strings.HasSuffix(unit.Filename, ".pod"):
return GetPodServiceName(unit), nil
default:
@@ -1495,6 +1520,10 @@ func GetBuildServiceName(podUnit *parser.UnitFile) string {
return getServiceName(podUnit, BuildGroup, "-build")
}
func GetArtifactServiceName(podUnit *parser.UnitFile) string {
return getServiceName(podUnit, ArtifactGroup, "-artifact")
}
func GetPodServiceName(podUnit *parser.UnitFile) string {
return getServiceName(podUnit, PodGroup, "-pod")
}
@@ -1871,7 +1900,7 @@ func handleStorageSource(quadletUnitFile, serviceUnitFile *parser.UnitFile, sour
if source[0] == '/' {
// Absolute path
serviceUnitFile.Add(UnitGroup, "RequiresMountsFor", source)
} else if strings.HasSuffix(source, ".volume") || (checkImage && strings.HasSuffix(source, ".image")) {
} else if strings.HasSuffix(source, ".volume") || (checkImage && strings.HasSuffix(source, ".image")) || strings.HasSuffix(source, ".artifact") {
sourceUnitInfo, ok := unitsInfoMap[source]
if !ok {
return "", fmt.Errorf("requested Quadlet source %s was not found", source)
@@ -2040,10 +2069,11 @@ func resolveContainerMountParams(containerUnitFile, serviceUnitFile *parser.Unit
// Source resolution is required only for these types of mounts
sourceResultionRequired := map[string]struct{}{
"volume": {},
"bind": {},
"glob": {},
"image": {},
"volume": {},
"bind": {},
"glob": {},
"image": {},
"artifact": {},
}
if _, ok := sourceResultionRequired[mountType]; !ok {
return mount, nil
@@ -2297,3 +2327,47 @@ func initServiceUnitFile(quadletUnitFile *parser.UnitFile, isUser bool, unitsInf
return service, unitInfo, nil
}
func ConvertArtifact(artifact *parser.UnitFile, unitsInfoMap map[string]*UnitInfo, isUser bool) (*parser.UnitFile, error) {
service, unitInfo, err := initServiceUnitFile(artifact, isUser, unitsInfoMap, ArtifactGroup)
if err != nil {
return nil, err
}
artifactName, ok := artifact.Lookup(ArtifactGroup, KeyArtifact)
if !ok || len(artifactName) == 0 {
return nil, fmt.Errorf("no Artifact key specified")
}
podman := createBasePodmanCommand(artifact, ArtifactGroup)
podman.add("artifact", "pull")
stringKeys := map[string]string{
KeyAuthFile: "--authfile",
KeyCertDir: "--cert-dir",
KeyCreds: "--creds",
KeyDecryptionKey: "--decryption-key",
KeyRetry: "--retry",
KeyRetryDelay: "--retry-delay",
}
lookupAndAddString(artifact, ArtifactGroup, stringKeys, podman)
boolKeys := map[string]string{
KeyQuiet: "--quiet",
KeyTLSVerify: "--tls-verify",
}
lookupAndAddBoolean(artifact, ArtifactGroup, boolKeys, podman)
handlePodmanArgs(artifact, ArtifactGroup, podman)
podman.add(artifactName)
service.AddCmdline(ServiceGroup, "ExecStart", podman.Args)
defaultOneshotServiceGroup(service, true)
unitInfo.ResourceName = artifactName
return service, nil
}

View File

@@ -4,6 +4,7 @@ var (
// Key: Extension
// Value: Processing order for resource naming dependencies
SupportedExtensions = map[string]int{
".artifact": 1,
".container": 4,
".volume": 2,
".kube": 4,

View File

@@ -0,0 +1,24 @@
## assert-podman-final-args localhost/imagename
## assert-podman-args "--name" "systemd-%N"
## assert-podman-args "--mount"
## assert-podman-args "type=artifact,source=quay.io/libpod/testartifact:20250206-single,destination=/artifacts"
## assert-podman-args "--rm"
## assert-podman-args "--replace"
## assert-podman-args "-d"
## assert-podman-args "--cgroups=split"
## assert-podman-args "--sdnotify=conmon"
## assert-key-is "Unit" "RequiresMountsFor" "%t/containers"
## assert-key-is "Service" "KillMode" "mixed"
## assert-key-is "Service" "Delegate" "yes"
## assert-key-is "Service" "Type" "notify"
## assert-key-is "Service" "NotifyAccess" "all"
## assert-key-is "Service" "SyslogIdentifier" "%N"
## assert-key-is-regex "Service" "ExecStopPost" "-[/S].*/podman rm -v -f -i systemd-%N"
## assert-key-is-regex "Service" "ExecStop" ".*/podman rm -v -f -i systemd-%N"
## assert-key-is "Service" "Environment" "PODMAN_SYSTEMD_UNIT=%n"
## assert-key-is-regex "Unit" "After" "network-online.target|podman-user-wait-network-online.service"
## assert-key-is-regex "Unit" "Wants" "network-online.target|podman-user-wait-network-online.service"
[Container]
Image=localhost/imagename
Mount=type=artifact,source=quay.io/libpod/testartifact:20250206-single,destination=/artifacts

View File

@@ -0,0 +1,10 @@
## assert-podman-final-args quay.io/libpod/testartifact:20250206-single
## assert-podman-args "artifact"
## assert-podman-args "pull"
## assert-key-is "Service" "Type" "oneshot"
## assert-key-is "Service" "RemainAfterExit" "yes"
## assert-key-is-regex "Unit" "After" "network-online.target|podman-user-wait-network-online.service"
## assert-key-is-regex "Unit" "Wants" "network-online.target|podman-user-wait-network-online.service"
[Artifact]
Artifact=quay.io/libpod/testartifact:20250206-single

View File

@@ -9,8 +9,6 @@ Mount=type=bind,src=/path/on/host,dst=/path/in/container,relabel=shared,U=true
## assert-podman-args-key-val "--mount" "," "type=volume,source=vol1,destination=/path/in/container,ro=true"
Mount=type=volume,source=vol1,destination=/path/in/container,ro=true
## assert-podman-args-key-val "--mount" "," "type=volume,source=systemd-basic,destination=/path/in/container,ro=true"
## assert-key-is "Unit" "Requires" "basic-volume.service" "basic-image.service"
## assert-key-is-regex "Unit" "After" "network-online.target|podman-user-wait-network-online.service" "basic-volume.service" "basic-image.service"
Mount=type=volume,source=basic.volume,destination=/path/in/container,ro=true
## assert-podman-args-key-val "--mount" "," "type=tmpfs,tmpfs-size=512M,destination=/path/in/container"
Mount=type=tmpfs,tmpfs-size=512M,destination=/path/in/container
@@ -18,6 +16,8 @@ Mount=type=tmpfs,tmpfs-size=512M,destination=/path/in/container
Mount=type=image,source=fedora,destination=/fedora-image,rw=true
## assert-podman-args-key-val "--mount" "," "type=image,source=localhost/imagename,destination=/fedora-image,rw=true"
Mount=type=image,source=basic.image,destination=/fedora-image,rw=true
## assert-podman-args-key-val "--mount" "," "type=artifact,source=quay.io/libpod/testartifact:20250206-single,destination=/artifacts"
Mount=type=artifact,source=basic.artifact,destination=/artifacts
## assert-podman-args-key-val "--mount" "," "type=devpts,destination=/dev/pts"
Mount=type=devpts,destination=/dev/pts
## assert-podman-args-key-val-regex "--mount" "," "type=bind,source=.*/podman-e2e-.*/subtest-.*/quadlet/path/on/host,destination=/path/in/container"
@@ -28,3 +28,5 @@ Mount=type=volume,source=vol1,destination=/path/in/container,ro
Mount=type=bind,src=/tmp,\"dst=/path,1\"
## assert-podman-args-key-val-regex "--mount" "," "type=bind,source=.*/podman-e2e-.*/subtest-.*/quadlet/src,destination=/dst/,idmap=uids=12-34-1;gids=56-78-1"
Mount=type=bind,source=./src/,destination=/dst/,idmap=uids=12-34-1;gids=56-78-1
## assert-key-is "Unit" "Requires" "basic-volume.service" "basic-image.service" "basic-artifact.service"
## assert-key-is-regex "Unit" "After" "network-online.target|podman-user-wait-network-online.service" "basic-volume.service" "basic-image.service" "basic-artifact.service"

View File

@@ -0,0 +1,23 @@
## assert-podman-final-args quay.io/libpod/testartifact:20250206-single
## assert-podman-args "artifact"
## assert-podman-args "pull"
## assert-podman-args "--authfile"
## assert-podman-args "/tmp/auth.json"
## assert-podman-args "--cert-dir"
## assert-podman-args "/tmp/certs"
## assert-podman-args "--quiet"
## assert-podman-args "--retry"
## assert-podman-args "3"
## assert-podman-args "--tls-verify=false"
## assert-key-is "Service" "Type" "oneshot"
## assert-key-is "Service" "RemainAfterExit" "yes"
## assert-key-is-regex "Unit" "After" "network-online.target|podman-user-wait-network-online.service"
## assert-key-is-regex "Unit" "Wants" "network-online.target|podman-user-wait-network-online.service"
[Artifact]
Artifact=quay.io/libpod/testartifact:20250206-single
AuthFile=/tmp/auth.json
CertDir=/tmp/certs
Quiet=true
Retry=3
TLSVerify=false

View File

@@ -51,6 +51,8 @@ func calcServiceName(path string) string {
service += "-image"
case ".build":
service += "-build"
case ".artifact":
service += "-artifact"
case ".pod":
service += "-pod"
}
@@ -1076,6 +1078,9 @@ BOGUS=foo
Entry("Build - Retry", "retry.build"),
Entry("Build - No WorkingDirectory with systemd specifier", "no-workingdirectory-systemd-specifier.build"),
Entry("Artifact - Basic", "basic.artifact"),
Entry("Artifact - Options", "options.artifact"),
Entry("Pod - Basic", "basic.pod"),
Entry("Pod - DNS", "dns.pod"),
Entry("Pod - DNS Option", "dns-option.pod"),
@@ -1171,13 +1176,14 @@ BOGUS=foo
runSuccessQuadletTestCase(fileName)
},
Entry("Container - Mount", "mount.container", []string{"basic.image", "basic.volume"}),
Entry("Container - Mount", "mount.container", []string{"basic.image", "basic.volume", "basic.artifact"}),
Entry("Container - Quadlet Network", "network.quadlet.container", []string{"basic.network"}),
Entry("Container - Quadlet Volume", "volume.container", []string{"basic.volume"}),
Entry("Container - Mount overriding service name", "mount.servicename.container", []string{"service-name.volume"}),
Entry("Container - Quadlet Network overriding service name", "network.quadlet.servicename.container", []string{"service-name.network"}),
Entry("Container - Quadlet Volume overriding service name", "volume.servicename.container", []string{"service-name.volume"}),
Entry("Container - Quadlet build with multiple tags", "build.multiple-tags.container", []string{"multiple-tags.build"}),
Entry("Container - Artifact Mount", "artifact-mount.container", []string{"basic.artifact"}),
Entry("Container - Reuse another container's network", "network.reuse.container", []string{"basic.container"}),
Entry("Container - Reuse another named container's network", "network.reuse.name.container", []string{"name.container"}),
Entry("Container - Reuse another container's network", "a.network.reuse.container", []string{"basic.container"}),
@@ -1186,6 +1192,7 @@ BOGUS=foo
"Container - Dependency between quadlet units",
"dependent.container",
[]string{
"basic.artifact",
"basic.build",
"basic.container",
"basic.image",
@@ -1239,6 +1246,7 @@ BOGUS=foo
"Build - Dependency between quadlet units",
"dependent.build",
[]string{
"basic.artifact",
"basic.build",
"basic.container",
"basic.image",
@@ -1258,6 +1266,7 @@ BOGUS=foo
"Pod - Dependency between quadlet units",
"dependent.pod",
[]string{
"basic.artifact",
"basic.build",
"basic.container",
"basic.image",
@@ -1272,6 +1281,7 @@ BOGUS=foo
"Image - Dependency between quadlet units",
"dependent.image",
[]string{
"basic.artifact",
"basic.build",
"basic.container",
"basic.image",
@@ -1286,6 +1296,7 @@ BOGUS=foo
"Network - Dependency between quadlet units",
"dependent.network",
[]string{
"basic.artifact",
"basic.build",
"basic.container",
"basic.image",

View File

@@ -1856,6 +1856,71 @@ EOF
done < <(parse_table "${dropin_files}")
}
@test "quadlet - artifact" {
local quadlet_tmpdir=$PODMAN_TMPDIR/quadlets
local registry=localhost:${PODMAN_LOGIN_REGISTRY_PORT}
local artifact_for_test=$registry/test-artifact:$(random_string)
local authfile=$PODMAN_TMPDIR/authfile.json
# Create a test artifact file
local test_artifact_dir=$PODMAN_TMPDIR/test-artifact
mkdir -p $test_artifact_dir
echo "test artifact content $(random_string)" > $test_artifact_dir/test-file.txt
# In order to test artifact pull but without possible Network issues,
# this test uses an additional registry.
# Start the registry and populate the authfile that we can use for the test.
start_registry
run_podman login --authfile=$authfile \
--tls-verify=false \
--username ${PODMAN_LOGIN_USER} \
--password ${PODMAN_LOGIN_PASS} \
$registry
# Create and push a test artifact to the registry
run_podman artifact add $artifact_for_test $test_artifact_dir/test-file.txt
run_podman artifact push --tls-verify=false --authfile=$authfile $artifact_for_test
# Remove the local artifact to make sure it will be pulled again
run_podman artifact rm $artifact_for_test
# Create artifact quadlet file
local artifact_file=$PODMAN_TMPDIR/test-artifact.artifact
cat >$artifact_file << EOF
[Artifact]
Artifact=$artifact_for_test
AuthFile=$authfile
TLSVerify=false
EOF
run_quadlet "$artifact_file"
service_setup $QUADLET_SERVICE_NAME
# Wait for the service to complete (it's a oneshot service)
local timeout=30
local count=0
while [ $count -lt $timeout ]; do
run systemctl show --value --property=ActiveState "$QUADLET_SERVICE_NAME"
if [ "$output" = "active" ]; then
break
fi
sleep 1
count=$((count + 1))
done
# Verify artifact was pulled
run_podman artifact ls
assert $status -eq 0 "Failed to list artifacts"
# Extract the repository and tag parts separately since artifact ls shows them in columns
local artifact_repo=$(echo "$artifact_for_test" | cut -d: -f1)
local artifact_tag=$(echo "$artifact_for_test" | cut -d: -f2)
assert "$output" =~ "$artifact_repo.*$artifact_tag" "Artifact should exist after quadlet service runs"
# Clean up
run_podman artifact rm $artifact_for_test
}
# Following issue: https://github.com/containers/podman/issues/24599
# Make sure future changes do not break
@test "quadlet - build with pull" {

View File

@@ -126,6 +126,8 @@ quadlet_to_service_name() {
suffix="-pod"
elif [ "$extension" == "build" ]; then
suffix="-build"
elif [ "$extension" == "artifact" ]; then
suffix="-artifact"
fi
echo "$filename$suffix.service"