13
13
# limitations under the License.
14
14
15
15
from io import BytesIO
16
+ import contextlib
16
17
import datetime
17
18
import json
18
19
import os
@@ -53,20 +54,33 @@ def assertTarballContains(self, tar, paths):
53
54
self .maxDiff = None
54
55
self .assertEqual (paths , tar .getnames ())
55
56
56
- def assertLayerNContains (self , img , n , paths ):
57
+ def assertTarballSymlink (self , tar , path , target ):
58
+ self .assertEqual (target , tar .getmember (path ).linkname )
59
+
60
+ @contextlib .contextmanager
61
+ def _tarball_layer_n (self , img , n ):
57
62
buf = BytesIO (img .blob (img .fs_layers ()[n ]))
58
- with tarfile .open (fileobj = buf , mode = 'r' ) as layer :
63
+ yield tarfile .open (fileobj = buf , mode = 'r' )
64
+
65
+ def assertLayerNContains (self , img , n , paths ):
66
+ with self ._tarball_layer_n (img , n ) as layer :
59
67
self .assertTarballContains (layer , paths )
60
68
69
+ def assertLayerNSymlink (self , img , n , path , target ):
70
+ with self ._tarball_layer_n (img , n ) as layer :
71
+ self .assertTarballSymlink (layer , path , target )
72
+
61
73
def assertNonZeroMtimesInTopLayer (self , img ):
62
- buf = BytesIO (img .blob (img .fs_layers ()[0 ]))
63
- with tarfile .open (fileobj = buf , mode = 'r' ) as layer :
74
+ with self ._tarball_layer_n (img , 0 ) as layer :
64
75
for member in layer .getmembers ():
65
76
self .assertNotEqual (member .mtime , 0 )
66
77
67
78
def assertTopLayerContains (self , img , paths ):
68
79
self .assertLayerNContains (img , 0 , paths )
69
80
81
+ def assertTopLayerSymlink (self , img , path , target ):
82
+ self .assertLayerNSymlink (img , 0 , path , target )
83
+
70
84
def assertConfigEqual (self , img , key , value ):
71
85
cfg = json .loads (img .config_file ())
72
86
self .assertEqual (value , cfg .get ('config' , {}).get (key ))
@@ -562,6 +576,12 @@ def test_py_image_with_symlinks_in_data(self):
562
576
'./app/testdata/py_image_with_symlinks_in_data.binary.runfiles/io_bazel_rules_docker/testdata/py_image.py' ,
563
577
'./app/testdata/py_image_with_symlinks_in_data.binary.runfiles/io_bazel_rules_docker/testdata/py_image_with_symlinks_in_data.binary' ,
564
578
'./app/testdata/py_image_with_symlinks_in_data.binary.runfiles/io_bazel_rules_docker/testdata/foo.txt' ,
579
+ # baz-symlink-real.txt is a real file, since the File that it points to is not in runfiles.files
580
+ './app/testdata/py_image_with_symlinks_in_data.binary.runfiles/io_bazel_rules_docker/baz' ,
581
+ './app/testdata/py_image_with_symlinks_in_data.binary.runfiles/io_bazel_rules_docker/baz/dir' ,
582
+ './app/testdata/py_image_with_symlinks_in_data.binary.runfiles/io_bazel_rules_docker/baz/dir/baz-symlink-real.txt' ,
583
+ # bar-root-symlink-real.txt is a real file, since the File that it points to is not in runfiles.files
584
+ './app/testdata/py_image_with_symlinks_in_data.binary.runfiles/bar-root-symlink-real.txt' ,
565
585
'./app/testdata/py_image_with_symlinks_in_data.binary.runfiles/io_bazel_rules_docker/testdata/__init__.py' ,
566
586
'./app/io_bazel_rules_docker' ,
567
587
# TODO(mattmoor): The path normalization for symlinks should match
@@ -571,10 +591,18 @@ def test_py_image_with_symlinks_in_data(self):
571
591
'/app/testdata/py_image_with_symlinks_in_data.binary.runfiles' ,
572
592
'/app/testdata/py_image_with_symlinks_in_data.binary.runfiles/io_bazel_rules_docker' ,
573
593
'/app/testdata/py_image_with_symlinks_in_data.binary.runfiles/io_bazel_rules_docker/foo-symlink.txt' ,
594
+ '/app/testdata/py_image_with_symlinks_in_data.binary.runfiles/foo-root-symlink.txt' ,
574
595
'/app/testdata/py_image_with_symlinks_in_data.binary' ,
575
596
'/app/testdata/py_image_with_symlinks_in_data.binary.runfiles/io_bazel_rules_docker/external' ,
576
597
])
577
598
599
+ # Test that root_symlinks that point to a file that is also in the runfiles tree is a symlink
600
+ self .assertTopLayerSymlink (
601
+ img ,
602
+ '/app/testdata/py_image_with_symlinks_in_data.binary.runfiles/foo-root-symlink.txt' ,
603
+ '/app/testdata/py_image_with_symlinks_in_data.binary.runfiles/io_bazel_rules_docker/testdata/foo.txt' ,
604
+ )
605
+
578
606
# Below that, we have a layer that generates symlinks for the library layer.
579
607
self .assertLayerNContains (img , 1 , [
580
608
'.' ,
@@ -586,6 +614,14 @@ def test_py_image_with_symlinks_in_data(self):
586
614
'/app/testdata/py_image_with_symlinks_in_data.binary.runfiles/io_bazel_rules_docker/testdata/py_image_library.py' ,
587
615
])
588
616
617
+ # Validate that library symlink is actually a symlink to the right path
618
+ self .assertLayerNSymlink (
619
+ img ,
620
+ 1 ,
621
+ '/app/testdata/py_image_with_symlinks_in_data.binary.runfiles/io_bazel_rules_docker/testdata/py_image_library.py' ,
622
+ '/app/io_bazel_rules_docker/testdata/py_image_library.py' ,
623
+ )
624
+
589
625
# Check the library layer, which is two below our application layer.
590
626
self .assertLayerNContains (img , 2 , [
591
627
'.' ,
0 commit comments