Skip to content

Commit

Permalink
kubeconfig generation: add tests for kops plugin
Browse files Browse the repository at this point in the history
Also slightly simplify the tests and Kubecfg Builder signature by
passing in the ConfigAccess only when needed.
  • Loading branch information
justinsb committed Aug 30, 2020
1 parent 0cda0f5 commit 8757a2c
Show file tree
Hide file tree
Showing 11 changed files with 111 additions and 142 deletions.
4 changes: 2 additions & 2 deletions cmd/kops/delete_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,9 @@ func RunDeleteCluster(ctx context.Context, f *util.Factory, out io.Writer, optio
}
}

b := kubeconfig.NewKubeconfigBuilder(clientcmd.NewDefaultPathOptions())
b := kubeconfig.NewKubeconfigBuilder()
b.Context = clusterName
err = b.DeleteKubeConfig()
err = b.DeleteKubeConfig(clientcmd.NewDefaultPathOptions())
if err != nil {
klog.Warningf("error removing kube config: %v", err)
}
Expand Down
3 changes: 1 addition & 2 deletions cmd/kops/export_kubecfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,6 @@ func RunExportKubecfg(ctx context.Context, f *util.Factory, out io.Writer, optio
keyStore,
secretStore,
&commands.CloudDiscoveryStatusStore{},
buildPathOptions(options),
options.admin,
options.user,
options.internal,
Expand All @@ -154,7 +153,7 @@ func RunExportKubecfg(ctx context.Context, f *util.Factory, out io.Writer, optio
return err
}

if err := conf.WriteKubecfg(); err != nil {
if err := conf.WriteKubecfg(buildPathOptions(options)); err != nil {
return err
}
}
Expand Down
3 changes: 1 addition & 2 deletions cmd/kops/update_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,6 @@ func RunUpdateCluster(ctx context.Context, f *util.Factory, clusterName string,
keyStore,
secretStore,
&commands.CloudDiscoveryStatusStore{},
clientcmd.NewDefaultPathOptions(),
c.admin,
c.user,
c.internal,
Expand All @@ -323,7 +322,7 @@ func RunUpdateCluster(ctx context.Context, f *util.Factory, clusterName string,
return nil, err
}

err = conf.WriteKubecfg()
err = conf.WriteKubecfg(clientcmd.NewDefaultPathOptions())
if err != nil {
return nil, err
}
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ require (
github.com/go-ini/ini v1.51.0
github.com/go-logr/logr v0.2.1-0.20200730175230-ee2de8da5be6
github.com/gogo/protobuf v1.3.1
github.com/google/go-cmp v0.4.0
github.com/google/uuid v1.1.1
github.com/gophercloud/gophercloud v0.11.1-0.20200518183226-7aec46f32c19
github.com/gorilla/mux v1.7.3
Expand Down
2 changes: 1 addition & 1 deletion pkg/commands/helpers/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ go_library(
"//upup/pkg/fi:go_default_library",
"//vendor/github.com/spf13/cobra:go_default_library",
"//vendor/k8s.io/client-go/util/homedir:go_default_library",
"//vendor/k8s.io/klog:go_default_library",
"//vendor/k8s.io/klog/v2:go_default_library",
"//vendor/k8s.io/kubectl/pkg/util/i18n:go_default_library",
],
)
2 changes: 1 addition & 1 deletion pkg/commands/helpers/kubectl_auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import (

"github.com/spf13/cobra"
"k8s.io/client-go/util/homedir"
"k8s.io/klog"
"k8s.io/klog/v2"
"k8s.io/kops/cmd/kops/util"
"k8s.io/kops/pkg/commands/commandutils"
"k8s.io/kops/pkg/pki"
Expand Down
2 changes: 1 addition & 1 deletion pkg/kubeconfig/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@ go_test(
"//pkg/pki:go_default_library",
"//upup/pkg/fi:go_default_library",
"//util/pkg/vfs:go_default_library",
"//vendor/k8s.io/client-go/tools/clientcmd:go_default_library",
"//vendor/github.com/google/go-cmp/cmp:go_default_library",
],
)
5 changes: 2 additions & 3 deletions pkg/kubeconfig/create_kubecfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
"sort"
"time"

"k8s.io/client-go/tools/clientcmd"
"k8s.io/klog/v2"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/apis/kops/util"
Expand All @@ -35,7 +34,7 @@ import (

const DefaultKubecfgAdminLifetime = 18 * time.Hour

func BuildKubecfg(cluster *kops.Cluster, keyStore fi.Keystore, secretStore fi.SecretStore, status kops.StatusStore, configAccess clientcmd.ConfigAccess, admin time.Duration, configUser string, internal bool, kopsStateStore string, useKopsAuthenticationPlugin bool) (*KubeconfigBuilder, error) {
func BuildKubecfg(cluster *kops.Cluster, keyStore fi.Keystore, secretStore fi.SecretStore, status kops.StatusStore, admin time.Duration, configUser string, internal bool, kopsStateStore string, useKopsAuthenticationPlugin bool) (*KubeconfigBuilder, error) {
clusterName := cluster.ObjectMeta.Name

var master string
Expand Down Expand Up @@ -98,7 +97,7 @@ func BuildKubecfg(cluster *kops.Cluster, keyStore fi.Keystore, secretStore fi.Se
}
}

b := NewKubeconfigBuilder(configAccess)
b := NewKubeconfigBuilder()

b.Context = clusterName
b.Server = server
Expand Down
210 changes: 92 additions & 118 deletions pkg/kubeconfig/create_kubecfg_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@ package kubeconfig

import (
"fmt"
"reflect"
"testing"
"time"

"k8s.io/client-go/tools/clientcmd"
"github.com/google/go-cmp/cmp"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/pki"
"k8s.io/kops/upup/pkg/fi"
Expand Down Expand Up @@ -123,121 +122,79 @@ func TestBuildKubecfg(t *testing.T) {
}()

type args struct {
cluster *kops.Cluster
keyStore fakeKeyStore
secretStore fi.SecretStore
status fakeStatusStore
configAccess clientcmd.ConfigAccess
admin time.Duration
user string
internal bool
cluster *kops.Cluster
secretStore fi.SecretStore
status fakeStatusStore
admin time.Duration
user string
internal bool
useKopsAuthenticationPlugin bool
}

publiccluster := buildMinimalCluster("testcluster", "testcluster.test.com")
emptyMasterPublicNameCluster := buildMinimalCluster("emptyMasterPublicNameCluster", "")
gossipCluster := buildMinimalCluster("testgossipcluster.k8s.local", "")

tests := []struct {
name string
args args
want *KubeconfigBuilder
wantErr bool
name string
args args
want *KubeconfigBuilder
wantErr bool
wantClientCert bool
}{
{
"Test Kube Config Data For Public DNS with admin",
args{
publiccluster,
fakeKeyStore{
FindKeypairFn: func(name string) (*pki.Certificate, *pki.PrivateKey, bool, error) {
return fakeCertificate(),
fakePrivateKey(),
true,
nil
},
},
nil,
fakeStatusStore{},
nil,
DefaultKubecfgAdminLifetime,
"",
false,
name: "Test Kube Config Data For Public DNS with admin",
args: args{
cluster: publiccluster,
status: fakeStatusStore{},
admin: DefaultKubecfgAdminLifetime,
user: "",
},
&KubeconfigBuilder{
want: &KubeconfigBuilder{
Context: "testcluster",
Server: "https://testcluster.test.com",
CACert: []byte(certData),
User: "testcluster",
},
false,
wantClientCert: true,
},
{
"Test Kube Config Data For Public DNS without admin",
args{
publiccluster,
fakeKeyStore{
FindKeypairFn: func(name string) (*pki.Certificate, *pki.PrivateKey, bool, error) {
return fakeCertificate(),
fakePrivateKey(),
true,
nil
},
},
nil,
fakeStatusStore{},
nil,
0,
"myuser",
false,
name: "Test Kube Config Data For Public DNS without admin",
args: args{
cluster: publiccluster,
status: fakeStatusStore{},
admin: 0,
user: "myuser",
},
&KubeconfigBuilder{
want: &KubeconfigBuilder{
Context: "testcluster",
Server: "https://testcluster.test.com",
CACert: []byte(certData),
User: "myuser",
},
false,
wantClientCert: false,
},
{
"Test Kube Config Data For Public DNS with Empty Master Name",
args{
emptyMasterPublicNameCluster,
fakeKeyStore{
FindKeypairFn: func(name string) (*pki.Certificate, *pki.PrivateKey, bool, error) {
return fakeCertificate(),
fakePrivateKey(),
true,
nil
},
},
nil,
fakeStatusStore{},
nil,
0,
"",
false,
name: "Test Kube Config Data For Public DNS with Empty Master Name",
args: args{
cluster: emptyMasterPublicNameCluster,
status: fakeStatusStore{},
admin: 0,
user: "",
},
&KubeconfigBuilder{
want: &KubeconfigBuilder{
Context: "emptyMasterPublicNameCluster",
Server: "https://api.emptyMasterPublicNameCluster",
CACert: []byte(certData),
User: "emptyMasterPublicNameCluster",
},
false,
wantClientCert: false,
},
{
"Test Kube Config Data For Gossip cluster",
args{
gossipCluster,
fakeKeyStore{
FindKeypairFn: func(name string) (*pki.Certificate, *pki.PrivateKey, bool, error) {
return fakeCertificate(),
fakePrivateKey(),
true,
nil
},
},
nil,
fakeStatusStore{
name: "Test Kube Config Data For Gossip cluster",
args: args{
cluster: gossipCluster,
status: fakeStatusStore{
GetApiIngressStatusFn: func(cluster *kops.Cluster) ([]kops.ApiIngressStatus, error) {
return []kops.ApiIngressStatus{
{
Expand All @@ -246,57 +203,74 @@ func TestBuildKubecfg(t *testing.T) {
}, nil
},
},
nil,
0,
"",
false,
},
&KubeconfigBuilder{
want: &KubeconfigBuilder{
Context: "testgossipcluster.k8s.local",
Server: "https://elbHostName",
CACert: []byte(certData),
User: "testgossipcluster.k8s.local",
},
false,
wantClientCert: false,
},
{
"Test Kube Config Data For internal DNS name with admin",
args{
publiccluster,
fakeKeyStore{
FindKeypairFn: func(name string) (*pki.Certificate, *pki.PrivateKey, bool, error) {
return fakeCertificate(),
fakePrivateKey(),
true,
nil
},
name: "Public DNS with kops auth plugin",
args: args{
cluster: publiccluster,
status: fakeStatusStore{},
admin: 0,
useKopsAuthenticationPlugin: true,
},
want: &KubeconfigBuilder{
Context: "testcluster",
Server: "https://testcluster.test.com",
CACert: []byte(certData),
User: "testcluster",
AuthenticationExec: []string{
"kops",
"helpers",
"kubectl-auth",
"--cluster=testcluster",
"--state=memfs://example-state-store",
},
nil,
fakeStatusStore{},
nil,
DefaultKubecfgAdminLifetime,
"",
true,
},
&KubeconfigBuilder{
Context: "testcluster",
Server: "https://internal.testcluster.test.com",
CACert: []byte(certData),
ClientCert: []byte(certData),
ClientKey: []byte(privatekeyData),
User: "testcluster",
wantClientCert: false,
},
{
name: "Test Kube Config Data For internal DNS name with admin",
args: args{
cluster: publiccluster,
status: fakeStatusStore{},
admin: DefaultKubecfgAdminLifetime,
internal: true,
},
want: &KubeconfigBuilder{
Context: "testcluster",
Server: "https://internal.testcluster.test.com",
CACert: []byte(certData),
User: "testcluster",
},
false,
wantClientCert: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := BuildKubecfg(tt.args.cluster, tt.args.keyStore, tt.args.secretStore, tt.args.status, tt.args.configAccess, tt.args.admin, tt.args.user, tt.args.internal)
kopsStateStore := "memfs://example-state-store"

keyStore := fakeKeyStore{
FindKeypairFn: func(name string) (*pki.Certificate, *pki.PrivateKey, bool, error) {
return fakeCertificate(),
fakePrivateKey(),
true,
nil
},
}

got, err := BuildKubecfg(tt.args.cluster, keyStore, tt.args.secretStore, tt.args.status, tt.args.admin, tt.args.user, tt.args.internal, kopsStateStore, tt.args.useKopsAuthenticationPlugin)
if (err != nil) != tt.wantErr {
t.Errorf("BuildKubecfg() error = %v, wantErr %v", err, tt.wantErr)
return
}
if tt.args.admin != 0 {
if tt.wantClientCert {
if got.ClientCert == nil {
t.Errorf("Expected ClientCert, got nil")
}
Expand All @@ -306,8 +280,8 @@ func TestBuildKubecfg(t *testing.T) {
tt.want.ClientCert = got.ClientCert
tt.want.ClientKey = got.ClientKey
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("BuildKubecfg() = %+v, want %+v", got, tt.want)
if diff := cmp.Diff(got, tt.want); diff != "" {
t.Errorf("BuildKubecfg() diff (+got, -want): %s", diff)
}
})
}
Expand Down
Loading

0 comments on commit 8757a2c

Please sign in to comment.