Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a new manifest command to support multi-architecture builds #1705

Merged
merged 97 commits into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
97 commits
Select commit Hold shift + click to select a range
835902d
commands: manifest: command to handle manifests
husni-faiz Mar 20, 2023
ffe1f93
cmd: manifest create: first PoC
husni-faiz Mar 20, 2023
08ec406
cmd: manifest: refactor code
husni-faiz Mar 27, 2023
9b2a978
cmd: manifest: use ggcr library
husni-faiz Apr 1, 2023
3fc79cc
cmd: manifest: use imgutil
husni-faiz Apr 5, 2023
6b6f2b0
manifest: use pack client interface
husni-faiz Apr 18, 2023
e3908c2
manifest_create: separate input validation and manifest creation
husni-faiz Apr 18, 2023
d767b1e
client: manifest sub command logic function templates
husni-faiz Apr 18, 2023
3c0b9cc
commands: manifest sub command templates
husni-faiz Apr 18, 2023
e9ca7cb
bugfix: manifest: create: use single char for shorthand flag
husni-faiz Apr 25, 2023
3a7c262
manifest: create: move flag validations into command logic
husni-faiz Apr 25, 2023
40eade3
manifest: create: remove path option from remote index:
husni-faiz Apr 25, 2023
67d5644
create_manifest: raise error if saving the index fails
husni-faiz Apr 25, 2023
b6b0f0d
manifest_create: add default layout path to save an index
husni-faiz Apr 25, 2023
43f97b5
manifest: flag command as experimental
husni-faiz Apr 30, 2023
c3ac0ce
client: create an index factory
husni-faiz May 1, 2023
1530c23
create_manifest: use the index factory
husni-faiz May 1, 2023
8460b97
manifest: register subcommands
husni-faiz May 2, 2023
715e18a
manifest: add annotate subcommand
husni-faiz May 2, 2023
4a478b9
manifest: add 'add' subcommand
husni-faiz May 2, 2023
b840b19
manifest: use pack home directory to store local manifests
husni-faiz May 9, 2023
6dee05d
manifest: return error instead of calling panic
husni-faiz May 21, 2023
ba95ad8
manifest add: AppendManifest wrapper function will be removed from im…
husni-faiz May 21, 2023
0631b34
manfiest: add remove command
husni-faiz May 23, 2023
605a994
manifest create: remove layout option
husni-faiz May 23, 2023
bb7902e
manifest add: remove redundent code
husni-faiz May 23, 2023
7be9189
manifest annotate: update example to use cnbs/sample-package
husni-faiz May 23, 2023
12b1c0f
manifest create: remove redundant comment
husni-faiz May 23, 2023
1824233
manifest create: simplify the logic for getting the mediatype
husni-faiz May 23, 2023
0b99d2b
manifest command: wrap erros with useful information
husni-faiz May 26, 2023
16b3496
manifest rm: rename file
husni-faiz May 26, 2023
090a0ef
manifest rm: change command name remove to rm
husni-faiz May 26, 2023
802b794
manifest rm: rename file
husni-faiz Jun 1, 2023
6ca7fcc
manifest remove: new command to delete a local index
husni-faiz Jun 1, 2023
bf1503e
manifest inspect: new command to inspect local index
husni-faiz Jun 1, 2023
2b8fdf1
manifest: code formatting
husni-faiz Jun 5, 2023
729c390
go mod tidy: imgutil v1.3.0
husni-faiz Jun 5, 2023
3cf9b10
Merge branch 'main' into test-manifest
jjbustamante Jun 30, 2023
4fe3a96
Merge branch 'main' into test-manifest
husni-faiz Jul 12, 2023
d4f809d
Use imgutil v1.4.0
husni-faiz Jul 12, 2023
ac9855f
fix lint
husni-faiz Jul 12, 2023
2cae965
manifest: make generate
husni-faiz Jul 12, 2023
a504b1a
fix format
husni-faiz Jul 12, 2023
4be0f38
Merge branch 'main' into test-manifest
jjbustamante Sep 20, 2023
1a7a930
WIP added pack manifest cli
WYGIN Dec 15, 2023
8fcb673
WIP updated code as per imgutil's ImageIndex PR
WYGIN Jan 9, 2024
9c52f2d
WIP upgraded imgutil to latest version
WYGIN Jan 22, 2024
13ee7f0
WIP fix some bugs of pack manifest cli
WYGIN Jan 22, 2024
5d5d8ec
WIP fix manifest cli
Feb 6, 2024
c74fe0f
WIP fix bugs related to OSFeatures and Push index
WYGIN Feb 9, 2024
6597bc8
WIP fix bugs related to imgutils
WYGIN Feb 12, 2024
3be294f
Merge branch 'main' into test-manifest
jjbustamante Feb 13, 2024
ddaf6bf
Merge branch 'test-manifest' into image-index
WYGIN Feb 14, 2024
c9e5850
WIP: added couple of tests
WYGIN Feb 19, 2024
5afa60a
added tests for client directive
WYGIN Feb 27, 2024
6d65501
added tests in commands package
WYGIN Feb 28, 2024
71316c3
chore: updated imgutil to latest version
WYGIN Mar 1, 2024
611507b
Merge branch 'main' into test-manifest
jjbustamante Mar 1, 2024
76a3678
refactor: change features, os-features, annotations to relevant flags
WYGIN Mar 4, 2024
0b477b2
fix: bug causing ignore --features, --os-features, --urls, --annotations
WYGIN Mar 4, 2024
83f7539
refactor: improve code readability
WYGIN Mar 30, 2024
94634dc
Merge branch 'main' into test-manifest
jjbustamante Apr 17, 2024
9c52e6a
Merge branch 'test-manifest' into image-index
jjbustamante Apr 17, 2024
ee7c3a3
Merge branch 'main' into test-manifest
jjbustamante Apr 24, 2024
6e65ec8
Merge branch 'test-manifest' into image-index
jjbustamante Apr 24, 2024
5168fa3
Merge pull request #3 from WYGIN/image-index
jjbustamante Apr 24, 2024
0f9c2cf
Merge branch 'deps/jjbustamante/update-to-docker-26' into test-manifest
jjbustamante Apr 24, 2024
64edeba
WIP - doing some refactoring and testing
jjbustamante Apr 26, 2024
33396da
WIP - running go mod tidy
jjbustamante Apr 26, 2024
71dfb60
WIP - fixing lint errors
jjbustamante Apr 26, 2024
7c1fbc3
WIP - fixing TestNewManifestCommand after removing 'exists'
jjbustamante Apr 26, 2024
29776ac
WIP - fixing unit tests
jjbustamante Apr 26, 2024
5f84b74
WIP - restoring .gitpod.yml file and fixing error with client initial…
jjbustamante Apr 26, 2024
e6fb2b7
WIP - removing some unused files
jjbustamante Apr 26, 2024
a657790
Merge branch 'main' into test-manifest
jjbustamante Apr 26, 2024
bf0144a
Merge branch 'main' into test-manifest
jjbustamante Apr 29, 2024
6cc186b
bumping imgutil dependency
jjbustamante Apr 29, 2024
6099f82
removing description from unit test
jjbustamante Apr 29, 2024
8cdc107
adding more test coverage, some refactoring, fixing comments form Nat…
jjbustamante Apr 29, 2024
88ca857
updating publish flag description
jjbustamante Apr 30, 2024
bd58f8d
updating to latest imgutil version, it fixes the issue overriding the…
jjbustamante Apr 30, 2024
59fa667
fixing a problem with the push media-type
jjbustamante Apr 30, 2024
5f1a28c
Fixing Natalie May 1 reviews comments
jjbustamante May 2, 2024
c7d4c06
fixing test
jjbustamante May 2, 2024
c71db73
adding client manifest push commands tests
jjbustamante May 2, 2024
9ae682e
Merge branch 'main' into test-manifest
jjbustamante May 2, 2024
000fb60
updating to docker 26 the last code from main
jjbustamante May 2, 2024
ca37f34
organizing the manifest commands unit test
jjbustamante May 2, 2024
72ae7f2
re-org the rm manifest tests
jjbustamante May 3, 2024
b974278
Merge branch 'main' into test-manifest
jjbustamante May 3, 2024
12cbadf
simplifying the error handling on manifest delete/remove command
jjbustamante May 3, 2024
346fe1b
Merge branch 'main' into test-manifest
jjbustamante May 3, 2024
b2ad463
adding IndexFactory test coverage
jjbustamante May 3, 2024
6e7f0f2
Fixing an error when format is not specified when creating an image i…
jjbustamante May 6, 2024
09a6373
bumping imgutil version to the one with image index implementation
jjbustamante May 7, 2024
922af8b
Adding acceptance test for manifest commands
jjbustamante May 7, 2024
318ad0d
Merge branch 'main' into test-manifest
jjbustamante May 8, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 144 additions & 0 deletions acceptance/acceptance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@ import (
"testing"
"time"

"github.com/buildpacks/imgutil"
"github.com/buildpacks/lifecycle/api"
dockertypes "github.com/docker/docker/api/types"
"github.com/docker/docker/client"
"github.com/google/go-containerregistry/pkg/name"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/types"
"github.com/pelletier/go-toml"
"github.com/sclevine/spec"
"github.com/sclevine/spec/report"
Expand Down Expand Up @@ -623,6 +626,147 @@ func testWithoutSpecificBuilderRequirement(
})
})
})

