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

command added to list-packages from package repository #1360

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions cli/pkg/kctrl/cmd/kctrl.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ func AddPackageCommands(o *KctrlOptions, cmd *cobra.Command, flagsFactory cmdcor
cmdcore.PackageAuthoringCommandsHelpGroup,
}))
pkgrepoCmd.AddCommand(pkgrepo.NewListCmd(pkgrepo.NewListOptions(o.ui, o.depsFactory, o.logger, opts), flagsFactory))
pkgrepoCmd.AddCommand(pkgrepo.NewListPackagesCmd(pkgrepo.NewListPackagesOptions(o.ui, o.logger, opts), flagsFactory))
pkgrepoCmd.AddCommand(pkgrepo.NewGetCmd(pkgrepo.NewGetOptions(o.ui, o.depsFactory, o.logger, opts), flagsFactory))
pkgrepoCmd.AddCommand(pkgrepo.NewDeleteCmd(pkgrepo.NewDeleteOptions(o.ui, o.depsFactory, o.logger, opts), flagsFactory))
pkgrepoCmd.AddCommand(pkgrepo.NewAddCmd(pkgrepo.NewAddOrUpdateOptions(o.ui, o.depsFactory, o.logger, opts), flagsFactory))
Expand Down
127 changes: 127 additions & 0 deletions cli/pkg/kctrl/cmd/package/repository/list-packages.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package repository

import (
"bytes"
"fmt"
"os"
"path/filepath"
"strings"

goexec "os/exec"

"github.com/cppforlife/go-cli-ui/ui"
uitable "github.com/cppforlife/go-cli-ui/ui/table"
"github.com/spf13/cobra"
cmdcore "github.com/vmware-tanzu/carvel-kapp-controller/cli/pkg/kctrl/cmd/core"
lclcfg "github.com/vmware-tanzu/carvel-kapp-controller/cli/pkg/kctrl/local"
"github.com/vmware-tanzu/carvel-kapp-controller/cli/pkg/kctrl/logger"
)

type ListPackagesOptions struct {
ui ui.UI
logger logger.Logger
pkgCmdTreeOpts cmdcore.PackageCommandTreeOpts
URL string
}

func NewListPackagesOptions(ui ui.UI, logger logger.Logger, pkgCmdTreeOpts cmdcore.PackageCommandTreeOpts) *ListPackagesOptions {
return &ListPackagesOptions{ui: ui, logger: logger, pkgCmdTreeOpts: pkgCmdTreeOpts}
}

func NewListPackagesCmd(o *ListPackagesOptions, flagsFactory cmdcore.FlagsFactory) *cobra.Command {
cmd := &cobra.Command{
Use: "list-packages",
Aliases: []string{"lp", "ls-p"},
Short: "List packages from a package repository from the given URL",
RunE: func(_ *cobra.Command, _ []string) error { return o.Run() },
Example: cmdcore.Examples{
cmdcore.Example{"List package repositories",
[]string{"package", "repository", "list-packages", "--url", "<package-repository-url>"},
},
}.Description("", o.pkgCmdTreeOpts),
SilenceUsage: true,
Annotations: map[string]string{"table": "",
cmdcore.PackageManagementCommandsHelpGroup.Key: cmdcore.PackageManagementCommandsHelpGroup.Value},
}

cmd.Flags().StringVarP(&o.URL, "url", "u", "", "Package repository URL")
cmd.MarkFlagRequired(o.URL)

return cmd
}

func (o *ListPackagesOptions) Run() error {
if len(o.URL) == 0 {
return fmt.Errorf("Expected package repository url to be non-empty")
}

configs, err := LoadImgpkgBundleToConfigs(o.ui, o.URL)
if err != nil {
return err
}

tableTitle := fmt.Sprintf("Listing Packages from Package Repository '%s'", o.URL)
table := uitable.Table{
Title: tableTitle,

Header: []uitable.Header{
uitable.NewHeader("Name"),
uitable.NewHeader("Version"),
},

SortBy: []uitable.ColumnSort{
{Column: 0, Asc: true},
{Column: 1, Asc: true},
},
}

for _, pkg := range configs.Pkgs {
table.Rows = append(table.Rows, []uitable.Value{
uitable.NewValueString(pkg.Spec.RefName),
uitable.NewValueString(pkg.Spec.Version),
})
}

o.ui.PrintTable(table)
return nil
}

