diff options
| author | jannfis <jann@mistrust.net> | 2020-12-30 09:45:48 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-12-30 09:45:48 +0100 |
| commit | 6269c394d6d6454d08b9a2dd18c6ba24acd1e461 (patch) | |
| tree | 92f438f65ffead8bacc5b03112f05f4a73191fb5 /pkg/kube | |
| parent | 2efdbca23c61554c3b2bd5fea4e26083e123c562 (diff) | |
refactor: Rename package client to kube (#135)
Signed-off-by: jannfis <jann@mistrust.net>
Diffstat (limited to 'pkg/kube')
| -rw-r--r-- | pkg/kube/kubernetes.go | 77 | ||||
| -rw-r--r-- | pkg/kube/kubernetes_test.go | 73 |
2 files changed, 150 insertions, 0 deletions
diff --git a/pkg/kube/kubernetes.go b/pkg/kube/kubernetes.go new file mode 100644 index 0000000..9b5fcc9 --- /dev/null +++ b/pkg/kube/kubernetes.go @@ -0,0 +1,77 @@ +package kube + +// Kubernetes client related code + +import ( + "context" + "fmt" + + "github.com/argoproj-labs/argocd-image-updater/pkg/metrics" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" +) + +type KubernetesClient struct { + Clientset kubernetes.Interface + Context context.Context +} + +func NewKubernetesClient(ctx context.Context, client kubernetes.Interface) *KubernetesClient { + kc := &KubernetesClient{} + kc.Context = ctx + kc.Clientset = client + return kc +} + +// NewKubernetesClient creates a new Kubernetes client object from given +// configuration file. If configuration file is the empty string, in-cluster +// client will be created. +func NewKubernetesClientFromConfig(ctx context.Context, kubeconfig string) (*KubernetesClient, error) { + var config *rest.Config + var err error + + if kubeconfig != "" { + config, err = clientcmd.BuildConfigFromFlags("", kubeconfig) + } else { + config, err = rest.InClusterConfig() + } + if err != nil { + return nil, err + } + + clientset, err := kubernetes.NewForConfig(config) + if err != nil { + return nil, err + } + + return NewKubernetesClient(ctx, clientset), nil +} + +// GetSecretData returns the raw data from named K8s secret in given namespace +func (client *KubernetesClient) GetSecretData(namespace string, secretName string) (map[string][]byte, error) { + secret, err := client.Clientset.CoreV1().Secrets(namespace).Get(client.Context, secretName, v1.GetOptions{}) + metrics.Clients().IncreaseK8sClientRequest(1) + if err != nil { + metrics.Clients().IncreaseK8sClientRequest(1) + return nil, err + } + return secret.Data, nil +} + +// GetSecretField returns the value of a field from named K8s secret in given namespace +func (client *KubernetesClient) GetSecretField(namespace string, secretName string, field string) (string, error) { + secret, err := client.GetSecretData(namespace, secretName) + metrics.Clients().IncreaseK8sClientRequest(1) + if err != nil { + metrics.Clients().IncreaseK8sClientRequest(1) + return "", err + } + if data, ok := secret[field]; !ok { + return "", fmt.Errorf("secret '%s/%s' does not have a field '%s'", namespace, secretName, field) + } else { + return string(data), nil + } +} diff --git a/pkg/kube/kubernetes_test.go b/pkg/kube/kubernetes_test.go new file mode 100644 index 0000000..9db9bef --- /dev/null +++ b/pkg/kube/kubernetes_test.go @@ -0,0 +1,73 @@ +package kube + +import ( + "context" + "os" + "testing" + + "github.com/argoproj-labs/argocd-image-updater/test/fake" + "github.com/argoproj-labs/argocd-image-updater/test/fixture" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func Test_NewKubernetesClient(t *testing.T) { + t.Run("Get new K8s client for remote cluster instance", func(t *testing.T) { + client, err := NewKubernetesClientFromConfig(context.TODO(), "../../test/testdata/kubernetes/config") + require.NoError(t, err) + assert.NotNil(t, client) + }) + + t.Run("Get new K8s client for in-cluster instance", func(t *testing.T) { + os.Setenv("KUBERNETES_SERVICE_HOST", "127.0.0.1") + os.Setenv("KUBERNETES_SERVICE_PORT", "6443") + defer os.Setenv("KUBERNETES_SERVICE_HOST", "") + defer os.Setenv("KUBERNETES_SERVICE_PORT", "") + client, err := NewKubernetesClientFromConfig(context.TODO(), "") + // We cannot create /var/run/secrets/kubernetes.io/serviceaccount/token so + // we just assume error and look for that path in error message. + assert.Errorf(t, err, "open /var/run/secrets/kubernetes.io/serviceaccount/token: no such file or directory") + assert.Nil(t, client) + }) +} + +func Test_GetDataFromSecrets(t *testing.T) { + t.Run("Get all data from dummy secret", func(t *testing.T) { + secret := fixture.MustCreateSecretFromFile("../../test/testdata/resources/dummy-secret.json") + clientset := fake.NewFakeClientsetWithResources(secret) + client := &KubernetesClient{Clientset: clientset} + data, err := client.GetSecretData("test-namespace", "test-secret") + require.NoError(t, err) + require.NotNil(t, data) + assert.Len(t, data, 1) + assert.Equal(t, "argocd", string(data["namespace"])) + }) + + t.Run("Get string data from dummy secret existing field", func(t *testing.T) { + secret := fixture.MustCreateSecretFromFile("../../test/testdata/resources/dummy-secret.json") + clientset := fake.NewFakeClientsetWithResources(secret) + client := &KubernetesClient{Clientset: clientset} + data, err := client.GetSecretField("test-namespace", "test-secret", "namespace") + require.NoError(t, err) + assert.Equal(t, "argocd", data) + }) + + t.Run("Get string data from dummy secret non-existing field", func(t *testing.T) { + secret := fixture.MustCreateSecretFromFile("../../test/testdata/resources/dummy-secret.json") + clientset := fake.NewFakeClientsetWithResources(secret) + client := &KubernetesClient{Clientset: clientset} + data, err := client.GetSecretField("test-namespace", "test-secret", "nonexisting") + require.Error(t, err) + require.Empty(t, data) + }) + + t.Run("Get string data from non-existing secret non-existing field", func(t *testing.T) { + secret := fixture.MustCreateSecretFromFile("../../test/testdata/resources/dummy-secret.json") + clientset := fake.NewFakeClientsetWithResources(secret) + client := &KubernetesClient{Clientset: clientset} + data, err := client.GetSecretField("test-namespace", "test", "namespace") + require.Error(t, err) + require.Empty(t, data) + }) +} |
