141 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			141 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.")
 | |
| 		}
 | |
| 	},
 | |
| 	)
 | |
| }
 |