Commit cfade1b5 authored by bryanl's avatar bryanl
Browse files

Add tests (unit/e2e) for ksonnet actions



* component list
* env describe
* env list
* env targets
* import
* ns create
* ns list
* param list
* param set
Signed-off-by: default avatarbryanl <bryanliles@gmail.com>
parent 336bcf73
......@@ -72,6 +72,12 @@
packages = ["."]
revision = "5df930a27be2502f99b292b7cc09ebad4d0891f4"
[[projects]]
name = "github.com/fsnotify/fsnotify"
packages = ["."]
revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9"
version = "v1.4.7"
[[projects]]
name = "github.com/ghodss/yaml"
packages = ["."]
......@@ -191,6 +197,22 @@
]
revision = "2bcd89a1743fd4b373f7370ce8ddc14dfbd18229"
[[projects]]
branch = "master"
name = "github.com/hashicorp/hcl"
packages = [
".",
"hcl/ast",
"hcl/parser",
"hcl/scanner",
"hcl/strconv",
"hcl/token",
"json/parser",
"json/scanner",
"json/token"
]
revision = "23c074d0eceb2b8a5bfdbb271ab780cde70f05a8"
[[projects]]
branch = "master"
name = "github.com/howeyc/gopass"
......@@ -234,6 +256,12 @@
]
revision = "152e1979764f713239ca25bcb0f3315e69215119"
[[projects]]
name = "github.com/magiconair/properties"
packages = ["."]
revision = "c3beff4c2358b44d0493c7dda585e7db7ff28ae6"
version = "v1.7.6"
[[projects]]
branch = "master"
name = "github.com/mailru/easyjson"
......@@ -255,6 +283,12 @@
packages = ["."]
revision = "fc9e8d8ef48496124e79ae0df75490096eccf6fe"
[[projects]]
branch = "master"
name = "github.com/mitchellh/mapstructure"
packages = ["."]
revision = "00c29f56e2386353d58c599509e8dc3801b0d716"
[[projects]]
name = "github.com/onsi/ginkgo"
packages = [
......@@ -297,6 +331,12 @@
]
revision = "c893efa28eb45626cdaa76c9f653b62488858837"
[[projects]]
name = "github.com/pelletier/go-toml"
packages = ["."]
revision = "acdc4509485b587f5e675510c4f2c63e90ff68a8"
version = "v1.1.0"
[[projects]]
branch = "master"
name = "github.com/petar/GoLLRB"
......@@ -346,6 +386,12 @@
]
revision = "9be650865eab0c12963d8753212f4f9c66cdcf12"
[[projects]]
name = "github.com/spf13/cast"
packages = ["."]
revision = "8965335b8c7107321228e3e3702cab9832751bac"
version = "v1.2.0"
[[projects]]
name = "github.com/spf13/cobra"
packages = [
......@@ -354,11 +400,23 @@
]
revision = "a1e4933ab784095895e33dbe9f001ba10cfe2060"
[[projects]]
branch = "master"
name = "github.com/spf13/jwalterweatherman"
packages = ["."]
revision = "7c0cea34c8ece3fbeb2b27ab9b59511d360fb394"
[[projects]]
name = "github.com/spf13/pflag"
packages = ["."]
revision = "e57e3eeb33f795204c1ca35f56c44f83227c6e66"
[[projects]]
name = "github.com/spf13/viper"
packages = ["."]
revision = "25b30aa063fc18e48662b86996252eabdcf2f0c7"
version = "v1.0.0"
[[projects]]
name = "github.com/stretchr/objx"
packages = ["."]
......@@ -610,6 +668,6 @@
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "7896ab56165a2edefa7b951f6ccf09a43084926d4095990a1a6b4568ed361ddd"
inputs-digest = "73de727a4e7bcb14e8920da27cac10d57953691ae734436022e83891b0d1b589"
solver-name = "gps-cdcl"
solver-version = 1
// Copyright 2018 The ksonnet authors
//
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package actions
import (
"io/ioutil"
"path/filepath"
"testing"
cmocks "github.com/ksonnet/ksonnet/component/mocks"
"github.com/ksonnet/ksonnet/metadata/app/mocks"
"github.com/spf13/afero"
"github.com/stretchr/testify/require"
)
func withApp(t *testing.T, fn func(*mocks.App)) {
fs := afero.NewMemMapFs()
appMock := &mocks.App{}
appMock.On("Fs").Return(fs)
appMock.On("Root").Return("/")
fn(appMock)
}
func assertOutput(t *testing.T, filename, actual string) {
path := filepath.Join("testdata", filename)
b, err := ioutil.ReadFile(path)
require.NoError(t, err)
require.Equal(t, string(b), actual)
}
func stageFile(t *testing.T, fs afero.Fs, src, dest string) {
in := filepath.Join("testdata", src)
b, err := ioutil.ReadFile(in)
require.NoError(t, err)
dir := filepath.Dir(dest)
err = fs.MkdirAll(dir, 0755)
require.NoError(t, err)
err = afero.WriteFile(fs, dest, b, 0644)
require.NoError(t, err)
}
func mockNsWithName(name string) *cmocks.Namespace {
m := &cmocks.Namespace{}
m.On("Name").Return(name)
return m
}
// Copyright 2018 The ksonnet authors
//
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package actions
import (
"io"
"os"
"sort"
"github.com/ksonnet/ksonnet/component"
"github.com/ksonnet/ksonnet/metadata/app"
"github.com/ksonnet/ksonnet/pkg/util/table"
"github.com/pkg/errors"
)
// RunComponentList runs `component list`
func RunComponentList(ksApp app.App, namespace, output string) error {
cl, err := NewComponentList(ksApp, namespace, output)
if err != nil {
return err
}
return cl.Run()
}
// ComponentList create a list of components in a namespace.
type ComponentList struct {
app app.App
nsName string
output string
cm component.Manager
out io.Writer
}
// NewComponentList creates an instance of ComponentList.
func NewComponentList(ksApp app.App, namespace, output string) (*ComponentList, error) {
cl := &ComponentList{
nsName: namespace,
output: output,
app: ksApp,
cm: component.DefaultManager,
out: os.Stdout,
}
return cl, nil
}
// Run runs the ComponentList action.
func (cl *ComponentList) Run() error {
ns, err := cl.cm.Namespace(cl.app, cl.nsName)
if err != nil {
return err
}
components, err := ns.Components()
if err != nil {
return err
}
switch cl.output {
default:
return errors.Errorf("invalid output option %q", cl.output)
case "":
cl.listComponents(components)
case "wide":
if err := cl.listComponentsWide(components); err != nil {
return err
}
}
return nil
}
func (cl *ComponentList) listComponents(components []component.Component) {
var list []string
for _, c := range components {
list = append(list, c.Name(false))
}
sort.Strings(list)
table := table.New(cl.out)
table.SetHeader([]string{"component"})
for _, item := range list {
table.Append([]string{item})
}
table.Render()
}
func (cl *ComponentList) listComponentsWide(components []component.Component) error {
var rows [][]string
for _, c := range components {
summaries, err := c.Summarize()
if err != nil {
return err
}
for _, summary := range summaries {
row := []string{
summary.ComponentName,
summary.Type,
summary.IndexStr,
summary.APIVersion,
summary.Kind,
summary.Name,
}
rows = append(rows, row)
}
}
table := table.New(cl.out)
table.SetHeader([]string{"component", "type", "index", "apiversion", "kind", "name"})
table.AppendBulk(rows)
table.Render()
return nil
}
// Copyright 2018 The ksonnet authors
//
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package actions
import (
"bytes"
"testing"
"github.com/ksonnet/ksonnet/component"
cmocks "github.com/ksonnet/ksonnet/component/mocks"
amocks "github.com/ksonnet/ksonnet/metadata/app/mocks"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)
func TestComponentList(t *testing.T) {
withApp(t, func(appMock *amocks.App) {
nsName := ""
output := ""
c := &cmocks.Component{}
c.On("Name", false).Return("c1")
cs := []component.Component{c}
ns := &cmocks.Namespace{}
ns.On("Components").Return(cs, nil)
cm := &cmocks.Manager{}
cm.On("Namespace", mock.Anything, "").Return(ns, nil)
a, err := NewComponentList(appMock, nsName, output)
require.NoError(t, err)
a.cm = cm
var buf bytes.Buffer
a.out = &buf
err = a.Run()
require.NoError(t, err)
assertOutput(t, "component/list/output.txt", buf.String())
})
}
func TestComponentList_wide(t *testing.T) {
withApp(t, func(appMock *amocks.App) {
nsName := ""
output := "wide"
summary := []component.Summary{
{ComponentName: "deployment"},
}
c := &cmocks.Component{}
c.On("Summarize").Return(summary, nil)
cs := []component.Component{c}
ns := &cmocks.Namespace{}
ns.On("Components").Return(cs, nil)
cm := &cmocks.Manager{}
cm.On("Namespace", mock.Anything, "").Return(ns, nil)
a, err := NewComponentList(appMock, nsName, output)
require.NoError(t, err)
a.cm = cm
var buf bytes.Buffer
a.out = &buf
err = a.Run()
require.NoError(t, err)
assertOutput(t, "component/list/wide.txt", buf.String())
})
}
// Copyright 2018 The ksonnet authors
//
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package actions
import (
"io"
"os"
"github.com/ksonnet/ksonnet/metadata/app"
yaml "gopkg.in/yaml.v2"
)
// RunEnvDescribe runs `env describe`
func RunEnvDescribe(ksApp app.App, envName string) error {
ed, err := NewEnvDescribe(ksApp, envName)
if err != nil {
return err
}
return ed.Run()
}
// EnvDescribe describes an environment by printing its configuration.
type EnvDescribe struct {
app app.App
envName string
out io.Writer
}
// NewEnvDescribe creates an instance of EnvDescribe.
func NewEnvDescribe(ksApp app.App, envName string) (*EnvDescribe, error) {
ed := &EnvDescribe{
app: ksApp,
envName: envName,
out: os.Stdout,
}
return ed, nil
}
// Run runs the EnvDescribe action.
func (ed *EnvDescribe) Run() error {
env, err := ed.app.Environment(ed.envName)
if err != nil {
return err
}
env.Name = ed.envName
b, err := yaml.Marshal(env)
if err != nil {
return err
}
_, err = ed.out.Write(b)
return err
}
// Copyright 2018 The ksonnet authors
//
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package actions
import (
"bytes"
"testing"
"github.com/ksonnet/ksonnet/metadata/app"
amocks "github.com/ksonnet/ksonnet/metadata/app/mocks"
"github.com/stretchr/testify/require"
)
func TestEnvDescribe(t *testing.T) {
withApp(t, func(appMock *amocks.App) {
envName := "default"
env := &app.EnvironmentSpec{
KubernetesVersion: "v1.7.0",
}
appMock.On("Environment", envName).Return(env, nil)
a, err := NewEnvDescribe(appMock, envName)
require.NoError(t, err)
var buf bytes.Buffer
a.out = &buf
err = a.Run()
require.NoError(t, err)
assertOutput(t, "env/describe/output.txt", buf.String())
})
}
// Copyright 2018 The ksonnet authors
//
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package actions
import (
"io"
"os"
"sort"
"github.com/ksonnet/ksonnet/metadata/app"
"github.com/ksonnet/ksonnet/pkg/util/table"
)
// RunEnvList runs `env list`
func RunEnvList(ksApp app.App) error {
nl, err := NewEnvList(ksApp)
if err != nil {
return err
}
return nl.Run()
}
// EnvList lists available namespaces
type EnvList struct {
app app.App
out io.Writer
}
// NewEnvList creates an instance of EnvList
func NewEnvList(ksApp app.App) (*EnvList, error) {
nl := &EnvList{
app: ksApp,
out: os.Stdout,
}
return nl, nil
}
// Run runs the env list action.
func (nl *EnvList) Run() error {
environments, err := nl.app.Environments()
if err != nil {
return err
}
table := table.New(nl.out)
table.SetHeader([]string{"name", "kubernetes-version", "namespace", "server"})
var rows [][]string
for name, env := range environments {
rows = append(rows, []string{
name,
env.KubernetesVersion,
env.Destination.Namespace,
env.Destination.Server,
})
}
sort.Slice(rows, func(i, j int) bool {
return rows[i][0] < rows[j][0]
})
table.AppendBulk(rows)
table.Render()
return nil
}
// Copyright 2018 The ksonnet authors
//
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package actions