Skip to content

Commit

Permalink
Merge pull request #5 from alenkacz/av/cli-improvement-improvement
Browse files Browse the repository at this point in the history
Read bundles from memory, no local repo. Small fixes
  • Loading branch information
fabianbaier committed Jun 5, 2019
2 parents fe819bf + e0c8c19 commit 53ec610
Show file tree
Hide file tree
Showing 10 changed files with 117 additions and 287 deletions.
122 changes: 22 additions & 100 deletions pkg/kudoctl/cmd/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,22 @@ package install

import (
"fmt"
"io/ioutil"
"os"
"strings"

"github.com/kudobuilder/kudo/pkg/apis/kudo/v1alpha1"
"github.com/kudobuilder/kudo/pkg/kudoctl/util/repo"
"sigs.k8s.io/yaml"

"github.com/kudobuilder/kudo/pkg/kudoctl/util/check"
"github.com/kudobuilder/kudo/pkg/kudoctl/util/helpers"
"github.com/kudobuilder/kudo/pkg/kudoctl/util/kudo"
"github.com/kudobuilder/kudo/pkg/kudoctl/util/repo"
"github.com/kudobuilder/kudo/pkg/kudoctl/util/vars"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"k8s.io/client-go/tools/clientcmd"
)

const (
bundlePath = "%s/%s"
fwPath = "%s/%s-framework.yaml"
fwVersionPath = "%s/%s-frameworkversion.yaml"
fwInstancePath = "%s/%s-instance.yaml"
)

