Skip to content

Commit

Permalink
feat: Add support for in-cluster auth
Browse files Browse the repository at this point in the history
Closes #223
  • Loading branch information
stepanstipl committed Nov 18, 2021
1 parent 4561085 commit 9b16f69
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 53 deletions.
11 changes: 5 additions & 6 deletions pkg/collector/cluster_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package collector

import (
"encoding/json"
"io/ioutil"
"path/filepath"
"strings"
"testing"

"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
Expand All @@ -16,14 +16,13 @@ import (

func TestNewClusterCollectorBadPath(t *testing.T) {
testOpts := ClusterOpts{Kubeconfig: "bad path"}
result, funcErr := NewClusterCollector(&testOpts, []string{})
_, err := NewClusterCollector(&testOpts, []string{})

if funcErr.Error() != "invalid configuration: no configuration has been provided" {
out, err := json.Marshal(result)
if !strings.Contains(err.Error(), "no configuration has been provided") {
if err != nil {
t.Errorf("Should have errored with invalid configuration error instead got: %s", string(out))
t.Errorf("Should have errored with invalid configuration error instead got: %s", err)
} else {
t.Errorf("Should have errored instead got: %s", funcErr)
t.Errorf("Should have failed but succeeded")
}
}
}
Expand Down
50 changes: 34 additions & 16 deletions pkg/collector/kube.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,30 +21,48 @@ func newKubeCollector(kubeconfig string, kubecontext string, discoveryClient dis
if discoveryClient != nil {
col.discoveryClient = discoveryClient
} else {
pathOptions := clientcmd.NewDefaultPathOptions()
if kubeconfig != "" {
pathOptions.GlobalFile = kubeconfig
var err error
if col.restConfig, err = newClientRestConfig(kubeconfig, kubecontext, rest.InClusterConfig); err != nil {
return nil, fmt.Errorf("failed to assemble client config: %w", err)
}

config, err := pathOptions.GetStartingConfig()

configOverrides := clientcmd.ConfigOverrides{}
if kubecontext != "" {
configOverrides.CurrentContext = kubecontext
if discoveryClient, err = discovery.NewDiscoveryClientForConfig(col.restConfig); err != nil {
return nil, fmt.Errorf("failed to create client: %w", err)
}
}

clientConfig := clientcmd.NewDefaultClientConfig(*config, &configOverrides)
col.restConfig, err = clientConfig.ClientConfig()
if err != nil {
return nil, err
}
return col, nil
}

if col.discoveryClient, err = discovery.NewDiscoveryClientForConfig(col.restConfig); err != nil {
return nil, err
func newClientRestConfig(kubeconfig string, kubecontext string, inClusterFn func() (*rest.Config, error)) (*rest.Config, error) {
if kubeconfig == "" {
if restConfig, err := inClusterFn(); err == nil {
return restConfig, nil
}
}

return col, nil
pathOptions := clientcmd.NewDefaultPathOptions()
if kubeconfig != "" {
pathOptions.GlobalFile = kubeconfig
}

config, err := pathOptions.GetStartingConfig()
if err != nil {
return nil, err
}

configOverrides := clientcmd.ConfigOverrides{}
if kubecontext != "" {
configOverrides.CurrentContext = kubecontext
}

clientConfig := clientcmd.NewDefaultClientConfig(*config, &configOverrides)
restConfig, err := clientConfig.ClientConfig()
if err != nil {
return nil, err
}

return restConfig, nil
}

func (c *kubeCollector) GetServerVersion() (*judge.Version, error) {
Expand Down
104 changes: 73 additions & 31 deletions pkg/collector/kube_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package collector

import (
"k8s.io/client-go/rest"
"os"
"path/filepath"
"testing"
Expand Down Expand Up @@ -33,36 +34,6 @@ func TestNewKubeCollectorError(t *testing.T) {
}
}

func TestNewKubeCollectorWithKubeconfigPath(t *testing.T) {
_, err := newKubeCollector("../../fixtures/kube.config.basic", "", nil)
if err != nil {
t.Fatalf("Failed with: %s", err)
}
}

func TestNewKubeCollectorMultipleFiles(t *testing.T) {
kcEnvVar := "KUBECONFIG"
oldKubeConfig, oldSet := os.LookupEnv(kcEnvVar)

if err := os.Setenv(kcEnvVar, "../../fixtures/kube.config.empty:../../fixtures/kube.config.basic"); err != nil {
t.Fatalf("Failed so set %s env variable for test: %s", kcEnvVar, err)
}

if _, err := newKubeCollector("", "", nil); err != nil {
t.Fatalf("Failed with: %s", err)
}

var err error
if oldSet {
err = os.Setenv(kcEnvVar, oldKubeConfig)
} else {
err = os.Unsetenv(kcEnvVar)
}
if err != nil {
t.Fatalf("Failed so reset %s env variable after test: %s", kcEnvVar, err)
}
}

func TestGetServerVersion(t *testing.T) {
gitVersion := "v1.2.3"
expectedVersion, _ := goversion.NewVersion(gitVersion)
Expand Down Expand Up @@ -105,12 +76,83 @@ func TestContext(t *testing.T) {
func TestContextMissing(t *testing.T) {
expectedContext := "non-existent"

_, err := newKubeCollector("../../fixtures/kube.config.context", expectedContext, nil)
_, err := newKubeCollector(filepath.Join(FIXTURES_DIR, "kube.config.context"), expectedContext, nil)
if err == nil {
t.Fatalf("Expected to fail when uisng non-existent context: %s", expectedContext)
}
}

func TestNewClientRestConfig(t *testing.T) {
_, err := newClientRestConfig("", "", rest.InClusterConfig)
if err != nil {
t.Fatalf("Failed with: %s", err)
}
}

func TestNewClientRestConfigError(t *testing.T) {
_, err := newClientRestConfig("does-not-exist", "", rest.InClusterConfig)

if err == nil {
t.Errorf("Expected to fail with non-existent kubeconfig")
}
}

func TestNewClientRestConfigWithKubeconfigPath(t *testing.T) {
_, err := newClientRestConfig(filepath.Join(FIXTURES_DIR, "kube.config.basic"), "", rest.InClusterConfig)
if err != nil {
t.Fatalf("Failed with: %s", err)
}
}

func TestNewClientRestConfigMultipleFiles(t *testing.T) {
env := setupEnv(t, map[string]string{
"KUBECONFIG": filepath.Join(FIXTURES_DIR, "kube.config.empty") + ":" + filepath.Join(FIXTURES_DIR, "kube.config.basic"),
})
defer env.reset()

if _, err := newClientRestConfig("", "", rest.InClusterConfig); err != nil {
t.Fatalf("Failed with: %s", err)
}
}

func TestNewClientRestConfigWithContext(t *testing.T) {
expectedContext := "test-context"
expectedHost := "https://test-cluster"

config, err := newClientRestConfig(filepath.Join(FIXTURES_DIR, "kube.config.context"), expectedContext, rest.InClusterConfig)
if err != nil {
t.Fatalf("Failed to create kubeCollector from fake client with context %s: %s", expectedContext, err)
}

if config.Host != expectedHost {
t.Fatalf("Expected host from context %s to be: %s, got %s instead", expectedContext, expectedHost, config.Host)
}
}

func TestNewClientRestConfigContextMissing(t *testing.T) {
expectedContext := "non-existent"

_, err := newClientRestConfig(filepath.Join(FIXTURES_DIR, "kube.config.context"), expectedContext, rest.InClusterConfig)
if err == nil {
t.Fatalf("Expected to fail when uisng non-existent context: %s", expectedContext)
}
}

func TestNewClientRestConfigInCluster(t *testing.T) {
expectedHost := "test-host"
inClusterFn := func() (*rest.Config, error) {
return &rest.Config{Host: expectedHost}, nil
}

cfg, err := newClientRestConfig("", "", inClusterFn)
if err != nil {
t.Fatalf("Failed to create in-cluster config: %s", err)
}
if cfg.Host != expectedHost {
t.Fatalf("Expected %s host, instead got: %s", expectedHost, cfg.Host)
}
}

type env struct {
initialVals map[string]string
initialState map[string]bool
Expand Down

0 comments on commit 9b16f69

Please sign in to comment.