mirror of
https://github.com/actions-runner-controller/actions-runner-controller.git
synced 2026-09-30 10:50:07 +02:00
Upgrade resources in-place, causing 1-1 mapping between autoscaling runner set and ephemeral runner set (#4516)
This commit is contained in:
@@ -25,6 +25,9 @@ import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
// secret constants
|
||||
@@ -43,6 +46,15 @@ var commonLabelKeys = [...]string{
|
||||
LabelKeyGitHubRepository,
|
||||
}
|
||||
|
||||
// annotationKeyIntegrityHash is used as a hash of the important fields
|
||||
// of each resource to determine if more drastic action should be taken.
|
||||
//
|
||||
// For example, annotations/labels are not something that should modify
|
||||
// the behavior of a resource, while the change in spec is. Therefore,
|
||||
// the spec hash should contain the spec fields in order to determine
|
||||
// modifications.
|
||||
const annotationKeyIntegrityHash = "actions.github.com/integrity-hash"
|
||||
|
||||
const labelValueKubernetesPartOf = "gha-runner-scale-set"
|
||||
|
||||
var (
|
||||
@@ -83,9 +95,27 @@ type SecretResolver interface {
|
||||
type ResourceBuilder struct {
|
||||
ExcludeLabelPropagationPrefixes []string
|
||||
SecretResolver
|
||||
Scheme *runtime.Scheme
|
||||
}
|
||||
|
||||
func (b *ResourceBuilder) newAutoScalingListener(autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, ephemeralRunnerSet *v1alpha1.EphemeralRunnerSet, namespace, image string, imagePullSecrets []corev1.LocalObjectReference) (*v1alpha1.AutoscalingListener, error) {
|
||||
func (b *ResourceBuilder) setSchemeIfUnset(scheme *runtime.Scheme) {
|
||||
if b.Scheme == nil {
|
||||
b.Scheme = scheme
|
||||
}
|
||||
}
|
||||
|
||||
func (b *ResourceBuilder) setControllerReference(owner client.Object, object client.Object) error {
|
||||
if b.Scheme == nil {
|
||||
b.Scheme = runtime.NewScheme()
|
||||
if err := v1alpha1.AddToScheme(b.Scheme); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return ctrl.SetControllerReference(owner, object, b.Scheme)
|
||||
}
|
||||
|
||||
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[runnerScaleSetIDAnnotationKey])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -100,6 +130,28 @@ func (b *ResourceBuilder) newAutoScalingListener(autoscalingRunnerSet *v1alpha1.
|
||||
effectiveMinRunners = *autoscalingRunnerSet.Spec.MinRunners
|
||||
}
|
||||
|
||||
spec := v1alpha1.AutoscalingListenerSpec{
|
||||
GitHubConfigURL: autoscalingRunnerSet.Spec.GitHubConfigUrl,
|
||||
GitHubConfigSecret: autoscalingRunnerSet.Spec.GitHubConfigSecret,
|
||||
VaultConfig: autoscalingRunnerSet.VaultConfig(),
|
||||
RunnerScaleSetID: runnerScaleSetID,
|
||||
AutoscalingRunnerSetNamespace: autoscalingRunnerSet.Namespace,
|
||||
AutoscalingRunnerSetName: autoscalingRunnerSet.Name,
|
||||
EphemeralRunnerSetName: ephemeralRunnerSet.Name,
|
||||
MinRunners: effectiveMinRunners,
|
||||
MaxRunners: effectiveMaxRunners,
|
||||
Image: image,
|
||||
ImagePullSecrets: imagePullSecrets,
|
||||
Proxy: autoscalingRunnerSet.Spec.Proxy,
|
||||
GitHubServerTLS: autoscalingRunnerSet.Spec.GitHubServerTLS,
|
||||
Metrics: autoscalingRunnerSet.Spec.ListenerMetrics,
|
||||
Template: autoscalingRunnerSet.Spec.ListenerTemplate,
|
||||
ServiceAccountMetadata: autoscalingRunnerSet.Spec.ListenerServiceAccountMetadata,
|
||||
RoleMetadata: autoscalingRunnerSet.Spec.ListenerRoleMetadata,
|
||||
RoleBindingMetadata: autoscalingRunnerSet.Spec.ListenerRoleBindingMetadata,
|
||||
ConfigSecretMetadata: autoscalingRunnerSet.Spec.ListenerConfigSecretMetadata,
|
||||
}
|
||||
|
||||
labels := b.filterAndMergeLabels(autoscalingRunnerSet.Labels, map[string]string{
|
||||
LabelKeyGitHubScaleSetNamespace: autoscalingRunnerSet.Namespace,
|
||||
LabelKeyGitHubScaleSetName: autoscalingRunnerSet.Name,
|
||||
@@ -113,8 +165,7 @@ func (b *ResourceBuilder) newAutoScalingListener(autoscalingRunnerSet *v1alpha1.
|
||||
}
|
||||
|
||||
annotations := map[string]string{
|
||||
annotationKeyRunnerSpecHash: autoscalingRunnerSet.ListenerSpecHash(),
|
||||
annotationKeyValuesHash: autoscalingRunnerSet.Annotations[annotationKeyValuesHash],
|
||||
annotationKeyIntegrityHash: spec.Hash(),
|
||||
}
|
||||
|
||||
if autoscalingRunnerSet.Spec.AutoscalingListenerMetadata != nil {
|
||||
@@ -129,27 +180,7 @@ func (b *ResourceBuilder) newAutoScalingListener(autoscalingRunnerSet *v1alpha1.
|
||||
Labels: labels,
|
||||
Annotations: annotations,
|
||||
},
|
||||
Spec: v1alpha1.AutoscalingListenerSpec{
|
||||
GitHubConfigUrl: autoscalingRunnerSet.Spec.GitHubConfigUrl,
|
||||
GitHubConfigSecret: autoscalingRunnerSet.Spec.GitHubConfigSecret,
|
||||
VaultConfig: autoscalingRunnerSet.VaultConfig(),
|
||||
RunnerScaleSetId: runnerScaleSetID,
|
||||
AutoscalingRunnerSetNamespace: autoscalingRunnerSet.Namespace,
|
||||
AutoscalingRunnerSetName: autoscalingRunnerSet.Name,
|
||||
EphemeralRunnerSetName: ephemeralRunnerSet.Name,
|
||||
MinRunners: effectiveMinRunners,
|
||||
MaxRunners: effectiveMaxRunners,
|
||||
Image: image,
|
||||
ImagePullSecrets: imagePullSecrets,
|
||||
Proxy: autoscalingRunnerSet.Spec.Proxy,
|
||||
GitHubServerTLS: autoscalingRunnerSet.Spec.GitHubServerTLS,
|
||||
Metrics: autoscalingRunnerSet.Spec.ListenerMetrics,
|
||||
Template: autoscalingRunnerSet.Spec.ListenerTemplate,
|
||||
ServiceAccountMetadata: autoscalingRunnerSet.Spec.ListenerServiceAccountMetadata,
|
||||
RoleMetadata: autoscalingRunnerSet.Spec.ListenerRoleMetadata,
|
||||
RoleBindingMetadata: autoscalingRunnerSet.Spec.ListenerRoleBindingMetadata,
|
||||
ConfigSecretMetadata: autoscalingRunnerSet.Spec.ListenerConfigSecretMetadata,
|
||||
},
|
||||
Spec: spec,
|
||||
}
|
||||
|
||||
return autoscalingListener, nil
|
||||
@@ -187,12 +218,12 @@ func (b *ResourceBuilder) newScaleSetListenerConfig(autoscalingListener *v1alpha
|
||||
}
|
||||
|
||||
config := ghalistenerconfig.Config{
|
||||
ConfigureURL: autoscalingListener.Spec.GitHubConfigUrl,
|
||||
ConfigureURL: autoscalingListener.Spec.GitHubConfigURL,
|
||||
EphemeralRunnerSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
||||
EphemeralRunnerSetName: autoscalingListener.Spec.EphemeralRunnerSetName,
|
||||
MaxRunners: autoscalingListener.Spec.MaxRunners,
|
||||
MinRunners: autoscalingListener.Spec.MinRunners,
|
||||
RunnerScaleSetID: autoscalingListener.Spec.RunnerScaleSetId,
|
||||
RunnerScaleSetID: autoscalingListener.Spec.RunnerScaleSetID,
|
||||
RunnerScaleSetName: autoscalingListener.Spec.AutoscalingRunnerSetName,
|
||||
ServerRootCA: cert,
|
||||
LogLevel: scaleSetListenerLogLevel,
|
||||
@@ -230,12 +261,12 @@ func (b *ResourceBuilder) newScaleSetListenerConfig(autoscalingListener *v1alpha
|
||||
labels = b.filterAndMergeLabels(autoscalingListener.Spec.ConfigSecretMetadata.Labels, nil)
|
||||
}
|
||||
|
||||
var annotations map[string]string
|
||||
annotations := make(map[string]string)
|
||||
if autoscalingListener.Spec.ConfigSecretMetadata != nil && len(autoscalingListener.Spec.ConfigSecretMetadata.Annotations) > 0 {
|
||||
annotations = autoscalingListener.Spec.ConfigSecretMetadata.Annotations
|
||||
}
|
||||
|
||||
return &corev1.Secret{
|
||||
desiredSecret := &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: scaleSetListenerConfigName(autoscalingListener),
|
||||
Namespace: autoscalingListener.Namespace,
|
||||
@@ -245,17 +276,90 @@ func (b *ResourceBuilder) newScaleSetListenerConfig(autoscalingListener *v1alpha
|
||||
Data: map[string][]byte{
|
||||
"config.json": buf.Bytes(),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
desiredSecret.Annotations[annotationKeyIntegrityHash] = scaleSetListenerConfigIntegrityHash(desiredSecret)
|
||||
|
||||
if err := b.setControllerReference(autoscalingListener, desiredSecret); err != nil {
|
||||
return nil, fmt.Errorf("failed to set controller reference for listener config secret: %w", err)
|
||||
}
|
||||
|
||||
return desiredSecret, nil
|
||||
}
|
||||
|
||||
func (b *ResourceBuilder) newScaleSetListenerPod(autoscalingListener *v1alpha1.AutoscalingListener, podConfig *corev1.Secret, serviceAccount *corev1.ServiceAccount, metricsConfig *listenerMetricsServerConfig, envs ...corev1.EnvVar) (*corev1.Pod, error) {
|
||||
listenerEnv := []corev1.EnvVar{
|
||||
func scaleSetListenerConfigIntegrityHash(secret *corev1.Secret) string {
|
||||
type data struct {
|
||||
Data map[string][]byte `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
d := data{
|
||||
Data: secret.Data,
|
||||
}
|
||||
|
||||
return hash.ComputeTemplateHash(&d)
|
||||
}
|
||||
|
||||
func (b *ResourceBuilder) newScaleSetListenerPod(
|
||||
autoscalingListener *v1alpha1.AutoscalingListener,
|
||||
podConfig *corev1.Secret,
|
||||
serviceAccount *corev1.ServiceAccount,
|
||||
role *rbacv1.Role,
|
||||
roleBinding *rbacv1.RoleBinding,
|
||||
metricsConfig *listenerMetricsServerConfig,
|
||||
) (*corev1.Pod, error) {
|
||||
envs := []corev1.EnvVar{
|
||||
{
|
||||
Name: "LISTENER_CONFIG_PATH",
|
||||
Value: "/etc/gha-listener/config.json",
|
||||
},
|
||||
}
|
||||
listenerEnv = append(listenerEnv, envs...)
|
||||
|
||||
if autoscalingListener.Spec.Proxy != nil {
|
||||
httpURL := corev1.EnvVar{
|
||||
Name: "http_proxy",
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
SecretKeyRef: &corev1.SecretKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: proxyListenerSecretName(autoscalingListener),
|
||||
},
|
||||
Key: "http_proxy",
|
||||
},
|
||||
},
|
||||
}
|
||||
if autoscalingListener.Spec.Proxy.HTTP != nil {
|
||||
envs = append(envs, httpURL)
|
||||
}
|
||||
|
||||
httpsURL := corev1.EnvVar{
|
||||
Name: "https_proxy",
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
SecretKeyRef: &corev1.SecretKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: proxyListenerSecretName(autoscalingListener),
|
||||
},
|
||||
Key: "https_proxy",
|
||||
},
|
||||
},
|
||||
}
|
||||
if autoscalingListener.Spec.Proxy.HTTPS != nil {
|
||||
envs = append(envs, httpsURL)
|
||||
}
|
||||
|
||||
noProxy := corev1.EnvVar{
|
||||
Name: "no_proxy",
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
SecretKeyRef: &corev1.SecretKeySelector{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: proxyListenerSecretName(autoscalingListener),
|
||||
},
|
||||
Key: "no_proxy",
|
||||
},
|
||||
},
|
||||
}
|
||||
if len(autoscalingListener.Spec.Proxy.NoProxy) > 0 {
|
||||
envs = append(envs, noProxy)
|
||||
}
|
||||
}
|
||||
|
||||
var ports []corev1.ContainerPort
|
||||
if metricsConfig != nil && len(metricsConfig.addr) != 0 {
|
||||
@@ -276,7 +380,7 @@ func (b *ResourceBuilder) newScaleSetListenerPod(autoscalingListener *v1alpha1.A
|
||||
{
|
||||
Name: autoscalingListenerContainerName,
|
||||
Image: autoscalingListener.Spec.Image,
|
||||
Env: listenerEnv,
|
||||
Env: envs,
|
||||
Command: []string{
|
||||
scaleSetListenerEntrypoint,
|
||||
},
|
||||
@@ -314,23 +418,28 @@ func (b *ResourceBuilder) newScaleSetListenerPod(autoscalingListener *v1alpha1.A
|
||||
APIVersion: "v1",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: autoscalingListener.Name,
|
||||
Namespace: autoscalingListener.Namespace,
|
||||
Labels: labels,
|
||||
OwnerReferences: []metav1.OwnerReference{
|
||||
{
|
||||
APIVersion: v1alpha1.GroupVersion.String(),
|
||||
Kind: "AutoscalingListener",
|
||||
UID: autoscalingListener.GetUID(),
|
||||
Name: autoscalingListener.GetName(),
|
||||
Controller: new(true),
|
||||
BlockOwnerDeletion: new(true),
|
||||
},
|
||||
},
|
||||
Name: autoscalingListener.Name,
|
||||
Namespace: autoscalingListener.Namespace,
|
||||
Labels: labels,
|
||||
Annotations: make(map[string]string),
|
||||
},
|
||||
Spec: podSpec,
|
||||
}
|
||||
|
||||
newRunnerScaleSetListenerPod.Annotations[annotationKeyIntegrityHash] = scaleSetListenerPodIntegrity(
|
||||
newRunnerScaleSetListenerPod,
|
||||
autoscalingListener,
|
||||
podConfig,
|
||||
serviceAccount,
|
||||
role,
|
||||
roleBinding,
|
||||
metricsConfig,
|
||||
)
|
||||
|
||||
if err := b.setControllerReference(autoscalingListener, newRunnerScaleSetListenerPod); err != nil {
|
||||
return nil, fmt.Errorf("failed to set controller reference for listener pod: %w", err)
|
||||
}
|
||||
|
||||
if autoscalingListener.Spec.Template != nil {
|
||||
mergeListenerPodWithTemplate(newRunnerScaleSetListenerPod, autoscalingListener.Spec.Template)
|
||||
}
|
||||
@@ -338,6 +447,38 @@ func (b *ResourceBuilder) newScaleSetListenerPod(autoscalingListener *v1alpha1.A
|
||||
return newRunnerScaleSetListenerPod, nil
|
||||
}
|
||||
|
||||
func scaleSetListenerPodIntegrity(
|
||||
pod *corev1.Pod,
|
||||
autoscalingListener *v1alpha1.AutoscalingListener,
|
||||
podConfig *corev1.Secret,
|
||||
serviceAccount *corev1.ServiceAccount,
|
||||
role *rbacv1.Role,
|
||||
roleBinding *rbacv1.RoleBinding,
|
||||
metricsConfig *listenerMetricsServerConfig,
|
||||
) string {
|
||||
type data struct {
|
||||
ListenerPodSpec *corev1.PodSpec `json:"listenerPodSpec,omitempty"`
|
||||
AutoscalingListenerIntegrityHash string `json:"autoscalingListenerIntegrityHash"`
|
||||
ConfigSecretIntegrityHash string `json:"configSecretIntegrityHash"`
|
||||
ServiceAccountIntegrityHash string `json:"serviceAccountIntegrityHash"`
|
||||
RoleIntegrityHash string `json:"roleIntegrityHash"`
|
||||
RoleBindingIntegrityHash string `json:"roleBindingIntegrityHash"`
|
||||
MetricsConfig *listenerMetricsServerConfig `json:"metricsConfig,omitempty"`
|
||||
}
|
||||
|
||||
d := data{
|
||||
ListenerPodSpec: &pod.Spec,
|
||||
AutoscalingListenerIntegrityHash: autoscalingListener.Annotations[annotationKeyIntegrityHash],
|
||||
ConfigSecretIntegrityHash: podConfig.Annotations[annotationKeyIntegrityHash],
|
||||
ServiceAccountIntegrityHash: serviceAccount.Annotations[annotationKeyIntegrityHash],
|
||||
RoleIntegrityHash: role.Annotations[annotationKeyIntegrityHash],
|
||||
RoleBindingIntegrityHash: roleBinding.Annotations[annotationKeyIntegrityHash],
|
||||
MetricsConfig: metricsConfig,
|
||||
}
|
||||
|
||||
return hash.ComputeTemplateHash(&d)
|
||||
}
|
||||
|
||||
func mergeListenerPodWithTemplate(pod *corev1.Pod, tmpl *corev1.PodTemplateSpec) {
|
||||
if pod.Annotations == nil {
|
||||
pod.Annotations = make(map[string]string)
|
||||
@@ -455,7 +596,7 @@ func mergeListenerContainer(base, from *corev1.Container) {
|
||||
base.TTY = from.TTY
|
||||
}
|
||||
|
||||
func (b *ResourceBuilder) newScaleSetListenerServiceAccount(autoscalingListener *v1alpha1.AutoscalingListener) *corev1.ServiceAccount {
|
||||
func (b *ResourceBuilder) newScaleSetListenerServiceAccount(autoscalingListener *v1alpha1.AutoscalingListener) (*corev1.ServiceAccount, error) {
|
||||
base := &corev1.ServiceAccount{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: autoscalingListener.Name,
|
||||
@@ -464,6 +605,7 @@ func (b *ResourceBuilder) newScaleSetListenerServiceAccount(autoscalingListener
|
||||
LabelKeyGitHubScaleSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
||||
LabelKeyGitHubScaleSetName: autoscalingListener.Spec.AutoscalingRunnerSetName,
|
||||
}),
|
||||
Annotations: make(map[string]string),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -472,22 +614,40 @@ func (b *ResourceBuilder) newScaleSetListenerServiceAccount(autoscalingListener
|
||||
base.Annotations = b.mergeAnnotations(autoscalingListener.Spec.ServiceAccountMetadata.Annotations, base.Annotations)
|
||||
}
|
||||
|
||||
return base
|
||||
base.Annotations[annotationKeyIntegrityHash] = scaleSetListenerServiceAccountIntegrityHash(base)
|
||||
|
||||
if err := b.setControllerReference(autoscalingListener, base); err != nil {
|
||||
return nil, fmt.Errorf("failed to set controller reference for listener service account: %w", err)
|
||||
}
|
||||
|
||||
return base, nil
|
||||
}
|
||||
|
||||
func scaleSetListenerServiceAccountIntegrityHash(sa *corev1.ServiceAccount) string {
|
||||
type data struct {
|
||||
Secrets []corev1.ObjectReference `json:"secrets"`
|
||||
ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets"`
|
||||
AutomountServiceAccountToken *bool `json:"automountServiceAccountToken"`
|
||||
}
|
||||
|
||||
d := data{
|
||||
Secrets: sa.Secrets,
|
||||
ImagePullSecrets: sa.ImagePullSecrets,
|
||||
AutomountServiceAccountToken: sa.AutomountServiceAccountToken,
|
||||
}
|
||||
|
||||
return hash.ComputeTemplateHash(&d)
|
||||
}
|
||||
|
||||
func (b *ResourceBuilder) newScaleSetListenerRole(autoscalingListener *v1alpha1.AutoscalingListener) *rbacv1.Role {
|
||||
rules := rulesForListenerRole([]string{autoscalingListener.Spec.EphemeralRunnerSetName})
|
||||
rulesHash := hash.ComputeTemplateHash(&rules)
|
||||
|
||||
labels := b.filterAndMergeLabels(autoscalingListener.Labels, map[string]string{
|
||||
LabelKeyGitHubScaleSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
||||
LabelKeyGitHubScaleSetName: autoscalingListener.Spec.AutoscalingRunnerSetName,
|
||||
labelKeyListenerNamespace: autoscalingListener.Namespace,
|
||||
labelKeyListenerName: autoscalingListener.Name,
|
||||
"role-policy-rules-hash": rulesHash,
|
||||
})
|
||||
|
||||
var annotations map[string]string
|
||||
annotations := make(map[string]string)
|
||||
if autoscalingListener.Spec.RoleMetadata != nil {
|
||||
labels = b.filterAndMergeLabels(autoscalingListener.Spec.RoleMetadata.Labels, labels)
|
||||
annotations = b.mergeAnnotations(autoscalingListener.Spec.RoleMetadata.Annotations, nil)
|
||||
@@ -500,18 +660,31 @@ func (b *ResourceBuilder) newScaleSetListenerRole(autoscalingListener *v1alpha1.
|
||||
Labels: labels,
|
||||
Annotations: annotations,
|
||||
},
|
||||
Rules: rules,
|
||||
Rules: rulesForListenerRole([]string{autoscalingListener.Spec.EphemeralRunnerSetName}),
|
||||
}
|
||||
|
||||
newRole.Annotations[annotationKeyIntegrityHash] = scaleSetRoleIntegrityHash(newRole)
|
||||
|
||||
return newRole
|
||||
}
|
||||
|
||||
func scaleSetRoleIntegrityHash(role *rbacv1.Role) string {
|
||||
type data struct {
|
||||
Rules []rbacv1.PolicyRule `json:"rules"`
|
||||
}
|
||||
|
||||
d := data{
|
||||
Rules: role.Rules,
|
||||
}
|
||||
|
||||
return hash.ComputeTemplateHash(&d)
|
||||
}
|
||||
|
||||
func (b *ResourceBuilder) newScaleSetListenerRoleBinding(autoscalingListener *v1alpha1.AutoscalingListener, listenerRole *rbacv1.Role, serviceAccount *corev1.ServiceAccount) *rbacv1.RoleBinding {
|
||||
roleRef := rbacv1.RoleRef{
|
||||
Kind: "Role",
|
||||
Name: listenerRole.Name,
|
||||
}
|
||||
roleRefHash := hash.ComputeTemplateHash(&roleRef)
|
||||
|
||||
subjects := []rbacv1.Subject{
|
||||
{
|
||||
@@ -520,19 +693,15 @@ func (b *ResourceBuilder) newScaleSetListenerRoleBinding(autoscalingListener *v1
|
||||
Name: serviceAccount.Name,
|
||||
},
|
||||
}
|
||||
subjectHash := hash.ComputeTemplateHash(&subjects)
|
||||
|
||||
labels := b.filterAndMergeLabels(autoscalingListener.Labels, map[string]string{
|
||||
LabelKeyGitHubScaleSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
||||
LabelKeyGitHubScaleSetName: autoscalingListener.Spec.AutoscalingRunnerSetName,
|
||||
labelKeyListenerNamespace: autoscalingListener.Namespace,
|
||||
labelKeyListenerName: autoscalingListener.Name,
|
||||
"role-binding-role-ref-hash": roleRefHash,
|
||||
"role-binding-subject-hash": subjectHash,
|
||||
})
|
||||
|
||||
var annotations map[string]string
|
||||
|
||||
annotations := make(map[string]string)
|
||||
if autoscalingListener.Spec.RoleBindingMetadata != nil {
|
||||
labels = b.filterAndMergeLabels(autoscalingListener.Spec.RoleBindingMetadata.Labels, labels)
|
||||
annotations = autoscalingListener.Spec.RoleBindingMetadata.Annotations
|
||||
@@ -549,15 +718,45 @@ func (b *ResourceBuilder) newScaleSetListenerRoleBinding(autoscalingListener *v1
|
||||
Subjects: subjects,
|
||||
}
|
||||
|
||||
newRoleBinding.Annotations[annotationKeyIntegrityHash] = scaleSetListenerRoleBindingIntegrityHash(newRoleBinding)
|
||||
|
||||
return newRoleBinding
|
||||
}
|
||||
|
||||
func scaleSetListenerRoleBindingIntegrityHash(rb *rbacv1.RoleBinding) string {
|
||||
type data struct {
|
||||
RoleRef rbacv1.RoleRef `json:"roleRef"`
|
||||
Subjects []rbacv1.Subject `json:"subjects"`
|
||||
}
|
||||
|
||||
d := data{
|
||||
RoleRef: rb.RoleRef,
|
||||
Subjects: rb.Subjects,
|
||||
}
|
||||
|
||||
return hash.ComputeTemplateHash(&d)
|
||||
}
|
||||
|
||||
func (b *ResourceBuilder) newEphemeralRunnerSet(autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet) (*v1alpha1.EphemeralRunnerSet, error) {
|
||||
runnerScaleSetID, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIDAnnotationKey])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
runnerSpecHash := autoscalingRunnerSet.RunnerSetSpecHash()
|
||||
|
||||
spec := v1alpha1.EphemeralRunnerSetSpec{
|
||||
Replicas: 0,
|
||||
EphemeralRunnerSpec: v1alpha1.EphemeralRunnerSpec{
|
||||
RunnerScaleSetID: runnerScaleSetID,
|
||||
GitHubConfigURL: autoscalingRunnerSet.Spec.GitHubConfigUrl,
|
||||
GitHubConfigSecret: autoscalingRunnerSet.Spec.GitHubConfigSecret,
|
||||
Proxy: autoscalingRunnerSet.Spec.Proxy,
|
||||
GitHubServerTLS: autoscalingRunnerSet.Spec.GitHubServerTLS,
|
||||
PodTemplateSpec: autoscalingRunnerSet.Spec.Template,
|
||||
VaultConfig: autoscalingRunnerSet.VaultConfig(),
|
||||
EphemeralRunnerConfigSecretMetadata: autoscalingRunnerSet.Spec.EphemeralRunnerConfigSecretMetadata,
|
||||
},
|
||||
EphemeralRunnerMetadata: autoscalingRunnerSet.Spec.EphemeralRunnerMetadata,
|
||||
}
|
||||
|
||||
labels := b.filterAndMergeLabels(autoscalingRunnerSet.Labels, map[string]string{
|
||||
LabelKeyKubernetesPartOf: labelValueKubernetesPartOf,
|
||||
@@ -574,7 +773,6 @@ func (b *ResourceBuilder) newEphemeralRunnerSet(autoscalingRunnerSet *v1alpha1.A
|
||||
annotations := map[string]string{
|
||||
AnnotationKeyGitHubRunnerGroupName: autoscalingRunnerSet.Annotations[AnnotationKeyGitHubRunnerGroupName],
|
||||
AnnotationKeyGitHubRunnerScaleSetName: autoscalingRunnerSet.Annotations[AnnotationKeyGitHubRunnerScaleSetName],
|
||||
annotationKeyRunnerSpecHash: runnerSpecHash,
|
||||
}
|
||||
|
||||
if autoscalingRunnerSet.Spec.EphemeralRunnerSetMetadata != nil {
|
||||
@@ -585,41 +783,70 @@ func (b *ResourceBuilder) newEphemeralRunnerSet(autoscalingRunnerSet *v1alpha1.A
|
||||
newEphemeralRunnerSet := &v1alpha1.EphemeralRunnerSet{
|
||||
TypeMeta: metav1.TypeMeta{},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
GenerateName: autoscalingRunnerSet.Name + "-",
|
||||
Namespace: autoscalingRunnerSet.Namespace,
|
||||
Labels: labels,
|
||||
Annotations: annotations,
|
||||
OwnerReferences: []metav1.OwnerReference{
|
||||
{
|
||||
APIVersion: v1alpha1.GroupVersion.String(),
|
||||
Kind: "AutoscalingRunnerSet",
|
||||
UID: autoscalingRunnerSet.GetUID(),
|
||||
Name: autoscalingRunnerSet.GetName(),
|
||||
Controller: new(true),
|
||||
BlockOwnerDeletion: new(true),
|
||||
},
|
||||
},
|
||||
},
|
||||
Spec: v1alpha1.EphemeralRunnerSetSpec{
|
||||
Replicas: 0,
|
||||
EphemeralRunnerSpec: v1alpha1.EphemeralRunnerSpec{
|
||||
RunnerScaleSetID: runnerScaleSetID,
|
||||
GitHubConfigUrl: autoscalingRunnerSet.Spec.GitHubConfigUrl,
|
||||
GitHubConfigSecret: autoscalingRunnerSet.Spec.GitHubConfigSecret,
|
||||
Proxy: autoscalingRunnerSet.Spec.Proxy,
|
||||
GitHubServerTLS: autoscalingRunnerSet.Spec.GitHubServerTLS,
|
||||
PodTemplateSpec: autoscalingRunnerSet.Spec.Template,
|
||||
VaultConfig: autoscalingRunnerSet.VaultConfig(),
|
||||
EphemeralRunnerConfigSecretMetadata: autoscalingRunnerSet.Spec.EphemeralRunnerConfigSecretMetadata,
|
||||
},
|
||||
EphemeralRunnerMetadata: autoscalingRunnerSet.Spec.EphemeralRunnerMetadata,
|
||||
Name: autoscalingRunnerSet.Name,
|
||||
Namespace: autoscalingRunnerSet.Namespace,
|
||||
Labels: labels,
|
||||
Annotations: annotations,
|
||||
},
|
||||
Spec: spec,
|
||||
}
|
||||
|
||||
newEphemeralRunnerSet.Annotations[annotationKeyIntegrityHash] = ephemeralRunnerSetIntegrityHash(newEphemeralRunnerSet)
|
||||
|
||||
if err := b.setControllerReference(autoscalingRunnerSet, newEphemeralRunnerSet); err != nil {
|
||||
return nil, fmt.Errorf("failed to set controller reference for ephemeral runner set: %w", err)
|
||||
}
|
||||
|
||||
return newEphemeralRunnerSet, nil
|
||||
}
|
||||
|
||||
func (b *ResourceBuilder) newEphemeralRunner(ephemeralRunnerSet *v1alpha1.EphemeralRunnerSet) *v1alpha1.EphemeralRunner {
|
||||
func ephemeralRunnerSetIntegrityHash(ers *v1alpha1.EphemeralRunnerSet) string {
|
||||
type data struct {
|
||||
EphemeralRunnerSpec v1alpha1.EphemeralRunnerSpec `json:"ephemeralRunnerSpec"`
|
||||
}
|
||||
|
||||
d := data{
|
||||
EphemeralRunnerSpec: ers.Spec.EphemeralRunnerSpec,
|
||||
}
|
||||
return hash.ComputeTemplateHash(&d)
|
||||
}
|
||||
|
||||
func (b *ResourceBuilder) newAutoscalingListenerProxySecret(autoscalingListener *v1alpha1.AutoscalingListener, data map[string][]byte) (*corev1.Secret, error) {
|
||||
newProxySecret := &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: proxyListenerSecretName(autoscalingListener),
|
||||
Namespace: autoscalingListener.Namespace,
|
||||
Labels: map[string]string{
|
||||
LabelKeyGitHubScaleSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
||||
LabelKeyGitHubScaleSetName: autoscalingListener.Spec.AutoscalingRunnerSetName,
|
||||
},
|
||||
Annotations: make(map[string]string, 1),
|
||||
},
|
||||
Data: data,
|
||||
}
|
||||
|
||||
newProxySecret.Annotations[annotationKeyIntegrityHash] = autoscalingListenerProxySecretIntegrityHash(newProxySecret)
|
||||
|
||||
if err := b.setControllerReference(autoscalingListener, newProxySecret); err != nil {
|
||||
return nil, fmt.Errorf("failed to set controller reference for listener proxy secret: %w", err)
|
||||
}
|
||||
|
||||
return newProxySecret, nil
|
||||
}
|
||||
|
||||
func autoscalingListenerProxySecretIntegrityHash(secret *corev1.Secret) string {
|
||||
type data struct {
|
||||
Data map[string][]byte `json:"data"`
|
||||
}
|
||||
|
||||
d := data{
|
||||
Data: secret.Data,
|
||||
}
|
||||
|
||||
return hash.ComputeTemplateHash(&d)
|
||||
}
|
||||
|
||||
func (b *ResourceBuilder) newEphemeralRunner(ephemeralRunnerSet *v1alpha1.EphemeralRunnerSet) (*v1alpha1.EphemeralRunner, error) {
|
||||
labels := make(map[string]string, len(ephemeralRunnerSet.Labels))
|
||||
maps.Copy(labels, ephemeralRunnerSet.Labels)
|
||||
labels[LabelKeyKubernetesComponent] = "runner"
|
||||
@@ -633,7 +860,7 @@ func (b *ResourceBuilder) newEphemeralRunner(ephemeralRunnerSet *v1alpha1.Epheme
|
||||
annotations = b.mergeAnnotations(ephemeralRunnerSet.Spec.EphemeralRunnerMetadata.Annotations, annotations)
|
||||
}
|
||||
|
||||
return &v1alpha1.EphemeralRunner{
|
||||
ephemeralRunner := &v1alpha1.EphemeralRunner{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
GenerateName: ephemeralRunnerSet.Name + "-runner-",
|
||||
Namespace: ephemeralRunnerSet.Namespace,
|
||||
@@ -643,22 +870,17 @@ func (b *ResourceBuilder) newEphemeralRunner(ephemeralRunnerSet *v1alpha1.Epheme
|
||||
ephemeralRunnerFinalizerName,
|
||||
ephemeralRunnerActionsFinalizerName,
|
||||
},
|
||||
OwnerReferences: []metav1.OwnerReference{
|
||||
{
|
||||
APIVersion: v1alpha1.GroupVersion.String(),
|
||||
Kind: "EphemeralRunnerSet",
|
||||
UID: ephemeralRunnerSet.GetUID(),
|
||||
Name: ephemeralRunnerSet.GetName(),
|
||||
Controller: new(true),
|
||||
BlockOwnerDeletion: new(true),
|
||||
},
|
||||
},
|
||||
},
|
||||
Spec: ephemeralRunnerSet.Spec.EphemeralRunnerSpec,
|
||||
}
|
||||
if err := b.setControllerReference(ephemeralRunnerSet, ephemeralRunner); err != nil {
|
||||
return nil, fmt.Errorf("failed to set controller reference for ephemeral runner: %w", err)
|
||||
}
|
||||
|
||||
return ephemeralRunner, nil
|
||||
}
|
||||
|
||||
func (b *ResourceBuilder) newEphemeralRunnerPod(runner *v1alpha1.EphemeralRunner, secret *corev1.Secret, envs ...corev1.EnvVar) *corev1.Pod {
|
||||
func (b *ResourceBuilder) newEphemeralRunnerPod(runner *v1alpha1.EphemeralRunner, secret *corev1.Secret, envs ...corev1.EnvVar) (*corev1.Pod, error) {
|
||||
var newPod corev1.Pod
|
||||
|
||||
annotations := make(map[string]string, len(runner.Annotations)+len(runner.Spec.Annotations))
|
||||
@@ -681,16 +903,6 @@ func (b *ResourceBuilder) newEphemeralRunnerPod(runner *v1alpha1.EphemeralRunner
|
||||
Namespace: runner.Namespace,
|
||||
Labels: labels,
|
||||
Annotations: annotations,
|
||||
OwnerReferences: []metav1.OwnerReference{
|
||||
{
|
||||
APIVersion: v1alpha1.GroupVersion.String(),
|
||||
Kind: "EphemeralRunner",
|
||||
UID: runner.GetUID(),
|
||||
Name: runner.GetName(),
|
||||
Controller: new(true),
|
||||
BlockOwnerDeletion: new(true),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
newPod.ObjectMeta = objectMeta
|
||||
@@ -727,10 +939,14 @@ func (b *ResourceBuilder) newEphemeralRunnerPod(runner *v1alpha1.EphemeralRunner
|
||||
newPod.Spec.Containers = append(newPod.Spec.Containers, c)
|
||||
}
|
||||
|
||||
return &newPod
|
||||
if err := b.setControllerReference(runner, &newPod); err != nil {
|
||||
return nil, fmt.Errorf("failed to set controller reference for ephemeral runner pod: %w", err)
|
||||
}
|
||||
|
||||
return &newPod, nil
|
||||
}
|
||||
|
||||
func (b *ResourceBuilder) newEphemeralRunnerJitSecret(ephemeralRunner *v1alpha1.EphemeralRunner, jitConfig *scaleset.RunnerScaleSetJitRunnerConfig) *corev1.Secret {
|
||||
func (b *ResourceBuilder) newEphemeralRunnerJitSecret(ephemeralRunner *v1alpha1.EphemeralRunner, jitConfig *scaleset.RunnerScaleSetJitRunnerConfig) (*corev1.Secret, error) {
|
||||
var (
|
||||
labels map[string]string
|
||||
annotations map[string]string
|
||||
@@ -741,7 +957,7 @@ func (b *ResourceBuilder) newEphemeralRunnerJitSecret(ephemeralRunner *v1alpha1.
|
||||
annotations = ephemeralRunner.Spec.EphemeralRunnerConfigSecretMetadata.Annotations
|
||||
}
|
||||
|
||||
return &corev1.Secret{
|
||||
jitSecret := &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: ephemeralRunner.Name,
|
||||
Namespace: ephemeralRunner.Namespace,
|
||||
@@ -755,10 +971,50 @@ func (b *ResourceBuilder) newEphemeralRunnerJitSecret(ephemeralRunner *v1alpha1.
|
||||
"scaleSetId": []byte(strconv.Itoa(jitConfig.Runner.RunnerScaleSetID)),
|
||||
},
|
||||
}
|
||||
if err := b.setControllerReference(ephemeralRunner, jitSecret); err != nil {
|
||||
return nil, fmt.Errorf("failed to set controller reference for ephemeral runner jit secret: %w", err)
|
||||
}
|
||||
|
||||
return jitSecret, nil
|
||||
}
|
||||
|
||||
func (b *ResourceBuilder) newEphemeralRunnerSetProxySecret(ephemeralRunnerSet *v1alpha1.EphemeralRunnerSet, data map[string][]byte) (*corev1.Secret, error) {
|
||||
runnerPodProxySecret := &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: proxyEphemeralRunnerSetSecretName(ephemeralRunnerSet),
|
||||
Namespace: ephemeralRunnerSet.Namespace,
|
||||
Labels: map[string]string{
|
||||
LabelKeyGitHubScaleSetName: ephemeralRunnerSet.Labels[LabelKeyGitHubScaleSetName],
|
||||
LabelKeyGitHubScaleSetNamespace: ephemeralRunnerSet.Labels[LabelKeyGitHubScaleSetNamespace],
|
||||
},
|
||||
Annotations: make(map[string]string, 1),
|
||||
},
|
||||
Data: data,
|
||||
}
|
||||
|
||||
runnerPodProxySecret.Annotations[annotationKeyIntegrityHash] = ephemeralRunnerSetProxySecretZIdentityHash(runnerPodProxySecret)
|
||||
|
||||
if err := b.setControllerReference(ephemeralRunnerSet, runnerPodProxySecret); err != nil {
|
||||
return nil, fmt.Errorf("failed to set controller reference for ephemeral runner set proxy secret: %w", err)
|
||||
}
|
||||
|
||||
return runnerPodProxySecret, nil
|
||||
}
|
||||
|
||||
func ephemeralRunnerSetProxySecretZIdentityHash(secret *corev1.Secret) string {
|
||||
type data struct {
|
||||
Data map[string][]byte `json:"data"`
|
||||
}
|
||||
|
||||
d := data{
|
||||
Data: secret.Data,
|
||||
}
|
||||
|
||||
return hash.ComputeTemplateHash(&d)
|
||||
}
|
||||
|
||||
func scaleSetListenerConfigName(autoscalingListener *v1alpha1.AutoscalingListener) string {
|
||||
return fmt.Sprintf("%s-config", autoscalingListener.Name)
|
||||
return autoscalingListener.Name + "-config"
|
||||
}
|
||||
|
||||
func hashSuffix(namespace, runnerGroup, configURL string) string {
|
||||
|
||||
Reference in New Issue
Block a user