github.com/ouraigua/jenkins-library@v0.0.0-20231028010029-fbeaf2f3aa9b/pkg/cnbutils/buildpack.go (about)

     1  // Package cnbutils provides utility functions to interact with Buildpacks
     2  package cnbutils
     3  
     4  import (
     5  	"encoding/json"
     6  	"os"
     7  	"path/filepath"
     8  
     9  	"github.com/SAP/jenkins-library/pkg/log"
    10  	"github.com/pkg/errors"
    11  )
    12  
    13  const bpCacheDir = "/tmp/buildpacks_cache"
    14  
    15  type BuildPackMetadata struct {
    16  	ID          string    `toml:"id,omitempty" json:"id,omitempty" yaml:"id,omitempty"`
    17  	Name        string    `toml:"name,omitempty" json:"name,omitempty" yaml:"name,omitempty"`
    18  	Version     string    `toml:"version,omitempty" json:"version,omitempty" yaml:"version,omitempty"`
    19  	Description string    `toml:"description,omitempty" json:"description,omitempty" yaml:"description,omitempty"`
    20  	Homepage    string    `toml:"homepage,omitempty" json:"homepage,omitempty" yaml:"homepage,omitempty"`
    21  	Keywords    []string  `toml:"keywords,omitempty" json:"keywords,omitempty" yaml:"keywords,omitempty"`
    22  	Licenses    []License `toml:"licenses,omitempty" json:"licenses,omitempty" yaml:"licenses,omitempty"`
    23  }
    24  
    25  type License struct {
    26  	Type string `toml:"type" json:"type"`
    27  	URI  string `toml:"uri" json:"uri"`
    28  }
    29  
    30  func DownloadBuildpacks(path string, bpacks []string, dockerCreds string, utils BuildUtils) error {
    31  	if dockerCreds != "" {
    32  		os.Setenv("DOCKER_CONFIG", filepath.Dir(dockerCreds))
    33  	}
    34  
    35  	err := utils.MkdirAll(bpCacheDir, os.ModePerm)
    36  	if err != nil {
    37  		return errors.Wrap(err, "failed to create temp directory for buildpack cache")
    38  	}
    39  
    40  	for _, bpack := range bpacks {
    41  		imageInfo, err := utils.GetRemoteImageInfo(bpack)
    42  		if err != nil {
    43  			return errors.Wrap(err, "failed to get remote image info of buildpack")
    44  		}
    45  		hash, err := imageInfo.Digest()
    46  		if err != nil {
    47  			return errors.Wrap(err, "failed to get image digest")
    48  		}
    49  		cacheDir := filepath.Join(bpCacheDir, hash.String())
    50  
    51  		cacheExists, err := utils.DirExists(cacheDir)
    52  		if err != nil {
    53  			return errors.Wrapf(err, "failed to check if cache dir '%s' exists", cacheDir)
    54  		}
    55  
    56  		if cacheExists {
    57  			log.Entry().Infof("Using cached buildpack '%s'", bpack)
    58  		} else {
    59  			err := utils.MkdirAll(cacheDir, os.ModePerm)
    60  			if err != nil {
    61  				return errors.Wrap(err, "failed to create temp directory for buildpack cache")
    62  			}
    63  
    64  			log.Entry().Infof("Downloading buildpack '%s' to %s", bpack, cacheDir)
    65  			_, err = utils.DownloadImageContent(bpack, cacheDir)
    66  			if err != nil {
    67  				return errors.Wrapf(err, "failed download buildpack image '%s'", bpack)
    68  			}
    69  		}
    70  
    71  		matches, err := utils.Glob(filepath.Join(cacheDir, "cnb/buildpacks/*"))
    72  		if err != nil {
    73  			return err
    74  		}
    75  
    76  		for _, match := range matches {
    77  			err = CreateVersionSymlinks(path, match, utils)
    78  			if err != nil {
    79  				return err
    80  			}
    81  		}
    82  	}
    83  
    84  	return nil
    85  }
    86  
    87  func GetMetadata(bpacks []string, utils BuildUtils) ([]BuildPackMetadata, error) {
    88  	var metadata []BuildPackMetadata
    89  
    90  	for _, bpack := range bpacks {
    91  		var bpackMeta BuildPackMetadata
    92  		imageInfo, err := utils.GetRemoteImageInfo(bpack)
    93  		if err != nil {
    94  			return nil, err
    95  		}
    96  
    97  		imgConf, err := imageInfo.ConfigFile()
    98  		if err != nil {
    99  			return nil, errors.Wrapf(err, "failed to read '%s' image config", bpack)
   100  		}
   101  
   102  		err = json.Unmarshal([]byte(imgConf.Config.Labels["io.buildpacks.buildpackage.metadata"]), &bpackMeta)
   103  		if err != nil {
   104  			return nil, err
   105  		}
   106  		metadata = append(metadata, bpackMeta)
   107  	}
   108  
   109  	return metadata, nil
   110  }
   111  
   112  func CreateVersionSymlinks(basePath, buildpackDir string, utils BuildUtils) error {
   113  	newBuildpackPath := filepath.Join(basePath, filepath.Base(buildpackDir))
   114  	err := utils.MkdirAll(newBuildpackPath, os.ModePerm)
   115  	if err != nil {
   116  		return err
   117  	}
   118  
   119  	versions, err := utils.Glob(filepath.Join(buildpackDir, "*"))
   120  	if err != nil {
   121  		return err
   122  	}
   123  
   124  	for _, version := range versions {
   125  		newVersionPath := filepath.Join(newBuildpackPath, filepath.Base(version))
   126  		exists, err := utils.DirExists(newVersionPath)
   127  		if err != nil {
   128  			return err
   129  		}
   130  
   131  		if !exists {
   132  			err = utils.Symlink(version, newVersionPath)
   133  			if err != nil {
   134  				return err
   135  			}
   136  		}
   137  	}
   138  
   139  	return nil
   140  }