summaryrefslogtreecommitdiff
path: root/pkg/kube
diff options
context:
space:
mode:
authorjannfis <jann@mistrust.net>2020-12-30 09:45:48 +0100
committerGitHub <noreply@github.com>2020-12-30 09:45:48 +0100
commit6269c394d6d6454d08b9a2dd18c6ba24acd1e461 (patch)
tree92f438f65ffead8bacc5b03112f05f4a73191fb5 /pkg/kube
parent2efdbca23c61554c3b2bd5fea4e26083e123c562 (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.go77
-rw-r--r--pkg/kube/kubernetes_test.go73
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)
+ })
+}