github.com/alibaba/sealer@v0.8.6-0.20220430115802-37a2bdaa8173/build/buildinstruction/utils.go (about)

     1  // Copyright © 2021 Alibaba Group Holding Ltd.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package buildinstruction
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"os"
    21  	"path/filepath"
    22  	"strings"
    23  
    24  	"github.com/alibaba/sealer/utils/collector"
    25  
    26  	fsutil "github.com/tonistiigi/fsutil/copy"
    27  
    28  	"github.com/alibaba/sealer/pkg/image"
    29  	"github.com/alibaba/sealer/pkg/image/cache"
    30  	"github.com/alibaba/sealer/utils"
    31  
    32  	"github.com/opencontainers/go-digest"
    33  
    34  	"github.com/alibaba/sealer/common"
    35  	"github.com/alibaba/sealer/logger"
    36  	v1 "github.com/alibaba/sealer/types/api/v1"
    37  	"github.com/alibaba/sealer/utils/archive"
    38  )
    39  
    40  func tryCache(parentID cache.ChainID,
    41  	layer v1.Layer,
    42  	cacheService cache.Service,
    43  	prober image.Prober,
    44  	srcFilesDgst digest.Digest) (hitCache bool, layerID digest.Digest, chainID cache.ChainID) {
    45  	var err error
    46  	cacheLayer := cacheService.NewCacheLayer(layer, srcFilesDgst)
    47  	cacheLayerID, err := prober.Probe(parentID.String(), &cacheLayer)
    48  	if err != nil {
    49  		logger.Debug("failed to probe cache for %+v, err: %s", layer, err)
    50  		return false, "", ""
    51  	}
    52  	// cache hit
    53  	logger.Info("---> Using cache %v", cacheLayerID)
    54  	//layer.ID = cacheLayerID
    55  	cID, err := cacheLayer.ChainID(parentID)
    56  	if err != nil {
    57  		return false, "", ""
    58  	}
    59  	return true, cacheLayerID, cID
    60  }
    61  
    62  func GenerateSourceFilesDigest(root, src string) (digest.Digest, error) {
    63  	m, err := fsutil.ResolveWildcards(root, src, true)
    64  	if err != nil {
    65  		return "", err
    66  	}
    67  
    68  	// wrong wildcards: no such file or directory
    69  	if len(m) == 0 {
    70  		return "", fmt.Errorf("%s not found", src)
    71  	}
    72  
    73  	if len(m) == 1 {
    74  		return generateDigest(filepath.Join(root, src))
    75  	}
    76  
    77  	tmp, err := utils.MkTmpdir()
    78  	if err != nil {
    79  		return "", fmt.Errorf("failed to create tmp dir %s:%v", tmp, err)
    80  	}
    81  
    82  	defer func() {
    83  		if err = os.RemoveAll(tmp); err != nil {
    84  			logger.Warn(err)
    85  		}
    86  	}()
    87  
    88  	xattrErrorHandler := func(dst, src, key string, err error) error {
    89  		logger.Warn(err)
    90  		return nil
    91  	}
    92  	opt := []fsutil.Opt{
    93  		fsutil.WithXAttrErrorHandler(xattrErrorHandler),
    94  	}
    95  
    96  	for _, s := range m {
    97  		if err := fsutil.Copy(context.TODO(), root, s, tmp, filepath.Base(s), opt...); err != nil {
    98  			return "", err
    99  		}
   100  	}
   101  
   102  	return generateDigest(tmp)
   103  }
   104  
   105  func generateDigest(path string) (digest.Digest, error) {
   106  	layerDgst, _, err := archive.TarCanonicalDigest(path)
   107  	if err != nil {
   108  		return "", err
   109  	}
   110  	return layerDgst, nil
   111  }
   112  
   113  // GetBaseLayersPath used in build stage, where the image still has from layer
   114  func GetBaseLayersPath(layers []v1.Layer) (res []string) {
   115  	for _, layer := range layers {
   116  		if layer.ID != "" {
   117  			res = append(res, filepath.Join(common.DefaultLayerDir, layer.ID.Hex()))
   118  		}
   119  	}
   120  	return res
   121  }
   122  
   123  func ParseCopyLayerContent(layerValue string) (src, dst string) {
   124  	dst = strings.Fields(layerValue)[1]
   125  	for _, p := range []string{"./", "/"} {
   126  		dst = strings.TrimPrefix(dst, p)
   127  	}
   128  	dst = strings.TrimSuffix(dst, "/")
   129  	src = strings.Fields(layerValue)[0]
   130  	return
   131  }
   132  
   133  func isRemoteSource(src string) bool {
   134  	if collector.IsURL(src) || collector.IsGitURL(src) {
   135  		return true
   136  	}
   137  	return false
   138  }