when("manifest", func() {
var (
indexRepoName string
repoName1 string
repoName2 string
indexLocalPath string
tmpDir string
err error
)

it.Before(func() {
h.SkipIf(t, !pack.SupportsFeature(invoke.ManifestCommands), "pack manifest commands are available since 0.34.0")

// local storage path
tmpDir, err = os.MkdirTemp("", "manifest-commands-test")
assert.Nil(err)
os.Setenv("XDG_RUNTIME_DIR", tmpDir)

// manifest commands are experimental
pack.EnableExperimental()

// used to avoid authentication issues with the local registry
os.Setenv("DOCKER_CONFIG", registryConfig.DockerConfigDir)
})

it.After(func() {
assert.Succeeds(os.RemoveAll(tmpDir))
})

when("create", func() {
it.Before(func() {
it.Before(func() {
indexRepoName = registryConfig.RepoName(h.NewRandomIndexRepoName())

// Manifest 1
repoName1 = fmt.Sprintf("%s:%s", indexRepoName, "busybox-amd64")
h.CreateRemoteImage(t, indexRepoName, "busybox-amd64", "busybox@sha256:a236a6469768c17ca1a6ac81a35fe6fbc1efd76b0dcdf5aebb1cf5f0774ee539")

// Manifest 2
repoName2 = fmt.Sprintf("%s:%s", indexRepoName, "busybox-arm64")
h.CreateRemoteImage(t, indexRepoName, "busybox-arm64", "busybox@sha256:0bcc1b827b855c65eaf6e031e894e682b6170160b8a676e1df7527a19d51fb1a")
})
})
when("--publish", func() {
it("creates and push the index to a remote registry", func() {
output := pack.RunSuccessfully("manifest", "create", "--publish", indexRepoName, repoName1, repoName2)
assertions.NewOutputAssertionManager(t, output).ReportsSuccessfulIndexPushed(indexRepoName)
h.AssertRemoteImageIndex(t, indexRepoName, types.OCIImageIndex, 2)
})
})

when("no --publish", func() {
it("creates the index locally", func() {
output := pack.RunSuccessfully("manifest", "create", indexRepoName, repoName1, repoName2)
assertions.NewOutputAssertionManager(t, output).ReportsSuccessfulIndexLocallyCreated(indexRepoName)

indexLocalPath = filepath.Join(tmpDir, imgutil.MakeFileSafeName(indexRepoName))
index := h.ReadIndexManifest(t, indexLocalPath)
h.AssertEq(t, len(index.Manifests), 2)
h.AssertEq(t, index.MediaType, types.OCIImageIndex)
})
})
})

when("index is already created", func() {
var digest v1.Hash

it.Before(func() {
indexRepoName = registryConfig.RepoName(h.NewRandomIndexRepoName())

// Manifest 1
repoName1 = fmt.Sprintf("%s:%s", indexRepoName, "busybox-amd64")
image1 := h.CreateRemoteImage(t, indexRepoName, "busybox-amd64", "busybox@sha256:a236a6469768c17ca1a6ac81a35fe6fbc1efd76b0dcdf5aebb1cf5f0774ee539")
digest, err = image1.Digest()
assert.Nil(err)

// Manifest 2
repoName2 = fmt.Sprintf("%s:%s", indexRepoName, "busybox-arm64")
h.CreateRemoteImage(t, indexRepoName, "busybox-arm64", "busybox@sha256:0bcc1b827b855c65eaf6e031e894e682b6170160b8a676e1df7527a19d51fb1a")

// create an index locally
pack.RunSuccessfully("manifest", "create", indexRepoName, repoName1)
indexLocalPath = filepath.Join(tmpDir, imgutil.MakeFileSafeName(indexRepoName))
})

when("add", func() {
it("adds the manifest to the index", func() {
output := pack.RunSuccessfully("manifest", "add", indexRepoName, repoName2)
assertions.NewOutputAssertionManager(t, output).ReportsSuccessfulManifestAddedToIndex(repoName2)

index := h.ReadIndexManifest(t, indexLocalPath)
h.AssertEq(t, len(index.Manifests), 2)
h.AssertEq(t, index.MediaType, types.OCIImageIndex)
})
})

when("remove", func() {
it("removes the index from local storage", func() {
output := pack.RunSuccessfully("manifest", "remove", indexRepoName)
assertions.NewOutputAssertionManager(t, output).ReportsSuccessfulIndexDeleted()

h.AssertPathDoesNotExists(t, indexLocalPath)
})
})

when("annotate", func() {
it("adds annotations to the manifest in the index", func() {
output := pack.RunSuccessfully("manifest", "annotate", indexRepoName, repoName1, "--annotations", "foo=bar")
assertions.NewOutputAssertionManager(t, output).ReportsSuccessfulIndexAnnotated(repoName1, indexRepoName)

index := h.ReadIndexManifest(t, indexLocalPath)
h.AssertEq(t, len(index.Manifests), 1)
h.AssertEq(t, len(index.Manifests[0].Annotations), 1)
})
})

when("rm", func() {
it.Before(func() {
// we need to point to the manifest digest we want to delete
repoName1 = fmt.Sprintf("%s@%s", repoName1, digest.String())
})

it("removes the manifest from the index", func() {
output := pack.RunSuccessfully("manifest", "rm", indexRepoName, repoName1)
assertions.NewOutputAssertionManager(t, output).ReportsSuccessfulRemoveManifestFromIndex(indexRepoName)

index := h.ReadIndexManifest(t, indexLocalPath)
h.AssertEq(t, len(index.Manifests), 0)
})
})

when("push", func() {
it("pushes the index to a remote registry", func() {
output := pack.RunSuccessfully("manifest", "push", indexRepoName)
assertions.NewOutputAssertionManager(t, output).ReportsSuccessfulIndexPushed(indexRepoName)
h.AssertRemoteImageIndex(t, indexRepoName, types.OCIImageIndex, 1)
})
})
})
})
}