func LoadImgpkgBundleToConfigs(ui ui.UI, bundleURL string) (lclcfg.Configs, error) {
var configs lclcfg.Configs
tmpDir, err := os.MkdirTemp(".", fmt.Sprintf("bundle-%s-*", strings.Replace(bundleURL, "/", "-", -1)))
if err != nil {
return configs, err
}
defer os.RemoveAll(tmpDir)

cmd := goexec.Command("imgpkg", "pull", "-b", bundleURL, "-o", tmpDir, "--tty=true")
ui.PrintLinef(fmt.Sprintf("$ %s", strings.Join(cmd.Args, " ")))

var stdoutBuf, stderrBuf bytes.Buffer
cmd.Stdout = &stdoutBuf
cmd.Stderr = &stderrBuf
err = cmd.Run()
if err != nil {
return configs, fmt.Errorf("%s", stderrBuf.String())
}
ui.PrintLinef(stdoutBuf.String())

filePaths := []string{}
err = filepath.Walk(tmpDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil
}
filePaths = append(filePaths, path)
return nil
})

if err != nil {
return configs, err
}

configs, err = lclcfg.NewConfigFromFiles(filePaths)
return configs, nil
}
8 changes: 8 additions & 0 deletions cli/pkg/kctrl/local/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,19 @@ func NewConfigFromFiles(paths []string) (Configs, error) {
}
configs.PkgInstalls = append(configs.PkgInstalls, pkgi)

case res.APIVersion == "imgpkg.carvel.dev/v1alpha1" && res.Kind == "ImagesLock", // ignoring images Lockfile
res.APIVersion == "data.packaging.carvel.dev/v1alpha1" && res.Kind == "PackageExtra",
// ignoring docs with comments
res.APIVersion == "" && res.Kind == "":
break

default:
return fmt.Errorf("Unknown apiVersion '%s' or kind '%s' for resource",
res.APIVersion, res.Kind)
}
return nil
})

if err != nil {
return configs, err
}
Expand Down Expand Up @@ -189,6 +196,7 @@ func parseResources(paths []string, resourceFunc func([]byte) error) error {
return fmt.Errorf("Parsing resource config '%s': %s", path, err)
}
}

}
return nil
}
25 changes: 25 additions & 0 deletions cli/test/e2e/package_repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,31 @@ func TestPackageRepository(t *testing.T) {
require.Error(t, err)
})

logger.Section("list packages from a package repository", func() {
out, _ := kappCtrl.RunWithOpts([]string{"package", "repository", "list-packages", "--url", pkgrURL, "--json"}, RunOpts{NoNamespace: true})
output := uitest.JSONUIFromBytes(t, []byte(out))
expectedOutputRows := []map[string]string{{
"name": "pkg.test.carvel.dev",
"version": "1.0.0",
}, {
"name": "pkg.test.carvel.dev",
"version": "2.0.0",
}, {
"name": "pkg.test.carvel.dev",
"version": "3.0.0-rc.1",
}}

require.Exactly(t, expectedOutputRows, output.Tables[0].Rows)
})

logger.Section("list packages from a package repository with invalid URL", func() {
pkgrURL := "index.docker.io/k8slt/kc-e2e-test-repo:invalid"
_, err := kappCtrl.RunWithOpts([]string{"package", "repository", "list-packages", "--url", pkgrURL, "--json"}, RunOpts{
NoNamespace: true, AllowError: true})
require.Contains(t, err.Error(), "MANIFEST_UNKNOWN: manifest unknown")

})

logger.Section("adding a repository", func() {
kappCtrl.Run([]string{"package", "repository", "add", "-r", pkgrName, "--url", pkgrURL})

Expand Down