Skip to content

Commit

Permalink
init: handle only "kudo-system" namespace (#984)
Browse files Browse the repository at this point in the history
Makes `init` command handle only `kudo-system` namespace. Other
namespaces are expected to be created beforehand.

Fixes #972
  • Loading branch information
hypnoglow authored and alenkacz committed Oct 23, 2019
1 parent f6e182f commit 1600119
Show file tree
Hide file tree
Showing 4 changed files with 407 additions and 27 deletions.
31 changes: 26 additions & 5 deletions pkg/kudoctl/cmd/init/prereqs.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package init

import (
"fmt"

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

v1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -54,6 +56,18 @@ func installRoleBindings(client kubernetes.Interface, opts Options) error {
}

func installNamespace(client corev1.NamespacesGetter, opts Options) error {
// We only manage kudo-system namespace. For others we expect they exist.
if opts.Namespace != defaultns {
_, err := client.Namespaces().Get(opts.Namespace, metav1.GetOptions{})
if err == nil {
return nil
}
if kerrors.IsNotFound(err) {
return fmt.Errorf("namespace %s does not exist - KUDO expects that any namespace except the default %s is created beforehand", opts.Namespace, defaultns)
}
return err
}

ns := generateSysNamespace(opts.Namespace)
_, err := client.Namespaces().Create(ns)
if kerrors.IsAlreadyExists(err) {
Expand Down Expand Up @@ -155,12 +169,19 @@ func PrereqManifests(opts Options) ([]string, error) {

// Prereq returns the slice of prerequisite objects for KUDO
func Prereq(opts Options) []runtime.Object {
ns := namespace(opts.Namespace)
svc := serviceAccount(opts)
rbac := roleBinding(opts)
secret := webhookSecret(opts)
var prereqs []runtime.Object

// We only manage kudo-system namespace. For others we expect they exist.
if opts.Namespace == defaultns {
prereqs = append(prereqs, namespace(opts.Namespace))
}

return []runtime.Object{ns, svc, rbac, secret}
return append(
prereqs,
serviceAccount(opts),
roleBinding(opts),
webhookSecret(opts),
)
}

// roleBinding provides the roleBinding rbac manifest for printing
Expand Down
15 changes: 14 additions & 1 deletion pkg/kudoctl/cmd/init_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
testutils "github.com/kudobuilder/kudo/pkg/test/utils"
"github.com/spf13/afero"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -103,8 +104,20 @@ func TestIntegInitWithNameSpace(t *testing.T) {
client: kclient,
ns: namespace,
}

// On first attempt, the namespace does not exist, so the error is expected.
err = cmd.run()
assert.Nil(t, err)
require.Error(t, err)
assert.Equal(t, err.Error(), `error installing: namespace integration-test does not exist - KUDO expects that any namespace except the default kudo-system is created beforehand`)

// Then we manually create the namespace.
ns := testutils.NewResource("v1", "Namespace", namespace, "")
assert.NoError(t, testClient.Create(context.TODO(), ns))
defer testClient.Delete(context.TODO(), ns)

// On second attempt run should succeed.
err = cmd.run()
assert.NoError(t, err)

// WaitForCRDs to be created... the init cmd did NOT wait
assert.Nil(t, testutils.WaitForCRDs(testenv.DiscoveryClient, crds))
Expand Down
63 changes: 42 additions & 21 deletions pkg/kudoctl/cmd/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"testing"

"github.com/kudobuilder/kudo/pkg/kudoctl/clog"
"github.com/kudobuilder/kudo/pkg/kudoctl/env"
"github.com/kudobuilder/kudo/pkg/kudoctl/kube"
"github.com/kudobuilder/kudo/pkg/kudoctl/kudohome"
"github.com/kudobuilder/kudo/pkg/kudoctl/util/repo"
Expand Down Expand Up @@ -118,32 +119,52 @@ func TestInitCmd_output(t *testing.T) {
}

func TestInitCmd_YAMLWriter(t *testing.T) {
file := "deploy-kudo.yaml"
fs := afero.NewMemMapFs()
out := &bytes.Buffer{}
initCmd := newInitCmd(fs, out)
flags := map[string]string{"dry-run": "true", "output": "yaml"}

for flag, value := range flags {
initCmd.Flags().Set(flag, value)
testCases := []struct {
file string
settings *env.Settings
}{
{
file: "deploy-kudo.yaml",
},
{
file: "deploy-kudo-ns-default.yaml",
settings: env.DefaultSettings, // "default" namespace
},
}
initCmd.RunE(initCmd, []string{})

gp := filepath.Join("testdata", file+".golden")
for _, tc := range testCases {
Settings = env.Settings{}
if tc.settings != nil {
Settings = *tc.settings
}

fs := afero.NewMemMapFs()
out := &bytes.Buffer{}
initCmd := newInitCmd(fs, out)

if *updateGolden {
t.Log("update golden file")
if err := ioutil.WriteFile(gp, out.Bytes(), 0644); err != nil {
t.Fatalf("failed to update golden file: %s", err)
flags := map[string]string{
"dry-run": "true",
"output": "yaml",
}
for name, value := range flags {
initCmd.Flags().Set(name, value)
}
initCmd.RunE(initCmd, []string{})

gp := filepath.Join("testdata", tc.file+".golden")

if *updateGolden {
t.Log("update golden file")
if err := ioutil.WriteFile(gp, out.Bytes(), 0644); err != nil {
t.Fatalf("failed to update golden file: %s", err)
}
}
g, err := ioutil.ReadFile(gp)
if err != nil {
t.Fatalf("failed reading .golden: %s", err)
}
}
g, err := ioutil.ReadFile(gp)
if err != nil {
t.Fatalf("failed reading .golden: %s", err)
}

if !bytes.Equal(out.Bytes(), g) {
t.Errorf("json does not match .golden file? %s", gp)
assert.Equal(t, string(g), out.String())
}
}

Expand Down
Loading

0 comments on commit 1600119

Please sign in to comment.