Refactor get_kubeconfig.go.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
This commit is contained in:
parent
541336b997
commit
381fd51e13
@ -27,51 +27,40 @@ import (
|
|||||||
"go.pinniped.dev/internal/here"
|
"go.pinniped.dev/internal/here"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
getKubeConfigCmdTokenFlagName = "token"
|
|
||||||
getKubeConfigCmdKubeconfigFlagName = "kubeconfig"
|
|
||||||
getKubeConfigCmdKubeconfigContextFlagName = "kubeconfig-context"
|
|
||||||
getKubeConfigCmdPinnipedNamespaceFlagName = "pinniped-namespace"
|
|
||||||
)
|
|
||||||
|
|
||||||
//nolint: gochecknoinits
|
//nolint: gochecknoinits
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(newGetKubeConfigCmd(os.Args, os.Stdout, os.Stderr).cmd)
|
rootCmd.AddCommand(newGetKubeConfigCommand().Command())
|
||||||
|
}
|
||||||
|
|
||||||
|
type getKubeConfigFlags struct {
|
||||||
|
token string
|
||||||
|
kubeconfig string
|
||||||
|
contextOverride string
|
||||||
|
namespace string
|
||||||
}
|
}
|
||||||
|
|
||||||
type getKubeConfigCommand struct {
|
type getKubeConfigCommand struct {
|
||||||
// runFunc is called by the cobra.Command.Run hook. It is included here for
|
flags getKubeConfigFlags
|
||||||
// testability.
|
// Test mocking points
|
||||||
runFunc func(
|
getPathToSelf func() (string, error)
|
||||||
stdout, stderr io.Writer,
|
kubeClientCreator func(restConfig *rest.Config) (pinnipedclientset.Interface, error)
|
||||||
token, kubeconfigPathOverride, currentContextOverride, pinnipedInstallationNamespace string,
|
|
||||||
)
|
|
||||||
|
|
||||||
// cmd is the cobra.Command for this CLI command. It is included here for
|
|
||||||
// testability.
|
|
||||||
cmd *cobra.Command
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newGetKubeConfigCmd(args []string, stdout, stderr io.Writer) *getKubeConfigCommand {
|
func newGetKubeConfigCommand() *getKubeConfigCommand {
|
||||||
c := &getKubeConfigCommand{
|
return &getKubeConfigCommand{
|
||||||
runFunc: runGetKubeConfig,
|
flags: getKubeConfigFlags{
|
||||||
}
|
namespace: "pinniped",
|
||||||
|
|
||||||
c.cmd = &cobra.Command{
|
|
||||||
Run: func(cmd *cobra.Command, _ []string) {
|
|
||||||
token := cmd.Flag(getKubeConfigCmdTokenFlagName).Value.String()
|
|
||||||
kubeconfigPathOverride := cmd.Flag(getKubeConfigCmdKubeconfigFlagName).Value.String()
|
|
||||||
currentContextOverride := cmd.Flag(getKubeConfigCmdKubeconfigContextFlagName).Value.String()
|
|
||||||
pinnipedInstallationNamespace := cmd.Flag(getKubeConfigCmdPinnipedNamespaceFlagName).Value.String()
|
|
||||||
c.runFunc(
|
|
||||||
stdout,
|
|
||||||
stderr,
|
|
||||||
token,
|
|
||||||
kubeconfigPathOverride,
|
|
||||||
currentContextOverride,
|
|
||||||
pinnipedInstallationNamespace,
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
|
getPathToSelf: os.Executable,
|
||||||
|
kubeClientCreator: func(restConfig *rest.Config) (pinnipedclientset.Interface, error) {
|
||||||
|
return pinnipedclientset.NewForConfig(restConfig)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *getKubeConfigCommand) Command() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
RunE: c.run,
|
||||||
Args: cobra.NoArgs, // do not accept positional arguments for this command
|
Args: cobra.NoArgs, // do not accept positional arguments for this command
|
||||||
Use: "get-kubeconfig",
|
Use: "get-kubeconfig",
|
||||||
Short: "Print a kubeconfig for authenticating into a cluster via Pinniped",
|
Short: "Print a kubeconfig for authenticating into a cluster via Pinniped",
|
||||||
@ -93,94 +82,40 @@ func newGetKubeConfigCmd(args []string, stdout, stderr io.Writer) *getKubeConfig
|
|||||||
kubectl --kubeconfig $HOME/mycluster-kubeconfig get pods
|
kubectl --kubeconfig $HOME/mycluster-kubeconfig get pods
|
||||||
`),
|
`),
|
||||||
}
|
}
|
||||||
|
cmd.Flags().StringVar(&c.flags.token, "token", "", "Credential to include in the resulting kubeconfig output (Required)")
|
||||||
c.cmd.SetArgs(args)
|
err := cmd.MarkFlagRequired("token")
|
||||||
c.cmd.SetOut(stdout)
|
|
||||||
c.cmd.SetErr(stderr)
|
|
||||||
|
|
||||||
c.cmd.Flags().StringP(
|
|
||||||
getKubeConfigCmdTokenFlagName,
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"Credential to include in the resulting kubeconfig output (Required)",
|
|
||||||
)
|
|
||||||
err := c.cmd.MarkFlagRequired(getKubeConfigCmdTokenFlagName)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
cmd.Flags().StringVar(&c.flags.kubeconfig, "kubeconfig", c.flags.kubeconfig, "Path to the kubeconfig file")
|
||||||
c.cmd.Flags().StringP(
|
cmd.Flags().StringVar(&c.flags.contextOverride, "kubeconfig-context", c.flags.contextOverride, "Kubeconfig context override")
|
||||||
getKubeConfigCmdKubeconfigFlagName,
|
cmd.Flags().StringVar(&c.flags.namespace, "pinniped-namespace", c.flags.namespace, "Namespace in which Pinniped was installed")
|
||||||
"",
|
return cmd
|
||||||
"",
|
|
||||||
"Path to the kubeconfig file",
|
|
||||||
)
|
|
||||||
|
|
||||||
c.cmd.Flags().StringP(
|
|
||||||
getKubeConfigCmdKubeconfigContextFlagName,
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"Kubeconfig context override",
|
|
||||||
)
|
|
||||||
|
|
||||||
c.cmd.Flags().StringP(
|
|
||||||
getKubeConfigCmdPinnipedNamespaceFlagName,
|
|
||||||
"",
|
|
||||||
"pinniped",
|
|
||||||
"Namespace in which Pinniped was installed",
|
|
||||||
)
|
|
||||||
|
|
||||||
return c
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func runGetKubeConfig(
|
func (c *getKubeConfigCommand) run(cmd *cobra.Command, args []string) error {
|
||||||
stdout, stderr io.Writer,
|
fullPathToSelf, err := c.getPathToSelf()
|
||||||
token, kubeconfigPathOverride, currentContextOverride, pinnipedInstallationNamespace string,
|
|
||||||
) {
|
|
||||||
err := getKubeConfig(
|
|
||||||
stdout,
|
|
||||||
stderr,
|
|
||||||
token,
|
|
||||||
kubeconfigPathOverride,
|
|
||||||
currentContextOverride,
|
|
||||||
pinnipedInstallationNamespace,
|
|
||||||
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) {
|
|
||||||
return pinnipedclientset.NewForConfig(restConfig)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
_, _ = fmt.Fprintf(os.Stderr, "error: %s\n", err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getKubeConfig(
|
|
||||||
outputWriter io.Writer,
|
|
||||||
warningsWriter io.Writer,
|
|
||||||
token string,
|
|
||||||
kubeconfigPathOverride string,
|
|
||||||
currentContextNameOverride string,
|
|
||||||
pinnipedInstallationNamespace string,
|
|
||||||
kubeClientCreator func(restConfig *rest.Config) (pinnipedclientset.Interface, error),
|
|
||||||
) error {
|
|
||||||
if token == "" {
|
|
||||||
return constable.Error("--" + getKubeConfigCmdTokenFlagName + " flag value cannot be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
fullPathToSelf, err := os.Executable()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not find path to self: %w", err)
|
return fmt.Errorf("could not find path to self: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
clientConfig := newClientConfig(kubeconfigPathOverride, currentContextNameOverride)
|
clientConfig := newClientConfig(c.flags.kubeconfig, c.flags.contextOverride)
|
||||||
|
|
||||||
currentKubeConfig, err := clientConfig.RawConfig()
|
currentKubeConfig, err := clientConfig.RawConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
credentialIssuerConfig, err := fetchPinnipedCredentialIssuerConfig(clientConfig, kubeClientCreator, pinnipedInstallationNamespace)
|
restConfig, err := clientConfig.ClientConfig()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
clientset, err := c.kubeClientCreator(restConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
credentialIssuerConfig, err := fetchPinnipedCredentialIssuerConfig(clientset, c.flags.namespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -189,19 +124,19 @@ func getKubeConfig(
|
|||||||
return constable.Error(`CredentialIssuerConfig "pinniped-config" was missing KubeConfigInfo`)
|
return constable.Error(`CredentialIssuerConfig "pinniped-config" was missing KubeConfigInfo`)
|
||||||
}
|
}
|
||||||
|
|
||||||
v1Cluster, err := copyCurrentClusterFromExistingKubeConfig(currentKubeConfig, currentContextNameOverride)
|
v1Cluster, err := copyCurrentClusterFromExistingKubeConfig(currentKubeConfig, c.flags.contextOverride)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = issueWarningForNonMatchingServerOrCA(v1Cluster, credentialIssuerConfig, warningsWriter)
|
err = issueWarningForNonMatchingServerOrCA(v1Cluster, credentialIssuerConfig, cmd.ErrOrStderr())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
config := newPinnipedKubeconfig(v1Cluster, fullPathToSelf, token, pinnipedInstallationNamespace)
|
config := newPinnipedKubeconfig(v1Cluster, fullPathToSelf, c.flags.token, c.flags.namespace)
|
||||||
|
|
||||||
err = writeConfigAsYAML(outputWriter, config)
|
err = writeConfigAsYAML(cmd.OutOrStdout(), config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -224,16 +159,7 @@ func issueWarningForNonMatchingServerOrCA(v1Cluster v1.Cluster, credentialIssuer
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchPinnipedCredentialIssuerConfig(clientConfig clientcmd.ClientConfig, kubeClientCreator func(restConfig *rest.Config) (pinnipedclientset.Interface, error), pinnipedInstallationNamespace string) (*configv1alpha1.CredentialIssuerConfig, error) {
|
func fetchPinnipedCredentialIssuerConfig(clientset pinnipedclientset.Interface, pinnipedInstallationNamespace string) (*configv1alpha1.CredentialIssuerConfig, error) {
|
||||||
restConfig, err := clientConfig.ClientConfig()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
clientset, err := kubeClientCreator(restConfig)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx, cancelFunc := context.WithTimeout(context.Background(), time.Second*20)
|
ctx, cancelFunc := context.WithTimeout(context.Background(), time.Second*20)
|
||||||
defer cancelFunc()
|
defer cancelFunc()
|
||||||
|
|
||||||
|
@ -7,16 +7,15 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"strings"
|
||||||
"os"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/sclevine/spec"
|
"github.com/spf13/cobra"
|
||||||
"github.com/sclevine/spec/report"
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
|
coretesting "k8s.io/client-go/testing"
|
||||||
|
|
||||||
configv1alpha1 "go.pinniped.dev/generated/1.19/apis/config/v1alpha1"
|
configv1alpha1 "go.pinniped.dev/generated/1.19/apis/config/v1alpha1"
|
||||||
pinnipedclientset "go.pinniped.dev/generated/1.19/client/clientset/versioned"
|
pinnipedclientset "go.pinniped.dev/generated/1.19/client/clientset/versioned"
|
||||||
@ -68,149 +67,60 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestNewGetKubeConfigCmd(t *testing.T) {
|
func TestNewGetKubeConfigCmd(t *testing.T) {
|
||||||
spec.Run(t, "newGetKubeConfigCmd", func(t *testing.T, when spec.G, it spec.S) {
|
t.Parallel()
|
||||||
var r *require.Assertions
|
tests := []struct {
|
||||||
var stdout, stderr *bytes.Buffer
|
name string
|
||||||
|
args []string
|
||||||
|
wantError bool
|
||||||
|
wantStdout string
|
||||||
|
wantStderr string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "help flag passed",
|
||||||
|
args: []string{"--help"},
|
||||||
|
wantStdout: knownGoodHelpForGetKubeConfig,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "missing required flag",
|
||||||
|
args: []string{},
|
||||||
|
wantError: true,
|
||||||
|
wantStdout: `Error: required flag(s) "token" not set` + "\n" + knownGoodUsageForGetKubeConfig,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
tt := tt
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
cmd := newGetKubeConfigCommand().Command()
|
||||||
|
require.NotNil(t, cmd)
|
||||||
|
|
||||||
it.Before(func() {
|
var stdout, stderr bytes.Buffer
|
||||||
r = require.New(t)
|
cmd.SetOut(&stdout)
|
||||||
|
cmd.SetErr(&stderr)
|
||||||
stdout, stderr = bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{})
|
cmd.SetArgs(tt.args)
|
||||||
|
err := cmd.Execute()
|
||||||
|
if tt.wantError {
|
||||||
|
require.Error(t, err)
|
||||||
|
} else {
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
require.Equal(t, tt.wantStdout, stdout.String(), "unexpected stdout")
|
||||||
|
require.Equal(t, tt.wantStderr, stderr.String(), "unexpected stderr")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("passes all flags to runFunc", func() {
|
|
||||||
args := []string{
|
|
||||||
"--token", "some-token",
|
|
||||||
"--kubeconfig", "some-kubeconfig",
|
|
||||||
"--kubeconfig-context", "some-kubeconfig-context",
|
|
||||||
"--pinniped-namespace", "some-pinniped-namespace",
|
|
||||||
}
|
}
|
||||||
c := newGetKubeConfigCmd(args, stdout, stderr)
|
|
||||||
|
|
||||||
runFuncCalled := false
|
|
||||||
c.runFunc = func(
|
|
||||||
out, err io.Writer,
|
|
||||||
token, kubeconfigPathOverride, currentContextOverride, pinnipedInstallationNamespace string,
|
|
||||||
) {
|
|
||||||
runFuncCalled = true
|
|
||||||
r.Equal("some-token", token)
|
|
||||||
r.Equal("some-kubeconfig", kubeconfigPathOverride)
|
|
||||||
r.Equal("some-kubeconfig-context", currentContextOverride)
|
|
||||||
r.Equal("some-pinniped-namespace", pinnipedInstallationNamespace)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
r.NoError(c.cmd.Execute())
|
type expectedKubeconfigYAML struct {
|
||||||
r.True(runFuncCalled)
|
clusterCAData string
|
||||||
r.Empty(stdout.String())
|
clusterServer string
|
||||||
r.Empty(stderr.String())
|
command string
|
||||||
})
|
token string
|
||||||
|
pinnipedEndpoint string
|
||||||
it("requires the 'token' flag", func() {
|
pinnipedCABundle string
|
||||||
args := []string{
|
namespace string
|
||||||
"--kubeconfig", "some-kubeconfig",
|
|
||||||
"--kubeconfig-context", "some-kubeconfig-context",
|
|
||||||
"--pinniped-namespace", "some-pinniped-namespace",
|
|
||||||
}
|
|
||||||
c := newGetKubeConfigCmd(args, stdout, stderr)
|
|
||||||
|
|
||||||
runFuncCalled := false
|
|
||||||
c.runFunc = func(
|
|
||||||
out, err io.Writer,
|
|
||||||
token, kubeconfigPathOverride, currentContextOverride, pinnipedInstallationNamespace string,
|
|
||||||
) {
|
|
||||||
runFuncCalled = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
errorMessage := `required flag(s) "token" not set`
|
func (e expectedKubeconfigYAML) String() string {
|
||||||
r.EqualError(c.cmd.Execute(), errorMessage)
|
|
||||||
r.False(runFuncCalled)
|
|
||||||
|
|
||||||
output := "Error: " + errorMessage + "\n" + knownGoodUsageForGetKubeConfig
|
|
||||||
r.Equal(output, stdout.String())
|
|
||||||
r.Empty(stderr.String())
|
|
||||||
})
|
|
||||||
|
|
||||||
it("defaults the flags correctly", func() {
|
|
||||||
args := []string{
|
|
||||||
"--token", "some-token",
|
|
||||||
}
|
|
||||||
c := newGetKubeConfigCmd(args, stdout, stderr)
|
|
||||||
|
|
||||||
runFuncCalled := false
|
|
||||||
c.runFunc = func(
|
|
||||||
out, err io.Writer,
|
|
||||||
token, kubeconfigPathOverride, currentContextOverride, pinnipedInstallationNamespace string,
|
|
||||||
) {
|
|
||||||
runFuncCalled = true
|
|
||||||
r.Equal("some-token", token)
|
|
||||||
r.Equal("", kubeconfigPathOverride)
|
|
||||||
r.Equal("", currentContextOverride)
|
|
||||||
r.Equal("pinniped", pinnipedInstallationNamespace)
|
|
||||||
}
|
|
||||||
|
|
||||||
r.NoError(c.cmd.Execute())
|
|
||||||
r.True(runFuncCalled)
|
|
||||||
r.Empty(stdout.String())
|
|
||||||
r.Empty(stderr.String())
|
|
||||||
})
|
|
||||||
|
|
||||||
it("fails when args are passed", func() {
|
|
||||||
args := []string{
|
|
||||||
"--token", "some-token",
|
|
||||||
"some-arg",
|
|
||||||
}
|
|
||||||
c := newGetKubeConfigCmd(args, stdout, stderr)
|
|
||||||
|
|
||||||
runFuncCalled := false
|
|
||||||
c.runFunc = func(
|
|
||||||
out, err io.Writer,
|
|
||||||
token, kubeconfigPathOverride, currentContextOverride, pinnipedInstallationNamespace string,
|
|
||||||
) {
|
|
||||||
runFuncCalled = true
|
|
||||||
}
|
|
||||||
|
|
||||||
errorMessage := `unknown command "some-arg" for "get-kubeconfig"`
|
|
||||||
r.EqualError(c.cmd.Execute(), errorMessage)
|
|
||||||
r.False(runFuncCalled)
|
|
||||||
|
|
||||||
output := "Error: " + errorMessage + "\n" + knownGoodUsageForGetKubeConfig
|
|
||||||
r.Equal(output, stdout.String())
|
|
||||||
r.Empty(stderr.String())
|
|
||||||
})
|
|
||||||
|
|
||||||
it("prints a nice help message", func() {
|
|
||||||
args := []string{
|
|
||||||
"--help",
|
|
||||||
}
|
|
||||||
c := newGetKubeConfigCmd(args, stdout, stderr)
|
|
||||||
|
|
||||||
runFuncCalled := false
|
|
||||||
c.runFunc = func(
|
|
||||||
out, err io.Writer,
|
|
||||||
token, kubeconfigPathOverride, currentContextOverride, pinnipedInstallationNamespace string,
|
|
||||||
) {
|
|
||||||
runFuncCalled = true
|
|
||||||
}
|
|
||||||
|
|
||||||
r.NoError(c.cmd.Execute())
|
|
||||||
r.False(runFuncCalled)
|
|
||||||
r.Equal(knownGoodHelpForGetKubeConfig, stdout.String())
|
|
||||||
r.Empty(stderr.String())
|
|
||||||
})
|
|
||||||
}, spec.Parallel(), spec.Report(report.Terminal{}))
|
|
||||||
}
|
|
||||||
|
|
||||||
func expectedKubeconfigYAML(
|
|
||||||
clusterCAData,
|
|
||||||
clusterServer,
|
|
||||||
command,
|
|
||||||
// nolint: unparam // Pass in the token even if it is always the same in practice
|
|
||||||
token,
|
|
||||||
pinnipedEndpoint,
|
|
||||||
pinnipedCABundle,
|
|
||||||
// nolint: unparam // Pass in the namespace even if it is always the same in practice
|
|
||||||
namespace string,
|
|
||||||
) string {
|
|
||||||
return here.Docf(`
|
return here.Docf(`
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
clusters:
|
clusters:
|
||||||
@ -246,16 +156,10 @@ func expectedKubeconfigYAML(
|
|||||||
installHint: |-
|
installHint: |-
|
||||||
The Pinniped CLI is required to authenticate to the current cluster.
|
The Pinniped CLI is required to authenticate to the current cluster.
|
||||||
For more information, please visit https://pinniped.dev
|
For more information, please visit https://pinniped.dev
|
||||||
`, clusterCAData, clusterServer, command, pinnipedEndpoint, pinnipedCABundle, namespace, token)
|
`, e.clusterCAData, e.clusterServer, e.command, e.pinnipedEndpoint, e.pinnipedCABundle, e.namespace, e.token)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newCredentialIssuerConfig(
|
func newCredentialIssuerConfig(name, namespace, server, certificateAuthorityData string) *configv1alpha1.CredentialIssuerConfig {
|
||||||
name,
|
|
||||||
//nolint: unparam // Pass in the namespace even if it is always the same in practice
|
|
||||||
namespace,
|
|
||||||
server,
|
|
||||||
certificateAuthorityData string,
|
|
||||||
) *configv1alpha1.CredentialIssuerConfig {
|
|
||||||
return &configv1alpha1.CredentialIssuerConfig{
|
return &configv1alpha1.CredentialIssuerConfig{
|
||||||
TypeMeta: metav1.TypeMeta{
|
TypeMeta: metav1.TypeMeta{
|
||||||
Kind: "CredentialIssuerConfig",
|
Kind: "CredentialIssuerConfig",
|
||||||
@ -274,439 +178,162 @@ func newCredentialIssuerConfig(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetKubeConfig(t *testing.T) {
|
func TestRun(t *testing.T) {
|
||||||
spec.Run(t, "cmd.getKubeConfig", func(t *testing.T, when spec.G, it spec.S) {
|
t.Parallel()
|
||||||
var r *require.Assertions
|
tests := []struct {
|
||||||
var outputBuffer *bytes.Buffer
|
name string
|
||||||
var warningsBuffer *bytes.Buffer
|
mocks func(*getKubeConfigCommand)
|
||||||
var fullPathToSelf string
|
wantError string
|
||||||
var pinnipedClient *pinnipedfake.Clientset
|
wantStdout string
|
||||||
const installationNamespace = "some-namespace"
|
wantStderr string
|
||||||
|
}{
|
||||||
it.Before(func() {
|
{
|
||||||
r = require.New(t)
|
name: "failure to get path to self",
|
||||||
|
mocks: func(cmd *getKubeConfigCommand) {
|
||||||
outputBuffer = new(bytes.Buffer)
|
cmd.getPathToSelf = func() (string, error) {
|
||||||
warningsBuffer = new(bytes.Buffer)
|
return "", fmt.Errorf("some error getting path to self")
|
||||||
|
}
|
||||||
var err error
|
},
|
||||||
fullPathToSelf, err = os.Executable()
|
wantError: "could not find path to self: some error getting path to self",
|
||||||
r.NoError(err)
|
},
|
||||||
|
{
|
||||||
pinnipedClient = pinnipedfake.NewSimpleClientset()
|
name: "kubeconfig does not exist",
|
||||||
})
|
mocks: func(cmd *getKubeConfigCommand) {
|
||||||
|
cmd.flags.kubeconfig = "./testdata/does-not-exist.yaml"
|
||||||
when("the CredentialIssuerConfig is found on the cluster with a configuration that matches the existing kubeconfig", func() {
|
},
|
||||||
it.Before(func() {
|
wantError: "stat ./testdata/does-not-exist.yaml: no such file or directory",
|
||||||
r.NoError(pinnipedClient.Tracker().Add(
|
},
|
||||||
newCredentialIssuerConfig(
|
{
|
||||||
"some-cic-name",
|
name: "fail to get client",
|
||||||
installationNamespace,
|
mocks: func(cmd *getKubeConfigCommand) {
|
||||||
"https://fake-server-url-value",
|
cmd.kubeClientCreator = func(_ *rest.Config) (pinnipedclientset.Interface, error) {
|
||||||
"fake-certificate-authority-data-value",
|
return nil, fmt.Errorf("some error configuring clientset")
|
||||||
),
|
}
|
||||||
))
|
},
|
||||||
})
|
wantError: "some error configuring clientset",
|
||||||
|
},
|
||||||
it("writes the kubeconfig to the given writer", func() {
|
{
|
||||||
kubeClientCreatorFuncWasCalled := false
|
name: "fail to get CredentialIssuerConfigs",
|
||||||
err := getKubeConfig(outputBuffer,
|
mocks: func(cmd *getKubeConfigCommand) {
|
||||||
warningsBuffer,
|
clientset := pinnipedfake.NewSimpleClientset()
|
||||||
"some-token",
|
clientset.PrependReactor("*", "*", func(_ coretesting.Action) (bool, runtime.Object, error) {
|
||||||
"./testdata/kubeconfig.yaml",
|
return true, nil, fmt.Errorf("some error getting CredentialIssuerConfigs")
|
||||||
"",
|
})
|
||||||
installationNamespace,
|
cmd.kubeClientCreator = func(_ *rest.Config) (pinnipedclientset.Interface, error) {
|
||||||
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) {
|
return clientset, nil
|
||||||
kubeClientCreatorFuncWasCalled = true
|
}
|
||||||
r.Equal("https://fake-server-url-value", restConfig.Host)
|
},
|
||||||
r.Equal("fake-certificate-authority-data-value", string(restConfig.CAData))
|
wantError: "some error getting CredentialIssuerConfigs",
|
||||||
return pinnipedClient, nil
|
},
|
||||||
},
|
{
|
||||||
)
|
name: "zero CredentialIssuerConfigs found",
|
||||||
r.NoError(err)
|
mocks: func(cmd *getKubeConfigCommand) {
|
||||||
r.True(kubeClientCreatorFuncWasCalled)
|
cmd.kubeClientCreator = func(_ *rest.Config) (pinnipedclientset.Interface, error) {
|
||||||
|
return pinnipedfake.NewSimpleClientset(
|
||||||
r.Empty(warningsBuffer.String())
|
newCredentialIssuerConfig("pinniped-config-1", "not-the-test-namespace", "", ""),
|
||||||
r.Equal(expectedKubeconfigYAML(
|
), nil
|
||||||
base64.StdEncoding.EncodeToString([]byte("fake-certificate-authority-data-value")),
|
}
|
||||||
"https://fake-server-url-value",
|
},
|
||||||
fullPathToSelf,
|
wantError: `No CredentialIssuerConfig was found in namespace "test-namespace". Is Pinniped installed on this cluster in namespace "test-namespace"?`,
|
||||||
"some-token",
|
},
|
||||||
"https://fake-server-url-value",
|
{
|
||||||
"fake-certificate-authority-data-value",
|
name: "multiple CredentialIssuerConfigs found",
|
||||||
installationNamespace,
|
mocks: func(cmd *getKubeConfigCommand) {
|
||||||
), outputBuffer.String())
|
cmd.kubeClientCreator = func(_ *rest.Config) (pinnipedclientset.Interface, error) {
|
||||||
})
|
return pinnipedfake.NewSimpleClientset(
|
||||||
|
newCredentialIssuerConfig("pinniped-config-1", "test-namespace", "", ""),
|
||||||
when("the currentContextOverride is used to specify a context other than the default context", func() {
|
newCredentialIssuerConfig("pinniped-config-2", "test-namespace", "", ""),
|
||||||
it.Before(func() {
|
), nil
|
||||||
// update the Server and CertificateAuthorityData to make them match the other kubeconfig context
|
}
|
||||||
r.NoError(pinnipedClient.Tracker().Update(
|
},
|
||||||
schema.GroupVersionResource{
|
wantError: `More than one CredentialIssuerConfig was found in namespace "test-namespace"`,
|
||||||
Group: configv1alpha1.GroupName,
|
},
|
||||||
Version: configv1alpha1.SchemeGroupVersion.Version,
|
{
|
||||||
Resource: "credentialissuerconfigs",
|
name: "CredentialIssuerConfig missing KubeConfigInfo",
|
||||||
},
|
mocks: func(cmd *getKubeConfigCommand) {
|
||||||
newCredentialIssuerConfig(
|
cic := newCredentialIssuerConfig("pinniped-config", "test-namespace", "", "")
|
||||||
"some-cic-name",
|
cic.Status.KubeConfigInfo = nil
|
||||||
installationNamespace,
|
cmd.kubeClientCreator = func(_ *rest.Config) (pinnipedclientset.Interface, error) {
|
||||||
"https://some-other-fake-server-url-value",
|
return pinnipedfake.NewSimpleClientset(cic), nil
|
||||||
"some-other-fake-certificate-authority-data-value",
|
}
|
||||||
),
|
},
|
||||||
installationNamespace,
|
wantError: `CredentialIssuerConfig "pinniped-config" was missing KubeConfigInfo`,
|
||||||
))
|
},
|
||||||
})
|
{
|
||||||
|
name: "KubeConfigInfo has invalid base64",
|
||||||
when("that context exists", func() {
|
mocks: func(cmd *getKubeConfigCommand) {
|
||||||
it("writes the kubeconfig to the given writer using the specified context", func() {
|
cic := newCredentialIssuerConfig("pinniped-config", "test-namespace", "https://example.com", "")
|
||||||
kubeClientCreatorFuncWasCalled := false
|
cic.Status.KubeConfigInfo.CertificateAuthorityData = "invalid-base64-test-ca"
|
||||||
err := getKubeConfig(outputBuffer,
|
cmd.kubeClientCreator = func(_ *rest.Config) (pinnipedclientset.Interface, error) {
|
||||||
warningsBuffer,
|
return pinnipedfake.NewSimpleClientset(cic), nil
|
||||||
"some-token",
|
}
|
||||||
"./testdata/kubeconfig.yaml",
|
},
|
||||||
"some-other-context",
|
wantError: `illegal base64 data at input byte 7`,
|
||||||
installationNamespace,
|
},
|
||||||
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) {
|
{
|
||||||
kubeClientCreatorFuncWasCalled = true
|
name: "success using remote CA data",
|
||||||
r.Equal("https://some-other-fake-server-url-value", restConfig.Host)
|
mocks: func(cmd *getKubeConfigCommand) {
|
||||||
r.Equal("some-other-fake-certificate-authority-data-value", string(restConfig.CAData))
|
cic := newCredentialIssuerConfig("pinniped-config", "test-namespace", "https://fake-server-url-value", "fake-certificate-authority-data-value")
|
||||||
return pinnipedClient, nil
|
cmd.kubeClientCreator = func(_ *rest.Config) (pinnipedclientset.Interface, error) {
|
||||||
},
|
return pinnipedfake.NewSimpleClientset(cic), nil
|
||||||
)
|
}
|
||||||
r.NoError(err)
|
},
|
||||||
r.True(kubeClientCreatorFuncWasCalled)
|
wantStdout: expectedKubeconfigYAML{
|
||||||
|
clusterCAData: "ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==",
|
||||||
r.Empty(warningsBuffer.String())
|
clusterServer: "https://fake-server-url-value",
|
||||||
r.Equal(expectedKubeconfigYAML(
|
command: "/path/to/pinniped",
|
||||||
base64.StdEncoding.EncodeToString([]byte("some-other-fake-certificate-authority-data-value")),
|
token: "test-token",
|
||||||
"https://some-other-fake-server-url-value",
|
pinnipedEndpoint: "https://fake-server-url-value",
|
||||||
fullPathToSelf,
|
pinnipedCABundle: "fake-certificate-authority-data-value",
|
||||||
"some-token",
|
namespace: "test-namespace",
|
||||||
"https://some-other-fake-server-url-value",
|
}.String(),
|
||||||
"some-other-fake-certificate-authority-data-value",
|
},
|
||||||
installationNamespace,
|
{
|
||||||
), outputBuffer.String())
|
name: "success using local CA data",
|
||||||
})
|
mocks: func(cmd *getKubeConfigCommand) {
|
||||||
})
|
cic := newCredentialIssuerConfig("pinniped-config", "test-namespace", "https://example.com", "test-ca")
|
||||||
|
cmd.kubeClientCreator = func(_ *rest.Config) (pinnipedclientset.Interface, error) {
|
||||||
when("that context does not exist the in the current kubeconfig", func() {
|
return pinnipedfake.NewSimpleClientset(cic), nil
|
||||||
it("returns an error", func() {
|
}
|
||||||
err := getKubeConfig(outputBuffer,
|
},
|
||||||
warningsBuffer,
|
wantStderr: `WARNING: Server and certificate authority did not match between local kubeconfig and Pinniped's CredentialIssuerConfig on the cluster. Using local kubeconfig values.`,
|
||||||
"some-token",
|
wantStdout: expectedKubeconfigYAML{
|
||||||
"./testdata/kubeconfig.yaml",
|
clusterCAData: "ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==",
|
||||||
"this-context-name-does-not-exist-in-kubeconfig.yaml",
|
clusterServer: "https://fake-server-url-value",
|
||||||
installationNamespace,
|
command: "/path/to/pinniped",
|
||||||
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) { return pinnipedClient, nil },
|
token: "test-token",
|
||||||
)
|
pinnipedEndpoint: "https://fake-server-url-value",
|
||||||
r.EqualError(err, `context "this-context-name-does-not-exist-in-kubeconfig.yaml" does not exist`)
|
pinnipedCABundle: "fake-certificate-authority-data-value",
|
||||||
r.Empty(warningsBuffer.String())
|
namespace: "test-namespace",
|
||||||
r.Empty(outputBuffer.String())
|
}.String(),
|
||||||
})
|
},
|
||||||
})
|
}
|
||||||
})
|
for _, tt := range tests {
|
||||||
|
tt := tt
|
||||||
when("the token passed in is empty", func() {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
it("returns an error", func() {
|
t.Parallel()
|
||||||
err := getKubeConfig(outputBuffer,
|
|
||||||
warningsBuffer,
|
// Start with a default getKubeConfigCommand, set some defaults, then apply any mocks.
|
||||||
"",
|
c := newGetKubeConfigCommand()
|
||||||
"./testdata/kubeconfig.yaml",
|
c.flags.token = "test-token"
|
||||||
"",
|
c.flags.namespace = "test-namespace"
|
||||||
installationNamespace,
|
c.getPathToSelf = func() (string, error) { return "/path/to/pinniped", nil }
|
||||||
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) { return pinnipedClient, nil },
|
c.flags.kubeconfig = "./testdata/kubeconfig.yaml"
|
||||||
)
|
tt.mocks(c)
|
||||||
r.EqualError(err, "--token flag value cannot be empty")
|
|
||||||
r.Empty(warningsBuffer.String())
|
cmd := &cobra.Command{}
|
||||||
r.Empty(outputBuffer.String())
|
var stdout, stderr bytes.Buffer
|
||||||
})
|
cmd.SetOut(&stdout)
|
||||||
})
|
cmd.SetErr(&stderr)
|
||||||
|
cmd.SetArgs([]string{})
|
||||||
when("the kubeconfig path passed refers to a file that does not exist", func() {
|
err := c.run(cmd, []string{})
|
||||||
it("returns an error", func() {
|
if tt.wantError != "" {
|
||||||
err := getKubeConfig(outputBuffer,
|
require.EqualError(t, err, tt.wantError)
|
||||||
warningsBuffer,
|
} else {
|
||||||
"some-token",
|
require.NoError(t, err)
|
||||||
"./testdata/this-file-does-not-exist.yaml",
|
}
|
||||||
"",
|
require.Equal(t, strings.TrimSpace(tt.wantStdout), strings.TrimSpace(stdout.String()), "unexpected stdout")
|
||||||
installationNamespace,
|
require.Equal(t, strings.TrimSpace(tt.wantStderr), strings.TrimSpace(stderr.String()), "unexpected stderr")
|
||||||
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) { return pinnipedClient, nil },
|
})
|
||||||
)
|
}
|
||||||
r.EqualError(err, "stat ./testdata/this-file-does-not-exist.yaml: no such file or directory")
|
|
||||||
r.Empty(warningsBuffer.String())
|
|
||||||
r.Empty(outputBuffer.String())
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
when("the kubeconfig path parameter is empty", func() {
|
|
||||||
it.Before(func() {
|
|
||||||
// Note that this is technically polluting other parallel tests in this file, but other tests
|
|
||||||
// are always specifying the kubeconfigPathOverride parameter, so they're not actually looking
|
|
||||||
// at the value of this environment variable.
|
|
||||||
r.NoError(os.Setenv("KUBECONFIG", "./testdata/kubeconfig.yaml"))
|
|
||||||
})
|
|
||||||
|
|
||||||
it.After(func() {
|
|
||||||
r.NoError(os.Unsetenv("KUBECONFIG"))
|
|
||||||
})
|
|
||||||
|
|
||||||
it("falls back to using the KUBECONFIG env var to find the kubeconfig file", func() {
|
|
||||||
kubeClientCreatorFuncWasCalled := false
|
|
||||||
err := getKubeConfig(outputBuffer,
|
|
||||||
warningsBuffer,
|
|
||||||
"some-token",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
installationNamespace,
|
|
||||||
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) {
|
|
||||||
kubeClientCreatorFuncWasCalled = true
|
|
||||||
r.Equal("https://fake-server-url-value", restConfig.Host)
|
|
||||||
r.Equal("fake-certificate-authority-data-value", string(restConfig.CAData))
|
|
||||||
return pinnipedClient, nil
|
|
||||||
},
|
|
||||||
)
|
|
||||||
r.NoError(err)
|
|
||||||
r.True(kubeClientCreatorFuncWasCalled)
|
|
||||||
|
|
||||||
r.Empty(warningsBuffer.String())
|
|
||||||
r.Equal(expectedKubeconfigYAML(
|
|
||||||
base64.StdEncoding.EncodeToString([]byte("fake-certificate-authority-data-value")),
|
|
||||||
"https://fake-server-url-value",
|
|
||||||
fullPathToSelf,
|
|
||||||
"some-token",
|
|
||||||
"https://fake-server-url-value",
|
|
||||||
"fake-certificate-authority-data-value",
|
|
||||||
installationNamespace,
|
|
||||||
), outputBuffer.String())
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
when("the wrong pinniped namespace is passed in", func() {
|
|
||||||
it("returns an error", func() {
|
|
||||||
kubeClientCreatorFuncWasCalled := false
|
|
||||||
err := getKubeConfig(outputBuffer,
|
|
||||||
warningsBuffer,
|
|
||||||
"some-token",
|
|
||||||
"./testdata/kubeconfig.yaml",
|
|
||||||
"",
|
|
||||||
"this-is-the-wrong-namespace",
|
|
||||||
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) {
|
|
||||||
kubeClientCreatorFuncWasCalled = true
|
|
||||||
r.Equal("https://fake-server-url-value", restConfig.Host)
|
|
||||||
r.Equal("fake-certificate-authority-data-value", string(restConfig.CAData))
|
|
||||||
return pinnipedClient, nil
|
|
||||||
},
|
|
||||||
)
|
|
||||||
r.EqualError(err, `No CredentialIssuerConfig was found in namespace "this-is-the-wrong-namespace". Is Pinniped installed on this cluster in namespace "this-is-the-wrong-namespace"?`)
|
|
||||||
r.True(kubeClientCreatorFuncWasCalled)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
when("there is more than one CredentialIssuerConfig is found on the cluster", func() {
|
|
||||||
it.Before(func() {
|
|
||||||
r.NoError(pinnipedClient.Tracker().Add(
|
|
||||||
newCredentialIssuerConfig(
|
|
||||||
"another-cic-name",
|
|
||||||
installationNamespace,
|
|
||||||
"https://fake-server-url-value",
|
|
||||||
"fake-certificate-authority-data-value",
|
|
||||||
),
|
|
||||||
))
|
|
||||||
})
|
|
||||||
|
|
||||||
it("returns an error", func() {
|
|
||||||
kubeClientCreatorFuncWasCalled := false
|
|
||||||
err := getKubeConfig(outputBuffer,
|
|
||||||
warningsBuffer,
|
|
||||||
"some-token",
|
|
||||||
"./testdata/kubeconfig.yaml",
|
|
||||||
"",
|
|
||||||
installationNamespace,
|
|
||||||
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) {
|
|
||||||
kubeClientCreatorFuncWasCalled = true
|
|
||||||
r.Equal("https://fake-server-url-value", restConfig.Host)
|
|
||||||
r.Equal("fake-certificate-authority-data-value", string(restConfig.CAData))
|
|
||||||
return pinnipedClient, nil
|
|
||||||
},
|
|
||||||
)
|
|
||||||
r.EqualError(err, `More than one CredentialIssuerConfig was found in namespace "some-namespace"`)
|
|
||||||
r.True(kubeClientCreatorFuncWasCalled)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
when("the CredentialIssuerConfig is found on the cluster with a configuration that does not match the existing kubeconfig", func() {
|
|
||||||
when("the Server doesn't match", func() {
|
|
||||||
it.Before(func() {
|
|
||||||
r.NoError(pinnipedClient.Tracker().Add(
|
|
||||||
newCredentialIssuerConfig(
|
|
||||||
"some-cic-name",
|
|
||||||
installationNamespace,
|
|
||||||
"non-matching-pinniped-server-url",
|
|
||||||
"fake-certificate-authority-data-value",
|
|
||||||
),
|
|
||||||
))
|
|
||||||
})
|
|
||||||
|
|
||||||
it("writes the kubeconfig to the given writer using the values found in the local kubeconfig and issues a warning", func() {
|
|
||||||
kubeClientCreatorFuncWasCalled := false
|
|
||||||
err := getKubeConfig(outputBuffer,
|
|
||||||
warningsBuffer,
|
|
||||||
"some-token",
|
|
||||||
"./testdata/kubeconfig.yaml",
|
|
||||||
"",
|
|
||||||
installationNamespace,
|
|
||||||
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) {
|
|
||||||
kubeClientCreatorFuncWasCalled = true
|
|
||||||
r.Equal("https://fake-server-url-value", restConfig.Host)
|
|
||||||
r.Equal("fake-certificate-authority-data-value", string(restConfig.CAData))
|
|
||||||
return pinnipedClient, nil
|
|
||||||
},
|
|
||||||
)
|
|
||||||
r.NoError(err)
|
|
||||||
r.True(kubeClientCreatorFuncWasCalled)
|
|
||||||
|
|
||||||
r.Equal(
|
|
||||||
"WARNING: Server and certificate authority did not match between local kubeconfig and Pinniped's CredentialIssuerConfig on the cluster. Using local kubeconfig values.\n",
|
|
||||||
warningsBuffer.String(),
|
|
||||||
)
|
|
||||||
r.Equal(expectedKubeconfigYAML(
|
|
||||||
base64.StdEncoding.EncodeToString([]byte("fake-certificate-authority-data-value")),
|
|
||||||
"https://fake-server-url-value",
|
|
||||||
fullPathToSelf,
|
|
||||||
"some-token",
|
|
||||||
"https://fake-server-url-value",
|
|
||||||
"fake-certificate-authority-data-value",
|
|
||||||
installationNamespace,
|
|
||||||
), outputBuffer.String())
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
when("the CA doesn't match", func() {
|
|
||||||
it.Before(func() {
|
|
||||||
r.NoError(pinnipedClient.Tracker().Add(
|
|
||||||
newCredentialIssuerConfig(
|
|
||||||
"some-cic-name",
|
|
||||||
installationNamespace,
|
|
||||||
"https://fake-server-url-value",
|
|
||||||
"non-matching-certificate-authority-data-value",
|
|
||||||
),
|
|
||||||
))
|
|
||||||
})
|
|
||||||
|
|
||||||
it("writes the kubeconfig to the given writer using the values found in the local kubeconfig and issues a warning", func() {
|
|
||||||
kubeClientCreatorFuncWasCalled := false
|
|
||||||
err := getKubeConfig(outputBuffer,
|
|
||||||
warningsBuffer,
|
|
||||||
"some-token",
|
|
||||||
"./testdata/kubeconfig.yaml",
|
|
||||||
"",
|
|
||||||
installationNamespace,
|
|
||||||
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) {
|
|
||||||
kubeClientCreatorFuncWasCalled = true
|
|
||||||
r.Equal("https://fake-server-url-value", restConfig.Host)
|
|
||||||
r.Equal("fake-certificate-authority-data-value", string(restConfig.CAData))
|
|
||||||
return pinnipedClient, nil
|
|
||||||
},
|
|
||||||
)
|
|
||||||
r.NoError(err)
|
|
||||||
r.True(kubeClientCreatorFuncWasCalled)
|
|
||||||
|
|
||||||
r.Equal(
|
|
||||||
"WARNING: Server and certificate authority did not match between local kubeconfig and Pinniped's CredentialIssuerConfig on the cluster. Using local kubeconfig values.\n",
|
|
||||||
warningsBuffer.String(),
|
|
||||||
)
|
|
||||||
r.Equal(expectedKubeconfigYAML(
|
|
||||||
base64.StdEncoding.EncodeToString([]byte("fake-certificate-authority-data-value")),
|
|
||||||
"https://fake-server-url-value",
|
|
||||||
fullPathToSelf,
|
|
||||||
"some-token",
|
|
||||||
"https://fake-server-url-value",
|
|
||||||
"fake-certificate-authority-data-value",
|
|
||||||
installationNamespace,
|
|
||||||
), outputBuffer.String())
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
when("the CredentialIssuerConfig is found on the cluster with an empty KubeConfigInfo", func() {
|
|
||||||
it.Before(func() {
|
|
||||||
r.NoError(pinnipedClient.Tracker().Add(
|
|
||||||
&configv1alpha1.CredentialIssuerConfig{
|
|
||||||
TypeMeta: metav1.TypeMeta{
|
|
||||||
Kind: "CredentialIssuerConfig",
|
|
||||||
APIVersion: configv1alpha1.SchemeGroupVersion.String(),
|
|
||||||
},
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "pinniped-config",
|
|
||||||
Namespace: installationNamespace,
|
|
||||||
},
|
|
||||||
Status: configv1alpha1.CredentialIssuerConfigStatus{},
|
|
||||||
},
|
|
||||||
))
|
|
||||||
})
|
|
||||||
|
|
||||||
it("returns an error", func() {
|
|
||||||
kubeClientCreatorFuncWasCalled := false
|
|
||||||
err := getKubeConfig(outputBuffer,
|
|
||||||
warningsBuffer,
|
|
||||||
"some-token",
|
|
||||||
"./testdata/kubeconfig.yaml",
|
|
||||||
"",
|
|
||||||
installationNamespace,
|
|
||||||
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) {
|
|
||||||
kubeClientCreatorFuncWasCalled = true
|
|
||||||
r.Equal("https://fake-server-url-value", restConfig.Host)
|
|
||||||
r.Equal("fake-certificate-authority-data-value", string(restConfig.CAData))
|
|
||||||
return pinnipedClient, nil
|
|
||||||
},
|
|
||||||
)
|
|
||||||
r.True(kubeClientCreatorFuncWasCalled)
|
|
||||||
r.EqualError(err, `CredentialIssuerConfig "pinniped-config" was missing KubeConfigInfo`)
|
|
||||||
r.Empty(warningsBuffer.String())
|
|
||||||
r.Empty(outputBuffer.String())
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
when("the CredentialIssuerConfig does not exist on the cluster", func() {
|
|
||||||
it("returns an error", func() {
|
|
||||||
kubeClientCreatorFuncWasCalled := false
|
|
||||||
err := getKubeConfig(outputBuffer,
|
|
||||||
warningsBuffer,
|
|
||||||
"some-token",
|
|
||||||
"./testdata/kubeconfig.yaml",
|
|
||||||
"",
|
|
||||||
installationNamespace,
|
|
||||||
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) {
|
|
||||||
kubeClientCreatorFuncWasCalled = true
|
|
||||||
r.Equal("https://fake-server-url-value", restConfig.Host)
|
|
||||||
r.Equal("fake-certificate-authority-data-value", string(restConfig.CAData))
|
|
||||||
return pinnipedClient, nil
|
|
||||||
},
|
|
||||||
)
|
|
||||||
r.True(kubeClientCreatorFuncWasCalled)
|
|
||||||
r.EqualError(err, `No CredentialIssuerConfig was found in namespace "some-namespace". Is Pinniped installed on this cluster in namespace "some-namespace"?`)
|
|
||||||
r.Empty(warningsBuffer.String())
|
|
||||||
r.Empty(outputBuffer.String())
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
when("there is an error while getting the CredentialIssuerConfig from the cluster", func() {
|
|
||||||
it("returns an error", func() {
|
|
||||||
err := getKubeConfig(outputBuffer,
|
|
||||||
warningsBuffer,
|
|
||||||
"some-token",
|
|
||||||
"./testdata/kubeconfig.yaml",
|
|
||||||
"",
|
|
||||||
installationNamespace,
|
|
||||||
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) {
|
|
||||||
return nil, fmt.Errorf("some error getting CredentialIssuerConfig")
|
|
||||||
},
|
|
||||||
)
|
|
||||||
r.EqualError(err, "some error getting CredentialIssuerConfig")
|
|
||||||
r.Empty(warningsBuffer.String())
|
|
||||||
r.Empty(outputBuffer.String())
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}, spec.Parallel(), spec.Report(report.Terminal{}))
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user