Skip to content

Commit 5713383

Browse files
authored
Merge pull request #6760 from BenjaminSchubert/bschubert/add-follow-symlink
Add a FollowSymlink option to AddAndCopyOptions to allow disabling deference of symlinks
2 parents 64db27a + 140edb4 commit 5713383

5 files changed

Lines changed: 112 additions & 20 deletions

File tree

add.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@ type AddAndCopyOptions struct {
122122
// AllowEmptyWildcard controls whether the operation succeeds when all
123123
// glob patterns match nothing. Defaults to false.
124124
AllowEmptyWildcard types.OptionalBool
125+
// FollowSymlink controls whether symlinks should be followed when copying content.
126+
// When set to false, symlinks are not dereferenced.
127+
FollowSymlink types.OptionalBool
125128
}
126129

127130
// getURL writes a tar archive containing the named content
@@ -615,6 +618,7 @@ func (b *Builder) Add(destination string, extract bool, options AddAndCopyOption
615618
ChownFiles: chownFiles,
616619
ChmodFiles: chmodDirsFiles,
617620
KeepDirectoryNames: options.DirCopyContents == types.OptionalBoolFalse,
621+
NoDerefSymlinks: options.FollowSymlink == types.OptionalBoolFalse,
618622
StripSetuidBit: options.StripSetuidBit,
619623
StripSetgidBit: options.StripSetgidBit,
620624
StripStickyBit: options.StripStickyBit,
@@ -790,6 +794,7 @@ func (b *Builder) Add(destination string, extract bool, options AddAndCopyOption
790794
Timestamp: options.Timestamp,
791795
DisallowWildcard: options.AllowWildcard == types.OptionalBoolFalse,
792796
AllowEmptyWildcard: options.AllowEmptyWildcard == types.OptionalBoolTrue,
797+
NoDerefSymlinks: options.FollowSymlink == types.OptionalBoolFalse,
793798
}
794799
getErr = copier.Get(contextDir, contextDir, getOptions, []string{globbedToGlobbable(globbed)}, writer)
795800
closeErr = writer.Close()

cmd/buildah/addcopy.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ type addCopyResults struct {
4545
link bool
4646
allowWildcard bool
4747
allowEmptyWildcard bool
48+
noFollowSymlinks bool
4849
}
4950

5051
func createCommand(addCopy string, desc string, short string, opts *addCopyResults) *cobra.Command {
@@ -80,6 +81,7 @@ func applyFlagVars(flags *pflag.FlagSet, opts *addCopyResults) {
8081
flags.StringVar(&opts.chmod, "chmod", "", "set the access permissions of the destination content")
8182
flags.StringVar(&opts.creds, "creds", "", "use `[username[:password]]` for accessing registries when pulling images")
8283
flags.BoolVar(&opts.link, "link", false, "enable layer caching for this operation (creates an independent layer)")
84+
flags.BoolVar(&opts.noFollowSymlinks, "no-follow-symlinks", false, "do not follow symlinks when copying content (copy the symlink itself)")
8385
if err := flags.MarkHidden("creds"); err != nil {
8486
panic(fmt.Sprintf("error marking creds as hidden: %v", err))
8587
}
@@ -256,6 +258,11 @@ func addAndCopyCmd(c *cobra.Command, args []string, verb string, iopts addCopyRe
256258
timestamp = &t
257259
}
258260

261+
followSymlink := types.OptionalBoolUndefined
262+
if iopts.noFollowSymlinks {
263+
followSymlink = types.OptionalBoolFalse
264+
}
265+
259266
options := buildah.AddAndCopyOptions{
260267
Chmod: iopts.chmod,
261268
Chown: iopts.chown,
@@ -272,6 +279,7 @@ func addAndCopyCmd(c *cobra.Command, args []string, verb string, iopts addCopyRe
272279
Parents: iopts.parents,
273280
Timestamp: timestamp,
274281
Link: iopts.link,
282+
FollowSymlink: followSymlink,
275283
}
276284
if iopts.contextdir != "" {
277285
var excludes []string

docs/buildah-add.1.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ container's filesystem. If `buildah run` creates a file and `buildah add --link`
8484
to the same path, the file from `buildah add --link` will be present in the committed image.
8585
The --link layer is applied after all container filesystem changes at commit time.
8686

87+
**--no-follow-symlinks**
88+
89+
When a local source is a symbolic link, copy the link as a symbolic link
90+
instead of dereferencing the link and copying the contents of the target.
91+
8792
**--quiet**, **-q**
8893

8994
Refrain from printing a digest of the added content.

docs/buildah-copy.1.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ container's filesystem. If `buildah run` creates a file and `buildah copy --link
8484
to the same path, the file from `buildah copy --link` will be present in the committed image.
8585
The --link layer is applied after all container filesystem changes at commit time.
8686

87+
**--no-follow-symlinks**
88+
89+
Don't follow and dereference the symlinks when copying the files. Instead, copy
90+
the symlinks themselves.
91+
8792
**--parents**
8893

8994
Preserve leading directories in the paths of items being copied, relative to either the

tests/add.bats

Lines changed: 89 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -401,19 +401,19 @@ EOF
401401
cid=$output
402402
run_buildah mount $cid
403403
root=$output
404-
404+
405405
run_buildah config --workingdir=/ $cid
406-
406+
407407
# Test 1: Simple add
408408
run_buildah add --link $cid ${TEST_SCRATCH_DIR}/randomfile
409-
409+
410410
# Test 2: Add with rename (file to file with different name)
411411
run_buildah add --link $cid ${TEST_SCRATCH_DIR}/randomfile /renamed-file
412-
412+
413413
# Test 3: Multiple files to directory
414414
mkdir $root/subdir
415415
run_buildah add --link $cid ${TEST_SCRATCH_DIR}/randomfile ${TEST_SCRATCH_DIR}/other-randomfile /subdir
416-
416+
417417
run_buildah unmount $cid
418418
run_buildah commit $WITH_POLICY_JSON $cid add-link-image
419419

@@ -430,13 +430,13 @@ EOF
430430
newcid=$output
431431
run_buildah mount $newcid
432432
newroot=$output
433-
433+
434434
test -s $newroot/randomfile
435435
cmp ${TEST_SCRATCH_DIR}/randomfile $newroot/randomfile
436-
436+
437437
test -s $newroot/renamed-file
438438
cmp ${TEST_SCRATCH_DIR}/randomfile $newroot/renamed-file
439-
439+
440440
test -s $newroot/subdir/randomfile
441441
cmp ${TEST_SCRATCH_DIR}/randomfile $newroot/subdir/randomfile
442442
test -s $newroot/subdir/other-randomfile
@@ -446,18 +446,18 @@ EOF
446446
@test "add-link-archive" {
447447
createrandom ${TEST_SCRATCH_DIR}/file1
448448
createrandom ${TEST_SCRATCH_DIR}/file2
449-
449+
450450
tar -c -C ${TEST_SCRATCH_DIR} -f ${TEST_SCRATCH_DIR}/archive.tar file1 file2
451451

452452
run_buildah from $WITH_POLICY_JSON scratch
453453
cid=$output
454-
454+
455455
run_buildah config --workingdir=/ $cid
456-
456+
457457
run_buildah add --link $cid ${TEST_SCRATCH_DIR}/archive.tar
458-
458+
459459
run_buildah add --link $cid ${TEST_SCRATCH_DIR}/archive.tar /destdir/
460-
460+
461461
run_buildah commit $WITH_POLICY_JSON $cid add-link-archive-image
462462

463463
run_buildah inspect --type=image add-link-archive-image
@@ -471,12 +471,12 @@ EOF
471471
newcid=$output
472472
run_buildah mount $newcid
473473
newroot=$output
474-
474+
475475
test -s $newroot/file1
476476
cmp ${TEST_SCRATCH_DIR}/file1 $newroot/file1
477477
test -s $newroot/file2
478478
cmp ${TEST_SCRATCH_DIR}/file2 $newroot/file2
479-
479+
480480
test -s $newroot/destdir/file1
481481
cmp ${TEST_SCRATCH_DIR}/file1 $newroot/destdir/file1
482482
test -s $newroot/destdir/file2
@@ -490,22 +490,22 @@ EOF
490490

491491
run_buildah from $WITH_POLICY_JSON scratch
492492
cid=$output
493-
493+
494494
run_buildah config --workingdir=/ $cid
495-
495+
496496
run_buildah add --link $cid ${TEST_SCRATCH_DIR}/testdir /testdir
497-
497+
498498
run_buildah commit $WITH_POLICY_JSON $cid add-link-dir-image
499499

500500
run_buildah from $WITH_POLICY_JSON add-link-dir-image
501501
newcid=$output
502502
run_buildah mount $newcid
503503
newroot=$output
504-
504+
505505
test -d $newroot/testdir
506506
test -s $newroot/testdir/file1
507507
test -s $newroot/testdir/subdir/file2
508-
508+
509509
cmp ${TEST_SCRATCH_DIR}/testdir/file1 $newroot/testdir/file1
510510
cmp ${TEST_SCRATCH_DIR}/testdir/subdir/file2 $newroot/testdir/subdir/file2
511511
}
@@ -562,3 +562,72 @@ EOF
562562
run_buildah 125 add --allow-empty-wildcard=true $cid ${TEST_SCRATCH_DIR}/no-such-file /dest4/
563563
expect_output --substring "no such file or directory"
564564
}
565+
566+
@test "add-symlink-root-follow-default" {
567+
createrandom ${TEST_SCRATCH_DIR}/file
568+
ln -s ./file ${TEST_SCRATCH_DIR}/symlink
569+
570+
run_buildah from $WITH_POLICY_JSON scratch
571+
cid=$output
572+
573+
run_buildah add $cid ${TEST_SCRATCH_DIR}/symlink /dest
574+
575+
run_buildah mount $cid
576+
root=$output
577+
ls -lahR $root
578+
cmp ${TEST_SCRATCH_DIR}/file $root/dest
579+
test -f $root/dest
580+
}
581+
582+
@test "add-symlink-root-no-follow" {
583+
createrandom ${TEST_SCRATCH_DIR}/file
584+
ln -s ./file ${TEST_SCRATCH_DIR}/symlink
585+
586+
run_buildah from $WITH_POLICY_JSON scratch
587+
cid=$output
588+
589+
# The symlink needs to point to something existing
590+
run_buildah add --no-follow-symlinks $cid ${TEST_SCRATCH_DIR}/file /file
591+
run_buildah add --no-follow-symlinks $cid ${TEST_SCRATCH_DIR}/symlink /dest
592+
593+
run_buildah mount $cid
594+
root=$output
595+
ls -lahR $root
596+
cmp ${TEST_SCRATCH_DIR}/file $root/dest
597+
test -L $root/dest
598+
test "$(readlink $root/dest)" = "./file"
599+
}
600+
601+
@test "add-symlink-child-follow-default" {
602+
mkdir ${TEST_SCRATCH_DIR}/src
603+
createrandom ${TEST_SCRATCH_DIR}/src/file
604+
ln -s ./file ${TEST_SCRATCH_DIR}/src/symlink
605+
606+
run_buildah from $WITH_POLICY_JSON scratch
607+
cid=$output
608+
609+
run_buildah add $cid ${TEST_SCRATCH_DIR}/src /dest
610+
611+
run_buildah mount $cid
612+
root=$output
613+
ls -lahR $root
614+
cmp ${TEST_SCRATCH_DIR}/src/file $root/dest/symlink
615+
test -f $root/dest/symlink
616+
}
617+
618+
@test "add-symlink-child-no-follow" {
619+
mkdir ${TEST_SCRATCH_DIR}/src
620+
createrandom ${TEST_SCRATCH_DIR}/src/file
621+
ln -s ./file ${TEST_SCRATCH_DIR}/src/symlink
622+
623+
run_buildah from $WITH_POLICY_JSON scratch
624+
cid=$output
625+
626+
run_buildah add --no-follow-symlinks $cid ${TEST_SCRATCH_DIR}/src /dest
627+
628+
run_buildah mount $cid
629+
root=$output
630+
ls -lahR $root
631+
test -L $root/dest/symlink
632+
test "$(readlink $root/dest/symlink)" = "./file"
633+
}

0 commit comments

Comments
 (0)