140 lines
4.0 KiB
Go
140 lines
4.0 KiB
Go
package e2e_arc
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/client-go/kubernetes"
|
|
"k8s.io/client-go/tools/clientcmd"
|
|
)
|
|
|
|
type podCountsByType struct {
|
|
controllers int
|
|
listeners int
|
|
runners int
|
|
}
|
|
|
|
func getPodsByType(clientset *kubernetes.Clientset) podCountsByType {
|
|
arc_namespace := "arc-systems"
|
|
availableArcPods, err := clientset.CoreV1().Pods(arc_namespace).List(context.TODO(), metav1.ListOptions{})
|
|
if err != nil {
|
|
panic(err.Error())
|
|
}
|
|
runners_namespace := "arc-runners"
|
|
availableRunnerPods, err := clientset.CoreV1().Pods(runners_namespace).List(context.TODO(), metav1.ListOptions{})
|
|
if err != nil {
|
|
panic(err.Error())
|
|
}
|
|
podsByType := podCountsByType{}
|
|
for _, pod := range availableArcPods.Items {
|
|
if strings.Contains(pod.Name, "controller") {
|
|
podsByType.controllers += 1
|
|
}
|
|
if strings.Contains(pod.Name, "listener") {
|
|
podsByType.listeners += 1
|
|
}
|
|
}
|
|
for _, pod := range availableRunnerPods.Items {
|
|
if strings.Contains(pod.Name, "runner") {
|
|
podsByType.runners += 1
|
|
}
|
|
}
|
|
return podsByType
|
|
}
|
|
|
|
func pollForClusterState(clientset *kubernetes.Clientset, expectedPodsCount podCountsByType, maxTime int) bool {
|
|
sleepTime := 5
|
|
maxRetries := maxTime / sleepTime
|
|
success := false
|
|
for i := 0; i <= maxRetries; i++ {
|
|
time.Sleep(time.Second * time.Duration(sleepTime))
|
|
availablePodsCount := getPodsByType(clientset)
|
|
if availablePodsCount == expectedPodsCount {
|
|
success = true
|
|
break
|
|
} else {
|
|
fmt.Printf("%v", availablePodsCount)
|
|
}
|
|
}
|
|
return success
|
|
}
|
|
|
|
func TestARCJobs(t *testing.T) {
|
|
configFile := filepath.Join(
|
|
os.Getenv("HOME"), ".kube", "config",
|
|
)
|
|
|
|
config, err := clientcmd.BuildConfigFromFlags("", configFile)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
clientset, err := kubernetes.NewForConfig(config)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
t.Run("Get available pods before job run", func(t *testing.T) {
|
|
expectedPodsCount := podCountsByType{1, 1, 0}
|
|
success := pollForClusterState(clientset, expectedPodsCount, 60)
|
|
if !success {
|
|
t.Fatal("Expected pods count did not match available pods count before job run.")
|
|
}
|
|
},
|
|
)
|
|
t.Run("Get available pods during job run", func(t *testing.T) {
|
|
c := http.Client{}
|
|
targetArcName := os.Getenv("ARC_NAME")
|
|
require.NotEmpty(t, targetArcName, "ARC_NAME environment variable is required for this test to run. (e.g. arc-e2e-test)")
|
|
|
|
targetWorkflow := os.Getenv("WORKFLOW_FILE")
|
|
require.NotEmpty(t, targetWorkflow, "WORKFLOW_FILE environment variable is required for this test to run. (e.g. e2e_test.yml)")
|
|
|
|
ght := os.Getenv("GITHUB_TOKEN")
|
|
require.NotEmpty(t, ght, "GITHUB_TOKEN environment variable is required for this test to run.")
|
|
|
|
// We are triggering manually a workflow that already exists in the repo.
|
|
// This workflow is expected to spin up a number of runner pods matching the runners value set in podCountsByType.
|
|
url := "https://api.github.com/repos/actions-runner-controller/arc_e2e_test_dummy/actions/workflows/" + targetWorkflow + "/dispatches"
|
|
jsonStr := []byte(fmt.Sprintf(`{"ref":"main", "inputs":{"arc_name":"%s"}}`, targetArcName))
|
|
|
|
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
req.Header.Add("Accept", "application/vnd.github+json")
|
|
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", ght))
|
|
req.Header.Add("X-GitHub-Api-Version", "2022-11-28")
|
|
|
|
resp, err := c.Do(req)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
expectedPodsCount := podCountsByType{1, 1, 3}
|
|
success := pollForClusterState(clientset, expectedPodsCount, 120)
|
|
if !success {
|
|
t.Fatal("Expected pods count did not match available pods count during job run.")
|
|
}
|
|
},
|
|
)
|
|
t.Run("Get available pods after job run", func(t *testing.T) {
|
|
expectedPodsCount := podCountsByType{1, 1, 0}
|
|
success := pollForClusterState(clientset, expectedPodsCount, 120)
|
|
if !success {
|
|
t.Fatal("Expected pods count did not match available pods count after job run.")
|
|
}
|
|
},
|
|
)
|
|
}
|