Skip to content

Commit

Permalink
Signed-off-by: sarthak <[email protected]>
Browse files Browse the repository at this point in the history
enable target support for extension
  • Loading branch information
sarthaksarthak9 committed Jan 25, 2024
1 parent 86ff68a commit caa7edc
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 29 deletions.
24 changes: 24 additions & 0 deletions internal/commands/extension_new.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ import (
"fmt"
"os"
"path/filepath"
"runtime"
"strings"

"github.com/spf13/cobra"

"github.com/buildpacks/pack/internal/style"
"github.com/buildpacks/pack/internal/target"
"github.com/buildpacks/pack/pkg/client"
"github.com/buildpacks/pack/pkg/dist"
"github.com/buildpacks/pack/pkg/logging"
)

Expand All @@ -19,6 +22,7 @@ type ExtensionNewFlags struct {
API string
Path string
Stacks []string
Targets []string
Version string
}

Expand Down Expand Up @@ -56,10 +60,23 @@ func ExtensionNew(logger logging.Logger, creator ExtensionCreator) *cobra.Comman
return fmt.Errorf("directory %s exists", style.Symbol(path))
}

var targets []dist.Target
if len(flags.Targets) == 0 && len(flags.Stacks) == 0 {
targets = []dist.Target{{
OS: runtime.GOOS,
Arch: runtime.GOARCH,
}}
} else {
if targets, err = target.ParseTargets(flags.Targets, logger); err != nil {
return err
}
}

if err := creator.NewExtension(cmd.Context(), client.NewExtensionOptions{
API: flags.API,
ID: id,
Path: path,
Targets: targets,
Version: flags.Version,
}); err != nil {
return err
Expand All @@ -72,6 +89,13 @@ func ExtensionNew(logger logging.Logger, creator ExtensionCreator) *cobra.Comman
cmd.Flags().StringVarP(&flags.API, "api", "a", "0.9", "Buildpack API compatibility of the generated extension")
cmd.Flags().StringVarP(&flags.Path, "path", "p", "", "Path to generate the extension")
cmd.Flags().StringVarP(&flags.Version, "version", "V", "1.0.0", "Version of the generated extension")
cmd.Flags().MarkDeprecated("stacks", "prefer `--targets` instead: https://github.com/buildpacks/rfcs/blob/main/text/0096-remove-stacks-mixins.md")
cmd.Flags().StringSliceVarP(&flags.Targets, "targets", "t", nil,
`Targets are the list platforms that one targeting, these are generated as part of scaffolding inside buildpack.toml file. one can provide target platforms in format [os][/arch][/variant]:[distroname@osversion@anotherversion];[distroname@osversion]
- Base case for two different architectures : '--targets "linux/amd64" --targets "linux/arm64"'
- case for distribution version: '--targets "windows/amd64:[email protected]"'
- case for different architecture with distributed versions : '--targets "linux/arm/v6:[email protected]" --targets "linux/arm/v6:[email protected]"'
`)

AddHelpFlag(cmd, "new")
return cmd
Expand Down
74 changes: 53 additions & 21 deletions internal/commands/extension_new_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import (
"bytes"
"os"
"path/filepath"
"runtime"
"testing"

"github.com/buildpacks/pack/pkg/client"
"github.com/buildpacks/pack/pkg/dist"
"github.com/buildpacks/pack/pkg/logging"

"github.com/golang/mock/gomock"
Expand Down Expand Up @@ -35,6 +37,10 @@ func testExtensionNewCommand(t *testing.T, when spec.G, it spec.S) {
mockClient *testmocks.MockPackClient
tmpDir string
)
targets := []dist.Target{{
OS: runtime.GOOS,
Arch: runtime.GOARCH,
}}

it.Before(func() {
var err error
Expand All @@ -54,11 +60,12 @@ func testExtensionNewCommand(t *testing.T, when spec.G, it spec.S) {

when("ExtensionNew#Execute", func() {
it("uses the args to generate artifacts", func() {
mockClient.EXPECT().NewBuildpack(gomock.Any(), client.NewExtensionOptions{
mockClient.EXPECT().NewExtension(gomock.Any(), client.NewExtensionOptions{
API: "0.8",
ID: "example/some-cnb",
Path: filepath.Join(tmpDir, "some-cnb"),
Version: "1.0.0",
Targets: targets,
}).Return(nil).MaxTimes(1)

path := filepath.Join(tmpDir, "some-cnb")
Expand All @@ -85,6 +92,15 @@ func testExtensionNewCommand(t *testing.T, when spec.G, it spec.S) {
ID: "example/targets",
Path: filepath.Join(tmpDir, "targets"),
Version: "1.0.0",
Targets: []dist.Target{{
OS: "linux",
Arch: "arm",
ArchVariant: "v6",
Distributions: []dist.Distribution{{
Name: "ubuntu",
Versions: []string{"14.04", "16.04"},
}},
}},
}).Return(nil).MaxTimes(1)

path := filepath.Join(tmpDir, "targets")
Expand All @@ -99,6 +115,15 @@ func testExtensionNewCommand(t *testing.T, when spec.G, it spec.S) {
ID: "example/targets",
Path: filepath.Join(tmpDir, "targets"),
Version: "1.0.0",
Targets: []dist.Target{{
OS: "os",
Arch: "arm",
ArchVariant: "v6",
Distributions: []dist.Distribution{{
Name: "ubuntu",
Versions: []string{"14.04", "16.04"},
}},
}},
}).Return(nil).MaxTimes(1)

path := filepath.Join(tmpDir, "targets")
Expand All @@ -114,6 +139,33 @@ func testExtensionNewCommand(t *testing.T, when spec.G, it spec.S) {
ID: "example/targets",
Path: filepath.Join(tmpDir, "targets"),
Version: "1.0.0",
Targets: []dist.Target{
{
OS: "linux",
Arch: "arm",
ArchVariant: "v6",
Distributions: []dist.Distribution{
{
Name: "ubuntu",
Versions: []string{"14.04", "16.04"},
},
{
Name: "debian",
Versions: []string{"8.10", "10.9"},
},
},
},
{
OS: "windows",
Arch: "amd64",
Distributions: []dist.Distribution{
{
Name: "windows-nano",
Versions: []string{"10.0.19041.1415"},
},
},
},
},
}).Return(nil).MaxTimes(1)

path := filepath.Join(tmpDir, "targets")
Expand All @@ -123,26 +175,6 @@ func testExtensionNewCommand(t *testing.T, when spec.G, it spec.S) {
h.AssertNil(t, err)
})
})
when("stacks ", func() {
it("flag should show deprecated message when used", func() {
mockClient.EXPECT().NewBuildpack(gomock.Any(), client.NewExtensionOptions{
API: "0.8",
ID: "example/stacks",
Path: filepath.Join(tmpDir, "stacks"),
Version: "1.0.0",
}).Return(nil).MaxTimes(1)

path := filepath.Join(tmpDir, "stacks")
output := new(bytes.Buffer)
command.SetOut(output)
command.SetErr(output)
command.SetArgs([]string{"--path", path, "example/stacks", "--stacks", "io.buildpacks.stacks.jammy"})

err := command.Execute()
h.AssertNil(t, err)
h.AssertContains(t, output.String(), "Flag --stacks has been deprecated,")
})
})
})
})
}
10 changes: 7 additions & 3 deletions pkg/client/new_extension.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,13 @@ type NewExtensionOptions struct {

// version of the output extension artifact.
Version string

// the targets this buildpack will work with
Targets []dist.Target
}