// CmdErrorProcessor returns the errors associated with cmd env
func CmdErrorProcessor(cmd *cobra.Command, args []string) error {

// default repo hardcoded for 0.2.0
// this won't work on windows
vars.RepoPath = ".kudo/repository"

// This makes --kubeconfig flag optional
if _, err := cmd.Flags().GetString("kubeconfig"); err != nil {
return fmt.Errorf("get flag: %+v", err)
Expand All @@ -42,13 +27,6 @@ func CmdErrorProcessor(cmd *cobra.Command, args []string) error {
return errors.WithMessage(err, "could not check kubeconfig path")
}

// Checking repo path of provided parameter or env variable, if none provided looking up default directory
if err := check.RepoPath(); err != nil {
if err = helpers.CreateRepoPath(); err != nil {
return errors.WithMessage(err, "could not create repo path")
}
}

if err := verifyFrameworks(args); err != nil {
return errors.WithMessage(err, "could not install framework(s)")
}
Expand Down Expand Up @@ -119,64 +97,55 @@ func verifySingleFramework(name, previous string, r repo.FrameworkRepository, i
bundleVersion = bv
}

// checking if bundle exists locally already
bundleName := bundleVersion.Name + "-" + bundleVersion.Version
bundlePath := fmt.Sprintf(bundlePath, vars.RepoPath, bundleName)

if _, err := os.Stat(bundlePath); err != nil && os.IsNotExist(err) {
if err = r.DownloadBundleFile(bundleName); err != nil {
return errors.Wrap(err, "failed to download bundle")
}
bundle, err := r.DownloadBundle(bundleName)
if err != nil {
return errors.Wrap(err, "failed to download bundle")
}

// Framework part

// Check if Framework exists
if !kc.FrameworkExistsInCluster(name) {
if err := installSingleFrameworkToCluster(name, bundlePath, kc); err != nil {
if err := installSingleFrameworkToCluster(name, bundle.Framework, kc); err != nil {
return errors.Wrap(err, "installing single Framework")
}
}

// FrameworkVersion part

// Get the string of the version in FrameworkVersion of a selected Framework
frameworkVersion, err := r.GetFrameworkVersion(name, bundlePath)
if err != nil {
return errors.Wrap(err, "getting FrameworkVersion version")
}

// Check if AnyFrameworkVersion for Framework exists
if !kc.AnyFrameworkVersionExistsInCluster(name) {
// FrameworkVersion CRD for Framework does not exist
if err := installSingleFrameworkVersionToCluster(name, bundlePath, kc); err != nil {
return errors.Wrap(err, "installing single FrameworkVersion")
if err := installSingleFrameworkVersionToCluster(name, kc, bundle.FrameworkVersion); err != nil {
return errors.Wrapf(err, "installing FrameworkVersion CRD for framework %s", name)
}
}

// Check if FrameworkVersion is out of sync with official FrameworkVersion for this Framework
if !kc.FrameworkVersionInClusterOutOfSync(name, frameworkVersion) {
if !kc.FrameworkVersionInClusterOutOfSync(name, bundle.FrameworkVersion.Spec.Version) {
// This happens when the given FrameworkVersion is not existing. E.g.
// when a version has been installed that is not part of the official kudobuilder/frameworks repo.
if !vars.AutoApprove {
fmt.Printf("No official FrameworkVersion has been found for \"%s\". "+
"Do you want to install one? (Yes/no) ", name)
if helpers.AskForConfirmation() {
if err := installSingleFrameworkVersionToCluster(name, bundlePath, kc); err != nil {
return errors.Wrapf(err, "installing single FrameworkVersion %s", name)
if err := installSingleFrameworkVersionToCluster(name, kc, bundle.FrameworkVersion); err != nil {
return errors.Wrapf(err, "installing FrameworkVersion CRD for framework %s", name)
}
}
} else {
if err := installSingleFrameworkVersionToCluster(name, bundlePath, kc); err != nil {
return errors.Wrapf(err, "installing single FrameworkVersion %s", name)
if err := installSingleFrameworkVersionToCluster(name, kc, bundle.FrameworkVersion); err != nil {
return errors.Wrapf(err, "installing FrameworkVersion CRD for framework %s", name)
}
}

}

// Dependencies of the particular FrameworkVersion
if vars.AllDependencies {
dependencyFrameworks, err := r.GetFrameworkVersionDependencies(name, bundlePath)
dependencyFrameworks, err := r.GetFrameworkVersionDependencies(name, bundle.FrameworkVersion)
if err != nil {
return errors.Wrap(err, "getting Framework dependencies")
}
Expand All @@ -199,7 +168,7 @@ func verifySingleFramework(name, previous string, r repo.FrameworkRepository, i

// Check if Instance exists in cluster
// It won't create the Instance if any in combination with given Framework Name and FrameworkVersion exists
if !kc.AnyInstanceExistsInCluster(name, frameworkVersion) {
if !kc.AnyInstanceExistsInCluster(name, bundle.FrameworkVersion.Spec.Version) {
// This happens when the given FrameworkVersion is not existing. E.g.
// when a version has been installed that is not part of the official kudobuilder/frameworks repo.
if !vars.AutoApprove {
Expand All @@ -208,12 +177,12 @@ func verifySingleFramework(name, previous string, r repo.FrameworkRepository, i
if helpers.AskForConfirmation() {
// If Instance is a dependency we need to make sure installSingleInstanceToCluster is aware of it.
// By having the previous string set we can make this distinction.
if err := installSingleInstanceToCluster(name, previous, bundlePath, kc); err != nil {
if err := installSingleInstanceToCluster(name, previous, bundle.Instance, kc); err != nil {
return errors.Wrap(err, "installing single Instance")
}
}
} else {
if err := installSingleInstanceToCluster(name, previous, bundlePath, kc); err != nil {
if err := installSingleInstanceToCluster(name, previous, bundle.Instance, kc); err != nil {
return errors.Wrap(err, "installing single Instance")
}
}
Expand All @@ -224,24 +193,8 @@ func verifySingleFramework(name, previous string, r repo.FrameworkRepository, i

// Todo: needs testing
// installSingleFrameworkToCluster installs a given Framework to the cluster
func installSingleFrameworkToCluster(name, path string, kc *kudo.Client) error {
frameworkPath := fmt.Sprintf(fwPath, path, name)
frameworkYamlFile, err := os.Open(frameworkPath)
if err != nil {
return errors.Wrap(err, "failed opening framework file")
}

frameworkByteValue, err := ioutil.ReadAll(frameworkYamlFile)
if err != nil {
return errors.Wrap(err, "failed reading framework file")
}

var f v1alpha1.Framework
if err = yaml.Unmarshal(frameworkByteValue, &f); err != nil {
return errors.Wrapf(err, "unmarshalling %s-framework.yaml content", name)
}

if _, err = kc.InstallFrameworkObjToCluster(&f); err != nil {
func installSingleFrameworkToCluster(name string, f *v1alpha1.Framework, kc *kudo.Client) error {
if _, err := kc.InstallFrameworkObjToCluster(f); err != nil {
return errors.Wrapf(err, "installing %s-framework.yaml", name)
}
fmt.Printf("framework.%s/%s created\n", f.APIVersion, f.Name)
Expand All @@ -250,24 +203,8 @@ func installSingleFrameworkToCluster(name, path string, kc *kudo.Client) error {

// Todo: needs testing
// installSingleFrameworkVersionToCluster installs a given FrameworkVersion to the cluster
func installSingleFrameworkVersionToCluster(name, path string, kc *kudo.Client) error {
frameworkVersionPath := fmt.Sprintf(fwVersionPath, path, name)
frameworkVersionYamlFile, err := os.Open(frameworkVersionPath)
if err != nil {
return errors.Wrap(err, "failed opening frameworkversion file")
}

frameworkVersionByteValue, err := ioutil.ReadAll(frameworkVersionYamlFile)
if err != nil {
return errors.Wrap(err, "failed reading frameworkversion file")
}

var fv v1alpha1.FrameworkVersion
if err = yaml.Unmarshal(frameworkVersionByteValue, &fv); err != nil {
return errors.Wrapf(err, "unmarshalling %s-frameworkversion.yaml content", name)
}

if _, err = kc.InstallFrameworkVersionObjToCluster(&fv); err != nil {
func installSingleFrameworkVersionToCluster(name string, kc *kudo.Client, fv *v1alpha1.FrameworkVersion) error {
if _, err := kc.InstallFrameworkVersionObjToCluster(fv); err != nil {
return errors.Wrapf(err, "installing %s-frameworkversion.yaml", name)
}
fmt.Printf("frameworkversion.%s/%s created\n", fv.APIVersion, fv.Name)
Expand All @@ -276,22 +213,7 @@ func installSingleFrameworkVersionToCluster(name, path string, kc *kudo.Client)

// Todo: needs more testing
// installSingleInstanceToCluster installs a given Instance to the cluster
func installSingleInstanceToCluster(name, previous, path string, kc *kudo.Client) error {
frameworkInstancePath := fmt.Sprintf(fwInstancePath, path, name)
frameworkInstanceYamlFile, err := os.Open(frameworkInstancePath)
if err != nil {
return errors.Wrap(err, "failed opening instance file")
}

frameworkInstanceByteValue, err := ioutil.ReadAll(frameworkInstanceYamlFile)
if err != nil {
return errors.Wrap(err, "failed reading instance file")
}

var i v1alpha1.Instance
if err = yaml.Unmarshal(frameworkInstanceByteValue, &i); err != nil {
return errors.Wrapf(err, "unmarshalling %s-instance.yaml content", name)
}
func installSingleInstanceToCluster(name, previous string, i *v1alpha1.Instance, kc *kudo.Client) error {
// Customizing Instance
// TODO: traversing, e.g. check function that looksup if key exists in the current FrameworkVersion
// That way just Parameters will be applied if they exist in the matching FrameworkVersion
Expand Down Expand Up @@ -321,7 +243,7 @@ func installSingleInstanceToCluster(name, previous, path string, kc *kudo.Client
}
i.Spec.Parameters = p
}
if _, err = kc.InstallInstanceObjToCluster(&i); err != nil {
if _, err := kc.InstallInstanceObjToCluster(i); err != nil {
return errors.Wrapf(err, "installing %s-instance.yaml", name)
}
fmt.Printf("instance.%s/%s created\n", i.APIVersion, i.Name)
Expand Down
2 changes: 0 additions & 2 deletions pkg/kudoctl/cmd/install/install_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ func TestInstallCmd(t *testing.T) {
cmdWrongDirKubeConfigFlag := &cobra.Command{}
cmdWrongDirKubeConfigFlag.Flags().StringVar(&vars.KubeConfigPath, "kubeconfig", "", "Usage")
vars.KubeConfigPath = "/tmp"
// some workaround for having index.yaml in circleci
vars.RepoPath = "/tmp"
index := []byte(`apiVersion: v1
entries:
kafka:
Expand Down
22 changes: 0 additions & 22 deletions pkg/kudoctl/util/check/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
)

const (
defaultKUDORepoPath = ".kudo/repository"
defaultKubeConfigPath = ".kube/config"
)

Expand Down Expand Up @@ -39,24 +38,3 @@ func getKubeConfigLocation() (string, error) {
}
return vars.KubeConfigPath, nil
}

// RepoPath checks if the repo path folder exists.
func RepoPath() error {
// Option to set a repo path within the environment
// overrides passed repo path parameter
repoPathEnv := os.Getenv("KUDO_REPO_PATH")
if repoPathEnv != "" {
vars.RepoPath = repoPathEnv
} else {
usr, err := user.Current()
if err != nil {
return errors.Wrap(err, "failed to determine user's home dir")
}
vars.RepoPath = filepath.Join(usr.HomeDir, defaultKUDORepoPath)
}

if _, err := os.Stat(vars.RepoPath); err != nil && os.IsNotExist(err) {
return errors.Wrap(err, "repo path does not exist")
}
return nil
}
25 changes: 0 additions & 25 deletions pkg/kudoctl/util/check/check_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package check

import (
"fmt"
"os/user"
"path/filepath"
"testing"
Expand Down Expand Up @@ -32,27 +31,3 @@ func TestKubeConfigPath(t *testing.T) {
t.Errorf("expected kubeconfig path '%v', kubeconfig path instead resolved as %v", expectedPath, location)
}
}

func TestRepoPath(t *testing.T) {
usr, err := user.Current()
if err != nil {
t.Error("failed to determine user's home dir")
}
usrDir := filepath.Join(usr.HomeDir, ".kudo/repository")

tests := []struct {
err string
}{
{fmt.Sprintf("repo path does not exist: stat %s: no such file or directory", usrDir)},
}

for _, tt := range tests {
// Just interested in errors
err := RepoPath()
if err != nil {
if err.Error() != tt.err {
t.Errorf("non existing test:\nexpected: %v\n got: %v", tt.err, err.Error())
}
}
}
}
12 changes: 0 additions & 12 deletions pkg/kudoctl/util/helpers/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,9 @@ package helpers

import (
"fmt"
"os"
"sort"
"strconv"

"github.com/kudobuilder/kudo/pkg/kudoctl/util/vars"
"github.com/pkg/errors"

"github.com/google/go-github/github" // with go modules disabled
)

Expand Down Expand Up @@ -68,11 +64,3 @@ func posString(slice []string, element string) int {
func containsString(slice []string, element string) bool {
return !(posString(slice, element) == -1)
}

// CreateRepoPath returns an error if os.MkdirAll fails to create the path
func CreateRepoPath() error {
if err := os.MkdirAll(vars.RepoPath, 0755); err != nil {
return errors.Wrap(err, "failed to create repo path")
}
return nil
}
16 changes: 0 additions & 16 deletions pkg/kudoctl/util/repo/repo.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
package repo

import (
"github.com/kudobuilder/kudo/pkg/apis/kudo/v1alpha1"
)

// RepositoryConfiguration represents a collection of parameters for framework repository
type RepositoryConfiguration struct {
LocalPath string `json:"localPath"`
Expand All @@ -24,24 +20,12 @@ type Metadata struct {
Name string `json:"name,omitempty"`
// A SemVer 2 conformant version string of the framework
Version string `protobuf:"bytes,4,opt,name=version" json:"version,omitempty"`
// The base version of the application enclosed inside of this framework.
BaseVersion string `json:"baseVersion,omitempty"`
// The KUDO API Version of this framework.
KudoVersion string `json:"kudoVersion,omitempty"`
// KubernetesVersion is a SemVer constraint specifying the version of Kubernetes required.
KubernetesVersion string `json:"kubernetesVersion,omitempty"`
// A SemVer 2 conformant version string of the framework to upgrade from
UpgradeVersion string `json:"upgradeVersion,omitempty"`
// Version dependencies to other frameworks
Dependencies []v1alpha1.FrameworkDependency `json:"dependencies,omitempty"`
// The URL to a relevant project page, git repo, or contact person
Home string `json:"home,omitempty"`
// Source is the URL to the source code of this framework
Sources []string `json:"sources,omitempty"`
// A one-sentence description of the framework
Description string `json:"description,omitempty"`
// The tag under which the framework can be found, e.g. incubating or stable
Tag string `json:"tag,omitempty"`
// A list of name and URL/email address combinations for the maintainer(s)
Maintainers []*Maintainer `json:"maintainers,omitempty"`
// Whether or not this framework is deprecated
Expand Down
Loading

0 comments on commit 53ec610

Please sign in to comment.