Surface EphemeralRunnerSet stats to AutoscalingRunnerSet (#2382)
This commit is contained in:
		
							parent
							
								
									322df79617
								
							
						
					
					
						commit
						babbfc77d5
					
				|  | @ -33,10 +33,14 @@ import ( | |||
| 
 | ||||
| //+kubebuilder:object:root=true
 | ||||
| //+kubebuilder:subresource:status
 | ||||
| //+kubebuilder:printcolumn:JSONPath=".spec.minRunners",name=Minimum Runners,type=number
 | ||||
| //+kubebuilder:printcolumn:JSONPath=".spec.maxRunners",name=Maximum Runners,type=number
 | ||||
| //+kubebuilder:printcolumn:JSONPath=".status.currentRunners",name=Current Runners,type=number
 | ||||
| //+kubebuilder:printcolumn:JSONPath=".spec.minRunners",name=Minimum Runners,type=integer
 | ||||
| //+kubebuilder:printcolumn:JSONPath=".spec.maxRunners",name=Maximum Runners,type=integer
 | ||||
| //+kubebuilder:printcolumn:JSONPath=".status.currentRunners",name=Current Runners,type=integer
 | ||||
| //+kubebuilder:printcolumn:JSONPath=".status.state",name=State,type=string
 | ||||
| //+kubebuilder:printcolumn:JSONPath=".status.pendingEphemeralRunners",name=Pending Runners,type=integer
 | ||||
| //+kubebuilder:printcolumn:JSONPath=".status.runningEphemeralRunners",name=Running Runners,type=integer
 | ||||
| //+kubebuilder:printcolumn:JSONPath=".status.finishedEphemeralRunners",name=Finished Runners,type=integer
 | ||||
| //+kubebuilder:printcolumn:JSONPath=".status.deletingEphemeralRunners",name=Deleting Runners,type=integer
 | ||||
| 
 | ||||
| // AutoscalingRunnerSet is the Schema for the autoscalingrunnersets API
 | ||||
| type AutoscalingRunnerSet struct { | ||||
|  | @ -228,10 +232,19 @@ type ProxyServerConfig struct { | |||
| // AutoscalingRunnerSetStatus defines the observed state of AutoscalingRunnerSet
 | ||||
| type AutoscalingRunnerSetStatus struct { | ||||
| 	// +optional
 | ||||
| 	CurrentRunners int `json:"currentRunners,omitempty"` | ||||
| 	CurrentRunners int `json:"currentRunners"` | ||||
| 
 | ||||
| 	// +optional
 | ||||
| 	State string `json:"state,omitempty"` | ||||
| 	State string `json:"state"` | ||||
| 
 | ||||
| 	// EphemeralRunner counts separated by the stage ephemeral runners are in, taken from the EphemeralRunnerSet
 | ||||
| 
 | ||||
| 	//+optional
 | ||||
| 	PendingEphemeralRunners int `json:"pendingEphemeralRunners"` | ||||
| 	// +optional
 | ||||
| 	RunningEphemeralRunners int `json:"runningEphemeralRunners"` | ||||
| 	// +optional
 | ||||
| 	FailedEphemeralRunners int `json:"failedEphemeralRunners"` | ||||
| } | ||||
| 
 | ||||
| func (ars *AutoscalingRunnerSet) ListenerSpecHash() string { | ||||
|  |  | |||
|  | @ -31,13 +31,27 @@ type EphemeralRunnerSetSpec struct { | |||
| // EphemeralRunnerSetStatus defines the observed state of EphemeralRunnerSet
 | ||||
| type EphemeralRunnerSetStatus struct { | ||||
| 	// CurrentReplicas is the number of currently running EphemeralRunner resources being managed by this EphemeralRunnerSet.
 | ||||
| 	CurrentReplicas int `json:"currentReplicas,omitempty"` | ||||
| 	CurrentReplicas int `json:"currentReplicas"` | ||||
| 
 | ||||
| 	// EphemeralRunner counts separated by the stage ephemeral runners are in
 | ||||
| 
 | ||||
| 	// +optional
 | ||||
| 	PendingEphemeralRunners int `json:"pendingEphemeralRunners"` | ||||
| 	// +optional
 | ||||
| 	RunningEphemeralRunners int `json:"runningEphemeralRunners"` | ||||
| 	// +optional
 | ||||
| 	FailedEphemeralRunners int `json:"failedEphemeralRunners"` | ||||
| } | ||||
| 
 | ||||
| // +kubebuilder:object:root=true
 | ||||
| // +kubebuilder:subresource:status
 | ||||
| // +kubebuilder:printcolumn:JSONPath=".spec.replicas",name="DesiredReplicas",type="integer"
 | ||||
| // +kubebuilder:printcolumn:JSONPath=".status.currentReplicas", name="CurrentReplicas",type="integer"
 | ||||
| //+kubebuilder:printcolumn:JSONPath=".status.pendingEphemeralRunners",name=Pending Runners,type=integer
 | ||||
| //+kubebuilder:printcolumn:JSONPath=".status.runningEphemeralRunners",name=Running Runners,type=integer
 | ||||
| //+kubebuilder:printcolumn:JSONPath=".status.finishedEphemeralRunners",name=Finished Runners,type=integer
 | ||||
| //+kubebuilder:printcolumn:JSONPath=".status.deletingEphemeralRunners",name=Deleting Runners,type=integer
 | ||||
| 
 | ||||
| // EphemeralRunnerSet is the Schema for the ephemeralrunnersets API
 | ||||
| type EphemeralRunnerSet struct { | ||||
| 	metav1.TypeMeta   `json:",inline"` | ||||
|  |  | |||
|  | @ -17,16 +17,28 @@ spec: | |||
|     - additionalPrinterColumns: | ||||
|         - jsonPath: .spec.minRunners | ||||
|           name: Minimum Runners | ||||
|           type: number | ||||
|           type: integer | ||||
|         - jsonPath: .spec.maxRunners | ||||
|           name: Maximum Runners | ||||
|           type: number | ||||
|           type: integer | ||||
|         - jsonPath: .status.currentRunners | ||||
|           name: Current Runners | ||||
|           type: number | ||||
|           type: integer | ||||
|         - jsonPath: .status.state | ||||
|           name: State | ||||
|           type: string | ||||
|         - jsonPath: .status.pendingEphemeralRunners | ||||
|           name: Pending Runners | ||||
|           type: integer | ||||
|         - jsonPath: .status.runningEphemeralRunners | ||||
|           name: Running Runners | ||||
|           type: integer | ||||
|         - jsonPath: .status.finishedEphemeralRunners | ||||
|           name: Finished Runners | ||||
|           type: integer | ||||
|         - jsonPath: .status.deletingEphemeralRunners | ||||
|           name: Deleting Runners | ||||
|           type: integer | ||||
|       name: v1alpha1 | ||||
|       schema: | ||||
|         openAPIV3Schema: | ||||
|  | @ -4306,6 +4318,12 @@ spec: | |||
|               properties: | ||||
|                 currentRunners: | ||||
|                   type: integer | ||||
|                 failedEphemeralRunners: | ||||
|                   type: integer | ||||
|                 pendingEphemeralRunners: | ||||
|                   type: integer | ||||
|                 runningEphemeralRunners: | ||||
|                   type: integer | ||||
|                 state: | ||||
|                   type: string | ||||
|               type: object | ||||
|  |  | |||
|  | @ -21,6 +21,18 @@ spec: | |||
|         - jsonPath: .status.currentReplicas | ||||
|           name: CurrentReplicas | ||||
|           type: integer | ||||
|         - jsonPath: .status.pendingEphemeralRunners | ||||
|           name: Pending Runners | ||||
|           type: integer | ||||
|         - jsonPath: .status.runningEphemeralRunners | ||||
|           name: Running Runners | ||||
|           type: integer | ||||
|         - jsonPath: .status.finishedEphemeralRunners | ||||
|           name: Finished Runners | ||||
|           type: integer | ||||
|         - jsonPath: .status.deletingEphemeralRunners | ||||
|           name: Deleting Runners | ||||
|           type: integer | ||||
|       name: v1alpha1 | ||||
|       schema: | ||||
|         openAPIV3Schema: | ||||
|  | @ -4296,6 +4308,14 @@ spec: | |||
|                 currentReplicas: | ||||
|                   description: CurrentReplicas is the number of currently running EphemeralRunner resources being managed by this EphemeralRunnerSet. | ||||
|                   type: integer | ||||
|                 failedEphemeralRunners: | ||||
|                   type: integer | ||||
|                 pendingEphemeralRunners: | ||||
|                   type: integer | ||||
|                 runningEphemeralRunners: | ||||
|                   type: integer | ||||
|               required: | ||||
|                 - currentReplicas | ||||
|               type: object | ||||
|           type: object | ||||
|       served: true | ||||
|  |  | |||
|  | @ -17,16 +17,28 @@ spec: | |||
|     - additionalPrinterColumns: | ||||
|         - jsonPath: .spec.minRunners | ||||
|           name: Minimum Runners | ||||
|           type: number | ||||
|           type: integer | ||||
|         - jsonPath: .spec.maxRunners | ||||
|           name: Maximum Runners | ||||
|           type: number | ||||
|           type: integer | ||||
|         - jsonPath: .status.currentRunners | ||||
|           name: Current Runners | ||||
|           type: number | ||||
|           type: integer | ||||
|         - jsonPath: .status.state | ||||
|           name: State | ||||
|           type: string | ||||
|         - jsonPath: .status.pendingEphemeralRunners | ||||
|           name: Pending Runners | ||||
|           type: integer | ||||
|         - jsonPath: .status.runningEphemeralRunners | ||||
|           name: Running Runners | ||||
|           type: integer | ||||
|         - jsonPath: .status.finishedEphemeralRunners | ||||
|           name: Finished Runners | ||||
|           type: integer | ||||
|         - jsonPath: .status.deletingEphemeralRunners | ||||
|           name: Deleting Runners | ||||
|           type: integer | ||||
|       name: v1alpha1 | ||||
|       schema: | ||||
|         openAPIV3Schema: | ||||
|  | @ -4306,6 +4318,12 @@ spec: | |||
|               properties: | ||||
|                 currentRunners: | ||||
|                   type: integer | ||||
|                 failedEphemeralRunners: | ||||
|                   type: integer | ||||
|                 pendingEphemeralRunners: | ||||
|                   type: integer | ||||
|                 runningEphemeralRunners: | ||||
|                   type: integer | ||||
|                 state: | ||||
|                   type: string | ||||
|               type: object | ||||
|  |  | |||
|  | @ -21,6 +21,18 @@ spec: | |||
|         - jsonPath: .status.currentReplicas | ||||
|           name: CurrentReplicas | ||||
|           type: integer | ||||
|         - jsonPath: .status.pendingEphemeralRunners | ||||
|           name: Pending Runners | ||||
|           type: integer | ||||
|         - jsonPath: .status.runningEphemeralRunners | ||||
|           name: Running Runners | ||||
|           type: integer | ||||
|         - jsonPath: .status.finishedEphemeralRunners | ||||
|           name: Finished Runners | ||||
|           type: integer | ||||
|         - jsonPath: .status.deletingEphemeralRunners | ||||
|           name: Deleting Runners | ||||
|           type: integer | ||||
|       name: v1alpha1 | ||||
|       schema: | ||||
|         openAPIV3Schema: | ||||
|  | @ -4296,6 +4308,14 @@ spec: | |||
|                 currentReplicas: | ||||
|                   description: CurrentReplicas is the number of currently running EphemeralRunner resources being managed by this EphemeralRunnerSet. | ||||
|                   type: integer | ||||
|                 failedEphemeralRunners: | ||||
|                   type: integer | ||||
|                 pendingEphemeralRunners: | ||||
|                   type: integer | ||||
|                 runningEphemeralRunners: | ||||
|                   type: integer | ||||
|               required: | ||||
|                 - currentReplicas | ||||
|               type: object | ||||
|           type: object | ||||
|       served: true | ||||
|  |  | |||
|  | @ -238,6 +238,9 @@ func (r *AutoscalingRunnerSetReconciler) Reconcile(ctx context.Context, req ctrl | |||
| 	if latestRunnerSet.Status.CurrentReplicas != autoscalingRunnerSet.Status.CurrentRunners { | ||||
| 		if err := patchSubResource(ctx, r.Status(), autoscalingRunnerSet, func(obj *v1alpha1.AutoscalingRunnerSet) { | ||||
| 			obj.Status.CurrentRunners = latestRunnerSet.Status.CurrentReplicas | ||||
| 			obj.Status.PendingEphemeralRunners = latestRunnerSet.Status.PendingEphemeralRunners | ||||
| 			obj.Status.RunningEphemeralRunners = latestRunnerSet.Status.RunningEphemeralRunners | ||||
| 			obj.Status.FailedEphemeralRunners = latestRunnerSet.Status.FailedEphemeralRunners | ||||
| 		}); err != nil { | ||||
| 			log.Error(err, "Failed to update autoscaling runner set status with current runner count") | ||||
| 			return ctrl.Result{}, err | ||||
|  |  | |||
|  | @ -157,23 +157,6 @@ var _ = Describe("Test AutoScalingRunnerSet controller", func() { | |||
| 			err := k8sClient.List(ctx, runnerSetList, client.InNamespace(autoscalingRunnerSet.Namespace)) | ||||
| 			Expect(err).NotTo(HaveOccurred(), "failed to list EphemeralRunnerSet") | ||||
| 			Expect(len(runnerSetList.Items)).To(BeEquivalentTo(1), "Only one EphemeralRunnerSet should be created") | ||||
| 			runnerSet := runnerSetList.Items[0] | ||||
| 			statusUpdate := runnerSet.DeepCopy() | ||||
| 			statusUpdate.Status.CurrentReplicas = 100 | ||||
| 			err = k8sClient.Status().Patch(ctx, statusUpdate, client.MergeFrom(&runnerSet)) | ||||
| 			Expect(err).NotTo(HaveOccurred(), "failed to patch EphemeralRunnerSet status") | ||||
| 
 | ||||
| 			Eventually( | ||||
| 				func() (int, error) { | ||||
| 					updated := new(v1alpha1.AutoscalingRunnerSet) | ||||
| 					err := k8sClient.Get(ctx, client.ObjectKey{Name: autoscalingRunnerSet.Name, Namespace: autoscalingRunnerSet.Namespace}, updated) | ||||
| 					if err != nil { | ||||
| 						return 0, fmt.Errorf("failed to get AutoScalingRunnerSet: %w", err) | ||||
| 					} | ||||
| 					return updated.Status.CurrentRunners, nil | ||||
| 				}, | ||||
| 				autoscalingRunnerSetTestTimeout, | ||||
| 				autoscalingRunnerSetTestInterval).Should(BeEquivalentTo(100), "AutoScalingRunnerSet status should be updated") | ||||
| 		}) | ||||
| 	}) | ||||
| 
 | ||||
|  | @ -398,9 +381,75 @@ var _ = Describe("Test AutoScalingRunnerSet controller", func() { | |||
| 					return updated.Annotations[runnerScaleSetRunnerGroupNameKey], nil | ||||
| 				}, | ||||
| 				autoscalingRunnerSetTestTimeout, | ||||
| 				autoscalingRunnerSetTestInterval).Should(BeEquivalentTo("testgroup2"), "AutoScalingRunnerSet should have the runner group in its annotation") | ||||
| 				autoscalingRunnerSetTestInterval, | ||||
| 			).Should(BeEquivalentTo("testgroup2"), "AutoScalingRunnerSet should have the runner group in its annotation") | ||||
| 		}) | ||||
| 	}) | ||||
| 
 | ||||
| 	It("Should update Status on EphemeralRunnerSet status Update", func() { | ||||
| 		ars := new(v1alpha1.AutoscalingRunnerSet) | ||||
| 		Eventually( | ||||
| 			func() (bool, error) { | ||||
| 				err := k8sClient.Get( | ||||
| 					ctx, | ||||
| 					client.ObjectKey{ | ||||
| 						Name:      autoscalingRunnerSet.Name, | ||||
| 						Namespace: autoscalingRunnerSet.Namespace, | ||||
| 					}, | ||||
| 					ars, | ||||
| 				) | ||||
| 				if err != nil { | ||||
| 					return false, err | ||||
| 				} | ||||
| 				return true, nil | ||||
| 			}, | ||||
| 			autoscalingRunnerSetTestTimeout, | ||||
| 			autoscalingRunnerSetTestInterval, | ||||
| 		).Should(BeTrue(), "AutoscalingRunnerSet should be created") | ||||
| 
 | ||||
| 		runnerSetList := new(v1alpha1.EphemeralRunnerSetList) | ||||
| 		Eventually(func() (int, error) { | ||||
| 			err := k8sClient.List(ctx, runnerSetList, client.InNamespace(ars.Namespace)) | ||||
| 			if err != nil { | ||||
| 				return 0, err | ||||
| 			} | ||||
| 			return len(runnerSetList.Items), nil | ||||
| 		}, | ||||
| 			autoscalingRunnerSetTestTimeout, | ||||
| 			autoscalingRunnerSetTestInterval, | ||||
| 		).Should(BeEquivalentTo(1), "Failed to fetch runner set list") | ||||
| 
 | ||||
| 		runnerSet := runnerSetList.Items[0] | ||||
| 		statusUpdate := runnerSet.DeepCopy() | ||||
| 		statusUpdate.Status.CurrentReplicas = 6 | ||||
| 		statusUpdate.Status.FailedEphemeralRunners = 1 | ||||
| 		statusUpdate.Status.RunningEphemeralRunners = 2 | ||||
| 		statusUpdate.Status.PendingEphemeralRunners = 3 | ||||
| 
 | ||||
| 		desiredStatus := v1alpha1.AutoscalingRunnerSetStatus{ | ||||
| 			CurrentRunners:          statusUpdate.Status.CurrentReplicas, | ||||
| 			State:                   "", | ||||
| 			PendingEphemeralRunners: statusUpdate.Status.PendingEphemeralRunners, | ||||
| 			RunningEphemeralRunners: statusUpdate.Status.RunningEphemeralRunners, | ||||
| 			FailedEphemeralRunners:  statusUpdate.Status.FailedEphemeralRunners, | ||||
| 		} | ||||
| 
 | ||||
| 		err := k8sClient.Status().Patch(ctx, statusUpdate, client.MergeFrom(&runnerSet)) | ||||
| 		Expect(err).NotTo(HaveOccurred(), "Failed to patch runner set status") | ||||
| 
 | ||||
| 		Eventually( | ||||
| 			func() (v1alpha1.AutoscalingRunnerSetStatus, error) { | ||||
| 				updated := new(v1alpha1.AutoscalingRunnerSet) | ||||
| 				err := k8sClient.Get(ctx, client.ObjectKey{Name: autoscalingRunnerSet.Name, Namespace: autoscalingRunnerSet.Namespace}, updated) | ||||
| 				if err != nil { | ||||
| 					return v1alpha1.AutoscalingRunnerSetStatus{}, fmt.Errorf("failed to get AutoScalingRunnerSet: %w", err) | ||||
| 				} | ||||
| 				return updated.Status, nil | ||||
| 			}, | ||||
| 			autoscalingRunnerSetTestTimeout, | ||||
| 			autoscalingRunnerSetTestInterval, | ||||
| 		).Should(BeEquivalentTo(desiredStatus), "AutoScalingRunnerSet status should be updated") | ||||
| 	}) | ||||
| }) | ||||
| 
 | ||||
| var _ = Describe("Test AutoScalingController updates", func() { | ||||
|  |  | |||
|  | @ -200,11 +200,18 @@ func (r *EphemeralRunnerSetReconciler) Reconcile(ctx context.Context, req ctrl.R | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	desiredStatus := v1alpha1.EphemeralRunnerSetStatus{ | ||||
| 		CurrentReplicas:         total, | ||||
| 		PendingEphemeralRunners: len(pendingEphemeralRunners), | ||||
| 		RunningEphemeralRunners: len(runningEphemeralRunners), | ||||
| 		FailedEphemeralRunners:  len(failedEphemeralRunners), | ||||
| 	} | ||||
| 
 | ||||
| 	// Update the status if needed.
 | ||||
| 	if ephemeralRunnerSet.Status.CurrentReplicas != total { | ||||
| 	if ephemeralRunnerSet.Status != desiredStatus { | ||||
| 		log.Info("Updating status with current runners count", "count", total) | ||||
| 		if err := patchSubResource(ctx, r.Status(), ephemeralRunnerSet, func(obj *v1alpha1.EphemeralRunnerSet) { | ||||
| 			obj.Status.CurrentReplicas = total | ||||
| 			obj.Status = desiredStatus | ||||
| 		}); err != nil { | ||||
| 			log.Error(err, "Failed to update status with current runners count") | ||||
| 			return ctrl.Result{}, err | ||||
|  |  | |||
|  | @ -559,6 +559,181 @@ var _ = Describe("Test EphemeralRunnerSet controller", func() { | |||
| 				ephemeralRunnerSetTestTimeout, | ||||
| 				ephemeralRunnerSetTestInterval).Should(BeEquivalentTo(0), "0 EphemeralRunner should be created") | ||||
| 		}) | ||||
| 
 | ||||
| 		It("Should update status on Ephemeral Runner state changes", func() { | ||||
| 			created := new(actionsv1alpha1.EphemeralRunnerSet) | ||||
| 			Eventually( | ||||
| 				func() error { | ||||
| 					return k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunnerSet.Name, Namespace: ephemeralRunnerSet.Namespace}, created) | ||||
| 				}, | ||||
| 				ephemeralRunnerSetTestTimeout, | ||||
| 				ephemeralRunnerSetTestInterval, | ||||
| 			).Should(Succeed(), "EphemeralRunnerSet should be created") | ||||
| 
 | ||||
| 			// Scale up the EphemeralRunnerSet
 | ||||
| 			updated := created.DeepCopy() | ||||
| 			updated.Spec.Replicas = 3 | ||||
| 			err := k8sClient.Update(ctx, updated) | ||||
| 			Expect(err).NotTo(HaveOccurred(), "failed to update EphemeralRunnerSet replica count") | ||||
| 
 | ||||
| 			runnerList := new(actionsv1alpha1.EphemeralRunnerList) | ||||
| 			Eventually( | ||||
| 				func() (bool, error) { | ||||
| 					err := k8sClient.List(ctx, runnerList, client.InNamespace(ephemeralRunnerSet.Namespace)) | ||||
| 					if err != nil { | ||||
| 						return false, err | ||||
| 					} | ||||
| 
 | ||||
| 					if len(runnerList.Items) != 3 { | ||||
| 						return false, err | ||||
| 					} | ||||
| 
 | ||||
| 					var pendingOriginal *v1alpha1.EphemeralRunner | ||||
| 					var runningOriginal *v1alpha1.EphemeralRunner | ||||
| 					var failedOriginal *v1alpha1.EphemeralRunner | ||||
| 					var empty []*v1alpha1.EphemeralRunner | ||||
| 					for _, runner := range runnerList.Items { | ||||
| 						switch runner.Status.RunnerId { | ||||
| 						case 101: | ||||
| 							pendingOriginal = runner.DeepCopy() | ||||
| 						case 102: | ||||
| 							runningOriginal = runner.DeepCopy() | ||||
| 						case 103: | ||||
| 							failedOriginal = runner.DeepCopy() | ||||
| 						default: | ||||
| 							empty = append(empty, runner.DeepCopy()) | ||||
| 						} | ||||
| 					} | ||||
| 
 | ||||
| 					refetch := false | ||||
| 					if pendingOriginal == nil { // if NO pending
 | ||||
| 						refetch = true | ||||
| 						pendingOriginal = empty[0] | ||||
| 						empty = empty[1:] | ||||
| 
 | ||||
| 						pending := pendingOriginal.DeepCopy() | ||||
| 						pending.Status.RunnerId = 101 | ||||
| 						pending.Status.Phase = corev1.PodPending | ||||
| 
 | ||||
| 						err = k8sClient.Status().Patch(ctx, pending, client.MergeFrom(pendingOriginal)) | ||||
| 						if err != nil { | ||||
| 							return false, err | ||||
| 						} | ||||
| 					} | ||||
| 
 | ||||
| 					if runningOriginal == nil { // if NO running
 | ||||
| 						refetch = true | ||||
| 						runningOriginal = empty[0] | ||||
| 						empty = empty[1:] | ||||
| 						running := runningOriginal.DeepCopy() | ||||
| 						running.Status.RunnerId = 102 | ||||
| 						running.Status.Phase = corev1.PodRunning | ||||
| 
 | ||||
| 						err = k8sClient.Status().Patch(ctx, running, client.MergeFrom(runningOriginal)) | ||||
| 						if err != nil { | ||||
| 							return false, err | ||||
| 						} | ||||
| 					} | ||||
| 
 | ||||
| 					if failedOriginal == nil { // if NO failed
 | ||||
| 						refetch = true | ||||
| 						failedOriginal = empty[0] | ||||
| 
 | ||||
| 						failed := pendingOriginal.DeepCopy() | ||||
| 						failed.Status.RunnerId = 103 | ||||
| 						failed.Status.Phase = corev1.PodFailed | ||||
| 
 | ||||
| 						err = k8sClient.Status().Patch(ctx, failed, client.MergeFrom(failedOriginal)) | ||||
| 						if err != nil { | ||||
| 							return false, err | ||||
| 						} | ||||
| 					} | ||||
| 
 | ||||
| 					return !refetch, nil | ||||
| 				}, | ||||
| 				ephemeralRunnerSetTestTimeout, | ||||
| 				ephemeralRunnerSetTestInterval, | ||||
| 			).Should(BeTrue(), "Failed to eventually update to one pending, one running and one failed") | ||||
| 
 | ||||
| 			desiredStatus := v1alpha1.EphemeralRunnerSetStatus{ | ||||
| 				CurrentReplicas:         3, | ||||
| 				PendingEphemeralRunners: 1, | ||||
| 				RunningEphemeralRunners: 1, | ||||
| 				FailedEphemeralRunners:  1, | ||||
| 			} | ||||
| 			Eventually( | ||||
| 				func() (v1alpha1.EphemeralRunnerSetStatus, error) { | ||||
| 					updated := new(v1alpha1.EphemeralRunnerSet) | ||||
| 					err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunnerSet.Name, Namespace: ephemeralRunnerSet.Namespace}, updated) | ||||
| 					if err != nil { | ||||
| 						return v1alpha1.EphemeralRunnerSetStatus{}, err | ||||
| 					} | ||||
| 					return updated.Status, nil | ||||
| 				}, | ||||
| 				ephemeralRunnerSetTestTimeout, | ||||
| 				ephemeralRunnerSetTestInterval, | ||||
| 			).Should(BeEquivalentTo(desiredStatus), "Status is not eventually updated to the desired one") | ||||
| 
 | ||||
| 			updated = new(v1alpha1.EphemeralRunnerSet) | ||||
| 			err = k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunnerSet.Name, Namespace: ephemeralRunnerSet.Namespace}, updated) | ||||
| 			Expect(err).NotTo(HaveOccurred(), "Failed to fetch ephemeral runner set") | ||||
| 
 | ||||
| 			updatedOriginal := updated.DeepCopy() | ||||
| 			updated.Spec.Replicas = 0 | ||||
| 
 | ||||
| 			err = k8sClient.Patch(ctx, updated, client.MergeFrom(updatedOriginal)) | ||||
| 			Expect(err).NotTo(HaveOccurred(), "Failed to patch ephemeral runner set with 0 replicas") | ||||
| 
 | ||||
| 			Eventually( | ||||
| 				func() (int, error) { | ||||
| 					runnerList = new(actionsv1alpha1.EphemeralRunnerList) | ||||
| 					err := k8sClient.List(ctx, runnerList, client.InNamespace(ephemeralRunnerSet.Namespace)) | ||||
| 					if err != nil { | ||||
| 						return -1, err | ||||
| 					} | ||||
| 					return len(runnerList.Items), nil | ||||
| 				}, | ||||
| 				ephemeralRunnerSetTestTimeout, | ||||
| 				ephemeralRunnerSetTestInterval, | ||||
| 			).Should(BeEquivalentTo(1), "Failed to eventually scale down") | ||||
| 
 | ||||
| 			desiredStatus = v1alpha1.EphemeralRunnerSetStatus{ | ||||
| 				CurrentReplicas:         1, | ||||
| 				PendingEphemeralRunners: 0, | ||||
| 				RunningEphemeralRunners: 0, | ||||
| 				FailedEphemeralRunners:  1, | ||||
| 			} | ||||
| 
 | ||||
| 			Eventually( | ||||
| 				func() (v1alpha1.EphemeralRunnerSetStatus, error) { | ||||
| 					updated := new(v1alpha1.EphemeralRunnerSet) | ||||
| 					err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunnerSet.Name, Namespace: ephemeralRunnerSet.Namespace}, updated) | ||||
| 					if err != nil { | ||||
| 						return v1alpha1.EphemeralRunnerSetStatus{}, err | ||||
| 					} | ||||
| 					return updated.Status, nil | ||||
| 				}, | ||||
| 				ephemeralRunnerSetTestTimeout, | ||||
| 				ephemeralRunnerSetTestInterval, | ||||
| 			).Should(BeEquivalentTo(desiredStatus), "Status is not eventually updated to the desired one") | ||||
| 
 | ||||