func testAcceptance(
Expand Down
36 changes: 36 additions & 0 deletions acceptance/assertions/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,42 @@ func (o OutputAssertionManager) ReportsSuccessfulImageBuild(name string) {
o.assert.ContainsF(o.output, "Successfully built image '%s'", name)
}

func (o OutputAssertionManager) ReportsSuccessfulIndexLocallyCreated(name string) {
o.testObject.Helper()

o.assert.ContainsF(o.output, "Successfully created manifest list '%s'", name)
}

func (o OutputAssertionManager) ReportsSuccessfulIndexPushed(name string) {
o.testObject.Helper()

o.assert.ContainsF(o.output, "Successfully pushed manifest list '%s' to registry", name)
}

func (o OutputAssertionManager) ReportsSuccessfulManifestAddedToIndex(name string) {
o.testObject.Helper()

o.assert.ContainsF(o.output, "Successfully added image '%s' to index", name)
}

func (o OutputAssertionManager) ReportsSuccessfulIndexDeleted() {
o.testObject.Helper()

o.assert.Contains(o.output, "Successfully deleted manifest list(s) from local storage")
}

func (o OutputAssertionManager) ReportsSuccessfulIndexAnnotated(name, manifest string) {
o.testObject.Helper()

o.assert.ContainsF(o.output, "Successfully annotated image '%s' in index '%s'", name, manifest)
}

func (o OutputAssertionManager) ReportsSuccessfulRemoveManifestFromIndex(name string) {
o.testObject.Helper()

o.assert.ContainsF(o.output, "Successfully removed image(s) from index: '%s'", name)
}

func (o OutputAssertionManager) ReportSuccessfulQuietBuild(name string) {
o.testObject.Helper()
o.testObject.Log("quiet mode")
Expand Down
4 changes: 4 additions & 0 deletions acceptance/invoke/pack.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ const (
PlatformRetries
FlattenBuilderCreationV2
FixesRunImageMetadata
ManifestCommands
)

var featureTests = map[Feature]func(i *PackInvoker) bool{
Expand Down Expand Up @@ -274,6 +275,9 @@ var featureTests = map[Feature]func(i *PackInvoker) bool{
FixesRunImageMetadata: func(i *PackInvoker) bool {
return i.atLeast("v0.34.0")
},
ManifestCommands: func(i *PackInvoker) bool {
return i.atLeast("v0.34.0")
},
}

func (i *PackInvoker) SupportsFeature(f Feature) bool {
Expand Down
1 change: 1 addition & 0 deletions cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ func NewPackCommand(logger ConfigurableLogger) (*cobra.Command, error) {
rootCmd.AddCommand(commands.SetDefaultRegistry(logger, cfg, cfgPath))
rootCmd.AddCommand(commands.RemoveRegistry(logger, cfg, cfgPath))
rootCmd.AddCommand(commands.YankBuildpack(logger, cfg, packClient))
rootCmd.AddCommand(commands.NewManifestCommand(logger, packClient))
}

packHome, err := config.PackHome()
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ require (
github.com/Masterminds/semver v1.5.0
github.com/Microsoft/go-winio v0.6.2
github.com/apex/log v1.9.0
github.com/buildpacks/imgutil v0.0.0-20240422175901-30b002586ecc
github.com/buildpacks/imgutil v0.0.0-20240507132533-9f7b96c3d09d
github.com/buildpacks/lifecycle v0.19.4
github.com/docker/cli v26.0.1+incompatible
github.com/docker/docker v26.1.1+incompatible
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/buildpacks/imgutil v0.0.0-20240422175901-30b002586ecc h1:Pxgpm4bIjgWY9a8r8xHlMYp6wzm5hIZHtw4Iux3XA0c=
github.com/buildpacks/imgutil v0.0.0-20240422175901-30b002586ecc/go.mod h1:n2R6VRuWsAX3cyHCp/u0Z4WJcixny0gYg075J39owrk=
github.com/buildpacks/imgutil v0.0.0-20240507132533-9f7b96c3d09d h1:GVRuY/C8j4pjOddeeZelbKKLMMX+dYR3TlxE4L1hECU=
github.com/buildpacks/imgutil v0.0.0-20240507132533-9f7b96c3d09d/go.mod h1:n2R6VRuWsAX3cyHCp/u0Z4WJcixny0gYg075J39owrk=
github.com/buildpacks/lifecycle v0.19.4 h1:lATTWyMs4m4+3+n6PgvmB0lBgut2+b8eZ+iu/wXwhrI=
github.com/buildpacks/lifecycle v0.19.4/go.mod h1:sWrBJzf/7dWrcHrWiV/P2+3jS8G8Ki5tczq8jO3XVRQ=
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
Expand Down
2 changes: 1 addition & 1 deletion internal/commands/buildpack_inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func BuildpackInspect(logger logging.Logger, cfg config.Config, client PackClien
return cmd
}

func buildpackInspect(logger logging.Logger, buildpackName, registryName string, flags BuildpackInspectFlags, cfg config.Config, pack PackClient) error {
func buildpackInspect(logger logging.Logger, buildpackName, registryName string, flags BuildpackInspectFlags, _ config.Config, pack PackClient) error {
logger.Infof("Inspecting buildpack: %s\n", style.Symbol(buildpackName))

inspectedBuildpacksOutput, err := inspectAllBuildpacks(
Expand Down
21 changes: 21 additions & 0 deletions internal/commands/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"os/signal"
"syscall"

"github.com/google/go-containerregistry/pkg/v1/types"
"github.com/pkg/errors"
"github.com/spf13/cobra"

Expand All @@ -32,6 +33,13 @@ type PackClient interface {
InspectExtension(client.InspectExtensionOptions) (*client.ExtensionInfo, error)
PullBuildpack(context.Context, client.PullBuildpackOptions) error
DownloadSBOM(name string, options client.DownloadSBOMOptions) error
CreateManifest(ctx context.Context, opts client.CreateManifestOptions) error
AnnotateManifest(ctx context.Context, opts client.ManifestAnnotateOptions) error
AddManifest(ctx context.Context, opts client.ManifestAddOptions) error
DeleteManifest(name []string) error
RemoveManifest(name string, images []string) error
PushManifest(client.PushManifestOptions) error
InspectManifest(string) error
}

func AddHelpFlag(cmd *cobra.Command, commandName string) {
Expand Down Expand Up @@ -107,3 +115,16 @@ func isTrustedBuilder(cfg config.Config, builder string) bool {
func deprecationWarning(logger logging.Logger, oldCmd, replacementCmd string) {
logger.Warnf("Command %s has been deprecated, please use %s instead", style.Symbol("pack "+oldCmd), style.Symbol("pack "+replacementCmd))
}

func parseFormatFlag(value string) (types.MediaType, error) {
var format types.MediaType
switch value {
case "oci":
format = types.OCIImageIndex
case "docker":
format = types.DockerManifestList
default:
return format, errors.Errorf("%s invalid media type format", value)
}
return format, nil
}
2 changes: 1 addition & 1 deletion internal/commands/extension_inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func ExtensionInspect(logger logging.Logger, cfg config.Config, client PackClien
return cmd
}

func extensionInspect(logger logging.Logger, extensionName string, cfg config.Config, pack PackClient) error {
func extensionInspect(logger logging.Logger, extensionName string, _ config.Config, pack PackClient) error {
logger.Infof("Inspecting extension: %s\n", style.Symbol(extensionName))

inspectedExtensionsOutput, err := inspectAllExtensions(
Expand Down
33 changes: 33 additions & 0 deletions internal/commands/manifest.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package commands

import (
"github.com/spf13/cobra"

"github.com/buildpacks/pack/pkg/logging"
)

func NewManifestCommand(logger logging.Logger, client PackClient) *cobra.Command {
cmd := &cobra.Command{
Use: "manifest",
Short: "Interact with OCI image indexes",
Long: `An image index is a higher-level manifest which points to specific image manifests and is ideal for one or more platforms; see: https://github.com/opencontainers/image-spec/ for more details

'pack manifest' commands provide tooling to create, update, or delete images indexes or push them to a remote registry.
'pack' will save a local copy of the image index at '$PACK_HOME/manifests'; the environment variable 'XDG_RUNTIME_DIR'
can be set to override the location, allowing manifests to be edited locally before being pushed to a registry.

These commands are experimental. For more information, consult the RFC which can be found at https://github.com/buildpacks/rfcs/blob/main/text/0124-pack-manifest-list-commands.md`,
RunE: nil,
}

cmd.AddCommand(ManifestCreate(logger, client))
cmd.AddCommand(ManifestAdd(logger, client))
cmd.AddCommand(ManifestAnnotate(logger, client))
cmd.AddCommand(ManifestDelete(logger, client))
cmd.AddCommand(ManifestInspect(logger, client))
cmd.AddCommand(ManifestPush(logger, client))
cmd.AddCommand(ManifestRemove(logger, client))

AddHelpFlag(cmd, "manifest")
return cmd
}
27 changes: 27 additions & 0 deletions internal/commands/manifest_add.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package commands

import (
"github.com/spf13/cobra"

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

// ManifestAdd adds a new image to a manifest list (image index).
func ManifestAdd(logger logging.Logger, pack PackClient) *cobra.Command {
cmd := &cobra.Command{
Use: "add [OPTIONS] <manifest-list> <manifest> [flags]",
Args: cobra.MatchAll(cobra.ExactArgs(2), cobra.OnlyValidArgs),
Short: "Add an image to a manifest list.",
Example: `pack manifest add my-image-index my-image:some-arch`,
RunE: logError(logger, func(cmd *cobra.Command, args []string) (err error) {
return pack.AddManifest(cmd.Context(), client.ManifestAddOptions{
IndexRepoName: args[0],
RepoName: args[1],
})
}),
}

AddHelpFlag(cmd, "add")
return cmd
}
Loading
Loading