mirror of
https://github.com/actions/actions-runner-controller.git
synced 2025-12-10 11:41:27 +00:00
Compare commits
86 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 | ||
|
|
1d24d3b00d | ||
|
|
9994d3aa60 | ||
|
|
a2ea12e93c | ||
|
|
d7b589bed5 | ||
|
|
4f293c6f79 | ||
|
|
c569304271 | ||
|
|
068f987238 | ||
|
|
a462ecbe79 | ||
|
|
c5d6842d5f | ||
|
|
947bc8ab5b | ||
|
|
9d5c6e85c5 | ||
|
|
2420a40c02 | ||
|
|
b3e7c723d2 | ||
|
|
2e36db52c3 | ||
|
|
5d41609bea | ||
|
|
e289fe43d4 | ||
|
|
91fddca3f7 | ||
|
|
befe4cee0a | ||
|
|
548acdf05c | ||
|
|
41f2ca3ed9 | ||
|
|
00996ec799 | ||
|
|
893833fdd5 | ||
|
|
7f3eef8761 | ||
|
|
40c905f25d | ||
|
|
2984de912c | ||
|
|
1df06a69d7 | ||
|
|
be47190d4c | ||
|
|
e8d8c6f357 | ||
|
|
0c091f59b6 | ||
|
|
a4751b74e0 | ||
|
|
adad3d5530 | ||
|
|
70156e3fea | ||
|
|
69abd51f30 | ||
|
|
73e35b1dc6 | ||
|
|
c4178d5633 | ||
|
|
edf924106b | ||
|
|
34ebbf74d1 | ||
|
|
a9af82ec78 | ||
|
|
b5e9e14244 | ||
|
|
910269aa11 | ||
|
|
149cf47c83 | ||
|
|
ec3afef00d | ||
|
|
7d0918b6d5 | ||
|
|
678eafcd67 |
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
|
|
||||||
567
.github/workflows/e2e-test-linux-vm.yaml
vendored
Normal file
567
.github/workflows/e2e-test-linux-vm.yaml
vendored
Normal file
@@ -0,0 +1,567 @@
|
|||||||
|
name: CI ARC E2E Linux VM Test
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
env:
|
||||||
|
TARGET_ORG: actions-runner-controller
|
||||||
|
TARGET_REPO: arc_e2e_test_dummy
|
||||||
|
IMAGE_NAME: "arc-test-image"
|
||||||
|
IMAGE_VERSION: "dev"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
default-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: |
|
||||||
|
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"
|
||||||
|
|
||||||
|
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
|
||||||
28
.github/workflows/publish-chart.yaml
vendored
28
.github/workflows/publish-chart.yaml
vendored
@@ -10,8 +10,8 @@ on:
|
|||||||
- 'charts/**'
|
- 'charts/**'
|
||||||
- '.github/workflows/publish-chart.yaml'
|
- '.github/workflows/publish-chart.yaml'
|
||||||
- '!charts/actions-runner-controller/docs/**'
|
- '!charts/actions-runner-controller/docs/**'
|
||||||
- '!charts/actions-runner-controller-2/**'
|
- '!charts/gha-runner-scale-set-controller/**'
|
||||||
- '!charts/auto-scaling-runner-set/**'
|
- '!charts/gha-runner-scale-set/**'
|
||||||
- '!**.md'
|
- '!**.md'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
@@ -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"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
name: Publish ARC 2
|
name: Publish Runner Scale Set Controller Charts
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
@@ -18,13 +18,13 @@ on:
|
|||||||
required: true
|
required: true
|
||||||
type: boolean
|
type: boolean
|
||||||
default: false
|
default: false
|
||||||
publish_actions_runner_controller_2_chart:
|
publish_gha_runner_scale_set_controller_chart:
|
||||||
description: 'Publish new helm chart for actions-runner-controller-2'
|
description: 'Publish new helm chart for gha-runner-scale-set-controller'
|
||||||
required: true
|
required: true
|
||||||
type: boolean
|
type: boolean
|
||||||
default: false
|
default: false
|
||||||
publish_auto_scaling_runner_set_chart:
|
publish_gha_runner_scale_set_chart:
|
||||||
description: 'Publish new helm chart for auto-scaling-runner-set'
|
description: 'Publish new helm chart for gha-runner-scale-set'
|
||||||
required: true
|
required: true
|
||||||
type: boolean
|
type: boolean
|
||||||
default: false
|
default: false
|
||||||
@@ -87,14 +87,14 @@ jobs:
|
|||||||
build-args: VERSION=${{ inputs.release_tag_name }}
|
build-args: VERSION=${{ inputs.release_tag_name }}
|
||||||
push: ${{ inputs.push_to_registries }}
|
push: ${{ inputs.push_to_registries }}
|
||||||
tags: |
|
tags: |
|
||||||
ghcr.io/${{ steps.resolve_parameters.outputs.repository_owner }}/actions-runner-controller-2:${{ inputs.release_tag_name }}
|
ghcr.io/${{ steps.resolve_parameters.outputs.repository_owner }}/gha-runner-scale-set-controller:${{ inputs.release_tag_name }}
|
||||||
ghcr.io/${{ steps.resolve_parameters.outputs.repository_owner }}/actions-runner-controller-2:${{ inputs.release_tag_name }}-${{ steps.resolve_parameters.outputs.short_sha }}
|
ghcr.io/${{ steps.resolve_parameters.outputs.repository_owner }}/gha-runner-scale-set-controller:${{ inputs.release_tag_name }}-${{ steps.resolve_parameters.outputs.short_sha }}
|
||||||
cache-from: type=gha
|
cache-from: type=gha
|
||||||
cache-to: type=gha,mode=max
|
cache-to: type=gha,mode=max
|
||||||
|
|
||||||
- name: Job summary
|
- name: Job summary
|
||||||
run: |
|
run: |
|
||||||
echo "The [publish-arc2](https://github.com/actions/actions-runner-controller/blob/main/.github/workflows/publish-arc2.yaml) workflow run was completed successfully!" >> $GITHUB_STEP_SUMMARY
|
echo "The [publish-runner-scale-set.yaml](https://github.com/actions/actions-runner-controller/blob/main/.github/workflows/publish-runner-scale-set.yaml) workflow run was completed successfully!" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "**Parameters:**" >> $GITHUB_STEP_SUMMARY
|
echo "**Parameters:**" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "- Ref: ${{ steps.resolve_parameters.outputs.resolvedRef }}" >> $GITHUB_STEP_SUMMARY
|
echo "- Ref: ${{ steps.resolve_parameters.outputs.resolvedRef }}" >> $GITHUB_STEP_SUMMARY
|
||||||
@@ -103,10 +103,10 @@ jobs:
|
|||||||
echo "- Push to registries: ${{ inputs.push_to_registries }}" >> $GITHUB_STEP_SUMMARY
|
echo "- Push to registries: ${{ inputs.push_to_registries }}" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
|
|
||||||
publish-helm-chart-arc-2:
|
publish-helm-chart-gha-runner-scale-set-controller:
|
||||||
if: ${{ inputs.publish_actions_runner_controller_2_chart == true }}
|
if: ${{ inputs.publish_gha_runner_scale_set_controller_chart == true }}
|
||||||
needs: build-push-image
|
needs: build-push-image
|
||||||
name: Publish Helm chart for actions-runner-controller-2
|
name: Publish Helm chart for gha-runner-scale-set-controller
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -129,31 +129,32 @@ jobs:
|
|||||||
echo "repository_owner=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
|
echo "repository_owner=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Set up Helm
|
- name: Set up Helm
|
||||||
uses: azure/setup-helm@v3.3
|
# Using https://github.com/Azure/setup-helm/releases/tag/v3.5
|
||||||
|
uses: azure/setup-helm@5119fcb9089d432beecbf79bb2c7915207344b78
|
||||||
with:
|
with:
|
||||||
version: ${{ env.HELM_VERSION }}
|
version: ${{ env.HELM_VERSION }}
|
||||||
|
|
||||||
- name: Publish new helm chart for actions-runner-controller-2
|
- name: Publish new helm chart for gha-runner-scale-set-controller
|
||||||
run: |
|
run: |
|
||||||
echo ${{ secrets.GITHUB_TOKEN }} | helm registry login ghcr.io --username ${{ github.actor }} --password-stdin
|
echo ${{ secrets.GITHUB_TOKEN }} | helm registry login ghcr.io --username ${{ github.actor }} --password-stdin
|
||||||
ACTIONS_RUNNER_CONTROLLER_2_CHART_VERSION_TAG=$(cat charts/actions-runner-controller-2/Chart.yaml | grep version: | cut -d " " -f 2)
|
GHA_RUNNER_SCALE_SET_CONTROLLER_CHART_VERSION_TAG=$(cat charts/gha-runner-scale-set-controller/Chart.yaml | grep version: | cut -d " " -f 2)
|
||||||
echo "ACTIONS_RUNNER_CONTROLLER_2_CHART_VERSION_TAG=${ACTIONS_RUNNER_CONTROLLER_2_CHART_VERSION_TAG}" >> $GITHUB_ENV
|
echo "GHA_RUNNER_SCALE_SET_CONTROLLER_CHART_VERSION_TAG=${GHA_RUNNER_SCALE_SET_CONTROLLER_CHART_VERSION_TAG}" >> $GITHUB_ENV
|
||||||
helm package charts/actions-runner-controller-2/ --version="${ACTIONS_RUNNER_CONTROLLER_2_CHART_VERSION_TAG}"
|
helm package charts/gha-runner-scale-set-controller/ --version="${GHA_RUNNER_SCALE_SET_CONTROLLER_CHART_VERSION_TAG}"
|
||||||
helm push actions-runner-controller-2-"${ACTIONS_RUNNER_CONTROLLER_2_CHART_VERSION_TAG}".tgz oci://ghcr.io/${{ steps.resolve_parameters.outputs.repository_owner }}/actions-runner-controller-charts
|
helm push gha-runner-scale-set-controller-"${GHA_RUNNER_SCALE_SET_CONTROLLER_CHART_VERSION_TAG}".tgz oci://ghcr.io/${{ steps.resolve_parameters.outputs.repository_owner }}/actions-runner-controller-charts
|
||||||
|
|
||||||
- name: Job summary
|
- name: Job summary
|
||||||
run: |
|
run: |
|
||||||
echo "New helm chart for actions-runner-controller-2 published successfully!" >> $GITHUB_STEP_SUMMARY
|
echo "New helm chart for gha-runner-scale-set-controller published successfully!" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "**Parameters:**" >> $GITHUB_STEP_SUMMARY
|
echo "**Parameters:**" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "- Ref: ${{ steps.resolve_parameters.outputs.resolvedRef }}" >> $GITHUB_STEP_SUMMARY
|
echo "- Ref: ${{ steps.resolve_parameters.outputs.resolvedRef }}" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "- Short SHA: ${{ steps.resolve_parameters.outputs.short_sha }}" >> $GITHUB_STEP_SUMMARY
|
echo "- Short SHA: ${{ steps.resolve_parameters.outputs.short_sha }}" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "- Actions-Runner-Controller-2 Chart version: ${{ env.ACTIONS_RUNNER_CONTROLLER_2_CHART_VERSION_TAG }}" >> $GITHUB_STEP_SUMMARY
|
echo "- gha-runner-scale-set-controller Chart version: ${{ env.GHA_RUNNER_SCALE_SET_CONTROLLER_CHART_VERSION_TAG }}" >> $GITHUB_STEP_SUMMARY
|
||||||
|
|
||||||
publish-helm-chart-auto-scaling-runner-set:
|
publish-helm-chart-gha-runner-scale-set:
|
||||||
if: ${{ inputs.publish_auto_scaling_runner_set_chart == true }}
|
if: ${{ inputs.publish_gha_runner_scale_set_chart == true }}
|
||||||
needs: build-push-image
|
needs: build-push-image
|
||||||
name: Publish Helm chart for auto-scaling-runner-set
|
name: Publish Helm chart for gha-runner-scale-set
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -176,24 +177,25 @@ jobs:
|
|||||||
echo "repository_owner=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
|
echo "repository_owner=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Set up Helm
|
- name: Set up Helm
|
||||||
uses: azure/setup-helm@v3.3
|
# Using https://github.com/Azure/setup-helm/releases/tag/v3.5
|
||||||
|
uses: azure/setup-helm@5119fcb9089d432beecbf79bb2c7915207344b78
|
||||||
with:
|
with:
|
||||||
version: ${{ env.HELM_VERSION }}
|
version: ${{ env.HELM_VERSION }}
|
||||||
|
|
||||||
- name: Publish new helm chart for auto-scaling-runner-set
|
- name: Publish new helm chart for gha-runner-scale-set
|
||||||
run: |
|
run: |
|
||||||
echo ${{ secrets.GITHUB_TOKEN }} | helm registry login ghcr.io --username ${{ github.actor }} --password-stdin
|
echo ${{ secrets.GITHUB_TOKEN }} | helm registry login ghcr.io --username ${{ github.actor }} --password-stdin
|
||||||
|
|
||||||
AUTO_SCALING_RUNNER_SET_CHART_VERSION_TAG=$(cat charts/auto-scaling-runner-set/Chart.yaml | grep version: | cut -d " " -f 2)
|
GHA_RUNNER_SCALE_SET_CHART_VERSION_TAG=$(cat charts/gha-runner-scale-set/Chart.yaml | grep version: | cut -d " " -f 2)
|
||||||
echo "AUTO_SCALING_RUNNER_SET_CHART_VERSION_TAG=${AUTO_SCALING_RUNNER_SET_CHART_VERSION_TAG}" >> $GITHUB_ENV
|
echo "GHA_RUNNER_SCALE_SET_CHART_VERSION_TAG=${GHA_RUNNER_SCALE_SET_CHART_VERSION_TAG}" >> $GITHUB_ENV
|
||||||
helm package charts/auto-scaling-runner-set/ --version="${AUTO_SCALING_RUNNER_SET_CHART_VERSION_TAG}"
|
helm package charts/gha-runner-scale-set/ --version="${GHA_RUNNER_SCALE_SET_CHART_VERSION_TAG}"
|
||||||
helm push auto-scaling-runner-set-"${AUTO_SCALING_RUNNER_SET_CHART_VERSION_TAG}".tgz oci://ghcr.io/${{ steps.resolve_parameters.outputs.repository_owner }}/actions-runner-controller-charts
|
helm push gha-runner-scale-set-"${GHA_RUNNER_SCALE_SET_CHART_VERSION_TAG}".tgz oci://ghcr.io/${{ steps.resolve_parameters.outputs.repository_owner }}/actions-runner-controller-charts
|
||||||
|
|
||||||
- name: Job summary
|
- name: Job summary
|
||||||
run: |
|
run: |
|
||||||
echo "New helm chart for auto-scaling-runner-set published successfully!" >> $GITHUB_STEP_SUMMARY
|
echo "New helm chart for gha-runner-scale-set published successfully!" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "**Parameters:**" >> $GITHUB_STEP_SUMMARY
|
echo "**Parameters:**" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "- Ref: ${{ steps.resolve_parameters.outputs.resolvedRef }}" >> $GITHUB_STEP_SUMMARY
|
echo "- Ref: ${{ steps.resolve_parameters.outputs.resolvedRef }}" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "- Short SHA: ${{ steps.resolve_parameters.outputs.short_sha }}" >> $GITHUB_STEP_SUMMARY
|
echo "- Short SHA: ${{ steps.resolve_parameters.outputs.short_sha }}" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "- Auto-Scaling-Runner-Set Chart version: ${{ env.AUTO_SCALING_RUNNER_SET_CHART_VERSION_TAG }}" >> $GITHUB_STEP_SUMMARY
|
echo "- gha-runner-scale-set Chart version: ${{ env.GHA_RUNNER_SCALE_SET_CHART_VERSION_TAG }}" >> $GITHUB_STEP_SUMMARY
|
||||||
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:
|
||||||
|
|||||||
2
.github/workflows/update-runners.yaml
vendored
2
.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,6 +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
|
||||||
|
|
||||||
- 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
|
|
||||||
15
.github/workflows/validate-chart.yaml
vendored
15
.github/workflows/validate-chart.yaml
vendored
@@ -1,12 +1,24 @@
|
|||||||
name: Validate Helm Chart
|
name: Validate Helm Chart
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
paths:
|
||||||
|
- 'charts/**'
|
||||||
|
- '.github/workflows/validate-chart.yaml'
|
||||||
|
- '!charts/actions-runner-controller/docs/**'
|
||||||
|
- '!**.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
|
||||||
@@ -26,7 +38,8 @@ jobs:
|
|||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set up Helm
|
- name: Set up Helm
|
||||||
uses: azure/setup-helm@v3.4
|
# Using https://github.com/Azure/setup-helm/releases/tag/v3.5
|
||||||
|
uses: azure/setup-helm@5119fcb9089d432beecbf79bb2c7915207344b78
|
||||||
with:
|
with:
|
||||||
version: ${{ env.HELM_VERSION }}
|
version: ${{ env.HELM_VERSION }}
|
||||||
|
|
||||||
|
|||||||
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
|
||||||
@@ -39,7 +39,8 @@ RUN --mount=target=. \
|
|||||||
go build -trimpath -ldflags="-s -w -X 'github.com/actions/actions-runner-controller/build.Version=${VERSION}'" -o /out/manager main.go && \
|
go build -trimpath -ldflags="-s -w -X 'github.com/actions/actions-runner-controller/build.Version=${VERSION}'" -o /out/manager main.go && \
|
||||||
go build -trimpath -ldflags="-s -w" -o /out/github-runnerscaleset-listener ./cmd/githubrunnerscalesetlistener && \
|
go build -trimpath -ldflags="-s -w" -o /out/github-runnerscaleset-listener ./cmd/githubrunnerscalesetlistener && \
|
||||||
go build -trimpath -ldflags="-s -w" -o /out/github-webhook-server ./cmd/githubwebhookserver && \
|
go build -trimpath -ldflags="-s -w" -o /out/github-webhook-server ./cmd/githubwebhookserver && \
|
||||||
go build -trimpath -ldflags="-s -w" -o /out/actions-metrics-server ./cmd/actionsmetricsserver
|
go build -trimpath -ldflags="-s -w" -o /out/actions-metrics-server ./cmd/actionsmetricsserver && \
|
||||||
|
go build -trimpath -ldflags="-s -w" -o /out/sleep ./cmd/sleep
|
||||||
|
|
||||||
# Use distroless as minimal base image to package the manager binary
|
# Use distroless as minimal base image to package the manager binary
|
||||||
# Refer to https://github.com/GoogleContainerTools/distroless for more details
|
# Refer to https://github.com/GoogleContainerTools/distroless for more details
|
||||||
@@ -51,6 +52,7 @@ COPY --from=builder /out/manager .
|
|||||||
COPY --from=builder /out/github-webhook-server .
|
COPY --from=builder /out/github-webhook-server .
|
||||||
COPY --from=builder /out/actions-metrics-server .
|
COPY --from=builder /out/actions-metrics-server .
|
||||||
COPY --from=builder /out/github-runnerscaleset-listener .
|
COPY --from=builder /out/github-runnerscaleset-listener .
|
||||||
|
COPY --from=builder /out/sleep .
|
||||||
|
|
||||||
USER 65532:65532
|
USER 65532:65532
|
||||||
|
|
||||||
|
|||||||
118
Makefile
118
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.301.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}
|
||||||
@@ -73,7 +73,7 @@ GO_TEST_ARGS ?= -short
|
|||||||
|
|
||||||
# Run tests
|
# Run tests
|
||||||
test: generate fmt vet manifests shellcheck
|
test: generate fmt vet manifests shellcheck
|
||||||
go test $(GO_TEST_ARGS) ./... -coverprofile cover.out
|
go test $(GO_TEST_ARGS) `go list ./... | grep -v ./test_e2e_arc` -coverprofile cover.out
|
||||||
go test -fuzz=Fuzz -fuzztime=10s -run=Fuzz* ./controllers/actions.summerwind.net
|
go test -fuzz=Fuzz -fuzztime=10s -run=Fuzz* ./controllers/actions.summerwind.net
|
||||||
|
|
||||||
test-with-deps: kube-apiserver etcd kubectl
|
test-with-deps: kube-apiserver etcd kubectl
|
||||||
@@ -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
|
||||||
@@ -113,66 +118,71 @@ manifests-gen-crds: controller-gen yq
|
|||||||
for YAMLFILE in config/crd/bases/actions*.yaml; do \
|
for YAMLFILE in config/crd/bases/actions*.yaml; do \
|
||||||
$(YQ) '.spec.preserveUnknownFields = false' --inplace "$$YAMLFILE" ; \
|
$(YQ) '.spec.preserveUnknownFields = false' --inplace "$$YAMLFILE" ; \
|
||||||
done
|
done
|
||||||
|
make manifests-gen-crds-fix DELETE_KEY=x-kubernetes-list-type
|
||||||
|
make manifests-gen-crds-fix DELETE_KEY=x-kubernetes-list-map-keys
|
||||||
|
|
||||||
|
manifests-gen-crds-fix: DELETE_KEY ?=
|
||||||
|
manifests-gen-crds-fix:
|
||||||
#runners
|
#runners
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.summerwind.dev_runners.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.summerwind.dev_runners.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.ephemeralContainers.items.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.summerwind.dev_runners.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.ephemeralContainers.items.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.summerwind.dev_runners.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.initContainers.items.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.summerwind.dev_runners.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.initContainers.items.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.summerwind.dev_runners.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.containers.items.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.summerwind.dev_runners.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.containers.items.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.summerwind.dev_runners.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.sidecarContainers.items.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.summerwind.dev_runners.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.sidecarContainers.items.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.summerwind.dev_runners.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.dockerdContainerResources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.summerwind.dev_runners.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.dockerdContainerResources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.summerwind.dev_runners.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.volumes.items.properties.ephemeral.properties.volumeClaimTemplate.properties.spec.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.summerwind.dev_runners.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.volumes.items.properties.ephemeral.properties.volumeClaimTemplate.properties.spec.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.summerwind.dev_runners.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.workVolumeClaimTemplate.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.summerwind.dev_runners.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.workVolumeClaimTemplate.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.summerwind.dev_runners.yaml
|
||||||
#runnerreplicasets
|
#runnerreplicasets
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.summerwind.dev_runnerreplicasets.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.summerwind.dev_runnerreplicasets.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.sidecarContainers.items.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.summerwind.dev_runnerreplicasets.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.sidecarContainers.items.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.summerwind.dev_runnerreplicasets.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.dockerdContainerResources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.summerwind.dev_runnerreplicasets.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.dockerdContainerResources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.summerwind.dev_runnerreplicasets.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.ephemeralContainers.items.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.summerwind.dev_runnerreplicasets.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.ephemeralContainers.items.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.summerwind.dev_runnerreplicasets.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.containers.items.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.summerwind.dev_runnerreplicasets.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.containers.items.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.summerwind.dev_runnerreplicasets.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.initContainers.items.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.summerwind.dev_runnerreplicasets.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.initContainers.items.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.summerwind.dev_runnerreplicasets.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.volumes.items.properties.ephemeral.properties.volumeClaimTemplate.properties.spec.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.summerwind.dev_runnerreplicasets.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.volumes.items.properties.ephemeral.properties.volumeClaimTemplate.properties.spec.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.summerwind.dev_runnerreplicasets.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.workVolumeClaimTemplate.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.summerwind.dev_runnerreplicasets.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.workVolumeClaimTemplate.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.summerwind.dev_runnerreplicasets.yaml
|
||||||
#runnerdeployments
|
#runnerdeployments
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.summerwind.dev_runnerdeployments.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.summerwind.dev_runnerdeployments.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.initContainers.items.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.summerwind.dev_runnerdeployments.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.initContainers.items.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.summerwind.dev_runnerdeployments.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.sidecarContainers.items.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.summerwind.dev_runnerdeployments.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.sidecarContainers.items.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.summerwind.dev_runnerdeployments.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.dockerdContainerResources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.summerwind.dev_runnerdeployments.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.dockerdContainerResources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.summerwind.dev_runnerdeployments.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.ephemeralContainers.items.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.summerwind.dev_runnerdeployments.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.ephemeralContainers.items.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.summerwind.dev_runnerdeployments.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.containers.items.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.summerwind.dev_runnerdeployments.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.containers.items.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.summerwind.dev_runnerdeployments.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.volumes.items.properties.ephemeral.properties.volumeClaimTemplate.properties.spec.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.summerwind.dev_runnerdeployments.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.volumes.items.properties.ephemeral.properties.volumeClaimTemplate.properties.spec.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.summerwind.dev_runnerdeployments.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.workVolumeClaimTemplate.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.summerwind.dev_runnerdeployments.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.workVolumeClaimTemplate.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.summerwind.dev_runnerdeployments.yaml
|
||||||
#runnersets
|
#runnersets
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.summerwind.dev_runnersets.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.summerwind.dev_runnersets.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.volumeClaimTemplates.items.properties.spec.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.summerwind.dev_runnersets.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.volumeClaimTemplates.items.properties.spec.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.summerwind.dev_runnersets.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.workVolumeClaimTemplate.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.summerwind.dev_runnersets.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.workVolumeClaimTemplate.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.summerwind.dev_runnersets.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.ephemeralContainers.items.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.summerwind.dev_runnersets.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.ephemeralContainers.items.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.summerwind.dev_runnersets.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.containers.items.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.summerwind.dev_runnersets.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.containers.items.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.summerwind.dev_runnersets.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.initContainers.items.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.summerwind.dev_runnersets.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.initContainers.items.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.summerwind.dev_runnersets.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.volumes.items.properties.ephemeral.properties.volumeClaimTemplate.properties.spec.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.summerwind.dev_runnersets.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.volumes.items.properties.ephemeral.properties.volumeClaimTemplate.properties.spec.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.summerwind.dev_runnersets.yaml
|
||||||
#autoscalingrunnersets
|
#autoscalingrunnersets
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.github.com_autoscalingrunnersets.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.github.com_autoscalingrunnersets.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.containers.items.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.github.com_autoscalingrunnersets.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.containers.items.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.github.com_autoscalingrunnersets.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.ephemeralContainers.items.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.github.com_autoscalingrunnersets.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.ephemeralContainers.items.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.github.com_autoscalingrunnersets.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.initContainers.items.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.github.com_autoscalingrunnersets.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.initContainers.items.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.github.com_autoscalingrunnersets.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.volumes.items.properties.ephemeral.properties.volumeClaimTemplate.properties.spec.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.github.com_autoscalingrunnersets.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.volumes.items.properties.ephemeral.properties.volumeClaimTemplate.properties.spec.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.github.com_autoscalingrunnersets.yaml
|
||||||
#ehemeralrunnersets
|
#ehemeralrunnersets
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.properties.spec.properties.initContainers.items.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.github.com_ephemeralrunnersets.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.properties.spec.properties.initContainers.items.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.github.com_ephemeralrunnersets.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.github.com_ephemeralrunnersets.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.template.properties.spec.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.github.com_ephemeralrunnersets.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.ephemeralRunnerSpec.properties.spec.properties.initContainers.items.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.github.com_ephemeralrunnersets.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.ephemeralRunnerSpec.properties.spec.properties.initContainers.items.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.github.com_ephemeralrunnersets.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.ephemeralRunnerSpec.properties.spec.properties.containers.items.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.github.com_ephemeralrunnersets.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.ephemeralRunnerSpec.properties.spec.properties.containers.items.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.github.com_ephemeralrunnersets.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.ephemeralRunnerSpec.properties.spec.properties.ephemeralContainers.items.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.github.com_ephemeralrunnersets.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.ephemeralRunnerSpec.properties.spec.properties.ephemeralContainers.items.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.github.com_ephemeralrunnersets.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.ephemeralRunnerSpec.properties.spec.properties.volumes.items.properties.ephemeral.properties.volumeClaimTemplate.properties.spec.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.github.com_ephemeralrunnersets.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.ephemeralRunnerSpec.properties.spec.properties.volumes.items.properties.ephemeral.properties.volumeClaimTemplate.properties.spec.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.github.com_ephemeralrunnersets.yaml
|
||||||
# ephemeralrunners
|
# ephemeralrunners
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.spec.properties.ephemeralContainers.items.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.github.com_ephemeralrunners.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.spec.properties.ephemeralContainers.items.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.github.com_ephemeralrunners.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.spec.properties.containers.items.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.github.com_ephemeralrunners.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.spec.properties.containers.items.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.github.com_ephemeralrunners.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.spec.properties.initContainers.items.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.github.com_ephemeralrunners.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.spec.properties.initContainers.items.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.github.com_ephemeralrunners.yaml
|
||||||
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.spec.properties.volumes.items.properties.ephemeral.properties.volumeClaimTemplate.properties.spec.properties.resources.properties.claims.x-kubernetes-list-type)' --inplace config/crd/bases/actions.github.com_ephemeralrunners.yaml
|
$(YQ) 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.spec.properties.volumes.items.properties.ephemeral.properties.volumeClaimTemplate.properties.spec.properties.resources.properties.claims.$(DELETE_KEY))' --inplace config/crd/bases/actions.github.com_ephemeralrunners.yaml
|
||||||
|
|
||||||
chart-crds:
|
chart-crds:
|
||||||
cp config/crd/bases/*.yaml charts/actions-runner-controller/crds/
|
cp config/crd/bases/*.yaml charts/actions-runner-controller/crds/
|
||||||
cp config/crd/bases/actions.github.com_autoscalingrunnersets.yaml charts/actions-runner-controller-2/crds/
|
cp config/crd/bases/actions.github.com_autoscalingrunnersets.yaml charts/gha-runner-scale-set-controller/crds/
|
||||||
cp config/crd/bases/actions.github.com_autoscalinglisteners.yaml charts/actions-runner-controller-2/crds/
|
cp config/crd/bases/actions.github.com_autoscalinglisteners.yaml charts/gha-runner-scale-set-controller/crds/
|
||||||
cp config/crd/bases/actions.github.com_ephemeralrunnersets.yaml charts/actions-runner-controller-2/crds/
|
cp config/crd/bases/actions.github.com_ephemeralrunnersets.yaml charts/gha-runner-scale-set-controller/crds/
|
||||||
cp config/crd/bases/actions.github.com_ephemeralrunners.yaml charts/actions-runner-controller-2/crds/
|
cp config/crd/bases/actions.github.com_ephemeralrunners.yaml charts/gha-runner-scale-set-controller/crds/
|
||||||
rm charts/actions-runner-controller/crds/actions.github.com_autoscalingrunnersets.yaml
|
rm charts/actions-runner-controller/crds/actions.github.com_autoscalingrunnersets.yaml
|
||||||
rm charts/actions-runner-controller/crds/actions.github.com_autoscalinglisteners.yaml
|
rm charts/actions-runner-controller/crds/actions.github.com_autoscalinglisteners.yaml
|
||||||
rm charts/actions-runner-controller/crds/actions.github.com_ephemeralrunnersets.yaml
|
rm charts/actions-runner-controller/crds/actions.github.com_ephemeralrunnersets.yaml
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ else
|
|||||||
echo 'Skipped deploying secret "github-webhook-server". Set WEBHOOK_GITHUB_TOKEN to deploy.' 1>&2
|
echo 'Skipped deploying secret "github-webhook-server". Set WEBHOOK_GITHUB_TOKEN to deploy.' 1>&2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "${WEBHOOK_GITHUB_TOKEN}" ]; then
|
if [ -n "${WEBHOOK_GITHUB_TOKEN}" ] && [ -z "${CREATE_SECRETS_USING_HELM}" ]; then
|
||||||
kubectl -n actions-runner-system delete secret \
|
kubectl -n actions-runner-system delete secret \
|
||||||
actions-metrics-server || :
|
actions-metrics-server || :
|
||||||
kubectl -n actions-runner-system create secret generic \
|
kubectl -n actions-runner-system create secret generic \
|
||||||
@@ -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,21 @@ 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 [ -z "${WEBHOOK_GITHUB_TOKEN}" ]; then
|
||||||
|
echo 'Failed deploying secret "actions-metrics-server" using helm. Set WEBHOOK_GITHUB_TOKEN to deploy.' 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
flags+=( --set actionsMetricsServer.secret.create=true)
|
||||||
|
flags+=( --set actionsMetricsServer.secret.github_token=${WEBHOOK_GITHUB_TOKEN})
|
||||||
|
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,90 +0,0 @@
|
|||||||
# ADR 0001: Produce the runner image for the scaleset client
|
|
||||||
**Date**: 2022-10-17
|
|
||||||
|
|
||||||
**Status**: Done
|
|
||||||
|
|
||||||
# Context
|
|
||||||
|
|
||||||
user can bring their own runner images, the contract we have are:
|
|
||||||
- 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:
|
|
||||||
|
|
||||||
- The current runner image requires caller to pass runner configure info, ex: URL and Config Token
|
|
||||||
- The current runner image has the runner binary under /runner
|
|
||||||
- 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.
|
|
||||||
|
|
||||||
# Guiding Principles
|
|
||||||
|
|
||||||
- Build image is separated in two stages.
|
|
||||||
|
|
||||||
## The first stage (build)
|
|
||||||
- Reuses the same base image, so it is faster to build.
|
|
||||||
- Installs utilities needed to download assets (runner and runner-container-hooks).
|
|
||||||
- Downloads the runner and stores it into `/actions-runner` 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.
|
|
||||||
|
|
||||||
Preview:
|
|
||||||
|
|
||||||
```Dockerfile
|
|
||||||
FROM mcr.microsoft.com/dotnet/runtime-deps:6.0 as build
|
|
||||||
|
|
||||||
ARG RUNNER_ARCH="x64"
|
|
||||||
ARG RUNNER_VERSION=2.298.2
|
|
||||||
ARG RUNNER_CONTAINER_HOOKS_VERSION=0.1.3
|
|
||||||
|
|
||||||
RUN apt update -y && apt install curl unzip -y
|
|
||||||
|
|
||||||
WORKDIR /actions-runner
|
|
||||||
RUN curl -f -L -o runner.tar.gz https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-linux-${RUNNER_ARCH}-${RUNNER_VERSION}.tar.gz \
|
|
||||||
&& tar xzf ./runner.tar.gz \
|
|
||||||
&& rm runner.tar.gz
|
|
||||||
|
|
||||||
RUN curl -f -L -o runner-container-hooks.zip https://github.com/actions/runner-container-hooks/releases/download/v${RUNNER_CONTAINER_HOOKS_VERSION}/actions-runner-hooks-k8s-${RUNNER_CONTAINER_HOOKS_VERSION}.zip \
|
|
||||||
&& unzip ./runner-container-hooks.zip -d ./k8s \
|
|
||||||
&& rm runner-container-hooks.zip
|
|
||||||
```
|
|
||||||
|
|
||||||
## The main image:
|
|
||||||
- Copies assets from the build stage to `/actions-runner`
|
|
||||||
- Does not provide an entrypoint. The entrypoint should be set within the container definition.
|
|
||||||
|
|
||||||
Preview:
|
|
||||||
|
|
||||||
```Dockerfile
|
|
||||||
FROM mcr.microsoft.com/dotnet/runtime-deps:6.0
|
|
||||||
|
|
||||||
WORKDIR /actions-runner
|
|
||||||
COPY --from=build /actions-runner .
|
|
||||||
```
|
|
||||||
|
|
||||||
## Example of pod spec with the init container copying assets
|
|
||||||
```yaml
|
|
||||||
apiVersion: v1
|
|
||||||
kind: Pod
|
|
||||||
metadata:
|
|
||||||
name: <name>
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: runner
|
|
||||||
image: <image>
|
|
||||||
command: ["/runner/run.sh"]
|
|
||||||
volumeMounts:
|
|
||||||
- name: runner
|
|
||||||
mountPath: /runner
|
|
||||||
initContainers:
|
|
||||||
- name: setup
|
|
||||||
image: <image>
|
|
||||||
command: ["sh", "-c", "cp -r /actions-runner/* /runner/"]
|
|
||||||
volumeMounts:
|
|
||||||
- name: runner
|
|
||||||
mountPath: /runner
|
|
||||||
volumes:
|
|
||||||
- name: runner
|
|
||||||
emptyDir: {}
|
|
||||||
```
|
|
||||||
@@ -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?*
|
|
||||||
@@ -57,6 +57,9 @@ type AutoscalingListenerSpec struct {
|
|||||||
|
|
||||||
// +optional
|
// +optional
|
||||||
Proxy *ProxyConfig `json:"proxy,omitempty"`
|
Proxy *ProxyConfig `json:"proxy,omitempty"`
|
||||||
|
|
||||||
|
// +optional
|
||||||
|
GitHubServerTLS *GitHubServerTLSConfig `json:"githubServerTLS,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// AutoscalingListenerStatus defines the observed state of AutoscalingListener
|
// AutoscalingListenerStatus defines the observed state of AutoscalingListener
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package v1alpha1
|
package v1alpha1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/x509"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -32,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 {
|
||||||
@@ -57,6 +62,9 @@ type AutoscalingRunnerSetSpec struct {
|
|||||||
// +optional
|
// +optional
|
||||||
RunnerGroup string `json:"runnerGroup,omitempty"`
|
RunnerGroup string `json:"runnerGroup,omitempty"`
|
||||||
|
|
||||||
|
// +optional
|
||||||
|
RunnerScaleSetName string `json:"runnerScaleSetName,omitempty"`
|
||||||
|
|
||||||
// +optional
|
// +optional
|
||||||
Proxy *ProxyConfig `json:"proxy,omitempty"`
|
Proxy *ProxyConfig `json:"proxy,omitempty"`
|
||||||
|
|
||||||
@@ -77,7 +85,44 @@ type AutoscalingRunnerSetSpec struct {
|
|||||||
|
|
||||||
type GitHubServerTLSConfig struct {
|
type GitHubServerTLSConfig struct {
|
||||||
// Required
|
// Required
|
||||||
RootCAsConfigMapRef string `json:"certConfigMapRef,omitempty"`
|
CertificateFrom *TLSCertificateSource `json:"certificateFrom,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *GitHubServerTLSConfig) ToCertPool(keyFetcher func(name, key string) ([]byte, error)) (*x509.CertPool, error) {
|
||||||
|
if c.CertificateFrom == nil {
|
||||||
|
return nil, fmt.Errorf("certificateFrom not specified")
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.CertificateFrom.ConfigMapKeyRef == nil {
|
||||||
|
return nil, fmt.Errorf("configMapKeyRef not specified")
|
||||||
|
}
|
||||||
|
|
||||||
|
cert, err := keyFetcher(c.CertificateFrom.ConfigMapKeyRef.Name, c.CertificateFrom.ConfigMapKeyRef.Key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"failed to fetch key %q in configmap %q: %w",
|
||||||
|
c.CertificateFrom.ConfigMapKeyRef.Key,
|
||||||
|
c.CertificateFrom.ConfigMapKeyRef.Name,
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
systemPool, err := x509.SystemCertPool()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get system cert pool: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pool := systemPool.Clone()
|
||||||
|
if !pool.AppendCertsFromPEM(cert) {
|
||||||
|
return nil, fmt.Errorf("failed to parse certificate")
|
||||||
|
}
|
||||||
|
|
||||||
|
return pool, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type TLSCertificateSource struct {
|
||||||
|
// Required
|
||||||
|
ConfigMapKeyRef *corev1.ConfigMapKeySelector `json:"configMapKeyRef,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProxyConfig struct {
|
type ProxyConfig struct {
|
||||||
@@ -187,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)
|
||||||
@@ -205,6 +258,7 @@ func (ars *AutoscalingRunnerSet) RunnerSetSpecHash() string {
|
|||||||
GitHubConfigUrl string
|
GitHubConfigUrl string
|
||||||
GitHubConfigSecret string
|
GitHubConfigSecret string
|
||||||
RunnerGroup string
|
RunnerGroup string
|
||||||
|
RunnerScaleSetName string
|
||||||
Proxy *ProxyConfig
|
Proxy *ProxyConfig
|
||||||
GitHubServerTLS *GitHubServerTLSConfig
|
GitHubServerTLS *GitHubServerTLSConfig
|
||||||
Template corev1.PodTemplateSpec
|
Template corev1.PodTemplateSpec
|
||||||
@@ -213,6 +267,7 @@ func (ars *AutoscalingRunnerSet) RunnerSetSpecHash() string {
|
|||||||
GitHubConfigUrl: ars.Spec.GitHubConfigUrl,
|
GitHubConfigUrl: ars.Spec.GitHubConfigUrl,
|
||||||
GitHubConfigSecret: ars.Spec.GitHubConfigSecret,
|
GitHubConfigSecret: ars.Spec.GitHubConfigSecret,
|
||||||
RunnerGroup: ars.Spec.RunnerGroup,
|
RunnerGroup: ars.Spec.RunnerGroup,
|
||||||
|
RunnerScaleSetName: ars.Spec.RunnerScaleSetName,
|
||||||
Proxy: ars.Spec.Proxy,
|
Proxy: ars.Spec.Proxy,
|
||||||
GitHubServerTLS: ars.Spec.GitHubServerTLS,
|
GitHubServerTLS: ars.Spec.GitHubServerTLS,
|
||||||
Template: ars.Spec.Template,
|
Template: ars.Spec.Template,
|
||||||
|
|||||||
@@ -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"`
|
||||||
|
|||||||
105
apis/actions.github.com/v1alpha1/tls_config_test.go
Normal file
105
apis/actions.github.com/v1alpha1/tls_config_test.go
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
package v1alpha1_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/actions/actions-runner-controller/apis/actions.github.com/v1alpha1"
|
||||||
|
"github.com/actions/actions-runner-controller/github/actions/testserver"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
v1 "k8s.io/api/core/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGitHubServerTLSConfig_ToCertPool(t *testing.T) {
|
||||||
|
t.Run("returns an error if CertificateFrom not specified", func(t *testing.T) {
|
||||||
|
c := &v1alpha1.GitHubServerTLSConfig{
|
||||||
|
CertificateFrom: nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
pool, err := c.ToCertPool(nil)
|
||||||
|
assert.Nil(t, pool)
|
||||||
|
|
||||||
|
require.Error(t, err)
|
||||||
|
assert.Equal(t, err.Error(), "certificateFrom not specified")
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("returns an error if CertificateFrom.ConfigMapKeyRef not specified", func(t *testing.T) {
|
||||||
|
c := &v1alpha1.GitHubServerTLSConfig{
|
||||||
|
CertificateFrom: &v1alpha1.TLSCertificateSource{},
|
||||||
|
}
|
||||||
|
|
||||||
|
pool, err := c.ToCertPool(nil)
|
||||||
|
assert.Nil(t, pool)
|
||||||
|
|
||||||
|
require.Error(t, err)
|
||||||
|
assert.Equal(t, err.Error(), "configMapKeyRef not specified")
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("returns a valid cert pool with correct configuration", func(t *testing.T) {
|
||||||
|
c := &v1alpha1.GitHubServerTLSConfig{
|
||||||
|
CertificateFrom: &v1alpha1.TLSCertificateSource{
|
||||||
|
ConfigMapKeyRef: &v1.ConfigMapKeySelector{
|
||||||
|
LocalObjectReference: v1.LocalObjectReference{
|
||||||
|
Name: "name",
|
||||||
|
},
|
||||||
|
Key: "key",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
certsFolder := filepath.Join(
|
||||||
|
"../../../",
|
||||||
|
"github",
|
||||||
|
"actions",
|
||||||
|
"testdata",
|
||||||
|
)
|
||||||
|
|
||||||
|
fetcher := func(name, key string) ([]byte, error) {
|
||||||
|
cert, err := os.ReadFile(filepath.Join(certsFolder, "rootCA.crt"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
pool := x509.NewCertPool()
|
||||||
|
ok := pool.AppendCertsFromPEM(cert)
|
||||||
|
assert.True(t, ok)
|
||||||
|
|
||||||
|
return cert, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
pool, err := c.ToCertPool(fetcher)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, pool)
|
||||||
|
|
||||||
|
// can be used to communicate with a server
|
||||||
|
serverSuccessfullyCalled := false
|
||||||
|
server := testserver.NewUnstarted(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
serverSuccessfullyCalled = true
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
}))
|
||||||
|
|
||||||
|
cert, err := tls.LoadX509KeyPair(
|
||||||
|
filepath.Join(certsFolder, "server.crt"),
|
||||||
|
filepath.Join(certsFolder, "server.key"),
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
server.TLS = &tls.Config{Certificates: []tls.Certificate{cert}}
|
||||||
|
server.StartTLS()
|
||||||
|
|
||||||
|
client := &http.Client{
|
||||||
|
Transport: &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{
|
||||||
|
RootCAs: pool,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = client.Get(server.URL)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.True(t, serverSuccessfullyCalled)
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -98,6 +98,11 @@ func (in *AutoscalingListenerSpec) DeepCopyInto(out *AutoscalingListenerSpec) {
|
|||||||
*out = new(ProxyConfig)
|
*out = new(ProxyConfig)
|
||||||
(*in).DeepCopyInto(*out)
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
|
if in.GitHubServerTLS != nil {
|
||||||
|
in, out := &in.GitHubServerTLS, &out.GitHubServerTLS
|
||||||
|
*out = new(GitHubServerTLSConfig)
|
||||||
|
(*in).DeepCopyInto(*out)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AutoscalingListenerSpec.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AutoscalingListenerSpec.
|
||||||
@@ -195,7 +200,7 @@ func (in *AutoscalingRunnerSetSpec) DeepCopyInto(out *AutoscalingRunnerSetSpec)
|
|||||||
if in.GitHubServerTLS != nil {
|
if in.GitHubServerTLS != nil {
|
||||||
in, out := &in.GitHubServerTLS, &out.GitHubServerTLS
|
in, out := &in.GitHubServerTLS, &out.GitHubServerTLS
|
||||||
*out = new(GitHubServerTLSConfig)
|
*out = new(GitHubServerTLSConfig)
|
||||||
**out = **in
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
in.Template.DeepCopyInto(&out.Template)
|
in.Template.DeepCopyInto(&out.Template)
|
||||||
if in.MaxRunners != nil {
|
if in.MaxRunners != nil {
|
||||||
@@ -395,7 +400,7 @@ func (in *EphemeralRunnerSpec) DeepCopyInto(out *EphemeralRunnerSpec) {
|
|||||||
if in.GitHubServerTLS != nil {
|
if in.GitHubServerTLS != nil {
|
||||||
in, out := &in.GitHubServerTLS, &out.GitHubServerTLS
|
in, out := &in.GitHubServerTLS, &out.GitHubServerTLS
|
||||||
*out = new(GitHubServerTLSConfig)
|
*out = new(GitHubServerTLSConfig)
|
||||||
**out = **in
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
in.PodTemplateSpec.DeepCopyInto(&out.PodTemplateSpec)
|
in.PodTemplateSpec.DeepCopyInto(&out.PodTemplateSpec)
|
||||||
}
|
}
|
||||||
@@ -435,6 +440,11 @@ func (in *EphemeralRunnerStatus) DeepCopy() *EphemeralRunnerStatus {
|
|||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *GitHubServerTLSConfig) DeepCopyInto(out *GitHubServerTLSConfig) {
|
func (in *GitHubServerTLSConfig) DeepCopyInto(out *GitHubServerTLSConfig) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
if in.CertificateFrom != nil {
|
||||||
|
in, out := &in.CertificateFrom, &out.CertificateFrom
|
||||||
|
*out = new(TLSCertificateSource)
|
||||||
|
(*in).DeepCopyInto(*out)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubServerTLSConfig.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitHubServerTLSConfig.
|
||||||
@@ -491,3 +501,23 @@ func (in *ProxyServerConfig) DeepCopy() *ProxyServerConfig {
|
|||||||
in.DeepCopyInto(out)
|
in.DeepCopyInto(out)
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *TLSCertificateSource) DeepCopyInto(out *TLSCertificateSource) {
|
||||||
|
*out = *in
|
||||||
|
if in.ConfigMapKeyRef != nil {
|
||||||
|
in, out := &in.ConfigMapKeyRef, &out.ConfigMapKeyRef
|
||||||
|
*out = new(v1.ConfigMapKeySelector)
|
||||||
|
(*in).DeepCopyInto(*out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSCertificateSource.
|
||||||
|
func (in *TLSCertificateSource) DeepCopy() *TLSCertificateSource {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(TLSCertificateSource)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
# This file defines the config for "ct" (chart tester) used by the helm linting GitHub workflow
|
# This file defines the config for "ct" (chart tester) used by the helm linting GitHub workflow
|
||||||
all: true
|
|
||||||
lint-conf: charts/.ci/lint-config.yaml
|
lint-conf: charts/.ci/lint-config.yaml
|
||||||
chart-repos:
|
chart-repos:
|
||||||
- jetstack=https://charts.jetstack.io
|
- jetstack=https://charts.jetstack.io
|
||||||
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/actions-runner-controller
|
||||||
|
|||||||
@@ -1,97 +0,0 @@
|
|||||||
{{/*
|
|
||||||
Expand the name of the chart.
|
|
||||||
*/}}
|
|
||||||
{{- define "actions-runner-controller-2.name" -}}
|
|
||||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Create a default fully qualified app name.
|
|
||||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
|
||||||
If release name contains chart name it will be used as a full name.
|
|
||||||
*/}}
|
|
||||||
{{- define "actions-runner-controller-2.fullname" -}}
|
|
||||||
{{- if .Values.fullnameOverride }}
|
|
||||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- else }}
|
|
||||||
{{- $name := default .Chart.Name .Values.nameOverride }}
|
|
||||||
{{- if contains $name .Release.Name }}
|
|
||||||
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- else }}
|
|
||||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Create chart name and version as used by the chart label.
|
|
||||||
*/}}
|
|
||||||
{{- define "actions-runner-controller-2.chart" -}}
|
|
||||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Common labels
|
|
||||||
*/}}
|
|
||||||
{{- define "actions-runner-controller-2.labels" -}}
|
|
||||||
helm.sh/chart: {{ include "actions-runner-controller-2.chart" . }}
|
|
||||||
{{ include "actions-runner-controller-2.selectorLabels" . }}
|
|
||||||
{{- if .Chart.AppVersion }}
|
|
||||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
|
||||||
{{- end }}
|
|
||||||
app.kubernetes.io/part-of: {{ .Chart.Name }}
|
|
||||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
|
||||||
{{- range $k, $v := .Values.labels }}
|
|
||||||
{{ $k }}: {{ $v }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Selector labels
|
|
||||||
*/}}
|
|
||||||
{{- define "actions-runner-controller-2.selectorLabels" -}}
|
|
||||||
app.kubernetes.io/name: {{ include "actions-runner-controller-2.name" . }}
|
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Create the name of the service account to use
|
|
||||||
*/}}
|
|
||||||
{{- define "actions-runner-controller-2.serviceAccountName" -}}
|
|
||||||
{{- if eq .Values.serviceAccount.name "default"}}
|
|
||||||
{{- fail "serviceAccount.name cannot be set to 'default'" }}
|
|
||||||
{{- end }}
|
|
||||||
{{- if .Values.serviceAccount.create }}
|
|
||||||
{{- default (include "actions-runner-controller-2.fullname" .) .Values.serviceAccount.name }}
|
|
||||||
{{- else }}
|
|
||||||
{{- if not .Values.serviceAccount.name }}
|
|
||||||
{{- fail "serviceAccount.name must be set if serviceAccount.create is false" }}
|
|
||||||
{{- else }}
|
|
||||||
{{- .Values.serviceAccount.name }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{- define "actions-runner-controller-2.managerRoleName" -}}
|
|
||||||
{{- include "actions-runner-controller-2.fullname" . }}-manager-role
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{- define "actions-runner-controller-2.managerRoleBinding" -}}
|
|
||||||
{{- include "actions-runner-controller-2.fullname" . }}-manager-rolebinding
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{- define "actions-runner-controller-2.leaderElectionRoleName" -}}
|
|
||||||
{{- include "actions-runner-controller-2.fullname" . }}-leader-election-role
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{- define "actions-runner-controller-2.leaderElectionRoleBinding" -}}
|
|
||||||
{{- include "actions-runner-controller-2.fullname" . }}-leader-election-rolebinding
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{- define "actions-runner-controller-2.imagePullSecretsNames" -}}
|
|
||||||
{{- $names := list }}
|
|
||||||
{{- range $k, $v := . }}
|
|
||||||
{{- $names = append $names $v.name }}
|
|
||||||
{{- end }}
|
|
||||||
{{- $names | join ","}}
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
{{- if gt (int (default 1 .Values.replicaCount)) 1 -}}
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
kind: RoleBinding
|
|
||||||
metadata:
|
|
||||||
name: {{ include "actions-runner-controller-2.leaderElectionRoleBinding" . }}
|
|
||||||
namespace: {{ .Release.Namespace }}
|
|
||||||
roleRef:
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
kind: Role
|
|
||||||
name: {{ include "actions-runner-controller-2.leaderElectionRoleName" . }}
|
|
||||||
subjects:
|
|
||||||
- kind: ServiceAccount
|
|
||||||
name: {{ include "actions-runner-controller-2.serviceAccountName" . }}
|
|
||||||
namespace: {{ .Release.Namespace }}
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
kind: ClusterRoleBinding
|
|
||||||
metadata:
|
|
||||||
name: {{ include "actions-runner-controller-2.managerRoleBinding" . }}
|
|
||||||
roleRef:
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
kind: ClusterRole
|
|
||||||
name: {{ include "actions-runner-controller-2.managerRoleName" . }}
|
|
||||||
subjects:
|
|
||||||
- kind: ServiceAccount
|
|
||||||
name: {{ include "actions-runner-controller-2.serviceAccountName" . }}
|
|
||||||
namespace: {{ .Release.Namespace }}
|
|
||||||
@@ -1,533 +0,0 @@
|
|||||||
package tests
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/gruntwork-io/terratest/modules/helm"
|
|
||||||
"github.com/gruntwork-io/terratest/modules/k8s"
|
|
||||||
"github.com/gruntwork-io/terratest/modules/random"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
"gopkg.in/yaml.v2"
|
|
||||||
appsv1 "k8s.io/api/apps/v1"
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
|
||||||
rbacv1 "k8s.io/api/rbac/v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Chart struct {
|
|
||||||
Version string `yaml:"version"`
|
|
||||||
AppVersion string `yaml:"appVersion"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplate_CreateServiceAccount(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../actions-runner-controller-2")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
releaseName := "test-arc"
|
|
||||||
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
|
||||||
|
|
||||||
options := &helm.Options{
|
|
||||||
SetValues: map[string]string{
|
|
||||||
"serviceAccount.create": "true",
|
|
||||||
"serviceAccount.annotations.foo": "bar",
|
|
||||||
},
|
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
|
||||||
}
|
|
||||||
|
|
||||||
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/serviceaccount.yaml"})
|
|
||||||
|
|
||||||
var serviceAccount corev1.ServiceAccount
|
|
||||||
helm.UnmarshalK8SYaml(t, output, &serviceAccount)
|
|
||||||
|
|
||||||
assert.Equal(t, namespaceName, serviceAccount.Namespace)
|
|
||||||
assert.Equal(t, "test-arc-actions-runner-controller-2", serviceAccount.Name)
|
|
||||||
assert.Equal(t, "bar", string(serviceAccount.Annotations["foo"]))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplate_CreateServiceAccount_OverwriteName(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../actions-runner-controller-2")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
releaseName := "test-arc"
|
|
||||||
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
|
||||||
|
|
||||||
options := &helm.Options{
|
|
||||||
SetValues: map[string]string{
|
|
||||||
"serviceAccount.create": "true",
|
|
||||||
"serviceAccount.name": "overwritten-name",
|
|
||||||
"serviceAccount.annotations.foo": "bar",
|
|
||||||
},
|
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
|
||||||
}
|
|
||||||
|
|
||||||
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/serviceaccount.yaml"})
|
|
||||||
|
|
||||||
var serviceAccount corev1.ServiceAccount
|
|
||||||
helm.UnmarshalK8SYaml(t, output, &serviceAccount)
|
|
||||||
|
|
||||||
assert.Equal(t, namespaceName, serviceAccount.Namespace)
|
|
||||||
assert.Equal(t, "overwritten-name", serviceAccount.Name)
|
|
||||||
assert.Equal(t, "bar", string(serviceAccount.Annotations["foo"]))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplate_CreateServiceAccount_CannotUseDefaultServiceAccount(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../actions-runner-controller-2")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
releaseName := "test-arc"
|
|
||||||
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
|
||||||
|
|
||||||
options := &helm.Options{
|
|
||||||
SetValues: map[string]string{
|
|
||||||
"serviceAccount.create": "true",
|
|
||||||
"serviceAccount.name": "default",
|
|
||||||
"serviceAccount.annotations.foo": "bar",
|
|
||||||
},
|
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = helm.RenderTemplateE(t, options, helmChartPath, releaseName, []string{"templates/serviceaccount.yaml"})
|
|
||||||
assert.ErrorContains(t, err, "serviceAccount.name cannot be set to 'default'", "We should get an error because the default service account cannot be used")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplate_NotCreateServiceAccount(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../actions-runner-controller-2")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
releaseName := "test-arc"
|
|
||||||
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
|
||||||
|
|
||||||
options := &helm.Options{
|
|
||||||
SetValues: map[string]string{
|
|
||||||
"serviceAccount.create": "false",
|
|
||||||
"serviceAccount.name": "overwritten-name",
|
|
||||||
"serviceAccount.annotations.foo": "bar",
|
|
||||||
},
|
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = helm.RenderTemplateE(t, options, helmChartPath, releaseName, []string{"templates/serviceaccount.yaml"})
|
|
||||||
assert.ErrorContains(t, err, "could not find template templates/serviceaccount.yaml in chart", "We should get an error because the template should be skipped")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplate_NotCreateServiceAccount_ServiceAccountNotSet(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../actions-runner-controller-2")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
releaseName := "test-arc"
|
|
||||||
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
|
||||||
|
|
||||||
options := &helm.Options{
|
|
||||||
SetValues: map[string]string{
|
|
||||||
"serviceAccount.create": "false",
|
|
||||||
"serviceAccount.annotations.foo": "bar",
|
|
||||||
},
|
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = helm.RenderTemplateE(t, options, helmChartPath, releaseName, []string{"templates/deployment.yaml"})
|
|
||||||
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) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../actions-runner-controller-2")
|
|
||||||
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_role.yaml"})
|
|
||||||
|
|
||||||
var managerRole rbacv1.ClusterRole
|
|
||||||
helm.UnmarshalK8SYaml(t, output, &managerRole)
|
|
||||||
|
|
||||||
assert.Empty(t, managerRole.Namespace, "ClusterRole should not have a namespace")
|
|
||||||
assert.Equal(t, "test-arc-actions-runner-controller-2-manager-role", managerRole.Name)
|
|
||||||
assert.Equal(t, 17, len(managerRole.Rules))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplate_ManagerRoleBinding(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../actions-runner-controller-2")
|
|
||||||
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_role_binding.yaml"})
|
|
||||||
|
|
||||||
var managerRoleBinding rbacv1.ClusterRoleBinding
|
|
||||||
helm.UnmarshalK8SYaml(t, output, &managerRoleBinding)
|
|
||||||
|
|
||||||
assert.Empty(t, managerRoleBinding.Namespace, "ClusterRoleBinding should not have a namespace")
|
|
||||||
assert.Equal(t, "test-arc-actions-runner-controller-2-manager-rolebinding", managerRoleBinding.Name)
|
|
||||||
assert.Equal(t, "test-arc-actions-runner-controller-2-manager-role", managerRoleBinding.RoleRef.Name)
|
|
||||||
assert.Equal(t, "test-arc-actions-runner-controller-2", managerRoleBinding.Subjects[0].Name)
|
|
||||||
assert.Equal(t, namespaceName, managerRoleBinding.Subjects[0].Namespace)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplate_ControllerDeployment_Defaults(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../actions-runner-controller-2")
|
|
||||||
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",
|
|
||||||
},
|
|
||||||
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-actions-runner-controller-2", deployment.Name)
|
|
||||||
assert.Equal(t, "actions-runner-controller-2-"+chart.Version, deployment.Labels["helm.sh/chart"])
|
|
||||||
assert.Equal(t, "actions-runner-controller-2", 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, int32(1), *deployment.Spec.Replicas)
|
|
||||||
|
|
||||||
assert.Equal(t, "actions-runner-controller-2", deployment.Spec.Selector.MatchLabels["app.kubernetes.io/name"])
|
|
||||||
assert.Equal(t, "test-arc", deployment.Spec.Selector.MatchLabels["app.kubernetes.io/instance"])
|
|
||||||
|
|
||||||
assert.Equal(t, "actions-runner-controller-2", 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-actions-runner-controller-2", 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)
|
|
||||||
|
|
||||||
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/actions-runner-controller-2: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, 2)
|
|
||||||
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.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, "metadata.name", deployment.Spec.Template.Spec.Containers[0].Env[0].ValueFrom.FieldRef.FieldPath)
|
|
||||||
|
|
||||||
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_ControllerDeployment_Customize(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../actions-runner-controller-2")
|
|
||||||
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{
|
|
||||||
"labels.foo": "bar",
|
|
||||||
"labels.github": "actions",
|
|
||||||
"replicaCount": "1",
|
|
||||||
"image.pullPolicy": "Always",
|
|
||||||
"image.tag": "dev",
|
|
||||||
"imagePullSecrets[0].name": "dockerhub",
|
|
||||||
"nameOverride": "actions-runner-controller-2-override",
|
|
||||||
"fullnameOverride": "actions-runner-controller-2-fullname-override",
|
|
||||||
"serviceAccount.name": "actions-runner-controller-2-sa",
|
|
||||||
"podAnnotations.foo": "bar",
|
|
||||||
"podSecurityContext.fsGroup": "1000",
|
|
||||||
"securityContext.runAsUser": "1000",
|
|
||||||
"securityContext.runAsNonRoot": "true",
|
|
||||||
"resources.limits.cpu": "500m",
|
|
||||||
"nodeSelector.foo": "bar",
|
|
||||||
"tolerations[0].key": "foo",
|
|
||||||
"affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[0].matchExpressions[0].key": "foo",
|
|
||||||
"affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[0].matchExpressions[0].operator": "bar",
|
|
||||||
"priorityClassName": "test-priority-class",
|
|
||||||
},
|
|
||||||
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, "actions-runner-controller-2-fullname-override", deployment.Name)
|
|
||||||
assert.Equal(t, "actions-runner-controller-2-"+chart.Version, deployment.Labels["helm.sh/chart"])
|
|
||||||
assert.Equal(t, "actions-runner-controller-2-override", 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, "bar", deployment.Labels["foo"])
|
|
||||||
assert.Equal(t, "actions", deployment.Labels["github"])
|
|
||||||
|
|
||||||
assert.Equal(t, int32(1), *deployment.Spec.Replicas)
|
|
||||||
|
|
||||||
assert.Equal(t, "actions-runner-controller-2-override", deployment.Spec.Selector.MatchLabels["app.kubernetes.io/name"])
|
|
||||||
assert.Equal(t, "test-arc", deployment.Spec.Selector.MatchLabels["app.kubernetes.io/instance"])
|
|
||||||
|
|
||||||
assert.Equal(t, "actions-runner-controller-2-override", deployment.Spec.Template.Labels["app.kubernetes.io/name"])
|
|
||||||
assert.Equal(t, "test-arc", deployment.Spec.Template.Labels["app.kubernetes.io/instance"])
|
|
||||||
|
|
||||||
assert.Equal(t, "bar", deployment.Spec.Template.Annotations["foo"])
|
|
||||||
assert.Equal(t, "manager", deployment.Spec.Template.Annotations["kubectl.kubernetes.io/default-container"])
|
|
||||||
|
|
||||||
assert.Len(t, deployment.Spec.Template.Spec.ImagePullSecrets, 1)
|
|
||||||
assert.Equal(t, "dockerhub", deployment.Spec.Template.Spec.ImagePullSecrets[0].Name)
|
|
||||||
assert.Equal(t, "actions-runner-controller-2-sa", deployment.Spec.Template.Spec.ServiceAccountName)
|
|
||||||
assert.Equal(t, int64(1000), *deployment.Spec.Template.Spec.SecurityContext.FSGroup)
|
|
||||||
assert.Equal(t, "test-priority-class", 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, 1)
|
|
||||||
assert.Equal(t, "bar", deployment.Spec.Template.Spec.NodeSelector["foo"])
|
|
||||||
|
|
||||||
assert.NotNil(t, deployment.Spec.Template.Spec.Affinity.NodeAffinity)
|
|
||||||
assert.Equal(t, "foo", deployment.Spec.Template.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms[0].MatchExpressions[0].Key)
|
|
||||||
assert.Equal(t, "bar", string(deployment.Spec.Template.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms[0].MatchExpressions[0].Operator))
|
|
||||||
|
|
||||||
assert.Len(t, deployment.Spec.Template.Spec.Tolerations, 1)
|
|
||||||
assert.Equal(t, "foo", deployment.Spec.Template.Spec.Tolerations[0].Key)
|
|
||||||
|
|
||||||
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/actions-runner-controller-2:dev", deployment.Spec.Template.Spec.Containers[0].Image)
|
|
||||||
assert.Equal(t, corev1.PullAlways, 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, "--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.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, "metadata.name", deployment.Spec.Template.Spec.Containers[0].Env[0].ValueFrom.FieldRef.FieldPath)
|
|
||||||
|
|
||||||
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, "500m", deployment.Spec.Template.Spec.Containers[0].Resources.Limits.Cpu().String())
|
|
||||||
assert.True(t, *deployment.Spec.Template.Spec.Containers[0].SecurityContext.RunAsNonRoot)
|
|
||||||
assert.Equal(t, int64(1000), *deployment.Spec.Template.Spec.Containers[0].SecurityContext.RunAsUser)
|
|
||||||
|
|
||||||
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_EnableLeaderElectionRole(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../actions-runner-controller-2")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
releaseName := "test-arc"
|
|
||||||
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
|
||||||
|
|
||||||
options := &helm.Options{
|
|
||||||
SetValues: map[string]string{
|
|
||||||
"replicaCount": "2",
|
|
||||||
},
|
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
|
||||||
}
|
|
||||||
|
|
||||||
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/leader_election_role.yaml"})
|
|
||||||
|
|
||||||
var leaderRole rbacv1.Role
|
|
||||||
helm.UnmarshalK8SYaml(t, output, &leaderRole)
|
|
||||||
|
|
||||||
assert.Equal(t, "test-arc-actions-runner-controller-2-leader-election-role", leaderRole.Name)
|
|
||||||
assert.Equal(t, namespaceName, leaderRole.Namespace)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplate_EnableLeaderElectionRoleBinding(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../actions-runner-controller-2")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
releaseName := "test-arc"
|
|
||||||
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
|
||||||
|
|
||||||
options := &helm.Options{
|
|
||||||
SetValues: map[string]string{
|
|
||||||
"replicaCount": "2",
|
|
||||||
},
|
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
|
||||||
}
|
|
||||||
|
|
||||||
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/leader_election_role_binding.yaml"})
|
|
||||||
|
|
||||||
var leaderRoleBinding rbacv1.RoleBinding
|
|
||||||
helm.UnmarshalK8SYaml(t, output, &leaderRoleBinding)
|
|
||||||
|
|
||||||
assert.Equal(t, "test-arc-actions-runner-controller-2-leader-election-rolebinding", leaderRoleBinding.Name)
|
|
||||||
assert.Equal(t, namespaceName, leaderRoleBinding.Namespace)
|
|
||||||
assert.Equal(t, "test-arc-actions-runner-controller-2-leader-election-role", leaderRoleBinding.RoleRef.Name)
|
|
||||||
assert.Equal(t, "test-arc-actions-runner-controller-2", leaderRoleBinding.Subjects[0].Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplate_EnableLeaderElection(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../actions-runner-controller-2")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
releaseName := "test-arc"
|
|
||||||
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
|
||||||
|
|
||||||
options := &helm.Options{
|
|
||||||
SetValues: map[string]string{
|
|
||||||
"replicaCount": "2",
|
|
||||||
"image.tag": "dev",
|
|
||||||
},
|
|
||||||
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-actions-runner-controller-2", deployment.Name)
|
|
||||||
|
|
||||||
assert.Equal(t, int32(2), *deployment.Spec.Replicas)
|
|
||||||
|
|
||||||
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/actions-runner-controller-2: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, 4)
|
|
||||||
assert.Equal(t, "--auto-scaling-runner-set-only", deployment.Spec.Template.Spec.Containers[0].Args[0])
|
|
||||||
assert.Equal(t, "--enable-leader-election", deployment.Spec.Template.Spec.Containers[0].Args[1])
|
|
||||||
assert.Equal(t, "--leader-election-id=test-arc-actions-runner-controller-2", deployment.Spec.Template.Spec.Containers[0].Args[2])
|
|
||||||
assert.Equal(t, "--log-level=debug", deployment.Spec.Template.Spec.Containers[0].Args[3])
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplate_ControllerDeployment_ForwardImagePullSecrets(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../actions-runner-controller-2")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
releaseName := "test-arc"
|
|
||||||
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
|
||||||
|
|
||||||
options := &helm.Options{
|
|
||||||
SetValues: map[string]string{
|
|
||||||
"imagePullSecrets[0].name": "dockerhub",
|
|
||||||
"imagePullSecrets[1].name": "ghcr",
|
|
||||||
},
|
|
||||||
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.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, "--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])
|
|
||||||
}
|
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ spec:
|
|||||||
metadata:
|
metadata:
|
||||||
{{- with .Values.actionsMetricsServer.podAnnotations }}
|
{{- with .Values.actionsMetricsServer.podAnnotations }}
|
||||||
annotations:
|
annotations:
|
||||||
kubectl.kubernetes.io/default-logs-container: "github-webhook-server"
|
kubectl.kubernetes.io/default-container: "actions-metrics-server"
|
||||||
{{- toYaml . | nindent 8 }}
|
{{- toYaml . | nindent 8 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
labels:
|
labels:
|
||||||
@@ -45,7 +45,7 @@ spec:
|
|||||||
{{- if .Values.runnerGithubURL }}
|
{{- if .Values.runnerGithubURL }}
|
||||||
- "--runner-github-url={{ .Values.runnerGithubURL }}"
|
- "--runner-github-url={{ .Values.runnerGithubURL }}"
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if .Values.actionsMetricsServer.logFormat }}
|
{{- if .Values.actionsMetricsServer.logFormat }}
|
||||||
- "--log-format={{ .Values.actionsMetricsServer.logFormat }}"
|
- "--log-format={{ .Values.actionsMetricsServer.logFormat }}"
|
||||||
{{- end }}
|
{{- end }}
|
||||||
command:
|
command:
|
||||||
@@ -74,25 +74,25 @@ spec:
|
|||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
key: github_token
|
key: github_token
|
||||||
name: {{ include "actions-runner-controller.githubWebhookServerSecretName" . }}
|
name: {{ include "actions-runner-controller-actions-metrics-server.secretName" . }}
|
||||||
optional: true
|
optional: true
|
||||||
- name: GITHUB_APP_ID
|
- name: GITHUB_APP_ID
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
key: github_app_id
|
key: github_app_id
|
||||||
name: {{ include "actions-runner-controller.githubWebhookServerSecretName" . }}
|
name: {{ include "actions-runner-controller-actions-metrics-server.secretName" . }}
|
||||||
optional: true
|
optional: true
|
||||||
- name: GITHUB_APP_INSTALLATION_ID
|
- name: GITHUB_APP_INSTALLATION_ID
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
key: github_app_installation_id
|
key: github_app_installation_id
|
||||||
name: {{ include "actions-runner-controller.githubWebhookServerSecretName" . }}
|
name: {{ include "actions-runner-controller-actions-metrics-server.secretName" . }}
|
||||||
optional: true
|
optional: true
|
||||||
- name: GITHUB_APP_PRIVATE_KEY
|
- name: GITHUB_APP_PRIVATE_KEY
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
key: github_app_private_key
|
key: github_app_private_key
|
||||||
name: {{ include "actions-runner-controller.githubWebhookServerSecretName" . }}
|
name: {{ include "actions-runner-controller-actions-metrics-server.secretName" . }}
|
||||||
optional: true
|
optional: true
|
||||||
{{- if .Values.authSecret.github_basicauth_username }}
|
{{- if .Values.authSecret.github_basicauth_username }}
|
||||||
- name: GITHUB_BASICAUTH_USERNAME
|
- name: GITHUB_BASICAUTH_USERNAME
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
{{- if .Values.actionsMetricsServer.enabled }}
|
||||||
|
{{- if .Values.actionsMetricsServer.secret.create }}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: {{ include "actions-runner-controller-actions-metrics-server.secretName" . }}
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
|
labels:
|
||||||
|
{{- include "actions-runner-controller.labels" . | nindent 4 }}
|
||||||
|
type: Opaque
|
||||||
|
data:
|
||||||
|
{{- if .Values.actionsMetricsServer.secret.github_webhook_secret_token }}
|
||||||
|
github_webhook_secret_token: {{ .Values.actionsMetricsServer.secret.github_webhook_secret_token | toString | b64enc }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.actionsMetricsServer.secret.github_app_id }}
|
||||||
|
github_app_id: {{ .Values.actionsMetricsServer.secret.github_app_id | toString | b64enc }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.actionsMetricsServer.secret.github_app_installation_id }}
|
||||||
|
github_app_installation_id: {{ .Values.actionsMetricsServer.secret.github_app_installation_id | toString | b64enc }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.actionsMetricsServer.secret.github_app_private_key }}
|
||||||
|
github_app_private_key: {{ .Values.actionsMetricsServer.secret.github_app_private_key | toString | b64enc }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.actionsMetricsServer.secret.github_token }}
|
||||||
|
github_token: {{ .Values.actionsMetricsServer.secret.github_token | toString | b64enc }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
@@ -51,11 +51,17 @@ spec:
|
|||||||
{{- if .Values.githubWebhookServer.queueLimit }}
|
{{- if .Values.githubWebhookServer.queueLimit }}
|
||||||
- "--queue-limit={{ .Values.githubWebhookServer.queueLimit }}"
|
- "--queue-limit={{ .Values.githubWebhookServer.queueLimit }}"
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if .Values.githubWebhookServer.logFormat }}
|
{{- if .Values.githubWebhookServer.logFormat }}
|
||||||
- "--log-format={{ .Values.githubWebhookServer.logFormat }}"
|
- "--log-format={{ .Values.githubWebhookServer.logFormat }}"
|
||||||
{{- end }}
|
{{- end }}
|
||||||
command:
|
command:
|
||||||
- "/github-webhook-server"
|
- "/github-webhook-server"
|
||||||
|
{{- if .Values.githubWebhookServer.lifecycle }}
|
||||||
|
{{- with .Values.githubWebhookServer.lifecycle }}
|
||||||
|
lifecycle:
|
||||||
|
{{- toYaml . | nindent 10 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
env:
|
env:
|
||||||
- name: GITHUB_WEBHOOK_SECRET_TOKEN
|
- name: GITHUB_WEBHOOK_SECRET_TOKEN
|
||||||
valueFrom:
|
valueFrom:
|
||||||
@@ -111,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 }}
|
||||||
@@ -148,7 +158,7 @@ spec:
|
|||||||
securityContext:
|
securityContext:
|
||||||
{{- toYaml .Values.securityContext | nindent 12 }}
|
{{- toYaml .Values.securityContext | nindent 12 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
terminationGracePeriodSeconds: 10
|
terminationGracePeriodSeconds: {{ .Values.githubWebhookServer.terminationGracePeriodSeconds }}
|
||||||
{{- with .Values.githubWebhookServer.nodeSelector }}
|
{{- with .Values.githubWebhookServer.nodeSelector }}
|
||||||
nodeSelector:
|
nodeSelector:
|
||||||
{{- toYaml . | nindent 8 }}
|
{{- toYaml . | nindent 8 }}
|
||||||
|
|||||||
@@ -23,4 +23,10 @@ spec:
|
|||||||
{{- end }}
|
{{- end }}
|
||||||
selector:
|
selector:
|
||||||
{{- include "actions-runner-controller-github-webhook-server.selectorLabels" . | nindent 4 }}
|
{{- include "actions-runner-controller-github-webhook-server.selectorLabels" . | nindent 4 }}
|
||||||
|
{{- if .Values.githubWebhookServer.service.loadBalancerSourceRanges }}
|
||||||
|
loadBalancerSourceRanges:
|
||||||
|
{{- range $ip := .Values.githubWebhookServer.service.loadBalancerSourceRanges }}
|
||||||
|
- {{ $ip -}}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -240,6 +240,7 @@ githubWebhookServer:
|
|||||||
protocol: TCP
|
protocol: TCP
|
||||||
name: http
|
name: http
|
||||||
#nodePort: someFixedPortForUseWithTerraformCdkCfnEtc
|
#nodePort: someFixedPortForUseWithTerraformCdkCfnEtc
|
||||||
|
loadBalancerSourceRanges: []
|
||||||
ingress:
|
ingress:
|
||||||
enabled: false
|
enabled: false
|
||||||
ingressClassName: ""
|
ingressClassName: ""
|
||||||
@@ -276,6 +277,21 @@ githubWebhookServer:
|
|||||||
# minAvailable: 1
|
# minAvailable: 1
|
||||||
# maxUnavailable: 3
|
# maxUnavailable: 3
|
||||||
# queueLimit: 100
|
# queueLimit: 100
|
||||||
|
terminationGracePeriodSeconds: 10
|
||||||
|
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: {}
|
||||||
|
|||||||
@@ -1,330 +0,0 @@
|
|||||||
{{/*
|
|
||||||
Expand the name of the chart.
|
|
||||||
*/}}
|
|
||||||
{{- define "auto-scaling-runner-set.name" -}}
|
|
||||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Create a default fully qualified app name.
|
|
||||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
|
||||||
If release name contains chart name it will be used as a full name.
|
|
||||||
*/}}
|
|
||||||
{{- define "auto-scaling-runner-set.fullname" -}}
|
|
||||||
{{- if .Values.fullnameOverride }}
|
|
||||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- else }}
|
|
||||||
{{- $name := default .Chart.Name .Values.nameOverride }}
|
|
||||||
{{- if contains $name .Release.Name }}
|
|
||||||
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- else }}
|
|
||||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Create chart name and version as used by the chart label.
|
|
||||||
*/}}
|
|
||||||
{{- define "auto-scaling-runner-set.chart" -}}
|
|
||||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Common labels
|
|
||||||
*/}}
|
|
||||||
{{- define "auto-scaling-runner-set.labels" -}}
|
|
||||||
helm.sh/chart: {{ include "auto-scaling-runner-set.chart" . }}
|
|
||||||
{{ include "auto-scaling-runner-set.selectorLabels" . }}
|
|
||||||
{{- if .Chart.AppVersion }}
|
|
||||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
|
||||||
{{- end }}
|
|
||||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Selector labels
|
|
||||||
*/}}
|
|
||||||
{{- define "auto-scaling-runner-set.selectorLabels" -}}
|
|
||||||
app.kubernetes.io/name: {{ include "auto-scaling-runner-set.name" . }}
|
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{- define "auto-scaling-runner-set.githubsecret" -}}
|
|
||||||
{{- if kindIs "string" .Values.githubConfigSecret }}
|
|
||||||
{{- if not (empty .Values.githubConfigSecret) }}
|
|
||||||
{{- .Values.githubConfigSecret }}
|
|
||||||
{{- else}}
|
|
||||||
{{- fail "Values.githubConfigSecret is required for setting auth with GitHub server." }}
|
|
||||||
{{- end }}
|
|
||||||
{{- else }}
|
|
||||||
{{- include "auto-scaling-runner-set.fullname" . }}-github-secret
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{- define "auto-scaling-runner-set.noPermissionServiceAccountName" -}}
|
|
||||||
{{- include "auto-scaling-runner-set.fullname" . }}-no-permission-service-account
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{- define "auto-scaling-runner-set.kubeModeRoleName" -}}
|
|
||||||
{{- include "auto-scaling-runner-set.fullname" . }}-kube-mode-role
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{- define "auto-scaling-runner-set.kubeModeServiceAccountName" -}}
|
|
||||||
{{- include "auto-scaling-runner-set.fullname" . }}-kube-mode-service-account
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{- define "auto-scaling-runner-set.dind-init-container" -}}
|
|
||||||
{{- range $i, $val := .Values.template.spec.containers -}}
|
|
||||||
{{- if eq $val.name "runner" -}}
|
|
||||||
image: {{ $val.image }}
|
|
||||||
{{- if $val.imagePullSecrets }}
|
|
||||||
imagePullSecrets:
|
|
||||||
{{ $val.imagePullSecrets | toYaml -}}
|
|
||||||
{{- end }}
|
|
||||||
command: ["cp"]
|
|
||||||
args: ["-r", "-v", "/actions-runner/externals/.", "/actions-runner/tmpDir/"]
|
|
||||||
volumeMounts:
|
|
||||||
- name: dind-externals
|
|
||||||
mountPath: /actions-runner/tmpDir
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{- define "auto-scaling-runner-set.dind-container" -}}
|
|
||||||
image: docker:dind
|
|
||||||
securityContext:
|
|
||||||
privileged: true
|
|
||||||
volumeMounts:
|
|
||||||
- name: work
|
|
||||||
mountPath: /actions-runner/_work
|
|
||||||
- name: dind-cert
|
|
||||||
mountPath: /certs/client
|
|
||||||
- name: dind-externals
|
|
||||||
mountPath: /actions-runner/externals
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{- define "auto-scaling-runner-set.dind-volume" -}}
|
|
||||||
- name: dind-cert
|
|
||||||
emptyDir: {}
|
|
||||||
- name: dind-externals
|
|
||||||
emptyDir: {}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{- define "auto-scaling-runner-set.dind-work-volume" -}}
|
|
||||||
{{- $createWorkVolume := 1 }}
|
|
||||||
{{- range $i, $volume := .Values.template.spec.volumes }}
|
|
||||||
{{- if eq $volume.name "work" }}
|
|
||||||
{{- $createWorkVolume = 0 -}}
|
|
||||||
- name: work
|
|
||||||
{{- range $key, $val := $volume }}
|
|
||||||
{{- if ne $key "name" }}
|
|
||||||
{{ $key }}: {{ $val }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- if eq $createWorkVolume 1 }}
|
|
||||||
- name: work
|
|
||||||
emptyDir: {}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{- define "auto-scaling-runner-set.kubernetes-mode-work-volume" -}}
|
|
||||||
{{- $createWorkVolume := 1 }}
|
|
||||||
{{- range $i, $volume := .Values.template.spec.volumes }}
|
|
||||||
{{- if eq $volume.name "work" }}
|
|
||||||
{{- $createWorkVolume = 0 -}}
|
|
||||||
- name: work
|
|
||||||
{{- range $key, $val := $volume }}
|
|
||||||
{{- if ne $key "name" }}
|
|
||||||
{{ $key }}: {{ $val }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- if eq $createWorkVolume 1 }}
|
|
||||||
- name: work
|
|
||||||
ephemeral:
|
|
||||||
volumeClaimTemplate:
|
|
||||||
spec:
|
|
||||||
{{- .Values.containerMode.kubernetesModeWorkVolumeClaim | toYaml | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{- define "auto-scaling-runner-set.non-work-volumes" -}}
|
|
||||||
{{- range $i, $volume := .Values.template.spec.volumes }}
|
|
||||||
{{- if ne $volume.name "work" }}
|
|
||||||
- name: {{ $volume.name }}
|
|
||||||
{{- range $key, $val := $volume }}
|
|
||||||
{{- if ne $key "name" }}
|
|
||||||
{{ $key }}: {{ $val }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{- define "auto-scaling-runner-set.non-runner-containers" -}}
|
|
||||||
{{- range $i, $container := .Values.template.spec.containers -}}
|
|
||||||
{{- if ne $container.name "runner" -}}
|
|
||||||
- name: {{ $container.name }}
|
|
||||||
{{- range $key, $val := $container }}
|
|
||||||
{{- if ne $key "name" }}
|
|
||||||
{{ $key }}: {{ $val }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{- define "auto-scaling-runner-set.dind-runner-container" -}}
|
|
||||||
{{- range $i, $container := .Values.template.spec.containers -}}
|
|
||||||
{{- if eq $container.name "runner" -}}
|
|
||||||
{{- range $key, $val := $container }}
|
|
||||||
{{- if and (ne $key "env") (ne $key "volumeMounts") (ne $key "name") }}
|
|
||||||
{{ $key }}: {{ $val }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- $setDockerHost := 1 }}
|
|
||||||
{{- $setDockerTlsVerify := 1 }}
|
|
||||||
{{- $setDockerCertPath := 1 }}
|
|
||||||
{{- $setRunnerWaitDocker := 1 }}
|
|
||||||
env:
|
|
||||||
{{- with $container.env }}
|
|
||||||
{{- range $i, $env := . }}
|
|
||||||
{{- if eq $env.name "DOCKER_HOST" }}
|
|
||||||
{{- $setDockerHost = 0 -}}
|
|
||||||
{{- end }}
|
|
||||||
{{- if eq $env.name "DOCKER_TLS_VERIFY" }}
|
|
||||||
{{- $setDockerTlsVerify = 0 -}}
|
|
||||||
{{- end }}
|
|
||||||
{{- if eq $env.name "DOCKER_CERT_PATH" }}
|
|
||||||
{{- $setDockerCertPath = 0 -}}
|
|
||||||
{{- end }}
|
|
||||||
{{- if eq $env.name "RUNNER_WAIT_FOR_DOCKER_IN_SECONDS" }}
|
|
||||||
{{- $setRunnerWaitDocker = 0 -}}
|
|
||||||
{{- end }}
|
|
||||||
- name: {{ $env.name }}
|
|
||||||
{{- range $envKey, $envVal := $env }}
|
|
||||||
{{- if ne $envKey "name" }}
|
|
||||||
{{ $envKey }}: {{ $envVal | toYaml | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- if $setDockerHost }}
|
|
||||||
- name: DOCKER_HOST
|
|
||||||
value: tcp://localhost:2376
|
|
||||||
{{- end }}
|
|
||||||
{{- if $setDockerTlsVerify }}
|
|
||||||
- name: DOCKER_TLS_VERIFY
|
|
||||||
value: "1"
|
|
||||||
{{- end }}
|
|
||||||
{{- if $setDockerCertPath }}
|
|
||||||
- name: DOCKER_CERT_PATH
|
|
||||||
value: /certs/client
|
|
||||||
{{- end }}
|
|
||||||
{{- if $setRunnerWaitDocker }}
|
|
||||||
- name: RUNNER_WAIT_FOR_DOCKER_IN_SECONDS
|
|
||||||
value: "120"
|
|
||||||
{{- end }}
|
|
||||||
{{- $mountWork := 1 }}
|
|
||||||
{{- $mountDindCert := 1 }}
|
|
||||||
volumeMounts:
|
|
||||||
{{- with $container.volumeMounts }}
|
|
||||||
{{- range $i, $volMount := . }}
|
|
||||||
{{- if eq $volMount.name "work" }}
|
|
||||||
{{- $mountWork = 0 -}}
|
|
||||||
{{- end }}
|
|
||||||
{{- if eq $volMount.name "dind-cert" }}
|
|
||||||
{{- $mountDindCert = 0 -}}
|
|
||||||
{{- end }}
|
|
||||||
- name: {{ $volMount.name }}
|
|
||||||
{{- range $mountKey, $mountVal := $volMount }}
|
|
||||||
{{- if ne $mountKey "name" }}
|
|
||||||
{{ $mountKey }}: {{ $mountVal | toYaml | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- if $mountWork }}
|
|
||||||
- name: work
|
|
||||||
mountPath: /actions-runner/_work
|
|
||||||
{{- end }}
|
|
||||||
{{- if $mountDindCert }}
|
|
||||||
- name: dind-cert
|
|
||||||
mountPath: /certs/client
|
|
||||||
readOnly: true
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{- define "auto-scaling-runner-set.kubernetes-mode-runner-container" -}}
|
|
||||||
{{- range $i, $container := .Values.template.spec.containers -}}
|
|
||||||
{{- if eq $container.name "runner" -}}
|
|
||||||
{{- range $key, $val := $container }}
|
|
||||||
{{- if and (ne $key "env") (ne $key "volumeMounts") (ne $key "name") }}
|
|
||||||
{{ $key }}: {{ $val }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- $setContainerHooks := 1 }}
|
|
||||||
{{- $setPodName := 1 }}
|
|
||||||
{{- $setRequireJobContainer := 1 }}
|
|
||||||
env:
|
|
||||||
{{- with $container.env }}
|
|
||||||
{{- range $i, $env := . }}
|
|
||||||
{{- if eq $env.name "ACTIONS_RUNNER_CONTAINER_HOOKS" }}
|
|
||||||
{{- $setContainerHooks = 0 -}}
|
|
||||||
{{- end }}
|
|
||||||
{{- if eq $env.name "ACTIONS_RUNNER_POD_NAME" }}
|
|
||||||
{{- $setPodName = 0 -}}
|
|
||||||
{{- end }}
|
|
||||||
{{- if eq $env.name "ACTIONS_RUNNER_REQUIRE_JOB_CONTAINER" }}
|
|
||||||
{{- $setRequireJobContainer = 0 -}}
|
|
||||||
{{- end }}
|
|
||||||
- name: {{ $env.name }}
|
|
||||||
{{- range $envKey, $envVal := $env }}
|
|
||||||
{{- if ne $envKey "name" }}
|
|
||||||
{{ $envKey }}: {{ $envVal | toYaml | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- if $setContainerHooks }}
|
|
||||||
- name: ACTIONS_RUNNER_CONTAINER_HOOKS
|
|
||||||
value: /actions-runner/k8s/index.js
|
|
||||||
{{- end }}
|
|
||||||
{{- if $setPodName }}
|
|
||||||
- name: ACTIONS_RUNNER_POD_NAME
|
|
||||||
valueFrom:
|
|
||||||
fieldRef:
|
|
||||||
fieldPath: metadata.name
|
|
||||||
{{- end }}
|
|
||||||
{{- if $setRequireJobContainer }}
|
|
||||||
- name: ACTIONS_RUNNER_REQUIRE_JOB_CONTAINER
|
|
||||||
value: "true"
|
|
||||||
{{- end }}
|
|
||||||
{{- $mountWork := 1 }}
|
|
||||||
volumeMounts:
|
|
||||||
{{- with $container.volumeMounts }}
|
|
||||||
{{- range $i, $volMount := . }}
|
|
||||||
{{- if eq $volMount.name "work" }}
|
|
||||||
{{- $mountWork = 0 -}}
|
|
||||||
{{- end }}
|
|
||||||
- name: {{ $volMount.name }}
|
|
||||||
{{- range $mountKey, $mountVal := $volMount }}
|
|
||||||
{{- if ne $mountKey "name" }}
|
|
||||||
{{ $mountKey }}: {{ $mountVal | toYaml | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- if $mountWork }}
|
|
||||||
- name: work
|
|
||||||
mountPath: /actions-runner/_work
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,108 +0,0 @@
|
|||||||
apiVersion: actions.github.com/v1alpha1
|
|
||||||
kind: AutoscalingRunnerSet
|
|
||||||
metadata:
|
|
||||||
name: {{ .Release.Name }}
|
|
||||||
namespace: {{ .Release.Namespace }}
|
|
||||||
labels:
|
|
||||||
{{- include "auto-scaling-runner-set.labels" . | nindent 4 }}
|
|
||||||
spec:
|
|
||||||
githubConfigUrl: {{ required ".Values.githubConfigUrl is required" .Values.githubConfigUrl }}
|
|
||||||
githubConfigSecret: {{ include "auto-scaling-runner-set.githubsecret" . }}
|
|
||||||
{{- with .Values.runnerGroup }}
|
|
||||||
runnerGroup: {{ . }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{- if .Values.proxy }}
|
|
||||||
proxy:
|
|
||||||
{{- if .Values.proxy.http }}
|
|
||||||
http:
|
|
||||||
url: {{ .Values.proxy.http.url }}
|
|
||||||
credentialSecretRef: {{ .Values.proxy.http.credentialSecretRef }}
|
|
||||||
{{ end }}
|
|
||||||
{{- if .Values.proxy.https }}
|
|
||||||
https:
|
|
||||||
url: {{ .Values.proxy.https.url }}
|
|
||||||
credentialSecretRef: {{ .Values.proxy.https.credentialSecretRef }}
|
|
||||||
{{ end }}
|
|
||||||
{{- if and .Values.proxy.noProxy (kindIs "slice" .Values.proxy.noProxy) }}
|
|
||||||
noProxy: {{ .Values.proxy.noProxy | toYaml | nindent 6}}
|
|
||||||
{{ end }}
|
|
||||||
{{ end }}
|
|
||||||
|
|
||||||
{{- if and (or (kindIs "int64" .Values.minRunners) (kindIs "float64" .Values.minRunners)) (or (kindIs "int64" .Values.maxRunners) (kindIs "float64" .Values.maxRunners)) }}
|
|
||||||
{{- if gt .Values.minRunners .Values.maxRunners }}
|
|
||||||
{{- fail "maxRunners has to be greater or equal to minRunners" }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{- if or (kindIs "int64" .Values.maxRunners) (kindIs "float64" .Values.maxRunners) }}
|
|
||||||
{{- if lt (.Values.maxRunners | int) 0 }}
|
|
||||||
{{- fail "maxRunners has to be greater or equal to 0" }}
|
|
||||||
{{- end }}
|
|
||||||
maxRunners: {{ .Values.maxRunners | int }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{- if or (kindIs "int64" .Values.minRunners) (kindIs "float64" .Values.minRunners) }}
|
|
||||||
{{- if lt (.Values.minRunners | int) 0 }}
|
|
||||||
{{- fail "minRunners has to be greater or equal to 0" }}
|
|
||||||
{{- end }}
|
|
||||||
minRunners: {{ .Values.minRunners | int }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
template:
|
|
||||||
{{- with .Values.template.metadata }}
|
|
||||||
metadata:
|
|
||||||
{{- with .labels }}
|
|
||||||
labels:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .annotations }}
|
|
||||||
annotations:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
spec:
|
|
||||||
{{- range $key, $val := .Values.template.spec }}
|
|
||||||
{{- if and (ne $key "containers") (ne $key "volumes") (ne $key "initContainers") (ne $key "serviceAccountName") }}
|
|
||||||
{{ $key }}: {{ $val | toYaml | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- if eq .Values.containerMode.type "kubernetes" }}
|
|
||||||
serviceAccountName: {{ default (include "auto-scaling-runner-set.kubeModeServiceAccountName" .) .Values.template.spec.serviceAccountName }}
|
|
||||||
{{- else }}
|
|
||||||
serviceAccountName: {{ default (include "auto-scaling-runner-set.noPermissionServiceAccountName" .) .Values.template.spec.serviceAccountName }}
|
|
||||||
{{- end }}
|
|
||||||
{{- if or .Values.template.spec.initContainers (eq .Values.containerMode.type "dind") }}
|
|
||||||
initContainers:
|
|
||||||
{{- if eq .Values.containerMode.type "dind" }}
|
|
||||||
- name: init-dind-externals
|
|
||||||
{{- include "auto-scaling-runner-set.dind-init-container" . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.template.spec.initContainers }}
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
containers:
|
|
||||||
{{- if eq .Values.containerMode.type "dind" }}
|
|
||||||
- name: runner
|
|
||||||
{{- include "auto-scaling-runner-set.dind-runner-container" . | nindent 8 }}
|
|
||||||
- name: dind
|
|
||||||
{{- include "auto-scaling-runner-set.dind-container" . | nindent 8 }}
|
|
||||||
{{- include "auto-scaling-runner-set.non-runner-containers" . | nindent 6 }}
|
|
||||||
{{- else if eq .Values.containerMode.type "kubernetes" }}
|
|
||||||
- name: runner
|
|
||||||
{{- include "auto-scaling-runner-set.kubernetes-mode-runner-container" . | nindent 8 }}
|
|
||||||
{{- include "auto-scaling-runner-set.non-runner-containers" . | nindent 6 }}
|
|
||||||
{{- else }}
|
|
||||||
{{ .Values.template.spec.containers | toYaml | nindent 6 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- if or .Values.template.spec.volumes (eq .Values.containerMode.type "dind") (eq .Values.containerMode.type "kubernetes") }}
|
|
||||||
volumes:
|
|
||||||
{{- if eq .Values.containerMode.type "dind" }}
|
|
||||||
{{- include "auto-scaling-runner-set.dind-volume" . | nindent 6 }}
|
|
||||||
{{- include "auto-scaling-runner-set.dind-work-volume" . | nindent 6 }}
|
|
||||||
{{- else if eq .Values.containerMode.type "kubernetes" }}
|
|
||||||
{{- include "auto-scaling-runner-set.kubernetes-mode-work-volume" . | nindent 6 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- include "auto-scaling-runner-set.non-work-volumes" . | nindent 6 }}
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
{{- if and (eq .Values.containerMode.type "kubernetes") (not .Values.template.spec.serviceAccountName) }}
|
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
|
||||||
kind: RoleBinding
|
|
||||||
metadata:
|
|
||||||
name: {{ include "auto-scaling-runner-set.kubeModeRoleName" . }}
|
|
||||||
namespace: {{ .Release.Namespace }}
|
|
||||||
roleRef:
|
|
||||||
apiGroup: rbac.authorization.k8s.io
|
|
||||||
kind: Role
|
|
||||||
name: {{ include "auto-scaling-runner-set.kubeModeRoleName" . }}
|
|
||||||
subjects:
|
|
||||||
- kind: ServiceAccount
|
|
||||||
name: {{ include "auto-scaling-runner-set.kubeModeServiceAccountName" . }}
|
|
||||||
namespace: {{ .Release.Namespace }}
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
{{- if and (eq .Values.containerMode.type "kubernetes") (not .Values.template.spec.serviceAccountName) }}
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ServiceAccount
|
|
||||||
metadata:
|
|
||||||
name: {{ include "auto-scaling-runner-set.kubeModeServiceAccountName" . }}
|
|
||||||
namespace: {{ .Release.Namespace }}
|
|
||||||
labels:
|
|
||||||
{{- include "auto-scaling-runner-set.labels" . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
{{- if and (ne .Values.containerMode.type "kubernetes") (not .Values.template.spec.serviceAccountName) }}
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ServiceAccount
|
|
||||||
metadata:
|
|
||||||
name: {{ include "auto-scaling-runner-set.noPermissionServiceAccountName" . }}
|
|
||||||
namespace: {{ .Release.Namespace }}
|
|
||||||
labels:
|
|
||||||
{{- include "auto-scaling-runner-set.labels" . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,782 +0,0 @@
|
|||||||
package tests
|
|
||||||
|
|
||||||
import (
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
v1alpha1 "github.com/actions/actions-runner-controller/apis/actions.github.com/v1alpha1"
|
|
||||||
"github.com/gruntwork-io/terratest/modules/helm"
|
|
||||||
"github.com/gruntwork-io/terratest/modules/k8s"
|
|
||||||
"github.com/gruntwork-io/terratest/modules/random"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
|
||||||
rbacv1 "k8s.io/api/rbac/v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestTemplateRenderedGitHubSecretWithGitHubToken(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-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",
|
|
||||||
},
|
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
|
||||||
}
|
|
||||||
|
|
||||||
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/githubsecret.yaml"})
|
|
||||||
|
|
||||||
var githubSecret corev1.Secret
|
|
||||||
helm.UnmarshalK8SYaml(t, output, &githubSecret)
|
|
||||||
|
|
||||||
assert.Equal(t, namespaceName, githubSecret.Namespace)
|
|
||||||
assert.Equal(t, "test-runners-auto-scaling-runner-set-github-secret", githubSecret.Name)
|
|
||||||
assert.Equal(t, "gh_token12345", string(githubSecret.Data["github_token"]))
|
|
||||||
assert.Equal(t, "actions.github.com/secret-protection", githubSecret.Finalizers[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplateRenderedGitHubSecretWithGitHubApp(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-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_app_id": "10",
|
|
||||||
"githubConfigSecret.github_app_installation_id": "100",
|
|
||||||
"githubConfigSecret.github_app_private_key": "private_key",
|
|
||||||
},
|
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
|
||||||
}
|
|
||||||
|
|
||||||
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/githubsecret.yaml"})
|
|
||||||
|
|
||||||
var githubSecret corev1.Secret
|
|
||||||
helm.UnmarshalK8SYaml(t, output, &githubSecret)
|
|
||||||
|
|
||||||
assert.Equal(t, namespaceName, githubSecret.Namespace)
|
|
||||||
assert.Equal(t, "10", string(githubSecret.Data["github_app_id"]))
|
|
||||||
assert.Equal(t, "100", string(githubSecret.Data["github_app_installation_id"]))
|
|
||||||
assert.Equal(t, "private_key", string(githubSecret.Data["github_app_private_key"]))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplateRenderedGitHubSecretErrorWithMissingAuthInput(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-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_app_id": "",
|
|
||||||
"githubConfigSecret.github_token": "",
|
|
||||||
},
|
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = helm.RenderTemplateE(t, options, helmChartPath, releaseName, []string{"templates/githubsecret.yaml"})
|
|
||||||
require.Error(t, err)
|
|
||||||
|
|
||||||
assert.ErrorContains(t, err, "provide .Values.githubConfigSecret.github_token or .Values.githubConfigSecret.github_app_id")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplateRenderedGitHubSecretErrorWithMissingAppInput(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-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_app_id": "10",
|
|
||||||
},
|
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = helm.RenderTemplateE(t, options, helmChartPath, releaseName, []string{"templates/githubsecret.yaml"})
|
|
||||||
require.Error(t, err)
|
|
||||||
|
|
||||||
assert.ErrorContains(t, err, "provide .Values.githubConfigSecret.github_app_installation_id and .Values.githubConfigSecret.github_app_private_key")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplateNotRenderedGitHubSecretWithPredefinedSecret(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-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": "pre-defined-secret",
|
|
||||||
},
|
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = helm.RenderTemplateE(t, options, helmChartPath, releaseName, []string{"templates/githubsecret.yaml"})
|
|
||||||
assert.ErrorContains(t, err, "could not find template templates/githubsecret.yaml in chart", "secret should not be rendered since a pre-defined secret is provided")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplateRenderedSetServiceAccountToNoPermission(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-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",
|
|
||||||
},
|
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
|
||||||
}
|
|
||||||
|
|
||||||
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/no_permission_serviceaccount.yaml"})
|
|
||||||
var serviceAccount corev1.ServiceAccount
|
|
||||||
helm.UnmarshalK8SYaml(t, output, &serviceAccount)
|
|
||||||
|
|
||||||
assert.Equal(t, namespaceName, serviceAccount.Namespace)
|
|
||||||
assert.Equal(t, "test-runners-auto-scaling-runner-set-no-permission-service-account", serviceAccount.Name)
|
|
||||||
|
|
||||||
output = helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/autoscalingrunnerset.yaml"})
|
|
||||||
var ars v1alpha1.AutoscalingRunnerSet
|
|
||||||
helm.UnmarshalK8SYaml(t, output, &ars)
|
|
||||||
|
|
||||||
assert.Equal(t, "test-runners-auto-scaling-runner-set-no-permission-service-account", ars.Spec.Template.Spec.ServiceAccountName)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplateRenderedSetServiceAccountToKubeMode(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-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",
|
|
||||||
"containerMode.type": "kubernetes",
|
|
||||||
},
|
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
|
||||||
}
|
|
||||||
|
|
||||||
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/kube_mode_serviceaccount.yaml"})
|
|
||||||
var serviceAccount corev1.ServiceAccount
|
|
||||||
helm.UnmarshalK8SYaml(t, output, &serviceAccount)
|
|
||||||
|
|
||||||
assert.Equal(t, namespaceName, serviceAccount.Namespace)
|
|
||||||
assert.Equal(t, "test-runners-auto-scaling-runner-set-kube-mode-service-account", serviceAccount.Name)
|
|
||||||
|
|
||||||
output = helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/kube_mode_role.yaml"})
|
|
||||||
var role rbacv1.Role
|
|
||||||
helm.UnmarshalK8SYaml(t, output, &role)
|
|
||||||
|
|
||||||
assert.Equal(t, namespaceName, role.Namespace)
|
|
||||||
assert.Equal(t, "test-runners-auto-scaling-runner-set-kube-mode-role", role.Name)
|
|
||||||
assert.Len(t, role.Rules, 5, "kube mode role should have 5 rules")
|
|
||||||
assert.Equal(t, "pods", role.Rules[0].Resources[0])
|
|
||||||
assert.Equal(t, "pods/exec", role.Rules[1].Resources[0])
|
|
||||||
assert.Equal(t, "pods/log", role.Rules[2].Resources[0])
|
|
||||||
assert.Equal(t, "jobs", role.Rules[3].Resources[0])
|
|
||||||
assert.Equal(t, "secrets", role.Rules[4].Resources[0])
|
|
||||||
|
|
||||||
output = helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/kube_mode_role_binding.yaml"})
|
|
||||||
var roleBinding rbacv1.RoleBinding
|
|
||||||
helm.UnmarshalK8SYaml(t, output, &roleBinding)
|
|
||||||
|
|
||||||
assert.Equal(t, namespaceName, roleBinding.Namespace)
|
|
||||||
assert.Equal(t, "test-runners-auto-scaling-runner-set-kube-mode-role", roleBinding.Name)
|
|
||||||
assert.Len(t, roleBinding.Subjects, 1)
|
|
||||||
assert.Equal(t, "test-runners-auto-scaling-runner-set-kube-mode-service-account", roleBinding.Subjects[0].Name)
|
|
||||||
assert.Equal(t, namespaceName, roleBinding.Subjects[0].Namespace)
|
|
||||||
assert.Equal(t, "test-runners-auto-scaling-runner-set-kube-mode-role", roleBinding.RoleRef.Name)
|
|
||||||
assert.Equal(t, "Role", roleBinding.RoleRef.Kind)
|
|
||||||
|
|
||||||
output = helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/autoscalingrunnerset.yaml"})
|
|
||||||
var ars v1alpha1.AutoscalingRunnerSet
|
|
||||||
helm.UnmarshalK8SYaml(t, output, &ars)
|
|
||||||
|
|
||||||
assert.Equal(t, "test-runners-auto-scaling-runner-set-kube-mode-service-account", ars.Spec.Template.Spec.ServiceAccountName)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplateRenderedUserProvideSetServiceAccount(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-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",
|
|
||||||
"template.spec.serviceAccountName": "test-service-account",
|
|
||||||
},
|
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = helm.RenderTemplateE(t, options, helmChartPath, releaseName, []string{"templates/no_permission_serviceaccount.yaml"})
|
|
||||||
assert.ErrorContains(t, err, "could not find template templates/no_permission_serviceaccount.yaml in chart", "no permission service account should not be rendered")
|
|
||||||
|
|
||||||
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/autoscalingrunnerset.yaml"})
|
|
||||||
var ars v1alpha1.AutoscalingRunnerSet
|
|
||||||
helm.UnmarshalK8SYaml(t, output, &ars)
|
|
||||||
|
|
||||||
assert.Equal(t, "test-service-account", ars.Spec.Template.Spec.ServiceAccountName)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplateRenderedAutoScalingRunnerSet(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-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",
|
|
||||||
},
|
|
||||||
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.Equal(t, namespaceName, ars.Namespace)
|
|
||||||
assert.Equal(t, "test-runners", ars.Name)
|
|
||||||
|
|
||||||
assert.Equal(t, "auto-scaling-runner-set", ars.Labels["app.kubernetes.io/name"])
|
|
||||||
assert.Equal(t, "test-runners", ars.Labels["app.kubernetes.io/instance"])
|
|
||||||
assert.Equal(t, "https://github.com/actions", ars.Spec.GitHubConfigUrl)
|
|
||||||
assert.Equal(t, "test-runners-auto-scaling-runner-set-github-secret", ars.Spec.GitHubConfigSecret)
|
|
||||||
|
|
||||||
assert.Empty(t, ars.Spec.RunnerGroup, "RunnerGroup should be empty")
|
|
||||||
|
|
||||||
assert.Nil(t, ars.Spec.MinRunners, "MinRunners should be nil")
|
|
||||||
assert.Nil(t, ars.Spec.MaxRunners, "MaxRunners should be nil")
|
|
||||||
assert.Nil(t, ars.Spec.Proxy, "Proxy should be nil")
|
|
||||||
assert.Nil(t, ars.Spec.GitHubServerTLS, "GitHubServerTLS should be nil")
|
|
||||||
|
|
||||||
assert.NotNil(t, ars.Spec.Template.Spec, "Template.Spec should not be nil")
|
|
||||||
|
|
||||||
assert.Len(t, ars.Spec.Template.Spec.Containers, 1, "Template.Spec should have 1 container")
|
|
||||||
assert.Equal(t, "runner", ars.Spec.Template.Spec.Containers[0].Name)
|
|
||||||
assert.Equal(t, "ghcr.io/actions/actions-runner:latest", ars.Spec.Template.Spec.Containers[0].Image)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplateRenderedAutoScalingRunnerSet_ProvideMetadata(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-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",
|
|
||||||
"template.metadata.labels.test1": "test1",
|
|
||||||
"template.metadata.labels.test2": "test2",
|
|
||||||
"template.metadata.annotations.test3": "test3",
|
|
||||||
"template.metadata.annotations.test4": "test4",
|
|
||||||
},
|
|
||||||
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.Equal(t, namespaceName, ars.Namespace)
|
|
||||||
assert.Equal(t, "test-runners", ars.Name)
|
|
||||||
|
|
||||||
assert.NotNil(t, ars.Spec.Template.Labels, "Template.Spec.Labels should not be nil")
|
|
||||||
assert.Equal(t, "test1", ars.Spec.Template.Labels["test1"], "Template.Spec.Labels should have test1")
|
|
||||||
assert.Equal(t, "test2", ars.Spec.Template.Labels["test2"], "Template.Spec.Labels should have test2")
|
|
||||||
|
|
||||||
assert.NotNil(t, ars.Spec.Template.Annotations, "Template.Spec.Annotations should not be nil")
|
|
||||||
assert.Equal(t, "test3", ars.Spec.Template.Annotations["test3"], "Template.Spec.Annotations should have test3")
|
|
||||||
assert.Equal(t, "test4", ars.Spec.Template.Annotations["test4"], "Template.Spec.Annotations should have test4")
|
|
||||||
|
|
||||||
assert.NotNil(t, ars.Spec.Template.Spec, "Template.Spec should not be nil")
|
|
||||||
|
|
||||||
assert.Len(t, ars.Spec.Template.Spec.Containers, 1, "Template.Spec should have 1 container")
|
|
||||||
assert.Equal(t, "runner", ars.Spec.Template.Spec.Containers[0].Name)
|
|
||||||
assert.Equal(t, "ghcr.io/actions/actions-runner:latest", ars.Spec.Template.Spec.Containers[0].Image)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplateRenderedAutoScalingRunnerSet_MaxRunnersValidationError(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-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",
|
|
||||||
"maxRunners": "-1",
|
|
||||||
},
|
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = helm.RenderTemplateE(t, options, helmChartPath, releaseName, []string{"templates/autoscalingrunnerset.yaml"})
|
|
||||||
require.Error(t, err)
|
|
||||||
|
|
||||||
assert.ErrorContains(t, err, "maxRunners has to be greater or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplateRenderedAutoScalingRunnerSet_MinRunnersValidationError(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-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",
|
|
||||||
"maxRunners": "1",
|
|
||||||
"minRunners": "-1",
|
|
||||||
},
|
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = helm.RenderTemplateE(t, options, helmChartPath, releaseName, []string{"templates/autoscalingrunnerset.yaml"})
|
|
||||||
require.Error(t, err)
|
|
||||||
|
|
||||||
assert.ErrorContains(t, err, "minRunners has to be greater or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplateRenderedAutoScalingRunnerSet_MinMaxRunnersValidationError(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-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",
|
|
||||||
"maxRunners": "0",
|
|
||||||
"minRunners": "1",
|
|
||||||
},
|
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = helm.RenderTemplateE(t, options, helmChartPath, releaseName, []string{"templates/autoscalingrunnerset.yaml"})
|
|
||||||
require.Error(t, err)
|
|
||||||
|
|
||||||
assert.ErrorContains(t, err, "maxRunners has to be greater or equal to minRunners")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplateRenderedAutoScalingRunnerSet_MinMaxRunnersValidationSameValue(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-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",
|
|
||||||
"maxRunners": "0",
|
|
||||||
"minRunners": "0",
|
|
||||||
},
|
|
||||||
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.Equal(t, 0, *ars.Spec.MinRunners, "MinRunners should be 0")
|
|
||||||
assert.Equal(t, 0, *ars.Spec.MaxRunners, "MaxRunners should be 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplateRenderedAutoScalingRunnerSet_MinMaxRunnersValidation_OnlyMin(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-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",
|
|
||||||
"minRunners": "5",
|
|
||||||
},
|
|
||||||
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.Equal(t, 5, *ars.Spec.MinRunners, "MinRunners should be 5")
|
|
||||||
assert.Nil(t, ars.Spec.MaxRunners, "MaxRunners should be nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplateRenderedAutoScalingRunnerSet_MinMaxRunnersValidation_OnlyMax(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-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",
|
|
||||||
"maxRunners": "5",
|
|
||||||
},
|
|
||||||
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.Equal(t, 5, *ars.Spec.MaxRunners, "MaxRunners should be 5")
|
|
||||||
assert.Nil(t, ars.Spec.MinRunners, "MinRunners should be nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplateRenderedAutoScalingRunnerSet_MinMaxRunners_FromValuesFile(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-set")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
testValuesPath, err := filepath.Abs("../tests/values.yaml")
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
releaseName := "test-runners"
|
|
||||||
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
|
||||||
|
|
||||||
options := &helm.Options{
|
|
||||||
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.Equal(t, 5, *ars.Spec.MinRunners, "MinRunners should be 5")
|
|
||||||
assert.Equal(t, 10, *ars.Spec.MaxRunners, "MaxRunners should be 10")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplateRenderedAutoScalingRunnerSet_EnableDinD(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-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",
|
|
||||||
"containerMode.type": "dind",
|
|
||||||
},
|
|
||||||
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.Equal(t, namespaceName, ars.Namespace)
|
|
||||||
assert.Equal(t, "test-runners", ars.Name)
|
|
||||||
|
|
||||||
assert.Equal(t, "auto-scaling-runner-set", ars.Labels["app.kubernetes.io/name"])
|
|
||||||
assert.Equal(t, "test-runners", ars.Labels["app.kubernetes.io/instance"])
|
|
||||||
assert.Equal(t, "https://github.com/actions", ars.Spec.GitHubConfigUrl)
|
|
||||||
assert.Equal(t, "test-runners-auto-scaling-runner-set-github-secret", ars.Spec.GitHubConfigSecret)
|
|
||||||
|
|
||||||
assert.Empty(t, ars.Spec.RunnerGroup, "RunnerGroup should be empty")
|
|
||||||
|
|
||||||
assert.Nil(t, ars.Spec.MinRunners, "MinRunners should be nil")
|
|
||||||
assert.Nil(t, ars.Spec.MaxRunners, "MaxRunners should be nil")
|
|
||||||
assert.Nil(t, ars.Spec.Proxy, "Proxy should be nil")
|
|
||||||
assert.Nil(t, ars.Spec.GitHubServerTLS, "GitHubServerTLS should be nil")
|
|
||||||
|
|
||||||
assert.NotNil(t, ars.Spec.Template.Spec, "Template.Spec should not be nil")
|
|
||||||
|
|
||||||
assert.Len(t, ars.Spec.Template.Spec.InitContainers, 1, "Template.Spec should have 1 init container")
|
|
||||||
assert.Equal(t, "init-dind-externals", ars.Spec.Template.Spec.InitContainers[0].Name)
|
|
||||||
assert.Equal(t, "ghcr.io/actions/actions-runner:latest", ars.Spec.Template.Spec.InitContainers[0].Image)
|
|
||||||
assert.Equal(t, "cp", ars.Spec.Template.Spec.InitContainers[0].Command[0])
|
|
||||||
assert.Equal(t, "-r -v /actions-runner/externals/. /actions-runner/tmpDir/", strings.Join(ars.Spec.Template.Spec.InitContainers[0].Args, " "))
|
|
||||||
|
|
||||||
assert.Len(t, ars.Spec.Template.Spec.Containers, 2, "Template.Spec should have 2 container")
|
|
||||||
assert.Equal(t, "runner", ars.Spec.Template.Spec.Containers[0].Name)
|
|
||||||
assert.Equal(t, "ghcr.io/actions/actions-runner:latest", ars.Spec.Template.Spec.Containers[0].Image)
|
|
||||||
assert.Len(t, ars.Spec.Template.Spec.Containers[0].Env, 4, "The runner container should have 4 env vars, DOCKER_HOST, DOCKER_TLS_VERIFY, DOCKER_CERT_PATH and RUNNER_WAIT_FOR_DOCKER_IN_SECONDS")
|
|
||||||
assert.Equal(t, "DOCKER_HOST", ars.Spec.Template.Spec.Containers[0].Env[0].Name)
|
|
||||||
assert.Equal(t, "tcp://localhost:2376", ars.Spec.Template.Spec.Containers[0].Env[0].Value)
|
|
||||||
assert.Equal(t, "DOCKER_TLS_VERIFY", ars.Spec.Template.Spec.Containers[0].Env[1].Name)
|
|
||||||
assert.Equal(t, "1", ars.Spec.Template.Spec.Containers[0].Env[1].Value)
|
|
||||||
assert.Equal(t, "DOCKER_CERT_PATH", ars.Spec.Template.Spec.Containers[0].Env[2].Name)
|
|
||||||
assert.Equal(t, "/certs/client", ars.Spec.Template.Spec.Containers[0].Env[2].Value)
|
|
||||||
assert.Equal(t, "RUNNER_WAIT_FOR_DOCKER_IN_SECONDS", ars.Spec.Template.Spec.Containers[0].Env[3].Name)
|
|
||||||
assert.Equal(t, "120", ars.Spec.Template.Spec.Containers[0].Env[3].Value)
|
|
||||||
|
|
||||||
assert.Len(t, ars.Spec.Template.Spec.Containers[0].VolumeMounts, 2, "The runner container should have 2 volume mounts, dind-cert and work")
|
|
||||||
assert.Equal(t, "work", ars.Spec.Template.Spec.Containers[0].VolumeMounts[0].Name)
|
|
||||||
assert.Equal(t, "/actions-runner/_work", ars.Spec.Template.Spec.Containers[0].VolumeMounts[0].MountPath)
|
|
||||||
assert.False(t, ars.Spec.Template.Spec.Containers[0].VolumeMounts[0].ReadOnly)
|
|
||||||
|
|
||||||
assert.Equal(t, "dind-cert", ars.Spec.Template.Spec.Containers[0].VolumeMounts[1].Name)
|
|
||||||
assert.Equal(t, "/certs/client", ars.Spec.Template.Spec.Containers[0].VolumeMounts[1].MountPath)
|
|
||||||
assert.True(t, ars.Spec.Template.Spec.Containers[0].VolumeMounts[1].ReadOnly)
|
|
||||||
|
|
||||||
assert.Equal(t, "dind", ars.Spec.Template.Spec.Containers[1].Name)
|
|
||||||
assert.Equal(t, "docker:dind", ars.Spec.Template.Spec.Containers[1].Image)
|
|
||||||
assert.True(t, *ars.Spec.Template.Spec.Containers[1].SecurityContext.Privileged)
|
|
||||||
assert.Len(t, ars.Spec.Template.Spec.Containers[1].VolumeMounts, 3, "The dind container should have 3 volume mounts, dind-cert, work and externals")
|
|
||||||
assert.Equal(t, "work", ars.Spec.Template.Spec.Containers[1].VolumeMounts[0].Name)
|
|
||||||
assert.Equal(t, "/actions-runner/_work", ars.Spec.Template.Spec.Containers[1].VolumeMounts[0].MountPath)
|
|
||||||
|
|
||||||
assert.Equal(t, "dind-cert", ars.Spec.Template.Spec.Containers[1].VolumeMounts[1].Name)
|
|
||||||
assert.Equal(t, "/certs/client", ars.Spec.Template.Spec.Containers[1].VolumeMounts[1].MountPath)
|
|
||||||
|
|
||||||
assert.Equal(t, "dind-externals", ars.Spec.Template.Spec.Containers[1].VolumeMounts[2].Name)
|
|
||||||
assert.Equal(t, "/actions-runner/externals", ars.Spec.Template.Spec.Containers[1].VolumeMounts[2].MountPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplateRenderedAutoScalingRunnerSet_EnableKubernetesMode(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-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",
|
|
||||||
"containerMode.type": "kubernetes",
|
|
||||||
},
|
|
||||||
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.Equal(t, namespaceName, ars.Namespace)
|
|
||||||
assert.Equal(t, "test-runners", ars.Name)
|
|
||||||
|
|
||||||
assert.Equal(t, "auto-scaling-runner-set", ars.Labels["app.kubernetes.io/name"])
|
|
||||||
assert.Equal(t, "test-runners", ars.Labels["app.kubernetes.io/instance"])
|
|
||||||
assert.Equal(t, "https://github.com/actions", ars.Spec.GitHubConfigUrl)
|
|
||||||
assert.Equal(t, "test-runners-auto-scaling-runner-set-github-secret", ars.Spec.GitHubConfigSecret)
|
|
||||||
|
|
||||||
assert.Empty(t, ars.Spec.RunnerGroup, "RunnerGroup should be empty")
|
|
||||||
assert.Nil(t, ars.Spec.MinRunners, "MinRunners should be nil")
|
|
||||||
assert.Nil(t, ars.Spec.MaxRunners, "MaxRunners should be nil")
|
|
||||||
assert.Nil(t, ars.Spec.Proxy, "Proxy should be nil")
|
|
||||||
assert.Nil(t, ars.Spec.GitHubServerTLS, "GitHubServerTLS should be nil")
|
|
||||||
|
|
||||||
assert.NotNil(t, ars.Spec.Template.Spec, "Template.Spec should not be nil")
|
|
||||||
|
|
||||||
assert.Len(t, ars.Spec.Template.Spec.Containers, 1, "Template.Spec should have 1 container")
|
|
||||||
assert.Equal(t, "runner", ars.Spec.Template.Spec.Containers[0].Name)
|
|
||||||
assert.Equal(t, "ghcr.io/actions/actions-runner:latest", ars.Spec.Template.Spec.Containers[0].Image)
|
|
||||||
|
|
||||||
assert.Equal(t, "ACTIONS_RUNNER_CONTAINER_HOOKS", ars.Spec.Template.Spec.Containers[0].Env[0].Name)
|
|
||||||
assert.Equal(t, "/actions-runner/k8s/index.js", ars.Spec.Template.Spec.Containers[0].Env[0].Value)
|
|
||||||
assert.Equal(t, "ACTIONS_RUNNER_POD_NAME", ars.Spec.Template.Spec.Containers[0].Env[1].Name)
|
|
||||||
assert.Equal(t, "ACTIONS_RUNNER_REQUIRE_JOB_CONTAINER", ars.Spec.Template.Spec.Containers[0].Env[2].Name)
|
|
||||||
assert.Equal(t, "true", ars.Spec.Template.Spec.Containers[0].Env[2].Value)
|
|
||||||
|
|
||||||
assert.Len(t, ars.Spec.Template.Spec.Volumes, 1, "Template.Spec should have 1 volume")
|
|
||||||
assert.Equal(t, "work", ars.Spec.Template.Spec.Volumes[0].Name)
|
|
||||||
assert.NotNil(t, ars.Spec.Template.Spec.Volumes[0].Ephemeral, "Template.Spec should have 1 ephemeral volume")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplateRenderedAutoScalingRunnerSet_UsePredefinedSecret(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-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": "pre-defined-secrets",
|
|
||||||
},
|
|
||||||
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.Equal(t, namespaceName, ars.Namespace)
|
|
||||||
assert.Equal(t, "test-runners", ars.Name)
|
|
||||||
|
|
||||||
assert.Equal(t, "auto-scaling-runner-set", ars.Labels["app.kubernetes.io/name"])
|
|
||||||
assert.Equal(t, "test-runners", ars.Labels["app.kubernetes.io/instance"])
|
|
||||||
assert.Equal(t, "https://github.com/actions", ars.Spec.GitHubConfigUrl)
|
|
||||||
assert.Equal(t, "pre-defined-secrets", ars.Spec.GitHubConfigSecret)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplateRenderedAutoScalingRunnerSet_ErrorOnEmptyPredefinedSecret(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-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": "",
|
|
||||||
},
|
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = helm.RenderTemplateE(t, options, helmChartPath, releaseName, []string{"templates/autoscalingrunnerset.yaml"})
|
|
||||||
require.Error(t, err)
|
|
||||||
|
|
||||||
assert.ErrorContains(t, err, "Values.githubConfigSecret is required for setting auth with GitHub server")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplateRenderedWithProxy(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-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": "pre-defined-secrets",
|
|
||||||
"proxy.http.url": "http://proxy.example.com",
|
|
||||||
"proxy.http.credentialSecretRef": "http-secret",
|
|
||||||
"proxy.https.url": "https://proxy.example.com",
|
|
||||||
"proxy.https.credentialSecretRef": "https-secret",
|
|
||||||
"proxy.noProxy": "{example.com,example.org}",
|
|
||||||
},
|
|
||||||
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
|
||||||
}
|
|
||||||
|
|
||||||
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/autoscalingrunnerset.yaml"})
|
|
||||||
|
|
||||||
var ars v1alpha1.AutoscalingRunnerSet
|
|
||||||
helm.UnmarshalK8SYaml(t, output, &ars)
|
|
||||||
|
|
||||||
require.NotNil(t, ars.Spec.Proxy)
|
|
||||||
require.NotNil(t, ars.Spec.Proxy.HTTP)
|
|
||||||
assert.Equal(t, "http://proxy.example.com", ars.Spec.Proxy.HTTP.Url)
|
|
||||||
assert.Equal(t, "http-secret", ars.Spec.Proxy.HTTP.CredentialSecretRef)
|
|
||||||
|
|
||||||
require.NotNil(t, ars.Spec.Proxy.HTTPS)
|
|
||||||
assert.Equal(t, "https://proxy.example.com", ars.Spec.Proxy.HTTPS.Url)
|
|
||||||
assert.Equal(t, "https-secret", ars.Spec.Proxy.HTTPS.CredentialSecretRef)
|
|
||||||
|
|
||||||
require.NotNil(t, ars.Spec.Proxy.NoProxy)
|
|
||||||
require.Len(t, ars.Spec.Proxy.NoProxy, 2)
|
|
||||||
assert.Contains(t, ars.Spec.Proxy.NoProxy, "example.com")
|
|
||||||
assert.Contains(t, ars.Spec.Proxy.NoProxy, "example.org")
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
apiVersion: v2
|
apiVersion: v2
|
||||||
name: actions-runner-controller-2
|
name: gha-runner-scale-set-controller
|
||||||
description: A Helm chart for install actions-runner-controller CRD
|
description: A Helm chart for install actions-runner-controller CRD
|
||||||
|
|
||||||
# A chart can be either an 'application' or a 'library' chart.
|
# A chart can be either an 'application' or a 'library' chart.
|
||||||
@@ -15,13 +15,13 @@ 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.2.0
|
version: 0.3.0
|
||||||
|
|
||||||
# This is the version number of the application being deployed. This version number should be
|
# This is the version number of the application being deployed. This version number should be
|
||||||
# incremented each time you make changes to the application. Versions are not expected to
|
# incremented each time you make changes to the application. Versions are not expected to
|
||||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||||
# It is recommended to use it with quotes.
|
# It is recommended to use it with quotes.
|
||||||
appVersion: "0.2.0"
|
appVersion: "0.3.0"
|
||||||
|
|
||||||
home: https://github.com/actions/actions-runner-controller
|
home: https://github.com/actions/actions-runner-controller
|
||||||
|
|
||||||
@@ -30,4 +30,4 @@ sources:
|
|||||||
|
|
||||||
maintainers:
|
maintainers:
|
||||||
- name: actions
|
- name: actions
|
||||||
url: https://github.com/actions
|
url: https://github.com/actions
|
||||||
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
|
||||||
@@ -55,6 +55,28 @@ spec:
|
|||||||
githubConfigUrl:
|
githubConfigUrl:
|
||||||
description: Required
|
description: Required
|
||||||
type: string
|
type: string
|
||||||
|
githubServerTLS:
|
||||||
|
properties:
|
||||||
|
certificateFrom:
|
||||||
|
description: Required
|
||||||
|
properties:
|
||||||
|
configMapKeyRef:
|
||||||
|
description: Required
|
||||||
|
properties:
|
||||||
|
key:
|
||||||
|
description: The key to select.
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||||
|
type: string
|
||||||
|
optional:
|
||||||
|
description: Specify whether the ConfigMap or its key must be defined
|
||||||
|
type: boolean
|
||||||
|
required:
|
||||||
|
- key
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
image:
|
image:
|
||||||
description: Required
|
description: Required
|
||||||
type: string
|
type: string
|
||||||
@@ -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:
|
||||||
@@ -51,9 +63,25 @@ spec:
|
|||||||
type: string
|
type: string
|
||||||
githubServerTLS:
|
githubServerTLS:
|
||||||
properties:
|
properties:
|
||||||
certConfigMapRef:
|
certificateFrom:
|
||||||
description: Required
|
description: Required
|
||||||
type: string
|
properties:
|
||||||
|
configMapKeyRef:
|
||||||
|
description: Required
|
||||||
|
properties:
|
||||||
|
key:
|
||||||
|
description: The key to select.
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||||
|
type: string
|
||||||
|
optional:
|
||||||
|
description: Specify whether the ConfigMap or its key must be defined
|
||||||
|
type: boolean
|
||||||
|
required:
|
||||||
|
- key
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
type: object
|
type: object
|
||||||
maxRunners:
|
maxRunners:
|
||||||
minimum: 0
|
minimum: 0
|
||||||
@@ -86,6 +114,8 @@ spec:
|
|||||||
type: object
|
type: object
|
||||||
runnerGroup:
|
runnerGroup:
|
||||||
type: string
|
type: string
|
||||||
|
runnerScaleSetName:
|
||||||
|
type: string
|
||||||
template:
|
template:
|
||||||
description: Required
|
description: Required
|
||||||
properties:
|
properties:
|
||||||
@@ -4288,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
|
||||||
@@ -64,9 +64,25 @@ spec:
|
|||||||
type: string
|
type: string
|
||||||
githubServerTLS:
|
githubServerTLS:
|
||||||
properties:
|
properties:
|
||||||
certConfigMapRef:
|
certificateFrom:
|
||||||
description: Required
|
description: Required
|
||||||
type: string
|
properties:
|
||||||
|
configMapKeyRef:
|
||||||
|
description: Required
|
||||||
|
properties:
|
||||||
|
key:
|
||||||
|
description: The key to select.
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||||
|
type: string
|
||||||
|
optional:
|
||||||
|
description: Specify whether the ConfigMap or its key must be defined
|
||||||
|
type: boolean
|
||||||
|
required:
|
||||||
|
- key
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
type: object
|
type: object
|
||||||
metadata:
|
metadata:
|
||||||
description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata'
|
description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata'
|
||||||
@@ -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:
|
||||||
@@ -46,9 +58,25 @@ spec:
|
|||||||
type: string
|
type: string
|
||||||
githubServerTLS:
|
githubServerTLS:
|
||||||
properties:
|
properties:
|
||||||
certConfigMapRef:
|
certificateFrom:
|
||||||
description: Required
|
description: Required
|
||||||
type: string
|
properties:
|
||||||
|
configMapKeyRef:
|
||||||
|
description: Required
|
||||||
|
properties:
|
||||||
|
key:
|
||||||
|
description: The key to select.
|
||||||
|
type: string
|
||||||
|
name:
|
||||||
|
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||||
|
type: string
|
||||||
|
optional:
|
||||||
|
description: Specify whether the ConfigMap or its key must be defined
|
||||||
|
type: boolean
|
||||||
|
required:
|
||||||
|
- key
|
||||||
|
type: object
|
||||||
|
type: object
|
||||||
type: object
|
type: object
|
||||||
metadata:
|
metadata:
|
||||||
description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata'
|
description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata'
|
||||||
@@ -4280,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
|
||||||
113
charts/gha-runner-scale-set-controller/templates/_helpers.tpl
Normal file
113
charts/gha-runner-scale-set-controller/templates/_helpers.tpl
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
{{/*
|
||||||
|
Expand the name of the chart.
|
||||||
|
*/}}
|
||||||
|
{{- define "gha-runner-scale-set-controller.name" -}}
|
||||||
|
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create a default fully qualified app name.
|
||||||
|
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||||
|
If release name contains chart name it will be used as a full name.
|
||||||
|
*/}}
|
||||||
|
{{- define "gha-runner-scale-set-controller.fullname" -}}
|
||||||
|
{{- if .Values.fullnameOverride }}
|
||||||
|
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- else }}
|
||||||
|
{{- $name := default .Chart.Name .Values.nameOverride }}
|
||||||
|
{{- if contains $name .Release.Name }}
|
||||||
|
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- else }}
|
||||||
|
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create chart name and version as used by the chart label.
|
||||||
|
*/}}
|
||||||
|
{{- define "gha-runner-scale-set-controller.chart" -}}
|
||||||
|
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Common labels
|
||||||
|
*/}}
|
||||||
|
{{- define "gha-runner-scale-set-controller.labels" -}}
|
||||||
|
helm.sh/chart: {{ include "gha-runner-scale-set-controller.chart" . }}
|
||||||
|
{{ include "gha-runner-scale-set-controller.selectorLabels" . }}
|
||||||
|
{{- if .Chart.AppVersion }}
|
||||||
|
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||||
|
{{- end }}
|
||||||
|
app.kubernetes.io/part-of: gha-runner-scale-set-controller
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
{{- range $k, $v := .Values.labels }}
|
||||||
|
{{ $k }}: {{ $v }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Selector labels
|
||||||
|
*/}}
|
||||||
|
{{- define "gha-runner-scale-set-controller.selectorLabels" -}}
|
||||||
|
app.kubernetes.io/name: {{ include "gha-runner-scale-set-controller.name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create the name of the service account to use
|
||||||
|
*/}}
|
||||||
|
{{- define "gha-runner-scale-set-controller.serviceAccountName" -}}
|
||||||
|
{{- if eq .Values.serviceAccount.name "default"}}
|
||||||
|
{{- fail "serviceAccount.name cannot be set to 'default'" }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.serviceAccount.create }}
|
||||||
|
{{- default (include "gha-runner-scale-set-controller.fullname" .) .Values.serviceAccount.name }}
|
||||||
|
{{- else }}
|
||||||
|
{{- if not .Values.serviceAccount.name }}
|
||||||
|
{{- fail "serviceAccount.name must be set if serviceAccount.create is false" }}
|
||||||
|
{{- else }}
|
||||||
|
{{- .Values.serviceAccount.name }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "gha-runner-scale-set-controller.managerClusterRoleName" -}}
|
||||||
|
{{- include "gha-runner-scale-set-controller.fullname" . }}-manager-cluster-role
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "gha-runner-scale-set-controller.managerClusterRoleBinding" -}}
|
||||||
|
{{- 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 }}
|
||||||
|
|
||||||
|
{{- define "gha-runner-scale-set-controller.leaderElectionRoleName" -}}
|
||||||
|
{{- include "gha-runner-scale-set-controller.fullname" . }}-leader-election-role
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "gha-runner-scale-set-controller.leaderElectionRoleBinding" -}}
|
||||||
|
{{- include "gha-runner-scale-set-controller.fullname" . }}-leader-election-rolebinding
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "gha-runner-scale-set-controller.imagePullSecretsNames" -}}
|
||||||
|
{{- $names := list }}
|
||||||
|
{{- range $k, $v := . }}
|
||||||
|
{{- $names = append $names $v.name }}
|
||||||
|
{{- end }}
|
||||||
|
{{- $names | join ","}}
|
||||||
|
{{- end }}
|
||||||
@@ -1,15 +1,20 @@
|
|||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ include "actions-runner-controller-2.fullname" . }}
|
name: {{ include "gha-runner-scale-set-controller.fullname" . }}
|
||||||
namespace: {{ .Release.Namespace }}
|
namespace: {{ .Release.Namespace }}
|
||||||
labels:
|
labels:
|
||||||
{{- include "actions-runner-controller-2.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:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
{{- include "actions-runner-controller-2.selectorLabels" . | nindent 6 }}
|
{{- include "gha-runner-scale-set-controller.selectorLabels" . | nindent 6 }}
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
@@ -18,16 +23,16 @@ 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 "actions-runner-controller-2.selectorLabels" . | nindent 8 }}
|
{{- include "gha-runner-scale-set-controller.selectorLabels" . | nindent 8 }}
|
||||||
spec:
|
spec:
|
||||||
{{- with .Values.imagePullSecrets }}
|
{{- with .Values.imagePullSecrets }}
|
||||||
imagePullSecrets:
|
imagePullSecrets:
|
||||||
{{- toYaml . | nindent 8 }}
|
{{- toYaml . | nindent 8 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
serviceAccountName: {{ include "actions-runner-controller-2.serviceAccountName" . }}
|
serviceAccountName: {{ include "gha-runner-scale-set-controller.serviceAccountName" . }}
|
||||||
{{- with .Values.podSecurityContext }}
|
{{- with .Values.podSecurityContext }}
|
||||||
securityContext:
|
securityContext:
|
||||||
{{- toYaml . | nindent 8 }}
|
{{- toYaml . | nindent 8 }}
|
||||||
@@ -43,33 +48,29 @@ spec:
|
|||||||
- "--auto-scaling-runner-set-only"
|
- "--auto-scaling-runner-set-only"
|
||||||
{{- if gt (int (default 1 .Values.replicaCount)) 1 }}
|
{{- if gt (int (default 1 .Values.replicaCount)) 1 }}
|
||||||
- "--enable-leader-election"
|
- "--enable-leader-election"
|
||||||
- "--leader-election-id={{ include "actions-runner-controller-2.fullname" . }}"
|
- "--leader-election-id={{ include "gha-runner-scale-set-controller.fullname" . }}"
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- with .Values.imagePullSecrets }}
|
{{- with .Values.imagePullSecrets }}
|
||||||
- "--auto-scaler-image-pull-secrets={{ include "actions-runner-controller-2.imagePullSecretsNames" . }}"
|
- "--auto-scaler-image-pull-secrets={{ include "gha-runner-scale-set-controller.imagePullSecretsNames" . }}"
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- 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,9 +1,9 @@
|
|||||||
{{- 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
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ include "actions-runner-controller-2.leaderElectionRoleName" . }}
|
name: {{ include "gha-runner-scale-set-controller.leaderElectionRoleName" . }}
|
||||||
namespace: {{ .Release.Namespace }}
|
namespace: {{ .Release.Namespace }}
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: ["coordination.k8s.io"]
|
- apiGroups: ["coordination.k8s.io"]
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
{{- if gt (int (default 1 .Values.replicaCount)) 1 }}
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: RoleBinding
|
||||||
|
metadata:
|
||||||
|
name: {{ include "gha-runner-scale-set-controller.leaderElectionRoleBinding" . }}
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: Role
|
||||||
|
name: {{ include "gha-runner-scale-set-controller.leaderElectionRoleName" . }}
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: {{ include "gha-runner-scale-set-controller.serviceAccountName" . }}
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
|
{{- end }}
|
||||||
@@ -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 "actions-runner-controller-2.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,38 +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
|
- list
|
||||||
- watch
|
- watch
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
@@ -151,10 +124,6 @@ rules:
|
|||||||
resources:
|
resources:
|
||||||
- rolebindings
|
- rolebindings
|
||||||
verbs:
|
verbs:
|
||||||
- create
|
|
||||||
- delete
|
|
||||||
- get
|
|
||||||
- update
|
|
||||||
- list
|
- list
|
||||||
- watch
|
- watch
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
@@ -162,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
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: RoleBinding
|
||||||
|
metadata:
|
||||||
|
name: {{ include "gha-runner-scale-set-controller.managerListenerRoleBinding" . }}
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: Role
|
||||||
|
name: {{ include "gha-runner-scale-set-controller.managerListenerRoleName" . }}
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: {{ include "gha-runner-scale-set-controller.serviceAccountName" . }}
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
@@ -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,11 +1,11 @@
|
|||||||
{{- if .Values.serviceAccount.create -}}
|
{{- if .Values.serviceAccount.create }}
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: ServiceAccount
|
kind: ServiceAccount
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ include "actions-runner-controller-2.serviceAccountName" . }}
|
name: {{ include "gha-runner-scale-set-controller.serviceAccountName" . }}
|
||||||
namespace: {{ .Release.Namespace }}
|
namespace: {{ .Release.Namespace }}
|
||||||
labels:
|
labels:
|
||||||
{{- include "actions-runner-controller-2.labels" . | nindent 4 }}
|
{{- include "gha-runner-scale-set-controller.labels" . | nindent 4 }}
|
||||||
{{- with .Values.serviceAccount.annotations }}
|
{{- with .Values.serviceAccount.annotations }}
|
||||||
annotations:
|
annotations:
|
||||||
{{- toYaml . | nindent 4 }}
|
{{- toYaml . | nindent 4 }}
|
||||||
878
charts/gha-runner-scale-set-controller/tests/template_test.go
Normal file
878
charts/gha-runner-scale-set-controller/tests/template_test.go
Normal file
@@ -0,0 +1,878 @@
|
|||||||
|
package tests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/gruntwork-io/terratest/modules/helm"
|
||||||
|
"github.com/gruntwork-io/terratest/modules/k8s"
|
||||||
|
"github.com/gruntwork-io/terratest/modules/random"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
appsv1 "k8s.io/api/apps/v1"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Chart struct {
|
||||||
|
Version string `yaml:"version"`
|
||||||
|
AppVersion string `yaml:"appVersion"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTemplate_CreateServiceAccount(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",
|
||||||
|
"serviceAccount.annotations.foo": "bar",
|
||||||
|
},
|
||||||
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
|
}
|
||||||
|
|
||||||
|
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/serviceaccount.yaml"})
|
||||||
|
|
||||||
|
var serviceAccount corev1.ServiceAccount
|
||||||
|
helm.UnmarshalK8SYaml(t, output, &serviceAccount)
|
||||||
|
|
||||||
|
assert.Equal(t, namespaceName, serviceAccount.Namespace)
|
||||||
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller", serviceAccount.Name)
|
||||||
|
assert.Equal(t, "bar", string(serviceAccount.Annotations["foo"]))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTemplate_CreateServiceAccount_OverwriteName(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",
|
||||||
|
"serviceAccount.name": "overwritten-name",
|
||||||
|
"serviceAccount.annotations.foo": "bar",
|
||||||
|
},
|
||||||
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
|
}
|
||||||
|
|
||||||
|
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/serviceaccount.yaml"})
|
||||||
|
|
||||||
|
var serviceAccount corev1.ServiceAccount
|
||||||
|
helm.UnmarshalK8SYaml(t, output, &serviceAccount)
|
||||||
|
|
||||||
|
assert.Equal(t, namespaceName, serviceAccount.Namespace)
|
||||||
|
assert.Equal(t, "overwritten-name", serviceAccount.Name)
|
||||||
|
assert.Equal(t, "bar", string(serviceAccount.Annotations["foo"]))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTemplate_CreateServiceAccount_CannotUseDefaultServiceAccount(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",
|
||||||
|
"serviceAccount.name": "default",
|
||||||
|
"serviceAccount.annotations.foo": "bar",
|
||||||
|
},
|
||||||
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = helm.RenderTemplateE(t, options, helmChartPath, releaseName, []string{"templates/serviceaccount.yaml"})
|
||||||
|
assert.ErrorContains(t, err, "serviceAccount.name cannot be set to 'default'", "We should get an error because the default service account cannot be used")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTemplate_NotCreateServiceAccount(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": "false",
|
||||||
|
"serviceAccount.name": "overwritten-name",
|
||||||
|
"serviceAccount.annotations.foo": "bar",
|
||||||
|
},
|
||||||
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = helm.RenderTemplateE(t, options, helmChartPath, releaseName, []string{"templates/serviceaccount.yaml"})
|
||||||
|
assert.ErrorContains(t, err, "could not find template templates/serviceaccount.yaml in chart", "We should get an error because the template should be skipped")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTemplate_NotCreateServiceAccount_ServiceAccountNotSet(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": "false",
|
||||||
|
"serviceAccount.annotations.foo": "bar",
|
||||||
|
},
|
||||||
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = helm.RenderTemplateE(t, options, helmChartPath, releaseName, []string{"templates/deployment.yaml"})
|
||||||
|
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_CreateManagerClusterRole(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_cluster_role.yaml"})
|
||||||
|
|
||||||
|
var managerClusterRole rbacv1.ClusterRole
|
||||||
|
helm.UnmarshalK8SYaml(t, output, &managerClusterRole)
|
||||||
|
|
||||||
|
assert.Empty(t, managerClusterRole.Namespace, "ClusterRole should not have a namespace")
|
||||||
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller-manager-cluster-role", managerClusterRole.Name)
|
||||||
|
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_ManagerClusterRoleBinding(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_cluster_role_binding.yaml"})
|
||||||
|
|
||||||
|
var managerClusterRoleBinding rbacv1.ClusterRoleBinding
|
||||||
|
helm.UnmarshalK8SYaml(t, output, &managerClusterRoleBinding)
|
||||||
|
|
||||||
|
assert.Empty(t, managerClusterRoleBinding.Namespace, "ClusterRoleBinding should not have a namespace")
|
||||||
|
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-cluster-role", managerClusterRoleBinding.RoleRef.Name)
|
||||||
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller", managerClusterRoleBinding.Subjects[0].Name)
|
||||||
|
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) {
|
||||||
|
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",
|
||||||
|
},
|
||||||
|
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.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, "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, managerImage, 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, 2)
|
||||||
|
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.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_ControllerDeployment_Customize(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{
|
||||||
|
"labels.foo": "bar",
|
||||||
|
"labels.github": "actions",
|
||||||
|
"replicaCount": "1",
|
||||||
|
"image.pullPolicy": "Always",
|
||||||
|
"image.tag": "dev",
|
||||||
|
"imagePullSecrets[0].name": "dockerhub",
|
||||||
|
"nameOverride": "gha-runner-scale-set-controller-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",
|
||||||
|
"podAnnotations.foo": "bar",
|
||||||
|
"podSecurityContext.fsGroup": "1000",
|
||||||
|
"securityContext.runAsUser": "1000",
|
||||||
|
"securityContext.runAsNonRoot": "true",
|
||||||
|
"resources.limits.cpu": "500m",
|
||||||
|
"nodeSelector.foo": "bar",
|
||||||
|
"tolerations[0].key": "foo",
|
||||||
|
"affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[0].matchExpressions[0].key": "foo",
|
||||||
|
"affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms[0].matchExpressions[0].operator": "bar",
|
||||||
|
"priorityClassName": "test-priority-class",
|
||||||
|
},
|
||||||
|
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, "gha-runner-scale-set-controller-fullname-override", 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-override", 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, "gha-runner-scale-set-controller", deployment.Labels["app.kubernetes.io/part-of"])
|
||||||
|
assert.Equal(t, "bar", deployment.Labels["foo"])
|
||||||
|
assert.Equal(t, "actions", deployment.Labels["github"])
|
||||||
|
|
||||||
|
assert.Equal(t, int32(1), *deployment.Spec.Replicas)
|
||||||
|
|
||||||
|
assert.Equal(t, "gha-runner-scale-set-controller-override", 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-override", deployment.Spec.Template.Labels["app.kubernetes.io/name"])
|
||||||
|
assert.Equal(t, "test-arc", deployment.Spec.Template.Labels["app.kubernetes.io/instance"])
|
||||||
|
|
||||||
|
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, "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.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, int64(1000), *deployment.Spec.Template.Spec.SecurityContext.FSGroup)
|
||||||
|
assert.Equal(t, "test-priority-class", 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, 1)
|
||||||
|
assert.Equal(t, "bar", deployment.Spec.Template.Spec.NodeSelector["foo"])
|
||||||
|
|
||||||
|
assert.NotNil(t, deployment.Spec.Template.Spec.Affinity.NodeAffinity)
|
||||||
|
assert.Equal(t, "foo", deployment.Spec.Template.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms[0].MatchExpressions[0].Key)
|
||||||
|
assert.Equal(t, "bar", string(deployment.Spec.Template.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms[0].MatchExpressions[0].Operator))
|
||||||
|
|
||||||
|
assert.Len(t, deployment.Spec.Template.Spec.Tolerations, 1)
|
||||||
|
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.Equal(t, "manager", deployment.Spec.Template.Spec.Containers[0].Name)
|
||||||
|
assert.Equal(t, managerImage, deployment.Spec.Template.Spec.Containers[0].Image)
|
||||||
|
assert.Equal(t, corev1.PullAlways, 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, "--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.Len(t, deployment.Spec.Template.Spec.Containers[0].Env, 3)
|
||||||
|
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, "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, "metadata.namespace", deployment.Spec.Template.Spec.Containers[0].Env[1].ValueFrom.FieldRef.FieldPath)
|
||||||
|
|
||||||
|
assert.Equal(t, "500m", deployment.Spec.Template.Spec.Containers[0].Resources.Limits.Cpu().String())
|
||||||
|
assert.True(t, *deployment.Spec.Template.Spec.Containers[0].SecurityContext.RunAsNonRoot)
|
||||||
|
assert.Equal(t, int64(1000), *deployment.Spec.Template.Spec.Containers[0].SecurityContext.RunAsUser)
|
||||||
|
|
||||||
|
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_EnableLeaderElectionRole(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{
|
||||||
|
"replicaCount": "2",
|
||||||
|
},
|
||||||
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
|
}
|
||||||
|
|
||||||
|
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/leader_election_role.yaml"})
|
||||||
|
|
||||||
|
var leaderRole rbacv1.Role
|
||||||
|
helm.UnmarshalK8SYaml(t, output, &leaderRole)
|
||||||
|
|
||||||
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller-leader-election-role", leaderRole.Name)
|
||||||
|
assert.Equal(t, namespaceName, leaderRole.Namespace)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTemplate_EnableLeaderElectionRoleBinding(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{
|
||||||
|
"replicaCount": "2",
|
||||||
|
},
|
||||||
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
|
}
|
||||||
|
|
||||||
|
output := helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/leader_election_role_binding.yaml"})
|
||||||
|
|
||||||
|
var leaderRoleBinding rbacv1.RoleBinding
|
||||||
|
helm.UnmarshalK8SYaml(t, output, &leaderRoleBinding)
|
||||||
|
|
||||||
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller-leader-election-rolebinding", leaderRoleBinding.Name)
|
||||||
|
assert.Equal(t, namespaceName, leaderRoleBinding.Namespace)
|
||||||
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller-leader-election-role", leaderRoleBinding.RoleRef.Name)
|
||||||
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller", leaderRoleBinding.Subjects[0].Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTemplate_EnableLeaderElection(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{
|
||||||
|
"replicaCount": "2",
|
||||||
|
"image.tag": "dev",
|
||||||
|
},
|
||||||
|
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, int32(2), *deployment.Spec.Replicas)
|
||||||
|
|
||||||
|
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, 4)
|
||||||
|
assert.Equal(t, "--auto-scaling-runner-set-only", deployment.Spec.Template.Spec.Containers[0].Args[0])
|
||||||
|
assert.Equal(t, "--enable-leader-election", deployment.Spec.Template.Spec.Containers[0].Args[1])
|
||||||
|
assert.Equal(t, "--leader-election-id=test-arc-gha-runner-scale-set-controller", deployment.Spec.Template.Spec.Containers[0].Args[2])
|
||||||
|
assert.Equal(t, "--log-level=debug", deployment.Spec.Template.Spec.Containers[0].Args[3])
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTemplate_ControllerDeployment_ForwardImagePullSecrets(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{
|
||||||
|
"imagePullSecrets[0].name": "dockerhub",
|
||||||
|
"imagePullSecrets[1].name": "ghcr",
|
||||||
|
},
|
||||||
|
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.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, "--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])
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
# Default values for actions-runner-controller-2.
|
# Default values for gha-runner-scale-set-controller.
|
||||||
# This is a YAML-formatted file.
|
# This is a YAML-formatted file.
|
||||||
# Declare variables to be passed into your templates.
|
# Declare variables to be passed into your templates.
|
||||||
labels: {}
|
labels: {}
|
||||||
|
|
||||||
# leaderElection will be enabled when replicaCount>1,
|
# leaderElection will be enabled when replicaCount>1,
|
||||||
# So, only one replica will in charge of reconciliation at a given time
|
# So, only one replica will in charge of reconciliation at a given time
|
||||||
# leaderElectionId will be set to {{ define actions-runner-controller-2.fullname }}.
|
# leaderElectionId will be set to {{ define gha-runner-scale-set-controller.fullname }}.
|
||||||
replicaCount: 1
|
replicaCount: 1
|
||||||
|
|
||||||
image:
|
image:
|
||||||
repository: "ghcr.io/actions/actions-runner-controller-2"
|
repository: "ghcr.io/actions/gha-runner-scale-set-controller"
|
||||||
pullPolicy: IfNotPresent
|
pullPolicy: IfNotPresent
|
||||||
# Overrides the image tag whose default is the chart appVersion.
|
# Overrides the image tag whose default is the chart appVersion.
|
||||||
tag: ""
|
tag: ""
|
||||||
@@ -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: ""
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
apiVersion: v2
|
apiVersion: v2
|
||||||
name: auto-scaling-runner-set
|
name: gha-runner-scale-set
|
||||||
description: A Helm chart for deploying an AutoScalingRunnerSet
|
description: A Helm chart for deploying an AutoScalingRunnerSet
|
||||||
|
|
||||||
# A chart can be either an 'application' or a 'library' chart.
|
# A chart can be either an 'application' or a 'library' chart.
|
||||||
@@ -15,13 +15,13 @@ 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.2.0
|
version: 0.3.0
|
||||||
|
|
||||||
# This is the version number of the application being deployed. This version number should be
|
# This is the version number of the application being deployed. This version number should be
|
||||||
# incremented each time you make changes to the application. Versions are not expected to
|
# incremented each time you make changes to the application. Versions are not expected to
|
||||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||||
# It is recommended to use it with quotes.
|
# It is recommended to use it with quotes.
|
||||||
appVersion: "0.2.0"
|
appVersion: "0.3.0"
|
||||||
|
|
||||||
home: https://github.com/actions/dev-arc
|
home: https://github.com/actions/dev-arc
|
||||||
|
|
||||||
@@ -30,4 +30,4 @@ sources:
|
|||||||
|
|
||||||
maintainers:
|
maintainers:
|
||||||
- name: actions
|
- name: actions
|
||||||
url: https://github.com/actions
|
url: https://github.com/actions
|
||||||
@@ -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
|
||||||
552
charts/gha-runner-scale-set/templates/_helpers.tpl
Normal file
552
charts/gha-runner-scale-set/templates/_helpers.tpl
Normal file
@@ -0,0 +1,552 @@
|
|||||||
|
{{/*
|
||||||
|
Expand the name of the chart.
|
||||||
|
*/}}
|
||||||
|
{{- define "gha-runner-scale-set.name" -}}
|
||||||
|
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create a default fully qualified app name.
|
||||||
|
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||||
|
If release name contains chart name it will be used as a full name.
|
||||||
|
*/}}
|
||||||
|
{{- define "gha-runner-scale-set.fullname" -}}
|
||||||
|
{{- if .Values.fullnameOverride }}
|
||||||
|
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- else }}
|
||||||
|
{{- $name := default .Chart.Name .Values.nameOverride }}
|
||||||
|
{{- if contains $name .Release.Name }}
|
||||||
|
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- else }}
|
||||||
|
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create chart name and version as used by the chart label.
|
||||||
|
*/}}
|
||||||
|
{{- define "gha-runner-scale-set.chart" -}}
|
||||||
|
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Common labels
|
||||||
|
*/}}
|
||||||
|
{{- define "gha-runner-scale-set.labels" -}}
|
||||||
|
helm.sh/chart: {{ include "gha-runner-scale-set.chart" . }}
|
||||||
|
{{ include "gha-runner-scale-set.selectorLabels" . }}
|
||||||
|
{{- if .Chart.AppVersion }}
|
||||||
|
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||||
|
{{- end }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
app.kubernetes.io/part-of: gha-runner-scale-set
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Selector labels
|
||||||
|
*/}}
|
||||||
|
{{- define "gha-runner-scale-set.selectorLabels" -}}
|
||||||
|
app.kubernetes.io/name: {{ include "gha-runner-scale-set.name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "gha-runner-scale-set.githubsecret" -}}
|
||||||
|
{{- if kindIs "string" .Values.githubConfigSecret }}
|
||||||
|
{{- if not (empty .Values.githubConfigSecret) }}
|
||||||
|
{{- .Values.githubConfigSecret }}
|
||||||
|
{{- else}}
|
||||||
|
{{- fail "Values.githubConfigSecret is required for setting auth with GitHub server." }}
|
||||||
|
{{- end }}
|
||||||
|
{{- else }}
|
||||||
|
{{- include "gha-runner-scale-set.fullname" . }}-github-secret
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "gha-runner-scale-set.noPermissionServiceAccountName" -}}
|
||||||
|
{{- include "gha-runner-scale-set.fullname" . }}-no-permission-service-account
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "gha-runner-scale-set.kubeModeRoleName" -}}
|
||||||
|
{{- include "gha-runner-scale-set.fullname" . }}-kube-mode-role
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "gha-runner-scale-set.kubeModeServiceAccountName" -}}
|
||||||
|
{{- include "gha-runner-scale-set.fullname" . }}-kube-mode-service-account
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "gha-runner-scale-set.dind-init-container" -}}
|
||||||
|
{{- range $i, $val := .Values.template.spec.containers }}
|
||||||
|
{{- if eq $val.name "runner" }}
|
||||||
|
image: {{ $val.image }}
|
||||||
|
command: ["cp"]
|
||||||
|
args: ["-r", "-v", "/home/runner/externals/.", "/home/runner/tmpDir/"]
|
||||||
|
volumeMounts:
|
||||||
|
- name: dind-externals
|
||||||
|
mountPath: /home/runner/tmpDir
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "gha-runner-scale-set.dind-container" -}}
|
||||||
|
image: docker:dind
|
||||||
|
securityContext:
|
||||||
|
privileged: true
|
||||||
|
volumeMounts:
|
||||||
|
- name: work
|
||||||
|
mountPath: /home/runner/_work
|
||||||
|
- name: dind-cert
|
||||||
|
mountPath: /certs/client
|
||||||
|
- name: dind-externals
|
||||||
|
mountPath: /home/runner/externals
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "gha-runner-scale-set.dind-volume" -}}
|
||||||
|
- name: dind-cert
|
||||||
|
emptyDir: {}
|
||||||
|
- name: dind-externals
|
||||||
|
emptyDir: {}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "gha-runner-scale-set.tls-volume" -}}
|
||||||
|
- name: github-server-tls-cert
|
||||||
|
configMap:
|
||||||
|
name: {{ .certificateFrom.configMapKeyRef.name }}
|
||||||
|
items:
|
||||||
|
- key: {{ .certificateFrom.configMapKeyRef.key }}
|
||||||
|
path: {{ .certificateFrom.configMapKeyRef.key }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "gha-runner-scale-set.dind-work-volume" -}}
|
||||||
|
{{- $createWorkVolume := 1 }}
|
||||||
|
{{- range $i, $volume := .Values.template.spec.volumes }}
|
||||||
|
{{- if eq $volume.name "work" }}
|
||||||
|
{{- $createWorkVolume = 0 }}
|
||||||
|
- {{ $volume | toYaml | nindent 2 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq $createWorkVolume 1 }}
|
||||||
|
- name: work
|
||||||
|
emptyDir: {}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "gha-runner-scale-set.kubernetes-mode-work-volume" -}}
|
||||||
|
{{- $createWorkVolume := 1 }}
|
||||||
|
{{- range $i, $volume := .Values.template.spec.volumes }}
|
||||||
|
{{- if eq $volume.name "work" }}
|
||||||
|
{{- $createWorkVolume = 0 }}
|
||||||
|
- {{ $volume | toYaml | nindent 2 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq $createWorkVolume 1 }}
|
||||||
|
- name: work
|
||||||
|
ephemeral:
|
||||||
|
volumeClaimTemplate:
|
||||||
|
spec:
|
||||||
|
{{- .Values.containerMode.kubernetesModeWorkVolumeClaim | toYaml | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "gha-runner-scale-set.non-work-volumes" -}}
|
||||||
|
{{- range $i, $volume := .Values.template.spec.volumes }}
|
||||||
|
{{- if ne $volume.name "work" }}
|
||||||
|
- {{ $volume | toYaml | nindent 2 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "gha-runner-scale-set.non-runner-containers" -}}
|
||||||
|
{{- range $i, $container := .Values.template.spec.containers }}
|
||||||
|
{{- if ne $container.name "runner" }}
|
||||||
|
- {{ $container | toYaml | nindent 2 }}
|
||||||
|
{{- 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 }}
|
||||||
|
|
||||||
|
{{- define "gha-runner-scale-set.dind-runner-container" -}}
|
||||||
|
{{- $tlsConfig := (default (dict) .Values.githubServerTLS) }}
|
||||||
|
{{- range $i, $container := .Values.template.spec.containers }}
|
||||||
|
{{- if eq $container.name "runner" }}
|
||||||
|
{{- range $key, $val := $container }}
|
||||||
|
{{- if and (ne $key "env") (ne $key "volumeMounts") (ne $key "name") }}
|
||||||
|
{{ $key }}: {{ $val | toYaml | nindent 2 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- $setDockerHost := 1 }}
|
||||||
|
{{- $setDockerTlsVerify := 1 }}
|
||||||
|
{{- $setDockerCertPath := 1 }}
|
||||||
|
{{- $setRunnerWaitDocker := 1 }}
|
||||||
|
{{- $setNodeExtraCaCerts := 0 }}
|
||||||
|
{{- $setRunnerUpdateCaCerts := 0 }}
|
||||||
|
{{- if $tlsConfig.runnerMountPath }}
|
||||||
|
{{- $setNodeExtraCaCerts = 1 }}
|
||||||
|
{{- $setRunnerUpdateCaCerts = 1 }}
|
||||||
|
{{- end }}
|
||||||
|
env:
|
||||||
|
{{- with $container.env }}
|
||||||
|
{{- range $i, $env := . }}
|
||||||
|
{{- if eq $env.name "DOCKER_HOST" }}
|
||||||
|
{{- $setDockerHost = 0 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq $env.name "DOCKER_TLS_VERIFY" }}
|
||||||
|
{{- $setDockerTlsVerify = 0 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq $env.name "DOCKER_CERT_PATH" }}
|
||||||
|
{{- $setDockerCertPath = 0 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq $env.name "RUNNER_WAIT_FOR_DOCKER_IN_SECONDS" }}
|
||||||
|
{{- $setRunnerWaitDocker = 0 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq $env.name "NODE_EXTRA_CA_CERTS" }}
|
||||||
|
{{- $setNodeExtraCaCerts = 0 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq $env.name "RUNNER_UPDATE_CA_CERTS" }}
|
||||||
|
{{- $setRunnerUpdateCaCerts = 0 }}
|
||||||
|
{{- end }}
|
||||||
|
- {{ $env | toYaml | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if $setDockerHost }}
|
||||||
|
- name: DOCKER_HOST
|
||||||
|
value: tcp://localhost:2376
|
||||||
|
{{- end }}
|
||||||
|
{{- if $setDockerTlsVerify }}
|
||||||
|
- name: DOCKER_TLS_VERIFY
|
||||||
|
value: "1"
|
||||||
|
{{- end }}
|
||||||
|
{{- if $setDockerCertPath }}
|
||||||
|
- name: DOCKER_CERT_PATH
|
||||||
|
value: /certs/client
|
||||||
|
{{- end }}
|
||||||
|
{{- if $setRunnerWaitDocker }}
|
||||||
|
- name: RUNNER_WAIT_FOR_DOCKER_IN_SECONDS
|
||||||
|
value: "120"
|
||||||
|
{{- end }}
|
||||||
|
{{- if $setNodeExtraCaCerts }}
|
||||||
|
- name: NODE_EXTRA_CA_CERTS
|
||||||
|
value: {{ clean (print $tlsConfig.runnerMountPath "/" $tlsConfig.certificateFrom.configMapKeyRef.key) }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if $setRunnerUpdateCaCerts }}
|
||||||
|
- name: RUNNER_UPDATE_CA_CERTS
|
||||||
|
value: "1"
|
||||||
|
{{- end }}
|
||||||
|
{{- $mountWork := 1 }}
|
||||||
|
{{- $mountDindCert := 1 }}
|
||||||
|
{{- $mountGitHubServerTLS := 0 }}
|
||||||
|
{{- if $tlsConfig.runnerMountPath }}
|
||||||
|
{{- $mountGitHubServerTLS = 1 }}
|
||||||
|
{{- end }}
|
||||||
|
volumeMounts:
|
||||||
|
{{- with $container.volumeMounts }}
|
||||||
|
{{- range $i, $volMount := . }}
|
||||||
|
{{- if eq $volMount.name "work" }}
|
||||||
|
{{- $mountWork = 0 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq $volMount.name "dind-cert" }}
|
||||||
|
{{- $mountDindCert = 0 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq $volMount.name "github-server-tls-cert" }}
|
||||||
|
{{- $mountGitHubServerTLS = 0 }}
|
||||||
|
{{- end }}
|
||||||
|
- {{ $volMount | toYaml | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if $mountWork }}
|
||||||
|
- name: work
|
||||||
|
mountPath: /home/runner/_work
|
||||||
|
{{- end }}
|
||||||
|
{{- if $mountDindCert }}
|
||||||
|
- name: dind-cert
|
||||||
|
mountPath: /certs/client
|
||||||
|
readOnly: true
|
||||||
|
{{- end }}
|
||||||
|
{{- if $mountGitHubServerTLS }}
|
||||||
|
- name: github-server-tls-cert
|
||||||
|
mountPath: {{ clean (print $tlsConfig.runnerMountPath "/" $tlsConfig.certificateFrom.configMapKeyRef.key) }}
|
||||||
|
subPath: {{ $tlsConfig.certificateFrom.configMapKeyRef.key }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "gha-runner-scale-set.kubernetes-mode-runner-container" -}}
|
||||||
|
{{- $tlsConfig := (default (dict) .Values.githubServerTLS) }}
|
||||||
|
{{- range $i, $container := .Values.template.spec.containers }}
|
||||||
|
{{- if eq $container.name "runner" }}
|
||||||
|
{{- range $key, $val := $container }}
|
||||||
|
{{- if and (ne $key "env") (ne $key "volumeMounts") (ne $key "name") }}
|
||||||
|
{{ $key }}: {{ $val | toYaml | nindent 2 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- $setContainerHooks := 1 }}
|
||||||
|
{{- $setPodName := 1 }}
|
||||||
|
{{- $setRequireJobContainer := 1 }}
|
||||||
|
{{- $setNodeExtraCaCerts := 0 }}
|
||||||
|
{{- $setRunnerUpdateCaCerts := 0 }}
|
||||||
|
{{- if $tlsConfig.runnerMountPath }}
|
||||||
|
{{- $setNodeExtraCaCerts = 1 }}
|
||||||
|
{{- $setRunnerUpdateCaCerts = 1 }}
|
||||||
|
{{- end }}
|
||||||
|
env:
|
||||||
|
{{- with $container.env }}
|
||||||
|
{{- range $i, $env := . }}
|
||||||
|
{{- if eq $env.name "ACTIONS_RUNNER_CONTAINER_HOOKS" }}
|
||||||
|
{{- $setContainerHooks = 0 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq $env.name "ACTIONS_RUNNER_POD_NAME" }}
|
||||||
|
{{- $setPodName = 0 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq $env.name "ACTIONS_RUNNER_REQUIRE_JOB_CONTAINER" }}
|
||||||
|
{{- $setRequireJobContainer = 0 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq $env.name "NODE_EXTRA_CA_CERTS" }}
|
||||||
|
{{- $setNodeExtraCaCerts = 0 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq $env.name "RUNNER_UPDATE_CA_CERTS" }}
|
||||||
|
{{- $setRunnerUpdateCaCerts = 0 }}
|
||||||
|
{{- end }}
|
||||||
|
- {{ $env | toYaml | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if $setContainerHooks }}
|
||||||
|
- name: ACTIONS_RUNNER_CONTAINER_HOOKS
|
||||||
|
value: /home/runner/k8s/index.js
|
||||||
|
{{- end }}
|
||||||
|
{{- if $setPodName }}
|
||||||
|
- name: ACTIONS_RUNNER_POD_NAME
|
||||||
|
valueFrom:
|
||||||
|
fieldRef:
|
||||||
|
fieldPath: metadata.name
|
||||||
|
{{- end }}
|
||||||
|
{{- if $setRequireJobContainer }}
|
||||||
|
- name: ACTIONS_RUNNER_REQUIRE_JOB_CONTAINER
|
||||||
|
value: "true"
|
||||||
|
{{- end }}
|
||||||
|
{{- if $setNodeExtraCaCerts }}
|
||||||
|
- name: NODE_EXTRA_CA_CERTS
|
||||||
|
value: {{ clean (print $tlsConfig.runnerMountPath "/" $tlsConfig.certificateFrom.configMapKeyRef.key) }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if $setRunnerUpdateCaCerts }}
|
||||||
|
- name: RUNNER_UPDATE_CA_CERTS
|
||||||
|
value: "1"
|
||||||
|
{{- end }}
|
||||||
|
{{- $mountWork := 1 }}
|
||||||
|
{{- $mountGitHubServerTLS := 0 }}
|
||||||
|
{{- if $tlsConfig.runnerMountPath }}
|
||||||
|
{{- $mountGitHubServerTLS = 1 }}
|
||||||
|
{{- end }}
|
||||||
|
volumeMounts:
|
||||||
|
{{- with $container.volumeMounts }}
|
||||||
|
{{- range $i, $volMount := . }}
|
||||||
|
{{- if eq $volMount.name "work" }}
|
||||||
|
{{- $mountWork = 0 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq $volMount.name "github-server-tls-cert" }}
|
||||||
|
{{- $mountGitHubServerTLS = 0 }}
|
||||||
|
{{- end }}
|
||||||
|
- {{ $volMount | toYaml | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if $mountWork }}
|
||||||
|
- name: work
|
||||||
|
mountPath: /home/runner/_work
|
||||||
|
{{- end }}
|
||||||
|
{{- if $mountGitHubServerTLS }}
|
||||||
|
- name: github-server-tls-cert
|
||||||
|
mountPath: {{ clean (print $tlsConfig.runnerMountPath "/" $tlsConfig.certificateFrom.configMapKeyRef.key) }}
|
||||||
|
subPath: {{ $tlsConfig.certificateFrom.configMapKeyRef.key }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "gha-runner-scale-set.default-mode-runner-containers" -}}
|
||||||
|
{{- $tlsConfig := (default (dict) .Values.githubServerTLS) }}
|
||||||
|
{{- range $i, $container := .Values.template.spec.containers }}
|
||||||
|
{{- if ne $container.name "runner" }}
|
||||||
|
- {{ $container | toYaml | nindent 2 }}
|
||||||
|
{{- else }}
|
||||||
|
- name: {{ $container.name }}
|
||||||
|
{{- range $key, $val := $container }}
|
||||||
|
{{- if and (ne $key "env") (ne $key "volumeMounts") (ne $key "name") }}
|
||||||
|
{{ $key }}: {{ $val | toYaml | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- $setNodeExtraCaCerts := 0 }}
|
||||||
|
{{- $setRunnerUpdateCaCerts := 0 }}
|
||||||
|
{{- if $tlsConfig.runnerMountPath }}
|
||||||
|
{{- $setNodeExtraCaCerts = 1 }}
|
||||||
|
{{- $setRunnerUpdateCaCerts = 1 }}
|
||||||
|
{{- end }}
|
||||||
|
env:
|
||||||
|
{{- with $container.env }}
|
||||||
|
{{- range $i, $env := . }}
|
||||||
|
{{- if eq $env.name "NODE_EXTRA_CA_CERTS" }}
|
||||||
|
{{- $setNodeExtraCaCerts = 0 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq $env.name "RUNNER_UPDATE_CA_CERTS" }}
|
||||||
|
{{- $setRunnerUpdateCaCerts = 0 }}
|
||||||
|
{{- end }}
|
||||||
|
- {{ $env | toYaml | nindent 6 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if $setNodeExtraCaCerts }}
|
||||||
|
- name: NODE_EXTRA_CA_CERTS
|
||||||
|
value: {{ clean (print $tlsConfig.runnerMountPath "/" $tlsConfig.certificateFrom.configMapKeyRef.key) }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if $setRunnerUpdateCaCerts }}
|
||||||
|
- name: RUNNER_UPDATE_CA_CERTS
|
||||||
|
value: "1"
|
||||||
|
{{- end }}
|
||||||
|
{{- $mountGitHubServerTLS := 0 }}
|
||||||
|
{{- if $tlsConfig.runnerMountPath }}
|
||||||
|
{{- $mountGitHubServerTLS = 1 }}
|
||||||
|
{{- end }}
|
||||||
|
volumeMounts:
|
||||||
|
{{- with $container.volumeMounts }}
|
||||||
|
{{- range $i, $volMount := . }}
|
||||||
|
{{- if eq $volMount.name "github-server-tls-cert" }}
|
||||||
|
{{- $mountGitHubServerTLS = 0 }}
|
||||||
|
{{- end }}
|
||||||
|
- {{ $volMount | toYaml | nindent 6 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if $mountGitHubServerTLS }}
|
||||||
|
- name: github-server-tls-cert
|
||||||
|
mountPath: {{ clean (print $tlsConfig.runnerMountPath "/" $tlsConfig.certificateFrom.configMapKeyRef.key) }}
|
||||||
|
subPath: {{ $tlsConfig.certificateFrom.configMapKeyRef.key }}
|
||||||
|
{{- 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 }}
|
||||||
142
charts/gha-runner-scale-set/templates/autoscalingrunnerset.yaml
Normal file
142
charts/gha-runner-scale-set/templates/autoscalingrunnerset.yaml
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
apiVersion: actions.github.com/v1alpha1
|
||||||
|
kind: AutoscalingRunnerSet
|
||||||
|
metadata:
|
||||||
|
{{- if or (not .Release.Name) (gt (len .Release.Name) 45) }}
|
||||||
|
{{ fail "Name must have up to 45 characters" }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if gt (len .Release.Namespace) 63 }}
|
||||||
|
{{ fail "Namespace must have up to 63 characters" }}
|
||||||
|
{{- end }}
|
||||||
|
name: {{ .Release.Name }}
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/component: "autoscaling-runner-set"
|
||||||
|
{{- include "gha-runner-scale-set.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
githubConfigUrl: {{ required ".Values.githubConfigUrl is required" (trimSuffix "/" .Values.githubConfigUrl) }}
|
||||||
|
githubConfigSecret: {{ include "gha-runner-scale-set.githubsecret" . }}
|
||||||
|
{{- with .Values.runnerGroup }}
|
||||||
|
runnerGroup: {{ . }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.runnerScaleSetName }}
|
||||||
|
runnerScaleSetName: {{ . }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if .Values.githubServerTLS }}
|
||||||
|
githubServerTLS:
|
||||||
|
{{- with .Values.githubServerTLS.certificateFrom }}
|
||||||
|
certificateFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: {{ .configMapKeyRef.name }}
|
||||||
|
key: {{ .configMapKeyRef.key }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if .Values.proxy }}
|
||||||
|
proxy:
|
||||||
|
{{- if .Values.proxy.http }}
|
||||||
|
http:
|
||||||
|
url: {{ .Values.proxy.http.url }}
|
||||||
|
{{- if .Values.proxy.http.credentialSecretRef }}
|
||||||
|
credentialSecretRef: {{ .Values.proxy.http.credentialSecretRef }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.proxy.https }}
|
||||||
|
https:
|
||||||
|
url: {{ .Values.proxy.https.url }}
|
||||||
|
{{- if .Values.proxy.https.credentialSecretRef }}
|
||||||
|
credentialSecretRef: {{ .Values.proxy.https.credentialSecretRef }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if and .Values.proxy.noProxy (kindIs "slice" .Values.proxy.noProxy) }}
|
||||||
|
noProxy: {{ .Values.proxy.noProxy | toYaml | nindent 6}}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if and (or (kindIs "int64" .Values.minRunners) (kindIs "float64" .Values.minRunners)) (or (kindIs "int64" .Values.maxRunners) (kindIs "float64" .Values.maxRunners)) }}
|
||||||
|
{{- if gt .Values.minRunners .Values.maxRunners }}
|
||||||
|
{{- fail "maxRunners has to be greater or equal to minRunners" }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if or (kindIs "int64" .Values.maxRunners) (kindIs "float64" .Values.maxRunners) }}
|
||||||
|
{{- if lt (.Values.maxRunners | int) 0 }}
|
||||||
|
{{- fail "maxRunners has to be greater or equal to 0" }}
|
||||||
|
{{- end }}
|
||||||
|
maxRunners: {{ .Values.maxRunners | int }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if or (kindIs "int64" .Values.minRunners) (kindIs "float64" .Values.minRunners) }}
|
||||||
|
{{- if lt (.Values.minRunners | int) 0 }}
|
||||||
|
{{- fail "minRunners has to be greater or equal to 0" }}
|
||||||
|
{{- end }}
|
||||||
|
minRunners: {{ .Values.minRunners | int }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
template:
|
||||||
|
{{- with .Values.template.metadata }}
|
||||||
|
metadata:
|
||||||
|
{{- with .labels }}
|
||||||
|
labels:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
{{- range $key, $val := .Values.template.spec }}
|
||||||
|
{{- if and (ne $key "containers") (ne $key "volumes") (ne $key "initContainers") (ne $key "serviceAccountName") }}
|
||||||
|
{{ $key }}: {{ $val | toYaml | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- $containerMode := .Values.containerMode }}
|
||||||
|
{{- if eq $containerMode.type "kubernetes" }}
|
||||||
|
serviceAccountName: {{ default (include "gha-runner-scale-set.kubeModeServiceAccountName" .) .Values.template.spec.serviceAccountName }}
|
||||||
|
{{- else }}
|
||||||
|
serviceAccountName: {{ default (include "gha-runner-scale-set.noPermissionServiceAccountName" .) .Values.template.spec.serviceAccountName }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if or .Values.template.spec.initContainers (eq $containerMode.type "dind") }}
|
||||||
|
initContainers:
|
||||||
|
{{- if eq $containerMode.type "dind" }}
|
||||||
|
- name: init-dind-externals
|
||||||
|
{{- include "gha-runner-scale-set.dind-init-container" . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.template.spec.initContainers }}
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
containers:
|
||||||
|
{{- if eq $containerMode.type "dind" }}
|
||||||
|
- name: runner
|
||||||
|
{{- include "gha-runner-scale-set.dind-runner-container" . | nindent 8 }}
|
||||||
|
- name: dind
|
||||||
|
{{- include "gha-runner-scale-set.dind-container" . | nindent 8 }}
|
||||||
|
{{- include "gha-runner-scale-set.non-runner-non-dind-containers" . | nindent 6 }}
|
||||||
|
{{- else if eq $containerMode.type "kubernetes" }}
|
||||||
|
- name: runner
|
||||||
|
{{- include "gha-runner-scale-set.kubernetes-mode-runner-container" . | nindent 8 }}
|
||||||
|
{{- include "gha-runner-scale-set.non-runner-containers" . | nindent 6 }}
|
||||||
|
{{- else }}
|
||||||
|
{{- include "gha-runner-scale-set.default-mode-runner-containers" . | nindent 6 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- $tlsConfig := (default (dict) .Values.githubServerTLS) }}
|
||||||
|
{{- if or .Values.template.spec.volumes (eq $containerMode.type "dind") (eq $containerMode.type "kubernetes") $tlsConfig.runnerMountPath }}
|
||||||
|
volumes:
|
||||||
|
{{- if $tlsConfig.runnerMountPath }}
|
||||||
|
{{- include "gha-runner-scale-set.tls-volume" $tlsConfig | nindent 6 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq $containerMode.type "dind" }}
|
||||||
|
{{- include "gha-runner-scale-set.dind-volume" . | nindent 6 }}
|
||||||
|
{{- include "gha-runner-scale-set.dind-work-volume" . | nindent 6 }}
|
||||||
|
{{- include "gha-runner-scale-set.non-work-volumes" . | nindent 6 }}
|
||||||
|
{{- else if eq $containerMode.type "kubernetes" }}
|
||||||
|
{{- include "gha-runner-scale-set.kubernetes-mode-work-volume" . | nindent 6 }}
|
||||||
|
{{- include "gha-runner-scale-set.non-work-volumes" . | nindent 6 }}
|
||||||
|
{{- else }}
|
||||||
|
{{- with .Values.template.spec.volumes }}
|
||||||
|
{{- toYaml . | nindent 6 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
@@ -2,10 +2,10 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Secret
|
kind: Secret
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ include "auto-scaling-runner-set.githubsecret" . }}
|
name: {{ include "gha-runner-scale-set.githubsecret" . }}
|
||||||
namespace: {{ .Release.Namespace }}
|
namespace: {{ .Release.Namespace }}
|
||||||
labels:
|
labels:
|
||||||
{{- include "auto-scaling-runner-set.labels" . | nindent 4 }}
|
{{- include "gha-runner-scale-set.labels" . | nindent 4 }}
|
||||||
finalizers:
|
finalizers:
|
||||||
- actions.github.com/secret-protection
|
- actions.github.com/secret-protection
|
||||||
data:
|
data:
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
{{- 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
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ include "auto-scaling-runner-set.kubeModeRoleName" . }}
|
name: {{ include "gha-runner-scale-set.kubeModeRoleName" . }}
|
||||||
namespace: {{ .Release.Namespace }}
|
namespace: {{ .Release.Namespace }}
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
@@ -21,4 +22,4 @@ rules:
|
|||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["secrets"]
|
resources: ["secrets"]
|
||||||
verbs: ["get", "list", "create", "delete"]
|
verbs: ["get", "list", "create", "delete"]
|
||||||
{{- end }}
|
{{- end }}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
{{- $containerMode := .Values.containerMode }}
|
||||||
|
{{- if and (eq $containerMode.type "kubernetes") (not .Values.template.spec.serviceAccountName) }}
|
||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: RoleBinding
|
||||||
|
metadata:
|
||||||
|
name: {{ include "gha-runner-scale-set.kubeModeRoleName" . }}
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: Role
|
||||||
|
name: {{ include "gha-runner-scale-set.kubeModeRoleName" . }}
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: {{ include "gha-runner-scale-set.kubeModeServiceAccountName" . }}
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
|
{{- end }}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
{{- $containerMode := .Values.containerMode }}
|
||||||
|
{{- if and (eq $containerMode.type "kubernetes") (not .Values.template.spec.serviceAccountName) }}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: {{ include "gha-runner-scale-set.kubeModeServiceAccountName" . }}
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
|
labels:
|
||||||
|
{{- include "gha-runner-scale-set.labels" . | nindent 4 }}
|
||||||
|
{{- 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 }}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
{{- $containerMode := .Values.containerMode }}
|
||||||
|
{{- if and (ne $containerMode.type "kubernetes") (not .Values.template.spec.serviceAccountName) }}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: {{ include "gha-runner-scale-set.noPermissionServiceAccountName" . }}
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
|
labels:
|
||||||
|
{{- include "gha-runner-scale-set.labels" . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
1694
charts/gha-runner-scale-set/tests/template_test.go
Normal file
1694
charts/gha-runner-scale-set/tests/template_test.go
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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,19 @@
|
|||||||
|
githubConfigUrl: https://github.com/actions/actions-runner-controller
|
||||||
|
githubConfigSecret:
|
||||||
|
github_token: test
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: other
|
||||||
|
image: other-image:latest
|
||||||
|
volumes:
|
||||||
|
- name: foo
|
||||||
|
emptyDir: {}
|
||||||
|
- name: bar
|
||||||
|
emptyDir: {}
|
||||||
|
- name: work
|
||||||
|
hostPath:
|
||||||
|
path: /data
|
||||||
|
type: Directory
|
||||||
|
containerMode:
|
||||||
|
type: dind
|
||||||
@@ -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
|
||||||
17
charts/gha-runner-scale-set/tests/values_extra_volumes.yaml
Normal file
17
charts/gha-runner-scale-set/tests/values_extra_volumes.yaml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
githubConfigUrl: https://github.com/actions/actions-runner-controller
|
||||||
|
githubConfigSecret:
|
||||||
|
github_token: test
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: other
|
||||||
|
image: other-image:latest
|
||||||
|
volumes:
|
||||||
|
- name: foo
|
||||||
|
emptyDir: {}
|
||||||
|
- name: bar
|
||||||
|
emptyDir: {}
|
||||||
|
- name: work
|
||||||
|
hostPath:
|
||||||
|
path: /data
|
||||||
|
type: Directory
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
githubConfigUrl: https://github.com/actions/actions-runner-controller
|
||||||
|
githubConfigSecret:
|
||||||
|
github_token: test
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: other
|
||||||
|
image: other-image:latest
|
||||||
|
volumes:
|
||||||
|
- name: foo
|
||||||
|
emptyDir: {}
|
||||||
|
- name: bar
|
||||||
|
emptyDir: {}
|
||||||
|
- name: work
|
||||||
|
hostPath:
|
||||||
|
path: /data
|
||||||
|
type: Directory
|
||||||
|
containerMode:
|
||||||
|
type: kubernetes
|
||||||
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
|
||||||
@@ -4,7 +4,7 @@ githubConfigUrl: ""
|
|||||||
|
|
||||||
## githubConfigSecret is the k8s secrets to use when auth with GitHub API.
|
## githubConfigSecret is the k8s secrets to use when auth with GitHub API.
|
||||||
## You can choose to use GitHub App or a PAT token
|
## You can choose to use GitHub App or a PAT token
|
||||||
githubConfigSecret:
|
githubConfigSecret:
|
||||||
### GitHub Apps Configuration
|
### GitHub Apps Configuration
|
||||||
## NOTE: IDs MUST be strings, use quotes
|
## NOTE: IDs MUST be strings, use quotes
|
||||||
#github_app_id: ""
|
#github_app_id: ""
|
||||||
@@ -13,7 +13,7 @@ githubConfigSecret:
|
|||||||
|
|
||||||
### GitHub PAT Configuration
|
### GitHub PAT Configuration
|
||||||
github_token: ""
|
github_token: ""
|
||||||
## If you have a pre-define Kubernetes secret in the same namespace the auto-scaling-runner-set is going to deploy,
|
## If you have a pre-define Kubernetes secret in the same namespace the gha-runner-scale-set is going to deploy,
|
||||||
## you can also reference it via `githubConfigSecret: pre-defined-secret`.
|
## you can also reference it via `githubConfigSecret: pre-defined-secret`.
|
||||||
## You need to make sure your predefined secret has all the required secret data set properly.
|
## You need to make sure your predefined secret has all the required secret data set properly.
|
||||||
## For a pre-defined secret using GitHub PAT, the secret needs to be created like this:
|
## For a pre-defined secret using GitHub PAT, the secret needs to be created like this:
|
||||||
@@ -44,26 +44,54 @@ githubConfigSecret:
|
|||||||
|
|
||||||
# runnerGroup: "default"
|
# runnerGroup: "default"
|
||||||
|
|
||||||
|
## name of the runner scale set to create. Defaults to the helm release name
|
||||||
|
# runnerScaleSetName: ""
|
||||||
|
|
||||||
|
## A self-signed CA certificate for communication with the GitHub server can be
|
||||||
|
## provided using a config map key selector. If `runnerMountPath` is set, for
|
||||||
|
## each runner pod ARC will:
|
||||||
|
## - create a `github-server-tls-cert` volume containing the certificate
|
||||||
|
## specified in `certificateFrom`
|
||||||
|
## - mount that volume on path `runnerMountPath`/{certificate name}
|
||||||
|
## - set NODE_EXTRA_CA_CERTS environment variable to that same path
|
||||||
|
## - set RUNNER_UPDATE_CA_CERTS environment variable to "1" (as of version
|
||||||
|
## 2.303.0 this will instruct the runner to reload certificates on the host)
|
||||||
|
##
|
||||||
|
## If any of the above had already been set by the user in the runner pod
|
||||||
|
## template, ARC will observe those and not overwrite them.
|
||||||
|
## Example configuration:
|
||||||
|
#
|
||||||
|
# githubServerTLS:
|
||||||
|
# certificateFrom:
|
||||||
|
# configMapKeyRef:
|
||||||
|
# name: config-map-name
|
||||||
|
# key: ca.pem
|
||||||
|
# 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: ["/actions-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", "/actions-runner/externals/.", "/actions-runner/tmpDir/"]
|
## command: ["cp", "-r", "-v", "/home/runner/externals/.", "/home/runner/tmpDir/"]
|
||||||
## volumeMounts:
|
## volumeMounts:
|
||||||
## - name: externalsInternal
|
## - name: dind-externals
|
||||||
## mountPath: /actions-runner/tmpDir
|
## mountPath: /home/runner/tmpDir
|
||||||
## containers:
|
## containers:
|
||||||
## - name: runner
|
## - name: runner
|
||||||
## image: ghcr.io/actions/actions-runner:latest
|
## image: ghcr.io/actions/actions-runner:latest
|
||||||
@@ -75,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: /actions-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
|
||||||
@@ -85,18 +113,18 @@ containerMode:
|
|||||||
## securityContext:
|
## securityContext:
|
||||||
## privileged: true
|
## privileged: true
|
||||||
## volumeMounts:
|
## volumeMounts:
|
||||||
## - mountPath: /certs/client
|
## - name: work
|
||||||
## name: dinDInternal
|
## mountPath: /home/runner/_work
|
||||||
## - mountPath: /actions-runner/_work
|
## - name: dind-cert
|
||||||
## name: workingDirectoryInternal
|
## mountPath: /certs/client
|
||||||
## - mountPath: /actions-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
|
||||||
@@ -107,7 +135,7 @@ containerMode:
|
|||||||
## image: ghcr.io/actions/actions-runner:latest
|
## image: ghcr.io/actions/actions-runner:latest
|
||||||
## env:
|
## env:
|
||||||
## - name: ACTIONS_RUNNER_CONTAINER_HOOKS
|
## - name: ACTIONS_RUNNER_CONTAINER_HOOKS
|
||||||
## value: /actions-runner/k8s/index.js
|
## value: /home/runner/k8s/index.js
|
||||||
## - name: ACTIONS_RUNNER_POD_NAME
|
## - name: ACTIONS_RUNNER_POD_NAME
|
||||||
## valueFrom:
|
## valueFrom:
|
||||||
## fieldRef:
|
## fieldRef:
|
||||||
@@ -116,7 +144,7 @@ containerMode:
|
|||||||
## value: "true"
|
## value: "true"
|
||||||
## volumeMounts:
|
## volumeMounts:
|
||||||
## - name: work
|
## - name: work
|
||||||
## mountPath: /actions-runner/_work
|
## mountPath: /home/runner/_work
|
||||||
## volumes:
|
## volumes:
|
||||||
## - name: work
|
## - name: work
|
||||||
## ephemeral:
|
## ephemeral:
|
||||||
@@ -127,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
|
||||||
@@ -18,7 +18,10 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/x509"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
@@ -28,6 +31,7 @@ import (
|
|||||||
"github.com/actions/actions-runner-controller/logging"
|
"github.com/actions/actions-runner-controller/logging"
|
||||||
"github.com/go-logr/logr"
|
"github.com/go-logr/logr"
|
||||||
"github.com/kelseyhightower/envconfig"
|
"github.com/kelseyhightower/envconfig"
|
||||||
|
"golang.org/x/net/http/httpproxy"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RunnerScaleSetListenerConfig struct {
|
type RunnerScaleSetListenerConfig struct {
|
||||||
@@ -41,6 +45,7 @@ type RunnerScaleSetListenerConfig struct {
|
|||||||
MaxRunners int `split_words:"true"`
|
MaxRunners int `split_words:"true"`
|
||||||
MinRunners int `split_words:"true"`
|
MinRunners int `split_words:"true"`
|
||||||
RunnerScaleSetId int `split_words:"true"`
|
RunnerScaleSetId int `split_words:"true"`
|
||||||
|
ServerRootCA string `split_words:"true"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -84,11 +89,11 @@ func run(rc RunnerScaleSetListenerConfig, logger logr.Logger) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actionsServiceClient, err := actions.NewClient(
|
actionsServiceClient, err := newActionsClientFromConfig(
|
||||||
rc.ConfigureUrl,
|
rc,
|
||||||
creds,
|
creds,
|
||||||
actions.WithUserAgent(fmt.Sprintf("actions-runner-controller/%s", build.Version)),
|
|
||||||
actions.WithLogger(logger),
|
actions.WithLogger(logger),
|
||||||
|
actions.WithUserAgent(fmt.Sprintf("actions-runner-controller/%s", build.Version)),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create an Actions Service client: %w", err)
|
return fmt.Errorf("failed to create an Actions Service client: %w", err)
|
||||||
@@ -155,3 +160,26 @@ func validateConfig(config *RunnerScaleSetListenerConfig) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newActionsClientFromConfig(config RunnerScaleSetListenerConfig, creds *actions.ActionsAuth, options ...actions.ClientOption) (*actions.Client, error) {
|
||||||
|
if config.ServerRootCA != "" {
|
||||||
|
systemPool, err := x509.SystemCertPool()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to load system cert pool: %w", err)
|
||||||
|
}
|
||||||
|
pool := systemPool.Clone()
|
||||||
|
ok := pool.AppendCertsFromPEM([]byte(config.ServerRootCA))
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("failed to parse root certificate")
|
||||||
|
}
|
||||||
|
|
||||||
|
options = append(options, actions.WithRootCAs(pool))
|
||||||
|
}
|
||||||
|
|
||||||
|
proxyFunc := httpproxy.FromEnvironment().ProxyFunc()
|
||||||
|
options = append(options, actions.WithProxy(func(req *http.Request) (*url.URL, error) {
|
||||||
|
return proxyFunc(req.URL)
|
||||||
|
}))
|
||||||
|
|
||||||
|
return actions.NewClient(config.ConfigureUrl, creds, options...)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,10 +1,20 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/actions/actions-runner-controller/github/actions"
|
||||||
|
"github.com/actions/actions-runner-controller/github/actions/testserver"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestConfigValidationMinMax(t *testing.T) {
|
func TestConfigValidationMinMax(t *testing.T) {
|
||||||
@@ -90,3 +100,154 @@ func TestConfigValidationConfigUrl(t *testing.T) {
|
|||||||
|
|
||||||
assert.ErrorContains(t, err, "GitHubConfigUrl is not provided", "Expected error about missing ConfigureUrl")
|
assert.ErrorContains(t, err, "GitHubConfigUrl is not provided", "Expected error about missing ConfigureUrl")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCustomerServerRootCA(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
certsFolder := filepath.Join(
|
||||||
|
"../../",
|
||||||
|
"github",
|
||||||
|
"actions",
|
||||||
|
"testdata",
|
||||||
|
)
|
||||||
|
certPath := filepath.Join(certsFolder, "server.crt")
|
||||||
|
keyPath := filepath.Join(certsFolder, "server.key")
|
||||||
|
|
||||||
|
serverCalledSuccessfully := false
|
||||||
|
|
||||||
|
server := testserver.NewUnstarted(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
serverCalledSuccessfully = true
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
w.Write([]byte(`{"count": 0}`))
|
||||||
|
}))
|
||||||
|
cert, err := tls.LoadX509KeyPair(certPath, keyPath)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
server.TLS = &tls.Config{Certificates: []tls.Certificate{cert}}
|
||||||
|
server.StartTLS()
|
||||||
|
|
||||||
|
var certsString string
|
||||||
|
rootCA, err := os.ReadFile(filepath.Join(certsFolder, "rootCA.crt"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
certsString = string(rootCA)
|
||||||
|
|
||||||
|
intermediate, err := os.ReadFile(filepath.Join(certsFolder, "intermediate.pem"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
certsString = certsString + string(intermediate)
|
||||||
|
|
||||||
|
config := RunnerScaleSetListenerConfig{
|
||||||
|
ConfigureUrl: server.ConfigURLForOrg("myorg"),
|
||||||
|
ServerRootCA: certsString,
|
||||||
|
}
|
||||||
|
creds := &actions.ActionsAuth{
|
||||||
|
Token: "token",
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := newActionsClientFromConfig(config, creds)
|
||||||
|
require.NoError(t, err)
|
||||||
|
_, err = client.GetRunnerScaleSet(ctx, 1, "test")
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.True(t, serverCalledSuccessfully)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProxySettings(t *testing.T) {
|
||||||
|
t.Run("http", func(t *testing.T) {
|
||||||
|
wentThroughProxy := false
|
||||||
|
|
||||||
|
proxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
wentThroughProxy = true
|
||||||
|
}))
|
||||||
|
t.Cleanup(func() {
|
||||||
|
proxy.Close()
|
||||||
|
})
|
||||||
|
|
||||||
|
prevProxy := os.Getenv("http_proxy")
|
||||||
|
os.Setenv("http_proxy", proxy.URL)
|
||||||
|
defer os.Setenv("http_proxy", prevProxy)
|
||||||
|
|
||||||
|
config := RunnerScaleSetListenerConfig{
|
||||||
|
ConfigureUrl: "https://github.com/org/repo",
|
||||||
|
}
|
||||||
|
creds := &actions.ActionsAuth{
|
||||||
|
Token: "token",
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := newActionsClientFromConfig(config, creds)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
req, err := http.NewRequest(http.MethodGet, "http://example.com", nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
_, err = client.Do(req)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.True(t, wentThroughProxy)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("https", func(t *testing.T) {
|
||||||
|
wentThroughProxy := false
|
||||||
|
|
||||||
|
proxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
wentThroughProxy = true
|
||||||
|
}))
|
||||||
|
t.Cleanup(func() {
|
||||||
|
proxy.Close()
|
||||||
|
})
|
||||||
|
|
||||||
|
prevProxy := os.Getenv("https_proxy")
|
||||||
|
os.Setenv("https_proxy", proxy.URL)
|
||||||
|
defer os.Setenv("https_proxy", prevProxy)
|
||||||
|
|
||||||
|
config := RunnerScaleSetListenerConfig{
|
||||||
|
ConfigureUrl: "https://github.com/org/repo",
|
||||||
|
}
|
||||||
|
creds := &actions.ActionsAuth{
|
||||||
|
Token: "token",
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := newActionsClientFromConfig(config, creds, actions.WithRetryMax(0))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
req, err := http.NewRequest(http.MethodGet, "https://example.com", nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
_, err = client.Do(req)
|
||||||
|
// proxy doesn't support https
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.True(t, wentThroughProxy)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("no_proxy", func(t *testing.T) {
|
||||||
|
wentThroughProxy := false
|
||||||
|
|
||||||
|
proxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
wentThroughProxy = true
|
||||||
|
}))
|
||||||
|
t.Cleanup(func() {
|
||||||
|
proxy.Close()
|
||||||
|
})
|
||||||
|
|
||||||
|
prevProxy := os.Getenv("http_proxy")
|
||||||
|
os.Setenv("http_proxy", proxy.URL)
|
||||||
|
defer os.Setenv("http_proxy", prevProxy)
|
||||||
|
|
||||||
|
prevNoProxy := os.Getenv("no_proxy")
|
||||||
|
os.Setenv("no_proxy", "example.com")
|
||||||
|
defer os.Setenv("no_proxy", prevNoProxy)
|
||||||
|
|
||||||
|
config := RunnerScaleSetListenerConfig{
|
||||||
|
ConfigureUrl: "https://github.com/org/repo",
|
||||||
|
}
|
||||||
|
creds := &actions.ActionsAuth{
|
||||||
|
Token: "token",
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := newActionsClientFromConfig(config, creds)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
req, err := http.NewRequest(http.MethodGet, "http://example.com", nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
_, err = client.Do(req)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.False(t, wentThroughProxy)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ func main() {
|
|||||||
if watchNamespace == "" {
|
if watchNamespace == "" {
|
||||||
logger.Info("-watch-namespace is empty. HorizontalRunnerAutoscalers in all the namespaces are watched, cached, and considered as scale targets.")
|
logger.Info("-watch-namespace is empty. HorizontalRunnerAutoscalers in all the namespaces are watched, cached, and considered as scale targets.")
|
||||||
} else {
|
} else {
|
||||||
logger.Info("-watch-namespace is %q. Only HorizontalRunnerAutoscalers in %q are watched, cached, and considered as scale targets.")
|
logger.Info("-watch-namespace is %q. Only HorizontalRunnerAutoscalers in %q are watched, cached, and considered as scale targets.", watchNamespace, watchNamespace)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctrl.SetLogger(logger)
|
ctrl.SetLogger(logger)
|
||||||
|
|||||||
33
cmd/sleep/main.go
Normal file
33
cmd/sleep/main.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2021 The actions-runner-controller authors.
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Seconds int
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Printf("sleeping for %d seconds\n", Seconds)
|
||||||
|
time.Sleep(time.Duration(Seconds) * time.Second)
|
||||||
|
fmt.Println("done sleeping")
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
flag.IntVar(&Seconds, "seconds", 60, "Number of seconds to sleep")
|
||||||
|
flag.Parse()
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user