diff --git a/go.sum b/go.sum index 1ffa49e6..70c107d9 100644 --- a/go.sum +++ b/go.sum @@ -194,6 +194,7 @@ honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= k8s.io/api v0.0.0-20190202010724-74b699b93c15 h1:AoUGjnJ3PJMFz+Rkp4lx3X+6mPUnY1MESJhbUSGX+pc= k8s.io/api v0.0.0-20190202010724-74b699b93c15/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= +k8s.io/api v0.0.0-20190313115550-3c12c96769cc h1:m/JS6kQd00rICnXLWlnJzMFQB4AplcURUopS8dKiWmI= k8s.io/apiextensions-apiserver v0.0.0-20190322231200-1c09d17c1352 h1:zukcRaXWkBtPh9YLgveTpIvNYzZ+DgAmpQAOxzIKB5c= k8s.io/apiextensions-apiserver v0.0.0-20190322231200-1c09d17c1352/go.mod h1:IxkesAMoaCRoLrPJdZNZUQp9NfZnzqaVzLhb2VEQzXE= k8s.io/apimachinery v0.0.0-20190207091153-095b9d203467 h1:zmz9UYvvXrK/B8EDqFuqreJEaXbIWdzEkNgWrN/Cd3o= diff --git a/internal/k8s/context.go b/internal/k8s/context.go index 92abb496..6de1ce13 100644 --- a/internal/k8s/context.go +++ b/internal/k8s/context.go @@ -7,10 +7,15 @@ import ( "k8s.io/client-go/tools/clientcmd/api" ) -// ContextRes represents a Kubernetes clusters configurations. -type ContextRes interface { +// Switchable represents a switchable resource. +type Switchable interface { + Switch(ctx string) error +} + +// SwitchableResource represents a Kubernetes clusters configurations. +type SwitchableResource interface { Cruder - Switch(n string) error + Switchable } // NamedContext represents a named cluster context. diff --git a/internal/resource/base.go b/internal/resource/base.go index 40952fd2..c2048ac4 100644 --- a/internal/resource/base.go +++ b/internal/resource/base.go @@ -49,12 +49,17 @@ type ( Base struct { Factory - connection Connection + Connection Connection path string - resource Cruder + Resource Cruder } ) +// NewBase returns a new base +func NewBase(c Connection, r Cruder) *Base { + return &Base{Connection: c, Resource: r} +} + // Name returns the resource namespaced name. func (b *Base) Name() string { return b.path @@ -68,7 +73,7 @@ func (*Base) ExtFields() Properties { // Get a resource by name func (b *Base) Get(path string) (Columnar, error) { ns, n := namespaced(path) - i, err := b.resource.Get(ns, n) + i, err := b.Resource.Get(ns, n) if err != nil { return nil, err } @@ -78,7 +83,7 @@ func (b *Base) Get(path string) (Columnar, error) { // List all resources func (b *Base) List(ns string) (Columnars, error) { - ii, err := b.resource.List(ns) + ii, err := b.Resource.List(ns) if err != nil { return nil, err } @@ -115,7 +120,7 @@ func (b *Base) Describe(kind, pa string, flags *genericclioptions.ConfigFlags) ( func (b *Base) Delete(path string) error { ns, n := namespaced(path) - return b.resource.Delete(ns, n) + return b.Resource.Delete(ns, n) } func (*Base) namespacedName(m metav1.ObjectMeta) string { diff --git a/internal/resource/cluster_test.go b/internal/resource/cluster_test.go index d144d992..92258784 100644 --- a/internal/resource/cluster_test.go +++ b/internal/resource/cluster_test.go @@ -13,8 +13,6 @@ import ( ) func TestClusterVersion(t *testing.T) { - setup(t) - cIfc, mxIfc := NewMockClusterMeta(), NewMockMetricsServer() m.When(cIfc.Version()).ThenReturn("1.2.3", nil) @@ -23,8 +21,6 @@ func TestClusterVersion(t *testing.T) { } func TestClusterNoVersion(t *testing.T) { - setup(t) - cIfc, mxIfc := NewMockClusterMeta(), NewMockMetricsServer() m.When(cIfc.Version()).ThenReturn("bad", fmt.Errorf("No data")) @@ -33,8 +29,6 @@ func TestClusterNoVersion(t *testing.T) { } func TestClusterName(t *testing.T) { - setup(t) - cIfc, mxIfc := NewMockClusterMeta(), NewMockMetricsServer() m.When(cIfc.ClusterName()).ThenReturn("fred") @@ -43,8 +37,6 @@ func TestClusterName(t *testing.T) { } func TestClusterMetrics(t *testing.T) { - setup(t) - cIfc, mxIfc := NewMockClusterMeta(), NewMockMetricsServer() m.When(mxIfc.ClusterLoad([]v1.Node{}, []mv1beta1.NodeMetrics{})).ThenReturn(clusterMetric()) @@ -54,7 +46,7 @@ func TestClusterMetrics(t *testing.T) { // Helpers... -func setup(t *testing.T) { +func TestUsingMocks(t *testing.T) { m.RegisterMockTestingT(t) m.RegisterMockFailHandler(func(m string, i ...int) { fmt.Println("Boom!", m, i) diff --git a/internal/resource/cm.go b/internal/resource/cm.go index 8b4cf4e8..1d91fda8 100644 --- a/internal/resource/cm.go +++ b/internal/resource/cm.go @@ -15,8 +15,8 @@ type ConfigMap struct { } // NewConfigMapList returns a new resource list. -func NewConfigMapList(c k8s.Connection, ns string) List { - return newList( +func NewConfigMapList(c Connection, ns string) List { + return NewList( ns, "cm", NewConfigMap(c), @@ -25,8 +25,8 @@ func NewConfigMapList(c k8s.Connection, ns string) List { } // NewConfigMap instantiates a new ConfigMap. -func NewConfigMap(c k8s.Connection) *ConfigMap { - m := &ConfigMap{&Base{connection: c, resource: k8s.NewConfigMap(c)}, nil} +func NewConfigMap(c Connection) *ConfigMap { + m := &ConfigMap{&Base{Connection: c, Resource: k8s.NewConfigMap(c)}, nil} m.Factory = m return m @@ -34,7 +34,7 @@ func NewConfigMap(c k8s.Connection) *ConfigMap { // New builds a new ConfigMap instance from a k8s resource. func (r *ConfigMap) New(i interface{}) Columnar { - cm := NewConfigMap(r.connection) + cm := NewConfigMap(r.Connection) switch instance := i.(type) { case *v1.ConfigMap: cm.instance = instance @@ -51,7 +51,7 @@ func (r *ConfigMap) New(i interface{}) Columnar { // Marshal resource to yaml. func (r *ConfigMap) Marshal(path string) (string, error) { ns, n := namespaced(path) - i, err := r.resource.Get(ns, n) + i, err := r.Resource.Get(ns, n) if err != nil { return "", err } diff --git a/internal/resource/cm_test.go b/internal/resource/cm_test.go index 6ecb14a8..5dcb0e41 100644 --- a/internal/resource/cm_test.go +++ b/internal/resource/cm_test.go @@ -11,18 +11,14 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func TestCMHeader(t *testing.T) { - assert.Equal(t, - resource.Row{"NAME", "DATA", "AGE"}, - newConfigMap().Header(resource.DefaultNamespace), - ) +func NewConfigMapListWithArgs(ns string, r *resource.ConfigMap) resource.List { + return resource.NewList(ns, "cm", r, resource.AllVerbsAccess|resource.DescribeAccess) } -func TestCMHeaderAllNS(t *testing.T) { - assert.Equal(t, - resource.Row{"NAMESPACE", "NAME", "DATA", "AGE"}, - newConfigMap().Header(resource.AllNamespaces), - ) +func NewConfigMapWithArgs(rc k8s.Connection, res resource.Cruder) *resource.ConfigMap { + r := &resource.ConfigMap{Base: resource.NewBase(rc, res)} + r.Factory = r + return r } func TestCMFieldsAllNS(t *testing.T) { @@ -39,102 +35,100 @@ func TestCMFields(t *testing.T) { } func TestCMGet(t *testing.T) { - setup(t) + rc := NewMockConnection() + cr := NewMockCruder() + m.When(cr.Get("blee", "fred")).ThenReturn(k8sCM(), nil) - conn := NewMockConnection() - ca := NewMockCruder() - m.When(ca.Get("blee", "fred")).ThenReturn(k8sCM(), nil) - - cm := resource.NewConfigMap(conn) + cm := NewConfigMapWithArgs(rc, cr) ma, err := cm.Get("blee/fred") + assert.Nil(t, err) - ca.VerifyWasCalledOnce().Get("blee", "fred") + cr.VerifyWasCalledOnce().Get("blee", "fred") assert.Equal(t, cm.New(k8sCM()), ma) } func TestCMList(t *testing.T) { - setup(t) + rc := NewMockConnection() + cr := NewMockCruder() + m.When(cr.List("blee")).ThenReturn(k8s.Collection{*k8sCM()}, nil) - conn := NewMockConnection() - ca := NewMockCruder() - m.When(ca.List("blee")).ThenReturn(k8s.Collection{*k8sCM()}, nil) - - cm := resource.NewConfigMap(conn) + cm := NewConfigMapWithArgs(rc, cr) ma, err := cm.List("blee") + assert.Nil(t, err) - ca.VerifyWasCalledOnce().List("blee") + cr.VerifyWasCalledOnce().List("blee") assert.Equal(t, resource.Columnars{cm.New(k8sCM())}, ma) } func TestCMDelete(t *testing.T) { - setup(t) + rc := NewMockConnection() + cr := NewMockCruder() + m.When(cr.Delete("blee", "fred")).ThenReturn(nil) - conn := NewMockConnection() - ca := NewMockCruder() - m.When(ca.Delete("blee", "fred")).ThenReturn(nil) + cm := NewConfigMapWithArgs(rc, cr) - cm := resource.NewConfigMap(conn) assert.Nil(t, cm.Delete("blee/fred")) - ca.VerifyWasCalledOnce().Delete("blee", "fred") + cr.VerifyWasCalledOnce().Delete("blee", "fred") } func TestCMMarshal(t *testing.T) { - setup(t) + rc := NewMockConnection() + cr := NewMockCruder() + m.When(cr.Get("blee", "fred")).ThenReturn(k8sCM(), nil) - conn := NewMockConnection() - ca := NewMockCruder() - m.When(ca.Get("blee", "fred")).ThenReturn(k8sCM(), nil) - - cm := resource.NewConfigMap(conn) + cm := NewConfigMapWithArgs(rc, cr) ma, err := cm.Marshal("blee/fred") - ca.VerifyWasCalledOnce().Get("blee", "fred") + cr.VerifyWasCalledOnce().Get("blee", "fred") assert.Nil(t, err) assert.Equal(t, cmYaml(), ma) } func TestCMListHasName(t *testing.T) { - setup(t) + rc := NewMockConnection() + cr := NewMockCruder() + + cm := NewConfigMapWithArgs(rc, cr) + l := NewConfigMapListWithArgs("blee", cm) - conn := NewMockConnection() - ca := NewMockCruder() - l := resource.NewConfigMapList(conn, "blee") assert.Equal(t, "cm", l.GetName()) } func TestCMListHasNamespace(t *testing.T) { - setup(t) + rc := NewMockConnection() + cr := NewMockCruder() + + cm := NewConfigMapWithArgs(rc, cr) + l := NewConfigMapListWithArgs("blee", cm) - conn := NewMockConnection() - ca := NewMockCruder() - l := resource.NewConfigMapList(conn, "blee") assert.Equal(t, "blee", l.GetNamespace()) } func TestCMListHasResource(t *testing.T) { - setup(t) + rc := NewMockConnection() + cr := NewMockCruder() + + cm := NewConfigMapWithArgs(rc, cr) + l := NewConfigMapListWithArgs("blee", cm) - conn := NewMockConnection() - ca := NewMockCruder() - l := resource.NewConfigMapList(conn, "blee") assert.NotNil(t, l.Resource()) } func TestCMListData(t *testing.T) { - setup(t) + rc := NewMockConnection() + cr := NewMockCruder() + m.When(cr.List("blee")).ThenReturn(k8s.Collection{*k8sCM()}, nil) - conn := NewMockConnection() - ca := NewMockCruder() - m.When(ca.List("blee")).ThenReturn(k8s.Collection{*k8sCM()}, nil) + cm := NewConfigMapWithArgs(rc, cr) + l := NewConfigMapListWithArgs("blee", cm) - l := resource.NewConfigMapList(conn, "blee") - // Make sure we can get deltas! + // Make sure we crn get deltas! for i := 0; i < 2; i++ { err := l.Reconcile() assert.Nil(t, err) } - ca.VerifyWasCalled(m.Times(2)).List("blee") + cr.VerifyWasCalled(m.Times(2)).List("blee") td := l.Data() assert.Equal(t, 1, len(td.Rows)) @@ -151,8 +145,8 @@ func TestCMListData(t *testing.T) { // Helpers... func newConfigMap() resource.Columnar { - conn := NewMockConnection() - return resource.NewConfigMap(conn).New(k8sCM()) + rc := NewMockConnection() + return resource.NewConfigMap(rc).New(k8sCM()) } func k8sCM() *v1.ConfigMap { diff --git a/internal/resource/context.go b/internal/resource/context.go index 1dd7be34..a44142dd 100644 --- a/internal/resource/context.go +++ b/internal/resource/context.go @@ -5,10 +5,10 @@ import ( "github.com/rs/zerolog/log" ) -// SwitchableRes represents a resource that can be switched. -type SwitchableRes interface { - k8s.Connection - k8s.ContextRes +// SwitchableResource represents a resource that can be switched. +type SwitchableResource interface { + k8s.Cruder + k8s.Switchable } // Context tracks a kubernetes resource. @@ -19,12 +19,12 @@ type Context struct { // NewContextList returns a new resource list. func NewContextList(c k8s.Connection, ns string) List { - return newList(NotNamespaced, "ctx", NewContext(c), SwitchAccess) + return NewList(NotNamespaced, "ctx", NewContext(c), SwitchAccess) } // NewContext instantiates a new Context. func NewContext(c k8s.Connection) *Context { - ctx := &Context{&Base{connection: c, resource: k8s.NewContext(c)}, nil} + ctx := &Context{Base: NewBase(c, k8s.NewContext(c))} ctx.Factory = ctx return ctx @@ -32,7 +32,7 @@ func NewContext(c k8s.Connection) *Context { // New builds a new Context instance from a k8s resource. func (r *Context) New(i interface{}) Columnar { - c := NewContext(r.connection) + c := NewContext(r.Connection) switch instance := i.(type) { case *k8s.NamedContext: c.instance = instance @@ -48,7 +48,7 @@ func (r *Context) New(i interface{}) Columnar { // Switch out current context. func (r *Context) Switch(c string) error { - return r.resource.(k8s.ContextRes).Switch(c) + return r.Resource.(SwitchableResource).Switch(c) } // Marshal the resource to yaml. diff --git a/internal/resource/context_test.go b/internal/resource/context_test.go index 9e778d04..f1ac16ed 100644 --- a/internal/resource/context_test.go +++ b/internal/resource/context_test.go @@ -7,83 +7,87 @@ import ( "github.com/derailed/k9s/internal/resource" m "github.com/petergtz/pegomock" "github.com/stretchr/testify/assert" - "k8s.io/client-go/tools/clientcmd/api" + api "k8s.io/client-go/tools/clientcmd/api" ) -func TestCTXHeader(t *testing.T) { - assert.Equal(t, - resource.Row{"NAME", "CLUSTER", "AUTHINFO", "NAMESPACE"}, - newContext().Header(""), - ) +func NewContextListWithArgs(ns string, ctx *resource.Context) resource.List { + return resource.NewList(resource.NotNamespaced, "ctx", ctx, resource.SwitchAccess) +} + +func NewContextWithArgs(c k8s.Connection, s resource.SwitchableResource) *resource.Context { + ctx := &resource.Context{Base: resource.NewBase(c, s)} + ctx.Factory = ctx + return ctx } func TestCTXSwitch(t *testing.T) { - setup(t) - - ca := NewMockSwitchableRes() + conn := NewMockConnection() + ca := NewMockSwitchableResource() m.When(ca.Switch("fred")).ThenReturn(nil) - ctx := resource.NewContextWithArgs(ca) + ctx := NewContextWithArgs(conn, ca) err := ctx.Switch("fred") + assert.Nil(t, err) ca.VerifyWasCalledOnce().Switch("fred") } func TestCTXList(t *testing.T) { - setup(t) - - ca := NewMockSwitchableRes() + conn := NewMockConnection() + ca := NewMockSwitchableResource() m.When(ca.List("blee")).ThenReturn(k8s.Collection{*k8sNamedCTX()}, nil) - ctx := resource.NewContextWithArgs(ca) + ctx := NewContextWithArgs(conn, ca) cc, err := ctx.List("blee") + assert.Nil(t, err) - assert.Equal(t, resource.Columnars{ctx.NewInstance(k8sNamedCTX())}, cc) + assert.Equal(t, resource.Columnars{ctx.New(k8sNamedCTX())}, cc) ca.VerifyWasCalledOnce().List("blee") } -func TestCTXDelete(t *testing.T) { - setup(t) - ca := NewMockSwitchableRes() +func TestCTXDelete(t *testing.T) { + conn := NewMockConnection() + ca := NewMockSwitchableResource() m.When(ca.Delete("", "fred")).ThenReturn(nil) - cm := resource.NewContextWithArgs(ca) - assert.Nil(t, cm.Delete("fred")) + ctx := NewContextWithArgs(conn, ca) + + assert.Nil(t, ctx.Delete("fred")) ca.VerifyWasCalledOnce().Delete("", "fred") } func TestCTXListHasName(t *testing.T) { - setup(t) + conn := NewMockConnection() + ca := NewMockSwitchableResource() - ca := NewMockSwitchableRes() - m.When(ca.List("blee")).ThenReturn(k8s.Collection{*k8sNamedCTX()}, nil) + ctx := NewContextWithArgs(conn, ca) + l := NewContextListWithArgs("blee", ctx) - l := resource.NewContextListWithArgs("blee", resource.NewContextWithArgs(ca)) assert.Equal(t, "ctx", l.GetName()) } func TestCTXListHasNamespace(t *testing.T) { - setup(t) + conn := NewMockConnection() + ca := NewMockSwitchableResource() + + ctx := NewContextWithArgs(conn, ca) + l := NewContextListWithArgs("blee", ctx) - ca := NewMockSwitchableRes() - l := resource.NewContextListWithArgs("blee", resource.NewContextWithArgs(ca)) assert.Equal(t, resource.NotNamespaced, l.GetNamespace()) } func TestCTXListHasResource(t *testing.T) { - setup(t) + conn := NewMockConnection() + ca := NewMockSwitchableResource() + + ctx := NewContextWithArgs(conn, ca) + l := NewContextListWithArgs("blee", ctx) - ca := NewMockSwitchableRes() - l := resource.NewContextListWithArgs("blee", resource.NewContextWithArgs(ca)) assert.NotNil(t, l.Resource()) } // Helpers... -func newContext() resource.Columnar { - return resource.NewContext().NewInstance(k8sNamedCTX()) -} - func k8sCTX() *api.Context { return &api.Context{ LocationOfOrigin: "fred", diff --git a/internal/resource/cr.go b/internal/resource/cr.go index e1ec11cf..03517045 100644 --- a/internal/resource/cr.go +++ b/internal/resource/cr.go @@ -14,7 +14,7 @@ type ClusterRole struct { // NewClusterRoleList returns a new resource list. func NewClusterRoleList(c k8s.Connection, ns string) List { - return newList( + return NewList( NotNamespaced, "clusterrole", NewClusterRole(c), @@ -24,7 +24,7 @@ func NewClusterRoleList(c k8s.Connection, ns string) List { // NewClusterRole instantiates a new ClusterRole. func NewClusterRole(c k8s.Connection) *ClusterRole { - cr := &ClusterRole{&Base{connection: c, resource: k8s.NewClusterRole(c)}, nil} + cr := &ClusterRole{&Base{Connection: c, Resource: k8s.NewClusterRole(c)}, nil} cr.Factory = cr return cr @@ -32,7 +32,7 @@ func NewClusterRole(c k8s.Connection) *ClusterRole { // New builds a new ClusterRole instance from a k8s resource. func (r *ClusterRole) New(i interface{}) Columnar { - c := NewClusterRole(r.connection) + c := NewClusterRole(r.Connection) switch instance := i.(type) { case *v1.ClusterRole: c.instance = instance @@ -49,7 +49,7 @@ func (r *ClusterRole) New(i interface{}) Columnar { // Marshal resource to yaml. func (r *ClusterRole) Marshal(path string) (string, error) { ns, n := namespaced(path) - i, err := r.resource.Get(ns, n) + i, err := r.Resource.Get(ns, n) if err != nil { return "", err } diff --git a/internal/resource/cr_binding.go b/internal/resource/cr_binding.go index 06e6c3d1..fcd2b907 100644 --- a/internal/resource/cr_binding.go +++ b/internal/resource/cr_binding.go @@ -14,17 +14,17 @@ type ClusterRoleBinding struct { // NewClusterRoleBindingList returns a new resource list. func NewClusterRoleBindingList(c k8s.Connection, _ string) List { - return newList( + return NewList( NotNamespaced, - "ctx", + "clusterrolebinding", NewClusterRoleBinding(c), - SwitchAccess|ViewAccess|DeleteAccess|DescribeAccess, + ViewAccess|DeleteAccess|DescribeAccess, ) } // NewClusterRoleBinding instantiates a new ClusterRoleBinding. func NewClusterRoleBinding(c k8s.Connection) *ClusterRoleBinding { - crb := &ClusterRoleBinding{&Base{connection: c, resource: k8s.NewClusterRoleBinding(c)}, nil} + crb := &ClusterRoleBinding{&Base{Connection: c, Resource: k8s.NewClusterRoleBinding(c)}, nil} crb.Factory = crb return crb @@ -32,7 +32,7 @@ func NewClusterRoleBinding(c k8s.Connection) *ClusterRoleBinding { // New builds a new tabular instance from a k8s resource. func (r *ClusterRoleBinding) New(i interface{}) Columnar { - crb := NewClusterRoleBinding(r.connection) + crb := NewClusterRoleBinding(r.Connection) switch instance := i.(type) { case *v1.ClusterRoleBinding: crb.instance = instance @@ -49,7 +49,7 @@ func (r *ClusterRoleBinding) New(i interface{}) Columnar { // Marshal resource to yaml. func (r *ClusterRoleBinding) Marshal(path string) (string, error) { ns, n := namespaced(path) - i, err := r.resource.Get(ns, n) + i, err := r.Resource.Get(ns, n) if err != nil { return "", err } diff --git a/internal/resource/cr_binding_test.go b/internal/resource/cr_binding_test.go index c846d138..4325a6ea 100644 --- a/internal/resource/cr_binding_test.go +++ b/internal/resource/cr_binding_test.go @@ -11,26 +11,30 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func TestCRBHeader(t *testing.T) { - assert.Equal(t, resource.Row{"NAME", "AGE"}, newCRB().Header(resource.DefaultNamespace)) +func NewClusterRoleBindingListWithArgs(ns string, r *resource.ClusterRoleBinding) resource.List { + return resource.NewList(resource.NotNamespaced, "clusterrolebinding", r, resource.ViewAccess|resource.DeleteAccess|resource.DescribeAccess) } -func TestCRBHeaderAllNS(t *testing.T) { - assert.Equal(t, resource.Row{"NAME", "AGE"}, newCRB().Header(resource.AllNamespaces)) +func NewClusterRoleBindingWithArgs(conn k8s.Connection, res resource.Cruder) *resource.ClusterRoleBinding { + r := &resource.ClusterRoleBinding{Base: resource.NewBase(conn, res)} + r.Factory = r + return r } func TestCRBFields(t *testing.T) { - r := newCRB().Fields(resource.AllNamespaces) + conn := NewMockConnection() + + r := newCRB(conn).Fields(resource.AllNamespaces) + assert.Equal(t, "fred", r[0]) } func TestCRBMarshal(t *testing.T) { - setup(t) - - ca := NewMockCaller() + conn := NewMockConnection() + ca := NewMockCruder() m.When(ca.Get("blee", "fred")).ThenReturn(k8sCRB(), nil) - cm := resource.NewClusterRoleBindingWithArgs(ca) + cm := NewClusterRoleBindingWithArgs(conn, ca) ma, err := cm.Marshal("blee/fred") ca.VerifyWasCalledOnce().Get("blee", "fred") @@ -39,12 +43,11 @@ func TestCRBMarshal(t *testing.T) { } func TestCRBListData(t *testing.T) { - setup(t) - - ca := NewMockCaller() + conn := NewMockConnection() + ca := NewMockCruder() m.When(ca.List(resource.NotNamespaced)).ThenReturn(k8s.Collection{*k8sCRB()}, nil) - l := resource.NewClusterRoleBindingListWithArgs("-", resource.NewClusterRoleBindingWithArgs(ca)) + l := NewClusterRoleBindingListWithArgs("-", NewClusterRoleBindingWithArgs(conn, ca)) // Make sure we can get deltas! for i := 0; i < 2; i++ { err := l.Reconcile() @@ -78,8 +81,8 @@ func k8sCRB() *rbacv1.ClusterRoleBinding { } } -func newCRB() resource.Columnar { - return resource.NewClusterRoleBinding().NewInstance(k8sCRB()) +func newCRB(c resource.Connection) resource.Columnar { + return resource.NewClusterRoleBinding(c).New(k8sCRB()) } func crbYaml() string { diff --git a/internal/resource/cr_test.go b/internal/resource/cr_test.go index a7ed5c4a..8fc7bc94 100644 --- a/internal/resource/cr_test.go +++ b/internal/resource/cr_test.go @@ -14,9 +14,23 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +func NewClusterRoleListWithArgs(ns string, r *resource.ClusterRole) resource.List { + return resource.NewList(resource.NotNamespaced, "clusterrole", r, resource.CRUDAccess|resource.DescribeAccess) +} + +func NewClusterRoleWithArgs(mc resource.Connection, res resource.Cruder) *resource.ClusterRole { + r := &resource.ClusterRole{Base: resource.NewBase(mc, res)} + r.Factory = r + return r +} + func TestCRListAccess(t *testing.T) { + mc := NewMockConnection() + mr := NewMockCruder() + ns := "blee" - l := resource.NewClusterRoleList(resource.AllNamespaces) + r := NewClusterRoleWithArgs(mc, mr) + l := NewClusterRoleListWithArgs(resource.AllNamespaces, r) l.SetNamespace(ns) assert.Equal(t, resource.NotNamespaced, l.GetNamespace()) @@ -26,14 +40,6 @@ func TestCRListAccess(t *testing.T) { } } -func TestCRHeader(t *testing.T) { - assert.Equal(t, resource.Row{"NAME", "AGE"}, newClusterRole().Header(resource.DefaultNamespace)) -} - -func TestCRHeaderAllNS(t *testing.T) { - assert.Equal(t, resource.Row{"NAME", "AGE"}, newClusterRole().Header(resource.AllNamespaces)) -} - func TestCRFields(t *testing.T) { r := newClusterRole().Fields("blee") assert.Equal(t, "fred"+strings.Repeat(" ", 66), r[0]) @@ -45,32 +51,32 @@ func TestCRFieldsAllNS(t *testing.T) { } func TestCRMarshal(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.Get("blee", "fred")).ThenReturn(k8sCR(), nil) - ca := NewMockCaller() - m.When(ca.Get("blee", "fred")).ThenReturn(k8sCR(), nil) + cr := NewClusterRoleWithArgs(mc, mr) + ma, err := cr.Marshal("blee/fred") - cm := resource.NewClusterRoleWithArgs(ca) - ma, err := cm.Marshal("blee/fred") - ca.VerifyWasCalledOnce().Get("blee", "fred") + mr.VerifyWasCalledOnce().Get("blee", "fred") assert.Nil(t, err) - assert.Equal(t, crYaml(), ma) + assert.Equal(t, mrYaml(), ma) } func TestCRListData(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.List(resource.NotNamespaced)).ThenReturn(k8s.Collection{*k8sCR()}, nil) - ca := NewMockCaller() - m.When(ca.List(resource.NotNamespaced)).ThenReturn(k8s.Collection{*k8sCR()}, nil) - - l := resource.NewClusterRoleListWithArgs("-", resource.NewClusterRoleWithArgs(ca)) - // Make sure we can get deltas! + l := NewClusterRoleListWithArgs("-", NewClusterRoleWithArgs(mc, mr)) + // Make sure we mcn get deltas! for i := 0; i < 2; i++ { err := l.Reconcile() assert.Nil(t, err) } - ca.VerifyWasCalled(m.Times(2)).List(resource.NotNamespaced) + mr.VerifyWasCalled(m.Times(2)).List(resource.NotNamespaced) + td := l.Data() assert.Equal(t, 1, len(td.Rows)) assert.Equal(t, resource.NotNamespaced, l.GetNamespace()) @@ -102,7 +108,8 @@ func k8sCR() *rbacv1.ClusterRole { } func newClusterRole() resource.Columnar { - return resource.NewClusterRole().NewInstance(k8sCR()) + conn := NewMockConnection() + return resource.NewClusterRole(conn).New(k8sCR()) } func testTime() time.Time { @@ -113,7 +120,7 @@ func testTime() time.Time { return t } -func crYaml() string { +func mrYaml() string { return `apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: diff --git a/internal/resource/crd.go b/internal/resource/crd.go index 6e6fe2ec..e1379f0b 100644 --- a/internal/resource/crd.go +++ b/internal/resource/crd.go @@ -18,7 +18,7 @@ type CRD struct { // NewCRDList returns a new resource list. func NewCRDList(c k8s.Connection, ns string) List { - return newList( + return NewList( NotNamespaced, "crd", NewCRD(c), @@ -28,7 +28,7 @@ func NewCRDList(c k8s.Connection, ns string) List { // NewCRD instantiates a new CRD. func NewCRD(c k8s.Connection) *CRD { - crd := &CRD{&Base{connection: c, resource: k8s.NewCRD(c)}, nil} + crd := &CRD{&Base{Connection: c, Resource: k8s.NewCRD(c)}, nil} crd.Factory = crd return crd @@ -36,7 +36,7 @@ func NewCRD(c k8s.Connection) *CRD { // New builds a new CRD instance from a k8s resource. func (r *CRD) New(i interface{}) Columnar { - c := NewCRD(r.connection) + c := NewCRD(r.Connection) switch instance := i.(type) { case *unstructured.Unstructured: c.instance = instance @@ -54,7 +54,7 @@ func (r *CRD) New(i interface{}) Columnar { // Marshal a resource. func (r *CRD) Marshal(path string) (string, error) { ns, n := namespaced(path) - i, err := r.resource.Get(ns, n) + i, err := r.Resource.Get(ns, n) if err != nil { return "", err } diff --git a/internal/resource/crd_test.go b/internal/resource/crd_test.go index f8e0177d..93930c0b 100644 --- a/internal/resource/crd_test.go +++ b/internal/resource/crd_test.go @@ -10,9 +10,23 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) +func NewCRDListWithArgs(ns string, r *resource.CRD) resource.List { + return resource.NewList("-", "crd", r, resource.CRUDAccess|resource.DescribeAccess) +} + +func NewCRDWithArgs(conn k8s.Connection, res resource.Cruder) *resource.CRD { + r := &resource.CRD{Base: resource.NewBase(conn, res)} + r.Factory = r + return r +} + func TestCRDListAccess(t *testing.T) { + mc := NewMockConnection() + mr := NewMockCruder() + ns := "blee" - l := resource.NewCRDList(resource.AllNamespaces) + r := NewCRDWithArgs(mc, mr) + l := NewCRDListWithArgs(resource.AllNamespaces, r) l.SetNamespace(ns) assert.Equal(t, resource.NotNamespaced, l.GetNamespace()) @@ -22,14 +36,6 @@ func TestCRDListAccess(t *testing.T) { } } -func TestCRDHeader(t *testing.T) { - assert.Equal(t, resource.Row{"NAME", "AGE"}, newCRD().Header(resource.DefaultNamespace)) -} - -func TestCRDHeaderAllNS(t *testing.T) { - assert.Equal(t, resource.Row{"NAME", "AGE"}, newCRD().Header(resource.AllNamespaces)) -} - func TestCRDFields(t *testing.T) { r := newCRD().Fields("blee") assert.Equal(t, "fred", r[0]) @@ -41,32 +47,31 @@ func TestCRDFieldsAllNS(t *testing.T) { } func TestCRDMarshal(t *testing.T) { - setup(t) + mc := NewMockConnection() + cr := NewMockCruder() + m.When(cr.Get("blee", "fred")).ThenReturn(k8sCRD(), nil) - ca := NewMockCaller() - m.When(ca.Get("blee", "fred")).ThenReturn(k8sCRD(), nil) + r := NewCRDWithArgs(mc, cr) + ma, err := r.Marshal("blee/fred") - cm := resource.NewCRDWithArgs(ca) - ma, err := cm.Marshal("blee/fred") - ca.VerifyWasCalledOnce().Get("blee", "fred") + cr.VerifyWasCalledOnce().Get("blee", "fred") assert.Nil(t, err) assert.Equal(t, crdYaml(), ma) } func TestCRDListData(t *testing.T) { - setup(t) + mc := NewMockConnection() + cr := NewMockCruder() + m.When(cr.List(resource.NotNamespaced)).ThenReturn(k8s.Collection{*k8sCRD()}, nil) - ca := NewMockCaller() - m.When(ca.List(resource.NotNamespaced)).ThenReturn(k8s.Collection{*k8sCRD()}, nil) - - l := resource.NewCRDListWithArgs("-", resource.NewCRDWithArgs(ca)) + l := NewCRDListWithArgs("-", NewCRDWithArgs(mc, cr)) // Make sure we can get deltas! for i := 0; i < 2; i++ { err := l.Reconcile() assert.Nil(t, err) } - ca.VerifyWasCalled(m.Times(2)).List(resource.NotNamespaced) + cr.VerifyWasCalled(m.Times(2)).List(resource.NotNamespaced) td := l.Data() assert.Equal(t, 1, len(td.Rows)) assert.Equal(t, resource.NotNamespaced, l.GetNamespace()) @@ -93,7 +98,8 @@ func k8sCRD() *unstructured.Unstructured { } func newCRD() resource.Columnar { - return resource.NewCRD().NewInstance(k8sCRD()) + mc := NewMockConnection() + return resource.NewCRD(mc).New(k8sCRD()) } func crdYaml() string { diff --git a/internal/resource/cronjob.go b/internal/resource/cronjob.go index ea800e1d..26b21fbb 100644 --- a/internal/resource/cronjob.go +++ b/internal/resource/cronjob.go @@ -29,7 +29,7 @@ type ( // NewCronJobList returns a new resource list. func NewCronJobList(c k8s.Connection, ns string) List { - return newList( + return NewList( ns, "cronjob", NewCronJob(c), @@ -39,7 +39,7 @@ func NewCronJobList(c k8s.Connection, ns string) List { // NewCronJob instantiates a new CronJob. func NewCronJob(c k8s.Connection) *CronJob { - cj := &CronJob{&Base{connection: c, resource: k8s.NewCronJob(c)}, nil} + cj := &CronJob{&Base{Connection: c, Resource: k8s.NewCronJob(c)}, nil} cj.Factory = cj return cj @@ -47,7 +47,7 @@ func NewCronJob(c k8s.Connection) *CronJob { // New builds a new CronJob instance from a k8s resource. func (r *CronJob) New(i interface{}) Columnar { - c := NewCronJob(r.connection) + c := NewCronJob(r.Connection) switch instance := i.(type) { case *batchv1beta1.CronJob: c.instance = instance @@ -64,7 +64,7 @@ func (r *CronJob) New(i interface{}) Columnar { // Marshal resource to yaml. func (r *CronJob) Marshal(path string) (string, error) { ns, n := namespaced(path) - i, err := r.resource.Get(ns, n) + i, err := r.Resource.Get(ns, n) if err != nil { return "", err } @@ -79,7 +79,7 @@ func (r *CronJob) Marshal(path string) (string, error) { // Run a given cronjob. func (r *CronJob) Run(pa string) error { ns, n := namespaced(pa) - if c, ok := r.resource.(Runnable); ok { + if c, ok := r.Resource.(Runnable); ok { return c.Run(ns, n) } diff --git a/internal/resource/cronjob_test.go b/internal/resource/cronjob_test.go index 02640cf6..11edb4d2 100644 --- a/internal/resource/cronjob_test.go +++ b/internal/resource/cronjob_test.go @@ -11,54 +11,62 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +func NewCronJobListWithArgs(ns string, r *resource.CronJob) resource.List { + return resource.NewList(ns, "cronjob", r, resource.AllVerbsAccess|resource.DescribeAccess) +} + +func NewCronJobWithArgs(conn k8s.Connection, res resource.Cruder) *resource.CronJob { + r := &resource.CronJob{Base: resource.NewBase(conn, res)} + r.Factory = r + return r +} + func TestCronJobListAccess(t *testing.T) { + mc := NewMockConnection() + mr := NewMockCruder() + ns := "blee" - l := resource.NewCronJobList(resource.AllNamespaces) + r := NewCronJobWithArgs(mc, mr) + l := NewCronJobListWithArgs(resource.AllNamespaces, r) l.SetNamespace(ns) - assert.Equal(t, "blee", l.GetNamespace()) + assert.Equal(t, ns, l.GetNamespace()) assert.Equal(t, "cronjob", l.GetName()) for _, a := range []int{resource.GetAccess, resource.ListAccess, resource.DeleteAccess, resource.ViewAccess, resource.EditAccess} { assert.True(t, l.Access(a)) } } -func TestCronJobHeader(t *testing.T) { - assert.Equal(t, resource.Row{"NAME", "SCHEDULE", "SUSPEND", "ACTIVE", "LAST_SCHEDULE", "AGE"}, newCronJob().Header(resource.DefaultNamespace)) -} - func TestCronJobFields(t *testing.T) { r := newCronJob().Fields("blee") assert.Equal(t, "fred", r[0]) } func TestCronJobMarshal(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.Get("blee", "fred")).ThenReturn(k8sCronJob(), nil) - ca := NewMockCaller() - m.When(ca.Get("blee", "fred")).ThenReturn(k8sCronJob(), nil) - - cm := resource.NewCronJobWithArgs(ca) + cm := NewCronJobWithArgs(mc, mr) ma, err := cm.Marshal("blee/fred") - ca.VerifyWasCalledOnce().Get("blee", "fred") + mr.VerifyWasCalledOnce().Get("blee", "fred") assert.Nil(t, err) assert.Equal(t, cronjobYaml(), ma) } func TestCronJobListData(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.List(resource.NotNamespaced)).ThenReturn(k8s.Collection{*k8sCronJob()}, nil) - ca := NewMockCaller() - m.When(ca.List(resource.NotNamespaced)).ThenReturn(k8s.Collection{*k8sCronJob()}, nil) - - l := resource.NewCronJobListWithArgs("-", resource.NewCronJobWithArgs(ca)) + l := NewCronJobListWithArgs("-", NewCronJobWithArgs(mc, mr)) // Make sure we can get deltas! for i := 0; i < 2; i++ { err := l.Reconcile() assert.Nil(t, err) } - ca.VerifyWasCalled(m.Times(2)).List(resource.NotNamespaced) + mr.VerifyWasCalled(m.Times(2)).List(resource.NotNamespaced) td := l.Data() assert.Equal(t, 1, len(td.Rows)) assert.Equal(t, resource.NotNamespaced, l.GetNamespace()) @@ -91,7 +99,8 @@ func k8sCronJob() *batchv1beta1.CronJob { } func newCronJob() resource.Columnar { - return resource.NewCronJob().NewInstance(k8sCronJob()) + mc := NewMockConnection() + return resource.NewCronJob(mc).New(k8sCronJob()) } func cronjobYaml() string { diff --git a/internal/resource/custom.go b/internal/resource/custom.go index ac1ae140..0bcc72fb 100644 --- a/internal/resource/custom.go +++ b/internal/resource/custom.go @@ -27,7 +27,7 @@ func NewCustomList(c k8s.Connection, ns, group, version, name string) List { if !c.IsNamespaced(name) { ns = NotNamespaced } - return newList( + return NewList( ns, name, NewCustom(c, group, version, name), AllVerbsAccess, @@ -36,16 +36,16 @@ func NewCustomList(c k8s.Connection, ns, group, version, name string) List { // NewCustom instantiates a new Kubernetes Resource. func NewCustom(c k8s.Connection, group, version, name string) *Custom { - cr := &Custom{Base: &Base{connection: c, resource: k8s.NewResource(c, group, version, name)}} + cr := &Custom{Base: &Base{Connection: c, Resource: k8s.NewResource(c, group, version, name)}} cr.Factory = cr - cr.group, cr.version, cr.name = cr.resource.(*k8s.Resource).GetInfo() + cr.group, cr.version, cr.name = cr.Resource.(*k8s.Resource).GetInfo() return cr } // New builds a new Custom instance from a k8s resource. func (r *Custom) New(i interface{}) Columnar { - cr := NewCustom(r.connection, "", "", "") + cr := NewCustom(r.Connection, "", "", "") switch instance := i.(type) { case *metav1beta1.TableRow: cr.instance = instance @@ -74,7 +74,7 @@ func (r *Custom) New(i interface{}) Columnar { // Marshal resource to yaml. func (r *Custom) Marshal(path string) (string, error) { ns, n := namespaced(path) - i, err := r.resource.Get(ns, n) + i, err := r.Resource.Get(ns, n) if err != nil { return "", err } @@ -89,7 +89,7 @@ func (r *Custom) Marshal(path string) (string, error) { // List all resources func (r *Custom) List(ns string) (Columnars, error) { - ii, err := r.resource.List(ns) + ii, err := r.Resource.List(ns) if err != nil { return nil, err } diff --git a/internal/resource/dp.go b/internal/resource/dp.go index 3a6d1319..bf9b2a74 100644 --- a/internal/resource/dp.go +++ b/internal/resource/dp.go @@ -16,7 +16,7 @@ type Deployment struct { // NewDeploymentList returns a new resource list. func NewDeploymentList(c k8s.Connection, ns string) List { - return newList( + return NewList( ns, "deploy", NewDeployment(c), @@ -26,7 +26,7 @@ func NewDeploymentList(c k8s.Connection, ns string) List { // NewDeployment instantiates a new Deployment. func NewDeployment(c k8s.Connection) *Deployment { - d := &Deployment{&Base{connection: c, resource: k8s.NewDeployment(c)}, nil} + d := &Deployment{&Base{Connection: c, Resource: k8s.NewDeployment(c)}, nil} d.Factory = d return d @@ -34,7 +34,7 @@ func NewDeployment(c k8s.Connection) *Deployment { // New builds a new Deployment instance from a k8s resource. func (r *Deployment) New(i interface{}) Columnar { - c := NewDeployment(r.connection) + c := NewDeployment(r.Connection) switch instance := i.(type) { case *v1.Deployment: c.instance = instance @@ -51,7 +51,7 @@ func (r *Deployment) New(i interface{}) Columnar { // Marshal resource to yaml. func (r *Deployment) Marshal(path string) (string, error) { ns, n := namespaced(path) - i, err := r.resource.Get(ns, n) + i, err := r.Resource.Get(ns, n) if err != nil { return "", err } diff --git a/internal/resource/dp_test.go b/internal/resource/dp_test.go index 60f82c3d..676d6e69 100644 --- a/internal/resource/dp_test.go +++ b/internal/resource/dp_test.go @@ -11,9 +11,22 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +func NewDeploymentListWithArgs(ns string, r *resource.Deployment) resource.List { + return resource.NewList(ns, "deploy", r, resource.AllVerbsAccess|resource.DescribeAccess) +} + +func NewDeploymentWithArgs(conn k8s.Connection, res resource.Cruder) *resource.Deployment { + r := &resource.Deployment{Base: resource.NewBase(conn, res)} + r.Factory = r + return r +} + func TestDeploymentListAccess(t *testing.T) { + mc := NewMockConnection() + mr := NewMockCruder() + ns := "blee" - l := resource.NewDeploymentList(resource.AllNamespaces) + l := NewDeploymentListWithArgs(resource.AllNamespaces, NewDeploymentWithArgs(mc, mr)) l.SetNamespace(ns) assert.Equal(t, "blee", l.GetNamespace()) @@ -23,42 +36,37 @@ func TestDeploymentListAccess(t *testing.T) { } } -func TestDeploymentHeader(t *testing.T) { - assert.Equal(t, resource.Row{"NAME", "DESIRED", "CURRENT", "UP-TO-DATE", "AVAILABLE", "AGE"}, newDeployment().Header(resource.DefaultNamespace)) -} - func TestDeploymentFields(t *testing.T) { r := newDeployment().Fields("blee") assert.Equal(t, "fred", r[0]) } func TestDeploymentMarshal(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.Get("blee", "fred")).ThenReturn(k8sDeployment(), nil) - ca := NewMockCaller() - m.When(ca.Get("blee", "fred")).ThenReturn(k8sDeployment(), nil) - - cm := resource.NewDeploymentWithArgs(ca) + cm := NewDeploymentWithArgs(mc, mr) ma, err := cm.Marshal("blee/fred") - ca.VerifyWasCalledOnce().Get("blee", "fred") + + mr.VerifyWasCalledOnce().Get("blee", "fred") assert.Nil(t, err) assert.Equal(t, dpYaml(), ma) } func TestDeploymentListData(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.List(resource.NotNamespaced)).ThenReturn(k8s.Collection{*k8sDeployment()}, nil) - ca := NewMockCaller() - m.When(ca.List(resource.NotNamespaced)).ThenReturn(k8s.Collection{*k8sDeployment()}, nil) - - l := resource.NewDeploymentListWithArgs("-", resource.NewDeploymentWithArgs(ca)) + l := NewDeploymentListWithArgs("-", NewDeploymentWithArgs(mc, mr)) // Make sure we can get deltas! for i := 0; i < 2; i++ { err := l.Reconcile() assert.Nil(t, err) } - ca.VerifyWasCalled(m.Times(2)).List(resource.NotNamespaced) + mr.VerifyWasCalled(m.Times(2)).List(resource.NotNamespaced) td := l.Data() assert.Equal(t, 1, len(td.Rows)) assert.Equal(t, resource.NotNamespaced, l.GetNamespace()) @@ -87,7 +95,8 @@ func k8sDeployment() *appsv1.Deployment { } func newDeployment() resource.Columnar { - return resource.NewDeployment().NewInstance(k8sDeployment()) + mc := NewMockConnection() + return resource.NewDeployment(mc).New(k8sDeployment()) } func dpYaml() string { diff --git a/internal/resource/ds.go b/internal/resource/ds.go index 047f9b70..27d86d4b 100644 --- a/internal/resource/ds.go +++ b/internal/resource/ds.go @@ -16,7 +16,7 @@ type DaemonSet struct { // NewDaemonSetList returns a new resource list. func NewDaemonSetList(c k8s.Connection, ns string) List { - return newList( + return NewList( ns, "ds", NewDaemonSet(c), @@ -26,7 +26,7 @@ func NewDaemonSetList(c k8s.Connection, ns string) List { // NewDaemonSet instantiates a new DaemonSet. func NewDaemonSet(c k8s.Connection) *DaemonSet { - ds := &DaemonSet{&Base{connection: c, resource: k8s.NewDaemonSet(c)}, nil} + ds := &DaemonSet{&Base{Connection: c, Resource: k8s.NewDaemonSet(c)}, nil} ds.Factory = ds return ds @@ -34,7 +34,7 @@ func NewDaemonSet(c k8s.Connection) *DaemonSet { // New builds a new DaemonSet instance from a k8s resource. func (r *DaemonSet) New(i interface{}) Columnar { - c := NewDaemonSet(r.connection) + c := NewDaemonSet(r.Connection) switch instance := i.(type) { case *extv1beta1.DaemonSet: c.instance = instance @@ -51,7 +51,7 @@ func (r *DaemonSet) New(i interface{}) Columnar { // Marshal resource to yaml. func (r *DaemonSet) Marshal(path string) (string, error) { ns, n := namespaced(path) - i, err := r.resource.Get(ns, n) + i, err := r.Resource.Get(ns, n) if err != nil { return "", err } diff --git a/internal/resource/ds_test.go b/internal/resource/ds_test.go index 117ff5a4..accfc2d8 100644 --- a/internal/resource/ds_test.go +++ b/internal/resource/ds_test.go @@ -11,9 +11,22 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +func NewDaemonSetListWithArgs(ns string, r *resource.DaemonSet) resource.List { + return resource.NewList(ns, "ds", r, resource.AllVerbsAccess|resource.DescribeAccess) +} + +func NewDaemonSetWithArgs(conn k8s.Connection, res resource.Cruder) *resource.DaemonSet { + r := &resource.DaemonSet{Base: resource.NewBase(conn, res)} + r.Factory = r + return r +} + func TestDSListAccess(t *testing.T) { + mc := NewMockConnection() + mr := NewMockCruder() + ns := "blee" - l := resource.NewDaemonSetList(resource.AllNamespaces) + l := NewDaemonSetListWithArgs(resource.AllNamespaces, NewDaemonSetWithArgs(mc, mr)) l.SetNamespace(ns) assert.Equal(t, "blee", l.GetNamespace()) @@ -23,45 +36,39 @@ func TestDSListAccess(t *testing.T) { } } -func TestDSHeader(t *testing.T) { - assert.Equal(t, resource.Row{"NAME", "DESIRED", "CURRENT", "READY", "UP-TO-DATE", "AVAILABLE", "NODE_SELECTOR", "AGE"}, newDS().Header(resource.DefaultNamespace)) -} - func TestDSFields(t *testing.T) { r := newDS().Fields("blee") assert.Equal(t, "fred", r[0]) } func TestDSMarshal(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.Get("blee", "fred")).ThenReturn(k8sDS(), nil) - ca := NewMockCaller() - m.When(ca.Get("blee", "fred")).ThenReturn(k8sDS(), nil) - - cm := resource.NewDaemonSetWithArgs(ca) + cm := NewDaemonSetWithArgs(mc, mr) ma, err := cm.Marshal("blee/fred") - ca.VerifyWasCalledOnce().Get("blee", "fred") + mr.VerifyWasCalledOnce().Get("blee", "fred") assert.Nil(t, err) assert.Equal(t, dsYaml(), ma) } func TestDSListData(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.List("blee")).ThenReturn(k8s.Collection{*k8sDS()}, nil) - ca := NewMockCaller() - m.When(ca.List(resource.NotNamespaced)).ThenReturn(k8s.Collection{*k8sDS()}, nil) - - l := resource.NewDaemonSetListWithArgs("-", resource.NewDaemonSetWithArgs(ca)) + l := NewDaemonSetListWithArgs("blee", NewDaemonSetWithArgs(mc, mr)) // Make sure we can get deltas! for i := 0; i < 2; i++ { err := l.Reconcile() assert.Nil(t, err) } - ca.VerifyWasCalled(m.Times(2)).List(resource.NotNamespaced) + mr.VerifyWasCalled(m.Times(2)).List("blee") td := l.Data() assert.Equal(t, 1, len(td.Rows)) - assert.Equal(t, resource.NotNamespaced, l.GetNamespace()) + assert.Equal(t, "blee", l.GetNamespace()) row := td.Rows["blee/fred"] assert.Equal(t, 8, len(row.Deltas)) for _, d := range row.Deltas { @@ -94,7 +101,8 @@ func k8sDS() *extv1beta1.DaemonSet { } func newDS() resource.Columnar { - return resource.NewDaemonSet().NewInstance(k8sDS()) + mc := NewMockConnection() + return resource.NewDaemonSet(mc).New(k8sDS()) } func dsYaml() string { diff --git a/internal/resource/ep.go b/internal/resource/ep.go index ca3c7b3d..e8d03020 100644 --- a/internal/resource/ep.go +++ b/internal/resource/ep.go @@ -18,7 +18,7 @@ type Endpoints struct { // NewEndpointsList returns a new resource list. func NewEndpointsList(c k8s.Connection, ns string) List { - return newList( + return NewList( ns, "ep", NewEndpoints(c), @@ -28,7 +28,7 @@ func NewEndpointsList(c k8s.Connection, ns string) List { // NewEndpoints instantiates a new Endpoints. func NewEndpoints(c k8s.Connection) *Endpoints { - ep := &Endpoints{&Base{connection: c, resource: k8s.NewEndpoints(c)}, nil} + ep := &Endpoints{&Base{Connection: c, Resource: k8s.NewEndpoints(c)}, nil} ep.Factory = ep return ep @@ -36,7 +36,7 @@ func NewEndpoints(c k8s.Connection) *Endpoints { // New builds a new Endpoints instance from a k8s resource. func (r *Endpoints) New(i interface{}) Columnar { - c := NewEndpoints(r.connection) + c := NewEndpoints(r.Connection) switch instance := i.(type) { case *v1.Endpoints: c.instance = instance @@ -53,7 +53,7 @@ func (r *Endpoints) New(i interface{}) Columnar { // Marshal resource to yaml. func (r *Endpoints) Marshal(path string) (string, error) { ns, n := namespaced(path) - i, err := r.resource.Get(ns, n) + i, err := r.Resource.Get(ns, n) if err != nil { return "", err } diff --git a/internal/resource/ep_test.go b/internal/resource/ep_test.go index 890bfc92..918b31ee 100644 --- a/internal/resource/ep_test.go +++ b/internal/resource/ep_test.go @@ -3,17 +3,33 @@ package resource_test import ( "testing" + // "github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/resource" m "github.com/petergtz/pegomock" + + // m "github.com/petergtz/pegomock" "github.com/stretchr/testify/assert" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +func NewEndpointsListWithArgs(ns string, r *resource.Endpoints) resource.List { + return resource.NewList(ns, "ep", r, resource.AllVerbsAccess|resource.DescribeAccess) +} + +func NewEndpointsWithArgs(conn k8s.Connection, res resource.Cruder) *resource.Endpoints { + r := &resource.Endpoints{Base: resource.NewBase(conn, res)} + r.Factory = r + return r +} + func TestEndpointsListAccess(t *testing.T) { + mc := NewMockConnection() + mr := NewMockCruder() + ns := "blee" - l := resource.NewEndpointsList(resource.AllNamespaces) + l := NewEndpointsListWithArgs(resource.AllNamespaces, NewEndpointsWithArgs(mc, mr)) l.SetNamespace(ns) assert.Equal(t, "blee", l.GetNamespace()) @@ -23,42 +39,31 @@ func TestEndpointsListAccess(t *testing.T) { } } -func TestEndpointsHeader(t *testing.T) { - assert.Equal(t, resource.Row{"NAME", "ENDPOINTS", "AGE"}, newEndpoints().Header(resource.DefaultNamespace)) -} - -func TestEndpointsFields(t *testing.T) { - r := newEndpoints().Fields("blee") - assert.Equal(t, "fred", r[0]) -} - func TestEndpointsMarshal(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.Get("blee", "fred")).ThenReturn(k8sEndpoints(), nil) - ca := NewMockCaller() - m.When(ca.Get("blee", "fred")).ThenReturn(k8sEndpoints(), nil) - - cm := resource.NewEndpointsWithArgs(ca) + cm := NewEndpointsWithArgs(mc, mr) ma, err := cm.Marshal("blee/fred") - ca.VerifyWasCalledOnce().Get("blee", "fred") + mr.VerifyWasCalledOnce().Get("blee", "fred") assert.Nil(t, err) assert.Equal(t, epYaml(), ma) } func TestEndpointsListData(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.List(resource.NotNamespaced)).ThenReturn(k8s.Collection{*k8sEndpoints()}, nil) - ca := NewMockCaller() - m.When(ca.List(resource.NotNamespaced)).ThenReturn(k8s.Collection{*k8sEndpoints()}, nil) - - l := resource.NewEndpointsListWithArgs("-", resource.NewEndpointsWithArgs(ca)) - // Make sure we can get deltas! + l := NewEndpointsListWithArgs("-", NewEndpointsWithArgs(mc, mr)) + // Make sure we mrn get deltas! for i := 0; i < 2; i++ { err := l.Reconcile() assert.Nil(t, err) } - ca.VerifyWasCalled(m.Times(2)).List(resource.NotNamespaced) + mr.VerifyWasCalled(m.Times(2)).List(resource.NotNamespaced) td := l.Data() assert.Equal(t, 1, len(td.Rows)) assert.Equal(t, resource.NotNamespaced, l.GetNamespace()) @@ -93,7 +98,8 @@ func k8sEndpoints() *v1.Endpoints { } func newEndpoints() resource.Columnar { - return resource.NewEndpoints().NewInstance(k8sEndpoints()) + mc := NewMockConnection() + return resource.NewEndpoints(mc).New(k8sEndpoints()) } func epYaml() string { diff --git a/internal/resource/evt.go b/internal/resource/evt.go index b8307b95..71f223c2 100644 --- a/internal/resource/evt.go +++ b/internal/resource/evt.go @@ -17,7 +17,7 @@ type Event struct { // NewEventList returns a new resource list. func NewEventList(c k8s.Connection, ns string) List { - return newList( + return NewList( ns, "ev", NewEvent(c), @@ -27,7 +27,7 @@ func NewEventList(c k8s.Connection, ns string) List { // NewEvent instantiates a new Event. func NewEvent(c k8s.Connection) *Event { - ev := &Event{&Base{connection: c, resource: k8s.NewEvent(c)}, nil} + ev := &Event{&Base{Connection: c, Resource: k8s.NewEvent(c)}, nil} ev.Factory = ev return ev @@ -35,7 +35,7 @@ func NewEvent(c k8s.Connection) *Event { // New builds a new Event instance from a k8s resource. func (r *Event) New(i interface{}) Columnar { - c := NewEvent(r.connection) + c := NewEvent(r.Connection) switch instance := i.(type) { case *v1.Event: c.instance = instance @@ -52,7 +52,7 @@ func (r *Event) New(i interface{}) Columnar { // Marshal resource to yaml. func (r *Event) Marshal(path string) (string, error) { ns, n := namespaced(path) - i, err := r.resource.Get(ns, n) + i, err := r.Resource.Get(ns, n) if err != nil { return "", err } diff --git a/internal/resource/evt_test.go b/internal/resource/evt_test.go index 53ffaadf..eb4056fc 100644 --- a/internal/resource/evt_test.go +++ b/internal/resource/evt_test.go @@ -11,57 +11,64 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func TestEventListAccess(t *testing.T) { +func NewEventListWithArgs(ns string, r *resource.Event) resource.List { + return resource.NewList(ns, "ev", r, resource.AllVerbsAccess|resource.DescribeAccess) +} + +func NewEventWithArgs(conn k8s.Connection, res resource.Cruder) *resource.Event { + r := &resource.Event{Base: resource.NewBase(conn, res)} + r.Factory = r + return r +} + +func TestEventAccess(t *testing.T) { + mc := NewMockConnection() + mr := NewMockCruder() + ns := "blee" - l := resource.NewEventList(resource.AllNamespaces) + l := NewEventListWithArgs(resource.AllNamespaces, NewEventWithArgs(mc, mr)) l.SetNamespace(ns) assert.Equal(t, "blee", l.GetNamespace()) - assert.Equal(t, "event", l.GetName()) + assert.Equal(t, "ev", l.GetName()) for _, a := range []int{resource.ListAccess, resource.NamespaceAccess} { assert.True(t, l.Access(a)) } } -func TestEventHeader(t *testing.T) { - assert.Equal(t, resource.Row{"NAME", "REASON", "SOURCE", "COUNT", "MESSAGE", "AGE"}, newEvent().Header(resource.DefaultNamespace)) -} - func TestEventFields(t *testing.T) { r := newEvent().Fields("blee") assert.Equal(t, resource.Row{"fred", "blah", "", "1"}, r[:4]) } func TestEventMarshal(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.Get("blee", "fred")).ThenReturn(k8sEvent(), nil) - ca := NewMockCaller() - m.When(ca.Get("blee", "fred")).ThenReturn(k8sEvent(), nil) - - cm := resource.NewEventWithArgs(ca) + cm := NewEventWithArgs(mc, mr) ma, err := cm.Marshal("blee/fred") - ca.VerifyWasCalledOnce().Get("blee", "fred") + mr.VerifyWasCalledOnce().Get("blee", "fred") assert.Nil(t, err) assert.Equal(t, evYaml(), ma) } -func TestEventListData(t *testing.T) { - setup(t) +func TestEventData(t *testing.T) { + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.List("blee")).ThenReturn(k8s.Collection{*k8sEvent()}, nil) - ca := NewMockCaller() - m.When(ca.List(resource.NotNamespaced)).ThenReturn(k8s.Collection{*k8sEvent()}, nil) - - l := resource.NewEventListWithArgs("-", resource.NewEventWithArgs(ca)) - // Make sure we can get deltas! + l := NewEventListWithArgs("blee", NewEventWithArgs(mc, mr)) + // Make sure we mrn get deltas! for i := 0; i < 2; i++ { err := l.Reconcile() assert.Nil(t, err) } - ca.VerifyWasCalled(m.Times(2)).List(resource.NotNamespaced) + mr.VerifyWasCalled(m.Times(2)).List("blee") td := l.Data() assert.Equal(t, 1, len(td.Rows)) - assert.Equal(t, resource.NotNamespaced, l.GetNamespace()) + assert.Equal(t, "blee", l.GetNamespace()) row := td.Rows["blee/fred"] assert.Equal(t, 6, len(row.Deltas)) for _, d := range row.Deltas { @@ -86,7 +93,8 @@ func k8sEvent() *v1.Event { } func newEvent() resource.Columnar { - return resource.NewEvent().NewInstance(k8sEvent()) + mc := NewMockConnection() + return resource.NewEvent(mc).New(k8sEvent()) } func evYaml() string { diff --git a/internal/resource/hpa.go b/internal/resource/hpa.go index 0e1c7bac..f1f4c27f 100644 --- a/internal/resource/hpa.go +++ b/internal/resource/hpa.go @@ -18,7 +18,7 @@ type HPA struct { // NewHPAList returns a new resource list. func NewHPAList(c k8s.Connection, ns string) List { - return newList( + return NewList( ns, "hpa", NewHPA(c), @@ -28,7 +28,7 @@ func NewHPAList(c k8s.Connection, ns string) List { // NewHPA instantiates a new HPA. func NewHPA(c k8s.Connection) *HPA { - hpa := &HPA{&Base{connection: c, resource: k8s.NewHPA(c)}, nil} + hpa := &HPA{&Base{Connection: c, Resource: k8s.NewHPA(c)}, nil} hpa.Factory = hpa return hpa @@ -36,7 +36,7 @@ func NewHPA(c k8s.Connection) *HPA { // New builds a new HPA instance from a k8s resource. func (r *HPA) New(i interface{}) Columnar { - c := NewHPA(r.connection) + c := NewHPA(r.Connection) switch instance := i.(type) { case *autoscalingv2beta2.HorizontalPodAutoscaler: c.instance = instance @@ -53,7 +53,7 @@ func (r *HPA) New(i interface{}) Columnar { // Marshal resource to yaml. func (r *HPA) Marshal(path string) (string, error) { ns, n := namespaced(path) - i, err := r.resource.Get(ns, n) + i, err := r.Resource.Get(ns, n) if err != nil { return "", err } diff --git a/internal/resource/hpa_test.go b/internal/resource/hpa_test.go index 7d3ea2bf..e9a35eba 100644 --- a/internal/resource/hpa_test.go +++ b/internal/resource/hpa_test.go @@ -5,18 +5,30 @@ import ( "github.com/derailed/k9s/internal/k8s" "github.com/derailed/k9s/internal/resource" - res "k8s.io/apimachinery/pkg/api/resource" - m "github.com/petergtz/pegomock" "github.com/stretchr/testify/assert" autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2" v1 "k8s.io/api/core/v1" + res "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +func NewHPAListWithArgs(ns string, r *resource.HPA) resource.List { + return resource.NewList(ns, "hpa", r, resource.AllVerbsAccess|resource.DescribeAccess) +} + +func NewHPAWithArgs(conn k8s.Connection, res resource.Cruder) *resource.HPA { + r := &resource.HPA{Base: resource.NewBase(conn, res)} + r.Factory = r + return r +} + func TestHPAListAccess(t *testing.T) { + mc := NewMockConnection() + mr := NewMockCruder() + ns := "blee" - l := resource.NewHPAList(resource.AllNamespaces) + l := NewHPAListWithArgs(resource.AllNamespaces, NewHPAWithArgs(mc, mr)) l.SetNamespace(ns) assert.Equal(t, "blee", l.GetNamespace()) @@ -26,45 +38,39 @@ func TestHPAListAccess(t *testing.T) { } } -func TestHPAHeader(t *testing.T) { - assert.Equal(t, resource.Row{"NAME", "REFERENCE", "TARGETS", "MINPODS", "MAXPODS", "REPLICAS", "AGE"}, newHPA().Header(resource.DefaultNamespace)) -} - func TestHPAFields(t *testing.T) { r := newHPA().Fields("blee") assert.Equal(t, "fred", r[0]) } func TestHPAMarshal(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.Get("blee", "fred")).ThenReturn(k8sHPA(), nil) - ca := NewMockCaller() - m.When(ca.Get("blee", "fred")).ThenReturn(k8sHPA(), nil) - - cm := resource.NewHPAWithArgs(ca) + cm := NewHPAWithArgs(mc, mr) ma, err := cm.Marshal("blee/fred") - ca.VerifyWasCalledOnce().Get("blee", "fred") + mr.VerifyWasCalledOnce().Get("blee", "fred") assert.Nil(t, err) assert.Equal(t, hpaYaml(), ma) } func TestHPAListData(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.List("blee")).ThenReturn(k8s.Collection{*k8sHPA()}, nil) - ca := NewMockCaller() - m.When(ca.List(resource.NotNamespaced)).ThenReturn(k8s.Collection{*k8sHPA()}, nil) - - l := resource.NewHPAListWithArgs("-", resource.NewHPAWithArgs(ca)) - // Make sure we can get deltas! + l := NewHPAListWithArgs("blee", NewHPAWithArgs(mc, mr)) + // Make sure we mrn get deltas! for i := 0; i < 2; i++ { err := l.Reconcile() assert.Nil(t, err) } - ca.VerifyWasCalled(m.Times(2)).List(resource.NotNamespaced) + mr.VerifyWasCalled(m.Times(2)).List("blee") td := l.Data() assert.Equal(t, 1, len(td.Rows)) - assert.Equal(t, resource.NotNamespaced, l.GetNamespace()) + assert.Equal(t, "blee", l.GetNamespace()) row := td.Rows["blee/fred"] assert.Equal(t, 7, len(row.Deltas)) for _, d := range row.Deltas { @@ -120,7 +126,8 @@ func k8sHPA() *autoscalingv2beta2.HorizontalPodAutoscaler { } func newHPA() resource.Columnar { - return resource.NewHPA().NewInstance(k8sHPA()) + mc := NewMockConnection() + return resource.NewHPA(mc).New(k8sHPA()) } func hpaYaml() string { diff --git a/internal/resource/ing.go b/internal/resource/ing.go index 3ab020b8..37210ead 100644 --- a/internal/resource/ing.go +++ b/internal/resource/ing.go @@ -17,7 +17,7 @@ type Ingress struct { // NewIngressList returns a new resource list. func NewIngressList(c k8s.Connection, ns string) List { - return newList( + return NewList( ns, "ing", NewIngress(c), @@ -27,7 +27,7 @@ func NewIngressList(c k8s.Connection, ns string) List { // NewIngress instantiates a new Ingress. func NewIngress(c k8s.Connection) *Ingress { - ing := &Ingress{&Base{connection: c, resource: k8s.NewIngress(c)}, nil} + ing := &Ingress{&Base{Connection: c, Resource: k8s.NewIngress(c)}, nil} ing.Factory = ing return ing @@ -35,7 +35,7 @@ func NewIngress(c k8s.Connection) *Ingress { // New builds a new Ingress instance from a k8s resource. func (r *Ingress) New(i interface{}) Columnar { - c := NewIngress(r.connection) + c := NewIngress(r.Connection) switch instance := i.(type) { case *v1beta1.Ingress: c.instance = instance @@ -52,7 +52,7 @@ func (r *Ingress) New(i interface{}) Columnar { // Marshal resource to yaml. func (r *Ingress) Marshal(path string) (string, error) { ns, n := namespaced(path) - i, err := r.resource.Get(ns, n) + i, err := r.Resource.Get(ns, n) if err != nil { return "", err } diff --git a/internal/resource/ing_test.go b/internal/resource/ing_test.go index 76a6ae02..0617abf4 100644 --- a/internal/resource/ing_test.go +++ b/internal/resource/ing_test.go @@ -11,9 +11,22 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +func NewIngressListWithArgs(ns string, r *resource.Ingress) resource.List { + return resource.NewList(ns, "ing", r, resource.AllVerbsAccess|resource.DescribeAccess) +} + +func NewIngressWithArgs(conn k8s.Connection, res resource.Cruder) *resource.Ingress { + r := &resource.Ingress{Base: resource.NewBase(conn, res)} + r.Factory = r + return r +} + func TestIngressListAccess(t *testing.T) { + mc := NewMockConnection() + mr := NewMockCruder() + ns := "blee" - l := resource.NewIngressList(resource.AllNamespaces) + l := NewIngressListWithArgs(resource.AllNamespaces, NewIngressWithArgs(mc, mr)) l.SetNamespace(ns) assert.Equal(t, "blee", l.GetNamespace()) @@ -23,45 +36,39 @@ func TestIngressListAccess(t *testing.T) { } } -func TestIngressHeader(t *testing.T) { - assert.Equal(t, resource.Row{"NAME", "HOSTS", "ADDRESS", "PORT", "AGE"}, newIngress().Header(resource.DefaultNamespace)) -} - func TestIngressFields(t *testing.T) { r := newIngress().Fields("blee") assert.Equal(t, "fred", r[0]) } func TestIngressMarshal(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.Get("blee", "fred")).ThenReturn(k8sIngress(), nil) - ca := NewMockCaller() - m.When(ca.Get("blee", "fred")).ThenReturn(k8sIngress(), nil) - - cm := resource.NewIngressWithArgs(ca) + cm := NewIngressWithArgs(mc, mr) ma, err := cm.Marshal("blee/fred") - ca.VerifyWasCalledOnce().Get("blee", "fred") + mr.VerifyWasCalledOnce().Get("blee", "fred") assert.Nil(t, err) assert.Equal(t, ingYaml(), ma) } func TestIngressListData(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.List("blee")).ThenReturn(k8s.Collection{*k8sIngress()}, nil) - ca := NewMockCaller() - m.When(ca.List(resource.NotNamespaced)).ThenReturn(k8s.Collection{*k8sIngress()}, nil) - - l := resource.NewIngressListWithArgs("-", resource.NewIngressWithArgs(ca)) - // Make sure we can get deltas! + l := NewIngressListWithArgs("blee", NewIngressWithArgs(mc, mr)) + // Make sure we mrn get deltas! for i := 0; i < 2; i++ { err := l.Reconcile() assert.Nil(t, err) } - ca.VerifyWasCalled(m.Times(2)).List(resource.NotNamespaced) + mr.VerifyWasCalled(m.Times(2)).List("blee") td := l.Data() assert.Equal(t, 1, len(td.Rows)) - assert.Equal(t, resource.NotNamespaced, l.GetNamespace()) + assert.Equal(t, "blee", l.GetNamespace()) row := td.Rows["blee/fred"] assert.Equal(t, 5, len(row.Deltas)) for _, d := range row.Deltas { @@ -88,7 +95,8 @@ func k8sIngress() *v1beta1.Ingress { } func newIngress() resource.Columnar { - return resource.NewIngress().NewInstance(k8sIngress()) + mc := NewMockConnection() + return resource.NewIngress(mc).New(k8sIngress()) } func ingYaml() string { diff --git a/internal/resource/job.go b/internal/resource/job.go index 65f9cb48..c4a95f39 100644 --- a/internal/resource/job.go +++ b/internal/resource/job.go @@ -20,7 +20,7 @@ type Job struct { // NewJobList returns a new resource list. func NewJobList(c k8s.Connection, ns string) List { - return newList( + return NewList( ns, "job", NewJob(c), @@ -30,7 +30,7 @@ func NewJobList(c k8s.Connection, ns string) List { // NewJob instantiates a new Job. func NewJob(c k8s.Connection) *Job { - j := &Job{&Base{connection: c, resource: k8s.NewJob(c)}, nil} + j := &Job{&Base{Connection: c, Resource: k8s.NewJob(c)}, nil} j.Factory = j return j @@ -38,7 +38,7 @@ func NewJob(c k8s.Connection) *Job { // New builds a new Job instance from a k8s resource. func (r *Job) New(i interface{}) Columnar { - c := NewJob(r.connection) + c := NewJob(r.Connection) switch instance := i.(type) { case *v1.Job: c.instance = instance @@ -55,7 +55,7 @@ func (r *Job) New(i interface{}) Columnar { // Marshal resource to yaml. func (r *Job) Marshal(path string) (string, error) { ns, n := namespaced(path) - i, err := r.resource.Get(ns, n) + i, err := r.Resource.Get(ns, n) if err != nil { return "", err } @@ -71,12 +71,12 @@ func (r *Job) Marshal(path string) (string, error) { func (r *Job) Containers(path string, includeInit bool) ([]string, error) { ns, n := namespaced(path) - return r.resource.(k8s.Loggable).Containers(ns, n, includeInit) + return r.Resource.(k8s.Loggable).Containers(ns, n, includeInit) } // Logs retrieves logs for a given container. func (r *Job) Logs(c chan<- string, ns, n, co string, lines int64, prev bool) (context.CancelFunc, error) { - req := r.resource.(k8s.Loggable).Logs(ns, n, co, lines, prev) + req := r.Resource.(k8s.Loggable).Logs(ns, n, co, lines, prev) ctx, cancel := context.WithCancel(context.TODO()) req.Context(ctx) diff --git a/internal/resource/job_test.go b/internal/resource/job_test.go index bc662132..4a5374e7 100644 --- a/internal/resource/job_test.go +++ b/internal/resource/job_test.go @@ -11,9 +11,22 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +func NewJobListWithArgs(ns string, r *resource.Job) resource.List { + return resource.NewList(ns, "job", r, resource.AllVerbsAccess|resource.DescribeAccess) +} + +func NewJobWithArgs(conn k8s.Connection, res resource.Cruder) *resource.Job { + r := &resource.Job{Base: resource.NewBase(conn, res)} + r.Factory = r + return r +} + func TestJobListAccess(t *testing.T) { + mc := NewMockConnection() + mr := NewMockCruder() + ns := "blee" - l := resource.NewJobList(resource.AllNamespaces) + l := NewJobListWithArgs(resource.AllNamespaces, NewJobWithArgs(mc, mr)) l.SetNamespace(ns) assert.Equal(t, "blee", l.GetNamespace()) @@ -23,45 +36,39 @@ func TestJobListAccess(t *testing.T) { } } -func TestJobHeader(t *testing.T) { - assert.Equal(t, resource.Row{"NAME", "COMPLETIONS", "DURATION", "AGE"}, newJob().Header(resource.DefaultNamespace)) -} - func TestJobFields(t *testing.T) { r := newJob().Fields("blee") assert.Equal(t, "fred", r[0]) } func TestJobMarshal(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.Get("blee", "fred")).ThenReturn(k8sJob(), nil) - ca := NewMockCaller() - m.When(ca.Get("blee", "fred")).ThenReturn(k8sJob(), nil) - - cm := resource.NewJobWithArgs(ca) + cm := NewJobWithArgs(mc, mr) ma, err := cm.Marshal("blee/fred") - ca.VerifyWasCalledOnce().Get("blee", "fred") + mr.VerifyWasCalledOnce().Get("blee", "fred") assert.Nil(t, err) assert.Equal(t, jobYaml(), ma) } func TestJobListData(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.List("blee")).ThenReturn(k8s.Collection{*k8sJob()}, nil) - ca := NewMockCaller() - m.When(ca.List(resource.NotNamespaced)).ThenReturn(k8s.Collection{*k8sJob()}, nil) - - l := resource.NewJobListWithArgs("-", resource.NewJobWithArgs(ca)) - // Make sure we can get deltas! + l := NewJobListWithArgs("blee", NewJobWithArgs(mc, mr)) + // Make sure we mrn get deltas! for i := 0; i < 2; i++ { err := l.Reconcile() assert.Nil(t, err) } - ca.VerifyWasCalled(m.Times(2)).List(resource.NotNamespaced) + mr.VerifyWasCalled(m.Times(2)).List("blee") td := l.Data() assert.Equal(t, 1, len(td.Rows)) - assert.Equal(t, resource.NotNamespaced, l.GetNamespace()) + assert.Equal(t, "blee", l.GetNamespace()) row := td.Rows["blee/fred"] assert.Equal(t, 4, len(row.Deltas)) for _, d := range row.Deltas { @@ -92,7 +99,8 @@ func k8sJob() *v1.Job { } func newJob() resource.Columnar { - return resource.NewJob().NewInstance(k8sJob()) + mc := NewMockConnection() + return resource.NewJob(mc).New(k8sJob()) } func jobYaml() string { diff --git a/internal/resource/list.go b/internal/resource/list.go index e69e5ca0..837173d8 100644 --- a/internal/resource/list.go +++ b/internal/resource/list.go @@ -107,7 +107,8 @@ func newRowEvent(a watch.EventType, f, d Row) *RowEvent { return &RowEvent{Action: a, Fields: f, Deltas: d} } -func newList(ns, name string, res Resource, verbs int) *list { +// NewList returns a new resource list. +func NewList(ns, name string, res Resource, verbs int) *list { return &list{ namespace: ns, name: name, diff --git a/internal/resource/mock_clustermeta_test.go b/internal/resource/mock_clustermeta_test.go index a6ed4259..3c4fba7d 100644 --- a/internal/resource/mock_clustermeta_test.go +++ b/internal/resource/mock_clustermeta_test.go @@ -112,6 +112,21 @@ func (mock *MockClusterMeta) HasMetrics() bool { return ret0 } +func (mock *MockClusterMeta) IsNamespaced(_param0 string) bool { + if mock == nil { + panic("mock must not be nil. Use myMock := NewMockClusterMeta().") + } + params := []pegomock.Param{_param0} + result := pegomock.GetGenericMockFrom(mock).Invoke("IsNamespaced", params, []reflect.Type{reflect.TypeOf((*bool)(nil)).Elem()}) + var ret0 bool + if len(result) != 0 { + if result[0] != nil { + ret0 = result[0].(bool) + } + } + return ret0 +} + func (mock *MockClusterMeta) MXDial() (*versioned.Clientset, error) { if mock == nil { panic("mock must not be nil. Use myMock := NewMockClusterMeta().") @@ -161,6 +176,21 @@ func (mock *MockClusterMeta) RestConfigOrDie() *rest.Config { return ret0 } +func (mock *MockClusterMeta) SupportsResource(_param0 string) bool { + if mock == nil { + panic("mock must not be nil. Use myMock := NewMockClusterMeta().") + } + params := []pegomock.Param{_param0} + result := pegomock.GetGenericMockFrom(mock).Invoke("SupportsResource", params, []reflect.Type{reflect.TypeOf((*bool)(nil)).Elem()}) + var ret0 bool + if len(result) != 0 { + if result[0] != nil { + ret0 = result[0].(bool) + } + } + return ret0 +} + func (mock *MockClusterMeta) SwitchContextOrDie(_param0 string) { if mock == nil { panic("mock must not be nil. Use myMock := NewMockClusterMeta().") @@ -342,6 +372,33 @@ func (c *ClusterMeta_HasMetrics_OngoingVerification) GetCapturedArguments() { func (c *ClusterMeta_HasMetrics_OngoingVerification) GetAllCapturedArguments() { } +func (verifier *VerifierClusterMeta) IsNamespaced(_param0 string) *ClusterMeta_IsNamespaced_OngoingVerification { + params := []pegomock.Param{_param0} + methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "IsNamespaced", params, verifier.timeout) + return &ClusterMeta_IsNamespaced_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} +} + +type ClusterMeta_IsNamespaced_OngoingVerification struct { + mock *MockClusterMeta + methodInvocations []pegomock.MethodInvocation +} + +func (c *ClusterMeta_IsNamespaced_OngoingVerification) GetCapturedArguments() string { + _param0 := c.GetAllCapturedArguments() + return _param0[len(_param0)-1] +} + +func (c *ClusterMeta_IsNamespaced_OngoingVerification) GetAllCapturedArguments() (_param0 []string) { + params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations) + if len(params) > 0 { + _param0 = make([]string, len(params[0])) + for u, param := range params[0] { + _param0[u] = param.(string) + } + } + return +} + func (verifier *VerifierClusterMeta) MXDial() *ClusterMeta_MXDial_OngoingVerification { params := []pegomock.Param{} methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "MXDial", params, verifier.timeout) @@ -393,6 +450,33 @@ func (c *ClusterMeta_RestConfigOrDie_OngoingVerification) GetCapturedArguments() func (c *ClusterMeta_RestConfigOrDie_OngoingVerification) GetAllCapturedArguments() { } +func (verifier *VerifierClusterMeta) SupportsResource(_param0 string) *ClusterMeta_SupportsResource_OngoingVerification { + params := []pegomock.Param{_param0} + methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "SupportsResource", params, verifier.timeout) + return &ClusterMeta_SupportsResource_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} +} + +type ClusterMeta_SupportsResource_OngoingVerification struct { + mock *MockClusterMeta + methodInvocations []pegomock.MethodInvocation +} + +func (c *ClusterMeta_SupportsResource_OngoingVerification) GetCapturedArguments() string { + _param0 := c.GetAllCapturedArguments() + return _param0[len(_param0)-1] +} + +func (c *ClusterMeta_SupportsResource_OngoingVerification) GetAllCapturedArguments() (_param0 []string) { + params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations) + if len(params) > 0 { + _param0 = make([]string, len(params[0])) + for u, param := range params[0] { + _param0[u] = param.(string) + } + } + return +} + func (verifier *VerifierClusterMeta) SwitchContextOrDie(_param0 string) *ClusterMeta_SwitchContextOrDie_OngoingVerification { params := []pegomock.Param{_param0} methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "SwitchContextOrDie", params, verifier.timeout) diff --git a/internal/resource/mock_connection_test.go b/internal/resource/mock_connection_test.go index ee870740..b6c6a635 100644 --- a/internal/resource/mock_connection_test.go +++ b/internal/resource/mock_connection_test.go @@ -82,6 +82,21 @@ func (mock *MockConnection) HasMetrics() bool { return ret0 } +func (mock *MockConnection) IsNamespaced(_param0 string) bool { + if mock == nil { + panic("mock must not be nil. Use myMock := NewMockConnection().") + } + params := []pegomock.Param{_param0} + result := pegomock.GetGenericMockFrom(mock).Invoke("IsNamespaced", params, []reflect.Type{reflect.TypeOf((*bool)(nil)).Elem()}) + var ret0 bool + if len(result) != 0 { + if result[0] != nil { + ret0 = result[0].(bool) + } + } + return ret0 +} + func (mock *MockConnection) MXDial() (*versioned.Clientset, error) { if mock == nil { panic("mock must not be nil. Use myMock := NewMockConnection().") @@ -131,6 +146,21 @@ func (mock *MockConnection) RestConfigOrDie() *rest.Config { return ret0 } +func (mock *MockConnection) SupportsResource(_param0 string) bool { + if mock == nil { + panic("mock must not be nil. Use myMock := NewMockConnection().") + } + params := []pegomock.Param{_param0} + result := pegomock.GetGenericMockFrom(mock).Invoke("SupportsResource", params, []reflect.Type{reflect.TypeOf((*bool)(nil)).Elem()}) + var ret0 bool + if len(result) != 0 { + if result[0] != nil { + ret0 = result[0].(bool) + } + } + return ret0 +} + func (mock *MockConnection) SwitchContextOrDie(_param0 string) { if mock == nil { panic("mock must not be nil. Use myMock := NewMockConnection().") @@ -244,6 +274,33 @@ func (c *Connection_HasMetrics_OngoingVerification) GetCapturedArguments() { func (c *Connection_HasMetrics_OngoingVerification) GetAllCapturedArguments() { } +func (verifier *VerifierConnection) IsNamespaced(_param0 string) *Connection_IsNamespaced_OngoingVerification { + params := []pegomock.Param{_param0} + methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "IsNamespaced", params, verifier.timeout) + return &Connection_IsNamespaced_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} +} + +type Connection_IsNamespaced_OngoingVerification struct { + mock *MockConnection + methodInvocations []pegomock.MethodInvocation +} + +func (c *Connection_IsNamespaced_OngoingVerification) GetCapturedArguments() string { + _param0 := c.GetAllCapturedArguments() + return _param0[len(_param0)-1] +} + +func (c *Connection_IsNamespaced_OngoingVerification) GetAllCapturedArguments() (_param0 []string) { + params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations) + if len(params) > 0 { + _param0 = make([]string, len(params[0])) + for u, param := range params[0] { + _param0[u] = param.(string) + } + } + return +} + func (verifier *VerifierConnection) MXDial() *Connection_MXDial_OngoingVerification { params := []pegomock.Param{} methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "MXDial", params, verifier.timeout) @@ -295,6 +352,33 @@ func (c *Connection_RestConfigOrDie_OngoingVerification) GetCapturedArguments() func (c *Connection_RestConfigOrDie_OngoingVerification) GetAllCapturedArguments() { } +func (verifier *VerifierConnection) SupportsResource(_param0 string) *Connection_SupportsResource_OngoingVerification { + params := []pegomock.Param{_param0} + methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "SupportsResource", params, verifier.timeout) + return &Connection_SupportsResource_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} +} + +type Connection_SupportsResource_OngoingVerification struct { + mock *MockConnection + methodInvocations []pegomock.MethodInvocation +} + +func (c *Connection_SupportsResource_OngoingVerification) GetCapturedArguments() string { + _param0 := c.GetAllCapturedArguments() + return _param0[len(_param0)-1] +} + +func (c *Connection_SupportsResource_OngoingVerification) GetAllCapturedArguments() (_param0 []string) { + params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations) + if len(params) > 0 { + _param0 = make([]string, len(params[0])) + for u, param := range params[0] { + _param0[u] = param.(string) + } + } + return +} + func (verifier *VerifierConnection) SwitchContextOrDie(_param0 string) *Connection_SwitchContextOrDie_OngoingVerification { params := []pegomock.Param{_param0} methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "SwitchContextOrDie", params, verifier.timeout) diff --git a/internal/resource/mock_resource_test.go b/internal/resource/mock_resource_test.go index 60fdc29e..9ba80bae 100644 --- a/internal/resource/mock_resource_test.go +++ b/internal/resource/mock_resource_test.go @@ -6,6 +6,7 @@ package resource_test import ( resource "github.com/derailed/k9s/internal/resource" pegomock "github.com/petergtz/pegomock" + genericclioptions "k8s.io/cli-runtime/pkg/genericclioptions" "reflect" "time" ) @@ -33,6 +34,25 @@ func (mock *MockResource) Delete(_param0 string) error { return ret0 } +func (mock *MockResource) Describe(_param0 string, _param1 string, _param2 *genericclioptions.ConfigFlags) (string, error) { + if mock == nil { + panic("mock must not be nil. Use myMock := NewMockResource().") + } + params := []pegomock.Param{_param0, _param1, _param2} + result := pegomock.GetGenericMockFrom(mock).Invoke("Describe", params, []reflect.Type{reflect.TypeOf((*string)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()}) + var ret0 string + var ret1 error + if len(result) != 0 { + if result[0] != nil { + ret0 = result[0].(string) + } + if result[1] != nil { + ret1 = result[1].(error) + } + } + return ret0, ret1 +} + func (mock *MockResource) Get(_param0 string) (resource.Columnar, error) { if mock == nil { panic("mock must not be nil. Use myMock := NewMockResource().") @@ -105,6 +125,21 @@ func (mock *MockResource) Marshal(_param0 string) (string, error) { return ret0, ret1 } +func (mock *MockResource) New(_param0 interface{}) resource.Columnar { + if mock == nil { + panic("mock must not be nil. Use myMock := NewMockResource().") + } + params := []pegomock.Param{_param0} + result := pegomock.GetGenericMockFrom(mock).Invoke("New", params, []reflect.Type{reflect.TypeOf((*resource.Columnar)(nil)).Elem()}) + var ret0 resource.Columnar + if len(result) != 0 { + if result[0] != nil { + ret0 = result[0].(resource.Columnar) + } + } + return ret0 +} + func (mock *MockResource) VerifyWasCalledOnce() *VerifierResource { return &VerifierResource{ mock: mock, @@ -169,6 +204,41 @@ func (c *Resource_Delete_OngoingVerification) GetAllCapturedArguments() (_param0 return } +func (verifier *VerifierResource) Describe(_param0 string, _param1 string, _param2 *genericclioptions.ConfigFlags) *Resource_Describe_OngoingVerification { + params := []pegomock.Param{_param0, _param1, _param2} + methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "Describe", params, verifier.timeout) + return &Resource_Describe_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} +} + +type Resource_Describe_OngoingVerification struct { + mock *MockResource + methodInvocations []pegomock.MethodInvocation +} + +func (c *Resource_Describe_OngoingVerification) GetCapturedArguments() (string, string, *genericclioptions.ConfigFlags) { + _param0, _param1, _param2 := c.GetAllCapturedArguments() + return _param0[len(_param0)-1], _param1[len(_param1)-1], _param2[len(_param2)-1] +} + +func (c *Resource_Describe_OngoingVerification) GetAllCapturedArguments() (_param0 []string, _param1 []string, _param2 []*genericclioptions.ConfigFlags) { + params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations) + if len(params) > 0 { + _param0 = make([]string, len(params[0])) + for u, param := range params[0] { + _param0[u] = param.(string) + } + _param1 = make([]string, len(params[1])) + for u, param := range params[1] { + _param1[u] = param.(string) + } + _param2 = make([]*genericclioptions.ConfigFlags, len(params[2])) + for u, param := range params[2] { + _param2[u] = param.(*genericclioptions.ConfigFlags) + } + } + return +} + func (verifier *VerifierResource) Get(_param0 string) *Resource_Get_OngoingVerification { params := []pegomock.Param{_param0} methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "Get", params, verifier.timeout) @@ -276,3 +346,30 @@ func (c *Resource_Marshal_OngoingVerification) GetAllCapturedArguments() (_param } return } + +func (verifier *VerifierResource) New(_param0 interface{}) *Resource_New_OngoingVerification { + params := []pegomock.Param{_param0} + methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "New", params, verifier.timeout) + return &Resource_New_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} +} + +type Resource_New_OngoingVerification struct { + mock *MockResource + methodInvocations []pegomock.MethodInvocation +} + +func (c *Resource_New_OngoingVerification) GetCapturedArguments() interface{} { + _param0 := c.GetAllCapturedArguments() + return _param0[len(_param0)-1] +} + +func (c *Resource_New_OngoingVerification) GetAllCapturedArguments() (_param0 []interface{}) { + params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations) + if len(params) > 0 { + _param0 = make([]interface{}, len(params[0])) + for u, param := range params[0] { + _param0[u] = param.(interface{}) + } + } + return +} diff --git a/internal/resource/mock_switchableres_test.go b/internal/resource/mock_switchableresource_test.go similarity index 59% rename from internal/resource/mock_switchableres_test.go rename to internal/resource/mock_switchableresource_test.go index 4585b31e..05482b7f 100644 --- a/internal/resource/mock_switchableres_test.go +++ b/internal/resource/mock_switchableresource_test.go @@ -1,5 +1,5 @@ // Code generated by pegomock. DO NOT EDIT. -// Source: github.com/derailed/k9s/internal/resource (interfaces: SwitchableRes) +// Source: github.com/derailed/k9s/internal/resource (interfaces: SwitchableResource) package resource_test @@ -10,17 +10,17 @@ import ( "time" ) -type MockSwitchableRes struct { +type MockSwitchableResource struct { fail func(message string, callerSkip ...int) } -func NewMockSwitchableRes() *MockSwitchableRes { - return &MockSwitchableRes{fail: pegomock.GlobalFailHandler} +func NewMockSwitchableResource() *MockSwitchableResource { + return &MockSwitchableResource{fail: pegomock.GlobalFailHandler} } -func (mock *MockSwitchableRes) Delete(_param0 string, _param1 string) error { +func (mock *MockSwitchableResource) Delete(_param0 string, _param1 string) error { if mock == nil { - panic("mock must not be nil. Use myMock := NewMockSwitchableRes().") + panic("mock must not be nil. Use myMock := NewMockSwitchableResource().") } params := []pegomock.Param{_param0, _param1} result := pegomock.GetGenericMockFrom(mock).Invoke("Delete", params, []reflect.Type{reflect.TypeOf((*error)(nil)).Elem()}) @@ -33,9 +33,9 @@ func (mock *MockSwitchableRes) Delete(_param0 string, _param1 string) error { return ret0 } -func (mock *MockSwitchableRes) Get(_param0 string, _param1 string) (interface{}, error) { +func (mock *MockSwitchableResource) Get(_param0 string, _param1 string) (interface{}, error) { if mock == nil { - panic("mock must not be nil. Use myMock := NewMockSwitchableRes().") + panic("mock must not be nil. Use myMock := NewMockSwitchableResource().") } params := []pegomock.Param{_param0, _param1} result := pegomock.GetGenericMockFrom(mock).Invoke("Get", params, []reflect.Type{reflect.TypeOf((*interface{})(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()}) @@ -52,9 +52,9 @@ func (mock *MockSwitchableRes) Get(_param0 string, _param1 string) (interface{}, return ret0, ret1 } -func (mock *MockSwitchableRes) List(_param0 string) (k8s.Collection, error) { +func (mock *MockSwitchableResource) List(_param0 string) (k8s.Collection, error) { if mock == nil { - panic("mock must not be nil. Use myMock := NewMockSwitchableRes().") + panic("mock must not be nil. Use myMock := NewMockSwitchableResource().") } params := []pegomock.Param{_param0} result := pegomock.GetGenericMockFrom(mock).Invoke("List", params, []reflect.Type{reflect.TypeOf((*k8s.Collection)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()}) @@ -71,9 +71,9 @@ func (mock *MockSwitchableRes) List(_param0 string) (k8s.Collection, error) { return ret0, ret1 } -func (mock *MockSwitchableRes) Switch(_param0 string) error { +func (mock *MockSwitchableResource) Switch(_param0 string) error { if mock == nil { - panic("mock must not be nil. Use myMock := NewMockSwitchableRes().") + panic("mock must not be nil. Use myMock := NewMockSwitchableResource().") } params := []pegomock.Param{_param0} result := pegomock.GetGenericMockFrom(mock).Invoke("Switch", params, []reflect.Type{reflect.TypeOf((*error)(nil)).Elem()}) @@ -86,60 +86,60 @@ func (mock *MockSwitchableRes) Switch(_param0 string) error { return ret0 } -func (mock *MockSwitchableRes) VerifyWasCalledOnce() *VerifierSwitchableRes { - return &VerifierSwitchableRes{ +func (mock *MockSwitchableResource) VerifyWasCalledOnce() *VerifierSwitchableResource { + return &VerifierSwitchableResource{ mock: mock, invocationCountMatcher: pegomock.Times(1), } } -func (mock *MockSwitchableRes) VerifyWasCalled(invocationCountMatcher pegomock.Matcher) *VerifierSwitchableRes { - return &VerifierSwitchableRes{ +func (mock *MockSwitchableResource) VerifyWasCalled(invocationCountMatcher pegomock.Matcher) *VerifierSwitchableResource { + return &VerifierSwitchableResource{ mock: mock, invocationCountMatcher: invocationCountMatcher, } } -func (mock *MockSwitchableRes) VerifyWasCalledInOrder(invocationCountMatcher pegomock.Matcher, inOrderContext *pegomock.InOrderContext) *VerifierSwitchableRes { - return &VerifierSwitchableRes{ +func (mock *MockSwitchableResource) VerifyWasCalledInOrder(invocationCountMatcher pegomock.Matcher, inOrderContext *pegomock.InOrderContext) *VerifierSwitchableResource { + return &VerifierSwitchableResource{ mock: mock, invocationCountMatcher: invocationCountMatcher, inOrderContext: inOrderContext, } } -func (mock *MockSwitchableRes) VerifyWasCalledEventually(invocationCountMatcher pegomock.Matcher, timeout time.Duration) *VerifierSwitchableRes { - return &VerifierSwitchableRes{ +func (mock *MockSwitchableResource) VerifyWasCalledEventually(invocationCountMatcher pegomock.Matcher, timeout time.Duration) *VerifierSwitchableResource { + return &VerifierSwitchableResource{ mock: mock, invocationCountMatcher: invocationCountMatcher, timeout: timeout, } } -type VerifierSwitchableRes struct { - mock *MockSwitchableRes +type VerifierSwitchableResource struct { + mock *MockSwitchableResource invocationCountMatcher pegomock.Matcher inOrderContext *pegomock.InOrderContext timeout time.Duration } -func (verifier *VerifierSwitchableRes) Delete(_param0 string, _param1 string) *SwitchableRes_Delete_OngoingVerification { +func (verifier *VerifierSwitchableResource) Delete(_param0 string, _param1 string) *SwitchableResource_Delete_OngoingVerification { params := []pegomock.Param{_param0, _param1} methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "Delete", params, verifier.timeout) - return &SwitchableRes_Delete_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} + return &SwitchableResource_Delete_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} } -type SwitchableRes_Delete_OngoingVerification struct { - mock *MockSwitchableRes +type SwitchableResource_Delete_OngoingVerification struct { + mock *MockSwitchableResource methodInvocations []pegomock.MethodInvocation } -func (c *SwitchableRes_Delete_OngoingVerification) GetCapturedArguments() (string, string) { +func (c *SwitchableResource_Delete_OngoingVerification) GetCapturedArguments() (string, string) { _param0, _param1 := c.GetAllCapturedArguments() return _param0[len(_param0)-1], _param1[len(_param1)-1] } -func (c *SwitchableRes_Delete_OngoingVerification) GetAllCapturedArguments() (_param0 []string, _param1 []string) { +func (c *SwitchableResource_Delete_OngoingVerification) GetAllCapturedArguments() (_param0 []string, _param1 []string) { params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations) if len(params) > 0 { _param0 = make([]string, len(params[0])) @@ -154,23 +154,23 @@ func (c *SwitchableRes_Delete_OngoingVerification) GetAllCapturedArguments() (_p return } -func (verifier *VerifierSwitchableRes) Get(_param0 string, _param1 string) *SwitchableRes_Get_OngoingVerification { +func (verifier *VerifierSwitchableResource) Get(_param0 string, _param1 string) *SwitchableResource_Get_OngoingVerification { params := []pegomock.Param{_param0, _param1} methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "Get", params, verifier.timeout) - return &SwitchableRes_Get_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} + return &SwitchableResource_Get_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} } -type SwitchableRes_Get_OngoingVerification struct { - mock *MockSwitchableRes +type SwitchableResource_Get_OngoingVerification struct { + mock *MockSwitchableResource methodInvocations []pegomock.MethodInvocation } -func (c *SwitchableRes_Get_OngoingVerification) GetCapturedArguments() (string, string) { +func (c *SwitchableResource_Get_OngoingVerification) GetCapturedArguments() (string, string) { _param0, _param1 := c.GetAllCapturedArguments() return _param0[len(_param0)-1], _param1[len(_param1)-1] } -func (c *SwitchableRes_Get_OngoingVerification) GetAllCapturedArguments() (_param0 []string, _param1 []string) { +func (c *SwitchableResource_Get_OngoingVerification) GetAllCapturedArguments() (_param0 []string, _param1 []string) { params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations) if len(params) > 0 { _param0 = make([]string, len(params[0])) @@ -185,23 +185,23 @@ func (c *SwitchableRes_Get_OngoingVerification) GetAllCapturedArguments() (_para return } -func (verifier *VerifierSwitchableRes) List(_param0 string) *SwitchableRes_List_OngoingVerification { +func (verifier *VerifierSwitchableResource) List(_param0 string) *SwitchableResource_List_OngoingVerification { params := []pegomock.Param{_param0} methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "List", params, verifier.timeout) - return &SwitchableRes_List_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} + return &SwitchableResource_List_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} } -type SwitchableRes_List_OngoingVerification struct { - mock *MockSwitchableRes +type SwitchableResource_List_OngoingVerification struct { + mock *MockSwitchableResource methodInvocations []pegomock.MethodInvocation } -func (c *SwitchableRes_List_OngoingVerification) GetCapturedArguments() string { +func (c *SwitchableResource_List_OngoingVerification) GetCapturedArguments() string { _param0 := c.GetAllCapturedArguments() return _param0[len(_param0)-1] } -func (c *SwitchableRes_List_OngoingVerification) GetAllCapturedArguments() (_param0 []string) { +func (c *SwitchableResource_List_OngoingVerification) GetAllCapturedArguments() (_param0 []string) { params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations) if len(params) > 0 { _param0 = make([]string, len(params[0])) @@ -212,23 +212,23 @@ func (c *SwitchableRes_List_OngoingVerification) GetAllCapturedArguments() (_par return } -func (verifier *VerifierSwitchableRes) Switch(_param0 string) *SwitchableRes_Switch_OngoingVerification { +func (verifier *VerifierSwitchableResource) Switch(_param0 string) *SwitchableResource_Switch_OngoingVerification { params := []pegomock.Param{_param0} methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "Switch", params, verifier.timeout) - return &SwitchableRes_Switch_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} + return &SwitchableResource_Switch_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations} } -type SwitchableRes_Switch_OngoingVerification struct { - mock *MockSwitchableRes +type SwitchableResource_Switch_OngoingVerification struct { + mock *MockSwitchableResource methodInvocations []pegomock.MethodInvocation } -func (c *SwitchableRes_Switch_OngoingVerification) GetCapturedArguments() string { +func (c *SwitchableResource_Switch_OngoingVerification) GetCapturedArguments() string { _param0 := c.GetAllCapturedArguments() return _param0[len(_param0)-1] } -func (c *SwitchableRes_Switch_OngoingVerification) GetAllCapturedArguments() (_param0 []string) { +func (c *SwitchableResource_Switch_OngoingVerification) GetAllCapturedArguments() (_param0 []string) { params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations) if len(params) > 0 { _param0 = make([]string, len(params[0])) diff --git a/internal/resource/no.go b/internal/resource/no.go index 32e22aef..f2416719 100644 --- a/internal/resource/no.go +++ b/internal/resource/no.go @@ -19,23 +19,23 @@ const ( type Node struct { *Base instance *v1.Node - metricsServer MetricsServer + MetricsServer MetricsServer metrics k8s.NodeMetrics } // NewNodeList returns a new resource list. -func NewNodeList(c k8s.Connection, ns string) List { - return newList( +func NewNodeList(c k8s.Connection, mx MetricsServer, ns string) List { + return NewList( NotNamespaced, "no", - NewNode(c), + NewNode(c, mx), ViewAccess|DescribeAccess, ) } // NewNode instantiates a new Node. -func NewNode(c k8s.Connection) *Node { - n := &Node{&Base{connection: c, resource: k8s.NewNode(c)}, nil, k8s.NewMetricsServer(c), k8s.NodeMetrics{}} +func NewNode(c k8s.Connection, mx MetricsServer) *Node { + n := &Node{&Base{Connection: c, Resource: k8s.NewNode(c)}, nil, mx, k8s.NodeMetrics{}} n.Factory = n return n @@ -43,7 +43,7 @@ func NewNode(c k8s.Connection) *Node { // New builds a new Node instance from a k8s resource. func (r *Node) New(i interface{}) Columnar { - c := NewNode(r.connection) + c := NewNode(r.Connection, r.MetricsServer) switch instance := i.(type) { case *v1.Node: c.instance = instance @@ -59,7 +59,7 @@ func (r *Node) New(i interface{}) Columnar { // List all resources for a given namespace. func (r *Node) List(ns string) (Columnars, error) { - nn, err := r.resource.List(ns) + nn, err := r.Resource.List(ns) if err != nil { return nil, err } @@ -70,9 +70,9 @@ func (r *Node) List(ns string) (Columnars, error) { } mx := make(k8s.NodesMetrics, len(nodes)) - if r.metricsServer.HasMetrics() { - nmx, _ := r.metricsServer.FetchNodesMetrics() - r.metricsServer.NodesMetrics(nodes, nmx, mx) + if r.MetricsServer.HasMetrics() { + nmx, _ := r.MetricsServer.FetchNodesMetrics() + r.MetricsServer.NodesMetrics(nodes, nmx, mx) } cc := make(Columnars, 0, len(nodes)) @@ -88,7 +88,7 @@ func (r *Node) List(ns string) (Columnars, error) { // Marshal a resource to yaml. func (r *Node) Marshal(path string) (string, error) { ns, n := namespaced(path) - i, err := r.resource.Get(ns, n) + i, err := r.Resource.Get(ns, n) if err != nil { log.Error().Err(err) return "", err diff --git a/internal/resource/no_test.go b/internal/resource/no_test.go index 2eb0fa4c..fe19330b 100644 --- a/internal/resource/no_test.go +++ b/internal/resource/no_test.go @@ -14,9 +14,23 @@ import ( v1beta1 "k8s.io/metrics/pkg/apis/metrics/v1beta1" ) +func NewNodeListWithArgs(ns string, r *resource.Node) resource.List { + return resource.NewList(resource.NotNamespaced, "no", r, resource.ViewAccess|resource.DescribeAccess) +} + +func NewNodeWithArgs(conn k8s.Connection, res resource.Cruder, mx resource.MetricsServer) *resource.Node { + r := &resource.Node{Base: resource.NewBase(conn, res), MetricsServer: mx} + r.Factory = r + return r +} + func TestNodeListAccess(t *testing.T) { + mc := NewMockConnection() + mr := NewMockCruder() + mx := NewMockMetricsServer() + ns := "blee" - l := resource.NewNodeList(resource.AllNamespaces) + l := NewNodeListWithArgs(resource.AllNamespaces, NewNodeWithArgs(mc, mr, mx)) l.SetNamespace(ns) assert.Equal(t, resource.NotNamespaced, l.GetNamespace()) @@ -32,46 +46,42 @@ func TestNodeFields(t *testing.T) { } func TestNodeMarshal(t *testing.T) { - setup(t) - + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.Get("blee", "fred")).ThenReturn(k8sNode(), nil) mx := NewMockMetricsServer() - // m.When(mx.NodesMetrics([]v1.Node{*k8sNode()})). - // ThenReturn(map[string]k8s.RawMetric{"fred": {}}, nil) - ca := NewMockCaller() - m.When(ca.Get("blee", "fred")).ThenReturn(k8sNode(), nil) - cm := resource.NewNodeWithArgs(ca, mx) + cm := NewNodeWithArgs(mc, mr, mx) ma, err := cm.Marshal("blee/fred") - ca.VerifyWasCalledOnce().Get("blee", "fred") + + mr.VerifyWasCalledOnce().Get("blee", "fred") assert.Nil(t, err) assert.Equal(t, noYaml(), ma) } func TestNodeListData(t *testing.T) { - setup(t) - - mockServer := NewMockMetricsServer() - m.When(mockServer.HasMetrics()).ThenReturn(true) - m.When(mockServer.FetchNodesMetrics()). + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.List("-")).ThenReturn(k8s.Collection{*k8sNode()}, nil) + mx := NewMockMetricsServer() + m.When(mx.HasMetrics()).ThenReturn(true) + m.When(mx.FetchNodesMetrics()). ThenReturn([]mv1beta1.NodeMetrics{makeMxNode("fred", "100m", "100Mi")}, nil) - ca := NewMockCaller() - m.When(ca.List("-")).ThenReturn(k8s.Collection{*k8sNode()}, nil) - - l := resource.NewNodeListWithArgs("", resource.NewNodeWithArgs(ca, mockServer)) - // Make sure we can get deltas! + l := NewNodeListWithArgs("-", NewNodeWithArgs(mc, mr, mx)) + // Make sure we mrn get deltas! for i := 0; i < 2; i++ { err := l.Reconcile() assert.Nil(t, err) } - ca.VerifyWasCalled(m.Times(2)).List("-") + mr.VerifyWasCalled(m.Times(2)).List("-") td := l.Data() assert.Equal(t, 1, len(td.Rows)) assert.Equal(t, resource.NotNamespaced, l.GetNamespace()) row, ok := td.Rows["fred"] assert.True(t, ok) - assert.Equal(t, 12, len(row.Deltas)) + assert.Equal(t, 14, len(row.Deltas)) for _, d := range row.Deltas { assert.Equal(t, "", d) } @@ -115,7 +125,9 @@ func makeRes(c, m string) v1.ResourceList { } func newNode() resource.Columnar { - return resource.NewNode().NewInstance(k8sNode()) + mc := NewMockConnection() + mx := NewMockMetricsServer() + return resource.NewNode(mc, mx).New(k8sNode()) } func noYaml() string { diff --git a/internal/resource/ns.go b/internal/resource/ns.go index 4e1d306d..506a38ca 100644 --- a/internal/resource/ns.go +++ b/internal/resource/ns.go @@ -14,7 +14,7 @@ type Namespace struct { // NewNamespaceList returns a new resource list. func NewNamespaceList(c k8s.Connection, ns string) List { - return newList( + return NewList( NotNamespaced, "ns", NewNamespace(c), @@ -24,7 +24,7 @@ func NewNamespaceList(c k8s.Connection, ns string) List { // NewNamespace instantiates a new Namespace. func NewNamespace(c k8s.Connection) *Namespace { - n := &Namespace{&Base{connection: c, resource: k8s.NewNamespace(c)}, nil} + n := &Namespace{&Base{Connection: c, Resource: k8s.NewNamespace(c)}, nil} n.Factory = n return n @@ -32,7 +32,7 @@ func NewNamespace(c k8s.Connection) *Namespace { // New builds a new Namespace instance from a k8s resource. func (r *Namespace) New(i interface{}) Columnar { - c := NewNamespace(r.connection) + c := NewNamespace(r.Connection) switch instance := i.(type) { case *v1.Namespace: c.instance = instance @@ -49,7 +49,7 @@ func (r *Namespace) New(i interface{}) Columnar { // Marshal a resource to yaml. func (r *Namespace) Marshal(path string) (string, error) { ns, n := namespaced(path) - i, err := r.resource.Get(ns, n) + i, err := r.Resource.Get(ns, n) if err != nil { log.Error().Err(err) return "", err diff --git a/internal/resource/ns_test.go b/internal/resource/ns_test.go index 03018866..9280e582 100644 --- a/internal/resource/ns_test.go +++ b/internal/resource/ns_test.go @@ -11,9 +11,22 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +func NewNamespaceListWithArgs(ns string, r *resource.Namespace) resource.List { + return resource.NewList(resource.NotNamespaced, "ns", r, resource.CRUDAccess|resource.DescribeAccess) +} + +func NewNamespaceWithArgs(conn k8s.Connection, res resource.Cruder) *resource.Namespace { + r := &resource.Namespace{Base: resource.NewBase(conn, res)} + r.Factory = r + return r +} + func TestNamespaceListAccess(t *testing.T) { + mc := NewMockConnection() + mr := NewMockCruder() + ns := "blee" - l := resource.NewNamespaceList(resource.AllNamespaces) + l := NewNamespaceListWithArgs(resource.AllNamespaces, NewNamespaceWithArgs(mc, mr)) l.SetNamespace(ns) assert.Equal(t, resource.NotNamespaced, l.GetNamespace()) @@ -23,42 +36,37 @@ func TestNamespaceListAccess(t *testing.T) { } } -func TestNamespaceHeader(t *testing.T) { - assert.Equal(t, resource.Row{"NAME", "STATUS", "AGE"}, newNamespace().Header(resource.DefaultNamespace)) -} - func TestNamespaceFields(t *testing.T) { r := newNamespace().Fields("blee") assert.Equal(t, "fred", r[0]) } func TestNamespaceMarshal(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.Get("", "fred")).ThenReturn(k8sNamespace(), nil) - ca := NewMockCaller() - m.When(ca.Get("", "fred")).ThenReturn(k8sNamespace(), nil) - - cm := resource.NewNamespaceWithArgs(ca) + cm := NewNamespaceWithArgs(mc, mr) ma, err := cm.Marshal("fred") - ca.VerifyWasCalledOnce().Get("", "fred") + + mr.VerifyWasCalledOnce().Get("", "fred") assert.Nil(t, err) assert.Equal(t, nsYaml(), ma) } func TestNamespaceListData(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.List(resource.NotNamespaced)).ThenReturn(k8s.Collection{*k8sNamespace()}, nil) - ca := NewMockCaller() - m.When(ca.List(resource.NotNamespaced)).ThenReturn(k8s.Collection{*k8sNamespace()}, nil) - - l := resource.NewNamespaceListWithArgs("-", resource.NewNamespaceWithArgs(ca)) - // Make sure we can get deltas! + l := NewNamespaceListWithArgs("-", NewNamespaceWithArgs(mc, mr)) + // Make sure we mrn get deltas! for i := 0; i < 2; i++ { err := l.Reconcile() assert.Nil(t, err) } - ca.VerifyWasCalled(m.Times(2)).List(resource.NotNamespaced) + mr.VerifyWasCalled(m.Times(2)).List(resource.NotNamespaced) td := l.Data() assert.Equal(t, 1, len(td.Rows)) assert.Equal(t, resource.NotNamespaced, l.GetNamespace()) @@ -83,7 +91,8 @@ func k8sNamespace() *v1.Namespace { } func newNamespace() resource.Columnar { - return resource.NewNamespace().NewInstance(k8sNamespace()) + mc := NewMockConnection() + return resource.NewNamespace(mc).New(k8sNamespace()) } func nsYaml() string { diff --git a/internal/resource/pdb.go b/internal/resource/pdb.go index 3a965493..fb28b9c6 100644 --- a/internal/resource/pdb.go +++ b/internal/resource/pdb.go @@ -17,7 +17,7 @@ type PodDisruptionBudget struct { // NewPDBList returns a new resource list. func NewPDBList(c k8s.Connection, ns string) List { - return newList( + return NewList( ns, "pdb", NewPDB(c), @@ -27,7 +27,7 @@ func NewPDBList(c k8s.Connection, ns string) List { // NewPDB instantiates a new PDB. func NewPDB(c k8s.Connection) *PodDisruptionBudget { - p := &PodDisruptionBudget{&Base{connection: c, resource: k8s.NewPodDisruptionBudget(c)}, nil} + p := &PodDisruptionBudget{&Base{Connection: c, Resource: k8s.NewPodDisruptionBudget(c)}, nil} p.Factory = p return p @@ -35,7 +35,7 @@ func NewPDB(c k8s.Connection) *PodDisruptionBudget { // New builds a new PDB instance from a k8s resource. func (r *PodDisruptionBudget) New(i interface{}) Columnar { - c := NewPDB(r.connection) + c := NewPDB(r.Connection) switch instance := i.(type) { case *v1beta1.PodDisruptionBudget: c.instance = instance @@ -56,7 +56,7 @@ func (r *PodDisruptionBudget) New(i interface{}) Columnar { // Marshal resource to yaml. func (r *PodDisruptionBudget) Marshal(path string) (string, error) { ns, n := namespaced(path) - i, err := r.resource.Get(ns, n) + i, err := r.Resource.Get(ns, n) if err != nil { return "", err } diff --git a/internal/resource/pdb_test.go b/internal/resource/pdb_test.go index 73173ffb..22b6c455 100644 --- a/internal/resource/pdb_test.go +++ b/internal/resource/pdb_test.go @@ -11,9 +11,22 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +func NewPDBListWithArgs(ns string, r *resource.PodDisruptionBudget) resource.List { + return resource.NewList(ns, "pdb", r, resource.AllVerbsAccess|resource.DescribeAccess) +} + +func NewPDBWithArgs(conn k8s.Connection, res resource.Cruder) *resource.PodDisruptionBudget { + r := &resource.PodDisruptionBudget{Base: resource.NewBase(conn, res)} + r.Factory = r + return r +} + func TestPDBListAccess(t *testing.T) { + mc := NewMockConnection() + mr := NewMockCruder() + ns := "blee" - l := resource.NewPDBList(resource.AllNamespaces) + l := NewPDBListWithArgs(resource.AllNamespaces, NewPDBWithArgs(mc, mr)) l.SetNamespace(ns) assert.Equal(t, ns, l.GetNamespace()) @@ -23,55 +36,39 @@ func TestPDBListAccess(t *testing.T) { } } -func TestPDBHeader(t *testing.T) { - row := resource.Row{ - "NAME", - "MIN AVAILABLE", - "MAX_ UNAVAILABLE", - "ALLOWED DISRUPTIONS", - "CURRENT", - "DESIRED", - "EXPECTED", - "AGE", - } - assert.Equal(t, row, newPDB().Header(resource.DefaultNamespace)) -} - func TestPDBFields(t *testing.T) { r := newPDB().Fields("blee") assert.Equal(t, "fred", r[0]) } func TestPDBMarshal(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.Get("blee", "fred")).ThenReturn(k8sPDB(), nil) - ca := NewMockCaller() - m.When(ca.Get("blee", "fred")).ThenReturn(k8sPDB(), nil) - - cm := resource.NewPDBWithArgs(ca) + cm := NewPDBWithArgs(mc, mr) ma, err := cm.Marshal("blee/fred") - ca.VerifyWasCalledOnce().Get("blee", "fred") + mr.VerifyWasCalledOnce().Get("blee", "fred") assert.Nil(t, err) assert.Equal(t, pdbYaml(), ma) } func TestPDBListData(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.List("blee")).ThenReturn(k8s.Collection{*k8sPDB()}, nil) - ca := NewMockCaller() - m.When(ca.List(resource.NotNamespaced)).ThenReturn(k8s.Collection{*k8sPDB()}, nil) - - l := resource.NewPDBListWithArgs("-", resource.NewPDBWithArgs(ca)) - // Make sure we can get deltas! + l := NewPDBListWithArgs("blee", NewPDBWithArgs(mc, mr)) + // Make sure we mrn get deltas! for i := 0; i < 2; i++ { err := l.Reconcile() assert.Nil(t, err) } - ca.VerifyWasCalled(m.Times(2)).List(resource.NotNamespaced) + mr.VerifyWasCalled(m.Times(2)).List("blee") td := l.Data() assert.Equal(t, 1, len(td.Rows)) - assert.Equal(t, resource.NotNamespaced, l.GetNamespace()) + assert.Equal(t, "blee", l.GetNamespace()) row := td.Rows["blee/fred"] assert.Equal(t, 8, len(row.Deltas)) for _, d := range row.Deltas { @@ -94,7 +91,8 @@ func k8sPDB() *v1beta1.PodDisruptionBudget { } func newPDB() resource.Columnar { - return resource.NewPDB().NewInstance(k8sPDB()) + mc := NewMockConnection() + return resource.NewPDB(mc).New(k8sPDB()) } func pdbYaml() string { diff --git a/internal/resource/pod.go b/internal/resource/pod.go index 65d69de7..5a9f467d 100644 --- a/internal/resource/pod.go +++ b/internal/resource/pod.go @@ -37,25 +37,25 @@ type ( // Pod that can be displayed in a table and interacted with. Pod struct { *Base - instance *v1.Pod - metricServer MetricsServer - metrics k8s.PodMetrics + instance *v1.Pod + MetricsServer MetricsServer + metrics k8s.PodMetrics } ) // NewPodList returns a new resource list. -func NewPodList(c k8s.Connection, ns string) List { - return newList( +func NewPodList(c k8s.Connection, mx MetricsServer, ns string) List { + return NewList( ns, "po", - NewPod(c), + NewPod(c, mx), AllVerbsAccess|DescribeAccess, ) } // NewPod instantiates a new Pod. -func NewPod(c k8s.Connection) *Pod { - p := &Pod{&Base{connection: c, resource: k8s.NewPod(c)}, nil, k8s.NewMetricsServer(c), k8s.PodMetrics{}} +func NewPod(c k8s.Connection, mx MetricsServer) *Pod { + p := &Pod{&Base{Connection: c, Resource: k8s.NewPod(c)}, nil, mx, k8s.PodMetrics{}} p.Factory = p return p @@ -63,7 +63,7 @@ func NewPod(c k8s.Connection) *Pod { // New builds a new Pod instance from a k8s resource. func (r *Pod) New(i interface{}) Columnar { - c := NewPod(r.connection) + c := NewPod(r.Connection, r.MetricsServer) switch instance := i.(type) { case *v1.Pod: c.instance = instance @@ -94,7 +94,7 @@ func (r *Pod) SetMetrics(m k8s.PodMetrics) { // Marshal resource to yaml. func (r *Pod) Marshal(path string) (string, error) { ns, n := namespaced(path) - i, err := r.resource.Get(ns, n) + i, err := r.Resource.Get(ns, n) if err != nil { return "", err } @@ -110,12 +110,12 @@ func (r *Pod) Marshal(path string) (string, error) { func (r *Pod) Containers(path string, includeInit bool) ([]string, error) { ns, po := namespaced(path) - return r.resource.(k8s.Loggable).Containers(ns, po, includeInit) + return r.Resource.(k8s.Loggable).Containers(ns, po, includeInit) } // Logs tails a given container logs func (r *Pod) Logs(c chan<- string, ns, n, co string, lines int64, prev bool) (context.CancelFunc, error) { - req := r.resource.(k8s.Loggable).Logs(ns, n, co, lines, prev) + req := r.Resource.(k8s.Loggable).Logs(ns, n, co, lines, prev) ctx, cancel := context.WithCancel(context.TODO()) req.Context(ctx) @@ -155,15 +155,15 @@ func (r *Pod) Logs(c chan<- string, ns, n, co string, lines int64, prev bool) (c // List resources for a given namespace. func (r *Pod) List(ns string) (Columnars, error) { - pods, err := r.resource.List(ns) + pods, err := r.Resource.List(ns) if err != nil { return nil, err } mx := make(k8s.PodsMetrics, len(pods)) - if r.metricServer.HasMetrics() { - pmx, _ := r.metricServer.FetchPodsMetrics(ns) - r.metricServer.PodsMetrics(pmx, mx) + if r.MetricsServer.HasMetrics() { + pmx, _ := r.MetricsServer.FetchPodsMetrics(ns) + r.MetricsServer.PodsMetrics(pmx, mx) } cc := make(Columnars, 0, len(pods)) diff --git a/internal/resource/pod_test.go b/internal/resource/pod_test.go index e4b6e875..ccc0ddfb 100644 --- a/internal/resource/pod_test.go +++ b/internal/resource/pod_test.go @@ -1,6 +1,7 @@ package resource_test import ( + "strings" "testing" "github.com/derailed/k9s/internal/k8s" @@ -9,11 +10,26 @@ import ( "github.com/stretchr/testify/assert" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + mv1beta1 "k8s.io/metrics/pkg/apis/metrics/v1beta1" ) +func NewPodListWithArgs(ns string, r *resource.Pod) resource.List { + return resource.NewList(ns, "po", r, resource.AllVerbsAccess|resource.DescribeAccess) +} + +func NewPodWithArgs(conn k8s.Connection, res resource.Cruder, mx resource.MetricsServer) *resource.Pod { + r := &resource.Pod{Base: resource.NewBase(conn, res), MetricsServer: mx} + r.Factory = r + return r +} + func TestPodListAccess(t *testing.T) { + mc := NewMockConnection() + mr := NewMockCruder() + mx := NewMockMetricsServer() + ns := "blee" - l := resource.NewPodList(resource.AllNamespaces) + l := NewPodListWithArgs(resource.AllNamespaces, NewPodWithArgs(mc, mr, mx)) l.SetNamespace(ns) assert.Equal(t, "blee", l.GetNamespace()) @@ -23,56 +39,51 @@ func TestPodListAccess(t *testing.T) { } } -func TestPodHeader(t *testing.T) { - assert.Equal(t, resource.Row{"NAME", "READY", "STATUS", "RESTARTS", "CPU", "MEM", "IP", "NODE", "QOS", "AGE"}, newPod().Header(resource.DefaultNamespace)) -} - func TestPodFields(t *testing.T) { r := newPod().Fields("blee") assert.Equal(t, resource.Pad("fred", 42), r[0]) } func TestPodMarshal(t *testing.T) { - setup(t) - + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.Get("blee", "fred")).ThenReturn(k8sPod(), nil) mx := NewMockMetricsServer() - // metrics := make(k8s.PodsMetrics, 1) - // m.When(mx.PodsMetrics([]mv1beta1.PodMetrics{}, metrics)).thenReturn() - ca := NewMockCaller() - m.When(ca.Get("blee", "fred")).ThenReturn(k8sPod(), nil) - cm := resource.NewPodWithArgs(ca, mx) + cm := NewPodWithArgs(mc, mr, mx) ma, err := cm.Marshal("blee/fred") - ca.VerifyWasCalledOnce().Get("blee", "fred") + + mr.VerifyWasCalledOnce().Get("blee", "fred") assert.Nil(t, err) assert.Equal(t, poYaml(), ma) } func TestPodListData(t *testing.T) { - setup(t) - + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.List("blee")).ThenReturn(k8s.Collection{*k8sPod()}, nil) mx := NewMockMetricsServer() - // m.When(mx.PodsMetrics("")).ThenReturn(map[string]k8s.Metric{"fred": {}}, nil) - ca := NewMockCaller() - m.When(ca.List("")).ThenReturn(k8s.Collection{*k8sPod()}, nil) + m.When(mx.HasMetrics()).ThenReturn(true) + m.When(mx.FetchPodsMetrics("blee")). + ThenReturn([]mv1beta1.PodMetrics{makeMxPod("fred", "100m", "20Mi")}, nil) - l := resource.NewPodListWithArgs("", resource.NewPodWithArgs(ca, mx)) - // Make sure we can get deltas! + l := NewPodListWithArgs("blee", NewPodWithArgs(mc, mr, mx)) + // Make sure we mcn get deltas! for i := 0; i < 2; i++ { err := l.Reconcile() assert.Nil(t, err) } - ca.VerifyWasCalled(m.Times(2)).List(resource.AllNamespaces) + mr.VerifyWasCalled(m.Times(2)).List("blee") td := l.Data() assert.Equal(t, 1, len(td.Rows)) - assert.Equal(t, resource.AllNamespaces, l.GetNamespace()) + assert.Equal(t, "blee", l.GetNamespace()) row := td.Rows["blee/fred"] - assert.Equal(t, 11, len(row.Deltas)) + assert.Equal(t, 10, len(row.Deltas)) for _, d := range row.Deltas { assert.Equal(t, "", d) } - assert.Equal(t, resource.Row{"blee"}, row.Fields[:1]) + assert.Equal(t, "fred", strings.TrimSpace(row.Fields[:1][0])) } // Helpers... @@ -131,7 +142,9 @@ func k8sPod() *v1.Pod { } func newPod() resource.Columnar { - return resource.NewPod().NewInstance(k8sPod()) + mc := NewMockConnection() + mx := NewMockMetricsServer() + return resource.NewPod(mc, mx).New(k8sPod()) } func poYaml() string { @@ -175,3 +188,17 @@ status: phase: Running ` } + +func makeMxPod(name, cpu, mem string) mv1beta1.PodMetrics { + return mv1beta1.PodMetrics{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: "default", + }, + Containers: []mv1beta1.ContainerMetrics{ + {Usage: makeRes(cpu, mem)}, + {Usage: makeRes(cpu, mem)}, + {Usage: makeRes(cpu, mem)}, + }, + } +} diff --git a/internal/resource/pv.go b/internal/resource/pv.go index b2a615cc..d91dd68d 100644 --- a/internal/resource/pv.go +++ b/internal/resource/pv.go @@ -17,7 +17,7 @@ type PV struct { // NewPVList returns a new resource list. func NewPVList(c k8s.Connection, ns string) List { - return newList( + return NewList( NotNamespaced, "pv", NewPV(c), @@ -27,7 +27,7 @@ func NewPVList(c k8s.Connection, ns string) List { // NewPV instantiates a new PV. func NewPV(c k8s.Connection) *PV { - p := &PV{&Base{connection: c, resource: k8s.NewPV(c)}, nil} + p := &PV{&Base{Connection: c, Resource: k8s.NewPV(c)}, nil} p.Factory = p return p @@ -35,7 +35,7 @@ func NewPV(c k8s.Connection) *PV { // New builds a new PV instance from a k8s resource. func (r *PV) New(i interface{}) Columnar { - c := NewPV(r.connection) + c := NewPV(r.Connection) switch instance := i.(type) { case *v1.PersistentVolume: c.instance = instance @@ -52,7 +52,7 @@ func (r *PV) New(i interface{}) Columnar { // Marshal resource to yaml. func (r *PV) Marshal(path string) (string, error) { ns, n := namespaced(path) - i, err := r.resource.Get(ns, n) + i, err := r.Resource.Get(ns, n) if err != nil { return "", err } diff --git a/internal/resource/pv_test.go b/internal/resource/pv_test.go index 36ae988b..cccf0c0a 100644 --- a/internal/resource/pv_test.go +++ b/internal/resource/pv_test.go @@ -11,9 +11,22 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +func NewPVListWithArgs(ns string, r *resource.PV) resource.List { + return resource.NewList(resource.NotNamespaced, "pv", r, resource.CRUDAccess|resource.DescribeAccess) +} + +func NewPVWithArgs(conn k8s.Connection, res resource.Cruder) *resource.PV { + r := &resource.PV{Base: resource.NewBase(conn, res)} + r.Factory = r + return r +} + func TestPVListAccess(t *testing.T) { + mc := NewMockConnection() + mr := NewMockCruder() + ns := "blee" - l := resource.NewPVList(resource.AllNamespaces) + l := NewPVListWithArgs(resource.AllNamespaces, NewPVWithArgs(mc, mr)) l.SetNamespace(ns) assert.Equal(t, resource.NotNamespaced, l.GetNamespace()) @@ -23,42 +36,36 @@ func TestPVListAccess(t *testing.T) { } } -func TestPVHeader(t *testing.T) { - assert.Equal(t, resource.Row{"NAME", "CAPACITY", "ACCESS MODES", "RECLAIM POLICY", "STATUS", "CLAIM", "STORAGECLASS", "REASON", "AGE"}, newPV().Header(resource.DefaultNamespace)) -} - func TestPVFields(t *testing.T) { r := newPV().Fields("blee") assert.Equal(t, "fred", r[0]) } func TestPVMarshal(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.Get("blee", "fred")).ThenReturn(k8sPV(), nil) - ca := NewMockCaller() - m.When(ca.Get("blee", "fred")).ThenReturn(k8sPV(), nil) - - cm := resource.NewPVWithArgs(ca) + cm := NewPVWithArgs(mc, mr) ma, err := cm.Marshal("blee/fred") - ca.VerifyWasCalledOnce().Get("blee", "fred") + mr.VerifyWasCalledOnce().Get("blee", "fred") assert.Nil(t, err) assert.Equal(t, pvYaml(), ma) } func TestPVListData(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.List(resource.NotNamespaced)).ThenReturn(k8s.Collection{*k8sPV()}, nil) - ca := NewMockCaller() - m.When(ca.List(resource.NotNamespaced)).ThenReturn(k8s.Collection{*k8sPV()}, nil) - - l := resource.NewPVListWithArgs("-", resource.NewPVWithArgs(ca)) - // Make sure we can get deltas! + l := NewPVListWithArgs("-", NewPVWithArgs(mc, mr)) + // Make sure we mrn get deltas! for i := 0; i < 2; i++ { err := l.Reconcile() assert.Nil(t, err) } - ca.VerifyWasCalled(m.Times(2)).List(resource.NotNamespaced) + mr.VerifyWasCalled(m.Times(2)).List(resource.NotNamespaced) td := l.Data() assert.Equal(t, 1, len(td.Rows)) assert.Equal(t, resource.NotNamespaced, l.GetNamespace()) @@ -84,7 +91,8 @@ func k8sPV() *v1.PersistentVolume { } func newPV() resource.Columnar { - return resource.NewPV().NewInstance(k8sPV()) + mc := NewMockConnection() + return resource.NewPV(mc).New(k8sPV()) } func pvYaml() string { diff --git a/internal/resource/pvc.go b/internal/resource/pvc.go index 26fd6557..d25ab700 100644 --- a/internal/resource/pvc.go +++ b/internal/resource/pvc.go @@ -14,7 +14,7 @@ type PVC struct { // NewPVCList returns a new resource list. func NewPVCList(c k8s.Connection, ns string) List { - return newList( + return NewList( ns, "pvc", NewPVC(c), @@ -24,7 +24,7 @@ func NewPVCList(c k8s.Connection, ns string) List { // NewPVC instantiates a new PVC. func NewPVC(c k8s.Connection) *PVC { - p := &PVC{&Base{connection: c, resource: k8s.NewPVC(c)}, nil} + p := &PVC{&Base{Connection: c, Resource: k8s.NewPVC(c)}, nil} p.Factory = p return p @@ -32,7 +32,7 @@ func NewPVC(c k8s.Connection) *PVC { // New builds a new PVC instance from a k8s resource. func (r *PVC) New(i interface{}) Columnar { - c := NewPVC(r.connection) + c := NewPVC(r.Connection) switch instance := i.(type) { case *v1.PersistentVolumeClaim: c.instance = instance @@ -49,7 +49,7 @@ func (r *PVC) New(i interface{}) Columnar { // Marshal resource to yaml. func (r *PVC) Marshal(path string) (string, error) { ns, n := namespaced(path) - i, err := r.resource.Get(ns, n) + i, err := r.Resource.Get(ns, n) if err != nil { return "", err } diff --git a/internal/resource/pvc_test.go b/internal/resource/pvc_test.go index f5d6ff57..44c7643e 100644 --- a/internal/resource/pvc_test.go +++ b/internal/resource/pvc_test.go @@ -12,9 +12,22 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +func NewPVCListWithArgs(ns string, r *resource.PVC) resource.List { + return resource.NewList(ns, "pvc", r, resource.AllVerbsAccess|resource.DescribeAccess) +} + +func NewPVCWithArgs(conn k8s.Connection, res resource.Cruder) *resource.PVC { + r := &resource.PVC{Base: resource.NewBase(conn, res)} + r.Factory = r + return r +} + func TestPVCListAccess(t *testing.T) { + mc := NewMockConnection() + mr := NewMockCruder() + ns := "blee" - l := resource.NewPVCList(resource.AllNamespaces) + l := NewPVCListWithArgs(resource.AllNamespaces, NewPVCWithArgs(mc, mr)) l.SetNamespace(ns) assert.Equal(t, "blee", l.GetNamespace()) @@ -24,45 +37,39 @@ func TestPVCListAccess(t *testing.T) { } } -func TestPVCHeader(t *testing.T) { - assert.Equal(t, resource.Row{"NAME", "STATUS", "VOLUME", "CAPACITY", "ACCESS MODES", "STORAGECLASS", "AGE"}, newPVC().Header(resource.DefaultNamespace)) -} - func TestPVCFields(t *testing.T) { r := newPVC().Fields("blee") assert.Equal(t, "fred", r[0]) } func TestPVCMarshal(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.Get("blee", "fred")).ThenReturn(k8sPVC(), nil) - ca := NewMockCaller() - m.When(ca.Get("blee", "fred")).ThenReturn(k8sPVC(), nil) - - cm := resource.NewPVCWithArgs(ca) + cm := NewPVCWithArgs(mc, mr) ma, err := cm.Marshal("blee/fred") - ca.VerifyWasCalledOnce().Get("blee", "fred") + mr.VerifyWasCalledOnce().Get("blee", "fred") assert.Nil(t, err) assert.Equal(t, pvcYaml(), ma) } func TestPVCListData(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.List("blee")).ThenReturn(k8s.Collection{*k8sPVC()}, nil) - ca := NewMockCaller() - m.When(ca.List(resource.NotNamespaced)).ThenReturn(k8s.Collection{*k8sPVC()}, nil) - - l := resource.NewPVCListWithArgs("-", resource.NewPVCWithArgs(ca)) - // Make sure we can get deltas! + l := NewPVCListWithArgs("blee", NewPVCWithArgs(mc, mr)) + // Make sure we mrn get deltas! for i := 0; i < 2; i++ { err := l.Reconcile() assert.Nil(t, err) } - ca.VerifyWasCalled(m.Times(2)).List(resource.NotNamespaced) + mr.VerifyWasCalled(m.Times(2)).List("blee") td := l.Data() assert.Equal(t, 1, len(td.Rows)) - assert.Equal(t, resource.NotNamespaced, l.GetNamespace()) + assert.Equal(t, "blee", l.GetNamespace()) row := td.Rows["blee/fred"] assert.Equal(t, 7, len(row.Deltas)) for _, d := range row.Deltas { @@ -92,7 +99,8 @@ func k8sPVC() *v1.PersistentVolumeClaim { } func newPVC() resource.Columnar { - return resource.NewPVC().NewInstance(k8sPVC()) + mc := NewMockConnection() + return resource.NewPVC(mc).New(k8sPVC()) } func pvcYaml() string { diff --git a/internal/resource/rc.go b/internal/resource/rc.go index 216ed767..6e281423 100644 --- a/internal/resource/rc.go +++ b/internal/resource/rc.go @@ -16,7 +16,7 @@ type ReplicationController struct { // NewReplicationControllerList returns a new resource list. func NewReplicationControllerList(c k8s.Connection, ns string) List { - return newList( + return NewList( ns, "rc", NewReplicationController(c), @@ -26,7 +26,7 @@ func NewReplicationControllerList(c k8s.Connection, ns string) List { // NewReplicationController instantiates a new ReplicationController. func NewReplicationController(c k8s.Connection) *ReplicationController { - r := &ReplicationController{&Base{connection: c, resource: k8s.NewReplicationController(c)}, nil} + r := &ReplicationController{&Base{Connection: c, Resource: k8s.NewReplicationController(c)}, nil} r.Factory = r return r @@ -34,7 +34,7 @@ func NewReplicationController(c k8s.Connection) *ReplicationController { // New builds a new ReplicationController instance from a k8s resource. func (r *ReplicationController) New(i interface{}) Columnar { - c := NewReplicationController(r.connection) + c := NewReplicationController(r.Connection) switch instance := i.(type) { case *v1.ReplicationController: c.instance = instance @@ -51,7 +51,7 @@ func (r *ReplicationController) New(i interface{}) Columnar { // Marshal a deployment given a namespaced name. func (r *ReplicationController) Marshal(path string) (string, error) { ns, n := namespaced(path) - i, err := r.resource.Get(ns, n) + i, err := r.Resource.Get(ns, n) if err != nil { return "", err } diff --git a/internal/resource/ro.go b/internal/resource/ro.go index 218a1ded..4b9f7fa4 100644 --- a/internal/resource/ro.go +++ b/internal/resource/ro.go @@ -16,7 +16,7 @@ type Role struct { // NewRoleList returns a new resource list. func NewRoleList(c k8s.Connection, ns string) List { - return newList( + return NewList( ns, "role", NewRole(c), @@ -26,7 +26,7 @@ func NewRoleList(c k8s.Connection, ns string) List { // NewRole instantiates a new Role. func NewRole(c k8s.Connection) *Role { - r := &Role{&Base{connection: c, resource: k8s.NewRole(c)}, nil} + r := &Role{&Base{Connection: c, Resource: k8s.NewRole(c)}, nil} r.Factory = r return r @@ -34,7 +34,7 @@ func NewRole(c k8s.Connection) *Role { // New builds a new Role instance from a k8s resource. func (r *Role) New(i interface{}) Columnar { - c := NewRole(r.connection) + c := NewRole(r.Connection) switch instance := i.(type) { case *v1.Role: c.instance = instance @@ -51,7 +51,7 @@ func (r *Role) New(i interface{}) Columnar { // Marshal resource to yaml. func (r *Role) Marshal(path string) (string, error) { ns, n := namespaced(path) - i, err := r.resource.Get(ns, n) + i, err := r.Resource.Get(ns, n) if err != nil { return "", err } diff --git a/internal/resource/ro_binding.go b/internal/resource/ro_binding.go index 6829ed0e..d4fefde6 100644 --- a/internal/resource/ro_binding.go +++ b/internal/resource/ro_binding.go @@ -16,7 +16,7 @@ type RoleBinding struct { // NewRoleBindingList returns a new resource list. func NewRoleBindingList(c k8s.Connection, ns string) List { - return newList( + return NewList( ns, "rolebinding", NewRoleBinding(c), @@ -26,7 +26,7 @@ func NewRoleBindingList(c k8s.Connection, ns string) List { // NewRoleBinding instantiates a new RoleBinding. func NewRoleBinding(c k8s.Connection) *RoleBinding { - r := &RoleBinding{&Base{connection: c, resource: k8s.NewRoleBinding(c)}, nil} + r := &RoleBinding{&Base{Connection: c, Resource: k8s.NewRoleBinding(c)}, nil} r.Factory = r return r @@ -34,7 +34,7 @@ func NewRoleBinding(c k8s.Connection) *RoleBinding { // New builds a new RoleBinding instance from a k8s resource. func (r *RoleBinding) New(i interface{}) Columnar { - c := NewRoleBinding(r.connection) + c := NewRoleBinding(r.Connection) switch instance := i.(type) { case *v1.RoleBinding: c.instance = instance @@ -51,7 +51,7 @@ func (r *RoleBinding) New(i interface{}) Columnar { // Marshal resource to yaml. func (r *RoleBinding) Marshal(path string) (string, error) { ns, n := namespaced(path) - i, err := r.resource.Get(ns, n) + i, err := r.Resource.Get(ns, n) if err != nil { return "", err } diff --git a/internal/resource/ro_binding_test.go b/internal/resource/ro_binding_test.go index 90bff2ff..cba2306c 100644 --- a/internal/resource/ro_binding_test.go +++ b/internal/resource/ro_binding_test.go @@ -11,33 +11,42 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +func NewRBListWithArgs(ns string, r *resource.RoleBinding) resource.List { + return resource.NewList(ns, "rb", r, resource.AllVerbsAccess|resource.DescribeAccess) +} + +func NewRBWithArgs(conn k8s.Connection, res resource.Cruder) *resource.RoleBinding { + r := &resource.RoleBinding{Base: resource.NewBase(conn, res)} + r.Factory = r + return r +} + func TestRBMarshal(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.Get("blee", "fred")).ThenReturn(k8sRB(), nil) - ca := NewMockCaller() - m.When(ca.Get("blee", "fred")).ThenReturn(k8sRB(), nil) - - cm := resource.NewRoleBindingWithArgs(ca) + cm := NewRBWithArgs(mc, mr) ma, err := cm.Marshal("blee/fred") - ca.VerifyWasCalledOnce().Get("blee", "fred") + + mr.VerifyWasCalledOnce().Get("blee", "fred") assert.Nil(t, err) assert.Equal(t, rbYaml(), ma) } func TestRBListData(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.List("blee")).ThenReturn(k8s.Collection{*k8sRB()}, nil) - ca := NewMockCaller() - m.When(ca.List("blee")).ThenReturn(k8s.Collection{*k8sRB()}, nil) - - l := resource.NewRoleBindingListWithArgs("blee", resource.NewRoleBindingWithArgs(ca)) - // Make sure we can get deltas! + l := NewRBListWithArgs("blee", NewRBWithArgs(mc, mr)) + // Make sure we mrn get deltas! for i := 0; i < 2; i++ { err := l.Reconcile() assert.Nil(t, err) } - ca.VerifyWasCalled(m.Times(2)).List("blee") + mr.VerifyWasCalled(m.Times(2)).List("blee") td := l.Data() assert.Equal(t, 1, len(td.Rows)) assert.Equal(t, "blee", l.GetNamespace()) @@ -73,7 +82,8 @@ func k8sRB() *v1.RoleBinding { } func newRB() resource.Columnar { - return resource.NewRoleBinding().NewInstance(k8sRB()) + mc := NewMockConnection() + return resource.NewRoleBinding(mc).New(k8sRB()) } func rbYaml() string { diff --git a/internal/resource/ro_test.go b/internal/resource/ro_test.go index 932f751d..82bef2bd 100644 --- a/internal/resource/ro_test.go +++ b/internal/resource/ro_test.go @@ -11,33 +11,41 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +func NewRoleListWithArgs(ns string, r *resource.Role) resource.List { + return resource.NewList(ns, "ro", r, resource.AllVerbsAccess|resource.DescribeAccess) +} + +func NewRoleWithArgs(conn k8s.Connection, res resource.Cruder) *resource.Role { + r := &resource.Role{Base: resource.NewBase(conn, res)} + r.Factory = r + return r +} + func TestRoleMarshal(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.Get("blee", "fred")).ThenReturn(k8sRole(), nil) - ca := NewMockCaller() - m.When(ca.Get("blee", "fred")).ThenReturn(k8sRole(), nil) - - cm := resource.NewRoleWithArgs(ca) + cm := NewRoleWithArgs(mc, mr) ma, err := cm.Marshal("blee/fred") - ca.VerifyWasCalledOnce().Get("blee", "fred") + mr.VerifyWasCalledOnce().Get("blee", "fred") assert.Nil(t, err) assert.Equal(t, roleYaml(), ma) } func TestRoleListData(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.List("blee")).ThenReturn(k8s.Collection{*k8sRole()}, nil) - ca := NewMockCaller() - m.When(ca.List("blee")).ThenReturn(k8s.Collection{*k8sRole()}, nil) - - l := resource.NewRoleListWithArgs("blee", resource.NewRoleWithArgs(ca)) - // Make sure we can get deltas! + l := NewRoleListWithArgs("blee", NewRoleWithArgs(mc, mr)) + // Make sure we mrn get deltas! for i := 0; i < 2; i++ { err := l.Reconcile() assert.Nil(t, err) } - ca.VerifyWasCalled(m.Times(2)).List("blee") + mr.VerifyWasCalled(m.Times(2)).List("blee") td := l.Data() assert.Equal(t, 1, len(td.Rows)) assert.Equal(t, "blee", l.GetNamespace()) @@ -62,7 +70,8 @@ func k8sRole() *v1.Role { } func newRole() resource.Columnar { - return resource.NewRole().NewInstance(k8sRole()) + mc := NewMockConnection() + return resource.NewRole(mc).New(k8sRole()) } func roleYaml() string { diff --git a/internal/resource/rs.go b/internal/resource/rs.go index e1969bf3..e30fc010 100644 --- a/internal/resource/rs.go +++ b/internal/resource/rs.go @@ -16,7 +16,7 @@ type ReplicaSet struct { // NewReplicaSetList returns a new resource list. func NewReplicaSetList(c k8s.Connection, ns string) List { - return newList( + return NewList( ns, "rs", NewReplicaSet(c), @@ -26,7 +26,7 @@ func NewReplicaSetList(c k8s.Connection, ns string) List { // NewReplicaSet instantiates a new ReplicaSet. func NewReplicaSet(c k8s.Connection) *ReplicaSet { - r := &ReplicaSet{&Base{connection: c, resource: k8s.NewReplicaSet(c)}, nil} + r := &ReplicaSet{&Base{Connection: c, Resource: k8s.NewReplicaSet(c)}, nil} r.Factory = r return r @@ -34,7 +34,7 @@ func NewReplicaSet(c k8s.Connection) *ReplicaSet { // New builds a new ReplicaSet instance from a k8s resource. func (r *ReplicaSet) New(i interface{}) Columnar { - c := NewReplicaSet(r.connection) + c := NewReplicaSet(r.Connection) switch instance := i.(type) { case *v1.ReplicaSet: c.instance = instance @@ -51,7 +51,7 @@ func (r *ReplicaSet) New(i interface{}) Columnar { // Marshal a deployment given a namespaced name. func (r *ReplicaSet) Marshal(path string) (string, error) { ns, n := namespaced(path) - i, err := r.resource.Get(ns, n) + i, err := r.Resource.Get(ns, n) if err != nil { return "", err } diff --git a/internal/resource/rs_test.go b/internal/resource/rs_test.go index aaaf3352..486c509e 100644 --- a/internal/resource/rs_test.go +++ b/internal/resource/rs_test.go @@ -11,33 +11,41 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +func NewReplicaSetListWithArgs(ns string, r *resource.ReplicaSet) resource.List { + return resource.NewList(ns, "rs", r, resource.AllVerbsAccess|resource.DescribeAccess) +} + +func NewReplicaSetWithArgs(conn k8s.Connection, res resource.Cruder) *resource.ReplicaSet { + r := &resource.ReplicaSet{Base: resource.NewBase(conn, res)} + r.Factory = r + return r +} + func TestReplicaSetMarshal(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.Get("blee", "fred")).ThenReturn(k8sReplicaSet(), nil) - ca := NewMockCaller() - m.When(ca.Get("blee", "fred")).ThenReturn(k8sReplicaSet(), nil) - - cm := resource.NewReplicaSetWithArgs(ca) + cm := NewReplicaSetWithArgs(mc, mr) ma, err := cm.Marshal("blee/fred") - ca.VerifyWasCalledOnce().Get("blee", "fred") + mr.VerifyWasCalledOnce().Get("blee", "fred") assert.Nil(t, err) assert.Equal(t, rsYaml(), ma) } func TestReplicaSetListData(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.List("blee")).ThenReturn(k8s.Collection{*k8sReplicaSet()}, nil) - ca := NewMockCaller() - m.When(ca.List("blee")).ThenReturn(k8s.Collection{*k8sReplicaSet()}, nil) - - l := resource.NewReplicaSetListWithArgs("blee", resource.NewReplicaSetWithArgs(ca)) + l := NewReplicaSetListWithArgs("blee", NewReplicaSetWithArgs(mc, mr)) // Make sure we can get deltas! for i := 0; i < 2; i++ { err := l.Reconcile() assert.Nil(t, err) } - ca.VerifyWasCalled(m.Times(2)).List("blee") + mr.VerifyWasCalled(m.Times(2)).List("blee") td := l.Data() assert.Equal(t, 1, len(td.Rows)) assert.Equal(t, "blee", l.GetNamespace()) @@ -70,7 +78,8 @@ func k8sReplicaSet() *v1.ReplicaSet { } func newReplicaSet() resource.Columnar { - return resource.NewReplicaSet().NewInstance(k8sReplicaSet()) + mc := NewMockConnection() + return resource.NewReplicaSet(mc).New(k8sReplicaSet()) } func rsYaml() string { diff --git a/internal/resource/sa.go b/internal/resource/sa.go index de03d868..d771feeb 100644 --- a/internal/resource/sa.go +++ b/internal/resource/sa.go @@ -16,7 +16,7 @@ type ServiceAccount struct { // NewServiceAccountList returns a new resource list. func NewServiceAccountList(c k8s.Connection, ns string) List { - return newList( + return NewList( ns, "sa", NewServiceAccount(c), @@ -26,7 +26,7 @@ func NewServiceAccountList(c k8s.Connection, ns string) List { // NewServiceAccount instantiates a new ServiceAccount. func NewServiceAccount(c k8s.Connection) *ServiceAccount { - s := &ServiceAccount{&Base{connection: c, resource: k8s.NewServiceAccount(c)}, nil} + s := &ServiceAccount{&Base{Connection: c, Resource: k8s.NewServiceAccount(c)}, nil} s.Factory = s return s @@ -34,7 +34,7 @@ func NewServiceAccount(c k8s.Connection) *ServiceAccount { // New builds a new ServiceAccount instance from a k8s resource. func (r *ServiceAccount) New(i interface{}) Columnar { - c := NewServiceAccount(r.connection) + c := NewServiceAccount(r.Connection) switch instance := i.(type) { case *v1.ServiceAccount: c.instance = instance @@ -51,7 +51,7 @@ func (r *ServiceAccount) New(i interface{}) Columnar { // Marshal resource to yaml. func (r *ServiceAccount) Marshal(path string) (string, error) { ns, n := namespaced(path) - i, err := r.resource.Get(ns, n) + i, err := r.Resource.Get(ns, n) if err != nil { return "", err } diff --git a/internal/resource/sa_test.go b/internal/resource/sa_test.go index bd3e0dc1..21396eeb 100644 --- a/internal/resource/sa_test.go +++ b/internal/resource/sa_test.go @@ -11,9 +11,22 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +func NewServiceAccountListWithArgs(ns string, r *resource.ServiceAccount) resource.List { + return resource.NewList(ns, "sa", r, resource.AllVerbsAccess|resource.DescribeAccess) +} + +func NewServiceAccountWithArgs(conn k8s.Connection, res resource.Cruder) *resource.ServiceAccount { + r := &resource.ServiceAccount{Base: resource.NewBase(conn, res)} + r.Factory = r + return r +} + func TestSaListAccess(t *testing.T) { + mc := NewMockConnection() + mr := NewMockCruder() + ns := "blee" - l := resource.NewServiceAccountList(resource.AllNamespaces) + l := NewServiceAccountListWithArgs(resource.AllNamespaces, NewServiceAccountWithArgs(mc, mr)) l.SetNamespace(ns) assert.Equal(t, ns, l.GetNamespace()) @@ -46,35 +59,33 @@ func TestSaFields(t *testing.T) { } func TestSAMarshal(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.Get("blee", "fred")).ThenReturn(k8sSA(), nil) - ca := NewMockCaller() - m.When(ca.Get("blee", "fred")).ThenReturn(k8sSA(), nil) - - cm := resource.NewServiceAccountWithArgs(ca) + cm := NewServiceAccountWithArgs(mc, mr) ma, err := cm.Marshal("blee/fred") - ca.VerifyWasCalledOnce().Get("blee", "fred") + mr.VerifyWasCalledOnce().Get("blee", "fred") assert.Nil(t, err) assert.Equal(t, saYaml(), ma) } func TestSAListData(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.List("blee")).ThenReturn(k8s.Collection{*k8sSA()}, nil) - ca := NewMockCaller() - m.When(ca.List("-")).ThenReturn(k8s.Collection{*k8sSA()}, nil) - - l := resource.NewServiceAccountListWithArgs("-", resource.NewServiceAccountWithArgs(ca)) - // Make sure we can get deltas! + l := NewServiceAccountListWithArgs("blee", NewServiceAccountWithArgs(mc, mr)) + // Make sure we mrn get deltas! for i := 0; i < 2; i++ { err := l.Reconcile() assert.Nil(t, err) } - ca.VerifyWasCalled(m.Times(2)).List("-") + mr.VerifyWasCalled(m.Times(2)).List("blee") td := l.Data() assert.Equal(t, 1, len(td.Rows)) - assert.Equal(t, resource.NotNamespaced, l.GetNamespace()) + assert.Equal(t, "blee", l.GetNamespace()) row := td.Rows["blee/fred"] assert.Equal(t, 3, len(row.Deltas)) for _, d := range row.Deltas { @@ -97,7 +108,8 @@ func k8sSA() *v1.ServiceAccount { } func newSa() resource.Columnar { - return resource.NewServiceAccount().NewInstance(k8sSA()) + mc := NewMockConnection() + return resource.NewServiceAccount(mc).New(k8sSA()) } func saHeader() resource.Row { diff --git a/internal/resource/secret.go b/internal/resource/secret.go index 59d2f212..73b81cf1 100644 --- a/internal/resource/secret.go +++ b/internal/resource/secret.go @@ -16,7 +16,7 @@ type Secret struct { // NewSecretList returns a new resource list. func NewSecretList(c k8s.Connection, ns string) List { - return newList( + return NewList( ns, "secret", NewSecret(c), @@ -26,7 +26,7 @@ func NewSecretList(c k8s.Connection, ns string) List { // NewSecret instantiates a new Secret. func NewSecret(c k8s.Connection) *Secret { - s := &Secret{&Base{connection: c, resource: k8s.NewSecret(c)}, nil} + s := &Secret{&Base{Connection: c, Resource: k8s.NewSecret(c)}, nil} s.Factory = s return s @@ -34,7 +34,7 @@ func NewSecret(c k8s.Connection) *Secret { // New builds a new Secret instance from a k8s resource. func (r *Secret) New(i interface{}) Columnar { - c := NewSecret(r.connection) + c := NewSecret(r.Connection) switch instance := i.(type) { case *v1.Secret: c.instance = instance @@ -51,7 +51,7 @@ func (r *Secret) New(i interface{}) Columnar { // Marshal resource to yaml. func (r *Secret) Marshal(path string) (string, error) { ns, n := namespaced(path) - i, err := r.resource.Get(ns, n) + i, err := r.Resource.Get(ns, n) if err != nil { return "", err } diff --git a/internal/resource/secret_test.go b/internal/resource/secret_test.go index fcf0d8b6..ea90273b 100644 --- a/internal/resource/secret_test.go +++ b/internal/resource/secret_test.go @@ -11,6 +11,16 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +func NewSecretListWithArgs(ns string, r *resource.Secret) resource.List { + return resource.NewList(ns, "secret", r, resource.AllVerbsAccess|resource.DescribeAccess) +} + +func NewSecretWithArgs(conn k8s.Connection, res resource.Cruder) *resource.Secret { + r := &resource.Secret{Base: resource.NewBase(conn, res)} + r.Factory = r + return r +} + func TestSecretHeader(t *testing.T) { assert.Equal(t, resource.Row{"NAME", "TYPE", "DATA", "AGE"}, @@ -41,93 +51,90 @@ func TestSecretFields(t *testing.T) { } func TestSecretGet(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.Get("blee", "fred")).ThenReturn(k8sSecret(), nil) - ca := NewMockCaller() - m.When(ca.Get("blee", "fred")).ThenReturn(k8sSecret(), nil) - - cm := resource.NewSecretWithArgs(ca) + cm := NewSecretWithArgs(mc, mr) ma, err := cm.Get("blee/fred") + assert.Nil(t, err) - ca.VerifyWasCalledOnce().Get("blee", "fred") - assert.Equal(t, cm.NewInstance(k8sSecret()), ma) + mr.VerifyWasCalledOnce().Get("blee", "fred") + assert.Equal(t, cm.New(k8sSecret()), ma) } func TestSecretList(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.List("blee")).ThenReturn(k8s.Collection{*k8sSecret()}, nil) - ca := NewMockCaller() - m.When(ca.List("blee")).ThenReturn(k8s.Collection{*k8sSecret()}, nil) - - cm := resource.NewSecretWithArgs(ca) + cm := NewSecretWithArgs(mc, mr) ma, err := cm.List("blee") + assert.Nil(t, err) - ca.VerifyWasCalledOnce().List("blee") - assert.Equal(t, resource.Columnars{cm.NewInstance(k8sSecret())}, ma) + mr.VerifyWasCalledOnce().List("blee") + assert.Equal(t, resource.Columnars{cm.New(k8sSecret())}, ma) } func TestSecretDelete(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.Delete("blee", "fred")).ThenReturn(nil) - ca := NewMockCaller() - m.When(ca.Delete("blee", "fred")).ThenReturn(nil) + cm := NewSecretWithArgs(mc, mr) - cm := resource.NewSecretWithArgs(ca) assert.Nil(t, cm.Delete("blee/fred")) - ca.VerifyWasCalledOnce().Delete("blee", "fred") + mr.VerifyWasCalledOnce().Delete("blee", "fred") } func TestSecretMarshal(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.Get("blee", "fred")).ThenReturn(k8sSecret(), nil) - ca := NewMockCaller() - m.When(ca.Get("blee", "fred")).ThenReturn(k8sSecret(), nil) - - cm := resource.NewSecretWithArgs(ca) + cm := NewSecretWithArgs(mc, mr) ma, err := cm.Marshal("blee/fred") - ca.VerifyWasCalledOnce().Get("blee", "fred") + + mr.VerifyWasCalledOnce().Get("blee", "fred") assert.Nil(t, err) assert.Equal(t, secretYaml(), ma) } func TestSecretListHasName(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() - ca := NewMockCaller() - l := resource.NewSecretListWithArgs("blee", resource.NewSecretWithArgs(ca)) + l := NewSecretListWithArgs("blee", NewSecretWithArgs(mc, mr)) assert.Equal(t, "secret", l.GetName()) } func TestSecretListHasNamespace(t *testing.T) { - setup(t) - - ca := NewMockCaller() - l := resource.NewSecretListWithArgs("blee", resource.NewSecretWithArgs(ca)) + mc := NewMockConnection() + mr := NewMockCruder() + l := NewSecretListWithArgs("blee", NewSecretWithArgs(mc, mr)) assert.Equal(t, "blee", l.GetNamespace()) } func TestSecretListHasResource(t *testing.T) { - setup(t) - - ca := NewMockCaller() - l := resource.NewSecretListWithArgs("blee", resource.NewSecretWithArgs(ca)) + mc := NewMockConnection() + mr := NewMockCruder() + l := NewSecretListWithArgs("blee", NewSecretWithArgs(mc, mr)) assert.NotNil(t, l.Resource()) } func TestSecretListData(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.List("blee")).ThenReturn(k8s.Collection{*k8sSecret()}, nil) - ca := NewMockCaller() - m.When(ca.List("blee")).ThenReturn(k8s.Collection{*k8sSecret()}, nil) - - l := resource.NewSecretListWithArgs("blee", resource.NewSecretWithArgs(ca)) - // Make sure we can get deltas! + l := NewSecretListWithArgs("blee", NewSecretWithArgs(mc, mr)) + // Make sure we mrn get deltas! for i := 0; i < 2; i++ { err := l.Reconcile() assert.Nil(t, err) } - ca.VerifyWasCalled(m.Times(2)).List("blee") + mr.VerifyWasCalled(m.Times(2)).List("blee") td := l.Data() assert.Equal(t, 1, len(td.Rows)) @@ -144,7 +151,8 @@ func TestSecretListData(t *testing.T) { // Helpers... func newSecret() resource.Columnar { - return resource.NewSecret().NewInstance(k8sSecret()) + mc := NewMockConnection() + return resource.NewSecret(mc).New(k8sSecret()) } func k8sSecret() *v1.Secret { diff --git a/internal/resource/sts.go b/internal/resource/sts.go index 5627896b..ed92f426 100644 --- a/internal/resource/sts.go +++ b/internal/resource/sts.go @@ -16,7 +16,7 @@ type StatefulSet struct { // NewStatefulSetList returns a new resource list. func NewStatefulSetList(c k8s.Connection, ns string) List { - return newList( + return NewList( ns, "sts", NewStatefulSet(c), @@ -26,7 +26,7 @@ func NewStatefulSetList(c k8s.Connection, ns string) List { // NewStatefulSet instantiates a new StatefulSet. func NewStatefulSet(c k8s.Connection) *StatefulSet { - s := &StatefulSet{&Base{connection: c, resource: k8s.NewStatefulSet(c)}, nil} + s := &StatefulSet{&Base{Connection: c, Resource: k8s.NewStatefulSet(c)}, nil} s.Factory = s return s @@ -34,7 +34,7 @@ func NewStatefulSet(c k8s.Connection) *StatefulSet { // New builds a new StatefulSet instance from a k8s resource. func (r *StatefulSet) New(i interface{}) Columnar { - c := NewStatefulSet(r.connection) + c := NewStatefulSet(r.Connection) switch instance := i.(type) { case *v1.StatefulSet: c.instance = instance @@ -51,7 +51,7 @@ func (r *StatefulSet) New(i interface{}) Columnar { // Marshal resource to yaml. func (r *StatefulSet) Marshal(path string) (string, error) { ns, n := namespaced(path) - i, err := r.resource.Get(ns, n) + i, err := r.Resource.Get(ns, n) if err != nil { return "", err } diff --git a/internal/resource/sts_test.go b/internal/resource/sts_test.go index 9ff8ba4f..156053ab 100644 --- a/internal/resource/sts_test.go +++ b/internal/resource/sts_test.go @@ -11,9 +11,22 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +func NewStatefulSetListWithArgs(ns string, r *resource.StatefulSet) resource.List { + return resource.NewList(ns, "sts", r, resource.AllVerbsAccess|resource.DescribeAccess) +} + +func NewStatefulSetWithArgs(conn k8s.Connection, res resource.Cruder) *resource.StatefulSet { + r := &resource.StatefulSet{Base: resource.NewBase(conn, res)} + r.Factory = r + return r +} + func TestStsListAccess(t *testing.T) { + mc := NewMockConnection() + mr := NewMockCruder() + ns := "blee" - l := resource.NewStatefulSetList(resource.AllNamespaces) + l := NewStatefulSetListWithArgs(resource.AllNamespaces, NewStatefulSetWithArgs(mc, mr)) l.SetNamespace(ns) assert.Equal(t, l.GetNamespace(), ns) @@ -46,32 +59,31 @@ func TestStsFields(t *testing.T) { } func TestSTSMarshal(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.Get("blee", "fred")).ThenReturn(k8sSTS(), nil) - ca := NewMockCaller() - m.When(ca.Get("blee", "fred")).ThenReturn(k8sSTS(), nil) - - cm := resource.NewStatefulSetWithArgs(ca) + cm := NewStatefulSetWithArgs(mc, mr) ma, err := cm.Marshal("blee/fred") - ca.VerifyWasCalledOnce().Get("blee", "fred") + + mr.VerifyWasCalledOnce().Get("blee", "fred") assert.Nil(t, err) assert.Equal(t, stsYaml(), ma) } func TestSTSListData(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.List("blee")).ThenReturn(k8s.Collection{*k8sSTS()}, nil) - ca := NewMockCaller() - m.When(ca.List("blee")).ThenReturn(k8s.Collection{*k8sSTS()}, nil) - - l := resource.NewStatefulSetListWithArgs("blee", resource.NewStatefulSetWithArgs(ca)) - // Make sure we can get deltas! + l := NewStatefulSetListWithArgs("blee", NewStatefulSetWithArgs(mc, mr)) + // Make sure we mrn get deltas! for i := 0; i < 2; i++ { err := l.Reconcile() assert.Nil(t, err) } - ca.VerifyWasCalled(m.Times(2)).List("blee") + mr.VerifyWasCalled(m.Times(2)).List("blee") td := l.Data() assert.Equal(t, 1, len(td.Rows)) assert.Equal(t, "blee", l.GetNamespace()) @@ -102,7 +114,8 @@ func k8sSTS() *v1.StatefulSet { } func newSts() resource.Columnar { - return resource.NewStatefulSet().NewInstance(k8sSTS()) + mc := NewMockConnection() + return resource.NewStatefulSet(mc).New(k8sSTS()) } func stsHeader() resource.Row { diff --git a/internal/resource/svc.go b/internal/resource/svc.go index 4f38af92..608408c6 100644 --- a/internal/resource/svc.go +++ b/internal/resource/svc.go @@ -20,7 +20,7 @@ type Service struct { // NewServiceList returns a new resource list. func NewServiceList(c k8s.Connection, ns string) List { - return newList( + return NewList( ns, "svc", NewService(c), @@ -30,7 +30,7 @@ func NewServiceList(c k8s.Connection, ns string) List { // NewService instantiates a new Service. func NewService(c k8s.Connection) *Service { - s := &Service{&Base{connection: c, resource: k8s.NewService(c)}, nil} + s := &Service{&Base{Connection: c, Resource: k8s.NewService(c)}, nil} s.Factory = s return s @@ -38,7 +38,7 @@ func NewService(c k8s.Connection) *Service { // New builds a new Service instance from a k8s resource. func (r *Service) New(i interface{}) Columnar { - c := NewService(r.connection) + c := NewService(r.Connection) switch instance := i.(type) { case *v1.Service: c.instance = instance @@ -56,7 +56,7 @@ func (r *Service) New(i interface{}) Columnar { // BOZO!! Why you need to fill type info?? func (r *Service) Marshal(path string) (string, error) { ns, n := namespaced(path) - i, err := r.resource.Get(ns, n) + i, err := r.Resource.Get(ns, n) if err != nil { return "", err } diff --git a/internal/resource/svc_test.go b/internal/resource/svc_test.go index bfb514a8..517abccc 100644 --- a/internal/resource/svc_test.go +++ b/internal/resource/svc_test.go @@ -11,9 +11,22 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +func NewServiceListWithArgs(ns string, r *resource.Service) resource.List { + return resource.NewList(ns, "svc", r, resource.AllVerbsAccess|resource.DescribeAccess) +} + +func NewServiceWithArgs(conn k8s.Connection, res resource.Cruder) *resource.Service { + r := &resource.Service{Base: resource.NewBase(conn, res)} + r.Factory = r + return r +} + func TestSvcListAccess(t *testing.T) { + mc := NewMockConnection() + mr := NewMockCruder() + ns := "blee" - l := resource.NewServiceList(resource.AllNamespaces) + l := NewServiceListWithArgs(resource.AllNamespaces, NewServiceWithArgs(mc, mr)) l.SetNamespace(ns) assert.Equal(t, l.GetNamespace(), ns) @@ -57,32 +70,30 @@ func TestSvcFields(t *testing.T) { } func TestSVCMarshal(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.Get("blee", "fred")).ThenReturn(k8sSVC(), nil) - ca := NewMockCaller() - m.When(ca.Get("blee", "fred")).ThenReturn(k8sSVC(), nil) - - cm := resource.NewServiceWithArgs(ca) + cm := NewServiceWithArgs(mc, mr) ma, err := cm.Marshal("blee/fred") - ca.VerifyWasCalledOnce().Get("blee", "fred") + mr.VerifyWasCalledOnce().Get("blee", "fred") assert.Nil(t, err) assert.Equal(t, svcYaml(), ma) } func TestSVCListData(t *testing.T) { - setup(t) + mc := NewMockConnection() + mr := NewMockCruder() + m.When(mr.List("blee")).ThenReturn(k8s.Collection{*k8sSVC()}, nil) - ca := NewMockCaller() - m.When(ca.List("blee")).ThenReturn(k8s.Collection{*k8sSVC()}, nil) - - l := resource.NewServiceListWithArgs("blee", resource.NewServiceWithArgs(ca)) - // Make sure we can get deltas! + l := NewServiceListWithArgs("blee", NewServiceWithArgs(mc, mr)) + // Make sure we mrn get deltas! for i := 0; i < 2; i++ { err := l.Reconcile() assert.Nil(t, err) } - ca.VerifyWasCalled(m.Times(2)).List("blee") + mr.VerifyWasCalled(m.Times(2)).List("blee") td := l.Data() assert.Equal(t, 1, len(td.Rows)) assert.Equal(t, "blee", l.GetNamespace()) @@ -120,7 +131,8 @@ func k8sSVC() *v1.Service { } func newSvc() resource.Columnar { - return resource.NewService().NewInstance(k8sSVC()) + mc := NewMockConnection() + return resource.NewService(mc).New(k8sSVC()) } func svcHeader() resource.Row {