github.com/buildpacks/pack@v0.33.3-0.20240516162812-884dd1837311/pkg/dist/buildpack_descriptor.go (about) 1 package dist 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "sort" 7 "strings" 8 9 "github.com/buildpacks/lifecycle/api" 10 11 "github.com/buildpacks/pack/internal/stringset" 12 "github.com/buildpacks/pack/internal/style" 13 ) 14 15 type BuildpackDescriptor struct { 16 WithAPI *api.Version `toml:"api"` 17 WithInfo ModuleInfo `toml:"buildpack"` 18 WithStacks []Stack `toml:"stacks,omitempty"` 19 WithTargets []Target `toml:"targets,omitempty"` 20 WithOrder Order `toml:"order"` 21 WithWindowsBuild bool 22 WithLinuxBuild bool 23 } 24 25 func (b *BuildpackDescriptor) EscapedID() string { 26 return strings.ReplaceAll(b.Info().ID, "/", "_") 27 } 28 29 func (b *BuildpackDescriptor) EnsureStackSupport(stackID string, providedMixins []string, validateRunStageMixins bool) error { 30 if len(b.Stacks()) == 0 { 31 return nil // Order buildpack or a buildpack using Targets, no validation required 32 } 33 34 bpMixins, err := b.findMixinsForStack(stackID) 35 if err != nil { 36 return err 37 } 38 39 if !validateRunStageMixins { 40 var filtered []string 41 for _, m := range bpMixins { 42 if !strings.HasPrefix(m, "run:") { 43 filtered = append(filtered, m) 44 } 45 } 46 bpMixins = filtered 47 } 48 49 _, missing, _ := stringset.Compare(providedMixins, bpMixins) 50 if len(missing) > 0 { 51 sort.Strings(missing) 52 return fmt.Errorf("buildpack %s requires missing mixin(s): %s", style.Symbol(b.Info().FullName()), strings.Join(missing, ", ")) 53 } 54 return nil 55 } 56 57 func (b *BuildpackDescriptor) EnsureTargetSupport(givenOS, givenArch, givenDistroName, givenDistroVersion string) error { 58 if len(b.Targets()) == 0 { 59 if (!b.WithLinuxBuild && !b.WithWindowsBuild) || len(b.Stacks()) > 0 { // nolint 60 return nil // Order buildpack or stack buildpack, no validation required 61 } else if b.WithLinuxBuild && givenOS == DefaultTargetOSLinux && givenArch == DefaultTargetArch { 62 return nil 63 } else if b.WithWindowsBuild && givenOS == DefaultTargetOSWindows && givenArch == DefaultTargetArch { 64 return nil 65 } 66 } 67 for _, bpTarget := range b.Targets() { 68 if bpTarget.OS == givenOS { 69 if bpTarget.Arch == "" || givenArch == "" || bpTarget.Arch == givenArch { 70 if len(bpTarget.Distributions) == 0 || givenDistroName == "" || givenDistroVersion == "" { 71 return nil 72 } 73 for _, bpDistro := range bpTarget.Distributions { 74 if bpDistro.Name == givenDistroName && bpDistro.Version == givenDistroVersion { 75 return nil 76 } 77 } 78 } 79 } 80 } 81 type osDistribution struct { 82 Name string `json:"name,omitempty"` 83 Version string `json:"version,omitempty"` 84 } 85 type target struct { 86 OS string `json:"os"` 87 Arch string `json:"arch"` 88 Distribution osDistribution `json:"distribution"` 89 } 90 return fmt.Errorf( 91 "unable to satisfy target os/arch constraints; build image: %s, buildpack %s: %s", 92 toJSONMaybe(target{ 93 OS: givenOS, 94 Arch: givenArch, 95 Distribution: osDistribution{Name: givenDistroName, Version: givenDistroVersion}, 96 }), 97 style.Symbol(b.Info().FullName()), 98 toJSONMaybe(b.Targets()), 99 ) 100 } 101 102 func toJSONMaybe(v interface{}) string { 103 b, err := json.Marshal(v) 104 if err != nil { 105 return fmt.Sprintf("%s", v) // hopefully v is a Stringer 106 } 107 return string(b) 108 } 109 110 func (b *BuildpackDescriptor) Kind() string { 111 return "buildpack" 112 } 113 114 func (b *BuildpackDescriptor) API() *api.Version { 115 return b.WithAPI 116 } 117 118 func (b *BuildpackDescriptor) Info() ModuleInfo { 119 return b.WithInfo 120 } 121 122 func (b *BuildpackDescriptor) Order() Order { 123 return b.WithOrder 124 } 125 126 func (b *BuildpackDescriptor) Stacks() []Stack { 127 return b.WithStacks 128 } 129 130 func (b *BuildpackDescriptor) Targets() []Target { 131 return b.WithTargets 132 } 133 134 func (b *BuildpackDescriptor) findMixinsForStack(stackID string) ([]string, error) { 135 for _, s := range b.Stacks() { 136 if s.ID == stackID || s.ID == "*" { 137 return s.Mixins, nil 138 } 139 } 140 return nil, fmt.Errorf("buildpack %s does not support stack %s", style.Symbol(b.Info().FullName()), style.Symbol(stackID)) 141 }