@@ -24,6 +24,8 @@ 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"
28+ libartTypes "go.podman.io/common/pkg/libartifact/types"
2729 "tags.cncf.io/container-device-interface/pkg/parser"
2830)
2931
@@ -233,7 +235,7 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
233235 command := makeCommand (s , imageData )
234236
235237 infraVol := len (compatibleOptions .Mounts ) > 0 || len (compatibleOptions .Volumes ) > 0 || len (compatibleOptions .ImageVolumes ) > 0 || len (compatibleOptions .OverlayVolumes ) > 0
236- opts , err := createContainerOptions (rt , s , pod , finalVolumes , finalOverlays , imageData , command , infraVol , * compatibleOptions )
238+ opts , err := createContainerOptions (ctx , rt , s , pod , finalVolumes , finalOverlays , imageData , command , infraVol , * compatibleOptions )
237239 if err != nil {
238240 return nil , nil , nil , err
239241 }
@@ -351,7 +353,7 @@ func isCDIDevice(device string) bool {
351353 return parser .IsQualifiedName (device )
352354}
353355
354- func createContainerOptions (rt * libpod.Runtime , s * specgen.SpecGenerator , pod * libpod.Pod , volumes []* specgen.NamedVolume , overlays []* specgen.OverlayVolume , imageData * libimage.ImageData , command []string , infraVolumes bool , compatibleOptions libpod.InfraInherit ) ([]libpod.CtrCreateOption , error ) {
356+ func createContainerOptions (ctx context. Context , rt * libpod.Runtime , s * specgen.SpecGenerator , pod * libpod.Pod , volumes []* specgen.NamedVolume , overlays []* specgen.OverlayVolume , imageData * libimage.ImageData , command []string , infraVolumes bool , compatibleOptions libpod.InfraInherit ) ([]libpod.CtrCreateOption , error ) {
355357 var options []libpod.CtrCreateOption
356358 var err error
357359
@@ -509,6 +511,11 @@ func createContainerOptions(rt *libpod.Runtime, s *specgen.SpecGenerator, pod *l
509511 }
510512
511513 if len (s .ArtifactVolumes ) != 0 {
514+ // Validate artifacts exist before creating the container
515+ if err := validateArtifactVolumes (ctx , rt , s .ArtifactVolumes ); err != nil {
516+ return nil , err
517+ }
518+
512519 vols := make ([]* libpod.ContainerArtifactVolume , 0 , len (s .ArtifactVolumes ))
513520 for _ , v := range s .ArtifactVolumes {
514521 vols = append (vols , & libpod.ContainerArtifactVolume {
@@ -755,3 +762,39 @@ func Inherit(infra *libpod.Container, s *specgen.SpecGenerator, rt *libpod.Runti
755762 }
756763 return options , infraSpec , compatibleOptions , nil
757764}
765+
766+ // validateArtifactVolumes checks that all artifacts exist and are accessible
767+ // at container creation time, preventing creation of containers that can never start.
768+ func validateArtifactVolumes (ctx context.Context , rt * libpod.Runtime , artifactVolumes []* specgen.ArtifactVolume ) error {
769+ if len (artifactVolumes ) == 0 {
770+ return nil
771+ }
772+
773+ artStore , err := rt .ArtifactStore ()
774+ if err != nil {
775+ return fmt .Errorf ("accessing artifact store: %w" , err )
776+ }
777+
778+ for _ , artifactMount := range artifactVolumes {
779+ // Use the same artifact store resolution logic as at start time
780+ // to ensure consistent validation behavior
781+ asr , err := store .NewArtifactStorageReference (artifactMount .Source )
782+ if err != nil {
783+ return fmt .Errorf ("invalid artifact reference %q: %w" , artifactMount .Source , err )
784+ }
785+
786+ // Validate artifact exists using the same logic as container start.
787+ // This ensures consistent behavior between creation and start time.
788+ _ /*paths*/ , err = artStore .BlobMountPaths (ctx , asr , & libartTypes.BlobMountPathOptions {
789+ FilterBlobOptions : libartTypes.FilterBlobOptions {
790+ Title : artifactMount .Title ,
791+ Digest : artifactMount .Digest ,
792+ },
793+ })
794+ if err != nil {
795+ return fmt .Errorf ("validating artifact %q: %w" , artifactMount .Source , err )
796+ }
797+ }
798+
799+ return nil
800+ }
0 commit comments