mirror of
https://github.com/actions/actions-runner-controller.git
synced 2025-12-10 11:41:27 +00:00
Compare commits
42 Commits
gha-runner
...
v0.27.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a608abd124 | ||
|
|
02d9add322 | ||
|
|
f5ac134787 | ||
|
|
42abad5def | ||
|
|
514b7da742 | ||
|
|
c8e3bb5ec3 | ||
|
|
878c9b8b49 | ||
|
|
4536707af6 | ||
|
|
13802c5a6d | ||
|
|
362fa5d52e | ||
|
|
65184f1ed8 | ||
|
|
c23e31123c | ||
|
|
56e1c62ac2 | ||
|
|
64cedff2b4 | ||
|
|
37f93b794e | ||
|
|
dc833e57a0 | ||
|
|
5228aded87 | ||
|
|
f49d08e4bc | ||
|
|
064039afc0 | ||
|
|
e5d8d65396 | ||
|
|
c465ace8fb | ||
|
|
34f3878829 | ||
|
|
44c3931d8e | ||
|
|
08acb1b831 | ||
|
|
40811ebe0e | ||
|
|
3417c5a3a8 | ||
|
|
172faa883c | ||
|
|
9e6c7d019f | ||
|
|
9fbcafa703 | ||
|
|
2bf83d0d7f | ||
|
|
19d30dea5f | ||
|
|
6c66c1633f | ||
|
|
e55708588b | ||
|
|
261d4371b5 | ||
|
|
bd9f32e354 | ||
|
|
babbfc77d5 | ||
|
|
322df79617 | ||
|
|
1c7c6639ed | ||
|
|
bcaac39a2e | ||
|
|
af625dd1cb | ||
|
|
44969659df | ||
|
|
a5f98dea75 |
45
.github/actions/e2e-arc-test/action.yaml
vendored
45
.github/actions/e2e-arc-test/action.yaml
vendored
@@ -1,45 +0,0 @@
|
|||||||
name: 'E2E ARC Test Action'
|
|
||||||
description: 'Includes common arc installation, setup and test file run'
|
|
||||||
|
|
||||||
inputs:
|
|
||||||
github-token:
|
|
||||||
description: 'JWT generated with Github App inputs'
|
|
||||||
required: true
|
|
||||||
config-url:
|
|
||||||
description: "URL of the repo, org or enterprise where the runner scale sets will be registered"
|
|
||||||
required: true
|
|
||||||
docker-image-repo:
|
|
||||||
description: "Local docker image repo for testing"
|
|
||||||
required: true
|
|
||||||
docker-image-tag:
|
|
||||||
description: "Tag of ARC Docker image for testing"
|
|
||||||
required: true
|
|
||||||
|
|
||||||
runs:
|
|
||||||
using: "composite"
|
|
||||||
steps:
|
|
||||||
- name: Install ARC
|
|
||||||
run: helm install arc --namespace "arc-systems" --create-namespace --set image.tag=${{ inputs.docker-image-tag }} --set image.repository=${{ inputs.docker-image-repo }} ./charts/gha-runner-scale-set-controller
|
|
||||||
shell: bash
|
|
||||||
- name: Get datetime
|
|
||||||
# We are using this value further in the runner installation to avoid runner name collision that are a risk with hard coded values.
|
|
||||||
# A datetime including the 3 nanoseconds are a good option for this and also adds to readability and runner sorting if needed.
|
|
||||||
run: echo "DATE_TIME=$(date +'%Y-%m-%d-%H-%M-%S-%3N')" >> $GITHUB_ENV
|
|
||||||
shell: bash
|
|
||||||
- name: Install runners
|
|
||||||
run: |
|
|
||||||
helm install "arc-runner-${{ env.DATE_TIME }}" \
|
|
||||||
--namespace "arc-runners" \
|
|
||||||
--create-namespace \
|
|
||||||
--set githubConfigUrl="${{ inputs.config-url }}" \
|
|
||||||
--set githubConfigSecret.github_token="${{ inputs.github-token }}" \
|
|
||||||
./charts/gha-runner-scale-set \
|
|
||||||
--debug
|
|
||||||
kubectl get pods -A
|
|
||||||
shell: bash
|
|
||||||
- name: Test ARC scales pods up and down
|
|
||||||
run: |
|
|
||||||
export GITHUB_TOKEN="${{ inputs.github-token }}"
|
|
||||||
export DATE_TIME="${{ env.DATE_TIME }}"
|
|
||||||
go test ./test_e2e_arc -v
|
|
||||||
shell: bash
|
|
||||||
160
.github/actions/execute-assert-arc-e2e/action.yaml
vendored
Normal file
160
.github/actions/execute-assert-arc-e2e/action.yaml
vendored
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
name: 'Execute and Assert ARC E2E Test Action'
|
||||||
|
description: 'Queue E2E test workflow and assert workflow run result to be succeed'
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
auth-token:
|
||||||
|
description: 'GitHub access token to queue workflow run'
|
||||||
|
required: true
|
||||||
|
repo-owner:
|
||||||
|
description: "The repository owner name that has the test workflow file, ex: actions"
|
||||||
|
required: true
|
||||||
|
repo-name:
|
||||||
|
description: "The repository name that has the test workflow file, ex: test"
|
||||||
|
required: true
|
||||||
|
workflow-file:
|
||||||
|
description: 'The file name of the workflow yaml, ex: test.yml'
|
||||||
|
required: true
|
||||||
|
arc-name:
|
||||||
|
description: 'The name of the configured gha-runner-scale-set'
|
||||||
|
required: true
|
||||||
|
arc-namespace:
|
||||||
|
description: 'The namespace of the configured gha-runner-scale-set'
|
||||||
|
required: true
|
||||||
|
arc-controller-namespace:
|
||||||
|
description: 'The namespace of the configured gha-runner-scale-set-controller'
|
||||||
|
required: true
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: "composite"
|
||||||
|
steps:
|
||||||
|
- name: Queue test workflow
|
||||||
|
shell: bash
|
||||||
|
id: queue_workflow
|
||||||
|
run: |
|
||||||
|
queue_time=`date +%FT%TZ`
|
||||||
|
echo "queue_time=$queue_time" >> $GITHUB_OUTPUT
|
||||||
|
curl -X POST https://api.github.com/repos/${{inputs.repo-owner}}/${{inputs.repo-name}}/actions/workflows/${{inputs.workflow-file}}/dispatches \
|
||||||
|
-H "Accept: application/vnd.github.v3+json" \
|
||||||
|
-H "Authorization: token ${{inputs.auth-token}}" \
|
||||||
|
-d '{"ref": "main", "inputs": { "arc_name": "${{inputs.arc-name}}" } }'
|
||||||
|
|
||||||
|
- name: Fetch workflow run & job ids
|
||||||
|
uses: actions/github-script@v6
|
||||||
|
id: query_workflow
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
// Try to find the workflow run triggered by the previous step using the workflow_dispatch event.
|
||||||
|
// - Find recently create workflow runs in the test repository
|
||||||
|
// - For each workflow run, list its workflow job and see if the job's labels contain `inputs.arc-name`
|
||||||
|
// - Since the inputs.arc-name should be unique per e2e workflow run, once we find the job with the label, we find the workflow that we just triggered.
|
||||||
|
function sleep(ms) {
|
||||||
|
return new Promise(resolve => setTimeout(resolve, ms))
|
||||||
|
}
|
||||||
|
const owner = '${{inputs.repo-owner}}'
|
||||||
|
const repo = '${{inputs.repo-name}}'
|
||||||
|
const workflow_id = '${{inputs.workflow-file}}'
|
||||||
|
let workflow_run_id = 0
|
||||||
|
let workflow_job_id = 0
|
||||||
|
let workflow_run_html_url = ""
|
||||||
|
let count = 0
|
||||||
|
while (count++<12) {
|
||||||
|
await sleep(10 * 1000);
|
||||||
|
let listRunResponse = await github.rest.actions.listWorkflowRuns({
|
||||||
|
owner: owner,
|
||||||
|
repo: repo,
|
||||||
|
workflow_id: workflow_id,
|
||||||
|
created: '>${{steps.queue_workflow.outputs.queue_time}}'
|
||||||
|
})
|
||||||
|
if (listRunResponse.data.total_count > 0) {
|
||||||
|
console.log(`Found some new workflow runs for ${workflow_id}`)
|
||||||
|
for (let i = 0; i<listRunResponse.data.total_count; i++) {
|
||||||
|
let workflowRun = listRunResponse.data.workflow_runs[i]
|
||||||
|
console.log(`Check if workflow run ${workflowRun.id} is triggered by us.`)
|
||||||
|
let listJobResponse = await github.rest.actions.listJobsForWorkflowRun({
|
||||||
|
owner: owner,
|
||||||
|
repo: repo,
|
||||||
|
run_id: workflowRun.id
|
||||||
|
})
|
||||||
|
console.log(`Workflow run ${workflowRun.id} has ${listJobResponse.data.total_count} jobs.`)
|
||||||
|
if (listJobResponse.data.total_count > 0) {
|
||||||
|
for (let j = 0; j<listJobResponse.data.total_count; j++) {
|
||||||
|
let workflowJob = listJobResponse.data.jobs[j]
|
||||||
|
console.log(`Check if workflow job ${workflowJob.id} is triggered by us.`)
|
||||||
|
console.log(JSON.stringify(workflowJob.labels));
|
||||||
|
if (workflowJob.labels.includes('${{inputs.arc-name}}')) {
|
||||||
|
console.log(`Workflow job ${workflowJob.id} (Run id: ${workflowJob.run_id}) is triggered by us.`)
|
||||||
|
workflow_run_id = workflowJob.run_id
|
||||||
|
workflow_job_id = workflowJob.id
|
||||||
|
workflow_run_html_url = workflowRun.html_url
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (workflow_job_id > 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (workflow_job_id > 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (workflow_job_id == 0) {
|
||||||
|
core.setFailed(`Can't find workflow run and workflow job triggered to 'runs-on ${{inputs.arc-name}}'`)
|
||||||
|
} else {
|
||||||
|
core.setOutput('workflow_run', workflow_run_id);
|
||||||
|
core.setOutput('workflow_job', workflow_job_id);
|
||||||
|
core.setOutput('workflow_run_url', workflow_run_html_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
- name: Generate summary about the triggered workflow run
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
cat <<-EOF > $GITHUB_STEP_SUMMARY
|
||||||
|
| **Triggered workflow run** |
|
||||||
|
|:--------------------------:|
|
||||||
|
| ${{steps.query_workflow.outputs.workflow_run_url}} |
|
||||||
|
EOF
|
||||||
|
|
||||||
|
- name: Wait for workflow to finish successfully
|
||||||
|
uses: actions/github-script@v6
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
// Wait 5 minutes and make sure the workflow run we triggered completed with result 'success'
|
||||||
|
function sleep(ms) {
|
||||||
|
return new Promise(resolve => setTimeout(resolve, ms))
|
||||||
|
}
|
||||||
|
const owner = '${{inputs.repo-owner}}'
|
||||||
|
const repo = '${{inputs.repo-name}}'
|
||||||
|
const workflow_run_id = ${{steps.query_workflow.outputs.workflow_run}}
|
||||||
|
const workflow_job_id = ${{steps.query_workflow.outputs.workflow_job}}
|
||||||
|
let count = 0
|
||||||
|
while (count++<10) {
|
||||||
|
await sleep(30 * 1000);
|
||||||
|
let getRunResponse = await github.rest.actions.getWorkflowRun({
|
||||||
|
owner: owner,
|
||||||
|
repo: repo,
|
||||||
|
run_id: workflow_run_id
|
||||||
|
})
|
||||||
|
console.log(`${getRunResponse.data.html_url}: ${getRunResponse.data.status} (${getRunResponse.data.conclusion})`);
|
||||||
|
if (getRunResponse.data.status == 'completed') {
|
||||||
|
if ( getRunResponse.data.conclusion == 'success') {
|
||||||
|
console.log(`Workflow run finished properly.`)
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
core.setFailed(`The triggered workflow run finish with result ${getRunResponse.data.conclusion}`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
core.setFailed(`The triggered workflow run didn't finish properly using ${{inputs.arc-name}}`)
|
||||||
|
|
||||||
|
- name: Gather logs and cleanup
|
||||||
|
shell: bash
|
||||||
|
if: always()
|
||||||
|
run: |
|
||||||
|
helm uninstall ${{ inputs.arc-name }} --namespace ${{inputs.arc-namespace}} --debug
|
||||||
|
kubectl wait --timeout=10s --for=delete AutoScalingRunnerSet -n ${{inputs.arc-name}} -l app.kubernetes.io/instance=${{ inputs.arc-name }}
|
||||||
|
kubectl logs deployment/arc-gha-runner-scale-set-controller -n ${{inputs.arc-controller-namespace}}
|
||||||
63
.github/actions/setup-arc-e2e/action.yaml
vendored
Normal file
63
.github/actions/setup-arc-e2e/action.yaml
vendored
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
name: 'Setup ARC E2E Test Action'
|
||||||
|
description: 'Build controller image, create kind cluster, load the image, and exchange ARC configure token.'
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
app-id:
|
||||||
|
description: 'GitHub App Id for exchange access token'
|
||||||
|
required: true
|
||||||
|
app-pk:
|
||||||
|
description: "GitHub App private key for exchange access token"
|
||||||
|
required: true
|
||||||
|
image-name:
|
||||||
|
description: "Local docker image name for building"
|
||||||
|
required: true
|
||||||
|
image-tag:
|
||||||
|
description: "Tag of ARC Docker image for building"
|
||||||
|
required: true
|
||||||
|
target-org:
|
||||||
|
description: "The test organization for ARC e2e test"
|
||||||
|
required: true
|
||||||
|
|
||||||
|
outputs:
|
||||||
|
token:
|
||||||
|
description: 'Token to use for configure ARC'
|
||||||
|
value: ${{steps.config-token.outputs.token}}
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: "composite"
|
||||||
|
steps:
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
with:
|
||||||
|
# Pinning v0.9.1 for Buildx and BuildKit v0.10.6
|
||||||
|
# BuildKit v0.11 which has a bug causing intermittent
|
||||||
|
# failures pushing images to GHCR
|
||||||
|
version: v0.9.1
|
||||||
|
driver-opts: image=moby/buildkit:v0.10.6
|
||||||
|
|
||||||
|
- name: Build controller image
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
file: Dockerfile
|
||||||
|
platforms: linux/amd64
|
||||||
|
load: true
|
||||||
|
build-args: |
|
||||||
|
DOCKER_IMAGE_NAME=${{inputs.image-name}}
|
||||||
|
VERSION=${{inputs.image-tag}}
|
||||||
|
tags: |
|
||||||
|
${{inputs.image-name}}:${{inputs.image-tag}}
|
||||||
|
no-cache: true
|
||||||
|
|
||||||
|
- name: Create minikube cluster and load image
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
minikube start
|
||||||
|
minikube image load ${{inputs.image-name}}:${{inputs.image-tag}}
|
||||||
|
|
||||||
|
- name: Get configure token
|
||||||
|
id: config-token
|
||||||
|
uses: peter-murray/workflow-application-token-action@8e1ba3bf1619726336414f1014e37f17fbadf1db
|
||||||
|
with:
|
||||||
|
application_id: ${{ inputs.app-id }}
|
||||||
|
application_private_key: ${{ inputs.app-pk }}
|
||||||
|
organization: ${{ inputs.target-org}}
|
||||||
43
.github/renovate.json5
vendored
43
.github/renovate.json5
vendored
@@ -1,43 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": ["config:base"],
|
|
||||||
"labels": ["dependencies"],
|
|
||||||
"packageRules": [
|
|
||||||
{
|
|
||||||
// automatically merge an update of runner
|
|
||||||
"matchPackageNames": ["actions/runner"],
|
|
||||||
"extractVersion": "^v(?<version>.*)$",
|
|
||||||
"automerge": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"regexManagers": [
|
|
||||||
{
|
|
||||||
// use https://github.com/actions/runner/releases
|
|
||||||
"fileMatch": [
|
|
||||||
".github/workflows/runners.yaml"
|
|
||||||
],
|
|
||||||
"matchStrings": ["RUNNER_VERSION: +(?<currentValue>.*?)\\n"],
|
|
||||||
"depNameTemplate": "actions/runner",
|
|
||||||
"datasourceTemplate": "github-releases"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fileMatch": [
|
|
||||||
"runner/Makefile",
|
|
||||||
"Makefile"
|
|
||||||
],
|
|
||||||
"matchStrings": ["RUNNER_VERSION \\?= +(?<currentValue>.*?)\\n"],
|
|
||||||
"depNameTemplate": "actions/runner",
|
|
||||||
"datasourceTemplate": "github-releases"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fileMatch": [
|
|
||||||
"runner/actions-runner.ubuntu-20.04.dockerfile",
|
|
||||||
"runner/actions-runner.ubuntu-22.04.dockerfile",
|
|
||||||
"runner/actions-runner-dind.ubuntu-20.04.dockerfile",
|
|
||||||
"runner/actions-runner-dind-rootless.ubuntu-20.04.dockerfile"
|
|
||||||
],
|
|
||||||
"matchStrings": ["RUNNER_VERSION=+(?<currentValue>.*?)\\n"],
|
|
||||||
"depNameTemplate": "actions/runner",
|
|
||||||
"datasourceTemplate": "github-releases"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
name: ARC Reusable Workflow
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
date_time:
|
|
||||||
description: 'Datetime for runner name uniqueness, format: %Y-%m-%d-%H-%M-%S-%3N, example: 2023-02-14-13-00-16-791'
|
|
||||||
required: true
|
|
||||||
jobs:
|
|
||||||
arc-runner-job:
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
job: [1, 2, 3]
|
|
||||||
runs-on: arc-runner-${{ inputs.date_time }}
|
|
||||||
steps:
|
|
||||||
- run: echo "Hello World!" >> $GITHUB_STEP_SUMMARY
|
|
||||||
584
.github/workflows/e2e-test-linux-vm.yaml
vendored
584
.github/workflows/e2e-test-linux-vm.yaml
vendored
@@ -5,47 +5,563 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
pull_request:
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
env:
|
env:
|
||||||
TARGET_ORG: actions-runner-controller
|
TARGET_ORG: actions-runner-controller
|
||||||
CLUSTER_NAME: e2e-test
|
TARGET_REPO: arc_e2e_test_dummy
|
||||||
RUNNER_VERSION: 2.302.1
|
IMAGE_NAME: "arc-test-image"
|
||||||
IMAGE_REPO: "test/test-image"
|
IMAGE_VERSION: "dev"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
setup-steps:
|
default-setup:
|
||||||
runs-on: [ubuntu-latest]
|
runs-on: ubuntu-latest
|
||||||
|
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.id == github.repository_id
|
||||||
|
env:
|
||||||
|
WORKFLOW_FILE: "arc-test-workflow.yaml"
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Add env variables
|
|
||||||
run: |
|
|
||||||
TAG=$(echo "0.0.$GITHUB_SHA")
|
|
||||||
echo "TAG=$TAG" >> $GITHUB_ENV
|
|
||||||
echo "IMAGE=$IMAGE_REPO:$TAG" >> $GITHUB_ENV
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v2
|
|
||||||
with:
|
with:
|
||||||
version: latest
|
ref: ${{github.head_ref}}
|
||||||
- name: Docker Build Test Image
|
|
||||||
run: |
|
- uses: ./.github/actions/setup-arc-e2e
|
||||||
DOCKER_CLI_EXPERIMENTAL=enabled DOCKER_BUILDKIT=1 docker buildx build --build-arg RUNNER_VERSION=$RUNNER_VERSION --build-arg TAG=$TAG -t $IMAGE . --load
|
id: setup
|
||||||
- name: Create Kind cluster
|
|
||||||
run: |
|
|
||||||
PATH=$(go env GOPATH)/bin:$PATH
|
|
||||||
kind create cluster --name $CLUSTER_NAME
|
|
||||||
- name: Load Image to Kind Cluster
|
|
||||||
run: kind load docker-image $IMAGE --name $CLUSTER_NAME
|
|
||||||
- name: Get Token
|
|
||||||
id: get_workflow_token
|
|
||||||
uses: peter-murray/workflow-application-token-action@8e1ba3bf1619726336414f1014e37f17fbadf1db
|
|
||||||
with:
|
with:
|
||||||
application_id: ${{ secrets.ACTIONS_ACCESS_APP_ID }}
|
app-id: ${{secrets.E2E_TESTS_ACCESS_APP_ID}}
|
||||||
application_private_key: ${{ secrets.ACTIONS_ACCESS_PK }}
|
app-pk: ${{secrets.E2E_TESTS_ACCESS_PK}}
|
||||||
organization: ${{ env.TARGET_ORG }}
|
image-name: ${{env.IMAGE_NAME}}
|
||||||
- uses: ./.github/actions/e2e-arc-test
|
image-tag: ${{env.IMAGE_VERSION}}
|
||||||
|
target-org: ${{env.TARGET_ORG}}
|
||||||
|
|
||||||
|
- name: Install gha-runner-scale-set-controller
|
||||||
|
id: install_arc_controller
|
||||||
|
run: |
|
||||||
|
helm install arc \
|
||||||
|
--namespace "arc-systems" \
|
||||||
|
--create-namespace \
|
||||||
|
--set image.repository=${{ env.IMAGE_NAME }} \
|
||||||
|
--set image.tag=${{ env.IMAGE_VERSION }} \
|
||||||
|
./charts/gha-runner-scale-set-controller \
|
||||||
|
--debug
|
||||||
|
count=0
|
||||||
|
while true; do
|
||||||
|
POD_NAME=$(kubectl get pods -n arc-systems -l app.kubernetes.io/name=gha-runner-scale-set-controller -o name)
|
||||||
|
if [ -n "$POD_NAME" ]; then
|
||||||
|
echo "Pod found: $POD_NAME"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if [ "$count" -ge 10 ]; then
|
||||||
|
echo "Timeout waiting for controller pod with label app.kubernetes.io/name=gha-runner-scale-set-controller"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l app.kubernetes.io/name=gha-runner-scale-set-controller
|
||||||
|
kubectl get pod -n arc-systems
|
||||||
|
kubectl describe deployment arc-gha-runner-scale-set-controller -n arc-systems
|
||||||
|
|
||||||
|
- name: Install gha-runner-scale-set
|
||||||
|
id: install_arc
|
||||||
|
run: |
|
||||||
|
ARC_NAME=${{github.job}}-$(date +'%M%S')$((($RANDOM + 100) % 100 + 1))
|
||||||
|
helm install "$ARC_NAME" \
|
||||||
|
--namespace "arc-runners" \
|
||||||
|
--create-namespace \
|
||||||
|
--set githubConfigUrl="https://github.com/${{ env.TARGET_ORG }}/${{env.TARGET_REPO}}" \
|
||||||
|
--set githubConfigSecret.github_token="${{ steps.setup.outputs.token }}" \
|
||||||
|
./charts/gha-runner-scale-set \
|
||||||
|
--debug
|
||||||
|
echo "ARC_NAME=$ARC_NAME" >> $GITHUB_OUTPUT
|
||||||
|
count=0
|
||||||
|
while true; do
|
||||||
|
POD_NAME=$(kubectl get pods -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME -o name)
|
||||||
|
if [ -n "$POD_NAME" ]; then
|
||||||
|
echo "Pod found: $POD_NAME"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if [ "$count" -ge 10 ]; then
|
||||||
|
echo "Timeout waiting for listener pod with label actions.github.com/scale-set-name=$ARC_NAME"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME
|
||||||
|
kubectl get pod -n arc-systems
|
||||||
|
|
||||||
|
- name: Test ARC E2E
|
||||||
|
uses: ./.github/actions/execute-assert-arc-e2e
|
||||||
|
timeout-minutes: 10
|
||||||
with:
|
with:
|
||||||
github-token: ${{ steps.get_workflow_token.outputs.token }}
|
auth-token: ${{ steps.setup.outputs.token }}
|
||||||
config-url: "https://github.com/actions-runner-controller/arc_e2e_test_dummy"
|
repo-owner: ${{ env.TARGET_ORG }}
|
||||||
docker-image-repo: $IMAGE_REPO
|
repo-name: ${{env.TARGET_REPO}}
|
||||||
docker-image-tag: $TAG
|
workflow-file: ${{env.WORKFLOW_FILE}}
|
||||||
|
arc-name: ${{steps.install_arc.outputs.ARC_NAME}}
|
||||||
|
arc-namespace: "arc-runners"
|
||||||
|
arc-controller-namespace: "arc-systems"
|
||||||
|
|
||||||
|
single-namespace-setup:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.id == github.repository_id
|
||||||
|
env:
|
||||||
|
WORKFLOW_FILE: "arc-test-workflow.yaml"
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
ref: ${{github.head_ref}}
|
||||||
|
|
||||||
|
- uses: ./.github/actions/setup-arc-e2e
|
||||||
|
id: setup
|
||||||
|
with:
|
||||||
|
app-id: ${{secrets.E2E_TESTS_ACCESS_APP_ID}}
|
||||||
|
app-pk: ${{secrets.E2E_TESTS_ACCESS_PK}}
|
||||||
|
image-name: ${{env.IMAGE_NAME}}
|
||||||
|
image-tag: ${{env.IMAGE_VERSION}}
|
||||||
|
target-org: ${{env.TARGET_ORG}}
|
||||||
|
|
||||||
|
- name: Install gha-runner-scale-set-controller
|
||||||
|
id: install_arc_controller
|
||||||
|
run: |
|
||||||
|
kubectl create namespace arc-runners
|
||||||
|
helm install arc \
|
||||||
|
--namespace "arc-systems" \
|
||||||
|
--create-namespace \
|
||||||
|
--set image.repository=${{ env.IMAGE_NAME }} \
|
||||||
|
--set image.tag=${{ env.IMAGE_VERSION }} \
|
||||||
|
--set flags.watchSingleNamespace=arc-runners \
|
||||||
|
./charts/gha-runner-scale-set-controller \
|
||||||
|
--debug
|
||||||
|
count=0
|
||||||
|
while true; do
|
||||||
|
POD_NAME=$(kubectl get pods -n arc-systems -l app.kubernetes.io/name=gha-runner-scale-set-controller -o name)
|
||||||
|
if [ -n "$POD_NAME" ]; then
|
||||||
|
echo "Pod found: $POD_NAME"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if [ "$count" -ge 10 ]; then
|
||||||
|
echo "Timeout waiting for controller pod with label app.kubernetes.io/name=gha-runner-scale-set-controller"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l app.kubernetes.io/name=gha-runner-scale-set-controller
|
||||||
|
kubectl get pod -n arc-systems
|
||||||
|
kubectl describe deployment arc-gha-runner-scale-set-controller -n arc-systems
|
||||||
|
|
||||||
|
- name: Install gha-runner-scale-set
|
||||||
|
id: install_arc
|
||||||
|
run: |
|
||||||
|
ARC_NAME=${{github.job}}-$(date +'%M%S')$((($RANDOM + 100) % 100 + 1))
|
||||||
|
helm install "$ARC_NAME" \
|
||||||
|
--namespace "arc-runners" \
|
||||||
|
--create-namespace \
|
||||||
|
--set githubConfigUrl="https://github.com/${{ env.TARGET_ORG }}/${{env.TARGET_REPO}}" \
|
||||||
|
--set githubConfigSecret.github_token="${{ steps.setup.outputs.token }}" \
|
||||||
|
./charts/gha-runner-scale-set \
|
||||||
|
--debug
|
||||||
|
echo "ARC_NAME=$ARC_NAME" >> $GITHUB_OUTPUT
|
||||||
|
count=0
|
||||||
|
while true; do
|
||||||
|
POD_NAME=$(kubectl get pods -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME -o name)
|
||||||
|
if [ -n "$POD_NAME" ]; then
|
||||||
|
echo "Pod found: $POD_NAME"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if [ "$count" -ge 10 ]; then
|
||||||
|
echo "Timeout waiting for listener pod with label actions.github.com/scale-set-name=$ARC_NAME"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME
|
||||||
|
kubectl get pod -n arc-systems
|
||||||
|
|
||||||
|
- name: Test ARC E2E
|
||||||
|
uses: ./.github/actions/execute-assert-arc-e2e
|
||||||
|
timeout-minutes: 10
|
||||||
|
with:
|
||||||
|
auth-token: ${{ steps.setup.outputs.token }}
|
||||||
|
repo-owner: ${{ env.TARGET_ORG }}
|
||||||
|
repo-name: ${{env.TARGET_REPO}}
|
||||||
|
workflow-file: ${{env.WORKFLOW_FILE}}
|
||||||
|
arc-name: ${{steps.install_arc.outputs.ARC_NAME}}
|
||||||
|
arc-namespace: "arc-runners"
|
||||||
|
arc-controller-namespace: "arc-systems"
|
||||||
|
|
||||||
|
dind-mode-setup:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.id == github.repository_id
|
||||||
|
env:
|
||||||
|
WORKFLOW_FILE: arc-test-dind-workflow.yaml
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
ref: ${{github.head_ref}}
|
||||||
|
|
||||||
|
- uses: ./.github/actions/setup-arc-e2e
|
||||||
|
id: setup
|
||||||
|
with:
|
||||||
|
app-id: ${{secrets.E2E_TESTS_ACCESS_APP_ID}}
|
||||||
|
app-pk: ${{secrets.E2E_TESTS_ACCESS_PK}}
|
||||||
|
image-name: ${{env.IMAGE_NAME}}
|
||||||
|
image-tag: ${{env.IMAGE_VERSION}}
|
||||||
|
target-org: ${{env.TARGET_ORG}}
|
||||||
|
|
||||||
|
- name: Install gha-runner-scale-set-controller
|
||||||
|
id: install_arc_controller
|
||||||
|
run: |
|
||||||
|
helm install arc \
|
||||||
|
--namespace "arc-systems" \
|
||||||
|
--create-namespace \
|
||||||
|
--set image.repository=${{ env.IMAGE_NAME }} \
|
||||||
|
--set image.tag=${{ env.IMAGE_VERSION }} \
|
||||||
|
./charts/gha-runner-scale-set-controller \
|
||||||
|
--debug
|
||||||
|
count=0
|
||||||
|
while true; do
|
||||||
|
POD_NAME=$(kubectl get pods -n arc-systems -l app.kubernetes.io/name=gha-runner-scale-set-controller -o name)
|
||||||
|
if [ -n "$POD_NAME" ]; then
|
||||||
|
echo "Pod found: $POD_NAME"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if [ "$count" -ge 10 ]; then
|
||||||
|
echo "Timeout waiting for controller pod with label app.kubernetes.io/name=gha-runner-scale-set-controller"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l app.kubernetes.io/name=gha-runner-scale-set-controller
|
||||||
|
kubectl get pod -n arc-systems
|
||||||
|
kubectl describe deployment arc-gha-runner-scale-set-controller -n arc-systems
|
||||||
|
|
||||||
|
- name: Install gha-runner-scale-set
|
||||||
|
id: install_arc
|
||||||
|
run: |
|
||||||
|
ARC_NAME=${{github.job}}-$(date +'%M%S')$((($RANDOM + 100) % 100 + 1))
|
||||||
|
helm install "$ARC_NAME" \
|
||||||
|
--namespace "arc-runners" \
|
||||||
|
--create-namespace \
|
||||||
|
--set githubConfigUrl="https://github.com/${{ env.TARGET_ORG }}/${{env.TARGET_REPO}}" \
|
||||||
|
--set githubConfigSecret.github_token="${{ steps.setup.outputs.token }}" \
|
||||||
|
--set containerMode.type="dind" \
|
||||||
|
./charts/gha-runner-scale-set \
|
||||||
|
--debug
|
||||||
|
echo "ARC_NAME=$ARC_NAME" >> $GITHUB_OUTPUT
|
||||||
|
count=0
|
||||||
|
while true; do
|
||||||
|
POD_NAME=$(kubectl get pods -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME -o name)
|
||||||
|
if [ -n "$POD_NAME" ]; then
|
||||||
|
echo "Pod found: $POD_NAME"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if [ "$count" -ge 10 ]; then
|
||||||
|
echo "Timeout waiting for listener pod with label actions.github.com/scale-set-name=$ARC_NAME"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME
|
||||||
|
kubectl get pod -n arc-systems
|
||||||
|
|
||||||
|
- name: Test ARC E2E
|
||||||
|
uses: ./.github/actions/execute-assert-arc-e2e
|
||||||
|
timeout-minutes: 10
|
||||||
|
with:
|
||||||
|
auth-token: ${{ steps.setup.outputs.token }}
|
||||||
|
repo-owner: ${{ env.TARGET_ORG }}
|
||||||
|
repo-name: ${{env.TARGET_REPO}}
|
||||||
|
workflow-file: ${{env.WORKFLOW_FILE}}
|
||||||
|
arc-name: ${{steps.install_arc.outputs.ARC_NAME}}
|
||||||
|
arc-namespace: "arc-runners"
|
||||||
|
arc-controller-namespace: "arc-systems"
|
||||||
|
|
||||||
|
kubernetes-mode-setup:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.id == github.repository_id
|
||||||
|
env:
|
||||||
|
WORKFLOW_FILE: "arc-test-kubernetes-workflow.yaml"
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
ref: ${{github.head_ref}}
|
||||||
|
|
||||||
|
- uses: ./.github/actions/setup-arc-e2e
|
||||||
|
id: setup
|
||||||
|
with:
|
||||||
|
app-id: ${{secrets.E2E_TESTS_ACCESS_APP_ID}}
|
||||||
|
app-pk: ${{secrets.E2E_TESTS_ACCESS_PK}}
|
||||||
|
image-name: ${{env.IMAGE_NAME}}
|
||||||
|
image-tag: ${{env.IMAGE_VERSION}}
|
||||||
|
target-org: ${{env.TARGET_ORG}}
|
||||||
|
|
||||||
|
- name: Install gha-runner-scale-set-controller
|
||||||
|
id: install_arc_controller
|
||||||
|
run: |
|
||||||
|
echo "Install openebs/dynamic-localpv-provisioner"
|
||||||
|
helm repo add openebs https://openebs.github.io/charts
|
||||||
|
helm repo update
|
||||||
|
helm install openebs openebs/openebs -n openebs --create-namespace
|
||||||
|
|
||||||
|
helm install arc \
|
||||||
|
--namespace "arc-systems" \
|
||||||
|
--create-namespace \
|
||||||
|
--set image.repository=${{ env.IMAGE_NAME }} \
|
||||||
|
--set image.tag=${{ env.IMAGE_VERSION }} \
|
||||||
|
./charts/gha-runner-scale-set-controller \
|
||||||
|
--debug
|
||||||
|
count=0
|
||||||
|
while true; do
|
||||||
|
POD_NAME=$(kubectl get pods -n arc-systems -l app.kubernetes.io/name=gha-runner-scale-set-controller -o name)
|
||||||
|
if [ -n "$POD_NAME" ]; then
|
||||||
|
echo "Pod found: $POD_NAME"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if [ "$count" -ge 10 ]; then
|
||||||
|
echo "Timeout waiting for controller pod with label app.kubernetes.io/name=gha-runner-scale-set-controller"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l app.kubernetes.io/name=gha-runner-scale-set-controller
|
||||||
|
kubectl get pod -n arc-systems
|
||||||
|
kubectl describe deployment arc-gha-runner-scale-set-controller -n arc-systems
|
||||||
|
kubectl wait --timeout=30s --for=condition=ready pod -n openebs -l name=openebs-localpv-provisioner
|
||||||
|
|
||||||
|
- name: Install gha-runner-scale-set
|
||||||
|
id: install_arc
|
||||||
|
run: |
|
||||||
|
ARC_NAME=${{github.job}}-$(date +'%M%S')$((($RANDOM + 100) % 100 + 1))
|
||||||
|
helm install "$ARC_NAME" \
|
||||||
|
--namespace "arc-runners" \
|
||||||
|
--create-namespace \
|
||||||
|
--set githubConfigUrl="https://github.com/${{ env.TARGET_ORG }}/${{env.TARGET_REPO}}" \
|
||||||
|
--set githubConfigSecret.github_token="${{ steps.setup.outputs.token }}" \
|
||||||
|
--set containerMode.type="kubernetes" \
|
||||||
|
--set containerMode.kubernetesModeWorkVolumeClaim.accessModes={"ReadWriteOnce"} \
|
||||||
|
--set containerMode.kubernetesModeWorkVolumeClaim.storageClassName="openebs-hostpath" \
|
||||||
|
--set containerMode.kubernetesModeWorkVolumeClaim.resources.requests.storage="1Gi" \
|
||||||
|
./charts/gha-runner-scale-set \
|
||||||
|
--debug
|
||||||
|
echo "ARC_NAME=$ARC_NAME" >> $GITHUB_OUTPUT
|
||||||
|
count=0
|
||||||
|
while true; do
|
||||||
|
POD_NAME=$(kubectl get pods -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME -o name)
|
||||||
|
if [ -n "$POD_NAME" ]; then
|
||||||
|
echo "Pod found: $POD_NAME"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if [ "$count" -ge 10 ]; then
|
||||||
|
echo "Timeout waiting for listener pod with label actions.github.com/scale-set-name=$ARC_NAME"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME
|
||||||
|
kubectl get pod -n arc-systems
|
||||||
|
|
||||||
|
- name: Test ARC E2E
|
||||||
|
uses: ./.github/actions/execute-assert-arc-e2e
|
||||||
|
timeout-minutes: 10
|
||||||
|
with:
|
||||||
|
auth-token: ${{ steps.setup.outputs.token }}
|
||||||
|
repo-owner: ${{ env.TARGET_ORG }}
|
||||||
|
repo-name: ${{env.TARGET_REPO}}
|
||||||
|
workflow-file: ${{env.WORKFLOW_FILE}}
|
||||||
|
arc-name: ${{steps.install_arc.outputs.ARC_NAME}}
|
||||||
|
arc-namespace: "arc-runners"
|
||||||
|
arc-controller-namespace: "arc-systems"
|
||||||
|
|
||||||
|
auth-proxy-setup:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.id == github.repository_id
|
||||||
|
env:
|
||||||
|
WORKFLOW_FILE: "arc-test-workflow.yaml"
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
ref: ${{github.head_ref}}
|
||||||
|
|
||||||
|
- uses: ./.github/actions/setup-arc-e2e
|
||||||
|
id: setup
|
||||||
|
with:
|
||||||
|
app-id: ${{secrets.E2E_TESTS_ACCESS_APP_ID}}
|
||||||
|
app-pk: ${{secrets.E2E_TESTS_ACCESS_PK}}
|
||||||
|
image-name: ${{env.IMAGE_NAME}}
|
||||||
|
image-tag: ${{env.IMAGE_VERSION}}
|
||||||
|
target-org: ${{env.TARGET_ORG}}
|
||||||
|
|
||||||
|
- name: Install gha-runner-scale-set-controller
|
||||||
|
id: install_arc_controller
|
||||||
|
run: |
|
||||||
|
helm install arc \
|
||||||
|
--namespace "arc-systems" \
|
||||||
|
--create-namespace \
|
||||||
|
--set image.repository=${{ env.IMAGE_NAME }} \
|
||||||
|
--set image.tag=${{ env.IMAGE_VERSION }} \
|
||||||
|
./charts/gha-runner-scale-set-controller \
|
||||||
|
--debug
|
||||||
|
count=0
|
||||||
|
while true; do
|
||||||
|
POD_NAME=$(kubectl get pods -n arc-systems -l app.kubernetes.io/name=gha-runner-scale-set-controller -o name)
|
||||||
|
if [ -n "$POD_NAME" ]; then
|
||||||
|
echo "Pod found: $POD_NAME"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if [ "$count" -ge 10 ]; then
|
||||||
|
echo "Timeout waiting for controller pod with label app.kubernetes.io/name=gha-runner-scale-set-controller"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l app.kubernetes.io/name=gha-runner-scale-set-controller
|
||||||
|
kubectl get pod -n arc-systems
|
||||||
|
kubectl describe deployment arc-gha-runner-scale-set-controller -n arc-systems
|
||||||
|
|
||||||
|
- name: Install gha-runner-scale-set
|
||||||
|
id: install_arc
|
||||||
|
run: |
|
||||||
|
docker run -d \
|
||||||
|
--name squid \
|
||||||
|
--publish 3128:3128 \
|
||||||
|
huangtingluo/squid-proxy:latest
|
||||||
|
kubectl create namespace arc-runners
|
||||||
|
kubectl create secret generic proxy-auth \
|
||||||
|
--namespace=arc-runners \
|
||||||
|
--from-literal=username=github \
|
||||||
|
--from-literal=password='actions'
|
||||||
|
ARC_NAME=${{github.job}}-$(date +'%M%S')$((($RANDOM + 100) % 100 + 1))
|
||||||
|
helm install "$ARC_NAME" \
|
||||||
|
--namespace "arc-runners" \
|
||||||
|
--create-namespace \
|
||||||
|
--set githubConfigUrl="https://github.com/${{ env.TARGET_ORG }}/${{env.TARGET_REPO}}" \
|
||||||
|
--set githubConfigSecret.github_token="${{ steps.setup.outputs.token }}" \
|
||||||
|
--set proxy.https.url="http://host.minikube.internal:3128" \
|
||||||
|
--set proxy.https.credentialSecretRef="proxy-auth" \
|
||||||
|
--set "proxy.noProxy[0]=10.96.0.1:443" \
|
||||||
|
./charts/gha-runner-scale-set \
|
||||||
|
--debug
|
||||||
|
echo "ARC_NAME=$ARC_NAME" >> $GITHUB_OUTPUT
|
||||||
|
count=0
|
||||||
|
while true; do
|
||||||
|
POD_NAME=$(kubectl get pods -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME -o name)
|
||||||
|
if [ -n "$POD_NAME" ]; then
|
||||||
|
echo "Pod found: $POD_NAME"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if [ "$count" -ge 10 ]; then
|
||||||
|
echo "Timeout waiting for listener pod with label actions.github.com/scale-set-name=$ARC_NAME"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME
|
||||||
|
kubectl get pod -n arc-systems
|
||||||
|
|
||||||
|
- name: Test ARC E2E
|
||||||
|
uses: ./.github/actions/execute-assert-arc-e2e
|
||||||
|
timeout-minutes: 10
|
||||||
|
with:
|
||||||
|
auth-token: ${{ steps.setup.outputs.token }}
|
||||||
|
repo-owner: ${{ env.TARGET_ORG }}
|
||||||
|
repo-name: ${{env.TARGET_REPO}}
|
||||||
|
workflow-file: ${{env.WORKFLOW_FILE}}
|
||||||
|
arc-name: ${{steps.install_arc.outputs.ARC_NAME}}
|
||||||
|
arc-namespace: "arc-runners"
|
||||||
|
arc-controller-namespace: "arc-systems"
|
||||||
|
|
||||||
|
anonymous-proxy-setup:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.id == github.repository_id
|
||||||
|
env:
|
||||||
|
WORKFLOW_FILE: "arc-test-workflow.yaml"
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
ref: ${{github.head_ref}}
|
||||||
|
|
||||||
|
- uses: ./.github/actions/setup-arc-e2e
|
||||||
|
id: setup
|
||||||
|
with:
|
||||||
|
app-id: ${{secrets.E2E_TESTS_ACCESS_APP_ID}}
|
||||||
|
app-pk: ${{secrets.E2E_TESTS_ACCESS_PK}}
|
||||||
|
image-name: ${{env.IMAGE_NAME}}
|
||||||
|
image-tag: ${{env.IMAGE_VERSION}}
|
||||||
|
target-org: ${{env.TARGET_ORG}}
|
||||||
|
|
||||||
|
- name: Install gha-runner-scale-set-controller
|
||||||
|
id: install_arc_controller
|
||||||
|
run: |
|
||||||
|
helm install arc \
|
||||||
|
--namespace "arc-systems" \
|
||||||
|
--create-namespace \
|
||||||
|
--set image.repository=${{ env.IMAGE_NAME }} \
|
||||||
|
--set image.tag=${{ env.IMAGE_VERSION }} \
|
||||||
|
./charts/gha-runner-scale-set-controller \
|
||||||
|
--debug
|
||||||
|
count=0
|
||||||
|
while true; do
|
||||||
|
POD_NAME=$(kubectl get pods -n arc-systems -l app.kubernetes.io/name=gha-runner-scale-set-controller -o name)
|
||||||
|
if [ -n "$POD_NAME" ]; then
|
||||||
|
echo "Pod found: $POD_NAME"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if [ "$count" -ge 10 ]; then
|
||||||
|
echo "Timeout waiting for controller pod with label app.kubernetes.io/name=gha-runner-scale-set-controller"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l app.kubernetes.io/name=gha-runner-scale-set-controller
|
||||||
|
kubectl get pod -n arc-systems
|
||||||
|
kubectl describe deployment arc-gha-runner-scale-set-controller -n arc-systems
|
||||||
|
|
||||||
|
- name: Install gha-runner-scale-set
|
||||||
|
id: install_arc
|
||||||
|
run: |
|
||||||
|
docker run -d \
|
||||||
|
--name squid \
|
||||||
|
--publish 3128:3128 \
|
||||||
|
ubuntu/squid:latest
|
||||||
|
ARC_NAME=${{github.job}}-$(date +'%M%S')$((($RANDOM + 100) % 100 + 1))
|
||||||
|
helm install "$ARC_NAME" \
|
||||||
|
--namespace "arc-runners" \
|
||||||
|
--create-namespace \
|
||||||
|
--set githubConfigUrl="https://github.com/${{ env.TARGET_ORG }}/${{env.TARGET_REPO}}" \
|
||||||
|
--set githubConfigSecret.github_token="${{ steps.setup.outputs.token }}" \
|
||||||
|
--set proxy.https.url="http://host.minikube.internal:3128" \
|
||||||
|
--set "proxy.noProxy[0]=10.96.0.1:443" \
|
||||||
|
./charts/gha-runner-scale-set \
|
||||||
|
--debug
|
||||||
|
echo "ARC_NAME=$ARC_NAME" >> $GITHUB_OUTPUT
|
||||||
|
count=0
|
||||||
|
while true; do
|
||||||
|
POD_NAME=$(kubectl get pods -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME -o name)
|
||||||
|
if [ -n "$POD_NAME" ]; then
|
||||||
|
echo "Pod found: $POD_NAME"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if [ "$count" -ge 10 ]; then
|
||||||
|
echo "Timeout waiting for listener pod with label actions.github.com/scale-set-name=$ARC_NAME"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME
|
||||||
|
kubectl get pod -n arc-systems
|
||||||
|
|
||||||
|
- name: Test ARC E2E
|
||||||
|
uses: ./.github/actions/execute-assert-arc-e2e
|
||||||
|
timeout-minutes: 10
|
||||||
|
with:
|
||||||
|
auth-token: ${{ steps.setup.outputs.token }}
|
||||||
|
repo-owner: ${{ env.TARGET_ORG }}
|
||||||
|
repo-name: ${{env.TARGET_REPO}}
|
||||||
|
workflow-file: ${{env.WORKFLOW_FILE}}
|
||||||
|
arc-name: ${{steps.install_arc.outputs.ARC_NAME}}
|
||||||
|
arc-namespace: "arc-runners"
|
||||||
|
arc-controller-namespace: "arc-systems"
|
||||||
|
|||||||
80
.github/workflows/go.yaml
vendored
Normal file
80
.github/workflows/go.yaml
vendored
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
name: Go
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
paths:
|
||||||
|
- '.github/workflows/go.yaml'
|
||||||
|
- '**.go'
|
||||||
|
- 'go.mod'
|
||||||
|
- 'go.sum'
|
||||||
|
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- '.github/workflows/go.yaml'
|
||||||
|
- '**.go'
|
||||||
|
- 'go.mod'
|
||||||
|
- 'go.sum'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
fmt:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions/setup-go@v4
|
||||||
|
with:
|
||||||
|
go-version-file: 'go.mod'
|
||||||
|
cache: false
|
||||||
|
- name: fmt
|
||||||
|
run: go fmt ./...
|
||||||
|
- name: Check diff
|
||||||
|
run: git diff --exit-code
|
||||||
|
|
||||||
|
lint:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions/setup-go@v4
|
||||||
|
with:
|
||||||
|
go-version-file: 'go.mod'
|
||||||
|
cache: false
|
||||||
|
- name: golangci-lint
|
||||||
|
uses: golangci/golangci-lint-action@v3
|
||||||
|
with:
|
||||||
|
only-new-issues: true
|
||||||
|
version: v1.51.1
|
||||||
|
|
||||||
|
generate:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions/setup-go@v4
|
||||||
|
with:
|
||||||
|
go-version-file: 'go.mod'
|
||||||
|
cache: false
|
||||||
|
- name: Generate
|
||||||
|
run: make generate
|
||||||
|
- name: Check diff
|
||||||
|
run: git diff --exit-code
|
||||||
|
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions/setup-go@v4
|
||||||
|
with:
|
||||||
|
go-version-file: 'go.mod'
|
||||||
|
- run: make manifests
|
||||||
|
- name: Check diff
|
||||||
|
run: git diff --exit-code
|
||||||
|
- name: Install kubebuilder
|
||||||
|
run: |
|
||||||
|
curl -L -O https://github.com/kubernetes-sigs/kubebuilder/releases/download/v2.3.2/kubebuilder_2.3.2_linux_amd64.tar.gz
|
||||||
|
tar zxvf kubebuilder_2.3.2_linux_amd64.tar.gz
|
||||||
|
sudo mv kubebuilder_2.3.2_linux_amd64 /usr/local/kubebuilder
|
||||||
|
- name: Run go tests
|
||||||
|
run: |
|
||||||
|
go test -short `go list ./... | grep -v ./test_e2e_arc`
|
||||||
23
.github/workflows/golangci-lint.yaml
vendored
23
.github/workflows/golangci-lint.yaml
vendored
@@ -1,23 +0,0 @@
|
|||||||
name: golangci-lint
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
pull_request:
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: read
|
|
||||||
jobs:
|
|
||||||
golangci:
|
|
||||||
name: lint
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/setup-go@v3
|
|
||||||
with:
|
|
||||||
go-version: 1.19
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: golangci-lint
|
|
||||||
uses: golangci/golangci-lint-action@v3
|
|
||||||
with:
|
|
||||||
only-new-issues: true
|
|
||||||
version: v1.49.0
|
|
||||||
4
.github/workflows/publish-arc.yaml
vendored
4
.github/workflows/publish-arc.yaml
vendored
@@ -29,6 +29,10 @@ jobs:
|
|||||||
release-controller:
|
release-controller:
|
||||||
name: Release
|
name: Release
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
# gha-runner-scale-set has its own release workflow.
|
||||||
|
# We don't want to publish a new actions-runner-controller image
|
||||||
|
# we release gha-runner-scale-set.
|
||||||
|
if: ${{ !startsWith(github.event.inputs.release_tag_name, 'gha-runner-scale-set-') }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|||||||
85
.github/workflows/publish-canary.yaml
vendored
85
.github/workflows/publish-canary.yaml
vendored
@@ -8,35 +8,47 @@ on:
|
|||||||
- master
|
- master
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- '**.md'
|
- '**.md'
|
||||||
|
- '.github/actions/**'
|
||||||
- '.github/ISSUE_TEMPLATE/**'
|
- '.github/ISSUE_TEMPLATE/**'
|
||||||
- '.github/workflows/validate-chart.yaml'
|
- '.github/workflows/e2e-test-dispatch-workflow.yaml'
|
||||||
- '.github/workflows/publish-chart.yaml'
|
- '.github/workflows/e2e-test-linux-vm.yaml'
|
||||||
- '.github/workflows/publish-arc.yaml'
|
- '.github/workflows/publish-arc.yaml'
|
||||||
- '.github/workflows/runners.yaml'
|
- '.github/workflows/publish-chart.yaml'
|
||||||
- '.github/workflows/validate-entrypoint.yaml'
|
- '.github/workflows/publish-runner-scale-set.yaml'
|
||||||
- '.github/renovate.*'
|
- '.github/workflows/release-runners.yaml'
|
||||||
|
- '.github/workflows/run-codeql.yaml'
|
||||||
|
- '.github/workflows/run-first-interaction.yaml'
|
||||||
|
- '.github/workflows/run-stale.yaml'
|
||||||
|
- '.github/workflows/update-runners.yaml'
|
||||||
|
- '.github/workflows/validate-arc.yaml'
|
||||||
|
- '.github/workflows/validate-chart.yaml'
|
||||||
|
- '.github/workflows/validate-gha-chart.yaml'
|
||||||
|
- '.github/workflows/validate-runners.yaml'
|
||||||
|
- '.github/dependabot.yml'
|
||||||
|
- '.github/RELEASE_NOTE_TEMPLATE.md'
|
||||||
- 'runner/**'
|
- 'runner/**'
|
||||||
- '.gitignore'
|
- '.gitignore'
|
||||||
- 'PROJECT'
|
- 'PROJECT'
|
||||||
- 'LICENSE'
|
- 'LICENSE'
|
||||||
- 'Makefile'
|
- 'Makefile'
|
||||||
|
|
||||||
env:
|
|
||||||
# Safeguard to prevent pushing images to registeries after build
|
|
||||||
PUSH_TO_REGISTRIES: true
|
|
||||||
TARGET_ORG: actions-runner-controller
|
|
||||||
TARGET_REPO: actions-runner-controller
|
|
||||||
|
|
||||||
# https://docs.github.com/en/rest/overview/permissions-required-for-github-apps
|
# https://docs.github.com/en/rest/overview/permissions-required-for-github-apps
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
packages: write
|
||||||
|
|
||||||
|
env:
|
||||||
|
# Safeguard to prevent pushing images to registeries after build
|
||||||
|
PUSH_TO_REGISTRIES: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
canary-build:
|
legacy-canary-build:
|
||||||
name: Build and Publish Canary Image
|
name: Build and Publish Legacy Canary Image
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
|
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
TARGET_ORG: actions-runner-controller
|
||||||
|
TARGET_REPO: actions-runner-controller
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
@@ -68,3 +80,50 @@ jobs:
|
|||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "**Status:**" >> $GITHUB_STEP_SUMMARY
|
echo "**Status:**" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "[https://github.com/actions-runner-controller/releases/actions/workflows/publish-canary.yaml](https://github.com/actions-runner-controller/releases/actions/workflows/publish-canary.yaml)" >> $GITHUB_STEP_SUMMARY
|
echo "[https://github.com/actions-runner-controller/releases/actions/workflows/publish-canary.yaml](https://github.com/actions-runner-controller/releases/actions/workflows/publish-canary.yaml)" >> $GITHUB_STEP_SUMMARY
|
||||||
|
|
||||||
|
canary-build:
|
||||||
|
name: Build and Publish gha-runner-scale-set-controller Canary Image
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Login to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
# Normalization is needed because upper case characters are not allowed in the repository name
|
||||||
|
# and the short sha is needed for image tagging
|
||||||
|
- name: Resolve parameters
|
||||||
|
id: resolve_parameters
|
||||||
|
run: |
|
||||||
|
echo "INFO: Resolving short sha"
|
||||||
|
echo "short_sha=$(git rev-parse --short ${{ github.ref }})" >> $GITHUB_OUTPUT
|
||||||
|
echo "INFO: Normalizing repository name (lowercase)"
|
||||||
|
echo "repository_owner=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
with:
|
||||||
|
version: latest
|
||||||
|
|
||||||
|
# Unstable builds - run at your own risk
|
||||||
|
- name: Build and Push
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ./Dockerfile
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
build-args: VERSION=canary-"${{ github.ref }}"
|
||||||
|
push: ${{ env.PUSH_TO_REGISTRIES }}
|
||||||
|
tags: |
|
||||||
|
ghcr.io/${{ steps.resolve_parameters.outputs.repository_owner }}/gha-runner-scale-set-controller:canary
|
||||||
|
ghcr.io/${{ steps.resolve_parameters.outputs.repository_owner }}/gha-runner-scale-set-controller:canary-${{ steps.resolve_parameters.outputs.short_sha }}
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
24
.github/workflows/publish-chart.yaml
vendored
24
.github/workflows/publish-chart.yaml
vendored
@@ -20,7 +20,7 @@ env:
|
|||||||
HELM_VERSION: v3.8.0
|
HELM_VERSION: v3.8.0
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: write
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lint-chart:
|
lint-chart:
|
||||||
@@ -173,10 +173,28 @@ jobs:
|
|||||||
--pages-branch 'gh-pages' \
|
--pages-branch 'gh-pages' \
|
||||||
--pages-index-path 'index.yaml'
|
--pages-index-path 'index.yaml'
|
||||||
|
|
||||||
|
# This step is required to not throw away changes made to the index.yaml on every new chart release.
|
||||||
|
#
|
||||||
|
# We update the index.yaml in the actions-runner-controller.github.io repo
|
||||||
|
# by appending the new chart version to the index.yaml saved in actions-runner-controller repo
|
||||||
|
# and copying and commiting the updated index.yaml to the github.io one.
|
||||||
|
# See below for more context:
|
||||||
|
# - https://github.com/actions-runner-controller/actions-runner-controller.github.io/pull/2
|
||||||
|
# - https://github.com/actions/actions-runner-controller/pull/2452
|
||||||
|
- name: Commit and push to actions/actions-runner-controller
|
||||||
|
run: |
|
||||||
|
git checkout gh-pages
|
||||||
|
git config user.name "$GITHUB_ACTOR"
|
||||||
|
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
|
||||||
|
git add .
|
||||||
|
git commit -m "Update index.yaml"
|
||||||
|
git push
|
||||||
|
working-directory: ${{ github.workspace }}
|
||||||
|
|
||||||
# Chart Release was never intended to publish to a different repo
|
# Chart Release was never intended to publish to a different repo
|
||||||
# this workaround is intended to move the index.yaml to the target repo
|
# this workaround is intended to move the index.yaml to the target repo
|
||||||
# where the github pages are hosted
|
# where the github pages are hosted
|
||||||
- name: Checkout pages repository
|
- name: Checkout target repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
repository: ${{ env.CHART_TARGET_ORG }}/${{ env.CHART_TARGET_REPO }}
|
repository: ${{ env.CHART_TARGET_ORG }}/${{ env.CHART_TARGET_REPO }}
|
||||||
@@ -188,7 +206,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
cp ${{ github.workspace }}/index.yaml ${{ env.CHART_TARGET_REPO }}/actions-runner-controller/index.yaml
|
cp ${{ github.workspace }}/index.yaml ${{ env.CHART_TARGET_REPO }}/actions-runner-controller/index.yaml
|
||||||
|
|
||||||
- name: Commit and push
|
- name: Commit and push to target repository
|
||||||
run: |
|
run: |
|
||||||
git config user.name "$GITHUB_ACTOR"
|
git config user.name "$GITHUB_ACTOR"
|
||||||
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
|
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
|
||||||
|
|||||||
2
.github/workflows/release-runners.yaml
vendored
2
.github/workflows/release-runners.yaml
vendored
@@ -17,7 +17,7 @@ env:
|
|||||||
PUSH_TO_REGISTRIES: true
|
PUSH_TO_REGISTRIES: true
|
||||||
TARGET_ORG: actions-runner-controller
|
TARGET_ORG: actions-runner-controller
|
||||||
TARGET_WORKFLOW: release-runners.yaml
|
TARGET_WORKFLOW: release-runners.yaml
|
||||||
DOCKER_VERSION: 20.10.21
|
DOCKER_VERSION: 20.10.23
|
||||||
RUNNER_CONTAINER_HOOKS_VERSION: 0.2.0
|
RUNNER_CONTAINER_HOOKS_VERSION: 0.2.0
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|||||||
3
.github/workflows/update-runners.yaml
vendored
3
.github/workflows/update-runners.yaml
vendored
@@ -77,6 +77,7 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
contents: write
|
contents: write
|
||||||
|
actions: write
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ github.token }}
|
GH_TOKEN: ${{ github.token }}
|
||||||
CURRENT_VERSION: ${{ needs.check_versions.outputs.current_version }}
|
CURRENT_VERSION: ${{ needs.check_versions.outputs.current_version }}
|
||||||
@@ -93,7 +94,7 @@ jobs:
|
|||||||
sed -i "s/$CURRENT_VERSION/$LATEST_VERSION/g" runner/Makefile
|
sed -i "s/$CURRENT_VERSION/$LATEST_VERSION/g" runner/Makefile
|
||||||
sed -i "s/$CURRENT_VERSION/$LATEST_VERSION/g" Makefile
|
sed -i "s/$CURRENT_VERSION/$LATEST_VERSION/g" Makefile
|
||||||
sed -i "s/$CURRENT_VERSION/$LATEST_VERSION/g" test/e2e/e2e_test.go
|
sed -i "s/$CURRENT_VERSION/$LATEST_VERSION/g" test/e2e/e2e_test.go
|
||||||
sed -i "s/$CURRENT_VERSION/$LATEST_VERSION/g" .github/workflows/e2e_test_linux_vm.yaml
|
sed -i "s/$CURRENT_VERSION/$LATEST_VERSION/g" .github/workflows/e2e-test-linux-vm.yaml
|
||||||
|
|
||||||
- name: Commit changes
|
- name: Commit changes
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
60
.github/workflows/validate-arc.yaml
vendored
60
.github/workflows/validate-arc.yaml
vendored
@@ -1,60 +0,0 @@
|
|||||||
name: Validate ARC
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
paths-ignore:
|
|
||||||
- '**.md'
|
|
||||||
- '.github/ISSUE_TEMPLATE/**'
|
|
||||||
- '.github/workflows/publish-canary.yaml'
|
|
||||||
- '.github/workflows/validate-chart.yaml'
|
|
||||||
- '.github/workflows/publish-chart.yaml'
|
|
||||||
- '.github/workflows/runners.yaml'
|
|
||||||
- '.github/workflows/publish-arc.yaml'
|
|
||||||
- '.github/workflows/validate-entrypoint.yaml'
|
|
||||||
- '.github/renovate.*'
|
|
||||||
- 'runner/**'
|
|
||||||
- '.gitignore'
|
|
||||||
- 'PROJECT'
|
|
||||||
- 'LICENSE'
|
|
||||||
- 'Makefile'
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test-controller:
|
|
||||||
name: Test ARC
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Set-up Go
|
|
||||||
uses: actions/setup-go@v3
|
|
||||||
with:
|
|
||||||
go-version: '1.19'
|
|
||||||
check-latest: false
|
|
||||||
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/go/pkg/mod
|
|
||||||
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-go-
|
|
||||||
|
|
||||||
- name: Install kubebuilder
|
|
||||||
run: |
|
|
||||||
curl -L -O https://github.com/kubernetes-sigs/kubebuilder/releases/download/v2.3.2/kubebuilder_2.3.2_linux_amd64.tar.gz
|
|
||||||
tar zxvf kubebuilder_2.3.2_linux_amd64.tar.gz
|
|
||||||
sudo mv kubebuilder_2.3.2_linux_amd64 /usr/local/kubebuilder
|
|
||||||
|
|
||||||
- name: Run tests
|
|
||||||
run: |
|
|
||||||
make test
|
|
||||||
|
|
||||||
- name: Verify manifests are up-to-date
|
|
||||||
run: |
|
|
||||||
make manifests
|
|
||||||
git diff --exit-code
|
|
||||||
4
.github/workflows/validate-chart.yaml
vendored
4
.github/workflows/validate-chart.yaml
vendored
@@ -9,12 +9,16 @@ on:
|
|||||||
- '.github/workflows/validate-chart.yaml'
|
- '.github/workflows/validate-chart.yaml'
|
||||||
- '!charts/actions-runner-controller/docs/**'
|
- '!charts/actions-runner-controller/docs/**'
|
||||||
- '!**.md'
|
- '!**.md'
|
||||||
|
- '!charts/gha-runner-scale-set-controller/**'
|
||||||
|
- '!charts/gha-runner-scale-set/**'
|
||||||
push:
|
push:
|
||||||
paths:
|
paths:
|
||||||
- 'charts/**'
|
- 'charts/**'
|
||||||
- '.github/workflows/validate-chart.yaml'
|
- '.github/workflows/validate-chart.yaml'
|
||||||
- '!charts/actions-runner-controller/docs/**'
|
- '!charts/actions-runner-controller/docs/**'
|
||||||
- '!**.md'
|
- '!**.md'
|
||||||
|
- '!charts/gha-runner-scale-set-controller/**'
|
||||||
|
- '!charts/gha-runner-scale-set/**'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
env:
|
env:
|
||||||
KUBE_SCORE_VERSION: 1.10.0
|
KUBE_SCORE_VERSION: 1.10.0
|
||||||
|
|||||||
134
.github/workflows/validate-gha-chart.yaml
vendored
Normal file
134
.github/workflows/validate-gha-chart.yaml
vendored
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
name: Validate Helm Chart (gha-runner-scale-set-controller and gha-runner-scale-set)
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
paths:
|
||||||
|
- 'charts/**'
|
||||||
|
- '.github/workflows/validate-gha-chart.yaml'
|
||||||
|
- '!charts/actions-runner-controller/**'
|
||||||
|
- '!**.md'
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- 'charts/**'
|
||||||
|
- '.github/workflows/validate-gha-chart.yaml'
|
||||||
|
- '!charts/actions-runner-controller/**'
|
||||||
|
- '!**.md'
|
||||||
|
workflow_dispatch:
|
||||||
|
env:
|
||||||
|
KUBE_SCORE_VERSION: 1.16.1
|
||||||
|
HELM_VERSION: v3.8.0
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
validate-chart:
|
||||||
|
name: Lint Chart
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Set up Helm
|
||||||
|
# Using https://github.com/Azure/setup-helm/releases/tag/v3.5
|
||||||
|
uses: azure/setup-helm@5119fcb9089d432beecbf79bb2c7915207344b78
|
||||||
|
with:
|
||||||
|
version: ${{ env.HELM_VERSION }}
|
||||||
|
|
||||||
|
- name: Set up kube-score
|
||||||
|
run: |
|
||||||
|
wget https://github.com/zegl/kube-score/releases/download/v${{ env.KUBE_SCORE_VERSION }}/kube-score_${{ env.KUBE_SCORE_VERSION }}_linux_amd64 -O kube-score
|
||||||
|
chmod 755 kube-score
|
||||||
|
|
||||||
|
- name: Kube-score generated manifests
|
||||||
|
run: helm template --values charts/.ci/values-kube-score.yaml charts/* | ./kube-score score -
|
||||||
|
--ignore-test pod-networkpolicy
|
||||||
|
--ignore-test deployment-has-poddisruptionbudget
|
||||||
|
--ignore-test deployment-has-host-podantiaffinity
|
||||||
|
--ignore-test container-security-context
|
||||||
|
--ignore-test pod-probes
|
||||||
|
--ignore-test container-image-tag
|
||||||
|
--enable-optional-test container-security-context-privileged
|
||||||
|
--enable-optional-test container-security-context-readonlyrootfilesystem
|
||||||
|
|
||||||
|
# python is a requirement for the chart-testing action below (supports yamllint among other tests)
|
||||||
|
- uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.7'
|
||||||
|
|
||||||
|
- name: Set up chart-testing
|
||||||
|
uses: helm/chart-testing-action@v2.3.1
|
||||||
|
|
||||||
|
- name: Set up latest version chart-testing
|
||||||
|
run: |
|
||||||
|
echo 'deb [trusted=yes] https://repo.goreleaser.com/apt/ /' | sudo tee /etc/apt/sources.list.d/goreleaser.list
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install goreleaser
|
||||||
|
git clone https://github.com/helm/chart-testing
|
||||||
|
cd chart-testing
|
||||||
|
unset CT_CONFIG_DIR
|
||||||
|
goreleaser build --clean --skip-validate
|
||||||
|
./dist/chart-testing_linux_amd64_v1/ct version
|
||||||
|
echo 'Adding ct directory to PATH...'
|
||||||
|
echo "$RUNNER_TEMP/chart-testing/dist/chart-testing_linux_amd64_v1" >> "$GITHUB_PATH"
|
||||||
|
echo 'Setting CT_CONFIG_DIR...'
|
||||||
|
echo "CT_CONFIG_DIR=$RUNNER_TEMP/chart-testing/etc" >> "$GITHUB_ENV"
|
||||||
|
working-directory: ${{ runner.temp }}
|
||||||
|
|
||||||
|
- name: Run chart-testing (list-changed)
|
||||||
|
id: list-changed
|
||||||
|
run: |
|
||||||
|
ct version
|
||||||
|
changed=$(ct list-changed --config charts/.ci/ct-config-gha.yaml)
|
||||||
|
if [[ -n "$changed" ]]; then
|
||||||
|
echo "::set-output name=changed::true"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Run chart-testing (lint)
|
||||||
|
run: |
|
||||||
|
ct lint --config charts/.ci/ct-config-gha.yaml
|
||||||
|
|
||||||
|
- name: Set up docker buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
if: steps.list-changed.outputs.changed == 'true'
|
||||||
|
with:
|
||||||
|
version: latest
|
||||||
|
|
||||||
|
- name: Build controller image
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
if: steps.list-changed.outputs.changed == 'true'
|
||||||
|
with:
|
||||||
|
file: Dockerfile
|
||||||
|
platforms: linux/amd64
|
||||||
|
load: true
|
||||||
|
build-args: |
|
||||||
|
DOCKER_IMAGE_NAME=test-arc
|
||||||
|
VERSION=dev
|
||||||
|
tags: |
|
||||||
|
test-arc:dev
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
|
|
||||||
|
- name: Create kind cluster
|
||||||
|
uses: helm/kind-action@v1.4.0
|
||||||
|
if: steps.list-changed.outputs.changed == 'true'
|
||||||
|
with:
|
||||||
|
cluster_name: chart-testing
|
||||||
|
|
||||||
|
- name: Load image into cluster
|
||||||
|
if: steps.list-changed.outputs.changed == 'true'
|
||||||
|
run: |
|
||||||
|
export DOCKER_IMAGE_NAME=test-arc
|
||||||
|
export VERSION=dev
|
||||||
|
export IMG_RESULT=load
|
||||||
|
make docker-buildx
|
||||||
|
kind load docker-image test-arc:dev --name chart-testing
|
||||||
|
|
||||||
|
- name: Run chart-testing (install)
|
||||||
|
if: steps.list-changed.outputs.changed == 'true'
|
||||||
|
run: |
|
||||||
|
ct install --config charts/.ci/ct-config-gha.yaml
|
||||||
11
Makefile
11
Makefile
@@ -5,7 +5,7 @@ else
|
|||||||
endif
|
endif
|
||||||
DOCKER_USER ?= $(shell echo ${DOCKER_IMAGE_NAME} | cut -d / -f1)
|
DOCKER_USER ?= $(shell echo ${DOCKER_IMAGE_NAME} | cut -d / -f1)
|
||||||
VERSION ?= dev
|
VERSION ?= dev
|
||||||
RUNNER_VERSION ?= 2.302.1
|
RUNNER_VERSION ?= 2.303.0
|
||||||
TARGETPLATFORM ?= $(shell arch)
|
TARGETPLATFORM ?= $(shell arch)
|
||||||
RUNNER_NAME ?= ${DOCKER_USER}/actions-runner
|
RUNNER_NAME ?= ${DOCKER_USER}/actions-runner
|
||||||
RUNNER_TAG ?= ${VERSION}
|
RUNNER_TAG ?= ${VERSION}
|
||||||
@@ -92,9 +92,14 @@ manager: generate fmt vet
|
|||||||
run: generate fmt vet manifests
|
run: generate fmt vet manifests
|
||||||
go run ./main.go
|
go run ./main.go
|
||||||
|
|
||||||
|
run-scaleset: generate fmt vet
|
||||||
|
CONTROLLER_MANAGER_POD_NAMESPACE=default \
|
||||||
|
CONTROLLER_MANAGER_CONTAINER_IMAGE="${DOCKER_IMAGE_NAME}:${VERSION}" \
|
||||||
|
go run ./main.go --auto-scaling-runner-set-only
|
||||||
|
|
||||||
# Install CRDs into a cluster
|
# Install CRDs into a cluster
|
||||||
install: manifests
|
install: manifests
|
||||||
kustomize build config/crd | kubectl apply -f -
|
kustomize build config/crd | kubectl apply --server-side -f -
|
||||||
|
|
||||||
# Uninstall CRDs from a cluster
|
# Uninstall CRDs from a cluster
|
||||||
uninstall: manifests
|
uninstall: manifests
|
||||||
@@ -103,7 +108,7 @@ uninstall: manifests
|
|||||||
# Deploy controller in the configured Kubernetes cluster in ~/.kube/config
|
# Deploy controller in the configured Kubernetes cluster in ~/.kube/config
|
||||||
deploy: manifests
|
deploy: manifests
|
||||||
cd config/manager && kustomize edit set image controller=${DOCKER_IMAGE_NAME}:${VERSION}
|
cd config/manager && kustomize edit set image controller=${DOCKER_IMAGE_NAME}:${VERSION}
|
||||||
kustomize build config/default | kubectl apply -f -
|
kustomize build config/default | kubectl apply --server-side -f -
|
||||||
|
|
||||||
# Generate manifests e.g. CRD, RBAC etc.
|
# Generate manifests e.g. CRD, RBAC etc.
|
||||||
manifests: manifests-gen-crds chart-crds
|
manifests: manifests-gen-crds chart-crds
|
||||||
|
|||||||
@@ -61,6 +61,9 @@ if [ "${tool}" == "helm" ]; then
|
|||||||
flags+=( --set githubWebhookServer.imagePullSecrets[0].name=${IMAGE_PULL_SECRET})
|
flags+=( --set githubWebhookServer.imagePullSecrets[0].name=${IMAGE_PULL_SECRET})
|
||||||
flags+=( --set actionsMetricsServer.imagePullSecrets[0].name=${IMAGE_PULL_SECRET})
|
flags+=( --set actionsMetricsServer.imagePullSecrets[0].name=${IMAGE_PULL_SECRET})
|
||||||
fi
|
fi
|
||||||
|
if [ "${WATCH_NAMESPACE}" != "" ]; then
|
||||||
|
flags+=( --set watchNamespace=${WATCH_NAMESPACE} --set singleNamespace=true)
|
||||||
|
fi
|
||||||
if [ "${CHART_VERSION}" != "" ]; then
|
if [ "${CHART_VERSION}" != "" ]; then
|
||||||
flags+=( --version ${CHART_VERSION})
|
flags+=( --version ${CHART_VERSION})
|
||||||
fi
|
fi
|
||||||
@@ -69,6 +72,9 @@ if [ "${tool}" == "helm" ]; then
|
|||||||
flags+=( --set githubWebhookServer.logFormat=${LOG_FORMAT})
|
flags+=( --set githubWebhookServer.logFormat=${LOG_FORMAT})
|
||||||
flags+=( --set actionsMetricsServer.logFormat=${LOG_FORMAT})
|
flags+=( --set actionsMetricsServer.logFormat=${LOG_FORMAT})
|
||||||
fi
|
fi
|
||||||
|
if [ "${ADMISSION_WEBHOOKS_TIMEOUT}" != "" ]; then
|
||||||
|
flags+=( --set admissionWebHooks.timeoutSeconds=${ADMISSION_WEBHOOKS_TIMEOUT})
|
||||||
|
fi
|
||||||
if [ -n "${CREATE_SECRETS_USING_HELM}" ]; then
|
if [ -n "${CREATE_SECRETS_USING_HELM}" ]; then
|
||||||
if [ -z "${WEBHOOK_GITHUB_TOKEN}" ]; then
|
if [ -z "${WEBHOOK_GITHUB_TOKEN}" ]; then
|
||||||
echo 'Failed deploying secret "actions-metrics-server" using helm. Set WEBHOOK_GITHUB_TOKEN to deploy.' 1>&2
|
echo 'Failed deploying secret "actions-metrics-server" using helm. Set WEBHOOK_GITHUB_TOKEN to deploy.' 1>&2
|
||||||
@@ -77,6 +83,10 @@ if [ "${tool}" == "helm" ]; then
|
|||||||
flags+=( --set actionsMetricsServer.secret.create=true)
|
flags+=( --set actionsMetricsServer.secret.create=true)
|
||||||
flags+=( --set actionsMetricsServer.secret.github_token=${WEBHOOK_GITHUB_TOKEN})
|
flags+=( --set actionsMetricsServer.secret.github_token=${WEBHOOK_GITHUB_TOKEN})
|
||||||
fi
|
fi
|
||||||
|
if [ -n "${GITHUB_WEBHOOK_SERVER_ENV_NAME}" ] && [ -n "${GITHUB_WEBHOOK_SERVER_ENV_VALUE}" ]; then
|
||||||
|
flags+=( --set githubWebhookServer.env[0].name=${GITHUB_WEBHOOK_SERVER_ENV_NAME})
|
||||||
|
flags+=( --set githubWebhookServer.env[0].value=${GITHUB_WEBHOOK_SERVER_ENV_VALUE})
|
||||||
|
fi
|
||||||
|
|
||||||
set -vx
|
set -vx
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
# Title
|
|
||||||
|
|
||||||
<!-- ADR titles should typically be imperative sentences. -->
|
|
||||||
|
|
||||||
**Status**: (Proposed|Accepted|Rejected|Superceded|Deprecated)
|
|
||||||
|
|
||||||
## Context
|
|
||||||
|
|
||||||
*What is the issue or background knowledge necessary for future readers
|
|
||||||
to understand why this ADR was written?*
|
|
||||||
|
|
||||||
## Decision
|
|
||||||
|
|
||||||
**What** is the change being proposed? / **How** will it be implemented?*
|
|
||||||
|
|
||||||
## Consequences
|
|
||||||
|
|
||||||
*What becomes easier or more difficult to do because of this change?*
|
|
||||||
@@ -33,10 +33,14 @@ import (
|
|||||||
|
|
||||||
//+kubebuilder:object:root=true
|
//+kubebuilder:object:root=true
|
||||||
//+kubebuilder:subresource:status
|
//+kubebuilder:subresource:status
|
||||||
//+kubebuilder:printcolumn:JSONPath=".spec.minRunners",name=Minimum Runners,type=number
|
//+kubebuilder:printcolumn:JSONPath=".spec.minRunners",name=Minimum Runners,type=integer
|
||||||
//+kubebuilder:printcolumn:JSONPath=".spec.maxRunners",name=Maximum Runners,type=number
|
//+kubebuilder:printcolumn:JSONPath=".spec.maxRunners",name=Maximum Runners,type=integer
|
||||||
//+kubebuilder:printcolumn:JSONPath=".status.currentRunners",name=Current Runners,type=number
|
//+kubebuilder:printcolumn:JSONPath=".status.currentRunners",name=Current Runners,type=integer
|
||||||
//+kubebuilder:printcolumn:JSONPath=".status.state",name=State,type=string
|
//+kubebuilder:printcolumn:JSONPath=".status.state",name=State,type=string
|
||||||
|
//+kubebuilder:printcolumn:JSONPath=".status.pendingEphemeralRunners",name=Pending Runners,type=integer
|
||||||
|
//+kubebuilder:printcolumn:JSONPath=".status.runningEphemeralRunners",name=Running Runners,type=integer
|
||||||
|
//+kubebuilder:printcolumn:JSONPath=".status.finishedEphemeralRunners",name=Finished Runners,type=integer
|
||||||
|
//+kubebuilder:printcolumn:JSONPath=".status.deletingEphemeralRunners",name=Deleting Runners,type=integer
|
||||||
|
|
||||||
// AutoscalingRunnerSet is the Schema for the autoscalingrunnersets API
|
// AutoscalingRunnerSet is the Schema for the autoscalingrunnersets API
|
||||||
type AutoscalingRunnerSet struct {
|
type AutoscalingRunnerSet struct {
|
||||||
@@ -228,14 +232,22 @@ type ProxyServerConfig struct {
|
|||||||
// AutoscalingRunnerSetStatus defines the observed state of AutoscalingRunnerSet
|
// AutoscalingRunnerSetStatus defines the observed state of AutoscalingRunnerSet
|
||||||
type AutoscalingRunnerSetStatus struct {
|
type AutoscalingRunnerSetStatus struct {
|
||||||
// +optional
|
// +optional
|
||||||
CurrentRunners int `json:"currentRunners,omitempty"`
|
CurrentRunners int `json:"currentRunners"`
|
||||||
|
|
||||||
// +optional
|
// +optional
|
||||||
State string `json:"state,omitempty"`
|
State string `json:"state"`
|
||||||
|
|
||||||
|
// EphemeralRunner counts separated by the stage ephemeral runners are in, taken from the EphemeralRunnerSet
|
||||||
|
|
||||||
|
//+optional
|
||||||
|
PendingEphemeralRunners int `json:"pendingEphemeralRunners"`
|
||||||
|
// +optional
|
||||||
|
RunningEphemeralRunners int `json:"runningEphemeralRunners"`
|
||||||
|
// +optional
|
||||||
|
FailedEphemeralRunners int `json:"failedEphemeralRunners"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ars *AutoscalingRunnerSet) ListenerSpecHash() string {
|
func (ars *AutoscalingRunnerSet) ListenerSpecHash() string {
|
||||||
type listenerSpec = AutoscalingRunnerSetSpec
|
|
||||||
arsSpec := ars.Spec.DeepCopy()
|
arsSpec := ars.Spec.DeepCopy()
|
||||||
spec := arsSpec
|
spec := arsSpec
|
||||||
return hash.ComputeTemplateHash(&spec)
|
return hash.ComputeTemplateHash(&spec)
|
||||||
|
|||||||
@@ -31,13 +31,27 @@ type EphemeralRunnerSetSpec struct {
|
|||||||
// EphemeralRunnerSetStatus defines the observed state of EphemeralRunnerSet
|
// EphemeralRunnerSetStatus defines the observed state of EphemeralRunnerSet
|
||||||
type EphemeralRunnerSetStatus struct {
|
type EphemeralRunnerSetStatus struct {
|
||||||
// CurrentReplicas is the number of currently running EphemeralRunner resources being managed by this EphemeralRunnerSet.
|
// CurrentReplicas is the number of currently running EphemeralRunner resources being managed by this EphemeralRunnerSet.
|
||||||
CurrentReplicas int `json:"currentReplicas,omitempty"`
|
CurrentReplicas int `json:"currentReplicas"`
|
||||||
|
|
||||||
|
// EphemeralRunner counts separated by the stage ephemeral runners are in
|
||||||
|
|
||||||
|
// +optional
|
||||||
|
PendingEphemeralRunners int `json:"pendingEphemeralRunners"`
|
||||||
|
// +optional
|
||||||
|
RunningEphemeralRunners int `json:"runningEphemeralRunners"`
|
||||||
|
// +optional
|
||||||
|
FailedEphemeralRunners int `json:"failedEphemeralRunners"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// +kubebuilder:object:root=true
|
// +kubebuilder:object:root=true
|
||||||
// +kubebuilder:subresource:status
|
// +kubebuilder:subresource:status
|
||||||
// +kubebuilder:printcolumn:JSONPath=".spec.replicas",name="DesiredReplicas",type="integer"
|
// +kubebuilder:printcolumn:JSONPath=".spec.replicas",name="DesiredReplicas",type="integer"
|
||||||
// +kubebuilder:printcolumn:JSONPath=".status.currentReplicas", name="CurrentReplicas",type="integer"
|
// +kubebuilder:printcolumn:JSONPath=".status.currentReplicas", name="CurrentReplicas",type="integer"
|
||||||
|
//+kubebuilder:printcolumn:JSONPath=".status.pendingEphemeralRunners",name=Pending Runners,type=integer
|
||||||
|
//+kubebuilder:printcolumn:JSONPath=".status.runningEphemeralRunners",name=Running Runners,type=integer
|
||||||
|
//+kubebuilder:printcolumn:JSONPath=".status.finishedEphemeralRunners",name=Finished Runners,type=integer
|
||||||
|
//+kubebuilder:printcolumn:JSONPath=".status.deletingEphemeralRunners",name=Deleting Runners,type=integer
|
||||||
|
|
||||||
// EphemeralRunnerSet is the Schema for the ephemeralrunnersets API
|
// EphemeralRunnerSet is the Schema for the ephemeralrunnersets API
|
||||||
type EphemeralRunnerSet struct {
|
type EphemeralRunnerSet struct {
|
||||||
metav1.TypeMeta `json:",inline"`
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
|||||||
@@ -77,6 +77,11 @@ type RunnerDeploymentStatus struct {
|
|||||||
// +kubebuilder:object:root=true
|
// +kubebuilder:object:root=true
|
||||||
// +kubebuilder:resource:shortName=rdeploy
|
// +kubebuilder:resource:shortName=rdeploy
|
||||||
// +kubebuilder:subresource:status
|
// +kubebuilder:subresource:status
|
||||||
|
// +kubebuilder:printcolumn:JSONPath=".spec.template.spec.enterprise",name=Enterprise,type=string
|
||||||
|
// +kubebuilder:printcolumn:JSONPath=".spec.template.spec.organization",name=Organization,type=string
|
||||||
|
// +kubebuilder:printcolumn:JSONPath=".spec.template.spec.repository",name=Repository,type=string
|
||||||
|
// +kubebuilder:printcolumn:JSONPath=".spec.template.spec.group",name=Group,type=string
|
||||||
|
// +kubebuilder:printcolumn:JSONPath=".spec.template.spec.labels",name=Labels,type=string
|
||||||
// +kubebuilder:printcolumn:JSONPath=".spec.replicas",name=Desired,type=number
|
// +kubebuilder:printcolumn:JSONPath=".spec.replicas",name=Desired,type=number
|
||||||
// +kubebuilder:printcolumn:JSONPath=".status.replicas",name=Current,type=number
|
// +kubebuilder:printcolumn:JSONPath=".status.replicas",name=Current,type=number
|
||||||
// +kubebuilder:printcolumn:JSONPath=".status.updatedReplicas",name=Up-To-Date,type=number
|
// +kubebuilder:printcolumn:JSONPath=".status.updatedReplicas",name=Up-To-Date,type=number
|
||||||
|
|||||||
9
charts/.ci/ct-config-gha.yaml
Normal file
9
charts/.ci/ct-config-gha.yaml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# This file defines the config for "ct" (chart tester) used by the helm linting GitHub workflow
|
||||||
|
lint-conf: charts/.ci/lint-config.yaml
|
||||||
|
chart-repos:
|
||||||
|
- jetstack=https://charts.jetstack.io
|
||||||
|
check-version-increment: false # Disable checking that the chart version has been bumped
|
||||||
|
charts:
|
||||||
|
- charts/gha-runner-scale-set-controller
|
||||||
|
- charts/gha-runner-scale-set
|
||||||
|
skip-clean-up: true
|
||||||
@@ -5,5 +5,3 @@ chart-repos:
|
|||||||
check-version-increment: false # Disable checking that the chart version has been bumped
|
check-version-increment: false # Disable checking that the chart version has been bumped
|
||||||
charts:
|
charts:
|
||||||
- charts/actions-runner-controller
|
- charts/actions-runner-controller
|
||||||
- charts/gha-runner-scale-set-controller
|
|
||||||
- charts/gha-runner-scale-set
|
|
||||||
@@ -15,10 +15,10 @@ type: application
|
|||||||
# This is the chart version. This version number should be incremented each time you make changes
|
# 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.
|
# to the chart and its templates, including the app version.
|
||||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||||
version: 0.22.0
|
version: 0.23.0
|
||||||
|
|
||||||
# Used as the default manager tag value when no tag property is provided in the values.yaml
|
# Used as the default manager tag value when no tag property is provided in the values.yaml
|
||||||
appVersion: 0.27.0
|
appVersion: 0.27.1
|
||||||
|
|
||||||
home: https://github.com/actions/actions-runner-controller
|
home: https://github.com/actions/actions-runner-controller
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,21 @@ spec:
|
|||||||
scope: Namespaced
|
scope: Namespaced
|
||||||
versions:
|
versions:
|
||||||
- additionalPrinterColumns:
|
- additionalPrinterColumns:
|
||||||
|
- jsonPath: .spec.template.spec.enterprise
|
||||||
|
name: Enterprise
|
||||||
|
type: string
|
||||||
|
- jsonPath: .spec.template.spec.organization
|
||||||
|
name: Organization
|
||||||
|
type: string
|
||||||
|
- jsonPath: .spec.template.spec.repository
|
||||||
|
name: Repository
|
||||||
|
type: string
|
||||||
|
- jsonPath: .spec.template.spec.group
|
||||||
|
name: Group
|
||||||
|
type: string
|
||||||
|
- jsonPath: .spec.template.spec.labels
|
||||||
|
name: Labels
|
||||||
|
type: string
|
||||||
- jsonPath: .spec.replicas
|
- jsonPath: .spec.replicas
|
||||||
name: Desired
|
name: Desired
|
||||||
type: number
|
type: number
|
||||||
|
|||||||
@@ -117,10 +117,14 @@ spec:
|
|||||||
name: {{ include "actions-runner-controller.secretName" . }}
|
name: {{ include "actions-runner-controller.secretName" . }}
|
||||||
optional: true
|
optional: true
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
{{- if kindIs "slice" .Values.githubWebhookServer.env }}
|
||||||
|
{{- toYaml .Values.githubWebhookServer.env | nindent 8 }}
|
||||||
|
{{- else }}
|
||||||
{{- range $key, $val := .Values.githubWebhookServer.env }}
|
{{- range $key, $val := .Values.githubWebhookServer.env }}
|
||||||
- name: {{ $key }}
|
- name: {{ $key }}
|
||||||
value: {{ $val | quote }}
|
value: {{ $val | quote }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default (cat "v" .Chart.AppVersion | replace " " "") }}"
|
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default (cat "v" .Chart.AppVersion | replace " " "") }}"
|
||||||
name: github-webhook-server
|
name: github-webhook-server
|
||||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||||
|
|||||||
@@ -250,14 +250,6 @@ rules:
|
|||||||
- patch
|
- patch
|
||||||
- update
|
- update
|
||||||
- watch
|
- watch
|
||||||
- apiGroups:
|
|
||||||
- ""
|
|
||||||
resources:
|
|
||||||
- secrets
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- watch
|
|
||||||
{{- if .Values.runner.statusUpdateHook.enabled }}
|
{{- if .Values.runner.statusUpdateHook.enabled }}
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- ""
|
- ""
|
||||||
@@ -311,11 +303,4 @@ rules:
|
|||||||
- list
|
- list
|
||||||
- create
|
- create
|
||||||
- delete
|
- delete
|
||||||
- apiGroups:
|
|
||||||
- ""
|
|
||||||
resources:
|
|
||||||
- secrets
|
|
||||||
verbs:
|
|
||||||
- create
|
|
||||||
- delete
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
{{- if .Values.scope.singleNamespace }}
|
||||||
|
kind: RoleBinding
|
||||||
|
{{- else }}
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
{{- end }}
|
||||||
|
metadata:
|
||||||
|
name: {{ include "actions-runner-controller.managerRoleName" . }}-secrets
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
{{- if .Values.scope.singleNamespace }}
|
||||||
|
kind: Role
|
||||||
|
{{- else }}
|
||||||
|
kind: ClusterRole
|
||||||
|
{{- end }}
|
||||||
|
name: {{ include "actions-runner-controller.managerRoleName" . }}-secrets
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: {{ include "actions-runner-controller.serviceAccountName" . }}
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
{{- if .Values.scope.singleNamespace }}
|
||||||
|
kind: Role
|
||||||
|
{{- else }}
|
||||||
|
kind: ClusterRole
|
||||||
|
{{- end }}
|
||||||
|
metadata:
|
||||||
|
creationTimestamp: null
|
||||||
|
name: {{ include "actions-runner-controller.managerRoleName" . }}-secrets
|
||||||
|
rules:
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- secrets
|
||||||
|
verbs:
|
||||||
|
- get
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
|
{{- if .Values.rbac.allowGrantingKubernetesContainerModePermissions }}
|
||||||
|
{{/* These permissions are required by ARC to create RBAC resources for the runner pod to use the kubernetes container mode. */}}
|
||||||
|
{{/* See https://github.com/actions/actions-runner-controller/pull/1268/files#r917331632 */}}
|
||||||
|
- create
|
||||||
|
- delete
|
||||||
|
{{- end }}
|
||||||
@@ -44,6 +44,7 @@ webhooks:
|
|||||||
resources:
|
resources:
|
||||||
- runners
|
- runners
|
||||||
sideEffects: None
|
sideEffects: None
|
||||||
|
timeoutSeconds: {{ .Values.admissionWebHooks.timeoutSeconds | default 10}}
|
||||||
- admissionReviewVersions:
|
- admissionReviewVersions:
|
||||||
- v1beta1
|
- v1beta1
|
||||||
{{- if .Values.scope.singleNamespace }}
|
{{- if .Values.scope.singleNamespace }}
|
||||||
@@ -74,6 +75,7 @@ webhooks:
|
|||||||
resources:
|
resources:
|
||||||
- runnerdeployments
|
- runnerdeployments
|
||||||
sideEffects: None
|
sideEffects: None
|
||||||
|
timeoutSeconds: {{ .Values.admissionWebHooks.timeoutSeconds | default 10}}
|
||||||
- admissionReviewVersions:
|
- admissionReviewVersions:
|
||||||
- v1beta1
|
- v1beta1
|
||||||
{{- if .Values.scope.singleNamespace }}
|
{{- if .Values.scope.singleNamespace }}
|
||||||
@@ -104,6 +106,7 @@ webhooks:
|
|||||||
resources:
|
resources:
|
||||||
- runnerreplicasets
|
- runnerreplicasets
|
||||||
sideEffects: None
|
sideEffects: None
|
||||||
|
timeoutSeconds: {{ .Values.admissionWebHooks.timeoutSeconds | default 10}}
|
||||||
- admissionReviewVersions:
|
- admissionReviewVersions:
|
||||||
- v1beta1
|
- v1beta1
|
||||||
{{- if .Values.scope.singleNamespace }}
|
{{- if .Values.scope.singleNamespace }}
|
||||||
@@ -136,6 +139,7 @@ webhooks:
|
|||||||
objectSelector:
|
objectSelector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
"actions-runner-controller/inject-registration-token": "true"
|
"actions-runner-controller/inject-registration-token": "true"
|
||||||
|
timeoutSeconds: {{ .Values.admissionWebHooks.timeoutSeconds | default 10}}
|
||||||
---
|
---
|
||||||
apiVersion: admissionregistration.k8s.io/v1
|
apiVersion: admissionregistration.k8s.io/v1
|
||||||
kind: ValidatingWebhookConfiguration
|
kind: ValidatingWebhookConfiguration
|
||||||
@@ -177,6 +181,7 @@ webhooks:
|
|||||||
resources:
|
resources:
|
||||||
- runners
|
- runners
|
||||||
sideEffects: None
|
sideEffects: None
|
||||||
|
timeoutSeconds: {{ .Values.admissionWebHooks.timeoutSeconds | default 10}}
|
||||||
- admissionReviewVersions:
|
- admissionReviewVersions:
|
||||||
- v1beta1
|
- v1beta1
|
||||||
{{- if .Values.scope.singleNamespace }}
|
{{- if .Values.scope.singleNamespace }}
|
||||||
@@ -207,6 +212,7 @@ webhooks:
|
|||||||
resources:
|
resources:
|
||||||
- runnerdeployments
|
- runnerdeployments
|
||||||
sideEffects: None
|
sideEffects: None
|
||||||
|
timeoutSeconds: {{ .Values.admissionWebHooks.timeoutSeconds | default 10}}
|
||||||
- admissionReviewVersions:
|
- admissionReviewVersions:
|
||||||
- v1beta1
|
- v1beta1
|
||||||
{{- if .Values.scope.singleNamespace }}
|
{{- if .Values.scope.singleNamespace }}
|
||||||
@@ -238,6 +244,7 @@ webhooks:
|
|||||||
- runnerreplicasets
|
- runnerreplicasets
|
||||||
sideEffects: None
|
sideEffects: None
|
||||||
{{ if not (or (hasKey .Values.admissionWebHooks "caBundle") .Values.certManagerEnabled) }}
|
{{ if not (or (hasKey .Values.admissionWebHooks "caBundle") .Values.certManagerEnabled) }}
|
||||||
|
timeoutSeconds: {{ .Values.admissionWebHooks.timeoutSeconds | default 10}}
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Secret
|
kind: Secret
|
||||||
|
|||||||
@@ -279,6 +279,19 @@ githubWebhookServer:
|
|||||||
# queueLimit: 100
|
# queueLimit: 100
|
||||||
terminationGracePeriodSeconds: 10
|
terminationGracePeriodSeconds: 10
|
||||||
lifecycle: {}
|
lifecycle: {}
|
||||||
|
# specify additional environment variables for the webhook server pod.
|
||||||
|
# It's possible to specify either key vale pairs e.g.:
|
||||||
|
# my_env_var: "some value"
|
||||||
|
# my_other_env_var: "other value"
|
||||||
|
|
||||||
|
# or a list of complete environment variable definitions e.g.:
|
||||||
|
# - name: GITHUB_WEBHOOK_SECRET_TOKEN
|
||||||
|
# valueFrom:
|
||||||
|
# secretKeyRef:
|
||||||
|
# key: GITHUB_WEBHOOK_SECRET_TOKEN
|
||||||
|
# name: prod-gha-controller-webhook-token
|
||||||
|
# optional: true
|
||||||
|
env: {}
|
||||||
|
|
||||||
actionsMetrics:
|
actionsMetrics:
|
||||||
serviceAnnotations: {}
|
serviceAnnotations: {}
|
||||||
|
|||||||
5
charts/gha-runner-scale-set-controller/ci/ci-values.yaml
Normal file
5
charts/gha-runner-scale-set-controller/ci/ci-values.yaml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# Set the following to dummy values.
|
||||||
|
# This is only useful in CI
|
||||||
|
image:
|
||||||
|
repository: test-arc
|
||||||
|
tag: dev
|
||||||
@@ -17,16 +17,28 @@ spec:
|
|||||||
- additionalPrinterColumns:
|
- additionalPrinterColumns:
|
||||||
- jsonPath: .spec.minRunners
|
- jsonPath: .spec.minRunners
|
||||||
name: Minimum Runners
|
name: Minimum Runners
|
||||||
type: number
|
type: integer
|
||||||
- jsonPath: .spec.maxRunners
|
- jsonPath: .spec.maxRunners
|
||||||
name: Maximum Runners
|
name: Maximum Runners
|
||||||
type: number
|
type: integer
|
||||||
- jsonPath: .status.currentRunners
|
- jsonPath: .status.currentRunners
|
||||||
name: Current Runners
|
name: Current Runners
|
||||||
type: number
|
type: integer
|
||||||
- jsonPath: .status.state
|
- jsonPath: .status.state
|
||||||
name: State
|
name: State
|
||||||
type: string
|
type: string
|
||||||
|
- jsonPath: .status.pendingEphemeralRunners
|
||||||
|
name: Pending Runners
|
||||||
|
type: integer
|
||||||
|
- jsonPath: .status.runningEphemeralRunners
|
||||||
|
name: Running Runners
|
||||||
|
type: integer
|
||||||
|
- jsonPath: .status.finishedEphemeralRunners
|
||||||
|
name: Finished Runners
|
||||||
|
type: integer
|
||||||
|
- jsonPath: .status.deletingEphemeralRunners
|
||||||
|
name: Deleting Runners
|
||||||
|
type: integer
|
||||||
name: v1alpha1
|
name: v1alpha1
|
||||||
schema:
|
schema:
|
||||||
openAPIV3Schema:
|
openAPIV3Schema:
|
||||||
@@ -4306,6 +4318,12 @@ spec:
|
|||||||
properties:
|
properties:
|
||||||
currentRunners:
|
currentRunners:
|
||||||
type: integer
|
type: integer
|
||||||
|
failedEphemeralRunners:
|
||||||
|
type: integer
|
||||||
|
pendingEphemeralRunners:
|
||||||
|
type: integer
|
||||||
|
runningEphemeralRunners:
|
||||||
|
type: integer
|
||||||
state:
|
state:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
|
|||||||
@@ -21,6 +21,18 @@ spec:
|
|||||||
- jsonPath: .status.currentReplicas
|
- jsonPath: .status.currentReplicas
|
||||||
name: CurrentReplicas
|
name: CurrentReplicas
|
||||||
type: integer
|
type: integer
|
||||||
|
- jsonPath: .status.pendingEphemeralRunners
|
||||||
|
name: Pending Runners
|
||||||
|
type: integer
|
||||||
|
- jsonPath: .status.runningEphemeralRunners
|
||||||
|
name: Running Runners
|
||||||
|
type: integer
|
||||||
|
- jsonPath: .status.finishedEphemeralRunners
|
||||||
|
name: Finished Runners
|
||||||
|
type: integer
|
||||||
|
- jsonPath: .status.deletingEphemeralRunners
|
||||||
|
name: Deleting Runners
|
||||||
|
type: integer
|
||||||
name: v1alpha1
|
name: v1alpha1
|
||||||
schema:
|
schema:
|
||||||
openAPIV3Schema:
|
openAPIV3Schema:
|
||||||
@@ -4296,6 +4308,14 @@ spec:
|
|||||||
currentReplicas:
|
currentReplicas:
|
||||||
description: CurrentReplicas is the number of currently running EphemeralRunner resources being managed by this EphemeralRunnerSet.
|
description: CurrentReplicas is the number of currently running EphemeralRunner resources being managed by this EphemeralRunnerSet.
|
||||||
type: integer
|
type: integer
|
||||||
|
failedEphemeralRunners:
|
||||||
|
type: integer
|
||||||
|
pendingEphemeralRunners:
|
||||||
|
type: integer
|
||||||
|
runningEphemeralRunners:
|
||||||
|
type: integer
|
||||||
|
required:
|
||||||
|
- currentReplicas
|
||||||
type: object
|
type: object
|
||||||
type: object
|
type: object
|
||||||
served: true
|
served: true
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ helm.sh/chart: {{ include "gha-runner-scale-set-controller.chart" . }}
|
|||||||
{{- if .Chart.AppVersion }}
|
{{- if .Chart.AppVersion }}
|
||||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
app.kubernetes.io/part-of: {{ .Chart.Name }}
|
app.kubernetes.io/part-of: gha-runner-scale-set-controller
|
||||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
{{- range $k, $v := .Values.labels }}
|
{{- range $k, $v := .Values.labels }}
|
||||||
{{ $k }}: {{ $v }}
|
{{ $k }}: {{ $v }}
|
||||||
@@ -59,25 +59,41 @@ Create the name of the service account to use
|
|||||||
*/}}
|
*/}}
|
||||||
{{- define "gha-runner-scale-set-controller.serviceAccountName" -}}
|
{{- define "gha-runner-scale-set-controller.serviceAccountName" -}}
|
||||||
{{- if eq .Values.serviceAccount.name "default"}}
|
{{- if eq .Values.serviceAccount.name "default"}}
|
||||||
{{- fail "serviceAccount.name cannot be set to 'default'" }}
|
{{- fail "serviceAccount.name cannot be set to 'default'" }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if .Values.serviceAccount.create }}
|
{{- if .Values.serviceAccount.create }}
|
||||||
{{- default (include "gha-runner-scale-set-controller.fullname" .) .Values.serviceAccount.name }}
|
{{- default (include "gha-runner-scale-set-controller.fullname" .) .Values.serviceAccount.name }}
|
||||||
{{- else }}
|
{{- else }}
|
||||||
{{- if not .Values.serviceAccount.name }}
|
{{- if not .Values.serviceAccount.name }}
|
||||||
{{- fail "serviceAccount.name must be set if serviceAccount.create is false" }}
|
{{- fail "serviceAccount.name must be set if serviceAccount.create is false" }}
|
||||||
{{- else }}
|
{{- else }}
|
||||||
{{- .Values.serviceAccount.name }}
|
{{- .Values.serviceAccount.name }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- define "gha-runner-scale-set-controller.managerRoleName" -}}
|
{{- define "gha-runner-scale-set-controller.managerClusterRoleName" -}}
|
||||||
{{- include "gha-runner-scale-set-controller.fullname" . }}-manager-role
|
{{- include "gha-runner-scale-set-controller.fullname" . }}-manager-cluster-role
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- define "gha-runner-scale-set-controller.managerRoleBinding" -}}
|
{{- define "gha-runner-scale-set-controller.managerClusterRoleBinding" -}}
|
||||||
{{- include "gha-runner-scale-set-controller.fullname" . }}-manager-rolebinding
|
{{- include "gha-runner-scale-set-controller.fullname" . }}-manager-cluster-rolebinding
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "gha-runner-scale-set-controller.managerSingleNamespaceRoleName" -}}
|
||||||
|
{{- include "gha-runner-scale-set-controller.fullname" . }}-manager-single-namespace-role
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "gha-runner-scale-set-controller.managerSingleNamespaceRoleBinding" -}}
|
||||||
|
{{- include "gha-runner-scale-set-controller.fullname" . }}-manager-single-namespace-rolebinding
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "gha-runner-scale-set-controller.managerListenerRoleName" -}}
|
||||||
|
{{- include "gha-runner-scale-set-controller.fullname" . }}-manager-listener-role
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "gha-runner-scale-set-controller.managerListenerRoleBinding" -}}
|
||||||
|
{{- include "gha-runner-scale-set-controller.fullname" . }}-manager-listener-rolebinding
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- define "gha-runner-scale-set-controller.leaderElectionRoleName" -}}
|
{{- define "gha-runner-scale-set-controller.leaderElectionRoleName" -}}
|
||||||
@@ -91,7 +107,7 @@ Create the name of the service account to use
|
|||||||
{{- define "gha-runner-scale-set-controller.imagePullSecretsNames" -}}
|
{{- define "gha-runner-scale-set-controller.imagePullSecretsNames" -}}
|
||||||
{{- $names := list }}
|
{{- $names := list }}
|
||||||
{{- range $k, $v := . }}
|
{{- range $k, $v := . }}
|
||||||
{{- $names = append $names $v.name }}
|
{{- $names = append $names $v.name }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- $names | join ","}}
|
{{- $names | join ","}}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|||||||
@@ -5,6 +5,11 @@ metadata:
|
|||||||
namespace: {{ .Release.Namespace }}
|
namespace: {{ .Release.Namespace }}
|
||||||
labels:
|
labels:
|
||||||
{{- include "gha-runner-scale-set-controller.labels" . | nindent 4 }}
|
{{- include "gha-runner-scale-set-controller.labels" . | nindent 4 }}
|
||||||
|
actions.github.com/controller-service-account-namespace: {{ .Release.Namespace }}
|
||||||
|
actions.github.com/controller-service-account-name: {{ include "gha-runner-scale-set-controller.serviceAccountName" . }}
|
||||||
|
{{- if .Values.flags.watchSingleNamespace }}
|
||||||
|
actions.github.com/controller-watch-single-namespace: {{ .Values.flags.watchSingleNamespace }}
|
||||||
|
{{- end }}
|
||||||
spec:
|
spec:
|
||||||
replicas: {{ default 1 .Values.replicaCount }}
|
replicas: {{ default 1 .Values.replicaCount }}
|
||||||
selector:
|
selector:
|
||||||
@@ -18,7 +23,7 @@ spec:
|
|||||||
{{- toYaml . | nindent 8 }}
|
{{- toYaml . | nindent 8 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
labels:
|
labels:
|
||||||
app.kubernetes.io/part-of: actions-runner-controller
|
app.kubernetes.io/part-of: gha-runner-scale-set-controller
|
||||||
app.kubernetes.io/component: controller-manager
|
app.kubernetes.io/component: controller-manager
|
||||||
app.kubernetes.io/version: {{ .Chart.Version }}
|
app.kubernetes.io/version: {{ .Chart.Version }}
|
||||||
{{- include "gha-runner-scale-set-controller.selectorLabels" . | nindent 8 }}
|
{{- include "gha-runner-scale-set-controller.selectorLabels" . | nindent 8 }}
|
||||||
@@ -51,25 +56,21 @@ spec:
|
|||||||
{{- with .Values.flags.logLevel }}
|
{{- with .Values.flags.logLevel }}
|
||||||
- "--log-level={{ . }}"
|
- "--log-level={{ . }}"
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
{{- with .Values.flags.watchSingleNamespace }}
|
||||||
|
- "--watch-single-namespace={{ . }}"
|
||||||
|
{{- end }}
|
||||||
command:
|
command:
|
||||||
- "/manager"
|
- "/manager"
|
||||||
env:
|
env:
|
||||||
- name: CONTROLLER_MANAGER_POD_NAME
|
- name: CONTROLLER_MANAGER_CONTAINER_IMAGE
|
||||||
valueFrom:
|
value: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
||||||
fieldRef:
|
|
||||||
fieldPath: metadata.name
|
|
||||||
- name: CONTROLLER_MANAGER_POD_NAMESPACE
|
- name: CONTROLLER_MANAGER_POD_NAMESPACE
|
||||||
valueFrom:
|
valueFrom:
|
||||||
fieldRef:
|
fieldRef:
|
||||||
fieldPath: metadata.namespace
|
fieldPath: metadata.namespace
|
||||||
{{- with .Values.env }}
|
{{- with .Values.env }}
|
||||||
{{- if kindIs "slice" .Values.env }}
|
{{- if kindIs "slice" . }}
|
||||||
{{- toYaml .Values.env | nindent 8 }}
|
{{- toYaml . | nindent 8 }}
|
||||||
{{- else }}
|
|
||||||
{{- range $key, $val := .Values.env }}
|
|
||||||
- name: {{ $key }}
|
|
||||||
value: {{ $val | quote }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- with .Values.resources }}
|
{{- with .Values.resources }}
|
||||||
@@ -98,4 +99,4 @@ spec:
|
|||||||
{{- with .Values.tolerations }}
|
{{- with .Values.tolerations }}
|
||||||
tolerations:
|
tolerations:
|
||||||
{{- toYaml . | nindent 8 }}
|
{{- toYaml . | nindent 8 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
{{- if gt (int (default 1 .Values.replicaCount)) 1 -}}
|
{{- if gt (int (default 1 .Values.replicaCount)) 1 }}
|
||||||
# permissions to do leader election.
|
# permissions to do leader election.
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: Role
|
kind: Role
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
{{- if gt (int (default 1 .Values.replicaCount)) 1 -}}
|
{{- if gt (int (default 1 .Values.replicaCount)) 1 }}
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: RoleBinding
|
kind: RoleBinding
|
||||||
metadata:
|
metadata:
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
|
{{- if empty .Values.flags.watchSingleNamespace }}
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: ClusterRole
|
kind: ClusterRole
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ include "gha-runner-scale-set-controller.managerRoleName" . }}
|
name: {{ include "gha-runner-scale-set-controller.managerClusterRoleName" . }}
|
||||||
rules:
|
rules:
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- actions.github.com
|
- actions.github.com
|
||||||
@@ -20,6 +21,7 @@ rules:
|
|||||||
resources:
|
resources:
|
||||||
- autoscalingrunnersets/finalizers
|
- autoscalingrunnersets/finalizers
|
||||||
verbs:
|
verbs:
|
||||||
|
- patch
|
||||||
- update
|
- update
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- actions.github.com
|
- actions.github.com
|
||||||
@@ -54,6 +56,7 @@ rules:
|
|||||||
resources:
|
resources:
|
||||||
- autoscalinglisteners/finalizers
|
- autoscalinglisteners/finalizers
|
||||||
verbs:
|
verbs:
|
||||||
|
- patch
|
||||||
- update
|
- update
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- actions.github.com
|
- actions.github.com
|
||||||
@@ -92,13 +95,8 @@ rules:
|
|||||||
resources:
|
resources:
|
||||||
- ephemeralrunners/finalizers
|
- ephemeralrunners/finalizers
|
||||||
verbs:
|
verbs:
|
||||||
- create
|
|
||||||
- delete
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- patch
|
- patch
|
||||||
- update
|
- update
|
||||||
- watch
|
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- actions.github.com
|
- actions.github.com
|
||||||
resources:
|
resources:
|
||||||
@@ -112,45 +110,13 @@ rules:
|
|||||||
resources:
|
resources:
|
||||||
- pods
|
- pods
|
||||||
verbs:
|
verbs:
|
||||||
- create
|
|
||||||
- delete
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- patch
|
|
||||||
- update
|
|
||||||
- watch
|
|
||||||
- apiGroups:
|
|
||||||
- ""
|
|
||||||
resources:
|
|
||||||
- pods/status
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- apiGroups:
|
|
||||||
- ""
|
|
||||||
resources:
|
|
||||||
- secrets
|
|
||||||
verbs:
|
|
||||||
- create
|
|
||||||
- delete
|
|
||||||
- get
|
|
||||||
- list
|
- list
|
||||||
- watch
|
- watch
|
||||||
- update
|
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- ""
|
- ""
|
||||||
resources:
|
resources:
|
||||||
- serviceaccounts
|
- serviceaccounts
|
||||||
verbs:
|
verbs:
|
||||||
- create
|
|
||||||
- delete
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- watch
|
|
||||||
- apiGroups:
|
|
||||||
- ""
|
|
||||||
resources:
|
|
||||||
- configmaps
|
|
||||||
verbs:
|
|
||||||
- list
|
- list
|
||||||
- watch
|
- watch
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
@@ -158,10 +124,6 @@ rules:
|
|||||||
resources:
|
resources:
|
||||||
- rolebindings
|
- rolebindings
|
||||||
verbs:
|
verbs:
|
||||||
- create
|
|
||||||
- delete
|
|
||||||
- get
|
|
||||||
- update
|
|
||||||
- list
|
- list
|
||||||
- watch
|
- watch
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
@@ -169,9 +131,6 @@ rules:
|
|||||||
resources:
|
resources:
|
||||||
- roles
|
- roles
|
||||||
verbs:
|
verbs:
|
||||||
- create
|
|
||||||
- delete
|
|
||||||
- get
|
|
||||||
- update
|
|
||||||
- list
|
- list
|
||||||
- watch
|
- watch
|
||||||
|
{{- end }}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{{- if empty .Values.flags.watchSingleNamespace }}
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: {{ include "gha-runner-scale-set-controller.managerClusterRoleBinding" . }}
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: {{ include "gha-runner-scale-set-controller.managerClusterRoleName" . }}
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: {{ include "gha-runner-scale-set-controller.serviceAccountName" . }}
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
|
{{- end }}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
name: {{ include "gha-runner-scale-set-controller.managerListenerRoleName" . }}
|
||||||
|
namespace: {{ .Release.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
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: ClusterRoleBinding
|
kind: RoleBinding
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ include "gha-runner-scale-set-controller.managerRoleBinding" . }}
|
name: {{ include "gha-runner-scale-set-controller.managerListenerRoleBinding" . }}
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
roleRef:
|
roleRef:
|
||||||
apiGroup: rbac.authorization.k8s.io
|
apiGroup: rbac.authorization.k8s.io
|
||||||
kind: ClusterRole
|
kind: Role
|
||||||
name: {{ include "gha-runner-scale-set-controller.managerRoleName" . }}
|
name: {{ include "gha-runner-scale-set-controller.managerListenerRoleName" . }}
|
||||||
subjects:
|
subjects:
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: {{ include "gha-runner-scale-set-controller.serviceAccountName" . }}
|
name: {{ include "gha-runner-scale-set-controller.serviceAccountName" . }}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
{{- if .Values.flags.watchSingleNamespace }}
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
name: {{ include "gha-runner-scale-set-controller.managerSingleNamespaceRoleName" . }}
|
||||||
|
namespace: {{ .Release.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.flags.watchSingleNamespace }}
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: RoleBinding
|
||||||
|
metadata:
|
||||||
|
name: {{ include "gha-runner-scale-set-controller.managerSingleNamespaceRoleBinding" . }}
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: Role
|
||||||
|
name: {{ include "gha-runner-scale-set-controller.managerSingleNamespaceRoleName" . }}
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: {{ include "gha-runner-scale-set-controller.serviceAccountName" . }}
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
|
{{- end }}
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
{{- if .Values.flags.watchSingleNamespace }}
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
name: {{ include "gha-runner-scale-set-controller.managerSingleNamespaceRoleName" . }}
|
||||||
|
namespace: {{ .Values.flags.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:
|
||||||
|
- 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
|
||||||
|
{{- end }}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
{{- if .Values.flags.watchSingleNamespace }}
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: RoleBinding
|
||||||
|
metadata:
|
||||||
|
name: {{ include "gha-runner-scale-set-controller.managerSingleNamespaceRoleBinding" . }}
|
||||||
|
namespace: {{ .Values.flags.watchSingleNamespace }}
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: Role
|
||||||
|
name: {{ include "gha-runner-scale-set-controller.managerSingleNamespaceRoleName" . }}
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: {{ include "gha-runner-scale-set-controller.serviceAccountName" . }}
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
|
{{- end }}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
{{- if .Values.serviceAccount.create -}}
|
{{- if .Values.serviceAccount.create }}
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: ServiceAccount
|
kind: ServiceAccount
|
||||||
metadata:
|
metadata:
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ func TestTemplate_NotCreateServiceAccount_ServiceAccountNotSet(t *testing.T) {
|
|||||||
assert.ErrorContains(t, err, "serviceAccount.name must be set if serviceAccount.create is false", "We should get an error because the default service account cannot be used")
|
assert.ErrorContains(t, err, "serviceAccount.name must be set if serviceAccount.create is false", "We should get an error because the default service account cannot be used")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTemplate_CreateManagerRole(t *testing.T) {
|
func TestTemplate_CreateManagerClusterRole(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
@@ -162,17 +162,23 @@ func TestTemplate_CreateManagerRole(t *testing.T) {
|
|||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
|
|
||||||
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/manager_role.yaml"})
|
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/manager_cluster_role.yaml"})
|
||||||
|
|
||||||
var managerRole rbacv1.ClusterRole
|
var managerClusterRole rbacv1.ClusterRole
|
||||||
helm.UnmarshalK8SYaml(t, output, &managerRole)
|
helm.UnmarshalK8SYaml(t, output, &managerClusterRole)
|
||||||
|
|
||||||
assert.Empty(t, managerRole.Namespace, "ClusterRole should not have a namespace")
|
assert.Empty(t, managerClusterRole.Namespace, "ClusterRole should not have a namespace")
|
||||||
assert.Equal(t, "test-arc-gha-runner-scale-set-controller-manager-role", managerRole.Name)
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller-manager-cluster-role", managerClusterRole.Name)
|
||||||
assert.Equal(t, 18, len(managerRole.Rules))
|
assert.Equal(t, 15, len(managerClusterRole.Rules))
|
||||||
|
|
||||||
|
_, err = helm.RenderTemplateE(t, options, helmChartPath, releaseName, []string{"templates/manager_single_namespace_controller_role.yaml"})
|
||||||
|
assert.ErrorContains(t, err, "could not find template templates/manager_single_namespace_controller_role.yaml in chart", "We should get an error because the template should be skipped")
|
||||||
|
|
||||||
|
_, err = helm.RenderTemplateE(t, options, helmChartPath, releaseName, []string{"templates/manager_single_namespace_watch_role.yaml"})
|
||||||
|
assert.ErrorContains(t, err, "could not find template templates/manager_single_namespace_watch_role.yaml in chart", "We should get an error because the template should be skipped")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTemplate_ManagerRoleBinding(t *testing.T) {
|
func TestTemplate_ManagerClusterRoleBinding(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
@@ -189,16 +195,80 @@ func TestTemplate_ManagerRoleBinding(t *testing.T) {
|
|||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
|
|
||||||
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/manager_role_binding.yaml"})
|
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/manager_cluster_role_binding.yaml"})
|
||||||
|
|
||||||
var managerRoleBinding rbacv1.ClusterRoleBinding
|
var managerClusterRoleBinding rbacv1.ClusterRoleBinding
|
||||||
helm.UnmarshalK8SYaml(t, output, &managerRoleBinding)
|
helm.UnmarshalK8SYaml(t, output, &managerClusterRoleBinding)
|
||||||
|
|
||||||
assert.Empty(t, managerRoleBinding.Namespace, "ClusterRoleBinding should not have a namespace")
|
assert.Empty(t, managerClusterRoleBinding.Namespace, "ClusterRoleBinding should not have a namespace")
|
||||||
assert.Equal(t, "test-arc-gha-runner-scale-set-controller-manager-rolebinding", managerRoleBinding.Name)
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller-manager-cluster-rolebinding", managerClusterRoleBinding.Name)
|
||||||
assert.Equal(t, "test-arc-gha-runner-scale-set-controller-manager-role", managerRoleBinding.RoleRef.Name)
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller-manager-cluster-role", managerClusterRoleBinding.RoleRef.Name)
|
||||||
assert.Equal(t, "test-arc-gha-runner-scale-set-controller", managerRoleBinding.Subjects[0].Name)
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller", managerClusterRoleBinding.Subjects[0].Name)
|
||||||
assert.Equal(t, namespaceName, managerRoleBinding.Subjects[0].Namespace)
|
assert.Equal(t, namespaceName, managerClusterRoleBinding.Subjects[0].Namespace)
|
||||||
|
|
||||||
|
_, err = helm.RenderTemplateE(t, options, helmChartPath, releaseName, []string{"templates/manager_single_namespace_controller_role_binding.yaml"})
|
||||||
|
assert.ErrorContains(t, err, "could not find template templates/manager_single_namespace_controller_role_binding.yaml in chart", "We should get an error because the template should be skipped")
|
||||||
|
|
||||||
|
_, err = helm.RenderTemplateE(t, options, helmChartPath, releaseName, []string{"templates/manager_single_namespace_watch_role_binding.yaml"})
|
||||||
|
assert.ErrorContains(t, err, "could not find template templates/manager_single_namespace_watch_role_binding.yaml in chart", "We should get an error because the template should be skipped")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTemplate_CreateManagerListenerRole(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// Path to the helm chart we will test
|
||||||
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set-controller")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
releaseName := "test-arc"
|
||||||
|
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
||||||
|
|
||||||
|
options := &helm.Options{
|
||||||
|
SetValues: map[string]string{},
|
||||||
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
|
}
|
||||||
|
|
||||||
|
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/manager_listener_role.yaml"})
|
||||||
|
|
||||||
|
var managerListenerRole rbacv1.Role
|
||||||
|
helm.UnmarshalK8SYaml(t, output, &managerListenerRole)
|
||||||
|
|
||||||
|
assert.Equal(t, namespaceName, managerListenerRole.Namespace, "Role should have a namespace")
|
||||||
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller-manager-listener-role", managerListenerRole.Name)
|
||||||
|
assert.Equal(t, 4, len(managerListenerRole.Rules))
|
||||||
|
assert.Equal(t, "pods", managerListenerRole.Rules[0].Resources[0])
|
||||||
|
assert.Equal(t, "pods/status", managerListenerRole.Rules[1].Resources[0])
|
||||||
|
assert.Equal(t, "secrets", managerListenerRole.Rules[2].Resources[0])
|
||||||
|
assert.Equal(t, "serviceaccounts", managerListenerRole.Rules[3].Resources[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTemplate_ManagerListenerRoleBinding(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// Path to the helm chart we will test
|
||||||
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set-controller")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
releaseName := "test-arc"
|
||||||
|
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
||||||
|
|
||||||
|
options := &helm.Options{
|
||||||
|
SetValues: map[string]string{
|
||||||
|
"serviceAccount.create": "true",
|
||||||
|
},
|
||||||
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
|
}
|
||||||
|
|
||||||
|
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/manager_listener_role_binding.yaml"})
|
||||||
|
|
||||||
|
var managerListenerRoleBinding rbacv1.RoleBinding
|
||||||
|
helm.UnmarshalK8SYaml(t, output, &managerListenerRoleBinding)
|
||||||
|
|
||||||
|
assert.Equal(t, namespaceName, managerListenerRoleBinding.Namespace, "RoleBinding should have a namespace")
|
||||||
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller-manager-listener-rolebinding", managerListenerRoleBinding.Name)
|
||||||
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller-manager-listener-role", managerListenerRoleBinding.RoleRef.Name)
|
||||||
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller", managerListenerRoleBinding.Subjects[0].Name)
|
||||||
|
assert.Equal(t, namespaceName, managerListenerRoleBinding.Subjects[0].Namespace)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTemplate_ControllerDeployment_Defaults(t *testing.T) {
|
func TestTemplate_ControllerDeployment_Defaults(t *testing.T) {
|
||||||
@@ -237,6 +307,10 @@ func TestTemplate_ControllerDeployment_Defaults(t *testing.T) {
|
|||||||
assert.Equal(t, "test-arc", deployment.Labels["app.kubernetes.io/instance"])
|
assert.Equal(t, "test-arc", deployment.Labels["app.kubernetes.io/instance"])
|
||||||
assert.Equal(t, chart.AppVersion, deployment.Labels["app.kubernetes.io/version"])
|
assert.Equal(t, chart.AppVersion, deployment.Labels["app.kubernetes.io/version"])
|
||||||
assert.Equal(t, "Helm", deployment.Labels["app.kubernetes.io/managed-by"])
|
assert.Equal(t, "Helm", deployment.Labels["app.kubernetes.io/managed-by"])
|
||||||
|
assert.Equal(t, namespaceName, deployment.Labels["actions.github.com/controller-service-account-namespace"])
|
||||||
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller", deployment.Labels["actions.github.com/controller-service-account-name"])
|
||||||
|
assert.NotContains(t, deployment.Labels, "actions.github.com/controller-watch-single-namespace")
|
||||||
|
assert.Equal(t, "gha-runner-scale-set-controller", deployment.Labels["app.kubernetes.io/part-of"])
|
||||||
|
|
||||||
assert.Equal(t, int32(1), *deployment.Spec.Replicas)
|
assert.Equal(t, int32(1), *deployment.Spec.Replicas)
|
||||||
|
|
||||||
@@ -261,9 +335,11 @@ func TestTemplate_ControllerDeployment_Defaults(t *testing.T) {
|
|||||||
assert.Nil(t, deployment.Spec.Template.Spec.Affinity)
|
assert.Nil(t, deployment.Spec.Template.Spec.Affinity)
|
||||||
assert.Len(t, deployment.Spec.Template.Spec.Tolerations, 0)
|
assert.Len(t, deployment.Spec.Template.Spec.Tolerations, 0)
|
||||||
|
|
||||||
|
managerImage := "ghcr.io/actions/gha-runner-scale-set-controller:dev"
|
||||||
|
|
||||||
assert.Len(t, deployment.Spec.Template.Spec.Containers, 1)
|
assert.Len(t, deployment.Spec.Template.Spec.Containers, 1)
|
||||||
assert.Equal(t, "manager", deployment.Spec.Template.Spec.Containers[0].Name)
|
assert.Equal(t, "manager", deployment.Spec.Template.Spec.Containers[0].Name)
|
||||||
assert.Equal(t, "ghcr.io/actions/gha-runner-scale-set-controller:dev", deployment.Spec.Template.Spec.Containers[0].Image)
|
assert.Equal(t, managerImage, deployment.Spec.Template.Spec.Containers[0].Image)
|
||||||
assert.Equal(t, corev1.PullIfNotPresent, deployment.Spec.Template.Spec.Containers[0].ImagePullPolicy)
|
assert.Equal(t, corev1.PullIfNotPresent, deployment.Spec.Template.Spec.Containers[0].ImagePullPolicy)
|
||||||
|
|
||||||
assert.Len(t, deployment.Spec.Template.Spec.Containers[0].Command, 1)
|
assert.Len(t, deployment.Spec.Template.Spec.Containers[0].Command, 1)
|
||||||
@@ -274,8 +350,8 @@ func TestTemplate_ControllerDeployment_Defaults(t *testing.T) {
|
|||||||
assert.Equal(t, "--log-level=debug", deployment.Spec.Template.Spec.Containers[0].Args[1])
|
assert.Equal(t, "--log-level=debug", deployment.Spec.Template.Spec.Containers[0].Args[1])
|
||||||
|
|
||||||
assert.Len(t, deployment.Spec.Template.Spec.Containers[0].Env, 2)
|
assert.Len(t, deployment.Spec.Template.Spec.Containers[0].Env, 2)
|
||||||
assert.Equal(t, "CONTROLLER_MANAGER_POD_NAME", deployment.Spec.Template.Spec.Containers[0].Env[0].Name)
|
assert.Equal(t, "CONTROLLER_MANAGER_CONTAINER_IMAGE", deployment.Spec.Template.Spec.Containers[0].Env[0].Name)
|
||||||
assert.Equal(t, "metadata.name", deployment.Spec.Template.Spec.Containers[0].Env[0].ValueFrom.FieldRef.FieldPath)
|
assert.Equal(t, managerImage, deployment.Spec.Template.Spec.Containers[0].Env[0].Value)
|
||||||
|
|
||||||
assert.Equal(t, "CONTROLLER_MANAGER_POD_NAMESPACE", deployment.Spec.Template.Spec.Containers[0].Env[1].Name)
|
assert.Equal(t, "CONTROLLER_MANAGER_POD_NAMESPACE", deployment.Spec.Template.Spec.Containers[0].Env[1].Name)
|
||||||
assert.Equal(t, "metadata.namespace", deployment.Spec.Template.Spec.Containers[0].Env[1].ValueFrom.FieldRef.FieldPath)
|
assert.Equal(t, "metadata.namespace", deployment.Spec.Template.Spec.Containers[0].Env[1].ValueFrom.FieldRef.FieldPath)
|
||||||
@@ -314,6 +390,8 @@ func TestTemplate_ControllerDeployment_Customize(t *testing.T) {
|
|||||||
"imagePullSecrets[0].name": "dockerhub",
|
"imagePullSecrets[0].name": "dockerhub",
|
||||||
"nameOverride": "gha-runner-scale-set-controller-override",
|
"nameOverride": "gha-runner-scale-set-controller-override",
|
||||||
"fullnameOverride": "gha-runner-scale-set-controller-fullname-override",
|
"fullnameOverride": "gha-runner-scale-set-controller-fullname-override",
|
||||||
|
"env[0].name": "ENV_VAR_NAME_1",
|
||||||
|
"env[0].value": "ENV_VAR_VALUE_1",
|
||||||
"serviceAccount.name": "gha-runner-scale-set-controller-sa",
|
"serviceAccount.name": "gha-runner-scale-set-controller-sa",
|
||||||
"podAnnotations.foo": "bar",
|
"podAnnotations.foo": "bar",
|
||||||
"podSecurityContext.fsGroup": "1000",
|
"podSecurityContext.fsGroup": "1000",
|
||||||
@@ -341,6 +419,7 @@ func TestTemplate_ControllerDeployment_Customize(t *testing.T) {
|
|||||||
assert.Equal(t, "test-arc", deployment.Labels["app.kubernetes.io/instance"])
|
assert.Equal(t, "test-arc", deployment.Labels["app.kubernetes.io/instance"])
|
||||||
assert.Equal(t, chart.AppVersion, deployment.Labels["app.kubernetes.io/version"])
|
assert.Equal(t, chart.AppVersion, deployment.Labels["app.kubernetes.io/version"])
|
||||||
assert.Equal(t, "Helm", deployment.Labels["app.kubernetes.io/managed-by"])
|
assert.Equal(t, "Helm", deployment.Labels["app.kubernetes.io/managed-by"])
|
||||||
|
assert.Equal(t, "gha-runner-scale-set-controller", deployment.Labels["app.kubernetes.io/part-of"])
|
||||||
assert.Equal(t, "bar", deployment.Labels["foo"])
|
assert.Equal(t, "bar", deployment.Labels["foo"])
|
||||||
assert.Equal(t, "actions", deployment.Labels["github"])
|
assert.Equal(t, "actions", deployment.Labels["github"])
|
||||||
|
|
||||||
@@ -355,6 +434,9 @@ func TestTemplate_ControllerDeployment_Customize(t *testing.T) {
|
|||||||
assert.Equal(t, "bar", deployment.Spec.Template.Annotations["foo"])
|
assert.Equal(t, "bar", deployment.Spec.Template.Annotations["foo"])
|
||||||
assert.Equal(t, "manager", deployment.Spec.Template.Annotations["kubectl.kubernetes.io/default-container"])
|
assert.Equal(t, "manager", deployment.Spec.Template.Annotations["kubectl.kubernetes.io/default-container"])
|
||||||
|
|
||||||
|
assert.Equal(t, "ENV_VAR_NAME_1", deployment.Spec.Template.Spec.Containers[0].Env[2].Name)
|
||||||
|
assert.Equal(t, "ENV_VAR_VALUE_1", deployment.Spec.Template.Spec.Containers[0].Env[2].Value)
|
||||||
|
|
||||||
assert.Len(t, deployment.Spec.Template.Spec.ImagePullSecrets, 1)
|
assert.Len(t, deployment.Spec.Template.Spec.ImagePullSecrets, 1)
|
||||||
assert.Equal(t, "dockerhub", deployment.Spec.Template.Spec.ImagePullSecrets[0].Name)
|
assert.Equal(t, "dockerhub", deployment.Spec.Template.Spec.ImagePullSecrets[0].Name)
|
||||||
assert.Equal(t, "gha-runner-scale-set-controller-sa", deployment.Spec.Template.Spec.ServiceAccountName)
|
assert.Equal(t, "gha-runner-scale-set-controller-sa", deployment.Spec.Template.Spec.ServiceAccountName)
|
||||||
@@ -375,9 +457,11 @@ func TestTemplate_ControllerDeployment_Customize(t *testing.T) {
|
|||||||
assert.Len(t, deployment.Spec.Template.Spec.Tolerations, 1)
|
assert.Len(t, deployment.Spec.Template.Spec.Tolerations, 1)
|
||||||
assert.Equal(t, "foo", deployment.Spec.Template.Spec.Tolerations[0].Key)
|
assert.Equal(t, "foo", deployment.Spec.Template.Spec.Tolerations[0].Key)
|
||||||
|
|
||||||
|
managerImage := "ghcr.io/actions/gha-runner-scale-set-controller:dev"
|
||||||
|
|
||||||
assert.Len(t, deployment.Spec.Template.Spec.Containers, 1)
|
assert.Len(t, deployment.Spec.Template.Spec.Containers, 1)
|
||||||
assert.Equal(t, "manager", deployment.Spec.Template.Spec.Containers[0].Name)
|
assert.Equal(t, "manager", deployment.Spec.Template.Spec.Containers[0].Name)
|
||||||
assert.Equal(t, "ghcr.io/actions/gha-runner-scale-set-controller:dev", deployment.Spec.Template.Spec.Containers[0].Image)
|
assert.Equal(t, managerImage, deployment.Spec.Template.Spec.Containers[0].Image)
|
||||||
assert.Equal(t, corev1.PullAlways, deployment.Spec.Template.Spec.Containers[0].ImagePullPolicy)
|
assert.Equal(t, corev1.PullAlways, deployment.Spec.Template.Spec.Containers[0].ImagePullPolicy)
|
||||||
|
|
||||||
assert.Len(t, deployment.Spec.Template.Spec.Containers[0].Command, 1)
|
assert.Len(t, deployment.Spec.Template.Spec.Containers[0].Command, 1)
|
||||||
@@ -388,9 +472,12 @@ func TestTemplate_ControllerDeployment_Customize(t *testing.T) {
|
|||||||
assert.Equal(t, "--auto-scaler-image-pull-secrets=dockerhub", deployment.Spec.Template.Spec.Containers[0].Args[1])
|
assert.Equal(t, "--auto-scaler-image-pull-secrets=dockerhub", deployment.Spec.Template.Spec.Containers[0].Args[1])
|
||||||
assert.Equal(t, "--log-level=debug", deployment.Spec.Template.Spec.Containers[0].Args[2])
|
assert.Equal(t, "--log-level=debug", deployment.Spec.Template.Spec.Containers[0].Args[2])
|
||||||
|
|
||||||
assert.Len(t, deployment.Spec.Template.Spec.Containers[0].Env, 2)
|
assert.Len(t, deployment.Spec.Template.Spec.Containers[0].Env, 3)
|
||||||
assert.Equal(t, "CONTROLLER_MANAGER_POD_NAME", deployment.Spec.Template.Spec.Containers[0].Env[0].Name)
|
assert.Equal(t, "CONTROLLER_MANAGER_CONTAINER_IMAGE", deployment.Spec.Template.Spec.Containers[0].Env[0].Name)
|
||||||
assert.Equal(t, "metadata.name", deployment.Spec.Template.Spec.Containers[0].Env[0].ValueFrom.FieldRef.FieldPath)
|
assert.Equal(t, managerImage, deployment.Spec.Template.Spec.Containers[0].Env[0].Value)
|
||||||
|
|
||||||
|
assert.Equal(t, "ENV_VAR_NAME_1", deployment.Spec.Template.Spec.Containers[0].Env[2].Name)
|
||||||
|
assert.Equal(t, "ENV_VAR_VALUE_1", deployment.Spec.Template.Spec.Containers[0].Env[2].Value)
|
||||||
|
|
||||||
assert.Equal(t, "CONTROLLER_MANAGER_POD_NAMESPACE", deployment.Spec.Template.Spec.Containers[0].Env[1].Name)
|
assert.Equal(t, "CONTROLLER_MANAGER_POD_NAMESPACE", deployment.Spec.Template.Spec.Containers[0].Env[1].Name)
|
||||||
assert.Equal(t, "metadata.namespace", deployment.Spec.Template.Spec.Containers[0].Env[1].ValueFrom.FieldRef.FieldPath)
|
assert.Equal(t, "metadata.namespace", deployment.Spec.Template.Spec.Containers[0].Env[1].ValueFrom.FieldRef.FieldPath)
|
||||||
@@ -531,3 +618,261 @@ func TestTemplate_ControllerDeployment_ForwardImagePullSecrets(t *testing.T) {
|
|||||||
assert.Equal(t, "--auto-scaler-image-pull-secrets=dockerhub,ghcr", deployment.Spec.Template.Spec.Containers[0].Args[1])
|
assert.Equal(t, "--auto-scaler-image-pull-secrets=dockerhub,ghcr", deployment.Spec.Template.Spec.Containers[0].Args[1])
|
||||||
assert.Equal(t, "--log-level=debug", deployment.Spec.Template.Spec.Containers[0].Args[2])
|
assert.Equal(t, "--log-level=debug", deployment.Spec.Template.Spec.Containers[0].Args[2])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTemplate_ControllerDeployment_WatchSingleNamespace(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// Path to the helm chart we will test
|
||||||
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set-controller")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
chartContent, err := os.ReadFile(filepath.Join(helmChartPath, "Chart.yaml"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
chart := new(Chart)
|
||||||
|
err = yaml.Unmarshal(chartContent, chart)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
releaseName := "test-arc"
|
||||||
|
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
||||||
|
|
||||||
|
options := &helm.Options{
|
||||||
|
SetValues: map[string]string{
|
||||||
|
"image.tag": "dev",
|
||||||
|
"flags.watchSingleNamespace": "demo",
|
||||||
|
},
|
||||||
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
|
}
|
||||||
|
|
||||||
|
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/deployment.yaml"})
|
||||||
|
|
||||||
|
var deployment appsv1.Deployment
|
||||||
|
helm.UnmarshalK8SYaml(t, output, &deployment)
|
||||||
|
|
||||||
|
assert.Equal(t, namespaceName, deployment.Namespace)
|
||||||
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller", deployment.Name)
|
||||||
|
assert.Equal(t, "gha-runner-scale-set-controller-"+chart.Version, deployment.Labels["helm.sh/chart"])
|
||||||
|
assert.Equal(t, "gha-runner-scale-set-controller", deployment.Labels["app.kubernetes.io/name"])
|
||||||
|
assert.Equal(t, "test-arc", deployment.Labels["app.kubernetes.io/instance"])
|
||||||
|
assert.Equal(t, chart.AppVersion, deployment.Labels["app.kubernetes.io/version"])
|
||||||
|
assert.Equal(t, "Helm", deployment.Labels["app.kubernetes.io/managed-by"])
|
||||||
|
assert.Equal(t, namespaceName, deployment.Labels["actions.github.com/controller-service-account-namespace"])
|
||||||
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller", deployment.Labels["actions.github.com/controller-service-account-name"])
|
||||||
|
assert.Equal(t, "demo", deployment.Labels["actions.github.com/controller-watch-single-namespace"])
|
||||||
|
|
||||||
|
assert.Equal(t, int32(1), *deployment.Spec.Replicas)
|
||||||
|
|
||||||
|
assert.Equal(t, "gha-runner-scale-set-controller", deployment.Spec.Selector.MatchLabels["app.kubernetes.io/name"])
|
||||||
|
assert.Equal(t, "test-arc", deployment.Spec.Selector.MatchLabels["app.kubernetes.io/instance"])
|
||||||
|
|
||||||
|
assert.Equal(t, "gha-runner-scale-set-controller", deployment.Spec.Template.Labels["app.kubernetes.io/name"])
|
||||||
|
assert.Equal(t, "test-arc", deployment.Spec.Template.Labels["app.kubernetes.io/instance"])
|
||||||
|
|
||||||
|
assert.Equal(t, "manager", deployment.Spec.Template.Annotations["kubectl.kubernetes.io/default-container"])
|
||||||
|
|
||||||
|
assert.Len(t, deployment.Spec.Template.Spec.ImagePullSecrets, 0)
|
||||||
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller", deployment.Spec.Template.Spec.ServiceAccountName)
|
||||||
|
assert.Nil(t, deployment.Spec.Template.Spec.SecurityContext)
|
||||||
|
assert.Empty(t, deployment.Spec.Template.Spec.PriorityClassName)
|
||||||
|
assert.Equal(t, int64(10), *deployment.Spec.Template.Spec.TerminationGracePeriodSeconds)
|
||||||
|
assert.Len(t, deployment.Spec.Template.Spec.Volumes, 1)
|
||||||
|
assert.Equal(t, "tmp", deployment.Spec.Template.Spec.Volumes[0].Name)
|
||||||
|
assert.NotNil(t, 10, deployment.Spec.Template.Spec.Volumes[0].EmptyDir)
|
||||||
|
|
||||||
|
assert.Len(t, deployment.Spec.Template.Spec.NodeSelector, 0)
|
||||||
|
assert.Nil(t, deployment.Spec.Template.Spec.Affinity)
|
||||||
|
assert.Len(t, deployment.Spec.Template.Spec.Tolerations, 0)
|
||||||
|
|
||||||
|
managerImage := "ghcr.io/actions/gha-runner-scale-set-controller:dev"
|
||||||
|
|
||||||
|
assert.Len(t, deployment.Spec.Template.Spec.Containers, 1)
|
||||||
|
assert.Equal(t, "manager", deployment.Spec.Template.Spec.Containers[0].Name)
|
||||||
|
assert.Equal(t, "ghcr.io/actions/gha-runner-scale-set-controller:dev", deployment.Spec.Template.Spec.Containers[0].Image)
|
||||||
|
assert.Equal(t, corev1.PullIfNotPresent, deployment.Spec.Template.Spec.Containers[0].ImagePullPolicy)
|
||||||
|
|
||||||
|
assert.Len(t, deployment.Spec.Template.Spec.Containers[0].Command, 1)
|
||||||
|
assert.Equal(t, "/manager", deployment.Spec.Template.Spec.Containers[0].Command[0])
|
||||||
|
|
||||||
|
assert.Len(t, deployment.Spec.Template.Spec.Containers[0].Args, 3)
|
||||||
|
assert.Equal(t, "--auto-scaling-runner-set-only", deployment.Spec.Template.Spec.Containers[0].Args[0])
|
||||||
|
assert.Equal(t, "--log-level=debug", deployment.Spec.Template.Spec.Containers[0].Args[1])
|
||||||
|
assert.Equal(t, "--watch-single-namespace=demo", deployment.Spec.Template.Spec.Containers[0].Args[2])
|
||||||
|
|
||||||
|
assert.Len(t, deployment.Spec.Template.Spec.Containers[0].Env, 2)
|
||||||
|
assert.Equal(t, "CONTROLLER_MANAGER_CONTAINER_IMAGE", deployment.Spec.Template.Spec.Containers[0].Env[0].Name)
|
||||||
|
assert.Equal(t, managerImage, deployment.Spec.Template.Spec.Containers[0].Env[0].Value)
|
||||||
|
|
||||||
|
assert.Equal(t, "CONTROLLER_MANAGER_POD_NAMESPACE", deployment.Spec.Template.Spec.Containers[0].Env[1].Name)
|
||||||
|
assert.Equal(t, "metadata.namespace", deployment.Spec.Template.Spec.Containers[0].Env[1].ValueFrom.FieldRef.FieldPath)
|
||||||
|
|
||||||
|
assert.Empty(t, deployment.Spec.Template.Spec.Containers[0].Resources)
|
||||||
|
assert.Nil(t, deployment.Spec.Template.Spec.Containers[0].SecurityContext)
|
||||||
|
assert.Len(t, deployment.Spec.Template.Spec.Containers[0].VolumeMounts, 1)
|
||||||
|
assert.Equal(t, "tmp", deployment.Spec.Template.Spec.Containers[0].VolumeMounts[0].Name)
|
||||||
|
assert.Equal(t, "/tmp", deployment.Spec.Template.Spec.Containers[0].VolumeMounts[0].MountPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTemplate_ControllerContainerEnvironmentVariables(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// Path to the helm chart we will test
|
||||||
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set-controller")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
releaseName := "test-arc"
|
||||||
|
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
||||||
|
|
||||||
|
options := &helm.Options{
|
||||||
|
SetValues: map[string]string{
|
||||||
|
"env[0].Name": "ENV_VAR_NAME_1",
|
||||||
|
"env[0].Value": "ENV_VAR_VALUE_1",
|
||||||
|
"env[1].Name": "ENV_VAR_NAME_2",
|
||||||
|
"env[1].ValueFrom.SecretKeyRef.Key": "ENV_VAR_NAME_2",
|
||||||
|
"env[1].ValueFrom.SecretKeyRef.Name": "secret-name",
|
||||||
|
"env[1].ValueFrom.SecretKeyRef.Optional": "true",
|
||||||
|
"env[2].Name": "ENV_VAR_NAME_3",
|
||||||
|
"env[2].Value": "",
|
||||||
|
"env[3].Name": "ENV_VAR_NAME_4",
|
||||||
|
},
|
||||||
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
|
}
|
||||||
|
|
||||||
|
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/deployment.yaml"})
|
||||||
|
|
||||||
|
var deployment appsv1.Deployment
|
||||||
|
helm.UnmarshalK8SYaml(t, output, &deployment)
|
||||||
|
|
||||||
|
assert.Equal(t, namespaceName, deployment.Namespace)
|
||||||
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller", deployment.Name)
|
||||||
|
|
||||||
|
assert.Len(t, deployment.Spec.Template.Spec.Containers[0].Env, 6)
|
||||||
|
assert.Equal(t, "ENV_VAR_NAME_1", deployment.Spec.Template.Spec.Containers[0].Env[2].Name)
|
||||||
|
assert.Equal(t, "ENV_VAR_VALUE_1", deployment.Spec.Template.Spec.Containers[0].Env[2].Value)
|
||||||
|
assert.Equal(t, "ENV_VAR_NAME_2", deployment.Spec.Template.Spec.Containers[0].Env[3].Name)
|
||||||
|
assert.Equal(t, "secret-name", deployment.Spec.Template.Spec.Containers[0].Env[3].ValueFrom.SecretKeyRef.Name)
|
||||||
|
assert.Equal(t, "ENV_VAR_NAME_2", deployment.Spec.Template.Spec.Containers[0].Env[3].ValueFrom.SecretKeyRef.Key)
|
||||||
|
assert.True(t, *deployment.Spec.Template.Spec.Containers[0].Env[3].ValueFrom.SecretKeyRef.Optional)
|
||||||
|
assert.Equal(t, "ENV_VAR_NAME_3", deployment.Spec.Template.Spec.Containers[0].Env[4].Name)
|
||||||
|
assert.Empty(t, deployment.Spec.Template.Spec.Containers[0].Env[4].Value)
|
||||||
|
assert.Equal(t, "ENV_VAR_NAME_4", deployment.Spec.Template.Spec.Containers[0].Env[5].Name)
|
||||||
|
assert.Empty(t, deployment.Spec.Template.Spec.Containers[0].Env[5].ValueFrom)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTemplate_WatchSingleNamespace_NotCreateManagerClusterRole(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// Path to the helm chart we will test
|
||||||
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set-controller")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
releaseName := "test-arc"
|
||||||
|
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
||||||
|
|
||||||
|
options := &helm.Options{
|
||||||
|
SetValues: map[string]string{
|
||||||
|
"flags.watchSingleNamespace": "demo",
|
||||||
|
},
|
||||||
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = helm.RenderTemplateE(t, options, helmChartPath, releaseName, []string{"templates/manager_cluster_role.yaml"})
|
||||||
|
assert.ErrorContains(t, err, "could not find template templates/manager_cluster_role.yaml in chart", "We should get an error because the template should be skipped")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTemplate_WatchSingleNamespace_NotManagerClusterRoleBinding(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// Path to the helm chart we will test
|
||||||
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set-controller")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
releaseName := "test-arc"
|
||||||
|
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
||||||
|
|
||||||
|
options := &helm.Options{
|
||||||
|
SetValues: map[string]string{
|
||||||
|
"serviceAccount.create": "true",
|
||||||
|
"flags.watchSingleNamespace": "demo",
|
||||||
|
},
|
||||||
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = helm.RenderTemplateE(t, options, helmChartPath, releaseName, []string{"templates/manager_cluster_role_binding.yaml"})
|
||||||
|
assert.ErrorContains(t, err, "could not find template templates/manager_cluster_role_binding.yaml in chart", "We should get an error because the template should be skipped")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTemplate_CreateManagerSingleNamespaceRole(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// Path to the helm chart we will test
|
||||||
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set-controller")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
releaseName := "test-arc"
|
||||||
|
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
||||||
|
|
||||||
|
options := &helm.Options{
|
||||||
|
SetValues: map[string]string{
|
||||||
|
"flags.watchSingleNamespace": "demo",
|
||||||
|
},
|
||||||
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
|
}
|
||||||
|
|
||||||
|
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/manager_single_namespace_controller_role.yaml"})
|
||||||
|
|
||||||
|
var managerSingleNamespaceControllerRole rbacv1.Role
|
||||||
|
helm.UnmarshalK8SYaml(t, output, &managerSingleNamespaceControllerRole)
|
||||||
|
|
||||||
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller-manager-single-namespace-role", managerSingleNamespaceControllerRole.Name)
|
||||||
|
assert.Equal(t, namespaceName, managerSingleNamespaceControllerRole.Namespace)
|
||||||
|
assert.Equal(t, 10, len(managerSingleNamespaceControllerRole.Rules))
|
||||||
|
|
||||||
|
output = helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/manager_single_namespace_watch_role.yaml"})
|
||||||
|
|
||||||
|
var managerSingleNamespaceWatchRole rbacv1.Role
|
||||||
|
helm.UnmarshalK8SYaml(t, output, &managerSingleNamespaceWatchRole)
|
||||||
|
|
||||||
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller-manager-single-namespace-role", managerSingleNamespaceWatchRole.Name)
|
||||||
|
assert.Equal(t, "demo", managerSingleNamespaceWatchRole.Namespace)
|
||||||
|
assert.Equal(t, 13, len(managerSingleNamespaceWatchRole.Rules))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTemplate_ManagerSingleNamespaceRoleBinding(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// Path to the helm chart we will test
|
||||||
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set-controller")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
releaseName := "test-arc"
|
||||||
|
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
||||||
|
|
||||||
|
options := &helm.Options{
|
||||||
|
SetValues: map[string]string{
|
||||||
|
"flags.watchSingleNamespace": "demo",
|
||||||
|
},
|
||||||
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
|
}
|
||||||
|
|
||||||
|
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/manager_single_namespace_controller_role_binding.yaml"})
|
||||||
|
|
||||||
|
var managerSingleNamespaceControllerRoleBinding rbacv1.RoleBinding
|
||||||
|
helm.UnmarshalK8SYaml(t, output, &managerSingleNamespaceControllerRoleBinding)
|
||||||
|
|
||||||
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller-manager-single-namespace-rolebinding", managerSingleNamespaceControllerRoleBinding.Name)
|
||||||
|
assert.Equal(t, namespaceName, managerSingleNamespaceControllerRoleBinding.Namespace)
|
||||||
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller-manager-single-namespace-role", managerSingleNamespaceControllerRoleBinding.RoleRef.Name)
|
||||||
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller", managerSingleNamespaceControllerRoleBinding.Subjects[0].Name)
|
||||||
|
assert.Equal(t, namespaceName, managerSingleNamespaceControllerRoleBinding.Subjects[0].Namespace)
|
||||||
|
|
||||||
|
output = helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/manager_single_namespace_watch_role_binding.yaml"})
|
||||||
|
|
||||||
|
var managerSingleNamespaceWatchRoleBinding rbacv1.RoleBinding
|
||||||
|
helm.UnmarshalK8SYaml(t, output, &managerSingleNamespaceWatchRoleBinding)
|
||||||
|
|
||||||
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller-manager-single-namespace-rolebinding", managerSingleNamespaceWatchRoleBinding.Name)
|
||||||
|
assert.Equal(t, "demo", managerSingleNamespaceWatchRoleBinding.Namespace)
|
||||||
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller-manager-single-namespace-role", managerSingleNamespaceWatchRoleBinding.RoleRef.Name)
|
||||||
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller", managerSingleNamespaceWatchRoleBinding.Subjects[0].Name)
|
||||||
|
assert.Equal(t, namespaceName, managerSingleNamespaceWatchRoleBinding.Subjects[0].Namespace)
|
||||||
|
}
|
||||||
|
|||||||
@@ -18,6 +18,17 @@ imagePullSecrets: []
|
|||||||
nameOverride: ""
|
nameOverride: ""
|
||||||
fullnameOverride: ""
|
fullnameOverride: ""
|
||||||
|
|
||||||
|
env:
|
||||||
|
## Define environment variables for the controller pod
|
||||||
|
# - name: "ENV_VAR_NAME_1"
|
||||||
|
# value: "ENV_VAR_VALUE_1"
|
||||||
|
# - name: "ENV_VAR_NAME_2"
|
||||||
|
# valueFrom:
|
||||||
|
# secretKeyRef:
|
||||||
|
# key: ENV_VAR_NAME_2
|
||||||
|
# name: secret-name
|
||||||
|
# optional: true
|
||||||
|
|
||||||
serviceAccount:
|
serviceAccount:
|
||||||
# Specifies whether a service account should be created for running the controller pod
|
# Specifies whether a service account should be created for running the controller pod
|
||||||
create: true
|
create: true
|
||||||
@@ -31,27 +42,27 @@ serviceAccount:
|
|||||||
podAnnotations: {}
|
podAnnotations: {}
|
||||||
|
|
||||||
podSecurityContext: {}
|
podSecurityContext: {}
|
||||||
# fsGroup: 2000
|
# fsGroup: 2000
|
||||||
|
|
||||||
securityContext: {}
|
securityContext: {}
|
||||||
# capabilities:
|
# capabilities:
|
||||||
# drop:
|
# drop:
|
||||||
# - ALL
|
# - ALL
|
||||||
# readOnlyRootFilesystem: true
|
# readOnlyRootFilesystem: true
|
||||||
# runAsNonRoot: true
|
# runAsNonRoot: true
|
||||||
# runAsUser: 1000
|
# runAsUser: 1000
|
||||||
|
|
||||||
resources: {}
|
resources: {}
|
||||||
# We usually recommend not to specify default resources and to leave this as a conscious
|
## We usually recommend not to specify default resources and to leave this as a conscious
|
||||||
# choice for the user. This also increases chances charts run on environments with little
|
## choice for the user. This also increases chances charts run on environments with little
|
||||||
# resources, such as Minikube. If you do want to specify resources, uncomment the following
|
## resources, such as Minikube. If you do want to specify resources, uncomment the following
|
||||||
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
|
## lines, adjust them as necessary, and remove the curly braces after 'resources:'.
|
||||||
# limits:
|
# limits:
|
||||||
# cpu: 100m
|
# cpu: 100m
|
||||||
# memory: 128Mi
|
# memory: 128Mi
|
||||||
# requests:
|
# requests:
|
||||||
# cpu: 100m
|
# cpu: 100m
|
||||||
# memory: 128Mi
|
# memory: 128Mi
|
||||||
|
|
||||||
nodeSelector: {}
|
nodeSelector: {}
|
||||||
|
|
||||||
@@ -68,3 +79,7 @@ flags:
|
|||||||
# Log level can be set here with one of the following values: "debug", "info", "warn", "error".
|
# Log level can be set here with one of the following values: "debug", "info", "warn", "error".
|
||||||
# Defaults to "debug".
|
# Defaults to "debug".
|
||||||
logLevel: "debug"
|
logLevel: "debug"
|
||||||
|
|
||||||
|
## Restricts the controller to only watch resources in the desired namespace.
|
||||||
|
## Defaults to watch all namespaces when unset.
|
||||||
|
# watchSingleNamespace: ""
|
||||||
|
|||||||
@@ -3,4 +3,4 @@
|
|||||||
githubConfigUrl: https://github.com/actions/actions-runner-controller
|
githubConfigUrl: https://github.com/actions/actions-runner-controller
|
||||||
|
|
||||||
githubConfigSecret:
|
githubConfigSecret:
|
||||||
github_token: test
|
github_token: test
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ helm.sh/chart: {{ include "gha-runner-scale-set.chart" . }}
|
|||||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
app.kubernetes.io/part-of: gha-runner-scale-set
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{/*
|
{{/*
|
||||||
@@ -75,19 +76,15 @@ app.kubernetes.io/instance: {{ .Release.Name }}
|
|||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- define "gha-runner-scale-set.dind-init-container" -}}
|
{{- define "gha-runner-scale-set.dind-init-container" -}}
|
||||||
{{- range $i, $val := .Values.template.spec.containers -}}
|
{{- range $i, $val := .Values.template.spec.containers }}
|
||||||
{{- if eq $val.name "runner" -}}
|
{{- if eq $val.name "runner" }}
|
||||||
image: {{ $val.image }}
|
image: {{ $val.image }}
|
||||||
{{- if $val.imagePullSecrets }}
|
|
||||||
imagePullSecrets:
|
|
||||||
{{ $val.imagePullSecrets | toYaml -}}
|
|
||||||
{{- end }}
|
|
||||||
command: ["cp"]
|
command: ["cp"]
|
||||||
args: ["-r", "-v", "/home/runner/externals/.", "/home/runner/tmpDir/"]
|
args: ["-r", "-v", "/home/runner/externals/.", "/home/runner/tmpDir/"]
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: dind-externals
|
- name: dind-externals
|
||||||
mountPath: /home/runner/tmpDir
|
mountPath: /home/runner/tmpDir
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
@@ -124,7 +121,7 @@ volumeMounts:
|
|||||||
{{- $createWorkVolume := 1 }}
|
{{- $createWorkVolume := 1 }}
|
||||||
{{- range $i, $volume := .Values.template.spec.volumes }}
|
{{- range $i, $volume := .Values.template.spec.volumes }}
|
||||||
{{- if eq $volume.name "work" }}
|
{{- if eq $volume.name "work" }}
|
||||||
{{- $createWorkVolume = 0 -}}
|
{{- $createWorkVolume = 0 }}
|
||||||
- {{ $volume | toYaml | nindent 2 }}
|
- {{ $volume | toYaml | nindent 2 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
@@ -138,7 +135,7 @@ volumeMounts:
|
|||||||
{{- $createWorkVolume := 1 }}
|
{{- $createWorkVolume := 1 }}
|
||||||
{{- range $i, $volume := .Values.template.spec.volumes }}
|
{{- range $i, $volume := .Values.template.spec.volumes }}
|
||||||
{{- if eq $volume.name "work" }}
|
{{- if eq $volume.name "work" }}
|
||||||
{{- $createWorkVolume = 0 -}}
|
{{- $createWorkVolume = 0 }}
|
||||||
- {{ $volume | toYaml | nindent 2 }}
|
- {{ $volume | toYaml | nindent 2 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
@@ -160,25 +157,28 @@ volumeMounts:
|
|||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- define "gha-runner-scale-set.non-runner-containers" -}}
|
{{- define "gha-runner-scale-set.non-runner-containers" -}}
|
||||||
{{- range $i, $container := .Values.template.spec.containers -}}
|
{{- range $i, $container := .Values.template.spec.containers }}
|
||||||
{{- if ne $container.name "runner" -}}
|
{{- if ne $container.name "runner" }}
|
||||||
- name: {{ $container.name }}
|
- {{ $container | toYaml | nindent 2 }}
|
||||||
{{- range $key, $val := $container }}
|
{{- end }}
|
||||||
{{- if ne $key "name" }}
|
{{- end }}
|
||||||
{{ $key }}: {{ $val }}
|
{{- end }}
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
{{- define "gha-runner-scale-set.non-runner-non-dind-containers" -}}
|
||||||
|
{{- range $i, $container := .Values.template.spec.containers }}
|
||||||
|
{{- if and (ne $container.name "runner") (ne $container.name "dind") }}
|
||||||
|
- {{ $container | toYaml | nindent 2 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- define "gha-runner-scale-set.dind-runner-container" -}}
|
{{- define "gha-runner-scale-set.dind-runner-container" -}}
|
||||||
{{- $tlsConfig := (default (dict) .Values.githubServerTLS) }}
|
{{- $tlsConfig := (default (dict) .Values.githubServerTLS) }}
|
||||||
{{- range $i, $container := .Values.template.spec.containers -}}
|
{{- range $i, $container := .Values.template.spec.containers }}
|
||||||
{{- if eq $container.name "runner" -}}
|
{{- if eq $container.name "runner" }}
|
||||||
{{- range $key, $val := $container }}
|
{{- range $key, $val := $container }}
|
||||||
{{- if and (ne $key "env") (ne $key "volumeMounts") (ne $key "name") }}
|
{{- if and (ne $key "env") (ne $key "volumeMounts") (ne $key "name") }}
|
||||||
{{ $key }}: {{ $val }}
|
{{ $key }}: {{ $val | toYaml | nindent 2 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- $setDockerHost := 1 }}
|
{{- $setDockerHost := 1 }}
|
||||||
@@ -195,29 +195,24 @@ env:
|
|||||||
{{- with $container.env }}
|
{{- with $container.env }}
|
||||||
{{- range $i, $env := . }}
|
{{- range $i, $env := . }}
|
||||||
{{- if eq $env.name "DOCKER_HOST" }}
|
{{- if eq $env.name "DOCKER_HOST" }}
|
||||||
{{- $setDockerHost = 0 -}}
|
{{- $setDockerHost = 0 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if eq $env.name "DOCKER_TLS_VERIFY" }}
|
{{- if eq $env.name "DOCKER_TLS_VERIFY" }}
|
||||||
{{- $setDockerTlsVerify = 0 -}}
|
{{- $setDockerTlsVerify = 0 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if eq $env.name "DOCKER_CERT_PATH" }}
|
{{- if eq $env.name "DOCKER_CERT_PATH" }}
|
||||||
{{- $setDockerCertPath = 0 -}}
|
{{- $setDockerCertPath = 0 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if eq $env.name "RUNNER_WAIT_FOR_DOCKER_IN_SECONDS" }}
|
{{- if eq $env.name "RUNNER_WAIT_FOR_DOCKER_IN_SECONDS" }}
|
||||||
{{- $setRunnerWaitDocker = 0 -}}
|
{{- $setRunnerWaitDocker = 0 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if eq $env.name "NODE_EXTRA_CA_CERTS" }}
|
{{- if eq $env.name "NODE_EXTRA_CA_CERTS" }}
|
||||||
{{- $setNodeExtraCaCerts = 0 -}}
|
{{- $setNodeExtraCaCerts = 0 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if eq $env.name "RUNNER_UPDATE_CA_CERTS" }}
|
{{- if eq $env.name "RUNNER_UPDATE_CA_CERTS" }}
|
||||||
{{- $setRunnerUpdateCaCerts = 0 -}}
|
{{- $setRunnerUpdateCaCerts = 0 }}
|
||||||
{{- end }}
|
|
||||||
- name: {{ $env.name }}
|
|
||||||
{{- range $envKey, $envVal := $env }}
|
|
||||||
{{- if ne $envKey "name" }}
|
|
||||||
{{ $envKey }}: {{ $envVal | toYaml | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
- {{ $env | toYaml | nindent 4 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if $setDockerHost }}
|
{{- if $setDockerHost }}
|
||||||
@@ -254,20 +249,15 @@ volumeMounts:
|
|||||||
{{- with $container.volumeMounts }}
|
{{- with $container.volumeMounts }}
|
||||||
{{- range $i, $volMount := . }}
|
{{- range $i, $volMount := . }}
|
||||||
{{- if eq $volMount.name "work" }}
|
{{- if eq $volMount.name "work" }}
|
||||||
{{- $mountWork = 0 -}}
|
{{- $mountWork = 0 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if eq $volMount.name "dind-cert" }}
|
{{- if eq $volMount.name "dind-cert" }}
|
||||||
{{- $mountDindCert = 0 -}}
|
{{- $mountDindCert = 0 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if eq $volMount.name "github-server-tls-cert" }}
|
{{- if eq $volMount.name "github-server-tls-cert" }}
|
||||||
{{- $mountGitHubServerTLS = 0 -}}
|
{{- $mountGitHubServerTLS = 0 }}
|
||||||
{{- end }}
|
|
||||||
- name: {{ $volMount.name }}
|
|
||||||
{{- range $mountKey, $mountVal := $volMount }}
|
|
||||||
{{- if ne $mountKey "name" }}
|
|
||||||
{{ $mountKey }}: {{ $mountVal | toYaml | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
- {{ $volMount | toYaml | nindent 4 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if $mountWork }}
|
{{- if $mountWork }}
|
||||||
@@ -290,11 +280,11 @@ volumeMounts:
|
|||||||
|
|
||||||
{{- define "gha-runner-scale-set.kubernetes-mode-runner-container" -}}
|
{{- define "gha-runner-scale-set.kubernetes-mode-runner-container" -}}
|
||||||
{{- $tlsConfig := (default (dict) .Values.githubServerTLS) }}
|
{{- $tlsConfig := (default (dict) .Values.githubServerTLS) }}
|
||||||
{{- range $i, $container := .Values.template.spec.containers -}}
|
{{- range $i, $container := .Values.template.spec.containers }}
|
||||||
{{- if eq $container.name "runner" -}}
|
{{- if eq $container.name "runner" }}
|
||||||
{{- range $key, $val := $container }}
|
{{- range $key, $val := $container }}
|
||||||
{{- if and (ne $key "env") (ne $key "volumeMounts") (ne $key "name") }}
|
{{- if and (ne $key "env") (ne $key "volumeMounts") (ne $key "name") }}
|
||||||
{{ $key }}: {{ $val }}
|
{{ $key }}: {{ $val | toYaml | nindent 2 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- $setContainerHooks := 1 }}
|
{{- $setContainerHooks := 1 }}
|
||||||
@@ -310,26 +300,21 @@ env:
|
|||||||
{{- with $container.env }}
|
{{- with $container.env }}
|
||||||
{{- range $i, $env := . }}
|
{{- range $i, $env := . }}
|
||||||
{{- if eq $env.name "ACTIONS_RUNNER_CONTAINER_HOOKS" }}
|
{{- if eq $env.name "ACTIONS_RUNNER_CONTAINER_HOOKS" }}
|
||||||
{{- $setContainerHooks = 0 -}}
|
{{- $setContainerHooks = 0 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if eq $env.name "ACTIONS_RUNNER_POD_NAME" }}
|
{{- if eq $env.name "ACTIONS_RUNNER_POD_NAME" }}
|
||||||
{{- $setPodName = 0 -}}
|
{{- $setPodName = 0 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if eq $env.name "ACTIONS_RUNNER_REQUIRE_JOB_CONTAINER" }}
|
{{- if eq $env.name "ACTIONS_RUNNER_REQUIRE_JOB_CONTAINER" }}
|
||||||
{{- $setRequireJobContainer = 0 -}}
|
{{- $setRequireJobContainer = 0 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if eq $env.name "NODE_EXTRA_CA_CERTS" }}
|
{{- if eq $env.name "NODE_EXTRA_CA_CERTS" }}
|
||||||
{{- $setNodeExtraCaCerts = 0 -}}
|
{{- $setNodeExtraCaCerts = 0 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if eq $env.name "RUNNER_UPDATE_CA_CERTS" }}
|
{{- if eq $env.name "RUNNER_UPDATE_CA_CERTS" }}
|
||||||
{{- $setRunnerUpdateCaCerts = 0 -}}
|
{{- $setRunnerUpdateCaCerts = 0 }}
|
||||||
{{- end }}
|
|
||||||
- name: {{ $env.name }}
|
|
||||||
{{- range $envKey, $envVal := $env }}
|
|
||||||
{{- if ne $envKey "name" }}
|
|
||||||
{{ $envKey }}: {{ $envVal | toYaml | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
- {{ $env | toYaml | nindent 4 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if $setContainerHooks }}
|
{{- if $setContainerHooks }}
|
||||||
@@ -363,17 +348,12 @@ volumeMounts:
|
|||||||
{{- with $container.volumeMounts }}
|
{{- with $container.volumeMounts }}
|
||||||
{{- range $i, $volMount := . }}
|
{{- range $i, $volMount := . }}
|
||||||
{{- if eq $volMount.name "work" }}
|
{{- if eq $volMount.name "work" }}
|
||||||
{{- $mountWork = 0 -}}
|
{{- $mountWork = 0 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if eq $volMount.name "github-server-tls-cert" }}
|
{{- if eq $volMount.name "github-server-tls-cert" }}
|
||||||
{{- $mountGitHubServerTLS = 0 -}}
|
{{- $mountGitHubServerTLS = 0 }}
|
||||||
{{- end }}
|
|
||||||
- name: {{ $volMount.name }}
|
|
||||||
{{- range $mountKey, $mountVal := $volMount }}
|
|
||||||
{{- if ne $mountKey "name" }}
|
|
||||||
{{ $mountKey }}: {{ $mountVal | toYaml | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
- {{ $volMount | toYaml | nindent 4 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if $mountWork }}
|
{{- if $mountWork }}
|
||||||
@@ -391,14 +371,14 @@ volumeMounts:
|
|||||||
|
|
||||||
{{- define "gha-runner-scale-set.default-mode-runner-containers" -}}
|
{{- define "gha-runner-scale-set.default-mode-runner-containers" -}}
|
||||||
{{- $tlsConfig := (default (dict) .Values.githubServerTLS) }}
|
{{- $tlsConfig := (default (dict) .Values.githubServerTLS) }}
|
||||||
{{- range $i, $container := .Values.template.spec.containers -}}
|
{{- range $i, $container := .Values.template.spec.containers }}
|
||||||
{{- if ne $container.name "runner" -}}
|
{{- if ne $container.name "runner" }}
|
||||||
- {{ $container | toYaml | nindent 2 }}
|
- {{ $container | toYaml | nindent 2 }}
|
||||||
{{- else }}
|
{{- else }}
|
||||||
- name: {{ $container.name }}
|
- name: {{ $container.name }}
|
||||||
{{- range $key, $val := $container }}
|
{{- range $key, $val := $container }}
|
||||||
{{- if and (ne $key "env") (ne $key "volumeMounts") (ne $key "name") }}
|
{{- if and (ne $key "env") (ne $key "volumeMounts") (ne $key "name") }}
|
||||||
{{ $key }}: {{ $val }}
|
{{ $key }}: {{ $val | toYaml | nindent 4 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- $setNodeExtraCaCerts := 0 }}
|
{{- $setNodeExtraCaCerts := 0 }}
|
||||||
@@ -411,17 +391,12 @@ volumeMounts:
|
|||||||
{{- with $container.env }}
|
{{- with $container.env }}
|
||||||
{{- range $i, $env := . }}
|
{{- range $i, $env := . }}
|
||||||
{{- if eq $env.name "NODE_EXTRA_CA_CERTS" }}
|
{{- if eq $env.name "NODE_EXTRA_CA_CERTS" }}
|
||||||
{{- $setNodeExtraCaCerts = 0 -}}
|
{{- $setNodeExtraCaCerts = 0 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if eq $env.name "RUNNER_UPDATE_CA_CERTS" }}
|
{{- if eq $env.name "RUNNER_UPDATE_CA_CERTS" }}
|
||||||
{{- $setRunnerUpdateCaCerts = 0 -}}
|
{{- $setRunnerUpdateCaCerts = 0 }}
|
||||||
{{- end }}
|
|
||||||
- name: {{ $env.name }}
|
|
||||||
{{- range $envKey, $envVal := $env }}
|
|
||||||
{{- if ne $envKey "name" }}
|
|
||||||
{{ $envKey }}: {{ $envVal | toYaml | nindent 10 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
- {{ $env | toYaml | nindent 6 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if $setNodeExtraCaCerts }}
|
{{- if $setNodeExtraCaCerts }}
|
||||||
@@ -440,14 +415,9 @@ volumeMounts:
|
|||||||
{{- with $container.volumeMounts }}
|
{{- with $container.volumeMounts }}
|
||||||
{{- range $i, $volMount := . }}
|
{{- range $i, $volMount := . }}
|
||||||
{{- if eq $volMount.name "github-server-tls-cert" }}
|
{{- if eq $volMount.name "github-server-tls-cert" }}
|
||||||
{{- $mountGitHubServerTLS = 0 -}}
|
{{- $mountGitHubServerTLS = 0 }}
|
||||||
{{- end }}
|
|
||||||
- name: {{ $volMount.name }}
|
|
||||||
{{- range $mountKey, $mountVal := $volMount }}
|
|
||||||
{{- if ne $mountKey "name" }}
|
|
||||||
{{ $mountKey }}: {{ $mountVal | toYaml | nindent 10 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
- {{ $volMount | toYaml | nindent 6 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if $mountGitHubServerTLS }}
|
{{- if $mountGitHubServerTLS }}
|
||||||
@@ -458,3 +428,125 @@ volumeMounts:
|
|||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "gha-runner-scale-set.managerRoleName" -}}
|
||||||
|
{{- include "gha-runner-scale-set.fullname" . }}-manager-role
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "gha-runner-scale-set.managerRoleBinding" -}}
|
||||||
|
{{- include "gha-runner-scale-set.fullname" . }}-manager-role-binding
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "gha-runner-scale-set.managerServiceAccountName" -}}
|
||||||
|
{{- $searchControllerDeployment := 1 }}
|
||||||
|
{{- if .Values.controllerServiceAccount }}
|
||||||
|
{{- if .Values.controllerServiceAccount.name }}
|
||||||
|
{{- $searchControllerDeployment = 0 }}
|
||||||
|
{{- .Values.controllerServiceAccount.name }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq $searchControllerDeployment 1 }}
|
||||||
|
{{- $multiNamespacesCounter := 0 }}
|
||||||
|
{{- $singleNamespaceCounter := 0 }}
|
||||||
|
{{- $controllerDeployment := dict }}
|
||||||
|
{{- $singleNamespaceControllerDeployments := dict }}
|
||||||
|
{{- $managerServiceAccountName := "" }}
|
||||||
|
{{- range $index, $deployment := (lookup "apps/v1" "Deployment" "" "").items }}
|
||||||
|
{{- if kindIs "map" $deployment.metadata.labels }}
|
||||||
|
{{- if eq (get $deployment.metadata.labels "app.kubernetes.io/part-of") "gha-runner-scale-set-controller" }}
|
||||||
|
{{- if hasKey $deployment.metadata.labels "actions.github.com/controller-watch-single-namespace" }}
|
||||||
|
{{- $singleNamespaceCounter = add $singleNamespaceCounter 1 }}
|
||||||
|
{{- $_ := set $singleNamespaceControllerDeployments (get $deployment.metadata.labels "actions.github.com/controller-watch-single-namespace") $deployment}}
|
||||||
|
{{- else }}
|
||||||
|
{{- $multiNamespacesCounter = add $multiNamespacesCounter 1 }}
|
||||||
|
{{- $controllerDeployment = $deployment }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if and (eq $multiNamespacesCounter 0) (eq $singleNamespaceCounter 0) }}
|
||||||
|
{{- fail "No gha-runner-scale-set-controller deployment found using label (app.kubernetes.io/part-of=gha-runner-scale-set-controller). Consider setting controllerServiceAccount.name in values.yaml to be explicit if you think the discovery is wrong." }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if and (gt $multiNamespacesCounter 0) (gt $singleNamespaceCounter 0) }}
|
||||||
|
{{- fail "Found both gha-runner-scale-set-controller installed with flags.watchSingleNamespace set and unset in cluster, this is not supported. Consider setting controllerServiceAccount.name in values.yaml to be explicit if you think the discovery is wrong." }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if gt $multiNamespacesCounter 1 }}
|
||||||
|
{{- fail "More than one gha-runner-scale-set-controller deployment found using label (app.kubernetes.io/part-of=gha-runner-scale-set-controller). Consider setting controllerServiceAccount.name in values.yaml to be explicit if you think the discovery is wrong." }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq $multiNamespacesCounter 1 }}
|
||||||
|
{{- with $controllerDeployment.metadata }}
|
||||||
|
{{- $managerServiceAccountName = (get $controllerDeployment.metadata.labels "actions.github.com/controller-service-account-name") }}
|
||||||
|
{{- end }}
|
||||||
|
{{- else if gt $singleNamespaceCounter 0 }}
|
||||||
|
{{- if hasKey $singleNamespaceControllerDeployments .Release.Namespace }}
|
||||||
|
{{- $controllerDeployment = get $singleNamespaceControllerDeployments .Release.Namespace }}
|
||||||
|
{{- with $controllerDeployment.metadata }}
|
||||||
|
{{- $managerServiceAccountName = (get $controllerDeployment.metadata.labels "actions.github.com/controller-service-account-name") }}
|
||||||
|
{{- end }}
|
||||||
|
{{- else }}
|
||||||
|
{{- fail "No gha-runner-scale-set-controller deployment that watch this namespace found using label (actions.github.com/controller-watch-single-namespace). Consider setting controllerServiceAccount.name in values.yaml to be explicit if you think the discovery is wrong." }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq $managerServiceAccountName "" }}
|
||||||
|
{{- fail "No service account name found for gha-runner-scale-set-controller deployment using label (actions.github.com/controller-service-account-name), consider setting controllerServiceAccount.name in values.yaml to be explicit if you think the discovery is wrong." }}
|
||||||
|
{{- end }}
|
||||||
|
{{- $managerServiceAccountName }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "gha-runner-scale-set.managerServiceAccountNamespace" -}}
|
||||||
|
{{- $searchControllerDeployment := 1 }}
|
||||||
|
{{- if .Values.controllerServiceAccount }}
|
||||||
|
{{- if .Values.controllerServiceAccount.namespace }}
|
||||||
|
{{- $searchControllerDeployment = 0 }}
|
||||||
|
{{- .Values.controllerServiceAccount.namespace }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq $searchControllerDeployment 1 }}
|
||||||
|
{{- $multiNamespacesCounter := 0 }}
|
||||||
|
{{- $singleNamespaceCounter := 0 }}
|
||||||
|
{{- $controllerDeployment := dict }}
|
||||||
|
{{- $singleNamespaceControllerDeployments := dict }}
|
||||||
|
{{- $managerServiceAccountNamespace := "" }}
|
||||||
|
{{- range $index, $deployment := (lookup "apps/v1" "Deployment" "" "").items }}
|
||||||
|
{{- if kindIs "map" $deployment.metadata.labels }}
|
||||||
|
{{- if eq (get $deployment.metadata.labels "app.kubernetes.io/part-of") "gha-runner-scale-set-controller" }}
|
||||||
|
{{- if hasKey $deployment.metadata.labels "actions.github.com/controller-watch-single-namespace" }}
|
||||||
|
{{- $singleNamespaceCounter = add $singleNamespaceCounter 1 }}
|
||||||
|
{{- $_ := set $singleNamespaceControllerDeployments (get $deployment.metadata.labels "actions.github.com/controller-watch-single-namespace") $deployment}}
|
||||||
|
{{- else }}
|
||||||
|
{{- $multiNamespacesCounter = add $multiNamespacesCounter 1 }}
|
||||||
|
{{- $controllerDeployment = $deployment }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if and (eq $multiNamespacesCounter 0) (eq $singleNamespaceCounter 0) }}
|
||||||
|
{{- fail "No gha-runner-scale-set-controller deployment found using label (app.kubernetes.io/part-of=gha-runner-scale-set-controller). Consider setting controllerServiceAccount.name in values.yaml to be explicit if you think the discovery is wrong." }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if and (gt $multiNamespacesCounter 0) (gt $singleNamespaceCounter 0) }}
|
||||||
|
{{- fail "Found both gha-runner-scale-set-controller installed with flags.watchSingleNamespace set and unset in cluster, this is not supported. Consider setting controllerServiceAccount.name in values.yaml to be explicit if you think the discovery is wrong." }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if gt $multiNamespacesCounter 1 }}
|
||||||
|
{{- fail "More than one gha-runner-scale-set-controller deployment found using label (app.kubernetes.io/part-of=gha-runner-scale-set-controller). Consider setting controllerServiceAccount.name in values.yaml to be explicit if you think the discovery is wrong." }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq $multiNamespacesCounter 1 }}
|
||||||
|
{{- with $controllerDeployment.metadata }}
|
||||||
|
{{- $managerServiceAccountNamespace = (get $controllerDeployment.metadata.labels "actions.github.com/controller-service-account-namespace") }}
|
||||||
|
{{- end }}
|
||||||
|
{{- else if gt $singleNamespaceCounter 0 }}
|
||||||
|
{{- if hasKey $singleNamespaceControllerDeployments .Release.Namespace }}
|
||||||
|
{{- $controllerDeployment = get $singleNamespaceControllerDeployments .Release.Namespace }}
|
||||||
|
{{- with $controllerDeployment.metadata }}
|
||||||
|
{{- $managerServiceAccountNamespace = (get $controllerDeployment.metadata.labels "actions.github.com/controller-service-account-namespace") }}
|
||||||
|
{{- end }}
|
||||||
|
{{- else }}
|
||||||
|
{{- fail "No gha-runner-scale-set-controller deployment that watch this namespace found using label (actions.github.com/controller-watch-single-namespace). Consider setting controllerServiceAccount.name in values.yaml to be explicit if you think the discovery is wrong." }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq $managerServiceAccountNamespace "" }}
|
||||||
|
{{- fail "No service account namespace found for gha-runner-scale-set-controller deployment using label (actions.github.com/controller-service-account-namespace), consider setting controllerServiceAccount.name in values.yaml to be explicit if you think the discovery is wrong." }}
|
||||||
|
{{- end }}
|
||||||
|
{{- $managerServiceAccountNamespace }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ metadata:
|
|||||||
name: {{ .Release.Name }}
|
name: {{ .Release.Name }}
|
||||||
namespace: {{ .Release.Namespace }}
|
namespace: {{ .Release.Namespace }}
|
||||||
labels:
|
labels:
|
||||||
|
app.kubernetes.io/component: "autoscaling-runner-set"
|
||||||
{{- include "gha-runner-scale-set.labels" . | nindent 4 }}
|
{{- include "gha-runner-scale-set.labels" . | nindent 4 }}
|
||||||
spec:
|
spec:
|
||||||
githubConfigUrl: {{ required ".Values.githubConfigUrl is required" (trimSuffix "/" .Values.githubConfigUrl) }}
|
githubConfigUrl: {{ required ".Values.githubConfigUrl is required" (trimSuffix "/" .Values.githubConfigUrl) }}
|
||||||
@@ -36,17 +37,21 @@ spec:
|
|||||||
{{- if .Values.proxy.http }}
|
{{- if .Values.proxy.http }}
|
||||||
http:
|
http:
|
||||||
url: {{ .Values.proxy.http.url }}
|
url: {{ .Values.proxy.http.url }}
|
||||||
|
{{- if .Values.proxy.http.credentialSecretRef }}
|
||||||
credentialSecretRef: {{ .Values.proxy.http.credentialSecretRef }}
|
credentialSecretRef: {{ .Values.proxy.http.credentialSecretRef }}
|
||||||
{{ end }}
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
{{- if .Values.proxy.https }}
|
{{- if .Values.proxy.https }}
|
||||||
https:
|
https:
|
||||||
url: {{ .Values.proxy.https.url }}
|
url: {{ .Values.proxy.https.url }}
|
||||||
|
{{- if .Values.proxy.https.credentialSecretRef }}
|
||||||
credentialSecretRef: {{ .Values.proxy.https.credentialSecretRef }}
|
credentialSecretRef: {{ .Values.proxy.https.credentialSecretRef }}
|
||||||
{{ end }}
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
{{- if and .Values.proxy.noProxy (kindIs "slice" .Values.proxy.noProxy) }}
|
{{- if and .Values.proxy.noProxy (kindIs "slice" .Values.proxy.noProxy) }}
|
||||||
noProxy: {{ .Values.proxy.noProxy | toYaml | nindent 6}}
|
noProxy: {{ .Values.proxy.noProxy | toYaml | nindent 6}}
|
||||||
{{ end }}
|
{{- end }}
|
||||||
{{ end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- if and (or (kindIs "int64" .Values.minRunners) (kindIs "float64" .Values.minRunners)) (or (kindIs "int64" .Values.maxRunners) (kindIs "float64" .Values.maxRunners)) }}
|
{{- if and (or (kindIs "int64" .Values.minRunners) (kindIs "float64" .Values.minRunners)) (or (kindIs "int64" .Values.maxRunners) (kindIs "float64" .Values.maxRunners)) }}
|
||||||
{{- if gt .Values.minRunners .Values.maxRunners }}
|
{{- if gt .Values.minRunners .Values.maxRunners }}
|
||||||
@@ -86,14 +91,15 @@ spec:
|
|||||||
{{ $key }}: {{ $val | toYaml | nindent 8 }}
|
{{ $key }}: {{ $val | toYaml | nindent 8 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if eq .Values.containerMode.type "kubernetes" }}
|
{{- $containerMode := .Values.containerMode }}
|
||||||
|
{{- if eq $containerMode.type "kubernetes" }}
|
||||||
serviceAccountName: {{ default (include "gha-runner-scale-set.kubeModeServiceAccountName" .) .Values.template.spec.serviceAccountName }}
|
serviceAccountName: {{ default (include "gha-runner-scale-set.kubeModeServiceAccountName" .) .Values.template.spec.serviceAccountName }}
|
||||||
{{- else }}
|
{{- else }}
|
||||||
serviceAccountName: {{ default (include "gha-runner-scale-set.noPermissionServiceAccountName" .) .Values.template.spec.serviceAccountName }}
|
serviceAccountName: {{ default (include "gha-runner-scale-set.noPermissionServiceAccountName" .) .Values.template.spec.serviceAccountName }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if or .Values.template.spec.initContainers (eq .Values.containerMode.type "dind") }}
|
{{- if or .Values.template.spec.initContainers (eq $containerMode.type "dind") }}
|
||||||
initContainers:
|
initContainers:
|
||||||
{{- if eq .Values.containerMode.type "dind" }}
|
{{- if eq $containerMode.type "dind" }}
|
||||||
- name: init-dind-externals
|
- name: init-dind-externals
|
||||||
{{- include "gha-runner-scale-set.dind-init-container" . | nindent 8 }}
|
{{- include "gha-runner-scale-set.dind-init-container" . | nindent 8 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
@@ -102,13 +108,13 @@ spec:
|
|||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
containers:
|
containers:
|
||||||
{{- if eq .Values.containerMode.type "dind" }}
|
{{- if eq $containerMode.type "dind" }}
|
||||||
- name: runner
|
- name: runner
|
||||||
{{- include "gha-runner-scale-set.dind-runner-container" . | nindent 8 }}
|
{{- include "gha-runner-scale-set.dind-runner-container" . | nindent 8 }}
|
||||||
- name: dind
|
- name: dind
|
||||||
{{- include "gha-runner-scale-set.dind-container" . | nindent 8 }}
|
{{- include "gha-runner-scale-set.dind-container" . | nindent 8 }}
|
||||||
{{- include "gha-runner-scale-set.non-runner-containers" . | nindent 6 }}
|
{{- include "gha-runner-scale-set.non-runner-non-dind-containers" . | nindent 6 }}
|
||||||
{{- else if eq .Values.containerMode.type "kubernetes" }}
|
{{- else if eq $containerMode.type "kubernetes" }}
|
||||||
- name: runner
|
- name: runner
|
||||||
{{- include "gha-runner-scale-set.kubernetes-mode-runner-container" . | nindent 8 }}
|
{{- include "gha-runner-scale-set.kubernetes-mode-runner-container" . | nindent 8 }}
|
||||||
{{- include "gha-runner-scale-set.non-runner-containers" . | nindent 6 }}
|
{{- include "gha-runner-scale-set.non-runner-containers" . | nindent 6 }}
|
||||||
@@ -116,16 +122,16 @@ spec:
|
|||||||
{{- include "gha-runner-scale-set.default-mode-runner-containers" . | nindent 6 }}
|
{{- include "gha-runner-scale-set.default-mode-runner-containers" . | nindent 6 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- $tlsConfig := (default (dict) .Values.githubServerTLS) }}
|
{{- $tlsConfig := (default (dict) .Values.githubServerTLS) }}
|
||||||
{{- if or .Values.template.spec.volumes (eq .Values.containerMode.type "dind") (eq .Values.containerMode.type "kubernetes") $tlsConfig.runnerMountPath }}
|
{{- if or .Values.template.spec.volumes (eq $containerMode.type "dind") (eq $containerMode.type "kubernetes") $tlsConfig.runnerMountPath }}
|
||||||
volumes:
|
volumes:
|
||||||
{{- if $tlsConfig.runnerMountPath }}
|
{{- if $tlsConfig.runnerMountPath }}
|
||||||
{{- include "gha-runner-scale-set.tls-volume" $tlsConfig | nindent 6 }}
|
{{- include "gha-runner-scale-set.tls-volume" $tlsConfig | nindent 6 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if eq .Values.containerMode.type "dind" }}
|
{{- if eq $containerMode.type "dind" }}
|
||||||
{{- include "gha-runner-scale-set.dind-volume" . | nindent 6 }}
|
{{- include "gha-runner-scale-set.dind-volume" . | nindent 6 }}
|
||||||
{{- include "gha-runner-scale-set.dind-work-volume" . | nindent 6 }}
|
{{- include "gha-runner-scale-set.dind-work-volume" . | nindent 6 }}
|
||||||
{{- include "gha-runner-scale-set.non-work-volumes" . | nindent 6 }}
|
{{- include "gha-runner-scale-set.non-work-volumes" . | nindent 6 }}
|
||||||
{{- else if eq .Values.containerMode.type "kubernetes" }}
|
{{- else if eq $containerMode.type "kubernetes" }}
|
||||||
{{- include "gha-runner-scale-set.kubernetes-mode-work-volume" . | nindent 6 }}
|
{{- include "gha-runner-scale-set.kubernetes-mode-work-volume" . | nindent 6 }}
|
||||||
{{- include "gha-runner-scale-set.non-work-volumes" . | nindent 6 }}
|
{{- include "gha-runner-scale-set.non-work-volumes" . | nindent 6 }}
|
||||||
{{- else }}
|
{{- else }}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{{- if and (eq .Values.containerMode.type "kubernetes") (not .Values.template.spec.serviceAccountName) }}
|
{{- $containerMode := .Values.containerMode }}
|
||||||
|
{{- if and (eq $containerMode.type "kubernetes") (not .Values.template.spec.serviceAccountName) }}
|
||||||
# default permission for runner pod service account in kubernetes mode (container hook)
|
# default permission for runner pod service account in kubernetes mode (container hook)
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: Role
|
kind: Role
|
||||||
@@ -21,4 +22,4 @@ rules:
|
|||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["secrets"]
|
resources: ["secrets"]
|
||||||
verbs: ["get", "list", "create", "delete"]
|
verbs: ["get", "list", "create", "delete"]
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{{- if and (eq .Values.containerMode.type "kubernetes") (not .Values.template.spec.serviceAccountName) }}
|
{{- $containerMode := .Values.containerMode }}
|
||||||
|
{{- if and (eq $containerMode.type "kubernetes") (not .Values.template.spec.serviceAccountName) }}
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: RoleBinding
|
kind: RoleBinding
|
||||||
metadata:
|
metadata:
|
||||||
@@ -12,4 +13,4 @@ subjects:
|
|||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: {{ include "gha-runner-scale-set.kubeModeServiceAccountName" . }}
|
name: {{ include "gha-runner-scale-set.kubeModeServiceAccountName" . }}
|
||||||
namespace: {{ .Release.Namespace }}
|
namespace: {{ .Release.Namespace }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{{- if and (eq .Values.containerMode.type "kubernetes") (not .Values.template.spec.serviceAccountName) }}
|
{{- $containerMode := .Values.containerMode }}
|
||||||
|
{{- if and (eq $containerMode.type "kubernetes") (not .Values.template.spec.serviceAccountName) }}
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: ServiceAccount
|
kind: ServiceAccount
|
||||||
metadata:
|
metadata:
|
||||||
@@ -6,4 +7,4 @@ metadata:
|
|||||||
namespace: {{ .Release.Namespace }}
|
namespace: {{ .Release.Namespace }}
|
||||||
labels:
|
labels:
|
||||||
{{- include "gha-runner-scale-set.labels" . | nindent 4 }}
|
{{- include "gha-runner-scale-set.labels" . | nindent 4 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|||||||
59
charts/gha-runner-scale-set/templates/manager_role.yaml
Normal file
59
charts/gha-runner-scale-set/templates/manager_role.yaml
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: Role
|
||||||
|
metadata:
|
||||||
|
name: {{ include "gha-runner-scale-set.managerRoleName" . }}
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
|
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:
|
||||||
|
- 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 }}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: RoleBinding
|
||||||
|
metadata:
|
||||||
|
name: {{ include "gha-runner-scale-set.managerRoleBinding" . }}
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: Role
|
||||||
|
name: {{ include "gha-runner-scale-set.managerRoleName" . }}
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: {{ include "gha-runner-scale-set.managerServiceAccountName" . | nindent 4 }}
|
||||||
|
namespace: {{ include "gha-runner-scale-set.managerServiceAccountNamespace" . | nindent 4 }}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
{{- if and (ne .Values.containerMode.type "kubernetes") (not .Values.template.spec.serviceAccountName) }}
|
{{- $containerMode := .Values.containerMode }}
|
||||||
|
{{- if and (ne $containerMode.type "kubernetes") (not .Values.template.spec.serviceAccountName) }}
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: ServiceAccount
|
kind: ServiceAccount
|
||||||
metadata:
|
metadata:
|
||||||
@@ -6,4 +7,4 @@ metadata:
|
|||||||
namespace: {{ .Release.Namespace }}
|
namespace: {{ .Release.Namespace }}
|
||||||
labels:
|
labels:
|
||||||
{{- include "gha-runner-scale-set.labels" . | nindent 4 }}
|
{{- include "gha-runner-scale-set.labels" . | nindent 4 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|||||||
@@ -27,8 +27,10 @@ func TestTemplateRenderedGitHubSecretWithGitHubToken(t *testing.T) {
|
|||||||
|
|
||||||
options := &helm.Options{
|
options := &helm.Options{
|
||||||
SetValues: map[string]string{
|
SetValues: map[string]string{
|
||||||
"githubConfigUrl": "https://github.com/actions",
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
"githubConfigSecret.github_token": "gh_token12345",
|
"githubConfigSecret.github_token": "gh_token12345",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
},
|
},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -60,6 +62,8 @@ func TestTemplateRenderedGitHubSecretWithGitHubApp(t *testing.T) {
|
|||||||
"githubConfigSecret.github_app_id": "10",
|
"githubConfigSecret.github_app_id": "10",
|
||||||
"githubConfigSecret.github_app_installation_id": "100",
|
"githubConfigSecret.github_app_installation_id": "100",
|
||||||
"githubConfigSecret.github_app_private_key": "private_key",
|
"githubConfigSecret.github_app_private_key": "private_key",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
},
|
},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -87,9 +91,11 @@ func TestTemplateRenderedGitHubSecretErrorWithMissingAuthInput(t *testing.T) {
|
|||||||
|
|
||||||
options := &helm.Options{
|
options := &helm.Options{
|
||||||
SetValues: map[string]string{
|
SetValues: map[string]string{
|
||||||
"githubConfigUrl": "https://github.com/actions",
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
"githubConfigSecret.github_app_id": "",
|
"githubConfigSecret.github_app_id": "",
|
||||||
"githubConfigSecret.github_token": "",
|
"githubConfigSecret.github_token": "",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
},
|
},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -112,8 +118,10 @@ func TestTemplateRenderedGitHubSecretErrorWithMissingAppInput(t *testing.T) {
|
|||||||
|
|
||||||
options := &helm.Options{
|
options := &helm.Options{
|
||||||
SetValues: map[string]string{
|
SetValues: map[string]string{
|
||||||
"githubConfigUrl": "https://github.com/actions",
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
"githubConfigSecret.github_app_id": "10",
|
"githubConfigSecret.github_app_id": "10",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
},
|
},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -136,8 +144,10 @@ func TestTemplateNotRenderedGitHubSecretWithPredefinedSecret(t *testing.T) {
|
|||||||
|
|
||||||
options := &helm.Options{
|
options := &helm.Options{
|
||||||
SetValues: map[string]string{
|
SetValues: map[string]string{
|
||||||
"githubConfigUrl": "https://github.com/actions",
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
"githubConfigSecret": "pre-defined-secret",
|
"githubConfigSecret": "pre-defined-secret",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
},
|
},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -158,8 +168,10 @@ func TestTemplateRenderedSetServiceAccountToNoPermission(t *testing.T) {
|
|||||||
|
|
||||||
options := &helm.Options{
|
options := &helm.Options{
|
||||||
SetValues: map[string]string{
|
SetValues: map[string]string{
|
||||||
"githubConfigUrl": "https://github.com/actions",
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
"githubConfigSecret.github_token": "gh_token12345",
|
"githubConfigSecret.github_token": "gh_token12345",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
},
|
},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -190,9 +202,11 @@ func TestTemplateRenderedSetServiceAccountToKubeMode(t *testing.T) {
|
|||||||
|
|
||||||
options := &helm.Options{
|
options := &helm.Options{
|
||||||
SetValues: map[string]string{
|
SetValues: map[string]string{
|
||||||
"githubConfigUrl": "https://github.com/actions",
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
"githubConfigSecret.github_token": "gh_token12345",
|
"githubConfigSecret.github_token": "gh_token12345",
|
||||||
"containerMode.type": "kubernetes",
|
"containerMode.type": "kubernetes",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
},
|
},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -248,9 +262,11 @@ func TestTemplateRenderedUserProvideSetServiceAccount(t *testing.T) {
|
|||||||
|
|
||||||
options := &helm.Options{
|
options := &helm.Options{
|
||||||
SetValues: map[string]string{
|
SetValues: map[string]string{
|
||||||
"githubConfigUrl": "https://github.com/actions",
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
"githubConfigSecret.github_token": "gh_token12345",
|
"githubConfigSecret.github_token": "gh_token12345",
|
||||||
"template.spec.serviceAccountName": "test-service-account",
|
"template.spec.serviceAccountName": "test-service-account",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
},
|
},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -277,8 +293,10 @@ func TestTemplateRenderedAutoScalingRunnerSet(t *testing.T) {
|
|||||||
|
|
||||||
options := &helm.Options{
|
options := &helm.Options{
|
||||||
SetValues: map[string]string{
|
SetValues: map[string]string{
|
||||||
"githubConfigUrl": "https://github.com/actions",
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
"githubConfigSecret.github_token": "gh_token12345",
|
"githubConfigSecret.github_token": "gh_token12345",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
},
|
},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -293,6 +311,10 @@ func TestTemplateRenderedAutoScalingRunnerSet(t *testing.T) {
|
|||||||
|
|
||||||
assert.Equal(t, "gha-runner-scale-set", ars.Labels["app.kubernetes.io/name"])
|
assert.Equal(t, "gha-runner-scale-set", ars.Labels["app.kubernetes.io/name"])
|
||||||
assert.Equal(t, "test-runners", ars.Labels["app.kubernetes.io/instance"])
|
assert.Equal(t, "test-runners", ars.Labels["app.kubernetes.io/instance"])
|
||||||
|
assert.Equal(t, "gha-runner-scale-set", ars.Labels["app.kubernetes.io/part-of"])
|
||||||
|
assert.Equal(t, "autoscaling-runner-set", ars.Labels["app.kubernetes.io/component"])
|
||||||
|
assert.NotEmpty(t, ars.Labels["app.kubernetes.io/version"])
|
||||||
|
|
||||||
assert.Equal(t, "https://github.com/actions", ars.Spec.GitHubConfigUrl)
|
assert.Equal(t, "https://github.com/actions", ars.Spec.GitHubConfigUrl)
|
||||||
assert.Equal(t, "test-runners-gha-runner-scale-set-github-secret", ars.Spec.GitHubConfigSecret)
|
assert.Equal(t, "test-runners-gha-runner-scale-set-github-secret", ars.Spec.GitHubConfigSecret)
|
||||||
|
|
||||||
@@ -322,9 +344,11 @@ func TestTemplateRenderedAutoScalingRunnerSet_RunnerScaleSetName(t *testing.T) {
|
|||||||
|
|
||||||
options := &helm.Options{
|
options := &helm.Options{
|
||||||
SetValues: map[string]string{
|
SetValues: map[string]string{
|
||||||
"githubConfigUrl": "https://github.com/actions",
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
"githubConfigSecret.github_token": "gh_token12345",
|
"githubConfigSecret.github_token": "gh_token12345",
|
||||||
"runnerScaleSetName": "test-runner-scale-set-name",
|
"runnerScaleSetName": "test-runner-scale-set-name",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
},
|
},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -375,6 +399,8 @@ func TestTemplateRenderedAutoScalingRunnerSet_ProvideMetadata(t *testing.T) {
|
|||||||
"template.metadata.labels.test2": "test2",
|
"template.metadata.labels.test2": "test2",
|
||||||
"template.metadata.annotations.test3": "test3",
|
"template.metadata.annotations.test3": "test3",
|
||||||
"template.metadata.annotations.test4": "test4",
|
"template.metadata.annotations.test4": "test4",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
},
|
},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -414,9 +440,11 @@ func TestTemplateRenderedAutoScalingRunnerSet_MaxRunnersValidationError(t *testi
|
|||||||
|
|
||||||
options := &helm.Options{
|
options := &helm.Options{
|
||||||
SetValues: map[string]string{
|
SetValues: map[string]string{
|
||||||
"githubConfigUrl": "https://github.com/actions",
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
"githubConfigSecret.github_token": "gh_token12345",
|
"githubConfigSecret.github_token": "gh_token12345",
|
||||||
"maxRunners": "-1",
|
"maxRunners": "-1",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
},
|
},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -439,10 +467,12 @@ func TestTemplateRenderedAutoScalingRunnerSet_MinRunnersValidationError(t *testi
|
|||||||
|
|
||||||
options := &helm.Options{
|
options := &helm.Options{
|
||||||
SetValues: map[string]string{
|
SetValues: map[string]string{
|
||||||
"githubConfigUrl": "https://github.com/actions",
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
"githubConfigSecret.github_token": "gh_token12345",
|
"githubConfigSecret.github_token": "gh_token12345",
|
||||||
"maxRunners": "1",
|
"maxRunners": "1",
|
||||||
"minRunners": "-1",
|
"minRunners": "-1",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
},
|
},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -465,10 +495,12 @@ func TestTemplateRenderedAutoScalingRunnerSet_MinMaxRunnersValidationError(t *te
|
|||||||
|
|
||||||
options := &helm.Options{
|
options := &helm.Options{
|
||||||
SetValues: map[string]string{
|
SetValues: map[string]string{
|
||||||
"githubConfigUrl": "https://github.com/actions",
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
"githubConfigSecret.github_token": "gh_token12345",
|
"githubConfigSecret.github_token": "gh_token12345",
|
||||||
"maxRunners": "0",
|
"maxRunners": "0",
|
||||||
"minRunners": "1",
|
"minRunners": "1",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
},
|
},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -491,10 +523,12 @@ func TestTemplateRenderedAutoScalingRunnerSet_MinMaxRunnersValidationSameValue(t
|
|||||||
|
|
||||||
options := &helm.Options{
|
options := &helm.Options{
|
||||||
SetValues: map[string]string{
|
SetValues: map[string]string{
|
||||||
"githubConfigUrl": "https://github.com/actions",
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
"githubConfigSecret.github_token": "gh_token12345",
|
"githubConfigSecret.github_token": "gh_token12345",
|
||||||
"maxRunners": "0",
|
"maxRunners": "0",
|
||||||
"minRunners": "0",
|
"minRunners": "0",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
},
|
},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -520,9 +554,11 @@ func TestTemplateRenderedAutoScalingRunnerSet_MinMaxRunnersValidation_OnlyMin(t
|
|||||||
|
|
||||||
options := &helm.Options{
|
options := &helm.Options{
|
||||||
SetValues: map[string]string{
|
SetValues: map[string]string{
|
||||||
"githubConfigUrl": "https://github.com/actions",
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
"githubConfigSecret.github_token": "gh_token12345",
|
"githubConfigSecret.github_token": "gh_token12345",
|
||||||
"minRunners": "5",
|
"minRunners": "5",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
},
|
},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -548,9 +584,11 @@ func TestTemplateRenderedAutoScalingRunnerSet_MinMaxRunnersValidation_OnlyMax(t
|
|||||||
|
|
||||||
options := &helm.Options{
|
options := &helm.Options{
|
||||||
SetValues: map[string]string{
|
SetValues: map[string]string{
|
||||||
"githubConfigUrl": "https://github.com/actions",
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
"githubConfigSecret.github_token": "gh_token12345",
|
"githubConfigSecret.github_token": "gh_token12345",
|
||||||
"maxRunners": "5",
|
"maxRunners": "5",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
},
|
},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -605,6 +643,10 @@ func TestTemplateRenderedAutoScalingRunnerSet_ExtraVolumes(t *testing.T) {
|
|||||||
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
||||||
|
|
||||||
options := &helm.Options{
|
options := &helm.Options{
|
||||||
|
SetValues: map[string]string{
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
|
},
|
||||||
ValuesFiles: []string{testValuesPath},
|
ValuesFiles: []string{testValuesPath},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -635,6 +677,10 @@ func TestTemplateRenderedAutoScalingRunnerSet_DinD_ExtraVolumes(t *testing.T) {
|
|||||||
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
||||||
|
|
||||||
options := &helm.Options{
|
options := &helm.Options{
|
||||||
|
SetValues: map[string]string{
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
|
},
|
||||||
ValuesFiles: []string{testValuesPath},
|
ValuesFiles: []string{testValuesPath},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -667,6 +713,10 @@ func TestTemplateRenderedAutoScalingRunnerSet_K8S_ExtraVolumes(t *testing.T) {
|
|||||||
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
||||||
|
|
||||||
options := &helm.Options{
|
options := &helm.Options{
|
||||||
|
SetValues: map[string]string{
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
|
},
|
||||||
ValuesFiles: []string{testValuesPath},
|
ValuesFiles: []string{testValuesPath},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -695,9 +745,11 @@ func TestTemplateRenderedAutoScalingRunnerSet_EnableDinD(t *testing.T) {
|
|||||||
|
|
||||||
options := &helm.Options{
|
options := &helm.Options{
|
||||||
SetValues: map[string]string{
|
SetValues: map[string]string{
|
||||||
"githubConfigUrl": "https://github.com/actions",
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
"githubConfigSecret.github_token": "gh_token12345",
|
"githubConfigSecret.github_token": "gh_token12345",
|
||||||
"containerMode.type": "dind",
|
"containerMode.type": "dind",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
},
|
},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -784,9 +836,11 @@ func TestTemplateRenderedAutoScalingRunnerSet_EnableKubernetesMode(t *testing.T)
|
|||||||
|
|
||||||
options := &helm.Options{
|
options := &helm.Options{
|
||||||
SetValues: map[string]string{
|
SetValues: map[string]string{
|
||||||
"githubConfigUrl": "https://github.com/actions",
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
"githubConfigSecret.github_token": "gh_token12345",
|
"githubConfigSecret.github_token": "gh_token12345",
|
||||||
"containerMode.type": "kubernetes",
|
"containerMode.type": "kubernetes",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
},
|
},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -839,8 +893,10 @@ func TestTemplateRenderedAutoScalingRunnerSet_UsePredefinedSecret(t *testing.T)
|
|||||||
|
|
||||||
options := &helm.Options{
|
options := &helm.Options{
|
||||||
SetValues: map[string]string{
|
SetValues: map[string]string{
|
||||||
"githubConfigUrl": "https://github.com/actions",
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
"githubConfigSecret": "pre-defined-secrets",
|
"githubConfigSecret": "pre-defined-secrets",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
},
|
},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -871,8 +927,10 @@ func TestTemplateRenderedAutoScalingRunnerSet_ErrorOnEmptyPredefinedSecret(t *te
|
|||||||
|
|
||||||
options := &helm.Options{
|
options := &helm.Options{
|
||||||
SetValues: map[string]string{
|
SetValues: map[string]string{
|
||||||
"githubConfigUrl": "https://github.com/actions",
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
"githubConfigSecret": "",
|
"githubConfigSecret": "",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
},
|
},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -895,13 +953,15 @@ func TestTemplateRenderedWithProxy(t *testing.T) {
|
|||||||
|
|
||||||
options := &helm.Options{
|
options := &helm.Options{
|
||||||
SetValues: map[string]string{
|
SetValues: map[string]string{
|
||||||
"githubConfigUrl": "https://github.com/actions",
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
"githubConfigSecret": "pre-defined-secrets",
|
"githubConfigSecret": "pre-defined-secrets",
|
||||||
"proxy.http.url": "http://proxy.example.com",
|
"controllerServiceAccount.name": "arc",
|
||||||
"proxy.http.credentialSecretRef": "http-secret",
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
"proxy.https.url": "https://proxy.example.com",
|
"proxy.http.url": "http://proxy.example.com",
|
||||||
"proxy.https.credentialSecretRef": "https-secret",
|
"proxy.http.credentialSecretRef": "http-secret",
|
||||||
"proxy.noProxy": "{example.com,example.org}",
|
"proxy.https.url": "https://proxy.example.com",
|
||||||
|
"proxy.https.credentialSecretRef": "https-secret",
|
||||||
|
"proxy.noProxy": "{example.com,example.org}",
|
||||||
},
|
},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -961,6 +1021,8 @@ func TestTemplateRenderedWithTLS(t *testing.T) {
|
|||||||
"githubServerTLS.certificateFrom.configMapKeyRef.name": "certs-configmap",
|
"githubServerTLS.certificateFrom.configMapKeyRef.name": "certs-configmap",
|
||||||
"githubServerTLS.certificateFrom.configMapKeyRef.key": "cert.pem",
|
"githubServerTLS.certificateFrom.configMapKeyRef.key": "cert.pem",
|
||||||
"githubServerTLS.runnerMountPath": "/runner/mount/path",
|
"githubServerTLS.runnerMountPath": "/runner/mount/path",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
},
|
},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -1018,6 +1080,8 @@ func TestTemplateRenderedWithTLS(t *testing.T) {
|
|||||||
"githubServerTLS.certificateFrom.configMapKeyRef.key": "cert.pem",
|
"githubServerTLS.certificateFrom.configMapKeyRef.key": "cert.pem",
|
||||||
"githubServerTLS.runnerMountPath": "/runner/mount/path/",
|
"githubServerTLS.runnerMountPath": "/runner/mount/path/",
|
||||||
"containerMode.type": "dind",
|
"containerMode.type": "dind",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
},
|
},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -1075,6 +1139,8 @@ func TestTemplateRenderedWithTLS(t *testing.T) {
|
|||||||
"githubServerTLS.certificateFrom.configMapKeyRef.key": "cert.pem",
|
"githubServerTLS.certificateFrom.configMapKeyRef.key": "cert.pem",
|
||||||
"githubServerTLS.runnerMountPath": "/runner/mount/path",
|
"githubServerTLS.runnerMountPath": "/runner/mount/path",
|
||||||
"containerMode.type": "kubernetes",
|
"containerMode.type": "kubernetes",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
},
|
},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -1132,6 +1198,8 @@ func TestTemplateRenderedWithTLS(t *testing.T) {
|
|||||||
"githubConfigSecret": "pre-defined-secrets",
|
"githubConfigSecret": "pre-defined-secrets",
|
||||||
"githubServerTLS.certificateFrom.configMapKeyRef.name": "certs-configmap",
|
"githubServerTLS.certificateFrom.configMapKeyRef.name": "certs-configmap",
|
||||||
"githubServerTLS.certificateFrom.configMapKeyRef.key": "cert.pem",
|
"githubServerTLS.certificateFrom.configMapKeyRef.key": "cert.pem",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
},
|
},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -1184,7 +1252,9 @@ func TestTemplateRenderedWithTLS(t *testing.T) {
|
|||||||
"githubConfigSecret": "pre-defined-secrets",
|
"githubConfigSecret": "pre-defined-secrets",
|
||||||
"githubServerTLS.certificateFrom.configMapKeyRef.name": "certs-configmap",
|
"githubServerTLS.certificateFrom.configMapKeyRef.name": "certs-configmap",
|
||||||
"githubServerTLS.certificateFrom.configMapKeyRef.key": "cert.pem",
|
"githubServerTLS.certificateFrom.configMapKeyRef.key": "cert.pem",
|
||||||
"containerMode.type": "dind",
|
"containerMode.type": "dind",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
},
|
},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -1237,7 +1307,9 @@ func TestTemplateRenderedWithTLS(t *testing.T) {
|
|||||||
"githubConfigSecret": "pre-defined-secrets",
|
"githubConfigSecret": "pre-defined-secrets",
|
||||||
"githubServerTLS.certificateFrom.configMapKeyRef.name": "certs-configmap",
|
"githubServerTLS.certificateFrom.configMapKeyRef.name": "certs-configmap",
|
||||||
"githubServerTLS.certificateFrom.configMapKeyRef.key": "cert.pem",
|
"githubServerTLS.certificateFrom.configMapKeyRef.key": "cert.pem",
|
||||||
"containerMode.type": "kubernetes",
|
"containerMode.type": "kubernetes",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
},
|
},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -1293,8 +1365,10 @@ func TestTemplateNamingConstraints(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
setValues := map[string]string{
|
setValues := map[string]string{
|
||||||
"githubConfigUrl": "https://github.com/actions",
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
"githubConfigSecret": "",
|
"githubConfigSecret": "",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
}
|
}
|
||||||
|
|
||||||
tt := map[string]struct {
|
tt := map[string]struct {
|
||||||
@@ -1339,8 +1413,10 @@ func TestTemplateRenderedGitHubConfigUrlEndsWIthSlash(t *testing.T) {
|
|||||||
|
|
||||||
options := &helm.Options{
|
options := &helm.Options{
|
||||||
SetValues: map[string]string{
|
SetValues: map[string]string{
|
||||||
"githubConfigUrl": "https://github.com/actions/",
|
"githubConfigUrl": "https://github.com/actions/",
|
||||||
"githubConfigSecret.github_token": "gh_token12345",
|
"githubConfigSecret.github_token": "gh_token12345",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
},
|
},
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
}
|
}
|
||||||
@@ -1354,3 +1430,265 @@ func TestTemplateRenderedGitHubConfigUrlEndsWIthSlash(t *testing.T) {
|
|||||||
assert.Equal(t, "test-runners", ars.Name)
|
assert.Equal(t, "test-runners", ars.Name)
|
||||||
assert.Equal(t, "https://github.com/actions", ars.Spec.GitHubConfigUrl)
|
assert.Equal(t, "https://github.com/actions", ars.Spec.GitHubConfigUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTemplate_CreateManagerRole(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// Path to the helm chart we will test
|
||||||
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
releaseName := "test-runners"
|
||||||
|
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
||||||
|
|
||||||
|
options := &helm.Options{
|
||||||
|
SetValues: map[string]string{
|
||||||
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
|
"githubConfigSecret.github_token": "gh_token12345",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
|
},
|
||||||
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
|
}
|
||||||
|
|
||||||
|
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/manager_role.yaml"})
|
||||||
|
|
||||||
|
var managerRole rbacv1.Role
|
||||||
|
helm.UnmarshalK8SYaml(t, output, &managerRole)
|
||||||
|
|
||||||
|
assert.Equal(t, namespaceName, managerRole.Namespace, "namespace should match the namespace of the Helm release")
|
||||||
|
assert.Equal(t, "test-runners-gha-runner-scale-set-manager-role", managerRole.Name)
|
||||||
|
assert.Equal(t, 5, len(managerRole.Rules))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTemplate_CreateManagerRole_UseConfigMaps(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// Path to the helm chart we will test
|
||||||
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
releaseName := "test-runners"
|
||||||
|
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
||||||
|
|
||||||
|
options := &helm.Options{
|
||||||
|
SetValues: map[string]string{
|
||||||
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
|
"githubConfigSecret.github_token": "gh_token12345",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
|
"githubServerTLS.certificateFrom.configMapKeyRef.name": "test",
|
||||||
|
},
|
||||||
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
|
}
|
||||||
|
|
||||||
|
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/manager_role.yaml"})
|
||||||
|
|
||||||
|
var managerRole rbacv1.Role
|
||||||
|
helm.UnmarshalK8SYaml(t, output, &managerRole)
|
||||||
|
|
||||||
|
assert.Equal(t, namespaceName, managerRole.Namespace, "namespace should match the namespace of the Helm release")
|
||||||
|
assert.Equal(t, "test-runners-gha-runner-scale-set-manager-role", managerRole.Name)
|
||||||
|
assert.Equal(t, 6, len(managerRole.Rules))
|
||||||
|
assert.Equal(t, "configmaps", managerRole.Rules[5].Resources[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTemplate_CreateManagerRoleBinding(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// Path to the helm chart we will test
|
||||||
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
releaseName := "test-runners"
|
||||||
|
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
||||||
|
|
||||||
|
options := &helm.Options{
|
||||||
|
SetValues: map[string]string{
|
||||||
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
|
"githubConfigSecret.github_token": "gh_token12345",
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
|
},
|
||||||
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
|
}
|
||||||
|
|
||||||
|
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/manager_role_binding.yaml"})
|
||||||
|
|
||||||
|
var managerRoleBinding rbacv1.RoleBinding
|
||||||
|
helm.UnmarshalK8SYaml(t, output, &managerRoleBinding)
|
||||||
|
|
||||||
|
assert.Equal(t, namespaceName, managerRoleBinding.Namespace, "namespace should match the namespace of the Helm release")
|
||||||
|
assert.Equal(t, "test-runners-gha-runner-scale-set-manager-role-binding", managerRoleBinding.Name)
|
||||||
|
assert.Equal(t, "test-runners-gha-runner-scale-set-manager-role", managerRoleBinding.RoleRef.Name)
|
||||||
|
assert.Equal(t, "arc", managerRoleBinding.Subjects[0].Name)
|
||||||
|
assert.Equal(t, "arc-system", managerRoleBinding.Subjects[0].Namespace)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTemplateRenderedAutoScalingRunnerSet_ExtraContainers(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// Path to the helm chart we will test
|
||||||
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
testValuesPath, err := filepath.Abs("../tests/values_extra_containers.yaml")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
releaseName := "test-runners"
|
||||||
|
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
||||||
|
|
||||||
|
options := &helm.Options{
|
||||||
|
SetValues: map[string]string{
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
|
},
|
||||||
|
ValuesFiles: []string{testValuesPath},
|
||||||
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
|
}
|
||||||
|
|
||||||
|
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/autoscalingrunnerset.yaml"}, "--debug")
|
||||||
|
|
||||||
|
var ars v1alpha1.AutoscalingRunnerSet
|
||||||
|
helm.UnmarshalK8SYaml(t, output, &ars)
|
||||||
|
|
||||||
|
assert.Len(t, ars.Spec.Template.Spec.Containers, 2, "There should be 2 containers")
|
||||||
|
assert.Equal(t, "runner", ars.Spec.Template.Spec.Containers[0].Name, "Container name should be runner")
|
||||||
|
assert.Equal(t, "other", ars.Spec.Template.Spec.Containers[1].Name, "Container name should be other")
|
||||||
|
assert.Equal(t, "250m", ars.Spec.Template.Spec.Containers[0].Resources.Limits.Cpu().String(), "CPU Limit should be set")
|
||||||
|
assert.Equal(t, "64Mi", ars.Spec.Template.Spec.Containers[0].Resources.Limits.Memory().String(), "Memory Limit should be set")
|
||||||
|
assert.Equal(t, "250m", ars.Spec.Template.Spec.Containers[1].Resources.Limits.Cpu().String(), "CPU Limit should be set")
|
||||||
|
assert.Equal(t, "64Mi", ars.Spec.Template.Spec.Containers[1].Resources.Limits.Memory().String(), "Memory Limit should be set")
|
||||||
|
assert.Equal(t, "SOME_ENV", ars.Spec.Template.Spec.Containers[0].Env[0].Name, "SOME_ENV should be set")
|
||||||
|
assert.Equal(t, "SOME_VALUE", ars.Spec.Template.Spec.Containers[0].Env[0].Value, "SOME_ENV should be set to `SOME_VALUE`")
|
||||||
|
assert.Equal(t, "MY_NODE_NAME", ars.Spec.Template.Spec.Containers[0].Env[1].Name, "MY_NODE_NAME should be set")
|
||||||
|
assert.Equal(t, "spec.nodeName", ars.Spec.Template.Spec.Containers[0].Env[1].ValueFrom.FieldRef.FieldPath, "MY_NODE_NAME should be set to `spec.nodeName`")
|
||||||
|
assert.Equal(t, "work", ars.Spec.Template.Spec.Containers[0].VolumeMounts[0].Name, "VolumeMount name should be work")
|
||||||
|
assert.Equal(t, "/work", ars.Spec.Template.Spec.Containers[0].VolumeMounts[0].MountPath, "VolumeMount mountPath should be /work")
|
||||||
|
assert.Equal(t, "others", ars.Spec.Template.Spec.Containers[0].VolumeMounts[1].Name, "VolumeMount name should be others")
|
||||||
|
assert.Equal(t, "/others", ars.Spec.Template.Spec.Containers[0].VolumeMounts[1].MountPath, "VolumeMount mountPath should be /others")
|
||||||
|
assert.Equal(t, "work", ars.Spec.Template.Spec.Volumes[0].Name, "Volume name should be work")
|
||||||
|
assert.Equal(t, corev1.DNSNone, ars.Spec.Template.Spec.DNSPolicy, "DNS Policy should be None")
|
||||||
|
assert.Equal(t, "192.0.2.1", ars.Spec.Template.Spec.DNSConfig.Nameservers[0], "DNS Nameserver should be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTemplateRenderedAutoScalingRunnerSet_ExtraPodSpec(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// Path to the helm chart we will test
|
||||||
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
testValuesPath, err := filepath.Abs("../tests/values_extra_pod_spec.yaml")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
releaseName := "test-runners"
|
||||||
|
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
||||||
|
|
||||||
|
options := &helm.Options{
|
||||||
|
SetValues: map[string]string{
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
|
},
|
||||||
|
ValuesFiles: []string{testValuesPath},
|
||||||
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
|
}
|
||||||
|
|
||||||
|
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/autoscalingrunnerset.yaml"})
|
||||||
|
|
||||||
|
var ars v1alpha1.AutoscalingRunnerSet
|
||||||
|
helm.UnmarshalK8SYaml(t, output, &ars)
|
||||||
|
|
||||||
|
assert.Len(t, ars.Spec.Template.Spec.Containers, 1, "There should be 1 containers")
|
||||||
|
assert.Equal(t, "runner", ars.Spec.Template.Spec.Containers[0].Name, "Container name should be runner")
|
||||||
|
assert.Equal(t, corev1.DNSNone, ars.Spec.Template.Spec.DNSPolicy, "DNS Policy should be None")
|
||||||
|
assert.Equal(t, "192.0.2.1", ars.Spec.Template.Spec.DNSConfig.Nameservers[0], "DNS Nameserver should be set")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTemplateRenderedAutoScalingRunnerSet_DinDMergePodSpec(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// Path to the helm chart we will test
|
||||||
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
testValuesPath, err := filepath.Abs("../tests/values_dind_merge_spec.yaml")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
releaseName := "test-runners"
|
||||||
|
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
||||||
|
|
||||||
|
options := &helm.Options{
|
||||||
|
SetValues: map[string]string{
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
|
},
|
||||||
|
ValuesFiles: []string{testValuesPath},
|
||||||
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
|
}
|
||||||
|
|
||||||
|
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/autoscalingrunnerset.yaml"}, "--debug")
|
||||||
|
|
||||||
|
var ars v1alpha1.AutoscalingRunnerSet
|
||||||
|
helm.UnmarshalK8SYaml(t, output, &ars)
|
||||||
|
|
||||||
|
assert.Len(t, ars.Spec.Template.Spec.Containers, 2, "There should be 2 containers")
|
||||||
|
assert.Equal(t, "runner", ars.Spec.Template.Spec.Containers[0].Name, "Container name should be runner")
|
||||||
|
assert.Equal(t, "250m", ars.Spec.Template.Spec.Containers[0].Resources.Limits.Cpu().String(), "CPU Limit should be set")
|
||||||
|
assert.Equal(t, "64Mi", ars.Spec.Template.Spec.Containers[0].Resources.Limits.Memory().String(), "Memory Limit should be set")
|
||||||
|
assert.Equal(t, "DOCKER_HOST", ars.Spec.Template.Spec.Containers[0].Env[0].Name, "DOCKER_HOST should be set")
|
||||||
|
assert.Equal(t, "tcp://localhost:9999", ars.Spec.Template.Spec.Containers[0].Env[0].Value, "DOCKER_HOST should be set to `tcp://localhost:9999`")
|
||||||
|
assert.Equal(t, "MY_NODE_NAME", ars.Spec.Template.Spec.Containers[0].Env[1].Name, "MY_NODE_NAME should be set")
|
||||||
|
assert.Equal(t, "spec.nodeName", ars.Spec.Template.Spec.Containers[0].Env[1].ValueFrom.FieldRef.FieldPath, "MY_NODE_NAME should be set to `spec.nodeName`")
|
||||||
|
assert.Equal(t, "DOCKER_TLS_VERIFY", ars.Spec.Template.Spec.Containers[0].Env[2].Name, "DOCKER_TLS_VERIFY should be set")
|
||||||
|
assert.Equal(t, "1", ars.Spec.Template.Spec.Containers[0].Env[2].Value, "DOCKER_TLS_VERIFY should be set to `1`")
|
||||||
|
assert.Equal(t, "DOCKER_CERT_PATH", ars.Spec.Template.Spec.Containers[0].Env[3].Name, "DOCKER_CERT_PATH should be set")
|
||||||
|
assert.Equal(t, "/certs/client", ars.Spec.Template.Spec.Containers[0].Env[3].Value, "DOCKER_CERT_PATH should be set to `/certs/client`")
|
||||||
|
assert.Equal(t, "work", ars.Spec.Template.Spec.Containers[0].VolumeMounts[0].Name, "VolumeMount name should be work")
|
||||||
|
assert.Equal(t, "/work", ars.Spec.Template.Spec.Containers[0].VolumeMounts[0].MountPath, "VolumeMount mountPath should be /work")
|
||||||
|
assert.Equal(t, "others", ars.Spec.Template.Spec.Containers[0].VolumeMounts[1].Name, "VolumeMount name should be others")
|
||||||
|
assert.Equal(t, "/others", ars.Spec.Template.Spec.Containers[0].VolumeMounts[1].MountPath, "VolumeMount mountPath should be /others")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTemplateRenderedAutoScalingRunnerSet_KubeModeMergePodSpec(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// Path to the helm chart we will test
|
||||||
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
testValuesPath, err := filepath.Abs("../tests/values_k8s_merge_spec.yaml")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
releaseName := "test-runners"
|
||||||
|
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
||||||
|
|
||||||
|
options := &helm.Options{
|
||||||
|
SetValues: map[string]string{
|
||||||
|
"controllerServiceAccount.name": "arc",
|
||||||
|
"controllerServiceAccount.namespace": "arc-system",
|
||||||
|
},
|
||||||
|
ValuesFiles: []string{testValuesPath},
|
||||||
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
|
}
|
||||||
|
|
||||||
|
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/autoscalingrunnerset.yaml"}, "--debug")
|
||||||
|
|
||||||
|
var ars v1alpha1.AutoscalingRunnerSet
|
||||||
|
helm.UnmarshalK8SYaml(t, output, &ars)
|
||||||
|
|
||||||
|
assert.Len(t, ars.Spec.Template.Spec.Containers, 1, "There should be 1 containers")
|
||||||
|
assert.Equal(t, "runner", ars.Spec.Template.Spec.Containers[0].Name, "Container name should be runner")
|
||||||
|
assert.Equal(t, "250m", ars.Spec.Template.Spec.Containers[0].Resources.Limits.Cpu().String(), "CPU Limit should be set")
|
||||||
|
assert.Equal(t, "64Mi", ars.Spec.Template.Spec.Containers[0].Resources.Limits.Memory().String(), "Memory Limit should be set")
|
||||||
|
assert.Equal(t, "ACTIONS_RUNNER_CONTAINER_HOOKS", ars.Spec.Template.Spec.Containers[0].Env[0].Name, "ACTIONS_RUNNER_CONTAINER_HOOKS should be set")
|
||||||
|
assert.Equal(t, "/k8s/index.js", ars.Spec.Template.Spec.Containers[0].Env[0].Value, "ACTIONS_RUNNER_CONTAINER_HOOKS should be set to `/k8s/index.js`")
|
||||||
|
assert.Equal(t, "MY_NODE_NAME", ars.Spec.Template.Spec.Containers[0].Env[1].Name, "MY_NODE_NAME should be set")
|
||||||
|
assert.Equal(t, "spec.nodeName", ars.Spec.Template.Spec.Containers[0].Env[1].ValueFrom.FieldRef.FieldPath, "MY_NODE_NAME should be set to `spec.nodeName`")
|
||||||
|
assert.Equal(t, "ACTIONS_RUNNER_POD_NAME", ars.Spec.Template.Spec.Containers[0].Env[2].Name, "ACTIONS_RUNNER_POD_NAME should be set")
|
||||||
|
assert.Equal(t, "ACTIONS_RUNNER_REQUIRE_JOB_CONTAINER", ars.Spec.Template.Spec.Containers[0].Env[3].Name, "ACTIONS_RUNNER_REQUIRE_JOB_CONTAINER should be set")
|
||||||
|
assert.Equal(t, "work", ars.Spec.Template.Spec.Containers[0].VolumeMounts[0].Name, "VolumeMount name should be work")
|
||||||
|
assert.Equal(t, "/work", ars.Spec.Template.Spec.Containers[0].VolumeMounts[0].MountPath, "VolumeMount mountPath should be /work")
|
||||||
|
assert.Equal(t, "others", ars.Spec.Template.Spec.Containers[0].VolumeMounts[1].Name, "VolumeMount name should be others")
|
||||||
|
assert.Equal(t, "/others", ars.Spec.Template.Spec.Containers[0].VolumeMounts[1].MountPath, "VolumeMount mountPath should be /others")
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,4 +2,7 @@ githubConfigUrl: https://github.com/actions/actions-runner-controller
|
|||||||
githubConfigSecret:
|
githubConfigSecret:
|
||||||
github_token: test
|
github_token: test
|
||||||
maxRunners: 10
|
maxRunners: 10
|
||||||
minRunners: 5
|
minRunners: 5
|
||||||
|
controllerServiceAccount:
|
||||||
|
name: "arc"
|
||||||
|
namespace: "arc-system"
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
githubConfigUrl: https://github.com/actions/actions-runner-controller
|
||||||
|
githubConfigSecret:
|
||||||
|
github_token: test
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: runner
|
||||||
|
image: runner-image:latest
|
||||||
|
env:
|
||||||
|
- name: DOCKER_HOST
|
||||||
|
value: tcp://localhost:9999
|
||||||
|
- name: MY_NODE_NAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: spec.nodeName
|
||||||
|
volumeMounts:
|
||||||
|
- name: work
|
||||||
|
mountPath: /work
|
||||||
|
- name: others
|
||||||
|
mountPath: /others
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: "64Mi"
|
||||||
|
cpu: "250m"
|
||||||
|
volumes:
|
||||||
|
- name: work
|
||||||
|
hostPath:
|
||||||
|
path: /data
|
||||||
|
type: Directory
|
||||||
|
containerMode:
|
||||||
|
type: dind
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
githubConfigUrl: https://github.com/actions/actions-runner-controller
|
||||||
|
githubConfigSecret:
|
||||||
|
github_token: test
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: runner
|
||||||
|
image: runner-image:latest
|
||||||
|
env:
|
||||||
|
- name: SOME_ENV
|
||||||
|
value: SOME_VALUE
|
||||||
|
- name: MY_NODE_NAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: spec.nodeName
|
||||||
|
volumeMounts:
|
||||||
|
- name: work
|
||||||
|
mountPath: /work
|
||||||
|
- name: others
|
||||||
|
mountPath: /others
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: "64Mi"
|
||||||
|
cpu: "250m"
|
||||||
|
- name: other
|
||||||
|
image: other-image:latest
|
||||||
|
volumeMounts:
|
||||||
|
- name: work
|
||||||
|
mountPath: /work
|
||||||
|
- name: others
|
||||||
|
mountPath: /others
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: "64Mi"
|
||||||
|
cpu: "250m"
|
||||||
|
volumes:
|
||||||
|
- name: work
|
||||||
|
hostPath:
|
||||||
|
path: /data
|
||||||
|
type: Directory
|
||||||
|
dnsPolicy: "None"
|
||||||
|
dnsConfig:
|
||||||
|
nameservers:
|
||||||
|
- 192.0.2.1
|
||||||
|
containerMode:
|
||||||
|
type: none
|
||||||
12
charts/gha-runner-scale-set/tests/values_extra_pod_spec.yaml
Normal file
12
charts/gha-runner-scale-set/tests/values_extra_pod_spec.yaml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
githubConfigUrl: https://github.com/actions/actions-runner-controller
|
||||||
|
githubConfigSecret:
|
||||||
|
github_token: test
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: runner
|
||||||
|
image: runner-image:latest
|
||||||
|
dnsPolicy: "None"
|
||||||
|
dnsConfig:
|
||||||
|
nameservers:
|
||||||
|
- 192.0.2.1
|
||||||
31
charts/gha-runner-scale-set/tests/values_k8s_merge_spec.yaml
Normal file
31
charts/gha-runner-scale-set/tests/values_k8s_merge_spec.yaml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
githubConfigUrl: https://github.com/actions/actions-runner-controller
|
||||||
|
githubConfigSecret:
|
||||||
|
github_token: test
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: runner
|
||||||
|
image: runner-image:latest
|
||||||
|
env:
|
||||||
|
- name: ACTIONS_RUNNER_CONTAINER_HOOKS
|
||||||
|
value: /k8s/index.js
|
||||||
|
- name: MY_NODE_NAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: spec.nodeName
|
||||||
|
volumeMounts:
|
||||||
|
- name: work
|
||||||
|
mountPath: /work
|
||||||
|
- name: others
|
||||||
|
mountPath: /others
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: "64Mi"
|
||||||
|
cpu: "250m"
|
||||||
|
volumes:
|
||||||
|
- name: work
|
||||||
|
hostPath:
|
||||||
|
path: /data
|
||||||
|
type: Directory
|
||||||
|
containerMode:
|
||||||
|
type: kubernetes
|
||||||
@@ -68,25 +68,29 @@ githubConfigSecret:
|
|||||||
# key: ca.pem
|
# key: ca.pem
|
||||||
# runnerMountPath: /usr/local/share/ca-certificates/
|
# runnerMountPath: /usr/local/share/ca-certificates/
|
||||||
|
|
||||||
|
# containerMode:
|
||||||
|
# type: "dind" ## type can be set to dind or kubernetes
|
||||||
|
# ## the following is required when containerMode.type=kubernetes
|
||||||
|
# kubernetesModeWorkVolumeClaim:
|
||||||
|
# accessModes: ["ReadWriteOnce"]
|
||||||
|
# # For local testing, use https://github.com/openebs/dynamic-localpv-provisioner/blob/develop/docs/quickstart.md to provide dynamic provision volume with storageClassName: openebs-hostpath
|
||||||
|
# storageClassName: "dynamic-blob-storage"
|
||||||
|
# resources:
|
||||||
|
# requests:
|
||||||
|
# storage: 1Gi
|
||||||
|
|
||||||
## template is the PodSpec for each runner Pod
|
## template is the PodSpec for each runner Pod
|
||||||
template:
|
template:
|
||||||
spec:
|
## template.spec will be modified if you change the container mode
|
||||||
containers:
|
|
||||||
- name: runner
|
|
||||||
image: ghcr.io/actions/actions-runner:latest
|
|
||||||
command: ["/home/runner/run.sh"]
|
|
||||||
|
|
||||||
containerMode:
|
|
||||||
type: "" ## type can be set to dind or kubernetes
|
|
||||||
## with containerMode.type=dind, we will populate the template.spec with following pod spec
|
## with containerMode.type=dind, we will populate the template.spec with following pod spec
|
||||||
## template:
|
## template:
|
||||||
## spec:
|
## spec:
|
||||||
## initContainers:
|
## initContainers:
|
||||||
## - name: initExternalsInternalVolume
|
## - name: init-dind-externals
|
||||||
## image: ghcr.io/actions/actions-runner:latest
|
## image: ghcr.io/actions/actions-runner:latest
|
||||||
## command: ["cp", "-r", "-v", "/home/runner/externals/.", "/home/runner/tmpDir/"]
|
## command: ["cp", "-r", "-v", "/home/runner/externals/.", "/home/runner/tmpDir/"]
|
||||||
## volumeMounts:
|
## volumeMounts:
|
||||||
## - name: externalsInternal
|
## - name: dind-externals
|
||||||
## mountPath: /home/runner/tmpDir
|
## mountPath: /home/runner/tmpDir
|
||||||
## containers:
|
## containers:
|
||||||
## - name: runner
|
## - name: runner
|
||||||
@@ -99,9 +103,9 @@ containerMode:
|
|||||||
## - name: DOCKER_CERT_PATH
|
## - name: DOCKER_CERT_PATH
|
||||||
## value: /certs/client
|
## value: /certs/client
|
||||||
## volumeMounts:
|
## volumeMounts:
|
||||||
## - name: workingDirectoryInternal
|
## - name: work
|
||||||
## mountPath: /home/runner/_work
|
## mountPath: /home/runner/_work
|
||||||
## - name: dinDInternal
|
## - name: dind-cert
|
||||||
## mountPath: /certs/client
|
## mountPath: /certs/client
|
||||||
## readOnly: true
|
## readOnly: true
|
||||||
## - name: dind
|
## - name: dind
|
||||||
@@ -109,18 +113,18 @@ containerMode:
|
|||||||
## securityContext:
|
## securityContext:
|
||||||
## privileged: true
|
## privileged: true
|
||||||
## volumeMounts:
|
## volumeMounts:
|
||||||
## - mountPath: /certs/client
|
## - name: work
|
||||||
## name: dinDInternal
|
## mountPath: /home/runner/_work
|
||||||
## - mountPath: /home/runner/_work
|
## - name: dind-cert
|
||||||
## name: workingDirectoryInternal
|
## mountPath: /certs/client
|
||||||
## - mountPath: /home/runner/externals
|
## - name: dind-externals
|
||||||
## name: externalsInternal
|
## mountPath: /home/runner/externals
|
||||||
## volumes:
|
## volumes:
|
||||||
## - name: dinDInternal
|
## - name: work
|
||||||
## emptyDir: {}
|
## emptyDir: {}
|
||||||
## - name: workingDirectoryInternal
|
## - name: dind-cert
|
||||||
## emptyDir: {}
|
## emptyDir: {}
|
||||||
## - name: externalsInternal
|
## - name: dind-externals
|
||||||
## emptyDir: {}
|
## emptyDir: {}
|
||||||
######################################################################################################
|
######################################################################################################
|
||||||
## with containerMode.type=kubernetes, we will populate the template.spec with following pod spec
|
## with containerMode.type=kubernetes, we will populate the template.spec with following pod spec
|
||||||
@@ -151,13 +155,18 @@ containerMode:
|
|||||||
## resources:
|
## resources:
|
||||||
## requests:
|
## requests:
|
||||||
## storage: 1Gi
|
## storage: 1Gi
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: runner
|
||||||
|
image: ghcr.io/actions/actions-runner:latest
|
||||||
|
command: ["/home/runner/run.sh"]
|
||||||
|
|
||||||
## the following is required when containerMode.type=kubernetes
|
## Optional controller service account that needs to have required Role and RoleBinding
|
||||||
kubernetesModeWorkVolumeClaim:
|
## to operate this gha-runner-scale-set installation.
|
||||||
accessModes: ["ReadWriteOnce"]
|
## The helm chart will try to find the controller deployment and its service account at installation time.
|
||||||
# For testing, use https://github.com/rancher/local-path-provisioner to provide dynamic provision volume
|
## In case the helm chart can't find the right service account, you can explicitly pass in the following value
|
||||||
# TODO: remove before release
|
## to help it finish RoleBinding with the right service account.
|
||||||
storageClassName: "dynamic-blob-storage"
|
## Note: if your controller is installed to only watch a single namespace, you have to pass these values explicitly.
|
||||||
resources:
|
# controllerServiceAccount:
|
||||||
requests:
|
# namespace: arc-system
|
||||||
storage: 1Gi
|
# name: test-arc-gha-runner-scale-set-controller
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ func TestCustomerServerRootCA(t *testing.T) {
|
|||||||
|
|
||||||
client, err := newActionsClientFromConfig(config, creds)
|
client, err := newActionsClientFromConfig(config, creds)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
_, err = client.GetRunnerScaleSet(ctx, "test")
|
_, err = client.GetRunnerScaleSet(ctx, 1, "test")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.True(t, serverCalledSuccessfully)
|
assert.True(t, serverCalledSuccessfully)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,16 +17,28 @@ spec:
|
|||||||
- additionalPrinterColumns:
|
- additionalPrinterColumns:
|
||||||
- jsonPath: .spec.minRunners
|
- jsonPath: .spec.minRunners
|
||||||
name: Minimum Runners
|
name: Minimum Runners
|
||||||
type: number
|
type: integer
|
||||||
- jsonPath: .spec.maxRunners
|
- jsonPath: .spec.maxRunners
|
||||||
name: Maximum Runners
|
name: Maximum Runners
|
||||||
type: number
|
type: integer
|
||||||
- jsonPath: .status.currentRunners
|
- jsonPath: .status.currentRunners
|
||||||
name: Current Runners
|
name: Current Runners
|
||||||
type: number
|
type: integer
|
||||||
- jsonPath: .status.state
|
- jsonPath: .status.state
|
||||||
name: State
|
name: State
|
||||||
type: string
|
type: string
|
||||||
|
- jsonPath: .status.pendingEphemeralRunners
|
||||||
|
name: Pending Runners
|
||||||
|
type: integer
|
||||||
|
- jsonPath: .status.runningEphemeralRunners
|
||||||
|
name: Running Runners
|
||||||
|
type: integer
|
||||||
|
- jsonPath: .status.finishedEphemeralRunners
|
||||||
|
name: Finished Runners
|
||||||
|
type: integer
|
||||||
|
- jsonPath: .status.deletingEphemeralRunners
|
||||||
|
name: Deleting Runners
|
||||||
|
type: integer
|
||||||
name: v1alpha1
|
name: v1alpha1
|
||||||
schema:
|
schema:
|
||||||
openAPIV3Schema:
|
openAPIV3Schema:
|
||||||
@@ -4306,6 +4318,12 @@ spec:
|
|||||||
properties:
|
properties:
|
||||||
currentRunners:
|
currentRunners:
|
||||||
type: integer
|
type: integer
|
||||||
|
failedEphemeralRunners:
|
||||||
|
type: integer
|
||||||
|
pendingEphemeralRunners:
|
||||||
|
type: integer
|
||||||
|
runningEphemeralRunners:
|
||||||
|
type: integer
|
||||||
state:
|
state:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
|
|||||||
@@ -21,6 +21,18 @@ spec:
|
|||||||
- jsonPath: .status.currentReplicas
|
- jsonPath: .status.currentReplicas
|
||||||
name: CurrentReplicas
|
name: CurrentReplicas
|
||||||
type: integer
|
type: integer
|
||||||
|
- jsonPath: .status.pendingEphemeralRunners
|
||||||
|
name: Pending Runners
|
||||||
|
type: integer
|
||||||
|
- jsonPath: .status.runningEphemeralRunners
|
||||||
|
name: Running Runners
|
||||||
|
type: integer
|
||||||
|
- jsonPath: .status.finishedEphemeralRunners
|
||||||
|
name: Finished Runners
|
||||||
|
type: integer
|
||||||
|
- jsonPath: .status.deletingEphemeralRunners
|
||||||
|
name: Deleting Runners
|
||||||
|
type: integer
|
||||||
name: v1alpha1
|
name: v1alpha1
|
||||||
schema:
|
schema:
|
||||||
openAPIV3Schema:
|
openAPIV3Schema:
|
||||||
@@ -4296,6 +4308,14 @@ spec:
|
|||||||
currentReplicas:
|
currentReplicas:
|
||||||
description: CurrentReplicas is the number of currently running EphemeralRunner resources being managed by this EphemeralRunnerSet.
|
description: CurrentReplicas is the number of currently running EphemeralRunner resources being managed by this EphemeralRunnerSet.
|
||||||
type: integer
|
type: integer
|
||||||
|
failedEphemeralRunners:
|
||||||
|
type: integer
|
||||||
|
pendingEphemeralRunners:
|
||||||
|
type: integer
|
||||||
|
runningEphemeralRunners:
|
||||||
|
type: integer
|
||||||
|
required:
|
||||||
|
- currentReplicas
|
||||||
type: object
|
type: object
|
||||||
type: object
|
type: object
|
||||||
served: true
|
served: true
|
||||||
|
|||||||
@@ -17,6 +17,21 @@ spec:
|
|||||||
scope: Namespaced
|
scope: Namespaced
|
||||||
versions:
|
versions:
|
||||||
- additionalPrinterColumns:
|
- additionalPrinterColumns:
|
||||||
|
- jsonPath: .spec.template.spec.enterprise
|
||||||
|
name: Enterprise
|
||||||
|
type: string
|
||||||
|
- jsonPath: .spec.template.spec.organization
|
||||||
|
name: Organization
|
||||||
|
type: string
|
||||||
|
- jsonPath: .spec.template.spec.repository
|
||||||
|
name: Repository
|
||||||
|
type: string
|
||||||
|
- jsonPath: .spec.template.spec.group
|
||||||
|
name: Group
|
||||||
|
type: string
|
||||||
|
- jsonPath: .spec.template.spec.labels
|
||||||
|
name: Labels
|
||||||
|
type: string
|
||||||
- jsonPath: .spec.replicas
|
- jsonPath: .spec.replicas
|
||||||
name: Desired
|
name: Desired
|
||||||
type: number
|
type: number
|
||||||
|
|||||||
10
config/manager/env-replacement.yaml
Normal file
10
config/manager/env-replacement.yaml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
source:
|
||||||
|
kind: Deployment
|
||||||
|
name: controller-manager
|
||||||
|
fieldPath: spec.template.spec.containers.[name=manager].image
|
||||||
|
targets:
|
||||||
|
- select:
|
||||||
|
kind: Deployment
|
||||||
|
name: controller-manager
|
||||||
|
fieldPaths:
|
||||||
|
- spec.template.spec.containers.[name=manager].env.[name=CONTROLLER_MANAGER_CONTAINER_IMAGE].value
|
||||||
@@ -6,3 +6,6 @@ images:
|
|||||||
- name: controller
|
- name: controller
|
||||||
newName: summerwind/actions-runner-controller
|
newName: summerwind/actions-runner-controller
|
||||||
newTag: dev
|
newTag: dev
|
||||||
|
|
||||||
|
replacements:
|
||||||
|
- path: env-replacement.yaml
|
||||||
|
|||||||
@@ -50,10 +50,8 @@ spec:
|
|||||||
optional: true
|
optional: true
|
||||||
- name: GITHUB_APP_PRIVATE_KEY
|
- name: GITHUB_APP_PRIVATE_KEY
|
||||||
value: /etc/actions-runner-controller/github_app_private_key
|
value: /etc/actions-runner-controller/github_app_private_key
|
||||||
- name: CONTROLLER_MANAGER_POD_NAME
|
- name: CONTROLLER_MANAGER_CONTAINER_IMAGE
|
||||||
valueFrom:
|
value: CONTROLLER_MANAGER_CONTAINER_IMAGE
|
||||||
fieldRef:
|
|
||||||
fieldPath: metadata.name
|
|
||||||
- name: CONTROLLER_MANAGER_POD_NAMESPACE
|
- name: CONTROLLER_MANAGER_POD_NAMESPACE
|
||||||
valueFrom:
|
valueFrom:
|
||||||
fieldRef:
|
fieldRef:
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ func (r *AutoscalingListenerReconciler) Reconcile(ctx context.Context, req ctrl.
|
|||||||
}
|
}
|
||||||
if !done {
|
if !done {
|
||||||
log.Info("Waiting for resources to be deleted before removing finalizer")
|
log.Info("Waiting for resources to be deleted before removing finalizer")
|
||||||
return ctrl.Result{}, nil
|
return ctrl.Result{Requeue: true}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info("Removing finalizer")
|
log.Info("Removing finalizer")
|
||||||
@@ -204,7 +204,7 @@ func (r *AutoscalingListenerReconciler) Reconcile(ctx context.Context, req ctrl.
|
|||||||
return r.createRoleBindingForListener(ctx, autoscalingListener, listenerRole, serviceAccount, log)
|
return r.createRoleBindingForListener(ctx, autoscalingListener, listenerRole, serviceAccount, log)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a secret containing proxy config if specifiec
|
// Create a secret containing proxy config if specified
|
||||||
if autoscalingListener.Spec.Proxy != nil {
|
if autoscalingListener.Spec.Proxy != nil {
|
||||||
proxySecret := new(corev1.Secret)
|
proxySecret := new(corev1.Secret)
|
||||||
if err := r.Get(ctx, types.NamespacedName{Namespace: autoscalingListener.Namespace, Name: proxyListenerSecretName(autoscalingListener)}, proxySecret); err != nil {
|
if err := r.Get(ctx, types.NamespacedName{Namespace: autoscalingListener.Namespace, Name: proxyListenerSecretName(autoscalingListener)}, proxySecret); err != nil {
|
||||||
@@ -299,7 +299,6 @@ func (r *AutoscalingListenerReconciler) SetupWithManager(mgr ctrl.Manager) error
|
|||||||
For(&v1alpha1.AutoscalingListener{}).
|
For(&v1alpha1.AutoscalingListener{}).
|
||||||
Owns(&corev1.Pod{}).
|
Owns(&corev1.Pod{}).
|
||||||
Owns(&corev1.ServiceAccount{}).
|
Owns(&corev1.ServiceAccount{}).
|
||||||
Owns(&corev1.Secret{}).
|
|
||||||
Watches(&source.Kind{Type: &rbacv1.Role{}}, handler.EnqueueRequestsFromMapFunc(labelBasedWatchFunc)).
|
Watches(&source.Kind{Type: &rbacv1.Role{}}, handler.EnqueueRequestsFromMapFunc(labelBasedWatchFunc)).
|
||||||
Watches(&source.Kind{Type: &rbacv1.RoleBinding{}}, handler.EnqueueRequestsFromMapFunc(labelBasedWatchFunc)).
|
Watches(&source.Kind{Type: &rbacv1.RoleBinding{}}, handler.EnqueueRequestsFromMapFunc(labelBasedWatchFunc)).
|
||||||
WithEventFilter(predicate.ResourceVersionChangedPredicate{}).
|
WithEventFilter(predicate.ResourceVersionChangedPredicate{}).
|
||||||
@@ -503,7 +502,7 @@ func (r *AutoscalingListenerReconciler) createSecretsForListener(ctx context.Con
|
|||||||
}
|
}
|
||||||
|
|
||||||
logger.Info("Created listener secret", "namespace", newListenerSecret.Namespace, "name", newListenerSecret.Name)
|
logger.Info("Created listener secret", "namespace", newListenerSecret.Namespace, "name", newListenerSecret.Name)
|
||||||
return ctrl.Result{}, nil
|
return ctrl.Result{Requeue: true}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *AutoscalingListenerReconciler) createProxySecret(ctx context.Context, autoscalingListener *v1alpha1.AutoscalingListener, logger logr.Logger) (ctrl.Result, error) {
|
func (r *AutoscalingListenerReconciler) createProxySecret(ctx context.Context, autoscalingListener *v1alpha1.AutoscalingListener, logger logr.Logger) (ctrl.Result, error) {
|
||||||
@@ -524,8 +523,8 @@ func (r *AutoscalingListenerReconciler) createProxySecret(ctx context.Context, a
|
|||||||
Name: proxyListenerSecretName(autoscalingListener),
|
Name: proxyListenerSecretName(autoscalingListener),
|
||||||
Namespace: autoscalingListener.Namespace,
|
Namespace: autoscalingListener.Namespace,
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
"auto-scaling-runner-set-namespace": autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
LabelKeyGitHubScaleSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
||||||
"auto-scaling-runner-set-name": autoscalingListener.Spec.AutoscalingRunnerSetName,
|
LabelKeyGitHubScaleSetName: autoscalingListener.Spec.AutoscalingRunnerSetName,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Data: data,
|
Data: data,
|
||||||
@@ -542,7 +541,7 @@ func (r *AutoscalingListenerReconciler) createProxySecret(ctx context.Context, a
|
|||||||
|
|
||||||
logger.Info("Created listener proxy secret", "namespace", newProxySecret.Namespace, "name", newProxySecret.Name)
|
logger.Info("Created listener proxy secret", "namespace", newProxySecret.Namespace, "name", newProxySecret.Name)
|
||||||
|
|
||||||
return ctrl.Result{}, nil
|
return ctrl.Result{Requeue: true}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *AutoscalingListenerReconciler) updateSecretsForListener(ctx context.Context, secret *corev1.Secret, mirrorSecret *corev1.Secret, logger logr.Logger) (ctrl.Result, error) {
|
func (r *AutoscalingListenerReconciler) updateSecretsForListener(ctx context.Context, secret *corev1.Secret, mirrorSecret *corev1.Secret, logger logr.Logger) (ctrl.Result, error) {
|
||||||
@@ -558,7 +557,7 @@ func (r *AutoscalingListenerReconciler) updateSecretsForListener(ctx context.Con
|
|||||||
}
|
}
|
||||||
|
|
||||||
logger.Info("Updated listener mirror secret", "namespace", updatedMirrorSecret.Namespace, "name", updatedMirrorSecret.Name, "hash", dataHash)
|
logger.Info("Updated listener mirror secret", "namespace", updatedMirrorSecret.Namespace, "name", updatedMirrorSecret.Name, "hash", dataHash)
|
||||||
return ctrl.Result{}, nil
|
return ctrl.Result{Requeue: true}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *AutoscalingListenerReconciler) createRoleForListener(ctx context.Context, autoscalingListener *v1alpha1.AutoscalingListener, logger logr.Logger) (ctrl.Result, error) {
|
func (r *AutoscalingListenerReconciler) createRoleForListener(ctx context.Context, autoscalingListener *v1alpha1.AutoscalingListener, logger logr.Logger) (ctrl.Result, error) {
|
||||||
|
|||||||
@@ -45,9 +45,8 @@ const (
|
|||||||
autoscalingRunnerSetOwnerKey = ".metadata.controller"
|
autoscalingRunnerSetOwnerKey = ".metadata.controller"
|
||||||
LabelKeyRunnerSpecHash = "runner-spec-hash"
|
LabelKeyRunnerSpecHash = "runner-spec-hash"
|
||||||
autoscalingRunnerSetFinalizerName = "autoscalingrunnerset.actions.github.com/finalizer"
|
autoscalingRunnerSetFinalizerName = "autoscalingrunnerset.actions.github.com/finalizer"
|
||||||
runnerScaleSetIdKey = "runner-scale-set-id"
|
runnerScaleSetIdAnnotationKey = "runner-scale-set-id"
|
||||||
runnerScaleSetNameKey = "runner-scale-set-name"
|
runnerScaleSetNameAnnotationKey = "runner-scale-set-name"
|
||||||
runnerScaleSetRunnerGroupNameKey = "runner-scale-set-runner-group-name"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// AutoscalingRunnerSetReconciler reconciles a AutoscalingRunnerSet object
|
// AutoscalingRunnerSetReconciler reconciles a AutoscalingRunnerSet object
|
||||||
@@ -140,7 +139,7 @@ func (r *AutoscalingRunnerSetReconciler) Reconcile(ctx context.Context, req ctrl
|
|||||||
return ctrl.Result{}, nil
|
return ctrl.Result{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
scaleSetIdRaw, ok := autoscalingRunnerSet.Annotations[runnerScaleSetIdKey]
|
scaleSetIdRaw, ok := autoscalingRunnerSet.Annotations[runnerScaleSetIdAnnotationKey]
|
||||||
if !ok {
|
if !ok {
|
||||||
// Need to create a new runner scale set on Actions service
|
// Need to create a new runner scale set on Actions service
|
||||||
log.Info("Runner scale set id annotation does not exist. Creating a new runner scale set.")
|
log.Info("Runner scale set id annotation does not exist. Creating a new runner scale set.")
|
||||||
@@ -154,14 +153,14 @@ func (r *AutoscalingRunnerSetReconciler) Reconcile(ctx context.Context, req ctrl
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the runner group of the scale set is up to date
|
// Make sure the runner group of the scale set is up to date
|
||||||
currentRunnerGroupName, ok := autoscalingRunnerSet.Annotations[runnerScaleSetRunnerGroupNameKey]
|
currentRunnerGroupName, ok := autoscalingRunnerSet.Annotations[AnnotationKeyGitHubRunnerGroupName]
|
||||||
if !ok || (len(autoscalingRunnerSet.Spec.RunnerGroup) > 0 && !strings.EqualFold(currentRunnerGroupName, autoscalingRunnerSet.Spec.RunnerGroup)) {
|
if !ok || (len(autoscalingRunnerSet.Spec.RunnerGroup) > 0 && !strings.EqualFold(currentRunnerGroupName, autoscalingRunnerSet.Spec.RunnerGroup)) {
|
||||||
log.Info("AutoScalingRunnerSet runner group changed. Updating the runner scale set.")
|
log.Info("AutoScalingRunnerSet runner group changed. Updating the runner scale set.")
|
||||||
return r.updateRunnerScaleSetRunnerGroup(ctx, autoscalingRunnerSet, log)
|
return r.updateRunnerScaleSetRunnerGroup(ctx, autoscalingRunnerSet, log)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the runner scale set name is up to date
|
// Make sure the runner scale set name is up to date
|
||||||
currentRunnerScaleSetName, ok := autoscalingRunnerSet.Annotations[runnerScaleSetNameKey]
|
currentRunnerScaleSetName, ok := autoscalingRunnerSet.Annotations[runnerScaleSetNameAnnotationKey]
|
||||||
if !ok || (len(autoscalingRunnerSet.Spec.RunnerScaleSetName) > 0 && !strings.EqualFold(currentRunnerScaleSetName, autoscalingRunnerSet.Spec.RunnerScaleSetName)) {
|
if !ok || (len(autoscalingRunnerSet.Spec.RunnerScaleSetName) > 0 && !strings.EqualFold(currentRunnerScaleSetName, autoscalingRunnerSet.Spec.RunnerScaleSetName)) {
|
||||||
log.Info("AutoScalingRunnerSet runner scale set name changed. Updating the runner scale set.")
|
log.Info("AutoScalingRunnerSet runner scale set name changed. Updating the runner scale set.")
|
||||||
return r.updateRunnerScaleSetName(ctx, autoscalingRunnerSet, log)
|
return r.updateRunnerScaleSetName(ctx, autoscalingRunnerSet, log)
|
||||||
@@ -238,6 +237,9 @@ func (r *AutoscalingRunnerSetReconciler) Reconcile(ctx context.Context, req ctrl
|
|||||||
if latestRunnerSet.Status.CurrentReplicas != autoscalingRunnerSet.Status.CurrentRunners {
|
if latestRunnerSet.Status.CurrentReplicas != autoscalingRunnerSet.Status.CurrentRunners {
|
||||||
if err := patchSubResource(ctx, r.Status(), autoscalingRunnerSet, func(obj *v1alpha1.AutoscalingRunnerSet) {
|
if err := patchSubResource(ctx, r.Status(), autoscalingRunnerSet, func(obj *v1alpha1.AutoscalingRunnerSet) {
|
||||||
obj.Status.CurrentRunners = latestRunnerSet.Status.CurrentReplicas
|
obj.Status.CurrentRunners = latestRunnerSet.Status.CurrentReplicas
|
||||||
|
obj.Status.PendingEphemeralRunners = latestRunnerSet.Status.PendingEphemeralRunners
|
||||||
|
obj.Status.RunningEphemeralRunners = latestRunnerSet.Status.RunningEphemeralRunners
|
||||||
|
obj.Status.FailedEphemeralRunners = latestRunnerSet.Status.FailedEphemeralRunners
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
log.Error(err, "Failed to update autoscaling runner set status with current runner count")
|
log.Error(err, "Failed to update autoscaling runner set status with current runner count")
|
||||||
return ctrl.Result{}, err
|
return ctrl.Result{}, err
|
||||||
@@ -313,24 +315,29 @@ func (r *AutoscalingRunnerSetReconciler) createRunnerScaleSet(ctx context.Contex
|
|||||||
logger.Error(err, "Failed to initialize Actions service client for creating a new runner scale set")
|
logger.Error(err, "Failed to initialize Actions service client for creating a new runner scale set")
|
||||||
return ctrl.Result{}, err
|
return ctrl.Result{}, err
|
||||||
}
|
}
|
||||||
runnerScaleSet, err := actionsClient.GetRunnerScaleSet(ctx, autoscalingRunnerSet.Spec.RunnerScaleSetName)
|
|
||||||
|
runnerGroupId := 1
|
||||||
|
if len(autoscalingRunnerSet.Spec.RunnerGroup) > 0 {
|
||||||
|
runnerGroup, err := actionsClient.GetRunnerGroupByName(ctx, autoscalingRunnerSet.Spec.RunnerGroup)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(err, "Failed to get runner group by name", "runnerGroup", autoscalingRunnerSet.Spec.RunnerGroup)
|
||||||
|
return ctrl.Result{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
runnerGroupId = int(runnerGroup.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
runnerScaleSet, err := actionsClient.GetRunnerScaleSet(ctx, runnerGroupId, autoscalingRunnerSet.Spec.RunnerScaleSetName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err, "Failed to get runner scale set from Actions service")
|
logger.Error(err, "Failed to get runner scale set from Actions service",
|
||||||
|
"runnerGroupId",
|
||||||
|
strconv.Itoa(runnerGroupId),
|
||||||
|
"runnerScaleSetName",
|
||||||
|
autoscalingRunnerSet.Spec.RunnerScaleSetName)
|
||||||
return ctrl.Result{}, err
|
return ctrl.Result{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
runnerGroupId := 1
|
|
||||||
if runnerScaleSet == nil {
|
if runnerScaleSet == nil {
|
||||||
if len(autoscalingRunnerSet.Spec.RunnerGroup) > 0 {
|
|
||||||
runnerGroup, err := actionsClient.GetRunnerGroupByName(ctx, autoscalingRunnerSet.Spec.RunnerGroup)
|
|
||||||
if err != nil {
|
|
||||||
logger.Error(err, "Failed to get runner group by name", "runnerGroup", autoscalingRunnerSet.Spec.RunnerGroup)
|
|
||||||
return ctrl.Result{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
runnerGroupId = int(runnerGroup.ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
runnerScaleSet, err = actionsClient.CreateRunnerScaleSet(
|
runnerScaleSet, err = actionsClient.CreateRunnerScaleSet(
|
||||||
ctx,
|
ctx,
|
||||||
&actions.RunnerScaleSet{
|
&actions.RunnerScaleSet{
|
||||||
@@ -357,12 +364,18 @@ func (r *AutoscalingRunnerSetReconciler) createRunnerScaleSet(ctx context.Contex
|
|||||||
if autoscalingRunnerSet.Annotations == nil {
|
if autoscalingRunnerSet.Annotations == nil {
|
||||||
autoscalingRunnerSet.Annotations = map[string]string{}
|
autoscalingRunnerSet.Annotations = map[string]string{}
|
||||||
}
|
}
|
||||||
|
if autoscalingRunnerSet.Labels == nil {
|
||||||
|
autoscalingRunnerSet.Labels = map[string]string{}
|
||||||
|
}
|
||||||
|
|
||||||
logger.Info("Adding runner scale set ID, name and runner group name as an annotation")
|
logger.Info("Adding runner scale set ID, name and runner group name as an annotation and url labels")
|
||||||
if err = patch(ctx, r.Client, autoscalingRunnerSet, func(obj *v1alpha1.AutoscalingRunnerSet) {
|
if err = patch(ctx, r.Client, autoscalingRunnerSet, func(obj *v1alpha1.AutoscalingRunnerSet) {
|
||||||
obj.Annotations[runnerScaleSetNameKey] = runnerScaleSet.Name
|
obj.Annotations[runnerScaleSetNameAnnotationKey] = runnerScaleSet.Name
|
||||||
obj.Annotations[runnerScaleSetIdKey] = strconv.Itoa(runnerScaleSet.Id)
|
obj.Annotations[runnerScaleSetIdAnnotationKey] = strconv.Itoa(runnerScaleSet.Id)
|
||||||
obj.Annotations[runnerScaleSetRunnerGroupNameKey] = runnerScaleSet.RunnerGroupName
|
obj.Annotations[AnnotationKeyGitHubRunnerGroupName] = runnerScaleSet.RunnerGroupName
|
||||||
|
if err := applyGitHubURLLabels(obj.Spec.GitHubConfigUrl, obj.Labels); err != nil { // should never happen
|
||||||
|
logger.Error(err, "Failed to apply GitHub URL labels")
|
||||||
|
}
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
logger.Error(err, "Failed to add runner scale set ID, name and runner group name as an annotation")
|
logger.Error(err, "Failed to add runner scale set ID, name and runner group name as an annotation")
|
||||||
return ctrl.Result{}, err
|
return ctrl.Result{}, err
|
||||||
@@ -376,7 +389,7 @@ func (r *AutoscalingRunnerSetReconciler) createRunnerScaleSet(ctx context.Contex
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetRunnerGroup(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, logger logr.Logger) (ctrl.Result, error) {
|
func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetRunnerGroup(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, logger logr.Logger) (ctrl.Result, error) {
|
||||||
runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdKey])
|
runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdAnnotationKey])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err, "Failed to parse runner scale set ID")
|
logger.Error(err, "Failed to parse runner scale set ID")
|
||||||
return ctrl.Result{}, err
|
return ctrl.Result{}, err
|
||||||
@@ -407,7 +420,7 @@ func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetRunnerGroup(ctx con
|
|||||||
|
|
||||||
logger.Info("Updating runner scale set runner group name as an annotation")
|
logger.Info("Updating runner scale set runner group name as an annotation")
|
||||||
if err := patch(ctx, r.Client, autoscalingRunnerSet, func(obj *v1alpha1.AutoscalingRunnerSet) {
|
if err := patch(ctx, r.Client, autoscalingRunnerSet, func(obj *v1alpha1.AutoscalingRunnerSet) {
|
||||||
obj.Annotations[runnerScaleSetRunnerGroupNameKey] = updatedRunnerScaleSet.RunnerGroupName
|
obj.Annotations[AnnotationKeyGitHubRunnerGroupName] = updatedRunnerScaleSet.RunnerGroupName
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
logger.Error(err, "Failed to update runner group name annotation")
|
logger.Error(err, "Failed to update runner group name annotation")
|
||||||
return ctrl.Result{}, err
|
return ctrl.Result{}, err
|
||||||
@@ -418,7 +431,7 @@ func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetRunnerGroup(ctx con
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetName(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, logger logr.Logger) (ctrl.Result, error) {
|
func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetName(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, logger logr.Logger) (ctrl.Result, error) {
|
||||||
runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdKey])
|
runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdAnnotationKey])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err, "Failed to parse runner scale set ID")
|
logger.Error(err, "Failed to parse runner scale set ID")
|
||||||
return ctrl.Result{}, err
|
return ctrl.Result{}, err
|
||||||
@@ -443,7 +456,7 @@ func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetName(ctx context.Co
|
|||||||
|
|
||||||
logger.Info("Updating runner scale set name as an annotation")
|
logger.Info("Updating runner scale set name as an annotation")
|
||||||
if err := patch(ctx, r.Client, autoscalingRunnerSet, func(obj *v1alpha1.AutoscalingRunnerSet) {
|
if err := patch(ctx, r.Client, autoscalingRunnerSet, func(obj *v1alpha1.AutoscalingRunnerSet) {
|
||||||
obj.Annotations[runnerScaleSetNameKey] = updatedRunnerScaleSet.Name
|
obj.Annotations[runnerScaleSetNameAnnotationKey] = updatedRunnerScaleSet.Name
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
logger.Error(err, "Failed to update runner scale set name annotation")
|
logger.Error(err, "Failed to update runner scale set name annotation")
|
||||||
return ctrl.Result{}, err
|
return ctrl.Result{}, err
|
||||||
@@ -455,7 +468,7 @@ func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetName(ctx context.Co
|
|||||||
|
|
||||||
func (r *AutoscalingRunnerSetReconciler) deleteRunnerScaleSet(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, logger logr.Logger) error {
|
func (r *AutoscalingRunnerSetReconciler) deleteRunnerScaleSet(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, logger logr.Logger) error {
|
||||||
logger.Info("Deleting the runner scale set from Actions service")
|
logger.Info("Deleting the runner scale set from Actions service")
|
||||||
runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdKey])
|
runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdAnnotationKey])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// If the annotation is not set correctly, or if it does not exist, we are going to get stuck in a loop trying to parse the scale set id.
|
// If the annotation is not set correctly, or if it does not exist, we are going to get stuck in a loop trying to parse the scale set id.
|
||||||
// If the configuration is invalid (secret does not exist for example), we never get to the point to create runner set. But then, manual cleanup
|
// If the configuration is invalid (secret does not exist for example), we never get to the point to create runner set. But then, manual cleanup
|
||||||
|
|||||||
@@ -117,19 +117,39 @@ var _ = Describe("Test AutoScalingRunnerSet controller", func() {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := created.Annotations[runnerScaleSetIdKey]; !ok {
|
if _, ok := created.Annotations[runnerScaleSetIdAnnotationKey]; !ok {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := created.Annotations[runnerScaleSetRunnerGroupNameKey]; !ok {
|
if _, ok := created.Annotations[AnnotationKeyGitHubRunnerGroupName]; !ok {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("%s_%s", created.Annotations[runnerScaleSetIdKey], created.Annotations[runnerScaleSetRunnerGroupNameKey]), nil
|
return fmt.Sprintf("%s_%s", created.Annotations[runnerScaleSetIdAnnotationKey], created.Annotations[AnnotationKeyGitHubRunnerGroupName]), nil
|
||||||
},
|
},
|
||||||
autoscalingRunnerSetTestTimeout,
|
autoscalingRunnerSetTestTimeout,
|
||||||
autoscalingRunnerSetTestInterval).Should(BeEquivalentTo("1_testgroup"), "RunnerScaleSet should be created/fetched and update the AutoScalingRunnerSet's annotation")
|
autoscalingRunnerSetTestInterval).Should(BeEquivalentTo("1_testgroup"), "RunnerScaleSet should be created/fetched and update the AutoScalingRunnerSet's annotation")
|
||||||
|
|
||||||
|
Eventually(
|
||||||
|
func() (string, error) {
|
||||||
|
err := k8sClient.Get(ctx, client.ObjectKey{Name: autoscalingRunnerSet.Name, Namespace: autoscalingRunnerSet.Namespace}, created)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := created.Labels[LabelKeyGitHubOrganization]; !ok {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := created.Labels[LabelKeyGitHubRepository]; !ok {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%s/%s", created.Labels[LabelKeyGitHubOrganization], created.Labels[LabelKeyGitHubRepository]), nil
|
||||||
|
},
|
||||||
|
autoscalingRunnerSetTestTimeout,
|
||||||
|
autoscalingRunnerSetTestInterval).Should(BeEquivalentTo("owner/repo"), "RunnerScaleSet should be created/fetched and update the AutoScalingRunnerSet's label")
|
||||||
|
|
||||||
// Check if ephemeral runner set is created
|
// Check if ephemeral runner set is created
|
||||||
Eventually(
|
Eventually(
|
||||||
func() (int, error) {
|
func() (int, error) {
|
||||||
@@ -157,23 +177,6 @@ var _ = Describe("Test AutoScalingRunnerSet controller", func() {
|
|||||||
err := k8sClient.List(ctx, runnerSetList, client.InNamespace(autoscalingRunnerSet.Namespace))
|
err := k8sClient.List(ctx, runnerSetList, client.InNamespace(autoscalingRunnerSet.Namespace))
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to list EphemeralRunnerSet")
|
Expect(err).NotTo(HaveOccurred(), "failed to list EphemeralRunnerSet")
|
||||||
Expect(len(runnerSetList.Items)).To(BeEquivalentTo(1), "Only one EphemeralRunnerSet should be created")
|
Expect(len(runnerSetList.Items)).To(BeEquivalentTo(1), "Only one EphemeralRunnerSet should be created")
|
||||||
runnerSet := runnerSetList.Items[0]
|
|
||||||
statusUpdate := runnerSet.DeepCopy()
|
|
||||||
statusUpdate.Status.CurrentReplicas = 100
|
|
||||||
err = k8sClient.Status().Patch(ctx, statusUpdate, client.MergeFrom(&runnerSet))
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to patch EphemeralRunnerSet status")
|
|
||||||
|
|
||||||
Eventually(
|
|
||||||
func() (int, error) {
|
|
||||||
updated := new(v1alpha1.AutoscalingRunnerSet)
|
|
||||||
err := k8sClient.Get(ctx, client.ObjectKey{Name: autoscalingRunnerSet.Name, Namespace: autoscalingRunnerSet.Namespace}, updated)
|
|
||||||
if err != nil {
|
|
||||||
return 0, fmt.Errorf("failed to get AutoScalingRunnerSet: %w", err)
|
|
||||||
}
|
|
||||||
return updated.Status.CurrentRunners, nil
|
|
||||||
},
|
|
||||||
autoscalingRunnerSetTestTimeout,
|
|
||||||
autoscalingRunnerSetTestInterval).Should(BeEquivalentTo(100), "AutoScalingRunnerSet status should be updated")
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -368,18 +371,18 @@ var _ = Describe("Test AutoScalingRunnerSet controller", func() {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := updated.Annotations[runnerScaleSetRunnerGroupNameKey]; !ok {
|
if _, ok := updated.Annotations[AnnotationKeyGitHubRunnerGroupName]; !ok {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return updated.Annotations[runnerScaleSetRunnerGroupNameKey], nil
|
return updated.Annotations[AnnotationKeyGitHubRunnerGroupName], nil
|
||||||
},
|
},
|
||||||
autoscalingRunnerSetTestTimeout,
|
autoscalingRunnerSetTestTimeout,
|
||||||
autoscalingRunnerSetTestInterval).Should(BeEquivalentTo("testgroup2"), "AutoScalingRunnerSet should have the new runner group in its annotation")
|
autoscalingRunnerSetTestInterval).Should(BeEquivalentTo("testgroup2"), "AutoScalingRunnerSet should have the new runner group in its annotation")
|
||||||
|
|
||||||
// delete the annotation and it should be re-added
|
// delete the annotation and it should be re-added
|
||||||
patched = autoscalingRunnerSet.DeepCopy()
|
patched = autoscalingRunnerSet.DeepCopy()
|
||||||
delete(patched.Annotations, runnerScaleSetRunnerGroupNameKey)
|
delete(patched.Annotations, AnnotationKeyGitHubRunnerGroupName)
|
||||||
err = k8sClient.Patch(ctx, patched, client.MergeFrom(autoscalingRunnerSet))
|
err = k8sClient.Patch(ctx, patched, client.MergeFrom(autoscalingRunnerSet))
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to patch AutoScalingRunnerSet")
|
Expect(err).NotTo(HaveOccurred(), "failed to patch AutoScalingRunnerSet")
|
||||||
|
|
||||||
@@ -391,16 +394,82 @@ var _ = Describe("Test AutoScalingRunnerSet controller", func() {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := updated.Annotations[runnerScaleSetRunnerGroupNameKey]; !ok {
|
if _, ok := updated.Annotations[AnnotationKeyGitHubRunnerGroupName]; !ok {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return updated.Annotations[runnerScaleSetRunnerGroupNameKey], nil
|
return updated.Annotations[AnnotationKeyGitHubRunnerGroupName], nil
|
||||||
},
|
},
|
||||||
autoscalingRunnerSetTestTimeout,
|
autoscalingRunnerSetTestTimeout,
|
||||||
autoscalingRunnerSetTestInterval).Should(BeEquivalentTo("testgroup2"), "AutoScalingRunnerSet should have the runner group in its annotation")
|
autoscalingRunnerSetTestInterval,
|
||||||
|
).Should(BeEquivalentTo("testgroup2"), "AutoScalingRunnerSet should have the runner group in its annotation")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("Should update Status on EphemeralRunnerSet status Update", func() {
|
||||||
|
ars := new(v1alpha1.AutoscalingRunnerSet)
|
||||||
|
Eventually(
|
||||||
|
func() (bool, error) {
|
||||||
|
err := k8sClient.Get(
|
||||||
|
ctx,
|
||||||
|
client.ObjectKey{
|
||||||
|
Name: autoscalingRunnerSet.Name,
|
||||||
|
Namespace: autoscalingRunnerSet.Namespace,
|
||||||
|
},
|
||||||
|
ars,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
},
|
||||||
|
autoscalingRunnerSetTestTimeout,
|
||||||
|
autoscalingRunnerSetTestInterval,
|
||||||
|
).Should(BeTrue(), "AutoscalingRunnerSet should be created")
|
||||||
|
|
||||||
|
runnerSetList := new(v1alpha1.EphemeralRunnerSetList)
|
||||||
|
Eventually(func() (int, error) {
|
||||||
|
err := k8sClient.List(ctx, runnerSetList, client.InNamespace(ars.Namespace))
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return len(runnerSetList.Items), nil
|
||||||
|
},
|
||||||
|
autoscalingRunnerSetTestTimeout,
|
||||||
|
autoscalingRunnerSetTestInterval,
|
||||||
|
).Should(BeEquivalentTo(1), "Failed to fetch runner set list")
|
||||||
|
|
||||||
|
runnerSet := runnerSetList.Items[0]
|
||||||
|
statusUpdate := runnerSet.DeepCopy()
|
||||||
|
statusUpdate.Status.CurrentReplicas = 6
|
||||||
|
statusUpdate.Status.FailedEphemeralRunners = 1
|
||||||
|
statusUpdate.Status.RunningEphemeralRunners = 2
|
||||||
|
statusUpdate.Status.PendingEphemeralRunners = 3
|
||||||
|
|
||||||
|
desiredStatus := v1alpha1.AutoscalingRunnerSetStatus{
|
||||||
|
CurrentRunners: statusUpdate.Status.CurrentReplicas,
|
||||||
|
State: "",
|
||||||
|
PendingEphemeralRunners: statusUpdate.Status.PendingEphemeralRunners,
|
||||||
|
RunningEphemeralRunners: statusUpdate.Status.RunningEphemeralRunners,
|
||||||
|
FailedEphemeralRunners: statusUpdate.Status.FailedEphemeralRunners,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := k8sClient.Status().Patch(ctx, statusUpdate, client.MergeFrom(&runnerSet))
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "Failed to patch runner set status")
|
||||||
|
|
||||||
|
Eventually(
|
||||||
|
func() (v1alpha1.AutoscalingRunnerSetStatus, error) {
|
||||||
|
updated := new(v1alpha1.AutoscalingRunnerSet)
|
||||||
|
err := k8sClient.Get(ctx, client.ObjectKey{Name: autoscalingRunnerSet.Name, Namespace: autoscalingRunnerSet.Namespace}, updated)
|
||||||
|
if err != nil {
|
||||||
|
return v1alpha1.AutoscalingRunnerSetStatus{}, fmt.Errorf("failed to get AutoScalingRunnerSet: %w", err)
|
||||||
|
}
|
||||||
|
return updated.Status, nil
|
||||||
|
},
|
||||||
|
autoscalingRunnerSetTestTimeout,
|
||||||
|
autoscalingRunnerSetTestInterval,
|
||||||
|
).Should(BeEquivalentTo(desiredStatus), "AutoScalingRunnerSet status should be updated")
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
var _ = Describe("Test AutoScalingController updates", func() {
|
var _ = Describe("Test AutoScalingController updates", func() {
|
||||||
@@ -490,7 +559,7 @@ var _ = Describe("Test AutoScalingController updates", func() {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
if val, ok := ars.Annotations[runnerScaleSetNameKey]; ok {
|
if val, ok := ars.Annotations[runnerScaleSetNameAnnotationKey]; ok {
|
||||||
return val, nil
|
return val, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -513,7 +582,7 @@ var _ = Describe("Test AutoScalingController updates", func() {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
if val, ok := ars.Annotations[runnerScaleSetNameKey]; ok {
|
if val, ok := ars.Annotations[runnerScaleSetNameAnnotationKey]; ok {
|
||||||
return val, nil
|
return val, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ func (r *EphemeralRunnerReconciler) Reconcile(ctx context.Context, req ctrl.Requ
|
|||||||
}
|
}
|
||||||
if !done {
|
if !done {
|
||||||
log.Info("Waiting for ephemeral runner owned resources to be deleted")
|
log.Info("Waiting for ephemeral runner owned resources to be deleted")
|
||||||
return ctrl.Result{}, nil
|
return ctrl.Result{Requeue: true}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
done, err = r.cleanupContainerHooksResources(ctx, ephemeralRunner, log)
|
done, err = r.cleanupContainerHooksResources(ctx, ephemeralRunner, log)
|
||||||
@@ -643,7 +643,7 @@ func (r *EphemeralRunnerReconciler) createSecret(ctx context.Context, runner *v1
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.Info("Created ephemeral runner secret", "secretName", jitSecret.Name)
|
log.Info("Created ephemeral runner secret", "secretName", jitSecret.Name)
|
||||||
return ctrl.Result{}, nil
|
return ctrl.Result{Requeue: true}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// updateRunStatusFromPod is responsible for updating non-exiting statuses.
|
// updateRunStatusFromPod is responsible for updating non-exiting statuses.
|
||||||
@@ -792,7 +792,6 @@ func (r *EphemeralRunnerReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
|||||||
return ctrl.NewControllerManagedBy(mgr).
|
return ctrl.NewControllerManagedBy(mgr).
|
||||||
For(&v1alpha1.EphemeralRunner{}).
|
For(&v1alpha1.EphemeralRunner{}).
|
||||||
Owns(&corev1.Pod{}).
|
Owns(&corev1.Pod{}).
|
||||||
Owns(&corev1.Secret{}).
|
|
||||||
WithEventFilter(predicate.ResourceVersionChangedPredicate{}).
|
WithEventFilter(predicate.ResourceVersionChangedPredicate{}).
|
||||||
Named("ephemeral-runner-controller").
|
Named("ephemeral-runner-controller").
|
||||||
Complete(r)
|
Complete(r)
|
||||||
|
|||||||
@@ -200,11 +200,18 @@ func (r *EphemeralRunnerSetReconciler) Reconcile(ctx context.Context, req ctrl.R
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
desiredStatus := v1alpha1.EphemeralRunnerSetStatus{
|
||||||
|
CurrentReplicas: total,
|
||||||
|
PendingEphemeralRunners: len(pendingEphemeralRunners),
|
||||||
|
RunningEphemeralRunners: len(runningEphemeralRunners),
|
||||||
|
FailedEphemeralRunners: len(failedEphemeralRunners),
|
||||||
|
}
|
||||||
|
|
||||||
// Update the status if needed.
|
// Update the status if needed.
|
||||||
if ephemeralRunnerSet.Status.CurrentReplicas != total {
|
if ephemeralRunnerSet.Status != desiredStatus {
|
||||||
log.Info("Updating status with current runners count", "count", total)
|
log.Info("Updating status with current runners count", "count", total)
|
||||||
if err := patchSubResource(ctx, r.Status(), ephemeralRunnerSet, func(obj *v1alpha1.EphemeralRunnerSet) {
|
if err := patchSubResource(ctx, r.Status(), ephemeralRunnerSet, func(obj *v1alpha1.EphemeralRunnerSet) {
|
||||||
obj.Status.CurrentReplicas = total
|
obj.Status = desiredStatus
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
log.Error(err, "Failed to update status with current runners count")
|
log.Error(err, "Failed to update status with current runners count")
|
||||||
return ctrl.Result{}, err
|
return ctrl.Result{}, err
|
||||||
@@ -349,10 +356,9 @@ func (r *EphemeralRunnerSetReconciler) createProxySecret(ctx context.Context, ep
|
|||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: proxyEphemeralRunnerSetSecretName(ephemeralRunnerSet),
|
Name: proxyEphemeralRunnerSetSecretName(ephemeralRunnerSet),
|
||||||
Namespace: ephemeralRunnerSet.Namespace,
|
Namespace: ephemeralRunnerSet.Namespace,
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
// TODO: figure out autoScalingRunnerSet name and set it as a label for this secret
|
LabelKeyGitHubScaleSetName: ephemeralRunnerSet.Labels[LabelKeyGitHubScaleSetName],
|
||||||
// "auto-scaling-runner-set-namespace": ephemeralRunnerSet.Namespace,
|
LabelKeyGitHubScaleSetNamespace: ephemeralRunnerSet.Labels[LabelKeyGitHubScaleSetNamespace],
|
||||||
// "auto-scaling-runner-set-name": ephemeralRunnerSet.Name,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Data: proxySecretData,
|
Data: proxySecretData,
|
||||||
|
|||||||
@@ -559,6 +559,181 @@ var _ = Describe("Test EphemeralRunnerSet controller", func() {
|
|||||||
ephemeralRunnerSetTestTimeout,
|
ephemeralRunnerSetTestTimeout,
|
||||||
ephemeralRunnerSetTestInterval).Should(BeEquivalentTo(0), "0 EphemeralRunner should be created")
|
ephemeralRunnerSetTestInterval).Should(BeEquivalentTo(0), "0 EphemeralRunner should be created")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("Should update status on Ephemeral Runner state changes", func() {
|
||||||
|
created := new(actionsv1alpha1.EphemeralRunnerSet)
|
||||||
|
Eventually(
|
||||||
|
func() error {
|
||||||
|
return k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunnerSet.Name, Namespace: ephemeralRunnerSet.Namespace}, created)
|
||||||
|
},
|
||||||
|
ephemeralRunnerSetTestTimeout,
|
||||||
|
ephemeralRunnerSetTestInterval,
|
||||||
|
).Should(Succeed(), "EphemeralRunnerSet should be created")
|
||||||
|
|
||||||
|
// Scale up the EphemeralRunnerSet
|
||||||
|
updated := created.DeepCopy()
|
||||||
|
updated.Spec.Replicas = 3
|
||||||
|
err := k8sClient.Update(ctx, updated)
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "failed to update EphemeralRunnerSet replica count")
|
||||||
|
|
||||||
|
runnerList := new(actionsv1alpha1.EphemeralRunnerList)
|
||||||
|
Eventually(
|
||||||
|
func() (bool, error) {
|
||||||
|
err := k8sClient.List(ctx, runnerList, client.InNamespace(ephemeralRunnerSet.Namespace))
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(runnerList.Items) != 3 {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var pendingOriginal *v1alpha1.EphemeralRunner
|
||||||
|
var runningOriginal *v1alpha1.EphemeralRunner
|
||||||
|
var failedOriginal *v1alpha1.EphemeralRunner
|
||||||
|
var empty []*v1alpha1.EphemeralRunner
|
||||||
|
for _, runner := range runnerList.Items {
|
||||||
|
switch runner.Status.RunnerId {
|
||||||
|
case 101:
|
||||||
|
pendingOriginal = runner.DeepCopy()
|
||||||
|
case 102:
|
||||||
|
runningOriginal = runner.DeepCopy()
|
||||||
|
case 103:
|
||||||
|
failedOriginal = runner.DeepCopy()
|
||||||
|
default:
|
||||||
|
empty = append(empty, runner.DeepCopy())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
refetch := false
|
||||||
|
if pendingOriginal == nil { // if NO pending
|
||||||
|
refetch = true
|
||||||
|
pendingOriginal = empty[0]
|
||||||
|
empty = empty[1:]
|
||||||
|
|
||||||
|
pending := pendingOriginal.DeepCopy()
|
||||||
|
pending.Status.RunnerId = 101
|
||||||
|
pending.Status.Phase = corev1.PodPending
|
||||||
|
|
||||||
|
err = k8sClient.Status().Patch(ctx, pending, client.MergeFrom(pendingOriginal))
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if runningOriginal == nil { // if NO running
|
||||||
|
refetch = true
|
||||||
|
runningOriginal = empty[0]
|
||||||
|
empty = empty[1:]
|
||||||
|
running := runningOriginal.DeepCopy()
|
||||||
|
running.Status.RunnerId = 102
|
||||||
|
running.Status.Phase = corev1.PodRunning
|
||||||
|
|
||||||
|
err = k8sClient.Status().Patch(ctx, running, client.MergeFrom(runningOriginal))
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if failedOriginal == nil { // if NO failed
|
||||||
|
refetch = true
|
||||||
|
failedOriginal = empty[0]
|
||||||
|
|
||||||
|
failed := pendingOriginal.DeepCopy()
|
||||||
|
failed.Status.RunnerId = 103
|
||||||
|
failed.Status.Phase = corev1.PodFailed
|
||||||
|
|
||||||
|
err = k8sClient.Status().Patch(ctx, failed, client.MergeFrom(failedOriginal))
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return !refetch, nil
|
||||||
|
},
|
||||||
|
ephemeralRunnerSetTestTimeout,
|
||||||
|
ephemeralRunnerSetTestInterval,
|
||||||
|
).Should(BeTrue(), "Failed to eventually update to one pending, one running and one failed")
|
||||||
|
|
||||||
|
desiredStatus := v1alpha1.EphemeralRunnerSetStatus{
|
||||||
|
CurrentReplicas: 3,
|
||||||
|
PendingEphemeralRunners: 1,
|
||||||
|
RunningEphemeralRunners: 1,
|
||||||
|
FailedEphemeralRunners: 1,
|
||||||
|
}
|
||||||
|
Eventually(
|
||||||
|
func() (v1alpha1.EphemeralRunnerSetStatus, error) {
|
||||||
|
updated := new(v1alpha1.EphemeralRunnerSet)
|
||||||
|
err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunnerSet.Name, Namespace: ephemeralRunnerSet.Namespace}, updated)
|
||||||
|
if err != nil {
|
||||||
|
return v1alpha1.EphemeralRunnerSetStatus{}, err
|
||||||
|
}
|
||||||
|
return updated.Status, nil
|
||||||
|
},
|
||||||
|
ephemeralRunnerSetTestTimeout,
|
||||||
|
ephemeralRunnerSetTestInterval,
|
||||||
|
).Should(BeEquivalentTo(desiredStatus), "Status is not eventually updated to the desired one")
|
||||||
|
|
||||||
|
updated = new(v1alpha1.EphemeralRunnerSet)
|
||||||
|
err = k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunnerSet.Name, Namespace: ephemeralRunnerSet.Namespace}, updated)
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "Failed to fetch ephemeral runner set")
|
||||||
|
|
||||||
|
updatedOriginal := updated.DeepCopy()
|
||||||
|
updated.Spec.Replicas = 0
|
||||||
|
|
||||||
|
err = k8sClient.Patch(ctx, updated, client.MergeFrom(updatedOriginal))
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "Failed to patch ephemeral runner set with 0 replicas")
|
||||||
|
|
||||||
|
Eventually(
|
||||||
|
func() (int, error) {
|
||||||
|
runnerList = new(actionsv1alpha1.EphemeralRunnerList)
|
||||||
|
err := k8sClient.List(ctx, runnerList, client.InNamespace(ephemeralRunnerSet.Namespace))
|
||||||
|
if err != nil {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
return len(runnerList.Items), nil
|
||||||
|
},
|
||||||
|
ephemeralRunnerSetTestTimeout,
|
||||||
|
ephemeralRunnerSetTestInterval,
|
||||||
|
).Should(BeEquivalentTo(1), "Failed to eventually scale down")
|
||||||
|
|
||||||
|
desiredStatus = v1alpha1.EphemeralRunnerSetStatus{
|
||||||
|
CurrentReplicas: 1,
|
||||||
|
PendingEphemeralRunners: 0,
|
||||||
|
RunningEphemeralRunners: 0,
|
||||||
|
FailedEphemeralRunners: 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
Eventually(
|
||||||
|
func() (v1alpha1.EphemeralRunnerSetStatus, error) {
|
||||||
|
updated := new(v1alpha1.EphemeralRunnerSet)
|
||||||
|
err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunnerSet.Name, Namespace: ephemeralRunnerSet.Namespace}, updated)
|
||||||
|
if err != nil {
|
||||||
|
return v1alpha1.EphemeralRunnerSetStatus{}, err
|
||||||
|
}
|
||||||
|
return updated.Status, nil
|
||||||
|
},
|
||||||
|
ephemeralRunnerSetTestTimeout,
|
||||||
|
ephemeralRunnerSetTestInterval,
|
||||||
|
).Should(BeEquivalentTo(desiredStatus), "Status is not eventually updated to the desired one")
|
||||||
|
|
||||||
|
err = k8sClient.Delete(ctx, &runnerList.Items[0])
|
||||||
|
Expect(err).To(BeNil(), "Failed to delete failed ephemeral runner")
|
||||||
|
|
||||||
|
desiredStatus = v1alpha1.EphemeralRunnerSetStatus{} // empty
|
||||||
|
Eventually(
|
||||||
|
func() (v1alpha1.EphemeralRunnerSetStatus, error) {
|
||||||
|
updated := new(v1alpha1.EphemeralRunnerSet)
|
||||||
|
err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunnerSet.Name, Namespace: ephemeralRunnerSet.Namespace}, updated)
|
||||||
|
if err != nil {
|
||||||
|
return v1alpha1.EphemeralRunnerSetStatus{}, err
|
||||||
|
}
|
||||||
|
return updated.Status, nil
|
||||||
|
},
|
||||||
|
ephemeralRunnerSetTestTimeout,
|
||||||
|
ephemeralRunnerSetTestInterval,
|
||||||
|
).Should(BeEquivalentTo(desiredStatus), "Status is not eventually updated to the desired one")
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -821,12 +996,13 @@ var _ = Describe("Test EphemeralRunnerSet controller with proxy settings", func(
|
|||||||
err = k8sClient.Status().Patch(ctx, runner, client.MergeFrom(&runnerList.Items[0]))
|
err = k8sClient.Status().Patch(ctx, runner, client.MergeFrom(&runnerList.Items[0]))
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to update ephemeral runner status")
|
Expect(err).NotTo(HaveOccurred(), "failed to update ephemeral runner status")
|
||||||
|
|
||||||
updatedRunnerSet := new(actionsv1alpha1.EphemeralRunnerSet)
|
runnerSet := new(actionsv1alpha1.EphemeralRunnerSet)
|
||||||
err = k8sClient.Get(ctx, client.ObjectKey{Namespace: ephemeralRunnerSet.Namespace, Name: ephemeralRunnerSet.Name}, updatedRunnerSet)
|
err = k8sClient.Get(ctx, client.ObjectKey{Namespace: ephemeralRunnerSet.Namespace, Name: ephemeralRunnerSet.Name}, runnerSet)
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to get EphemeralRunnerSet")
|
Expect(err).NotTo(HaveOccurred(), "failed to get EphemeralRunnerSet")
|
||||||
|
|
||||||
|
updatedRunnerSet := runnerSet.DeepCopy()
|
||||||
updatedRunnerSet.Spec.Replicas = 0
|
updatedRunnerSet.Spec.Replicas = 0
|
||||||
err = k8sClient.Update(ctx, updatedRunnerSet)
|
err = k8sClient.Patch(ctx, updatedRunnerSet, client.MergeFrom(runnerSet))
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to update EphemeralRunnerSet")
|
Expect(err).NotTo(HaveOccurred(), "failed to update EphemeralRunnerSet")
|
||||||
|
|
||||||
Eventually(
|
Eventually(
|
||||||
@@ -965,12 +1141,13 @@ var _ = Describe("Test EphemeralRunnerSet controller with custom root CA", func(
|
|||||||
err = k8sClient.Status().Patch(ctx, runner, client.MergeFrom(&runnerList.Items[0]))
|
err = k8sClient.Status().Patch(ctx, runner, client.MergeFrom(&runnerList.Items[0]))
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to update ephemeral runner status")
|
Expect(err).NotTo(HaveOccurred(), "failed to update ephemeral runner status")
|
||||||
|
|
||||||
updatedRunnerSet := new(actionsv1alpha1.EphemeralRunnerSet)
|
currentRunnerSet := new(actionsv1alpha1.EphemeralRunnerSet)
|
||||||
err = k8sClient.Get(ctx, client.ObjectKey{Namespace: ephemeralRunnerSet.Namespace, Name: ephemeralRunnerSet.Name}, updatedRunnerSet)
|
err = k8sClient.Get(ctx, client.ObjectKey{Namespace: ephemeralRunnerSet.Namespace, Name: ephemeralRunnerSet.Name}, currentRunnerSet)
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to get EphemeralRunnerSet")
|
Expect(err).NotTo(HaveOccurred(), "failed to get EphemeralRunnerSet")
|
||||||
|
|
||||||
|
updatedRunnerSet := currentRunnerSet.DeepCopy()
|
||||||
updatedRunnerSet.Spec.Replicas = 0
|
updatedRunnerSet.Spec.Replicas = 0
|
||||||
err = k8sClient.Update(ctx, updatedRunnerSet)
|
err = k8sClient.Patch(ctx, updatedRunnerSet, client.MergeFrom(currentRunnerSet))
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to update EphemeralRunnerSet")
|
Expect(err).NotTo(HaveOccurred(), "failed to update EphemeralRunnerSet")
|
||||||
|
|
||||||
// wait for server to be called
|
// wait for server to be called
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
"github.com/actions/actions-runner-controller/apis/actions.github.com/v1alpha1"
|
"github.com/actions/actions-runner-controller/apis/actions.github.com/v1alpha1"
|
||||||
"github.com/actions/actions-runner-controller/build"
|
"github.com/actions/actions-runner-controller/build"
|
||||||
|
"github.com/actions/actions-runner-controller/github/actions"
|
||||||
"github.com/actions/actions-runner-controller/hash"
|
"github.com/actions/actions-runner-controller/hash"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
rbacv1 "k8s.io/api/rbac/v1"
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
@@ -19,12 +20,42 @@ const (
|
|||||||
jitTokenKey = "jitToken"
|
jitTokenKey = "jitToken"
|
||||||
)
|
)
|
||||||
|
|
||||||
// labels applied to resources
|
// Labels applied to resources
|
||||||
const (
|
const (
|
||||||
LabelKeyAutoScaleRunnerSetName = "auto-scaling-runner-set-name"
|
// Kubernetes labels
|
||||||
LabelKeyAutoScaleRunnerSetNamespace = "auto-scaling-runner-set-namespace"
|
LabelKeyKubernetesPartOf = "app.kubernetes.io/part-of"
|
||||||
|
LabelKeyKubernetesComponent = "app.kubernetes.io/component"
|
||||||
|
LabelKeyKubernetesVersion = "app.kubernetes.io/version"
|
||||||
|
|
||||||
|
// Github labels
|
||||||
|
LabelKeyGitHubScaleSetName = "actions.github.com/scale-set-name"
|
||||||
|
LabelKeyGitHubScaleSetNamespace = "actions.github.com/scale-set-namespace"
|
||||||
|
LabelKeyGitHubEnterprise = "actions.github.com/enterprise"
|
||||||
|
LabelKeyGitHubOrganization = "actions.github.com/organization"
|
||||||
|
LabelKeyGitHubRepository = "actions.github.com/repository"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const AnnotationKeyGitHubRunnerGroupName = "actions.github.com/runner-group-name"
|
||||||
|
|
||||||
|
// Labels applied to listener roles
|
||||||
|
const (
|
||||||
|
labelKeyListenerName = "auto-scaling-listener-name"
|
||||||
|
labelKeyListenerNamespace = "auto-scaling-listener-namespace"
|
||||||
|
)
|
||||||
|
|
||||||
|
var commonLabelKeys = [...]string{
|
||||||
|
LabelKeyKubernetesPartOf,
|
||||||
|
LabelKeyKubernetesComponent,
|
||||||
|
LabelKeyKubernetesVersion,
|
||||||
|
LabelKeyGitHubScaleSetName,
|
||||||
|
LabelKeyGitHubScaleSetNamespace,
|
||||||
|
LabelKeyGitHubEnterprise,
|
||||||
|
LabelKeyGitHubOrganization,
|
||||||
|
LabelKeyGitHubRepository,
|
||||||
|
}
|
||||||
|
|
||||||
|
const labelValueKubernetesPartOf = "gha-runner-scale-set"
|
||||||
|
|
||||||
type resourceBuilder struct{}
|
type resourceBuilder struct{}
|
||||||
|
|
||||||
func (b *resourceBuilder) newScaleSetListenerPod(autoscalingListener *v1alpha1.AutoscalingListener, serviceAccount *corev1.ServiceAccount, secret *corev1.Secret, envs ...corev1.EnvVar) *corev1.Pod {
|
func (b *resourceBuilder) newScaleSetListenerPod(autoscalingListener *v1alpha1.AutoscalingListener, serviceAccount *corev1.ServiceAccount, secret *corev1.Secret, envs ...corev1.EnvVar) *corev1.Pod {
|
||||||
@@ -129,6 +160,11 @@ func (b *resourceBuilder) newScaleSetListenerPod(autoscalingListener *v1alpha1.A
|
|||||||
RestartPolicy: corev1.RestartPolicyNever,
|
RestartPolicy: corev1.RestartPolicyNever,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
labels := make(map[string]string, len(autoscalingListener.Labels))
|
||||||
|
for key, val := range autoscalingListener.Labels {
|
||||||
|
labels[key] = val
|
||||||
|
}
|
||||||
|
|
||||||
newRunnerScaleSetListenerPod := &corev1.Pod{
|
newRunnerScaleSetListenerPod := &corev1.Pod{
|
||||||
TypeMeta: metav1.TypeMeta{
|
TypeMeta: metav1.TypeMeta{
|
||||||
Kind: "Pod",
|
Kind: "Pod",
|
||||||
@@ -137,10 +173,7 @@ func (b *resourceBuilder) newScaleSetListenerPod(autoscalingListener *v1alpha1.A
|
|||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: autoscalingListener.Name,
|
Name: autoscalingListener.Name,
|
||||||
Namespace: autoscalingListener.Namespace,
|
Namespace: autoscalingListener.Namespace,
|
||||||
Labels: map[string]string{
|
Labels: labels,
|
||||||
LabelKeyAutoScaleRunnerSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
|
||||||
LabelKeyAutoScaleRunnerSetName: autoscalingListener.Spec.AutoscalingRunnerSetName,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
Spec: podSpec,
|
Spec: podSpec,
|
||||||
}
|
}
|
||||||
@@ -149,14 +182,28 @@ func (b *resourceBuilder) newScaleSetListenerPod(autoscalingListener *v1alpha1.A
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *resourceBuilder) newEphemeralRunnerSet(autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet) (*v1alpha1.EphemeralRunnerSet, error) {
|
func (b *resourceBuilder) newEphemeralRunnerSet(autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet) (*v1alpha1.EphemeralRunnerSet, error) {
|
||||||
runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdKey])
|
runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdAnnotationKey])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
runnerSpecHash := autoscalingRunnerSet.RunnerSetSpecHash()
|
runnerSpecHash := autoscalingRunnerSet.RunnerSetSpecHash()
|
||||||
|
|
||||||
newLabels := map[string]string{}
|
newLabels := map[string]string{
|
||||||
newLabels[LabelKeyRunnerSpecHash] = runnerSpecHash
|
LabelKeyRunnerSpecHash: runnerSpecHash,
|
||||||
|
LabelKeyKubernetesPartOf: labelValueKubernetesPartOf,
|
||||||
|
LabelKeyKubernetesComponent: "runner-set",
|
||||||
|
LabelKeyKubernetesVersion: autoscalingRunnerSet.Labels[LabelKeyKubernetesVersion],
|
||||||
|
LabelKeyGitHubScaleSetName: autoscalingRunnerSet.Name,
|
||||||
|
LabelKeyGitHubScaleSetNamespace: autoscalingRunnerSet.Namespace,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := applyGitHubURLLabels(autoscalingRunnerSet.Spec.GitHubConfigUrl, newLabels); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to apply GitHub URL labels: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
newAnnotations := map[string]string{
|
||||||
|
AnnotationKeyGitHubRunnerGroupName: autoscalingRunnerSet.Annotations[AnnotationKeyGitHubRunnerGroupName],
|
||||||
|
}
|
||||||
|
|
||||||
newEphemeralRunnerSet := &v1alpha1.EphemeralRunnerSet{
|
newEphemeralRunnerSet := &v1alpha1.EphemeralRunnerSet{
|
||||||
TypeMeta: metav1.TypeMeta{},
|
TypeMeta: metav1.TypeMeta{},
|
||||||
@@ -164,6 +211,7 @@ func (b *resourceBuilder) newEphemeralRunnerSet(autoscalingRunnerSet *v1alpha1.A
|
|||||||
GenerateName: autoscalingRunnerSet.ObjectMeta.Name + "-",
|
GenerateName: autoscalingRunnerSet.ObjectMeta.Name + "-",
|
||||||
Namespace: autoscalingRunnerSet.ObjectMeta.Namespace,
|
Namespace: autoscalingRunnerSet.ObjectMeta.Namespace,
|
||||||
Labels: newLabels,
|
Labels: newLabels,
|
||||||
|
Annotations: newAnnotations,
|
||||||
},
|
},
|
||||||
Spec: v1alpha1.EphemeralRunnerSetSpec{
|
Spec: v1alpha1.EphemeralRunnerSetSpec{
|
||||||
Replicas: 0,
|
Replicas: 0,
|
||||||
@@ -187,8 +235,8 @@ func (b *resourceBuilder) newScaleSetListenerServiceAccount(autoscalingListener
|
|||||||
Name: scaleSetListenerServiceAccountName(autoscalingListener),
|
Name: scaleSetListenerServiceAccountName(autoscalingListener),
|
||||||
Namespace: autoscalingListener.Namespace,
|
Namespace: autoscalingListener.Namespace,
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
LabelKeyAutoScaleRunnerSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
LabelKeyGitHubScaleSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
||||||
LabelKeyAutoScaleRunnerSetName: autoscalingListener.Spec.AutoscalingRunnerSetName,
|
LabelKeyGitHubScaleSetName: autoscalingListener.Spec.AutoscalingRunnerSetName,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -202,11 +250,11 @@ func (b *resourceBuilder) newScaleSetListenerRole(autoscalingListener *v1alpha1.
|
|||||||
Name: scaleSetListenerRoleName(autoscalingListener),
|
Name: scaleSetListenerRoleName(autoscalingListener),
|
||||||
Namespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
Namespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
LabelKeyAutoScaleRunnerSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
LabelKeyGitHubScaleSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
||||||
LabelKeyAutoScaleRunnerSetName: autoscalingListener.Spec.AutoscalingRunnerSetName,
|
LabelKeyGitHubScaleSetName: autoscalingListener.Spec.AutoscalingRunnerSetName,
|
||||||
"auto-scaling-listener-namespace": autoscalingListener.Namespace,
|
labelKeyListenerNamespace: autoscalingListener.Namespace,
|
||||||
"auto-scaling-listener-name": autoscalingListener.Name,
|
labelKeyListenerName: autoscalingListener.Name,
|
||||||
"role-policy-rules-hash": rulesHash,
|
"role-policy-rules-hash": rulesHash,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Rules: rules,
|
Rules: rules,
|
||||||
@@ -236,12 +284,12 @@ func (b *resourceBuilder) newScaleSetListenerRoleBinding(autoscalingListener *v1
|
|||||||
Name: scaleSetListenerRoleName(autoscalingListener),
|
Name: scaleSetListenerRoleName(autoscalingListener),
|
||||||
Namespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
Namespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
LabelKeyAutoScaleRunnerSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
LabelKeyGitHubScaleSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
||||||
LabelKeyAutoScaleRunnerSetName: autoscalingListener.Spec.AutoscalingRunnerSetName,
|
LabelKeyGitHubScaleSetName: autoscalingListener.Spec.AutoscalingRunnerSetName,
|
||||||
"auto-scaling-listener-namespace": autoscalingListener.Namespace,
|
labelKeyListenerNamespace: autoscalingListener.Namespace,
|
||||||
"auto-scaling-listener-name": autoscalingListener.Name,
|
labelKeyListenerName: autoscalingListener.Name,
|
||||||
"role-binding-role-ref-hash": roleRefHash,
|
"role-binding-role-ref-hash": roleRefHash,
|
||||||
"role-binding-subject-hash": subjectHash,
|
"role-binding-subject-hash": subjectHash,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
RoleRef: roleRef,
|
RoleRef: roleRef,
|
||||||
@@ -259,9 +307,9 @@ func (b *resourceBuilder) newScaleSetListenerSecretMirror(autoscalingListener *v
|
|||||||
Name: scaleSetListenerSecretMirrorName(autoscalingListener),
|
Name: scaleSetListenerSecretMirrorName(autoscalingListener),
|
||||||
Namespace: autoscalingListener.Namespace,
|
Namespace: autoscalingListener.Namespace,
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
LabelKeyAutoScaleRunnerSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
LabelKeyGitHubScaleSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
||||||
LabelKeyAutoScaleRunnerSetName: autoscalingListener.Spec.AutoscalingRunnerSetName,
|
LabelKeyGitHubScaleSetName: autoscalingListener.Spec.AutoscalingRunnerSetName,
|
||||||
"secret-data-hash": dataHash,
|
"secret-data-hash": dataHash,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Data: secret.DeepCopy().Data,
|
Data: secret.DeepCopy().Data,
|
||||||
@@ -271,7 +319,7 @@ func (b *resourceBuilder) newScaleSetListenerSecretMirror(autoscalingListener *v
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *resourceBuilder) newAutoScalingListener(autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, ephemeralRunnerSet *v1alpha1.EphemeralRunnerSet, namespace, image string, imagePullSecrets []corev1.LocalObjectReference) (*v1alpha1.AutoscalingListener, error) {
|
func (b *resourceBuilder) newAutoScalingListener(autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, ephemeralRunnerSet *v1alpha1.EphemeralRunnerSet, namespace, image string, imagePullSecrets []corev1.LocalObjectReference) (*v1alpha1.AutoscalingListener, error) {
|
||||||
runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdKey])
|
runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdAnnotationKey])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -285,14 +333,25 @@ func (b *resourceBuilder) newAutoScalingListener(autoscalingRunnerSet *v1alpha1.
|
|||||||
effectiveMinRunners = *autoscalingRunnerSet.Spec.MinRunners
|
effectiveMinRunners = *autoscalingRunnerSet.Spec.MinRunners
|
||||||
}
|
}
|
||||||
|
|
||||||
|
githubConfig, err := actions.ParseGitHubConfigFromURL(autoscalingRunnerSet.Spec.GitHubConfigUrl)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to parse github config from url: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
autoscalingListener := &v1alpha1.AutoscalingListener{
|
autoscalingListener := &v1alpha1.AutoscalingListener{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: scaleSetListenerName(autoscalingRunnerSet),
|
Name: scaleSetListenerName(autoscalingRunnerSet),
|
||||||
Namespace: namespace,
|
Namespace: namespace,
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
LabelKeyAutoScaleRunnerSetNamespace: autoscalingRunnerSet.Namespace,
|
LabelKeyGitHubScaleSetNamespace: autoscalingRunnerSet.Namespace,
|
||||||
LabelKeyAutoScaleRunnerSetName: autoscalingRunnerSet.Name,
|
LabelKeyGitHubScaleSetName: autoscalingRunnerSet.Name,
|
||||||
LabelKeyRunnerSpecHash: autoscalingRunnerSet.ListenerSpecHash(),
|
LabelKeyKubernetesPartOf: labelValueKubernetesPartOf,
|
||||||
|
LabelKeyKubernetesComponent: "runner-scale-set-listener",
|
||||||
|
LabelKeyKubernetesVersion: autoscalingRunnerSet.Labels[LabelKeyKubernetesVersion],
|
||||||
|
LabelKeyGitHubEnterprise: githubConfig.Enterprise,
|
||||||
|
LabelKeyGitHubOrganization: githubConfig.Organization,
|
||||||
|
LabelKeyGitHubRepository: githubConfig.Repository,
|
||||||
|
LabelKeyRunnerSpecHash: autoscalingRunnerSet.ListenerSpecHash(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: v1alpha1.AutoscalingListenerSpec{
|
Spec: v1alpha1.AutoscalingListenerSpec{
|
||||||
@@ -315,11 +374,30 @@ func (b *resourceBuilder) newAutoScalingListener(autoscalingRunnerSet *v1alpha1.
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *resourceBuilder) newEphemeralRunner(ephemeralRunnerSet *v1alpha1.EphemeralRunnerSet) *v1alpha1.EphemeralRunner {
|
func (b *resourceBuilder) newEphemeralRunner(ephemeralRunnerSet *v1alpha1.EphemeralRunnerSet) *v1alpha1.EphemeralRunner {
|
||||||
|
labels := make(map[string]string)
|
||||||
|
for _, key := range commonLabelKeys {
|
||||||
|
switch key {
|
||||||
|
case LabelKeyKubernetesComponent:
|
||||||
|
labels[key] = "runner"
|
||||||
|
default:
|
||||||
|
v, ok := ephemeralRunnerSet.Labels[key]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
labels[key] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
annotations := make(map[string]string)
|
||||||
|
for key, val := range ephemeralRunnerSet.Annotations {
|
||||||
|
annotations[key] = val
|
||||||
|
}
|
||||||
return &v1alpha1.EphemeralRunner{
|
return &v1alpha1.EphemeralRunner{
|
||||||
TypeMeta: metav1.TypeMeta{},
|
TypeMeta: metav1.TypeMeta{},
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
GenerateName: ephemeralRunnerSet.Name + "-runner-",
|
GenerateName: ephemeralRunnerSet.Name + "-runner-",
|
||||||
Namespace: ephemeralRunnerSet.Namespace,
|
Namespace: ephemeralRunnerSet.Namespace,
|
||||||
|
Labels: labels,
|
||||||
|
Annotations: annotations,
|
||||||
},
|
},
|
||||||
Spec: ephemeralRunnerSet.Spec.EphemeralRunnerSpec,
|
Spec: ephemeralRunnerSet.Spec.EphemeralRunnerSpec,
|
||||||
}
|
}
|
||||||
@@ -337,6 +415,7 @@ func (b *resourceBuilder) newEphemeralRunnerPod(ctx context.Context, runner *v1a
|
|||||||
for k, v := range runner.Spec.PodTemplateSpec.Labels {
|
for k, v := range runner.Spec.PodTemplateSpec.Labels {
|
||||||
labels[k] = v
|
labels[k] = v
|
||||||
}
|
}
|
||||||
|
labels["actions-ephemeral-runner"] = string(corev1.ConditionTrue)
|
||||||
|
|
||||||
for k, v := range runner.ObjectMeta.Annotations {
|
for k, v := range runner.ObjectMeta.Annotations {
|
||||||
annotations[k] = v
|
annotations[k] = v
|
||||||
@@ -352,8 +431,6 @@ func (b *resourceBuilder) newEphemeralRunnerPod(ctx context.Context, runner *v1a
|
|||||||
runner.Status.RunnerJITConfig,
|
runner.Status.RunnerJITConfig,
|
||||||
)
|
)
|
||||||
|
|
||||||
labels["actions-ephemeral-runner"] = string(corev1.ConditionTrue)
|
|
||||||
|
|
||||||
objectMeta := metav1.ObjectMeta{
|
objectMeta := metav1.ObjectMeta{
|
||||||
Name: runner.ObjectMeta.Name,
|
Name: runner.ObjectMeta.Name,
|
||||||
Namespace: runner.ObjectMeta.Namespace,
|
Namespace: runner.ObjectMeta.Namespace,
|
||||||
@@ -469,3 +546,22 @@ func rulesForListenerRole(resourceNames []string) []rbacv1.PolicyRule {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func applyGitHubURLLabels(url string, labels map[string]string) error {
|
||||||
|
githubConfig, err := actions.ParseGitHubConfigFromURL(url)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to parse github config from url: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(githubConfig.Enterprise) > 0 {
|
||||||
|
labels[LabelKeyGitHubEnterprise] = githubConfig.Enterprise
|
||||||
|
}
|
||||||
|
if len(githubConfig.Organization) > 0 {
|
||||||
|
labels[LabelKeyGitHubOrganization] = githubConfig.Organization
|
||||||
|
}
|
||||||
|
if len(githubConfig.Repository) > 0 {
|
||||||
|
labels[LabelKeyGitHubRepository] = githubConfig.Repository
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
93
controllers/actions.github.com/resourcebuilder_test.go
Normal file
93
controllers/actions.github.com/resourcebuilder_test.go
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
package actionsgithubcom
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/actions/actions-runner-controller/apis/actions.github.com/v1alpha1"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLabelPropagation(t *testing.T) {
|
||||||
|
autoscalingRunnerSet := v1alpha1.AutoscalingRunnerSet{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "test-scale-set",
|
||||||
|
Namespace: "test-ns",
|
||||||
|
Labels: map[string]string{
|
||||||
|
LabelKeyKubernetesPartOf: labelValueKubernetesPartOf,
|
||||||
|
LabelKeyKubernetesVersion: "0.2.0",
|
||||||
|
},
|
||||||
|
Annotations: map[string]string{
|
||||||
|
runnerScaleSetIdAnnotationKey: "1",
|
||||||
|
AnnotationKeyGitHubRunnerGroupName: "test-group",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Spec: v1alpha1.AutoscalingRunnerSetSpec{
|
||||||
|
GitHubConfigUrl: "https://github.com/org/repo",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var b resourceBuilder
|
||||||
|
ephemeralRunnerSet, err := b.newEphemeralRunnerSet(&autoscalingRunnerSet)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, labelValueKubernetesPartOf, ephemeralRunnerSet.Labels[LabelKeyKubernetesPartOf])
|
||||||
|
assert.Equal(t, "runner-set", ephemeralRunnerSet.Labels[LabelKeyKubernetesComponent])
|
||||||
|
assert.Equal(t, autoscalingRunnerSet.Labels[LabelKeyKubernetesVersion], ephemeralRunnerSet.Labels[LabelKeyKubernetesVersion])
|
||||||
|
assert.NotEmpty(t, ephemeralRunnerSet.Labels[LabelKeyRunnerSpecHash])
|
||||||
|
assert.Equal(t, autoscalingRunnerSet.Name, ephemeralRunnerSet.Labels[LabelKeyGitHubScaleSetName])
|
||||||
|
assert.Equal(t, autoscalingRunnerSet.Namespace, ephemeralRunnerSet.Labels[LabelKeyGitHubScaleSetNamespace])
|
||||||
|
assert.Equal(t, "", ephemeralRunnerSet.Labels[LabelKeyGitHubEnterprise])
|
||||||
|
assert.Equal(t, "org", ephemeralRunnerSet.Labels[LabelKeyGitHubOrganization])
|
||||||
|
assert.Equal(t, "repo", ephemeralRunnerSet.Labels[LabelKeyGitHubRepository])
|
||||||
|
assert.Equal(t, autoscalingRunnerSet.Annotations[AnnotationKeyGitHubRunnerGroupName], ephemeralRunnerSet.Annotations[AnnotationKeyGitHubRunnerGroupName])
|
||||||
|
|
||||||
|
listener, err := b.newAutoScalingListener(&autoscalingRunnerSet, ephemeralRunnerSet, autoscalingRunnerSet.Namespace, "test:latest", nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, labelValueKubernetesPartOf, listener.Labels[LabelKeyKubernetesPartOf])
|
||||||
|
assert.Equal(t, "runner-scale-set-listener", listener.Labels[LabelKeyKubernetesComponent])
|
||||||
|
assert.Equal(t, autoscalingRunnerSet.Labels[LabelKeyKubernetesVersion], listener.Labels[LabelKeyKubernetesVersion])
|
||||||
|
assert.NotEmpty(t, ephemeralRunnerSet.Labels[LabelKeyRunnerSpecHash])
|
||||||
|
assert.Equal(t, autoscalingRunnerSet.Name, listener.Labels[LabelKeyGitHubScaleSetName])
|
||||||
|
assert.Equal(t, autoscalingRunnerSet.Namespace, listener.Labels[LabelKeyGitHubScaleSetNamespace])
|
||||||
|
assert.Equal(t, "", listener.Labels[LabelKeyGitHubEnterprise])
|
||||||
|
assert.Equal(t, "org", listener.Labels[LabelKeyGitHubOrganization])
|
||||||
|
assert.Equal(t, "repo", listener.Labels[LabelKeyGitHubRepository])
|
||||||
|
|
||||||
|
listenerServiceAccount := &corev1.ServiceAccount{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "test",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
listenerSecret := &corev1.Secret{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "test",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
listenerPod := b.newScaleSetListenerPod(listener, listenerServiceAccount, listenerSecret)
|
||||||
|
assert.Equal(t, listenerPod.Labels, listener.Labels)
|
||||||
|
|
||||||
|
ephemeralRunner := b.newEphemeralRunner(ephemeralRunnerSet)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
for _, key := range commonLabelKeys {
|
||||||
|
if key == LabelKeyKubernetesComponent {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
assert.Equal(t, ephemeralRunnerSet.Labels[key], ephemeralRunner.Labels[key])
|
||||||
|
}
|
||||||
|
assert.Equal(t, "runner", ephemeralRunner.Labels[LabelKeyKubernetesComponent])
|
||||||
|
assert.Equal(t, autoscalingRunnerSet.Annotations[AnnotationKeyGitHubRunnerGroupName], ephemeralRunner.Annotations[AnnotationKeyGitHubRunnerGroupName])
|
||||||
|
|
||||||
|
runnerSecret := &corev1.Secret{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "test",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
pod := b.newEphemeralRunnerPod(context.TODO(), ephemeralRunner, runnerSecret)
|
||||||
|
for key := range ephemeralRunner.Labels {
|
||||||
|
assert.Equal(t, ephemeralRunner.Labels[key], pod.Labels[key])
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -76,9 +76,12 @@ func TestNewRunnerPod(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "certs-client",
|
Name: "docker-sock",
|
||||||
VolumeSource: corev1.VolumeSource{
|
VolumeSource: corev1.VolumeSource{
|
||||||
EmptyDir: &corev1.EmptyDirVolumeSource{},
|
EmptyDir: &corev1.EmptyDirVolumeSource{
|
||||||
|
Medium: corev1.StorageMediumMemory,
|
||||||
|
SizeLimit: resource.NewScaledQuantity(1, resource.Mega),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -137,15 +140,7 @@ func TestNewRunnerPod(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "DOCKER_HOST",
|
Name: "DOCKER_HOST",
|
||||||
Value: "tcp://localhost:2376",
|
Value: "unix:///run/docker/docker.sock",
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "DOCKER_TLS_VERIFY",
|
|
||||||
Value: "1",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "DOCKER_CERT_PATH",
|
|
||||||
Value: "/certs/client",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
VolumeMounts: []corev1.VolumeMount{
|
VolumeMounts: []corev1.VolumeMount{
|
||||||
@@ -158,9 +153,8 @@ func TestNewRunnerPod(t *testing.T) {
|
|||||||
MountPath: "/runner/_work",
|
MountPath: "/runner/_work",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "certs-client",
|
Name: "docker-sock",
|
||||||
MountPath: "/certs/client",
|
MountPath: "/run/docker",
|
||||||
ReadOnly: true,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ImagePullPolicy: corev1.PullAlways,
|
ImagePullPolicy: corev1.PullAlways,
|
||||||
@@ -169,10 +163,15 @@ func TestNewRunnerPod(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: "docker",
|
Name: "docker",
|
||||||
Image: "default-docker-image",
|
Image: "default-docker-image",
|
||||||
|
Args: []string{
|
||||||
|
"dockerd",
|
||||||
|
"--host=unix:///run/docker/docker.sock",
|
||||||
|
"--group=$(DOCKER_GROUP_GID)",
|
||||||
|
},
|
||||||
Env: []corev1.EnvVar{
|
Env: []corev1.EnvVar{
|
||||||
{
|
{
|
||||||
Name: "DOCKER_TLS_CERTDIR",
|
Name: "DOCKER_GROUP_GID",
|
||||||
Value: "/certs",
|
Value: "121",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
VolumeMounts: []corev1.VolumeMount{
|
VolumeMounts: []corev1.VolumeMount{
|
||||||
@@ -181,8 +180,8 @@ func TestNewRunnerPod(t *testing.T) {
|
|||||||
MountPath: "/runner",
|
MountPath: "/runner",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "certs-client",
|
Name: "docker-sock",
|
||||||
MountPath: "/certs/client",
|
MountPath: "/run/docker",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "work",
|
Name: "work",
|
||||||
@@ -485,9 +484,12 @@ func TestNewRunnerPod(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "certs-client",
|
Name: "docker-sock",
|
||||||
VolumeSource: corev1.VolumeSource{
|
VolumeSource: corev1.VolumeSource{
|
||||||
EmptyDir: &corev1.EmptyDirVolumeSource{},
|
EmptyDir: &corev1.EmptyDirVolumeSource{
|
||||||
|
Medium: corev1.StorageMediumMemory,
|
||||||
|
SizeLimit: resource.NewScaledQuantity(1, resource.Mega),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -501,9 +503,8 @@ func TestNewRunnerPod(t *testing.T) {
|
|||||||
MountPath: "/runner",
|
MountPath: "/runner",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "certs-client",
|
Name: "docker-sock",
|
||||||
MountPath: "/certs/client",
|
MountPath: "/run/docker",
|
||||||
ReadOnly: true,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
@@ -527,9 +528,12 @@ func TestNewRunnerPod(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "certs-client",
|
Name: "docker-sock",
|
||||||
VolumeSource: corev1.VolumeSource{
|
VolumeSource: corev1.VolumeSource{
|
||||||
EmptyDir: &corev1.EmptyDirVolumeSource{},
|
EmptyDir: &corev1.EmptyDirVolumeSource{
|
||||||
|
Medium: corev1.StorageMediumMemory,
|
||||||
|
SizeLimit: resource.NewScaledQuantity(1, resource.Mega),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -606,9 +610,12 @@ func TestNewRunnerPodFromRunnerController(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "certs-client",
|
Name: "docker-sock",
|
||||||
VolumeSource: corev1.VolumeSource{
|
VolumeSource: corev1.VolumeSource{
|
||||||
EmptyDir: &corev1.EmptyDirVolumeSource{},
|
EmptyDir: &corev1.EmptyDirVolumeSource{
|
||||||
|
Medium: corev1.StorageMediumMemory,
|
||||||
|
SizeLimit: resource.NewScaledQuantity(1, resource.Mega),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -667,15 +674,7 @@ func TestNewRunnerPodFromRunnerController(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "DOCKER_HOST",
|
Name: "DOCKER_HOST",
|
||||||
Value: "tcp://localhost:2376",
|
Value: "unix:///run/docker/docker.sock",
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "DOCKER_TLS_VERIFY",
|
|
||||||
Value: "1",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "DOCKER_CERT_PATH",
|
|
||||||
Value: "/certs/client",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "RUNNER_NAME",
|
Name: "RUNNER_NAME",
|
||||||
@@ -696,9 +695,8 @@ func TestNewRunnerPodFromRunnerController(t *testing.T) {
|
|||||||
MountPath: "/runner/_work",
|
MountPath: "/runner/_work",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "certs-client",
|
Name: "docker-sock",
|
||||||
MountPath: "/certs/client",
|
MountPath: "/run/docker",
|
||||||
ReadOnly: true,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ImagePullPolicy: corev1.PullAlways,
|
ImagePullPolicy: corev1.PullAlways,
|
||||||
@@ -707,10 +705,15 @@ func TestNewRunnerPodFromRunnerController(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: "docker",
|
Name: "docker",
|
||||||
Image: "default-docker-image",
|
Image: "default-docker-image",
|
||||||
|
Args: []string{
|
||||||
|
"dockerd",
|
||||||
|
"--host=unix:///run/docker/docker.sock",
|
||||||
|
"--group=$(DOCKER_GROUP_GID)",
|
||||||
|
},
|
||||||
Env: []corev1.EnvVar{
|
Env: []corev1.EnvVar{
|
||||||
{
|
{
|
||||||
Name: "DOCKER_TLS_CERTDIR",
|
Name: "DOCKER_GROUP_GID",
|
||||||
Value: "/certs",
|
Value: "121",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
VolumeMounts: []corev1.VolumeMount{
|
VolumeMounts: []corev1.VolumeMount{
|
||||||
@@ -719,8 +722,8 @@ func TestNewRunnerPodFromRunnerController(t *testing.T) {
|
|||||||
MountPath: "/runner",
|
MountPath: "/runner",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "certs-client",
|
Name: "docker-sock",
|
||||||
MountPath: "/certs/client",
|
MountPath: "/run/docker",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "work",
|
Name: "work",
|
||||||
@@ -1079,6 +1082,10 @@ func TestNewRunnerPodFromRunnerController(t *testing.T) {
|
|||||||
Name: "work",
|
Name: "work",
|
||||||
MountPath: "/runner/_work",
|
MountPath: "/runner/_work",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "docker-sock",
|
||||||
|
MountPath: "/run/docker",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -1097,9 +1104,12 @@ func TestNewRunnerPodFromRunnerController(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "certs-client",
|
Name: "docker-sock",
|
||||||
VolumeSource: corev1.VolumeSource{
|
VolumeSource: corev1.VolumeSource{
|
||||||
EmptyDir: &corev1.EmptyDirVolumeSource{},
|
EmptyDir: &corev1.EmptyDirVolumeSource{
|
||||||
|
Medium: corev1.StorageMediumMemory,
|
||||||
|
SizeLimit: resource.NewScaledQuantity(1, resource.Mega),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
workGenericEphemeralVolume,
|
workGenericEphemeralVolume,
|
||||||
@@ -1110,13 +1120,12 @@ func TestNewRunnerPodFromRunnerController(t *testing.T) {
|
|||||||
MountPath: "/runner/_work",
|
MountPath: "/runner/_work",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "runner",
|
Name: "docker-sock",
|
||||||
MountPath: "/runner",
|
MountPath: "/run/docker",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "certs-client",
|
Name: "runner",
|
||||||
MountPath: "/certs/client",
|
MountPath: "/runner",
|
||||||
ReadOnly: true,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
@@ -1144,9 +1153,12 @@ func TestNewRunnerPodFromRunnerController(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "certs-client",
|
Name: "docker-sock",
|
||||||
VolumeSource: corev1.VolumeSource{
|
VolumeSource: corev1.VolumeSource{
|
||||||
EmptyDir: &corev1.EmptyDirVolumeSource{},
|
EmptyDir: &corev1.EmptyDirVolumeSource{
|
||||||
|
Medium: corev1.StorageMediumMemory,
|
||||||
|
SizeLimit: resource.NewScaledQuantity(1, resource.Mega),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
workGenericEphemeralVolume,
|
workGenericEphemeralVolume,
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import (
|
|||||||
"github.com/go-logr/logr"
|
"github.com/go-logr/logr"
|
||||||
|
|
||||||
kerrors "k8s.io/apimachinery/pkg/api/errors"
|
kerrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/client-go/tools/record"
|
"k8s.io/client-go/tools/record"
|
||||||
ctrl "sigs.k8s.io/controller-runtime"
|
ctrl "sigs.k8s.io/controller-runtime"
|
||||||
@@ -1001,6 +1002,35 @@ func newRunnerPodWithContainerMode(containerMode string, template corev1.Pod, ru
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// explicitly invoke `dockerd` to avoid automatic TLS / TCP binding
|
||||||
|
dockerdContainer.Args = append([]string{
|
||||||
|
"dockerd",
|
||||||
|
"--host=unix:///run/docker/docker.sock",
|
||||||
|
}, dockerdContainer.Args...)
|
||||||
|
|
||||||
|
// this must match a GID for the user in the runner image
|
||||||
|
// default matches GitHub Actions infra (and default runner images
|
||||||
|
// for actions-runner-controller) so typically should not need to be
|
||||||
|
// overridden
|
||||||
|
if ok, _ := envVarPresent("DOCKER_GROUP_GID", dockerdContainer.Env); !ok {
|
||||||
|
dockerdContainer.Env = append(dockerdContainer.Env,
|
||||||
|
corev1.EnvVar{
|
||||||
|
Name: "DOCKER_GROUP_GID",
|
||||||
|
Value: "121",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
dockerdContainer.Args = append(dockerdContainer.Args, "--group=$(DOCKER_GROUP_GID)")
|
||||||
|
|
||||||
|
// ideally, we could mount the socket directly at `/var/run/docker.sock`
|
||||||
|
// to use the default, but that's not practical since it won't exist
|
||||||
|
// when the container starts, so can't use subPath on the volume mount
|
||||||
|
runnerContainer.Env = append(runnerContainer.Env,
|
||||||
|
corev1.EnvVar{
|
||||||
|
Name: "DOCKER_HOST",
|
||||||
|
Value: "unix:///run/docker/docker.sock",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
if ok, _ := workVolumePresent(pod.Spec.Volumes); !ok {
|
if ok, _ := workVolumePresent(pod.Spec.Volumes); !ok {
|
||||||
pod.Spec.Volumes = append(pod.Spec.Volumes,
|
pod.Spec.Volumes = append(pod.Spec.Volumes,
|
||||||
corev1.Volume{
|
corev1.Volume{
|
||||||
@@ -1014,9 +1044,12 @@ func newRunnerPodWithContainerMode(containerMode string, template corev1.Pod, ru
|
|||||||
|
|
||||||
pod.Spec.Volumes = append(pod.Spec.Volumes,
|
pod.Spec.Volumes = append(pod.Spec.Volumes,
|
||||||
corev1.Volume{
|
corev1.Volume{
|
||||||
Name: "certs-client",
|
Name: "docker-sock",
|
||||||
VolumeSource: corev1.VolumeSource{
|
VolumeSource: corev1.VolumeSource{
|
||||||
EmptyDir: &corev1.EmptyDirVolumeSource{},
|
EmptyDir: &corev1.EmptyDirVolumeSource{
|
||||||
|
Medium: corev1.StorageMediumMemory,
|
||||||
|
SizeLimit: resource.NewScaledQuantity(1, resource.Mega),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -1030,28 +1063,14 @@ func newRunnerPodWithContainerMode(containerMode string, template corev1.Pod, ru
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
runnerContainer.VolumeMounts = append(runnerContainer.VolumeMounts,
|
if ok, _ := volumeMountPresent("docker-sock", runnerContainer.VolumeMounts); !ok {
|
||||||
corev1.VolumeMount{
|
runnerContainer.VolumeMounts = append(runnerContainer.VolumeMounts,
|
||||||
Name: "certs-client",
|
corev1.VolumeMount{
|
||||||
MountPath: "/certs/client",
|
Name: "docker-sock",
|
||||||
ReadOnly: true,
|
MountPath: "/run/docker",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
}
|
||||||
runnerContainer.Env = append(runnerContainer.Env, []corev1.EnvVar{
|
|
||||||
{
|
|
||||||
Name: "DOCKER_HOST",
|
|
||||||
Value: "tcp://localhost:2376",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "DOCKER_TLS_VERIFY",
|
|
||||||
Value: "1",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "DOCKER_CERT_PATH",
|
|
||||||
Value: "/certs/client",
|
|
||||||
},
|
|
||||||
}...)
|
|
||||||
|
|
||||||
// Determine the volume mounts assigned to the docker sidecar. In case extra mounts are included in the RunnerSpec, append them to the standard
|
// Determine the volume mounts assigned to the docker sidecar. In case extra mounts are included in the RunnerSpec, append them to the standard
|
||||||
// set of mounts. See https://github.com/actions/actions-runner-controller/issues/435 for context.
|
// set of mounts. See https://github.com/actions/actions-runner-controller/issues/435 for context.
|
||||||
@@ -1060,14 +1079,16 @@ func newRunnerPodWithContainerMode(containerMode string, template corev1.Pod, ru
|
|||||||
Name: runnerVolumeName,
|
Name: runnerVolumeName,
|
||||||
MountPath: runnerVolumeMountPath,
|
MountPath: runnerVolumeMountPath,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Name: "certs-client",
|
|
||||||
MountPath: "/certs/client",
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mountPresent, _ := workVolumeMountPresent(dockerdContainer.VolumeMounts)
|
if p, _ := volumeMountPresent("docker-sock", dockerdContainer.VolumeMounts); !p {
|
||||||
if !mountPresent {
|
dockerVolumeMounts = append(dockerVolumeMounts, corev1.VolumeMount{
|
||||||
|
Name: "docker-sock",
|
||||||
|
MountPath: "/run/docker",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if p, _ := workVolumeMountPresent(dockerdContainer.VolumeMounts); !p {
|
||||||
dockerVolumeMounts = append(dockerVolumeMounts, corev1.VolumeMount{
|
dockerVolumeMounts = append(dockerVolumeMounts, corev1.VolumeMount{
|
||||||
Name: "work",
|
Name: "work",
|
||||||
MountPath: workDir,
|
MountPath: workDir,
|
||||||
@@ -1078,11 +1099,6 @@ func newRunnerPodWithContainerMode(containerMode string, template corev1.Pod, ru
|
|||||||
dockerdContainer.Image = defaultDockerImage
|
dockerdContainer.Image = defaultDockerImage
|
||||||
}
|
}
|
||||||
|
|
||||||
dockerdContainer.Env = append(dockerdContainer.Env, corev1.EnvVar{
|
|
||||||
Name: "DOCKER_TLS_CERTDIR",
|
|
||||||
Value: "/certs",
|
|
||||||
})
|
|
||||||
|
|
||||||
if dockerdContainer.SecurityContext == nil {
|
if dockerdContainer.SecurityContext == nil {
|
||||||
dockerdContainer.SecurityContext = &corev1.SecurityContext{
|
dockerdContainer.SecurityContext = &corev1.SecurityContext{
|
||||||
Privileged: &privileged,
|
Privileged: &privileged,
|
||||||
@@ -1273,6 +1289,15 @@ func removeFinalizer(finalizers []string, finalizerName string) ([]string, bool)
|
|||||||
return result, removed
|
return result, removed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func envVarPresent(name string, items []corev1.EnvVar) (bool, int) {
|
||||||
|
for index, item := range items {
|
||||||
|
if item.Name == name {
|
||||||
|
return true, index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, -1
|
||||||
|
}
|
||||||
|
|
||||||
func workVolumePresent(items []corev1.Volume) (bool, int) {
|
func workVolumePresent(items []corev1.Volume) (bool, int) {
|
||||||
for index, item := range items {
|
for index, item := range items {
|
||||||
if item.Name == "work" {
|
if item.Name == "work" {
|
||||||
@@ -1283,12 +1308,16 @@ func workVolumePresent(items []corev1.Volume) (bool, int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func workVolumeMountPresent(items []corev1.VolumeMount) (bool, int) {
|
func workVolumeMountPresent(items []corev1.VolumeMount) (bool, int) {
|
||||||
|
return volumeMountPresent("work", items)
|
||||||
|
}
|
||||||
|
|
||||||
|
func volumeMountPresent(name string, items []corev1.VolumeMount) (bool, int) {
|
||||||
for index, item := range items {
|
for index, item := range items {
|
||||||
if item.Name == "work" {
|
if item.Name == name {
|
||||||
return true, index
|
return true, index
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false, 0
|
return false, -1
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyWorkVolumeClaimTemplateToPod(pod *corev1.Pod, workVolumeClaimTemplate *v1alpha1.WorkVolumeClaimTemplate, workDir string) error {
|
func applyWorkVolumeClaimTemplateToPod(pod *corev1.Pod, workVolumeClaimTemplate *v1alpha1.WorkVolumeClaimTemplate, workDir string) error {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
# ADR 0001: Produce the runner image for the scaleset client
|
# ADR 2022-10-17: Produce the runner image for the scaleset client
|
||||||
|
|
||||||
**Date**: 2022-10-17
|
**Date**: 2022-10-17
|
||||||
|
|
||||||
**Status**: Done
|
**Status**: Done
|
||||||
@@ -7,6 +8,7 @@
|
|||||||
|
|
||||||
We aim to provide an similar experience (as close as possible) between self-hosted and GitHub-hosted runners. To achieve this, we are making the following changes to align our self-hosted runner container image with the Ubuntu runners managed by GitHub.
|
We aim to provide an similar experience (as close as possible) between self-hosted and GitHub-hosted runners. To achieve this, we are making the following changes to align our self-hosted runner container image with the Ubuntu runners managed by GitHub.
|
||||||
Here are the changes:
|
Here are the changes:
|
||||||
|
|
||||||
- We created a USER `runner(1001)` and a GROUP `docker(123)`
|
- We created a USER `runner(1001)` and a GROUP `docker(123)`
|
||||||
- `sudo` has been on the image and the `runner` will be a passwordless sudoer.
|
- `sudo` has been on the image and the `runner` will be a passwordless sudoer.
|
||||||
- The runner binary was placed placed under `/home/runner/` and launched using `/home/runner/run.sh`
|
- The runner binary was placed placed under `/home/runner/` and launched using `/home/runner/run.sh`
|
||||||
@@ -18,31 +20,33 @@ The latest Dockerfile can be found at: https://github.com/actions/runner/blob/ma
|
|||||||
|
|
||||||
# Context
|
# Context
|
||||||
|
|
||||||
user can bring their own runner images, the contract we have are:
|
users can bring their own runner images, the contract we require is:
|
||||||
- It must have a runner binary under /actions-runner (/actions-runner/run.sh exists)
|
|
||||||
- The WORKDIR is set to /actions-runner
|
|
||||||
- If the user inside the container is root, the ENV RUNNER_ALLOW_RUNASROOT should be set to 1
|
|
||||||
|
|
||||||
The existing ARC runner images will not work with the new ARC mode out-of-box for the following reason:
|
- It must have a runner binary under `/actions-runner` i.e. `/actions-runner/run.sh` exists
|
||||||
|
- The `WORKDIR` is set to `/actions-runner`
|
||||||
|
- If the user inside the container is root, the environment variable `RUNNER_ALLOW_RUNASROOT` should be set to `1`
|
||||||
|
|
||||||
- The current runner image requires caller to pass runner configure info, ex: URL and Config Token
|
The existing [ARC runner images](https://github.com/orgs/actions-runner-controller/packages?tab=packages&q=actions-runner) will not work with the new ARC mode out-of-box for the following reason:
|
||||||
- The current runner image has the runner binary under /runner
|
|
||||||
|
- The current runner image requires the caller to pass runner configuration info, ex: URL and Config Token
|
||||||
|
- The current runner image has the runner binary under `/runner` which violates the contract described above
|
||||||
- The current runner image requires a special entrypoint script in order to work around some volume mount limitation for setting up DinD.
|
- The current runner image requires a special entrypoint script in order to work around some volume mount limitation for setting up DinD.
|
||||||
|
|
||||||
However, since we expose the raw runner Pod spec to our user, advanced user can modify the helm values.yaml to make everything lines up properly.
|
Since we expose the raw runner PodSpec to our end users, they can modify the helm `values.yaml` to adjust the runner container to their needs.
|
||||||
|
|
||||||
# Guiding Principles
|
# Guiding Principles
|
||||||
|
|
||||||
- Build image is separated in two stages.
|
- Build image is separated in two stages.
|
||||||
|
|
||||||
## The first stage (build)
|
## The first stage (build)
|
||||||
|
|
||||||
- Reuses the same base image, so it is faster to build.
|
- Reuses the same base image, so it is faster to build.
|
||||||
- Installs utilities needed to download assets (runner and runner-container-hooks).
|
- Installs utilities needed to download assets (`runner` and `runner-container-hooks`).
|
||||||
- Downloads the runner and stores it into `/actions-runner` directory.
|
- Downloads the runner and stores it into `/actions-runner` directory.
|
||||||
- Downloads the runner-container-hooks and stores it into `/actions-runner/k8s` directory.
|
- Downloads the runner-container-hooks and stores it into `/actions-runner/k8s` directory.
|
||||||
- You can use build arguments to control the runner version, the target platform and runner container hooks version.
|
- You can use build arguments to control the runner version, the target platform and runner container hooks version.
|
||||||
|
|
||||||
Preview:
|
Preview (the published runner image might vary):
|
||||||
|
|
||||||
```Dockerfile
|
```Dockerfile
|
||||||
FROM mcr.microsoft.com/dotnet/runtime-deps:6.0 as build
|
FROM mcr.microsoft.com/dotnet/runtime-deps:6.0 as build
|
||||||
@@ -64,6 +68,7 @@ RUN curl -f -L -o runner-container-hooks.zip https://github.com/actions/runner-c
|
|||||||
```
|
```
|
||||||
|
|
||||||
## The main image:
|
## The main image:
|
||||||
|
|
||||||
- Copies assets from the build stage to `/actions-runner`
|
- Copies assets from the build stage to `/actions-runner`
|
||||||
- Does not provide an entrypoint. The entrypoint should be set within the container definition.
|
- Does not provide an entrypoint. The entrypoint should be set within the container definition.
|
||||||
|
|
||||||
@@ -77,6 +82,7 @@ COPY --from=build /actions-runner .
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Example of pod spec with the init container copying assets
|
## Example of pod spec with the init container copying assets
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Pod
|
kind: Pod
|
||||||
@@ -84,20 +90,20 @@ metadata:
|
|||||||
name: <name>
|
name: <name>
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: runner
|
|
||||||
image: <image>
|
|
||||||
command: ["/runner/run.sh"]
|
|
||||||
volumeMounts:
|
|
||||||
- name: runner
|
- name: runner
|
||||||
mountPath: /runner
|
image: <image>
|
||||||
|
command: ["/runner/run.sh"]
|
||||||
|
volumeMounts:
|
||||||
|
- name: runner
|
||||||
|
mountPath: /runner
|
||||||
initContainers:
|
initContainers:
|
||||||
- name: setup
|
- name: setup
|
||||||
image: <image>
|
image: <image>
|
||||||
command: ["sh", "-c", "cp -r /actions-runner/* /runner/"]
|
command: ["sh", "-c", "cp -r /actions-runner/* /runner/"]
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: runner
|
- name: runner
|
||||||
mountPath: /runner
|
mountPath: /runner
|
||||||
volumes:
|
volumes:
|
||||||
- name: runner
|
- name: runner
|
||||||
emptyDir: {}
|
emptyDir: {}
|
||||||
```
|
```
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# ADR 0003: Lifetime of RunnerScaleSet on Service
|
# ADR 2022-10-27: Lifetime of RunnerScaleSet on Service
|
||||||
|
|
||||||
**Date**: 2022-10-27
|
**Date**: 2022-10-27
|
||||||
|
|
||||||
@@ -12,8 +12,9 @@ The `RunnerScaleSet` object will represent a set of homogeneous self-hosted runn
|
|||||||
|
|
||||||
A `RunnerScaleSet` client (ARC) needs to communicate with the Actions service via HTTP long-poll in a certain protocol to get a workflow job successfully landed on one of its homogeneous self-hosted runners.
|
A `RunnerScaleSet` client (ARC) needs to communicate with the Actions service via HTTP long-poll in a certain protocol to get a workflow job successfully landed on one of its homogeneous self-hosted runners.
|
||||||
|
|
||||||
In this ADR, I want to discuss the following within the context of actions-runner-controller's new scaling mode:
|
In this ADR, we discuss the following within the context of actions-runner-controller's new scaling mode:
|
||||||
- Who and how to create a RunnerScaleSet on the service?
|
|
||||||
|
- Who and how to create a RunnerScaleSet on the service?
|
||||||
- Who and how to delete a RunnerScaleSet on the service?
|
- Who and how to delete a RunnerScaleSet on the service?
|
||||||
- What will happen to all the runners and jobs when the deletion happens?
|
- What will happen to all the runners and jobs when the deletion happens?
|
||||||
|
|
||||||
@@ -30,18 +31,19 @@ In this ADR, I want to discuss the following within the context of actions-runne
|
|||||||
|
|
||||||
- When the user patch existing `AutoScalingRunnerSet`'s RunnerScaleSet related properly, ex: `runnerGroupName`, `runnerWorkDir`, the controller needs to make an HTTP PATCH call to the `_apis/runtime/runnerscalesets/2` endpoint in order to update the object on the service.
|
- When the user patch existing `AutoScalingRunnerSet`'s RunnerScaleSet related properly, ex: `runnerGroupName`, `runnerWorkDir`, the controller needs to make an HTTP PATCH call to the `_apis/runtime/runnerscalesets/2` endpoint in order to update the object on the service.
|
||||||
- We will put the deployed `AutoScalingRunnerSet` resource in an error state when the user tries to patch the resource with a different `githubConfigUrl`
|
- We will put the deployed `AutoScalingRunnerSet` resource in an error state when the user tries to patch the resource with a different `githubConfigUrl`
|
||||||
> Basically, you can't move a deployed `AutoScalingRunnerSet` across GitHub entity, repoA->repoB, repoA->OrgC, etc.
|
> Basically, you can't move a deployed `AutoScalingRunnerSet` across GitHub entity, repoA->repoB, repoA->OrgC, etc.
|
||||||
> We evaluated blocking the change before instead of erroring at runtime and that we decided not to go down this route because it forces us to re-introduce admission webhooks (require cert-manager).
|
> We evaluated blocking the change before instead of erroring at runtime and that we decided not to go down this route because it forces us to re-introduce admission webhooks (require cert-manager).
|
||||||
|
|
||||||
## RunnerScaleSet deletion
|
## RunnerScaleSet deletion
|
||||||
|
|
||||||
- `AutoScalingRunnerSet` custom resource controller will delete the `RunnerScaleSet` object in the Actions service on any `AutoScalingRunnerSet` resource deletion.
|
- `AutoScalingRunnerSet` custom resource controller will delete the `RunnerScaleSet` object in the Actions service on any `AutoScalingRunnerSet` resource deletion.
|
||||||
> `AutoScalingRunnerSet` deletion will contain several steps:
|
> `AutoScalingRunnerSet` deletion will contain several steps:
|
||||||
> - Stop the listener app so no more new jobs coming and no more scaling up/down.
|
>
|
||||||
> - Request scale down to 0
|
> - Stop the listener app so no more new jobs coming and no more scaling up/down.
|
||||||
> - Force stop all runners
|
> - Request scale down to 0
|
||||||
> - Wait for the scale down to 0
|
> - Force stop all runners
|
||||||
> - Delete the `RunnerScaleSet` object from service via REST API
|
> - Wait for the scale down to 0
|
||||||
|
> - Delete the `RunnerScaleSet` object from service via REST API
|
||||||
- The deletion is via REST API on Actions service `DELETE _apis/runtime/runnerscalesets/1`
|
- The deletion is via REST API on Actions service `DELETE _apis/runtime/runnerscalesets/1`
|
||||||
- The deletion needs to use the runner registration token (admin).
|
- The deletion needs to use the runner registration token (admin).
|
||||||
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
# ADR 0004: Technical detail about actions-runner-controller repository transfer
|
# ADR 2022-11-04: Technical detail about actions-runner-controller repository transfer
|
||||||
|
|
||||||
**Date**: 2022-11-04
|
**Date**: 2022-11-04
|
||||||
|
|
||||||
**Status**: Done
|
**Status**: Done
|
||||||
@@ -8,16 +9,17 @@
|
|||||||
As part of ARC Private Beta: Repository Migration & Open Sourcing Process, we have decided to transfer the current [actions-runner-controller repository](https://github.com/actions-runner-controller/actions-runner-controller) into the [Actions org](https://github.com/actions).
|
As part of ARC Private Beta: Repository Migration & Open Sourcing Process, we have decided to transfer the current [actions-runner-controller repository](https://github.com/actions-runner-controller/actions-runner-controller) into the [Actions org](https://github.com/actions).
|
||||||
|
|
||||||
**Goals:**
|
**Goals:**
|
||||||
|
|
||||||
- A clear signal that GitHub will start taking over ARC and provide support.
|
- A clear signal that GitHub will start taking over ARC and provide support.
|
||||||
- Since we are going to deprecate the existing auto-scale mode in ARC at some point, we want to have a clear separation between the legacy mode (not supported) and the new mode (supported).
|
- Since we are going to deprecate the existing auto-scale mode in ARC at some point, we want to have a clear separation between the legacy mode (not supported) and the new mode (supported).
|
||||||
- Avoid disrupting users as much as we can, existing ARC users will not notice any difference after the repository transfer, they can keep upgrading to the newer version of ARC and keep using the legacy mode.
|
- Avoid disrupting users as much as we can, existing ARC users will not notice any difference after the repository transfer, they can keep upgrading to the newer version of ARC and keep using the legacy mode.
|
||||||
|
|
||||||
**Challenges**
|
**Challenges**
|
||||||
- The original creator's name (`summerwind`) is all over the place, including some critical parts of ARC:
|
|
||||||
- The k8s user resource API's full name is `actions.summerwind.dev/v1alpha1/RunnerDeployment`, renaming it to `actions.github.com` is a breaking change and will force the user to rebuild their entire k8s cluster.
|
|
||||||
- All docker images around ARC (controller + default runner) is published to [dockerhub/summerwind](https://hub.docker.com/u/summerwind)
|
|
||||||
- The helm chart for ARC is currently hosted on [GitHub pages](https://actions-runner-controller.github.io/actions-runner-controller) for https://github.com/actions-runner-controller/actions-runner-controller, moving the repository means we will break users who install ARC via the helm chart
|
|
||||||
|
|
||||||
|
- The original creator's name (`summerwind`) is all over the place, including some critical parts of ARC:
|
||||||
|
- The k8s user resource API's full name is `actions.summerwind.dev/v1alpha1/RunnerDeployment`, renaming it to `actions.github.com` is a breaking change and will force the user to rebuild their entire k8s cluster.
|
||||||
|
- All docker images around ARC (controller + default runner) is published to [dockerhub/summerwind](https://hub.docker.com/u/summerwind)
|
||||||
|
- The helm chart for ARC is currently hosted on [GitHub pages](https://actions-runner-controller.github.io/actions-runner-controller) for https://github.com/actions-runner-controller/actions-runner-controller, moving the repository means we will break users who install ARC via the helm chart
|
||||||
|
|
||||||
# Decisions
|
# Decisions
|
||||||
|
|
||||||
@@ -27,8 +29,9 @@ As part of ARC Private Beta: Repository Migration & Open Sourcing Process, we ha
|
|||||||
- For any new resource API we are going to add, those will be named properly under GitHub, ex: `actions.github.com/v1alpha1/AutoScalingRunnerSet`
|
- For any new resource API we are going to add, those will be named properly under GitHub, ex: `actions.github.com/v1alpha1/AutoScalingRunnerSet`
|
||||||
|
|
||||||
Benefits:
|
Benefits:
|
||||||
|
|
||||||
- A clear separation from existing ARC:
|
- A clear separation from existing ARC:
|
||||||
- Easy for the support engineer to triage income tickets and figure out whether we need to support the use case from the user
|
- Easy for the support engineer to triage income tickets and figure out whether we need to support the use case from the user
|
||||||
- We won't break existing users when they upgrade to a newer version of ARC after the repository transfer
|
- We won't break existing users when they upgrade to a newer version of ARC after the repository transfer
|
||||||
|
|
||||||
Based on the spike done by `@nikola-jokic`, we have confidence that we can host multiple resources with different API names under the same repository, and the published ARC controller can handle both resources properly.
|
Based on the spike done by `@nikola-jokic`, we have confidence that we can host multiple resources with different API names under the same repository, and the published ARC controller can handle both resources properly.
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
# ADR 0007: Adding labels to our resources
|
# ADR 2022-12-05: Adding labels to our resources
|
||||||
|
|
||||||
**Date**: 2022-12-05
|
**Date**: 2022-12-05
|
||||||
|
|
||||||
**Status**: Done
|
**Status**: Superceded [^1]
|
||||||
|
|
||||||
## Context
|
## Context
|
||||||
|
|
||||||
@@ -20,12 +20,15 @@ Assuming standard logging that would allow us to get all ARC logs by running
|
|||||||
```bash
|
```bash
|
||||||
kubectl logs -l 'app.kubernetes.io/part-of=actions-runner-controller'
|
kubectl logs -l 'app.kubernetes.io/part-of=actions-runner-controller'
|
||||||
```
|
```
|
||||||
|
|
||||||
which would be very useful for development to begin with.
|
which would be very useful for development to begin with.
|
||||||
|
|
||||||
The proposal is to add these sets of labels to the pods ARC creates:
|
The proposal is to add these sets of labels to the pods ARC creates:
|
||||||
|
|
||||||
#### controller-manager
|
#### controller-manager
|
||||||
|
|
||||||
Labels to be set by the Helm chart:
|
Labels to be set by the Helm chart:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
@@ -35,7 +38,9 @@ metadata:
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### Listener
|
#### Listener
|
||||||
|
|
||||||
Labels to be set by controller at creation:
|
Labels to be set by controller at creation:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
@@ -43,7 +48,7 @@ metadata:
|
|||||||
app.kubernetes.io/component: runner-scale-set-listener
|
app.kubernetes.io/component: runner-scale-set-listener
|
||||||
app.kubernetes.io/version: "x.x.x"
|
app.kubernetes.io/version: "x.x.x"
|
||||||
actions.github.com/scale-set-name: scale-set-name # this corresponds to metadata.name as set for AutoscalingRunnerSet
|
actions.github.com/scale-set-name: scale-set-name # this corresponds to metadata.name as set for AutoscalingRunnerSet
|
||||||
|
|
||||||
# the following labels are to be extracted by the config URL
|
# the following labels are to be extracted by the config URL
|
||||||
actions.github.com/enterprise: enterprise
|
actions.github.com/enterprise: enterprise
|
||||||
actions.github.com/organization: organization
|
actions.github.com/organization: organization
|
||||||
@@ -51,7 +56,9 @@ metadata:
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### Runner
|
#### Runner
|
||||||
|
|
||||||
Labels to be set by controller at creation:
|
Labels to be set by controller at creation:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
@@ -78,3 +85,5 @@ Or for example if they're having problems specifically with runners:
|
|||||||
|
|
||||||
This way users don't have to understand ARC moving parts but we still have a
|
This way users don't have to understand ARC moving parts but we still have a
|
||||||
way to target them specifically if we need to.
|
way to target them specifically if we need to.
|
||||||
|
|
||||||
|
[^1]: Superseded by [ADR 2023-04-14](2023-04-14-adding-labels-k8s-resources.md)
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
# ADR 0008: Pick the right runner to scale down
|
# ADR 2022-12-27: Pick the right runner to scale down
|
||||||
|
|
||||||
**Date**: 2022-12-27
|
**Date**: 2022-12-27
|
||||||
|
|
||||||
**Status**: Done
|
**Status**: Done
|
||||||
@@ -7,35 +8,37 @@
|
|||||||
|
|
||||||
- A custom resource `EphemeralRunnerSet` manage a set of custom resource `EphemeralRunners`
|
- A custom resource `EphemeralRunnerSet` manage a set of custom resource `EphemeralRunners`
|
||||||
- The `EphemeralRunnerSet` has `Replicas` in its `Spec`, and the responsibility of the `EphemeralRunnerSet_controller` is to reconcile a given `EphemeralRunnerSet` to have
|
- The `EphemeralRunnerSet` has `Replicas` in its `Spec`, and the responsibility of the `EphemeralRunnerSet_controller` is to reconcile a given `EphemeralRunnerSet` to have
|
||||||
the same amount of `EphemeralRunners` as the `Spec.Replicas` defined.
|
the same amount of `EphemeralRunners` as the `Spec.Replicas` defined.
|
||||||
- This means the `EphemeralRunnerSet_controller` will scale up the `EphemeralRunnerSet` by creating more `EphemeralRunner` in the case of the `Spec.Replicas` is higher than
|
- This means the `EphemeralRunnerSet_controller` will scale up the `EphemeralRunnerSet` by creating more `EphemeralRunner` in the case of the `Spec.Replicas` is higher than
|
||||||
the current amount of `EphemeralRunners`.
|
the current amount of `EphemeralRunners`.
|
||||||
- This also means the `EphemeralRunnerSet_controller` will scale down the `EphemeralRunnerSet` by finding some existing `EphemeralRunner` to delete in the case of
|
- This also means the `EphemeralRunnerSet_controller` will scale down the `EphemeralRunnerSet` by finding some existing `EphemeralRunner` to delete in the case of
|
||||||
the `Spec.Replicas` is less than the current amount of `EphemeralRunners`.
|
the `Spec.Replicas` is less than the current amount of `EphemeralRunners`.
|
||||||
|
|
||||||
This ADR is about how can we find the right existing `EphemeralRunner` to delete when we need to scale down.
|
This ADR is about how can we find the right existing `EphemeralRunner` to delete when we need to scale down.
|
||||||
|
|
||||||
|
## Current approach
|
||||||
## Current approach
|
|
||||||
|
|
||||||
1. `EphemeralRunnerSet_controller` figure out how many `EphemeralRunner` it needs to delete, ex: need to scale down from 10 to 2 means we need to delete 8 `EphemeralRunner`
|
1. `EphemeralRunnerSet_controller` figure out how many `EphemeralRunner` it needs to delete, ex: need to scale down from 10 to 2 means we need to delete 8 `EphemeralRunner`
|
||||||
|
|
||||||
2. `EphemeralRunnerSet_controller` find all `EphemeralRunner` that is in the `Running` or `Pending` phase.
|
2. `EphemeralRunnerSet_controller` find all `EphemeralRunner` that is in the `Running` or `Pending` phase.
|
||||||
> `Pending` means the `EphemeralRunner` is still probably creating and a runner has not yet configured with the Actions service.
|
|
||||||
> `Running` means the `EphemeralRunner` is created and a runner has probably configured with Actions service, the runner may sit there idle,
|
> `Pending` means the `EphemeralRunner` is still probably creating and a runner has not yet configured with the Actions service.
|
||||||
> or maybe actively running a workflow job. We don't have a clear answer for it from the ARC side. (Actions service knows it for sure)
|
> `Running` means the `EphemeralRunner` is created and a runner has probably configured with Actions service, the runner may sit there idle,
|
||||||
|
> or maybe actively running a workflow job. We don't have a clear answer for it from the ARC side. (Actions service knows it for sure)
|
||||||
|
|
||||||
3. `EphemeralRunnerSet_controller` make an HTTP DELETE request to the Actions service for each `EphemeralRunner` from the previous step and ask the Actions service to delete the runner via `RunnerId`.
|
3. `EphemeralRunnerSet_controller` make an HTTP DELETE request to the Actions service for each `EphemeralRunner` from the previous step and ask the Actions service to delete the runner via `RunnerId`.
|
||||||
(The `RunnerId` is generated after the runner registered with the Actions service, and stored on the `EphemeralRunner.Status.RunnerId`)
|
(The `RunnerId` is generated after the runner registered with the Actions service, and stored on the `EphemeralRunner.Status.RunnerId`)
|
||||||
> - The HTTP DELETE request looks like the following:
|
|
||||||
> `DELETE https://pipelines.actions.githubusercontent.com/WoxlUxJHrKEzIp4Nz3YmrmLlZBonrmj9xCJ1lrzcJ9ZsD1Tnw7/_apis/distributedtask/pools/0/agents/1024`
|
|
||||||
> The Actions service will return 2 types of responses:
|
|
||||||
> 1. 204 (No Content): The runner with Id 1024 has been successfully removed from the service or the runner with Id 1024 doesn't exist.
|
|
||||||
> 2. 400 (Bad Request) with JSON body that contains an error message like `JobStillRunningException`: The service can't remove this runner at this point since it has been
|
|
||||||
> assigned to a job request, the client won't be able to remove the runner until the runner finishes its current assigned job request.
|
|
||||||
|
|
||||||
4. `EphemeralRunnerSet_controller` will ignore any deletion error from runners that are still running a job, and keep trying deletion until the amount of `204` equals the amount of
|
> - The HTTP DELETE request looks like the following:
|
||||||
`EphemeralRunner` needs to delete.
|
> `DELETE https://pipelines.actions.githubusercontent.com/WoxlUxJHrKEzIp4Nz3YmrmLlZBonrmj9xCJ1lrzcJ9ZsD1Tnw7/_apis/distributedtask/pools/0/agents/1024`
|
||||||
|
> The Actions service will return 2 types of responses:
|
||||||
|
>
|
||||||
|
> 1. 204 (No Content): The runner with Id 1024 has been successfully removed from the service or the runner with Id 1024 doesn't exist.
|
||||||
|
> 2. 400 (Bad Request) with JSON body that contains an error message like `JobStillRunningException`: The service can't remove this runner at this point since it has been
|
||||||
|
> assigned to a job request, the client won't be able to remove the runner until the runner finishes its current assigned job request.
|
||||||
|
|
||||||
|
4. `EphemeralRunnerSet_controller` will ignore any deletion error from runners that are still running a job, and keep trying deletion until the amount of `204` equals the amount of
|
||||||
|
`EphemeralRunner` needs to delete.
|
||||||
|
|
||||||
## The problem with the current approach
|
## The problem with the current approach
|
||||||
|
|
||||||
@@ -68,6 +71,7 @@ this would be a big `NO` from a security point of view since we may not trust th
|
|||||||
The nature of the k8s controller-runtime means we might reconcile the resource base on stale cache data.
|
The nature of the k8s controller-runtime means we might reconcile the resource base on stale cache data.
|
||||||
|
|
||||||
I think our goal for the solution should be:
|
I think our goal for the solution should be:
|
||||||
|
|
||||||
- Reduce wasteful HTTP requests on a scale-down as much as we can.
|
- Reduce wasteful HTTP requests on a scale-down as much as we can.
|
||||||
- We can accept that we might make 1 or 2 wasteful requests to Actions service, but we can't accept making 5/10+ of them.
|
- We can accept that we might make 1 or 2 wasteful requests to Actions service, but we can't accept making 5/10+ of them.
|
||||||
- See if we can meet feature parity with what the RunnerJobHook support with compromise any security concerns.
|
- See if we can meet feature parity with what the RunnerJobHook support with compromise any security concerns.
|
||||||
@@ -77,9 +81,11 @@ a simple thought is how about we somehow attach some info to the `EphemeralRunne
|
|||||||
|
|
||||||
How about we send this info from the service to the auto-scaling-listener via the existing HTTP long-poll
|
How about we send this info from the service to the auto-scaling-listener via the existing HTTP long-poll
|
||||||
and let the listener patch the `EphemeralRunner.Status` to indicate it's running a job?
|
and let the listener patch the `EphemeralRunner.Status` to indicate it's running a job?
|
||||||
|
|
||||||
> The listener is normally in a separate namespace with elevated permission and it's something we can trust.
|
> The listener is normally in a separate namespace with elevated permission and it's something we can trust.
|
||||||
|
|
||||||
Changes:
|
Changes:
|
||||||
|
|
||||||
- Introduce a new message type `JobStarted` (in addition to the existing `JobAvailable/JobAssigned/JobCompleted`) on the service side, the message is sent when a runner of the `RunnerScaleSet` get assigned to a job,
|
- Introduce a new message type `JobStarted` (in addition to the existing `JobAvailable/JobAssigned/JobCompleted`) on the service side, the message is sent when a runner of the `RunnerScaleSet` get assigned to a job,
|
||||||
`RequestId`, `RunnerId`, and `RunnerName` will be included in the message.
|
`RequestId`, `RunnerId`, and `RunnerName` will be included in the message.
|
||||||
- Add `RequestId (int)` to `EphemeralRunner.Status`, this will indicate which job the runner is running.
|
- Add `RequestId (int)` to `EphemeralRunner.Status`, this will indicate which job the runner is running.
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
# Automate updating runner version
|
# ADR 2023-02-02: Automate updating runner version
|
||||||
|
|
||||||
**Status**: Proposed
|
**Date**: 2023-02-02
|
||||||
|
|
||||||
|
**Status**: Done
|
||||||
|
|
||||||
## Context
|
## Context
|
||||||
|
|
||||||
@@ -16,6 +18,7 @@ version is updated (and this is currently done manually).
|
|||||||
|
|
||||||
We can have another workflow running on a cadence (hourly seems sensible) and checking for new runner
|
We can have another workflow running on a cadence (hourly seems sensible) and checking for new runner
|
||||||
releases, creating a PR updating `RUNNER_VERSION` in:
|
releases, creating a PR updating `RUNNER_VERSION` in:
|
||||||
|
|
||||||
- `.github/workflows/release-runners.yaml`
|
- `.github/workflows/release-runners.yaml`
|
||||||
- `Makefile`
|
- `Makefile`
|
||||||
- `runner/Makefile`
|
- `runner/Makefile`
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
# ADR 0007: Limit Permissions for Service Accounts in Actions-Runner-Controller
|
# ADR 2023-02-10: Limit Permissions for Service Accounts in Actions-Runner-Controller
|
||||||
|
|
||||||
**Date**: 2023-02-10
|
**Date**: 2023-02-10
|
||||||
|
|
||||||
**Status**: Pending
|
**Status**: Done
|
||||||
|
|
||||||
## Context
|
## Context
|
||||||
|
|
||||||
- `actions-runner-controller` is a Kubernetes CRD (with controller) built using https://github.com/kubernetes-sigs/controller-runtime
|
- `actions-runner-controller` is a Kubernetes CRD (with controller) built using https://github.com/kubernetes-sigs/controller-runtime
|
||||||
|
|
||||||
- [controller-runtime](https://github.com/kubernetes-sigs/controller-runtime) has a default cache based k8s API client.Reader to make query k8s API server more efficiency.
|
- [controller-runtime](https://github.com/kubernetes-sigs/controller-runtime) has a default cache based k8s API client.Reader to make query k8s API server more efficiency.
|
||||||
|
|
||||||
- The cache-based API client requires cluster scope `list` and `watch` permission for any resource the controller may query.
|
- The cache-based API client requires cluster scope `list` and `watch` permission for any resource the controller may query.
|
||||||
|
|
||||||
@@ -22,6 +23,7 @@ There are 3 service accounts involved for a working `AutoscalingRunnerSet` based
|
|||||||
This should have the lowest privilege (not any `RoleBinding` nor `ClusterRoleBinding`) by default, in the case of `containerMode=kubernetes`, it will get certain write permission with `RoleBinding` to limit the permission to a single namespace.
|
This should have the lowest privilege (not any `RoleBinding` nor `ClusterRoleBinding`) by default, in the case of `containerMode=kubernetes`, it will get certain write permission with `RoleBinding` to limit the permission to a single namespace.
|
||||||
|
|
||||||
> References:
|
> References:
|
||||||
|
>
|
||||||
> - ./charts/gha-runner-scale-set/templates/no_permission_serviceaccount.yaml
|
> - ./charts/gha-runner-scale-set/templates/no_permission_serviceaccount.yaml
|
||||||
> - ./charts/gha-runner-scale-set/templates/kube_mode_role.yaml
|
> - ./charts/gha-runner-scale-set/templates/kube_mode_role.yaml
|
||||||
> - ./charts/gha-runner-scale-set/templates/kube_mode_role_binding.yaml
|
> - ./charts/gha-runner-scale-set/templates/kube_mode_role_binding.yaml
|
||||||
@@ -52,7 +54,7 @@ The current `ClusterRole` has the following permissions:
|
|||||||
|
|
||||||
## Limit cluster role permission on Secrets
|
## Limit cluster role permission on Secrets
|
||||||
|
|
||||||
The cluster scope `List` `Secrets` permission might be a blocker for adopting `actions-runner-controller` for certain customers as they may have certain restriction in their cluster that simply doesn't allow any service account to have cluster scope `List Secrets` permission.
|
The cluster scope `List` `Secrets` permission might be a blocker for adopting `actions-runner-controller` for certain customers as they may have certain restriction in their cluster that simply doesn't allow any service account to have cluster scope `List Secrets` permission.
|
||||||
|
|
||||||
To help these customers and improve security for `actions-runner-controller` in general, we will try to limit the `ClusterRole` permission of the controller manager's service account down to the following:
|
To help these customers and improve security for `actions-runner-controller` in general, we will try to limit the `ClusterRole` permission of the controller manager's service account down to the following:
|
||||||
|
|
||||||
@@ -79,9 +81,10 @@ The `Role` and `RoleBinding` creation will happen during the `helm install demo
|
|||||||
|
|
||||||
During `helm install demo oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set-controller`, we will store the controller's service account info as labels on the controller `Deployment`.
|
During `helm install demo oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set-controller`, we will store the controller's service account info as labels on the controller `Deployment`.
|
||||||
Ex:
|
Ex:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
actions.github.com/controller-service-account-namespace: {{ .Release.Namespace }}
|
actions.github.com/controller-service-account-namespace: {{ .Release.Namespace }}
|
||||||
actions.github.com/controller-service-account-name: {{ include "gha-runner-scale-set-controller.serviceAccountName" . }}
|
actions.github.com/controller-service-account-name: {{ include "gha-runner-scale-set-controller.serviceAccountName" . }}
|
||||||
```
|
```
|
||||||
|
|
||||||
Introduce a new `Role` per `AutoScalingRunnerSet` installation and `RoleBinding` the `Role` with the controller's `ServiceAccount` in the namespace that each `AutoScalingRunnerSet` deployed with the following permission.
|
Introduce a new `Role` per `AutoScalingRunnerSet` installation and `RoleBinding` the `Role` with the controller's `ServiceAccount` in the namespace that each `AutoScalingRunnerSet` deployed with the following permission.
|
||||||
@@ -102,8 +105,9 @@ The `gha-runner-scale-set` helm chart will use this service account to properly
|
|||||||
The `gha-runner-scale-set` helm chart will also allow customers to explicitly provide the controller service account info, in case the `helm lookup` couldn't locate the right controller `Deployment`.
|
The `gha-runner-scale-set` helm chart will also allow customers to explicitly provide the controller service account info, in case the `helm lookup` couldn't locate the right controller `Deployment`.
|
||||||
|
|
||||||
New sections in `values.yaml` of `gha-runner-scale-set`:
|
New sections in `values.yaml` of `gha-runner-scale-set`:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
## Optional controller service account that needs to have required Role and RoleBinding
|
## Optional controller service account that needs to have required Role and RoleBinding
|
||||||
## to operate this gha-runner-scale-set installation.
|
## to operate this gha-runner-scale-set installation.
|
||||||
## The helm chart will try to find the controller deployment and its service account at installation time.
|
## The helm chart will try to find the controller deployment and its service account at installation time.
|
||||||
## In case the helm chart can't find the right service account, you can explicitly pass in the following value
|
## In case the helm chart can't find the right service account, you can explicitly pass in the following value
|
||||||
@@ -129,5 +133,6 @@ You will deploy the `AutoScalingRunnerSet` with something like `helm install dem
|
|||||||
In this mode, you will end up with a manager `Role` that has all Get/List/Create/Delete/Update/Patch/Watch permissions on resources we need, and a `RoleBinding` to bind the `Role` with the controller `ServiceAccount` in the watched single namespace and the controller namespace, ex: `test-namespace` and `arc-system` in the above example.
|
In this mode, you will end up with a manager `Role` that has all Get/List/Create/Delete/Update/Patch/Watch permissions on resources we need, and a `RoleBinding` to bind the `Role` with the controller `ServiceAccount` in the watched single namespace and the controller namespace, ex: `test-namespace` and `arc-system` in the above example.
|
||||||
|
|
||||||
The downside of this mode:
|
The downside of this mode:
|
||||||
|
|
||||||
- When you have multiple controllers deployed, they will still use the same version of the CRD. So you will need to make sure every controller you deployed has to be the same version as each other.
|
- When you have multiple controllers deployed, they will still use the same version of the CRD. So you will need to make sure every controller you deployed has to be the same version as each other.
|
||||||
- You can't mismatch install both `actions-runner-controller` in this mode (watchSingleNamespace) with the regular installation mode (watchAllClusterNamespaces) in your cluster.
|
- You can't mismatch install both `actions-runner-controller` in this mode (watchSingleNamespace) with the regular installation mode (watchAllClusterNamespaces) in your cluster.
|
||||||
84
docs/adrs/2023-03-17-workflow-improvements.md
Normal file
84
docs/adrs/2023-03-17-workflow-improvements.md
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
# Improve ARC workflows for autoscaling runner sets
|
||||||
|
|
||||||
|
**Date**: 2023-03-17
|
||||||
|
|
||||||
|
**Status**: Done
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
In the [actions-runner-controller](https://github.com/actions/actions-runner-controller)
|
||||||
|
repository we essentially have two projects living side by side: the "legacy"
|
||||||
|
actions-runner-controller and the new one GitHub is supporting
|
||||||
|
(gha-runner-scale-set). To hasten progress we relied on existing workflows and
|
||||||
|
added some of our own (e.g.: end-to-end tests). We now got to a point where it's
|
||||||
|
sort of confusing what does what and why, not to mention the increased running
|
||||||
|
times of some those workflows and some GHA-related flaky tests getting in the
|
||||||
|
way of legacy ARC and viceversa. The three main areas we want to cover are: Go
|
||||||
|
code, Kubernetes manifests / Helm charts and E2E tests.
|
||||||
|
|
||||||
|
## Go code
|
||||||
|
|
||||||
|
At the moment we have three workflows that validate Go code:
|
||||||
|
|
||||||
|
- [golangci-lint](https://github.com/actions/actions-runner-controller/blob/34f3878/.github/workflows/golangci-lint.yaml):
|
||||||
|
this is a collection of linters that currently runs on all PRs and push to
|
||||||
|
master
|
||||||
|
- [Validate ARC](https://github.com/actions/actions-runner-controller/blob/01e9dd3/.github/workflows/validate-arc.yaml):
|
||||||
|
this is a bit of a catch-all workflow, other than Go tests this also validates
|
||||||
|
Kubernetes manifests, runs `go generate`, `go fmt` and `go vet`
|
||||||
|
- [Run CodeQL](https://github.com/actions/actions-runner-controller/blob/a095f0b66aad5fbc8aa8d7032f3299233e4c84d2/.github/workflows/run-codeql.yaml)
|
||||||
|
|
||||||
|
### Proposal
|
||||||
|
|
||||||
|
I think having one `Go` workflow that collects everything-Go would help a ton with
|
||||||
|
reliability and understandability of what's going on. This shouldn't be limited
|
||||||
|
to the GHA-supported mode as there are changes that even if made outside the GHA
|
||||||
|
code base could affect us (such as a dependency update).
|
||||||
|
This workflow should only run on changes to `*.go` files, `go.mod` and `go.sum`.
|
||||||
|
It should have these jobs, aiming to cover all existing functionality and
|
||||||
|
eliminate some duplication:
|
||||||
|
|
||||||
|
- `test`: run all Go tests in the project. We currently use the `-short` and
|
||||||
|
`-coverprofile` flags: while `-short` is used to skip [old ARC E2E
|
||||||
|
tests](https://github.com/actions/actions-runner-controller/blob/master/test/e2e/e2e_test.go#L85-L87),
|
||||||
|
`-coverprofile` is adding to the test time without really giving us any value
|
||||||
|
in return. We should also start using `actions/setup-go@v4` to take advantage
|
||||||
|
of caching (it would speed up our tests by a lot) or enable it on `v3` if we
|
||||||
|
have a strong reason not to upgrade. We should keep ignoring our E2E tests too
|
||||||
|
as those will be run elsewhere (either use `Short` there too or ignoring the
|
||||||
|
package like we currently do). As a dependency for tests this needs to run
|
||||||
|
`make manifests` first: we should fail there and then if there is a diff.
|
||||||
|
- `fmt`: we currently run `go fmt ./...` as part of `Validate ARC` but do
|
||||||
|
nothing with the results. We should fail in case of a diff. We don't need
|
||||||
|
caching for this job.
|
||||||
|
- `lint`: this corresponds to what's currently the `golanci-lint` workflow (this
|
||||||
|
also covers `go vet` which currently happens as part of `Validate ARC too`)
|
||||||
|
- `generate`: the current behaviour for this is actually quite risky, we
|
||||||
|
generate our code in `Validate ARC` workflow and use the results to run the
|
||||||
|
tests but we don't validate that up to date generate code is checked in. This
|
||||||
|
job should run `go generate` and fail on a diff.
|
||||||
|
- `vulncheck`: **EDIT: this is covered by CodeQL** the Go team is maintaining [`govulncheck`](https://go.dev/blog/vuln), a tool to recursively
|
||||||
|
analyzing all function calls in Go code and spot vulnerabilities on the call
|
||||||
|
stack.
|
||||||
|
|
||||||
|
## Kubernetes manifests / Helm charts
|
||||||
|
|
||||||
|
We have [recently separated](https://github.com/actions/actions-runner-controller/commit/bd9f32e3540663360cf47f04acad26e6010f772e)
|
||||||
|
Helm chart validation and we validate up-to-dateness of manifests as part of `Go
|
||||||
|
/ test`.
|
||||||
|
|
||||||
|
## End to end tests
|
||||||
|
|
||||||
|
These tests are giving us really good coverage and should be one of the main
|
||||||
|
actors when it comes to trusting our releases. Two improvements that could be
|
||||||
|
done here are:
|
||||||
|
|
||||||
|
- renaming the workflow to `GHA E2E`: since renaming our resources the `gha`
|
||||||
|
prefix has been used to identify things related to the mode GitHub supports
|
||||||
|
and these jobs strictly validate the GitHub mode _only_. Having a shorter name
|
||||||
|
allows for more readability of the various scenarios (e.g. `GHA E2E /
|
||||||
|
single-namespace-setup`).
|
||||||
|
- the test currently monitors and validates the number of pods spawning during
|
||||||
|
the workflow but not the outcome of the workflow. While not necessary to look
|
||||||
|
at pods specifics, we should at least guarantee that the workflow can
|
||||||
|
successfully conclude.
|
||||||
89
docs/adrs/2023-04-14-adding-labels-k8s-resources.md
Normal file
89
docs/adrs/2023-04-14-adding-labels-k8s-resources.md
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
# ADR 2023-04-14: Adding labels to our resources
|
||||||
|
|
||||||
|
**Date**: 2023-04-14
|
||||||
|
|
||||||
|
**Status**: Done [^1]
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
Users need to provide us with logs so that we can help support and troubleshoot their issues. We need a way for our users to filter and retrieve the logs we need.
|
||||||
|
|
||||||
|
## Proposal
|
||||||
|
|
||||||
|
A good start would be a catch-all label to get all logs that are
|
||||||
|
ARC-related: one of the [recommended labels](https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/)
|
||||||
|
is `app.kubernetes.io/part-of` and we can set that for all ARC components
|
||||||
|
to be `actions-runner-controller`.
|
||||||
|
|
||||||
|
Assuming standard logging that would allow us to get all ARC logs by running
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl logs -l 'app.kubernetes.io/part-of=gha-runner-scale-set-controller'
|
||||||
|
```
|
||||||
|
|
||||||
|
which would be very useful for development to begin with.
|
||||||
|
|
||||||
|
The proposal is to add these sets of labels to the pods ARC creates:
|
||||||
|
|
||||||
|
#### controller-manager
|
||||||
|
|
||||||
|
Labels to be set by the Helm chart:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/part-of: gha-runner-scale-set-controller
|
||||||
|
app.kubernetes.io/component: controller-manager
|
||||||
|
app.kubernetes.io/version: "x.x.x"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Listener
|
||||||
|
|
||||||
|
Labels to be set by controller at creation:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/part-of: gha-runner-scale-set-controller
|
||||||
|
app.kubernetes.io/component: runner-scale-set-listener
|
||||||
|
app.kubernetes.io/version: "x.x.x"
|
||||||
|
actions.github.com/scale-set-name: scale-set-name # this corresponds to metadata.name as set for AutoscalingRunnerSet
|
||||||
|
|
||||||
|
# the following labels are to be extracted by the config URL
|
||||||
|
actions.github.com/enterprise: enterprise
|
||||||
|
actions.github.com/organization: organization
|
||||||
|
actions.github.com/repository: repository
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Runner
|
||||||
|
|
||||||
|
Labels to be set by controller at creation:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/part-of: gha-runner-scale-set-controller
|
||||||
|
app.kubernetes.io/component: runner
|
||||||
|
app.kubernetes.io/version: "x.x.x"
|
||||||
|
actions.github.com/scale-set-name: scale-set-name # this corresponds to metadata.name as set for AutoscalingRunnerSet
|
||||||
|
actions.github.com/runner-name: runner-name
|
||||||
|
actions.github.com/runner-group-name: runner-group-name
|
||||||
|
|
||||||
|
# the following labels are to be extracted by the config URL
|
||||||
|
actions.github.com/enterprise: enterprise
|
||||||
|
actions.github.com/organization: organization
|
||||||
|
actions.github.com/repository: repository
|
||||||
|
```
|
||||||
|
|
||||||
|
This would allow us to ask users:
|
||||||
|
|
||||||
|
> Can you please send us the logs coming from pods labelled 'app.kubernetes.io/part-of=gha-runner-scale-set-controller'?
|
||||||
|
|
||||||
|
Or for example if they're having problems specifically with runners:
|
||||||
|
|
||||||
|
> Can you please send us the logs coming from pods labelled 'app.kubernetes.io/component=runner'?
|
||||||
|
|
||||||
|
This way users don't have to understand ARC moving parts but we still have a
|
||||||
|
way to target them specifically if we need to.
|
||||||
|
|
||||||
|
[^1]: Supersedes [ADR 2022-12-05](2022-12-05-adding-labels-k8s-resources.md)
|
||||||
18
docs/adrs/yyyy-mm-dd-TEMPLATE.md
Normal file
18
docs/adrs/yyyy-mm-dd-TEMPLATE.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Title
|
||||||
|
|
||||||
|
<!-- ADR titles should typically be imperative sentences. -->
|
||||||
|
|
||||||
|
**Status**: (Proposed|Accepted|Rejected|Superceded|Deprecated)
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
_What is the issue or background knowledge necessary for future readers
|
||||||
|
to understand why this ADR was written?_
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
|
||||||
|
_**What** is the change being proposed? **How** will it be implemented?_
|
||||||
|
|
||||||
|
## Consequences
|
||||||
|
|
||||||
|
_What becomes easier or more difficult to do because of this change?_
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
# Autoscaling Runner Scale Sets mode
|
# Autoscaling Runner Scale Sets mode
|
||||||
|
|
||||||
**⚠️ This mode is currently only available for a limited number of organizations.**
|
|
||||||
|
|
||||||
This new autoscaling mode brings numerous enhancements (described in the following sections) that will make your experience more reliable and secure.
|
This new autoscaling mode brings numerous enhancements (described in the following sections) that will make your experience more reliable and secure.
|
||||||
|
|
||||||
## How it works
|
## How it works
|
||||||
@@ -124,6 +122,31 @@ https://user-images.githubusercontent.com/568794/212668313-8946ddc5-60c1-461f-a7
|
|||||||
arc-runners arc-runner-set-rmrgw-runner-p9p5n 1/1 Running 0 21s
|
arc-runners arc-runner-set-rmrgw-runner-p9p5n 1/1 Running 0 21s
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Upgrade to newer versions
|
||||||
|
|
||||||
|
Upgrading actions-runner-controller requires a few extra steps because CRDs will not be automatically upgraded (this is a helm limitation).
|
||||||
|
|
||||||
|
1. Uninstall the autoscaling runner set first
|
||||||
|
|
||||||
|
```bash
|
||||||
|
INSTALLATION_NAME="arc-runner-set"
|
||||||
|
NAMESPACE="arc-runners"
|
||||||
|
helm uninstall "${INSTALLATION_NAME}" --namespace "${NAMESPACE}"
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Wait for all the pods to drain
|
||||||
|
|
||||||
|
1. Pull the new helm chart, unpack it and update the CRDs. When applying this step, don't forget to replace `<PATH>` with the path of the `gha-runner-scale-set-controller` helm chart:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm pull oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set-controller \
|
||||||
|
--version 0.3.0 \
|
||||||
|
--untar && \
|
||||||
|
kubectl replace -f <PATH>/gha-runner-scale-set-controller/crds/
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Reinstall actions-runner-controller using the steps from the previous section
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
### Check the logs
|
### Check the logs
|
||||||
@@ -132,10 +155,12 @@ You can check the logs of the controller pod using the following command:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Controller logs
|
# Controller logs
|
||||||
$ kubectl logs -n "${NAMESPACE}" -l app.kubernetes.io/name=gha-runner-scale-set-controller
|
kubectl logs -n "${NAMESPACE}" -l app.kubernetes.io/name=gha-runner-scale-set-controller
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
# Runner set listener logs
|
# Runner set listener logs
|
||||||
kubectl logs -n "${NAMESPACE}" -l auto-scaling-runner-set-namespace=arc-systems -l auto-scaling-runner-set-name=arc-runner-set
|
kubectl logs -n "${NAMESPACE}" -l actions.github.com/scale-set-namespace=arc-systems -l actions.github.com/scale-set-name=arc-runner-set
|
||||||
```
|
```
|
||||||
|
|
||||||
### Naming error: `Name must have up to characters`
|
### Naming error: `Name must have up to characters`
|
||||||
@@ -156,6 +181,42 @@ Error: INSTALLATION FAILED: execution error at (gha-runner-scale-set/templates/a
|
|||||||
|
|
||||||
Verify that the secret you provided is correct and that the `githubConfigUrl` you provided is accurate.
|
Verify that the secret you provided is correct and that the `githubConfigUrl` you provided is accurate.
|
||||||
|
|
||||||
|
### Access to the path `/home/runner/_work/_tool` is denied error
|
||||||
|
|
||||||
|
You might see this error if you're using kubernetes mode with persistent volumes. This is because the runner container is running with a non-root user and is causing a permissions mismatch with the mounted volume.
|
||||||
|
|
||||||
|
To fix this, you can either:
|
||||||
|
|
||||||
|
1. Use a volume type that supports `securityContext.fsGroup` (`hostPath` volumes don't support it, `local` volumes do as well as other types). Update the `fsGroup` of your runner pod to match the GID of the runner. You can do that by updating the `gha-runner-scale-set` helm chart values to include the following:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
spec:
|
||||||
|
securityContext:
|
||||||
|
fsGroup: 123
|
||||||
|
containers:
|
||||||
|
- name: runner
|
||||||
|
image: ghcr.io/actions/actions-runner:<VERSION> # Replace <VERSION> with the version you want to use
|
||||||
|
command: ["/home/runner/run.sh"]
|
||||||
|
```
|
||||||
|
|
||||||
|
1. If updating the `securityContext` of your runner pod is not a viable solution, you can workaround the issue by using `initContainers` to change the mounted volume's ownership, as follows:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
initContainers:
|
||||||
|
- name: kube-init
|
||||||
|
image: ghcr.io/actions/actions-runner:latest
|
||||||
|
command: ["sudo", "chown", "-R", "1001:123", "/home/runner/_work"]
|
||||||
|
volumeMounts:
|
||||||
|
- name: work
|
||||||
|
mountPath: /home/runner/_work
|
||||||
|
containers:
|
||||||
|
- name: runner
|
||||||
|
image: ghcr.io/actions/actions-runner:latest
|
||||||
|
command: ["/home/runner/run.sh"]
|
||||||
|
```
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
### v0.3.0
|
### v0.3.0
|
||||||
@@ -182,56 +243,3 @@ Verify that the secret you provided is correct and that the `githubConfigUrl` yo
|
|||||||
1. Fixed a bug that was preventing runner scale from being removed from the backend when they were deleted from the cluster [#2255](https://github.com/actions/actions-runner-controller/pull/2255) [#2223](https://github.com/actions/actions-runner-controller/pull/2223)
|
1. Fixed a bug that was preventing runner scale from being removed from the backend when they were deleted from the cluster [#2255](https://github.com/actions/actions-runner-controller/pull/2255) [#2223](https://github.com/actions/actions-runner-controller/pull/2223)
|
||||||
1. Fixed bugs with the helm chart definitions preventing certain values from being set [#2222](https://github.com/actions/actions-runner-controller/pull/2222)
|
1. Fixed bugs with the helm chart definitions preventing certain values from being set [#2222](https://github.com/actions/actions-runner-controller/pull/2222)
|
||||||
1. Fixed a bug that prevented the configuration of a runner group for a runner scale set [#2216](https://github.com/actions/actions-runner-controller/pull/2216)
|
1. Fixed a bug that prevented the configuration of a runner group for a runner scale set [#2216](https://github.com/actions/actions-runner-controller/pull/2216)
|
||||||
|
|
||||||
#### Log
|
|
||||||
|
|
||||||
- [1c7b7f4](https://github.com/actions/actions-runner-controller/commit/1c7b7f4) Bump arc-2 chart version and prepare 0.2.0 release [#2313](https://github.com/actions/actions-runner-controller/pull/2313)
|
|
||||||
- [73e22a1](https://github.com/actions/actions-runner-controller/commit/73e22a1) Disable metrics serving in proxy tests [#2307](https://github.com/actions/actions-runner-controller/pull/2307)
|
|
||||||
- [9b44f00](https://github.com/actions/actions-runner-controller/commit/9b44f00) Documentation corrections [#2116](https://github.com/actions/actions-runner-controller/pull/2116)
|
|
||||||
- [6b4250c](https://github.com/actions/actions-runner-controller/commit/6b4250c) Add support for proxy [#2286](https://github.com/actions/actions-runner-controller/pull/2286)
|
|
||||||
- [ced8822](https://github.com/actions/actions-runner-controller/commit/ced8822) Resolves the erroneous webhook scale down due to check runs [#2119](https://github.com/actions/actions-runner-controller/pull/2119)
|
|
||||||
- [44c06c2](https://github.com/actions/actions-runner-controller/commit/44c06c2) fix: case-insensitive webhook label matching [#2302](https://github.com/actions/actions-runner-controller/pull/2302)
|
|
||||||
- [4103fe3](https://github.com/actions/actions-runner-controller/commit/4103fe3) Use DOCKER_IMAGE_NAME instead of NAME to avoid conflict. [#2303](https://github.com/actions/actions-runner-controller/pull/2303)
|
|
||||||
- [a44fe04](https://github.com/actions/actions-runner-controller/commit/a44fe04) Fix manager crashloopback for ARC deployments without scaleset-related controllers [#2293](https://github.com/actions/actions-runner-controller/pull/2293)
|
|
||||||
- [274d0c8](https://github.com/actions/actions-runner-controller/commit/274d0c8) Added ability to configure log level from chart values [#2252](https://github.com/actions/actions-runner-controller/pull/2252)
|
|
||||||
- [256e08e](https://github.com/actions/actions-runner-controller/commit/256e08e) Ask runner to wait for docker daemon from DinD. [#2292](https://github.com/actions/actions-runner-controller/pull/2292)
|
|
||||||
- [f677fd5](https://github.com/actions/actions-runner-controller/commit/f677fd5) doc: Fix chart name for helm commands in docs [#2287](https://github.com/actions/actions-runner-controller/pull/2287)
|
|
||||||
- [d962714](https://github.com/actions/actions-runner-controller/commit/d962714) Fix helm chart when containerMode.type=dind. [#2291](https://github.com/actions/actions-runner-controller/pull/2291)
|
|
||||||
- [3886f28](https://github.com/actions/actions-runner-controller/commit/3886f28) Add EKS test environment Terraform templates [#2290](https://github.com/actions/actions-runner-controller/pull/2290)
|
|
||||||
- [dab9004](https://github.com/actions/actions-runner-controller/commit/dab9004) Added workflow to be triggered via rest api dispatch in e2e test [#2283](https://github.com/actions/actions-runner-controller/pull/2283)
|
|
||||||
- [dd8ec1a](https://github.com/actions/actions-runner-controller/commit/dd8ec1a) Add testserver package [#2281](https://github.com/actions/actions-runner-controller/pull/2281)
|
|
||||||
- [8e52a6d](https://github.com/actions/actions-runner-controller/commit/8e52a6d) EphemeralRunner: On cleanup, if pod is pending, delete from service [#2255](https://github.com/actions/actions-runner-controller/pull/2255)
|
|
||||||
- [9990243](https://github.com/actions/actions-runner-controller/commit/9990243) Early return if finalizer does not exist to make it more readable [#2262](https://github.com/actions/actions-runner-controller/pull/2262)
|
|
||||||
- [0891981](https://github.com/actions/actions-runner-controller/commit/0891981) Port ADRs from internal repo [#2267](https://github.com/actions/actions-runner-controller/pull/2267)
|
|
||||||
- [facae69](https://github.com/actions/actions-runner-controller/commit/facae69) Remove un-required permissions for the manager-role of the new `AutoScalingRunnerSet` [#2260](https://github.com/actions/actions-runner-controller/pull/2260)
|
|
||||||
- [8f62e35](https://github.com/actions/actions-runner-controller/commit/8f62e35) Add options to multi client [#2257](https://github.com/actions/actions-runner-controller/pull/2257)
|
|
||||||
- [55951c2](https://github.com/actions/actions-runner-controller/commit/55951c2) Add new workflow to automate runner updates [#2247](https://github.com/actions/actions-runner-controller/pull/2247)
|
|
||||||
- [c4297d2](https://github.com/actions/actions-runner-controller/commit/c4297d2) Avoid deleting scale set if annotation is not parsable or if it does not exist [#2239](https://github.com/actions/actions-runner-controller/pull/2239)
|
|
||||||
- [0774f06](https://github.com/actions/actions-runner-controller/commit/0774f06) ADR: automate runner updates [#2244](https://github.com/actions/actions-runner-controller/pull/2244)
|
|
||||||
- [92ab11b](https://github.com/actions/actions-runner-controller/commit/92ab11b) Use UUID v5 for client identifiers [#2241](https://github.com/actions/actions-runner-controller/pull/2241)
|
|
||||||
- [7414dc6](https://github.com/actions/actions-runner-controller/commit/7414dc6) Add Identifier to actions.Client [#2237](https://github.com/actions/actions-runner-controller/pull/2237)
|
|
||||||
- [34efb9d](https://github.com/actions/actions-runner-controller/commit/34efb9d) Add documentation to update ARC with prometheus CRDs needed by actions metrics server [#2209](https://github.com/actions/actions-runner-controller/pull/2209)
|
|
||||||
- [fbad561](https://github.com/actions/actions-runner-controller/commit/fbad561) Allow provide pre-defined kubernetes secret when helm-install AutoScalingRunnerSet [#2234](https://github.com/actions/actions-runner-controller/pull/2234)
|
|
||||||
- [a5cef7e](https://github.com/actions/actions-runner-controller/commit/a5cef7e) Resolve CI break due to bad merge. [#2236](https://github.com/actions/actions-runner-controller/pull/2236)
|
|
||||||
- [1f4fe46](https://github.com/actions/actions-runner-controller/commit/1f4fe46) Delete RunnerScaleSet on service when AutoScalingRunnerSet is deleted. [#2223](https://github.com/actions/actions-runner-controller/pull/2223)
|
|
||||||
- [067686c](https://github.com/actions/actions-runner-controller/commit/067686c) Fix typos and markdown structure in troubleshooting guide [#2148](https://github.com/actions/actions-runner-controller/pull/2148)
|
|
||||||
- [df12e00](https://github.com/actions/actions-runner-controller/commit/df12e00) Remove network requests from actions.NewClient [#2219](https://github.com/actions/actions-runner-controller/pull/2219)
|
|
||||||
- [cc26593](https://github.com/actions/actions-runner-controller/commit/cc26593) Skip CT when list-changed=false. [#2228](https://github.com/actions/actions-runner-controller/pull/2228)
|
|
||||||
- [835eac7](https://github.com/actions/actions-runner-controller/commit/835eac7) Fix helm charts when pass values file. [#2222](https://github.com/actions/actions-runner-controller/pull/2222)
|
|
||||||
- [01e9dd3](https://github.com/actions/actions-runner-controller/commit/01e9dd3) Update Validate ARC workflow to go 1.19 [#2220](https://github.com/actions/actions-runner-controller/pull/2220)
|
|
||||||
- [8038181](https://github.com/actions/actions-runner-controller/commit/8038181) Allow update runner group for AutoScalingRunnerSet [#2216](https://github.com/actions/actions-runner-controller/pull/2216)
|
|
||||||
- [219ba5b](https://github.com/actions/actions-runner-controller/commit/219ba5b) chore(deps): bump sigs.k8s.io/controller-runtime from 0.13.1 to 0.14.1 [#2132](https://github.com/actions/actions-runner-controller/pull/2132)
|
|
||||||
- [b09e3a2](https://github.com/actions/actions-runner-controller/commit/b09e3a2) Return error for non-existing runner group. [#2215](https://github.com/actions/actions-runner-controller/pull/2215)
|
|
||||||
- [7ea60e4](https://github.com/actions/actions-runner-controller/commit/7ea60e4) Fix intermittent image push failures to GHCR [#2214](https://github.com/actions/actions-runner-controller/pull/2214)
|
|
||||||
- [c8918f5](https://github.com/actions/actions-runner-controller/commit/c8918f5) Fix URL for authenticating using a GitHub app [#2206](https://github.com/actions/actions-runner-controller/pull/2206)
|
|
||||||
- [d57d17f](https://github.com/actions/actions-runner-controller/commit/d57d17f) Add support for custom CA in actions.Client [#2199](https://github.com/actions/actions-runner-controller/pull/2199)
|
|
||||||
- [6e69c75](https://github.com/actions/actions-runner-controller/commit/6e69c75) chore(deps): bump github.com/hashicorp/go-retryablehttp from 0.7.1 to 0.7.2 [#2203](https://github.com/actions/actions-runner-controller/pull/2203)
|
|
||||||
- [882bfab](https://github.com/actions/actions-runner-controller/commit/882bfab) Renaming autoScaling to autoscaling in tests matching the convention [#2201](https://github.com/actions/actions-runner-controller/pull/2201)
|
|
||||||
- [3327f62](https://github.com/actions/actions-runner-controller/commit/3327f62) Refactor actions.Client with options to help extensibility [#2193](https://github.com/actions/actions-runner-controller/pull/2193)
|
|
||||||
- [282f2dd](https://github.com/actions/actions-runner-controller/commit/282f2dd) chore(deps): bump github.com/onsi/gomega from 1.20.2 to 1.25.0 [#2169](https://github.com/actions/actions-runner-controller/pull/2169)
|
|
||||||
- [d67f808](https://github.com/actions/actions-runner-controller/commit/d67f808) Include nikola-jokic in CODEOWNERS file [#2184](https://github.com/actions/actions-runner-controller/pull/2184)
|
|
||||||
- [4932412](https://github.com/actions/actions-runner-controller/commit/4932412) Fix L0 test to make it more reliable. [#2178](https://github.com/actions/actions-runner-controller/pull/2178)
|
|
||||||
- [6da1cde](https://github.com/actions/actions-runner-controller/commit/6da1cde) Update runner version to 2.301.1 [#2182](https://github.com/actions/actions-runner-controller/pull/2182)
|
|
||||||
- [f9bae70](https://github.com/actions/actions-runner-controller/commit/f9bae70) Add distinct namespace best practice note [#2181](https://github.com/actions/actions-runner-controller/pull/2181)
|
|
||||||
- [05a3908](https://github.com/actions/actions-runner-controller/commit/05a3908) Add arc-2 quickstart guide [#2180](https://github.com/actions/actions-runner-controller/pull/2180)
|
|
||||||
- [606ed1b](https://github.com/actions/actions-runner-controller/commit/606ed1b) Add Repository information to Runner Status [#2093](https://github.com/actions/actions-runner-controller/pull/2093)
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ const (
|
|||||||
|
|
||||||
//go:generate mockery --inpackage --name=ActionsService
|
//go:generate mockery --inpackage --name=ActionsService
|
||||||
type ActionsService interface {
|
type ActionsService interface {
|
||||||
GetRunnerScaleSet(ctx context.Context, runnerScaleSetName string) (*RunnerScaleSet, error)
|
GetRunnerScaleSet(ctx context.Context, runnerGroupId int, runnerScaleSetName string) (*RunnerScaleSet, error)
|
||||||
GetRunnerScaleSetById(ctx context.Context, runnerScaleSetId int) (*RunnerScaleSet, error)
|
GetRunnerScaleSetById(ctx context.Context, runnerScaleSetId int) (*RunnerScaleSet, error)
|
||||||
GetRunnerGroupByName(ctx context.Context, runnerGroup string) (*RunnerGroup, error)
|
GetRunnerGroupByName(ctx context.Context, runnerGroup string) (*RunnerGroup, error)
|
||||||
CreateRunnerScaleSet(ctx context.Context, runnerScaleSet *RunnerScaleSet) (*RunnerScaleSet, error)
|
CreateRunnerScaleSet(ctx context.Context, runnerScaleSet *RunnerScaleSet) (*RunnerScaleSet, error)
|
||||||
@@ -285,8 +285,8 @@ func (c *Client) NewActionsServiceRequest(ctx context.Context, method, path stri
|
|||||||
return req, nil
|
return req, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetRunnerScaleSet(ctx context.Context, runnerScaleSetName string) (*RunnerScaleSet, error) {
|
func (c *Client) GetRunnerScaleSet(ctx context.Context, runnerGroupId int, runnerScaleSetName string) (*RunnerScaleSet, error) {
|
||||||
path := fmt.Sprintf("/%s?name=%s", scaleSetEndpoint, runnerScaleSetName)
|
path := fmt.Sprintf("/%s?runnerGroupId=%d&name=%s", scaleSetEndpoint, runnerGroupId, runnerScaleSetName)
|
||||||
req, err := c.NewActionsServiceRequest(ctx, http.MethodGet, path, nil)
|
req, err := c.NewActionsServiceRequest(ctx, http.MethodGet, path, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ func TestGetRunnerScaleSet(t *testing.T) {
|
|||||||
client, err := actions.NewClient(server.configURLForOrg("my-org"), auth)
|
client, err := actions.NewClient(server.configURLForOrg("my-org"), auth)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
got, err := client.GetRunnerScaleSet(ctx, scaleSetName)
|
got, err := client.GetRunnerScaleSet(ctx, 1, scaleSetName)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, want, got)
|
assert.Equal(t, want, got)
|
||||||
})
|
})
|
||||||
@@ -50,7 +50,7 @@ func TestGetRunnerScaleSet(t *testing.T) {
|
|||||||
client, err := actions.NewClient(server.configURLForOrg("my-org"), auth)
|
client, err := actions.NewClient(server.configURLForOrg("my-org"), auth)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
_, err = client.GetRunnerScaleSet(ctx, scaleSetName)
|
_, err = client.GetRunnerScaleSet(ctx, 1, scaleSetName)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
expectedPath := "/tenant/123/_apis/runtime/runnerscalesets"
|
expectedPath := "/tenant/123/_apis/runtime/runnerscalesets"
|
||||||
@@ -67,7 +67,7 @@ func TestGetRunnerScaleSet(t *testing.T) {
|
|||||||
client, err := actions.NewClient(server.configURLForOrg("my-org"), auth)
|
client, err := actions.NewClient(server.configURLForOrg("my-org"), auth)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
_, err = client.GetRunnerScaleSet(ctx, scaleSetName)
|
_, err = client.GetRunnerScaleSet(ctx, 1, scaleSetName)
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@ func TestGetRunnerScaleSet(t *testing.T) {
|
|||||||
client, err := actions.NewClient(server.configURLForOrg("my-org"), auth)
|
client, err := actions.NewClient(server.configURLForOrg("my-org"), auth)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
_, err = client.GetRunnerScaleSet(ctx, scaleSetName)
|
_, err = client.GetRunnerScaleSet(ctx, 1, scaleSetName)
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -102,7 +102,7 @@ func TestGetRunnerScaleSet(t *testing.T) {
|
|||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
_, err = client.GetRunnerScaleSet(ctx, scaleSetName)
|
_, err = client.GetRunnerScaleSet(ctx, 1, scaleSetName)
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
expectedRetry := retryMax + 1
|
expectedRetry := retryMax + 1
|
||||||
assert.Equalf(t, actualRetry, expectedRetry, "A retry was expected after the first request but got: %v", actualRetry)
|
assert.Equalf(t, actualRetry, expectedRetry, "A retry was expected after the first request but got: %v", actualRetry)
|
||||||
@@ -118,7 +118,7 @@ func TestGetRunnerScaleSet(t *testing.T) {
|
|||||||
client, err := actions.NewClient(server.configURLForOrg("my-org"), auth)
|
client, err := actions.NewClient(server.configURLForOrg("my-org"), auth)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
got, err := client.GetRunnerScaleSet(ctx, scaleSetName)
|
got, err := client.GetRunnerScaleSet(ctx, 1, scaleSetName)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, want, got)
|
assert.Equal(t, want, got)
|
||||||
})
|
})
|
||||||
@@ -133,7 +133,7 @@ func TestGetRunnerScaleSet(t *testing.T) {
|
|||||||
client, err := actions.NewClient(server.configURLForOrg("my-org"), auth)
|
client, err := actions.NewClient(server.configURLForOrg("my-org"), auth)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
_, err = client.GetRunnerScaleSet(ctx, scaleSetName)
|
_, err = client.GetRunnerScaleSet(ctx, 1, scaleSetName)
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
assert.Equal(t, wantErr.Error(), err.Error())
|
assert.Equal(t, wantErr.Error(), err.Error())
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ func (f *FakeClient) applyDefaults() {
|
|||||||
f.getRunnerByNameResult.RunnerReference = defaultRunnerReference
|
f.getRunnerByNameResult.RunnerReference = defaultRunnerReference
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FakeClient) GetRunnerScaleSet(ctx context.Context, runnerScaleSetName string) (*actions.RunnerScaleSet, error) {
|
func (f *FakeClient) GetRunnerScaleSet(ctx context.Context, runnerGroupId int, runnerScaleSetName string) (*actions.RunnerScaleSet, error) {
|
||||||
return f.getRunnerScaleSetResult.RunnerScaleSet, f.getRunnerScaleSetResult.err
|
return f.getRunnerScaleSetResult.RunnerScaleSet, f.getRunnerScaleSetResult.err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -263,13 +263,13 @@ func (_m *MockActionsService) GetRunnerGroupByName(ctx context.Context, runnerGr
|
|||||||
return r0, r1
|
return r0, r1
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRunnerScaleSet provides a mock function with given fields: ctx, runnerScaleSetName
|
// GetRunnerScaleSet provides a mock function with given fields: ctx, runnerGroupId, runnerScaleSetName
|
||||||
func (_m *MockActionsService) GetRunnerScaleSet(ctx context.Context, runnerScaleSetName string) (*RunnerScaleSet, error) {
|
func (_m *MockActionsService) GetRunnerScaleSet(ctx context.Context, runnerGroupId int, runnerScaleSetName string) (*RunnerScaleSet, error) {
|
||||||
ret := _m.Called(ctx, runnerScaleSetName)
|
ret := _m.Called(ctx, runnerGroupId, runnerScaleSetName)
|
||||||
|
|
||||||
var r0 *RunnerScaleSet
|
var r0 *RunnerScaleSet
|
||||||
if rf, ok := ret.Get(0).(func(context.Context, string) *RunnerScaleSet); ok {
|
if rf, ok := ret.Get(0).(func(context.Context, int, string) *RunnerScaleSet); ok {
|
||||||
r0 = rf(ctx, runnerScaleSetName)
|
r0 = rf(ctx, runnerGroupId, runnerScaleSetName)
|
||||||
} else {
|
} else {
|
||||||
if ret.Get(0) != nil {
|
if ret.Get(0) != nil {
|
||||||
r0 = ret.Get(0).(*RunnerScaleSet)
|
r0 = ret.Get(0).(*RunnerScaleSet)
|
||||||
@@ -277,8 +277,8 @@ func (_m *MockActionsService) GetRunnerScaleSet(ctx context.Context, runnerScale
|
|||||||
}
|
}
|
||||||
|
|
||||||
var r1 error
|
var r1 error
|
||||||
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
if rf, ok := ret.Get(1).(func(context.Context, int, string) error); ok {
|
||||||
r1 = rf(ctx, runnerScaleSetName)
|
r1 = rf(ctx, runnerGroupId, runnerScaleSetName)
|
||||||
} else {
|
} else {
|
||||||
r1 = ret.Error(1)
|
r1 = ret.Error(1)
|
||||||
}
|
}
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -1,6 +1,6 @@
|
|||||||
module github.com/actions/actions-runner-controller
|
module github.com/actions/actions-runner-controller
|
||||||
|
|
||||||
go 1.19
|
go 1.20
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/bradleyfalzon/ghinstallation/v2 v2.1.0
|
github.com/bradleyfalzon/ghinstallation/v2 v2.1.0
|
||||||
|
|||||||
189
main.go
189
main.go
@@ -17,7 +17,6 @@ limitations under the License.
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
@@ -35,10 +34,11 @@ import (
|
|||||||
"github.com/kelseyhightower/envconfig"
|
"github.com/kelseyhightower/envconfig"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
|
||||||
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
|
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
|
||||||
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
|
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
|
||||||
ctrl "sigs.k8s.io/controller-runtime"
|
ctrl "sigs.k8s.io/controller-runtime"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/cache"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
// +kubebuilder:scaffold:imports
|
// +kubebuilder:scaffold:imports
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -47,9 +47,7 @@ const (
|
|||||||
defaultDockerImage = "docker:dind"
|
defaultDockerImage = "docker:dind"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var scheme = runtime.NewScheme()
|
||||||
scheme = runtime.NewScheme()
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
_ = clientgoscheme.AddToScheme(scheme)
|
_ = clientgoscheme.AddToScheme(scheme)
|
||||||
@@ -68,6 +66,7 @@ func (i *stringSlice) Set(value string) error {
|
|||||||
*i = append(*i, value)
|
*i = append(*i, value)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
@@ -92,6 +91,7 @@ func main() {
|
|||||||
namespace string
|
namespace string
|
||||||
logLevel string
|
logLevel string
|
||||||
logFormat string
|
logFormat string
|
||||||
|
watchSingleNamespace string
|
||||||
|
|
||||||
autoScalerImagePullSecrets stringSlice
|
autoScalerImagePullSecrets stringSlice
|
||||||
|
|
||||||
@@ -128,6 +128,7 @@ func main() {
|
|||||||
flag.DurationVar(&syncPeriod, "sync-period", 1*time.Minute, "Determines the minimum frequency at which K8s resources managed by this controller are reconciled.")
|
flag.DurationVar(&syncPeriod, "sync-period", 1*time.Minute, "Determines the minimum frequency at which K8s resources managed by this controller are reconciled.")
|
||||||
flag.Var(&commonRunnerLabels, "common-runner-labels", "Runner labels in the K1=V1,K2=V2,... format that are inherited all the runners created by the controller. See https://github.com/actions/actions-runner-controller/issues/321 for more information")
|
flag.Var(&commonRunnerLabels, "common-runner-labels", "Runner labels in the K1=V1,K2=V2,... format that are inherited all the runners created by the controller. See https://github.com/actions/actions-runner-controller/issues/321 for more information")
|
||||||
flag.StringVar(&namespace, "watch-namespace", "", "The namespace to watch for custom resources. Set to empty for letting it watch for all namespaces.")
|
flag.StringVar(&namespace, "watch-namespace", "", "The namespace to watch for custom resources. Set to empty for letting it watch for all namespaces.")
|
||||||
|
flag.StringVar(&watchSingleNamespace, "watch-single-namespace", "", "Restrict to watch for custom resources in a single namespace.")
|
||||||
flag.StringVar(&logLevel, "log-level", logging.LogLevelDebug, `The verbosity of the logging. Valid values are "debug", "info", "warn", "error". Defaults to "debug".`)
|
flag.StringVar(&logLevel, "log-level", logging.LogLevelDebug, `The verbosity of the logging. Valid values are "debug", "info", "warn", "error". Defaults to "debug".`)
|
||||||
flag.StringVar(&logFormat, "log-format", "text", `The log format. Valid options are "text" and "json". Defaults to "text"`)
|
flag.StringVar(&logFormat, "log-format", "text", `The log format. Valid options are "text" and "json". Defaults to "text"`)
|
||||||
flag.BoolVar(&autoScalingRunnerSetOnly, "auto-scaling-runner-set-only", false, "Make controller only reconcile AutoRunnerScaleSet object.")
|
flag.BoolVar(&autoScalingRunnerSetOnly, "auto-scaling-runner-set-only", false, "Make controller only reconcile AutoRunnerScaleSet object.")
|
||||||
@@ -151,36 +152,101 @@ func main() {
|
|||||||
|
|
||||||
ctrl.SetLogger(log)
|
ctrl.SetLogger(log)
|
||||||
|
|
||||||
|
managerNamespace := ""
|
||||||
|
var newCache cache.NewCacheFunc
|
||||||
|
|
||||||
if autoScalingRunnerSetOnly {
|
if autoScalingRunnerSetOnly {
|
||||||
// We don't support metrics for AutoRunnerScaleSet for now
|
// We don't support metrics for AutoRunnerScaleSet for now
|
||||||
metricsAddr = "0"
|
metricsAddr = "0"
|
||||||
|
|
||||||
|
managerNamespace = os.Getenv("CONTROLLER_MANAGER_POD_NAMESPACE")
|
||||||
|
if managerNamespace == "" {
|
||||||
|
log.Error(err, "unable to obtain manager pod namespace")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(watchSingleNamespace) > 0 {
|
||||||
|
newCache = cache.MultiNamespacedCacheBuilder([]string{managerNamespace, watchSingleNamespace})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
|
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
|
||||||
Scheme: scheme,
|
Scheme: scheme,
|
||||||
|
NewCache: newCache,
|
||||||
MetricsBindAddress: metricsAddr,
|
MetricsBindAddress: metricsAddr,
|
||||||
LeaderElection: enableLeaderElection,
|
LeaderElection: enableLeaderElection,
|
||||||
LeaderElectionID: leaderElectionId,
|
LeaderElectionID: leaderElectionId,
|
||||||
Port: port,
|
Port: port,
|
||||||
SyncPeriod: &syncPeriod,
|
SyncPeriod: &syncPeriod,
|
||||||
Namespace: namespace,
|
Namespace: namespace,
|
||||||
|
ClientDisableCacheFor: []client.Object{
|
||||||
|
&corev1.Secret{},
|
||||||
|
&corev1.ConfigMap{},
|
||||||
|
},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err, "unable to start manager")
|
log.Error(err, "unable to start manager")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
multiClient := actionssummerwindnet.NewMultiGitHubClient(
|
if autoScalingRunnerSetOnly {
|
||||||
mgr.GetClient(),
|
managerImage := os.Getenv("CONTROLLER_MANAGER_CONTAINER_IMAGE")
|
||||||
ghClient,
|
if managerImage == "" {
|
||||||
)
|
log.Error(err, "unable to obtain listener image")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
actionsMultiClient := actions.NewMultiClient(
|
actionsMultiClient := actions.NewMultiClient(
|
||||||
"actions-runner-controller/"+build.Version,
|
"actions-runner-controller/"+build.Version,
|
||||||
log.WithName("actions-clients"),
|
log.WithName("actions-clients"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if err = (&actionsgithubcom.AutoscalingRunnerSetReconciler{
|
||||||
|
Client: mgr.GetClient(),
|
||||||
|
Log: log.WithName("AutoscalingRunnerSet"),
|
||||||
|
Scheme: mgr.GetScheme(),
|
||||||
|
ControllerNamespace: managerNamespace,
|
||||||
|
DefaultRunnerScaleSetListenerImage: managerImage,
|
||||||
|
ActionsClient: actionsMultiClient,
|
||||||
|
DefaultRunnerScaleSetListenerImagePullSecrets: autoScalerImagePullSecrets,
|
||||||
|
}).SetupWithManager(mgr); err != nil {
|
||||||
|
log.Error(err, "unable to create controller", "controller", "AutoscalingRunnerSet")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = (&actionsgithubcom.EphemeralRunnerReconciler{
|
||||||
|
Client: mgr.GetClient(),
|
||||||
|
Log: log.WithName("EphemeralRunner"),
|
||||||
|
Scheme: mgr.GetScheme(),
|
||||||
|
ActionsClient: actionsMultiClient,
|
||||||
|
}).SetupWithManager(mgr); err != nil {
|
||||||
|
log.Error(err, "unable to create controller", "controller", "EphemeralRunner")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = (&actionsgithubcom.EphemeralRunnerSetReconciler{
|
||||||
|
Client: mgr.GetClient(),
|
||||||
|
Log: log.WithName("EphemeralRunnerSet"),
|
||||||
|
Scheme: mgr.GetScheme(),
|
||||||
|
ActionsClient: actionsMultiClient,
|
||||||
|
}).SetupWithManager(mgr); err != nil {
|
||||||
|
log.Error(err, "unable to create controller", "controller", "EphemeralRunnerSet")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if err = (&actionsgithubcom.AutoscalingListenerReconciler{
|
||||||
|
Client: mgr.GetClient(),
|
||||||
|
Log: log.WithName("AutoscalingListener"),
|
||||||
|
Scheme: mgr.GetScheme(),
|
||||||
|
}).SetupWithManager(mgr); err != nil {
|
||||||
|
log.Error(err, "unable to create controller", "controller", "AutoscalingListener")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
multiClient := actionssummerwindnet.NewMultiGitHubClient(
|
||||||
|
mgr.GetClient(),
|
||||||
|
ghClient,
|
||||||
|
)
|
||||||
|
|
||||||
if !autoScalingRunnerSetOnly {
|
|
||||||
runnerReconciler := &actionssummerwindnet.RunnerReconciler{
|
runnerReconciler := &actionssummerwindnet.RunnerReconciler{
|
||||||
Client: mgr.GetClient(),
|
Client: mgr.GetClient(),
|
||||||
Log: log.WithName("runner"),
|
Log: log.WithName("runner"),
|
||||||
@@ -314,94 +380,15 @@ func main() {
|
|||||||
log.Error(err, "unable to create webhook", "webhook", "RunnerReplicaSet")
|
log.Error(err, "unable to create webhook", "webhook", "RunnerReplicaSet")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
injector := &actionssummerwindnet.PodRunnerTokenInjector{
|
||||||
}
|
Client: mgr.GetClient(),
|
||||||
|
GitHubClient: multiClient,
|
||||||
// We use this environment avariable to turn on the ScaleSet related controllers.
|
Log: ctrl.Log.WithName("webhook").WithName("PodRunnerTokenInjector"),
|
||||||
// Otherwise ARC's legacy chart is unable to deploy a working ARC controller-manager pod,
|
}
|
||||||
// due to that the chart does not contain new actions.* CRDs while ARC requires those CRDs.
|
if err = injector.SetupWithManager(mgr); err != nil {
|
||||||
//
|
log.Error(err, "unable to create webhook server", "webhook", "PodRunnerTokenInjector")
|
||||||
// We might have used a more explicitly named environment variable for this,
|
os.Exit(1)
|
||||||
// e.g. "CONTROLLER_MANAGER_ENABLE_SCALE_SET" to explicitly enable the new controllers,
|
|
||||||
// or "CONTROLLER_MANAGER_DISABLE_SCALE_SET" to explicitly disable the new controllers.
|
|
||||||
// However, doing so would affect either private ARC testers or current ARC users
|
|
||||||
// who run ARC without those variabls.
|
|
||||||
mgrPodName := os.Getenv("CONTROLLER_MANAGER_POD_NAME")
|
|
||||||
if mgrPodName != "" {
|
|
||||||
mgrPodNamespace := os.Getenv("CONTROLLER_MANAGER_POD_NAMESPACE")
|
|
||||||
var mgrPod corev1.Pod
|
|
||||||
err = mgr.GetAPIReader().Get(context.Background(), types.NamespacedName{Namespace: mgrPodNamespace, Name: mgrPodName}, &mgrPod)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err, fmt.Sprintf("unable to obtain manager pod: %s (%s)", mgrPodName, mgrPodNamespace))
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
var mgrContainer *corev1.Container
|
|
||||||
for _, container := range mgrPod.Spec.Containers {
|
|
||||||
if container.Name == "manager" {
|
|
||||||
mgrContainer = &container
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if mgrContainer != nil {
|
|
||||||
log.Info("Detected manager container", "image", mgrContainer.Image)
|
|
||||||
} else {
|
|
||||||
log.Error(err, "unable to obtain manager container image")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
if err = (&actionsgithubcom.AutoscalingRunnerSetReconciler{
|
|
||||||
Client: mgr.GetClient(),
|
|
||||||
Log: log.WithName("AutoscalingRunnerSet"),
|
|
||||||
Scheme: mgr.GetScheme(),
|
|
||||||
ControllerNamespace: mgrPodNamespace,
|
|
||||||
DefaultRunnerScaleSetListenerImage: mgrContainer.Image,
|
|
||||||
ActionsClient: actionsMultiClient,
|
|
||||||
DefaultRunnerScaleSetListenerImagePullSecrets: autoScalerImagePullSecrets,
|
|
||||||
}).SetupWithManager(mgr); err != nil {
|
|
||||||
log.Error(err, "unable to create controller", "controller", "AutoscalingRunnerSet")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = (&actionsgithubcom.EphemeralRunnerReconciler{
|
|
||||||
Client: mgr.GetClient(),
|
|
||||||
Log: log.WithName("EphemeralRunner"),
|
|
||||||
Scheme: mgr.GetScheme(),
|
|
||||||
ActionsClient: actionsMultiClient,
|
|
||||||
}).SetupWithManager(mgr); err != nil {
|
|
||||||
log.Error(err, "unable to create controller", "controller", "EphemeralRunner")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = (&actionsgithubcom.EphemeralRunnerSetReconciler{
|
|
||||||
Client: mgr.GetClient(),
|
|
||||||
Log: log.WithName("EphemeralRunnerSet"),
|
|
||||||
Scheme: mgr.GetScheme(),
|
|
||||||
ActionsClient: actionsMultiClient,
|
|
||||||
}).SetupWithManager(mgr); err != nil {
|
|
||||||
log.Error(err, "unable to create controller", "controller", "EphemeralRunnerSet")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
if err = (&actionsgithubcom.AutoscalingListenerReconciler{
|
|
||||||
Client: mgr.GetClient(),
|
|
||||||
Log: log.WithName("AutoscalingListener"),
|
|
||||||
Scheme: mgr.GetScheme(),
|
|
||||||
}).SetupWithManager(mgr); err != nil {
|
|
||||||
log.Error(err, "unable to create controller", "controller", "AutoscalingListener")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
// +kubebuilder:scaffold:builder
|
|
||||||
}
|
|
||||||
|
|
||||||
if !disableAdmissionWebhook && !autoScalingRunnerSetOnly {
|
|
||||||
injector := &actionssummerwindnet.PodRunnerTokenInjector{
|
|
||||||
Client: mgr.GetClient(),
|
|
||||||
GitHubClient: multiClient,
|
|
||||||
Log: ctrl.Log.WithName("webhook").WithName("PodRunnerTokenInjector"),
|
|
||||||
}
|
|
||||||
if err = injector.SetupWithManager(mgr); err != nil {
|
|
||||||
log.Error(err, "unable to create webhook server", "webhook", "PodRunnerTokenInjector")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user