e2e tests
parent
bd00613e7e
commit
379affe794
|
@ -0,0 +1,187 @@
|
|||
package tests
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/keel-hq/keel/types"
|
||||
|
||||
apps_v1 "k8s.io/api/apps/v1"
|
||||
"k8s.io/api/core/v1"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
var dockerHub0150Webhook = `{
|
||||
"push_data": {
|
||||
"pushed_at": 1497467660,
|
||||
"images": [],
|
||||
"tag": "0.0.15",
|
||||
"pusher": "karolisr"
|
||||
},
|
||||
"repository": {
|
||||
"status": "Active",
|
||||
"description": "",
|
||||
"is_trusted": false,
|
||||
"repo_url": "https://hub.docker.com/r/webhook-demo",
|
||||
"owner": "karolisr",
|
||||
"is_official": false,
|
||||
"is_private": false,
|
||||
"name": "keel",
|
||||
"namespace": "karolisr",
|
||||
"star_count": 0,
|
||||
"comment_count": 0,
|
||||
"date_created": 1497032538,
|
||||
"repo_name": "karolisr/webhook-demo"
|
||||
}
|
||||
}`
|
||||
|
||||
func TestSemverUpdate(t *testing.T) {
|
||||
|
||||
// stop := make(chan struct{})
|
||||
context, cancel := context.WithCancel(context.Background())
|
||||
// defer close(ctx)
|
||||
defer cancel()
|
||||
|
||||
go startKeel(context)
|
||||
|
||||
_, kcs := getKubernetesClient()
|
||||
|
||||
t.Run("UpdateThroughDockerHubWebhook", func(t *testing.T) {
|
||||
|
||||
testNamespace := createNamespaceForTest()
|
||||
defer deleteTestNamespace(testNamespace)
|
||||
|
||||
dep := &apps_v1.Deployment{
|
||||
meta_v1.TypeMeta{},
|
||||
meta_v1.ObjectMeta{
|
||||
Name: "deployment-1",
|
||||
Namespace: testNamespace,
|
||||
Labels: map[string]string{types.KeelPolicyLabel: "all"},
|
||||
Annotations: map[string]string{},
|
||||
},
|
||||
apps_v1.DeploymentSpec{
|
||||
Selector: &meta_v1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"app": "wd-1",
|
||||
},
|
||||
},
|
||||
Template: v1.PodTemplateSpec{
|
||||
ObjectMeta: meta_v1.ObjectMeta{
|
||||
Labels: map[string]string{
|
||||
"app": "wd-1",
|
||||
"release": "1",
|
||||
},
|
||||
},
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
v1.Container{
|
||||
Name: "wd-1",
|
||||
Image: "karolisr/webhook-demo:0.0.14",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
apps_v1.DeploymentStatus{},
|
||||
}
|
||||
|
||||
_, err := kcs.AppsV1().Deployments(testNamespace).Create(dep)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create deployment: %s", err)
|
||||
}
|
||||
// giving some time to get started
|
||||
// TODO: replace with a readiness check function to wait for 1/1 READY
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
// sending webhook
|
||||
client := http.DefaultClient
|
||||
buf := bytes.NewBufferString(dockerHub0150Webhook)
|
||||
req, err := http.NewRequest("POST", "http://localhost:9300/v1/webhooks/dockerhub", buf)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create req: %s", err)
|
||||
}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make a webhook request to keel: %s", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
t.Errorf("unexpected webhook response from keel: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
updated, err := kcs.AppsV1().Deployments(testNamespace).Get(dep.ObjectMeta.Name, meta_v1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get deployment: %s", err)
|
||||
}
|
||||
|
||||
if updated.Spec.Template.Spec.Containers[0].Image != "karolisr/webhook-demo:0.0.15" {
|
||||
t.Errorf("expected 'karolisr/webhook-demo:0.0.15', got: '%s'", updated.Spec.Template.Spec.Containers[0].Image)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("UpdateThroughDockerHubPolling", func(t *testing.T) {
|
||||
|
||||
testNamespace := createNamespaceForTest()
|
||||
defer deleteTestNamespace(testNamespace)
|
||||
|
||||
dep := &apps_v1.Deployment{
|
||||
meta_v1.TypeMeta{},
|
||||
meta_v1.ObjectMeta{
|
||||
Name: "deployment-1",
|
||||
Namespace: testNamespace,
|
||||
Labels: map[string]string{
|
||||
types.KeelPolicyLabel: "major",
|
||||
types.KeelTriggerLabel: "poll",
|
||||
},
|
||||
Annotations: map[string]string{},
|
||||
},
|
||||
apps_v1.DeploymentSpec{
|
||||
Selector: &meta_v1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"app": "wd-1",
|
||||
},
|
||||
},
|
||||
Template: v1.PodTemplateSpec{
|
||||
ObjectMeta: meta_v1.ObjectMeta{
|
||||
Labels: map[string]string{
|
||||
"app": "wd-1",
|
||||
"release": "1",
|
||||
},
|
||||
},
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
v1.Container{
|
||||
Name: "wd-1",
|
||||
Image: "keelhq/push-workflow-example:0.1.0-dev",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
apps_v1.DeploymentStatus{},
|
||||
}
|
||||
|
||||
_, err := kcs.AppsV1().Deployments(testNamespace).Create(dep)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create deployment: %s", err)
|
||||
}
|
||||
// giving some time to get started
|
||||
// TODO: replace with a readiness check function to wait for 1/1 READY
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
updated, err := kcs.AppsV1().Deployments(testNamespace).Get(dep.ObjectMeta.Name, meta_v1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get deployment: %s", err)
|
||||
}
|
||||
|
||||
if updated.Spec.Template.Spec.Containers[0].Image != "keelhq/push-workflow-example:0.5.0-dev" {
|
||||
t.Errorf("expected 'keelhq/push-workflow-example:0.5.0-dev', got: '%s'", updated.Spec.Template.Spec.Containers[0].Image)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
|
||||
// load the gcp plugin (required to authenticate against GKE clusters).
|
||||
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var kubeConfig = flag.String("kubeconfig", "", "Path to Kubernetes config file")
|
||||
|
||||
func getKubeConfig() string {
|
||||
if *kubeConfig != "" {
|
||||
return *kubeConfig
|
||||
}
|
||||
|
||||
return filepath.Join(os.Getenv("HOME"), ".kube", "config")
|
||||
}
|
||||
|
||||
func getKubernetesClient() (*rest.Config, *kubernetes.Clientset) {
|
||||
// use the current context in kubeconfig
|
||||
config, err := clientcmd.BuildConfigFromFlags("", getKubeConfig())
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
|
||||
// create the clientset
|
||||
clientSet, err := kubernetes.NewForConfig(config)
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
|
||||
return config, clientSet
|
||||
}
|
||||
|
||||
func createNamespaceForTest() string {
|
||||
_, clientset := getKubernetesClient()
|
||||
ns := &v1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
GenerateName: "keel-e2e-test-",
|
||||
},
|
||||
}
|
||||
cns, err := clientset.CoreV1().Namespaces().Create(ns)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
log.Infof("test namespace '%s' created", cns.Name)
|
||||
|
||||
return cns.Name
|
||||
}
|
||||
|
||||
func deleteTestNamespace(namespace string) error {
|
||||
|
||||
defer log.Infof("test namespace '%s' deleted", namespace)
|
||||
_, clientset := getKubernetesClient()
|
||||
deleteOptions := metav1.DeleteOptions{}
|
||||
return clientset.CoreV1().Namespaces().Delete(namespace, &deleteOptions)
|
||||
}
|
||||
|
||||
func startKeel(ctx context.Context) error {
|
||||
|
||||
log.Info("keel started")
|
||||
defer log.Info("keel stopped")
|
||||
|
||||
cmd := "keel"
|
||||
args := []string{"--no-incluster", "--kubeconfig", getKubeConfig()}
|
||||
c := exec.CommandContext(ctx, cmd, args...)
|
||||
c.Stdout = os.Stdout
|
||||
c.Stderr = os.Stderr
|
||||
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
err := c.Process.Kill()
|
||||
if err != nil {
|
||||
log.Errorf("failed to kill keel process: %s", err)
|
||||
}
|
||||
}()
|
||||
|
||||
return c.Run()
|
||||
}
|
Loading…
Reference in New Issue