Skip to content

Commit 6a7b9ff

Browse files
committed
Implement artifact validation during container creation and add validation utility
Signed-off-by: MayorFaj <[email protected]>
1 parent 1e70e14 commit 6a7b9ff

File tree

3 files changed

+65
-39
lines changed

3 files changed

+65
-39
lines changed

libpod/container_internal_common.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,19 @@ func (c *Container) generateSpec(ctx context.Context) (s *spec.Spec, cleanupFunc
544544
}
545545

546546
if len(c.config.ArtifactVolumes) > 0 {
547+
// Validate all artifacts exist before attempting to mount
548+
mounts := make([]ArtifactMountValidation, len(c.config.ArtifactVolumes))
549+
for i, av := range c.config.ArtifactVolumes {
550+
mounts[i] = ArtifactMountValidation{
551+
Source: av.Source,
552+
Title: av.Title,
553+
Digest: av.Digest,
554+
}
555+
}
556+
if err := c.runtime.ValidateArtifactMounts(ctx, mounts); err != nil {
557+
return nil, nil, err
558+
}
559+
547560
artStore, err := c.runtime.ArtifactStore()
548561
if err != nil {
549562
return nil, nil, err
@@ -3167,3 +3180,37 @@ func maybeClampOOMScoreAdj(oomScoreValue int) (int, error) {
31673180
}
31683181
return oomScoreValue, nil
31693182
}
3183+
3184+
// ValidateArtifactMounts checks that all artifact mounts are valid by verifying
3185+
// the artifacts exist and can be accessed. This is used during both container
3186+
// creation and start to provide early validation.
3187+
func (r *Runtime) ValidateArtifactMounts(ctx context.Context, mounts []ArtifactMountValidation) error {
3188+
if len(mounts) == 0 {
3189+
return nil
3190+
}
3191+
3192+
artStore, err := r.ArtifactStore()
3193+
if err != nil {
3194+
return fmt.Errorf("accessing artifact store: %w", err)
3195+
}
3196+
3197+
for _, mount := range mounts {
3198+
asr, err := store.NewArtifactStorageReference(mount.Source)
3199+
if err != nil {
3200+
return fmt.Errorf("invalid artifact reference %q: %w", mount.Source, err)
3201+
}
3202+
3203+
// Validate artifact exists by attempting to resolve its blob mount paths
3204+
_, err = artStore.BlobMountPaths(ctx, asr, &libartTypes.BlobMountPathOptions{
3205+
FilterBlobOptions: libartTypes.FilterBlobOptions{
3206+
Title: mount.Title,
3207+
Digest: mount.Digest,
3208+
},
3209+
})
3210+
if err != nil {
3211+
return fmt.Errorf("validating artifact %q: %w", mount.Source, err)
3212+
}
3213+
}
3214+
3215+
return nil
3216+
}

libpod/runtime.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,15 @@ import (
4747
"go.podman.io/storage/pkg/unshare"
4848
)
4949

50+
// ArtifactMountValidation contains the minimal information needed to validate
51+
// an artifact mount without requiring the full ContainerArtifactVolume structure.
52+
// This type is used to pass validation data to Runtime.ValidateArtifactMounts.
53+
type ArtifactMountValidation struct {
54+
Source string
55+
Title string
56+
Digest string
57+
}
58+
5059
// Set up the JSON library for all of Libpod
5160
var json = jsoniter.ConfigCompatibleWithStandardLibrary
5261

pkg/specgen/generate/container_create.go

Lines changed: 9 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ 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"
2927
"tags.cncf.io/container-device-interface/pkg/parser"
3028
)
3129

@@ -512,7 +510,15 @@ func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen.
512510

513511
if len(s.ArtifactVolumes) != 0 {
514512
// Validate artifacts exist before creating the container
515-
if err := validateArtifactVolumes(ctx, rt, s.ArtifactVolumes); err != nil {
513+
mounts := make([]libpod.ArtifactMountValidation, len(s.ArtifactVolumes))
514+
for i, av := range s.ArtifactVolumes {
515+
mounts[i] = libpod.ArtifactMountValidation{
516+
Source: av.Source,
517+
Title: av.Title,
518+
Digest: av.Digest,
519+
}
520+
}
521+
if err := rt.ValidateArtifactMounts(ctx, mounts); err != nil {
516522
return nil, err
517523
}
518524

@@ -762,39 +768,3 @@ func Inherit(infra *libpod.Container, s *specgen.SpecGenerator, rt *libpod.Runti
762768
}
763769
return options, infraSpec, compatibleOptions, nil
764770
}
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

Comments
 (0)