Use metrics to display runner statuses instead of status field for EphemeralRunnerSet and AutoscalingRunnerSet (#4557)
This commit is contained in:
parent
368e2f28b8
commit
f6a3d738de
|
|
@ -42,11 +42,11 @@ type AutoscalingListenerSpec struct {
|
|||
// +optional
|
||||
EphemeralRunnerSetName string `json:"ephemeralRunnerSetName,omitempty"`
|
||||
|
||||
// +kubebuilder:validation:Minimum:=0
|
||||
// +kubebuilder:validation:Minimum=0
|
||||
// +optional
|
||||
MaxRunners int `json:"maxRunners,omitempty"`
|
||||
|
||||
// +kubebuilder:validation:Minimum:=0
|
||||
// +kubebuilder:validation:Minimum=0
|
||||
// +optional
|
||||
MinRunners int `json:"minRunners,omitempty"`
|
||||
|
||||
|
|
@ -109,6 +109,7 @@ type AutoscalingListener struct {
|
|||
Status AutoscalingListenerStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// AutoscalingListenerList is a list of AutoscalingListener resources
|
||||
// +kubebuilder:object:root=true
|
||||
// AutoscalingListenerList contains a list of AutoscalingListener
|
||||
type AutoscalingListenerList struct {
|
||||
|
|
|
|||
|
|
@ -317,20 +317,8 @@ type HistogramMetric struct {
|
|||
|
||||
// AutoscalingRunnerSetStatus defines the observed state of AutoscalingRunnerSet
|
||||
type AutoscalingRunnerSetStatus struct {
|
||||
// +optional
|
||||
CurrentRunners int `json:"currentRunners"`
|
||||
|
||||
// +optional
|
||||
Phase AutoscalingRunnerSetPhase `json:"phase"`
|
||||
|
||||
// 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"`
|
||||
}
|
||||
|
||||
type AutoscalingRunnerSetPhase string
|
||||
|
|
|
|||
|
|
@ -40,15 +40,6 @@ 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.
|
||||
// +optional
|
||||
CurrentReplicas int `json:"currentReplicas"`
|
||||
// +optional
|
||||
PendingEphemeralRunners int `json:"pendingEphemeralRunners"`
|
||||
// +optional
|
||||
RunningEphemeralRunners int `json:"runningEphemeralRunners"`
|
||||
// +optional
|
||||
FailedEphemeralRunners int `json:"failedEphemeralRunners"`
|
||||
// +optional
|
||||
Phase EphemeralRunnerSetPhase `json:"phase"`
|
||||
}
|
||||
|
|
@ -66,11 +57,6 @@ const (
|
|||
// +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
|
||||
// +kubebuilder:printcolumn:JSONPath=".status.phase",name=Phase,type=string
|
||||
|
||||
// EphemeralRunnerSet is the Schema for the ephemeralrunnersets API
|
||||
|
|
|
|||
|
|
@ -16541,16 +16541,8 @@ spec:
|
|||
status:
|
||||
description: AutoscalingRunnerSetStatus defines the observed state of AutoscalingRunnerSet
|
||||
properties:
|
||||
currentRunners:
|
||||
type: integer
|
||||
failedEphemeralRunners:
|
||||
type: integer
|
||||
pendingEphemeralRunners:
|
||||
type: integer
|
||||
phase:
|
||||
type: string
|
||||
runningEphemeralRunners:
|
||||
type: integer
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
|
|
|
|||
|
|
@ -18,21 +18,6 @@ spec:
|
|||
- jsonPath: .spec.replicas
|
||||
name: DesiredReplicas
|
||||
type: integer
|
||||
- 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
|
||||
- jsonPath: .status.phase
|
||||
name: Phase
|
||||
type: string
|
||||
|
|
@ -8310,18 +8295,9 @@ spec:
|
|||
status:
|
||||
description: EphemeralRunnerSetStatus defines the observed state of EphemeralRunnerSet
|
||||
properties:
|
||||
currentReplicas:
|
||||
description: CurrentReplicas is the number of currently running EphemeralRunner resources being managed by this EphemeralRunnerSet.
|
||||
type: integer
|
||||
failedEphemeralRunners:
|
||||
type: integer
|
||||
pendingEphemeralRunners:
|
||||
type: integer
|
||||
phase:
|
||||
description: EphemeralRunnerSetPhase is the phase of the ephemeral runner set resource
|
||||
type: string
|
||||
runningEphemeralRunners:
|
||||
type: integer
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
|
|
|
|||
|
|
@ -16541,16 +16541,8 @@ spec:
|
|||
status:
|
||||
description: AutoscalingRunnerSetStatus defines the observed state of AutoscalingRunnerSet
|
||||
properties:
|
||||
currentRunners:
|
||||
type: integer
|
||||
failedEphemeralRunners:
|
||||
type: integer
|
||||
pendingEphemeralRunners:
|
||||
type: integer
|
||||
phase:
|
||||
type: string
|
||||
runningEphemeralRunners:
|
||||
type: integer
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
|
|
|
|||
|
|
@ -18,21 +18,6 @@ spec:
|
|||
- jsonPath: .spec.replicas
|
||||
name: DesiredReplicas
|
||||
type: integer
|
||||
- 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
|
||||
- jsonPath: .status.phase
|
||||
name: Phase
|
||||
type: string
|
||||
|
|
@ -8310,18 +8295,9 @@ spec:
|
|||
status:
|
||||
description: EphemeralRunnerSetStatus defines the observed state of EphemeralRunnerSet
|
||||
properties:
|
||||
currentReplicas:
|
||||
description: CurrentReplicas is the number of currently running EphemeralRunner resources being managed by this EphemeralRunnerSet.
|
||||
type: integer
|
||||
failedEphemeralRunners:
|
||||
type: integer
|
||||
pendingEphemeralRunners:
|
||||
type: integer
|
||||
phase:
|
||||
description: EphemeralRunnerSetPhase is the phase of the ephemeral runner set resource
|
||||
type: string
|
||||
runningEphemeralRunners:
|
||||
type: integer
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
|
|
|
|||
|
|
@ -16541,16 +16541,8 @@ spec:
|
|||
status:
|
||||
description: AutoscalingRunnerSetStatus defines the observed state of AutoscalingRunnerSet
|
||||
properties:
|
||||
currentRunners:
|
||||
type: integer
|
||||
failedEphemeralRunners:
|
||||
type: integer
|
||||
pendingEphemeralRunners:
|
||||
type: integer
|
||||
phase:
|
||||
type: string
|
||||
runningEphemeralRunners:
|
||||
type: integer
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
|
|
|
|||
|
|
@ -18,21 +18,6 @@ spec:
|
|||
- jsonPath: .spec.replicas
|
||||
name: DesiredReplicas
|
||||
type: integer
|
||||
- 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
|
||||
- jsonPath: .status.phase
|
||||
name: Phase
|
||||
type: string
|
||||
|
|
@ -8310,18 +8295,9 @@ spec:
|
|||
status:
|
||||
description: EphemeralRunnerSetStatus defines the observed state of EphemeralRunnerSet
|
||||
properties:
|
||||
currentReplicas:
|
||||
description: CurrentReplicas is the number of currently running EphemeralRunner resources being managed by this EphemeralRunnerSet.
|
||||
type: integer
|
||||
failedEphemeralRunners:
|
||||
type: integer
|
||||
pendingEphemeralRunners:
|
||||
type: integer
|
||||
phase:
|
||||
description: EphemeralRunnerSetPhase is the phase of the ephemeral runner set resource
|
||||
type: string
|
||||
runningEphemeralRunners:
|
||||
type: integer
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
|
|
|
|||
|
|
@ -292,18 +292,6 @@ func (r *AutoscalingRunnerSetReconciler) Reconcile(ctx context.Context, req ctrl
|
|||
}
|
||||
|
||||
if ephemeralRunnerSet.Annotations[annotationKeyIntegrityHash] != desired.Annotations[annotationKeyIntegrityHash] {
|
||||
// When runners are actively processing jobs, defer the spec update:
|
||||
// delete the listener to stop accepting new jobs, but leave the ERS
|
||||
// (and its running pods) untouched until all jobs have drained.
|
||||
if ephemeralRunnerSet.Status.RunningEphemeralRunners+ephemeralRunnerSet.Status.PendingEphemeralRunners > 0 {
|
||||
log.Info("Ephemeral runner set spec changed but runners are still active; deleting listener to stop new jobs")
|
||||
if _, err := r.cleanupListener(ctx, &autoscalingRunnerSet, log); err != nil {
|
||||
log.Error(err, "Failed to clean up listener while waiting for runners to drain")
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
return ctrl.Result{RequeueAfter: 1 * time.Second}, nil
|
||||
}
|
||||
|
||||
original := ephemeralRunnerSet.DeepCopy()
|
||||
ephemeralRunnerSet.Spec.EphemeralRunnerMetadata = desired.Spec.EphemeralRunnerMetadata
|
||||
ephemeralRunnerSet.Spec.EphemeralRunnerSpec = desired.Spec.EphemeralRunnerSpec
|
||||
|
|
@ -386,7 +374,6 @@ func (r *AutoscalingRunnerSetReconciler) Reconcile(ctx context.Context, req ctrl
|
|||
if err := r.updateStatus(
|
||||
ctx,
|
||||
&autoscalingRunnerSet,
|
||||
&ephemeralRunnerSet,
|
||||
v1alpha1.AutoscalingRunnerSetPhaseRunning,
|
||||
log,
|
||||
); err != nil {
|
||||
|
|
@ -432,24 +419,14 @@ func (r *AutoscalingRunnerSetReconciler) cleanUpResources(ctx context.Context, a
|
|||
}
|
||||
|
||||
// Update the status of autoscaling runner set if necessary
|
||||
func (r *AutoscalingRunnerSetReconciler) updateStatus(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, ephemeralRunnerSet *v1alpha1.EphemeralRunnerSet, phase v1alpha1.AutoscalingRunnerSetPhase, log logr.Logger) error {
|
||||
countDiff := ephemeralRunnerSet != nil && ephemeralRunnerSet.Status.CurrentReplicas != autoscalingRunnerSet.Status.CurrentRunners
|
||||
func (r *AutoscalingRunnerSetReconciler) updateStatus(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, phase v1alpha1.AutoscalingRunnerSetPhase, log logr.Logger) error {
|
||||
phaseDiff := phase != autoscalingRunnerSet.Status.Phase
|
||||
if !countDiff && !phaseDiff {
|
||||
if !phaseDiff {
|
||||
return nil
|
||||
}
|
||||
|
||||
original := autoscalingRunnerSet.DeepCopy()
|
||||
if phaseDiff {
|
||||
autoscalingRunnerSet.Status.Phase = phase
|
||||
}
|
||||
|
||||
if countDiff && ephemeralRunnerSet != nil {
|
||||
autoscalingRunnerSet.Status.CurrentRunners = ephemeralRunnerSet.Status.CurrentReplicas
|
||||
autoscalingRunnerSet.Status.PendingEphemeralRunners = ephemeralRunnerSet.Status.PendingEphemeralRunners
|
||||
autoscalingRunnerSet.Status.RunningEphemeralRunners = ephemeralRunnerSet.Status.RunningEphemeralRunners
|
||||
autoscalingRunnerSet.Status.FailedEphemeralRunners = ephemeralRunnerSet.Status.FailedEphemeralRunners
|
||||
}
|
||||
autoscalingRunnerSet.Status.Phase = phase
|
||||
|
||||
if err := r.Status().Patch(ctx, autoscalingRunnerSet, client.MergeFrom(original)); err != nil {
|
||||
log.Error(err, "Failed to patch autoscaling runner set status")
|
||||
|
|
|
|||
|
|
@ -837,111 +837,6 @@ var _ = Describe("Test AutoScalingRunnerSet controller", Ordered, func() {
|
|||
})
|
||||
})
|
||||
|
||||
Context("When updating an AutoscalingRunnerSet with running or pending jobs", func() {
|
||||
It("It should wait for running and pending jobs to finish before applying the update.", func() {
|
||||
// Wait till the listener is created
|
||||
listener := new(v1alpha1.AutoscalingListener)
|
||||
Eventually(
|
||||
func() error {
|
||||
return k8sClient.Get(ctx, client.ObjectKey{Name: scaleSetListenerName(autoscalingRunnerSet), Namespace: autoscalingRunnerSet.Namespace}, listener)
|
||||
},
|
||||
autoscalingRunnerSetTestTimeout,
|
||||
autoscalingRunnerSetTestInterval,
|
||||
).Should(Succeed(), "Listener should be created")
|
||||
|
||||
// Wait till the ephemeral runner set is created
|
||||
Eventually(
|
||||
func() (int, error) {
|
||||
runnerSetList := new(v1alpha1.EphemeralRunnerSetList)
|
||||
err := k8sClient.List(ctx, runnerSetList, client.InNamespace(autoscalingRunnerSet.Namespace))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return len(runnerSetList.Items), nil
|
||||
},
|
||||
autoscalingRunnerSetTestTimeout,
|
||||
autoscalingRunnerSetTestInterval,
|
||||
).Should(BeEquivalentTo(1), "Only one EphemeralRunnerSet should be created")
|
||||
|
||||
runnerSetList := new(v1alpha1.EphemeralRunnerSetList)
|
||||
err := k8sClient.List(ctx, runnerSetList, client.InNamespace(autoscalingRunnerSet.Namespace))
|
||||
Expect(err).NotTo(HaveOccurred(), "failed to list EphemeralRunnerSet")
|
||||
|
||||
// Emulate running and pending jobs
|
||||
runnerSet := runnerSetList.Items[0]
|
||||
activeRunnerSet := runnerSet.DeepCopy()
|
||||
activeRunnerSet.Status.CurrentReplicas = 6
|
||||
activeRunnerSet.Status.FailedEphemeralRunners = 1
|
||||
activeRunnerSet.Status.RunningEphemeralRunners = 2
|
||||
activeRunnerSet.Status.PendingEphemeralRunners = 3
|
||||
|
||||
desiredStatus := v1alpha1.AutoscalingRunnerSetStatus{
|
||||
CurrentRunners: activeRunnerSet.Status.CurrentReplicas,
|
||||
Phase: v1alpha1.AutoscalingRunnerSetPhaseRunning,
|
||||
PendingEphemeralRunners: activeRunnerSet.Status.PendingEphemeralRunners,
|
||||
RunningEphemeralRunners: activeRunnerSet.Status.RunningEphemeralRunners,
|
||||
FailedEphemeralRunners: activeRunnerSet.Status.FailedEphemeralRunners,
|
||||
}
|
||||
|
||||
err = k8sClient.Status().Patch(ctx, activeRunnerSet, 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")
|
||||
|
||||
// Patch the AutoScalingRunnerSet image which should trigger
|
||||
// the recreation of the Listener and EphemeralRunnerSet
|
||||
patched := autoscalingRunnerSet.DeepCopy()
|
||||
if patched.Annotations == nil {
|
||||
patched.Annotations = make(map[string]string)
|
||||
}
|
||||
patched.Annotations[annotationKeyIntegrityHash] = "testgroup2"
|
||||
patched.Spec.Template.Spec = corev1.PodSpec{
|
||||
Containers: []corev1.Container{
|
||||
{
|
||||
Name: "runner",
|
||||
Image: "ghcr.io/actions/abcd:1.1.1",
|
||||
},
|
||||
},
|
||||
}
|
||||
err = k8sClient.Patch(ctx, patched, client.MergeFrom(autoscalingRunnerSet))
|
||||
Expect(err).NotTo(HaveOccurred(), "failed to patch AutoScalingRunnerSet")
|
||||
autoscalingRunnerSet = patched.DeepCopy()
|
||||
|
||||
// The EphemeralRunnerSet should not be recreated
|
||||
Consistently(
|
||||
func() (string, error) {
|
||||
runnerSetList := new(v1alpha1.EphemeralRunnerSetList)
|
||||
err := k8sClient.List(ctx, runnerSetList, client.InNamespace(autoscalingRunnerSet.Namespace))
|
||||
Expect(err).NotTo(HaveOccurred(), "failed to fetch AutoScalingRunnerSet")
|
||||
return runnerSetList.Items[0].Name, nil
|
||||
},
|
||||
autoscalingRunnerSetTestTimeout,
|
||||
autoscalingRunnerSetTestInterval,
|
||||
).Should(Equal(activeRunnerSet.Name), "The EphemeralRunnerSet should not be recreated")
|
||||
|
||||
// The listener should not be recreated
|
||||
Consistently(
|
||||
func() error {
|
||||
return k8sClient.Get(ctx, client.ObjectKey{Name: scaleSetListenerName(autoscalingRunnerSet), Namespace: autoscalingRunnerSet.Namespace}, listener)
|
||||
},
|
||||
autoscalingRunnerSetTestTimeout,
|
||||
autoscalingRunnerSetTestInterval,
|
||||
).ShouldNot(Succeed(), "Listener should not be recreated")
|
||||
})
|
||||
})
|
||||
|
||||
It("Should update Status on EphemeralRunnerSet status Update", func() {
|
||||
ars := new(v1alpha1.AutoscalingRunnerSet)
|
||||
Eventually(
|
||||
|
|
@ -978,17 +873,10 @@ var _ = Describe("Test AutoScalingRunnerSet controller", Ordered, func() {
|
|||
|
||||
runnerSet := runnerSetList.Items[0]
|
||||
statusUpdate := runnerSet.DeepCopy()
|
||||
statusUpdate.Status.CurrentReplicas = 6
|
||||
statusUpdate.Status.FailedEphemeralRunners = 1
|
||||
statusUpdate.Status.RunningEphemeralRunners = 2
|
||||
statusUpdate.Status.PendingEphemeralRunners = 3
|
||||
statusUpdate.Status.Phase = v1alpha1.EphemeralRunnerSetPhaseRunning
|
||||
|
||||
desiredStatus := v1alpha1.AutoscalingRunnerSetStatus{
|
||||
CurrentRunners: statusUpdate.Status.CurrentReplicas,
|
||||
Phase: v1alpha1.AutoscalingRunnerSetPhaseRunning,
|
||||
PendingEphemeralRunners: statusUpdate.Status.PendingEphemeralRunners,
|
||||
RunningEphemeralRunners: statusUpdate.Status.RunningEphemeralRunners,
|
||||
FailedEphemeralRunners: statusUpdate.Status.FailedEphemeralRunners,
|
||||
Phase: v1alpha1.AutoscalingRunnerSetPhaseRunning,
|
||||
}
|
||||
|
||||
err := k8sClient.Status().Patch(ctx, statusUpdate, client.MergeFrom(&runnerSet))
|
||||
|
|
|
|||
|
|
@ -22,9 +22,12 @@ import (
|
|||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/actions/actions-runner-controller/apis/actions.github.com/v1alpha1"
|
||||
"github.com/actions/actions-runner-controller/controllers/actions.github.com/metrics"
|
||||
"github.com/actions/actions-runner-controller/github/actions"
|
||||
"github.com/actions/scaleset"
|
||||
"github.com/go-logr/logr"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
|
@ -46,11 +49,19 @@ const (
|
|||
// EphemeralRunnerReconciler reconciles a EphemeralRunner object
|
||||
type EphemeralRunnerReconciler struct {
|
||||
client.Client
|
||||
Log logr.Logger
|
||||
Scheme *runtime.Scheme
|
||||
Log logr.Logger
|
||||
Scheme *runtime.Scheme
|
||||
PublishMetrics bool
|
||||
ResourceBuilder
|
||||
}
|
||||
|
||||
var ephemeralRunnerPhaseMetrics = struct {
|
||||
sync.Mutex
|
||||
phases map[types.NamespacedName]v1alpha1.EphemeralRunnerPhase
|
||||
}{
|
||||
phases: map[types.NamespacedName]v1alpha1.EphemeralRunnerPhase{},
|
||||
}
|
||||
|
||||
// precompute backoff durations for failed ephemeral runners
|
||||
// the len(failedRunnerBackoff) must be equal to maxFailures + 1
|
||||
var failedRunnerBackoff = []time.Duration{
|
||||
|
|
@ -86,6 +97,8 @@ func (r *EphemeralRunnerReconciler) Reconcile(ctx context.Context, req ctrl.Requ
|
|||
original := ephemeralRunner.DeepCopy()
|
||||
|
||||
if !ephemeralRunner.DeletionTimestamp.IsZero() {
|
||||
r.publishEphemeralRunnerPhaseMetric(&ephemeralRunner, "", log)
|
||||
|
||||
if !controllerutil.ContainsFinalizer(&ephemeralRunner, ephemeralRunnerFinalizerName) {
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
|
@ -142,6 +155,8 @@ func (r *EphemeralRunnerReconciler) Reconcile(ctx context.Context, req ctrl.Requ
|
|||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
||||
r.publishEphemeralRunnerPhaseMetric(&ephemeralRunner, ephemeralRunner.Status.Phase, log)
|
||||
|
||||
if ephemeralRunner.IsDone() {
|
||||
log.Info("Cleaning up resources after after ephemeral runner termination", "phase", ephemeralRunner.Status.Phase)
|
||||
err := r.cleanupResources(ctx, &ephemeralRunner, log)
|
||||
|
|
@ -337,6 +352,10 @@ func (r *EphemeralRunnerReconciler) Reconcile(ctx context.Context, req ctrl.Requ
|
|||
// If the runner container exits with 0, we assume that the runner has finished successfully.
|
||||
// If side-car container exits with non-zero, it shouldn't affect the runner. Runner exit code
|
||||
// drives the controller's inference of whether the job has succeeded or failed.
|
||||
if err := r.markAsSucceeded(ctx, &ephemeralRunner, pod, log); err != nil {
|
||||
log.Error(err, "Failed to set ephemeral runner to phase Succeeded")
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
if err := r.Delete(ctx, &ephemeralRunner); err != nil {
|
||||
log.Error(err, "Failed to delete ephemeral runner after successful completion")
|
||||
return ctrl.Result{}, err
|
||||
|
|
@ -390,6 +409,10 @@ func (r *EphemeralRunnerReconciler) Reconcile(ctx context.Context, req ctrl.Requ
|
|||
|
||||
default: // succeeded
|
||||
log.Info("Ephemeral runner has finished successfully, deleting ephemeral runner", "exitCode", cs.State.Terminated.ExitCode)
|
||||
if err := r.markAsSucceeded(ctx, &ephemeralRunner, pod, log); err != nil {
|
||||
log.Error(err, "Failed to set ephemeral runner to phase Succeeded")
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
if err := r.Delete(ctx, &ephemeralRunner); err != nil {
|
||||
log.Error(err, "Failed to delete ephemeral runner after successful completion")
|
||||
return ctrl.Result{}, err
|
||||
|
|
@ -583,6 +606,7 @@ func (r *EphemeralRunnerReconciler) markAsFailed(ctx context.Context, ephemeralR
|
|||
if err := r.Status().Patch(ctx, ephemeralRunner, client.MergeFrom(original)); err != nil {
|
||||
return fmt.Errorf("failed to update ephemeral runner status Phase/Message: %w", err)
|
||||
}
|
||||
r.publishEphemeralRunnerPhaseMetric(ephemeralRunner, ephemeralRunner.Status.Phase, log)
|
||||
|
||||
log.Info("Removing the runner from the service")
|
||||
if err := r.deleteRunnerFromService(ctx, ephemeralRunner, log); err != nil {
|
||||
|
|
@ -604,6 +628,7 @@ func (r *EphemeralRunnerReconciler) markAsOutdated(ctx context.Context, ephemera
|
|||
if err := r.Status().Patch(ctx, ephemeralRunner, client.MergeFrom(original)); err != nil {
|
||||
return fmt.Errorf("failed to update ephemeral runner status Phase/Message: %w", err)
|
||||
}
|
||||
r.publishEphemeralRunnerPhaseMetric(ephemeralRunner, ephemeralRunner.Status.Phase, log)
|
||||
|
||||
log.Info("Removing the runner from the service")
|
||||
if err := r.deleteRunnerFromService(ctx, ephemeralRunner, log); err != nil {
|
||||
|
|
@ -612,6 +637,23 @@ func (r *EphemeralRunnerReconciler) markAsOutdated(ctx context.Context, ephemera
|
|||
return nil
|
||||
}
|
||||
|
||||
func (r *EphemeralRunnerReconciler) markAsSucceeded(ctx context.Context, ephemeralRunner *v1alpha1.EphemeralRunner, pod *corev1.Pod, log logr.Logger) error {
|
||||
log.Info("Updating ephemeral runner status to Succeeded")
|
||||
|
||||
original := ephemeralRunner.DeepCopy()
|
||||
ephemeralRunner.Status.Phase = v1alpha1.EphemeralRunnerPhaseSucceeded
|
||||
ephemeralRunner.Status.Ready = false
|
||||
ephemeralRunner.Status.Reason = pod.Status.Reason
|
||||
ephemeralRunner.Status.Message = pod.Status.Message
|
||||
if err := r.Status().Patch(ctx, ephemeralRunner, client.MergeFrom(original)); err != nil {
|
||||
return fmt.Errorf("failed to update ephemeral runner status Phase/Message: %w", err)
|
||||
}
|
||||
r.publishEphemeralRunnerPhaseMetric(ephemeralRunner, ephemeralRunner.Status.Phase, log)
|
||||
|
||||
log.Info("EphemeralRunner is marked as Succeeded")
|
||||
return nil
|
||||
}
|
||||
|
||||
// deletePodAsFailed is responsible for deleting the pod and updating the .Status.Failures for tracking failure count.
|
||||
// It should not be responsible for setting the status to Failed.
|
||||
//
|
||||
|
|
@ -835,11 +877,61 @@ func (r *EphemeralRunnerReconciler) updateRunStatusFromPod(ctx context.Context,
|
|||
if err := r.Status().Patch(ctx, ephemeralRunner, client.MergeFrom(original)); err != nil {
|
||||
return fmt.Errorf("failed to update runner status for Phase/Reason/Message/Ready: %w", err)
|
||||
}
|
||||
r.publishEphemeralRunnerPhaseMetric(ephemeralRunner, ephemeralRunner.Status.Phase, log)
|
||||
|
||||
log.Info("Updated ephemeral runner status")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *EphemeralRunnerReconciler) publishEphemeralRunnerPhaseMetric(ephemeralRunner *v1alpha1.EphemeralRunner, phase v1alpha1.EphemeralRunnerPhase, log logr.Logger) {
|
||||
if !r.PublishMetrics {
|
||||
return
|
||||
}
|
||||
|
||||
commonLabels, err := ephemeralRunnerMetricLabels(ephemeralRunner)
|
||||
if err != nil {
|
||||
log.Error(err, "Failed to build ephemeral runner metric labels")
|
||||
return
|
||||
}
|
||||
|
||||
key := types.NamespacedName{Namespace: ephemeralRunner.Namespace, Name: ephemeralRunner.Name}
|
||||
|
||||
ephemeralRunnerPhaseMetrics.Lock()
|
||||
defer ephemeralRunnerPhaseMetrics.Unlock()
|
||||
|
||||
previousPhase, ok := ephemeralRunnerPhaseMetrics.phases[key]
|
||||
if ok && previousPhase == phase {
|
||||
return
|
||||
}
|
||||
|
||||
if ok {
|
||||
metrics.SubEphemeralRunner(commonLabels, previousPhase)
|
||||
}
|
||||
|
||||
if phase == "" {
|
||||
delete(ephemeralRunnerPhaseMetrics.phases, key)
|
||||
return
|
||||
}
|
||||
|
||||
metrics.AddEphemeralRunner(commonLabels, phase)
|
||||
ephemeralRunnerPhaseMetrics.phases[key] = phase
|
||||
}
|
||||
|
||||
func ephemeralRunnerMetricLabels(ephemeralRunner *v1alpha1.EphemeralRunner) (metrics.CommonLabels, error) {
|
||||
parsedURL, err := actions.ParseGitHubConfigFromURL(ephemeralRunner.Spec.GitHubConfigURL)
|
||||
if err != nil {
|
||||
return metrics.CommonLabels{}, fmt.Errorf("github config URL is invalid: %w", err)
|
||||
}
|
||||
|
||||
return metrics.CommonLabels{
|
||||
Name: ephemeralRunner.Labels[LabelKeyGitHubScaleSetName],
|
||||
Namespace: ephemeralRunner.Labels[LabelKeyGitHubScaleSetNamespace],
|
||||
Repository: parsedURL.Repository,
|
||||
Organization: parsedURL.Organization,
|
||||
Enterprise: parsedURL.Enterprise,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *EphemeralRunnerReconciler) deleteRunnerFromService(ctx context.Context, ephemeralRunner *v1alpha1.EphemeralRunner, log logr.Logger) error {
|
||||
client, err := r.GetActionsService(ctx, ephemeralRunner)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -27,9 +27,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/actions/actions-runner-controller/apis/actions.github.com/v1alpha1"
|
||||
"github.com/actions/actions-runner-controller/controllers/actions.github.com/metrics"
|
||||
"github.com/actions/actions-runner-controller/controllers/actions.github.com/multiclient"
|
||||
"github.com/actions/actions-runner-controller/github/actions"
|
||||
"github.com/actions/scaleset"
|
||||
"github.com/go-logr/logr"
|
||||
"go.uber.org/multierr"
|
||||
|
|
@ -51,9 +49,8 @@ const (
|
|||
// EphemeralRunnerSetReconciler reconciles a EphemeralRunnerSet object
|
||||
type EphemeralRunnerSetReconciler struct {
|
||||
client.Client
|
||||
Log logr.Logger
|
||||
Scheme *runtime.Scheme
|
||||
PublishMetrics bool
|
||||
Log logr.Logger
|
||||
Scheme *runtime.Scheme
|
||||
ResourceBuilder
|
||||
}
|
||||
|
||||
|
|
@ -205,29 +202,6 @@ func (r *EphemeralRunnerSetReconciler) Reconcile(ctx context.Context, req ctrl.R
|
|||
"deleting", len(ephemeralRunnersByState.deleting),
|
||||
)
|
||||
|
||||
if r.PublishMetrics {
|
||||
githubConfigURL := ephemeralRunnerSet.Spec.EphemeralRunnerSpec.GitHubConfigURL
|
||||
parsedURL, err := actions.ParseGitHubConfigFromURL(githubConfigURL)
|
||||
if err != nil {
|
||||
log.Error(err, "Github Config URL is invalid", "URL", githubConfigURL)
|
||||
// stop reconciling on this object
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
||||
metrics.SetEphemeralRunnerCountsByStatus(
|
||||
metrics.CommonLabels{
|
||||
Name: ephemeralRunnerSet.Labels[LabelKeyGitHubScaleSetName],
|
||||
Namespace: ephemeralRunnerSet.Labels[LabelKeyGitHubScaleSetNamespace],
|
||||
Repository: parsedURL.Repository,
|
||||
Organization: parsedURL.Organization,
|
||||
Enterprise: parsedURL.Enterprise,
|
||||
},
|
||||
len(ephemeralRunnersByState.pending),
|
||||
len(ephemeralRunnersByState.running),
|
||||
len(ephemeralRunnersByState.failed),
|
||||
)
|
||||
}
|
||||
|
||||
total := ephemeralRunnersByState.scaleTotal()
|
||||
if ephemeralRunnerSet.Spec.PatchID == 0 || ephemeralRunnerSet.Spec.PatchID != ephemeralRunnersByState.latestPatchID {
|
||||
defer func() {
|
||||
|
|
@ -272,7 +246,6 @@ func (r *EphemeralRunnerSetReconciler) Reconcile(ctx context.Context, req ctrl.R
|
|||
|
||||
func (r *EphemeralRunnerSetReconciler) updateStatus(ctx context.Context, ephemeralRunnerSet *v1alpha1.EphemeralRunnerSet, state *ephemeralRunnersByState, log logr.Logger) error {
|
||||
original := ephemeralRunnerSet.DeepCopy()
|
||||
total := state.scaleTotal()
|
||||
var phase v1alpha1.EphemeralRunnerSetPhase
|
||||
switch {
|
||||
case len(state.outdated) > 0:
|
||||
|
|
@ -283,11 +256,7 @@ func (r *EphemeralRunnerSetReconciler) updateStatus(ctx context.Context, ephemer
|
|||
phase = ephemeralRunnerSet.Status.Phase
|
||||
}
|
||||
desiredStatus := v1alpha1.EphemeralRunnerSetStatus{
|
||||
CurrentReplicas: total,
|
||||
Phase: phase,
|
||||
PendingEphemeralRunners: len(state.pending),
|
||||
RunningEphemeralRunners: len(state.running),
|
||||
FailedEphemeralRunners: len(state.failed),
|
||||
Phase: phase,
|
||||
}
|
||||
|
||||
// Update the status if needed.
|
||||
|
|
|
|||
|
|
@ -9,14 +9,21 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/actions/actions-runner-controller/controllers/actions.github.com/metrics"
|
||||
"github.com/actions/actions-runner-controller/github/actions"
|
||||
"github.com/actions/scaleset"
|
||||
prometheusdto "github.com/prometheus/client_model/go"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
kerrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
logf "sigs.k8s.io/controller-runtime/pkg/log"
|
||||
controllerMetrics "sigs.k8s.io/controller-runtime/pkg/metrics"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
|
|
@ -34,10 +41,92 @@ const (
|
|||
ephemeralRunnerSetTestInterval = time.Millisecond * 250
|
||||
)
|
||||
|
||||
var registerActionsGithubMetricsForTest sync.Once
|
||||
|
||||
func TestPrecomputedConstants(t *testing.T) {
|
||||
require.Equal(t, len(failedRunnerBackoff), maxFailures+1)
|
||||
}
|
||||
|
||||
func expectEphemeralRunnerPhase(ctx context.Context, ephemeralRunner *v1alpha1.EphemeralRunner, phase v1alpha1.EphemeralRunnerPhase) {
|
||||
updated := new(v1alpha1.EphemeralRunner)
|
||||
err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, updated)
|
||||
Expect(err).NotTo(HaveOccurred(), "failed to get ephemeral runner")
|
||||
Expect(updated.Status.Phase).To(Equal(phase))
|
||||
}
|
||||
|
||||
func expectEphemeralRunnerPhaseMetric(ephemeralRunner *v1alpha1.EphemeralRunner, phase v1alpha1.EphemeralRunnerPhase, expected float64) {
|
||||
metricName := ephemeralRunnerPhaseMetricName(phase)
|
||||
Expect(metricName).NotTo(BeEmpty(), "unexpected ephemeral runner phase")
|
||||
|
||||
parsedURL, err := actions.ParseGitHubConfigFromURL(ephemeralRunner.Spec.GitHubConfigURL)
|
||||
Expect(err).NotTo(HaveOccurred(), "failed to parse GitHub config URL")
|
||||
|
||||
value, err := ephemeralRunnerPhaseMetricValue(metricName, map[string]string{
|
||||
"name": ephemeralRunner.Labels[LabelKeyGitHubScaleSetName],
|
||||
"namespace": ephemeralRunner.Labels[LabelKeyGitHubScaleSetNamespace],
|
||||
"repository": parsedURL.Repository,
|
||||
"organization": parsedURL.Organization,
|
||||
"enterprise": parsedURL.Enterprise,
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred(), "failed to gather ephemeral runner phase metrics")
|
||||
Expect(value).To(Equal(expected))
|
||||
}
|
||||
|
||||
func ephemeralRunnerPhaseMetricName(phase v1alpha1.EphemeralRunnerPhase) string {
|
||||
switch phase {
|
||||
case v1alpha1.EphemeralRunnerPhasePending:
|
||||
return "gha_controller_pending_ephemeral_runners"
|
||||
case v1alpha1.EphemeralRunnerPhaseRunning:
|
||||
return "gha_controller_running_ephemeral_runners"
|
||||
case v1alpha1.EphemeralRunnerPhaseSucceeded:
|
||||
return "gha_controller_succeeded_ephemeral_runners"
|
||||
case v1alpha1.EphemeralRunnerPhaseFailed:
|
||||
return "gha_controller_failed_ephemeral_runners"
|
||||
case v1alpha1.EphemeralRunnerPhaseOutdated:
|
||||
return "gha_controller_outdated_ephemeral_runners"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func ephemeralRunnerPhaseMetricValue(metricName string, labels map[string]string) (float64, error) {
|
||||
metricFamilies, err := controllerMetrics.Registry.Gather()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
for _, metricFamily := range metricFamilies {
|
||||
if metricFamily.GetName() != metricName {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, metric := range metricFamily.GetMetric() {
|
||||
if metricHasLabels(metric, labels) {
|
||||
if metric.GetGauge() == nil {
|
||||
return 0, nil
|
||||
}
|
||||
return metric.GetGauge().GetValue(), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func metricHasLabels(metric *prometheusdto.Metric, labels map[string]string) bool {
|
||||
metricLabels := map[string]string{}
|
||||
for _, label := range metric.GetLabel() {
|
||||
metricLabels[label.GetName()] = label.GetValue()
|
||||
}
|
||||
|
||||
for name, value := range labels {
|
||||
if metricLabels[name] != value {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
var _ = Describe("Test EphemeralRunnerSet controller", func() {
|
||||
var ctx context.Context
|
||||
var mgr ctrl.Manager
|
||||
|
|
@ -133,20 +222,20 @@ var _ = Describe("Test EphemeralRunnerSet controller", func() {
|
|||
ephemeralRunnerSetTestInterval,
|
||||
).Should(BeEquivalentTo(0), "No EphemeralRunner should be created")
|
||||
|
||||
// Check if the status stay 0
|
||||
// Check if the status is initialized
|
||||
Consistently(
|
||||
func() (int, error) {
|
||||
func() (v1alpha1.EphemeralRunnerSetPhase, error) {
|
||||
runnerSet := new(v1alpha1.EphemeralRunnerSet)
|
||||
err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunnerSet.Name, Namespace: ephemeralRunnerSet.Namespace}, runnerSet)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
return "", err
|
||||
}
|
||||
|
||||
return int(runnerSet.Status.CurrentReplicas), nil
|
||||
return runnerSet.Status.Phase, nil
|
||||
},
|
||||
ephemeralRunnerSetTestTimeout,
|
||||
ephemeralRunnerSetTestInterval,
|
||||
).Should(BeEquivalentTo(0), "EphemeralRunnerSet status should be 0")
|
||||
).Should(BeEquivalentTo(v1alpha1.EphemeralRunnerSetPhaseRunning), "EphemeralRunnerSet status should be running")
|
||||
|
||||
// Scaling up the EphemeralRunnerSet
|
||||
updated := created.DeepCopy()
|
||||
|
|
@ -187,20 +276,20 @@ var _ = Describe("Test EphemeralRunnerSet controller", func() {
|
|||
ephemeralRunnerSetTestInterval,
|
||||
).Should(BeEquivalentTo(5), "5 EphemeralRunner should be created")
|
||||
|
||||
// Check if the status is updated
|
||||
// Check if the status stays running
|
||||
Eventually(
|
||||
func() (int, error) {
|
||||
func() (v1alpha1.EphemeralRunnerSetPhase, error) {
|
||||
runnerSet := new(v1alpha1.EphemeralRunnerSet)
|
||||
err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunnerSet.Name, Namespace: ephemeralRunnerSet.Namespace}, runnerSet)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
return "", err
|
||||
}
|
||||
|
||||
return int(runnerSet.Status.CurrentReplicas), nil
|
||||
return runnerSet.Status.Phase, nil
|
||||
},
|
||||
ephemeralRunnerSetTestTimeout,
|
||||
ephemeralRunnerSetTestInterval,
|
||||
).Should(BeEquivalentTo(5), "EphemeralRunnerSet status should be 5")
|
||||
).Should(BeEquivalentTo(v1alpha1.EphemeralRunnerSetPhaseRunning), "EphemeralRunnerSet status should be running")
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -1184,11 +1273,7 @@ var _ = Describe("Test EphemeralRunnerSet controller", func() {
|
|||
).Should(BeTrue(), "Failed to eventually update to one pending, one running and one failed")
|
||||
|
||||
desiredStatus := v1alpha1.EphemeralRunnerSetStatus{
|
||||
Phase: v1alpha1.EphemeralRunnerSetPhaseRunning,
|
||||
CurrentReplicas: 3,
|
||||
PendingEphemeralRunners: 1,
|
||||
RunningEphemeralRunners: 1,
|
||||
FailedEphemeralRunners: 1,
|
||||
Phase: v1alpha1.EphemeralRunnerSetPhaseRunning,
|
||||
}
|
||||
Eventually(
|
||||
func() (v1alpha1.EphemeralRunnerSetStatus, error) {
|
||||
|
|
@ -1227,11 +1312,7 @@ var _ = Describe("Test EphemeralRunnerSet controller", func() {
|
|||
).Should(BeEquivalentTo(1), "Failed to eventually scale down")
|
||||
|
||||
desiredStatus = v1alpha1.EphemeralRunnerSetStatus{
|
||||
CurrentReplicas: 1,
|
||||
PendingEphemeralRunners: 0,
|
||||
RunningEphemeralRunners: 0,
|
||||
FailedEphemeralRunners: 1,
|
||||
Phase: v1alpha1.EphemeralRunnerSetPhaseRunning,
|
||||
Phase: v1alpha1.EphemeralRunnerSetPhaseRunning,
|
||||
}
|
||||
|
||||
Eventually(
|
||||
|
|
@ -1251,11 +1332,7 @@ var _ = Describe("Test EphemeralRunnerSet controller", func() {
|
|||
Expect(err).To(BeNil(), "Failed to delete failed ephemeral runner")
|
||||
|
||||
desiredStatus = v1alpha1.EphemeralRunnerSetStatus{
|
||||
CurrentReplicas: 0,
|
||||
PendingEphemeralRunners: 0,
|
||||
RunningEphemeralRunners: 0,
|
||||
FailedEphemeralRunners: 0,
|
||||
Phase: v1alpha1.EphemeralRunnerSetPhaseRunning,
|
||||
Phase: v1alpha1.EphemeralRunnerSetPhaseRunning,
|
||||
}
|
||||
Eventually(
|
||||
func() (v1alpha1.EphemeralRunnerSetStatus, error) {
|
||||
|
|
@ -1273,6 +1350,148 @@ var _ = Describe("Test EphemeralRunnerSet controller", func() {
|
|||
})
|
||||
})
|
||||
|
||||
var _ = Describe("EphemeralRunner phase metrics", func() {
|
||||
var ctx context.Context
|
||||
var autoscalingNS *corev1.Namespace
|
||||
var mgr ctrl.Manager
|
||||
var configSecret *corev1.Secret
|
||||
var controller *EphemeralRunnerReconciler
|
||||
var ephemeralRunner *v1alpha1.EphemeralRunner
|
||||
var request ctrl.Request
|
||||
|
||||
BeforeEach(func() {
|
||||
registerActionsGithubMetricsForTest.Do(func() {
|
||||
metrics.RegisterMetrics()
|
||||
})
|
||||
|
||||
ephemeralRunnerPhaseMetrics.Lock()
|
||||
ephemeralRunnerPhaseMetrics.phases = map[types.NamespacedName]v1alpha1.EphemeralRunnerPhase{}
|
||||
ephemeralRunnerPhaseMetrics.Unlock()
|
||||
|
||||
ctx = context.Background()
|
||||
autoscalingNS, mgr = createNamespace(GinkgoT(), k8sClient)
|
||||
configSecret = createDefaultSecret(GinkgoT(), k8sClient, autoscalingNS.Name)
|
||||
|
||||
controller = &EphemeralRunnerReconciler{
|
||||
Client: k8sClient,
|
||||
Scheme: mgr.GetScheme(),
|
||||
Log: logf.Log,
|
||||
PublishMetrics: true,
|
||||
ResourceBuilder: ResourceBuilder{
|
||||
SecretResolver: secretresolver.New(k8sClient, fake.NewMultiClient(
|
||||
fake.WithClient(
|
||||
fake.NewClient(
|
||||
fake.WithGenerateJitRunnerConfig(
|
||||
&scaleset.RunnerScaleSetJitRunnerConfig{
|
||||
Runner: &scaleset.RunnerReference{ID: 100, Name: "test-runner"},
|
||||
EncodedJITConfig: "fake-jit-config",
|
||||
},
|
||||
nil,
|
||||
),
|
||||
),
|
||||
),
|
||||
)),
|
||||
},
|
||||
}
|
||||
|
||||
ephemeralRunner = &v1alpha1.EphemeralRunner{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test-runner",
|
||||
Namespace: autoscalingNS.Name,
|
||||
Labels: map[string]string{
|
||||
LabelKeyGitHubScaleSetName: "test-scale-set",
|
||||
LabelKeyGitHubScaleSetNamespace: autoscalingNS.Name,
|
||||
},
|
||||
},
|
||||
Spec: v1alpha1.EphemeralRunnerSpec{
|
||||
GitHubConfigURL: "https://github.com/owner/repo",
|
||||
GitHubConfigSecret: configSecret.Name,
|
||||
RunnerScaleSetID: 100,
|
||||
PodTemplateSpec: corev1.PodTemplateSpec{
|
||||
Spec: corev1.PodSpec{
|
||||
Containers: []corev1.Container{
|
||||
{
|
||||
Name: v1alpha1.EphemeralRunnerContainerName,
|
||||
Image: "ghcr.io/actions/runner",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
err := k8sClient.Create(ctx, ephemeralRunner)
|
||||
Expect(err).NotTo(HaveOccurred(), "failed to create ephemeral runner")
|
||||
|
||||
request = ctrl.Request{NamespacedName: types.NamespacedName{Namespace: ephemeralRunner.Namespace, Name: ephemeralRunner.Name}}
|
||||
})
|
||||
|
||||
It("publishes pending, running, and succeeded phase transitions", func() {
|
||||
_, err := controller.Reconcile(ctx, request)
|
||||
Expect(err).NotTo(HaveOccurred(), "failed to reconcile ephemeral runner")
|
||||
|
||||
pod := new(corev1.Pod)
|
||||
Eventually(func() error {
|
||||
return k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, pod)
|
||||
}, ephemeralRunnerSetTestTimeout, ephemeralRunnerSetTestInterval).Should(Succeed(), "expected ephemeral runner pod to be created")
|
||||
|
||||
podPending := pod.DeepCopy()
|
||||
podPending.Status.Phase = corev1.PodPending
|
||||
podPending.Status.ContainerStatuses = []corev1.ContainerStatus{
|
||||
{
|
||||
Name: v1alpha1.EphemeralRunnerContainerName,
|
||||
State: corev1.ContainerState{},
|
||||
},
|
||||
}
|
||||
err = k8sClient.Status().Patch(ctx, podPending, client.MergeFrom(pod))
|
||||
Expect(err).NotTo(HaveOccurred(), "failed to patch pod to pending")
|
||||
|
||||
_, err = controller.Reconcile(ctx, request)
|
||||
Expect(err).NotTo(HaveOccurred(), "failed to reconcile pending pod")
|
||||
expectEphemeralRunnerPhase(ctx, ephemeralRunner, v1alpha1.EphemeralRunnerPhasePending)
|
||||
expectEphemeralRunnerPhaseMetric(ephemeralRunner, v1alpha1.EphemeralRunnerPhasePending, 1)
|
||||
expectEphemeralRunnerPhaseMetric(ephemeralRunner, v1alpha1.EphemeralRunnerPhaseRunning, 0)
|
||||
|
||||
podRunning := podPending.DeepCopy()
|
||||
podRunning.Status.Phase = corev1.PodRunning
|
||||
podRunning.Status.ContainerStatuses = []corev1.ContainerStatus{
|
||||
{
|
||||
Name: v1alpha1.EphemeralRunnerContainerName,
|
||||
State: corev1.ContainerState{
|
||||
Running: &corev1.ContainerStateRunning{StartedAt: metav1.Now()},
|
||||
},
|
||||
},
|
||||
}
|
||||
err = k8sClient.Status().Patch(ctx, podRunning, client.MergeFrom(podPending))
|
||||
Expect(err).NotTo(HaveOccurred(), "failed to patch pod to running")
|
||||
|
||||
_, err = controller.Reconcile(ctx, request)
|
||||
Expect(err).NotTo(HaveOccurred(), "failed to reconcile running pod")
|
||||
expectEphemeralRunnerPhase(ctx, ephemeralRunner, v1alpha1.EphemeralRunnerPhaseRunning)
|
||||
expectEphemeralRunnerPhaseMetric(ephemeralRunner, v1alpha1.EphemeralRunnerPhasePending, 0)
|
||||
expectEphemeralRunnerPhaseMetric(ephemeralRunner, v1alpha1.EphemeralRunnerPhaseRunning, 1)
|
||||
|
||||
podSucceeded := podRunning.DeepCopy()
|
||||
podSucceeded.Status.Phase = corev1.PodSucceeded
|
||||
podSucceeded.Status.ContainerStatuses = []corev1.ContainerStatus{
|
||||
{
|
||||
Name: v1alpha1.EphemeralRunnerContainerName,
|
||||
State: corev1.ContainerState{
|
||||
Terminated: &corev1.ContainerStateTerminated{ExitCode: 0},
|
||||
},
|
||||
},
|
||||
}
|
||||
err = k8sClient.Status().Patch(ctx, podSucceeded, client.MergeFrom(podRunning))
|
||||
Expect(err).NotTo(HaveOccurred(), "failed to patch pod to succeeded")
|
||||
|
||||
_, err = controller.Reconcile(ctx, request)
|
||||
Expect(err).NotTo(HaveOccurred(), "failed to reconcile succeeded pod")
|
||||
expectEphemeralRunnerPhase(ctx, ephemeralRunner, v1alpha1.EphemeralRunnerPhaseSucceeded)
|
||||
expectEphemeralRunnerPhaseMetric(ephemeralRunner, v1alpha1.EphemeralRunnerPhaseRunning, 0)
|
||||
expectEphemeralRunnerPhaseMetric(ephemeralRunner, v1alpha1.EphemeralRunnerPhaseSucceeded, 1)
|
||||
})
|
||||
})
|
||||
|
||||
var _ = Describe("Test EphemeralRunnerSet controller with proxy settings", func() {
|
||||
var ctx context.Context
|
||||
var mgr ctrl.Manager
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package metrics
|
||||
|
||||
import (
|
||||
"github.com/actions/actions-runner-controller/apis/actions.github.com/v1alpha1"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"sigs.k8s.io/controller-runtime/pkg/metrics"
|
||||
)
|
||||
|
|
@ -50,6 +51,14 @@ var (
|
|||
},
|
||||
labels,
|
||||
)
|
||||
succeededEphemeralRunners = prometheus.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Subsystem: githubScaleSetControllerSubsystem,
|
||||
Name: "succeeded_ephemeral_runners",
|
||||
Help: "Number of ephemeral runners in a succeeded state.",
|
||||
},
|
||||
labels,
|
||||
)
|
||||
failedEphemeralRunners = prometheus.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Subsystem: githubScaleSetControllerSubsystem,
|
||||
|
|
@ -58,6 +67,14 @@ var (
|
|||
},
|
||||
labels,
|
||||
)
|
||||
outdatedEphemeralRunners = prometheus.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Subsystem: githubScaleSetControllerSubsystem,
|
||||
Name: "outdated_ephemeral_runners",
|
||||
Help: "Number of ephemeral runners in an outdated state.",
|
||||
},
|
||||
labels,
|
||||
)
|
||||
runningListeners = prometheus.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Subsystem: githubScaleSetControllerSubsystem,
|
||||
|
|
@ -72,15 +89,34 @@ func RegisterMetrics() {
|
|||
metrics.Registry.MustRegister(
|
||||
pendingEphemeralRunners,
|
||||
runningEphemeralRunners,
|
||||
succeededEphemeralRunners,
|
||||
failedEphemeralRunners,
|
||||
outdatedEphemeralRunners,
|
||||
runningListeners,
|
||||
)
|
||||
}
|
||||
|
||||
func SetEphemeralRunnerCountsByStatus(commonLabels CommonLabels, pending, running, failed int) {
|
||||
pendingEphemeralRunners.With(commonLabels.labels()).Set(float64(pending))
|
||||
runningEphemeralRunners.With(commonLabels.labels()).Set(float64(running))
|
||||
failedEphemeralRunners.With(commonLabels.labels()).Set(float64(failed))
|
||||
func AddEphemeralRunner(commonLabels CommonLabels, phase v1alpha1.EphemeralRunnerPhase) {
|
||||
updateEphemeralRunner(commonLabels, phase, 1)
|
||||
}
|
||||
|
||||
func SubEphemeralRunner(commonLabels CommonLabels, phase v1alpha1.EphemeralRunnerPhase) {
|
||||
updateEphemeralRunner(commonLabels, phase, -1)
|
||||
}
|
||||
|
||||
func updateEphemeralRunner(commonLabels CommonLabels, phase v1alpha1.EphemeralRunnerPhase, delta float64) {
|
||||
switch phase {
|
||||
case v1alpha1.EphemeralRunnerPhasePending:
|
||||
pendingEphemeralRunners.With(commonLabels.labels()).Add(delta)
|
||||
case v1alpha1.EphemeralRunnerPhaseRunning:
|
||||
runningEphemeralRunners.With(commonLabels.labels()).Add(delta)
|
||||
case v1alpha1.EphemeralRunnerPhaseSucceeded:
|
||||
succeededEphemeralRunners.With(commonLabels.labels()).Add(delta)
|
||||
case v1alpha1.EphemeralRunnerPhaseFailed:
|
||||
failedEphemeralRunners.With(commonLabels.labels()).Add(delta)
|
||||
case v1alpha1.EphemeralRunnerPhaseOutdated:
|
||||
outdatedEphemeralRunners.With(commonLabels.labels()).Add(delta)
|
||||
}
|
||||
}
|
||||
|
||||
func AddRunningListener(commonLabels CommonLabels) {
|
||||
|
|
|
|||
|
|
@ -1,19 +1,19 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
-----END CERTIFICATE-----
|
||||
|
|
|
|||
|
|
@ -1,20 +1,20 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDQjCCAiqgAwIBAgIUHT3JtqsYKs7NHv1LNyS9RYC7vsAwDQYJKoZIhvcNAQEL
|
||||
BQAwHzEdMBsGA1UEAwwUVGVzdCBJbnRlcm1lZGlhdGUgQ0EwHhcNMjUwMjI4MTIw
|
||||
MTMwWhcNMjYwNzEzMTIwMTMwWjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0G
|
||||
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDHwI/xSLgCuQrx+WsvupA8w4eMdSef
|
||||
WGw523OJYPJkDYJGgSGsjVb9htba6vXYbGNohuluEAZIyT7GvmPezTokeVMkuSYT
|
||||
lSV8xplFEtDlQhTzaI/cofbi7qtT91/5zS/w0JSaNosThGtZg/M4ZOiMj04m0NGK
|
||||
Zz56l9Lpe/yM7fPda++D9xYEGSSdwK9CqqwF+cXN09d6IK1VINIIjT3Sdb9Sssok
|
||||
GWmD7UUPLvwZ5379+HRs1K8AFXqvbkeWVYtrJwJMxJGVnNSeiqKGSmMEpP7tVNHl
|
||||
s4V7oyQXd8KX+HpziiayjGy9giVteJJi/bAmUp+0+hTHBes5fOWI5JyDAgMBAAGj
|
||||
gYAwfjAfBgNVHSMEGDAWgBSmAyntm95+KoyL3ffLBXZKSpk1VTAJBgNVHRMEAjAA
|
||||
MIIDQjCCAiqgAwIBAgIUbiA5aoS2wqoRlN7qlS1CUrQRrZIwDQYJKoZIhvcNAQEL
|
||||
BQAwHzEdMBsGA1UEAwwUVGVzdCBJbnRlcm1lZGlhdGUgQ0EwHhcNMjYwNzEzMTMy
|
||||
NDA3WhcNMjcxMTI1MTMyNDA3WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0G
|
||||
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDf2xz5c/Kts7iYFbznIBqnos0OZw1m
|
||||
XqQRfd8Ub7mcRcNu5LAS+QXaMCQrtSS8HaiOWrnmXVnY0Dtm9BYYgxCLbffBjPgv
|
||||
CjMURftuI0fvFfFHhNOeuO1Y6N3z4YFY9UHldiqBIKmzrEKl6ZzibbHhIWlOFdMC
|
||||
IHosnO+9LgXgEcr242yrBczl2SWycXG4OGag4yp2FrsvrKtdqyErJBuyIQHv51k6
|
||||
Eo5vz42UxZCcjBciSe/X2Tf+KDLzslZDfnY+8PWU2Dx5DaMZAxNVa78jRDhKact9
|
||||
jOunKd1JRj/GZkV5EKL/lIJJQPgcNCl0s8swKlicEYpqEdS4Ayj0fF7DAgMBAAGj
|
||||
gYAwfjAfBgNVHSMEGDAWgBTjYR9enoN6IY3lzzq7hF4R3Pxr7jAJBgNVHRMEAjAA
|
||||
MAsGA1UdDwQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHREECDAGhwR/
|
||||
AAABMB0GA1UdDgQWBBTVdJE2lkGsNIU3LlEf3rN5fyaRkjANBgkqhkiG9w0BAQsF
|
||||
AAOCAQEAo1klH9WMsPWTN9qN3tdud07eatulEKo/0okaph6MJ59ozseOzxrfpwL0
|
||||
67Nr8yl+VwZqrRTBurp0n6G+n0j8UHfWjSrAqN4yUHl+heT0HpnLR2FE9YgZEmxR
|
||||
bPfVbPBef/eJeE7/U6imfBYzzMajua+hg05sVHUNNdPaFOP+Xj47x8uQmf9w5/kf
|
||||
MrylRUSgH5RRge4+2T5hmNM9tHfF6OfDHitrXnl+X6h/x/tkBvDcUXtKa5xuEcSg
|
||||
WpmJKl3pKfXvdmCIrj9Vca+UD2Bntkk2jgDTLEPJAxMgrsQRhnUJclaunnd1NQbc
|
||||
FmjFW7iaNvDVKt+vYqH8ff8U9iCB2g==
|
||||
AAABMB0GA1UdDgQWBBQtvGpvrghOSrZI4B1ieqKJc69RVDANBgkqhkiG9w0BAQsF
|
||||
AAOCAQEAm33hxRyoocCNH2OUhzogkSbi59+an4bLV07uTm3thrdhNKefsPlt1D6Q
|
||||
11QTafhH8RAjlnn/PavLgk3WpTvuC4imlPfhxjf1gRg0zJXW3y0GC2wizSm5cXdK
|
||||
L1ikKpLd17Gys4kGwMLqxCZunpGQnoJpEWBrg3kc7RPp6rgLRMAuj/ZwUzV9nNiU
|
||||
YUA64FYY4ISIZigYGCkJUpqgyUQYsD+lYWZl2QlVje1riXIPReIBxd4kcMLqng0l
|
||||
IysTAnZ+vNMWVLjhthGlOfs0yDaIoDa2HHskdaGtlz97SPfIUlDJ/20QLDMZEv0M
|
||||
uSjtuu8PGy+iMI5+SfBE9D4cF1tn0w==
|
||||
-----END CERTIFICATE-----
|
||||
|
|
|
|||
|
|
@ -1,28 +1,28 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDHwI/xSLgCuQrx
|
||||
+WsvupA8w4eMdSefWGw523OJYPJkDYJGgSGsjVb9htba6vXYbGNohuluEAZIyT7G
|
||||
vmPezTokeVMkuSYTlSV8xplFEtDlQhTzaI/cofbi7qtT91/5zS/w0JSaNosThGtZ
|
||||
g/M4ZOiMj04m0NGKZz56l9Lpe/yM7fPda++D9xYEGSSdwK9CqqwF+cXN09d6IK1V
|
||||
INIIjT3Sdb9SssokGWmD7UUPLvwZ5379+HRs1K8AFXqvbkeWVYtrJwJMxJGVnNSe
|
||||
iqKGSmMEpP7tVNHls4V7oyQXd8KX+HpziiayjGy9giVteJJi/bAmUp+0+hTHBes5
|
||||
fOWI5JyDAgMBAAECggEADanzbrrds3n68LByD5LAeRea9xWwfyrqRE7pqVUTX5q4
|
||||
9Z+xsP7+G1uU6Oa3qHVJm4XXA+tesq3peGjfpgb92i7ebB2qKB7EsLNZGqt91KDf
|
||||
lALsDFib7cwLtjOuwgSyKdPqxl3Cx7QAL+Bhy9LDQZIv82HHY6NKV9J43/XWQcGK
|
||||
KNZyS1o0vBWvt135YeE3qfQA9Ww8GI3jWyk49QDOVtVNZ1HRQpXPkt5exAyU8JpW
|
||||
Y3Y5VqyEcKPBRlw/scEc5CRuzIP3P06Y+NEuuvnlnDt/BR/wyyuPiZoIqGXhXUKe
|
||||
oDzEmtVrvB5RmhRc1PoS1l1GBfBfVqwkLUmeSitn8QKBgQD1pC6Ukiqtm7vyhirU
|
||||
ynE+Dik/gHBBW6fQalD7yZwStid1+HfIvoU+RB0wyPUVwbu7eOoMnjG2ChLYX7cV
|
||||
UhAcu5ZWFhlc8OS5bGGMI99d4ueBqTYONqnCV3DhiWZhs8OesiF3hohE6jV3G5xC
|
||||
ra8DzImMpujyMIWXvOwnPLRWCQKBgQDQLPwTvx472XbY1aWviQkzxMgxP8l9D+lO
|
||||
nBaybarLxDa+89RMWidgJX2kGM7i6FgicGgSNpNDIYNLrVZYAz11PP6o2Oqa9ZaR
|
||||
5IvnfhP1iOwSgIoC8weNSE+Y0Lw/w0IOW71+XsfgswhJG45eXV8hRqYpUEkjjl1x
|
||||
nQM0hCshKwKBgCQDFfEiHK+nDT7Y/J6Fr2Rxnwp4QfzS+x9K9uRzAjacDdz1uFnt
|
||||
1Ir0YXMtgwDVjjhF2cpPxunxQCIIpkax6TrNJZUpWD6P8nhcs1BgUfbptRcFP6+F
|
||||
xA2B1EK8ag4Y1K0HYHCtgHzZ+Uyk95uu6uGbsu6z6aLYCj3crKJz+9xBAoGACOdT
|
||||
pLiQ33hul9mTa42N4jPxaAHVaU7r6JvOcLU2D98FhGdDVjyo4HjaBdG1z4imdFqg
|
||||
aN8Cr2VYiz0Pq1YAI+qG7cvRRO1qEjVXMoB29BJ2Hlh3Dqc8VHOaS+vpkUSVp62O
|
||||
zj/ZhqfBm/bcwPZ3YiH2a1/usOGe54QSpgVdHt8CgYBr6xpKQSrQvgtiuv9kCzI+
|
||||
WQYP2Xxj+zsQb29hagXY/JllKOl5aDGz2qMV2RgOWZabB/xxkAeTF4A26wWrmcq0
|
||||
wsv96jEl1MtI3lB3bi/8Y/tctkNsp0drvDZdfnGMpzxDafECKdxdFvhO63p7yBOA
|
||||
LG1OvFTywkxBuOUKsNsErQ==
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDf2xz5c/Kts7iY
|
||||
FbznIBqnos0OZw1mXqQRfd8Ub7mcRcNu5LAS+QXaMCQrtSS8HaiOWrnmXVnY0Dtm
|
||||
9BYYgxCLbffBjPgvCjMURftuI0fvFfFHhNOeuO1Y6N3z4YFY9UHldiqBIKmzrEKl
|
||||
6ZzibbHhIWlOFdMCIHosnO+9LgXgEcr242yrBczl2SWycXG4OGag4yp2FrsvrKtd
|
||||
qyErJBuyIQHv51k6Eo5vz42UxZCcjBciSe/X2Tf+KDLzslZDfnY+8PWU2Dx5DaMZ
|
||||
AxNVa78jRDhKact9jOunKd1JRj/GZkV5EKL/lIJJQPgcNCl0s8swKlicEYpqEdS4
|
||||
Ayj0fF7DAgMBAAECggEAEoAkRPuC4KQCfmzUsV25kwXFIH3k1INZPoOigA8ujfTe
|
||||
dRfb82pDd3S647/ZrhBd1PIFL73V7Jf9DzVFOp5hkiky+WFb3sT4ue60tZwF2Gnk
|
||||
VUHr6WmLXoM6wLdwF+vt5JE5BXX8TUSdBEnddOf8jciHA8FeMIYcAsh8Y1932qMG
|
||||
OoSMQPKgpR4Ii62GsufLrzhfShatQXWikO/O5/DaOWlOgye9CMF0JA/f5OnwqRa4
|
||||
qKQGlYrRbXtxBhjOjUJ4t0g3bTKuOhYpPdDQLf9AZqdS29fD89p+dtKvzf1eQlGZ
|
||||
siPvPTSRvWjvzmEbqau1tPIGtp+fsxG2s1l05zu3yQKBgQD2QZW1i/PrVT1k4ueY
|
||||
gweM9Iaj1J40URyUmgTh2aLWBGB+fHSYzYVlabpogtQ6FoNCJBOJ2nPARbcoIrin
|
||||
6ArEDS0ih5H0l5h6ky/lXjIftqhiKcpf8yr82Y5xlVML0nTG7q/S/3AEWGdAiom3
|
||||
JPGGcEAMwmEsVWeVmldqMy8L+wKBgQDotqDLPMk8TTW9G/2SkuhYvmi+TkR+50/e
|
||||
fgBU99E+6rZtEqqkiIwAnwHF5zCtvWWEEqaHMKoQfB1D5WgKvN0LrGfsJhQnxUT/
|
||||
uZT6uIblXcpCX+2QJqM4AYedkEkK+GNdIvnFiMU0QFibooFsaMD124Qp8yE5o9MW
|
||||
5TXftCz12QKBgQDSHc3OtRawEvAql80CfbLAm5gSTAWdICRhyzUlPBzLvbpT0n9u
|
||||
LdaHXHo4WIEa+0CN+9hMBIBFa3bHITEr2zrsY03Cq6hm6b6pv9LbQ89C7giokX3i
|
||||
9soUKtF2qvHMIYuQffK590gt/PxEvrCY+0W17ytHd8eQG2Mh7CpwLDIVZwKBgBRU
|
||||
J9W5OKcQ45nigRM1zCA8ee/t7GPdlweLoEHL6DaD0G3UzJ1U5E4FleUQ3hq/Scfw
|
||||
zSVQJfsMrI3K03zkpLapV+a0KNyUigOA1bfVOMt+lvWXZaxLA8UXtR4ZhZf0vNFd
|
||||
Bc6wtPFskZD+8CllOT4A8BmuCH/9hKoiWcNx/N95AoGAevwj2U2/TVQdlfTe2WDO
|
||||
G/rT8nEtohcbrQyYm+yLySsKDB9AY6pPJPTW7lWfz9oXAPYeyCErtQYSIiT0OodX
|
||||
EdRRmynKaRYBPxL4XNU+3oHKjuMF5+Eip+KJrONseik4ubYVQvU6DbX/xbFpyFbQ
|
||||
PEj26Z+E4YTsviOuWu7EkYQ=
|
||||
-----END PRIVATE KEY-----
|
||||
|
|
|
|||
|
|
@ -1,19 +1,19 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
-----END CERTIFICATE-----
|
||||
|
|
|
|||
|
|
@ -1,20 +1,20 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDOjCCAiKgAwIBAgIUQr7R8yN5+2and6ucUOPF6oIbD48wDQYJKoZIhvcNAQEL
|
||||
BQAwFzEVMBMGA1UEAwwMVGVzdCBSb290IENBMB4XDTI1MDIyODEyMDEzMFoXDTI2
|
||||
MDcxMzEyMDEzMFowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0B
|
||||
AQEFAAOCAQ8AMIIBCgKCAQEA4oL2hAPQlDVaNJru5fIstkpoVSuam0vpswC7ciRc
|
||||
XQRjF3q8kjtIA7+jdySsKJqOLGnybDX3awvRyKMEjq11IfnZLjZc+FzTlA+x4z0h
|
||||
MHb0GiBFXKNzrExGI9F0KEPtFxcMIqZ119LY2ReexxWkZBQYlgTepaevp71za4c2
|
||||
n4Zy1+0iS5+uklZ4ANKMTBGlN76Qgt530VnpNiIeUbiUzY58Vx4q7kFcUv/oSz8p
|
||||
rbXr+/GGpAjrOc6/JsezRE8YK2po60dvV80TJ2Jt6pduvF7OSQnq/v4mJl1xuXKl
|
||||
Byo9HLbeu3BuVRWQs2/EwEzx5kX3Ugysl9Bm44K2yKe9/QIDAQABo4GAMH4wHwYD
|
||||
VR0jBBgwFoAUfd/q0BY4fkVBV3X+HWzXH0toW08wCQYDVR0TBAIwADALBgNVHQ8E
|
||||
MIIDOjCCAiKgAwIBAgIUVy/UETGamzkzSYS3TortnzNWCeowDQYJKoZIhvcNAQEL
|
||||
BQAwFzEVMBMGA1UEAwwMVGVzdCBSb290IENBMB4XDTI2MDcxMzEzMjQwN1oXDTI3
|
||||
MTEyNTEzMjQwN1owFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0B
|
||||
AQEFAAOCAQ8AMIIBCgKCAQEAuzF9o1Wc2r1sjIeJRtjzquwqfbOBVefd1264YeSc
|
||||
cR/V8TNaI7KWo9dftWt7P2t6zysw6DzPcwh//+iCuvEAyo1uXd+jwPQyJJsrjC5f
|
||||
pLSltk6BV/qObXGqJtqdj7mGkrlRWUhLzxyU4KqrSoiQTNZisON++vrjPiIADqFv
|
||||
EWrA9aEsaa0HYXGwQCLmuCwPd3CxQldPX3yzGSI0SRj/StkTAq94wFx2OrGPeJ2N
|
||||
PKbftMifHG+OUXpl3J4N0xAP5A8vEXCFDwJIzOnY0a5fxKLlcfHB1oArscuNU61G
|
||||
gzYkRgEr+B3NrX1zT01lzbIPXZM39MxUZJkgzFUNAZgBNQIDAQABo4GAMH4wHwYD
|
||||
VR0jBBgwFoAUvdo7QuZUxixdWGUVTFVO5aOKrWwwCQYDVR0TBAIwADALBgNVHQ8E
|
||||
BAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0RBAgwBocEfwAAATAdBgNV
|
||||
HQ4EFgQUe0rTTfWjho3hgeLTnajTCpddo2MwDQYJKoZIhvcNAQELBQADggEBAIR2
|
||||
5zkA7rPnddxCunsz8Jjq3wyhR/KiAFz+RGeFeiXDkF2fWr7QIQ9KbFbv8tpfXR7P
|
||||
B75bY0sXwutHMB2sZDi92cH5sthNBfp19fI35cxcU4oTPxp4UZJKEiA3Qx8y73CX
|
||||
NJu1009nPdOJNlIboDGAFdZ5SH6RCh+YcQZ68kjHPWBIpXxLbs9FN3QmpbAvtLh1
|
||||
PoPaSy7IjKmxm1u+Lf6tyIn2IiB3MiynaB3OKvbkLCseM/5SZKMk6WKSDWopOCJr
|
||||
xciPOc+yeLz5I2Omn0uViOIIciqjlgxncWAyNtDgvJcecwqB2cPiIhk6GY0QZ1uM
|
||||
e7KoqGzWXvWLqJ13a9U=
|
||||
HQ4EFgQUAHxI5UMg4SIhBu/GMKrTaX6Ir+IwDQYJKoZIhvcNAQELBQADggEBACkv
|
||||
3Y89Xwn4PM+PTUa3VyrvMVOqaOtbfSV9I1Duf2/CQ2er3LdJHgH8VjDKc3lRNQMF
|
||||
F6c9FTQWs0SoYe3KufKgt52f/hLkU0AS42eps5TKXitznAs/5NNh0Oom6Vv/V+H+
|
||||
CIOs+KrekzQ1Uu8f8XJHmjP9zQ4bQ+7+9uZZxHsE4P6pkz9gf896qL8ZjJGnEB8C
|
||||
xelSm+MX3iCmDG2s3RZrMSjRRHiluylcliftwY4OlbuMrBXS1Of3N9nzhpePYQbM
|
||||
Pcy5mIO5t5HGiPeRJ30/JKuNM55wP/wNbSicUQNc+x4nkVq/AMKKCtyiLs8aAhZu
|
||||
IzEG5rEh7Ypi6s+ic8s=
|
||||
-----END CERTIFICATE-----
|
||||
|
|
|
|||
|
|
@ -1,28 +1,28 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDigvaEA9CUNVo0
|
||||
mu7l8iy2SmhVK5qbS+mzALtyJFxdBGMXerySO0gDv6N3JKwomo4safJsNfdrC9HI
|
||||
owSOrXUh+dkuNlz4XNOUD7HjPSEwdvQaIEVco3OsTEYj0XQoQ+0XFwwipnXX0tjZ
|
||||
F57HFaRkFBiWBN6lp6+nvXNrhzafhnLX7SJLn66SVngA0oxMEaU3vpCC3nfRWek2
|
||||
Ih5RuJTNjnxXHiruQVxS/+hLPymttev78YakCOs5zr8mx7NETxgramjrR29XzRMn
|
||||
Ym3ql268Xs5JCer+/iYmXXG5cqUHKj0ctt67cG5VFZCzb8TATPHmRfdSDKyX0Gbj
|
||||
grbIp739AgMBAAECggEADgUIbbAFbJbyHV1q5Jqc/9oSeRW40lyG0Mh+fEMZ4Gam
|
||||
x3ZA+QAS+1W/hV6ktTf+YsCv+4NKQWWQN3iM41PYcyDmu1XWt/Hu5TQk0NQgxhd8
|
||||
EP3nAnkvbf5OkmWiveHuaRvJFCqfZ/Cp8U3lSvHg+edwhMs1CKXHWSeAXwBrIMEb
|
||||
ajpxuD3B/NT/CGmKnj3cgAuIbvNHVIcwu8ACbpczDL++vi7KrWmOJn1QzSlUlNFi
|
||||
fsgnF0heO5Uff4vkjXU84INQxOP3tbvXcDNiwDewZy75h2d3Pv+ku8GoZYWFUXSJ
|
||||
yKtafJMJUD0kJMuKhkzrwYcQGY6ioSYisPK+JoungQKBgQD8fWmuHwCXbM4Ckyns
|
||||
Wg4f+kG8d+wypgIs6ENmgr9UnNB0N6n7nO7v/4l/l7IN9CQQmdtSvek2ytk5rGBM
|
||||
XUAWxZaokE3MecxR0EUJx42k/k3dN4XgU/YNk4D6/wpEsyUATE4nIFDVjxE+Jc07
|
||||
CZ2CUWKyxTPGz2kfHnEQ0vFiYQKBgQDlqRiGlJ6c99zTas2wrvr+50aQhn6BryDK
|
||||
kjGM6woPnnwMq+Jy6vum3o0cU+iNNeFAijShXo2XR3iZJcoJ2sPhy3dRWdBNdFyy
|
||||
hwxgD0cXzEjQL0M03DPDykTnM7ZvE6KUZjnxJZkytJHLKapoGzxBH9656zx5qnuH
|
||||
MPYwTWg5HQKBgDKBD4OBtgeT/v0q3KbnOI4S69U8E6Xp6ON8rgayPn05RMUKYVjw
|
||||
AidFcQZxnG8IF7KuY92AGUcZeiv8G+MKgAhOC526B6XP8xumUjjrjpyjNYX7Vi8R
|
||||
/FSo3ZLXMwGc59jQao2O/DxLesJ4oz2c5cGsb9acdYfd8wQDfdBEsX3hAoGAc4Pu
|
||||
NiMi9MknZZ/e/fPFg9lIgQFlOE2iLMID8mF2mgyZULZUHIFdOr3ONGVwHzbuqcva
|
||||
VSB+D41/d2iuiu5igHwa8+w8/fh9d7691sNYevvh0/Ux1LC9yMlAhxpXtN8nc4VH
|
||||
t6e1uu9gNdQrRloMoKUrHlDYBkpd/838xqbouXECgYEArwn+eXKD5zgNN4jEbNBp
|
||||
ygIp+Oh2abt+CNQjfLUa+qon5ziH53mHixJ2hpaOa6Rxxu9R2ZgNLtbodm+ccD8z
|
||||
ZNA7Z0rApAwfuhD8zIzkZ4HuARN8eopYmTubpzDkAcfRWhw1EBDQc0V6trl+EJsK
|
||||
xfbmGepRVWXw2dLmxhA9/zM=
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC7MX2jVZzavWyM
|
||||
h4lG2POq7Cp9s4FV593Xbrhh5JxxH9XxM1ojspaj11+1a3s/a3rPKzDoPM9zCH//
|
||||
6IK68QDKjW5d36PA9DIkmyuMLl+ktKW2ToFX+o5tcaom2p2PuYaSuVFZSEvPHJTg
|
||||
qqtKiJBM1mKw4376+uM+IgAOoW8RasD1oSxprQdhcbBAIua4LA93cLFCV09ffLMZ
|
||||
IjRJGP9K2RMCr3jAXHY6sY94nY08pt+0yJ8cb45RemXcng3TEA/kDy8RcIUPAkjM
|
||||
6djRrl/EouVx8cHWgCuxy41TrUaDNiRGASv4Hc2tfXNPTWXNsg9dkzf0zFRkmSDM
|
||||
VQ0BmAE1AgMBAAECggEAGpnI0cobtRXP9BRalJ/F2Jcg3qYAjhWZ98A7IWYcORMe
|
||||
Et2KRKJfN78mUaCJbhS26fOoSohBroYZsmL3GNugkigQ8/QQ0B2jdoI6aPw6CSzG
|
||||
k6aKSNdJIBJT7JuKYl8p2XXOMpLMew0Dtv1pw/iuEM0yTxK0+7NlUXIBchLMtrun
|
||||
O5krr85tDZQfTQzWzo6HfYv5tbyCyYHrQmXP24vh9UIAV32tahx3lfR2u3tZPVsE
|
||||
7FWueR523AwcnaMtK3d40RGLceCsO9vYrOu2sLkTadtp0YfnFxDw90slarolE3AY
|
||||
tl8OrDMDFFtOM7E+25CvV9aRTbkh0PPMuZ0b5zV4AQKBgQD1Qy4zvcOe4cKZJcH+
|
||||
vB0wnUuq2BwpqombSPY8h5pHuJgcovWHlD6QGNwpqPhq06skkce4+cN/LE1Opchs
|
||||
ZEuBAK+mzg+FXqiLKdPRfEiEVapxWFLLW0IVrDUV+rjRl8FAxmKeY3b4iAfhNs3B
|
||||
y3dG3hLSyjXF0xF4ZVtLdDvWAQKBgQDDY329L+iBRAd4DNKoSHB0B6cX59HaI/vJ
|
||||
KPUfDfKRKoNwxDk+ZKnu+Mq9o2LsIObG8nE42otLI3H1Yf9A4CPaVEIiDKxzl9Qh
|
||||
1sDvYQ81tRksd3llghYW5R7tRsUEXbGiT35O0UW8V3M/DZnScSFw/OgF1BHpB9nN
|
||||
XORUDpKzNQKBgD36IQXAMVvH7vXmXbRycunjBckBXXSF/Mn50QeQuMLg+cdawrLl
|
||||
Gj4tmg0I/uV34aqXECJFM0rCtjJmoFQLsCzEMJ71OWTZe7vW8Qjh4C1YvH5x9FIh
|
||||
GH0DjFKmjeeg8pvcxfUCa4D4Vw1pXOtY8CY/XgBYSuhXovWKn1xc3fYBAoGBAKVi
|
||||
ZH8ruyEXpT7Pk8wPrOf5xkzs02tSxAAMpBcKJkUL+EAOR+nxKQn3Gx0T3FrEqrLB
|
||||
ambWTctnEEHFFlsinhZi9at+kMYzQML31U2KGWa7iLhj1KTATNRKUjhDi+ZbLE2X
|
||||
/fDXILEAULORXp+LVOQfnoG4dQSLuacjtr0TrMb1AoGAXd/MNTpw3U1QiaY9Qhm/
|
||||
kH5j+5mkOe0zs520mLCQW0bV1l2MiW+4TIACDS8Ok7Ln89N3heeDcmLXecCNBMn2
|
||||
5peofJj0fVhHNWMjmFWdZr2Gzy3OP4nHY+pLoLJylgq99zSWL2EwtAo2Yje/Omz+
|
||||
8aUFUg2z34K+VpDf4D9qWd4=
|
||||
-----END PRIVATE KEY-----
|
||||
|
|
|
|||
2
main.go
2
main.go
|
|
@ -340,6 +340,7 @@ func main() {
|
|||
Client: mgr.GetClient(),
|
||||
Log: log.WithName("EphemeralRunner").WithValues("version", build.Version),
|
||||
Scheme: mgr.GetScheme(),
|
||||
PublishMetrics: metricsAddr != "0",
|
||||
ResourceBuilder: rb,
|
||||
}).SetupWithManager(mgr, runnerOpts...); err != nil {
|
||||
log.Error(err, "unable to create controller", "controller", "EphemeralRunner")
|
||||
|
|
@ -350,7 +351,6 @@ func main() {
|
|||
Client: mgr.GetClient(),
|
||||
Log: log.WithName("EphemeralRunnerSet").WithValues("version", build.Version),
|
||||
Scheme: mgr.GetScheme(),
|
||||
PublishMetrics: metricsAddr != "0",
|
||||
ResourceBuilder: rb,
|
||||
}).SetupWithManager(mgr, controllerOpts...); err != nil {
|
||||
log.Error(err, "unable to create controller", "controller", "EphemeralRunnerSet")
|
||||
|
|
|
|||
Loading…
Reference in New Issue