This repository has been archived by the owner on Dec 21, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: Introduce needed methods before deprecating kubernetes-utils (#…
…477) * chore: Introduce needed methods before deprecating kubernetes-utils Signed-off-by: odubajDT <[email protected]> * move to correct folder Signed-off-by: odubajDT <[email protected]> * fix Signed-off-by: odubajDT <[email protected]> * restructuring Signed-off-by: odubajDT <[email protected]> * go mod tidy Signed-off-by: odubajDT <[email protected]> * restructure Signed-off-by: odubajDT <[email protected]> * refactor code Signed-off-by: odubajDT <[email protected]> * remove unneeded methods Signed-off-by: odubajDT <[email protected]> * first version of tests Signed-off-by: odubajDT <[email protected]> * covered by tests Signed-off-by: odubajDT <[email protected]> * missing comments Signed-off-by: odubajDT <[email protected]> * polish Signed-off-by: odubajDT <[email protected]> * fix Signed-off-by: odubajDT <[email protected]> * pr review Signed-off-by: odubajDT <[email protected]>
- Loading branch information
Showing
10 changed files
with
1,058 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package kubeutils | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/client-go/kubernetes" | ||
) | ||
|
||
// APITokenProvider wraps around the kubernetes interface to enhance testability | ||
type APITokenProvider struct { | ||
clientSet kubernetes.Interface | ||
} | ||
|
||
// NewAPITokenProvider creates new APITokenProvider | ||
func NewAPITokenProvider(useInClusterConfig bool) (*APITokenProvider, error) { | ||
clientSet, err := GetClientSet(useInClusterConfig) | ||
if err != nil { | ||
return nil, fmt.Errorf("could not create APITokenProvider: %s", err.Error()) | ||
} | ||
return &APITokenProvider{clientSet: clientSet}, nil | ||
} | ||
|
||
// GetKeptnAPITokenFromSecret returns the `keptn-api-token` data secret from Keptn Installation | ||
func (a *APITokenProvider) GetKeptnAPITokenFromSecret(ctx context.Context, namespace string, secretName string) (string, error) { | ||
keptnSecret, err := a.clientSet.CoreV1().Secrets(namespace).Get(ctx, secretName, metav1.GetOptions{}) | ||
if err != nil { | ||
return "", err | ||
} | ||
if apitoken, ok := keptnSecret.Data["keptn-api-token"]; ok { | ||
return string(apitoken), nil | ||
} | ||
return "", fmt.Errorf("data 'keptn-api-token' not found") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package kubeutils | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
v1 "k8s.io/api/core/v1" | ||
"k8s.io/apimachinery/pkg/runtime" | ||
"k8s.io/client-go/kubernetes/fake" | ||
k8stesting "k8s.io/client-go/testing" | ||
) | ||
|
||
func TestAPITokenProvider_GetKeptnAPITokenFromSecret_FailClientSet(t *testing.T) { | ||
kubernetes := fake.NewSimpleClientset() | ||
kubernetes.Fake.PrependReactor("get", "secrets", func(action k8stesting.Action) (handled bool, ret runtime.Object, err error) { | ||
return true, nil, fmt.Errorf("error retrieving kubernetes secret") | ||
}) | ||
apiTokenProvider := &APITokenProvider{clientSet: kubernetes} | ||
res, err := apiTokenProvider.GetKeptnAPITokenFromSecret(context.TODO(), "keptn", "secret") | ||
require.Equal(t, "", res) | ||
require.Error(t, err) | ||
require.Equal(t, fmt.Errorf("error retrieving kubernetes secret"), err) | ||
|
||
} | ||
|
||
func TestAPITokenProvider_GetKeptnAPITokenFromSecret_InvalidData(t *testing.T) { | ||
kubernetes := fake.NewSimpleClientset() | ||
kubernetes.Fake.PrependReactor("get", "secrets", func(action k8stesting.Action) (handled bool, ret runtime.Object, err error) { | ||
return true, &v1.Secret{Data: map[string][]byte{"some-data": []byte("token")}}, nil | ||
}) | ||
apiTokenProvider := &APITokenProvider{clientSet: kubernetes} | ||
res, err := apiTokenProvider.GetKeptnAPITokenFromSecret(context.TODO(), "keptn", "secret") | ||
require.Equal(t, "", res) | ||
require.Error(t, err) | ||
require.Equal(t, fmt.Errorf("data 'keptn-api-token' not found"), err) | ||
|
||
} | ||
|
||
func TestAPITokenProvider_GetKeptnAPITokenFromSecret_ValidData(t *testing.T) { | ||
kubernetes := fake.NewSimpleClientset() | ||
kubernetes.Fake.PrependReactor("get", "secrets", func(action k8stesting.Action) (handled bool, ret runtime.Object, err error) { | ||
return true, &v1.Secret{Data: map[string][]byte{"keptn-api-token": []byte("token")}}, nil | ||
}) | ||
apiTokenProvider := &APITokenProvider{clientSet: kubernetes} | ||
res, err := apiTokenProvider.GetKeptnAPITokenFromSecret(context.TODO(), "keptn", "secret") | ||
require.Equal(t, "token", res) | ||
require.Nil(t, err) | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package kubeutils | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/client-go/kubernetes" | ||
) | ||
|
||
// KeptnEndpointProvider wraps around the kubernetes interface to enhance testability | ||
type KeptnEndpointProvider struct { | ||
clientSet kubernetes.Interface | ||
} | ||
|
||
// NewKeptnEndpointProvider creates new KeptnEndpointProvider | ||
func NewKeptnEndpointProvider(useInClusterConfig bool) (*KeptnEndpointProvider, error) { | ||
clientSet, err := GetClientSet(useInClusterConfig) | ||
if err != nil { | ||
return nil, fmt.Errorf("could not create KeptnEndpointProvider: %s", err.Error()) | ||
} | ||
return &KeptnEndpointProvider{clientSet: clientSet}, nil | ||
} | ||
|
||
// GetKeptnEndpointFromIngress returns the host of ingress object Keptn Installation | ||
func (a *KeptnEndpointProvider) GetKeptnEndpointFromIngress(ctx context.Context, namespace string, ingressName string) (string, error) { | ||
keptnIngress, err := a.clientSet.ExtensionsV1beta1().Ingresses(namespace).Get(ctx, ingressName, metav1.GetOptions{}) | ||
if err != nil { | ||
return "", err | ||
} | ||
if keptnIngress.Spec.Rules != nil { | ||
return keptnIngress.Spec.Rules[0].Host, nil | ||
} | ||
return "", fmt.Errorf("cannot retrieve ingress data: ingress rule does not exist") | ||
} | ||
|
||
// GetKeptnEndpointFromService returns the loadbalancer service IP from Keptn Installation | ||
func (a *KeptnEndpointProvider) GetKeptnEndpointFromService(ctx context.Context, namespace string, serviceName string) (string, error) { | ||
keptnService, err := a.clientSet.CoreV1().Services(namespace).Get(ctx, serviceName, metav1.GetOptions{}) | ||
if err != nil { | ||
return "", err | ||
} | ||
switch keptnService.Spec.Type { | ||
case "LoadBalancer": | ||
if len(keptnService.Status.LoadBalancer.Ingress) > 0 { | ||
return keptnService.Status.LoadBalancer.Ingress[0].IP, nil | ||
} | ||
return "", fmt.Errorf("Loadbalancer IP isn't found") | ||
default: | ||
return "", fmt.Errorf("it doesn't support ClusterIP & NodePort type service for fetching endpoint automatically") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
package kubeutils | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
v1 "k8s.io/api/core/v1" | ||
"k8s.io/api/extensions/v1beta1" | ||
"k8s.io/apimachinery/pkg/runtime" | ||
"k8s.io/client-go/kubernetes/fake" | ||
k8stesting "k8s.io/client-go/testing" | ||
) | ||
|
||
func TestKeptnEndpointProvider_GetKeptnEndpointFromIngress_FailClientSet(t *testing.T) { | ||
kubernetes := fake.NewSimpleClientset() | ||
kubernetes.Fake.PrependReactor("get", "ingresses", func(action k8stesting.Action) (handled bool, ret runtime.Object, err error) { | ||
return true, nil, fmt.Errorf("error retrieving kubernetes ingress") | ||
}) | ||
keptnEndpointProvider := &KeptnEndpointProvider{clientSet: kubernetes} | ||
res, err := keptnEndpointProvider.GetKeptnEndpointFromIngress(context.TODO(), "keptn", "ingress") | ||
require.Equal(t, "", res) | ||
require.Error(t, err) | ||
require.Equal(t, fmt.Errorf("error retrieving kubernetes ingress"), err) | ||
} | ||
|
||
func TestKeptnEndpointProvider_GetKeptnEndpointFromIngress_Invalid(t *testing.T) { | ||
kubernetes := fake.NewSimpleClientset() | ||
kubernetes.Fake.PrependReactor("get", "ingresses", func(action k8stesting.Action) (handled bool, ret runtime.Object, err error) { | ||
return true, &v1beta1.Ingress{Spec: v1beta1.IngressSpec{}}, nil | ||
}) | ||
keptnEndpointProvider := &KeptnEndpointProvider{clientSet: kubernetes} | ||
res, err := keptnEndpointProvider.GetKeptnEndpointFromIngress(context.TODO(), "keptn", "ingress") | ||
require.Equal(t, "", res) | ||
require.Error(t, err) | ||
require.Equal(t, fmt.Errorf("cannot retrieve ingress data: ingress rule does not exist"), err) | ||
} | ||
|
||
func TestKeptnEndpointProvider_GetKeptnEndpointFromIngress_Valid(t *testing.T) { | ||
kubernetes := fake.NewSimpleClientset() | ||
kubernetes.Fake.PrependReactor("get", "ingresses", func(action k8stesting.Action) (handled bool, ret runtime.Object, err error) { | ||
return true, &v1beta1.Ingress{ | ||
Spec: v1beta1.IngressSpec{ | ||
Rules: []v1beta1.IngressRule{ | ||
{ | ||
Host: "1.1.1.1", | ||
}, | ||
}, | ||
}, | ||
}, nil | ||
}) | ||
keptnEndpointProvider := &KeptnEndpointProvider{clientSet: kubernetes} | ||
res, err := keptnEndpointProvider.GetKeptnEndpointFromIngress(context.TODO(), "keptn", "api-keptn-ingress") | ||
require.Equal(t, "1.1.1.1", res) | ||
require.Nil(t, err) | ||
} | ||
|
||
func TestKeptnEndpointProvider_GetKeptnEndpointFromService_FailClientSet(t *testing.T) { | ||
kubernetes := fake.NewSimpleClientset() | ||
kubernetes.Fake.PrependReactor("get", "services", func(action k8stesting.Action) (handled bool, ret runtime.Object, err error) { | ||
return true, nil, fmt.Errorf("error retrieving kubernetes service") | ||
}) | ||
keptnEndpointProvider := &KeptnEndpointProvider{clientSet: kubernetes} | ||
res, err := keptnEndpointProvider.GetKeptnEndpointFromService(context.TODO(), "keptn", "service1") | ||
require.Equal(t, "", res) | ||
require.Error(t, err) | ||
require.Equal(t, fmt.Errorf("error retrieving kubernetes service"), err) | ||
} | ||
|
||
func TestKeptnEndpointProvider_GetKeptnEndpointFromService_NoLoadBalancer(t *testing.T) { | ||
kubernetes := fake.NewSimpleClientset() | ||
kubernetes.Fake.PrependReactor("get", "services", func(action k8stesting.Action) (handled bool, ret runtime.Object, err error) { | ||
return true, &v1.Service{Spec: v1.ServiceSpec{Type: v1.ServiceTypeClusterIP}}, nil | ||
}) | ||
keptnEndpointProvider := &KeptnEndpointProvider{clientSet: kubernetes} | ||
res, err := keptnEndpointProvider.GetKeptnEndpointFromService(context.TODO(), "keptn22", "service") | ||
require.Equal(t, "", res) | ||
require.Error(t, err) | ||
require.Equal(t, fmt.Errorf("it doesn't support ClusterIP & NodePort type service for fetching endpoint automatically"), err) | ||
} | ||
|
||
func TestKeptnEndpointProvider_GetKeptnEndpointFromService_LoadBalancerNoIngress(t *testing.T) { | ||
kubernetes := fake.NewSimpleClientset() | ||
kubernetes.Fake.PrependReactor("get", "services", func(action k8stesting.Action) (handled bool, ret runtime.Object, err error) { | ||
return true, &v1.Service{ | ||
Spec: v1.ServiceSpec{ | ||
Type: v1.ServiceTypeLoadBalancer}, | ||
Status: v1.ServiceStatus{ | ||
LoadBalancer: v1.LoadBalancerStatus{}, | ||
}, | ||
}, nil | ||
}) | ||
keptnEndpointProvider := &KeptnEndpointProvider{clientSet: kubernetes} | ||
res, err := keptnEndpointProvider.GetKeptnEndpointFromService(context.TODO(), "keptn22", "service") | ||
require.Equal(t, "", res) | ||
require.Error(t, err) | ||
require.Equal(t, fmt.Errorf("Loadbalancer IP isn't found"), err) | ||
} | ||
|
||
func TestKeptnEndpointProvider_GetKeptnEndpointFromService_LoadBalancerIngressIP(t *testing.T) { | ||
kubernetes := fake.NewSimpleClientset() | ||
kubernetes.Fake.PrependReactor("get", "services", func(action k8stesting.Action) (handled bool, ret runtime.Object, err error) { | ||
return true, &v1.Service{ | ||
Spec: v1.ServiceSpec{Type: v1.ServiceTypeLoadBalancer}, | ||
Status: v1.ServiceStatus{ | ||
LoadBalancer: v1.LoadBalancerStatus{ | ||
Ingress: []v1.LoadBalancerIngress{ | ||
{IP: "1.1.1.1"}, | ||
}, | ||
}, | ||
}, | ||
}, nil | ||
}) | ||
keptnEndpointProvider := &KeptnEndpointProvider{clientSet: kubernetes} | ||
res, err := keptnEndpointProvider.GetKeptnEndpointFromService(context.TODO(), "keptn22", "service") | ||
require.Equal(t, "1.1.1.1", res) | ||
require.Nil(t, err) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package kubeutils | ||
|
||
import ( | ||
"os" | ||
"path/filepath" | ||
|
||
"k8s.io/client-go/kubernetes" | ||
|
||
"github.com/keptn/go-utils/pkg/common/fileutils" | ||
|
||
"k8s.io/client-go/rest" | ||
"k8s.io/client-go/tools/clientcmd" | ||
) | ||
|
||
// GetClientSet returns the kubernetes Clientset | ||
func GetClientSet(useInClusterConfig bool) (*kubernetes.Clientset, error) { | ||
|
||
var config *rest.Config | ||
var err error | ||
if useInClusterConfig { | ||
config, err = rest.InClusterConfig() | ||
} else { | ||
var kubeconfig string | ||
if os.Getenv("KUBECONFIG") != "" { | ||
kubeconfig = fileutils.ExpandTilde(os.Getenv("KUBECONFIG")) | ||
} else { | ||
kubeconfig = filepath.Join( | ||
fileutils.UserHomeDir(), ".kube", "config", | ||
) | ||
} | ||
config, err = clientcmd.BuildConfigFromFlags("", kubeconfig) | ||
} | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return kubernetes.NewForConfig(config) | ||
} |
Oops, something went wrong.