@@ -19,6 +19,7 @@ import (
19
19
"github.com/containers/buildah/define"
20
20
buildahdocker "github.com/containers/buildah/docker"
21
21
"github.com/containers/buildah/internal"
22
+ internalParse "github.com/containers/buildah/internal/parse"
22
23
"github.com/containers/buildah/internal/tmpdir"
23
24
internalUtil "github.com/containers/buildah/internal/util"
24
25
"github.com/containers/buildah/pkg/parse"
@@ -1280,7 +1281,11 @@ func (s *StageExecutor) Execute(ctx context.Context, base string) (imgID string,
1280
1281
// No base image means there's nothing to put in a
1281
1282
// layer, so don't create one.
1282
1283
emptyLayer := (s .builder .FromImageID == "" )
1283
- if imgID , ref , err = s .commit (ctx , s .getCreatedBy (nil , "" ), emptyLayer , s .output , s .executor .squash || s .executor .confidentialWorkload .Convert , lastStage ); err != nil {
1284
+ createdBy , err := s .getCreatedBy (nil , "" )
1285
+ if err != nil {
1286
+ return "" , nil , false , err
1287
+ }
1288
+ if imgID , ref , err = s .commit (ctx , createdBy , emptyLayer , s .output , s .executor .squash || s .executor .confidentialWorkload .Convert , lastStage ); err != nil {
1284
1289
return "" , nil , false , fmt .Errorf ("committing base container: %w" , err )
1285
1290
}
1286
1291
} else {
@@ -1427,7 +1432,11 @@ func (s *StageExecutor) Execute(ctx context.Context, base string) (imgID string,
1427
1432
if s .executor .timestamp != nil {
1428
1433
timestamp = * s .executor .timestamp
1429
1434
}
1430
- s .builder .AddPrependedEmptyLayer (& timestamp , s .getCreatedBy (node , addedContentSummary ), "" , "" )
1435
+ createdBy , err := s .getCreatedBy (node , addedContentSummary )
1436
+ if err != nil {
1437
+ return "" , nil , false , err
1438
+ }
1439
+ s .builder .AddPrependedEmptyLayer (& timestamp , createdBy , "" , "" )
1431
1440
continue
1432
1441
}
1433
1442
// This is the last instruction for this stage,
@@ -1437,7 +1446,11 @@ func (s *StageExecutor) Execute(ctx context.Context, base string) (imgID string,
1437
1446
// stage.
1438
1447
if lastStage || imageIsUsedLater {
1439
1448
logCommit (s .output , i )
1440
- imgID , ref , err = s .commit (ctx , s .getCreatedBy (node , addedContentSummary ), false , s .output , s .executor .squash , lastStage && lastInstruction )
1449
+ createdBy , err := s .getCreatedBy (node , addedContentSummary )
1450
+ if err != nil {
1451
+ return "" , nil , false , err
1452
+ }
1453
+ imgID , ref , err = s .commit (ctx , createdBy , false , s .output , s .executor .squash , lastStage && lastInstruction )
1441
1454
if err != nil {
1442
1455
return "" , nil , false , fmt .Errorf ("committing container for step %+v: %w" , * step , err )
1443
1456
}
@@ -1658,14 +1671,18 @@ func (s *StageExecutor) Execute(ctx context.Context, base string) (imgID string,
1658
1671
// We're not going to find any more cache hits, so we
1659
1672
// can stop looking for them.
1660
1673
checkForLayers = false
1674
+ createdBy , err := s .getCreatedBy (node , addedContentSummary )
1675
+ if err != nil {
1676
+ return "" , nil , false , err
1677
+ }
1661
1678
// Create a new image, maybe with a new layer, with the
1662
1679
// name for this stage if it's the last instruction.
1663
1680
logCommit (s .output , i )
1664
1681
// While committing we always set squash to false here
1665
1682
// because at this point we want to save history for
1666
1683
// layers even if its a squashed build so that they
1667
1684
// can be part of the build cache.
1668
- imgID , ref , err = s .commit (ctx , s . getCreatedBy ( node , addedContentSummary ) , ! s .stepRequiresLayer (step ), commitName , false , lastStage && lastInstruction )
1685
+ imgID , ref , err = s .commit (ctx , createdBy , ! s .stepRequiresLayer (step ), commitName , false , lastStage && lastInstruction )
1669
1686
if err != nil {
1670
1687
return "" , nil , false , fmt .Errorf ("committing container for step %+v: %w" , * step , err )
1671
1688
}
@@ -1696,12 +1713,16 @@ func (s *StageExecutor) Execute(ctx context.Context, base string) (imgID string,
1696
1713
1697
1714
if lastInstruction && lastStage {
1698
1715
if s .executor .squash || s .executor .confidentialWorkload .Convert || len (s .executor .sbomScanOptions ) != 0 {
1716
+ createdBy , err := s .getCreatedBy (node , addedContentSummary )
1717
+ if err != nil {
1718
+ return "" , nil , false , err
1719
+ }
1699
1720
// If this is the last instruction of the last stage,
1700
1721
// create a squashed or confidential workload
1701
1722
// version of the image if that's what we're after,
1702
1723
// or a normal one if we need to scan the image while
1703
1724
// committing it.
1704
- imgID , ref , err = s .commit (ctx , s . getCreatedBy ( node , addedContentSummary ) , ! s .stepRequiresLayer (step ), commitName , s .executor .squash || s .executor .confidentialWorkload .Convert , lastStage && lastInstruction )
1725
+ imgID , ref , err = s .commit (ctx , createdBy , ! s .stepRequiresLayer (step ), commitName , s .executor .squash || s .executor .confidentialWorkload .Convert , lastStage && lastInstruction )
1705
1726
if err != nil {
1706
1727
return "" , nil , false , fmt .Errorf ("committing final squash step %+v: %w" , * step , err )
1707
1728
}
@@ -1793,54 +1814,58 @@ func historyEntriesEqual(base, derived v1.History) bool {
1793
1814
// that we're comparing.
1794
1815
// Used to verify whether a cache of the intermediate image exists and whether
1795
1816
// to run the build again.
1796
- func (s * StageExecutor ) historyAndDiffIDsMatch (baseHistory []v1.History , baseDiffIDs []digest.Digest , child * parser.Node , history []v1.History , diffIDs []digest.Digest , addedContentSummary string , buildAddsLayer bool ) bool {
1817
+ func (s * StageExecutor ) historyAndDiffIDsMatch (baseHistory []v1.History , baseDiffIDs []digest.Digest , child * parser.Node , history []v1.History , diffIDs []digest.Digest , addedContentSummary string , buildAddsLayer bool ) ( bool , error ) {
1797
1818
// our history should be as long as the base's, plus one entry for what
1798
1819
// we're doing
1799
1820
if len (history ) != len (baseHistory )+ 1 {
1800
- return false
1821
+ return false , nil
1801
1822
}
1802
1823
// check that each entry in the base history corresponds to an entry in
1803
1824
// our history, and count how many of them add a layer diff
1804
1825
expectedDiffIDs := 0
1805
1826
for i := range baseHistory {
1806
1827
if ! historyEntriesEqual (baseHistory [i ], history [i ]) {
1807
- return false
1828
+ return false , nil
1808
1829
}
1809
1830
if ! baseHistory [i ].EmptyLayer {
1810
1831
expectedDiffIDs ++
1811
1832
}
1812
1833
}
1813
1834
if len (baseDiffIDs ) != expectedDiffIDs {
1814
- return false
1835
+ return false , nil
1815
1836
}
1816
1837
if buildAddsLayer {
1817
1838
// we're adding a layer, so we should have exactly one more
1818
1839
// layer than the base image
1819
1840
if len (diffIDs ) != expectedDiffIDs + 1 {
1820
- return false
1841
+ return false , nil
1821
1842
}
1822
1843
} else {
1823
1844
// we're not adding a layer, so we should have exactly the same
1824
1845
// layers as the base image
1825
1846
if len (diffIDs ) != expectedDiffIDs {
1826
- return false
1847
+ return false , nil
1827
1848
}
1828
1849
}
1829
1850
// compare the diffs for the layers that we should have in common
1830
1851
for i := range baseDiffIDs {
1831
1852
if diffIDs [i ] != baseDiffIDs [i ] {
1832
- return false
1853
+ return false , nil
1833
1854
}
1834
1855
}
1835
- return history [len (baseHistory )].CreatedBy == s .getCreatedBy (child , addedContentSummary )
1856
+ createdBy , err := s .getCreatedBy (child , addedContentSummary )
1857
+ if err != nil {
1858
+ return false , err
1859
+ }
1860
+ return history [len (baseHistory )].CreatedBy == createdBy , nil
1836
1861
}
1837
1862
1838
1863
// getCreatedBy returns the command the image at node will be created by. If
1839
1864
// the passed-in CompositeDigester is not nil, it is assumed to have the digest
1840
1865
// information for the content if the node is ADD or COPY.
1841
- func (s * StageExecutor ) getCreatedBy (node * parser.Node , addedContentSummary string ) string {
1866
+ func (s * StageExecutor ) getCreatedBy (node * parser.Node , addedContentSummary string ) ( string , error ) {
1842
1867
if node == nil {
1843
- return "/bin/sh"
1868
+ return "/bin/sh" , nil
1844
1869
}
1845
1870
switch strings .ToUpper (node .Value ) {
1846
1871
case "ARG" :
@@ -1850,15 +1875,55 @@ func (s *StageExecutor) getCreatedBy(node *parser.Node, addedContentSummary stri
1850
1875
}
1851
1876
}
1852
1877
buildArgs := s .getBuildArgsKey ()
1853
- return "/bin/sh -c #(nop) ARG " + buildArgs
1878
+ return "/bin/sh -c #(nop) ARG " + buildArgs , nil
1854
1879
case "RUN" :
1855
1880
shArg := ""
1856
1881
buildArgs := s .getBuildArgsResolvedForRun ()
1882
+ mountOptionSource := ""
1883
+ mountOptionFrom := ""
1884
+ appendCheckSum := ""
1885
+ var err error
1886
+ for _ , flag := range node .Flags {
1887
+ if strings .HasPrefix (flag , "--mount" ) {
1888
+ mountOptionSource , mountOptionFrom = internalParse .GetFromAndSourceKeysFromMountFlag (flag )
1889
+ // If source is not specified then default is '.'
1890
+ if mountOptionSource == "" {
1891
+ mountOptionSource = "."
1892
+ }
1893
+ }
1894
+ }
1895
+ // Source specificed is part of stage, image or additional-build-context.
1896
+ if mountOptionFrom != "" {
1897
+ // If this is not a stage then get digest of image or additional build context
1898
+ if _ , ok := s .executor .stages [mountOptionFrom ]; ! ok {
1899
+ if builder , ok := s .executor .containerMap [mountOptionFrom ]; ok {
1900
+ // Found valid image, get image digest.
1901
+ appendCheckSum = builder .FromImageDigest
1902
+ } else {
1903
+ // Found additional build context, get directory sha.
1904
+ appendCheckSum , err = internalUtil .GeneratePathChecksum (filepath .Join (s .executor .additionalBuildContexts [mountOptionFrom ].Value , mountOptionSource ))
1905
+ if err != nil {
1906
+ return "" , fmt .Errorf ("Unable to generate checksum for image history: %w" , err )
1907
+ }
1908
+ }
1909
+ }
1910
+ } else {
1911
+ if mountOptionSource != "" {
1912
+ appendCheckSum , err = internalUtil .GeneratePathChecksum (filepath .Join (s .executor .contextDir , mountOptionSource ))
1913
+ if err != nil {
1914
+ return "" , fmt .Errorf ("Unable to generate checksum for image history: %w" , err )
1915
+ }
1916
+ }
1917
+ }
1857
1918
if len (node .Original ) > 4 {
1858
1919
shArg = node .Original [4 :]
1859
1920
}
1921
+ if appendCheckSum != "" {
1922
+ // add a seperator to appendCheckSum
1923
+ appendCheckSum = ":" + appendCheckSum
1924
+ }
1860
1925
if buildArgs != "" {
1861
- return "|" + strconv .Itoa (len (strings .Split (buildArgs , " " ))) + " " + buildArgs + " /bin/sh -c " + shArg
1926
+ return "|" + strconv .Itoa (len (strings .Split (buildArgs , " " ))) + " " + buildArgs + " /bin/sh -c " + shArg + appendCheckSum , nil
1862
1927
}
1863
1928
result := "/bin/sh -c " + shArg
1864
1929
if len (node .Heredocs ) > 0 {
@@ -1867,15 +1932,15 @@ func (s *StageExecutor) getCreatedBy(node *parser.Node, addedContentSummary stri
1867
1932
result = result + "\n " + heredocContent
1868
1933
}
1869
1934
}
1870
- return result
1935
+ return result + appendCheckSum , nil
1871
1936
case "ADD" , "COPY" :
1872
1937
destination := node
1873
1938
for destination .Next != nil {
1874
1939
destination = destination .Next
1875
1940
}
1876
- return "/bin/sh -c #(nop) " + strings .ToUpper (node .Value ) + " " + addedContentSummary + " in " + destination .Value + " "
1941
+ return "/bin/sh -c #(nop) " + strings .ToUpper (node .Value ) + " " + addedContentSummary + " in " + destination .Value + " " , nil
1877
1942
default :
1878
- return "/bin/sh -c #(nop) " + node .Original
1943
+ return "/bin/sh -c #(nop) " + node .Original , nil
1879
1944
}
1880
1945
}
1881
1946
@@ -2024,7 +2089,10 @@ func (s *StageExecutor) generateCacheKey(ctx context.Context, currNode *parser.N
2024
2089
fmt .Fprintln (hash , diffIDs [i ].String ())
2025
2090
}
2026
2091
}
2027
- createdBy := s .getCreatedBy (currNode , addedContentDigest )
2092
+ createdBy , err := s .getCreatedBy (currNode , addedContentDigest )
2093
+ if err != nil {
2094
+ return "" , err
2095
+ }
2028
2096
fmt .Fprintf (hash , "%t" , buildAddsLayer )
2029
2097
fmt .Fprintln (hash , createdBy )
2030
2098
fmt .Fprintln (hash , manifestType )
@@ -2204,7 +2272,11 @@ func (s *StageExecutor) intermediateImageExists(ctx context.Context, currNode *p
2204
2272
continue
2205
2273
}
2206
2274
// children + currNode is the point of the Dockerfile we are currently at.
2207
- if s .historyAndDiffIDsMatch (baseHistory , baseDiffIDs , currNode , history , diffIDs , addedContentDigest , buildAddsLayer ) {
2275
+ diff , err := s .historyAndDiffIDsMatch (baseHistory , baseDiffIDs , currNode , history , diffIDs , addedContentDigest , buildAddsLayer )
2276
+ if err != nil {
2277
+ return "" , err
2278
+ }
2279
+ if diff {
2208
2280
return image .ID , nil
2209
2281
}
2210
2282
}
0 commit comments