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 }