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

Repo Index #730

Merged
merged 46 commits into from
Aug 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
9c7a6ab
Feature package command
kensipe Jul 26, 2019
7d7b21a
add afero as a file system abstraction. Tests currently still use OsFs
kensipe Aug 2, 2019
bb13f23
adding in checks for tarball creation
kensipe Aug 5, 2019
3ce5768
happy linter.. happy life
kensipe Aug 5, 2019
154cbfa
tar test written for in-mem
kensipe Aug 5, 2019
e6042ad
hash on gzip is problematic, tar and untar with a check of a file is …
kensipe Aug 5, 2019
be0c21a
switched to using testdata for package cmd test
kensipe Aug 6, 2019
2058b09
linter needs to be my precondition of git push
kensipe Aug 6, 2019
62f2564
reducing visiblity of fs
kensipe Aug 6, 2019
d6b9090
tarball code needs to use tarball writer
kensipe Aug 6, 2019
7f0634b
move afero out of main and into cmd package
kensipe Aug 6, 2019
615a323
Apply suggestions from code review
kensipe Aug 7, 2019
b9b1ec4
updates based on pr feedback
kensipe Aug 7, 2019
d2d76a5
adding details based on PR feedback
kensipe Aug 7, 2019
d22b67c
start of repo cmd
kensipe Aug 6, 2019
c6e980b
todo list
kensipe Aug 6, 2019
12d12bb
temp stop
kensipe Aug 7, 2019
2d2e0df
Merge branch 'master' into ken/repo-index
kensipe Aug 8, 2019
8f055f2
merge to master complete
kensipe Aug 8, 2019
090d06d
tests for bundle verisons and index files
kensipe Aug 9, 2019
8763b0a
switched bundle for package
kensipe Aug 9, 2019
c81348a
mapping package files to package versions with tests
kensipe Aug 9, 2019
dd7398d
adding newIndexFile function and updated tests
kensipe Aug 9, 2019
2c3ec82
adding url component to index
kensipe Aug 12, 2019
c8486d8
latest
kensipe Aug 12, 2019
855ed8a
Merge branch 'master' into ken/repo-index
kensipe Aug 12, 2019
e723dd9
tar to crd to package
kensipe Aug 12, 2019
06a851c
working index
kensipe Aug 14, 2019
f338190
Merge branch 'master' into ken/repo-index
kensipe Aug 14, 2019
48e6332
Merge branch 'master' into ken/repo-index
kensipe Aug 15, 2019
30bcbc2
grammar fix
kensipe Aug 16, 2019
a2ec239
removed apivresion from index
kensipe Aug 16, 2019
cb70549
adding appVersion to metadata and min k8s version is 1.15.0
kensipe Aug 16, 2019
0c6b8ca
remove create date to packages
kensipe Aug 16, 2019
5c04ea4
writing from cmd
kensipe Aug 16, 2019
8f0aaa2
Merge branch 'master' into ken/repo-index
kensipe Aug 16, 2019
adcd1f3
renaming source file name
kensipe Aug 19, 2019
841283b
clean up
kensipe Aug 19, 2019
b9015e8
code and comment cleanup
kensipe Aug 19, 2019
39405b2
refactor to index
kensipe Aug 19, 2019
04a49e1
Merge branch 'master' into ken/repo-index
kensipe Aug 19, 2019
db14af4
happy linter happy life
kensipe Aug 19, 2019
429157d
Apply suggestions from code review
kensipe Aug 21, 2019
1bdeb00
updates based on pr feedback
kensipe Aug 21, 2019
b7cca7f
update based on pr feedback
kensipe Aug 21, 2019
7e49009
update desc for length
kensipe Aug 21, 2019
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 go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ require (
github.com/huandu/xstrings v1.2.0 // indirect
github.com/imdario/mergo v0.3.7 // indirect
github.com/leodido/go-urn v1.1.0 // indirect
github.com/magiconair/properties v1.8.0
github.com/markbates/inflect v1.0.4 // indirect
github.com/masterminds/sprig v2.18.0+incompatible
github.com/onsi/ginkgo v1.7.0 // indirect
Expand Down
1 change: 1 addition & 0 deletions pkg/bundle/operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type Operator struct {
Name string `json:"name"`
Description string `json:"description,omitempty"`
Version string `json:"version"`
AppVersion string `json:"appVersion,omitempty"`
KUDOVersion string `json:"kudoVersion,omitempty"`
KubernetesVersion string `json:"kubernetesVersion,omitempty"`
Maintainers []v1alpha1.Maintainer `json:"maintainers,omitempty"`
Expand Down
48 changes: 18 additions & 30 deletions pkg/kudoctl/bundle/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import (
"io"
"io/ioutil"
"os"
"path/filepath"
"strings"

"github.com/kudobuilder/kudo/pkg/kudoctl/files"

"github.com/pkg/errors"
"github.com/spf13/afero"
)
Expand All @@ -19,7 +20,10 @@ import (

// Bundle is an abstraction of the collection of files that makes up a package. It is anything we can retrieve the PackageCRDs from.
type Bundle interface {
// transformed server view
GetCRDs() (*PackageCRDs, error)
// working with local package files
GetPkgFiles() (*PackageFiles, error)
}

type tarBundle struct {
Expand Down Expand Up @@ -68,23 +72,32 @@ func NewBundleFromReader(r io.Reader) Bundle {
return tarBundle{r}
}

func (b tarBundle) GetCRDs() (*PackageCRDs, error) {
// GetPkgFiles returns the command side package files
func (b tarBundle) GetPkgFiles() (*PackageFiles, error) {
return parseTarPackage(b.reader)
}

p, err := parseTarPackage(b.reader)
// GetCRDs returns the server side CRDs
func (b tarBundle) GetCRDs() (*PackageCRDs, error) {
p, err := b.GetPkgFiles()
if err != nil {
return nil, errors.Wrap(err, "while extracting package files")
}
return p.getCRDs()
}

func (b fileBundle) GetCRDs() (*PackageCRDs, error) {
p, err := fromFolder(b.fs, b.path)
p, err := b.GetPkgFiles()
if err != nil {
return nil, errors.Wrap(err, "while reading package from the file system")
}
return p.getCRDs()
}

func (b fileBundle) GetPkgFiles() (*PackageFiles, error) {
return fromFolder(b.fs, b.path)
}

// ToTarBundle takes a path to operator files and creates a tgz of those files with the destination and name provided
func ToTarBundle(fs afero.Fs, path string, destination string, overwrite bool) (string, error) {
pkg, err := fromFolder(fs, path)
Expand All @@ -93,7 +106,7 @@ func ToTarBundle(fs afero.Fs, path string, destination string, overwrite bool) (
}

name := packageVersionedName(pkg)
target, e := getFullPathToTarget(fs, destination, name, overwrite)
target, e := files.FullPathToTarget(fs, destination, fmt.Sprintf("%v.tgz", name), overwrite)
if e != nil {
return "", e
}
Expand All @@ -111,31 +124,6 @@ func ToTarBundle(fs afero.Fs, path string, destination string, overwrite bool) (
return target, err
}

// getFullPathToTarget takes destination path and file name and provides a clean full path while ensure the file does not exist.
func getFullPathToTarget(fs afero.Fs, destination string, name string, overwrite bool) (string, error) {
if destination == "." {
destination = ""
}
if destination != "" {
if strings.Contains(destination, "~") {
userHome, _ := os.UserHomeDir()
destination = strings.Replace(destination, "~", userHome, 1)
}
fi, err := fs.Stat(destination)
if err != nil || !fi.Mode().IsDir() {
return "", fmt.Errorf("destination \"%v\" is not a proper directory", destination)
}
name = filepath.Join(destination, name)
}
target := filepath.Clean(fmt.Sprintf("%v.tgz", name))
if exists, _ := afero.Exists(fs, target); exists {
if !overwrite {
return "", fmt.Errorf("target file exists. Remove or --overwrite. File:%v", target)
}
}
return target, nil
}

// packageVersionedName provides the version name of a package provided a set of PackageFiles. Ex. "zookeeper-0.1.0"
func packageVersionedName(pkg *PackageFiles) string {
return fmt.Sprintf("%v-%v", pkg.Operator.Name, pkg.Operator.Version)
Expand Down
66 changes: 62 additions & 4 deletions pkg/kudoctl/bundle/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,21 @@ package bundle

import (
"fmt"
"io"
"regexp"
"strconv"
"strings"

"github.com/kudobuilder/kudo/pkg/util/kudo"

"k8s.io/apimachinery/pkg/util/rand"

"github.com/kudobuilder/kudo/pkg/apis/kudo/v1alpha1"
"github.com/kudobuilder/kudo/pkg/bundle"
"github.com/kudobuilder/kudo/pkg/kudoctl/files"
"github.com/kudobuilder/kudo/pkg/util/kudo"

"github.com/pkg/errors"
"github.com/spf13/afero"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/rand"
"sigs.k8s.io/yaml"
)

Expand All @@ -41,6 +43,12 @@ type PackageFiles struct {
Params []v1alpha1.Parameter
}

// PackageFilesDigest is a tuple of data used to return the package files AND the digest of a tarball
type PackageFilesDigest struct {
PkgFiles *PackageFiles
Digest string
}

func parsePackageFile(filePath string, fileBytes []byte, currentPackage *PackageFiles) error {
isOperatorFile := func(name string) bool {
return strings.HasSuffix(name, operatorFileName)
Expand Down Expand Up @@ -196,3 +204,53 @@ func (p *PackageFiles) getCRDs() (*PackageCRDs, error) {
Instance: instance,
}, nil
}

// GetFilesDigest maps []string of paths to the [] Operators
func GetFilesDigest(fs afero.Fs, paths []string) []*PackageFilesDigest {
return mapPaths(fs, paths, pathToOperator)
}

// work of map path, swallows errors to return only packages that are valid
func mapPaths(fs afero.Fs, paths []string, f func(afero.Fs, string) (*PackageFilesDigest, error)) []*PackageFilesDigest {
ops := make([]*PackageFilesDigest, 0)
for _, path := range paths {
op, err := f(fs, path)
if err != nil {
fmt.Printf("WARNING: operator: %v is invalid", path)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use log.Println() instead? Or at least print to stderr.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets let this go... we don't have proper logging yet and I have a PR that is built off this PR which introduces a debug flag with debug printing. This seems like something that should be a debug print out. (or logging).

continue
}
ops = append(ops, op)
}

return ops
}

// pathToOperator takes a single path and returns an operator or error
func pathToOperator(fs afero.Fs, path string) (*PackageFilesDigest, error) {
reader, err := fs.Open(path)
if err != nil {
return nil, err
}
digest, err := files.Sha256Sum(reader)
if err != nil {
return nil, err
}
// restart reading of file after getting digest
reader.Seek(0, io.SeekStart)

pkg, err := readerToOperator(reader)
pfd := &PackageFilesDigest{
pkg,
digest,
}
return pfd, err
}

func readerToOperator(r io.Reader) (*PackageFiles, error) {
b := NewBundleFromReader(r)
pkg, err := b.GetPkgFiles()
if err != nil {
return nil, err
}
return pkg, nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ spec:
maintainers:
- Alena Varkockova <avarkockova@mesosphere.com>
- Tom Runyon <runyontr@gmail.com>
- Ken Sipe <kensipe@gmail.com>
kudoVersion: 0.2.0
kubernetesVersion: 1.5.1
kubernetesVersion: 1.15.0
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ spec:
maintainers:
- Alena Varkockova <avarkockova@mesosphere.com>
- Tom Runyon <runyontr@gmail.com>
- Ken Sipe <kensipe@gmail.com>
kudoVersion: 0.2.0
kubernetesVersion: 1.5.1
kubernetesVersion: 1.15.0
Binary file modified pkg/kudoctl/bundle/testdata/zk.tar.gz
Binary file not shown.
4 changes: 3 additions & 1 deletion pkg/kudoctl/bundle/testdata/zk/operator.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
name: "zookeeper"
version: "0.1.0"
appVersion: "3.4.10"
kudoVersion: 0.2.0
kubernetesVersion: 1.5.1
kubernetesVersion: 1.15.0
maintainers:
- Alena Varkockova <avarkockova@mesosphere.com>
- Tom Runyon <runyontr@gmail.com>
- Ken Sipe <kensipe@gmail.com>
url: https://zookeeper.apache.org/
tasks:
infra:
Expand Down
3 changes: 3 additions & 0 deletions pkg/kudoctl/cmd/package_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cmd

import (
"os"
"path/filepath"
"testing"

"github.com/kudobuilder/kudo/pkg/kudoctl/files"
Expand All @@ -22,6 +23,8 @@ var packageCmdArgs = []struct {

func TestTableNewBundleCmd(t *testing.T) {
fs := afero.NewMemMapFs()
testdir, _ := filepath.Abs("")
fs.Mkdir(testdir, 0777)
files.CopyOperatorToFs(fs, "../bundle/testdata/zk", "/opt")
for _, test := range packageCmdArgs {
newCmdBundle := newPackageCmd(fs, os.Stdout)
Expand Down
29 changes: 29 additions & 0 deletions pkg/kudoctl/cmd/repo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package cmd

import (
"io"

"github.com/spf13/afero"
"github.com/spf13/cobra"
)

const repoDesc = `
This command consists of multiple sub-commands to interact with KUDO repositories.

It can be used to add, remove, list, and index kudo repositories.
Example usage:
$ kubectl kudo repo add [NAME] [REPO_URL]`

// newRepoCmd for repo commands such as building a repo index
func newRepoCmd(fs afero.Fs, out io.Writer) *cobra.Command {
cmd := &cobra.Command{
Use: "repo [FLAGS] add|remove|list|index| update [ARGS]",
Short: "Package an official KUDO operator.",
Long: `Add, list, remove, update, and index kudo repositories`,
Example: repoDesc,
}

cmd.AddCommand(newRepoIndexCmd(fs, out))

return cmd
}
82 changes: 82 additions & 0 deletions pkg/kudoctl/cmd/repo_index.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package cmd

import (
"fmt"
"io"
"time"

"github.com/kudobuilder/kudo/pkg/kudoctl/files"
"github.com/kudobuilder/kudo/pkg/kudoctl/util/repo"

"github.com/spf13/afero"
"github.com/spf13/cobra"
)

const repoIndexDesc = `
Read the provided directory and generate an index file based on the packages found.

This tool is used for creating an 'index.yaml' file for a KUDO package repository. To
set an absolute URL to the operators, use '--url' flag.

# Create an index file for all KUDO packages in the repo-dir.
$ kubectl kudo repo index repo-dir`

type repoIndexCmd struct {
path string
url string
overwrite bool
out io.Writer
fs afero.Fs
}

// newRepoIndexCmd for repo commands such as building a repo index file.
func newRepoIndexCmd(fs afero.Fs, out io.Writer) *cobra.Command {
index := &repoIndexCmd{out: out, fs: fs}
cmd := &cobra.Command{
Use: "index [flags] <DIR>",
Short: "Generate an index file given a directory containing KUDO packages",
Long: repoIndexDesc,
RunE: func(cmd *cobra.Command, args []string) error {
if err := validateRepoIndex(args); err != nil {
return err
}
index.path = args[0]
if err := index.run(); err != nil {
return err
}
return nil
},
SilenceUsage: true,
}

f := cmd.Flags()
f.StringVar(&index.url, "url", "", "URL of the operator repository")
f.BoolVarP(&index.overwrite, "overwrite", "o", false, "Overwrite existing package")

return cmd
}

func validateRepoIndex(args []string) error {
if len(args) != 1 {
return fmt.Errorf("expecting exactly one argument - directory containing the operators to package")
}
return nil
}

// run returns the errors associated with cmd env
func (ri *repoIndexCmd) run() error {
target, err := files.FullPathToTarget(ri.fs, ri.path, "index.yaml", ri.overwrite)
if err != nil {
return err
}

t := time.Now()
i, err := repo.IndexDirectory(ri.fs, ri.path, ri.url, &t)
if err != nil {
return err
}

i.WriteFile(fs, target)
fmt.Fprintf(ri.out, "index %v created.\n", target)
return nil
}
1 change: 1 addition & 0 deletions pkg/kudoctl/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ and serves as an API aggregation layer.
cmd.AddCommand(newPackageCmd(fs, cmd.OutOrStdout()))
cmd.AddCommand(newGetCmd())
cmd.AddCommand(newPlanCmd())
cmd.AddCommand(newRepoCmd(fs, cmd.OutOrStdout()))
cmd.AddCommand(newTestCmd())
cmd.AddCommand(newVersionCmd())
cmd.PersistentFlags().String("kubeconfig", os.Getenv("HOME")+"/.kube/config", "Path to your Kubernetes configuration file")
Expand Down
Loading