Skip to content

Commit c9cce5f

Browse files
committed
Add artifact validation during container creation and enhance tests for non-existent artifacts
1 parent 23306d1 commit c9cce5f

File tree

2 files changed

+92
-0
lines changed

2 files changed

+92
-0
lines changed

pkg/specgen/generate/container_create.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"go.podman.io/common/libimage"
2525
"go.podman.io/common/libnetwork/pasta"
2626
"go.podman.io/common/libnetwork/slirp4netns"
27+
"go.podman.io/common/pkg/libartifact/store"
2728
"tags.cncf.io/container-device-interface/pkg/parser"
2829
)
2930

@@ -509,6 +510,11 @@ func createContainerOptions(rt *libpod.Runtime, s *specgen.SpecGenerator, pod *l
509510
}
510511

511512
if len(s.ArtifactVolumes) != 0 {
513+
// Validate artifacts exist before creating the container
514+
if err := validateArtifactVolumes(ctx, rt, s.ArtifactVolumes); err != nil {
515+
return nil, nil, nil, err
516+
}
517+
512518
vols := make([]*libpod.ContainerArtifactVolume, 0, len(s.ArtifactVolumes))
513519
for _, v := range s.ArtifactVolumes {
514520
vols = append(vols, &libpod.ContainerArtifactVolume{
@@ -755,3 +761,39 @@ func Inherit(infra *libpod.Container, s *specgen.SpecGenerator, rt *libpod.Runti
755761
}
756762
return options, infraSpec, compatibleOptions, nil
757763
}
764+
765+
// validateArtifactVolumes checks that all artifacts exist and are accessible
766+
// at container creation time, preventing creation of containers that can never start.
767+
func validateArtifactVolumes(ctx context.Context, rt *libpod.Runtime, artifactVolumes []*specgen.ArtifactVolume) error {
768+
if len(artifactVolumes) == 0 {
769+
return nil
770+
}
771+
772+
artStore, err := rt.ArtifactStore()
773+
if err != nil {
774+
return fmt.Errorf("accessing artifact store: %w", err)
775+
}
776+
777+
for _, artifactMount := range artifactVolumes {
778+
// Use the same artifact store resolution logic as at start time
779+
// to ensure consistent validation behavior
780+
asr, err := artStore.NewArtifactStorageReference(artifactMount.Source)
781+
if err != nil {
782+
return fmt.Errorf("invalid artifact reference %q: %w", artifactMount.Source, err)
783+
}
784+
785+
// Validate artifact exists using the same logic as container start.
786+
// This ensures consistent behavior between creation and start time.
787+
_ /*paths*/, err = artStore.BlobMountPaths(ctx, asr, &store.BlobMountPathOptions{
788+
FilterBlobOptions: store.FilterBlobOptions{
789+
Title: artifactMount.Title,
790+
Digest: artifactMount.Digest,
791+
},
792+
})
793+
if err != nil {
794+
return fmt.Errorf("validating artifact %q: %w", artifactMount.Source, err)
795+
}
796+
}
797+
798+
return nil
799+
}

test/e2e/artifact_mount_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,4 +245,54 @@ var _ = Describe("Podman artifact mount", func() {
245245
Expect(session).To(ExitWithError(125, "/test: duplicate mount destination"))
246246
}
247247
})
248+
249+
It("podman create should fail with non-existent artifact", func() {
250+
// Verify that creating a container with a non-existent artifact fails at creation time
251+
cmd := []string{
252+
"create",
253+
"--name", "test-nonexistent",
254+
"--mount", "type=artifact,source=nonexistent-artifact,destination=/data",
255+
ALPINE,
256+
"echo", "hello",
257+
}
258+
session := podmanTest.Podman(cmd)
259+
session.WaitWithDefaultTimeout()
260+
Expect(session).Should(Exit(125))
261+
// Verify error comes from our validation code
262+
Expect(session.ErrorToString()).To(SatisfyAll(
263+
ContainSubstring("validating artifact"),
264+
ContainSubstring("nonexistent-artifact"),
265+
))
266+
267+
// Ensure container was not created
268+
rmSession := podmanTest.Podman([]string{"rm", "test-nonexistent"})
269+
rmSession.WaitWithDefaultTimeout()
270+
Expect(rmSession).Should(Exit(1))
271+
Expect(rmSession.ErrorToString()).To(ContainSubstring("no such container"))
272+
})
273+
274+
It("podman run should fail with non-existent artifact", func() {
275+
// Verify that running a container with a non-existent artifact fails at creation time
276+
cmd := []string{
277+
"run",
278+
"--name", "test-run-nonexistent",
279+
"--mount", "type=artifact,source=invalid-artifact-ref,destination=/test",
280+
ALPINE,
281+
"echo", "hello",
282+
}
283+
session := podmanTest.Podman(cmd)
284+
session.WaitWithDefaultTimeout()
285+
Expect(session).Should(Exit(125))
286+
// Verify error comes from our validation code
287+
Expect(session.ErrorToString()).To(SatisfyAll(
288+
ContainSubstring("validating artifact"),
289+
ContainSubstring("invalid-artifact-ref"),
290+
))
291+
292+
// Ensure container was not created
293+
psSession := podmanTest.Podman([]string{"ps", "-a", "--filter", "name=test-run-nonexistent"})
294+
psSession.WaitWithDefaultTimeout()
295+
Expect(psSession).Should(Exit(0))
296+
Expect(psSession.OutputToString()).ToNot(ContainSubstring("test-run-nonexistent"))
297+
})
248298
})

0 commit comments

Comments
 (0)