| 			err = k8sClient.Delete(ctx, &runnerList.Items[0]) | ||||
| 			Expect(err).To(BeNil(), "Failed to delete failed ephemeral runner") | ||||
| 
 | ||||
| 			desiredStatus = v1alpha1.EphemeralRunnerSetStatus{} // empty
 | ||||
| 			Eventually( | ||||
| 				func() (v1alpha1.EphemeralRunnerSetStatus, error) { | ||||
| 					updated := new(v1alpha1.EphemeralRunnerSet) | ||||
| 					err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunnerSet.Name, Namespace: ephemeralRunnerSet.Namespace}, updated) | ||||
| 					if err != nil { | ||||
| 						return v1alpha1.EphemeralRunnerSetStatus{}, err | ||||
| 					} | ||||
| 					return updated.Status, nil | ||||
| 				}, | ||||
| 				ephemeralRunnerSetTestTimeout, | ||||
| 				ephemeralRunnerSetTestInterval, | ||||
| 			).Should(BeEquivalentTo(desiredStatus), "Status is not eventually updated to the desired one") | ||||
| 		}) | ||||
| 	}) | ||||
| }) | ||||
| 
 | ||||
|  | @ -821,12 +996,13 @@ var _ = Describe("Test EphemeralRunnerSet controller with proxy settings", func( | |||
| 		err = k8sClient.Status().Patch(ctx, runner, client.MergeFrom(&runnerList.Items[0])) | ||||
| 		Expect(err).NotTo(HaveOccurred(), "failed to update ephemeral runner status") | ||||
| 
 | ||||
| 		updatedRunnerSet := new(actionsv1alpha1.EphemeralRunnerSet) | ||||
| 		err = k8sClient.Get(ctx, client.ObjectKey{Namespace: ephemeralRunnerSet.Namespace, Name: ephemeralRunnerSet.Name}, updatedRunnerSet) | ||||
| 		runnerSet := new(actionsv1alpha1.EphemeralRunnerSet) | ||||
| 		err = k8sClient.Get(ctx, client.ObjectKey{Namespace: ephemeralRunnerSet.Namespace, Name: ephemeralRunnerSet.Name}, runnerSet) | ||||
| 		Expect(err).NotTo(HaveOccurred(), "failed to get EphemeralRunnerSet") | ||||
| 
 | ||||
| 		updatedRunnerSet := runnerSet.DeepCopy() | ||||
| 		updatedRunnerSet.Spec.Replicas = 0 | ||||
| 		err = k8sClient.Update(ctx, updatedRunnerSet) | ||||
| 		err = k8sClient.Patch(ctx, updatedRunnerSet, client.MergeFrom(runnerSet)) | ||||
| 		Expect(err).NotTo(HaveOccurred(), "failed to update EphemeralRunnerSet") | ||||
| 
 | ||||
| 		Eventually( | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue