Add labels to autoscaling runner set subresources to allow easier inspection (#2391)
Co-authored-by: Tingluo Huang <tingluohuang@github.com>
This commit is contained in:
		
							parent
							
								
									64cedff2b4
								
							
						
					
					
						commit
						56e1c62ac2
					
				|  | @ -79,18 +79,18 @@ jobs: | ||||||
|           echo "ARC_NAME=$ARC_NAME" >> $GITHUB_OUTPUT |           echo "ARC_NAME=$ARC_NAME" >> $GITHUB_OUTPUT | ||||||
|           count=0 |           count=0 | ||||||
|           while true; do |           while true; do | ||||||
|             POD_NAME=$(kubectl get pods -n arc-systems -l auto-scaling-runner-set-name=$ARC_NAME -o name) |             POD_NAME=$(kubectl get pods -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME -o name) | ||||||
|             if [ -n "$POD_NAME" ]; then |             if [ -n "$POD_NAME" ]; then | ||||||
|               echo "Pod found: $POD_NAME" |               echo "Pod found: $POD_NAME" | ||||||
|               break |               break | ||||||
|             fi |             fi | ||||||
|             if [ "$count" -ge 10 ]; then |             if [ "$count" -ge 10 ]; then | ||||||
|               echo "Timeout waiting for listener pod with label auto-scaling-runner-set-name=$ARC_NAME" |               echo "Timeout waiting for listener pod with label actions.github.com/scale-set-name=$ARC_NAME" | ||||||
|               exit 1 |               exit 1 | ||||||
|             fi |             fi | ||||||
|             sleep 1 |             sleep 1 | ||||||
|           done |           done | ||||||
|           kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l auto-scaling-runner-set-name=$ARC_NAME |           kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME | ||||||
|           kubectl get pod -n arc-systems |           kubectl get pod -n arc-systems | ||||||
| 
 | 
 | ||||||
|       - name: Test ARC E2E |       - name: Test ARC E2E | ||||||
|  | @ -167,18 +167,18 @@ jobs: | ||||||
|           echo "ARC_NAME=$ARC_NAME" >> $GITHUB_OUTPUT |           echo "ARC_NAME=$ARC_NAME" >> $GITHUB_OUTPUT | ||||||
|           count=0 |           count=0 | ||||||
|           while true; do |           while true; do | ||||||
|             POD_NAME=$(kubectl get pods -n arc-systems -l auto-scaling-runner-set-name=$ARC_NAME -o name) |             POD_NAME=$(kubectl get pods -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME -o name) | ||||||
|             if [ -n "$POD_NAME" ]; then |             if [ -n "$POD_NAME" ]; then | ||||||
|               echo "Pod found: $POD_NAME" |               echo "Pod found: $POD_NAME" | ||||||
|               break |               break | ||||||
|             fi |             fi | ||||||
|             if [ "$count" -ge 10 ]; then |             if [ "$count" -ge 10 ]; then | ||||||
|               echo "Timeout waiting for listener pod with label auto-scaling-runner-set-name=$ARC_NAME" |               echo "Timeout waiting for listener pod with label actions.github.com/scale-set-name=$ARC_NAME" | ||||||
|               exit 1 |               exit 1 | ||||||
|             fi |             fi | ||||||
|             sleep 1 |             sleep 1 | ||||||
|           done |           done | ||||||
|           kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l auto-scaling-runner-set-name=$ARC_NAME |           kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME | ||||||
|           kubectl get pod -n arc-systems |           kubectl get pod -n arc-systems | ||||||
| 
 | 
 | ||||||
|       - name: Test ARC E2E |       - name: Test ARC E2E | ||||||
|  | @ -254,18 +254,18 @@ jobs: | ||||||
|           echo "ARC_NAME=$ARC_NAME" >> $GITHUB_OUTPUT |           echo "ARC_NAME=$ARC_NAME" >> $GITHUB_OUTPUT | ||||||
|           count=0 |           count=0 | ||||||
|           while true; do |           while true; do | ||||||
|             POD_NAME=$(kubectl get pods -n arc-systems -l auto-scaling-runner-set-name=$ARC_NAME -o name) |             POD_NAME=$(kubectl get pods -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME -o name) | ||||||
|             if [ -n "$POD_NAME" ]; then |             if [ -n "$POD_NAME" ]; then | ||||||
|               echo "Pod found: $POD_NAME" |               echo "Pod found: $POD_NAME" | ||||||
|               break |               break | ||||||
|             fi |             fi | ||||||
|             if [ "$count" -ge 10 ]; then |             if [ "$count" -ge 10 ]; then | ||||||
|               echo "Timeout waiting for listener pod with label auto-scaling-runner-set-name=$ARC_NAME" |               echo "Timeout waiting for listener pod with label actions.github.com/scale-set-name=$ARC_NAME" | ||||||
|               exit 1 |               exit 1 | ||||||
|             fi |             fi | ||||||
|             sleep 1 |             sleep 1 | ||||||
|           done |           done | ||||||
|           kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l auto-scaling-runner-set-name=$ARC_NAME |           kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME | ||||||
|           kubectl get pod -n arc-systems |           kubectl get pod -n arc-systems | ||||||
| 
 | 
 | ||||||
|       - name: Test ARC E2E |       - name: Test ARC E2E | ||||||
|  | @ -350,18 +350,18 @@ jobs: | ||||||
|           echo "ARC_NAME=$ARC_NAME" >> $GITHUB_OUTPUT |           echo "ARC_NAME=$ARC_NAME" >> $GITHUB_OUTPUT | ||||||
|           count=0 |           count=0 | ||||||
|           while true; do |           while true; do | ||||||
|             POD_NAME=$(kubectl get pods -n arc-systems -l auto-scaling-runner-set-name=$ARC_NAME -o name) |             POD_NAME=$(kubectl get pods -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME -o name) | ||||||
|             if [ -n "$POD_NAME" ]; then |             if [ -n "$POD_NAME" ]; then | ||||||
|               echo "Pod found: $POD_NAME" |               echo "Pod found: $POD_NAME" | ||||||
|               break |               break | ||||||
|             fi |             fi | ||||||
|             if [ "$count" -ge 10 ]; then |             if [ "$count" -ge 10 ]; then | ||||||
|               echo "Timeout waiting for listener pod with label auto-scaling-runner-set-name=$ARC_NAME" |               echo "Timeout waiting for listener pod with label actions.github.com/scale-set-name=$ARC_NAME" | ||||||
|               exit 1 |               exit 1 | ||||||
|             fi |             fi | ||||||
|             sleep 1 |             sleep 1 | ||||||
|           done |           done | ||||||
|           kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l auto-scaling-runner-set-name=$ARC_NAME |           kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME | ||||||
|           kubectl get pod -n arc-systems |           kubectl get pod -n arc-systems | ||||||
| 
 | 
 | ||||||
|       - name: Test ARC E2E |       - name: Test ARC E2E | ||||||
|  | @ -448,18 +448,18 @@ jobs: | ||||||
|           echo "ARC_NAME=$ARC_NAME" >> $GITHUB_OUTPUT |           echo "ARC_NAME=$ARC_NAME" >> $GITHUB_OUTPUT | ||||||
|           count=0 |           count=0 | ||||||
|           while true; do |           while true; do | ||||||
|             POD_NAME=$(kubectl get pods -n arc-systems -l auto-scaling-runner-set-name=$ARC_NAME -o name) |             POD_NAME=$(kubectl get pods -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME -o name) | ||||||
|             if [ -n "$POD_NAME" ]; then |             if [ -n "$POD_NAME" ]; then | ||||||
|               echo "Pod found: $POD_NAME" |               echo "Pod found: $POD_NAME" | ||||||
|               break |               break | ||||||
|             fi |             fi | ||||||
|             if [ "$count" -ge 10 ]; then |             if [ "$count" -ge 10 ]; then | ||||||
|               echo "Timeout waiting for listener pod with label auto-scaling-runner-set-name=$ARC_NAME" |               echo "Timeout waiting for listener pod with label actions.github.com/scale-set-name=$ARC_NAME" | ||||||
|               exit 1 |               exit 1 | ||||||
|             fi |             fi | ||||||
|             sleep 1 |             sleep 1 | ||||||
|           done |           done | ||||||
|           kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l auto-scaling-runner-set-name=$ARC_NAME |           kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME | ||||||
|           kubectl get pod -n arc-systems |           kubectl get pod -n arc-systems | ||||||
| 
 | 
 | ||||||
|       - name: Test ARC E2E |       - name: Test ARC E2E | ||||||
|  | @ -540,18 +540,18 @@ jobs: | ||||||
|           echo "ARC_NAME=$ARC_NAME" >> $GITHUB_OUTPUT |           echo "ARC_NAME=$ARC_NAME" >> $GITHUB_OUTPUT | ||||||
|           count=0 |           count=0 | ||||||
|           while true; do |           while true; do | ||||||
|             POD_NAME=$(kubectl get pods -n arc-systems -l auto-scaling-runner-set-name=$ARC_NAME -o name) |             POD_NAME=$(kubectl get pods -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME -o name) | ||||||
|             if [ -n "$POD_NAME" ]; then |             if [ -n "$POD_NAME" ]; then | ||||||
|               echo "Pod found: $POD_NAME" |               echo "Pod found: $POD_NAME" | ||||||
|               break |               break | ||||||
|             fi |             fi | ||||||
|             if [ "$count" -ge 10 ]; then |             if [ "$count" -ge 10 ]; then | ||||||
|               echo "Timeout waiting for listener pod with label auto-scaling-runner-set-name=$ARC_NAME" |               echo "Timeout waiting for listener pod with label actions.github.com/scale-set-name=$ARC_NAME" | ||||||
|               exit 1 |               exit 1 | ||||||
|             fi |             fi | ||||||
|             sleep 1 |             sleep 1 | ||||||
|           done |           done | ||||||
|           kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l auto-scaling-runner-set-name=$ARC_NAME |           kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME | ||||||
|           kubectl get pod -n arc-systems |           kubectl get pod -n arc-systems | ||||||
| 
 | 
 | ||||||
|       - name: Test ARC E2E |       - name: Test ARC E2E | ||||||
|  |  | ||||||
|  | @ -40,6 +40,7 @@ helm.sh/chart: {{ include "gha-runner-scale-set.chart" . }} | ||||||
| app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} | ||||||
| {{- end }} | {{- end }} | ||||||
| app.kubernetes.io/managed-by: {{ .Release.Service }} | app.kubernetes.io/managed-by: {{ .Release.Service }} | ||||||
|  | app.kubernetes.io/part-of: gha-runner-scale-set | ||||||
| {{- end }} | {{- end }} | ||||||
| 
 | 
 | ||||||