func (c *Client) NewExtension(ctx context.Context, opts NewExtensionOptions) error {
err := createExtensionTOML(opts.Path, opts.ID, opts.Version, opts.API, c)
err := createExtensionTOML(opts.Path, opts.ID, opts.Version, opts.API, opts.Targets, c)
if err != nil {
return err
}
Expand All @@ -73,14 +76,15 @@ func createBashExtension(path string, c *Client) error {
return nil
}

func createExtensionTOML(path, id, version, apiStr string, c *Client) error {
func createExtensionTOML(path, id, version, apiStr string, targets []dist.Target, c *Client) error {
api, err := api.NewVersion(apiStr)
if err != nil {
return err
}

extensionTOML := dist.ExtensionDescriptor{
WithAPI: api,
WithAPI: api,
WithTargets: targets,
WithInfo: dist.ModuleInfo{
ID: id,
Version: version,
Expand Down
64 changes: 59 additions & 5 deletions pkg/dist/extension_descriptor.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,76 @@
package dist

import (
"fmt"
"strings"

"github.com/buildpacks/lifecycle/api"

"github.com/buildpacks/pack/internal/style"
)

type ExtensionDescriptor struct {
WithAPI *api.Version `toml:"api"`
WithInfo ModuleInfo `toml:"extension"`
WithAPI *api.Version `toml:"api"`
WithInfo ModuleInfo `toml:"extension"`
WithTargets []Target `toml:"targets,omitempty"`
WithWindowsBuild bool
WithLinuxBuild bool
}

func (e *ExtensionDescriptor) EnsureStackSupport(_ string, _ []string, _ bool) error {
return nil
}

func (e *ExtensionDescriptor) EnsureTargetSupport(_, _, _, _ string) error {
return nil
func (e *ExtensionDescriptor) EnsureTargetSupport(os, arch, distroName, distroVersion string) error {
if len(e.Targets()) == 0 {
if (!e.WithLinuxBuild && !e.WithWindowsBuild) || len(e.Stacks()) > 0 { // nolint
return nil // Order extension or stack extension, no validation required
} else if e.WithLinuxBuild && os == DefaultTargetOSLinux && arch == DefaultTargetArch {
return nil
} else if e.WithWindowsBuild && os == DefaultTargetOSWindows && arch == DefaultTargetArch {
return nil
}
}
for _, target := range e.Targets() {
if target.OS == os {
if target.Arch == "" || arch == "" || target.Arch == arch {
if len(target.Distributions) == 0 || distroName == "" || distroVersion == "" {
return nil
}
for _, distro := range target.Distributions {
if distro.Name == distroName {
if len(distro.Versions) == 0 {
return nil
}
for _, version := range distro.Versions {
if version == distroVersion {
return nil
}
}
}
}
}
}
}
type osDistribution struct {
Name string `json:"name,omitempty"`
Version string `json:"version,omitempty"`
}
type target struct {
OS string `json:"os"`
Arch string `json:"arch"`
Distribution osDistribution `json:"distribution"`
}
return fmt.Errorf(
"unable to satisfy target os/arch constraints; build image: %s, extension %s: %s",
toJSONMaybe(target{
OS: os,
Arch: arch,
Distribution: osDistribution{Name: distroName, Version: distroVersion},
}),
style.Symbol(e.Info().FullName()),
toJSONMaybe(e.Targets()),
)
}

func (e *ExtensionDescriptor) EscapedID() string {
Expand Down Expand Up @@ -44,5 +98,5 @@ func (e *ExtensionDescriptor) Stacks() []Stack {
}

func (e *ExtensionDescriptor) Targets() []Target {
return nil
return e.WithTargets
}

0 comments on commit caa7edc

Please sign in to comment.