mirror of
https://github.com/actions/actions-runner-controller.git
synced 2026-02-01 18:10:54 +08:00
Compare commits
6 Commits
master
...
nikola-jok
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0824407642 | ||
|
|
14c9793b0b | ||
|
|
87c91832e2 | ||
|
|
79b2ff087c | ||
|
|
506abf167d | ||
|
|
a1a796ee4d |
14
.github/workflows/gha-validate-chart.yaml
vendored
14
.github/workflows/gha-validate-chart.yaml
vendored
@@ -18,7 +18,7 @@ on:
|
||||
workflow_dispatch:
|
||||
env:
|
||||
KUBE_SCORE_VERSION: 1.16.1
|
||||
HELM_VERSION: v3.17.0
|
||||
HELM_VERSION: v3.19.4
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -61,6 +61,18 @@ jobs:
|
||||
if [[ -n "$changed" ]]; then
|
||||
echo "changed=true" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
echo "changed_charts<<EOF" >> $GITHUB_OUTPUT
|
||||
echo "$changed" >> $GITHUB_OUTPUT
|
||||
echo "EOF" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Install helm-unittest
|
||||
if: contains(steps.list-changed.outputs.changed_charts, 'charts/gha-runner-scale-set-controller-experimental')
|
||||
run: |
|
||||
helm plugin install https://github.com/helm-unittest/helm-unittest.git
|
||||
- name: Run helm-unittest (gha-runner-scale-set-controller-experimental)
|
||||
if: contains(steps.list-changed.outputs.changed_charts, 'charts/gha-runner-scale-set-controller-experimental')
|
||||
run: |
|
||||
helm unittest ./charts/gha-runner-scale-set-controller-experimental/
|
||||
|
||||
- name: Run chart-testing (lint)
|
||||
run: |
|
||||
|
||||
4
Makefile
4
Makefile
@@ -182,6 +182,10 @@ chart-crds:
|
||||
cp config/crd/bases/actions.github.com_autoscalinglisteners.yaml charts/gha-runner-scale-set-controller/crds/
|
||||
cp config/crd/bases/actions.github.com_ephemeralrunnersets.yaml charts/gha-runner-scale-set-controller/crds/
|
||||
cp config/crd/bases/actions.github.com_ephemeralrunners.yaml charts/gha-runner-scale-set-controller/crds/
|
||||
cp config/crd/bases/actions.github.com_autoscalingrunnersets.yaml charts/gha-runner-scale-set-controller-experimental/crds/
|
||||
cp config/crd/bases/actions.github.com_autoscalinglisteners.yaml charts/gha-runner-scale-set-controller-experimental/crds/
|
||||
cp config/crd/bases/actions.github.com_ephemeralrunnersets.yaml charts/gha-runner-scale-set-controller-experimental/crds/
|
||||
cp config/crd/bases/actions.github.com_ephemeralrunners.yaml charts/gha-runner-scale-set-controller-experimental/crds/
|
||||
rm charts/actions-runner-controller/crds/actions.github.com_autoscalingrunnersets.yaml
|
||||
rm charts/actions-runner-controller/crds/actions.github.com_autoscalinglisteners.yaml
|
||||
rm charts/actions-runner-controller/crds/actions.github.com_ephemeralrunnersets.yaml
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# Patterns to ignore when building packages.
|
||||
# This supports shell glob matching, relative path matching, and
|
||||
# negation (prefixed with !). Only one pattern per line.
|
||||
.DS_Store
|
||||
# Common VCS dirs
|
||||
.git/
|
||||
.gitignore
|
||||
.bzr/
|
||||
.bzrignore
|
||||
.hg/
|
||||
.hgignore
|
||||
.svn/
|
||||
# Common backup files
|
||||
*.swp
|
||||
*.bak
|
||||
*.tmp
|
||||
*.orig
|
||||
*~
|
||||
# Various IDEs
|
||||
.project
|
||||
.idea/
|
||||
*.tmproj
|
||||
.vscode/
|
||||
tests/
|
||||
@@ -0,0 +1,33 @@
|
||||
apiVersion: v2
|
||||
name: gha-runner-scale-set-controller-experimental
|
||||
description: A Helm chart for install actions-runner-controller CRD
|
||||
|
||||
# A chart can be either an 'application' or a 'library' chart.
|
||||
#
|
||||
# Application charts are a collection of templates that can be packaged into versioned archives
|
||||
# to be deployed.
|
||||
#
|
||||
# Library charts provide useful utilities or functions for the chart developer. They're included as
|
||||
# a dependency of application charts to inject those utilities and functions into the rendering
|
||||
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
|
||||
type: application
|
||||
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 0.14.0
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||
# It is recommended to use it with quotes.
|
||||
appVersion: "0.14.0"
|
||||
|
||||
home: https://github.com/actions/actions-runner-controller
|
||||
|
||||
sources:
|
||||
- "https://github.com/actions/actions-runner-controller"
|
||||
|
||||
maintainers:
|
||||
- name: actions
|
||||
url: https://github.com/actions
|
||||
@@ -0,0 +1,5 @@
|
||||
# Set the following to dummy values.
|
||||
# This is only useful in CI
|
||||
controller:
|
||||
manager:
|
||||
image: test-arc:dev
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
||||
Thank you for installing {{ .Chart.Name }}.
|
||||
|
||||
Your release is named {{ .Release.Name }}.
|
||||
@@ -0,0 +1,67 @@
|
||||
{{/*
|
||||
Allow overriding the namespace for the resources.
|
||||
*/}}
|
||||
{{- define "gha-controller.namespace" -}}
|
||||
{{- if .Values.namespaceOverride }}
|
||||
{{- .Values.namespaceOverride }}
|
||||
{{- else }}
|
||||
{{- .Release.Namespace }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name.
|
||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||
If release name contains chart name it will be used as a full name.
|
||||
*/}}
|
||||
{{- define "gha-controller.name" -}}
|
||||
{{- if .Values.nameOverride }}
|
||||
{{- .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- $name := default (include "gha-base-name" .) .Values.nameOverride }}
|
||||
{{- if contains $name .Release.Name }}
|
||||
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Labels applied to the controller deployment
|
||||
*/}}
|
||||
{{- define "gha-controller.labels" -}}
|
||||
{{- $resourceLabels := dict "app.kubernetes.io/component" "controller-manager" -}}
|
||||
{{- $commonLabels := include "gha-common.labels" . | fromYaml -}}
|
||||
{{- $userLabels := include "apply-non-reserved-gha-labels-and-annotations" (.Values.controller.metadata.labels | default (dict)) | fromYaml -}}
|
||||
{{- $global := include "apply-non-reserved-gha-labels-and-annotations" (.Values.labels | default (dict)) | fromYaml -}}
|
||||
{{- $labels := mergeOverwrite $global $userLabels $resourceLabels $commonLabels -}}
|
||||
|
||||
{{- /* Reserved actions.github.com/* labels owned by the chart itself */ -}}
|
||||
{{- $_ := set $labels "actions.github.com/controller-service-account-namespace" (include "gha-controller.namespace" .) -}}
|
||||
{{- $_ := set $labels "actions.github.com/controller-service-account-name" (include "gha-controller.service-account-name" .) -}}
|
||||
{{- with .Values.controller.manager.config.watchSingleNamespace }}
|
||||
{{- $_ := set $labels "actions.github.com/controller-watch-single-namespace" . -}}
|
||||
{{- end }}
|
||||
|
||||
{{- toYaml $labels -}}
|
||||
{{- end }}
|
||||
|
||||
|
||||
{{/*
|
||||
Create the name of the service account to use
|
||||
*/}}
|
||||
{{- define "gha-controller.service-account-name" -}}
|
||||
{{- if eq .Values.controller.serviceAccount.name "default"}}
|
||||
{{- fail "serviceAccount.name cannot be set to 'default'" }}
|
||||
{{- end }}
|
||||
{{- if .Values.controller.serviceAccount.create }}
|
||||
{{- default (include "gha-controller.name" .) .Values.controller.serviceAccount.name }}
|
||||
{{- else }}
|
||||
{{- if not .Values.controller.serviceAccount.name }}
|
||||
{{- fail "serviceAccount.name must be set if serviceAccount.create is false" }}
|
||||
{{- else }}
|
||||
{{- .Values.controller.serviceAccount.name }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,126 @@
|
||||
|
||||
{{/*
|
||||
Labels applied to the controller Pod template (spec.template.metadata.labels)
|
||||
*/}}
|
||||
{{- define "gha-controller-template.labels" -}}
|
||||
{{- $static := dict "app.kubernetes.io/part-of" "gha-rs-controller" "app.kubernetes.io/component" "controller-manager" -}}
|
||||
{{- $_ := set $static "app.kubernetes.io/version" (.Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-") -}}
|
||||
{{- $selector := include "gha-controller.selector-labels" . | fromYaml -}}
|
||||
{{- $podUser := include "apply-non-reserved-gha-labels-and-annotations" (.Values.controller.pod.metadata.labels | default (dict)) | fromYaml -}}
|
||||
{{- $labels := mergeOverwrite $podUser $selector $static -}}
|
||||
{{- toYaml $labels -}}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Annotations applied to the controller Pod template (spec.template.metadata.annotations)
|
||||
*/}}
|
||||
{{- define "gha-controller-template.annotations" -}}
|
||||
{{- $static := dict "kubectl.kubernetes.io/default-container" "manager" -}}
|
||||
{{- $podUser := include "apply-non-reserved-gha-labels-and-annotations" (.Values.controller.pod.metadata.annotations | default (dict)) | fromYaml -}}
|
||||
{{- $annotations := mergeOverwrite $podUser $static -}}
|
||||
{{- toYaml $annotations -}}
|
||||
{{- end }}
|
||||
|
||||
{{- define "gha-controller-template.manager-container" -}}
|
||||
name: manager
|
||||
image: "{{ .Values.controller.manager.container.image }}"
|
||||
imagePullPolicy: {{ default .Values.controller.manager.container.pullPolicy "IfNotPresent" }}
|
||||
command:
|
||||
- "/manager"
|
||||
args:
|
||||
- "--auto-scaling-runner-set-only"
|
||||
{{- if gt (int (default 1 .Values.controller.replicaCount)) 1 }}
|
||||
- "--enable-leader-election"
|
||||
- "--leader-election-id={{ include "gha-controller.name" . }}"
|
||||
{{- end }}
|
||||
{{- with .Values.imagePullSecrets }}
|
||||
{{- range . }}
|
||||
- "--auto-scaler-image-pull-secrets={{- .name -}}"
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- with .Values.controller.manager.config.logLevel }}
|
||||
- "--log-level={{ . }}"
|
||||
{{- end }}
|
||||
{{- with .Values.controller.manager.config.logFormat }}
|
||||
- "--log-format={{ . }}"
|
||||
{{- end }}
|
||||
{{- with .Values.controller.manager.config.watchSingleNamespace }}
|
||||
- "--watch-single-namespace={{ . }}"
|
||||
{{- end }}
|
||||
{{- with .Values.controller.manager.config.runnerMaxConcurrentReconciles }}
|
||||
- "--runner-max-concurrent-reconciles={{ . }}"
|
||||
{{- end }}
|
||||
{{- with .Values.controller.manager.config.updateStrategy }}
|
||||
- "--update-strategy={{ . }}"
|
||||
{{- end }}
|
||||
{{- if .Values.controller.metrics }}
|
||||
{{- with .Values.controller.metrics }}
|
||||
- "--listener-metrics-addr={{ .listenerAddr }}"
|
||||
- "--listener-metrics-endpoint={{ .listenerEndpoint }}"
|
||||
- "--metrics-addr={{ .controllerManagerAddr }}"
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
- "--listener-metrics-addr=0"
|
||||
- "--listener-metrics-endpoint="
|
||||
- "--metrics-addr=0"
|
||||
{{- end }}
|
||||
{{- range .Values.controller.manager.config.excludeLabelPropagationPrefixes }}
|
||||
- "--exclude-label-propagation-prefix={{ . }}"
|
||||
{{- end }}
|
||||
{{- with .Values.controller.manager.config.k8sClientRateLimiterQPS }}
|
||||
- "--k8s-client-rate-limiter-qps={{ . }}"
|
||||
{{- end }}
|
||||
{{- with .Values.controller.manager.config.k8sClientRateLimiterBurst }}
|
||||
- "--k8s-client-rate-limiter-burst={{ . }}"
|
||||
{{- end }}
|
||||
{{- with .Values.controller.manager.container.extraArgs }}
|
||||
{{- range . }}
|
||||
- "{{ . }}"
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- $ports := list -}}
|
||||
{{- if .Values.controller.metrics }}
|
||||
{{- $metricsPort := dict "containerPort" ((regexReplaceAll ":([0-9]+)" .Values.controller.metrics.controllerManagerAddr "${1}") | int) "protocol" "TCP" "name" "metrics" -}}
|
||||
{{- $ports = append $ports $metricsPort -}}
|
||||
{{- end }}
|
||||
{{- with .Values.controller.manager.container.extraPorts }}
|
||||
{{- if kindIs "slice" . }}
|
||||
{{- $ports = concat $ports . -}}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if gt (len $ports) 0 }}
|
||||
ports:
|
||||
{{- toYaml $ports | nindent 2 }}
|
||||
{{- end }}
|
||||
env:
|
||||
- name: CONTROLLER_MANAGER_CONTAINER_IMAGE
|
||||
value: "{{ .Values.controller.manager.container.image }}"
|
||||
- name: CONTROLLER_MANAGER_POD_NAMESPACE
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.namespace
|
||||
{{- with .Values.controller.manager.container.env }}
|
||||
{{- if kindIs "slice" . }}
|
||||
{{- toYaml . | nindent 2 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- with .Values.controller.manager.container.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 2 }}
|
||||
{{- end }}
|
||||
{{- with .Values.controller.manager.container.securityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 2 }}
|
||||
{{- end }}
|
||||
volumeMounts:
|
||||
- mountPath: /tmp
|
||||
name: tmp
|
||||
{{- with .Values.controller.manager.container.extraVolumeMounts }}
|
||||
{{- range . }}
|
||||
- {{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range .Values.controller.pod.extraVolumeMounts }}
|
||||
- {{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,74 @@
|
||||
{{- define "gha-base-name" -}}
|
||||
gha-rs-controller
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create chart name and version as used by the chart label.
|
||||
*/}}
|
||||
{{- define "gha-controller.chart" -}}
|
||||
{{- printf "%s-%s" (include "gha-base-name" .) .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Common labels
|
||||
*/}}
|
||||
{{- define "gha-common.labels" -}}
|
||||
helm.sh/chart: {{ include "gha-controller.chart" . }}
|
||||
{{- if .Chart.AppVersion }}
|
||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||
{{- end }}
|
||||
app.kubernetes.io/part-of: "gha-rs-controller"
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
|
||||
app.kubernetes.io/name: {{ include "gha-controller.name" . }}
|
||||
app.kubernetes.io/namespace: {{ include "gha-controller.namespace" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end }}
|
||||
|
||||
|
||||
{{- define "gha-controller.manager-cluster-role-name" -}}
|
||||
{{- include "gha-controller.name" . }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "gha-controller.manager-cluster-role-binding" -}}
|
||||
{{- include "gha-controller.name" . }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "gha-controller.manager-single-namespace-role-name" -}}
|
||||
{{- include "gha-controller.name" . }}-single-namespace
|
||||
{{- end }}
|
||||
|
||||
{{- define "gha-controller.manager-single-namespace-role-binding" -}}
|
||||
{{- include "gha-controller.name" . }}-single-namespace
|
||||
{{- end }}
|
||||
|
||||
{{- define "gha-controller.manager-single-namespace-watch-role-name" -}}
|
||||
{{- include "gha-controller.name" . }}-single-namespace-watch
|
||||
{{- end }}
|
||||
|
||||
{{- define "gha-controller.manager-single-namespace-watch-role-binding" -}}
|
||||
{{- include "gha-controller.name" . }}-single-namespace-watch
|
||||
{{- end }}
|
||||
|
||||
{{- define "gha-controller.manager-listener-role-name" -}}
|
||||
{{- include "gha-controller.name" . }}-listener
|
||||
{{- end }}
|
||||
|
||||
{{- define "gha-controller.manager-listener-role-binding" -}}
|
||||
{{- include "gha-controller.name" . }}-listener
|
||||
{{- end }}
|
||||
|
||||
{{- define "gha-controller.leaderElectionRoleName" -}}
|
||||
{{- include "gha-controller.name" . }}-leader-election
|
||||
{{- end }}
|
||||
|
||||
{{- define "gha-controller.leader-election-role-name" -}}
|
||||
{{- include "gha-controller.leaderElectionRoleName" . -}}
|
||||
{{- end }}
|
||||
|
||||
{{- define "gha-controller.leaderElectionRoleBinding" -}}
|
||||
{{- include "gha-controller.name" . }}-leader-election
|
||||
{{- end }}
|
||||
|
||||
{{- define "gha-controller.leader-election-role-binding" -}}
|
||||
{{- include "gha-controller.leaderElectionRoleBinding" . -}}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,25 @@
|
||||
{{/*
|
||||
Takes a map of user labels and removes the ones with "actions.github.com/" prefix
|
||||
*/}}
|
||||
{{- define "apply-non-reserved-gha-labels-and-annotations" -}}
|
||||
{{- $userLabels := . -}}
|
||||
{{- $processed := dict -}}
|
||||
{{- range $key, $value := $userLabels -}}
|
||||
{{- if not (hasPrefix "actions.github.com/" $key) -}}
|
||||
{{- $_ := set $processed $key $value -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- if not (empty $processed) -}}
|
||||
{{- $processed | toYaml }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "gha-controller.selector-labels" -}}
|
||||
app.kubernetes.io/name: {{ include "gha-controller.name" . }}
|
||||
app.kubernetes.io/namespace: {{ include "gha-controller.namespace" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "gha-controller.labels" -}}
|
||||
{{- include "gha-controller.labels" . -}}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,42 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "gha-controller.name" . }}
|
||||
namespace: {{ include "gha-controller.namespace" . }}
|
||||
labels:
|
||||
{{- include "gha-controller.labels" . | nindent 4 }}
|
||||
spec:
|
||||
replicas: {{ default 1 .Values.controller.replicaCount }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "gha-controller.selector-labels" . | nindent 6 }}
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
{{- include "gha-controller-template.annotations" . | nindent 8 }}
|
||||
labels:
|
||||
{{- include "gha-controller-template.labels" . | nindent 8 }}
|
||||
spec:
|
||||
{{- with .Values.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
serviceAccountName: {{ include "gha-controller.service-account-name" . }}
|
||||
containers:
|
||||
-
|
||||
{{- include "gha-controller-template.manager-container" . | nindent 10 }}
|
||||
{{- range .Values.controller.pod.containers }}
|
||||
-
|
||||
{{- toYaml . | nindent 10 }}
|
||||
{{- end }}
|
||||
terminationGracePeriodSeconds: {{ default 10 .Values.controller.pod.terminationGracePeriodSeconds }}
|
||||
volumes:
|
||||
- name: tmp
|
||||
emptyDir: {}
|
||||
{{- range .Values.controller.pod.extraVolumes }}
|
||||
- {{- toYaml . | nindent 10 }}
|
||||
{{- end }}
|
||||
{{- $runnerPodSpecExtraFields := (omit .Values.controller.pod "containers" "serviceAccountName" "terminationGracePeriodSeconds") -}}
|
||||
{{- if gt (len $runnerPodSpecExtraFields) 0 }}
|
||||
{{- toYaml $runnerPodSpecExtraFields | nindent 6 }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,15 @@
|
||||
{{- if gt (int (default 1 .Values.controller.replicaCount)) 1 }}
|
||||
# permissions to do leader election.
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: {{ include "gha-controller.leader-election-role-name" . }}
|
||||
namespace: {{ include "gha-controller.namespace" . }}
|
||||
rules:
|
||||
- apiGroups: ["coordination.k8s.io"]
|
||||
resources: ["leases"]
|
||||
verbs: ["get", "watch", "list", "delete", "update", "create"]
|
||||
- apiGroups: [""]
|
||||
resources: ["events"]
|
||||
verbs: ["create", "patch"]
|
||||
{{- end }}
|
||||
@@ -0,0 +1,15 @@
|
||||
{{- if gt (int (default 1 .Values.controller.replicaCount)) 1 }}
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: {{ include "gha-controller.leader-election-role-binding" . }}
|
||||
namespace: {{ include "gha-controller.namespace" . }}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: {{ include "gha-controller.leader-election-role-name" . }}
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ include "gha-controller.service-account-name" . }}
|
||||
namespace: {{ include "gha-controller.namespace" . }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,144 @@
|
||||
{{- if empty .Values.controller.manager.config.watchSingleNamespace }}
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: {{ include "gha-controller.manager-cluster-role-name" . }}
|
||||
rules:
|
||||
- apiGroups:
|
||||
- actions.github.com
|
||||
resources:
|
||||
- autoscalingrunnersets
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- actions.github.com
|
||||
resources:
|
||||
- autoscalingrunnersets/finalizers
|
||||
verbs:
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- actions.github.com
|
||||
resources:
|
||||
- autoscalingrunnersets/status
|
||||
verbs:
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- actions.github.com
|
||||
resources:
|
||||
- autoscalinglisteners
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- actions.github.com
|
||||
resources:
|
||||
- autoscalinglisteners/status
|
||||
verbs:
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- actions.github.com
|
||||
resources:
|
||||
- autoscalinglisteners/finalizers
|
||||
verbs:
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- actions.github.com
|
||||
resources:
|
||||
- ephemeralrunnersets
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- actions.github.com
|
||||
resources:
|
||||
- ephemeralrunnersets/status
|
||||
verbs:
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- actions.github.com
|
||||
resources:
|
||||
- ephemeralrunnersets/finalizers
|
||||
verbs:
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- actions.github.com
|
||||
resources:
|
||||
- ephemeralrunners
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- actions.github.com
|
||||
resources:
|
||||
- ephemeralrunners/finalizers
|
||||
verbs:
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- actions.github.com
|
||||
resources:
|
||||
- ephemeralrunners/status
|
||||
verbs:
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- pods
|
||||
verbs:
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- serviceaccounts
|
||||
verbs:
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- rbac.authorization.k8s.io
|
||||
resources:
|
||||
- rolebindings
|
||||
verbs:
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- rbac.authorization.k8s.io
|
||||
resources:
|
||||
- roles
|
||||
verbs:
|
||||
- list
|
||||
- watch
|
||||
- patch
|
||||
{{- end }}
|
||||
@@ -0,0 +1,14 @@
|
||||
{{- if empty .Values.controller.manager.config.watchSingleNamespace }}
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: {{ include "gha-controller.manager-cluster-role-binding" . }}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: {{ include "gha-controller.manager-cluster-role-name" . }}
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ include "gha-controller.service-account-name" . }}
|
||||
namespace: {{ include "gha-controller.namespace" . }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,40 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: {{ include "gha-controller.manager-listener-role-name" . }}
|
||||
namespace: {{ include "gha-controller.namespace" . }}
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- pods
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- pods/status
|
||||
verbs:
|
||||
- get
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- secrets
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- serviceaccounts
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
@@ -0,0 +1,13 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: {{ include "gha-controller.manager-listener-role-binding" . }}
|
||||
namespace: {{ include "gha-controller.namespace" . }}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: {{ include "gha-controller.manager-listener-role-name" . }}
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ include "gha-controller.service-account-name" . }}
|
||||
namespace: {{ include "gha-controller.namespace" . }}
|
||||
@@ -0,0 +1,84 @@
|
||||
{{- if .Values.controller.manager.config.watchSingleNamespace }}
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: {{ include "gha-controller.manager-single-namespace-role-name" . }}
|
||||
namespace: {{ include "gha-controller.namespace" . }}
|
||||
rules:
|
||||
- apiGroups:
|
||||
- actions.github.com
|
||||
resources:
|
||||
- autoscalinglisteners
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- actions.github.com
|
||||
resources:
|
||||
- autoscalinglisteners/status
|
||||
verbs:
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- actions.github.com
|
||||
resources:
|
||||
- autoscalinglisteners/finalizers
|
||||
verbs:
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- pods
|
||||
verbs:
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- serviceaccounts
|
||||
verbs:
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- rbac.authorization.k8s.io
|
||||
resources:
|
||||
- rolebindings
|
||||
verbs:
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- rbac.authorization.k8s.io
|
||||
resources:
|
||||
- roles
|
||||
verbs:
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- actions.github.com
|
||||
resources:
|
||||
- autoscalingrunnersets
|
||||
verbs:
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- actions.github.com
|
||||
resources:
|
||||
- ephemeralrunnersets
|
||||
verbs:
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- actions.github.com
|
||||
resources:
|
||||
- ephemeralrunners
|
||||
verbs:
|
||||
- list
|
||||
- watch
|
||||
{{- end }}
|
||||
@@ -0,0 +1,15 @@
|
||||
{{- if .Values.controller.manager.config.watchSingleNamespace }}
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: {{ include "gha-controller.manager-single-namespace-role-binding" . }}
|
||||
namespace: {{ include "gha-controller.namespace" . }}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: {{ include "gha-controller.manager-single-namespace-role-name" . }}
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ include "gha-controller.service-account-name" . }}
|
||||
namespace: {{ include "gha-controller.namespace" . }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,125 @@
|
||||
{{- if .Values.controller.manager.config.watchSingleNamespace }}
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: {{ include "gha-controller.manager-single-namespace-watch-role-name" . }}
|
||||
namespace: {{ .Values.controller.manager.config.watchSingleNamespace }}
|
||||
rules:
|
||||
- apiGroups:
|
||||
- actions.github.com
|
||||
resources:
|
||||
- autoscalingrunnersets
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- actions.github.com
|
||||
resources:
|
||||
- autoscalingrunnersets/finalizers
|
||||
verbs:
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- actions.github.com
|
||||
resources:
|
||||
- autoscalingrunnersets/status
|
||||
verbs:
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- actions.github.com
|
||||
resources:
|
||||
- ephemeralrunnersets
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- actions.github.com
|
||||
resources:
|
||||
- ephemeralrunnersets/status
|
||||
verbs:
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- actions.github.com
|
||||
resources:
|
||||
- ephemeralrunnersets/finalizers
|
||||
verbs:
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- actions.github.com
|
||||
resources:
|
||||
- ephemeralrunners
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- watch
|
||||
- apiGroups:
|
||||
- actions.github.com
|
||||
resources:
|
||||
- ephemeralrunners/finalizers
|
||||
verbs:
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- actions.github.com
|
||||
resources:
|
||||
- ephemeralrunners/status
|
||||
verbs:
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- actions.github.com
|
||||
resources:
|
||||
- autoscalinglisteners
|
||||
verbs:
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- pods
|
||||
verbs:
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- serviceaccounts
|
||||
verbs:
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- rbac.authorization.k8s.io
|
||||
resources:
|
||||
- rolebindings
|
||||
verbs:
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- rbac.authorization.k8s.io
|
||||
resources:
|
||||
- roles
|
||||
verbs:
|
||||
- list
|
||||
- watch
|
||||
- patch
|
||||
{{- end }}
|
||||
@@ -0,0 +1,15 @@
|
||||
{{- if .Values.controller.manager.config.watchSingleNamespace }}
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: {{ include "gha-controller.manager-single-namespace-watch-role-binding" . }}
|
||||
namespace: {{ .Values.controller.manager.config.watchSingleNamespace }}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: {{ include "gha-controller.manager-single-namespace-watch-role-name" . }}
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ include "gha-controller.service-account-name" . }}
|
||||
namespace: {{ include "gha-controller.namespace" . }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,13 @@
|
||||
{{- if .Values.controller.serviceAccount.create }}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ include "gha-controller.service-account-name" . }}
|
||||
namespace: {{ include "gha-controller.namespace" . }}
|
||||
labels:
|
||||
{{- include "gha-controller.labels" . | nindent 4 }}
|
||||
{{- with .Values.controller.serviceAccount.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,75 @@
|
||||
suite: "Controller Deployment args"
|
||||
templates:
|
||||
- deployment.yaml
|
||||
tests:
|
||||
- it: should include metrics-disabled flags by default
|
||||
release:
|
||||
name: "test-arc"
|
||||
namespace: "test-ns"
|
||||
asserts:
|
||||
- contains:
|
||||
path: spec.template.spec.containers[0].args
|
||||
content: "--metrics-addr=0"
|
||||
- contains:
|
||||
path: spec.template.spec.containers[0].args
|
||||
content: "--listener-metrics-addr=0"
|
||||
- contains:
|
||||
path: spec.template.spec.containers[0].args
|
||||
content: "--listener-metrics-endpoint="
|
||||
|
||||
- it: should include watch-single-namespace flag when configured
|
||||
set:
|
||||
controller:
|
||||
manager:
|
||||
config:
|
||||
watchSingleNamespace: "demo"
|
||||
release:
|
||||
name: "test-arc"
|
||||
namespace: "test-ns"
|
||||
asserts:
|
||||
- contains:
|
||||
path: spec.template.spec.containers[0].args
|
||||
content: "--watch-single-namespace=demo"
|
||||
|
||||
- it: should include exclude-label-propagation-prefix flags when configured
|
||||
set:
|
||||
controller:
|
||||
manager:
|
||||
config:
|
||||
excludeLabelPropagationPrefixes:
|
||||
- "prefix.com/"
|
||||
- "complete.io/label"
|
||||
release:
|
||||
name: "test-arc"
|
||||
namespace: "test-ns"
|
||||
asserts:
|
||||
- contains:
|
||||
path: spec.template.spec.containers[0].args
|
||||
content: "--exclude-label-propagation-prefix=prefix.com/"
|
||||
- contains:
|
||||
path: spec.template.spec.containers[0].args
|
||||
content: "--exclude-label-propagation-prefix=complete.io/label"
|
||||
|
||||
- it: should render metrics port when metrics are enabled
|
||||
set:
|
||||
controller:
|
||||
metrics:
|
||||
controllerManagerAddr: ":8080"
|
||||
listenerAddr: ":8081"
|
||||
listenerEndpoint: "/metrics"
|
||||
release:
|
||||
name: "test-arc"
|
||||
namespace: "test-ns"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].ports[0].containerPort
|
||||
value: 8080
|
||||
- contains:
|
||||
path: spec.template.spec.containers[0].args
|
||||
content: "--metrics-addr=:8080"
|
||||
- contains:
|
||||
path: spec.template.spec.containers[0].args
|
||||
content: "--listener-metrics-addr=:8081"
|
||||
- contains:
|
||||
path: spec.template.spec.containers[0].args
|
||||
content: "--listener-metrics-endpoint=/metrics"
|
||||
@@ -0,0 +1,46 @@
|
||||
suite: "Controller Deployment env"
|
||||
templates:
|
||||
- deployment.yaml
|
||||
tests:
|
||||
- it: should not render envFrom in manager container
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- notExists:
|
||||
path: spec.template.spec.containers[0].envFrom
|
||||
- notExists:
|
||||
path: spec.template.spec.containers[0].ports
|
||||
|
||||
- it: should include extra env entries from values
|
||||
set:
|
||||
controller:
|
||||
manager:
|
||||
container:
|
||||
env:
|
||||
- name: "FOO"
|
||||
value: "bar"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- contains:
|
||||
path: spec.template.spec.containers[0].env
|
||||
content:
|
||||
name: "FOO"
|
||||
value: "bar"
|
||||
|
||||
- it: should enable leader election when replicaCount > 1
|
||||
set:
|
||||
controller:
|
||||
replicaCount: 2
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- contains:
|
||||
path: spec.template.spec.containers[0].args
|
||||
content: "--enable-leader-election"
|
||||
- contains:
|
||||
path: spec.template.spec.containers[0].args
|
||||
content: "--leader-election-id=test-name-gha-rs-controller"
|
||||
@@ -0,0 +1,54 @@
|
||||
suite: "Controller Deployment extra containers"
|
||||
templates:
|
||||
- deployment.yaml
|
||||
tests:
|
||||
- it: should render manager container first and then extra containers
|
||||
set:
|
||||
controller:
|
||||
pod:
|
||||
containers:
|
||||
- name: "sidecar"
|
||||
image: "busybox:1.36"
|
||||
command:
|
||||
- "sh"
|
||||
- "-c"
|
||||
args:
|
||||
- "echo hello && sleep 3600"
|
||||
- name: "another"
|
||||
image: "alpine:3.19"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].name
|
||||
value: "manager"
|
||||
- equal:
|
||||
path: spec.template.spec.containers[1].name
|
||||
value: "sidecar"
|
||||
- equal:
|
||||
path: spec.template.spec.containers[1].image
|
||||
value: "busybox:1.36"
|
||||
- equal:
|
||||
path: spec.template.spec.containers[1].command[0]
|
||||
value: "sh"
|
||||
- equal:
|
||||
path: spec.template.spec.containers[1].args[0]
|
||||
value: "echo hello && sleep 3600"
|
||||
- equal:
|
||||
path: spec.template.spec.containers[2].name
|
||||
value: "another"
|
||||
- equal:
|
||||
path: spec.template.spec.containers[2].image
|
||||
value: "alpine:3.19"
|
||||
|
||||
- it: should not fail when extra containers are unset
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].name
|
||||
value: "manager"
|
||||
- notExists:
|
||||
path: spec.template.spec.containers[1]
|
||||
@@ -0,0 +1,33 @@
|
||||
suite: "Controller Deployment imagePullSecrets"
|
||||
templates:
|
||||
- deployment.yaml
|
||||
tests:
|
||||
- it: should not render imagePullSecrets by default
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- notExists:
|
||||
path: spec.template.spec.imagePullSecrets
|
||||
|
||||
- it: should render imagePullSecrets and forward them as args when configured
|
||||
set:
|
||||
imagePullSecrets:
|
||||
- name: regcred
|
||||
- name: another
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.template.spec.imagePullSecrets[0].name
|
||||
value: regcred
|
||||
- equal:
|
||||
path: spec.template.spec.imagePullSecrets[1].name
|
||||
value: another
|
||||
- contains:
|
||||
path: spec.template.spec.containers[0].args
|
||||
content: "--auto-scaler-image-pull-secrets=regcred"
|
||||
- contains:
|
||||
path: spec.template.spec.containers[0].args
|
||||
content: "--auto-scaler-image-pull-secrets=another"
|
||||
@@ -0,0 +1,52 @@
|
||||
suite: "Controller Deployment pod extra fields"
|
||||
templates:
|
||||
- deployment.yaml
|
||||
tests:
|
||||
- it: should render extra pod spec fields from controller.pod
|
||||
set:
|
||||
controller:
|
||||
pod:
|
||||
nodeSelector:
|
||||
kubernetes.io/os: linux
|
||||
tolerations:
|
||||
- key: "dedicated"
|
||||
operator: "Equal"
|
||||
value: "arc"
|
||||
effect: "NoSchedule"
|
||||
hostNetwork: true
|
||||
dnsPolicy: "ClusterFirstWithHostNet"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.template.spec.nodeSelector["kubernetes.io/os"]
|
||||
value: "linux"
|
||||
- equal:
|
||||
path: spec.template.spec.tolerations[0].key
|
||||
value: "dedicated"
|
||||
- equal:
|
||||
path: spec.template.spec.tolerations[0].value
|
||||
value: "arc"
|
||||
- equal:
|
||||
path: spec.template.spec.hostNetwork
|
||||
value: true
|
||||
- equal:
|
||||
path: spec.template.spec.dnsPolicy
|
||||
value: "ClusterFirstWithHostNet"
|
||||
|
||||
- it: should not allow overriding serviceAccountName via controller.pod
|
||||
set:
|
||||
controller:
|
||||
pod:
|
||||
serviceAccountName: "hacker-sa"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.template.spec.serviceAccountName
|
||||
value: "test-name-gha-rs-controller"
|
||||
- notEqual:
|
||||
path: spec.template.spec.serviceAccountName
|
||||
value: "hacker-sa"
|
||||
@@ -0,0 +1,27 @@
|
||||
suite: "Controller Deployment smoke"
|
||||
templates:
|
||||
- deployment.yaml
|
||||
tests:
|
||||
- it: should render deployment basics
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: apiVersion
|
||||
value: "apps/v1"
|
||||
- equal:
|
||||
path: kind
|
||||
value: "Deployment"
|
||||
- equal:
|
||||
path: metadata.name
|
||||
value: "test-name-gha-rs-controller"
|
||||
- equal:
|
||||
path: metadata.namespace
|
||||
value: "test-namespace"
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].name
|
||||
value: "manager"
|
||||
- contains:
|
||||
path: spec.template.spec.containers[0].command
|
||||
content: "/manager"
|
||||
@@ -0,0 +1,37 @@
|
||||
suite: "Controller Manager ClusterRoleBinding"
|
||||
templates:
|
||||
- manager_cluster_role_binding.yaml
|
||||
tests:
|
||||
- it: should render when watchSingleNamespace is empty
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: apiVersion
|
||||
value: "rbac.authorization.k8s.io/v1"
|
||||
- equal:
|
||||
path: kind
|
||||
value: "ClusterRoleBinding"
|
||||
- equal:
|
||||
path: subjects[0].kind
|
||||
value: "ServiceAccount"
|
||||
- equal:
|
||||
path: subjects[0].name
|
||||
value: "test-name-gha-rs-controller"
|
||||
- equal:
|
||||
path: subjects[0].namespace
|
||||
value: "test-namespace"
|
||||
|
||||
- it: should not render when watchSingleNamespace is set
|
||||
set:
|
||||
controller:
|
||||
manager:
|
||||
config:
|
||||
watchSingleNamespace: "my-ns"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- hasDocuments:
|
||||
count: 0
|
||||
@@ -0,0 +1,24 @@
|
||||
suite: "Controller namespaceOverride"
|
||||
templates:
|
||||
- deployment.yaml
|
||||
- serviceaccount.yaml
|
||||
tests:
|
||||
- it: should apply namespaceOverride to deployment and serviceaccount
|
||||
set:
|
||||
namespaceOverride: "override-ns"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "release-ns"
|
||||
asserts:
|
||||
- equal:
|
||||
path: metadata.namespace
|
||||
value: "override-ns"
|
||||
template: deployment.yaml
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/controller-service-account-namespace"]
|
||||
value: "override-ns"
|
||||
template: deployment.yaml
|
||||
- equal:
|
||||
path: metadata.namespace
|
||||
value: "override-ns"
|
||||
template: serviceaccount.yaml
|
||||
@@ -0,0 +1,38 @@
|
||||
suite: "Controller RBAC cluster"
|
||||
templates:
|
||||
- manager_cluster_role.yaml
|
||||
tests:
|
||||
- it: should render manager ClusterRole when watchSingleNamespace is empty
|
||||
release:
|
||||
name: "test-arc"
|
||||
namespace: "test-ns"
|
||||
asserts:
|
||||
- equal:
|
||||
path: kind
|
||||
value: "ClusterRole"
|
||||
- equal:
|
||||
path: metadata.name
|
||||
value: "test-arc-gha-rs-controller"
|
||||
- contains:
|
||||
path: rules
|
||||
content:
|
||||
apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- pods
|
||||
verbs:
|
||||
- list
|
||||
- watch
|
||||
|
||||
- it: should not render manager ClusterRole when watchSingleNamespace is set
|
||||
set:
|
||||
controller:
|
||||
manager:
|
||||
config:
|
||||
watchSingleNamespace: "demo"
|
||||
release:
|
||||
name: "test-arc"
|
||||
namespace: "test-ns"
|
||||
asserts:
|
||||
- hasDocuments:
|
||||
count: 0
|
||||
@@ -0,0 +1,52 @@
|
||||
suite: "Controller RBAC leader election"
|
||||
templates:
|
||||
- leader_election_role.yaml
|
||||
- leader_election_role_binding.yaml
|
||||
tests:
|
||||
- it: should not render leader election resources when replicaCount is 1
|
||||
set:
|
||||
controller:
|
||||
replicaCount: 1
|
||||
release:
|
||||
name: "test-arc"
|
||||
namespace: "test-ns"
|
||||
asserts:
|
||||
- hasDocuments:
|
||||
count: 0
|
||||
template: leader_election_role.yaml
|
||||
- hasDocuments:
|
||||
count: 0
|
||||
template: leader_election_role_binding.yaml
|
||||
|
||||
- it: should render leader election resources when replicaCount > 1
|
||||
set:
|
||||
controller:
|
||||
replicaCount: 2
|
||||
release:
|
||||
name: "test-arc"
|
||||
namespace: "test-ns"
|
||||
asserts:
|
||||
- equal:
|
||||
path: kind
|
||||
value: "Role"
|
||||
template: leader_election_role.yaml
|
||||
- equal:
|
||||
path: metadata.name
|
||||
value: "test-arc-gha-rs-controller-leader-election"
|
||||
template: leader_election_role.yaml
|
||||
- equal:
|
||||
path: metadata.namespace
|
||||
value: "test-ns"
|
||||
template: leader_election_role.yaml
|
||||
- equal:
|
||||
path: kind
|
||||
value: "RoleBinding"
|
||||
template: leader_election_role_binding.yaml
|
||||
- equal:
|
||||
path: roleRef.name
|
||||
value: "test-arc-gha-rs-controller-leader-election"
|
||||
template: leader_election_role_binding.yaml
|
||||
- equal:
|
||||
path: subjects[0].name
|
||||
value: "test-arc-gha-rs-controller"
|
||||
template: leader_election_role_binding.yaml
|
||||
@@ -0,0 +1,68 @@
|
||||
suite: "Controller RBAC listener"
|
||||
templates:
|
||||
- manager_listener_role.yaml
|
||||
- manager_listener_role_binding.yaml
|
||||
tests:
|
||||
- it: should render listener role with expected rules
|
||||
release:
|
||||
name: "test-arc"
|
||||
namespace: "test-ns"
|
||||
asserts:
|
||||
- equal:
|
||||
path: kind
|
||||
value: "Role"
|
||||
template: manager_listener_role.yaml
|
||||
- equal:
|
||||
path: metadata.name
|
||||
value: "test-arc-gha-rs-controller-listener"
|
||||
template: manager_listener_role.yaml
|
||||
- equal:
|
||||
path: metadata.namespace
|
||||
value: "test-ns"
|
||||
template: manager_listener_role.yaml
|
||||
- equal:
|
||||
path: rules[0].resources[0]
|
||||
value: "pods"
|
||||
template: manager_listener_role.yaml
|
||||
- equal:
|
||||
path: rules[1].resources[0]
|
||||
value: "pods/status"
|
||||
template: manager_listener_role.yaml
|
||||
- equal:
|
||||
path: rules[2].resources[0]
|
||||
value: "secrets"
|
||||
template: manager_listener_role.yaml
|
||||
- equal:
|
||||
path: rules[3].resources[0]
|
||||
value: "serviceaccounts"
|
||||
template: manager_listener_role.yaml
|
||||
|
||||
- it: should bind listener role to controller serviceaccount
|
||||
release:
|
||||
name: "test-arc"
|
||||
namespace: "test-ns"
|
||||
asserts:
|
||||
- equal:
|
||||
path: kind
|
||||
value: "RoleBinding"
|
||||
template: manager_listener_role_binding.yaml
|
||||
- equal:
|
||||
path: metadata.name
|
||||
value: "test-arc-gha-rs-controller-listener"
|
||||
template: manager_listener_role_binding.yaml
|
||||
- equal:
|
||||
path: metadata.namespace
|
||||
value: "test-ns"
|
||||
template: manager_listener_role_binding.yaml
|
||||
- equal:
|
||||
path: roleRef.name
|
||||
value: "test-arc-gha-rs-controller-listener"
|
||||
template: manager_listener_role_binding.yaml
|
||||
- equal:
|
||||
path: subjects[0].name
|
||||
value: "test-arc-gha-rs-controller"
|
||||
template: manager_listener_role_binding.yaml
|
||||
- equal:
|
||||
path: subjects[0].namespace
|
||||
value: "test-ns"
|
||||
template: manager_listener_role_binding.yaml
|
||||
@@ -0,0 +1,56 @@
|
||||
suite: "Controller RBAC single-namespace mode"
|
||||
templates:
|
||||
- manager_single_namespace_controller_role.yaml
|
||||
- manager_single_namespace_controller_role_binding.yaml
|
||||
- manager_single_namespace_watch_role.yaml
|
||||
- manager_single_namespace_watch_role_binding.yaml
|
||||
tests:
|
||||
- it: should not render single-namespace roles when watchSingleNamespace is empty
|
||||
set:
|
||||
controller:
|
||||
manager:
|
||||
config:
|
||||
watchSingleNamespace: ""
|
||||
release:
|
||||
name: "test-arc"
|
||||
namespace: "test-ns"
|
||||
asserts:
|
||||
- hasDocuments:
|
||||
count: 0
|
||||
template: manager_single_namespace_controller_role.yaml
|
||||
- hasDocuments:
|
||||
count: 0
|
||||
template: manager_single_namespace_controller_role_binding.yaml
|
||||
- hasDocuments:
|
||||
count: 0
|
||||
template: manager_single_namespace_watch_role.yaml
|
||||
- hasDocuments:
|
||||
count: 0
|
||||
template: manager_single_namespace_watch_role_binding.yaml
|
||||
|
||||
- it: should render roles in controller namespace and watch namespace
|
||||
set:
|
||||
controller:
|
||||
manager:
|
||||
config:
|
||||
watchSingleNamespace: "demo"
|
||||
release:
|
||||
name: "test-arc"
|
||||
namespace: "ctrl-ns"
|
||||
asserts:
|
||||
- equal:
|
||||
path: metadata.namespace
|
||||
value: "ctrl-ns"
|
||||
template: manager_single_namespace_controller_role.yaml
|
||||
- equal:
|
||||
path: metadata.namespace
|
||||
value: "ctrl-ns"
|
||||
template: manager_single_namespace_controller_role_binding.yaml
|
||||
- equal:
|
||||
path: metadata.namespace
|
||||
value: "demo"
|
||||
template: manager_single_namespace_watch_role.yaml
|
||||
- equal:
|
||||
path: metadata.namespace
|
||||
value: "demo"
|
||||
template: manager_single_namespace_watch_role_binding.yaml
|
||||
@@ -0,0 +1,72 @@
|
||||
suite: "Controller ServiceAccount"
|
||||
templates:
|
||||
- serviceaccount.yaml
|
||||
tests:
|
||||
- it: should render serviceaccount by default
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: apiVersion
|
||||
value: "v1"
|
||||
- equal:
|
||||
path: kind
|
||||
value: "ServiceAccount"
|
||||
- equal:
|
||||
path: metadata.name
|
||||
value: "test-name-gha-rs-controller"
|
||||
- equal:
|
||||
path: metadata.namespace
|
||||
value: "test-namespace"
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/controller-service-account-name"]
|
||||
value: "test-name-gha-rs-controller"
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/controller-service-account-namespace"]
|
||||
value: "test-namespace"
|
||||
|
||||
- it: should allow overriding serviceAccount.name when create is true
|
||||
set:
|
||||
controller:
|
||||
serviceAccount:
|
||||
create: true
|
||||
name: "overwritten-name"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: metadata.name
|
||||
value: "overwritten-name"
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/controller-service-account-name"]
|
||||
value: "overwritten-name"
|
||||
|
||||
- it: should render serviceAccount annotations
|
||||
set:
|
||||
controller:
|
||||
serviceAccount:
|
||||
create: true
|
||||
annotations:
|
||||
foo: bar
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: metadata.annotations.foo
|
||||
value: "bar"
|
||||
|
||||
- it: should not render when serviceAccount.create is false
|
||||
set:
|
||||
controller:
|
||||
serviceAccount:
|
||||
create: false
|
||||
name: "existing-sa"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- hasDocuments:
|
||||
count: 0
|
||||
@@ -0,0 +1,32 @@
|
||||
suite: "Controller ServiceAccount validation"
|
||||
templates:
|
||||
- serviceaccount.yaml
|
||||
- deployment.yaml
|
||||
tests:
|
||||
- it: should fail if serviceAccount.name is 'default'
|
||||
set:
|
||||
controller:
|
||||
serviceAccount:
|
||||
create: true
|
||||
name: "default"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: "serviceAccount.name cannot be set to 'default'"
|
||||
template: serviceaccount.yaml
|
||||
|
||||
- it: should fail when serviceAccount.create is false and name is not set
|
||||
set:
|
||||
controller:
|
||||
serviceAccount:
|
||||
create: false
|
||||
name: ""
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: "serviceAccount.name must be set if serviceAccount.create is false"
|
||||
template: deployment.yaml
|
||||
111
charts/gha-runner-scale-set-controller-experimental/values.yaml
Normal file
111
charts/gha-runner-scale-set-controller-experimental/values.yaml
Normal file
@@ -0,0 +1,111 @@
|
||||
# Global chart-level labels applied to all resources (Deployment, RBAC, etc.).
|
||||
labels: {}
|
||||
|
||||
# Overrides the default `.Release.Namespace` for all resources in this chart.
|
||||
namespaceOverride: ""
|
||||
|
||||
# Optional imagePullSecrets added to the controller Pod spec.
|
||||
# When set, the manager container also receives `--auto-scaler-image-pull-secrets=<name>` args.
|
||||
imagePullSecrets: []
|
||||
|
||||
controller:
|
||||
# Number of controller replicas.
|
||||
replicaCount: 1
|
||||
|
||||
# Deployment-level metadata
|
||||
metadata:
|
||||
labels: {}
|
||||
annotations: {}
|
||||
|
||||
manager:
|
||||
config:
|
||||
# Log level: "debug", "info", "warn", "error".
|
||||
logLevel: "debug"
|
||||
# Log format: "text", "json".
|
||||
logFormat: "text"
|
||||
|
||||
# Restricts the controller to only watch resources in the desired namespace.
|
||||
# Defaults to watch all namespaces when unset.
|
||||
watchSingleNamespace: ""
|
||||
|
||||
# The maximum number of concurrent reconciles which can be run by the EphemeralRunner controller.
|
||||
runnerMaxConcurrentReconciles: 2
|
||||
|
||||
# How the controller handles upgrades with running jobs: "immediate" or "eventual".
|
||||
updateStrategy: "immediate"
|
||||
|
||||
# List of label prefixes that should NOT be propagated to internal resources.
|
||||
excludeLabelPropagationPrefixes: []
|
||||
# Example:
|
||||
# excludeLabelPropagationPrefixes:
|
||||
# - "argocd.argoproj.io/instance"
|
||||
|
||||
# K8s client rate limiter parameters.
|
||||
k8sClientRateLimiterQPS: null
|
||||
k8sClientRateLimiterBurst: null
|
||||
|
||||
container:
|
||||
image: "ghcr.io/actions/gha-runner-scale-set-controller:latest"
|
||||
pullPolicy: IfNotPresent
|
||||
# Extra arguments appended to the default set generated by the chart.
|
||||
extraArgs: []
|
||||
# Container-level environment variables.
|
||||
env: []
|
||||
# Container-level security context.
|
||||
securityContext: {}
|
||||
# Container-level resource requests/limits.
|
||||
resources: {}
|
||||
# Additional volume mounts on the manager container.
|
||||
extraVolumeMounts: []
|
||||
# Extra container ports (metrics port is derived from controller.metrics).
|
||||
extraPorts: []
|
||||
|
||||
serviceAccount:
|
||||
# Specifies whether a service account should be created.
|
||||
create: true
|
||||
# Annotations to add to the service account.
|
||||
annotations: {}
|
||||
# The name of the service account to use.
|
||||
# If not set and create is true, a name is generated using the fullname template.
|
||||
name: ""
|
||||
|
||||
# Pod-level configuration.
|
||||
pod:
|
||||
metadata:
|
||||
labels: {}
|
||||
annotations: {}
|
||||
spec: {}
|
||||
# Pod-level security context.
|
||||
securityContext: {}
|
||||
# Pod priority class name.
|
||||
priorityClassName: ""
|
||||
# Node selection constraints.
|
||||
nodeSelector: {}
|
||||
# Pod tolerations.
|
||||
tolerations: []
|
||||
# Pod affinity.
|
||||
affinity: {}
|
||||
# Pod topology spread constraints.
|
||||
topologySpreadConstraints: []
|
||||
# Pod termination grace period (overrides default 10s).
|
||||
terminationGracePeriodSeconds: null
|
||||
|
||||
# Extra volumes appended to the default ones.
|
||||
extraVolumes: []
|
||||
# Extra volume mounts appended to the default ones.
|
||||
extraVolumeMounts: []
|
||||
|
||||
# Raw extra podSpec fields to be merged into spec.template.spec.
|
||||
# Example:
|
||||
# extraSpec:
|
||||
# hostAliases:
|
||||
# - ip: "127.0.0.1"
|
||||
# hostnames: ["example.local"]
|
||||
extraSpec: {}
|
||||
|
||||
# Metrics configuration. If omitted, metrics are disabled.
|
||||
# metrics:
|
||||
# controllerManagerAddr: ":8080"
|
||||
# listenerAddr: ":8080"
|
||||
# listenerEndpoint: "/metrics"
|
||||
|
||||
24
charts/gha-runner-scale-set-experimental/.helmignore
Normal file
24
charts/gha-runner-scale-set-experimental/.helmignore
Normal file
@@ -0,0 +1,24 @@
|
||||
# Patterns to ignore when building packages.
|
||||
# This supports shell glob matching, relative path matching, and
|
||||
# negation (prefixed with !). Only one pattern per line.
|
||||
.DS_Store
|
||||
# Common VCS dirs
|
||||
.git/
|
||||
.gitignore
|
||||
.bzr/
|
||||
.bzrignore
|
||||
.hg/
|
||||
.hgignore
|
||||
.svn/
|
||||
# Common backup files
|
||||
*.swp
|
||||
*.bak
|
||||
*.tmp
|
||||
*.orig
|
||||
*~
|
||||
# Various IDEs
|
||||
.project
|
||||
.idea/
|
||||
*.tmproj
|
||||
.vscode/
|
||||
tests/
|
||||
33
charts/gha-runner-scale-set-experimental/Chart.yaml
Normal file
33
charts/gha-runner-scale-set-experimental/Chart.yaml
Normal file
@@ -0,0 +1,33 @@
|
||||
apiVersion: v2
|
||||
name: gha-runner-scale-set-experimental
|
||||
description: A Helm chart for deploying an AutoScalingRunnerSet
|
||||
|
||||
# A chart can be either an 'application' or a 'library' chart.
|
||||
#
|
||||
# Application charts are a collection of templates that can be packaged into versioned archives
|
||||
# to be deployed.
|
||||
#
|
||||
# Library charts provide useful utilities or functions for the chart developer. They're included as
|
||||
# a dependency of application charts to inject those utilities and functions into the rendering
|
||||
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
|
||||
type: application
|
||||
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: "0.14.0"
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||
# It is recommended to use it with quotes.
|
||||
appVersion: "0.14.0"
|
||||
|
||||
home: https://github.com/actions/actions-runner-controller
|
||||
|
||||
sources:
|
||||
- "https://github.com/actions/actions-runner-controller"
|
||||
|
||||
maintainers:
|
||||
- name: actions
|
||||
url: https://github.com/actions
|
||||
@@ -0,0 +1,61 @@
|
||||
{{/*
|
||||
Create the labels for the autoscaling runner set.
|
||||
*/}}
|
||||
{{- define "autoscaling-runner-set.labels" -}}
|
||||
{{- $resourceLabels := dict "app.kubernetes.io/component" "autoscaling-runner-set" -}}
|
||||
{{- $commonLabels := include "gha-common-labels" . | fromYaml -}}
|
||||
{{- $userLabels := include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.autoscalingRunnerSet.metadata.labels | default (dict)) | fromYaml -}}
|
||||
{{- $global := include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.all.metadata.labels | default (dict)) | fromYaml -}}
|
||||
{{- toYaml (mergeOverwrite $global $userLabels $resourceLabels $commonLabels) }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the annotations for the autoscaling runner set.
|
||||
|
||||
Order of precedence:
|
||||
1) resource.all.metadata.annotations
|
||||
2) resource.autoscalingRunnerSet.metadata.annotations
|
||||
Reserved annotations are excluded from both levels.
|
||||
*/}}
|
||||
{{- define "autoscaling-runner-set.annotations" -}}
|
||||
{{- $global := (include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.all.metadata.annotations | default (dict))) | fromYaml -}}
|
||||
{{- $resource := (include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.autoscalingRunnerSet.metadata.annotations | default (dict))) | fromYaml -}}
|
||||
{{- $annotations := mergeOverwrite $global $resource -}}
|
||||
{{- if not (empty $annotations) -}}
|
||||
{{- toYaml $annotations }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Container spec that is expanded for the runner container
|
||||
*/}}
|
||||
{{- define "autoscaling-runner-set.template-runner-container" -}}
|
||||
{{- if not .Values.runner.container }}
|
||||
{{ fail "You must provide a runner container specification in values.runner.container" }}
|
||||
{{- end }}
|
||||
{{- $tlsConfig := (default (dict) .Values.githubServerTLS) -}}
|
||||
name: runner
|
||||
image: {{ .Values.runner.container.image | default "ghcr.io/actions/runner:latest" }}
|
||||
command: {{ toJson (default (list "/home/runner/run.sh") .Values.runner.container.command) }}
|
||||
{{- $extra := omit .Values.runner.container "name" "image" "command" -}}
|
||||
{{- if not (empty $extra) -}}
|
||||
{{toYaml $extra }}
|
||||
{{- end -}}
|
||||
{{- end }}
|
||||
|
||||
{{- define "autoscaling-runner-set.template-service-account" -}}
|
||||
{{- $runner := (.Values.runner | default dict) -}}
|
||||
{{- $runnerMode := (index $runner "mode" | default "") -}}
|
||||
{{- $kubeMode := (index $runner "kubernetesMode" | default dict) -}}
|
||||
{{- $kubeServiceAccountName := (index $kubeMode "serviceAccountName" | default "") -}}
|
||||
{{- $kubeDefaults := (index $kubeMode "default" | default true) -}}
|
||||
{{- if ne $runnerMode "kubernetes" }}
|
||||
{{- include "no-permission-serviceaccount.name" . }}
|
||||
{{- else if not (empty $kubeServiceAccountName) }}
|
||||
{{- $kubeServiceAccountName }}
|
||||
{{- else if $kubeDefaults }}
|
||||
{{- include "kube-mode-serviceaccount.name" . }}
|
||||
{{- else }}
|
||||
{{- fail "runner.kubernetesMode.serviceAccountName must be set when runner.mode is 'kubernetes' and runner.kubernetesMode.default is false" -}}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
117
charts/gha-runner-scale-set-experimental/templates/_defaults.tpl
Normal file
117
charts/gha-runner-scale-set-experimental/templates/_defaults.tpl
Normal file
@@ -0,0 +1,117 @@
|
||||
{{- define "autoscaling-runner-set.name" -}}
|
||||
{{- $name := .Values.runnerScaleSetName | default .Release.Name | replace "_" "-" | trimSuffix "-" }}
|
||||
{{- if or (empty $name) (gt (len $name) 45) }}
|
||||
{{ fail "Autoscaling runner set name must have up to 45 characters" }}
|
||||
{{- end }}
|
||||
{{- $name }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "autoscaling-runner-set.namespace" -}}
|
||||
{{- .Values.namespaceOverride | default .Release.Namespace -}}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
The name of the manager Role.
|
||||
*/}}
|
||||
{{- define "manager-role.name" -}}
|
||||
{{- printf "%s-manager-role" (include "autoscaling-runner-set.name" .) -}}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create chart name and version as used by the chart label.
|
||||
*/}}
|
||||
{{- define "gha-runner-scale-set.chart" -}}
|
||||
{{- printf "gha-rs-%s" .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
The name of the GitHub secret used for authentication.
|
||||
*/}}
|
||||
{{- define "github-secret.name" -}}
|
||||
{{- if not (empty .Values.auth.secretName) -}}
|
||||
{{- .Values.auth.secretName -}}
|
||||
{{- else -}}
|
||||
{{- include "autoscaling-runner-set.name" . }}-github-secret
|
||||
{{- end -}}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
The name of the no-permission ServiceAccount.
|
||||
|
||||
This ServiceAccount is intended for non-kubernetes runner modes when the user
|
||||
has not specified an explicit ServiceAccount.
|
||||
*/}}
|
||||
{{- define "no-permission-serviceaccount.name" -}}
|
||||
{{- printf "%s-no-permission" (include "autoscaling-runner-set.name" .) -}}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
The name of the kubernetes-mode Role.
|
||||
|
||||
Kept intentionally aligned with the legacy chart behavior.
|
||||
*/}}
|
||||
{{- define "kube-mode-role.name" -}}
|
||||
{{- printf "%s-kube-mode" (include "autoscaling-runner-set.name" .) -}}
|
||||
{{- end }}
|
||||
|
||||
|
||||
{{/*
|
||||
The name of the kubernetes-mode RoleBinding.
|
||||
|
||||
Kept intentionally aligned with the kubernetes-mode Role name.
|
||||
*/}}
|
||||
{{- define "kube-mode-role-binding.name" -}}
|
||||
{{- include "kube-mode-role.name" . -}}
|
||||
{{- end }}
|
||||
|
||||
|
||||
{{/*
|
||||
The name of the kubernetes-mode ServiceAccount.
|
||||
|
||||
Kept intentionally aligned with the legacy chart behavior.
|
||||
*/}}
|
||||
{{- define "kube-mode-serviceaccount.name" -}}
|
||||
{{- include "kube-mode-role.name" . -}}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the common labels used across all resources.
|
||||
*/}}
|
||||
{{- define "gha-common-labels" -}}
|
||||
helm.sh/chart: {{ include "gha-runner-scale-set.chart" . }}
|
||||
app.kubernetes.io/name: {{ include "autoscaling-runner-set.name" . }}
|
||||
app.kubernetes.io/instance: {{ include "autoscaling-runner-set.name" . }}
|
||||
app.kubernetes.io/version: {{ .Chart.AppVersion }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
app.kubernetes.io/part-of: "gha-rs"
|
||||
actions.github.com/scale-set-name: {{ include "autoscaling-runner-set.name" . }}
|
||||
actions.github.com/scale-set-namespace: {{ include "autoscaling-runner-set.namespace" . }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Get the runner container image.
|
||||
It defaults to ghcr.io/actions/actions-runner:latest if not specified.
|
||||
*/}}
|
||||
{{- define "runner.image" -}}
|
||||
{{- $runner := .Values.runner.container | default dict -}}
|
||||
{{- if not (kindIs "map" $runner) -}}
|
||||
{{- fail "runner.container must be a map/object" -}}
|
||||
{{- end -}}
|
||||
{{- $image := $runner.image | default "ghcr.io/actions/actions-runner:latest" -}}
|
||||
{{- if not (kindIs "string" $image) -}}
|
||||
{{- fail "runner.container.image must be a string" -}}
|
||||
{{- end -}}
|
||||
{{- $image }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "runner.command" -}}
|
||||
{{- $runner := .Values.runner.container | default dict -}}
|
||||
{{- if not (kindIs "map" $runner) -}}
|
||||
{{- fail "runner.container must be a map/object" -}}
|
||||
{{- end -}}
|
||||
{{- $command := $runner.command | default (list "/home/runner/run.sh") -}}
|
||||
{{- if not (kindIs "slice" $command) -}}
|
||||
{{- fail "runner.container.command must be a list/array" -}}
|
||||
{{- end -}}
|
||||
{{- toJson $command -}}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,71 @@
|
||||
{{/*
|
||||
Create the labels for the GitHub auth secret.
|
||||
*/}}
|
||||
{{- define "github-secret.labels" -}}
|
||||
{{- $resourceLabels := dict "app.kubernetes.io/component" "github-secret" -}}
|
||||
{{- $commonLabels := include "gha-common-labels" . | fromYaml -}}
|
||||
{{- $global := include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.all.metadata.labels | default (dict)) | fromYaml -}}
|
||||
{{- toYaml (mergeOverwrite $global $resourceLabels $commonLabels) }}
|
||||
{{- end }}
|
||||
|
||||
|
||||
{{/*
|
||||
Create the annotations for the GitHub auth secret.
|
||||
|
||||
Only global annotations are applied.
|
||||
Reserved annotations are excluded.
|
||||
*/}}
|
||||
{{- define "github-secret.annotations" -}}
|
||||
{{- $annotations := (include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.all.metadata.annotations | default (dict))) | fromYaml -}}
|
||||
{{- if not (empty $annotations) -}}
|
||||
{{- toYaml $annotations }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the labels for the no-permission ServiceAccount.
|
||||
*/}}
|
||||
{{- define "no-permission-serviceaccount.labels" -}}
|
||||
{{- $resourceLabels := dict "app.kubernetes.io/component" "no-permission-serviceaccount" -}}
|
||||
{{- $commonLabels := include "gha-common-labels" . | fromYaml -}}
|
||||
{{- $userLabels := include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.noPermissionServiceAccount.metadata.labels | default (dict)) | fromYaml -}}
|
||||
{{- $global := include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.all.metadata.labels | default (dict)) | fromYaml -}}
|
||||
{{- toYaml (mergeOverwrite $global $userLabels $resourceLabels $commonLabels) }}
|
||||
{{- end }}
|
||||
|
||||
|
||||
{{/*
|
||||
Create the annotations for the no-permission ServiceAccount.
|
||||
|
||||
Order of precedence:
|
||||
1) resource.all.metadata.annotations
|
||||
2) resource.noPermissionServiceAccount.metadata.annotations
|
||||
Reserved annotations are excluded from both levels.
|
||||
*/}}
|
||||
{{- define "no-permission-serviceaccount.annotations" -}}
|
||||
{{- $global := (include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.all.metadata.annotations | default (dict))) | fromYaml -}}
|
||||
{{- $resource := (include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.noPermissionServiceAccount.metadata.annotations | default (dict))) | fromYaml -}}
|
||||
{{- $annotations := mergeOverwrite $global $resource -}}
|
||||
{{- if not (empty $annotations) -}}
|
||||
{{- toYaml $annotations }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
|
||||
{{/*
|
||||
Takes a map of user labels and removes the ones with "actions.github.com/" prefix
|
||||
*/}}
|
||||
{{- define "apply-non-reserved-gha-labels-and-annotations" -}}
|
||||
{{- $userLabels := . -}}
|
||||
{{- $processed := dict -}}
|
||||
{{- range $key, $value := $userLabels -}}
|
||||
{{- if not (hasPrefix "actions.github.com/" $key) -}}
|
||||
{{- $_ := set $processed $key $value -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- if not (empty $processed) -}}
|
||||
{{- $processed | toYaml }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
{{- define "listener-template.pod" -}}
|
||||
{{- $metadata := .Values.listenerPodTemplate.metadata | default dict -}}
|
||||
{{- $spec := .Values.listenerPodTemplate.spec | default dict -}}
|
||||
{{- if and (empty $metadata) (empty $spec) -}}
|
||||
{{- fail "listenerPodTemplate must have at least metadata or spec defined" -}}
|
||||
{{- end -}}
|
||||
{{- with $metadata -}}
|
||||
metadata:
|
||||
{{- toYaml . | nindent 2 }}
|
||||
{{- end }}
|
||||
{{- with $spec -}}
|
||||
spec:
|
||||
{{- $containers := (index . "containers" | default (list)) -}}
|
||||
{{- if empty $containers }}
|
||||
containers:
|
||||
- name: listener
|
||||
{{- else }}
|
||||
containers:
|
||||
{{- toYaml $containers | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- $rest := (omit . "containers") -}}
|
||||
{{- if gt (len $rest) 0 }}
|
||||
{{- toYaml $rest | nindent 2 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,69 @@
|
||||
{{/*
|
||||
Create the labels for the manager Role.
|
||||
*/}}
|
||||
{{- define "manager-role.labels" -}}
|
||||
{{- $resourceLabels := dict "app.kubernetes.io/component" "manager-role" -}}
|
||||
{{- $commonLabels := include "gha-common-labels" . | fromYaml -}}
|
||||
{{- $userLabels := include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.managerRole.metadata.labels | default (dict)) | fromYaml -}}
|
||||
{{- $global := include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.all.metadata.labels | default (dict)) | fromYaml -}}
|
||||
{{- toYaml (mergeOverwrite $global $userLabels $resourceLabels $commonLabels) }}
|
||||
{{- end }}
|
||||
|
||||
|
||||
{{/*
|
||||
Create the annotations for the manager Role.
|
||||
|
||||
Order of precedence:
|
||||
1) resource.all.metadata.annotations
|
||||
2) resource.managerRole.metadata.annotations
|
||||
Reserved annotations are excluded from both levels.
|
||||
*/}}
|
||||
{{- define "manager-role.annotations" -}}
|
||||
{{- $global := (include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.all.metadata.annotations | default (dict))) | fromYaml -}}
|
||||
{{- $resource := (include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.managerRole.metadata.annotations | default (dict))) | fromYaml -}}
|
||||
{{- $annotations := mergeOverwrite $global $resource -}}
|
||||
{{- if not (empty $annotations) -}}
|
||||
{{- toYaml $annotations }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
|
||||
{{/*
|
||||
The name of the manager RoleBinding.
|
||||
|
||||
Kept intentionally aligned with the manager Role name, mirroring the legacy
|
||||
chart behavior.
|
||||
*/}}
|
||||
{{- define "manager-role-binding.name" -}}
|
||||
{{- include "manager-role.name" . -}}
|
||||
{{- end }}
|
||||
|
||||
|
||||
{{/*
|
||||
Create the labels for the manager RoleBinding.
|
||||
*/}}
|
||||
{{- define "manager-role-binding.labels" -}}
|
||||
{{- $resourceLabels := dict "app.kubernetes.io/component" "manager-role-binding" -}}
|
||||
{{- $commonLabels := include "gha-common-labels" . | fromYaml -}}
|
||||
{{- $userLabels := include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.managerRoleBinding.metadata.labels | default (dict)) | fromYaml -}}
|
||||
{{- $global := include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.all.metadata.labels | default (dict)) | fromYaml -}}
|
||||
{{- toYaml (mergeOverwrite $global $userLabels $resourceLabels $commonLabels) }}
|
||||
{{- end }}
|
||||
|
||||
|
||||
{{/*
|
||||
Create the annotations for the manager RoleBinding.
|
||||
|
||||
Order of precedence:
|
||||
1) resource.all.metadata.annotations
|
||||
2) resource.managerRoleBinding.metadata.annotations
|
||||
Reserved annotations are excluded from both levels.
|
||||
*/}}
|
||||
{{- define "manager-role-binding.annotations" -}}
|
||||
{{- $global := (include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.all.metadata.annotations | default (dict))) | fromYaml -}}
|
||||
{{- $resource := (include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.managerRoleBinding.metadata.annotations | default (dict))) | fromYaml -}}
|
||||
{{- $annotations := mergeOverwrite $global $resource -}}
|
||||
{{- if not (empty $annotations) -}}
|
||||
{{- toYaml $annotations }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,121 @@
|
||||
{{- define "runner-mode-dind.runner-container" -}}
|
||||
name: runner
|
||||
image: {{ include "runner.image" . | quote }}
|
||||
command: {{ include "runner.command" . }}
|
||||
env:
|
||||
- {{ include "runner-mode-dind.env-docker-host" . | nindent 4 }}
|
||||
- {{ include "runner-mode-dind.env-wait-for-docker-timeout" . | nindent 4 }}
|
||||
{{/* TODO:: Should we skip DOCKER_HOST and RUNNER_WAIT_FOR_DOCKER_IN_SECONDS? */}}
|
||||
{{- with .Values.runner.env }}
|
||||
{{- toYaml . | nindent 2 }}
|
||||
{{- end }}
|
||||
volumeMounts:
|
||||
- name: work
|
||||
mountPath: /home/runner/_work
|
||||
- name: dind-sock
|
||||
mountPath: {{ include "runner-mode-dind.sock-mount-dir" . | quote }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "runner-mode-dind.dind-container" -}}
|
||||
{{- $dind := .Values.runner.dind | default dict -}}
|
||||
name: {{ $dind.container.name | default "dind" }}
|
||||
image: {{ $dind.container.image | default "docker:dind" | quote }}
|
||||
args:
|
||||
{{- include "runner-mode-dind.args" . | nindent 2 }}
|
||||
env:
|
||||
- name: DOCKER_GROUP_GID
|
||||
value: {{ ($dind.dockerGroupId | default "123") | quote }}
|
||||
securityContext:
|
||||
{{- if $dind.container.securityContext }}
|
||||
{{- toYaml $dind.container.securityContext | nindent 2 }}
|
||||
{{ else }}
|
||||
{{- toYaml (dict "privileged" true) | nindent 2 }}
|
||||
{{- end }}
|
||||
restartPolicy: Always
|
||||
startupProbe:
|
||||
{{- include "runner-mode-dind.startup-probe" . | nindent 2 }}
|
||||
volumeMounts:
|
||||
- name: work
|
||||
mountPath: /home/runner/_work
|
||||
- name: dind-sock
|
||||
mountPath: {{ include "runner-mode-dind.sock-mount-dir" . | quote }}
|
||||
{{- if $dind.copyExternals }}
|
||||
- name: dind-externals
|
||||
mountPath: /home/runner/externals
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "runner-mode-dind.pod-volumes" -}}
|
||||
- name: work
|
||||
emptyDir: {}
|
||||
- name: dind-sock
|
||||
emptyDir: {}
|
||||
{{- if .Values.runner.dind.copyExternals }}
|
||||
- name: dind-externals
|
||||
emptyDir: {}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "runner-mode-dind.copy-externals" -}}
|
||||
name: init-dind-externals
|
||||
image: ghcr.io/actions/actions-runner:latest
|
||||
command: ["cp", "-r", "/home/runner/externals/.", "/home/runner/tmpDir/"]
|
||||
volumeMounts:
|
||||
- name: dind-externals
|
||||
mountPath: /home/runner/tmpDir
|
||||
{{- end }}
|
||||
|
||||
{{- define "runner-mode-dind.startup-probe" -}}
|
||||
exec:
|
||||
command:
|
||||
- docker
|
||||
- info
|
||||
initialDelaySeconds: 0
|
||||
failureThreshold: 24
|
||||
periodSeconds: 5
|
||||
{{- end }}
|
||||
|
||||
{{- define "runner-mode-dind.args" -}}
|
||||
{{- $dind := .Values.runner.dind | default dict -}}
|
||||
{{- $dockerSock := $dind.dockerSock | default "unix:///var/run/docker.sock" -}}
|
||||
{{- if not (kindIs "string" $dockerSock) -}}
|
||||
{{- fail "runner.dind.dockerSock must be a string" -}}
|
||||
{{- end -}}
|
||||
- dockerd
|
||||
- {{ printf "--host=%s" $dockerSock }}
|
||||
- --group=$(DOCKER_GROUP_GID)
|
||||
{{- end }}
|
||||
|
||||
{{- define "runner-mode-dind.env-docker-host" -}}
|
||||
{{- $dind := .Values.runner.dind | default dict -}}
|
||||
{{- $dockerSock := $dind.dockerSock | default "unix:///var/run/docker.sock" -}}
|
||||
{{- if not (kindIs "string" $dockerSock) -}}
|
||||
{{- fail "runner.dind.dockerSock must be a string" -}}
|
||||
{{- end -}}
|
||||
name: DOCKER_HOST
|
||||
value: {{ $dockerSock | quote }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "runner-mode-dind.env-wait-for-docker-timeout" -}}
|
||||
{{- $dind := .Values.runner.dind | default dict -}}
|
||||
{{- $waitForDockerInSeconds := $dind.waitForDockerInSeconds | default 120 -}}
|
||||
{{- if not (or (kindIs "int" $waitForDockerInSeconds) (kindIs "int64" $waitForDockerInSeconds) (kindIs "float64" $waitForDockerInSeconds)) -}}
|
||||
{{- fail "runner.dind.waitForDockerInSeconds must be a number" -}}
|
||||
{{- end -}}
|
||||
{{- $waitForDockerInSecondsInt := ($waitForDockerInSeconds | int) -}}
|
||||
{{- if lt $waitForDockerInSecondsInt 0 -}}
|
||||
{{- fail "runner.dind.waitForDockerInSeconds must be non-negative" -}}
|
||||
{{- end -}}
|
||||
name: RUNNER_WAIT_FOR_DOCKER_IN_SECONDS
|
||||
value: {{ $waitForDockerInSecondsInt | toString | quote }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "runner-mode-dind.sock-mount-dir" -}}
|
||||
{{- $dind := .Values.runner.dind | default dict -}}
|
||||
{{- $dockerSock := $dind.dockerSock | default "unix:///var/run/docker.sock" -}}
|
||||
{{- if not (kindIs "string" $dockerSock) -}}
|
||||
{{- fail "runner.dind.dockerSock must be a string" -}}
|
||||
{{- end -}}
|
||||
{{- $dockerSockPath := trimPrefix "unix://" $dockerSock -}}
|
||||
{{- dir $dockerSockPath -}}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,213 @@
|
||||
{{- define "runner-mode-kubernetes.runner-container" -}}
|
||||
{{- $runner := (.Values.runner | default dict) -}}
|
||||
{{- $kubeMode := (index $runner "kubernetesMode" | default dict) -}}
|
||||
{{- $hookPath := (index $kubeMode "hookPath" | default "/home/runner/k8s/index.js") -}}
|
||||
{{- $extensionRef := (index $kubeMode "extensionRef" | default "") -}}
|
||||
{{- $extension := (index $kubeMode "extension" | default dict) -}}
|
||||
{{- $extensionYaml := "" -}}
|
||||
{{- if kindIs "map" $extension -}}
|
||||
{{- $extensionYaml = (index $extension "yaml" | default "") -}}
|
||||
{{- end -}}
|
||||
{{- $hasExtension := or (not (empty $extensionRef)) (not (empty $extensionYaml)) -}}
|
||||
{{- $hookTemplatePath := printf "%s/hook-template.yaml" (dir $hookPath) -}}
|
||||
{{- $setHookTemplateEnv := true -}}
|
||||
{{- $userEnv := (.Values.runner.env | default list) -}}
|
||||
{{- if kindIs "slice" $userEnv -}}
|
||||
{{- range $userEnv -}}
|
||||
{{- if and (kindIs "map" .) (eq ((index . "name") | default "") "ACTIONS_RUNNER_CONTAINER_HOOK_TEMPLATE") -}}
|
||||
{{- $setHookTemplateEnv = false -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- if not (kindIs "string" $hookPath) -}}
|
||||
{{- fail "runner.kubernetesMode.hookPath must be a string" -}}
|
||||
{{- end -}}
|
||||
{{- if not (kindIs "string" $extensionRef) -}}
|
||||
{{- fail "runner.kubernetesMode.extensionRef must be a string" -}}
|
||||
{{- end -}}
|
||||
{{- if and (empty $extensionRef) (hasKey $kubeMode "extension") (not (kindIs "map" $extension)) -}}
|
||||
{{- fail "runner.kubernetesMode.extension must be an object when runner.kubernetesMode.extensionRef is empty" -}}
|
||||
{{- end -}}
|
||||
{{- if and (empty $extensionRef) (not (kindIs "string" $extensionYaml)) -}}
|
||||
{{- fail "runner.kubernetesMode.extension.yaml must be a string" -}}
|
||||
{{- end -}}
|
||||
{{- $requireJobContainer := true -}}
|
||||
{{- if hasKey $kubeMode "requireJobContainer" -}}
|
||||
{{- $requireJobContainer = (index $kubeMode "requireJobContainer") -}}
|
||||
{{- end -}}
|
||||
{{- if not (kindIs "bool" $requireJobContainer) -}}
|
||||
{{- fail "runner.kubernetesMode.requireJobContainer must be a bool" -}}
|
||||
{{- end -}}
|
||||
name: runner
|
||||
image: {{ include "runner.image" . | quote }}
|
||||
command: {{ include "runner.command" . }}
|
||||
env:
|
||||
- name: ACTIONS_RUNNER_CONTAINER_HOOKS
|
||||
value: {{ $hookPath | quote }}
|
||||
- name: ACTIONS_RUNNER_POD_NAME
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.name
|
||||
- name: ACTIONS_RUNNER_REQUIRE_JOB_CONTAINER
|
||||
value: {{ ternary "true" "false" $requireJobContainer | quote }}
|
||||
{{- if and $hasExtension $setHookTemplateEnv }}
|
||||
- name: ACTIONS_RUNNER_CONTAINER_HOOK_TEMPLATE
|
||||
value: {{ $hookTemplatePath | quote }}
|
||||
{{- end }}
|
||||
{{- with .Values.runner.env }}
|
||||
{{- toYaml . | nindent 2 }}
|
||||
{{- end }}
|
||||
volumeMounts:
|
||||
- name: work
|
||||
mountPath: /home/runner/_work
|
||||
{{- if $hasExtension }}
|
||||
- name: hook-extension
|
||||
mountPath: {{ $hookTemplatePath | quote }}
|
||||
subPath: extension
|
||||
readOnly: true
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "runner-mode-kubernetes.pod-volumes" -}}
|
||||
{{- $runner := (.Values.runner | default dict) -}}
|
||||
{{- $kubeMode := (index $runner "kubernetesMode" | default dict) -}}
|
||||
{{- $extensionRef := (index $kubeMode "extensionRef" | default "") -}}
|
||||
{{- $extension := (index $kubeMode "extension" | default dict) -}}
|
||||
{{- $extensionYaml := "" -}}
|
||||
{{- if kindIs "map" $extension -}}
|
||||
{{- $extensionYaml = (index $extension "yaml" | default "") -}}
|
||||
{{- end -}}
|
||||
{{- $hasExtension := or (not (empty $extensionRef)) (not (empty $extensionYaml)) -}}
|
||||
{{- $claim := (index $kubeMode "workVolumeClaim" | default dict) -}}
|
||||
{{- if and (not (empty $claim)) (not (kindIs "map" $claim)) -}}
|
||||
{{- fail "runner.kubernetesMode.workVolumeClaim must be a map/object" -}}
|
||||
{{- end -}}
|
||||
{{- if not (kindIs "string" $extensionRef) -}}
|
||||
{{- fail "runner.kubernetesMode.extensionRef must be a string" -}}
|
||||
{{- end -}}
|
||||
{{- if and (empty $extensionRef) (hasKey $kubeMode "extension") (not (kindIs "map" $extension)) -}}
|
||||
{{- fail "runner.kubernetesMode.extension must be an object when runner.kubernetesMode.extensionRef is empty" -}}
|
||||
{{- end -}}
|
||||
{{- if and (empty $extensionRef) (not (kindIs "string" $extensionYaml)) -}}
|
||||
{{- fail "runner.kubernetesMode.extension.yaml must be a string" -}}
|
||||
{{- end -}}
|
||||
{{- $defaultClaim := dict "accessModes" (list "ReadWriteOnce") "storageClassName" "local-path" "resources" (dict "requests" (dict "storage" "1Gi")) -}}
|
||||
{{- $claimSpec := mergeOverwrite $defaultClaim $claim -}}
|
||||
- name: work
|
||||
ephemeral:
|
||||
volumeClaimTemplate:
|
||||
spec:
|
||||
{{- toYaml $claimSpec | nindent 8 }}
|
||||
{{- if $hasExtension }}
|
||||
- name: hook-extension
|
||||
configMap:
|
||||
name: {{ if not (empty $extensionRef) }}{{ $extensionRef | quote }}{{ else }}{{ include "kube-mode-extension.name" . | quote }}{{ end }}
|
||||
{{- end }}
|
||||
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the annotations for the kubernetes-mode ServiceAccount.
|
||||
|
||||
Order of precedence:
|
||||
1) resource.all.metadata.annotations
|
||||
2) resource.kubernetesModeServiceAccount.metadata.annotations
|
||||
Reserved annotations are excluded from both levels.
|
||||
*/}}
|
||||
{{- define "kube-mode-serviceaccount.annotations" -}}
|
||||
{{- $global := (include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.all.metadata.annotations | default (dict))) | fromYaml -}}
|
||||
{{- $resource := (include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.kubernetesModeServiceAccount.metadata.annotations | default (dict))) | fromYaml -}}
|
||||
{{- $annotations := mergeOverwrite $global $resource -}}
|
||||
{{- if not (empty $annotations) -}}
|
||||
{{- toYaml $annotations }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the labels for the kubernetes-mode ServiceAccount.
|
||||
*/}}
|
||||
{{- define "kube-mode-serviceaccount.labels" -}}
|
||||
{{- $resourceLabels := dict "app.kubernetes.io/component" "kube-mode-serviceaccount" -}}
|
||||
{{- $commonLabels := include "gha-common-labels" . | fromYaml -}}
|
||||
{{- $userLabels := include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.kubernetesModeServiceAccount.metadata.labels | default (dict)) | fromYaml -}}
|
||||
{{- $global := include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.all.metadata.labels | default (dict)) | fromYaml -}}
|
||||
{{- toYaml (mergeOverwrite $global $userLabels $resourceLabels $commonLabels) }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the labels for the kubernetes-mode Role.
|
||||
*/}}
|
||||
{{- define "kube-mode-role.labels" -}}
|
||||
{{- $resourceLabels := dict "app.kubernetes.io/component" "kube-mode-role" -}}
|
||||
{{- $commonLabels := include "gha-common-labels" . | fromYaml -}}
|
||||
{{- $userLabels := include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.kubernetesModeRole.metadata.labels | default (dict)) | fromYaml -}}
|
||||
{{- $global := include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.all.metadata.labels | default (dict)) | fromYaml -}}
|
||||
{{- toYaml (mergeOverwrite $global $userLabels $resourceLabels $commonLabels) }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the annotations for the kubernetes-mode RoleBinding.
|
||||
|
||||
Order of precedence:
|
||||
1) resource.all.metadata.annotations
|
||||
2) resource.kubernetesModeRoleBinding.metadata.annotations
|
||||
Reserved annotations are excluded from both levels.
|
||||
*/}}
|
||||
{{- define "kube-mode-role-binding.annotations" -}}
|
||||
{{- $global := (include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.all.metadata.annotations | default (dict))) | fromYaml -}}
|
||||
{{- $resource := (include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.kubernetesModeRoleBinding.metadata.annotations | default (dict))) | fromYaml -}}
|
||||
{{- $annotations := mergeOverwrite $global $resource -}}
|
||||
{{- if not (empty $annotations) -}}
|
||||
{{- toYaml $annotations }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the labels for the kubernetes-mode RoleBinding.
|
||||
*/}}
|
||||
{{- define "kube-mode-role-binding.labels" -}}
|
||||
{{- $resourceLabels := dict "app.kubernetes.io/component" "kube-mode-role-binding" -}}
|
||||
{{- $commonLabels := include "gha-common-labels" . | fromYaml -}}
|
||||
{{- $userLabels := include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.kubernetesModeRoleBinding.metadata.labels | default (dict)) | fromYaml -}}
|
||||
{{- $global := include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.all.metadata.labels | default (dict)) | fromYaml -}}
|
||||
{{- toYaml (mergeOverwrite $global $userLabels $resourceLabels $commonLabels) }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the annotations for the kubernetes-mode Role.
|
||||
|
||||
Order of precedence:
|
||||
1) resource.all.metadata.annotations
|
||||
2) resource.kubernetesModeRole.metadata.annotations
|
||||
Reserved annotations are excluded from both levels.
|
||||
*/}}
|
||||
{{- define "kube-mode-role.annotations" -}}
|
||||
{{- $global := (include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.all.metadata.annotations | default (dict))) | fromYaml -}}
|
||||
{{- $resource := (include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.kubernetesModeRole.metadata.annotations | default (dict))) | fromYaml -}}
|
||||
{{- $annotations := mergeOverwrite $global $resource -}}
|
||||
{{- if not (empty $annotations) -}}
|
||||
{{- toYaml $annotations }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "kube-mode-extension.name" -}}
|
||||
{{- $runner := (.Values.runner | default dict) -}}
|
||||
{{- $kubeMode := (index $runner "kubernetesMode" | default dict) -}}
|
||||
{{- $extension := (index $kubeMode "extension" | default dict) -}}
|
||||
{{- $meta := (index $extension "metadata" | default dict) -}}
|
||||
{{- $name := (index $meta "name" | default "") -}}
|
||||
{{- if not (kindIs "string" $name) -}}
|
||||
{{- fail "runner.kubernetesMode.extension.metadata.name must be a string" -}}
|
||||
{{- end -}}
|
||||
{{- default (printf "%s-hook-extension" (include "autoscaling-runner-set.name" .) | trunc 63 | trimSuffix "-") $name -}}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the labels for the hook extension ConfigMap.
|
||||
*/}}
|
||||
{{- define "kube-mode-extension.labels" -}}
|
||||
{{- $resourceLabels := dict "app.kubernetes.io/component" "hook-extension" -}}
|
||||
{{- $commonLabels := include "gha-common-labels" . | fromYaml -}}
|
||||
{{- $global := include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.all.metadata.labels | default (dict)) | fromYaml -}}
|
||||
{{- toYaml (mergeOverwrite $global $resourceLabels $commonLabels) -}}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,65 @@
|
||||
{{/*
|
||||
Create labels for the runner Pod template (spec.template.metadata.labels).
|
||||
|
||||
Order of precedence:
|
||||
1) resource.all.metadata.labels
|
||||
2) runner.pod.metadata.labels
|
||||
3) common labels (cannot be overridden)
|
||||
|
||||
Reserved actions.github.com/* labels are excluded from user/global inputs.
|
||||
*/}}
|
||||
{{- define "autoscaling-runner-set.runner-pod.labels" -}}
|
||||
{{- $runner := (.Values.runner | default dict) -}}
|
||||
{{- $pod := (index $runner "pod" | default dict) -}}
|
||||
{{- if not (kindIs "map" $pod) -}}
|
||||
{{- fail ".Values.runner.pod must be a map/object" -}}
|
||||
{{- end -}}
|
||||
{{- $podMetadata := (index $pod "metadata" | default dict) -}}
|
||||
{{- if not (kindIs "map" $podMetadata) -}}
|
||||
{{- fail ".Values.runner.pod.metadata must be a map/object" -}}
|
||||
{{- end -}}
|
||||
{{- $userRaw := (index $podMetadata "labels" | default (dict)) -}}
|
||||
{{- if not (kindIs "map" $userRaw) -}}
|
||||
{{- fail ".Values.runner.pod.metadata.labels must be a map/object" -}}
|
||||
{{- end -}}
|
||||
{{- $global := include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.all.metadata.labels | default (dict)) | fromYaml -}}
|
||||
{{- $user := include "apply-non-reserved-gha-labels-and-annotations" $userRaw | fromYaml -}}
|
||||
{{- $common := include "gha-common-labels" . | fromYaml -}}
|
||||
{{- $labels := mergeOverwrite $global $user $common -}}
|
||||
{{- if not (empty $labels) -}}
|
||||
{{- toYaml $labels -}}
|
||||
{{- end -}}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create annotations for the runner Pod template (spec.template.metadata.annotations).
|
||||
|
||||
Order of precedence:
|
||||
1) resource.all.metadata.annotations
|
||||
2) runner.pod.metadata.annotations
|
||||
|
||||
Reserved actions.github.com/* annotations are excluded from user/global inputs.
|
||||
*/}}
|
||||
{{- define "autoscaling-runner-set.runner-pod.annotations" -}}
|
||||
{{- $runner := (.Values.runner | default dict) -}}
|
||||
{{- $pod := (index $runner "pod" | default dict) -}}
|
||||
{{- if not (kindIs "map" $pod) -}}
|
||||
{{- fail ".Values.runner.pod must be a map/object" -}}
|
||||
{{- end -}}
|
||||
{{- $podMetadata := (index $pod "metadata" | default dict) -}}
|
||||
{{- if not (kindIs "map" $podMetadata) -}}
|
||||
{{- fail ".Values.runner.pod.metadata must be a map/object" -}}
|
||||
{{- end -}}
|
||||
{{- $userRaw := (index $podMetadata "annotations" | default (dict)) -}}
|
||||
{{- if not (kindIs "map" $userRaw) -}}
|
||||
{{- fail ".Values.runner.pod.metadata.annotations must be a map/object" -}}
|
||||
{{- end -}}
|
||||
{{- $global := (include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.all.metadata.annotations | default (dict))) | fromYaml -}}
|
||||
{{- $user := (include "apply-non-reserved-gha-labels-and-annotations" $userRaw) | fromYaml -}}
|
||||
{{- $annotations := mergeOverwrite $global $user -}}
|
||||
{{- if not (empty $annotations) -}}
|
||||
{{- toYaml $annotations -}}
|
||||
{{- end -}}
|
||||
{{- end }}
|
||||
|
||||
|
||||
@@ -0,0 +1,219 @@
|
||||
{{- $runner := (.Values.runner | default dict) }}
|
||||
{{- $runnerMode := (index $runner "mode" | default "") }}
|
||||
{{- $kubeMode := (index $runner "kubernetesMode" | default dict) }}
|
||||
{{- $dind := (index $runner "dind" | default dict) }}
|
||||
{{- $kubeDefaults := (index $kubeMode "default" | default true) }}
|
||||
{{- $kubeServiceAccountName := (index $kubeMode "serviceAccountName" | default "") }}
|
||||
{{- $usesKubernetesSecrets := or (not .Values.secretResolution) (eq .Values.secretResolution.type "kubernetes") }}
|
||||
|
||||
{{- $runnerPod := (index $runner "pod" | default dict) -}}
|
||||
{{- if not (kindIs "map" $runnerPod) -}}
|
||||
{{- fail ".Values.runner.pod must be an object" -}}
|
||||
{{- end }}
|
||||
{{- $runnerPodSpec := (index $runnerPod "spec" | default dict) -}}
|
||||
{{- if not (kindIs "map" $runnerPodSpec) -}}
|
||||
{{- fail ".Values.runner.pod.spec must be an object" -}}
|
||||
{{- end }}
|
||||
|
||||
{{- $extraContainers := (index $runnerPodSpec "containers" | default list) -}}
|
||||
{{- if not (kindIs "slice" $extraContainers) -}}
|
||||
{{- fail ".Values.runner.pod.spec.containers must be a list of container specifications" -}}
|
||||
{{- end }}
|
||||
{{- range $extraContainers -}}
|
||||
{{- if not (kindIs "map" .) -}}
|
||||
{{- fail ".Values.runner.pod.spec.containers must be a list of container specifications" -}}
|
||||
{{- end }}
|
||||
{{- $extraContainerName := (index . "name" | default "") -}}
|
||||
{{- if empty $extraContainerName -}}
|
||||
{{- fail ".Values.runner.pod.spec.containers[].name is required" -}}
|
||||
{{- end }}
|
||||
{{- if eq $extraContainerName "runner" -}}
|
||||
{{- fail ".Values.runner.pod.spec.containers[].name must not be 'runner' (reserved)" -}}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- $extraInitContainers := (index $runnerPodSpec "initContainers" | default list) -}}
|
||||
{{- if not (kindIs "slice" $extraInitContainers) -}}
|
||||
{{- fail ".Values.runner.pod.spec.initContainers must be a list of container specifications" -}}
|
||||
{{- end }}
|
||||
{{- range $extraInitContainers -}}
|
||||
{{- if not (kindIs "map" .) -}}
|
||||
{{- fail ".Values.runner.pod.spec.initContainers must be a list of container specifications" -}}
|
||||
{{- end }}
|
||||
{{- $extraInitContainerName := (index . "name" | default "") -}}
|
||||
{{- if empty $extraInitContainerName -}}
|
||||
{{- fail ".Values.runner.pod.spec.initContainers[].name is required" -}}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- $runnerPodSpecExtraFields := (omit $runnerPodSpec "containers" "initContainers" "volumes" "serviceAccountName") -}}
|
||||
{{- $extraVolumes := (index $runnerPodSpec "volumes" | default list) -}}
|
||||
{{- if not (kindIs "slice" $extraVolumes) -}}
|
||||
{{- fail ".Values.runner.pod.spec.volumes must be a list of volume specifications" -}}
|
||||
{{- end }}
|
||||
{{- $hasInitContainers := or (gt (len $extraInitContainers) 0) (eq $runnerMode "dind") -}}
|
||||
{{- $hasVolumes := or (gt (len $extraVolumes) 0) (eq $runnerMode "kubernetes") (eq $runnerMode "dind") -}}
|
||||
apiVersion: actions.github.com/v1alpha1
|
||||
kind: AutoscalingRunnerSet
|
||||
metadata:
|
||||
name: {{ include "autoscaling-runner-set.name" . | quote }}
|
||||
namespace: {{ include "autoscaling-runner-set.namespace" . | quote }}
|
||||
labels:
|
||||
{{- include "autoscaling-runner-set.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
{{- include "autoscaling-runner-set.annotations" . | nindent 4 }}
|
||||
actions.github.com/values-hash: {{ toJson .Values | sha256sum | trunc 63 }}
|
||||
{{- if and $usesKubernetesSecrets (empty .Values.auth.secretName) }}
|
||||
actions.github.com/cleanup-github-secret-name: {{ include "github-secret.name" . | quote }}
|
||||
{{- end }}
|
||||
actions.github.com/cleanup-manager-role-binding: {{ include "manager-role-binding.name" . | quote }}
|
||||
actions.github.com/cleanup-manager-role-name: {{ include "manager-role.name" . | quote }}
|
||||
{{- if ne $runnerMode "kubernetes" }}
|
||||
actions.github.com/cleanup-no-permission-service-account-name: {{ include "no-permission-serviceaccount.name" . | quote }}
|
||||
{{- end }}
|
||||
{{- if and (eq $runnerMode "kubernetes") $kubeDefaults (empty $kubeServiceAccountName) }}
|
||||
actions.github.com/cleanup-kubernetes-mode-role-binding-name: {{ include "kube-mode-role-binding.name" . | quote }}
|
||||
actions.github.com/cleanup-kubernetes-mode-role-name: {{ include "kube-mode-role.name" . | quote }}
|
||||
actions.github.com/cleanup-kubernetes-mode-service-account-name: {{ include "kube-mode-serviceaccount.name" . | quote }}
|
||||
{{- end }}
|
||||
|
||||
spec:
|
||||
githubConfigUrl: {{ required ".Values.auth.url is required" (trimSuffix "/" .Values.auth.url) | quote }}
|
||||
githubConfigSecret: {{ include "github-secret.name" . | quote }}
|
||||
runnerGroup: {{ .Values.scaleset.runnerGroup | quote }}
|
||||
runnerScaleSetName: {{ .Values.scaleset.name | quote }}
|
||||
|
||||
{{- if .Values.githubServerTLS }}
|
||||
githubServerTLS:
|
||||
{{- with .Values.githubServerTLS.certificateFrom }}
|
||||
certificateFrom:
|
||||
configMapKeyRef:
|
||||
name: {{ .configMapKeyRef.name }}
|
||||
key: {{ .configMapKeyRef.key }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- if and .Values.secretResolution (ne .Values.secretResolution.type "kubernetes") }}
|
||||
vaultConfig:
|
||||
type: {{ .Values.secretResolution.type }}
|
||||
{{- if .Values.secretResolution.proxy }}
|
||||
proxy: {{- toYaml .Values.secretResolution.proxy | nindent 6 }}
|
||||
{{- end }}
|
||||
{{- if eq .Values.secretResolution.type "azureKeyVault" }}
|
||||
azureKeyVault:
|
||||
url: {{ .Values.secretResolution.azureKeyVault.url }}
|
||||
tenantId: {{ .Values.secretResolution.azureKeyVault.tenantId }}
|
||||
clientId: {{ .Values.secretResolution.azureKeyVault.clientId }}
|
||||
certificatePath: {{ .Values.secretResolution.azureKeyVault.certificatePath }}
|
||||
secretKey: {{ .Values.secretResolution.azureKeyVault.secretKey }}
|
||||
{{- else }}
|
||||
{{- fail (printf "Unsupported keyVault type: %s" .Values.secretResolution.type) }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- if .Values.proxy }}
|
||||
proxy:
|
||||
{{- if .Values.proxy.http }}
|
||||
http:
|
||||
url: {{ .Values.proxy.http.url }}
|
||||
{{- if .Values.proxy.http.credentialSecretRef }}
|
||||
credentialSecretRef: {{ .Values.proxy.http.credentialSecretRef }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.proxy.https }}
|
||||
https:
|
||||
url: {{ .Values.proxy.https.url }}
|
||||
{{- if .Values.proxy.https.credentialSecretRef }}
|
||||
credentialSecretRef: {{ .Values.proxy.https.credentialSecretRef }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if and .Values.proxy.noProxy (kindIs "slice" .Values.proxy.noProxy) }}
|
||||
noProxy: {{ .Values.proxy.noProxy | toYaml | nindent 6}}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- if and (or (kindIs "int64" .Values.scaleset.minRunners) (kindIs "float64" .Values.scaleset.minRunners)) (or (kindIs "int64" .Values.scaleset.maxRunners) (kindIs "float64" .Values.scaleset.maxRunners)) }}
|
||||
{{- if gt .Values.scaleset.minRunners .Values.scaleset.maxRunners }}
|
||||
{{- fail "maxRunners has to be greater or equal to minRunners" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- if or (kindIs "int64" .Values.scaleset.maxRunners) (kindIs "float64" .Values.scaleset.maxRunners)}}
|
||||
{{- if lt (.Values.scaleset.maxRunners | int) 0 }}
|
||||
{{- fail "maxRunners has to be greater or equal to 0" }}
|
||||
{{- end }}
|
||||
maxRunners: {{ .Values.scaleset.maxRunners | int }}
|
||||
{{- end }}
|
||||
|
||||
{{- if or (kindIs "int64" .Values.scaleset.minRunners) (kindIs "float64" .Values.scaleset.minRunners) }}
|
||||
{{- if lt (.Values.scaleset.minRunners | int) 0 }}
|
||||
{{- fail "minRunners has to be greater or equal to 0" }}
|
||||
{{- end }}
|
||||
minRunners: {{ .Values.scaleset.minRunners | int }}
|
||||
{{- end }}
|
||||
|
||||
{{- if and .Values.listenerPodTemplate (or .Values.listenerPodTemplate.metadata .Values.listenerPodTemplate.spec) }}
|
||||
listenerTemplate:
|
||||
{{- include "listener-template.pod" . | nindent 4}}
|
||||
{{- end }}
|
||||
|
||||
{{- with .Values.listenerMetrics }}
|
||||
listenerMetrics:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
|
||||
template:
|
||||
{{- $runnerPodLabels := (include "autoscaling-runner-set.runner-pod.labels" .) -}}
|
||||
{{- $runnerPodAnnotations := (include "autoscaling-runner-set.runner-pod.annotations" .) -}}
|
||||
{{- if or $runnerPodLabels $runnerPodAnnotations }}
|
||||
metadata:
|
||||
{{- if $runnerPodLabels }}
|
||||
labels:
|
||||
{{- $runnerPodLabels | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if $runnerPodAnnotations }}
|
||||
annotations:
|
||||
{{- $runnerPodAnnotations | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
spec:
|
||||
serviceAccountName: {{ include "autoscaling-runner-set.template-service-account" . | quote }}
|
||||
{{- if $hasInitContainers }}
|
||||
initContainers:
|
||||
{{- if and (eq $runnerMode "dind") $dind.copyExternals }}
|
||||
- {{ include "runner-mode-dind.copy-externals" . | nindent 10 }}
|
||||
{{- end }}
|
||||
{{- range $extraInitContainers }}
|
||||
- {{ toYaml . | nindent 10 }}
|
||||
{{- end }}
|
||||
{{- if eq $runnerMode "dind" }}
|
||||
- {{ include "runner-mode-dind.dind-container" . | nindent 10 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
containers:
|
||||
-
|
||||
{{- if eq $runnerMode "kubernetes" }}
|
||||
{{- include "runner-mode-kubernetes.runner-container" . | nindent 10 }}
|
||||
{{- else }}
|
||||
{{- include "runner-mode-dind.runner-container" . | nindent 10 }}
|
||||
{{- end }}
|
||||
{{- if $extraContainers }}
|
||||
{{- range $extraContainers }}
|
||||
- {{ toYaml . | nindent 10 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if $hasVolumes }}
|
||||
volumes:
|
||||
{{- if eq $runnerMode "kubernetes" }}
|
||||
{{- include "runner-mode-kubernetes.pod-volumes" . | nindent 8 }}
|
||||
{{- else }}
|
||||
{{- include "runner-mode-dind.pod-volumes" . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if $extraVolumes }}
|
||||
{{- range $extraVolumes }}
|
||||
- {{ toYaml . | nindent 10 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if gt (len $runnerPodSpecExtraFields) 0 }}
|
||||
{{- toYaml $runnerPodSpecExtraFields | nindent 6 }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,28 @@
|
||||
{{- $usesKubernetesSecrets := or (not .Values.secretResolution) (eq .Values.secretResolution.type "kubernetes") -}}
|
||||
|
||||
{{- if and (not $usesKubernetesSecrets) (empty .Values.auth.secretName) -}}
|
||||
{{- fail ".Values.auth.secretName is required when .Values.secretResolution.type is not \"kubernetes\"" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if and $usesKubernetesSecrets (empty .Values.auth.secretName) -}}
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ include "github-secret.name" . | quote }}
|
||||
namespace: {{ include "autoscaling-runner-set.namespace" . | quote }}
|
||||
labels:
|
||||
{{- include "github-secret.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
{{- include "github-secret.annotations" . | nindent 4 }}
|
||||
finalizers:
|
||||
- actions.github.com/cleanup-protection
|
||||
type: Opaque
|
||||
data:
|
||||
{{- if not (empty .Values.auth.app.clientId) }}
|
||||
github_app_id: {{ .Values.auth.app.clientId | toString | b64enc }}
|
||||
github_app_installation_id: {{ required ".Values.auth.app.installationId is required when using GitHub App auth" .Values.auth.app.installationId | toString | b64enc }}
|
||||
github_app_private_key: {{ required ".Values.auth.app.privateKey is required when using GitHub App auth" .Values.auth.app.privateKey | toString | b64enc }}
|
||||
{{- else }}
|
||||
github_token: {{ required ".Values.auth.githubToken is required when auth.secretName and auth.app.clientId are not set" .Values.auth.githubToken | toString | b64enc }}
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,56 @@
|
||||
{{- $runner := (.Values.runner | default dict) -}}
|
||||
{{- $runnerMode := (index $runner "mode" | default "") -}}
|
||||
{{- $kubeMode := (index $runner "kubernetesMode" | default dict) -}}
|
||||
{{- $extensionRef := (index $kubeMode "extensionRef" | default "") -}}
|
||||
{{- if not (kindIs "string" $extensionRef) -}}
|
||||
{{- fail "runner.kubernetesMode.extensionRef must be a string" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if and (eq $runnerMode "kubernetes") (empty $extensionRef) -}}
|
||||
{{- $extension := (index $kubeMode "extension" | default dict) -}}
|
||||
{{- if and (hasKey $kubeMode "extension") (not (kindIs "map" $extension)) -}}
|
||||
{{- fail "runner.kubernetesMode.extension must be an object" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $extensionMeta := dict -}}
|
||||
{{- $extensionName := "" -}}
|
||||
{{- $extensionNamespace := "" -}}
|
||||
{{- $extensionYaml := "" -}}
|
||||
{{- if kindIs "map" $extension -}}
|
||||
{{- $extensionMeta = (index $extension "metadata" | default dict) -}}
|
||||
{{- if not (kindIs "map" $extensionMeta) -}}
|
||||
{{- fail "runner.kubernetesMode.extension.metadata must be an object" -}}
|
||||
{{- end -}}
|
||||
{{- $extensionName = (index $extensionMeta "name" | default "") -}}
|
||||
{{- $extensionNamespace = (index $extensionMeta "namespace" | default "") -}}
|
||||
{{- $extensionYaml = (index $extension "yaml" | default "") -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if not (kindIs "string" $extensionName) -}}
|
||||
{{- fail "runner.kubernetesMode.extension.metadata.name must be a string" -}}
|
||||
{{- end -}}
|
||||
{{- if not (kindIs "string" $extensionNamespace) -}}
|
||||
{{- fail "runner.kubernetesMode.extension.metadata.namespace must be a string" -}}
|
||||
{{- end -}}
|
||||
{{- if not (kindIs "string" $extensionYaml) -}}
|
||||
{{- fail "runner.kubernetesMode.extension.yaml must be a string" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if not (empty $extensionYaml) -}}
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ default (printf "%s-hook-extension" (include "autoscaling-runner-set.name" .) | trunc 63 | trimSuffix "-") $extensionName | quote }}
|
||||
namespace: {{ default (include "autoscaling-runner-set.namespace" .) $extensionNamespace | quote }}
|
||||
labels:
|
||||
{{- include "kube-mode-extension.labels" . | nindent 4 }}
|
||||
{{- $annotations := (include "apply-non-reserved-gha-labels-and-annotations" (.Values.resource.all.metadata.annotations | default (dict))) | fromYaml -}}
|
||||
{{- if not (empty $annotations) }}
|
||||
annotations:
|
||||
{{- toYaml $annotations | nindent 4 }}
|
||||
{{- end }}
|
||||
data:
|
||||
extension: |-
|
||||
{{ $extensionYaml | indent 4 }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,42 @@
|
||||
{{- $runner := (.Values.runner | default dict) -}}
|
||||
{{- $runnerMode := (index $runner "mode" | default "") -}}
|
||||
{{- $kubeMode := (index $runner "kubernetesMode" | default dict) -}}
|
||||
{{- $kubeDefaults := (index $kubeMode "default" | default true) -}}
|
||||
{{- $kubeServiceAccountName := (index $kubeMode "serviceAccountName" | default "") -}}
|
||||
{{- if and (eq $runnerMode "kubernetes") $kubeDefaults (empty $kubeServiceAccountName) }}
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: {{ include "kube-mode-role.name" . | quote }}
|
||||
namespace: {{ include "autoscaling-runner-set.namespace" . | quote }}
|
||||
labels:
|
||||
{{- include "kube-mode-role.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
{{- include "kube-mode-role.annotations" . | nindent 4 }}
|
||||
finalizers:
|
||||
- actions.github.com/cleanup-protection
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["pods"]
|
||||
verbs: ["get", "list", "create", "delete"]
|
||||
- apiGroups: [""]
|
||||
resources: ["pods/exec"]
|
||||
verbs: ["get", "create"]
|
||||
- apiGroups: [""]
|
||||
resources: ["pods/log"]
|
||||
verbs: ["get", "list", "watch"]
|
||||
- apiGroups: ["batch"]
|
||||
resources: ["jobs"]
|
||||
verbs: ["get", "list", "create", "delete"]
|
||||
- apiGroups: [""]
|
||||
resources: ["secrets"]
|
||||
verbs: ["get", "list", "create", "delete"]
|
||||
{{- with .Values.resource.kubernetesModeRole.extraRules }}
|
||||
{{- if not (empty .) }}
|
||||
{{- if not (kindIs "slice" .) -}}
|
||||
{{- fail ".Values.resource.kubernetesModeRole.extraRules must be a list of RBAC policy rules" -}}
|
||||
{{- end }}
|
||||
{{ toYaml . | nindent 2 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,26 @@
|
||||
{{- $runner := (.Values.runner | default dict) -}}
|
||||
{{- $runnerMode := (index $runner "mode" | default "") -}}
|
||||
{{- $kubeMode := (index $runner "kubernetesMode" | default dict) -}}
|
||||
{{- $kubeDefaults := (index $kubeMode "default" | default true) -}}
|
||||
{{- $kubeServiceAccountName := (index $kubeMode "serviceAccountName" | default "") -}}
|
||||
{{- if and (eq $runnerMode "kubernetes") $kubeDefaults (empty $kubeServiceAccountName) }}
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: {{ include "kube-mode-role-binding.name" . | quote }}
|
||||
namespace: {{ include "autoscaling-runner-set.namespace" . | quote }}
|
||||
labels:
|
||||
{{- include "kube-mode-role-binding.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
{{- include "kube-mode-role-binding.annotations" . | nindent 4 }}
|
||||
finalizers:
|
||||
- actions.github.com/cleanup-protection
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: {{ include "kube-mode-role.name" . | quote }}
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ include "kube-mode-serviceaccount.name" . | quote }}
|
||||
namespace: {{ include "autoscaling-runner-set.namespace" . | quote }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,18 @@
|
||||
{{- $runner := (.Values.runner | default dict) -}}
|
||||
{{- $runnerMode := (index $runner "mode" | default "") -}}
|
||||
{{- $kubeMode := (index $runner "kubernetesMode" | default dict) -}}
|
||||
{{- $kubeDefaults := (index $kubeMode "default" | default true) -}}
|
||||
{{- $kubeServiceAccountName := (index $kubeMode "serviceAccountName" | default "") -}}
|
||||
{{- if and (eq $runnerMode "kubernetes") $kubeDefaults (empty $kubeServiceAccountName) }}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ include "kube-mode-serviceaccount.name" . | quote }}
|
||||
namespace: {{ include "autoscaling-runner-set.namespace" . | quote }}
|
||||
labels:
|
||||
{{- include "kube-mode-serviceaccount.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
{{- include "kube-mode-serviceaccount.annotations" . | nindent 4 }}
|
||||
finalizers:
|
||||
- actions.github.com/cleanup-protection
|
||||
{{- end }}
|
||||
@@ -0,0 +1,85 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: {{ include "manager-role.name" . | quote }}
|
||||
namespace: {{ include "autoscaling-runner-set.namespace" . | quote }}
|
||||
labels:
|
||||
{{- include "manager-role.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
{{- include "manager-role.annotations" . | nindent 4 }}
|
||||
finalizers:
|
||||
- actions.github.com/cleanup-protection
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- pods
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- pods/status
|
||||
verbs:
|
||||
- get
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- secrets
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- serviceaccounts
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- list
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- rbac.authorization.k8s.io
|
||||
resources:
|
||||
- rolebindings
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
- apiGroups:
|
||||
- rbac.authorization.k8s.io
|
||||
resources:
|
||||
- roles
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- get
|
||||
- patch
|
||||
- update
|
||||
{{- if .Values.githubServerTLS }}
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- configmaps
|
||||
verbs:
|
||||
- get
|
||||
{{- end }}
|
||||
|
||||
{{- with .Values.resource.managerRole.extraRules }}
|
||||
{{- if not (empty .) }}
|
||||
{{- if not (kindIs "slice" .) -}}
|
||||
{{- fail ".Values.resource.managerRole.extraRules must be a list of RBAC policy rules" -}}
|
||||
{{- end }}
|
||||
{{ toYaml . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,22 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: {{ include "manager-role-binding.name" . | quote }}
|
||||
namespace: {{ include "autoscaling-runner-set.namespace" . | quote }}
|
||||
labels:
|
||||
{{- include "manager-role-binding.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
{{- include "manager-role-binding.annotations" . | nindent 4 }}
|
||||
finalizers:
|
||||
- actions.github.com/cleanup-protection
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: {{ include "manager-role.name" . | quote }}
|
||||
subjects:
|
||||
{{- if not .Values.controllerServiceAccount }}
|
||||
{{- fail "controllerServiceAccount must be set" -}}
|
||||
{{- end }}
|
||||
- kind: ServiceAccount
|
||||
name: {{ required "controllerServiceAccount.name must be set" .Values.controllerServiceAccount.name | quote }}
|
||||
namespace: {{ required "controllerServiceAccount.namespace must be set" .Values.controllerServiceAccount.namespace | quote }}
|
||||
@@ -0,0 +1,14 @@
|
||||
{{- $runnerMode := (.Values.runner.mode | default "") -}}
|
||||
{{- if ne $runnerMode "kubernetes" -}}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ include "no-permission-serviceaccount.name" . | quote }}
|
||||
namespace: {{ include "autoscaling-runner-set.namespace" . | quote }}
|
||||
labels:
|
||||
{{- include "no-permission-serviceaccount.labels" . | nindent 4 }}
|
||||
annotations:
|
||||
{{- include "no-permission-serviceaccount.annotations" . | nindent 4 }}
|
||||
finalizers:
|
||||
- actions.github.com/cleanup-protection
|
||||
{{- end }}
|
||||
@@ -0,0 +1,79 @@
|
||||
suite: "Test AutoscalingRunnerSet Annotations"
|
||||
templates:
|
||||
- autoscalingrunnserset.yaml
|
||||
tests:
|
||||
- it: should render values-hash annotation
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- exists:
|
||||
path: metadata.annotations["actions.github.com/values-hash"]
|
||||
|
||||
- it: should merge global and resource annotations (resource overrides global)
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
resource:
|
||||
all:
|
||||
metadata:
|
||||
annotations:
|
||||
a: "global"
|
||||
shared: "global"
|
||||
autoscalingRunnerSet:
|
||||
metadata:
|
||||
annotations:
|
||||
b: "resource"
|
||||
shared: "resource"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: metadata.annotations.a
|
||||
value: "global"
|
||||
- equal:
|
||||
path: metadata.annotations.b
|
||||
value: "resource"
|
||||
- equal:
|
||||
path: metadata.annotations.shared
|
||||
value: "resource"
|
||||
|
||||
- it: should not allow overriding reserved values-hash annotation
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
resource:
|
||||
all:
|
||||
metadata:
|
||||
annotations:
|
||||
actions.github.com/values-hash: "user-value"
|
||||
ok: "ok"
|
||||
autoscalingRunnerSet:
|
||||
metadata:
|
||||
annotations:
|
||||
actions.github.com/cleanup-something: "should-not-render"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: metadata.annotations.ok
|
||||
value: "ok"
|
||||
- notEqual:
|
||||
path: metadata.annotations["actions.github.com/values-hash"]
|
||||
value: "user-value"
|
||||
- notExists:
|
||||
path: metadata.annotations["actions.github.com/cleanup-something"]
|
||||
@@ -0,0 +1,245 @@
|
||||
suite: "Test AutoscalingRunnerSet Authentication & Configuration"
|
||||
templates:
|
||||
- autoscalingrunnserset.yaml
|
||||
tests:
|
||||
- it: should require githubConfigUrl
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: ".Values.auth.url is required"
|
||||
|
||||
- it: should render githubConfigUrl from auth.url
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.githubConfigUrl
|
||||
value: "https://github.com/org"
|
||||
|
||||
- it: should trim trailing slash from githubConfigUrl
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org/"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.githubConfigUrl
|
||||
value: "https://github.com/org"
|
||||
|
||||
- it: should render default githubConfigSecret from release name
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.githubConfigSecret
|
||||
value: "test-name-github-secret"
|
||||
|
||||
- it: should render custom githubConfigSecret when auth.secretName is provided
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
auth.secretName: "custom-github-secret"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.githubConfigSecret
|
||||
value: "custom-github-secret"
|
||||
|
||||
- it: should render default runnerGroup when not configured
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.runnerGroup
|
||||
value: "default"
|
||||
|
||||
- it: should render custom runnerGroup when configured
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
scaleset.runnerGroup: "custom-group"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.runnerGroup
|
||||
value: "custom-group"
|
||||
|
||||
- it: should render runnerGroup with special characters
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
scaleset.runnerGroup: "my-custom-runner-group-123"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.runnerGroup
|
||||
value: "my-custom-runner-group-123"
|
||||
|
||||
- it: should render runnerScaleSetName from scaleset.name
|
||||
set:
|
||||
scaleset.name: "my-runner-set"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.runnerScaleSetName
|
||||
value: "my-runner-set"
|
||||
|
||||
- it: should use release name as metadata name when runnerScaleSetName not provided
|
||||
set:
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
release:
|
||||
name: "release-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: metadata.name
|
||||
value: "release-name"
|
||||
|
||||
- it: should use scaleset.name for spec.runnerScaleSetName when provided
|
||||
set:
|
||||
scaleset.name: "spec-runner-name"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
release:
|
||||
name: "release-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.runnerScaleSetName
|
||||
value: "spec-runner-name"
|
||||
|
||||
- it: should not normalize underscores in runnerScaleSetName (underscores are preserved)
|
||||
set:
|
||||
scaleset.name: "my_runner_set"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.runnerScaleSetName
|
||||
value: "my_runner_set"
|
||||
|
||||
- it: should reject metadata name exceeding 45 characters
|
||||
set:
|
||||
runnerScaleSetName: "this-is-a-very-long-name-that-exceeds-forty-five-characters-long"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: "Autoscaling runner set name must have up to 45 characters"
|
||||
|
||||
- it: should handle githubConfigUrl with enterprise GitHub instance
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.enterprise.com/api/v3"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.githubConfigUrl
|
||||
value: "https://github.enterprise.com/api/v3"
|
||||
|
||||
- it: should render all configuration together
|
||||
set:
|
||||
runnerScaleSetName: "prod-runners"
|
||||
scaleset.name: "prod-spec-name"
|
||||
auth.url: "https://github.com/myorg"
|
||||
auth.githubToken: "gh_token12345"
|
||||
auth.secretName: "gh-token-secret"
|
||||
scaleset.runnerGroup: "prod-group"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
release:
|
||||
name: "prod-scale-set"
|
||||
namespace: "arc"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.githubConfigUrl
|
||||
value: "https://github.com/myorg"
|
||||
- equal:
|
||||
path: spec.githubConfigSecret
|
||||
value: "gh-token-secret"
|
||||
- equal:
|
||||
path: spec.runnerGroup
|
||||
value: "prod-group"
|
||||
- equal:
|
||||
path: spec.runnerScaleSetName
|
||||
value: "prod-spec-name"
|
||||
- equal:
|
||||
path: metadata.name
|
||||
value: "prod-runners"
|
||||
- equal:
|
||||
path: metadata.namespace
|
||||
value: "arc"
|
||||
@@ -0,0 +1,342 @@
|
||||
suite: "AutoscalingRunnerSet dind mode podspec"
|
||||
templates:
|
||||
- autoscalingrunnserset.yaml
|
||||
tests:
|
||||
- it: should render the default dind pod spec (initContainers, runner container, volumes)
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
runner:
|
||||
mode: "dind"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[0].name
|
||||
value: init-dind-externals
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[0].image
|
||||
value: ghcr.io/actions/actions-runner:latest
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[0].command[0]
|
||||
value: cp
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].name
|
||||
value: dind
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].image
|
||||
value: docker:dind
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].args[0]
|
||||
value: dockerd
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].args[1]
|
||||
value: --host=unix:///var/run/docker.sock
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].args[2]
|
||||
value: --group=$(DOCKER_GROUP_GID)
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].env[0].name
|
||||
value: DOCKER_GROUP_GID
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].env[0].value
|
||||
value: "123"
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].securityContext.privileged
|
||||
value: true
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].startupProbe.exec.command[0]
|
||||
value: docker
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].startupProbe.exec.command[1]
|
||||
value: info
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].volumeMounts[0].name
|
||||
value: work
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].volumeMounts[0].mountPath
|
||||
value: /home/runner/_work
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].volumeMounts[1].name
|
||||
value: dind-sock
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].volumeMounts[1].mountPath
|
||||
value: /var/run
|
||||
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].name
|
||||
value: runner
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].image
|
||||
value: ghcr.io/actions/actions-runner:latest
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].env[0].name
|
||||
value: DOCKER_HOST
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].env[0].value
|
||||
value: unix:///var/run/docker.sock
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].env[1].name
|
||||
value: RUNNER_WAIT_FOR_DOCKER_IN_SECONDS
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].env[1].value
|
||||
value: "120"
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].volumeMounts[0].name
|
||||
value: work
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].volumeMounts[0].mountPath
|
||||
value: /home/runner/_work
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].volumeMounts[1].name
|
||||
value: dind-sock
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].volumeMounts[1].mountPath
|
||||
value: /var/run
|
||||
|
||||
- contains:
|
||||
path: spec.template.spec.volumes
|
||||
content:
|
||||
name: work
|
||||
emptyDir: {}
|
||||
- contains:
|
||||
path: spec.template.spec.volumes
|
||||
content:
|
||||
name: dind-sock
|
||||
emptyDir: {}
|
||||
- contains:
|
||||
path: spec.template.spec.volumes
|
||||
content:
|
||||
name: dind-externals
|
||||
emptyDir: {}
|
||||
|
||||
- it: should omit init-dind-externals and dind-externals volume when copyExternals is false
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
runner:
|
||||
mode: "dind"
|
||||
dind:
|
||||
copyExternals: false
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[0].name
|
||||
value: dind
|
||||
- notExists:
|
||||
path: spec.template.spec.initContainers[1]
|
||||
- notExists:
|
||||
path: spec.template.spec.volumes[2]
|
||||
- notExists:
|
||||
path: spec.template.spec.initContainers[0].volumeMounts[2]
|
||||
|
||||
- it: should allow overriding dind container name, image, and securityContext
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
runner:
|
||||
mode: "dind"
|
||||
dind:
|
||||
container:
|
||||
name: "dockerd-custom"
|
||||
image: "docker:27.3-dind"
|
||||
securityContext:
|
||||
privileged: false
|
||||
runAsUser: 1000
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].name
|
||||
value: dockerd-custom
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].image
|
||||
value: docker:27.3-dind
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].securityContext.privileged
|
||||
value: false
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].securityContext.runAsUser
|
||||
value: 1000
|
||||
|
||||
- it: should respect dockerSock override in DOCKER_HOST, mountPath, and dind args
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
runner:
|
||||
mode: "dind"
|
||||
dind:
|
||||
dockerSock: "unix:///var/run/custom/docker.sock"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].env[0].name
|
||||
value: DOCKER_HOST
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].env[0].value
|
||||
value: unix:///var/run/custom/docker.sock
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].volumeMounts[1].mountPath
|
||||
value: /var/run/custom
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].volumeMounts[1].mountPath
|
||||
value: /var/run/custom
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].args[1]
|
||||
value: --host=unix:///var/run/custom/docker.sock
|
||||
|
||||
- it: should respect waitForDockerInSeconds override
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
runner:
|
||||
mode: "dind"
|
||||
dind:
|
||||
waitForDockerInSeconds: 30
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].env[1].name
|
||||
value: RUNNER_WAIT_FOR_DOCKER_IN_SECONDS
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].env[1].value
|
||||
value: "30"
|
||||
|
||||
- it: should include extraInitContainers in dind mode
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
runner:
|
||||
mode: "dind"
|
||||
pod:
|
||||
spec:
|
||||
initContainers:
|
||||
- name: "extra-init-1"
|
||||
image: "busybox:1.36"
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- "sh"
|
||||
- "-c"
|
||||
args:
|
||||
- "echo extra-init && env | grep FOO"
|
||||
env:
|
||||
- name: FOO
|
||||
value: BAR
|
||||
resources:
|
||||
requests:
|
||||
cpu: 10m
|
||||
memory: 16Mi
|
||||
limits:
|
||||
cpu: 100m
|
||||
memory: 64Mi
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
volumeMounts:
|
||||
- name: work
|
||||
mountPath: /work
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[0].name
|
||||
value: init-dind-externals
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].name
|
||||
value: extra-init-1
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].image
|
||||
value: busybox:1.36
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].imagePullPolicy
|
||||
value: IfNotPresent
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].command[0]
|
||||
value: sh
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].args[0]
|
||||
value: echo extra-init && env | grep FOO
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].env[0].name
|
||||
value: FOO
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].env[0].value
|
||||
value: BAR
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].resources.requests.cpu
|
||||
value: 10m
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].resources.requests.memory
|
||||
value: 16Mi
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].resources.limits.cpu
|
||||
value: 100m
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].resources.limits.memory
|
||||
value: 64Mi
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].securityContext.runAsNonRoot
|
||||
value: true
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].securityContext.runAsUser
|
||||
value: 1000
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].volumeMounts[0].name
|
||||
value: work
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[1].volumeMounts[0].mountPath
|
||||
value: /work
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[2].name
|
||||
value: dind
|
||||
|
||||
- it: should include extraVolumes in dind mode
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
runner:
|
||||
mode: "dind"
|
||||
pod:
|
||||
spec:
|
||||
volumes:
|
||||
- name: "cache"
|
||||
emptyDir: {}
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- contains:
|
||||
path: spec.template.spec.volumes
|
||||
content:
|
||||
name: cache
|
||||
emptyDir: {}
|
||||
@@ -0,0 +1,84 @@
|
||||
suite: "AutoscalingRunnerSet extraContainers"
|
||||
templates:
|
||||
- autoscalingrunnserset.yaml
|
||||
tests:
|
||||
- it: should append extraContainers after the runner container
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
runner:
|
||||
mode: "kubernetes"
|
||||
pod:
|
||||
spec:
|
||||
containers:
|
||||
- name: "sidecar"
|
||||
image: "busybox:1.36"
|
||||
command: ["sh", "-c", "sleep 3600"]
|
||||
resources:
|
||||
limits:
|
||||
cpu: "250m"
|
||||
memory: "64Mi"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].name
|
||||
value: runner
|
||||
- equal:
|
||||
path: spec.template.spec.containers[1].name
|
||||
value: sidecar
|
||||
- equal:
|
||||
path: spec.template.spec.containers[1].image
|
||||
value: busybox:1.36
|
||||
- equal:
|
||||
path: spec.template.spec.containers[1].resources.limits.cpu
|
||||
value: 250m
|
||||
- equal:
|
||||
path: spec.template.spec.containers[1].resources.limits.memory
|
||||
value: 64Mi
|
||||
|
||||
- it: should fail when runner.pod.spec.containers is not a list
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
runner:
|
||||
mode: "kubernetes"
|
||||
pod:
|
||||
spec:
|
||||
containers:
|
||||
name: "not-a-list"
|
||||
image: "busybox:1.36"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: ".Values.runner.pod.spec.containers must be a list of container specifications"
|
||||
|
||||
- it: should fail when a container is named runner
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
runner:
|
||||
mode: "kubernetes"
|
||||
pod:
|
||||
spec:
|
||||
containers:
|
||||
- name: "runner"
|
||||
image: "busybox:1.36"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: ".Values.runner.pod.spec.containers[].name must not be 'runner' (reserved)"
|
||||
@@ -0,0 +1,84 @@
|
||||
suite: "AutoscalingRunnerSet initContainers"
|
||||
templates:
|
||||
- autoscalingrunnserset.yaml
|
||||
tests:
|
||||
- it: should render initContainers when runner.pod.spec.initContainers configured in non-dind mode
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
runner:
|
||||
pod:
|
||||
spec:
|
||||
initContainers:
|
||||
- name: "extra-init-1"
|
||||
image: "busybox:1.36"
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- "sh"
|
||||
- "-c"
|
||||
args:
|
||||
- "echo non-dind extra init"
|
||||
env:
|
||||
- name: FOO
|
||||
value: BAR
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
resources:
|
||||
requests:
|
||||
cpu: 10m
|
||||
memory: 16Mi
|
||||
limits:
|
||||
cpu: 100m
|
||||
memory: 64Mi
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[0].name
|
||||
value: extra-init-1
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[0].image
|
||||
value: busybox:1.36
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[0].imagePullPolicy
|
||||
value: IfNotPresent
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[0].command[0]
|
||||
value: sh
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[0].args[0]
|
||||
value: echo non-dind extra init
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[0].env[0].name
|
||||
value: FOO
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[0].env[0].value
|
||||
value: BAR
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[0].securityContext.runAsNonRoot
|
||||
value: true
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[0].securityContext.runAsUser
|
||||
value: 1000
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[0].resources.requests.cpu
|
||||
value: 10m
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[0].resources.requests.memory
|
||||
value: 16Mi
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[0].resources.limits.cpu
|
||||
value: 100m
|
||||
- equal:
|
||||
path: spec.template.spec.initContainers[0].resources.limits.memory
|
||||
value: 64Mi
|
||||
- notExists:
|
||||
path: spec.template.spec.initContainers[1]
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].name
|
||||
value: runner
|
||||
@@ -0,0 +1,61 @@
|
||||
suite: "GitHub Server TLS"
|
||||
templates:
|
||||
- autoscalingrunnserset.yaml
|
||||
- manager_role.yaml
|
||||
tests:
|
||||
- it: should render spec.githubServerTLS and allow manager role to read the configmap
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
githubServerTLS:
|
||||
certificateFrom:
|
||||
configMapKeyRef:
|
||||
name: "my-ca-config"
|
||||
key: "ca.crt"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.githubServerTLS.certificateFrom.configMapKeyRef.name
|
||||
value: my-ca-config
|
||||
template: autoscalingrunnserset.yaml
|
||||
- equal:
|
||||
path: spec.githubServerTLS.certificateFrom.configMapKeyRef.key
|
||||
value: ca.crt
|
||||
template: autoscalingrunnserset.yaml
|
||||
- contains:
|
||||
path: rules
|
||||
content:
|
||||
apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- configmaps
|
||||
verbs:
|
||||
- get
|
||||
template: manager_role.yaml
|
||||
|
||||
- it: should not include the manager role configmap rule when githubServerTLS is not configured
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- notContains:
|
||||
path: rules
|
||||
content:
|
||||
apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- configmaps
|
||||
verbs:
|
||||
- get
|
||||
template: manager_role.yaml
|
||||
@@ -0,0 +1,101 @@
|
||||
suite: "AutoscalingRunnerSet kubernetes mode hook extension wiring"
|
||||
templates:
|
||||
- autoscalingrunnserset.yaml
|
||||
tests:
|
||||
- it: should mount hook extension ConfigMap when inline extension.yaml is set
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
runner:
|
||||
mode: "kubernetes"
|
||||
kubernetesMode:
|
||||
hookPath: "/home/runner/k8s/index.js"
|
||||
extension:
|
||||
metadata:
|
||||
name: "my-hook-extension"
|
||||
namespace: "test-namespace"
|
||||
yaml: "foo: bar"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- contains:
|
||||
path: spec.template.spec.containers[0].env
|
||||
content:
|
||||
name: ACTIONS_RUNNER_CONTAINER_HOOK_TEMPLATE
|
||||
value: /home/runner/k8s/hook-template.yaml
|
||||
- contains:
|
||||
path: spec.template.spec.volumes
|
||||
content:
|
||||
name: hook-extension
|
||||
configMap:
|
||||
name: my-hook-extension
|
||||
- contains:
|
||||
path: spec.template.spec.containers[0].volumeMounts
|
||||
content:
|
||||
name: hook-extension
|
||||
mountPath: /home/runner/k8s/hook-template.yaml
|
||||
subPath: extension
|
||||
readOnly: true
|
||||
|
||||
- it: should mount hook extension ConfigMap when extensionRef is set
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
runner:
|
||||
mode: "kubernetes"
|
||||
kubernetesMode:
|
||||
extensionRef: "existing-hook-extension"
|
||||
hookPath: "/home/runner/k8s/index.js"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- contains:
|
||||
path: spec.template.spec.containers[0].env
|
||||
content:
|
||||
name: ACTIONS_RUNNER_CONTAINER_HOOK_TEMPLATE
|
||||
value: /home/runner/k8s/hook-template.yaml
|
||||
- contains:
|
||||
path: spec.template.spec.volumes
|
||||
content:
|
||||
name: hook-extension
|
||||
configMap:
|
||||
name: existing-hook-extension
|
||||
- contains:
|
||||
path: spec.template.spec.containers[0].volumeMounts
|
||||
content:
|
||||
name: hook-extension
|
||||
mountPath: /home/runner/k8s/hook-template.yaml
|
||||
subPath: extension
|
||||
readOnly: true
|
||||
|
||||
- it: should allow using extensionRef without defining inline extension
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
runner:
|
||||
mode: "kubernetes"
|
||||
kubernetesMode:
|
||||
extensionRef: "existing-hook-extension"
|
||||
extension: "not-a-map"
|
||||
hookPath: "/home/runner/k8s/index.js"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- contains:
|
||||
path: spec.template.spec.volumes
|
||||
content:
|
||||
name: hook-extension
|
||||
configMap:
|
||||
name: existing-hook-extension
|
||||
@@ -0,0 +1,133 @@
|
||||
suite: "AutoscalingRunnerSet kubernetes mode podspec"
|
||||
templates:
|
||||
- autoscalingrunnserset.yaml
|
||||
tests:
|
||||
- it: should render the default kubernetes pod spec (runner container, ephemeral work volume)
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
runner:
|
||||
mode: "kubernetes"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- notExists:
|
||||
path: spec.template.spec.initContainers
|
||||
- equal:
|
||||
path: spec.template.spec.serviceAccountName
|
||||
value: test-name-kube-mode
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].name
|
||||
value: runner
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].image
|
||||
value: ghcr.io/actions/actions-runner:latest
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].env[0].name
|
||||
value: ACTIONS_RUNNER_CONTAINER_HOOKS
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].env[0].value
|
||||
value: /home/runner/k8s/index.js
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].env[1].name
|
||||
value: ACTIONS_RUNNER_POD_NAME
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].env[1].valueFrom.fieldRef.fieldPath
|
||||
value: metadata.name
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].env[2].name
|
||||
value: ACTIONS_RUNNER_REQUIRE_JOB_CONTAINER
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].env[2].value
|
||||
value: "true"
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].volumeMounts[0].name
|
||||
value: work
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].volumeMounts[0].mountPath
|
||||
value: /home/runner/_work
|
||||
- notExists:
|
||||
path: spec.template.spec.containers[0].volumeMounts[1]
|
||||
- equal:
|
||||
path: spec.template.spec.volumes[0].name
|
||||
value: work
|
||||
- equal:
|
||||
path: spec.template.spec.volumes[0].ephemeral.volumeClaimTemplate.spec.accessModes[0]
|
||||
value: ReadWriteOnce
|
||||
- equal:
|
||||
path: spec.template.spec.volumes[0].ephemeral.volumeClaimTemplate.spec.storageClassName
|
||||
value: local-path
|
||||
- equal:
|
||||
path: spec.template.spec.volumes[0].ephemeral.volumeClaimTemplate.spec.resources.requests.storage
|
||||
value: 1Gi
|
||||
|
||||
- it: should allow overriding kubernetes mode hookPath, requireJobContainer, and workVolumeClaim
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
runner:
|
||||
mode: "kubernetes"
|
||||
kubernetesMode:
|
||||
hookPath: "/home/runner/custom/k8s/index.js"
|
||||
requireJobContainer: false
|
||||
workVolumeClaim:
|
||||
storageClassName: "fast-ssd"
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].env[0].value
|
||||
value: /home/runner/custom/k8s/index.js
|
||||
- equal:
|
||||
path: spec.template.spec.containers[0].env[2].value
|
||||
value: "false"
|
||||
- equal:
|
||||
path: spec.template.spec.volumes[0].ephemeral.volumeClaimTemplate.spec.storageClassName
|
||||
value: fast-ssd
|
||||
- equal:
|
||||
path: spec.template.spec.volumes[0].ephemeral.volumeClaimTemplate.spec.resources.requests.storage
|
||||
value: 10Gi
|
||||
|
||||
- it: should include extraVolumes in kubernetes mode
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
runner:
|
||||
mode: "kubernetes"
|
||||
pod:
|
||||
spec:
|
||||
volumes:
|
||||
- name: cache
|
||||
emptyDir: {}
|
||||
- name: custom-config
|
||||
configMap:
|
||||
name: example-config
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- contains:
|
||||
path: spec.template.spec.volumes
|
||||
content:
|
||||
name: cache
|
||||
emptyDir: {}
|
||||
- contains:
|
||||
path: spec.template.spec.volumes
|
||||
content:
|
||||
name: custom-config
|
||||
configMap:
|
||||
name: example-config
|
||||
@@ -0,0 +1,293 @@
|
||||
suite: "Test AutoscalingRunnerSet Labels"
|
||||
templates:
|
||||
- autoscalingrunnserset.yaml
|
||||
tests:
|
||||
- it: should render base labels
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
chart:
|
||||
appVersion: "0.14.0"
|
||||
asserts:
|
||||
- equal:
|
||||
path: metadata.labels["helm.sh/chart"]
|
||||
value: "gha-rs-0.14.0"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/name"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/instance"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/component"]
|
||||
value: "autoscaling-runner-set"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/managed-by"]
|
||||
value: "Helm"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/part-of"]
|
||||
value: "gha-rs"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/version"]
|
||||
value: "0.14.0"
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/scale-set-name"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/scale-set-namespace"]
|
||||
value: "test-namespace"
|
||||
|
||||
- it: should include user-defined labels
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
resource:
|
||||
autoscalingRunnerSet:
|
||||
metadata:
|
||||
labels:
|
||||
team: "backend"
|
||||
environment: "production"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: metadata.labels["team"]
|
||||
value: "backend"
|
||||
- equal:
|
||||
path: metadata.labels["environment"]
|
||||
value: "production"
|
||||
- equal:
|
||||
path: metadata.labels["helm.sh/chart"]
|
||||
value: "gha-rs-0.14.0"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/name"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/instance"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/component"]
|
||||
value: "autoscaling-runner-set"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/managed-by"]
|
||||
value: "Helm"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/part-of"]
|
||||
value: "gha-rs"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/version"]
|
||||
value: "0.14.0"
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/scale-set-name"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/scale-set-namespace"]
|
||||
value: "test-namespace"
|
||||
|
||||
- it: should include global labels
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
resource:
|
||||
all:
|
||||
metadata:
|
||||
labels:
|
||||
global-team: "platform"
|
||||
owner: "devops"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: metadata.labels["global-team"]
|
||||
value: "platform"
|
||||
- equal:
|
||||
path: metadata.labels["owner"]
|
||||
value: "devops"
|
||||
- equal:
|
||||
path: metadata.labels["helm.sh/chart"]
|
||||
value: "gha-rs-0.14.0"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/name"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/instance"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/component"]
|
||||
value: "autoscaling-runner-set"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/managed-by"]
|
||||
value: "Helm"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/part-of"]
|
||||
value: "gha-rs"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/version"]
|
||||
value: "0.14.0"
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/scale-set-name"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/scale-set-namespace"]
|
||||
value: "test-namespace"
|
||||
|
||||
- it: should merge both user and global labels
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
resource:
|
||||
autoscalingRunnerSet:
|
||||
metadata:
|
||||
labels:
|
||||
team: "backend"
|
||||
environment: "staging"
|
||||
all:
|
||||
metadata:
|
||||
labels:
|
||||
global-team: "platform"
|
||||
environment: "production"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: metadata.labels["team"]
|
||||
value: "backend"
|
||||
- equal:
|
||||
path: metadata.labels["global-team"]
|
||||
value: "platform"
|
||||
- equal:
|
||||
path: metadata.labels["environment"]
|
||||
value: "staging"
|
||||
- equal:
|
||||
path: metadata.labels["helm.sh/chart"]
|
||||
value: "gha-rs-0.14.0"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/name"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/instance"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/component"]
|
||||
value: "autoscaling-runner-set"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/managed-by"]
|
||||
value: "Helm"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/part-of"]
|
||||
value: "gha-rs"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/version"]
|
||||
value: "0.14.0"
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/scale-set-name"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/scale-set-namespace"]
|
||||
value: "test-namespace"
|
||||
|
||||
- it: should allow user labels to override global labels
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
resource:
|
||||
autoscalingRunnerSet:
|
||||
metadata:
|
||||
labels:
|
||||
tier: "frontend"
|
||||
cost-center: "100"
|
||||
all:
|
||||
metadata:
|
||||
labels:
|
||||
tier: "backend"
|
||||
environment: "staging"
|
||||
cost-center: "200"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: metadata.labels["tier"]
|
||||
value: "frontend"
|
||||
- equal:
|
||||
path: metadata.labels["cost-center"]
|
||||
value: "100"
|
||||
- equal:
|
||||
path: metadata.labels["environment"]
|
||||
value: "staging"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/name"]
|
||||
value: "test-name"
|
||||
|
||||
- it: should preserve actions.github.com custom labels from user config
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
resource:
|
||||
autoscalingRunnerSet:
|
||||
metadata:
|
||||
labels:
|
||||
team: "backend"
|
||||
actions.github.com/custom-label: "user-value"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: metadata.labels["team"]
|
||||
value: "backend"
|
||||
- notExists:
|
||||
path: metadata.labels["actions.github.com/custom-label"]
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/scale-set-name"]
|
||||
value: "test-name"
|
||||
|
||||
- it: should preserve actions.github.com custom labels from global config
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
resource:
|
||||
all:
|
||||
metadata:
|
||||
labels:
|
||||
owner: "devops"
|
||||
actions.github.com/global-custom: "global-value"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: metadata.labels["owner"]
|
||||
value: "devops"
|
||||
- notExists:
|
||||
path: metadata.labels["actions.github.com/global-custom"]
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/scale-set-name"]
|
||||
value: "test-name"
|
||||
@@ -0,0 +1,55 @@
|
||||
suite: "Test AutoscalingRunnerSet Listener Metrics"
|
||||
templates:
|
||||
- autoscalingrunnserset.yaml
|
||||
tests:
|
||||
- it: should not render listenerMetrics when not configured
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- notExists:
|
||||
path: spec.listenerMetrics
|
||||
|
||||
- it: should render listenerMetrics when configured
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
listenerMetrics:
|
||||
counters:
|
||||
gha_started_jobs_total:
|
||||
labels:
|
||||
- repository
|
||||
- organization
|
||||
histograms:
|
||||
gha_job_startup_duration_seconds:
|
||||
buckets:
|
||||
- 0.1
|
||||
- 1
|
||||
- 2.5
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- exists:
|
||||
path: spec.listenerMetrics
|
||||
- equal:
|
||||
path: spec.listenerMetrics.counters.gha_started_jobs_total.labels[0]
|
||||
value: repository
|
||||
- equal:
|
||||
path: spec.listenerMetrics.counters.gha_started_jobs_total.labels[1]
|
||||
value: organization
|
||||
- contains:
|
||||
path: spec.listenerMetrics.histograms.gha_job_startup_duration_seconds.buckets
|
||||
content: 0.1
|
||||
- contains:
|
||||
path: spec.listenerMetrics.histograms.gha_job_startup_duration_seconds.buckets
|
||||
content: 2.5
|
||||
@@ -0,0 +1,46 @@
|
||||
suite: "AutoscalingRunnerSet listenerPodTemplate"
|
||||
templates:
|
||||
- autoscalingrunnserset.yaml
|
||||
tests:
|
||||
- it: should render listenerTemplate from listenerPodTemplate
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
listenerPodTemplate:
|
||||
spec:
|
||||
containers:
|
||||
- name: listener
|
||||
image: "ghcr.io/actions/actions-runner-controller/actionsmetricsserver:latest"
|
||||
securityContext:
|
||||
runAsUser: 1000
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.listenerTemplate.spec.containers[0].name
|
||||
value: listener
|
||||
- equal:
|
||||
path: spec.listenerTemplate.spec.containers[0].securityContext.runAsUser
|
||||
value: 1000
|
||||
|
||||
- it: should default listenerTemplate containers when not specified
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
listenerPodTemplate:
|
||||
spec:
|
||||
restartPolicy: Always
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.listenerTemplate.spec.containers[0].name
|
||||
value: listener
|
||||
@@ -0,0 +1,71 @@
|
||||
suite: "Test AutoscalingRunnerSet MinMax Runners"
|
||||
templates:
|
||||
- autoscalingrunnserset.yaml
|
||||
tests:
|
||||
- it: should set minRunners and maxRunners correctly
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
scaleset.minRunners: 2
|
||||
scaleset.maxRunners: 5
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.minRunners
|
||||
value: 2
|
||||
- equal:
|
||||
path: spec.maxRunners
|
||||
value: 5
|
||||
- it: should fail when minRunners is greater than maxRunners
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
scaleset.minRunners: 6
|
||||
scaleset.maxRunners: 5
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- failedTemplate: {}
|
||||
- it: should work when minRunners equals maxRunners
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
scaleset.minRunners: 5
|
||||
scaleset.maxRunners: 5
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.minRunners
|
||||
value: 5
|
||||
- equal:
|
||||
path: spec.maxRunners
|
||||
value: 5
|
||||
- it: should not set minRunners and maxRunners when not provided
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- notExists:
|
||||
path: spec.minRunners
|
||||
- notExists:
|
||||
path: spec.maxRunners
|
||||
@@ -0,0 +1,290 @@
|
||||
suite: "Test AutoscalingRunnerSet Proxy Configuration"
|
||||
templates:
|
||||
- autoscalingrunnserset.yaml
|
||||
tests:
|
||||
- it: should not render proxy section when not configured
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- notExists:
|
||||
path: spec.proxy
|
||||
|
||||
- it: should render http proxy configuration
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
proxy:
|
||||
http:
|
||||
url: "http://proxy.example.com:3128"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.proxy.http.url
|
||||
value: "http://proxy.example.com:3128"
|
||||
- notExists:
|
||||
path: spec.proxy.https
|
||||
|
||||
- it: should render https proxy configuration
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
proxy:
|
||||
https:
|
||||
url: "https://secure-proxy.example.com:3128"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.proxy.https.url
|
||||
value: "https://secure-proxy.example.com:3128"
|
||||
- notExists:
|
||||
path: spec.proxy.http
|
||||
|
||||
- it: should render both http and https proxy configuration
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
proxy:
|
||||
http:
|
||||
url: "http://proxy.example.com:3128"
|
||||
https:
|
||||
url: "https://secure-proxy.example.com:3128"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.proxy.http.url
|
||||
value: "http://proxy.example.com:3128"
|
||||
- equal:
|
||||
path: spec.proxy.https.url
|
||||
value: "https://secure-proxy.example.com:3128"
|
||||
|
||||
- it: should render http proxy with credential secret reference
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
proxy:
|
||||
http:
|
||||
url: "http://proxy.example.com:3128"
|
||||
credentialSecretRef: "proxy-credentials"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.proxy.http.url
|
||||
value: "http://proxy.example.com:3128"
|
||||
- equal:
|
||||
path: spec.proxy.http.credentialSecretRef
|
||||
value: "proxy-credentials"
|
||||
|
||||
- it: should render https proxy with credential secret reference
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
proxy:
|
||||
https:
|
||||
url: "https://secure-proxy.example.com:3128"
|
||||
credentialSecretRef: "secure-proxy-creds"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.proxy.https.url
|
||||
value: "https://secure-proxy.example.com:3128"
|
||||
- equal:
|
||||
path: spec.proxy.https.credentialSecretRef
|
||||
value: "secure-proxy-creds"
|
||||
|
||||
- it: should render proxy with noProxy list
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
proxy:
|
||||
http:
|
||||
url: "http://proxy.example.com:3128"
|
||||
noProxy:
|
||||
- "localhost"
|
||||
- "127.0.0.1"
|
||||
- ".example.local"
|
||||
- "10.0.0.0/8"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.proxy.http.url
|
||||
value: "http://proxy.example.com:3128"
|
||||
- contains:
|
||||
path: spec.proxy.noProxy
|
||||
content: "localhost"
|
||||
- contains:
|
||||
path: spec.proxy.noProxy
|
||||
content: "127.0.0.1"
|
||||
- contains:
|
||||
path: spec.proxy.noProxy
|
||||
content: ".example.local"
|
||||
- contains:
|
||||
path: spec.proxy.noProxy
|
||||
content: "10.0.0.0/8"
|
||||
|
||||
- it: should render complete proxy configuration with all options
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
proxy:
|
||||
http:
|
||||
url: "http://proxy.example.com:3128"
|
||||
credentialSecretRef: "proxy-credentials"
|
||||
https:
|
||||
url: "https://secure-proxy.example.com:3128"
|
||||
credentialSecretRef: "secure-proxy-creds"
|
||||
noProxy:
|
||||
- "localhost"
|
||||
- "127.0.0.1"
|
||||
- ".local"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.proxy.http.url
|
||||
value: "http://proxy.example.com:3128"
|
||||
- equal:
|
||||
path: spec.proxy.http.credentialSecretRef
|
||||
value: "proxy-credentials"
|
||||
- equal:
|
||||
path: spec.proxy.https.url
|
||||
value: "https://secure-proxy.example.com:3128"
|
||||
- equal:
|
||||
path: spec.proxy.https.credentialSecretRef
|
||||
value: "secure-proxy-creds"
|
||||
- contains:
|
||||
path: spec.proxy.noProxy
|
||||
content: "localhost"
|
||||
- contains:
|
||||
path: spec.proxy.noProxy
|
||||
content: "127.0.0.1"
|
||||
- contains:
|
||||
path: spec.proxy.noProxy
|
||||
content: ".local"
|
||||
|
||||
- it: should render proxy configuration with empty noProxy list
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
proxy:
|
||||
http:
|
||||
url: "http://proxy.example.com:3128"
|
||||
noProxy: []
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.proxy.http.url
|
||||
value: "http://proxy.example.com:3128"
|
||||
- notExists:
|
||||
path: spec.proxy.noProxy
|
||||
|
||||
- it: should not render proxy when configured as empty object
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
proxy: {}
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- notExists:
|
||||
path: spec.proxy
|
||||
|
||||
- it: should render proxy with only http without credentials
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
proxy:
|
||||
http:
|
||||
url: "http://unauthenticated-proxy.example.com:8080"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.proxy.http.url
|
||||
value: "http://unauthenticated-proxy.example.com:8080"
|
||||
- notExists:
|
||||
path: spec.proxy.http.credentialSecretRef
|
||||
- notExists:
|
||||
path: spec.proxy.https
|
||||
|
||||
- it: should render proxy with https and noProxy without http
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
proxy:
|
||||
https:
|
||||
url: "https://secure-proxy.example.com:3128"
|
||||
noProxy:
|
||||
- "internal.example.com"
|
||||
- "*.local"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.proxy.https.url
|
||||
value: "https://secure-proxy.example.com:3128"
|
||||
- notExists:
|
||||
path: spec.proxy.http
|
||||
- contains:
|
||||
path: spec.proxy.noProxy
|
||||
content: "internal.example.com"
|
||||
- contains:
|
||||
path: spec.proxy.noProxy
|
||||
content: "*.local"
|
||||
@@ -0,0 +1,87 @@
|
||||
suite: "AutoscalingRunnerSet runner pod metadata"
|
||||
templates:
|
||||
- autoscalingrunnserset.yaml
|
||||
tests:
|
||||
- it: should render runner.pod.metadata labels and annotations merged with common/global metadata
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
resource:
|
||||
all:
|
||||
metadata:
|
||||
labels:
|
||||
team: "platform"
|
||||
annotations:
|
||||
global-annotation: "1"
|
||||
runner:
|
||||
pod:
|
||||
metadata:
|
||||
labels:
|
||||
purpose: "ci"
|
||||
annotations:
|
||||
pod-annotation: "2"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
chart:
|
||||
appVersion: "0.14.0"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.template.metadata.labels["purpose"]
|
||||
value: "ci"
|
||||
- equal:
|
||||
path: spec.template.metadata.labels["team"]
|
||||
value: "platform"
|
||||
- equal:
|
||||
path: spec.template.metadata.labels["helm.sh/chart"]
|
||||
value: "gha-rs-0.14.0"
|
||||
- equal:
|
||||
path: spec.template.metadata.labels["app.kubernetes.io/name"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: spec.template.metadata.labels["app.kubernetes.io/managed-by"]
|
||||
value: "Helm"
|
||||
- equal:
|
||||
path: spec.template.metadata.labels["actions.github.com/scale-set-name"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: spec.template.metadata.annotations["global-annotation"]
|
||||
value: "1"
|
||||
- equal:
|
||||
path: spec.template.metadata.annotations["pod-annotation"]
|
||||
value: "2"
|
||||
|
||||
- it: should drop reserved actions.github.com/* keys from runner.pod.metadata
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
runner:
|
||||
pod:
|
||||
metadata:
|
||||
labels:
|
||||
actions.github.com/scale-set-name: "should-not-override"
|
||||
ok: "yes"
|
||||
annotations:
|
||||
actions.github.com/some-annotation: "should-not-appear"
|
||||
ok-annotation: "yes"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.template.metadata.labels["actions.github.com/scale-set-name"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: spec.template.metadata.labels["ok"]
|
||||
value: "yes"
|
||||
- notExists:
|
||||
path: spec.template.metadata.annotations["actions.github.com/some-annotation"]
|
||||
- equal:
|
||||
path: spec.template.metadata.annotations["ok-annotation"]
|
||||
value: "yes"
|
||||
@@ -0,0 +1,45 @@
|
||||
suite: autoscaling runner set runner pod spec initContainers validation
|
||||
|
||||
templates:
|
||||
- templates/autoscalingrunnserset.yaml
|
||||
|
||||
tests:
|
||||
- it: should fail when runner.pod.spec.initContainers is not a list
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
runner:
|
||||
mode: "kubernetes"
|
||||
pod:
|
||||
spec:
|
||||
initContainers:
|
||||
name: "not-a-list"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: ".Values.runner.pod.spec.initContainers must be a list of container specifications"
|
||||
|
||||
- it: should fail when initContainers entry has no name
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
runner:
|
||||
mode: "kubernetes"
|
||||
pod:
|
||||
spec:
|
||||
initContainers:
|
||||
- image: "busybox:1.36"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: ".Values.runner.pod.spec.initContainers[].name is required"
|
||||
@@ -0,0 +1,45 @@
|
||||
suite: AutoscalingRunnerSet runner pod spec passthrough fields
|
||||
|
||||
templates:
|
||||
- templates/autoscalingrunnserset.yaml
|
||||
|
||||
tests:
|
||||
- it: should apply additional runner.pod.spec fields to the runner pod spec
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
runner:
|
||||
mode: "kubernetes"
|
||||
pod:
|
||||
spec:
|
||||
nodeSelector:
|
||||
disktype: ssd
|
||||
tolerations:
|
||||
- key: "dedicated"
|
||||
operator: "Equal"
|
||||
value: "ci"
|
||||
effect: "NoSchedule"
|
||||
priorityClassName: "runner-high"
|
||||
terminationGracePeriodSeconds: 42
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.template.spec.nodeSelector.disktype
|
||||
value: ssd
|
||||
- equal:
|
||||
path: spec.template.spec.tolerations[0].key
|
||||
value: dedicated
|
||||
- equal:
|
||||
path: spec.template.spec.tolerations[0].value
|
||||
value: ci
|
||||
- equal:
|
||||
path: spec.template.spec.priorityClassName
|
||||
value: runner-high
|
||||
- equal:
|
||||
path: spec.template.spec.terminationGracePeriodSeconds
|
||||
value: 42
|
||||
@@ -0,0 +1,25 @@
|
||||
suite: autoscaling runner set runner pod spec volumes validation
|
||||
|
||||
templates:
|
||||
- templates/autoscalingrunnserset.yaml
|
||||
|
||||
tests:
|
||||
- it: should fail when runner.pod.spec.volumes is not a list
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
runner:
|
||||
mode: "kubernetes"
|
||||
pod:
|
||||
spec:
|
||||
volumes:
|
||||
name: "not-a-list"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: ".Values.runner.pod.spec.volumes must be a list of volume specifications"
|
||||
@@ -0,0 +1,110 @@
|
||||
suite: "Test AutoscalingRunnerSet Vault Config"
|
||||
templates:
|
||||
- autoscalingrunnserset.yaml
|
||||
tests:
|
||||
- it: should not render vaultConfig when secretResolution.type is kubernetes
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
secretResolution:
|
||||
type: kubernetes
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- notExists:
|
||||
path: spec.vaultConfig
|
||||
|
||||
- it: should render azureKeyVault vaultConfig when configured
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
secretResolution:
|
||||
type: azureKeyVault
|
||||
azureKeyVault:
|
||||
url: "https://myvault.vault.azure.net"
|
||||
tenantId: "tenant-123"
|
||||
clientId: "client-456"
|
||||
certificatePath: "/etc/certs/akv.pem"
|
||||
secretKey: "secret-key-name"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.vaultConfig.type
|
||||
value: azureKeyVault
|
||||
- equal:
|
||||
path: spec.vaultConfig.azureKeyVault.url
|
||||
value: "https://myvault.vault.azure.net"
|
||||
- equal:
|
||||
path: spec.vaultConfig.azureKeyVault.tenantId
|
||||
value: "tenant-123"
|
||||
- equal:
|
||||
path: spec.vaultConfig.azureKeyVault.clientId
|
||||
value: "client-456"
|
||||
- equal:
|
||||
path: spec.vaultConfig.azureKeyVault.certificatePath
|
||||
value: "/etc/certs/akv.pem"
|
||||
- equal:
|
||||
path: spec.vaultConfig.azureKeyVault.secretKey
|
||||
value: "secret-key-name"
|
||||
|
||||
- it: should render vaultConfig proxy when configured
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
secretResolution:
|
||||
type: azureKeyVault
|
||||
proxy:
|
||||
http:
|
||||
url: "http://proxy.example.com:3128"
|
||||
credentialSecretRef: "proxy-credentials"
|
||||
noProxy:
|
||||
- "localhost"
|
||||
azureKeyVault:
|
||||
url: "https://myvault.vault.azure.net"
|
||||
tenantId: "tenant-123"
|
||||
clientId: "client-456"
|
||||
certificatePath: "/etc/certs/akv.pem"
|
||||
secretKey: "secret-key-name"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.vaultConfig.proxy.http.url
|
||||
value: "http://proxy.example.com:3128"
|
||||
- equal:
|
||||
path: spec.vaultConfig.proxy.http.credentialSecretRef
|
||||
value: "proxy-credentials"
|
||||
- contains:
|
||||
path: spec.vaultConfig.proxy.noProxy
|
||||
content: "localhost"
|
||||
- notExists:
|
||||
path: spec.proxy
|
||||
|
||||
- it: should fail for unsupported secretResolution.type
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
secretResolution:
|
||||
type: "hashicorpVault"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: "Unsupported keyVault type: hashicorpVault"
|
||||
@@ -0,0 +1,49 @@
|
||||
suite: "Test GitHub Secret Annotations"
|
||||
templates:
|
||||
- githubsecret.yaml
|
||||
tests:
|
||||
- it: should include global annotations
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
resource:
|
||||
all:
|
||||
metadata:
|
||||
annotations:
|
||||
a: "global"
|
||||
shared: "global"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: metadata.annotations.a
|
||||
value: "global"
|
||||
- equal:
|
||||
path: metadata.annotations.shared
|
||||
value: "global"
|
||||
|
||||
- it: should drop actions.github.com annotations from global config
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
resource:
|
||||
all:
|
||||
metadata:
|
||||
annotations:
|
||||
ok: "ok"
|
||||
actions.github.com/values-hash: "user-value"
|
||||
actions.github.com/cleanup-something: "should-not-render"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: metadata.annotations.ok
|
||||
value: "ok"
|
||||
- notExists:
|
||||
path: metadata.annotations["actions.github.com/values-hash"]
|
||||
- notExists:
|
||||
path: metadata.annotations["actions.github.com/cleanup-something"]
|
||||
@@ -0,0 +1,78 @@
|
||||
suite: "Test GitHub Secret Data"
|
||||
templates:
|
||||
- githubsecret.yaml
|
||||
tests:
|
||||
- it: should render PAT token when configured
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- exists:
|
||||
path: data.github_token
|
||||
- equal:
|
||||
path: data.github_token
|
||||
value: "Z2hfdG9rZW4xMjM0NQ=="
|
||||
- notExists:
|
||||
path: data.github_app_id
|
||||
- notExists:
|
||||
path: data.github_app_installation_id
|
||||
- notExists:
|
||||
path: data.github_app_private_key
|
||||
|
||||
- it: should render GitHub App keys when app is configured
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.app:
|
||||
clientId: "123"
|
||||
installationId: "456"
|
||||
privateKey: "mykey"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- notExists:
|
||||
path: data.github_token
|
||||
- equal:
|
||||
path: data.github_app_id
|
||||
value: "MTIz"
|
||||
- equal:
|
||||
path: data.github_app_installation_id
|
||||
value: "NDU2"
|
||||
- equal:
|
||||
path: data.github_app_private_key
|
||||
value: "bXlrZXk="
|
||||
|
||||
- it: should fail if app is configured without installationId
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.app:
|
||||
clientId: "123"
|
||||
privateKey: "mykey"
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: ".Values.auth.app.installationId is required when using GitHub App auth"
|
||||
|
||||
- it: should fail if app is configured without privateKey
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.app:
|
||||
clientId: "123"
|
||||
installationId: "456"
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: ".Values.auth.app.privateKey is required when using GitHub App auth"
|
||||
|
||||
- it: should fail if neither PAT token nor GitHub App is configured
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: ".Values.auth.githubToken is required when auth.secretName and auth.app.clientId are not set"
|
||||
@@ -0,0 +1,129 @@
|
||||
suite: "Test GitHub Secret Labels"
|
||||
templates:
|
||||
- githubsecret.yaml
|
||||
tests:
|
||||
- it: should render base labels
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
chart:
|
||||
appVersion: "0.14.0"
|
||||
asserts:
|
||||
- equal:
|
||||
path: metadata.labels["helm.sh/chart"]
|
||||
value: "gha-rs-0.14.0"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/name"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/instance"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/component"]
|
||||
value: "github-secret"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/managed-by"]
|
||||
value: "Helm"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/part-of"]
|
||||
value: "gha-rs"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/version"]
|
||||
value: "0.14.0"
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/scale-set-name"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/scale-set-namespace"]
|
||||
value: "test-namespace"
|
||||
|
||||
- it: should include global labels
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
resource:
|
||||
all:
|
||||
metadata:
|
||||
labels:
|
||||
global-team: "platform"
|
||||
owner: "devops"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: metadata.labels["global-team"]
|
||||
value: "platform"
|
||||
- equal:
|
||||
path: metadata.labels["owner"]
|
||||
value: "devops"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/component"]
|
||||
value: "github-secret"
|
||||
|
||||
- it: should drop actions.github.com custom labels from global config
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
resource:
|
||||
all:
|
||||
metadata:
|
||||
labels:
|
||||
owner: "devops"
|
||||
actions.github.com/global-custom: "global-value"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: metadata.labels["owner"]
|
||||
value: "devops"
|
||||
- notExists:
|
||||
path: metadata.labels["actions.github.com/global-custom"]
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/scale-set-name"]
|
||||
value: "test-name"
|
||||
|
||||
- it: should not allow global labels to override reserved labels
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
resource:
|
||||
all:
|
||||
metadata:
|
||||
labels:
|
||||
helm.sh/chart: "bad"
|
||||
app.kubernetes.io/name: "bad"
|
||||
app.kubernetes.io/instance: "bad"
|
||||
app.kubernetes.io/component: "bad"
|
||||
actions.github.com/scale-set-name: "bad"
|
||||
actions.github.com/scale-set-namespace: "bad"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: metadata.labels["helm.sh/chart"]
|
||||
value: "gha-rs-0.14.0"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/name"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/instance"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/component"]
|
||||
value: "github-secret"
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/scale-set-name"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/scale-set-namespace"]
|
||||
value: "test-namespace"
|
||||
@@ -0,0 +1,15 @@
|
||||
suite: "Test GitHub Secret pre-defined secret"
|
||||
templates:
|
||||
- githubsecret.yaml
|
||||
tests:
|
||||
- it: should not render githubsecret when auth.secretName is provided
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.secretName: "pre-defined-secret"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- hasDocuments:
|
||||
count: 0
|
||||
@@ -0,0 +1,89 @@
|
||||
suite: "Hook extension ConfigMap"
|
||||
templates:
|
||||
- hook_extension.yaml
|
||||
tests:
|
||||
- it: should render ConfigMap with data.extension from extension.yaml
|
||||
set:
|
||||
runner:
|
||||
mode: "kubernetes"
|
||||
kubernetesMode:
|
||||
extension:
|
||||
metadata:
|
||||
name: "my-hook-extension"
|
||||
namespace: "test-namespace"
|
||||
yaml: |
|
||||
foo: bar
|
||||
nested:
|
||||
a: 1
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "ignored-by-test" # overridden by extension.metadata.namespace above
|
||||
asserts:
|
||||
- equal:
|
||||
path: apiVersion
|
||||
value: v1
|
||||
- equal:
|
||||
path: kind
|
||||
value: ConfigMap
|
||||
- equal:
|
||||
path: metadata.name
|
||||
value: my-hook-extension
|
||||
- equal:
|
||||
path: metadata.namespace
|
||||
value: test-namespace
|
||||
- equal:
|
||||
path: data.extension
|
||||
value: |-
|
||||
foo: bar
|
||||
nested:
|
||||
a: 1
|
||||
|
||||
- it: should not render when extension.yaml is empty
|
||||
set:
|
||||
runner:
|
||||
mode: "kubernetes"
|
||||
kubernetesMode:
|
||||
extension:
|
||||
metadata:
|
||||
name: "my-hook-extension"
|
||||
namespace: "test-namespace"
|
||||
yaml: ""
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- hasDocuments:
|
||||
count: 0
|
||||
|
||||
- it: should not render when extensionRef is set
|
||||
set:
|
||||
runner:
|
||||
mode: "kubernetes"
|
||||
kubernetesMode:
|
||||
extensionRef: "existing-hook-extension"
|
||||
extension:
|
||||
metadata:
|
||||
name: "my-hook-extension"
|
||||
namespace: "test-namespace"
|
||||
yaml: |
|
||||
foo: bar
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- hasDocuments:
|
||||
count: 0
|
||||
|
||||
- it: should not require inline extension when extensionRef is set
|
||||
set:
|
||||
runner:
|
||||
mode: "kubernetes"
|
||||
kubernetesMode:
|
||||
extensionRef: "existing-hook-extension"
|
||||
extension: "not-a-map"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- hasDocuments:
|
||||
count: 0
|
||||
@@ -0,0 +1,182 @@
|
||||
suite: "Test Kubernetes Mode RoleBinding"
|
||||
templates:
|
||||
- kube_mode_role_binding.yaml
|
||||
tests:
|
||||
- it: should render base rolebinding metadata in kubernetes mode
|
||||
set:
|
||||
runner:
|
||||
mode: "kubernetes"
|
||||
kubernetesMode:
|
||||
default: true
|
||||
serviceAccountName: ""
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
chart:
|
||||
appVersion: "0.14.0"
|
||||
asserts:
|
||||
- equal:
|
||||
path: apiVersion
|
||||
value: "rbac.authorization.k8s.io/v1"
|
||||
- equal:
|
||||
path: kind
|
||||
value: "RoleBinding"
|
||||
- equal:
|
||||
path: metadata.name
|
||||
value: "test-name-kube-mode"
|
||||
- equal:
|
||||
path: metadata.namespace
|
||||
value: "test-namespace"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/component"]
|
||||
value: "kube-mode-role-binding"
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/scale-set-name"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/scale-set-namespace"]
|
||||
value: "test-namespace"
|
||||
- equal:
|
||||
path: metadata.finalizers[0]
|
||||
value: "actions.github.com/cleanup-protection"
|
||||
- equal:
|
||||
path: roleRef.kind
|
||||
value: "Role"
|
||||
- equal:
|
||||
path: roleRef.name
|
||||
value: "test-name-kube-mode"
|
||||
- equal:
|
||||
path: subjects[0].kind
|
||||
value: "ServiceAccount"
|
||||
- equal:
|
||||
path: subjects[0].name
|
||||
value: "test-name-kube-mode"
|
||||
- equal:
|
||||
path: subjects[0].namespace
|
||||
value: "test-namespace"
|
||||
|
||||
- it: should not render when runner mode is not kubernetes
|
||||
set:
|
||||
runner:
|
||||
mode: "dind"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- hasDocuments:
|
||||
count: 0
|
||||
|
||||
- it: should not render when serviceAccountName is provided
|
||||
set:
|
||||
runner:
|
||||
mode: "kubernetes"
|
||||
kubernetesMode:
|
||||
default: true
|
||||
serviceAccountName: "custom-sa"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- hasDocuments:
|
||||
count: 0
|
||||
|
||||
- it: should include global and resource labels
|
||||
set:
|
||||
runner:
|
||||
mode: "kubernetes"
|
||||
kubernetesMode:
|
||||
default: true
|
||||
serviceAccountName: ""
|
||||
resource:
|
||||
all:
|
||||
metadata:
|
||||
labels:
|
||||
global-team: "platform"
|
||||
kubernetesModeRoleBinding:
|
||||
metadata:
|
||||
labels:
|
||||
rb-team: "arc"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: metadata.labels["global-team"]
|
||||
value: "platform"
|
||||
- equal:
|
||||
path: metadata.labels["rb-team"]
|
||||
value: "arc"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/component"]
|
||||
value: "kube-mode-role-binding"
|
||||
|
||||
- it: should drop actions.github.com custom labels from config
|
||||
set:
|
||||
runner:
|
||||
mode: "kubernetes"
|
||||
kubernetesMode:
|
||||
default: true
|
||||
serviceAccountName: ""
|
||||
resource:
|
||||
all:
|
||||
metadata:
|
||||
labels:
|
||||
owner: "devops"
|
||||
actions.github.com/global-custom: "global-value"
|
||||
kubernetesModeRoleBinding:
|
||||
metadata:
|
||||
labels:
|
||||
actions.github.com/rb-custom: "rb-value"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: metadata.labels["owner"]
|
||||
value: "devops"
|
||||
- notExists:
|
||||
path: metadata.labels["actions.github.com/global-custom"]
|
||||
- notExists:
|
||||
path: metadata.labels["actions.github.com/rb-custom"]
|
||||
|
||||
- it: should not allow overriding reserved labels
|
||||
set:
|
||||
runner:
|
||||
mode: "kubernetes"
|
||||
kubernetesMode:
|
||||
default: true
|
||||
serviceAccountName: ""
|
||||
resource:
|
||||
all:
|
||||
metadata:
|
||||
labels:
|
||||
helm.sh/chart: "bad"
|
||||
app.kubernetes.io/name: "bad"
|
||||
app.kubernetes.io/instance: "bad"
|
||||
app.kubernetes.io/component: "bad"
|
||||
actions.github.com/scale-set-name: "bad"
|
||||
actions.github.com/scale-set-namespace: "bad"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
chart:
|
||||
appVersion: "0.14.0"
|
||||
asserts:
|
||||
- equal:
|
||||
path: metadata.labels["helm.sh/chart"]
|
||||
value: "gha-rs-0.14.0"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/name"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/instance"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/component"]
|
||||
value: "kube-mode-role-binding"
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/scale-set-name"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/scale-set-namespace"]
|
||||
value: "test-namespace"
|
||||
@@ -0,0 +1,117 @@
|
||||
suite: "Test Kubernetes Mode Role"
|
||||
templates:
|
||||
- kube_mode_role.yaml
|
||||
tests:
|
||||
- it: should render base role metadata in kubernetes mode
|
||||
set:
|
||||
runner:
|
||||
mode: "kubernetes"
|
||||
kubernetesMode:
|
||||
default: true
|
||||
serviceAccountName: ""
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
chart:
|
||||
appVersion: "0.14.0"
|
||||
asserts:
|
||||
- equal:
|
||||
path: apiVersion
|
||||
value: "rbac.authorization.k8s.io/v1"
|
||||
- equal:
|
||||
path: kind
|
||||
value: "Role"
|
||||
- equal:
|
||||
path: metadata.name
|
||||
value: "test-name-kube-mode"
|
||||
- equal:
|
||||
path: metadata.namespace
|
||||
value: "test-namespace"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/component"]
|
||||
value: "kube-mode-role"
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/scale-set-name"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/scale-set-namespace"]
|
||||
value: "test-namespace"
|
||||
- equal:
|
||||
path: metadata.finalizers[0]
|
||||
value: "actions.github.com/cleanup-protection"
|
||||
|
||||
- it: should append extra RBAC policy rules
|
||||
set:
|
||||
runner:
|
||||
mode: "kubernetes"
|
||||
kubernetesMode:
|
||||
default: true
|
||||
serviceAccountName: ""
|
||||
resource:
|
||||
kubernetesModeRole:
|
||||
extraRules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- "events"
|
||||
verbs:
|
||||
- "create"
|
||||
- "patch"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: rules[5].apiGroups[0]
|
||||
value: ""
|
||||
- equal:
|
||||
path: rules[5].resources[0]
|
||||
value: "events"
|
||||
- equal:
|
||||
path: rules[5].verbs[0]
|
||||
value: "create"
|
||||
- equal:
|
||||
path: rules[5].verbs[1]
|
||||
value: "patch"
|
||||
|
||||
- it: should fail when extraRules is not a list
|
||||
set:
|
||||
runner:
|
||||
mode: "kubernetes"
|
||||
kubernetesMode:
|
||||
default: true
|
||||
serviceAccountName: ""
|
||||
resource:
|
||||
kubernetesModeRole:
|
||||
extraRules: "not-a-list"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: ".Values.resource.kubernetesModeRole.extraRules must be a list of RBAC policy rules"
|
||||
|
||||
- it: should not render when runner mode is not kubernetes
|
||||
set:
|
||||
runner:
|
||||
mode: "dind"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- hasDocuments:
|
||||
count: 0
|
||||
|
||||
- it: should not render when serviceAccountName is provided
|
||||
set:
|
||||
runner:
|
||||
mode: "kubernetes"
|
||||
kubernetesMode:
|
||||
default: true
|
||||
serviceAccountName: "custom-sa"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- hasDocuments:
|
||||
count: 0
|
||||
@@ -0,0 +1,167 @@
|
||||
suite: "Test Kubernetes Mode ServiceAccount"
|
||||
templates:
|
||||
- kube_mode_serviceaccount.yaml
|
||||
tests:
|
||||
- it: should render base serviceaccount metadata in kubernetes mode
|
||||
set:
|
||||
runner:
|
||||
mode: "kubernetes"
|
||||
kubernetesMode:
|
||||
default: true
|
||||
serviceAccountName: ""
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
chart:
|
||||
appVersion: "0.14.0"
|
||||
asserts:
|
||||
- equal:
|
||||
path: apiVersion
|
||||
value: "v1"
|
||||
- equal:
|
||||
path: kind
|
||||
value: "ServiceAccount"
|
||||
- equal:
|
||||
path: metadata.name
|
||||
value: "test-name-kube-mode"
|
||||
- equal:
|
||||
path: metadata.namespace
|
||||
value: "test-namespace"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/component"]
|
||||
value: "kube-mode-serviceaccount"
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/scale-set-name"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/scale-set-namespace"]
|
||||
value: "test-namespace"
|
||||
- equal:
|
||||
path: metadata.finalizers[0]
|
||||
value: "actions.github.com/cleanup-protection"
|
||||
|
||||
- it: should not render when runner mode is not kubernetes
|
||||
set:
|
||||
runner:
|
||||
mode: "dind"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- hasDocuments:
|
||||
count: 0
|
||||
|
||||
- it: should not render when serviceAccountName is provided
|
||||
set:
|
||||
runner:
|
||||
mode: "kubernetes"
|
||||
kubernetesMode:
|
||||
default: true
|
||||
serviceAccountName: "custom-sa"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- hasDocuments:
|
||||
count: 0
|
||||
|
||||
- it: should include global and resource labels
|
||||
set:
|
||||
runner:
|
||||
mode: "kubernetes"
|
||||
kubernetesMode:
|
||||
default: true
|
||||
serviceAccountName: ""
|
||||
resource:
|
||||
all:
|
||||
metadata:
|
||||
labels:
|
||||
global-team: "platform"
|
||||
kubernetesModeServiceAccount:
|
||||
metadata:
|
||||
labels:
|
||||
sa-team: "arc"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: metadata.labels["global-team"]
|
||||
value: "platform"
|
||||
- equal:
|
||||
path: metadata.labels["sa-team"]
|
||||
value: "arc"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/component"]
|
||||
value: "kube-mode-serviceaccount"
|
||||
|
||||
- it: should drop actions.github.com custom labels from config
|
||||
set:
|
||||
runner:
|
||||
mode: "kubernetes"
|
||||
kubernetesMode:
|
||||
default: true
|
||||
serviceAccountName: ""
|
||||
resource:
|
||||
all:
|
||||
metadata:
|
||||
labels:
|
||||
owner: "devops"
|
||||
actions.github.com/global-custom: "global-value"
|
||||
kubernetesModeServiceAccount:
|
||||
metadata:
|
||||
labels:
|
||||
actions.github.com/sa-custom: "sa-value"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: metadata.labels["owner"]
|
||||
value: "devops"
|
||||
- notExists:
|
||||
path: metadata.labels["actions.github.com/global-custom"]
|
||||
- notExists:
|
||||
path: metadata.labels["actions.github.com/sa-custom"]
|
||||
|
||||
- it: should not allow overriding reserved labels
|
||||
set:
|
||||
runner:
|
||||
mode: "kubernetes"
|
||||
kubernetesMode:
|
||||
default: true
|
||||
serviceAccountName: ""
|
||||
resource:
|
||||
all:
|
||||
metadata:
|
||||
labels:
|
||||
helm.sh/chart: "bad"
|
||||
app.kubernetes.io/name: "bad"
|
||||
app.kubernetes.io/instance: "bad"
|
||||
app.kubernetes.io/component: "bad"
|
||||
actions.github.com/scale-set-name: "bad"
|
||||
actions.github.com/scale-set-namespace: "bad"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
chart:
|
||||
appVersion: "0.14.0"
|
||||
asserts:
|
||||
- equal:
|
||||
path: metadata.labels["helm.sh/chart"]
|
||||
value: "gha-rs-0.14.0"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/name"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/instance"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/component"]
|
||||
value: "kube-mode-serviceaccount"
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/scale-set-name"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/scale-set-namespace"]
|
||||
value: "test-namespace"
|
||||
@@ -0,0 +1,48 @@
|
||||
suite: "Test Manager RoleBinding Annotations"
|
||||
templates:
|
||||
- manager_role_binding.yaml
|
||||
tests:
|
||||
- it: should merge global and resource annotations (resource wins)
|
||||
set:
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
resource:
|
||||
all:
|
||||
metadata:
|
||||
annotations:
|
||||
owner: "platform"
|
||||
environment: "production"
|
||||
managerRoleBinding:
|
||||
metadata:
|
||||
annotations:
|
||||
environment: "staging"
|
||||
team: "backend"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: metadata.annotations["owner"]
|
||||
value: "platform"
|
||||
- equal:
|
||||
path: metadata.annotations["team"]
|
||||
value: "backend"
|
||||
- equal:
|
||||
path: metadata.annotations["environment"]
|
||||
value: "staging"
|
||||
|
||||
- it: should not allow actions.github.com/* annotations from user input
|
||||
set:
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
resource:
|
||||
managerRoleBinding:
|
||||
metadata:
|
||||
annotations:
|
||||
actions.github.com/something: "overridden"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- notExists:
|
||||
path: metadata.annotations["actions.github.com/something"]
|
||||
@@ -0,0 +1,91 @@
|
||||
suite: "Test Manager RoleBinding Labels"
|
||||
templates:
|
||||
- manager_role_binding.yaml
|
||||
tests:
|
||||
- it: should render base labels
|
||||
set:
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
chart:
|
||||
appVersion: "0.14.0"
|
||||
asserts:
|
||||
- equal:
|
||||
path: metadata.labels["helm.sh/chart"]
|
||||
value: "gha-rs-0.14.0"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/name"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/instance"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/component"]
|
||||
value: "manager-role-binding"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/managed-by"]
|
||||
value: "Helm"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/part-of"]
|
||||
value: "gha-rs"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/version"]
|
||||
value: "0.14.0"
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/scale-set-name"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/scale-set-namespace"]
|
||||
value: "test-namespace"
|
||||
|
||||
- it: should merge global and resource labels (resource wins)
|
||||
set:
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
resource:
|
||||
all:
|
||||
metadata:
|
||||
labels:
|
||||
owner: "platform"
|
||||
environment: "production"
|
||||
managerRoleBinding:
|
||||
metadata:
|
||||
labels:
|
||||
environment: "staging"
|
||||
team: "backend"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
chart:
|
||||
appVersion: "0.14.0"
|
||||
asserts:
|
||||
- equal:
|
||||
path: metadata.labels["owner"]
|
||||
value: "platform"
|
||||
- equal:
|
||||
path: metadata.labels["team"]
|
||||
value: "backend"
|
||||
- equal:
|
||||
path: metadata.labels["environment"]
|
||||
value: "staging"
|
||||
|
||||
- it: should not allow actions.github.com/* labels from user input
|
||||
set:
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
resource:
|
||||
managerRoleBinding:
|
||||
metadata:
|
||||
labels:
|
||||
actions.github.com/scale-set-name: "overridden"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
chart:
|
||||
appVersion: "0.14.0"
|
||||
asserts:
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/scale-set-name"]
|
||||
value: "test-name"
|
||||
@@ -0,0 +1,76 @@
|
||||
suite: "Test Manager Role Extra Rules"
|
||||
templates:
|
||||
- manager_role.yaml
|
||||
tests:
|
||||
- it: should render base role metadata
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
chart:
|
||||
appVersion: "0.14.0"
|
||||
asserts:
|
||||
- equal:
|
||||
path: apiVersion
|
||||
value: "rbac.authorization.k8s.io/v1"
|
||||
- equal:
|
||||
path: kind
|
||||
value: "Role"
|
||||
- equal:
|
||||
path: metadata.name
|
||||
value: "test-name-manager-role"
|
||||
- equal:
|
||||
path: metadata.namespace
|
||||
value: "test-namespace"
|
||||
- equal:
|
||||
path: metadata.labels["app.kubernetes.io/component"]
|
||||
value: "manager-role"
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/scale-set-name"]
|
||||
value: "test-name"
|
||||
- equal:
|
||||
path: metadata.labels["actions.github.com/scale-set-namespace"]
|
||||
value: "test-namespace"
|
||||
- equal:
|
||||
path: metadata.finalizers[0]
|
||||
value: "actions.github.com/cleanup-protection"
|
||||
|
||||
- it: should append extra RBAC policy rules
|
||||
set:
|
||||
resource:
|
||||
managerRole:
|
||||
extraRules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- "events"
|
||||
verbs:
|
||||
- "create"
|
||||
- "patch"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- equal:
|
||||
path: rules[6].apiGroups[0]
|
||||
value: ""
|
||||
- equal:
|
||||
path: rules[6].resources[0]
|
||||
value: "events"
|
||||
- equal:
|
||||
path: rules[6].verbs[0]
|
||||
value: "create"
|
||||
- equal:
|
||||
path: rules[6].verbs[1]
|
||||
value: "patch"
|
||||
|
||||
- it: should fail when extraRules is not a list
|
||||
set:
|
||||
resource:
|
||||
managerRole:
|
||||
extraRules: "not-a-list"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "test-namespace"
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: ".Values.resource.managerRole.extraRules must be a list of RBAC policy rules"
|
||||
@@ -0,0 +1,25 @@
|
||||
suite: "Namespace override"
|
||||
templates:
|
||||
- autoscalingrunnserset.yaml
|
||||
- githubsecret.yaml
|
||||
tests:
|
||||
- it: should apply namespaceOverride to AutoscalingRunnerSet and GitHub Secret
|
||||
set:
|
||||
namespaceOverride: "override-ns"
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_token12345"
|
||||
controllerServiceAccount.name: "arc"
|
||||
controllerServiceAccount.namespace: "arc-system"
|
||||
release:
|
||||
name: "test-name"
|
||||
namespace: "release-ns"
|
||||
asserts:
|
||||
- equal:
|
||||
path: metadata.namespace
|
||||
value: "override-ns"
|
||||
template: autoscalingrunnserset.yaml
|
||||
- equal:
|
||||
path: metadata.namespace
|
||||
value: "override-ns"
|
||||
template: githubsecret.yaml
|
||||
386
charts/gha-runner-scale-set-experimental/values.yaml
Normal file
386
charts/gha-runner-scale-set-experimental/values.yaml
Normal file
@@ -0,0 +1,386 @@
|
||||
## By default .Release.namespace is used
|
||||
namespaceOverride: ""
|
||||
|
||||
scaleset:
|
||||
# Name of the scaleset
|
||||
name: ""
|
||||
runnerGroup: "default"
|
||||
## minRunners is the min number of idle runners. The target number of runners created will be
|
||||
## calculated as a sum of minRunners and the number of jobs assigned to the scale set.
|
||||
# minRunners: 0
|
||||
## maxRunners is the max number of runners the autoscaling runner set will scale up to.
|
||||
# maxRunners: 5
|
||||
|
||||
# Auth object provides authorization parameters.
|
||||
# You should apply either:
|
||||
# 1) secretName referencing the secret containing authorization parameters in the same namespace where the scale set is being installed in
|
||||
# 2) app object parameters
|
||||
# 3) github_tokne
|
||||
#
|
||||
# If multiple of them are set, only single one will be applied based on the above mentioned order.
|
||||
auth:
|
||||
url: "" # Required
|
||||
githubToken: ""
|
||||
secretName: ""
|
||||
app:
|
||||
clientId: ""
|
||||
installationId: ""
|
||||
privateKey: ""
|
||||
|
||||
# secretResolution configures how secrets are resolved for this scale set.
|
||||
# By default, secrets are resolved using Kubernetes secrets. When Kubernetes
|
||||
# secrets are used, no proxy config will be applied.
|
||||
#
|
||||
# If you decide to use secret integrations with vaults, you can configure
|
||||
# proxy settings for the vault communication here.
|
||||
secretResolution:
|
||||
# Name of the secret resolver to use.
|
||||
# Available values:
|
||||
# - "kubernetes" - use Kubernetes secrets
|
||||
# - "azureKeyVault" - use Azure Key Vault
|
||||
type: "kubernetes"
|
||||
|
||||
## Proxy settings when type is NOT "kubernetes"
|
||||
# proxy:
|
||||
# http:
|
||||
# url: http://proxy.com:1234
|
||||
# credentialSecretRef: proxy-auth # a secret with `username` and `password` keys
|
||||
# https:
|
||||
# url: http://proxy.com:1234
|
||||
# credentialSecretRef: proxy-auth # a secret with `username` and `password` keys
|
||||
# noProxy:
|
||||
# - example.com
|
||||
# - example.org
|
||||
|
||||
## Configuration for Azure Key Vault integration
|
||||
# azureKeyVault:
|
||||
# url: ""
|
||||
# client_id: ""
|
||||
# tenant_id: ""
|
||||
# certificate_path: ""
|
||||
|
||||
## Proxy can be used to define proxy settings that will be used by the
|
||||
## controller, the listener and the runner of this scale set.
|
||||
# proxy:
|
||||
# http:
|
||||
# url: http://proxy.com:1234
|
||||
# credentialSecretRef: proxy-auth # a secret with `username` and `password` keys
|
||||
# https:
|
||||
# url: http://proxy.com:1234
|
||||
# credentialSecretRef: proxy-auth # a secret with `username` and `password` keys
|
||||
# noProxy:
|
||||
# - example.com
|
||||
# - example.org
|
||||
|
||||
## listenerTemplate is the PodSpec for each listener Pod
|
||||
## For reference: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodSpec
|
||||
# listenerPodTemplate:
|
||||
# spec:
|
||||
# containers:
|
||||
# # Use this section to append additional configuration to the listener container.
|
||||
# # If you change the name of the container, the configuration will not be applied to the listener,
|
||||
# # and it will be treated as a side-car container.
|
||||
# - name: listener
|
||||
# securityContext:
|
||||
# runAsUser: 1000
|
||||
# # Use this section to add the configuration of a side-car container.
|
||||
# # Comment it out or remove it if you don't need it.
|
||||
# # Spec for this container will be applied as is without any modifications.
|
||||
# - name: side-car
|
||||
# image: example-sidecar
|
||||
|
||||
## Resource object allows modifying resources created by the chart itself
|
||||
resource:
|
||||
# Specifies metadata that will be applied to all resources managed by ARC
|
||||
all:
|
||||
metadata:
|
||||
labels: {}
|
||||
annotations: {}
|
||||
|
||||
# Specifies metadata that will be applied to the AutoscalingRunnerSet resource
|
||||
autoscalingRunnerSet:
|
||||
metadata:
|
||||
labels: {}
|
||||
annotations: {}
|
||||
|
||||
# Specifies metadata that will be applied to the manager Role resource
|
||||
managerRole:
|
||||
metadata:
|
||||
labels: {}
|
||||
annotations: {}
|
||||
extraRules: []
|
||||
|
||||
# Specifies metadata that will be applied to the manager RoleBinding resource
|
||||
managerRoleBinding:
|
||||
metadata:
|
||||
labels: {}
|
||||
annotations: {}
|
||||
|
||||
# Specifies metadata that will be applied to the no-permission ServiceAccount
|
||||
# (created for non-kubernetes runner modes).
|
||||
noPermissionServiceAccount:
|
||||
metadata:
|
||||
labels: {}
|
||||
annotations: {}
|
||||
|
||||
# Specifies metadata that will be applied to the kubernetes-mode RoleBinding
|
||||
# (created when runner.mode is "kubernetes" and a ServiceAccountName is not provided).
|
||||
kubernetesModeRoleBinding:
|
||||
metadata:
|
||||
labels: {}
|
||||
annotations: {}
|
||||
|
||||
# Specifies metadata that will be applied to the kubernetes-mode Role.
|
||||
kubernetesModeRole:
|
||||
metadata:
|
||||
labels: {}
|
||||
annotations: {}
|
||||
extraRules: []
|
||||
|
||||
# Specifies metadata that will be applied to the kubernetes-mode ServiceAccount.
|
||||
kubernetesModeServiceAccount:
|
||||
metadata:
|
||||
labels: {}
|
||||
annotations: {}
|
||||
|
||||
# TODO: Add more resource customizations when needed
|
||||
|
||||
# Template applied for the runner container
|
||||
runner:
|
||||
# Mode can be used to automatically add configuration for the selected mode
|
||||
# The available modes are:
|
||||
# - "" (default) - no additional configuration is applied
|
||||
# - "kubernetes" - configuration for running jobs in Kubernetes mode is applied
|
||||
# - "dind" - configuration for running jobs in Docker-in-Docker mode is
|
||||
#
|
||||
# For each mode, we provide configuration out of the box that works for most use
|
||||
# cases. You can customize our configuration by modifying the fields below,
|
||||
# or you can leave mode empty and provide your own complete configuration.
|
||||
mode: ""
|
||||
|
||||
pod:
|
||||
metadata:
|
||||
labels: {}
|
||||
annotations: {}
|
||||
# Runner pod template customization.
|
||||
#
|
||||
# All fields under runner.pod.spec (except those listed below) are applied directly to
|
||||
# spec.template.spec of the generated runner pod.
|
||||
#
|
||||
# Special handling:
|
||||
# - spec.containers: appended after the generated "runner" container (name "runner" is reserved)
|
||||
# - spec.initContainers: appended after any generated initContainers (e.g. dind mode)
|
||||
# - spec.volumes: appended after generated volumes
|
||||
#
|
||||
# Note: serviceAccountName is managed by the chart and cannot be overridden via runner.pod.spec.
|
||||
spec:
|
||||
# The name "runner" is reserved and must not be used here.
|
||||
containers: []
|
||||
initContainers: []
|
||||
volumes: []
|
||||
|
||||
# container field is applied to the container named "runner". You cannot override the name of the runner container
|
||||
container:
|
||||
image: "ghcr.io/actions/actions-runner:latest"
|
||||
command: ["/home/runner/run.sh"]
|
||||
|
||||
dind:
|
||||
copyExternals: true
|
||||
dockerGroupId: "123"
|
||||
dockerSock: "unix:///var/run/docker.sock"
|
||||
waitForDockerInSeconds: 120
|
||||
container:
|
||||
image: "docker:dind"
|
||||
|
||||
kubernetesMode:
|
||||
serviceAccountName: ""
|
||||
hookPath: "/home/runner/k8s/index.js"
|
||||
requireJobContainer: true
|
||||
extensionRef: ""
|
||||
extension:
|
||||
metadata:
|
||||
name: ""
|
||||
namespace: ""
|
||||
yaml: ""
|
||||
|
||||
## A self-signed CA certificate for communication with the GitHub server can be
|
||||
## provided using a config map key selector. If `runnerMountPath` is set, for
|
||||
## each runner pod ARC will:
|
||||
## - create a `github-server-tls-cert` volume containing the certificate
|
||||
## specified in `certificateFrom`
|
||||
## - mount that volume on path `runnerMountPath`/{certificate name}
|
||||
## - set NODE_EXTRA_CA_CERTS environment variable to that same path
|
||||
## - set RUNNER_UPDATE_CA_CERTS environment variable to "1" (as of version
|
||||
## 2.303.0 this will instruct the runner to reload certificates on the host)
|
||||
##
|
||||
## If any of the above had already been set by the user in the runner pod
|
||||
## template, ARC will observe those and not overwrite them.
|
||||
## Example configuration:
|
||||
#
|
||||
# githubServerTLS:
|
||||
# certificateFrom:
|
||||
# configMapKeyRef:
|
||||
# name: config-map-name
|
||||
# key: ca.crt
|
||||
# runnerMountPath: /usr/local/share/ca-certificates/
|
||||
|
||||
## controllerServiceAccount is the service account of the controller
|
||||
controllerServiceAccount:
|
||||
namespace: ""
|
||||
name: ""
|
||||
|
||||
## listenerMetrics are configurable metrics applied to the listener.
|
||||
## In order to avoid helm merging these fields, we left the metrics commented out.
|
||||
## When configuring metrics, please uncomment the listenerMetrics object below.
|
||||
## You can modify the configuration to remove the label or specify custom buckets for histogram.
|
||||
##
|
||||
## If the buckets field is not specified, the default buckets will be applied. Default buckets are
|
||||
## provided here for documentation purposes
|
||||
# listenerMetrics:
|
||||
# counters:
|
||||
# gha_started_jobs_total:
|
||||
# labels:
|
||||
# ["repository", "organization", "enterprise", "job_name", "event_name", "job_workflow_ref", "job_workflow_name", "job_workflow_target"]
|
||||
# gha_completed_jobs_total:
|
||||
# labels:
|
||||
# [
|
||||
# "repository",
|
||||
# "organization",
|
||||
# "enterprise",
|
||||
# "job_name",
|
||||
# "event_name",
|
||||
# "job_result",
|
||||
# "job_workflow_ref",
|
||||
# "job_workflow_name",
|
||||
# "job_workflow_target",
|
||||
# ]
|
||||
# gauges:
|
||||
# gha_assigned_jobs:
|
||||
# labels: ["name", "namespace", "repository", "organization", "enterprise"]
|
||||
# gha_running_jobs:
|
||||
# labels: ["name", "namespace", "repository", "organization", "enterprise"]
|
||||
# gha_registered_runners:
|
||||
# labels: ["name", "namespace", "repository", "organization", "enterprise"]
|
||||
# gha_busy_runners:
|
||||
# labels: ["name", "namespace", "repository", "organization", "enterprise"]
|
||||
# gha_min_runners:
|
||||
# labels: ["name", "namespace", "repository", "organization", "enterprise"]
|
||||
# gha_max_runners:
|
||||
# labels: ["name", "namespace", "repository", "organization", "enterprise"]
|
||||
# gha_desired_runners:
|
||||
# labels: ["name", "namespace", "repository", "organization", "enterprise"]
|
||||
# gha_idle_runners:
|
||||
# labels: ["name", "namespace", "repository", "organization", "enterprise"]
|
||||
# histograms:
|
||||
# gha_job_startup_duration_seconds:
|
||||
# labels:
|
||||
# ["repository", "organization", "enterprise", "job_name", "event_name","job_workflow_ref", "job_workflow_name", "job_workflow_target"]
|
||||
# buckets:
|
||||
# [
|
||||
# 0.01,
|
||||
# 0.05,
|
||||
# 0.1,
|
||||
# 0.5,
|
||||
# 1.0,
|
||||
# 2.0,
|
||||
# 3.0,
|
||||
# 4.0,
|
||||
# 5.0,
|
||||
# 6.0,
|
||||
# 7.0,
|
||||
# 8.0,
|
||||
# 9.0,
|
||||
# 10.0,
|
||||
# 12.0,
|
||||
# 15.0,
|
||||
# 18.0,
|
||||
# 20.0,
|
||||
# 25.0,
|
||||
# 30.0,
|
||||
# 40.0,
|
||||
# 50.0,
|
||||
# 60.0,
|
||||
# 70.0,
|
||||
# 80.0,
|
||||
# 90.0,
|
||||
# 100.0,
|
||||
# 110.0,
|
||||
# 120.0,
|
||||
# 150.0,
|
||||
# 180.0,
|
||||
# 210.0,
|
||||
# 240.0,
|
||||
# 300.0,
|
||||
# 360.0,
|
||||
# 420.0,
|
||||
# 480.0,
|
||||
# 540.0,
|
||||
# 600.0,
|
||||
# 900.0,
|
||||
# 1200.0,
|
||||
# 1800.0,
|
||||
# 2400.0,
|
||||
# 3000.0,
|
||||
# 3600.0,
|
||||
# ]
|
||||
# gha_job_execution_duration_seconds:
|
||||
# labels:
|
||||
# [
|
||||
# "repository",
|
||||
# "organization",
|
||||
# "enterprise",
|
||||
# "job_name",
|
||||
# "event_name",
|
||||
# "job_result",
|
||||
# "job_workflow_ref",
|
||||
# "job_workflow_name",
|
||||
# "job_workflow_target"
|
||||
# ]
|
||||
# buckets:
|
||||
# [
|
||||
# 0.01,
|
||||
# 0.05,
|
||||
# 0.1,
|
||||
# 0.5,
|
||||
# 1.0,
|
||||
# 2.0,
|
||||
# 3.0,
|
||||
# 4.0,
|
||||
# 5.0,
|
||||
# 6.0,
|
||||
# 7.0,
|
||||
# 8.0,
|
||||
# 9.0,
|
||||
# 10.0,
|
||||
# 12.0,
|
||||
# 15.0,
|
||||
# 18.0,
|
||||
# 20.0,
|
||||
# 25.0,
|
||||
# 30.0,
|
||||
# 40.0,
|
||||
# 50.0,
|
||||
# 60.0,
|
||||
# 70.0,
|
||||
# 80.0,
|
||||
# 90.0,
|
||||
# 100.0,
|
||||
# 110.0,
|
||||
# 120.0,
|
||||
# 150.0,
|
||||
# 180.0,
|
||||
# 210.0,
|
||||
# 240.0,
|
||||
# 300.0,
|
||||
# 360.0,
|
||||
# 420.0,
|
||||
# 480.0,
|
||||
# 540.0,
|
||||
# 600.0,
|
||||
# 900.0,
|
||||
# 1200.0,
|
||||
# 1800.0,
|
||||
# 2400.0,
|
||||
# 3000.0,
|
||||
# 3600.0,
|
||||
# ]
|
||||
@@ -21,3 +21,4 @@
|
||||
.idea/
|
||||
*.tmproj
|
||||
.vscode/
|
||||
tests/
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
suite: "AutoscalingRunnerSet"
|
||||
templates:
|
||||
- autoscalingrunnserset.yaml
|
||||
tests:
|
||||
- it: should render base labels
|
||||
set:
|
||||
scaleset.name: "test"
|
||||
auth.url: "https://github.com/org"
|
||||
auth.githubToken: "gh_"
|
||||
@@ -274,10 +274,6 @@ func (c *Client) Identifier() string {
|
||||
func (c *Client) Do(req *http.Request) (*http.Response, error) {
|
||||
resp, err := c.Client.Do(req)
|
||||
if err != nil {
|
||||
// If we have a response even with an error, include the status code
|
||||
if resp != nil {
|
||||
return nil, fmt.Errorf("client request failed with status code %d: %w", resp.StatusCode, err)
|
||||
}
|
||||
return nil, fmt.Errorf("client request failed: %w", err)
|
||||
}
|
||||
|
||||
@@ -860,8 +856,7 @@ func (c *Client) GenerateJitRunnerConfig(ctx context.Context, jitRunnerSetting *
|
||||
|
||||
resp, err := c.Do(req)
|
||||
if err != nil {
|
||||
// Include the URL and method in the error for better debugging
|
||||
return nil, fmt.Errorf("failed to issue the request %s %s: %w", req.Method, req.URL.String(), err)
|
||||
return nil, fmt.Errorf("failed to issue the request: %w", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
|
||||
@@ -2,7 +2,6 @@ package actions_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -59,37 +58,4 @@ func TestGenerateJitRunnerConfig(t *testing.T) {
|
||||
assert.NotNil(t, err)
|
||||
assert.Equalf(t, actualRetry, expectedRetry, "A retry was expected after the first request but got: %v", actualRetry)
|
||||
})
|
||||
|
||||
t.Run("Error includes HTTP method and URL when request fails", func(t *testing.T) {
|
||||
runnerSettings := &actions.RunnerScaleSetJitRunnerSetting{}
|
||||
|
||||
server := newActionsServer(t, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}))
|
||||
|
||||
client, err := actions.NewClient(
|
||||
server.configURLForOrg("my-org"),
|
||||
auth,
|
||||
actions.WithRetryMax(0), // No retries to get immediate error
|
||||
actions.WithRetryWaitMax(1*time.Millisecond),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = client.GenerateJitRunnerConfig(ctx, runnerSettings, 1)
|
||||
require.NotNil(t, err)
|
||||
// Verify error message includes HTTP method and URL for better debugging
|
||||
errMsg := err.Error()
|
||||
assert.Contains(t, errMsg, "POST", "Error message should include HTTP method")
|
||||
assert.Contains(t, errMsg, "generatejitconfig", "Error message should include URL path")
|
||||
|
||||
// The error might be an ActionsError (if response was received) or a wrapped error (if Do() failed)
|
||||
// In either case, the error message should include request details
|
||||
var actionsErr *actions.ActionsError
|
||||
if errors.As(err, &actionsErr) {
|
||||
// If we got an ActionsError, verify the status code is included
|
||||
assert.Equal(t, http.StatusInternalServerError, actionsErr.StatusCode)
|
||||
}
|
||||
// If it's a wrapped error from Do(), the error message already includes the method and URL
|
||||
// which is what we're testing for
|
||||
})
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ type ActionsError struct {
|
||||
}
|
||||
|
||||
func (e *ActionsError) Error() string {
|
||||
return fmt.Sprintf("actions error: StatusCode %d, ActivityId %q: %v", e.StatusCode, e.ActivityID, e.Err)
|
||||
return fmt.Sprintf("actions error: StatusCode %d, AcivityId %q: %v", e.StatusCode, e.ActivityID, e.Err)
|
||||
}
|
||||
|
||||
func (e *ActionsError) Unwrap() error {
|
||||
@@ -112,7 +112,7 @@ type MessageQueueTokenExpiredError struct {
|
||||
}
|
||||
|
||||
func (e *MessageQueueTokenExpiredError) Error() string {
|
||||
return fmt.Sprintf("MessageQueueTokenExpiredError: ActivityId %q, StatusCode %d: %s", e.activityID, e.statusCode, e.msg)
|
||||
return fmt.Sprintf("MessageQueueTokenExpiredError: AcivityId %q, StatusCode %d: %s", e.activityID, e.statusCode, e.msg)
|
||||
}
|
||||
|
||||
type HttpClientSideError struct {
|
||||
|
||||
@@ -22,7 +22,7 @@ func TestActionsError(t *testing.T) {
|
||||
|
||||
s := err.Error()
|
||||
assert.Contains(t, s, "StatusCode 404")
|
||||
assert.Contains(t, s, "ActivityId \"activity-id\"")
|
||||
assert.Contains(t, s, "AcivityId \"activity-id\"")
|
||||
assert.Contains(t, s, "example error description")
|
||||
})
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
DIR="$(dirname "${BASH_SOURCE[0]}")"
|
||||
|
||||
DIR="$(realpath "${DIR}")"
|
||||
|
||||
TEST_DIR="$(realpath "${DIR}/../test/actions.github.com")"
|
||||
|
||||
89
test/actions.github.com/anonymous-proxy-setup-v2.test.sh
Executable file
89
test/actions.github.com/anonymous-proxy-setup-v2.test.sh
Executable file
@@ -0,0 +1,89 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
DIR="$(realpath "$(dirname "${BASH_SOURCE[0]}")")"
|
||||
|
||||
ROOT_DIR="$(realpath "${DIR}/../..")"
|
||||
|
||||
source "${DIR}/helper.sh"
|
||||
|
||||
export VERSION="$(chart_version "${ROOT_DIR}/charts/gha-runner-scale-set-controller-experimental/Chart.yaml")"
|
||||
|
||||
SCALE_SET_NAME="anonymous-proxy-$(date +'%M%S')$(((RANDOM + 100) % 100 + 1))"
|
||||
SCALE_SET_NAMESPACE="arc-runners"
|
||||
WORKFLOW_FILE="arc-test-workflow.yaml"
|
||||
ARC_NAME="arc"
|
||||
ARC_NAMESPACE="arc-systems"
|
||||
|
||||
function install_arc() {
|
||||
echo "Creating namespace ${ARC_NAMESPACE}"
|
||||
kubectl create namespace "${SCALE_SET_NAMESPACE}"
|
||||
|
||||
echo "Installing ARC"
|
||||
helm install "${ARC_NAME}" \
|
||||
--namespace "${ARC_NAMESPACE}" \
|
||||
--create-namespace \
|
||||
--set controller.manager.container.image="${IMAGE_NAME}:${IMAGE_TAG}" \
|
||||
"${ROOT_DIR}/charts/gha-runner-scale-set-controller-experimental" \
|
||||
--debug
|
||||
|
||||
if ! NAME="${ARC_NAME}" NAMESPACE="${ARC_NAMESPACE}" wait_for_arc; then
|
||||
NAMESPACE="${ARC_NAMESPACE}" log_arc
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
function install_squid() {
|
||||
echo "Starting squid-proxy"
|
||||
kubectl apply -f "${DIR}/anonymous-proxy-setup.squid.yaml"
|
||||
}
|
||||
|
||||
function install_scale_set() {
|
||||
echo "Installing scale set ${SCALE_SET_NAMESPACE}/${SCALE_SET_NAME}"
|
||||
|
||||
helm install "${SCALE_SET_NAME}" \
|
||||
--namespace "${SCALE_SET_NAMESPACE}" \
|
||||
--create-namespace \
|
||||
--set controllerServiceAccount.name="${ARC_NAME}-gha-rs-controller" \
|
||||
--set controllerServiceAccount.namespace="${ARC_NAMESPACE}" \
|
||||
--set auth.url="https://github.com/${TARGET_ORG}/${TARGET_REPO}" \
|
||||
--set auth.githubToken="${GITHUB_TOKEN}" \
|
||||
--set proxy.https.url="http://squid.default.svc.cluster.local:3128" \
|
||||
--set "proxy.noProxy[0]=10.96.0.1:443" \
|
||||
"${ROOT_DIR}/charts/gha-runner-scale-set-experimental"
|
||||
|
||||
if ! NAME="${SCALE_SET_NAME}" NAMESPACE="${ARC_NAMESPACE}" wait_for_scale_set; then
|
||||
NAMESPACE="${ARC_NAMESPACE}" log_arc
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
function main() {
|
||||
local failed=()
|
||||
|
||||
build_image
|
||||
create_cluster
|
||||
|
||||
install_arc
|
||||
install_squid
|
||||
|
||||
install_scale_set || {
|
||||
echo "Scale set installation failed"
|
||||
NAMESPACE="${ARC_NAMESPACE}" log_arc
|
||||
delete_cluster
|
||||
exit 1
|
||||
}
|
||||
|
||||
WORKFLOW_FILE="${WORKFLOW_FILE}" SCALE_SET_NAME="${SCALE_SET_NAME}" run_workflow || failed+=("run_workflow")
|
||||
|
||||
INSTALLATION_NAME="${SCALE_SET_NAME}" NAMESPACE="${SCALE_SET_NAMESPACE}" cleanup_scale_set || failed+=("cleanup_scale_set")
|
||||
|
||||
NAMESPACE="${ARC_NAMESPACE}" log_arc || failed+=("log_arc")
|
||||
|
||||
delete_cluster
|
||||
|
||||
print_results "${failed[@]}"
|
||||
}
|
||||
|
||||
main
|
||||
@@ -8,6 +8,8 @@ ROOT_DIR="$(realpath "${DIR}/../..")"
|
||||
|
||||
source "${DIR}/helper.sh"
|
||||
|
||||
export VERSION="$(chart_version "${ROOT_DIR}/charts/gha-runner-scale-set-controller/Chart.yaml")"
|
||||
|
||||
SCALE_SET_NAME="anonymous-proxy-$(date +'%M%S')$(((RANDOM + 100) % 100 + 1))"
|
||||
SCALE_SET_NAMESPACE="arc-runners"
|
||||
WORKFLOW_FILE="arc-test-workflow.yaml"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user