| {{/* | {{/* | ||||||
|  |  | ||||||
|  | @ -10,6 +10,7 @@ metadata: | ||||||
|   name: {{ .Release.Name }} |   name: {{ .Release.Name }} | ||||||
|   namespace: {{ .Release.Namespace }} |   namespace: {{ .Release.Namespace }} | ||||||
|   labels: |   labels: | ||||||
|  |     app.kubernetes.io/component: "autoscaling-runner-set" | ||||||
|     {{- include "gha-runner-scale-set.labels" . | nindent 4 }} |     {{- include "gha-runner-scale-set.labels" . | nindent 4 }} | ||||||
| spec: | spec: | ||||||
|   githubConfigUrl: {{ required ".Values.githubConfigUrl is required" (trimSuffix "/" .Values.githubConfigUrl) }} |   githubConfigUrl: {{ required ".Values.githubConfigUrl is required" (trimSuffix "/" .Values.githubConfigUrl) }} | ||||||
|  |  | ||||||
|  | @ -311,6 +311,10 @@ func TestTemplateRenderedAutoScalingRunnerSet(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| 	assert.Equal(t, "gha-runner-scale-set", ars.Labels["app.kubernetes.io/name"]) | 	assert.Equal(t, "gha-runner-scale-set", ars.Labels["app.kubernetes.io/name"]) | ||||||
| 	assert.Equal(t, "test-runners", ars.Labels["app.kubernetes.io/instance"]) | 	assert.Equal(t, "test-runners", ars.Labels["app.kubernetes.io/instance"]) | ||||||
|  | 	assert.Equal(t, "gha-runner-scale-set", ars.Labels["app.kubernetes.io/part-of"]) | ||||||
|  | 	assert.Equal(t, "autoscaling-runner-set", ars.Labels["app.kubernetes.io/component"]) | ||||||
|  | 	assert.NotEmpty(t, ars.Labels["app.kubernetes.io/version"]) | ||||||
|  | 
 | ||||||
| 	assert.Equal(t, "https://github.com/actions", ars.Spec.GitHubConfigUrl) | 	assert.Equal(t, "https://github.com/actions", ars.Spec.GitHubConfigUrl) | ||||||
| 	assert.Equal(t, "test-runners-gha-runner-scale-set-github-secret", ars.Spec.GitHubConfigSecret) | 	assert.Equal(t, "test-runners-gha-runner-scale-set-github-secret", ars.Spec.GitHubConfigSecret) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -523,8 +523,8 @@ func (r *AutoscalingListenerReconciler) createProxySecret(ctx context.Context, a | ||||||
| 			Name:      proxyListenerSecretName(autoscalingListener), | 			Name:      proxyListenerSecretName(autoscalingListener), | ||||||
| 			Namespace: autoscalingListener.Namespace, | 			Namespace: autoscalingListener.Namespace, | ||||||
| 			Labels: map[string]string{ | 			Labels: map[string]string{ | ||||||
| 				"auto-scaling-runner-set-namespace": autoscalingListener.Spec.AutoscalingRunnerSetNamespace, | 				LabelKeyGitHubScaleSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace, | ||||||
| 				"auto-scaling-runner-set-name":      autoscalingListener.Spec.AutoscalingRunnerSetName, | 				LabelKeyGitHubScaleSetName:      autoscalingListener.Spec.AutoscalingRunnerSetName, | ||||||
| 			}, | 			}, | ||||||
| 		}, | 		}, | ||||||
| 		Data: data, | 		Data: data, | ||||||
|  |  | ||||||
|  | @ -45,9 +45,8 @@ const ( | ||||||
| 	autoscalingRunnerSetOwnerKey      = ".metadata.controller" | 	autoscalingRunnerSetOwnerKey      = ".metadata.controller" | ||||||
| 	LabelKeyRunnerSpecHash            = "runner-spec-hash" | 	LabelKeyRunnerSpecHash            = "runner-spec-hash" | ||||||
| 	autoscalingRunnerSetFinalizerName = "autoscalingrunnerset.actions.github.com/finalizer" | 	autoscalingRunnerSetFinalizerName = "autoscalingrunnerset.actions.github.com/finalizer" | ||||||
| 	runnerScaleSetIdKey               = "runner-scale-set-id" | 	runnerScaleSetIdAnnotationKey     = "runner-scale-set-id" | ||||||
| 	runnerScaleSetNameKey             = "runner-scale-set-name" | 	runnerScaleSetNameAnnotationKey   = "runner-scale-set-name" | ||||||
| 	runnerScaleSetRunnerGroupNameKey  = "runner-scale-set-runner-group-name" |  | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // AutoscalingRunnerSetReconciler reconciles a AutoscalingRunnerSet object
 | // AutoscalingRunnerSetReconciler reconciles a AutoscalingRunnerSet object
 | ||||||
|  | @ -140,7 +139,7 @@ func (r *AutoscalingRunnerSetReconciler) Reconcile(ctx context.Context, req ctrl | ||||||
| 		return ctrl.Result{}, nil | 		return ctrl.Result{}, nil | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	scaleSetIdRaw, ok := autoscalingRunnerSet.Annotations[runnerScaleSetIdKey] | 	scaleSetIdRaw, ok := autoscalingRunnerSet.Annotations[runnerScaleSetIdAnnotationKey] | ||||||
| 	if !ok { | 	if !ok { | ||||||
| 		// Need to create a new runner scale set on Actions service
 | 		// Need to create a new runner scale set on Actions service
 | ||||||
| 		log.Info("Runner scale set id annotation does not exist. Creating a new runner scale set.") | 		log.Info("Runner scale set id annotation does not exist. Creating a new runner scale set.") | ||||||
|  | @ -154,14 +153,14 @@ func (r *AutoscalingRunnerSetReconciler) Reconcile(ctx context.Context, req ctrl | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Make sure the runner group of the scale set is up to date
 | 	// Make sure the runner group of the scale set is up to date
 | ||||||
| 	currentRunnerGroupName, ok := autoscalingRunnerSet.Annotations[runnerScaleSetRunnerGroupNameKey] | 	currentRunnerGroupName, ok := autoscalingRunnerSet.Annotations[AnnotationKeyGitHubRunnerGroupName] | ||||||
| 	if !ok || (len(autoscalingRunnerSet.Spec.RunnerGroup) > 0 && !strings.EqualFold(currentRunnerGroupName, autoscalingRunnerSet.Spec.RunnerGroup)) { | 	if !ok || (len(autoscalingRunnerSet.Spec.RunnerGroup) > 0 && !strings.EqualFold(currentRunnerGroupName, autoscalingRunnerSet.Spec.RunnerGroup)) { | ||||||
| 		log.Info("AutoScalingRunnerSet runner group changed. Updating the runner scale set.") | 		log.Info("AutoScalingRunnerSet runner group changed. Updating the runner scale set.") | ||||||
| 		return r.updateRunnerScaleSetRunnerGroup(ctx, autoscalingRunnerSet, log) | 		return r.updateRunnerScaleSetRunnerGroup(ctx, autoscalingRunnerSet, log) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Make sure the runner scale set name is up to date
 | 	// Make sure the runner scale set name is up to date
 | ||||||
| 	currentRunnerScaleSetName, ok := autoscalingRunnerSet.Annotations[runnerScaleSetNameKey] | 	currentRunnerScaleSetName, ok := autoscalingRunnerSet.Annotations[runnerScaleSetNameAnnotationKey] | ||||||
| 	if !ok || (len(autoscalingRunnerSet.Spec.RunnerScaleSetName) > 0 && !strings.EqualFold(currentRunnerScaleSetName, autoscalingRunnerSet.Spec.RunnerScaleSetName)) { | 	if !ok || (len(autoscalingRunnerSet.Spec.RunnerScaleSetName) > 0 && !strings.EqualFold(currentRunnerScaleSetName, autoscalingRunnerSet.Spec.RunnerScaleSetName)) { | ||||||
| 		log.Info("AutoScalingRunnerSet runner scale set name changed. Updating the runner scale set.") | 		log.Info("AutoScalingRunnerSet runner scale set name changed. Updating the runner scale set.") | ||||||
| 		return r.updateRunnerScaleSetName(ctx, autoscalingRunnerSet, log) | 		return r.updateRunnerScaleSetName(ctx, autoscalingRunnerSet, log) | ||||||
|  | @ -365,12 +364,18 @@ func (r *AutoscalingRunnerSetReconciler) createRunnerScaleSet(ctx context.Contex | ||||||
| 	if autoscalingRunnerSet.Annotations == nil { | 	if autoscalingRunnerSet.Annotations == nil { | ||||||
| 		autoscalingRunnerSet.Annotations = map[string]string{} | 		autoscalingRunnerSet.Annotations = map[string]string{} | ||||||
| 	} | 	} | ||||||
|  | 	if autoscalingRunnerSet.Labels == nil { | ||||||
|  | 		autoscalingRunnerSet.Labels = map[string]string{} | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	logger.Info("Adding runner scale set ID, name and runner group name as an annotation") | 	logger.Info("Adding runner scale set ID, name and runner group name as an annotation and url labels") | ||||||
| 	if err = patch(ctx, r.Client, autoscalingRunnerSet, func(obj *v1alpha1.AutoscalingRunnerSet) { | 	if err = patch(ctx, r.Client, autoscalingRunnerSet, func(obj *v1alpha1.AutoscalingRunnerSet) { | ||||||
| 		obj.Annotations[runnerScaleSetNameKey] = runnerScaleSet.Name | 		obj.Annotations[runnerScaleSetNameAnnotationKey] = runnerScaleSet.Name | ||||||
| 		obj.Annotations[runnerScaleSetIdKey] = strconv.Itoa(runnerScaleSet.Id) | 		obj.Annotations[runnerScaleSetIdAnnotationKey] = strconv.Itoa(runnerScaleSet.Id) | ||||||
| 		obj.Annotations[runnerScaleSetRunnerGroupNameKey] = runnerScaleSet.RunnerGroupName | 		obj.Annotations[AnnotationKeyGitHubRunnerGroupName] = runnerScaleSet.RunnerGroupName | ||||||
|  | 		if err := applyGitHubURLLabels(obj.Spec.GitHubConfigUrl, obj.Labels); err != nil { // should never happen
 | ||||||
|  | 			logger.Error(err, "Failed to apply GitHub URL labels") | ||||||
|  | 		} | ||||||
| 	}); err != nil { | 	}); err != nil { | ||||||
| 		logger.Error(err, "Failed to add runner scale set ID, name and runner group name as an annotation") | 		logger.Error(err, "Failed to add runner scale set ID, name and runner group name as an annotation") | ||||||
| 		return ctrl.Result{}, err | 		return ctrl.Result{}, err | ||||||
|  | @ -384,7 +389,7 @@ func (r *AutoscalingRunnerSetReconciler) createRunnerScaleSet(ctx context.Contex | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetRunnerGroup(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, logger logr.Logger) (ctrl.Result, error) { | func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetRunnerGroup(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, logger logr.Logger) (ctrl.Result, error) { | ||||||
| 	runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdKey]) | 	runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdAnnotationKey]) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		logger.Error(err, "Failed to parse runner scale set ID") | 		logger.Error(err, "Failed to parse runner scale set ID") | ||||||
| 		return ctrl.Result{}, err | 		return ctrl.Result{}, err | ||||||
|  | @ -415,7 +420,7 @@ func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetRunnerGroup(ctx con | ||||||
| 
 | 
 | ||||||
| 	logger.Info("Updating runner scale set runner group name as an annotation") | 	logger.Info("Updating runner scale set runner group name as an annotation") | ||||||
| 	if err := patch(ctx, r.Client, autoscalingRunnerSet, func(obj *v1alpha1.AutoscalingRunnerSet) { | 	if err := patch(ctx, r.Client, autoscalingRunnerSet, func(obj *v1alpha1.AutoscalingRunnerSet) { | ||||||
| 		obj.Annotations[runnerScaleSetRunnerGroupNameKey] = updatedRunnerScaleSet.RunnerGroupName | 		obj.Annotations[AnnotationKeyGitHubRunnerGroupName] = updatedRunnerScaleSet.RunnerGroupName | ||||||
| 	}); err != nil { | 	}); err != nil { | ||||||
| 		logger.Error(err, "Failed to update runner group name annotation") | 		logger.Error(err, "Failed to update runner group name annotation") | ||||||
| 		return ctrl.Result{}, err | 		return ctrl.Result{}, err | ||||||
|  | @ -426,7 +431,7 @@ func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetRunnerGroup(ctx con | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetName(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, logger logr.Logger) (ctrl.Result, error) { | func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetName(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, logger logr.Logger) (ctrl.Result, error) { | ||||||
| 	runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdKey]) | 	runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdAnnotationKey]) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		logger.Error(err, "Failed to parse runner scale set ID") | 		logger.Error(err, "Failed to parse runner scale set ID") | ||||||
| 		return ctrl.Result{}, err | 		return ctrl.Result{}, err | ||||||
|  | @ -451,7 +456,7 @@ func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetName(ctx context.Co | ||||||
| 
 | 
 | ||||||
| 	logger.Info("Updating runner scale set name as an annotation") | 	logger.Info("Updating runner scale set name as an annotation") | ||||||
| 	if err := patch(ctx, r.Client, autoscalingRunnerSet, func(obj *v1alpha1.AutoscalingRunnerSet) { | 	if err := patch(ctx, r.Client, autoscalingRunnerSet, func(obj *v1alpha1.AutoscalingRunnerSet) { | ||||||
| 		obj.Annotations[runnerScaleSetNameKey] = updatedRunnerScaleSet.Name | 		obj.Annotations[runnerScaleSetNameAnnotationKey] = updatedRunnerScaleSet.Name | ||||||
| 	}); err != nil { | 	}); err != nil { | ||||||
| 		logger.Error(err, "Failed to update runner scale set name annotation") | 		logger.Error(err, "Failed to update runner scale set name annotation") | ||||||
| 		return ctrl.Result{}, err | 		return ctrl.Result{}, err | ||||||
|  | @ -463,7 +468,7 @@ func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetName(ctx context.Co | ||||||
| 
 | 
 | ||||||
| func (r *AutoscalingRunnerSetReconciler) deleteRunnerScaleSet(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, logger logr.Logger) error { | func (r *AutoscalingRunnerSetReconciler) deleteRunnerScaleSet(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, logger logr.Logger) error { | ||||||
| 	logger.Info("Deleting the runner scale set from Actions service") | 	logger.Info("Deleting the runner scale set from Actions service") | ||||||
| 	runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdKey]) | 	runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdAnnotationKey]) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		// If the annotation is not set correctly, or if it does not exist, we are going to get stuck in a loop trying to parse the scale set id.
 | 		// If the annotation is not set correctly, or if it does not exist, we are going to get stuck in a loop trying to parse the scale set id.
 | ||||||
| 		// If the configuration is invalid (secret does not exist for example), we never get to the point to create runner set. But then, manual cleanup
 | 		// If the configuration is invalid (secret does not exist for example), we never get to the point to create runner set. But then, manual cleanup
 | ||||||
|  |  | ||||||
|  | @ -117,19 +117,39 @@ var _ = Describe("Test AutoScalingRunnerSet controller", func() { | ||||||
| 						return "", err | 						return "", err | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
| 					if _, ok := created.Annotations[runnerScaleSetIdKey]; !ok { | 					if _, ok := created.Annotations[runnerScaleSetIdAnnotationKey]; !ok { | ||||||
| 						return "", nil | 						return "", nil | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
| 					if _, ok := created.Annotations[runnerScaleSetRunnerGroupNameKey]; !ok { | 					if _, ok := created.Annotations[AnnotationKeyGitHubRunnerGroupName]; !ok { | ||||||
| 						return "", nil | 						return "", nil | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
| 					return fmt.Sprintf("%s_%s", created.Annotations[runnerScaleSetIdKey], created.Annotations[runnerScaleSetRunnerGroupNameKey]), nil | 					return fmt.Sprintf("%s_%s", created.Annotations[runnerScaleSetIdAnnotationKey], created.Annotations[AnnotationKeyGitHubRunnerGroupName]), nil | ||||||
| 				}, | 				}, | ||||||
| 				autoscalingRunnerSetTestTimeout, | 				autoscalingRunnerSetTestTimeout, | ||||||
| 				autoscalingRunnerSetTestInterval).Should(BeEquivalentTo("1_testgroup"), "RunnerScaleSet should be created/fetched and update the AutoScalingRunnerSet's annotation") | 				autoscalingRunnerSetTestInterval).Should(BeEquivalentTo("1_testgroup"), "RunnerScaleSet should be created/fetched and update the AutoScalingRunnerSet's annotation") | ||||||
| 
 | 
 | ||||||
|  | 			Eventually( | ||||||
|  | 				func() (string, error) { | ||||||
|  | 					err := k8sClient.Get(ctx, client.ObjectKey{Name: autoscalingRunnerSet.Name, Namespace: autoscalingRunnerSet.Namespace}, created) | ||||||
|  | 					if err != nil { | ||||||
|  | 						return "", err | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					if _, ok := created.Labels[LabelKeyGitHubOrganization]; !ok { | ||||||
|  | 						return "", nil | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					if _, ok := created.Labels[LabelKeyGitHubRepository]; !ok { | ||||||
|  | 						return "", nil | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
|  | 					return fmt.Sprintf("%s/%s", created.Labels[LabelKeyGitHubOrganization], created.Labels[LabelKeyGitHubRepository]), nil | ||||||
|  | 				}, | ||||||
|  | 				autoscalingRunnerSetTestTimeout, | ||||||
|  | 				autoscalingRunnerSetTestInterval).Should(BeEquivalentTo("owner/repo"), "RunnerScaleSet should be created/fetched and update the AutoScalingRunnerSet's label") | ||||||
|  | 
 | ||||||
| 			// Check if ephemeral runner set is created
 | 			// Check if ephemeral runner set is created
 | ||||||
| 			Eventually( | 			Eventually( | ||||||
| 				func() (int, error) { | 				func() (int, error) { | ||||||
|  | @ -351,18 +371,18 @@ var _ = Describe("Test AutoScalingRunnerSet controller", func() { | ||||||
| 						return "", err | 						return "", err | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
| 					if _, ok := updated.Annotations[runnerScaleSetRunnerGroupNameKey]; !ok { | 					if _, ok := updated.Annotations[AnnotationKeyGitHubRunnerGroupName]; !ok { | ||||||
| 						return "", nil | 						return "", nil | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
| 					return updated.Annotations[runnerScaleSetRunnerGroupNameKey], nil | 					return updated.Annotations[AnnotationKeyGitHubRunnerGroupName], nil | ||||||
| 				}, | 				}, | ||||||
| 				autoscalingRunnerSetTestTimeout, | 				autoscalingRunnerSetTestTimeout, | ||||||
| 				autoscalingRunnerSetTestInterval).Should(BeEquivalentTo("testgroup2"), "AutoScalingRunnerSet should have the new runner group in its annotation") | 				autoscalingRunnerSetTestInterval).Should(BeEquivalentTo("testgroup2"), "AutoScalingRunnerSet should have the new runner group in its annotation") | ||||||
| 
 | 
 | ||||||
| 			// delete the annotation and it should be re-added
 | 			// delete the annotation and it should be re-added
 | ||||||
| 			patched = autoscalingRunnerSet.DeepCopy() | 			patched = autoscalingRunnerSet.DeepCopy() | ||||||
| 			delete(patched.Annotations, runnerScaleSetRunnerGroupNameKey) | 			delete(patched.Annotations, AnnotationKeyGitHubRunnerGroupName) | ||||||
| 			err = k8sClient.Patch(ctx, patched, client.MergeFrom(autoscalingRunnerSet)) | 			err = k8sClient.Patch(ctx, patched, client.MergeFrom(autoscalingRunnerSet)) | ||||||
| 			Expect(err).NotTo(HaveOccurred(), "failed to patch AutoScalingRunnerSet") | 			Expect(err).NotTo(HaveOccurred(), "failed to patch AutoScalingRunnerSet") | ||||||
| 
 | 
 | ||||||
|  | @ -374,11 +394,11 @@ var _ = Describe("Test AutoScalingRunnerSet controller", func() { | ||||||
| 						return "", err | 						return "", err | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
| 					if _, ok := updated.Annotations[runnerScaleSetRunnerGroupNameKey]; !ok { | 					if _, ok := updated.Annotations[AnnotationKeyGitHubRunnerGroupName]; !ok { | ||||||
| 						return "", nil | 						return "", nil | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
| 					return updated.Annotations[runnerScaleSetRunnerGroupNameKey], nil | 					return updated.Annotations[AnnotationKeyGitHubRunnerGroupName], nil | ||||||
| 				}, | 				}, | ||||||
| 				autoscalingRunnerSetTestTimeout, | 				autoscalingRunnerSetTestTimeout, | ||||||
| 				autoscalingRunnerSetTestInterval, | 				autoscalingRunnerSetTestInterval, | ||||||
|  | @ -539,7 +559,7 @@ var _ = Describe("Test AutoScalingController updates", func() { | ||||||
| 						return "", err | 						return "", err | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
| 					if val, ok := ars.Annotations[runnerScaleSetNameKey]; ok { | 					if val, ok := ars.Annotations[runnerScaleSetNameAnnotationKey]; ok { | ||||||
| 						return val, nil | 						return val, nil | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
|  | @ -562,7 +582,7 @@ var _ = Describe("Test AutoScalingController updates", func() { | ||||||
| 						return "", err | 						return "", err | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
| 					if val, ok := ars.Annotations[runnerScaleSetNameKey]; ok { | 					if val, ok := ars.Annotations[runnerScaleSetNameAnnotationKey]; ok { | ||||||
| 						return val, nil | 						return val, nil | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -357,9 +357,8 @@ func (r *EphemeralRunnerSetReconciler) createProxySecret(ctx context.Context, ep | ||||||
| 			Name:      proxyEphemeralRunnerSetSecretName(ephemeralRunnerSet), | 			Name:      proxyEphemeralRunnerSetSecretName(ephemeralRunnerSet), | ||||||
| 			Namespace: ephemeralRunnerSet.Namespace, | 			Namespace: ephemeralRunnerSet.Namespace, | ||||||
| 			Labels: map[string]string{ | 			Labels: map[string]string{ | ||||||
| 				// TODO: figure out autoScalingRunnerSet name and set it as a label for this secret
 | 				LabelKeyGitHubScaleSetName:      ephemeralRunnerSet.Labels[LabelKeyGitHubScaleSetName], | ||||||
| 				// "auto-scaling-runner-set-namespace": ephemeralRunnerSet.Namespace,
 | 				LabelKeyGitHubScaleSetNamespace: ephemeralRunnerSet.Labels[LabelKeyGitHubScaleSetNamespace], | ||||||
| 				// "auto-scaling-runner-set-name": ephemeralRunnerSet.Name,
 |  | ||||||
| 			}, | 			}, | ||||||
| 		}, | 		}, | ||||||
| 		Data: proxySecretData, | 		Data: proxySecretData, | ||||||
|  |  | ||||||
|  | @ -8,6 +8,7 @@ import ( | ||||||
| 
 | 
 | ||||||
| 	"github.com/actions/actions-runner-controller/apis/actions.github.com/v1alpha1" | 	"github.com/actions/actions-runner-controller/apis/actions.github.com/v1alpha1" | ||||||
| 	"github.com/actions/actions-runner-controller/build" | 	"github.com/actions/actions-runner-controller/build" | ||||||
|  | 	"github.com/actions/actions-runner-controller/github/actions" | ||||||
| 	"github.com/actions/actions-runner-controller/hash" | 	"github.com/actions/actions-runner-controller/hash" | ||||||
| 	corev1 "k8s.io/api/core/v1" | 	corev1 "k8s.io/api/core/v1" | ||||||
| 	rbacv1 "k8s.io/api/rbac/v1" | 	rbacv1 "k8s.io/api/rbac/v1" | ||||||
|  | @ -19,12 +20,42 @@ const ( | ||||||
| 	jitTokenKey = "jitToken" | 	jitTokenKey = "jitToken" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // labels applied to resources
 | // Labels applied to resources
 | ||||||
| const ( | const ( | ||||||
| 	LabelKeyAutoScaleRunnerSetName      = "auto-scaling-runner-set-name" | 	// Kubernetes labels
 | ||||||
| 	LabelKeyAutoScaleRunnerSetNamespace = "auto-scaling-runner-set-namespace" | 	LabelKeyKubernetesPartOf    = "app.kubernetes.io/part-of" | ||||||
|  | 	LabelKeyKubernetesComponent = "app.kubernetes.io/component" | ||||||
|  | 	LabelKeyKubernetesVersion   = "app.kubernetes.io/version" | ||||||
|  | 
 | ||||||
|  | 	// Github labels
 | ||||||
|  | 	LabelKeyGitHubScaleSetName      = "actions.github.com/scale-set-name" | ||||||
|  | 	LabelKeyGitHubScaleSetNamespace = "actions.github.com/scale-set-namespace" | ||||||
|  | 	LabelKeyGitHubEnterprise        = "actions.github.com/enterprise" | ||||||
|  | 	LabelKeyGitHubOrganization      = "actions.github.com/organization" | ||||||
|  | 	LabelKeyGitHubRepository        = "actions.github.com/repository" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | const AnnotationKeyGitHubRunnerGroupName = "actions.github.com/runner-group-name" | ||||||
|  | 
 | ||||||
|  | // Labels applied to listener roles
 | ||||||
|  | const ( | ||||||
|  | 	labelKeyListenerName      = "auto-scaling-listener-name" | ||||||
|  | 	labelKeyListenerNamespace = "auto-scaling-listener-namespace" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var commonLabelKeys = [...]string{ | ||||||
|  | 	LabelKeyKubernetesPartOf, | ||||||
|  | 	LabelKeyKubernetesComponent, | ||||||
|  | 	LabelKeyKubernetesVersion, | ||||||
|  | 	LabelKeyGitHubScaleSetName, | ||||||
|  | 	LabelKeyGitHubScaleSetNamespace, | ||||||
|  | 	LabelKeyGitHubEnterprise, | ||||||
|  | 	LabelKeyGitHubOrganization, | ||||||
|  | 	LabelKeyGitHubRepository, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const labelValueKubernetesPartOf = "gha-runner-scale-set" | ||||||
|  | 
 | ||||||
| type resourceBuilder struct{} | type resourceBuilder struct{} | ||||||
| 
 | 
 | ||||||
| func (b *resourceBuilder) newScaleSetListenerPod(autoscalingListener *v1alpha1.AutoscalingListener, serviceAccount *corev1.ServiceAccount, secret *corev1.Secret, envs ...corev1.EnvVar) *corev1.Pod { | func (b *resourceBuilder) newScaleSetListenerPod(autoscalingListener *v1alpha1.AutoscalingListener, serviceAccount *corev1.ServiceAccount, secret *corev1.Secret, envs ...corev1.EnvVar) *corev1.Pod { | ||||||
|  | @ -129,6 +160,11 @@ func (b *resourceBuilder) newScaleSetListenerPod(autoscalingListener *v1alpha1.A | ||||||
| 		RestartPolicy:    corev1.RestartPolicyNever, | 		RestartPolicy:    corev1.RestartPolicyNever, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	labels := make(map[string]string, len(autoscalingListener.Labels)) | ||||||
|  | 	for key, val := range autoscalingListener.Labels { | ||||||
|  | 		labels[key] = val | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	newRunnerScaleSetListenerPod := &corev1.Pod{ | 	newRunnerScaleSetListenerPod := &corev1.Pod{ | ||||||
| 		TypeMeta: metav1.TypeMeta{ | 		TypeMeta: metav1.TypeMeta{ | ||||||
| 			Kind:       "Pod", | 			Kind:       "Pod", | ||||||
|  | @ -137,10 +173,7 @@ func (b *resourceBuilder) newScaleSetListenerPod(autoscalingListener *v1alpha1.A | ||||||
| 		ObjectMeta: metav1.ObjectMeta{ | 		ObjectMeta: metav1.ObjectMeta{ | ||||||
| 			Name:      autoscalingListener.Name, | 			Name:      autoscalingListener.Name, | ||||||
| 			Namespace: autoscalingListener.Namespace, | 			Namespace: autoscalingListener.Namespace, | ||||||
| 			Labels: map[string]string{ | 			Labels:    labels, | ||||||
| 				LabelKeyAutoScaleRunnerSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace, |  | ||||||
| 				LabelKeyAutoScaleRunnerSetName:      autoscalingListener.Spec.AutoscalingRunnerSetName, |  | ||||||
| 			}, |  | ||||||
| 		}, | 		}, | ||||||
| 		Spec: podSpec, | 		Spec: podSpec, | ||||||
| 	} | 	} | ||||||
|  | @ -149,14 +182,28 @@ func (b *resourceBuilder) newScaleSetListenerPod(autoscalingListener *v1alpha1.A | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (b *resourceBuilder) newEphemeralRunnerSet(autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet) (*v1alpha1.EphemeralRunnerSet, error) { | func (b *resourceBuilder) newEphemeralRunnerSet(autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet) (*v1alpha1.EphemeralRunnerSet, error) { | ||||||
| 	runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdKey]) | 	runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdAnnotationKey]) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	runnerSpecHash := autoscalingRunnerSet.RunnerSetSpecHash() | 	runnerSpecHash := autoscalingRunnerSet.RunnerSetSpecHash() | ||||||
| 
 | 
 | ||||||
| 	newLabels := map[string]string{} | 	newLabels := map[string]string{ | ||||||
| 	newLabels[LabelKeyRunnerSpecHash] = runnerSpecHash | 		LabelKeyRunnerSpecHash:          runnerSpecHash, | ||||||
|  | 		LabelKeyKubernetesPartOf:        labelValueKubernetesPartOf, | ||||||
|  | 		LabelKeyKubernetesComponent:     "runner-set", | ||||||
|  | 		LabelKeyKubernetesVersion:       autoscalingRunnerSet.Labels[LabelKeyKubernetesVersion], | ||||||
|  | 		LabelKeyGitHubScaleSetName:      autoscalingRunnerSet.Name, | ||||||
|  | 		LabelKeyGitHubScaleSetNamespace: autoscalingRunnerSet.Namespace, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if err := applyGitHubURLLabels(autoscalingRunnerSet.Spec.GitHubConfigUrl, newLabels); err != nil { | ||||||
|  | 		return nil, fmt.Errorf("failed to apply GitHub URL labels: %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	newAnnotations := map[string]string{ | ||||||
|  | 		AnnotationKeyGitHubRunnerGroupName: autoscalingRunnerSet.Annotations[AnnotationKeyGitHubRunnerGroupName], | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	newEphemeralRunnerSet := &v1alpha1.EphemeralRunnerSet{ | 	newEphemeralRunnerSet := &v1alpha1.EphemeralRunnerSet{ | ||||||
| 		TypeMeta: metav1.TypeMeta{}, | 		TypeMeta: metav1.TypeMeta{}, | ||||||
|  | @ -164,6 +211,7 @@ func (b *resourceBuilder) newEphemeralRunnerSet(autoscalingRunnerSet *v1alpha1.A | ||||||
| 			GenerateName: autoscalingRunnerSet.ObjectMeta.Name + "-", | 			GenerateName: autoscalingRunnerSet.ObjectMeta.Name + "-", | ||||||
| 			Namespace:    autoscalingRunnerSet.ObjectMeta.Namespace, | 			Namespace:    autoscalingRunnerSet.ObjectMeta.Namespace, | ||||||
| 			Labels:       newLabels, | 			Labels:       newLabels, | ||||||
|  | 			Annotations:  newAnnotations, | ||||||
| 		}, | 		}, | ||||||
| 		Spec: v1alpha1.EphemeralRunnerSetSpec{ | 		Spec: v1alpha1.EphemeralRunnerSetSpec{ | ||||||
| 			Replicas: 0, | 			Replicas: 0, | ||||||
|  | @ -187,8 +235,8 @@ func (b *resourceBuilder) newScaleSetListenerServiceAccount(autoscalingListener | ||||||
| 			Name:      scaleSetListenerServiceAccountName(autoscalingListener), | 			Name:      scaleSetListenerServiceAccountName(autoscalingListener), | ||||||
| 			Namespace: autoscalingListener.Namespace, | 			Namespace: autoscalingListener.Namespace, | ||||||
| 			Labels: map[string]string{ | 			Labels: map[string]string{ | ||||||
| 				LabelKeyAutoScaleRunnerSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace, | 				LabelKeyGitHubScaleSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace, | ||||||
| 				LabelKeyAutoScaleRunnerSetName:      autoscalingListener.Spec.AutoscalingRunnerSetName, | 				LabelKeyGitHubScaleSetName:      autoscalingListener.Spec.AutoscalingRunnerSetName, | ||||||
| 			}, | 			}, | ||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
|  | @ -202,10 +250,10 @@ func (b *resourceBuilder) newScaleSetListenerRole(autoscalingListener *v1alpha1. | ||||||
| 			Name:      scaleSetListenerRoleName(autoscalingListener), | 			Name:      scaleSetListenerRoleName(autoscalingListener), | ||||||
| 			Namespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace, | 			Namespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace, | ||||||
| 			Labels: map[string]string{ | 			Labels: map[string]string{ | ||||||
| 				LabelKeyAutoScaleRunnerSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace, | 				LabelKeyGitHubScaleSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace, | ||||||
| 				LabelKeyAutoScaleRunnerSetName:      autoscalingListener.Spec.AutoscalingRunnerSetName, | 				LabelKeyGitHubScaleSetName:      autoscalingListener.Spec.AutoscalingRunnerSetName, | ||||||
| 				"auto-scaling-listener-namespace":   autoscalingListener.Namespace, | 				labelKeyListenerNamespace:       autoscalingListener.Namespace, | ||||||
| 				"auto-scaling-listener-name":        autoscalingListener.Name, | 				labelKeyListenerName:            autoscalingListener.Name, | ||||||
| 				"role-policy-rules-hash":        rulesHash, | 				"role-policy-rules-hash":        rulesHash, | ||||||
| 			}, | 			}, | ||||||
| 		}, | 		}, | ||||||
|  | @ -236,10 +284,10 @@ func (b *resourceBuilder) newScaleSetListenerRoleBinding(autoscalingListener *v1 | ||||||
| 			Name:      scaleSetListenerRoleName(autoscalingListener), | 			Name:      scaleSetListenerRoleName(autoscalingListener), | ||||||
| 			Namespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace, | 			Namespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace, | ||||||
| 			Labels: map[string]string{ | 			Labels: map[string]string{ | ||||||
| 				LabelKeyAutoScaleRunnerSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace, | 				LabelKeyGitHubScaleSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace, | ||||||
| 				LabelKeyAutoScaleRunnerSetName:      autoscalingListener.Spec.AutoscalingRunnerSetName, | 				LabelKeyGitHubScaleSetName:      autoscalingListener.Spec.AutoscalingRunnerSetName, | ||||||
| 				"auto-scaling-listener-namespace":   autoscalingListener.Namespace, | 				labelKeyListenerNamespace:       autoscalingListener.Namespace, | ||||||
| 				"auto-scaling-listener-name":        autoscalingListener.Name, | 				labelKeyListenerName:            autoscalingListener.Name, | ||||||
| 				"role-binding-role-ref-hash":    roleRefHash, | 				"role-binding-role-ref-hash":    roleRefHash, | ||||||
| 				"role-binding-subject-hash":     subjectHash, | 				"role-binding-subject-hash":     subjectHash, | ||||||
| 			}, | 			}, | ||||||
|  | @ -259,8 +307,8 @@ func (b *resourceBuilder) newScaleSetListenerSecretMirror(autoscalingListener *v | ||||||
| 			Name:      scaleSetListenerSecretMirrorName(autoscalingListener), | 			Name:      scaleSetListenerSecretMirrorName(autoscalingListener), | ||||||
| 			Namespace: autoscalingListener.Namespace, | 			Namespace: autoscalingListener.Namespace, | ||||||
| 			Labels: map[string]string{ | 			Labels: map[string]string{ | ||||||
| 				LabelKeyAutoScaleRunnerSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace, | 				LabelKeyGitHubScaleSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace, | ||||||
| 				LabelKeyAutoScaleRunnerSetName:      autoscalingListener.Spec.AutoscalingRunnerSetName, | 				LabelKeyGitHubScaleSetName:      autoscalingListener.Spec.AutoscalingRunnerSetName, | ||||||
| 				"secret-data-hash":              dataHash, | 				"secret-data-hash":              dataHash, | ||||||
| 			}, | 			}, | ||||||
| 		}, | 		}, | ||||||
|  | @ -271,7 +319,7 @@ func (b *resourceBuilder) newScaleSetListenerSecretMirror(autoscalingListener *v | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (b *resourceBuilder) newAutoScalingListener(autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, ephemeralRunnerSet *v1alpha1.EphemeralRunnerSet, namespace, image string, imagePullSecrets []corev1.LocalObjectReference) (*v1alpha1.AutoscalingListener, error) { | func (b *resourceBuilder) newAutoScalingListener(autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, ephemeralRunnerSet *v1alpha1.EphemeralRunnerSet, namespace, image string, imagePullSecrets []corev1.LocalObjectReference) (*v1alpha1.AutoscalingListener, error) { | ||||||
| 	runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdKey]) | 	runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdAnnotationKey]) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  | @ -285,13 +333,24 @@ func (b *resourceBuilder) newAutoScalingListener(autoscalingRunnerSet *v1alpha1. | ||||||
| 		effectiveMinRunners = *autoscalingRunnerSet.Spec.MinRunners | 		effectiveMinRunners = *autoscalingRunnerSet.Spec.MinRunners | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	githubConfig, err := actions.ParseGitHubConfigFromURL(autoscalingRunnerSet.Spec.GitHubConfigUrl) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, fmt.Errorf("failed to parse github config from url: %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	autoscalingListener := &v1alpha1.AutoscalingListener{ | 	autoscalingListener := &v1alpha1.AutoscalingListener{ | ||||||
| 		ObjectMeta: metav1.ObjectMeta{ | 		ObjectMeta: metav1.ObjectMeta{ | ||||||
| 			Name:      scaleSetListenerName(autoscalingRunnerSet), | 			Name:      scaleSetListenerName(autoscalingRunnerSet), | ||||||
| 			Namespace: namespace, | 			Namespace: namespace, | ||||||
| 			Labels: map[string]string{ | 			Labels: map[string]string{ | ||||||
| 				LabelKeyAutoScaleRunnerSetNamespace: autoscalingRunnerSet.Namespace, | 				LabelKeyGitHubScaleSetNamespace: autoscalingRunnerSet.Namespace, | ||||||
| 				LabelKeyAutoScaleRunnerSetName:      autoscalingRunnerSet.Name, | 				LabelKeyGitHubScaleSetName:      autoscalingRunnerSet.Name, | ||||||
|  | 				LabelKeyKubernetesPartOf:        labelValueKubernetesPartOf, | ||||||
|  | 				LabelKeyKubernetesComponent:     "runner-scale-set-listener", | ||||||
|  | 				LabelKeyKubernetesVersion:       autoscalingRunnerSet.Labels[LabelKeyKubernetesVersion], | ||||||
|  | 				LabelKeyGitHubEnterprise:        githubConfig.Enterprise, | ||||||
|  | 				LabelKeyGitHubOrganization:      githubConfig.Organization, | ||||||
|  | 				LabelKeyGitHubRepository:        githubConfig.Repository, | ||||||
| 				LabelKeyRunnerSpecHash:          autoscalingRunnerSet.ListenerSpecHash(), | 				LabelKeyRunnerSpecHash:          autoscalingRunnerSet.ListenerSpecHash(), | ||||||
| 			}, | 			}, | ||||||
| 		}, | 		}, | ||||||
|  | @ -315,11 +374,30 @@ func (b *resourceBuilder) newAutoScalingListener(autoscalingRunnerSet *v1alpha1. | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (b *resourceBuilder) newEphemeralRunner(ephemeralRunnerSet *v1alpha1.EphemeralRunnerSet) *v1alpha1.EphemeralRunner { | func (b *resourceBuilder) newEphemeralRunner(ephemeralRunnerSet *v1alpha1.EphemeralRunnerSet) *v1alpha1.EphemeralRunner { | ||||||
|  | 	labels := make(map[string]string) | ||||||
|  | 	for _, key := range commonLabelKeys { | ||||||
|  | 		switch key { | ||||||
|  | 		case LabelKeyKubernetesComponent: | ||||||
|  | 			labels[key] = "runner" | ||||||
|  | 		default: | ||||||
|  | 			v, ok := ephemeralRunnerSet.Labels[key] | ||||||
|  | 			if !ok { | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 			labels[key] = v | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	annotations := make(map[string]string) | ||||||
|  | 	for key, val := range ephemeralRunnerSet.Annotations { | ||||||
|  | 		annotations[key] = val | ||||||
|  | 	} | ||||||
| 	return &v1alpha1.EphemeralRunner{ | 	return &v1alpha1.EphemeralRunner{ | ||||||
| 		TypeMeta: metav1.TypeMeta{}, | 		TypeMeta: metav1.TypeMeta{}, | ||||||
| 		ObjectMeta: metav1.ObjectMeta{ | 		ObjectMeta: metav1.ObjectMeta{ | ||||||
| 			GenerateName: ephemeralRunnerSet.Name + "-runner-", | 			GenerateName: ephemeralRunnerSet.Name + "-runner-", | ||||||
| 			Namespace:    ephemeralRunnerSet.Namespace, | 			Namespace:    ephemeralRunnerSet.Namespace, | ||||||
|  | 			Labels:       labels, | ||||||
|  | 			Annotations:  annotations, | ||||||
| 		}, | 		}, | ||||||
| 		Spec: ephemeralRunnerSet.Spec.EphemeralRunnerSpec, | 		Spec: ephemeralRunnerSet.Spec.EphemeralRunnerSpec, | ||||||
| 	} | 	} | ||||||
|  | @ -337,6 +415,7 @@ func (b *resourceBuilder) newEphemeralRunnerPod(ctx context.Context, runner *v1a | ||||||
| 	for k, v := range runner.Spec.PodTemplateSpec.Labels { | 	for k, v := range runner.Spec.PodTemplateSpec.Labels { | ||||||
| 		labels[k] = v | 		labels[k] = v | ||||||
| 	} | 	} | ||||||
|  | 	labels["actions-ephemeral-runner"] = string(corev1.ConditionTrue) | ||||||
| 
 | 
 | ||||||
| 	for k, v := range runner.ObjectMeta.Annotations { | 	for k, v := range runner.ObjectMeta.Annotations { | ||||||
| 		annotations[k] = v | 		annotations[k] = v | ||||||
|  | @ -352,8 +431,6 @@ func (b *resourceBuilder) newEphemeralRunnerPod(ctx context.Context, runner *v1a | ||||||
| 		runner.Status.RunnerJITConfig, | 		runner.Status.RunnerJITConfig, | ||||||
| 	) | 	) | ||||||
| 
 | 
 | ||||||
| 	labels["actions-ephemeral-runner"] = string(corev1.ConditionTrue) |  | ||||||
| 
 |  | ||||||
| 	objectMeta := metav1.ObjectMeta{ | 	objectMeta := metav1.ObjectMeta{ | ||||||
| 		Name:        runner.ObjectMeta.Name, | 		Name:        runner.ObjectMeta.Name, | ||||||
| 		Namespace:   runner.ObjectMeta.Namespace, | 		Namespace:   runner.ObjectMeta.Namespace, | ||||||
|  | @ -469,3 +546,22 @@ func rulesForListenerRole(resourceNames []string) []rbacv1.PolicyRule { | ||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func applyGitHubURLLabels(url string, labels map[string]string) error { | ||||||
|  | 	githubConfig, err := actions.ParseGitHubConfigFromURL(url) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return fmt.Errorf("failed to parse github config from url: %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if len(githubConfig.Enterprise) > 0 { | ||||||
|  | 		labels[LabelKeyGitHubEnterprise] = githubConfig.Enterprise | ||||||
|  | 	} | ||||||
|  | 	if len(githubConfig.Organization) > 0 { | ||||||
|  | 		labels[LabelKeyGitHubOrganization] = githubConfig.Organization | ||||||
|  | 	} | ||||||
|  | 	if len(githubConfig.Repository) > 0 { | ||||||
|  | 		labels[LabelKeyGitHubRepository] = githubConfig.Repository | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -0,0 +1,93 @@ | ||||||
|  | package actionsgithubcom | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"context" | ||||||
|  | 	"testing" | ||||||
|  | 
 | ||||||
|  | 	"github.com/actions/actions-runner-controller/apis/actions.github.com/v1alpha1" | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
|  | 	"github.com/stretchr/testify/require" | ||||||
|  | 	corev1 "k8s.io/api/core/v1" | ||||||
|  | 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func TestLabelPropagation(t *testing.T) { | ||||||
|  | 	autoscalingRunnerSet := v1alpha1.AutoscalingRunnerSet{ | ||||||
|  | 		ObjectMeta: metav1.ObjectMeta{ | ||||||
|  | 			Name:      "test-scale-set", | ||||||
|  | 			Namespace: "test-ns", | ||||||
|  | 			Labels: map[string]string{ | ||||||
|  | 				LabelKeyKubernetesPartOf:  labelValueKubernetesPartOf, | ||||||
|  | 				LabelKeyKubernetesVersion: "0.2.0", | ||||||
|  | 			}, | ||||||
|  | 			Annotations: map[string]string{ | ||||||
|  | 				runnerScaleSetIdAnnotationKey:      "1", | ||||||
|  | 				AnnotationKeyGitHubRunnerGroupName: "test-group", | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		Spec: v1alpha1.AutoscalingRunnerSetSpec{ | ||||||
|  | 			GitHubConfigUrl: "https://github.com/org/repo", | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	var b resourceBuilder | ||||||
|  | 	ephemeralRunnerSet, err := b.newEphemeralRunnerSet(&autoscalingRunnerSet) | ||||||
|  | 	require.NoError(t, err) | ||||||
|  | 	assert.Equal(t, labelValueKubernetesPartOf, ephemeralRunnerSet.Labels[LabelKeyKubernetesPartOf]) | ||||||
|  | 	assert.Equal(t, "runner-set", ephemeralRunnerSet.Labels[LabelKeyKubernetesComponent]) | ||||||
|  | 	assert.Equal(t, autoscalingRunnerSet.Labels[LabelKeyKubernetesVersion], ephemeralRunnerSet.Labels[LabelKeyKubernetesVersion]) | ||||||
|  | 	assert.NotEmpty(t, ephemeralRunnerSet.Labels[LabelKeyRunnerSpecHash]) | ||||||
|  | 	assert.Equal(t, autoscalingRunnerSet.Name, ephemeralRunnerSet.Labels[LabelKeyGitHubScaleSetName]) | ||||||
|  | 	assert.Equal(t, autoscalingRunnerSet.Namespace, ephemeralRunnerSet.Labels[LabelKeyGitHubScaleSetNamespace]) | ||||||
|  | 	assert.Equal(t, "", ephemeralRunnerSet.Labels[LabelKeyGitHubEnterprise]) | ||||||
|  | 	assert.Equal(t, "org", ephemeralRunnerSet.Labels[LabelKeyGitHubOrganization]) | ||||||
|  | 	assert.Equal(t, "repo", ephemeralRunnerSet.Labels[LabelKeyGitHubRepository]) | ||||||
|  | 	assert.Equal(t, autoscalingRunnerSet.Annotations[AnnotationKeyGitHubRunnerGroupName], ephemeralRunnerSet.Annotations[AnnotationKeyGitHubRunnerGroupName]) | ||||||
|  | 
 | ||||||
|  | 	listener, err := b.newAutoScalingListener(&autoscalingRunnerSet, ephemeralRunnerSet, autoscalingRunnerSet.Namespace, "test:latest", nil) | ||||||
|  | 	require.NoError(t, err) | ||||||
|  | 	assert.Equal(t, labelValueKubernetesPartOf, listener.Labels[LabelKeyKubernetesPartOf]) | ||||||
|  | 	assert.Equal(t, "runner-scale-set-listener", listener.Labels[LabelKeyKubernetesComponent]) | ||||||
|  | 	assert.Equal(t, autoscalingRunnerSet.Labels[LabelKeyKubernetesVersion], listener.Labels[LabelKeyKubernetesVersion]) | ||||||
|  | 	assert.NotEmpty(t, ephemeralRunnerSet.Labels[LabelKeyRunnerSpecHash]) | ||||||
|  | 	assert.Equal(t, autoscalingRunnerSet.Name, listener.Labels[LabelKeyGitHubScaleSetName]) | ||||||
|  | 	assert.Equal(t, autoscalingRunnerSet.Namespace, listener.Labels[LabelKeyGitHubScaleSetNamespace]) | ||||||
|  | 	assert.Equal(t, "", listener.Labels[LabelKeyGitHubEnterprise]) | ||||||
|  | 	assert.Equal(t, "org", listener.Labels[LabelKeyGitHubOrganization]) | ||||||
|  | 	assert.Equal(t, "repo", listener.Labels[LabelKeyGitHubRepository]) | ||||||
|  | 
 | ||||||
|  | 	listenerServiceAccount := &corev1.ServiceAccount{ | ||||||
|  | 		ObjectMeta: metav1.ObjectMeta{ | ||||||
|  | 			Name: "test", | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	listenerSecret := &corev1.Secret{ | ||||||
|  | 		ObjectMeta: metav1.ObjectMeta{ | ||||||
|  | 			Name: "test", | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	listenerPod := b.newScaleSetListenerPod(listener, listenerServiceAccount, listenerSecret) | ||||||
|  | 	assert.Equal(t, listenerPod.Labels, listener.Labels) | ||||||
|  | 
 | ||||||
|  | 	ephemeralRunner := b.newEphemeralRunner(ephemeralRunnerSet) | ||||||
|  | 	require.NoError(t, err) | ||||||
|  | 
 | ||||||
|  | 	for _, key := range commonLabelKeys { | ||||||
|  | 		if key == LabelKeyKubernetesComponent { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 		assert.Equal(t, ephemeralRunnerSet.Labels[key], ephemeralRunner.Labels[key]) | ||||||
|  | 	} | ||||||
|  | 	assert.Equal(t, "runner", ephemeralRunner.Labels[LabelKeyKubernetesComponent]) | ||||||
|  | 	assert.Equal(t, autoscalingRunnerSet.Annotations[AnnotationKeyGitHubRunnerGroupName], ephemeralRunner.Annotations[AnnotationKeyGitHubRunnerGroupName]) | ||||||
|  | 
 | ||||||
|  | 	runnerSecret := &corev1.Secret{ | ||||||
|  | 		ObjectMeta: metav1.ObjectMeta{ | ||||||
|  | 			Name: "test", | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	pod := b.newEphemeralRunnerPod(context.TODO(), ephemeralRunner, runnerSecret) | ||||||
|  | 	for key := range ephemeralRunner.Labels { | ||||||
|  | 		assert.Equal(t, ephemeralRunner.Labels[key], pod.Labels[key]) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -160,7 +160,7 @@ kubectl logs -n "${NAMESPACE}" -l app.kubernetes.io/name=gha-runner-scale-set-co | ||||||
| 
 | 
 | ||||||
| ```bash | ```bash | ||||||
| # Runner set listener logs | # Runner set listener logs | ||||||
| kubectl logs -n "${NAMESPACE}" -l auto-scaling-runner-set-namespace=arc-systems -l auto-scaling-runner-set-name=arc-runner-set | kubectl logs -n "${NAMESPACE}" -l actions.github.com/scale-set-namespace=arc-systems -l actions.github.com/scale-set-name=arc-runner-set | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| ### Naming error: `Name must have up to characters` | ### Naming error: `Name must have up to characters` | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue