mirror of
https://github.com/actions/actions-runner-controller.git
synced 2025-12-10 11:41:27 +00:00
Compare commits
44 Commits
gha-runner
...
gha-runner
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
45
.github/actions/e2e-arc-test/action.yaml
vendored
Normal file
45
.github/actions/e2e-arc-test/action.yaml
vendored
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
name: 'E2E ARC Test Action'
|
||||||
|
description: 'Includes common arc installation, setup and test file run'
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
github-token:
|
||||||
|
description: 'JWT generated with Github App inputs'
|
||||||
|
required: true
|
||||||
|
config-url:
|
||||||
|
description: "URL of the repo, org or enterprise where the runner scale sets will be registered"
|
||||||
|
required: true
|
||||||
|
docker-image-repo:
|
||||||
|
description: "Local docker image repo for testing"
|
||||||
|
required: true
|
||||||
|
docker-image-tag:
|
||||||
|
description: "Tag of ARC Docker image for testing"
|
||||||
|
required: true
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: "composite"
|
||||||
|
steps:
|
||||||
|
- name: Install ARC
|
||||||
|
run: helm install arc --namespace "arc-systems" --create-namespace --set image.tag=${{ inputs.docker-image-tag }} --set image.repository=${{ inputs.docker-image-repo }} ./charts/gha-runner-scale-set-controller
|
||||||
|
shell: bash
|
||||||
|
- name: Get datetime
|
||||||
|
# We are using this value further in the runner installation to avoid runner name collision that are a risk with hard coded values.
|
||||||
|
# A datetime including the 3 nanoseconds are a good option for this and also adds to readability and runner sorting if needed.
|
||||||
|
run: echo "DATE_TIME=$(date +'%Y-%m-%d-%H-%M-%S-%3N')" >> $GITHUB_ENV
|
||||||
|
shell: bash
|
||||||
|
- name: Install runners
|
||||||
|
run: |
|
||||||
|
helm install "arc-runner-${{ env.DATE_TIME }}" \
|
||||||
|
--namespace "arc-runners" \
|
||||||
|
--create-namespace \
|
||||||
|
--set githubConfigUrl="${{ inputs.config-url }}" \
|
||||||
|
--set githubConfigSecret.github_token="${{ inputs.github-token }}" \
|
||||||
|
./charts/gha-runner-scale-set \
|
||||||
|
--debug
|
||||||
|
kubectl get pods -A
|
||||||
|
shell: bash
|
||||||
|
- name: Test ARC scales pods up and down
|
||||||
|
run: |
|
||||||
|
export GITHUB_TOKEN="${{ inputs.github-token }}"
|
||||||
|
export DATE_TIME="${{ env.DATE_TIME }}"
|
||||||
|
go test ./test_e2e_arc -v
|
||||||
|
shell: bash
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
name: ARC-REUSABLE-WORKFLOW
|
name: ARC Reusable Workflow
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
|
|||||||
51
.github/workflows/e2e-test-linux-vm.yaml
vendored
Normal file
51
.github/workflows/e2e-test-linux-vm.yaml
vendored
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
name: CI ARC E2E Linux VM Test
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
TARGET_ORG: actions-runner-controller
|
||||||
|
CLUSTER_NAME: e2e-test
|
||||||
|
RUNNER_VERSION: 2.302.1
|
||||||
|
IMAGE_REPO: "test/test-image"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
setup-steps:
|
||||||
|
runs-on: [ubuntu-latest]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Add env variables
|
||||||
|
run: |
|
||||||
|
TAG=$(echo "0.0.$GITHUB_SHA")
|
||||||
|
echo "TAG=$TAG" >> $GITHUB_ENV
|
||||||
|
echo "IMAGE=$IMAGE_REPO:$TAG" >> $GITHUB_ENV
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
with:
|
||||||
|
version: latest
|
||||||
|
- name: Docker Build Test Image
|
||||||
|
run: |
|
||||||
|
DOCKER_CLI_EXPERIMENTAL=enabled DOCKER_BUILDKIT=1 docker buildx build --build-arg RUNNER_VERSION=$RUNNER_VERSION --build-arg TAG=$TAG -t $IMAGE . --load
|
||||||
|
- name: Create Kind cluster
|
||||||
|
run: |
|
||||||
|
PATH=$(go env GOPATH)/bin:$PATH
|
||||||
|
kind create cluster --name $CLUSTER_NAME
|
||||||
|
- name: Load Image to Kind Cluster
|
||||||
|
run: kind load docker-image $IMAGE --name $CLUSTER_NAME
|
||||||
|
- name: Get Token
|
||||||
|
id: get_workflow_token
|
||||||
|
uses: peter-murray/workflow-application-token-action@8e1ba3bf1619726336414f1014e37f17fbadf1db
|
||||||
|
with:
|
||||||
|
application_id: ${{ secrets.ACTIONS_ACCESS_APP_ID }}
|
||||||
|
application_private_key: ${{ secrets.ACTIONS_ACCESS_PK }}
|
||||||
|
organization: ${{ env.TARGET_ORG }}
|
||||||
|
- uses: ./.github/actions/e2e-arc-test
|
||||||
|
with:
|
||||||
|
github-token: ${{ steps.get_workflow_token.outputs.token }}
|
||||||
|
config-url: "https://github.com/actions-runner-controller/arc_e2e_test_dummy"
|
||||||
|
docker-image-repo: $IMAGE_REPO
|
||||||
|
docker-image-tag: $TAG
|
||||||
4
.github/workflows/publish-chart.yaml
vendored
4
.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:
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
1
.github/workflows/update-runners.yaml
vendored
1
.github/workflows/update-runners.yaml
vendored
@@ -93,6 +93,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: |
|
||||||
|
|||||||
11
.github/workflows/validate-chart.yaml
vendored
11
.github/workflows/validate-chart.yaml
vendored
@@ -1,6 +1,14 @@
|
|||||||
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'
|
||||||
push:
|
push:
|
||||||
paths:
|
paths:
|
||||||
- 'charts/**'
|
- 'charts/**'
|
||||||
@@ -26,7 +34,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 }}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
109
Makefile
109
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.302.1
|
||||||
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
|
||||||
@@ -113,66 +113,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 \
|
||||||
@@ -69,6 +69,14 @@ 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 [ -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
|
||||||
|
|
||||||
set -vx
|
set -vx
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,19 @@
|
|||||||
|
|
||||||
**Status**: Done
|
**Status**: Done
|
||||||
|
|
||||||
|
# Breaking Changes
|
||||||
|
|
||||||
|
We aim to provide an similar experience (as close as possible) between self-hosted and GitHub-hosted runners. To achieve this, we are making the following changes to align our self-hosted runner container image with the Ubuntu runners managed by GitHub.
|
||||||
|
Here are the changes:
|
||||||
|
- We created a USER `runner(1001)` and a GROUP `docker(123)`
|
||||||
|
- `sudo` has been on the image and the `runner` will be a passwordless sudoer.
|
||||||
|
- The runner binary was placed placed under `/home/runner/` and launched using `/home/runner/run.sh`
|
||||||
|
- The runner's work directory is `/home/runner/_work`
|
||||||
|
- `$HOME` will point to `/home/runner`
|
||||||
|
- The container image user will be the `runner(1001)`
|
||||||
|
|
||||||
|
The latest Dockerfile can be found at: https://github.com/actions/runner/blob/main/images/Dockerfile
|
||||||
|
|
||||||
# Context
|
# Context
|
||||||
|
|
||||||
user can bring their own runner images, the contract we have are:
|
user can bring their own runner images, the contract we have are:
|
||||||
|
|||||||
133
adrs/2023-02-10-limit-manager-role-permission.md
Normal file
133
adrs/2023-02-10-limit-manager-role-permission.md
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
# ADR 0007: Limit Permissions for Service Accounts in Actions-Runner-Controller
|
||||||
|
**Date**: 2023-02-10
|
||||||
|
|
||||||
|
**Status**: Pending
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
- `actions-runner-controller` is a Kubernetes CRD (with controller) built using https://github.com/kubernetes-sigs/controller-runtime
|
||||||
|
|
||||||
|
- [controller-runtime](https://github.com/kubernetes-sigs/controller-runtime) has a default cache based k8s API client.Reader to make query k8s API server more efficiency.
|
||||||
|
|
||||||
|
- The cache-based API client requires cluster scope `list` and `watch` permission for any resource the controller may query.
|
||||||
|
|
||||||
|
- This documentation only scopes to the AutoscalingRunnerSet CRD and its controller.
|
||||||
|
|
||||||
|
## Service accounts and their role binding in actions-runner-controller
|
||||||
|
|
||||||
|
There are 3 service accounts involved for a working `AutoscalingRunnerSet` based `actions-runner-controller`
|
||||||
|
|
||||||
|
1. Service account for each Ephemeral runner Pod
|
||||||
|
|
||||||
|
This should have the lowest privilege (not any `RoleBinding` nor `ClusterRoleBinding`) by default, in the case of `containerMode=kubernetes`, it will get certain write permission with `RoleBinding` to limit the permission to a single namespace.
|
||||||
|
|
||||||
|
> References:
|
||||||
|
> - ./charts/gha-runner-scale-set/templates/no_permission_serviceaccount.yaml
|
||||||
|
> - ./charts/gha-runner-scale-set/templates/kube_mode_role.yaml
|
||||||
|
> - ./charts/gha-runner-scale-set/templates/kube_mode_role_binding.yaml
|
||||||
|
> - ./charts/gha-runner-scale-set/templates/kube_mode_serviceaccount.yaml
|
||||||
|
|
||||||
|
2. Service account for AutoScalingListener Pod
|
||||||
|
|
||||||
|
This has a `RoleBinding` to a single namespace with a `Role` that has permission to `PATCH` `EphemeralRunnerSet` and `EphemeralRunner`.
|
||||||
|
|
||||||
|
3. Service account for the controller manager
|
||||||
|
|
||||||
|
Since the CRD controller is a singleton installed in the cluster that manages the CRD across multiple namespaces by default, the service account of the controller manager pod has a `ClusterRoleBinding` to a `ClusterRole` with broader permissions.
|
||||||
|
|
||||||
|
The current `ClusterRole` has the following permissions:
|
||||||
|
|
||||||
|
- Get/List/Create/Delete/Update/Patch/Watch on `AutoScalingRunnerSets` (with `Status` and `Finalizer` sub-resource)
|
||||||
|
- Get/List/Create/Delete/Update/Patch/Watch on `AutoScalingListeners` (with `Status` and `Finalizer` sub-resource)
|
||||||
|
- Get/List/Create/Delete/Update/Patch/Watch on `EphemeralRunnerSets` (with `Status` and `Finalizer` sub-resource)
|
||||||
|
- Get/List/Create/Delete/Update/Patch/Watch on `EphemeralRunners` (with `Status` and `Finalizer` sub-resource)
|
||||||
|
|
||||||
|
- Get/List/Create/Delete/Update/Patch/Watch on `Pods` (with `Status` sub-resource)
|
||||||
|
- **Get/List/Create/Delete/Update/Patch/Watch on `Secrets`**
|
||||||
|
- Get/List/Create/Delete/Update/Patch/Watch on `Roles`
|
||||||
|
- Get/List/Create/Delete/Update/Patch/Watch on `RoleBindings`
|
||||||
|
- Get/List/Create/Delete/Update/Patch/Watch on `ServiceAccounts`
|
||||||
|
|
||||||
|
> Full list can be found at: https://github.com/actions/actions-runner-controller/blob/facae69e0b189d3b5dd659f36df8a829516d2896/charts/actions-runner-controller-2/templates/manager_role.yaml
|
||||||
|
|
||||||
|
## Limit cluster role permission on Secrets
|
||||||
|
|
||||||
|
The cluster scope `List` `Secrets` permission might be a blocker for adopting `actions-runner-controller` for certain customers as they may have certain restriction in their cluster that simply doesn't allow any service account to have cluster scope `List Secrets` permission.
|
||||||
|
|
||||||
|
To help these customers and improve security for `actions-runner-controller` in general, we will try to limit the `ClusterRole` permission of the controller manager's service account down to the following:
|
||||||
|
|
||||||
|
- Get/List/Create/Delete/Update/Patch/Watch on `AutoScalingRunnerSets` (with `Status` and `Finalizer` sub-resource)
|
||||||
|
- Get/List/Create/Delete/Update/Patch/Watch on `AutoScalingListeners` (with `Status` and `Finalizer` sub-resource)
|
||||||
|
- Get/List/Create/Delete/Update/Patch/Watch on `EphemeralRunnerSets` (with `Status` and `Finalizer` sub-resource)
|
||||||
|
- Get/List/Create/Delete/Update/Patch/Watch on `EphemeralRunners` (with `Status` and `Finalizer` sub-resource)
|
||||||
|
|
||||||
|
- List/Watch on `Pods`
|
||||||
|
- List/Watch on `Roles`
|
||||||
|
- List/Watch on `RoleBindings`
|
||||||
|
- List/Watch on `ServiceAccounts`
|
||||||
|
|
||||||
|
> We will change the default cache-based client to bypass cache on reading `Secrets` and `ConfigMaps`(ConfigMap is used when you configure `githubServerTLS`), so we can eliminate the need for `List` and `Watch` `Secrets` permission in cluster scope.
|
||||||
|
|
||||||
|
Introduce a new `Role` for the controller and `RoleBinding` the `Role` with the controller's `ServiceAccount` in the namespace the controller is deployed. This role will grant the controller's service account required permission to work with `AutoScalingListeners` in the controller namespace.
|
||||||
|
|
||||||
|
- Get/Create/Delete on `Pods`
|
||||||
|
- Get on `Pods/status`
|
||||||
|
- Get/Create/Delete/Update/Patch on `Secrets`
|
||||||
|
- Get/Create/Delete/Update/Patch on `ServiceAccounts`
|
||||||
|
|
||||||
|
The `Role` and `RoleBinding` creation will happen during the `helm install demo oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set-controller`
|
||||||
|
|
||||||
|
During `helm install demo oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set-controller`, we will store the controller's service account info as labels on the controller `Deployment`.
|
||||||
|
Ex:
|
||||||
|
```yaml
|
||||||
|
actions.github.com/controller-service-account-namespace: {{ .Release.Namespace }}
|
||||||
|
actions.github.com/controller-service-account-name: {{ include "gha-runner-scale-set-controller.serviceAccountName" . }}
|
||||||
|
```
|
||||||
|
|
||||||
|
Introduce a new `Role` per `AutoScalingRunnerSet` installation and `RoleBinding` the `Role` with the controller's `ServiceAccount` in the namespace that each `AutoScalingRunnerSet` deployed with the following permission.
|
||||||
|
|
||||||
|
- Get/Create/Delete/Update/Patch/List on `Secrets`
|
||||||
|
- Create/Delete on `Pods`
|
||||||
|
- Get on `Pods/status`
|
||||||
|
- Get/Create/Delete/Update/Patch on `Roles`
|
||||||
|
- Get/Create/Delete/Update/Patch on `RoleBindings`
|
||||||
|
- Get on `ConfigMaps`
|
||||||
|
|
||||||
|
The `Role` and `RoleBinding` creation will happen during `helm install demo oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set` to grant the controller's service account required permissions to operate in the namespace the `AutoScalingRunnerSet` deployed.
|
||||||
|
|
||||||
|
The `gha-runner-scale-set` helm chart will try to find the `Deployment` of the controller using `helm lookup`, and get the service account info from the labels of the controller `Deployment` (`actions.github.com/controller-service-account-namespace` and `actions.github.com/controller-service-account-name`).
|
||||||
|
|
||||||
|
The `gha-runner-scale-set` helm chart will use this service account to properly render the `RoleBinding` template.
|
||||||
|
|
||||||
|
The `gha-runner-scale-set` helm chart will also allow customers to explicitly provide the controller service account info, in case the `helm lookup` couldn't locate the right controller `Deployment`.
|
||||||
|
|
||||||
|
New sections in `values.yaml` of `gha-runner-scale-set`:
|
||||||
|
```yaml
|
||||||
|
## Optional controller service account that needs to have required Role and RoleBinding
|
||||||
|
## to operate this gha-runner-scale-set installation.
|
||||||
|
## The helm chart will try to find the controller deployment and its service account at installation time.
|
||||||
|
## In case the helm chart can't find the right service account, you can explicitly pass in the following value
|
||||||
|
## to help it finish RoleBinding with the right service account.
|
||||||
|
## Note: if your controller is installed to only watch a single namespace, you have to pass these values explicitly.
|
||||||
|
controllerServiceAccount:
|
||||||
|
namespace: arc-system
|
||||||
|
name: test-arc-gha-runner-scale-set-controller
|
||||||
|
```
|
||||||
|
|
||||||
|
## Install ARC to only watch/react resources in a single namespace
|
||||||
|
|
||||||
|
In case the user doesn't want to have any `ClusterRole`, they can choose to install the `actions-runner-controller` in a mode that only requires a `Role` with `RoleBinding` in a particular namespace.
|
||||||
|
|
||||||
|
In this mode, the `actions-runner-controller` will only be able to watch the `AutoScalingRunnerSet` resource in a single namespace.
|
||||||
|
|
||||||
|
If you want to deploy multiple `AutoScalingRunnerSet` into different namespaces, you will need to install `actions-runner-controller` in this mode multiple times as well and have each installation watch the namespace you want to deploy an `AutoScalingRunnerSet`
|
||||||
|
|
||||||
|
You will install `actions-runner-controller` with something like `helm install arc --namespace arc-system --set watchSingleNamespace=test-namespace oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set-controller` (the `test-namespace` namespace needs to be created first).
|
||||||
|
|
||||||
|
You will deploy the `AutoScalingRunnerSet` with something like `helm install demo --namespace TestNamespace oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set`
|
||||||
|
|
||||||
|
In this mode, you will end up with a manager `Role` that has all Get/List/Create/Delete/Update/Patch/Watch permissions on resources we need, and a `RoleBinding` to bind the `Role` with the controller `ServiceAccount` in the watched single namespace and the controller namespace, ex: `test-namespace` and `arc-system` in the above example.
|
||||||
|
|
||||||
|
The downside of this mode:
|
||||||
|
- When you have multiple controllers deployed, they will still use the same version of the CRD. So you will need to make sure every controller you deployed has to be the same version as each other.
|
||||||
|
- You can't mismatch install both `actions-runner-controller` in this mode (watchSingleNamespace) with the regular installation mode (watchAllClusterNamespaces) in your cluster.
|
||||||
@@ -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"
|
||||||
@@ -57,6 +58,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 +81,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 {
|
||||||
@@ -205,6 +246,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 +255,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,
|
||||||
|
|||||||
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
# 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
|
||||||
|
- charts/gha-runner-scale-set-controller
|
||||||
|
- charts/gha-runner-scale-set
|
||||||
@@ -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 }}
|
|
||||||
@@ -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:
|
||||||
@@ -148,7 +154,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 }}
|
||||||
|
|||||||
@@ -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,8 @@ githubWebhookServer:
|
|||||||
# minAvailable: 1
|
# minAvailable: 1
|
||||||
# maxUnavailable: 3
|
# maxUnavailable: 3
|
||||||
# queueLimit: 100
|
# queueLimit: 100
|
||||||
|
terminationGracePeriodSeconds: 10
|
||||||
|
lifecycle: {}
|
||||||
|
|
||||||
actionsMetrics:
|
actionsMetrics:
|
||||||
serviceAnnotations: {}
|
serviceAnnotations: {}
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -51,9 +51,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 +102,8 @@ spec:
|
|||||||
type: object
|
type: object
|
||||||
runnerGroup:
|
runnerGroup:
|
||||||
type: string
|
type: string
|
||||||
|
runnerScaleSetName:
|
||||||
|
type: string
|
||||||
template:
|
template:
|
||||||
description: Required
|
description: Required
|
||||||
properties:
|
properties:
|
||||||
@@ -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'
|
||||||
@@ -46,9 +46,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'
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{{/*
|
{{/*
|
||||||
Expand the name of the chart.
|
Expand the name of the chart.
|
||||||
*/}}
|
*/}}
|
||||||
{{- define "actions-runner-controller-2.name" -}}
|
{{- define "gha-runner-scale-set-controller.name" -}}
|
||||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ 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).
|
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.
|
If release name contains chart name it will be used as a full name.
|
||||||
*/}}
|
*/}}
|
||||||
{{- define "actions-runner-controller-2.fullname" -}}
|
{{- define "gha-runner-scale-set-controller.fullname" -}}
|
||||||
{{- if .Values.fullnameOverride }}
|
{{- if .Values.fullnameOverride }}
|
||||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
||||||
{{- else }}
|
{{- else }}
|
||||||
@@ -26,16 +26,16 @@ If release name contains chart name it will be used as a full name.
|
|||||||
{{/*
|
{{/*
|
||||||
Create chart name and version as used by the chart label.
|
Create chart name and version as used by the chart label.
|
||||||
*/}}
|
*/}}
|
||||||
{{- define "actions-runner-controller-2.chart" -}}
|
{{- define "gha-runner-scale-set-controller.chart" -}}
|
||||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{/*
|
{{/*
|
||||||
Common labels
|
Common labels
|
||||||
*/}}
|
*/}}
|
||||||
{{- define "actions-runner-controller-2.labels" -}}
|
{{- define "gha-runner-scale-set-controller.labels" -}}
|
||||||
helm.sh/chart: {{ include "actions-runner-controller-2.chart" . }}
|
helm.sh/chart: {{ include "gha-runner-scale-set-controller.chart" . }}
|
||||||
{{ include "actions-runner-controller-2.selectorLabels" . }}
|
{{ include "gha-runner-scale-set-controller.selectorLabels" . }}
|
||||||
{{- if .Chart.AppVersion }}
|
{{- if .Chart.AppVersion }}
|
||||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
@@ -49,20 +49,20 @@ app.kubernetes.io/managed-by: {{ .Release.Service }}
|
|||||||
{{/*
|
{{/*
|
||||||
Selector labels
|
Selector labels
|
||||||
*/}}
|
*/}}
|
||||||
{{- define "actions-runner-controller-2.selectorLabels" -}}
|
{{- define "gha-runner-scale-set-controller.selectorLabels" -}}
|
||||||
app.kubernetes.io/name: {{ include "actions-runner-controller-2.name" . }}
|
app.kubernetes.io/name: {{ include "gha-runner-scale-set-controller.name" . }}
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{/*
|
{{/*
|
||||||
Create the name of the service account to use
|
Create the name of the service account to use
|
||||||
*/}}
|
*/}}
|
||||||
{{- define "actions-runner-controller-2.serviceAccountName" -}}
|
{{- define "gha-runner-scale-set-controller.serviceAccountName" -}}
|
||||||
{{- if eq .Values.serviceAccount.name "default"}}
|
{{- if eq .Values.serviceAccount.name "default"}}
|
||||||
{{- fail "serviceAccount.name cannot be set to 'default'" }}
|
{{- fail "serviceAccount.name cannot be set to 'default'" }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if .Values.serviceAccount.create }}
|
{{- if .Values.serviceAccount.create }}
|
||||||
{{- default (include "actions-runner-controller-2.fullname" .) .Values.serviceAccount.name }}
|
{{- default (include "gha-runner-scale-set-controller.fullname" .) .Values.serviceAccount.name }}
|
||||||
{{- else }}
|
{{- else }}
|
||||||
{{- if not .Values.serviceAccount.name }}
|
{{- if not .Values.serviceAccount.name }}
|
||||||
{{- fail "serviceAccount.name must be set if serviceAccount.create is false" }}
|
{{- fail "serviceAccount.name must be set if serviceAccount.create is false" }}
|
||||||
@@ -72,23 +72,23 @@ Create the name of the service account to use
|
|||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- define "actions-runner-controller-2.managerRoleName" -}}
|
{{- define "gha-runner-scale-set-controller.managerRoleName" -}}
|
||||||
{{- include "actions-runner-controller-2.fullname" . }}-manager-role
|
{{- include "gha-runner-scale-set-controller.fullname" . }}-manager-role
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- define "actions-runner-controller-2.managerRoleBinding" -}}
|
{{- define "gha-runner-scale-set-controller.managerRoleBinding" -}}
|
||||||
{{- include "actions-runner-controller-2.fullname" . }}-manager-rolebinding
|
{{- include "gha-runner-scale-set-controller.fullname" . }}-manager-rolebinding
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- define "actions-runner-controller-2.leaderElectionRoleName" -}}
|
{{- define "gha-runner-scale-set-controller.leaderElectionRoleName" -}}
|
||||||
{{- include "actions-runner-controller-2.fullname" . }}-leader-election-role
|
{{- include "gha-runner-scale-set-controller.fullname" . }}-leader-election-role
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- define "actions-runner-controller-2.leaderElectionRoleBinding" -}}
|
{{- define "gha-runner-scale-set-controller.leaderElectionRoleBinding" -}}
|
||||||
{{- include "actions-runner-controller-2.fullname" . }}-leader-election-rolebinding
|
{{- include "gha-runner-scale-set-controller.fullname" . }}-leader-election-rolebinding
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- define "actions-runner-controller-2.imagePullSecretsNames" -}}
|
{{- define "gha-runner-scale-set-controller.imagePullSecretsNames" -}}
|
||||||
{{- $names := list }}
|
{{- $names := list }}
|
||||||
{{- range $k, $v := . }}
|
{{- range $k, $v := . }}
|
||||||
{{- $names = append $names $v.name }}
|
{{- $names = append $names $v.name }}
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
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 }}
|
||||||
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:
|
||||||
@@ -21,13 +21,13 @@ spec:
|
|||||||
app.kubernetes.io/part-of: actions-runner-controller
|
app.kubernetes.io/part-of: actions-runner-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,10 +43,10 @@ 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={{ . }}"
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
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"]
|
||||||
@@ -2,14 +2,14 @@
|
|||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: RoleBinding
|
kind: RoleBinding
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ include "actions-runner-controller-2.leaderElectionRoleBinding" . }}
|
name: {{ include "gha-runner-scale-set-controller.leaderElectionRoleBinding" . }}
|
||||||
namespace: {{ .Release.Namespace }}
|
namespace: {{ .Release.Namespace }}
|
||||||
roleRef:
|
roleRef:
|
||||||
apiGroup: rbac.authorization.k8s.io
|
apiGroup: rbac.authorization.k8s.io
|
||||||
kind: Role
|
kind: Role
|
||||||
name: {{ include "actions-runner-controller-2.leaderElectionRoleName" . }}
|
name: {{ include "gha-runner-scale-set-controller.leaderElectionRoleName" . }}
|
||||||
subjects:
|
subjects:
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: {{ include "actions-runner-controller-2.serviceAccountName" . }}
|
name: {{ include "gha-runner-scale-set-controller.serviceAccountName" . }}
|
||||||
namespace: {{ .Release.Namespace }}
|
namespace: {{ .Release.Namespace }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
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.managerRoleName" . }}
|
||||||
rules:
|
rules:
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- actions.github.com
|
- actions.github.com
|
||||||
@@ -146,6 +146,13 @@ rules:
|
|||||||
- get
|
- get
|
||||||
- list
|
- list
|
||||||
- watch
|
- watch
|
||||||
|
- apiGroups:
|
||||||
|
- ""
|
||||||
|
resources:
|
||||||
|
- configmaps
|
||||||
|
verbs:
|
||||||
|
- list
|
||||||
|
- watch
|
||||||
- apiGroups:
|
- apiGroups:
|
||||||
- rbac.authorization.k8s.io
|
- rbac.authorization.k8s.io
|
||||||
resources:
|
resources:
|
||||||
@@ -167,4 +174,4 @@ rules:
|
|||||||
- get
|
- get
|
||||||
- update
|
- update
|
||||||
- list
|
- list
|
||||||
- watch
|
- watch
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
|
kind: ClusterRoleBinding
|
||||||
|
metadata:
|
||||||
|
name: {{ include "gha-runner-scale-set-controller.managerRoleBinding" . }}
|
||||||
|
roleRef:
|
||||||
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
kind: ClusterRole
|
||||||
|
name: {{ include "gha-runner-scale-set-controller.managerRoleName" . }}
|
||||||
|
subjects:
|
||||||
|
- kind: ServiceAccount
|
||||||
|
name: {{ include "gha-runner-scale-set-controller.serviceAccountName" . }}
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
@@ -2,10 +2,10 @@
|
|||||||
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 }}
|
||||||
@@ -26,7 +26,7 @@ func TestTemplate_CreateServiceAccount(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../actions-runner-controller-2")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set-controller")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-arc"
|
releaseName := "test-arc"
|
||||||
@@ -46,7 +46,7 @@ func TestTemplate_CreateServiceAccount(t *testing.T) {
|
|||||||
helm.UnmarshalK8SYaml(t, output, &serviceAccount)
|
helm.UnmarshalK8SYaml(t, output, &serviceAccount)
|
||||||
|
|
||||||
assert.Equal(t, namespaceName, serviceAccount.Namespace)
|
assert.Equal(t, namespaceName, serviceAccount.Namespace)
|
||||||
assert.Equal(t, "test-arc-actions-runner-controller-2", serviceAccount.Name)
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller", serviceAccount.Name)
|
||||||
assert.Equal(t, "bar", string(serviceAccount.Annotations["foo"]))
|
assert.Equal(t, "bar", string(serviceAccount.Annotations["foo"]))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ func TestTemplate_CreateServiceAccount_OverwriteName(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../actions-runner-controller-2")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set-controller")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-arc"
|
releaseName := "test-arc"
|
||||||
@@ -83,7 +83,7 @@ func TestTemplate_CreateServiceAccount_CannotUseDefaultServiceAccount(t *testing
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../actions-runner-controller-2")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set-controller")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-arc"
|
releaseName := "test-arc"
|
||||||
@@ -106,7 +106,7 @@ func TestTemplate_NotCreateServiceAccount(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../actions-runner-controller-2")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set-controller")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-arc"
|
releaseName := "test-arc"
|
||||||
@@ -129,7 +129,7 @@ func TestTemplate_NotCreateServiceAccount_ServiceAccountNotSet(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../actions-runner-controller-2")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set-controller")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-arc"
|
releaseName := "test-arc"
|
||||||
@@ -151,7 +151,7 @@ func TestTemplate_CreateManagerRole(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../actions-runner-controller-2")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set-controller")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-arc"
|
releaseName := "test-arc"
|
||||||
@@ -168,15 +168,15 @@ func TestTemplate_CreateManagerRole(t *testing.T) {
|
|||||||
helm.UnmarshalK8SYaml(t, output, &managerRole)
|
helm.UnmarshalK8SYaml(t, output, &managerRole)
|
||||||
|
|
||||||
assert.Empty(t, managerRole.Namespace, "ClusterRole should not have a namespace")
|
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, "test-arc-gha-runner-scale-set-controller-manager-role", managerRole.Name)
|
||||||
assert.Equal(t, 17, len(managerRole.Rules))
|
assert.Equal(t, 18, len(managerRole.Rules))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTemplate_ManagerRoleBinding(t *testing.T) {
|
func TestTemplate_ManagerRoleBinding(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../actions-runner-controller-2")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set-controller")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-arc"
|
releaseName := "test-arc"
|
||||||
@@ -195,9 +195,9 @@ func TestTemplate_ManagerRoleBinding(t *testing.T) {
|
|||||||
helm.UnmarshalK8SYaml(t, output, &managerRoleBinding)
|
helm.UnmarshalK8SYaml(t, output, &managerRoleBinding)
|
||||||
|
|
||||||
assert.Empty(t, managerRoleBinding.Namespace, "ClusterRoleBinding should not have a namespace")
|
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-gha-runner-scale-set-controller-manager-rolebinding", managerRoleBinding.Name)
|
||||||
assert.Equal(t, "test-arc-actions-runner-controller-2-manager-role", managerRoleBinding.RoleRef.Name)
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller-manager-role", managerRoleBinding.RoleRef.Name)
|
||||||
assert.Equal(t, "test-arc-actions-runner-controller-2", managerRoleBinding.Subjects[0].Name)
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller", managerRoleBinding.Subjects[0].Name)
|
||||||
assert.Equal(t, namespaceName, managerRoleBinding.Subjects[0].Namespace)
|
assert.Equal(t, namespaceName, managerRoleBinding.Subjects[0].Namespace)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,7 +205,7 @@ func TestTemplate_ControllerDeployment_Defaults(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../actions-runner-controller-2")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set-controller")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
chartContent, err := os.ReadFile(filepath.Join(helmChartPath, "Chart.yaml"))
|
chartContent, err := os.ReadFile(filepath.Join(helmChartPath, "Chart.yaml"))
|
||||||
@@ -231,25 +231,25 @@ func TestTemplate_ControllerDeployment_Defaults(t *testing.T) {
|
|||||||
helm.UnmarshalK8SYaml(t, output, &deployment)
|
helm.UnmarshalK8SYaml(t, output, &deployment)
|
||||||
|
|
||||||
assert.Equal(t, namespaceName, deployment.Namespace)
|
assert.Equal(t, namespaceName, deployment.Namespace)
|
||||||
assert.Equal(t, "test-arc-actions-runner-controller-2", deployment.Name)
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller", deployment.Name)
|
||||||
assert.Equal(t, "actions-runner-controller-2-"+chart.Version, deployment.Labels["helm.sh/chart"])
|
assert.Equal(t, "gha-runner-scale-set-controller-"+chart.Version, deployment.Labels["helm.sh/chart"])
|
||||||
assert.Equal(t, "actions-runner-controller-2", deployment.Labels["app.kubernetes.io/name"])
|
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, "test-arc", deployment.Labels["app.kubernetes.io/instance"])
|
||||||
assert.Equal(t, chart.AppVersion, deployment.Labels["app.kubernetes.io/version"])
|
assert.Equal(t, chart.AppVersion, deployment.Labels["app.kubernetes.io/version"])
|
||||||
assert.Equal(t, "Helm", deployment.Labels["app.kubernetes.io/managed-by"])
|
assert.Equal(t, "Helm", deployment.Labels["app.kubernetes.io/managed-by"])
|
||||||
|
|
||||||
assert.Equal(t, int32(1), *deployment.Spec.Replicas)
|
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, "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, "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, "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, "test-arc", deployment.Spec.Template.Labels["app.kubernetes.io/instance"])
|
||||||
|
|
||||||
assert.Equal(t, "manager", deployment.Spec.Template.Annotations["kubectl.kubernetes.io/default-container"])
|
assert.Equal(t, "manager", deployment.Spec.Template.Annotations["kubectl.kubernetes.io/default-container"])
|
||||||
|
|
||||||
assert.Len(t, deployment.Spec.Template.Spec.ImagePullSecrets, 0)
|
assert.Len(t, deployment.Spec.Template.Spec.ImagePullSecrets, 0)
|
||||||
assert.Equal(t, "test-arc-actions-runner-controller-2", deployment.Spec.Template.Spec.ServiceAccountName)
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller", deployment.Spec.Template.Spec.ServiceAccountName)
|
||||||
assert.Nil(t, deployment.Spec.Template.Spec.SecurityContext)
|
assert.Nil(t, deployment.Spec.Template.Spec.SecurityContext)
|
||||||
assert.Empty(t, deployment.Spec.Template.Spec.PriorityClassName)
|
assert.Empty(t, deployment.Spec.Template.Spec.PriorityClassName)
|
||||||
assert.Equal(t, int64(10), *deployment.Spec.Template.Spec.TerminationGracePeriodSeconds)
|
assert.Equal(t, int64(10), *deployment.Spec.Template.Spec.TerminationGracePeriodSeconds)
|
||||||
@@ -263,7 +263,7 @@ func TestTemplate_ControllerDeployment_Defaults(t *testing.T) {
|
|||||||
|
|
||||||
assert.Len(t, deployment.Spec.Template.Spec.Containers, 1)
|
assert.Len(t, deployment.Spec.Template.Spec.Containers, 1)
|
||||||
assert.Equal(t, "manager", deployment.Spec.Template.Spec.Containers[0].Name)
|
assert.Equal(t, "manager", deployment.Spec.Template.Spec.Containers[0].Name)
|
||||||
assert.Equal(t, "ghcr.io/actions/actions-runner-controller-2:dev", deployment.Spec.Template.Spec.Containers[0].Image)
|
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.Equal(t, corev1.PullIfNotPresent, deployment.Spec.Template.Spec.Containers[0].ImagePullPolicy)
|
||||||
|
|
||||||
assert.Len(t, deployment.Spec.Template.Spec.Containers[0].Command, 1)
|
assert.Len(t, deployment.Spec.Template.Spec.Containers[0].Command, 1)
|
||||||
@@ -291,7 +291,7 @@ func TestTemplate_ControllerDeployment_Customize(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../actions-runner-controller-2")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set-controller")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
chartContent, err := os.ReadFile(filepath.Join(helmChartPath, "Chart.yaml"))
|
chartContent, err := os.ReadFile(filepath.Join(helmChartPath, "Chart.yaml"))
|
||||||
@@ -312,9 +312,9 @@ func TestTemplate_ControllerDeployment_Customize(t *testing.T) {
|
|||||||
"image.pullPolicy": "Always",
|
"image.pullPolicy": "Always",
|
||||||
"image.tag": "dev",
|
"image.tag": "dev",
|
||||||
"imagePullSecrets[0].name": "dockerhub",
|
"imagePullSecrets[0].name": "dockerhub",
|
||||||
"nameOverride": "actions-runner-controller-2-override",
|
"nameOverride": "gha-runner-scale-set-controller-override",
|
||||||
"fullnameOverride": "actions-runner-controller-2-fullname-override",
|
"fullnameOverride": "gha-runner-scale-set-controller-fullname-override",
|
||||||
"serviceAccount.name": "actions-runner-controller-2-sa",
|
"serviceAccount.name": "gha-runner-scale-set-controller-sa",
|
||||||
"podAnnotations.foo": "bar",
|
"podAnnotations.foo": "bar",
|
||||||
"podSecurityContext.fsGroup": "1000",
|
"podSecurityContext.fsGroup": "1000",
|
||||||
"securityContext.runAsUser": "1000",
|
"securityContext.runAsUser": "1000",
|
||||||
@@ -335,9 +335,9 @@ func TestTemplate_ControllerDeployment_Customize(t *testing.T) {
|
|||||||
helm.UnmarshalK8SYaml(t, output, &deployment)
|
helm.UnmarshalK8SYaml(t, output, &deployment)
|
||||||
|
|
||||||
assert.Equal(t, namespaceName, deployment.Namespace)
|
assert.Equal(t, namespaceName, deployment.Namespace)
|
||||||
assert.Equal(t, "actions-runner-controller-2-fullname-override", deployment.Name)
|
assert.Equal(t, "gha-runner-scale-set-controller-fullname-override", deployment.Name)
|
||||||
assert.Equal(t, "actions-runner-controller-2-"+chart.Version, deployment.Labels["helm.sh/chart"])
|
assert.Equal(t, "gha-runner-scale-set-controller-"+chart.Version, deployment.Labels["helm.sh/chart"])
|
||||||
assert.Equal(t, "actions-runner-controller-2-override", deployment.Labels["app.kubernetes.io/name"])
|
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, "test-arc", deployment.Labels["app.kubernetes.io/instance"])
|
||||||
assert.Equal(t, chart.AppVersion, deployment.Labels["app.kubernetes.io/version"])
|
assert.Equal(t, chart.AppVersion, deployment.Labels["app.kubernetes.io/version"])
|
||||||
assert.Equal(t, "Helm", deployment.Labels["app.kubernetes.io/managed-by"])
|
assert.Equal(t, "Helm", deployment.Labels["app.kubernetes.io/managed-by"])
|
||||||
@@ -346,10 +346,10 @@ func TestTemplate_ControllerDeployment_Customize(t *testing.T) {
|
|||||||
|
|
||||||
assert.Equal(t, int32(1), *deployment.Spec.Replicas)
|
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, "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, "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, "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, "test-arc", deployment.Spec.Template.Labels["app.kubernetes.io/instance"])
|
||||||
|
|
||||||
assert.Equal(t, "bar", deployment.Spec.Template.Annotations["foo"])
|
assert.Equal(t, "bar", deployment.Spec.Template.Annotations["foo"])
|
||||||
@@ -357,7 +357,7 @@ func TestTemplate_ControllerDeployment_Customize(t *testing.T) {
|
|||||||
|
|
||||||
assert.Len(t, deployment.Spec.Template.Spec.ImagePullSecrets, 1)
|
assert.Len(t, deployment.Spec.Template.Spec.ImagePullSecrets, 1)
|
||||||
assert.Equal(t, "dockerhub", deployment.Spec.Template.Spec.ImagePullSecrets[0].Name)
|
assert.Equal(t, "dockerhub", deployment.Spec.Template.Spec.ImagePullSecrets[0].Name)
|
||||||
assert.Equal(t, "actions-runner-controller-2-sa", deployment.Spec.Template.Spec.ServiceAccountName)
|
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, int64(1000), *deployment.Spec.Template.Spec.SecurityContext.FSGroup)
|
||||||
assert.Equal(t, "test-priority-class", deployment.Spec.Template.Spec.PriorityClassName)
|
assert.Equal(t, "test-priority-class", deployment.Spec.Template.Spec.PriorityClassName)
|
||||||
assert.Equal(t, int64(10), *deployment.Spec.Template.Spec.TerminationGracePeriodSeconds)
|
assert.Equal(t, int64(10), *deployment.Spec.Template.Spec.TerminationGracePeriodSeconds)
|
||||||
@@ -377,7 +377,7 @@ func TestTemplate_ControllerDeployment_Customize(t *testing.T) {
|
|||||||
|
|
||||||
assert.Len(t, deployment.Spec.Template.Spec.Containers, 1)
|
assert.Len(t, deployment.Spec.Template.Spec.Containers, 1)
|
||||||
assert.Equal(t, "manager", deployment.Spec.Template.Spec.Containers[0].Name)
|
assert.Equal(t, "manager", deployment.Spec.Template.Spec.Containers[0].Name)
|
||||||
assert.Equal(t, "ghcr.io/actions/actions-runner-controller-2:dev", deployment.Spec.Template.Spec.Containers[0].Image)
|
assert.Equal(t, "ghcr.io/actions/gha-runner-scale-set-controller:dev", deployment.Spec.Template.Spec.Containers[0].Image)
|
||||||
assert.Equal(t, corev1.PullAlways, deployment.Spec.Template.Spec.Containers[0].ImagePullPolicy)
|
assert.Equal(t, corev1.PullAlways, deployment.Spec.Template.Spec.Containers[0].ImagePullPolicy)
|
||||||
|
|
||||||
assert.Len(t, deployment.Spec.Template.Spec.Containers[0].Command, 1)
|
assert.Len(t, deployment.Spec.Template.Spec.Containers[0].Command, 1)
|
||||||
@@ -408,7 +408,7 @@ func TestTemplate_EnableLeaderElectionRole(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../actions-runner-controller-2")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set-controller")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-arc"
|
releaseName := "test-arc"
|
||||||
@@ -426,7 +426,7 @@ func TestTemplate_EnableLeaderElectionRole(t *testing.T) {
|
|||||||
var leaderRole rbacv1.Role
|
var leaderRole rbacv1.Role
|
||||||
helm.UnmarshalK8SYaml(t, output, &leaderRole)
|
helm.UnmarshalK8SYaml(t, output, &leaderRole)
|
||||||
|
|
||||||
assert.Equal(t, "test-arc-actions-runner-controller-2-leader-election-role", leaderRole.Name)
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller-leader-election-role", leaderRole.Name)
|
||||||
assert.Equal(t, namespaceName, leaderRole.Namespace)
|
assert.Equal(t, namespaceName, leaderRole.Namespace)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,7 +434,7 @@ func TestTemplate_EnableLeaderElectionRoleBinding(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../actions-runner-controller-2")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set-controller")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-arc"
|
releaseName := "test-arc"
|
||||||
@@ -452,17 +452,17 @@ func TestTemplate_EnableLeaderElectionRoleBinding(t *testing.T) {
|
|||||||
var leaderRoleBinding rbacv1.RoleBinding
|
var leaderRoleBinding rbacv1.RoleBinding
|
||||||
helm.UnmarshalK8SYaml(t, output, &leaderRoleBinding)
|
helm.UnmarshalK8SYaml(t, output, &leaderRoleBinding)
|
||||||
|
|
||||||
assert.Equal(t, "test-arc-actions-runner-controller-2-leader-election-rolebinding", leaderRoleBinding.Name)
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller-leader-election-rolebinding", leaderRoleBinding.Name)
|
||||||
assert.Equal(t, namespaceName, leaderRoleBinding.Namespace)
|
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-gha-runner-scale-set-controller-leader-election-role", leaderRoleBinding.RoleRef.Name)
|
||||||
assert.Equal(t, "test-arc-actions-runner-controller-2", leaderRoleBinding.Subjects[0].Name)
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller", leaderRoleBinding.Subjects[0].Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTemplate_EnableLeaderElection(t *testing.T) {
|
func TestTemplate_EnableLeaderElection(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../actions-runner-controller-2")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set-controller")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-arc"
|
releaseName := "test-arc"
|
||||||
@@ -482,13 +482,13 @@ func TestTemplate_EnableLeaderElection(t *testing.T) {
|
|||||||
helm.UnmarshalK8SYaml(t, output, &deployment)
|
helm.UnmarshalK8SYaml(t, output, &deployment)
|
||||||
|
|
||||||
assert.Equal(t, namespaceName, deployment.Namespace)
|
assert.Equal(t, namespaceName, deployment.Namespace)
|
||||||
assert.Equal(t, "test-arc-actions-runner-controller-2", deployment.Name)
|
assert.Equal(t, "test-arc-gha-runner-scale-set-controller", deployment.Name)
|
||||||
|
|
||||||
assert.Equal(t, int32(2), *deployment.Spec.Replicas)
|
assert.Equal(t, int32(2), *deployment.Spec.Replicas)
|
||||||
|
|
||||||
assert.Len(t, deployment.Spec.Template.Spec.Containers, 1)
|
assert.Len(t, deployment.Spec.Template.Spec.Containers, 1)
|
||||||
assert.Equal(t, "manager", deployment.Spec.Template.Spec.Containers[0].Name)
|
assert.Equal(t, "manager", deployment.Spec.Template.Spec.Containers[0].Name)
|
||||||
assert.Equal(t, "ghcr.io/actions/actions-runner-controller-2:dev", deployment.Spec.Template.Spec.Containers[0].Image)
|
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.Equal(t, corev1.PullIfNotPresent, deployment.Spec.Template.Spec.Containers[0].ImagePullPolicy)
|
||||||
|
|
||||||
assert.Len(t, deployment.Spec.Template.Spec.Containers[0].Command, 1)
|
assert.Len(t, deployment.Spec.Template.Spec.Containers[0].Command, 1)
|
||||||
@@ -497,7 +497,7 @@ func TestTemplate_EnableLeaderElection(t *testing.T) {
|
|||||||
assert.Len(t, deployment.Spec.Template.Spec.Containers[0].Args, 4)
|
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, "--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, "--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, "--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])
|
assert.Equal(t, "--log-level=debug", deployment.Spec.Template.Spec.Containers[0].Args[3])
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -505,7 +505,7 @@ func TestTemplate_ControllerDeployment_ForwardImagePullSecrets(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../actions-runner-controller-2")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set-controller")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-arc"
|
releaseName := "test-arc"
|
||||||
@@ -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: ""
|
||||||
@@ -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
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{{/*
|
{{/*
|
||||||
Expand the name of the chart.
|
Expand the name of the chart.
|
||||||
*/}}
|
*/}}
|
||||||
{{- define "auto-scaling-runner-set.name" -}}
|
{{- define "gha-runner-scale-set.name" -}}
|
||||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ 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).
|
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.
|
If release name contains chart name it will be used as a full name.
|
||||||
*/}}
|
*/}}
|
||||||
{{- define "auto-scaling-runner-set.fullname" -}}
|
{{- define "gha-runner-scale-set.fullname" -}}
|
||||||
{{- if .Values.fullnameOverride }}
|
{{- if .Values.fullnameOverride }}
|
||||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
||||||
{{- else }}
|
{{- else }}
|
||||||
@@ -26,16 +26,16 @@ If release name contains chart name it will be used as a full name.
|
|||||||
{{/*
|
{{/*
|
||||||
Create chart name and version as used by the chart label.
|
Create chart name and version as used by the chart label.
|
||||||
*/}}
|
*/}}
|
||||||
{{- define "auto-scaling-runner-set.chart" -}}
|
{{- define "gha-runner-scale-set.chart" -}}
|
||||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{/*
|
{{/*
|
||||||
Common labels
|
Common labels
|
||||||
*/}}
|
*/}}
|
||||||
{{- define "auto-scaling-runner-set.labels" -}}
|
{{- define "gha-runner-scale-set.labels" -}}
|
||||||
helm.sh/chart: {{ include "auto-scaling-runner-set.chart" . }}
|
helm.sh/chart: {{ include "gha-runner-scale-set.chart" . }}
|
||||||
{{ include "auto-scaling-runner-set.selectorLabels" . }}
|
{{ include "gha-runner-scale-set.selectorLabels" . }}
|
||||||
{{- if .Chart.AppVersion }}
|
{{- if .Chart.AppVersion }}
|
||||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
@@ -45,12 +45,12 @@ app.kubernetes.io/managed-by: {{ .Release.Service }}
|
|||||||
{{/*
|
{{/*
|
||||||
Selector labels
|
Selector labels
|
||||||
*/}}
|
*/}}
|
||||||
{{- define "auto-scaling-runner-set.selectorLabels" -}}
|
{{- define "gha-runner-scale-set.selectorLabels" -}}
|
||||||
app.kubernetes.io/name: {{ include "auto-scaling-runner-set.name" . }}
|
app.kubernetes.io/name: {{ include "gha-runner-scale-set.name" . }}
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- define "auto-scaling-runner-set.githubsecret" -}}
|
{{- define "gha-runner-scale-set.githubsecret" -}}
|
||||||
{{- if kindIs "string" .Values.githubConfigSecret }}
|
{{- if kindIs "string" .Values.githubConfigSecret }}
|
||||||
{{- if not (empty .Values.githubConfigSecret) }}
|
{{- if not (empty .Values.githubConfigSecret) }}
|
||||||
{{- .Values.githubConfigSecret }}
|
{{- .Values.githubConfigSecret }}
|
||||||
@@ -58,23 +58,23 @@ app.kubernetes.io/instance: {{ .Release.Name }}
|
|||||||
{{- fail "Values.githubConfigSecret is required for setting auth with GitHub server." }}
|
{{- fail "Values.githubConfigSecret is required for setting auth with GitHub server." }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- else }}
|
{{- else }}
|
||||||
{{- include "auto-scaling-runner-set.fullname" . }}-github-secret
|
{{- include "gha-runner-scale-set.fullname" . }}-github-secret
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- define "auto-scaling-runner-set.noPermissionServiceAccountName" -}}
|
{{- define "gha-runner-scale-set.noPermissionServiceAccountName" -}}
|
||||||
{{- include "auto-scaling-runner-set.fullname" . }}-no-permission-service-account
|
{{- include "gha-runner-scale-set.fullname" . }}-no-permission-service-account
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- define "auto-scaling-runner-set.kubeModeRoleName" -}}
|
{{- define "gha-runner-scale-set.kubeModeRoleName" -}}
|
||||||
{{- include "auto-scaling-runner-set.fullname" . }}-kube-mode-role
|
{{- include "gha-runner-scale-set.fullname" . }}-kube-mode-role
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- define "auto-scaling-runner-set.kubeModeServiceAccountName" -}}
|
{{- define "gha-runner-scale-set.kubeModeServiceAccountName" -}}
|
||||||
{{- include "auto-scaling-runner-set.fullname" . }}-kube-mode-service-account
|
{{- include "gha-runner-scale-set.fullname" . }}-kube-mode-service-account
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- define "auto-scaling-runner-set.dind-init-container" -}}
|
{{- define "gha-runner-scale-set.dind-init-container" -}}
|
||||||
{{- range $i, $val := .Values.template.spec.containers -}}
|
{{- range $i, $val := .Values.template.spec.containers -}}
|
||||||
{{- if eq $val.name "runner" -}}
|
{{- if eq $val.name "runner" -}}
|
||||||
image: {{ $val.image }}
|
image: {{ $val.image }}
|
||||||
@@ -83,45 +83,49 @@ imagePullSecrets:
|
|||||||
{{ $val.imagePullSecrets | toYaml -}}
|
{{ $val.imagePullSecrets | toYaml -}}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
command: ["cp"]
|
command: ["cp"]
|
||||||
args: ["-r", "-v", "/actions-runner/externals/.", "/actions-runner/tmpDir/"]
|
args: ["-r", "-v", "/home/runner/externals/.", "/home/runner/tmpDir/"]
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: dind-externals
|
- name: dind-externals
|
||||||
mountPath: /actions-runner/tmpDir
|
mountPath: /home/runner/tmpDir
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- define "auto-scaling-runner-set.dind-container" -}}
|
{{- define "gha-runner-scale-set.dind-container" -}}
|
||||||
image: docker:dind
|
image: docker:dind
|
||||||
securityContext:
|
securityContext:
|
||||||
privileged: true
|
privileged: true
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: work
|
- name: work
|
||||||
mountPath: /actions-runner/_work
|
mountPath: /home/runner/_work
|
||||||
- name: dind-cert
|
- name: dind-cert
|
||||||
mountPath: /certs/client
|
mountPath: /certs/client
|
||||||
- name: dind-externals
|
- name: dind-externals
|
||||||
mountPath: /actions-runner/externals
|
mountPath: /home/runner/externals
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- define "auto-scaling-runner-set.dind-volume" -}}
|
{{- define "gha-runner-scale-set.dind-volume" -}}
|
||||||
- name: dind-cert
|
- name: dind-cert
|
||||||
emptyDir: {}
|
emptyDir: {}
|
||||||
- name: dind-externals
|
- name: dind-externals
|
||||||
emptyDir: {}
|
emptyDir: {}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- define "auto-scaling-runner-set.dind-work-volume" -}}
|
{{- 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 }}
|
{{- $createWorkVolume := 1 }}
|
||||||
{{- range $i, $volume := .Values.template.spec.volumes }}
|
{{- range $i, $volume := .Values.template.spec.volumes }}
|
||||||
{{- if eq $volume.name "work" }}
|
{{- if eq $volume.name "work" }}
|
||||||
{{- $createWorkVolume = 0 -}}
|
{{- $createWorkVolume = 0 -}}
|
||||||
- name: work
|
- {{ $volume | toYaml | nindent 2 }}
|
||||||
{{- range $key, $val := $volume }}
|
|
||||||
{{- if ne $key "name" }}
|
|
||||||
{{ $key }}: {{ $val }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if eq $createWorkVolume 1 }}
|
{{- if eq $createWorkVolume 1 }}
|
||||||
@@ -130,17 +134,12 @@ volumeMounts:
|
|||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- define "auto-scaling-runner-set.kubernetes-mode-work-volume" -}}
|
{{- define "gha-runner-scale-set.kubernetes-mode-work-volume" -}}
|
||||||
{{- $createWorkVolume := 1 }}
|
{{- $createWorkVolume := 1 }}
|
||||||
{{- range $i, $volume := .Values.template.spec.volumes }}
|
{{- range $i, $volume := .Values.template.spec.volumes }}
|
||||||
{{- if eq $volume.name "work" }}
|
{{- if eq $volume.name "work" }}
|
||||||
{{- $createWorkVolume = 0 -}}
|
{{- $createWorkVolume = 0 -}}
|
||||||
- name: work
|
- {{ $volume | toYaml | nindent 2 }}
|
||||||
{{- range $key, $val := $volume }}
|
|
||||||
{{- if ne $key "name" }}
|
|
||||||
{{ $key }}: {{ $val }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if eq $createWorkVolume 1 }}
|
{{- if eq $createWorkVolume 1 }}
|
||||||
@@ -152,20 +151,15 @@ volumeMounts:
|
|||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- define "auto-scaling-runner-set.non-work-volumes" -}}
|
{{- define "gha-runner-scale-set.non-work-volumes" -}}
|
||||||
{{- range $i, $volume := .Values.template.spec.volumes }}
|
{{- range $i, $volume := .Values.template.spec.volumes }}
|
||||||
{{- if ne $volume.name "work" }}
|
{{- if ne $volume.name "work" }}
|
||||||
- name: {{ $volume.name }}
|
- {{ $volume | toYaml | nindent 2 }}
|
||||||
{{- range $key, $val := $volume }}
|
|
||||||
{{- if ne $key "name" }}
|
|
||||||
{{ $key }}: {{ $val }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- define "auto-scaling-runner-set.non-runner-containers" -}}
|
{{- define "gha-runner-scale-set.non-runner-containers" -}}
|
||||||
{{- range $i, $container := .Values.template.spec.containers -}}
|
{{- range $i, $container := .Values.template.spec.containers -}}
|
||||||
{{- if ne $container.name "runner" -}}
|
{{- if ne $container.name "runner" -}}
|
||||||
- name: {{ $container.name }}
|
- name: {{ $container.name }}
|
||||||
@@ -178,7 +172,8 @@ volumeMounts:
|
|||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- define "auto-scaling-runner-set.dind-runner-container" -}}
|
{{- define "gha-runner-scale-set.dind-runner-container" -}}
|
||||||
|
{{- $tlsConfig := (default (dict) .Values.githubServerTLS) }}
|
||||||
{{- range $i, $container := .Values.template.spec.containers -}}
|
{{- range $i, $container := .Values.template.spec.containers -}}
|
||||||
{{- if eq $container.name "runner" -}}
|
{{- if eq $container.name "runner" -}}
|
||||||
{{- range $key, $val := $container }}
|
{{- range $key, $val := $container }}
|
||||||
@@ -190,6 +185,12 @@ volumeMounts:
|
|||||||
{{- $setDockerTlsVerify := 1 }}
|
{{- $setDockerTlsVerify := 1 }}
|
||||||
{{- $setDockerCertPath := 1 }}
|
{{- $setDockerCertPath := 1 }}
|
||||||
{{- $setRunnerWaitDocker := 1 }}
|
{{- $setRunnerWaitDocker := 1 }}
|
||||||
|
{{- $setNodeExtraCaCerts := 0 }}
|
||||||
|
{{- $setRunnerUpdateCaCerts := 0 }}
|
||||||
|
{{- if $tlsConfig.runnerMountPath }}
|
||||||
|
{{- $setNodeExtraCaCerts = 1 }}
|
||||||
|
{{- $setRunnerUpdateCaCerts = 1 }}
|
||||||
|
{{- end }}
|
||||||
env:
|
env:
|
||||||
{{- with $container.env }}
|
{{- with $container.env }}
|
||||||
{{- range $i, $env := . }}
|
{{- range $i, $env := . }}
|
||||||
@@ -205,6 +206,12 @@ env:
|
|||||||
{{- if eq $env.name "RUNNER_WAIT_FOR_DOCKER_IN_SECONDS" }}
|
{{- if eq $env.name "RUNNER_WAIT_FOR_DOCKER_IN_SECONDS" }}
|
||||||
{{- $setRunnerWaitDocker = 0 -}}
|
{{- $setRunnerWaitDocker = 0 -}}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
{{- if eq $env.name "NODE_EXTRA_CA_CERTS" }}
|
||||||
|
{{- $setNodeExtraCaCerts = 0 -}}
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq $env.name "RUNNER_UPDATE_CA_CERTS" }}
|
||||||
|
{{- $setRunnerUpdateCaCerts = 0 -}}
|
||||||
|
{{- end }}
|
||||||
- name: {{ $env.name }}
|
- name: {{ $env.name }}
|
||||||
{{- range $envKey, $envVal := $env }}
|
{{- range $envKey, $envVal := $env }}
|
||||||
{{- if ne $envKey "name" }}
|
{{- if ne $envKey "name" }}
|
||||||
@@ -229,8 +236,20 @@ env:
|
|||||||
- name: RUNNER_WAIT_FOR_DOCKER_IN_SECONDS
|
- name: RUNNER_WAIT_FOR_DOCKER_IN_SECONDS
|
||||||
value: "120"
|
value: "120"
|
||||||
{{- 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 }}
|
||||||
{{- $mountWork := 1 }}
|
{{- $mountWork := 1 }}
|
||||||
{{- $mountDindCert := 1 }}
|
{{- $mountDindCert := 1 }}
|
||||||
|
{{- $mountGitHubServerTLS := 0 }}
|
||||||
|
{{- if $tlsConfig.runnerMountPath }}
|
||||||
|
{{- $mountGitHubServerTLS = 1 }}
|
||||||
|
{{- end }}
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
{{- with $container.volumeMounts }}
|
{{- with $container.volumeMounts }}
|
||||||
{{- range $i, $volMount := . }}
|
{{- range $i, $volMount := . }}
|
||||||
@@ -240,6 +259,9 @@ volumeMounts:
|
|||||||
{{- if eq $volMount.name "dind-cert" }}
|
{{- if eq $volMount.name "dind-cert" }}
|
||||||
{{- $mountDindCert = 0 -}}
|
{{- $mountDindCert = 0 -}}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
{{- if eq $volMount.name "github-server-tls-cert" }}
|
||||||
|
{{- $mountGitHubServerTLS = 0 -}}
|
||||||
|
{{- end }}
|
||||||
- name: {{ $volMount.name }}
|
- name: {{ $volMount.name }}
|
||||||
{{- range $mountKey, $mountVal := $volMount }}
|
{{- range $mountKey, $mountVal := $volMount }}
|
||||||
{{- if ne $mountKey "name" }}
|
{{- if ne $mountKey "name" }}
|
||||||
@@ -250,18 +272,24 @@ volumeMounts:
|
|||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if $mountWork }}
|
{{- if $mountWork }}
|
||||||
- name: work
|
- name: work
|
||||||
mountPath: /actions-runner/_work
|
mountPath: /home/runner/_work
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if $mountDindCert }}
|
{{- if $mountDindCert }}
|
||||||
- name: dind-cert
|
- name: dind-cert
|
||||||
mountPath: /certs/client
|
mountPath: /certs/client
|
||||||
readOnly: true
|
readOnly: true
|
||||||
{{- 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 }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- define "auto-scaling-runner-set.kubernetes-mode-runner-container" -}}
|
{{- define "gha-runner-scale-set.kubernetes-mode-runner-container" -}}
|
||||||
|
{{- $tlsConfig := (default (dict) .Values.githubServerTLS) }}
|
||||||
{{- range $i, $container := .Values.template.spec.containers -}}
|
{{- range $i, $container := .Values.template.spec.containers -}}
|
||||||
{{- if eq $container.name "runner" -}}
|
{{- if eq $container.name "runner" -}}
|
||||||
{{- range $key, $val := $container }}
|
{{- range $key, $val := $container }}
|
||||||
@@ -272,6 +300,12 @@ volumeMounts:
|
|||||||
{{- $setContainerHooks := 1 }}
|
{{- $setContainerHooks := 1 }}
|
||||||
{{- $setPodName := 1 }}
|
{{- $setPodName := 1 }}
|
||||||
{{- $setRequireJobContainer := 1 }}
|
{{- $setRequireJobContainer := 1 }}
|
||||||
|
{{- $setNodeExtraCaCerts := 0 }}
|
||||||
|
{{- $setRunnerUpdateCaCerts := 0 }}
|
||||||
|
{{- if $tlsConfig.runnerMountPath }}
|
||||||
|
{{- $setNodeExtraCaCerts = 1 }}
|
||||||
|
{{- $setRunnerUpdateCaCerts = 1 }}
|
||||||
|
{{- end }}
|
||||||
env:
|
env:
|
||||||
{{- with $container.env }}
|
{{- with $container.env }}
|
||||||
{{- range $i, $env := . }}
|
{{- range $i, $env := . }}
|
||||||
@@ -284,6 +318,12 @@ env:
|
|||||||
{{- if eq $env.name "ACTIONS_RUNNER_REQUIRE_JOB_CONTAINER" }}
|
{{- if eq $env.name "ACTIONS_RUNNER_REQUIRE_JOB_CONTAINER" }}
|
||||||
{{- $setRequireJobContainer = 0 -}}
|
{{- $setRequireJobContainer = 0 -}}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
{{- if eq $env.name "NODE_EXTRA_CA_CERTS" }}
|
||||||
|
{{- $setNodeExtraCaCerts = 0 -}}
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq $env.name "RUNNER_UPDATE_CA_CERTS" }}
|
||||||
|
{{- $setRunnerUpdateCaCerts = 0 -}}
|
||||||
|
{{- end }}
|
||||||
- name: {{ $env.name }}
|
- name: {{ $env.name }}
|
||||||
{{- range $envKey, $envVal := $env }}
|
{{- range $envKey, $envVal := $env }}
|
||||||
{{- if ne $envKey "name" }}
|
{{- if ne $envKey "name" }}
|
||||||
@@ -294,7 +334,7 @@ env:
|
|||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if $setContainerHooks }}
|
{{- if $setContainerHooks }}
|
||||||
- name: ACTIONS_RUNNER_CONTAINER_HOOKS
|
- name: ACTIONS_RUNNER_CONTAINER_HOOKS
|
||||||
value: /actions-runner/k8s/index.js
|
value: /home/runner/k8s/index.js
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if $setPodName }}
|
{{- if $setPodName }}
|
||||||
- name: ACTIONS_RUNNER_POD_NAME
|
- name: ACTIONS_RUNNER_POD_NAME
|
||||||
@@ -306,13 +346,28 @@ env:
|
|||||||
- name: ACTIONS_RUNNER_REQUIRE_JOB_CONTAINER
|
- name: ACTIONS_RUNNER_REQUIRE_JOB_CONTAINER
|
||||||
value: "true"
|
value: "true"
|
||||||
{{- 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 }}
|
||||||
{{- $mountWork := 1 }}
|
{{- $mountWork := 1 }}
|
||||||
|
{{- $mountGitHubServerTLS := 0 }}
|
||||||
|
{{- if $tlsConfig.runnerMountPath }}
|
||||||
|
{{- $mountGitHubServerTLS = 1 }}
|
||||||
|
{{- end }}
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
{{- with $container.volumeMounts }}
|
{{- with $container.volumeMounts }}
|
||||||
{{- range $i, $volMount := . }}
|
{{- range $i, $volMount := . }}
|
||||||
{{- if eq $volMount.name "work" }}
|
{{- if eq $volMount.name "work" }}
|
||||||
{{- $mountWork = 0 -}}
|
{{- $mountWork = 0 -}}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
{{- if eq $volMount.name "github-server-tls-cert" }}
|
||||||
|
{{- $mountGitHubServerTLS = 0 -}}
|
||||||
|
{{- end }}
|
||||||
- name: {{ $volMount.name }}
|
- name: {{ $volMount.name }}
|
||||||
{{- range $mountKey, $mountVal := $volMount }}
|
{{- range $mountKey, $mountVal := $volMount }}
|
||||||
{{- if ne $mountKey "name" }}
|
{{- if ne $mountKey "name" }}
|
||||||
@@ -323,8 +378,83 @@ volumeMounts:
|
|||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if $mountWork }}
|
{{- if $mountWork }}
|
||||||
- name: work
|
- name: work
|
||||||
mountPath: /actions-runner/_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 }}
|
||||||
{{- 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 }}
|
||||||
|
{{- 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 }}
|
||||||
|
- name: {{ $env.name }}
|
||||||
|
{{- range $envKey, $envVal := $env }}
|
||||||
|
{{- if ne $envKey "name" }}
|
||||||
|
{{ $envKey }}: {{ $envVal | toYaml | nindent 10 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- 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 }}
|
||||||
|
- name: {{ $volMount.name }}
|
||||||
|
{{- range $mountKey, $mountVal := $volMount }}
|
||||||
|
{{- if ne $mountKey "name" }}
|
||||||
|
{{ $mountKey }}: {{ $mountVal | toYaml | nindent 10 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- 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 }}
|
||||||
@@ -1,16 +1,35 @@
|
|||||||
apiVersion: actions.github.com/v1alpha1
|
apiVersion: actions.github.com/v1alpha1
|
||||||
kind: AutoscalingRunnerSet
|
kind: AutoscalingRunnerSet
|
||||||
metadata:
|
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 }}
|
name: {{ .Release.Name }}
|
||||||
namespace: {{ .Release.Namespace }}
|
namespace: {{ .Release.Namespace }}
|
||||||
labels:
|
labels:
|
||||||
{{- include "auto-scaling-runner-set.labels" . | nindent 4 }}
|
{{- include "gha-runner-scale-set.labels" . | nindent 4 }}
|
||||||
spec:
|
spec:
|
||||||
githubConfigUrl: {{ required ".Values.githubConfigUrl is required" .Values.githubConfigUrl }}
|
githubConfigUrl: {{ required ".Values.githubConfigUrl is required" (trimSuffix "/" .Values.githubConfigUrl) }}
|
||||||
githubConfigSecret: {{ include "auto-scaling-runner-set.githubsecret" . }}
|
githubConfigSecret: {{ include "gha-runner-scale-set.githubsecret" . }}
|
||||||
{{- with .Values.runnerGroup }}
|
{{- with .Values.runnerGroup }}
|
||||||
runnerGroup: {{ . }}
|
runnerGroup: {{ . }}
|
||||||
{{- end }}
|
{{- 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 }}
|
{{- if .Values.proxy }}
|
||||||
proxy:
|
proxy:
|
||||||
@@ -68,41 +87,50 @@ spec:
|
|||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if eq .Values.containerMode.type "kubernetes" }}
|
{{- if eq .Values.containerMode.type "kubernetes" }}
|
||||||
serviceAccountName: {{ default (include "auto-scaling-runner-set.kubeModeServiceAccountName" .) .Values.template.spec.serviceAccountName }}
|
serviceAccountName: {{ default (include "gha-runner-scale-set.kubeModeServiceAccountName" .) .Values.template.spec.serviceAccountName }}
|
||||||
{{- else }}
|
{{- else }}
|
||||||
serviceAccountName: {{ default (include "auto-scaling-runner-set.noPermissionServiceAccountName" .) .Values.template.spec.serviceAccountName }}
|
serviceAccountName: {{ default (include "gha-runner-scale-set.noPermissionServiceAccountName" .) .Values.template.spec.serviceAccountName }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if or .Values.template.spec.initContainers (eq .Values.containerMode.type "dind") }}
|
{{- if or .Values.template.spec.initContainers (eq .Values.containerMode.type "dind") }}
|
||||||
initContainers:
|
initContainers:
|
||||||
{{- if eq .Values.containerMode.type "dind" }}
|
{{- if eq .Values.containerMode.type "dind" }}
|
||||||
- name: init-dind-externals
|
- name: init-dind-externals
|
||||||
{{- include "auto-scaling-runner-set.dind-init-container" . | nindent 8 }}
|
{{- include "gha-runner-scale-set.dind-init-container" . | nindent 8 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- with .Values.template.spec.initContainers }}
|
{{- with .Values.template.spec.initContainers }}
|
||||||
{{- toYaml . | nindent 8 }}
|
{{- toYaml . | nindent 8 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
containers:
|
containers:
|
||||||
{{- if eq .Values.containerMode.type "dind" }}
|
{{- if eq .Values.containerMode.type "dind" }}
|
||||||
- name: runner
|
- name: runner
|
||||||
{{- include "auto-scaling-runner-set.dind-runner-container" . | nindent 8 }}
|
{{- include "gha-runner-scale-set.dind-runner-container" . | nindent 8 }}
|
||||||
- name: dind
|
- name: dind
|
||||||
{{- include "auto-scaling-runner-set.dind-container" . | nindent 8 }}
|
{{- include "gha-runner-scale-set.dind-container" . | nindent 8 }}
|
||||||
{{- include "auto-scaling-runner-set.non-runner-containers" . | nindent 6 }}
|
{{- include "gha-runner-scale-set.non-runner-containers" . | nindent 6 }}
|
||||||
{{- else if eq .Values.containerMode.type "kubernetes" }}
|
{{- else if eq .Values.containerMode.type "kubernetes" }}
|
||||||
- name: runner
|
- name: runner
|
||||||
{{- include "auto-scaling-runner-set.kubernetes-mode-runner-container" . | nindent 8 }}
|
{{- include "gha-runner-scale-set.kubernetes-mode-runner-container" . | nindent 8 }}
|
||||||
{{- include "auto-scaling-runner-set.non-runner-containers" . | nindent 6 }}
|
{{- include "gha-runner-scale-set.non-runner-containers" . | nindent 6 }}
|
||||||
{{- else }}
|
{{- else }}
|
||||||
{{ .Values.template.spec.containers | toYaml | nindent 6 }}
|
{{- include "gha-runner-scale-set.default-mode-runner-containers" . | nindent 6 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if or .Values.template.spec.volumes (eq .Values.containerMode.type "dind") (eq .Values.containerMode.type "kubernetes") }}
|
{{- $tlsConfig := (default (dict) .Values.githubServerTLS) }}
|
||||||
volumes:
|
{{- if or .Values.template.spec.volumes (eq .Values.containerMode.type "dind") (eq .Values.containerMode.type "kubernetes") $tlsConfig.runnerMountPath }}
|
||||||
{{- if eq .Values.containerMode.type "dind" }}
|
volumes:
|
||||||
{{- include "auto-scaling-runner-set.dind-volume" . | nindent 6 }}
|
{{- if $tlsConfig.runnerMountPath }}
|
||||||
{{- include "auto-scaling-runner-set.dind-work-volume" . | nindent 6 }}
|
{{- include "gha-runner-scale-set.tls-volume" $tlsConfig | nindent 6 }}
|
||||||
{{- else if eq .Values.containerMode.type "kubernetes" }}
|
|
||||||
{{- include "auto-scaling-runner-set.kubernetes-mode-work-volume" . | nindent 6 }}
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- include "auto-scaling-runner-set.non-work-volumes" . | nindent 6 }}
|
{{- if eq .Values.containerMode.type "dind" }}
|
||||||
{{- end }}
|
{{- 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 .Values.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:
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
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: [""]
|
||||||
@@ -2,14 +2,14 @@
|
|||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: RoleBinding
|
kind: RoleBinding
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ include "auto-scaling-runner-set.kubeModeRoleName" . }}
|
name: {{ include "gha-runner-scale-set.kubeModeRoleName" . }}
|
||||||
namespace: {{ .Release.Namespace }}
|
namespace: {{ .Release.Namespace }}
|
||||||
roleRef:
|
roleRef:
|
||||||
apiGroup: rbac.authorization.k8s.io
|
apiGroup: rbac.authorization.k8s.io
|
||||||
kind: Role
|
kind: Role
|
||||||
name: {{ include "auto-scaling-runner-set.kubeModeRoleName" . }}
|
name: {{ include "gha-runner-scale-set.kubeModeRoleName" . }}
|
||||||
subjects:
|
subjects:
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: {{ include "auto-scaling-runner-set.kubeModeServiceAccountName" . }}
|
name: {{ include "gha-runner-scale-set.kubeModeServiceAccountName" . }}
|
||||||
namespace: {{ .Release.Namespace }}
|
namespace: {{ .Release.Namespace }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
@@ -2,8 +2,8 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: ServiceAccount
|
kind: ServiceAccount
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ include "auto-scaling-runner-set.kubeModeServiceAccountName" . }}
|
name: {{ include "gha-runner-scale-set.kubeModeServiceAccountName" . }}
|
||||||
namespace: {{ .Release.Namespace }}
|
namespace: {{ .Release.Namespace }}
|
||||||
labels:
|
labels:
|
||||||
{{- include "auto-scaling-runner-set.labels" . | nindent 4 }}
|
{{- include "gha-runner-scale-set.labels" . | nindent 4 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
@@ -2,8 +2,8 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: ServiceAccount
|
kind: ServiceAccount
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ include "auto-scaling-runner-set.noPermissionServiceAccountName" . }}
|
name: {{ include "gha-runner-scale-set.noPermissionServiceAccountName" . }}
|
||||||
namespace: {{ .Release.Namespace }}
|
namespace: {{ .Release.Namespace }}
|
||||||
labels:
|
labels:
|
||||||
{{- include "auto-scaling-runner-set.labels" . | nindent 4 }}
|
{{- include "gha-runner-scale-set.labels" . | nindent 4 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
@@ -19,7 +19,7 @@ func TestTemplateRenderedGitHubSecretWithGitHubToken(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-set")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-runners"
|
releaseName := "test-runners"
|
||||||
@@ -39,7 +39,7 @@ func TestTemplateRenderedGitHubSecretWithGitHubToken(t *testing.T) {
|
|||||||
helm.UnmarshalK8SYaml(t, output, &githubSecret)
|
helm.UnmarshalK8SYaml(t, output, &githubSecret)
|
||||||
|
|
||||||
assert.Equal(t, namespaceName, githubSecret.Namespace)
|
assert.Equal(t, namespaceName, githubSecret.Namespace)
|
||||||
assert.Equal(t, "test-runners-auto-scaling-runner-set-github-secret", githubSecret.Name)
|
assert.Equal(t, "test-runners-gha-runner-scale-set-github-secret", githubSecret.Name)
|
||||||
assert.Equal(t, "gh_token12345", string(githubSecret.Data["github_token"]))
|
assert.Equal(t, "gh_token12345", string(githubSecret.Data["github_token"]))
|
||||||
assert.Equal(t, "actions.github.com/secret-protection", githubSecret.Finalizers[0])
|
assert.Equal(t, "actions.github.com/secret-protection", githubSecret.Finalizers[0])
|
||||||
}
|
}
|
||||||
@@ -48,7 +48,7 @@ func TestTemplateRenderedGitHubSecretWithGitHubApp(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-set")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-runners"
|
releaseName := "test-runners"
|
||||||
@@ -79,7 +79,7 @@ func TestTemplateRenderedGitHubSecretErrorWithMissingAuthInput(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-set")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-runners"
|
releaseName := "test-runners"
|
||||||
@@ -104,7 +104,7 @@ func TestTemplateRenderedGitHubSecretErrorWithMissingAppInput(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-set")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-runners"
|
releaseName := "test-runners"
|
||||||
@@ -128,7 +128,7 @@ func TestTemplateNotRenderedGitHubSecretWithPredefinedSecret(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-set")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-runners"
|
releaseName := "test-runners"
|
||||||
@@ -150,7 +150,7 @@ func TestTemplateRenderedSetServiceAccountToNoPermission(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-set")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-runners"
|
releaseName := "test-runners"
|
||||||
@@ -169,20 +169,20 @@ func TestTemplateRenderedSetServiceAccountToNoPermission(t *testing.T) {
|
|||||||
helm.UnmarshalK8SYaml(t, output, &serviceAccount)
|
helm.UnmarshalK8SYaml(t, output, &serviceAccount)
|
||||||
|
|
||||||
assert.Equal(t, namespaceName, serviceAccount.Namespace)
|
assert.Equal(t, namespaceName, serviceAccount.Namespace)
|
||||||
assert.Equal(t, "test-runners-auto-scaling-runner-set-no-permission-service-account", serviceAccount.Name)
|
assert.Equal(t, "test-runners-gha-runner-scale-set-no-permission-service-account", serviceAccount.Name)
|
||||||
|
|
||||||
output = helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/autoscalingrunnerset.yaml"})
|
output = helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/autoscalingrunnerset.yaml"})
|
||||||
var ars v1alpha1.AutoscalingRunnerSet
|
var ars v1alpha1.AutoscalingRunnerSet
|
||||||
helm.UnmarshalK8SYaml(t, output, &ars)
|
helm.UnmarshalK8SYaml(t, output, &ars)
|
||||||
|
|
||||||
assert.Equal(t, "test-runners-auto-scaling-runner-set-no-permission-service-account", ars.Spec.Template.Spec.ServiceAccountName)
|
assert.Equal(t, "test-runners-gha-runner-scale-set-no-permission-service-account", ars.Spec.Template.Spec.ServiceAccountName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTemplateRenderedSetServiceAccountToKubeMode(t *testing.T) {
|
func TestTemplateRenderedSetServiceAccountToKubeMode(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-set")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-runners"
|
releaseName := "test-runners"
|
||||||
@@ -202,14 +202,14 @@ func TestTemplateRenderedSetServiceAccountToKubeMode(t *testing.T) {
|
|||||||
helm.UnmarshalK8SYaml(t, output, &serviceAccount)
|
helm.UnmarshalK8SYaml(t, output, &serviceAccount)
|
||||||
|
|
||||||
assert.Equal(t, namespaceName, serviceAccount.Namespace)
|
assert.Equal(t, namespaceName, serviceAccount.Namespace)
|
||||||
assert.Equal(t, "test-runners-auto-scaling-runner-set-kube-mode-service-account", serviceAccount.Name)
|
assert.Equal(t, "test-runners-gha-runner-scale-set-kube-mode-service-account", serviceAccount.Name)
|
||||||
|
|
||||||
output = helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/kube_mode_role.yaml"})
|
output = helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/kube_mode_role.yaml"})
|
||||||
var role rbacv1.Role
|
var role rbacv1.Role
|
||||||
helm.UnmarshalK8SYaml(t, output, &role)
|
helm.UnmarshalK8SYaml(t, output, &role)
|
||||||
|
|
||||||
assert.Equal(t, namespaceName, role.Namespace)
|
assert.Equal(t, namespaceName, role.Namespace)
|
||||||
assert.Equal(t, "test-runners-auto-scaling-runner-set-kube-mode-role", role.Name)
|
assert.Equal(t, "test-runners-gha-runner-scale-set-kube-mode-role", role.Name)
|
||||||
assert.Len(t, role.Rules, 5, "kube mode role should have 5 rules")
|
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", role.Rules[0].Resources[0])
|
||||||
assert.Equal(t, "pods/exec", role.Rules[1].Resources[0])
|
assert.Equal(t, "pods/exec", role.Rules[1].Resources[0])
|
||||||
@@ -222,25 +222,25 @@ func TestTemplateRenderedSetServiceAccountToKubeMode(t *testing.T) {
|
|||||||
helm.UnmarshalK8SYaml(t, output, &roleBinding)
|
helm.UnmarshalK8SYaml(t, output, &roleBinding)
|
||||||
|
|
||||||
assert.Equal(t, namespaceName, roleBinding.Namespace)
|
assert.Equal(t, namespaceName, roleBinding.Namespace)
|
||||||
assert.Equal(t, "test-runners-auto-scaling-runner-set-kube-mode-role", roleBinding.Name)
|
assert.Equal(t, "test-runners-gha-runner-scale-set-kube-mode-role", roleBinding.Name)
|
||||||
assert.Len(t, roleBinding.Subjects, 1)
|
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, "test-runners-gha-runner-scale-set-kube-mode-service-account", roleBinding.Subjects[0].Name)
|
||||||
assert.Equal(t, namespaceName, roleBinding.Subjects[0].Namespace)
|
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, "test-runners-gha-runner-scale-set-kube-mode-role", roleBinding.RoleRef.Name)
|
||||||
assert.Equal(t, "Role", roleBinding.RoleRef.Kind)
|
assert.Equal(t, "Role", roleBinding.RoleRef.Kind)
|
||||||
|
|
||||||
output = helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/autoscalingrunnerset.yaml"})
|
output = helm.RenderTemplate(t, options, helmChartPath, releaseName, []string{"templates/autoscalingrunnerset.yaml"})
|
||||||
var ars v1alpha1.AutoscalingRunnerSet
|
var ars v1alpha1.AutoscalingRunnerSet
|
||||||
helm.UnmarshalK8SYaml(t, output, &ars)
|
helm.UnmarshalK8SYaml(t, output, &ars)
|
||||||
|
|
||||||
assert.Equal(t, "test-runners-auto-scaling-runner-set-kube-mode-service-account", ars.Spec.Template.Spec.ServiceAccountName)
|
assert.Equal(t, "test-runners-gha-runner-scale-set-kube-mode-service-account", ars.Spec.Template.Spec.ServiceAccountName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTemplateRenderedUserProvideSetServiceAccount(t *testing.T) {
|
func TestTemplateRenderedUserProvideSetServiceAccount(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-set")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-runners"
|
releaseName := "test-runners"
|
||||||
@@ -269,7 +269,7 @@ func TestTemplateRenderedAutoScalingRunnerSet(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-set")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-runners"
|
releaseName := "test-runners"
|
||||||
@@ -291,10 +291,57 @@ func TestTemplateRenderedAutoScalingRunnerSet(t *testing.T) {
|
|||||||
assert.Equal(t, namespaceName, ars.Namespace)
|
assert.Equal(t, namespaceName, ars.Namespace)
|
||||||
assert.Equal(t, "test-runners", ars.Name)
|
assert.Equal(t, "test-runners", ars.Name)
|
||||||
|
|
||||||
assert.Equal(t, "auto-scaling-runner-set", ars.Labels["app.kubernetes.io/name"])
|
assert.Equal(t, "gha-runner-scale-set", ars.Labels["app.kubernetes.io/name"])
|
||||||
assert.Equal(t, "test-runners", ars.Labels["app.kubernetes.io/instance"])
|
assert.Equal(t, "test-runners", ars.Labels["app.kubernetes.io/instance"])
|
||||||
assert.Equal(t, "https://github.com/actions", ars.Spec.GitHubConfigUrl)
|
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.Equal(t, "test-runners-gha-runner-scale-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_RunnerScaleSetName(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// Path to the helm chart we will test
|
||||||
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
releaseName := "test-runners"
|
||||||
|
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
||||||
|
|
||||||
|
options := &helm.Options{
|
||||||
|
SetValues: map[string]string{
|
||||||
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
|
"githubConfigSecret.github_token": "gh_token12345",
|
||||||
|
"runnerScaleSetName": "test-runner-scale-set-name",
|
||||||
|
},
|
||||||
|
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, "gha-runner-scale-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-gha-runner-scale-set-github-secret", ars.Spec.GitHubConfigSecret)
|
||||||
|
assert.Equal(t, "test-runner-scale-set-name", ars.Spec.RunnerScaleSetName)
|
||||||
|
|
||||||
assert.Empty(t, ars.Spec.RunnerGroup, "RunnerGroup should be empty")
|
assert.Empty(t, ars.Spec.RunnerGroup, "RunnerGroup should be empty")
|
||||||
|
|
||||||
@@ -314,7 +361,7 @@ func TestTemplateRenderedAutoScalingRunnerSet_ProvideMetadata(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-set")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-runners"
|
releaseName := "test-runners"
|
||||||
@@ -359,7 +406,7 @@ func TestTemplateRenderedAutoScalingRunnerSet_MaxRunnersValidationError(t *testi
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-set")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-runners"
|
releaseName := "test-runners"
|
||||||
@@ -384,7 +431,7 @@ func TestTemplateRenderedAutoScalingRunnerSet_MinRunnersValidationError(t *testi
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-set")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-runners"
|
releaseName := "test-runners"
|
||||||
@@ -410,7 +457,7 @@ func TestTemplateRenderedAutoScalingRunnerSet_MinMaxRunnersValidationError(t *te
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-set")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-runners"
|
releaseName := "test-runners"
|
||||||
@@ -436,7 +483,7 @@ func TestTemplateRenderedAutoScalingRunnerSet_MinMaxRunnersValidationSameValue(t
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-set")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-runners"
|
releaseName := "test-runners"
|
||||||
@@ -465,7 +512,7 @@ func TestTemplateRenderedAutoScalingRunnerSet_MinMaxRunnersValidation_OnlyMin(t
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-set")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-runners"
|
releaseName := "test-runners"
|
||||||
@@ -493,7 +540,7 @@ func TestTemplateRenderedAutoScalingRunnerSet_MinMaxRunnersValidation_OnlyMax(t
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-set")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-runners"
|
releaseName := "test-runners"
|
||||||
@@ -521,7 +568,7 @@ func TestTemplateRenderedAutoScalingRunnerSet_MinMaxRunners_FromValuesFile(t *te
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-set")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
testValuesPath, err := filepath.Abs("../tests/values.yaml")
|
testValuesPath, err := filepath.Abs("../tests/values.yaml")
|
||||||
@@ -544,11 +591,103 @@ func TestTemplateRenderedAutoScalingRunnerSet_MinMaxRunners_FromValuesFile(t *te
|
|||||||
assert.Equal(t, 10, *ars.Spec.MaxRunners, "MaxRunners should be 10")
|
assert.Equal(t, 10, *ars.Spec.MaxRunners, "MaxRunners should be 10")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTemplateRenderedAutoScalingRunnerSet_ExtraVolumes(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// Path to the helm chart we will test
|
||||||
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
testValuesPath, err := filepath.Abs("../tests/values_extra_volumes.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.Len(t, ars.Spec.Template.Spec.Volumes, 3, "Volumes should be 3")
|
||||||
|
assert.Equal(t, "foo", ars.Spec.Template.Spec.Volumes[0].Name, "Volume name should be foo")
|
||||||
|
assert.Equal(t, "bar", ars.Spec.Template.Spec.Volumes[1].Name, "Volume name should be bar")
|
||||||
|
assert.Equal(t, "work", ars.Spec.Template.Spec.Volumes[2].Name, "Volume name should be work")
|
||||||
|
assert.Equal(t, "/data", ars.Spec.Template.Spec.Volumes[2].HostPath.Path, "Volume host path should be /data")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTemplateRenderedAutoScalingRunnerSet_DinD_ExtraVolumes(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// Path to the helm chart we will test
|
||||||
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
testValuesPath, err := filepath.Abs("../tests/values_dind_extra_volumes.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.Len(t, ars.Spec.Template.Spec.Volumes, 5, "Volumes should be 5")
|
||||||
|
assert.Equal(t, "dind-cert", ars.Spec.Template.Spec.Volumes[0].Name, "Volume name should be dind-cert")
|
||||||
|
assert.Equal(t, "dind-externals", ars.Spec.Template.Spec.Volumes[1].Name, "Volume name should be dind-externals")
|
||||||
|
assert.Equal(t, "work", ars.Spec.Template.Spec.Volumes[2].Name, "Volume name should be work")
|
||||||
|
assert.Equal(t, "/data", ars.Spec.Template.Spec.Volumes[2].HostPath.Path, "Volume host path should be /data")
|
||||||
|
assert.Equal(t, "foo", ars.Spec.Template.Spec.Volumes[3].Name, "Volume name should be foo")
|
||||||
|
assert.Equal(t, "bar", ars.Spec.Template.Spec.Volumes[4].Name, "Volume name should be bar")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTemplateRenderedAutoScalingRunnerSet_K8S_ExtraVolumes(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// Path to the helm chart we will test
|
||||||
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
testValuesPath, err := filepath.Abs("../tests/values_k8s_extra_volumes.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.Len(t, ars.Spec.Template.Spec.Volumes, 3, "Volumes should be 3")
|
||||||
|
assert.Equal(t, "work", ars.Spec.Template.Spec.Volumes[0].Name, "Volume name should be work")
|
||||||
|
assert.Equal(t, "/data", ars.Spec.Template.Spec.Volumes[0].HostPath.Path, "Volume host path should be /data")
|
||||||
|
assert.Equal(t, "foo", ars.Spec.Template.Spec.Volumes[1].Name, "Volume name should be foo")
|
||||||
|
assert.Equal(t, "bar", ars.Spec.Template.Spec.Volumes[2].Name, "Volume name should be bar")
|
||||||
|
}
|
||||||
|
|
||||||
func TestTemplateRenderedAutoScalingRunnerSet_EnableDinD(t *testing.T) {
|
func TestTemplateRenderedAutoScalingRunnerSet_EnableDinD(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-set")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-runners"
|
releaseName := "test-runners"
|
||||||
@@ -571,10 +710,10 @@ func TestTemplateRenderedAutoScalingRunnerSet_EnableDinD(t *testing.T) {
|
|||||||
assert.Equal(t, namespaceName, ars.Namespace)
|
assert.Equal(t, namespaceName, ars.Namespace)
|
||||||
assert.Equal(t, "test-runners", ars.Name)
|
assert.Equal(t, "test-runners", ars.Name)
|
||||||
|
|
||||||
assert.Equal(t, "auto-scaling-runner-set", ars.Labels["app.kubernetes.io/name"])
|
assert.Equal(t, "gha-runner-scale-set", ars.Labels["app.kubernetes.io/name"])
|
||||||
assert.Equal(t, "test-runners", ars.Labels["app.kubernetes.io/instance"])
|
assert.Equal(t, "test-runners", ars.Labels["app.kubernetes.io/instance"])
|
||||||
assert.Equal(t, "https://github.com/actions", ars.Spec.GitHubConfigUrl)
|
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.Equal(t, "test-runners-gha-runner-scale-set-github-secret", ars.Spec.GitHubConfigSecret)
|
||||||
|
|
||||||
assert.Empty(t, ars.Spec.RunnerGroup, "RunnerGroup should be empty")
|
assert.Empty(t, ars.Spec.RunnerGroup, "RunnerGroup should be empty")
|
||||||
|
|
||||||
@@ -589,7 +728,7 @@ func TestTemplateRenderedAutoScalingRunnerSet_EnableDinD(t *testing.T) {
|
|||||||
assert.Equal(t, "init-dind-externals", ars.Spec.Template.Spec.InitContainers[0].Name)
|
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, "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, "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.Equal(t, "-r -v /home/runner/externals/. /home/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.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, "runner", ars.Spec.Template.Spec.Containers[0].Name)
|
||||||
@@ -606,7 +745,7 @@ func TestTemplateRenderedAutoScalingRunnerSet_EnableDinD(t *testing.T) {
|
|||||||
|
|
||||||
assert.Len(t, ars.Spec.Template.Spec.Containers[0].VolumeMounts, 2, "The runner container should have 2 volume mounts, dind-cert and work")
|
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, "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.Equal(t, "/home/runner/_work", ars.Spec.Template.Spec.Containers[0].VolumeMounts[0].MountPath)
|
||||||
assert.False(t, ars.Spec.Template.Spec.Containers[0].VolumeMounts[0].ReadOnly)
|
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, "dind-cert", ars.Spec.Template.Spec.Containers[0].VolumeMounts[1].Name)
|
||||||
@@ -618,20 +757,26 @@ func TestTemplateRenderedAutoScalingRunnerSet_EnableDinD(t *testing.T) {
|
|||||||
assert.True(t, *ars.Spec.Template.Spec.Containers[1].SecurityContext.Privileged)
|
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.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, "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, "/home/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, "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, "/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, "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)
|
assert.Equal(t, "/home/runner/externals", ars.Spec.Template.Spec.Containers[1].VolumeMounts[2].MountPath)
|
||||||
|
|
||||||
|
assert.Len(t, ars.Spec.Template.Spec.Volumes, 3, "Volumes should be 3")
|
||||||
|
assert.Equal(t, "dind-cert", ars.Spec.Template.Spec.Volumes[0].Name, "Volume name should be dind-cert")
|
||||||
|
assert.Equal(t, "dind-externals", ars.Spec.Template.Spec.Volumes[1].Name, "Volume name should be dind-externals")
|
||||||
|
assert.Equal(t, "work", ars.Spec.Template.Spec.Volumes[2].Name, "Volume name should be work")
|
||||||
|
assert.NotNil(t, ars.Spec.Template.Spec.Volumes[2].EmptyDir, "Volume work should be an emptyDir")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTemplateRenderedAutoScalingRunnerSet_EnableKubernetesMode(t *testing.T) {
|
func TestTemplateRenderedAutoScalingRunnerSet_EnableKubernetesMode(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-set")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-runners"
|
releaseName := "test-runners"
|
||||||
@@ -654,10 +799,10 @@ func TestTemplateRenderedAutoScalingRunnerSet_EnableKubernetesMode(t *testing.T)
|
|||||||
assert.Equal(t, namespaceName, ars.Namespace)
|
assert.Equal(t, namespaceName, ars.Namespace)
|
||||||
assert.Equal(t, "test-runners", ars.Name)
|
assert.Equal(t, "test-runners", ars.Name)
|
||||||
|
|
||||||
assert.Equal(t, "auto-scaling-runner-set", ars.Labels["app.kubernetes.io/name"])
|
assert.Equal(t, "gha-runner-scale-set", ars.Labels["app.kubernetes.io/name"])
|
||||||
assert.Equal(t, "test-runners", ars.Labels["app.kubernetes.io/instance"])
|
assert.Equal(t, "test-runners", ars.Labels["app.kubernetes.io/instance"])
|
||||||
assert.Equal(t, "https://github.com/actions", ars.Spec.GitHubConfigUrl)
|
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.Equal(t, "test-runners-gha-runner-scale-set-github-secret", ars.Spec.GitHubConfigSecret)
|
||||||
|
|
||||||
assert.Empty(t, ars.Spec.RunnerGroup, "RunnerGroup should be empty")
|
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.MinRunners, "MinRunners should be nil")
|
||||||
@@ -672,7 +817,7 @@ func TestTemplateRenderedAutoScalingRunnerSet_EnableKubernetesMode(t *testing.T)
|
|||||||
assert.Equal(t, "ghcr.io/actions/actions-runner:latest", ars.Spec.Template.Spec.Containers[0].Image)
|
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_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, "/home/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_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, "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.Equal(t, "true", ars.Spec.Template.Spec.Containers[0].Env[2].Value)
|
||||||
@@ -686,7 +831,7 @@ func TestTemplateRenderedAutoScalingRunnerSet_UsePredefinedSecret(t *testing.T)
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-set")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-runners"
|
releaseName := "test-runners"
|
||||||
@@ -708,7 +853,7 @@ func TestTemplateRenderedAutoScalingRunnerSet_UsePredefinedSecret(t *testing.T)
|
|||||||
assert.Equal(t, namespaceName, ars.Namespace)
|
assert.Equal(t, namespaceName, ars.Namespace)
|
||||||
assert.Equal(t, "test-runners", ars.Name)
|
assert.Equal(t, "test-runners", ars.Name)
|
||||||
|
|
||||||
assert.Equal(t, "auto-scaling-runner-set", ars.Labels["app.kubernetes.io/name"])
|
assert.Equal(t, "gha-runner-scale-set", ars.Labels["app.kubernetes.io/name"])
|
||||||
assert.Equal(t, "test-runners", ars.Labels["app.kubernetes.io/instance"])
|
assert.Equal(t, "test-runners", ars.Labels["app.kubernetes.io/instance"])
|
||||||
assert.Equal(t, "https://github.com/actions", ars.Spec.GitHubConfigUrl)
|
assert.Equal(t, "https://github.com/actions", ars.Spec.GitHubConfigUrl)
|
||||||
assert.Equal(t, "pre-defined-secrets", ars.Spec.GitHubConfigSecret)
|
assert.Equal(t, "pre-defined-secrets", ars.Spec.GitHubConfigSecret)
|
||||||
@@ -718,7 +863,7 @@ func TestTemplateRenderedAutoScalingRunnerSet_ErrorOnEmptyPredefinedSecret(t *te
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-set")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-runners"
|
releaseName := "test-runners"
|
||||||
@@ -742,7 +887,7 @@ func TestTemplateRenderedWithProxy(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Path to the helm chart we will test
|
// Path to the helm chart we will test
|
||||||
helmChartPath, err := filepath.Abs("../../auto-scaling-runner-set")
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
releaseName := "test-runners"
|
releaseName := "test-runners"
|
||||||
@@ -780,3 +925,432 @@ func TestTemplateRenderedWithProxy(t *testing.T) {
|
|||||||
assert.Contains(t, ars.Spec.Proxy.NoProxy, "example.com")
|
assert.Contains(t, ars.Spec.Proxy.NoProxy, "example.com")
|
||||||
assert.Contains(t, ars.Spec.Proxy.NoProxy, "example.org")
|
assert.Contains(t, ars.Spec.Proxy.NoProxy, "example.org")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTemplateRenderedWithTLS(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
||||||
|
|
||||||
|
render := func(t *testing.T, options *helm.Options) v1alpha1.AutoscalingRunnerSet {
|
||||||
|
// Path to the helm chart we will test
|
||||||
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
releaseName := "test-runners"
|
||||||
|
|
||||||
|
output := helm.RenderTemplate(
|
||||||
|
t,
|
||||||
|
options,
|
||||||
|
helmChartPath,
|
||||||
|
releaseName,
|
||||||
|
[]string{"templates/autoscalingrunnerset.yaml"},
|
||||||
|
)
|
||||||
|
|
||||||
|
var ars v1alpha1.AutoscalingRunnerSet
|
||||||
|
helm.UnmarshalK8SYaml(t, output, &ars)
|
||||||
|
|
||||||
|
return ars
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("providing githubServerTLS.runnerMountPath", func(t *testing.T) {
|
||||||
|
t.Run("mode: default", func(t *testing.T) {
|
||||||
|
options := &helm.Options{
|
||||||
|
SetValues: map[string]string{
|
||||||
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
|
"githubConfigSecret": "pre-defined-secrets",
|
||||||
|
"githubServerTLS.certificateFrom.configMapKeyRef.name": "certs-configmap",
|
||||||
|
"githubServerTLS.certificateFrom.configMapKeyRef.key": "cert.pem",
|
||||||
|
"githubServerTLS.runnerMountPath": "/runner/mount/path",
|
||||||
|
},
|
||||||
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
|
}
|
||||||
|
|
||||||
|
ars := render(t, options)
|
||||||
|
|
||||||
|
require.NotNil(t, ars.Spec.GitHubServerTLS)
|
||||||
|
expected := &v1alpha1.GitHubServerTLSConfig{
|
||||||
|
CertificateFrom: &v1alpha1.TLSCertificateSource{
|
||||||
|
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
|
||||||
|
LocalObjectReference: corev1.LocalObjectReference{
|
||||||
|
Name: "certs-configmap",
|
||||||
|
},
|
||||||
|
Key: "cert.pem",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert.Equal(t, expected, ars.Spec.GitHubServerTLS)
|
||||||
|
|
||||||
|
var volume *corev1.Volume
|
||||||
|
for _, v := range ars.Spec.Template.Spec.Volumes {
|
||||||
|
if v.Name == "github-server-tls-cert" {
|
||||||
|
volume = &v
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
require.NotNil(t, volume)
|
||||||
|
assert.Equal(t, "certs-configmap", volume.ConfigMap.LocalObjectReference.Name)
|
||||||
|
assert.Equal(t, "cert.pem", volume.ConfigMap.Items[0].Key)
|
||||||
|
assert.Equal(t, "cert.pem", volume.ConfigMap.Items[0].Path)
|
||||||
|
|
||||||
|
assert.Contains(t, ars.Spec.Template.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{
|
||||||
|
Name: "github-server-tls-cert",
|
||||||
|
MountPath: "/runner/mount/path/cert.pem",
|
||||||
|
SubPath: "cert.pem",
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.Contains(t, ars.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{
|
||||||
|
Name: "NODE_EXTRA_CA_CERTS",
|
||||||
|
Value: "/runner/mount/path/cert.pem",
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.Contains(t, ars.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{
|
||||||
|
Name: "RUNNER_UPDATE_CA_CERTS",
|
||||||
|
Value: "1",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("mode: dind", func(t *testing.T) {
|
||||||
|
options := &helm.Options{
|
||||||
|
SetValues: map[string]string{
|
||||||
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
|
"githubConfigSecret": "pre-defined-secrets",
|
||||||
|
"githubServerTLS.certificateFrom.configMapKeyRef.name": "certs-configmap",
|
||||||
|
"githubServerTLS.certificateFrom.configMapKeyRef.key": "cert.pem",
|
||||||
|
"githubServerTLS.runnerMountPath": "/runner/mount/path/",
|
||||||
|
"containerMode.type": "dind",
|
||||||
|
},
|
||||||
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
|
}
|
||||||
|
|
||||||
|
ars := render(t, options)
|
||||||
|
|
||||||
|
require.NotNil(t, ars.Spec.GitHubServerTLS)
|
||||||
|
expected := &v1alpha1.GitHubServerTLSConfig{
|
||||||
|
CertificateFrom: &v1alpha1.TLSCertificateSource{
|
||||||
|
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
|
||||||
|
LocalObjectReference: corev1.LocalObjectReference{
|
||||||
|
Name: "certs-configmap",
|
||||||
|
},
|
||||||
|
Key: "cert.pem",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert.Equal(t, expected, ars.Spec.GitHubServerTLS)
|
||||||
|
|
||||||
|
var volume *corev1.Volume
|
||||||
|
for _, v := range ars.Spec.Template.Spec.Volumes {
|
||||||
|
if v.Name == "github-server-tls-cert" {
|
||||||
|
volume = &v
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
require.NotNil(t, volume)
|
||||||
|
assert.Equal(t, "certs-configmap", volume.ConfigMap.LocalObjectReference.Name)
|
||||||
|
assert.Equal(t, "cert.pem", volume.ConfigMap.Items[0].Key)
|
||||||
|
assert.Equal(t, "cert.pem", volume.ConfigMap.Items[0].Path)
|
||||||
|
|
||||||
|
assert.Contains(t, ars.Spec.Template.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{
|
||||||
|
Name: "github-server-tls-cert",
|
||||||
|
MountPath: "/runner/mount/path/cert.pem",
|
||||||
|
SubPath: "cert.pem",
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.Contains(t, ars.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{
|
||||||
|
Name: "NODE_EXTRA_CA_CERTS",
|
||||||
|
Value: "/runner/mount/path/cert.pem",
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.Contains(t, ars.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{
|
||||||
|
Name: "RUNNER_UPDATE_CA_CERTS",
|
||||||
|
Value: "1",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("mode: kubernetes", func(t *testing.T) {
|
||||||
|
options := &helm.Options{
|
||||||
|
SetValues: map[string]string{
|
||||||
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
|
"githubConfigSecret": "pre-defined-secrets",
|
||||||
|
"githubServerTLS.certificateFrom.configMapKeyRef.name": "certs-configmap",
|
||||||
|
"githubServerTLS.certificateFrom.configMapKeyRef.key": "cert.pem",
|
||||||
|
"githubServerTLS.runnerMountPath": "/runner/mount/path",
|
||||||
|
"containerMode.type": "kubernetes",
|
||||||
|
},
|
||||||
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
|
}
|
||||||
|
|
||||||
|
ars := render(t, options)
|
||||||
|
|
||||||
|
require.NotNil(t, ars.Spec.GitHubServerTLS)
|
||||||
|
expected := &v1alpha1.GitHubServerTLSConfig{
|
||||||
|
CertificateFrom: &v1alpha1.TLSCertificateSource{
|
||||||
|
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
|
||||||
|
LocalObjectReference: corev1.LocalObjectReference{
|
||||||
|
Name: "certs-configmap",
|
||||||
|
},
|
||||||
|
Key: "cert.pem",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert.Equal(t, expected, ars.Spec.GitHubServerTLS)
|
||||||
|
|
||||||
|
var volume *corev1.Volume
|
||||||
|
for _, v := range ars.Spec.Template.Spec.Volumes {
|
||||||
|
if v.Name == "github-server-tls-cert" {
|
||||||
|
volume = &v
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
require.NotNil(t, volume)
|
||||||
|
assert.Equal(t, "certs-configmap", volume.ConfigMap.LocalObjectReference.Name)
|
||||||
|
assert.Equal(t, "cert.pem", volume.ConfigMap.Items[0].Key)
|
||||||
|
assert.Equal(t, "cert.pem", volume.ConfigMap.Items[0].Path)
|
||||||
|
|
||||||
|
assert.Contains(t, ars.Spec.Template.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{
|
||||||
|
Name: "github-server-tls-cert",
|
||||||
|
MountPath: "/runner/mount/path/cert.pem",
|
||||||
|
SubPath: "cert.pem",
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.Contains(t, ars.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{
|
||||||
|
Name: "NODE_EXTRA_CA_CERTS",
|
||||||
|
Value: "/runner/mount/path/cert.pem",
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.Contains(t, ars.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{
|
||||||
|
Name: "RUNNER_UPDATE_CA_CERTS",
|
||||||
|
Value: "1",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("without providing githubServerTLS.runnerMountPath", func(t *testing.T) {
|
||||||
|
t.Run("mode: default", func(t *testing.T) {
|
||||||
|
options := &helm.Options{
|
||||||
|
SetValues: map[string]string{
|
||||||
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
|
"githubConfigSecret": "pre-defined-secrets",
|
||||||
|
"githubServerTLS.certificateFrom.configMapKeyRef.name": "certs-configmap",
|
||||||
|
"githubServerTLS.certificateFrom.configMapKeyRef.key": "cert.pem",
|
||||||
|
},
|
||||||
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
|
}
|
||||||
|
|
||||||
|
ars := render(t, options)
|
||||||
|
|
||||||
|
require.NotNil(t, ars.Spec.GitHubServerTLS)
|
||||||
|
expected := &v1alpha1.GitHubServerTLSConfig{
|
||||||
|
CertificateFrom: &v1alpha1.TLSCertificateSource{
|
||||||
|
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
|
||||||
|
LocalObjectReference: corev1.LocalObjectReference{
|
||||||
|
Name: "certs-configmap",
|
||||||
|
},
|
||||||
|
Key: "cert.pem",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert.Equal(t, expected, ars.Spec.GitHubServerTLS)
|
||||||
|
|
||||||
|
var volume *corev1.Volume
|
||||||
|
for _, v := range ars.Spec.Template.Spec.Volumes {
|
||||||
|
if v.Name == "github-server-tls-cert" {
|
||||||
|
volume = &v
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert.Nil(t, volume)
|
||||||
|
|
||||||
|
assert.NotContains(t, ars.Spec.Template.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{
|
||||||
|
Name: "github-server-tls-cert",
|
||||||
|
MountPath: "/runner/mount/path/cert.pem",
|
||||||
|
SubPath: "cert.pem",
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.NotContains(t, ars.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{
|
||||||
|
Name: "NODE_EXTRA_CA_CERTS",
|
||||||
|
Value: "/runner/mount/path/cert.pem",
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.NotContains(t, ars.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{
|
||||||
|
Name: "RUNNER_UPDATE_CA_CERTS",
|
||||||
|
Value: "1",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("mode: dind", func(t *testing.T) {
|
||||||
|
options := &helm.Options{
|
||||||
|
SetValues: map[string]string{
|
||||||
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
|
"githubConfigSecret": "pre-defined-secrets",
|
||||||
|
"githubServerTLS.certificateFrom.configMapKeyRef.name": "certs-configmap",
|
||||||
|
"githubServerTLS.certificateFrom.configMapKeyRef.key": "cert.pem",
|
||||||
|
"containerMode.type": "dind",
|
||||||
|
},
|
||||||
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
|
}
|
||||||
|
|
||||||
|
ars := render(t, options)
|
||||||
|
|
||||||
|
require.NotNil(t, ars.Spec.GitHubServerTLS)
|
||||||
|
expected := &v1alpha1.GitHubServerTLSConfig{
|
||||||
|
CertificateFrom: &v1alpha1.TLSCertificateSource{
|
||||||
|
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
|
||||||
|
LocalObjectReference: corev1.LocalObjectReference{
|
||||||
|
Name: "certs-configmap",
|
||||||
|
},
|
||||||
|
Key: "cert.pem",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert.Equal(t, expected, ars.Spec.GitHubServerTLS)
|
||||||
|
|
||||||
|
var volume *corev1.Volume
|
||||||
|
for _, v := range ars.Spec.Template.Spec.Volumes {
|
||||||
|
if v.Name == "github-server-tls-cert" {
|
||||||
|
volume = &v
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert.Nil(t, volume)
|
||||||
|
|
||||||
|
assert.NotContains(t, ars.Spec.Template.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{
|
||||||
|
Name: "github-server-tls-cert",
|
||||||
|
MountPath: "/runner/mount/path/cert.pem",
|
||||||
|
SubPath: "cert.pem",
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.NotContains(t, ars.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{
|
||||||
|
Name: "NODE_EXTRA_CA_CERTS",
|
||||||
|
Value: "/runner/mount/path/cert.pem",
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.NotContains(t, ars.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{
|
||||||
|
Name: "RUNNER_UPDATE_CA_CERTS",
|
||||||
|
Value: "1",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("mode: kubernetes", func(t *testing.T) {
|
||||||
|
options := &helm.Options{
|
||||||
|
SetValues: map[string]string{
|
||||||
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
|
"githubConfigSecret": "pre-defined-secrets",
|
||||||
|
"githubServerTLS.certificateFrom.configMapKeyRef.name": "certs-configmap",
|
||||||
|
"githubServerTLS.certificateFrom.configMapKeyRef.key": "cert.pem",
|
||||||
|
"containerMode.type": "kubernetes",
|
||||||
|
},
|
||||||
|
KubectlOptions: k8s.NewKubectlOptions("", "", namespaceName),
|
||||||
|
}
|
||||||
|
|
||||||
|
ars := render(t, options)
|
||||||
|
|
||||||
|
require.NotNil(t, ars.Spec.GitHubServerTLS)
|
||||||
|
expected := &v1alpha1.GitHubServerTLSConfig{
|
||||||
|
CertificateFrom: &v1alpha1.TLSCertificateSource{
|
||||||
|
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
|
||||||
|
LocalObjectReference: corev1.LocalObjectReference{
|
||||||
|
Name: "certs-configmap",
|
||||||
|
},
|
||||||
|
Key: "cert.pem",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert.Equal(t, expected, ars.Spec.GitHubServerTLS)
|
||||||
|
|
||||||
|
var volume *corev1.Volume
|
||||||
|
for _, v := range ars.Spec.Template.Spec.Volumes {
|
||||||
|
if v.Name == "github-server-tls-cert" {
|
||||||
|
volume = &v
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert.Nil(t, volume)
|
||||||
|
|
||||||
|
assert.NotContains(t, ars.Spec.Template.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{
|
||||||
|
Name: "github-server-tls-cert",
|
||||||
|
MountPath: "/runner/mount/path/cert.pem",
|
||||||
|
SubPath: "cert.pem",
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.NotContains(t, ars.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{
|
||||||
|
Name: "NODE_EXTRA_CA_CERTS",
|
||||||
|
Value: "/runner/mount/path/cert.pem",
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.NotContains(t, ars.Spec.Template.Spec.Containers[0].Env, corev1.EnvVar{
|
||||||
|
Name: "RUNNER_UPDATE_CA_CERTS",
|
||||||
|
Value: "1",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTemplateNamingConstraints(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// Path to the helm chart we will test
|
||||||
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
setValues := map[string]string{
|
||||||
|
"githubConfigUrl": "https://github.com/actions",
|
||||||
|
"githubConfigSecret": "",
|
||||||
|
}
|
||||||
|
|
||||||
|
tt := map[string]struct {
|
||||||
|
releaseName string
|
||||||
|
namespaceName string
|
||||||
|
expectedError string
|
||||||
|
}{
|
||||||
|
"Name too long": {
|
||||||
|
releaseName: strings.Repeat("a", 46),
|
||||||
|
namespaceName: "test-" + strings.ToLower(random.UniqueId()),
|
||||||
|
expectedError: "Name must have up to 45 characters",
|
||||||
|
},
|
||||||
|
"Namespace too long": {
|
||||||
|
releaseName: "test-" + strings.ToLower(random.UniqueId()),
|
||||||
|
namespaceName: strings.Repeat("a", 64),
|
||||||
|
expectedError: "Namespace must have up to 63 characters",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, tc := range tt {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
options := &helm.Options{
|
||||||
|
SetValues: setValues,
|
||||||
|
KubectlOptions: k8s.NewKubectlOptions("", "", tc.namespaceName),
|
||||||
|
}
|
||||||
|
_, err = helm.RenderTemplateE(t, options, helmChartPath, tc.releaseName, []string{"templates/autoscalingrunnerset.yaml"})
|
||||||
|
require.Error(t, err)
|
||||||
|
assert.ErrorContains(t, err, tc.expectedError)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTemplateRenderedGitHubConfigUrlEndsWIthSlash(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// Path to the helm chart we will test
|
||||||
|
helmChartPath, err := filepath.Abs("../../gha-runner-scale-set")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
releaseName := "test-runners"
|
||||||
|
namespaceName := "test-" + strings.ToLower(random.UniqueId())
|
||||||
|
|
||||||
|
options := &helm.Options{
|
||||||
|
SetValues: map[string]string{
|
||||||
|
"githubConfigUrl": "https://github.com/actions/",
|
||||||
|
"githubConfigSecret.github_token": "gh_token12345",
|
||||||
|
},
|
||||||
|
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, "https://github.com/actions", ars.Spec.GitHubConfigUrl)
|
||||||
|
}
|
||||||
@@ -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
|
||||||
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
|
||||||
@@ -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,13 +44,37 @@ 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/
|
||||||
|
|
||||||
## template is the PodSpec for each runner Pod
|
## template is the PodSpec for each runner Pod
|
||||||
template:
|
template:
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: runner
|
- name: runner
|
||||||
image: ghcr.io/actions/actions-runner:latest
|
image: ghcr.io/actions/actions-runner:latest
|
||||||
command: ["/actions-runner/run.sh"]
|
command: ["/home/runner/run.sh"]
|
||||||
|
|
||||||
containerMode:
|
containerMode:
|
||||||
type: "" ## type can be set to dind or kubernetes
|
type: "" ## type can be set to dind or kubernetes
|
||||||
@@ -60,10 +84,10 @@ containerMode:
|
|||||||
## initContainers:
|
## initContainers:
|
||||||
## - name: initExternalsInternalVolume
|
## - name: initExternalsInternalVolume
|
||||||
## 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: externalsInternal
|
||||||
## 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
|
||||||
@@ -76,7 +100,7 @@ containerMode:
|
|||||||
## value: /certs/client
|
## value: /certs/client
|
||||||
## volumeMounts:
|
## volumeMounts:
|
||||||
## - name: workingDirectoryInternal
|
## - name: workingDirectoryInternal
|
||||||
## mountPath: /actions-runner/_work
|
## mountPath: /home/runner/_work
|
||||||
## - name: dinDInternal
|
## - name: dinDInternal
|
||||||
## mountPath: /certs/client
|
## mountPath: /certs/client
|
||||||
## readOnly: true
|
## readOnly: true
|
||||||
@@ -87,9 +111,9 @@ containerMode:
|
|||||||
## volumeMounts:
|
## volumeMounts:
|
||||||
## - mountPath: /certs/client
|
## - mountPath: /certs/client
|
||||||
## name: dinDInternal
|
## name: dinDInternal
|
||||||
## - mountPath: /actions-runner/_work
|
## - mountPath: /home/runner/_work
|
||||||
## name: workingDirectoryInternal
|
## name: workingDirectoryInternal
|
||||||
## - mountPath: /actions-runner/externals
|
## - mountPath: /home/runner/externals
|
||||||
## name: externalsInternal
|
## name: externalsInternal
|
||||||
## volumes:
|
## volumes:
|
||||||
## - name: dinDInternal
|
## - name: dinDInternal
|
||||||
@@ -107,7 +131,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 +140,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:
|
||||||
@@ -136,4 +160,4 @@ containerMode:
|
|||||||
storageClassName: "dynamic-blob-storage"
|
storageClassName: "dynamic-blob-storage"
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: 1Gi
|
storage: 1Gi
|
||||||
@@ -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, "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()
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -51,9 +51,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 +102,8 @@ spec:
|
|||||||
type: object
|
type: object
|
||||||
runnerGroup:
|
runnerGroup:
|
||||||
type: string
|
type: string
|
||||||
|
runnerScaleSetName:
|
||||||
|
type: string
|
||||||
template:
|
template:
|
||||||
description: Required
|
description: Required
|
||||||
properties:
|
properties:
|
||||||
|
|||||||
@@ -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'
|
||||||
|
|||||||
@@ -46,9 +46,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'
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ func (r *AutoscalingListenerReconciler) Reconcile(ctx context.Context, req ctrl.
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.Info("Successfully removed finalizer after cleanup")
|
log.Info("Successfully removed finalizer after cleanup")
|
||||||
|
return ctrl.Result{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if !controllerutil.ContainsFinalizer(autoscalingListener, autoscalingListenerFinalizerName) {
|
if !controllerutil.ContainsFinalizer(autoscalingListener, autoscalingListenerFinalizerName) {
|
||||||
@@ -422,6 +423,15 @@ func (r *AutoscalingListenerReconciler) createListenerPod(ctx context.Context, a
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if autoscalingListener.Spec.GitHubServerTLS != nil {
|
||||||
|
env, err := r.certificateEnvVarForListener(ctx, autoscalingRunnerSet, autoscalingListener)
|
||||||
|
if err != nil {
|
||||||
|
return ctrl.Result{}, fmt.Errorf("failed to create certificate env var for listener: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
envs = append(envs, env)
|
||||||
|
}
|
||||||
|
|
||||||
newPod := r.resourceBuilder.newScaleSetListenerPod(autoscalingListener, serviceAccount, secret, envs...)
|
newPod := r.resourceBuilder.newScaleSetListenerPod(autoscalingListener, serviceAccount, secret, envs...)
|
||||||
|
|
||||||
if err := ctrl.SetControllerReference(autoscalingListener, newPod, r.Scheme); err != nil {
|
if err := ctrl.SetControllerReference(autoscalingListener, newPod, r.Scheme); err != nil {
|
||||||
@@ -438,6 +448,47 @@ func (r *AutoscalingListenerReconciler) createListenerPod(ctx context.Context, a
|
|||||||
return ctrl.Result{}, nil
|
return ctrl.Result{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *AutoscalingListenerReconciler) certificateEnvVarForListener(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, autoscalingListener *v1alpha1.AutoscalingListener) (corev1.EnvVar, error) {
|
||||||
|
if autoscalingListener.Spec.GitHubServerTLS.CertificateFrom == nil {
|
||||||
|
return corev1.EnvVar{}, fmt.Errorf("githubServerTLS.certificateFrom is not specified")
|
||||||
|
}
|
||||||
|
|
||||||
|
if autoscalingListener.Spec.GitHubServerTLS.CertificateFrom.ConfigMapKeyRef == nil {
|
||||||
|
return corev1.EnvVar{}, fmt.Errorf("githubServerTLS.certificateFrom.configMapKeyRef is not specified")
|
||||||
|
}
|
||||||
|
|
||||||
|
var configmap corev1.ConfigMap
|
||||||
|
err := r.Get(
|
||||||
|
ctx,
|
||||||
|
types.NamespacedName{
|
||||||
|
Namespace: autoscalingRunnerSet.Namespace,
|
||||||
|
Name: autoscalingListener.Spec.GitHubServerTLS.CertificateFrom.ConfigMapKeyRef.Name,
|
||||||
|
},
|
||||||
|
&configmap,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return corev1.EnvVar{}, fmt.Errorf(
|
||||||
|
"failed to get configmap %s: %w",
|
||||||
|
autoscalingListener.Spec.GitHubServerTLS.CertificateFrom.ConfigMapKeyRef.Name,
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
certificate, ok := configmap.Data[autoscalingListener.Spec.GitHubServerTLS.CertificateFrom.ConfigMapKeyRef.Key]
|
||||||
|
if !ok {
|
||||||
|
return corev1.EnvVar{}, fmt.Errorf(
|
||||||
|
"key %s is not found in configmap %s",
|
||||||
|
autoscalingListener.Spec.GitHubServerTLS.CertificateFrom.ConfigMapKeyRef.Key,
|
||||||
|
autoscalingListener.Spec.GitHubServerTLS.CertificateFrom.ConfigMapKeyRef.Name,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return corev1.EnvVar{
|
||||||
|
Name: "GITHUB_SERVER_ROOT_CA",
|
||||||
|
Value: certificate,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *AutoscalingListenerReconciler) createSecretsForListener(ctx context.Context, autoscalingListener *v1alpha1.AutoscalingListener, secret *corev1.Secret, logger logr.Logger) (ctrl.Result, error) {
|
func (r *AutoscalingListenerReconciler) createSecretsForListener(ctx context.Context, autoscalingListener *v1alpha1.AutoscalingListener, secret *corev1.Secret, logger logr.Logger) (ctrl.Result, error) {
|
||||||
newListenerSecret := r.resourceBuilder.newScaleSetListenerSecretMirror(autoscalingListener, secret)
|
newListenerSecret := r.resourceBuilder.newScaleSetListenerSecretMirror(autoscalingListener, secret)
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package actionsgithubcom
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
@@ -28,46 +30,23 @@ const (
|
|||||||
|
|
||||||
var _ = Describe("Test AutoScalingListener controller", func() {
|
var _ = Describe("Test AutoScalingListener controller", func() {
|
||||||
var ctx context.Context
|
var ctx context.Context
|
||||||
var cancel context.CancelFunc
|
var mgr ctrl.Manager
|
||||||
autoscalingNS := new(corev1.Namespace)
|
var autoscalingNS *corev1.Namespace
|
||||||
autoscalingRunnerSet := new(actionsv1alpha1.AutoscalingRunnerSet)
|
var autoscalingRunnerSet *actionsv1alpha1.AutoscalingRunnerSet
|
||||||
configSecret := new(corev1.Secret)
|
var configSecret *corev1.Secret
|
||||||
autoscalingListener := new(actionsv1alpha1.AutoscalingListener)
|
var autoscalingListener *actionsv1alpha1.AutoscalingListener
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
ctx, cancel = context.WithCancel(context.TODO())
|
ctx = context.Background()
|
||||||
autoscalingNS = &corev1.Namespace{
|
autoscalingNS, mgr = createNamespace(GinkgoT(), k8sClient)
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "testns-autoscaling-listener" + RandStringRunes(5)},
|
configSecret = createDefaultSecret(GinkgoT(), k8sClient, autoscalingNS.Name)
|
||||||
}
|
|
||||||
|
|
||||||
err := k8sClient.Create(ctx, autoscalingNS)
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to create test namespace for AutoScalingRunnerSet")
|
|
||||||
|
|
||||||
configSecret = &corev1.Secret{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "github-config-secret",
|
|
||||||
Namespace: autoscalingNS.Name,
|
|
||||||
},
|
|
||||||
Data: map[string][]byte{
|
|
||||||
"github_token": []byte(autoscalingListenerTestGitHubToken),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
err = k8sClient.Create(ctx, configSecret)
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to create config secret")
|
|
||||||
|
|
||||||
mgr, err := ctrl.NewManager(cfg, ctrl.Options{
|
|
||||||
Namespace: autoscalingNS.Name,
|
|
||||||
MetricsBindAddress: "0",
|
|
||||||
})
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to create manager")
|
|
||||||
|
|
||||||
controller := &AutoscalingListenerReconciler{
|
controller := &AutoscalingListenerReconciler{
|
||||||
Client: mgr.GetClient(),
|
Client: mgr.GetClient(),
|
||||||
Scheme: mgr.GetScheme(),
|
Scheme: mgr.GetScheme(),
|
||||||
Log: logf.Log,
|
Log: logf.Log,
|
||||||
}
|
}
|
||||||
err = controller.SetupWithManager(mgr)
|
err := controller.SetupWithManager(mgr)
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to setup controller")
|
Expect(err).NotTo(HaveOccurred(), "failed to setup controller")
|
||||||
|
|
||||||
min := 1
|
min := 1
|
||||||
@@ -119,19 +98,7 @@ var _ = Describe("Test AutoScalingListener controller", func() {
|
|||||||
err = k8sClient.Create(ctx, autoscalingListener)
|
err = k8sClient.Create(ctx, autoscalingListener)
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to create AutoScalingListener")
|
Expect(err).NotTo(HaveOccurred(), "failed to create AutoScalingListener")
|
||||||
|
|
||||||
go func() {
|
startManagers(GinkgoT(), mgr)
|
||||||
defer GinkgoRecover()
|
|
||||||
|
|
||||||
err := mgr.Start(ctx)
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to start manager")
|
|
||||||
}()
|
|
||||||
})
|
|
||||||
|
|
||||||
AfterEach(func() {
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
err := k8sClient.Delete(ctx, autoscalingNS)
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to delete test namespace for AutoScalingRunnerSet")
|
|
||||||
})
|
})
|
||||||
|
|
||||||
Context("When creating a new AutoScalingListener", func() {
|
Context("When creating a new AutoScalingListener", func() {
|
||||||
@@ -396,11 +363,11 @@ var _ = Describe("Test AutoScalingListener controller", func() {
|
|||||||
|
|
||||||
var _ = Describe("Test AutoScalingListener controller with proxy", func() {
|
var _ = Describe("Test AutoScalingListener controller with proxy", func() {
|
||||||
var ctx context.Context
|
var ctx context.Context
|
||||||
var cancel context.CancelFunc
|
var mgr ctrl.Manager
|
||||||
autoscalingNS := new(corev1.Namespace)
|
var autoscalingNS *corev1.Namespace
|
||||||
autoscalingRunnerSet := new(actionsv1alpha1.AutoscalingRunnerSet)
|
var autoscalingRunnerSet *actionsv1alpha1.AutoscalingRunnerSet
|
||||||
configSecret := new(corev1.Secret)
|
var configSecret *corev1.Secret
|
||||||
autoscalingListener := new(actionsv1alpha1.AutoscalingListener)
|
var autoscalingListener *actionsv1alpha1.AutoscalingListener
|
||||||
|
|
||||||
createRunnerSetAndListener := func(proxy *actionsv1alpha1.ProxyConfig) {
|
createRunnerSetAndListener := func(proxy *actionsv1alpha1.ProxyConfig) {
|
||||||
min := 1
|
min := 1
|
||||||
@@ -456,54 +423,19 @@ var _ = Describe("Test AutoScalingListener controller with proxy", func() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
ctx, cancel = context.WithCancel(context.TODO())
|
ctx = context.Background()
|
||||||
autoscalingNS = &corev1.Namespace{
|
autoscalingNS, mgr = createNamespace(GinkgoT(), k8sClient)
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "testns-autoscaling-listener" + RandStringRunes(5)},
|
configSecret = createDefaultSecret(GinkgoT(), k8sClient, autoscalingNS.Name)
|
||||||
}
|
|
||||||
|
|
||||||
err := k8sClient.Create(ctx, autoscalingNS)
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to create test namespace for AutoScalingRunnerSet")
|
|
||||||
|
|
||||||
configSecret = &corev1.Secret{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "github-config-secret",
|
|
||||||
Namespace: autoscalingNS.Name,
|
|
||||||
},
|
|
||||||
Data: map[string][]byte{
|
|
||||||
"github_token": []byte(autoscalingListenerTestGitHubToken),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
err = k8sClient.Create(ctx, configSecret)
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to create config secret")
|
|
||||||
|
|
||||||
mgr, err := ctrl.NewManager(cfg, ctrl.Options{
|
|
||||||
Namespace: autoscalingNS.Name,
|
|
||||||
MetricsBindAddress: "0",
|
|
||||||
})
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to create manager")
|
|
||||||
|
|
||||||
controller := &AutoscalingListenerReconciler{
|
controller := &AutoscalingListenerReconciler{
|
||||||
Client: mgr.GetClient(),
|
Client: mgr.GetClient(),
|
||||||
Scheme: mgr.GetScheme(),
|
Scheme: mgr.GetScheme(),
|
||||||
Log: logf.Log,
|
Log: logf.Log,
|
||||||
}
|
}
|
||||||
err = controller.SetupWithManager(mgr)
|
err := controller.SetupWithManager(mgr)
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to setup controller")
|
Expect(err).NotTo(HaveOccurred(), "failed to setup controller")
|
||||||
|
|
||||||
go func() {
|
startManagers(GinkgoT(), mgr)
|
||||||
defer GinkgoRecover()
|
|
||||||
|
|
||||||
err := mgr.Start(ctx)
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to start manager")
|
|
||||||
}()
|
|
||||||
})
|
|
||||||
|
|
||||||
AfterEach(func() {
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
err := k8sClient.Delete(ctx, autoscalingNS)
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to delete test namespace for AutoScalingRunnerSet")
|
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should create a secret in the listener namespace containing proxy details, use it to populate env vars on the pod and should delete it as part of cleanup", func() {
|
It("should create a secret in the listener namespace containing proxy details, use it to populate env vars on the pod and should delete it as part of cleanup", func() {
|
||||||
@@ -624,3 +556,165 @@ var _ = Describe("Test AutoScalingListener controller with proxy", func() {
|
|||||||
autoscalingListenerTestInterval).Should(Succeed(), "failed to delete secret with proxy details")
|
autoscalingListenerTestInterval).Should(Succeed(), "failed to delete secret with proxy details")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
var _ = Describe("Test GitHub Server TLS configuration", func() {
|
||||||
|
var ctx context.Context
|
||||||
|
var mgr ctrl.Manager
|
||||||
|
var autoscalingNS *corev1.Namespace
|
||||||
|
var autoscalingRunnerSet *actionsv1alpha1.AutoscalingRunnerSet
|
||||||
|
var configSecret *corev1.Secret
|
||||||
|
var autoscalingListener *actionsv1alpha1.AutoscalingListener
|
||||||
|
var rootCAConfigMap *corev1.ConfigMap
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
ctx = context.Background()
|
||||||
|
autoscalingNS, mgr = createNamespace(GinkgoT(), k8sClient)
|
||||||
|
configSecret = createDefaultSecret(GinkgoT(), k8sClient, autoscalingNS.Name)
|
||||||
|
|
||||||
|
cert, err := os.ReadFile(filepath.Join(
|
||||||
|
"../../",
|
||||||
|
"github",
|
||||||
|
"actions",
|
||||||
|
"testdata",
|
||||||
|
"rootCA.crt",
|
||||||
|
))
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "failed to read root CA cert")
|
||||||
|
rootCAConfigMap = &corev1.ConfigMap{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "root-ca-configmap",
|
||||||
|
Namespace: autoscalingNS.Name,
|
||||||
|
},
|
||||||
|
Data: map[string]string{
|
||||||
|
"rootCA.crt": string(cert),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
err = k8sClient.Create(ctx, rootCAConfigMap)
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "failed to create configmap with root CAs")
|
||||||
|
|
||||||
|
controller := &AutoscalingListenerReconciler{
|
||||||
|
Client: mgr.GetClient(),
|
||||||
|
Scheme: mgr.GetScheme(),
|
||||||
|
Log: logf.Log,
|
||||||
|
}
|
||||||
|
err = controller.SetupWithManager(mgr)
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "failed to setup controller")
|
||||||
|
|
||||||
|
min := 1
|
||||||
|
max := 10
|
||||||
|
autoscalingRunnerSet = &actionsv1alpha1.AutoscalingRunnerSet{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "test-asrs",
|
||||||
|
Namespace: autoscalingNS.Name,
|
||||||
|
},
|
||||||
|
Spec: actionsv1alpha1.AutoscalingRunnerSetSpec{
|
||||||
|
GitHubConfigUrl: "https://github.com/owner/repo",
|
||||||
|
GitHubConfigSecret: configSecret.Name,
|
||||||
|
GitHubServerTLS: &actionsv1alpha1.GitHubServerTLSConfig{
|
||||||
|
CertificateFrom: &actionsv1alpha1.TLSCertificateSource{
|
||||||
|
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
|
||||||
|
LocalObjectReference: corev1.LocalObjectReference{
|
||||||
|
Name: rootCAConfigMap.Name,
|
||||||
|
},
|
||||||
|
Key: "rootCA.crt",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MaxRunners: &max,
|
||||||
|
MinRunners: &min,
|
||||||
|
Template: corev1.PodTemplateSpec{
|
||||||
|
Spec: corev1.PodSpec{
|
||||||
|
Containers: []corev1.Container{
|
||||||
|
{
|
||||||
|
Name: "runner",
|
||||||
|
Image: "ghcr.io/actions/runner",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
err = k8sClient.Create(ctx, autoscalingRunnerSet)
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "failed to create AutoScalingRunnerSet")
|
||||||
|
|
||||||
|
autoscalingListener = &actionsv1alpha1.AutoscalingListener{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "test-asl",
|
||||||
|
Namespace: autoscalingNS.Name,
|
||||||
|
},
|
||||||
|
Spec: actionsv1alpha1.AutoscalingListenerSpec{
|
||||||
|
GitHubConfigUrl: "https://github.com/owner/repo",
|
||||||
|
GitHubConfigSecret: configSecret.Name,
|
||||||
|
GitHubServerTLS: &actionsv1alpha1.GitHubServerTLSConfig{
|
||||||
|
CertificateFrom: &actionsv1alpha1.TLSCertificateSource{
|
||||||
|
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
|
||||||
|
LocalObjectReference: corev1.LocalObjectReference{
|
||||||
|
Name: rootCAConfigMap.Name,
|
||||||
|
},
|
||||||
|
Key: "rootCA.crt",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
RunnerScaleSetId: 1,
|
||||||
|
AutoscalingRunnerSetNamespace: autoscalingRunnerSet.Namespace,
|
||||||
|
AutoscalingRunnerSetName: autoscalingRunnerSet.Name,
|
||||||
|
EphemeralRunnerSetName: "test-ers",
|
||||||
|
MaxRunners: 10,
|
||||||
|
MinRunners: 1,
|
||||||
|
Image: "ghcr.io/owner/repo",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
err = k8sClient.Create(ctx, autoscalingListener)
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "failed to create AutoScalingListener")
|
||||||
|
|
||||||
|
startManagers(GinkgoT(), mgr)
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("When creating a new AutoScalingListener", func() {
|
||||||
|
It("It should set the certificates as an environment variable on the pod", func() {
|
||||||
|
pod := new(corev1.Pod)
|
||||||
|
Eventually(
|
||||||
|
func(g Gomega) {
|
||||||
|
err := k8sClient.Get(
|
||||||
|
ctx,
|
||||||
|
client.ObjectKey{
|
||||||
|
Name: autoscalingListener.Name,
|
||||||
|
Namespace: autoscalingListener.Namespace,
|
||||||
|
},
|
||||||
|
pod,
|
||||||
|
)
|
||||||
|
|
||||||
|
g.Expect(err).NotTo(HaveOccurred(), "failed to get pod")
|
||||||
|
g.Expect(pod.Spec.Containers).NotTo(BeEmpty(), "pod should have containers")
|
||||||
|
g.Expect(pod.Spec.Containers[0].Env).NotTo(BeEmpty(), "pod should have env variables")
|
||||||
|
|
||||||
|
var env *corev1.EnvVar
|
||||||
|
for _, e := range pod.Spec.Containers[0].Env {
|
||||||
|
if e.Name == "GITHUB_SERVER_ROOT_CA" {
|
||||||
|
env = &e
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g.Expect(env).NotTo(BeNil(), "pod should have an env variable named GITHUB_SERVER_ROOT_CA_PATH")
|
||||||
|
|
||||||
|
cert, err := os.ReadFile(filepath.Join(
|
||||||
|
"../../",
|
||||||
|
"github",
|
||||||
|
"actions",
|
||||||
|
"testdata",
|
||||||
|
"rootCA.crt",
|
||||||
|
))
|
||||||
|
g.Expect(err).NotTo(HaveOccurred(), "failed to read rootCA.crt")
|
||||||
|
|
||||||
|
g.Expect(env.Value).To(
|
||||||
|
BeEquivalentTo(string(cert)),
|
||||||
|
"GITHUB_SERVER_ROOT_CA should be the rootCA.crt",
|
||||||
|
)
|
||||||
|
}).
|
||||||
|
WithTimeout(autoscalingRunnerSetTestTimeout).
|
||||||
|
WithPolling(autoscalingListenerTestInterval).
|
||||||
|
Should(Succeed(), "failed to create pod with volume and env variable")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|||||||
@@ -44,14 +44,10 @@ const (
|
|||||||
// TODO: Replace with shared image.
|
// TODO: Replace with shared image.
|
||||||
autoscalingRunnerSetOwnerKey = ".metadata.controller"
|
autoscalingRunnerSetOwnerKey = ".metadata.controller"
|
||||||
LabelKeyRunnerSpecHash = "runner-spec-hash"
|
LabelKeyRunnerSpecHash = "runner-spec-hash"
|
||||||
LabelKeyAutoScaleRunnerSetName = "auto-scale-runner-set-name"
|
|
||||||
autoscalingRunnerSetFinalizerName = "autoscalingrunnerset.actions.github.com/finalizer"
|
autoscalingRunnerSetFinalizerName = "autoscalingrunnerset.actions.github.com/finalizer"
|
||||||
runnerScaleSetIdKey = "runner-scale-set-id"
|
runnerScaleSetIdKey = "runner-scale-set-id"
|
||||||
|
runnerScaleSetNameKey = "runner-scale-set-name"
|
||||||
runnerScaleSetRunnerGroupNameKey = "runner-scale-set-runner-group-name"
|
runnerScaleSetRunnerGroupNameKey = "runner-scale-set-runner-group-name"
|
||||||
|
|
||||||
// scaleSetListenerLabel is the key of pod.meta.labels to label
|
|
||||||
// that the pod is a listener application
|
|
||||||
scaleSetListenerLabel = "runner-scale-set-listener"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// AutoscalingRunnerSetReconciler reconciles a AutoscalingRunnerSet object
|
// AutoscalingRunnerSetReconciler reconciles a AutoscalingRunnerSet object
|
||||||
@@ -128,6 +124,7 @@ func (r *AutoscalingRunnerSetReconciler) Reconcile(ctx context.Context, req ctrl
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.Info("Successfully removed finalizer after cleanup")
|
log.Info("Successfully removed finalizer after cleanup")
|
||||||
|
return ctrl.Result{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if !controllerutil.ContainsFinalizer(autoscalingRunnerSet, autoscalingRunnerSetFinalizerName) {
|
if !controllerutil.ContainsFinalizer(autoscalingRunnerSet, autoscalingRunnerSetFinalizerName) {
|
||||||
@@ -163,6 +160,13 @@ func (r *AutoscalingRunnerSetReconciler) Reconcile(ctx context.Context, req ctrl
|
|||||||
return r.updateRunnerScaleSetRunnerGroup(ctx, autoscalingRunnerSet, log)
|
return r.updateRunnerScaleSetRunnerGroup(ctx, autoscalingRunnerSet, log)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure the runner scale set name is up to date
|
||||||
|
currentRunnerScaleSetName, ok := autoscalingRunnerSet.Annotations[runnerScaleSetNameKey]
|
||||||
|
if !ok || (len(autoscalingRunnerSet.Spec.RunnerScaleSetName) > 0 && !strings.EqualFold(currentRunnerScaleSetName, autoscalingRunnerSet.Spec.RunnerScaleSetName)) {
|
||||||
|
log.Info("AutoScalingRunnerSet runner scale set name changed. Updating the runner scale set.")
|
||||||
|
return r.updateRunnerScaleSetName(ctx, autoscalingRunnerSet, log)
|
||||||
|
}
|
||||||
|
|
||||||
secret := new(corev1.Secret)
|
secret := new(corev1.Secret)
|
||||||
if err := r.Get(ctx, types.NamespacedName{Namespace: autoscalingRunnerSet.Namespace, Name: autoscalingRunnerSet.Spec.GitHubConfigSecret}, secret); err != nil {
|
if err := r.Get(ctx, types.NamespacedName{Namespace: autoscalingRunnerSet.Namespace, Name: autoscalingRunnerSet.Spec.GitHubConfigSecret}, secret); err != nil {
|
||||||
log.Error(err, "Failed to find GitHub config secret.",
|
log.Error(err, "Failed to find GitHub config secret.",
|
||||||
@@ -302,11 +306,14 @@ func (r *AutoscalingRunnerSetReconciler) deleteEphemeralRunnerSets(ctx context.C
|
|||||||
func (r *AutoscalingRunnerSetReconciler) createRunnerScaleSet(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, logger logr.Logger) (ctrl.Result, error) {
|
func (r *AutoscalingRunnerSetReconciler) createRunnerScaleSet(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, logger logr.Logger) (ctrl.Result, error) {
|
||||||
logger.Info("Creating a new runner scale set")
|
logger.Info("Creating a new runner scale set")
|
||||||
actionsClient, err := r.actionsClientFor(ctx, autoscalingRunnerSet)
|
actionsClient, err := r.actionsClientFor(ctx, autoscalingRunnerSet)
|
||||||
|
if len(autoscalingRunnerSet.Spec.RunnerScaleSetName) == 0 {
|
||||||
|
autoscalingRunnerSet.Spec.RunnerScaleSetName = autoscalingRunnerSet.Name
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err, "Failed to initialize Actions service client for creating a new runner scale set")
|
logger.Error(err, "Failed to initialize Actions service client for creating a new runner scale set")
|
||||||
return ctrl.Result{}, err
|
return ctrl.Result{}, err
|
||||||
}
|
}
|
||||||
runnerScaleSet, err := actionsClient.GetRunnerScaleSet(ctx, autoscalingRunnerSet.Name)
|
runnerScaleSet, err := actionsClient.GetRunnerScaleSet(ctx, autoscalingRunnerSet.Spec.RunnerScaleSetName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err, "Failed to get runner scale set from Actions service")
|
logger.Error(err, "Failed to get runner scale set from Actions service")
|
||||||
return ctrl.Result{}, err
|
return ctrl.Result{}, err
|
||||||
@@ -327,11 +334,11 @@ func (r *AutoscalingRunnerSetReconciler) createRunnerScaleSet(ctx context.Contex
|
|||||||
runnerScaleSet, err = actionsClient.CreateRunnerScaleSet(
|
runnerScaleSet, err = actionsClient.CreateRunnerScaleSet(
|
||||||
ctx,
|
ctx,
|
||||||
&actions.RunnerScaleSet{
|
&actions.RunnerScaleSet{
|
||||||
Name: autoscalingRunnerSet.Name,
|
Name: autoscalingRunnerSet.Spec.RunnerScaleSetName,
|
||||||
RunnerGroupId: runnerGroupId,
|
RunnerGroupId: runnerGroupId,
|
||||||
Labels: []actions.Label{
|
Labels: []actions.Label{
|
||||||
{
|
{
|
||||||
Name: autoscalingRunnerSet.Name,
|
Name: autoscalingRunnerSet.Spec.RunnerScaleSetName,
|
||||||
Type: "System",
|
Type: "System",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -351,16 +358,20 @@ func (r *AutoscalingRunnerSetReconciler) createRunnerScaleSet(ctx context.Contex
|
|||||||
autoscalingRunnerSet.Annotations = map[string]string{}
|
autoscalingRunnerSet.Annotations = map[string]string{}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info("Adding runner scale set ID and runner group name as an annotation")
|
logger.Info("Adding runner scale set ID, name and runner group name as an annotation")
|
||||||
if err = patch(ctx, r.Client, autoscalingRunnerSet, func(obj *v1alpha1.AutoscalingRunnerSet) {
|
if err = patch(ctx, r.Client, autoscalingRunnerSet, func(obj *v1alpha1.AutoscalingRunnerSet) {
|
||||||
|
obj.Annotations[runnerScaleSetNameKey] = runnerScaleSet.Name
|
||||||
obj.Annotations[runnerScaleSetIdKey] = strconv.Itoa(runnerScaleSet.Id)
|
obj.Annotations[runnerScaleSetIdKey] = strconv.Itoa(runnerScaleSet.Id)
|
||||||
obj.Annotations[runnerScaleSetRunnerGroupNameKey] = runnerScaleSet.RunnerGroupName
|
obj.Annotations[runnerScaleSetRunnerGroupNameKey] = runnerScaleSet.RunnerGroupName
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
logger.Error(err, "Failed to add runner scale set ID and runner group name as an annotation")
|
logger.Error(err, "Failed to add runner scale set ID, name and runner group name as an annotation")
|
||||||
return ctrl.Result{}, err
|
return ctrl.Result{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info("Updated with runner scale set ID and runner group name as an annotation")
|
logger.Info("Updated with runner scale set ID, name and runner group name as an annotation",
|
||||||
|
"id", runnerScaleSet.Id,
|
||||||
|
"name", runnerScaleSet.Name,
|
||||||
|
"runnerGroupName", runnerScaleSet.RunnerGroupName)
|
||||||
return ctrl.Result{}, nil
|
return ctrl.Result{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -388,7 +399,7 @@ func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetRunnerGroup(ctx con
|
|||||||
runnerGroupId = int(runnerGroup.ID)
|
runnerGroupId = int(runnerGroup.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
updatedRunnerScaleSet, err := actionsClient.UpdateRunnerScaleSet(ctx, runnerScaleSetId, &actions.RunnerScaleSet{Name: autoscalingRunnerSet.Name, RunnerGroupId: runnerGroupId})
|
updatedRunnerScaleSet, err := actionsClient.UpdateRunnerScaleSet(ctx, runnerScaleSetId, &actions.RunnerScaleSet{RunnerGroupId: runnerGroupId})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(err, "Failed to update runner scale set", "runnerScaleSetId", runnerScaleSetId)
|
logger.Error(err, "Failed to update runner scale set", "runnerScaleSetId", runnerScaleSetId)
|
||||||
return ctrl.Result{}, err
|
return ctrl.Result{}, err
|
||||||
@@ -406,6 +417,42 @@ func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetRunnerGroup(ctx con
|
|||||||
return ctrl.Result{}, nil
|
return ctrl.Result{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetName(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, logger logr.Logger) (ctrl.Result, error) {
|
||||||
|
runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdKey])
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(err, "Failed to parse runner scale set ID")
|
||||||
|
return ctrl.Result{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(autoscalingRunnerSet.Spec.RunnerScaleSetName) == 0 {
|
||||||
|
logger.Info("Runner scale set name is not specified, skipping")
|
||||||
|
return ctrl.Result{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
actionsClient, err := r.actionsClientFor(ctx, autoscalingRunnerSet)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(err, "Failed to initialize Actions service client for updating a existing runner scale set")
|
||||||
|
return ctrl.Result{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
updatedRunnerScaleSet, err := actionsClient.UpdateRunnerScaleSet(ctx, runnerScaleSetId, &actions.RunnerScaleSet{Name: autoscalingRunnerSet.Spec.RunnerScaleSetName})
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(err, "Failed to update runner scale set", "runnerScaleSetId", runnerScaleSetId)
|
||||||
|
return ctrl.Result{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("Updating runner scale set name as an annotation")
|
||||||
|
if err := patch(ctx, r.Client, autoscalingRunnerSet, func(obj *v1alpha1.AutoscalingRunnerSet) {
|
||||||
|
obj.Annotations[runnerScaleSetNameKey] = updatedRunnerScaleSet.Name
|
||||||
|
}); err != nil {
|
||||||
|
logger.Error(err, "Failed to update runner scale set name annotation")
|
||||||
|
return ctrl.Result{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("Updated runner scale set with match name", "name", updatedRunnerScaleSet.Name)
|
||||||
|
return ctrl.Result{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *AutoscalingRunnerSetReconciler) deleteRunnerScaleSet(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, logger logr.Logger) error {
|
func (r *AutoscalingRunnerSetReconciler) deleteRunnerScaleSet(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, logger logr.Logger) error {
|
||||||
logger.Info("Deleting the runner scale set from Actions service")
|
logger.Info("Deleting the runner scale set from Actions service")
|
||||||
runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdKey])
|
runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdKey])
|
||||||
@@ -494,7 +541,23 @@ func (r *AutoscalingRunnerSetReconciler) actionsClientFor(ctx context.Context, a
|
|||||||
return nil, fmt.Errorf("failed to find GitHub config secret: %w", err)
|
return nil, fmt.Errorf("failed to find GitHub config secret: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var opts []actions.ClientOption
|
opts, err := r.actionsClientOptionsFor(ctx, autoscalingRunnerSet)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get actions client options: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.ActionsClient.GetClientFromSecret(
|
||||||
|
ctx,
|
||||||
|
autoscalingRunnerSet.Spec.GitHubConfigUrl,
|
||||||
|
autoscalingRunnerSet.Namespace,
|
||||||
|
configSecret.Data,
|
||||||
|
opts...,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *AutoscalingRunnerSetReconciler) actionsClientOptionsFor(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet) ([]actions.ClientOption, error) {
|
||||||
|
var options []actions.ClientOption
|
||||||
|
|
||||||
if autoscalingRunnerSet.Spec.Proxy != nil {
|
if autoscalingRunnerSet.Spec.Proxy != nil {
|
||||||
proxyFunc, err := autoscalingRunnerSet.Spec.Proxy.ProxyFunc(func(s string) (*corev1.Secret, error) {
|
proxyFunc, err := autoscalingRunnerSet.Spec.Proxy.ProxyFunc(func(s string) (*corev1.Secret, error) {
|
||||||
var secret corev1.Secret
|
var secret corev1.Secret
|
||||||
@@ -509,16 +572,35 @@ func (r *AutoscalingRunnerSetReconciler) actionsClientFor(ctx context.Context, a
|
|||||||
return nil, fmt.Errorf("failed to get proxy func: %w", err)
|
return nil, fmt.Errorf("failed to get proxy func: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
opts = append(opts, actions.WithProxy(proxyFunc))
|
options = append(options, actions.WithProxy(proxyFunc))
|
||||||
}
|
}
|
||||||
|
|
||||||
return r.ActionsClient.GetClientFromSecret(
|
tlsConfig := autoscalingRunnerSet.Spec.GitHubServerTLS
|
||||||
ctx,
|
if tlsConfig != nil {
|
||||||
autoscalingRunnerSet.Spec.GitHubConfigUrl,
|
pool, err := tlsConfig.ToCertPool(func(name, key string) ([]byte, error) {
|
||||||
autoscalingRunnerSet.Namespace,
|
var configmap corev1.ConfigMap
|
||||||
configSecret.Data,
|
err := r.Get(
|
||||||
opts...,
|
ctx,
|
||||||
)
|
types.NamespacedName{
|
||||||
|
Namespace: autoscalingRunnerSet.Namespace,
|
||||||
|
Name: name,
|
||||||
|
},
|
||||||
|
&configmap,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get configmap %s: %w", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return []byte(configmap.Data[key]), nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get tls config: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
options = append(options, actions.WithRootCAs(pool))
|
||||||
|
}
|
||||||
|
|
||||||
|
return options, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetupWithManager sets up the controller with the Manager.
|
// SetupWithManager sets up the controller with the Manager.
|
||||||
|
|||||||
@@ -2,10 +2,13 @@ package actionsgithubcom
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -35,38 +38,15 @@ const (
|
|||||||
|
|
||||||
var _ = Describe("Test AutoScalingRunnerSet controller", func() {
|
var _ = Describe("Test AutoScalingRunnerSet controller", func() {
|
||||||
var ctx context.Context
|
var ctx context.Context
|
||||||
var cancel context.CancelFunc
|
var mgr ctrl.Manager
|
||||||
autoscalingNS := new(corev1.Namespace)
|
var autoscalingNS *corev1.Namespace
|
||||||
autoscalingRunnerSet := new(v1alpha1.AutoscalingRunnerSet)
|
var autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet
|
||||||
configSecret := new(corev1.Secret)
|
var configSecret *corev1.Secret
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
ctx, cancel = context.WithCancel(context.TODO())
|
ctx = context.Background()
|
||||||
autoscalingNS = &corev1.Namespace{
|
autoscalingNS, mgr = createNamespace(GinkgoT(), k8sClient)
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "testns-autoscaling" + RandStringRunes(5)},
|
configSecret = createDefaultSecret(GinkgoT(), k8sClient, autoscalingNS.Name)
|
||||||
}
|
|
||||||
|
|
||||||
err := k8sClient.Create(ctx, autoscalingNS)
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to create test namespace for AutoScalingRunnerSet")
|
|
||||||
|
|
||||||
configSecret = &corev1.Secret{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "github-config-secret",
|
|
||||||
Namespace: autoscalingNS.Name,
|
|
||||||
},
|
|
||||||
Data: map[string][]byte{
|
|
||||||
"github_token": []byte(autoscalingRunnerSetTestGitHubToken),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
err = k8sClient.Create(ctx, configSecret)
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to create config secret")
|
|
||||||
|
|
||||||
mgr, err := ctrl.NewManager(cfg, ctrl.Options{
|
|
||||||
Namespace: autoscalingNS.Name,
|
|
||||||
MetricsBindAddress: "0",
|
|
||||||
})
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to create manager")
|
|
||||||
|
|
||||||
controller := &AutoscalingRunnerSetReconciler{
|
controller := &AutoscalingRunnerSetReconciler{
|
||||||
Client: mgr.GetClient(),
|
Client: mgr.GetClient(),
|
||||||
@@ -76,7 +56,7 @@ var _ = Describe("Test AutoScalingRunnerSet controller", func() {
|
|||||||
DefaultRunnerScaleSetListenerImage: "ghcr.io/actions/arc",
|
DefaultRunnerScaleSetListenerImage: "ghcr.io/actions/arc",
|
||||||
ActionsClient: fake.NewMultiClient(),
|
ActionsClient: fake.NewMultiClient(),
|
||||||
}
|
}
|
||||||
err = controller.SetupWithManager(mgr)
|
err := controller.SetupWithManager(mgr)
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to setup controller")
|
Expect(err).NotTo(HaveOccurred(), "failed to setup controller")
|
||||||
|
|
||||||
min := 1
|
min := 1
|
||||||
@@ -108,19 +88,7 @@ var _ = Describe("Test AutoScalingRunnerSet controller", func() {
|
|||||||
err = k8sClient.Create(ctx, autoscalingRunnerSet)
|
err = k8sClient.Create(ctx, autoscalingRunnerSet)
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to create AutoScalingRunnerSet")
|
Expect(err).NotTo(HaveOccurred(), "failed to create AutoScalingRunnerSet")
|
||||||
|
|
||||||
go func() {
|
startManagers(GinkgoT(), mgr)
|
||||||
defer GinkgoRecover()
|
|
||||||
|
|
||||||
err := mgr.Start(ctx)
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to start manager")
|
|
||||||
}()
|
|
||||||
})
|
|
||||||
|
|
||||||
AfterEach(func() {
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
err := k8sClient.Delete(ctx, autoscalingNS)
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to delete test namespace for AutoScalingRunnerSet")
|
|
||||||
})
|
})
|
||||||
|
|
||||||
Context("When creating a new AutoScalingRunnerSet", func() {
|
Context("When creating a new AutoScalingRunnerSet", func() {
|
||||||
@@ -435,39 +403,138 @@ var _ = Describe("Test AutoScalingRunnerSet controller", func() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
var _ = Describe("Test AutoScalingController updates", func() {
|
||||||
|
Context("Creating autoscaling runner set with RunnerScaleSetName set", func() {
|
||||||
|
var ctx context.Context
|
||||||
|
var mgr ctrl.Manager
|
||||||
|
var autoscalingNS *corev1.Namespace
|
||||||
|
var autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet
|
||||||
|
var configSecret *corev1.Secret
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
ctx = context.Background()
|
||||||
|
autoscalingNS, mgr = createNamespace(GinkgoT(), k8sClient)
|
||||||
|
configSecret = createDefaultSecret(GinkgoT(), k8sClient, autoscalingNS.Name)
|
||||||
|
|
||||||
|
controller := &AutoscalingRunnerSetReconciler{
|
||||||
|
Client: mgr.GetClient(),
|
||||||
|
Scheme: mgr.GetScheme(),
|
||||||
|
Log: logf.Log,
|
||||||
|
ControllerNamespace: autoscalingNS.Name,
|
||||||
|
DefaultRunnerScaleSetListenerImage: "ghcr.io/actions/arc",
|
||||||
|
ActionsClient: fake.NewMultiClient(
|
||||||
|
fake.WithDefaultClient(
|
||||||
|
fake.NewFakeClient(
|
||||||
|
fake.WithUpdateRunnerScaleSet(
|
||||||
|
&actions.RunnerScaleSet{
|
||||||
|
Id: 1,
|
||||||
|
Name: "testset_update",
|
||||||
|
RunnerGroupId: 1,
|
||||||
|
RunnerGroupName: "testgroup",
|
||||||
|
Labels: []actions.Label{{Type: "test", Name: "test"}},
|
||||||
|
RunnerSetting: actions.RunnerSetting{},
|
||||||
|
CreatedOn: time.Now(),
|
||||||
|
RunnerJitConfigUrl: "test.test.test",
|
||||||
|
Statistics: nil,
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
nil,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
err := controller.SetupWithManager(mgr)
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "failed to setup controller")
|
||||||
|
|
||||||
|
startManagers(GinkgoT(), mgr)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("It should be create AutoScalingRunnerSet and has annotation for the RunnerScaleSetName", func() {
|
||||||
|
min := 1
|
||||||
|
max := 10
|
||||||
|
autoscalingRunnerSet = &v1alpha1.AutoscalingRunnerSet{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "test-asrs",
|
||||||
|
Namespace: autoscalingNS.Name,
|
||||||
|
},
|
||||||
|
Spec: v1alpha1.AutoscalingRunnerSetSpec{
|
||||||
|
GitHubConfigUrl: "https://github.com/owner/repo",
|
||||||
|
GitHubConfigSecret: configSecret.Name,
|
||||||
|
MaxRunners: &max,
|
||||||
|
MinRunners: &min,
|
||||||
|
RunnerScaleSetName: "testset",
|
||||||
|
RunnerGroup: "testgroup",
|
||||||
|
Template: corev1.PodTemplateSpec{
|
||||||
|
Spec: corev1.PodSpec{
|
||||||
|
Containers: []corev1.Container{
|
||||||
|
{
|
||||||
|
Name: "runner",
|
||||||
|
Image: "ghcr.io/actions/runner",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := k8sClient.Create(ctx, autoscalingRunnerSet)
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "failed to create AutoScalingRunnerSet")
|
||||||
|
|
||||||
|
// Wait for the AutoScalingRunnerSet to be created with right annotation
|
||||||
|
ars := new(v1alpha1.AutoscalingRunnerSet)
|
||||||
|
Eventually(
|
||||||
|
func() (string, error) {
|
||||||
|
err := k8sClient.Get(ctx, client.ObjectKey{Name: autoscalingRunnerSet.Name, Namespace: autoscalingRunnerSet.Namespace}, ars)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if val, ok := ars.Annotations[runnerScaleSetNameKey]; ok {
|
||||||
|
return val, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", nil
|
||||||
|
},
|
||||||
|
autoscalingRunnerSetTestTimeout,
|
||||||
|
autoscalingRunnerSetTestInterval,
|
||||||
|
).Should(BeEquivalentTo(autoscalingRunnerSet.Spec.RunnerScaleSetName), "AutoScalingRunnerSet should have annotation for the RunnerScaleSetName")
|
||||||
|
|
||||||
|
update := autoscalingRunnerSet.DeepCopy()
|
||||||
|
update.Spec.RunnerScaleSetName = "testset_update"
|
||||||
|
err = k8sClient.Patch(ctx, update, client.MergeFrom(autoscalingRunnerSet))
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "failed to update AutoScalingRunnerSet")
|
||||||
|
|
||||||
|
// Wait for the AutoScalingRunnerSet to be updated with right annotation
|
||||||
|
Eventually(
|
||||||
|
func() (string, error) {
|
||||||
|
err := k8sClient.Get(ctx, client.ObjectKey{Name: autoscalingRunnerSet.Name, Namespace: autoscalingRunnerSet.Namespace}, ars)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if val, ok := ars.Annotations[runnerScaleSetNameKey]; ok {
|
||||||
|
return val, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", nil
|
||||||
|
},
|
||||||
|
autoscalingRunnerSetTestTimeout,
|
||||||
|
autoscalingRunnerSetTestInterval,
|
||||||
|
).Should(BeEquivalentTo(update.Spec.RunnerScaleSetName), "AutoScalingRunnerSet should have a updated annotation for the RunnerScaleSetName")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
var _ = Describe("Test AutoscalingController creation failures", func() {
|
var _ = Describe("Test AutoscalingController creation failures", func() {
|
||||||
Context("When autoscaling runner set creation fails on the client", func() {
|
Context("When autoscaling runner set creation fails on the client", func() {
|
||||||
var ctx context.Context
|
var ctx context.Context
|
||||||
var cancel context.CancelFunc
|
var mgr ctrl.Manager
|
||||||
autoscalingNS := new(corev1.Namespace)
|
var autoscalingNS *corev1.Namespace
|
||||||
configSecret := new(corev1.Secret)
|
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
ctx, cancel = context.WithCancel(context.TODO())
|
ctx = context.Background()
|
||||||
autoscalingNS = &corev1.Namespace{
|
autoscalingNS, mgr = createNamespace(GinkgoT(), k8sClient)
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "testns-autoscaling" + RandStringRunes(5)},
|
|
||||||
}
|
|
||||||
|
|
||||||
err := k8sClient.Create(ctx, autoscalingNS)
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to create test namespace for AutoScalingRunnerSet")
|
|
||||||
|
|
||||||
configSecret = &corev1.Secret{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "github-config-secret",
|
|
||||||
Namespace: autoscalingNS.Name,
|
|
||||||
},
|
|
||||||
Data: map[string][]byte{
|
|
||||||
"github_token": []byte(autoscalingRunnerSetTestGitHubToken),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
err = k8sClient.Create(ctx, configSecret)
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to create config secret")
|
|
||||||
|
|
||||||
mgr, err := ctrl.NewManager(cfg, ctrl.Options{
|
|
||||||
MetricsBindAddress: "0",
|
|
||||||
})
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to create manager")
|
|
||||||
|
|
||||||
controller := &AutoscalingRunnerSetReconciler{
|
controller := &AutoscalingRunnerSetReconciler{
|
||||||
Client: mgr.GetClient(),
|
Client: mgr.GetClient(),
|
||||||
@@ -477,22 +544,10 @@ var _ = Describe("Test AutoscalingController creation failures", func() {
|
|||||||
DefaultRunnerScaleSetListenerImage: "ghcr.io/actions/arc",
|
DefaultRunnerScaleSetListenerImage: "ghcr.io/actions/arc",
|
||||||
ActionsClient: fake.NewMultiClient(),
|
ActionsClient: fake.NewMultiClient(),
|
||||||
}
|
}
|
||||||
err = controller.SetupWithManager(mgr)
|
err := controller.SetupWithManager(mgr)
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to setup controller")
|
Expect(err).NotTo(HaveOccurred(), "failed to setup controller")
|
||||||
|
|
||||||
go func() {
|
startManagers(GinkgoT(), mgr)
|
||||||
defer GinkgoRecover()
|
|
||||||
|
|
||||||
err := mgr.Start(ctx)
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to start manager")
|
|
||||||
}()
|
|
||||||
})
|
|
||||||
|
|
||||||
AfterEach(func() {
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
err := k8sClient.Delete(ctx, autoscalingNS)
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to delete test namespace for AutoScalingRunnerSet")
|
|
||||||
})
|
})
|
||||||
|
|
||||||
It("It should be able to clean up if annotation related to scale set id does not exist", func() {
|
It("It should be able to clean up if annotation related to scale set id does not exist", func() {
|
||||||
@@ -583,57 +638,17 @@ var _ = Describe("Test AutoscalingController creation failures", func() {
|
|||||||
var _ = Describe("Test Client optional configuration", func() {
|
var _ = Describe("Test Client optional configuration", func() {
|
||||||
Context("When specifying a proxy", func() {
|
Context("When specifying a proxy", func() {
|
||||||
var ctx context.Context
|
var ctx context.Context
|
||||||
var cancel context.CancelFunc
|
|
||||||
|
|
||||||
autoscalingNS := new(corev1.Namespace)
|
|
||||||
configSecret := new(corev1.Secret)
|
|
||||||
var mgr ctrl.Manager
|
var mgr ctrl.Manager
|
||||||
|
var autoscalingNS *corev1.Namespace
|
||||||
|
var configSecret *corev1.Secret
|
||||||
|
var controller *AutoscalingRunnerSetReconciler
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
ctx, cancel = context.WithCancel(context.TODO())
|
ctx = context.Background()
|
||||||
autoscalingNS = &corev1.Namespace{
|
autoscalingNS, mgr = createNamespace(GinkgoT(), k8sClient)
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "testns-autoscaling" + RandStringRunes(5)},
|
configSecret = createDefaultSecret(GinkgoT(), k8sClient, autoscalingNS.Name)
|
||||||
}
|
|
||||||
|
|
||||||
err := k8sClient.Create(ctx, autoscalingNS)
|
controller = &AutoscalingRunnerSetReconciler{
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to create test namespace for AutoScalingRunnerSet")
|
|
||||||
|
|
||||||
configSecret = &corev1.Secret{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "github-config-secret",
|
|
||||||
Namespace: autoscalingNS.Name,
|
|
||||||
},
|
|
||||||
Data: map[string][]byte{
|
|
||||||
"github_token": []byte(autoscalingRunnerSetTestGitHubToken),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
err = k8sClient.Create(ctx, configSecret)
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to create config secret")
|
|
||||||
|
|
||||||
mgr, err = ctrl.NewManager(cfg, ctrl.Options{
|
|
||||||
Namespace: autoscalingNS.Name,
|
|
||||||
MetricsBindAddress: "0",
|
|
||||||
})
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to create manager")
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
defer GinkgoRecover()
|
|
||||||
|
|
||||||
err := mgr.Start(ctx)
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to start manager")
|
|
||||||
}()
|
|
||||||
})
|
|
||||||
|
|
||||||
AfterEach(func() {
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
err := k8sClient.Delete(ctx, autoscalingNS)
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to delete test namespace for AutoScalingRunnerSet")
|
|
||||||
})
|
|
||||||
|
|
||||||
It("should be able to make requests to a server using a proxy", func() {
|
|
||||||
controller := &AutoscalingRunnerSetReconciler{
|
|
||||||
Client: mgr.GetClient(),
|
Client: mgr.GetClient(),
|
||||||
Scheme: mgr.GetScheme(),
|
Scheme: mgr.GetScheme(),
|
||||||
Log: logf.Log,
|
Log: logf.Log,
|
||||||
@@ -644,6 +659,10 @@ var _ = Describe("Test Client optional configuration", func() {
|
|||||||
err := controller.SetupWithManager(mgr)
|
err := controller.SetupWithManager(mgr)
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to setup controller")
|
Expect(err).NotTo(HaveOccurred(), "failed to setup controller")
|
||||||
|
|
||||||
|
startManagers(GinkgoT(), mgr)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should be able to make requests to a server using a proxy", func() {
|
||||||
serverSuccessfullyCalled := false
|
serverSuccessfullyCalled := false
|
||||||
proxy := testserver.New(GinkgoT(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
proxy := testserver.New(GinkgoT(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
serverSuccessfullyCalled = true
|
serverSuccessfullyCalled = true
|
||||||
@@ -681,7 +700,7 @@ var _ = Describe("Test Client optional configuration", func() {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err = k8sClient.Create(ctx, autoscalingRunnerSet)
|
err := k8sClient.Create(ctx, autoscalingRunnerSet)
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to create AutoScalingRunnerSet")
|
Expect(err).NotTo(HaveOccurred(), "failed to create AutoScalingRunnerSet")
|
||||||
|
|
||||||
// wait for server to be called
|
// wait for server to be called
|
||||||
@@ -695,17 +714,6 @@ var _ = Describe("Test Client optional configuration", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("should be able to make requests to a server using a proxy with user info", func() {
|
It("should be able to make requests to a server using a proxy with user info", func() {
|
||||||
controller := &AutoscalingRunnerSetReconciler{
|
|
||||||
Client: mgr.GetClient(),
|
|
||||||
Scheme: mgr.GetScheme(),
|
|
||||||
Log: logf.Log,
|
|
||||||
ControllerNamespace: autoscalingNS.Name,
|
|
||||||
DefaultRunnerScaleSetListenerImage: "ghcr.io/actions/arc",
|
|
||||||
ActionsClient: actions.NewMultiClient("test", logr.Discard()),
|
|
||||||
}
|
|
||||||
err := controller.SetupWithManager(mgr)
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to setup controller")
|
|
||||||
|
|
||||||
serverSuccessfullyCalled := false
|
serverSuccessfullyCalled := false
|
||||||
proxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
proxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
header := r.Header.Get("Proxy-Authorization")
|
header := r.Header.Get("Proxy-Authorization")
|
||||||
@@ -734,7 +742,7 @@ var _ = Describe("Test Client optional configuration", func() {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err = k8sClient.Create(ctx, secretCredentials)
|
err := k8sClient.Create(ctx, secretCredentials)
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to create secret credentials")
|
Expect(err).NotTo(HaveOccurred(), "failed to create secret credentials")
|
||||||
|
|
||||||
min := 1
|
min := 1
|
||||||
@@ -782,4 +790,242 @@ var _ = Describe("Test Client optional configuration", func() {
|
|||||||
).Should(BeTrue(), "server was not called")
|
).Should(BeTrue(), "server was not called")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Context("When specifying a configmap for root CAs", func() {
|
||||||
|
var ctx context.Context
|
||||||
|
var mgr ctrl.Manager
|
||||||
|
var autoscalingNS *corev1.Namespace
|
||||||
|
var configSecret *corev1.Secret
|
||||||
|
var rootCAConfigMap *corev1.ConfigMap
|
||||||
|
var controller *AutoscalingRunnerSetReconciler
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
ctx = context.Background()
|
||||||
|
autoscalingNS, mgr = createNamespace(GinkgoT(), k8sClient)
|
||||||
|
configSecret = createDefaultSecret(GinkgoT(), k8sClient, autoscalingNS.Name)
|
||||||
|
|
||||||
|
cert, err := os.ReadFile(filepath.Join(
|
||||||
|
"../../",
|
||||||
|
"github",
|
||||||
|
"actions",
|
||||||
|
"testdata",
|
||||||
|
"rootCA.crt",
|
||||||
|
))
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "failed to read root CA cert")
|
||||||
|
rootCAConfigMap = &corev1.ConfigMap{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "root-ca-configmap",
|
||||||
|
Namespace: autoscalingNS.Name,
|
||||||
|
},
|
||||||
|
Data: map[string]string{
|
||||||
|
"rootCA.crt": string(cert),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
err = k8sClient.Create(ctx, rootCAConfigMap)
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "failed to create configmap with root CAs")
|
||||||
|
|
||||||
|
controller = &AutoscalingRunnerSetReconciler{
|
||||||
|
Client: mgr.GetClient(),
|
||||||
|
Scheme: mgr.GetScheme(),
|
||||||
|
Log: logf.Log,
|
||||||
|
ControllerNamespace: autoscalingNS.Name,
|
||||||
|
DefaultRunnerScaleSetListenerImage: "ghcr.io/actions/arc",
|
||||||
|
ActionsClient: fake.NewMultiClient(),
|
||||||
|
}
|
||||||
|
err = controller.SetupWithManager(mgr)
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "failed to setup controller")
|
||||||
|
|
||||||
|
startManagers(GinkgoT(), mgr)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should be able to make requests to a server using root CAs", func() {
|
||||||
|
controller.ActionsClient = actions.NewMultiClient("test", logr.Discard())
|
||||||
|
|
||||||
|
certsFolder := filepath.Join(
|
||||||
|
"../../",
|
||||||
|
"github",
|
||||||
|
"actions",
|
||||||
|
"testdata",
|
||||||
|
)
|
||||||
|
certPath := filepath.Join(certsFolder, "server.crt")
|
||||||
|
keyPath := filepath.Join(certsFolder, "server.key")
|
||||||
|
|
||||||
|
serverSuccessfullyCalled := false
|
||||||
|
server := testserver.NewUnstarted(GinkgoT(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
serverSuccessfullyCalled = true
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
}))
|
||||||
|
cert, err := tls.LoadX509KeyPair(certPath, keyPath)
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "failed to load server cert")
|
||||||
|
|
||||||
|
server.TLS = &tls.Config{Certificates: []tls.Certificate{cert}}
|
||||||
|
server.StartTLS()
|
||||||
|
|
||||||
|
min := 1
|
||||||
|
max := 10
|
||||||
|
autoscalingRunnerSet := &v1alpha1.AutoscalingRunnerSet{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "test-asrs",
|
||||||
|
Namespace: autoscalingNS.Name,
|
||||||
|
},
|
||||||
|
Spec: v1alpha1.AutoscalingRunnerSetSpec{
|
||||||
|
GitHubConfigUrl: server.ConfigURLForOrg("my-org"),
|
||||||
|
GitHubConfigSecret: configSecret.Name,
|
||||||
|
GitHubServerTLS: &v1alpha1.GitHubServerTLSConfig{
|
||||||
|
CertificateFrom: &v1alpha1.TLSCertificateSource{
|
||||||
|
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
|
||||||
|
LocalObjectReference: corev1.LocalObjectReference{
|
||||||
|
Name: rootCAConfigMap.Name,
|
||||||
|
},
|
||||||
|
Key: "rootCA.crt",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MaxRunners: &max,
|
||||||
|
MinRunners: &min,
|
||||||
|
RunnerGroup: "testgroup",
|
||||||
|
Template: corev1.PodTemplateSpec{
|
||||||
|
Spec: corev1.PodSpec{
|
||||||
|
Containers: []corev1.Container{
|
||||||
|
{
|
||||||
|
Name: "runner",
|
||||||
|
Image: "ghcr.io/actions/runner",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
err = k8sClient.Create(ctx, autoscalingRunnerSet)
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "failed to create AutoScalingRunnerSet")
|
||||||
|
|
||||||
|
// wait for server to be called
|
||||||
|
Eventually(
|
||||||
|
func() (bool, error) {
|
||||||
|
return serverSuccessfullyCalled, nil
|
||||||
|
},
|
||||||
|
autoscalingRunnerSetTestTimeout,
|
||||||
|
1*time.Nanosecond,
|
||||||
|
).Should(BeTrue(), "server was not called")
|
||||||
|
})
|
||||||
|
|
||||||
|
It("it creates a listener referencing the right configmap for TLS", func() {
|
||||||
|
min := 1
|
||||||
|
max := 10
|
||||||
|
autoscalingRunnerSet := &v1alpha1.AutoscalingRunnerSet{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "test-asrs",
|
||||||
|
Namespace: autoscalingNS.Name,
|
||||||
|
},
|
||||||
|
Spec: v1alpha1.AutoscalingRunnerSetSpec{
|
||||||
|
GitHubConfigUrl: "https://github.com/owner/repo",
|
||||||
|
GitHubConfigSecret: configSecret.Name,
|
||||||
|
GitHubServerTLS: &v1alpha1.GitHubServerTLSConfig{
|
||||||
|
CertificateFrom: &v1alpha1.TLSCertificateSource{
|
||||||
|
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
|
||||||
|
LocalObjectReference: corev1.LocalObjectReference{
|
||||||
|
Name: rootCAConfigMap.Name,
|
||||||
|
},
|
||||||
|
Key: "rootCA.crt",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MaxRunners: &max,
|
||||||
|
MinRunners: &min,
|
||||||
|
RunnerGroup: "testgroup",
|
||||||
|
Template: corev1.PodTemplateSpec{
|
||||||
|
Spec: corev1.PodSpec{
|
||||||
|
Containers: []corev1.Container{
|
||||||
|
{
|
||||||
|
Name: "runner",
|
||||||
|
Image: "ghcr.io/actions/runner",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := k8sClient.Create(ctx, autoscalingRunnerSet)
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "failed to create AutoScalingRunnerSet")
|
||||||
|
|
||||||
|
Eventually(
|
||||||
|
func(g Gomega) {
|
||||||
|
listener := new(v1alpha1.AutoscalingListener)
|
||||||
|
err := k8sClient.Get(
|
||||||
|
ctx,
|
||||||
|
client.ObjectKey{
|
||||||
|
Name: scaleSetListenerName(autoscalingRunnerSet),
|
||||||
|
Namespace: autoscalingRunnerSet.Namespace,
|
||||||
|
},
|
||||||
|
listener,
|
||||||
|
)
|
||||||
|
g.Expect(err).NotTo(HaveOccurred(), "failed to get listener")
|
||||||
|
|
||||||
|
g.Expect(listener.Spec.GitHubServerTLS).NotTo(BeNil(), "listener does not have TLS config")
|
||||||
|
g.Expect(listener.Spec.GitHubServerTLS).To(BeEquivalentTo(autoscalingRunnerSet.Spec.GitHubServerTLS), "listener does not have TLS config")
|
||||||
|
},
|
||||||
|
autoscalingRunnerSetTestTimeout,
|
||||||
|
autoscalingListenerTestInterval,
|
||||||
|
).Should(Succeed(), "tls config is incorrect")
|
||||||
|
})
|
||||||
|
|
||||||
|
It("it creates an ephemeral runner set referencing the right configmap for TLS", func() {
|
||||||
|
min := 1
|
||||||
|
max := 10
|
||||||
|
autoscalingRunnerSet := &v1alpha1.AutoscalingRunnerSet{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "test-asrs",
|
||||||
|
Namespace: autoscalingNS.Name,
|
||||||
|
},
|
||||||
|
Spec: v1alpha1.AutoscalingRunnerSetSpec{
|
||||||
|
GitHubConfigUrl: "https://github.com/owner/repo",
|
||||||
|
GitHubConfigSecret: configSecret.Name,
|
||||||
|
GitHubServerTLS: &v1alpha1.GitHubServerTLSConfig{
|
||||||
|
CertificateFrom: &v1alpha1.TLSCertificateSource{
|
||||||
|
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
|
||||||
|
LocalObjectReference: corev1.LocalObjectReference{
|
||||||
|
Name: rootCAConfigMap.Name,
|
||||||
|
},
|
||||||
|
Key: "rootCA.crt",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MaxRunners: &max,
|
||||||
|
MinRunners: &min,
|
||||||
|
RunnerGroup: "testgroup",
|
||||||
|
Template: corev1.PodTemplateSpec{
|
||||||
|
Spec: corev1.PodSpec{
|
||||||
|
Containers: []corev1.Container{
|
||||||
|
{
|
||||||
|
Name: "runner",
|
||||||
|
Image: "ghcr.io/actions/runner",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := k8sClient.Create(ctx, autoscalingRunnerSet)
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "failed to create AutoScalingRunnerSet")
|
||||||
|
|
||||||
|
Eventually(
|
||||||
|
func(g Gomega) {
|
||||||
|
runnerSetList := new(v1alpha1.EphemeralRunnerSetList)
|
||||||
|
err := k8sClient.List(ctx, runnerSetList, client.InNamespace(autoscalingRunnerSet.Namespace))
|
||||||
|
g.Expect(err).NotTo(HaveOccurred(), "failed to list EphemeralRunnerSet")
|
||||||
|
g.Expect(runnerSetList.Items).To(HaveLen(1), "expected 1 EphemeralRunnerSet to be created")
|
||||||
|
|
||||||
|
runnerSet := &runnerSetList.Items[0]
|
||||||
|
|
||||||
|
g.Expect(runnerSet.Spec.EphemeralRunnerSpec.GitHubServerTLS).NotTo(BeNil(), "expected EphemeralRunnerSpec.GitHubServerTLS to be set")
|
||||||
|
g.Expect(runnerSet.Spec.EphemeralRunnerSpec.GitHubServerTLS).To(BeEquivalentTo(autoscalingRunnerSet.Spec.GitHubServerTLS), "EphemeralRunnerSpec does not have TLS config")
|
||||||
|
},
|
||||||
|
autoscalingRunnerSetTestTimeout,
|
||||||
|
autoscalingListenerTestInterval,
|
||||||
|
).Should(Succeed())
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -680,6 +680,21 @@ func (r *EphemeralRunnerReconciler) actionsClientFor(ctx context.Context, runner
|
|||||||
return nil, fmt.Errorf("failed to get secret: %w", err)
|
return nil, fmt.Errorf("failed to get secret: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
opts, err := r.actionsClientOptionsFor(ctx, runner)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get actions client options: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.ActionsClient.GetClientFromSecret(
|
||||||
|
ctx,
|
||||||
|
runner.Spec.GitHubConfigUrl,
|
||||||
|
runner.Namespace,
|
||||||
|
secret.Data,
|
||||||
|
opts...,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *EphemeralRunnerReconciler) actionsClientOptionsFor(ctx context.Context, runner *v1alpha1.EphemeralRunner) ([]actions.ClientOption, error) {
|
||||||
var opts []actions.ClientOption
|
var opts []actions.ClientOption
|
||||||
if runner.Spec.Proxy != nil {
|
if runner.Spec.Proxy != nil {
|
||||||
proxyFunc, err := runner.Spec.Proxy.ProxyFunc(func(s string) (*corev1.Secret, error) {
|
proxyFunc, err := runner.Spec.Proxy.ProxyFunc(func(s string) (*corev1.Secret, error) {
|
||||||
@@ -698,13 +713,32 @@ func (r *EphemeralRunnerReconciler) actionsClientFor(ctx context.Context, runner
|
|||||||
opts = append(opts, actions.WithProxy(proxyFunc))
|
opts = append(opts, actions.WithProxy(proxyFunc))
|
||||||
}
|
}
|
||||||
|
|
||||||
return r.ActionsClient.GetClientFromSecret(
|
tlsConfig := runner.Spec.GitHubServerTLS
|
||||||
ctx,
|
if tlsConfig != nil {
|
||||||
runner.Spec.GitHubConfigUrl,
|
pool, err := tlsConfig.ToCertPool(func(name, key string) ([]byte, error) {
|
||||||
runner.Namespace,
|
var configmap corev1.ConfigMap
|
||||||
secret.Data,
|
err := r.Get(
|
||||||
opts...,
|
ctx,
|
||||||
)
|
types.NamespacedName{
|
||||||
|
Namespace: runner.Namespace,
|
||||||
|
Name: name,
|
||||||
|
},
|
||||||
|
&configmap,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get configmap %s: %w", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return []byte(configmap.Data[key]), nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get tls config: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
opts = append(opts, actions.WithRootCAs(pool))
|
||||||
|
}
|
||||||
|
|
||||||
|
return opts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// runnerRegisteredWithService checks if the runner is still registered with the service
|
// runnerRegisteredWithService checks if the runner is still registered with the service
|
||||||
|
|||||||
@@ -2,10 +2,13 @@ package actionsgithubcom
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -14,6 +17,7 @@ import (
|
|||||||
"github.com/go-logr/logr"
|
"github.com/go-logr/logr"
|
||||||
|
|
||||||
"github.com/actions/actions-runner-controller/github/actions/fake"
|
"github.com/actions/actions-runner-controller/github/actions/fake"
|
||||||
|
"github.com/actions/actions-runner-controller/github/actions/testserver"
|
||||||
. "github.com/onsi/ginkgo/v2"
|
. "github.com/onsi/ginkgo/v2"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
@@ -22,11 +26,9 @@ import (
|
|||||||
ctrl "sigs.k8s.io/controller-runtime"
|
ctrl "sigs.k8s.io/controller-runtime"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
logf "sigs.k8s.io/controller-runtime/pkg/log"
|
logf "sigs.k8s.io/controller-runtime/pkg/log"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/manager"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
gh_token = "gh_token"
|
|
||||||
timeout = time.Second * 10
|
timeout = time.Second * 10
|
||||||
interval = time.Millisecond * 250
|
interval = time.Millisecond * 250
|
||||||
runnerImage = "ghcr.io/actions/actions-runner:latest"
|
runnerImage = "ghcr.io/actions/actions-runner:latest"
|
||||||
@@ -61,7 +63,7 @@ func newExampleRunner(name, namespace, configSecretName string) *v1alpha1.Epheme
|
|||||||
{
|
{
|
||||||
Name: "setup",
|
Name: "setup",
|
||||||
Image: runnerImage,
|
Image: runnerImage,
|
||||||
Command: []string{"sh", "-c", "cp -r /actions-runner/* /runner/"},
|
Command: []string{"sh", "-c", "cp -r /home/runner/* /runner/"},
|
||||||
VolumeMounts: []corev1.VolumeMount{
|
VolumeMounts: []corev1.VolumeMount{
|
||||||
{
|
{
|
||||||
Name: "runner",
|
Name: "runner",
|
||||||
@@ -87,42 +89,16 @@ func newExampleRunner(name, namespace, configSecretName string) *v1alpha1.Epheme
|
|||||||
var _ = Describe("EphemeralRunner", func() {
|
var _ = Describe("EphemeralRunner", func() {
|
||||||
Describe("Resource manipulation", func() {
|
Describe("Resource manipulation", func() {
|
||||||
var ctx context.Context
|
var ctx context.Context
|
||||||
var cancel context.CancelFunc
|
var mgr ctrl.Manager
|
||||||
|
var autoscalingNS *corev1.Namespace
|
||||||
autoscalingNS := new(corev1.Namespace)
|
var configSecret *corev1.Secret
|
||||||
configSecret := new(corev1.Secret)
|
var controller *EphemeralRunnerReconciler
|
||||||
|
var ephemeralRunner *v1alpha1.EphemeralRunner
|
||||||
controller := new(EphemeralRunnerReconciler)
|
|
||||||
ephemeralRunner := new(v1alpha1.EphemeralRunner)
|
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
ctx, cancel = context.WithCancel(context.Background())
|
ctx = context.Background()
|
||||||
autoscalingNS = &corev1.Namespace{
|
autoscalingNS, mgr = createNamespace(GinkgoT(), k8sClient)
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
configSecret = createDefaultSecret(GinkgoT(), k8sClient, autoscalingNS.Name)
|
||||||
Name: "testns-autoscaling-runner" + RandStringRunes(5),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
err := k8sClient.Create(ctx, autoscalingNS)
|
|
||||||
Expect(err).To(BeNil(), "failed to create test namespace for EphemeralRunner")
|
|
||||||
|
|
||||||
configSecret = &corev1.Secret{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "github-config-secret",
|
|
||||||
Namespace: autoscalingNS.Name,
|
|
||||||
},
|
|
||||||
Data: map[string][]byte{
|
|
||||||
"github_token": []byte(gh_token),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
err = k8sClient.Create(ctx, configSecret)
|
|
||||||
Expect(err).To(BeNil(), "failed to create config secret")
|
|
||||||
|
|
||||||
mgr, err := ctrl.NewManager(cfg, ctrl.Options{
|
|
||||||
Namespace: autoscalingNS.Name,
|
|
||||||
MetricsBindAddress: "0",
|
|
||||||
})
|
|
||||||
Expect(err).To(BeNil(), "failed to create manager")
|
|
||||||
|
|
||||||
controller = &EphemeralRunnerReconciler{
|
controller = &EphemeralRunnerReconciler{
|
||||||
Client: mgr.GetClient(),
|
Client: mgr.GetClient(),
|
||||||
@@ -131,26 +107,14 @@ var _ = Describe("EphemeralRunner", func() {
|
|||||||
ActionsClient: fake.NewMultiClient(),
|
ActionsClient: fake.NewMultiClient(),
|
||||||
}
|
}
|
||||||
|
|
||||||
err = controller.SetupWithManager(mgr)
|
err := controller.SetupWithManager(mgr)
|
||||||
Expect(err).To(BeNil(), "failed to setup controller")
|
Expect(err).To(BeNil(), "failed to setup controller")
|
||||||
|
|
||||||
ephemeralRunner = newExampleRunner("test-runner", autoscalingNS.Name, configSecret.Name)
|
ephemeralRunner = newExampleRunner("test-runner", autoscalingNS.Name, configSecret.Name)
|
||||||
err = k8sClient.Create(ctx, ephemeralRunner)
|
err = k8sClient.Create(ctx, ephemeralRunner)
|
||||||
Expect(err).To(BeNil(), "failed to create ephemeral runner")
|
Expect(err).To(BeNil(), "failed to create ephemeral runner")
|
||||||
|
|
||||||
go func() {
|
startManagers(GinkgoT(), mgr)
|
||||||
defer GinkgoRecover()
|
|
||||||
|
|
||||||
err := mgr.Start(ctx)
|
|
||||||
Expect(err).To(BeNil(), "failed to start manager")
|
|
||||||
}()
|
|
||||||
})
|
|
||||||
|
|
||||||
AfterEach(func() {
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
err := k8sClient.Delete(ctx, autoscalingNS)
|
|
||||||
Expect(err).To(BeNil(), "failed to delete test namespace for EphemeralRunner")
|
|
||||||
})
|
})
|
||||||
|
|
||||||
It("It should create/add all required resources for EphemeralRunner (finalizer, jit secret)", func() {
|
It("It should create/add all required resources for EphemeralRunner (finalizer, jit secret)", func() {
|
||||||
@@ -668,52 +632,17 @@ var _ = Describe("EphemeralRunner", func() {
|
|||||||
|
|
||||||
Describe("Checking the API", func() {
|
Describe("Checking the API", func() {
|
||||||
var ctx context.Context
|
var ctx context.Context
|
||||||
var cancel context.CancelFunc
|
var autoscalingNS *corev1.Namespace
|
||||||
|
var configSecret *corev1.Secret
|
||||||
autoscalingNS := new(corev1.Namespace)
|
var controller *EphemeralRunnerReconciler
|
||||||
configSecret := new(corev1.Secret)
|
var mgr ctrl.Manager
|
||||||
|
|
||||||
var mgr manager.Manager
|
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
ctx, cancel = context.WithCancel(context.Background())
|
ctx = context.Background()
|
||||||
autoscalingNS = &corev1.Namespace{
|
autoscalingNS, mgr = createNamespace(GinkgoT(), k8sClient)
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
configSecret = createDefaultSecret(GinkgoT(), k8sClient, autoscalingNS.Name)
|
||||||
Name: "testns-autoscaling-runner" + RandStringRunes(5),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
err := k8sClient.Create(ctx, autoscalingNS)
|
|
||||||
Expect(err).To(BeNil(), "failed to create test namespace for EphemeralRunner")
|
|
||||||
|
|
||||||
configSecret = &corev1.Secret{
|
controller = &EphemeralRunnerReconciler{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "github-config-secret",
|
|
||||||
Namespace: autoscalingNS.Name,
|
|
||||||
},
|
|
||||||
Data: map[string][]byte{
|
|
||||||
"github_token": []byte(gh_token),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
err = k8sClient.Create(ctx, configSecret)
|
|
||||||
Expect(err).To(BeNil(), "failed to create config secret")
|
|
||||||
|
|
||||||
mgr, err = ctrl.NewManager(cfg, ctrl.Options{
|
|
||||||
Namespace: autoscalingNS.Name,
|
|
||||||
MetricsBindAddress: "0",
|
|
||||||
})
|
|
||||||
Expect(err).To(BeNil(), "failed to create manager")
|
|
||||||
})
|
|
||||||
|
|
||||||
AfterEach(func() {
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
err := k8sClient.Delete(ctx, autoscalingNS)
|
|
||||||
Expect(err).To(BeNil(), "failed to delete test namespace for EphemeralRunner")
|
|
||||||
})
|
|
||||||
|
|
||||||
It("It should set the Phase to Succeeded", func() {
|
|
||||||
controller := &EphemeralRunnerReconciler{
|
|
||||||
Client: mgr.GetClient(),
|
Client: mgr.GetClient(),
|
||||||
Scheme: mgr.GetScheme(),
|
Scheme: mgr.GetScheme(),
|
||||||
Log: logf.Log,
|
Log: logf.Log,
|
||||||
@@ -732,20 +661,16 @@ var _ = Describe("EphemeralRunner", func() {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
err := controller.SetupWithManager(mgr)
|
err := controller.SetupWithManager(mgr)
|
||||||
Expect(err).To(BeNil(), "failed to setup controller")
|
Expect(err).To(BeNil(), "failed to setup controller")
|
||||||
|
|
||||||
go func() {
|
startManagers(GinkgoT(), mgr)
|
||||||
defer GinkgoRecover()
|
})
|
||||||
|
|
||||||
err := mgr.Start(ctx)
|
|
||||||
Expect(err).To(BeNil(), "failed to start manager")
|
|
||||||
}()
|
|
||||||
|
|
||||||
|
It("It should set the Phase to Succeeded", func() {
|
||||||
ephemeralRunner := newExampleRunner("test-runner", autoscalingNS.Name, configSecret.Name)
|
ephemeralRunner := newExampleRunner("test-runner", autoscalingNS.Name, configSecret.Name)
|
||||||
|
|
||||||
err = k8sClient.Create(ctx, ephemeralRunner)
|
err := k8sClient.Create(ctx, ephemeralRunner)
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
pod := new(corev1.Pod)
|
pod := new(corev1.Pod)
|
||||||
@@ -780,40 +705,15 @@ var _ = Describe("EphemeralRunner", func() {
|
|||||||
|
|
||||||
Describe("Pod proxy config", func() {
|
Describe("Pod proxy config", func() {
|
||||||
var ctx context.Context
|
var ctx context.Context
|
||||||
var cancel context.CancelFunc
|
var mgr ctrl.Manager
|
||||||
|
var autoScalingNS *corev1.Namespace
|
||||||
autoScalingNS := new(corev1.Namespace)
|
var configSecret *corev1.Secret
|
||||||
configSecret := new(corev1.Secret)
|
var controller *EphemeralRunnerReconciler
|
||||||
controller := new(EphemeralRunnerReconciler)
|
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
ctx, cancel = context.WithCancel(context.Background())
|
ctx = context.Background()
|
||||||
autoScalingNS = &corev1.Namespace{
|
autoScalingNS, mgr = createNamespace(GinkgoT(), k8sClient)
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
configSecret = createDefaultSecret(GinkgoT(), k8sClient, autoScalingNS.Name)
|
||||||
Name: "testns-autoscaling-runner" + RandStringRunes(5),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
err := k8sClient.Create(ctx, autoScalingNS)
|
|
||||||
Expect(err).To(BeNil(), "failed to create test namespace for EphemeralRunner")
|
|
||||||
|
|
||||||
configSecret = &corev1.Secret{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "github-config-secret",
|
|
||||||
Namespace: autoScalingNS.Name,
|
|
||||||
},
|
|
||||||
Data: map[string][]byte{
|
|
||||||
"github_token": []byte(gh_token),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
err = k8sClient.Create(ctx, configSecret)
|
|
||||||
Expect(err).To(BeNil(), "failed to create config secret")
|
|
||||||
|
|
||||||
mgr, err := ctrl.NewManager(cfg, ctrl.Options{
|
|
||||||
Namespace: autoScalingNS.Name,
|
|
||||||
MetricsBindAddress: "0",
|
|
||||||
})
|
|
||||||
Expect(err).To(BeNil(), "failed to create manager")
|
|
||||||
|
|
||||||
controller = &EphemeralRunnerReconciler{
|
controller = &EphemeralRunnerReconciler{
|
||||||
Client: mgr.GetClient(),
|
Client: mgr.GetClient(),
|
||||||
@@ -821,23 +721,10 @@ var _ = Describe("EphemeralRunner", func() {
|
|||||||
Log: logf.Log,
|
Log: logf.Log,
|
||||||
ActionsClient: fake.NewMultiClient(),
|
ActionsClient: fake.NewMultiClient(),
|
||||||
}
|
}
|
||||||
|
err := controller.SetupWithManager(mgr)
|
||||||
err = controller.SetupWithManager(mgr)
|
|
||||||
Expect(err).To(BeNil(), "failed to setup controller")
|
Expect(err).To(BeNil(), "failed to setup controller")
|
||||||
|
|
||||||
go func() {
|
startManagers(GinkgoT(), mgr)
|
||||||
defer GinkgoRecover()
|
|
||||||
|
|
||||||
err := mgr.Start(ctx)
|
|
||||||
Expect(err).To(BeNil(), "failed to start manager")
|
|
||||||
}()
|
|
||||||
})
|
|
||||||
|
|
||||||
AfterEach(func() {
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
err := k8sClient.Delete(ctx, autoScalingNS)
|
|
||||||
Expect(err).To(BeNil(), "failed to delete test namespace for EphemeralRunner")
|
|
||||||
})
|
})
|
||||||
|
|
||||||
It("uses an actions client with proxy transport", func() {
|
It("uses an actions client with proxy transport", func() {
|
||||||
@@ -958,4 +845,100 @@ var _ = Describe("EphemeralRunner", func() {
|
|||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Describe("TLS config", func() {
|
||||||
|
var ctx context.Context
|
||||||
|
var mgr ctrl.Manager
|
||||||
|
var autoScalingNS *corev1.Namespace
|
||||||
|
var configSecret *corev1.Secret
|
||||||
|
var controller *EphemeralRunnerReconciler
|
||||||
|
var rootCAConfigMap *corev1.ConfigMap
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
ctx = context.Background()
|
||||||
|
autoScalingNS, mgr = createNamespace(GinkgoT(), k8sClient)
|
||||||
|
configSecret = createDefaultSecret(GinkgoT(), k8sClient, autoScalingNS.Name)
|
||||||
|
|
||||||
|
cert, err := os.ReadFile(filepath.Join(
|
||||||
|
"../../",
|
||||||
|
"github",
|
||||||
|
"actions",
|
||||||
|
"testdata",
|
||||||
|
"rootCA.crt",
|
||||||
|
))
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "failed to read root CA cert")
|
||||||
|
rootCAConfigMap = &corev1.ConfigMap{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "root-ca-configmap",
|
||||||
|
Namespace: autoScalingNS.Name,
|
||||||
|
},
|
||||||
|
Data: map[string]string{
|
||||||
|
"rootCA.crt": string(cert),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
err = k8sClient.Create(ctx, rootCAConfigMap)
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "failed to create configmap with root CAs")
|
||||||
|
|
||||||
|
controller = &EphemeralRunnerReconciler{
|
||||||
|
Client: mgr.GetClient(),
|
||||||
|
Scheme: mgr.GetScheme(),
|
||||||
|
Log: logf.Log,
|
||||||
|
ActionsClient: fake.NewMultiClient(),
|
||||||
|
}
|
||||||
|
|
||||||
|
err = controller.SetupWithManager(mgr)
|
||||||
|
Expect(err).To(BeNil(), "failed to setup controller")
|
||||||
|
|
||||||
|
startManagers(GinkgoT(), mgr)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should be able to make requests to a server using root CAs", func() {
|
||||||
|
certsFolder := filepath.Join(
|
||||||
|
"../../",
|
||||||
|
"github",
|
||||||
|
"actions",
|
||||||
|
"testdata",
|
||||||
|
)
|
||||||
|
certPath := filepath.Join(certsFolder, "server.crt")
|
||||||
|
keyPath := filepath.Join(certsFolder, "server.key")
|
||||||
|
|
||||||
|
serverSuccessfullyCalled := false
|
||||||
|
server := testserver.NewUnstarted(GinkgoT(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
serverSuccessfullyCalled = true
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
}))
|
||||||
|
cert, err := tls.LoadX509KeyPair(certPath, keyPath)
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "failed to load server cert")
|
||||||
|
|
||||||
|
server.TLS = &tls.Config{Certificates: []tls.Certificate{cert}}
|
||||||
|
server.StartTLS()
|
||||||
|
|
||||||
|
// Use an actual client
|
||||||
|
controller.ActionsClient = actions.NewMultiClient("test", logr.Discard())
|
||||||
|
|
||||||
|
ephemeralRunner := newExampleRunner("test-runner", autoScalingNS.Name, configSecret.Name)
|
||||||
|
ephemeralRunner.Spec.GitHubConfigUrl = server.ConfigURLForOrg("my-org")
|
||||||
|
ephemeralRunner.Spec.GitHubServerTLS = &v1alpha1.GitHubServerTLSConfig{
|
||||||
|
CertificateFrom: &v1alpha1.TLSCertificateSource{
|
||||||
|
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
|
||||||
|
LocalObjectReference: corev1.LocalObjectReference{
|
||||||
|
Name: rootCAConfigMap.Name,
|
||||||
|
},
|
||||||
|
Key: "rootCA.crt",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
err = k8sClient.Create(ctx, ephemeralRunner)
|
||||||
|
Expect(err).To(BeNil(), "failed to create ephemeral runner")
|
||||||
|
|
||||||
|
Eventually(
|
||||||
|
func() bool {
|
||||||
|
return serverSuccessfullyCalled
|
||||||
|
},
|
||||||
|
2*time.Second,
|
||||||
|
interval,
|
||||||
|
).Should(BeTrue(), "failed to contact server")
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -450,6 +450,22 @@ func (r *EphemeralRunnerSetReconciler) actionsClientFor(ctx context.Context, rs
|
|||||||
if err := r.Get(ctx, types.NamespacedName{Namespace: rs.Namespace, Name: rs.Spec.EphemeralRunnerSpec.GitHubConfigSecret}, secret); err != nil {
|
if err := r.Get(ctx, types.NamespacedName{Namespace: rs.Namespace, Name: rs.Spec.EphemeralRunnerSpec.GitHubConfigSecret}, secret); err != nil {
|
||||||
return nil, fmt.Errorf("failed to get secret: %w", err)
|
return nil, fmt.Errorf("failed to get secret: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
opts, err := r.actionsClientOptionsFor(ctx, rs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get actions client options: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.ActionsClient.GetClientFromSecret(
|
||||||
|
ctx,
|
||||||
|
rs.Spec.EphemeralRunnerSpec.GitHubConfigUrl,
|
||||||
|
rs.Namespace,
|
||||||
|
secret.Data,
|
||||||
|
opts...,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *EphemeralRunnerSetReconciler) actionsClientOptionsFor(ctx context.Context, rs *v1alpha1.EphemeralRunnerSet) ([]actions.ClientOption, error) {
|
||||||
var opts []actions.ClientOption
|
var opts []actions.ClientOption
|
||||||
if rs.Spec.EphemeralRunnerSpec.Proxy != nil {
|
if rs.Spec.EphemeralRunnerSpec.Proxy != nil {
|
||||||
proxyFunc, err := rs.Spec.EphemeralRunnerSpec.Proxy.ProxyFunc(func(s string) (*corev1.Secret, error) {
|
proxyFunc, err := rs.Spec.EphemeralRunnerSpec.Proxy.ProxyFunc(func(s string) (*corev1.Secret, error) {
|
||||||
@@ -468,13 +484,32 @@ func (r *EphemeralRunnerSetReconciler) actionsClientFor(ctx context.Context, rs
|
|||||||
opts = append(opts, actions.WithProxy(proxyFunc))
|
opts = append(opts, actions.WithProxy(proxyFunc))
|
||||||
}
|
}
|
||||||
|
|
||||||
return r.ActionsClient.GetClientFromSecret(
|
tlsConfig := rs.Spec.EphemeralRunnerSpec.GitHubServerTLS
|
||||||
ctx,
|
if tlsConfig != nil {
|
||||||
rs.Spec.EphemeralRunnerSpec.GitHubConfigUrl,
|
pool, err := tlsConfig.ToCertPool(func(name, key string) ([]byte, error) {
|
||||||
rs.Namespace,
|
var configmap corev1.ConfigMap
|
||||||
secret.Data,
|
err := r.Get(
|
||||||
opts...,
|
ctx,
|
||||||
)
|
types.NamespacedName{
|
||||||
|
Namespace: rs.Namespace,
|
||||||
|
Name: name,
|
||||||
|
},
|
||||||
|
&configmap,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get configmap %s: %w", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return []byte(configmap.Data[key]), nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get tls config: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
opts = append(opts, actions.WithRootCAs(pool))
|
||||||
|
}
|
||||||
|
|
||||||
|
return opts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetupWithManager sets up the controller with the Manager.
|
// SetupWithManager sets up the controller with the Manager.
|
||||||
|
|||||||
@@ -2,10 +2,13 @@ package actionsgithubcom
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -24,6 +27,7 @@ import (
|
|||||||
v1alpha1 "github.com/actions/actions-runner-controller/apis/actions.github.com/v1alpha1"
|
v1alpha1 "github.com/actions/actions-runner-controller/apis/actions.github.com/v1alpha1"
|
||||||
"github.com/actions/actions-runner-controller/github/actions"
|
"github.com/actions/actions-runner-controller/github/actions"
|
||||||
"github.com/actions/actions-runner-controller/github/actions/fake"
|
"github.com/actions/actions-runner-controller/github/actions/fake"
|
||||||
|
"github.com/actions/actions-runner-controller/github/actions/testserver"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -34,38 +38,15 @@ const (
|
|||||||
|
|
||||||
var _ = Describe("Test EphemeralRunnerSet controller", func() {
|
var _ = Describe("Test EphemeralRunnerSet controller", func() {
|
||||||
var ctx context.Context
|
var ctx context.Context
|
||||||
var cancel context.CancelFunc
|
var mgr ctrl.Manager
|
||||||
autoscalingNS := new(corev1.Namespace)
|
var autoscalingNS *corev1.Namespace
|
||||||
ephemeralRunnerSet := new(actionsv1alpha1.EphemeralRunnerSet)
|
var ephemeralRunnerSet *actionsv1alpha1.EphemeralRunnerSet
|
||||||
configSecret := new(corev1.Secret)
|
var configSecret *corev1.Secret
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
ctx, cancel = context.WithCancel(context.TODO())
|
ctx = context.Background()
|
||||||
autoscalingNS = &corev1.Namespace{
|
autoscalingNS, mgr = createNamespace(GinkgoT(), k8sClient)
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "testns-autoscaling-runnerset" + RandStringRunes(5)},
|
configSecret = createDefaultSecret(GinkgoT(), k8sClient, autoscalingNS.Name)
|
||||||
}
|
|
||||||
|
|
||||||
err := k8sClient.Create(ctx, autoscalingNS)
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to create test namespace for EphemeralRunnerSet")
|
|
||||||
|
|
||||||
configSecret = &corev1.Secret{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "github-config-secret",
|
|
||||||
Namespace: autoscalingNS.Name,
|
|
||||||
},
|
|
||||||
Data: map[string][]byte{
|
|
||||||
"github_token": []byte(ephemeralRunnerSetTestGitHubToken),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
err = k8sClient.Create(ctx, configSecret)
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to create config secret")
|
|
||||||
|
|
||||||
mgr, err := ctrl.NewManager(cfg, ctrl.Options{
|
|
||||||
Namespace: autoscalingNS.Name,
|
|
||||||
MetricsBindAddress: "0",
|
|
||||||
})
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to create manager")
|
|
||||||
|
|
||||||
controller := &EphemeralRunnerSetReconciler{
|
controller := &EphemeralRunnerSetReconciler{
|
||||||
Client: mgr.GetClient(),
|
Client: mgr.GetClient(),
|
||||||
@@ -73,7 +54,7 @@ var _ = Describe("Test EphemeralRunnerSet controller", func() {
|
|||||||
Log: logf.Log,
|
Log: logf.Log,
|
||||||
ActionsClient: fake.NewMultiClient(),
|
ActionsClient: fake.NewMultiClient(),
|
||||||
}
|
}
|
||||||
err = controller.SetupWithManager(mgr)
|
err := controller.SetupWithManager(mgr)
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to setup controller")
|
Expect(err).NotTo(HaveOccurred(), "failed to setup controller")
|
||||||
|
|
||||||
ephemeralRunnerSet = &actionsv1alpha1.EphemeralRunnerSet{
|
ephemeralRunnerSet = &actionsv1alpha1.EphemeralRunnerSet{
|
||||||
@@ -103,19 +84,7 @@ var _ = Describe("Test EphemeralRunnerSet controller", func() {
|
|||||||
err = k8sClient.Create(ctx, ephemeralRunnerSet)
|
err = k8sClient.Create(ctx, ephemeralRunnerSet)
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to create EphemeralRunnerSet")
|
Expect(err).NotTo(HaveOccurred(), "failed to create EphemeralRunnerSet")
|
||||||
|
|
||||||
go func() {
|
startManagers(GinkgoT(), mgr)
|
||||||
defer GinkgoRecover()
|
|
||||||
|
|
||||||
err := mgr.Start(ctx)
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to start manager")
|
|
||||||
}()
|
|
||||||
})
|
|
||||||
|
|
||||||
AfterEach(func() {
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
err := k8sClient.Delete(ctx, autoscalingNS)
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to delete test namespace for EphemeralRunnerSet")
|
|
||||||
})
|
})
|
||||||
|
|
||||||
Context("When creating a new EphemeralRunnerSet", func() {
|
Context("When creating a new EphemeralRunnerSet", func() {
|
||||||
@@ -595,38 +564,15 @@ var _ = Describe("Test EphemeralRunnerSet controller", func() {
|
|||||||
|
|
||||||
var _ = Describe("Test EphemeralRunnerSet controller with proxy settings", func() {
|
var _ = Describe("Test EphemeralRunnerSet controller with proxy settings", func() {
|
||||||
var ctx context.Context
|
var ctx context.Context
|
||||||
var cancel context.CancelFunc
|
var mgr ctrl.Manager
|
||||||
autoscalingNS := new(corev1.Namespace)
|
var autoscalingNS *corev1.Namespace
|
||||||
ephemeralRunnerSet := new(actionsv1alpha1.EphemeralRunnerSet)
|
var ephemeralRunnerSet *actionsv1alpha1.EphemeralRunnerSet
|
||||||
configSecret := new(corev1.Secret)
|
var configSecret *corev1.Secret
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
ctx, cancel = context.WithCancel(context.TODO())
|
ctx = context.Background()
|
||||||
autoscalingNS = &corev1.Namespace{
|
autoscalingNS, mgr = createNamespace(GinkgoT(), k8sClient)
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "testns-autoscaling-runnerset" + RandStringRunes(5)},
|
configSecret = createDefaultSecret(GinkgoT(), k8sClient, autoscalingNS.Name)
|
||||||
}
|
|
||||||
|
|
||||||
err := k8sClient.Create(ctx, autoscalingNS)
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to create test namespace for EphemeralRunnerSet")
|
|
||||||
|
|
||||||
configSecret = &corev1.Secret{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "github-config-secret",
|
|
||||||
Namespace: autoscalingNS.Name,
|
|
||||||
},
|
|
||||||
Data: map[string][]byte{
|
|
||||||
"github_token": []byte(ephemeralRunnerSetTestGitHubToken),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
err = k8sClient.Create(ctx, configSecret)
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to create config secret")
|
|
||||||
|
|
||||||
mgr, err := ctrl.NewManager(cfg, ctrl.Options{
|
|
||||||
Namespace: autoscalingNS.Name,
|
|
||||||
MetricsBindAddress: "0",
|
|
||||||
})
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to create manager")
|
|
||||||
|
|
||||||
controller := &EphemeralRunnerSetReconciler{
|
controller := &EphemeralRunnerSetReconciler{
|
||||||
Client: mgr.GetClient(),
|
Client: mgr.GetClient(),
|
||||||
@@ -634,22 +580,10 @@ var _ = Describe("Test EphemeralRunnerSet controller with proxy settings", func(
|
|||||||
Log: logf.Log,
|
Log: logf.Log,
|
||||||
ActionsClient: actions.NewMultiClient("test", logr.Discard()),
|
ActionsClient: actions.NewMultiClient("test", logr.Discard()),
|
||||||
}
|
}
|
||||||
err = controller.SetupWithManager(mgr)
|
err := controller.SetupWithManager(mgr)
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to setup controller")
|
Expect(err).NotTo(HaveOccurred(), "failed to setup controller")
|
||||||
|
|
||||||
go func() {
|
startManagers(GinkgoT(), mgr)
|
||||||
defer GinkgoRecover()
|
|
||||||
|
|
||||||
err := mgr.Start(ctx)
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to start manager")
|
|
||||||
}()
|
|
||||||
})
|
|
||||||
|
|
||||||
AfterEach(func() {
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
err := k8sClient.Delete(ctx, autoscalingNS)
|
|
||||||
Expect(err).NotTo(HaveOccurred(), "failed to delete test namespace for EphemeralRunnerSet")
|
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should create a proxy secret and delete the proxy secreat after the runner-set is deleted", func() {
|
It("should create a proxy secret and delete the proxy secreat after the runner-set is deleted", func() {
|
||||||
@@ -904,3 +838,148 @@ var _ = Describe("Test EphemeralRunnerSet controller with proxy settings", func(
|
|||||||
).Should(BeEquivalentTo(true))
|
).Should(BeEquivalentTo(true))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
var _ = Describe("Test EphemeralRunnerSet controller with custom root CA", func() {
|
||||||
|
var ctx context.Context
|
||||||
|
var mgr ctrl.Manager
|
||||||
|
var autoscalingNS *corev1.Namespace
|
||||||
|
var ephemeralRunnerSet *actionsv1alpha1.EphemeralRunnerSet
|
||||||
|
var configSecret *corev1.Secret
|
||||||
|
var rootCAConfigMap *corev1.ConfigMap
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
ctx = context.Background()
|
||||||
|
autoscalingNS, mgr = createNamespace(GinkgoT(), k8sClient)
|
||||||
|
configSecret = createDefaultSecret(GinkgoT(), k8sClient, autoscalingNS.Name)
|
||||||
|
|
||||||
|
cert, err := os.ReadFile(filepath.Join(
|
||||||
|
"../../",
|
||||||
|
"github",
|
||||||
|
"actions",
|
||||||
|
"testdata",
|
||||||
|
"rootCA.crt",
|
||||||
|
))
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "failed to read root CA cert")
|
||||||
|
rootCAConfigMap = &corev1.ConfigMap{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "root-ca-configmap",
|
||||||
|
Namespace: autoscalingNS.Name,
|
||||||
|
},
|
||||||
|
Data: map[string]string{
|
||||||
|
"rootCA.crt": string(cert),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
err = k8sClient.Create(ctx, rootCAConfigMap)
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "failed to create configmap with root CAs")
|
||||||
|
|
||||||
|
controller := &EphemeralRunnerSetReconciler{
|
||||||
|
Client: mgr.GetClient(),
|
||||||
|
Scheme: mgr.GetScheme(),
|
||||||
|
Log: logf.Log,
|
||||||
|
ActionsClient: actions.NewMultiClient("test", logr.Discard()),
|
||||||
|
}
|
||||||
|
err = controller.SetupWithManager(mgr)
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "failed to setup controller")
|
||||||
|
|
||||||
|
startManagers(GinkgoT(), mgr)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should be able to make requests to a server using root CAs", func() {
|
||||||
|
certsFolder := filepath.Join(
|
||||||
|
"../../",
|
||||||
|
"github",
|
||||||
|
"actions",
|
||||||
|
"testdata",
|
||||||
|
)
|
||||||
|
certPath := filepath.Join(certsFolder, "server.crt")
|
||||||
|
keyPath := filepath.Join(certsFolder, "server.key")
|
||||||
|
|
||||||
|
serverSuccessfullyCalled := false
|
||||||
|
server := testserver.NewUnstarted(GinkgoT(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
serverSuccessfullyCalled = true
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
}))
|
||||||
|
cert, err := tls.LoadX509KeyPair(certPath, keyPath)
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "failed to load server cert")
|
||||||
|
|
||||||
|
server.TLS = &tls.Config{Certificates: []tls.Certificate{cert}}
|
||||||
|
server.StartTLS()
|
||||||
|
|
||||||
|
ephemeralRunnerSet = &actionsv1alpha1.EphemeralRunnerSet{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "test-asrs",
|
||||||
|
Namespace: autoscalingNS.Name,
|
||||||
|
},
|
||||||
|
Spec: actionsv1alpha1.EphemeralRunnerSetSpec{
|
||||||
|
Replicas: 1,
|
||||||
|
EphemeralRunnerSpec: actionsv1alpha1.EphemeralRunnerSpec{
|
||||||
|
GitHubConfigUrl: server.ConfigURLForOrg("my-org"),
|
||||||
|
GitHubConfigSecret: configSecret.Name,
|
||||||
|
GitHubServerTLS: &actionsv1alpha1.GitHubServerTLSConfig{
|
||||||
|
CertificateFrom: &v1alpha1.TLSCertificateSource{
|
||||||
|
ConfigMapKeyRef: &corev1.ConfigMapKeySelector{
|
||||||
|
LocalObjectReference: corev1.LocalObjectReference{
|
||||||
|
Name: rootCAConfigMap.Name,
|
||||||
|
},
|
||||||
|
Key: "rootCA.crt",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
RunnerScaleSetId: 100,
|
||||||
|
PodTemplateSpec: corev1.PodTemplateSpec{
|
||||||
|
Spec: corev1.PodSpec{
|
||||||
|
Containers: []corev1.Container{
|
||||||
|
{
|
||||||
|
Name: "runner",
|
||||||
|
Image: "ghcr.io/actions/runner",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
err = k8sClient.Create(ctx, ephemeralRunnerSet)
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "failed to create EphemeralRunnerSet")
|
||||||
|
|
||||||
|
runnerList := new(actionsv1alpha1.EphemeralRunnerList)
|
||||||
|
Eventually(func() (int, error) {
|
||||||
|
err := k8sClient.List(ctx, runnerList, client.InNamespace(ephemeralRunnerSet.Namespace))
|
||||||
|
if err != nil {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return len(runnerList.Items), nil
|
||||||
|
},
|
||||||
|
ephemeralRunnerSetTestTimeout,
|
||||||
|
ephemeralRunnerSetTestInterval,
|
||||||
|
).Should(BeEquivalentTo(1), "failed to create ephemeral runner")
|
||||||
|
|
||||||
|
runner := runnerList.Items[0].DeepCopy()
|
||||||
|
Expect(runner.Spec.GitHubServerTLS).NotTo(BeNil(), "runner tls config should not be nil")
|
||||||
|
Expect(runner.Spec.GitHubServerTLS).To(BeEquivalentTo(ephemeralRunnerSet.Spec.EphemeralRunnerSpec.GitHubServerTLS), "runner tls config should be correct")
|
||||||
|
|
||||||
|
runner.Status.Phase = corev1.PodRunning
|
||||||
|
runner.Status.RunnerId = 100
|
||||||
|
err = k8sClient.Status().Patch(ctx, runner, client.MergeFrom(&runnerList.Items[0]))
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "failed to update ephemeral runner status")
|
||||||
|
|
||||||
|
updatedRunnerSet := new(actionsv1alpha1.EphemeralRunnerSet)
|
||||||
|
err = k8sClient.Get(ctx, client.ObjectKey{Namespace: ephemeralRunnerSet.Namespace, Name: ephemeralRunnerSet.Name}, updatedRunnerSet)
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "failed to get EphemeralRunnerSet")
|
||||||
|
|
||||||
|
updatedRunnerSet.Spec.Replicas = 0
|
||||||
|
err = k8sClient.Update(ctx, updatedRunnerSet)
|
||||||
|
Expect(err).NotTo(HaveOccurred(), "failed to update EphemeralRunnerSet")
|
||||||
|
|
||||||
|
// wait for server to be called
|
||||||
|
Eventually(
|
||||||
|
func() bool {
|
||||||
|
return serverSuccessfullyCalled
|
||||||
|
},
|
||||||
|
autoscalingRunnerSetTestTimeout,
|
||||||
|
1*time.Nanosecond,
|
||||||
|
).Should(BeTrue(), "server was not called")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|||||||
71
controllers/actions.github.com/helpers_test.go
Normal file
71
controllers/actions.github.com/helpers_test.go
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
package actionsgithubcom
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/onsi/ginkgo/v2"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
ctrl "sigs.k8s.io/controller-runtime"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/manager"
|
||||||
|
)
|
||||||
|
|
||||||
|
const defaultGitHubToken = "gh_token"
|
||||||
|
|
||||||
|
func startManagers(t ginkgo.GinkgoTInterface, first manager.Manager, others ...manager.Manager) {
|
||||||
|
for _, mgr := range append([]manager.Manager{first}, others...) {
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
|
||||||
|
g, ctx := errgroup.WithContext(ctx)
|
||||||
|
g.Go(func() error {
|
||||||
|
return mgr.Start(ctx)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
cancel()
|
||||||
|
require.NoError(t, g.Wait())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createNamespace(t ginkgo.GinkgoTInterface, client client.Client) (*corev1.Namespace, manager.Manager) {
|
||||||
|
ns := &corev1.Namespace{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "testns-autoscaling" + RandStringRunes(5)},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := k8sClient.Create(context.Background(), ns)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
err := k8sClient.Delete(context.Background(), ns)
|
||||||
|
require.NoError(t, err)
|
||||||
|
})
|
||||||
|
|
||||||
|
mgr, err := ctrl.NewManager(cfg, ctrl.Options{
|
||||||
|
Namespace: ns.Name,
|
||||||
|
MetricsBindAddress: "0",
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
return ns, mgr
|
||||||
|
}
|
||||||
|
|
||||||
|
func createDefaultSecret(t ginkgo.GinkgoTInterface, client client.Client, namespace string) *corev1.Secret {
|
||||||
|
secret := &corev1.Secret{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "github-config-secret",
|
||||||
|
Namespace: namespace,
|
||||||
|
},
|
||||||
|
Data: map[string][]byte{
|
||||||
|
"github_token": []byte(defaultGitHubToken),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := k8sClient.Create(context.Background(), secret)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
return secret
|
||||||
|
}
|
||||||
@@ -14,16 +14,20 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// secret constants
|
||||||
const (
|
const (
|
||||||
jitTokenKey = "jitToken"
|
jitTokenKey = "jitToken"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// labels applied to resources
|
||||||
|
const (
|
||||||
|
LabelKeyAutoScaleRunnerSetName = "auto-scaling-runner-set-name"
|
||||||
|
LabelKeyAutoScaleRunnerSetNamespace = "auto-scaling-runner-set-namespace"
|
||||||
|
)
|
||||||
|
|
||||||
type resourceBuilder struct{}
|
type resourceBuilder struct{}
|
||||||
|
|
||||||
func (b *resourceBuilder) newScaleSetListenerPod(autoscalingListener *v1alpha1.AutoscalingListener, serviceAccount *corev1.ServiceAccount, secret *corev1.Secret, envs ...corev1.EnvVar) *corev1.Pod {
|
func (b *resourceBuilder) newScaleSetListenerPod(autoscalingListener *v1alpha1.AutoscalingListener, serviceAccount *corev1.ServiceAccount, secret *corev1.Secret, envs ...corev1.EnvVar) *corev1.Pod {
|
||||||
newLabels := map[string]string{}
|
|
||||||
newLabels[scaleSetListenerLabel] = fmt.Sprintf("%v-%v", autoscalingListener.Spec.AutoscalingRunnerSetNamespace, autoscalingListener.Spec.AutoscalingRunnerSetName)
|
|
||||||
|
|
||||||
listenerEnv := []corev1.EnvVar{
|
listenerEnv := []corev1.EnvVar{
|
||||||
{
|
{
|
||||||
Name: "GITHUB_CONFIGURE_URL",
|
Name: "GITHUB_CONFIGURE_URL",
|
||||||
@@ -133,7 +137,10 @@ func (b *resourceBuilder) newScaleSetListenerPod(autoscalingListener *v1alpha1.A
|
|||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: autoscalingListener.Name,
|
Name: autoscalingListener.Name,
|
||||||
Namespace: autoscalingListener.Namespace,
|
Namespace: autoscalingListener.Namespace,
|
||||||
Labels: newLabels,
|
Labels: map[string]string{
|
||||||
|
LabelKeyAutoScaleRunnerSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
||||||
|
LabelKeyAutoScaleRunnerSetName: autoscalingListener.Spec.AutoscalingRunnerSetName,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Spec: podSpec,
|
Spec: podSpec,
|
||||||
}
|
}
|
||||||
@@ -180,8 +187,8 @@ func (b *resourceBuilder) newScaleSetListenerServiceAccount(autoscalingListener
|
|||||||
Name: scaleSetListenerServiceAccountName(autoscalingListener),
|
Name: scaleSetListenerServiceAccountName(autoscalingListener),
|
||||||
Namespace: autoscalingListener.Namespace,
|
Namespace: autoscalingListener.Namespace,
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
"auto-scaling-runner-set-namespace": autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
LabelKeyAutoScaleRunnerSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
||||||
"auto-scaling-runner-set-name": autoscalingListener.Spec.AutoscalingRunnerSetName,
|
LabelKeyAutoScaleRunnerSetName: autoscalingListener.Spec.AutoscalingRunnerSetName,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -195,8 +202,8 @@ func (b *resourceBuilder) newScaleSetListenerRole(autoscalingListener *v1alpha1.
|
|||||||
Name: scaleSetListenerRoleName(autoscalingListener),
|
Name: scaleSetListenerRoleName(autoscalingListener),
|
||||||
Namespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
Namespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
"auto-scaling-runner-set-namespace": autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
LabelKeyAutoScaleRunnerSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
||||||
"auto-scaling-runner-set-name": autoscalingListener.Spec.AutoscalingRunnerSetName,
|
LabelKeyAutoScaleRunnerSetName: autoscalingListener.Spec.AutoscalingRunnerSetName,
|
||||||
"auto-scaling-listener-namespace": autoscalingListener.Namespace,
|
"auto-scaling-listener-namespace": autoscalingListener.Namespace,
|
||||||
"auto-scaling-listener-name": autoscalingListener.Name,
|
"auto-scaling-listener-name": autoscalingListener.Name,
|
||||||
"role-policy-rules-hash": rulesHash,
|
"role-policy-rules-hash": rulesHash,
|
||||||
@@ -229,8 +236,8 @@ func (b *resourceBuilder) newScaleSetListenerRoleBinding(autoscalingListener *v1
|
|||||||
Name: scaleSetListenerRoleName(autoscalingListener),
|
Name: scaleSetListenerRoleName(autoscalingListener),
|
||||||
Namespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
Namespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
"auto-scaling-runner-set-namespace": autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
LabelKeyAutoScaleRunnerSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
||||||
"auto-scaling-runner-set-name": autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
LabelKeyAutoScaleRunnerSetName: autoscalingListener.Spec.AutoscalingRunnerSetName,
|
||||||
"auto-scaling-listener-namespace": autoscalingListener.Namespace,
|
"auto-scaling-listener-namespace": autoscalingListener.Namespace,
|
||||||
"auto-scaling-listener-name": autoscalingListener.Name,
|
"auto-scaling-listener-name": autoscalingListener.Name,
|
||||||
"role-binding-role-ref-hash": roleRefHash,
|
"role-binding-role-ref-hash": roleRefHash,
|
||||||
@@ -252,8 +259,8 @@ func (b *resourceBuilder) newScaleSetListenerSecretMirror(autoscalingListener *v
|
|||||||
Name: scaleSetListenerSecretMirrorName(autoscalingListener),
|
Name: scaleSetListenerSecretMirrorName(autoscalingListener),
|
||||||
Namespace: autoscalingListener.Namespace,
|
Namespace: autoscalingListener.Namespace,
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
"auto-scaling-runner-set-namespace": autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
LabelKeyAutoScaleRunnerSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
|
||||||
"auto-scaling-runner-set-name": autoscalingListener.Spec.AutoscalingRunnerSetName,
|
LabelKeyAutoScaleRunnerSetName: autoscalingListener.Spec.AutoscalingRunnerSetName,
|
||||||
"secret-data-hash": dataHash,
|
"secret-data-hash": dataHash,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -283,8 +290,8 @@ func (b *resourceBuilder) newAutoScalingListener(autoscalingRunnerSet *v1alpha1.
|
|||||||
Name: scaleSetListenerName(autoscalingRunnerSet),
|
Name: scaleSetListenerName(autoscalingRunnerSet),
|
||||||
Namespace: namespace,
|
Namespace: namespace,
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
"auto-scaling-runner-set-namespace": autoscalingRunnerSet.Namespace,
|
LabelKeyAutoScaleRunnerSetNamespace: autoscalingRunnerSet.Namespace,
|
||||||
"auto-scaling-runner-set-name": autoscalingRunnerSet.Name,
|
LabelKeyAutoScaleRunnerSetName: autoscalingRunnerSet.Name,
|
||||||
LabelKeyRunnerSpecHash: autoscalingRunnerSet.ListenerSpecHash(),
|
LabelKeyRunnerSpecHash: autoscalingRunnerSet.ListenerSpecHash(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -300,6 +307,7 @@ func (b *resourceBuilder) newAutoScalingListener(autoscalingRunnerSet *v1alpha1.
|
|||||||
Image: image,
|
Image: image,
|
||||||
ImagePullSecrets: imagePullSecrets,
|
ImagePullSecrets: imagePullSecrets,
|
||||||
Proxy: autoscalingRunnerSet.Spec.Proxy,
|
Proxy: autoscalingRunnerSet.Spec.Proxy,
|
||||||
|
GitHubServerTLS: autoscalingRunnerSet.Spec.GitHubServerTLS,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,9 +39,11 @@ import (
|
|||||||
// These tests use Ginkgo (BDD-style Go testing framework). Refer to
|
// These tests use Ginkgo (BDD-style Go testing framework). Refer to
|
||||||
// http://onsi.github.io/ginkgo/ to learn more about Ginkgo.
|
// http://onsi.github.io/ginkgo/ to learn more about Ginkgo.
|
||||||
|
|
||||||
var cfg *rest.Config
|
var (
|
||||||
var k8sClient client.Client
|
cfg *rest.Config
|
||||||
var testEnv *envtest.Environment
|
k8sClient client.Client
|
||||||
|
testEnv *envtest.Environment
|
||||||
|
)
|
||||||
|
|
||||||
func TestAPIs(t *testing.T) {
|
func TestAPIs(t *testing.T) {
|
||||||
RegisterFailHandler(Fail)
|
RegisterFailHandler(Fail)
|
||||||
|
|||||||
@@ -157,8 +157,8 @@ func (s *batchScaler) batchScale(ctx context.Context, batch batchScaleOperation)
|
|||||||
|
|
||||||
scale.log.V(2).Info("Adding capacity reservation", "amount", amount)
|
scale.log.V(2).Info("Adding capacity reservation", "amount", amount)
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
if amount > 0 {
|
if amount > 0 {
|
||||||
now := time.Now()
|
|
||||||
copy.Spec.CapacityReservations = append(copy.Spec.CapacityReservations, v1alpha1.CapacityReservation{
|
copy.Spec.CapacityReservations = append(copy.Spec.CapacityReservations, v1alpha1.CapacityReservation{
|
||||||
EffectiveTime: metav1.Time{Time: now},
|
EffectiveTime: metav1.Time{Time: now},
|
||||||
ExpirationTime: metav1.Time{Time: now.Add(scale.trigger.Duration.Duration)},
|
ExpirationTime: metav1.Time{Time: now.Add(scale.trigger.Duration.Duration)},
|
||||||
@@ -169,12 +169,48 @@ func (s *batchScaler) batchScale(ctx context.Context, batch batchScaleOperation)
|
|||||||
} else if amount < 0 {
|
} else if amount < 0 {
|
||||||
var reservations []v1alpha1.CapacityReservation
|
var reservations []v1alpha1.CapacityReservation
|
||||||
|
|
||||||
var found bool
|
var (
|
||||||
|
found bool
|
||||||
|
foundIdx int
|
||||||
|
)
|
||||||
|
|
||||||
for _, r := range copy.Spec.CapacityReservations {
|
for i, r := range copy.Spec.CapacityReservations {
|
||||||
|
r := r
|
||||||
if !found && r.Replicas+amount == 0 {
|
if !found && r.Replicas+amount == 0 {
|
||||||
found = true
|
found = true
|
||||||
|
foundIdx = i
|
||||||
} else {
|
} else {
|
||||||
|
// Note that we nil-check max replicas because this "fix" is needed only when there is the upper limit of runners.
|
||||||
|
// In other words, you don't need to reset effective time and expiration time when there is no max replicas.
|
||||||
|
// That's because the desired replicas would already contain the reservation since it's creation.
|
||||||
|
if found && copy.Spec.MaxReplicas != nil && i > foundIdx+*copy.Spec.MaxReplicas {
|
||||||
|
// Update newer CapacityReservations' time to now to trigger reconcile
|
||||||
|
// Without this, we might stuck in minReplicas unnecessarily long.
|
||||||
|
// That is, we might not scale up after an ephemeral runner has been deleted
|
||||||
|
// until a new scale up, all runners finish, or after DefaultRunnerPodRecreationDelayAfterWebhookScale
|
||||||
|
// See https://github.com/actions/actions-runner-controller/issues/2254 for more context.
|
||||||
|
r.EffectiveTime = metav1.Time{Time: now}
|
||||||
|
|
||||||
|
// We also reset the scale trigger expiration time, so that you don't need to tweak
|
||||||
|
// scale trigger duratoin depending on maxReplicas.
|
||||||
|
// A detailed explanation follows.
|
||||||
|
//
|
||||||
|
// Let's say maxReplicas=3 and the workflow job of status=canceled result in deleting the first capacity reservation hence i=0.
|
||||||
|
// We are interested in at least four reservations and runners:
|
||||||
|
// i=0 - already included in the current desired replicas, but just got deleted
|
||||||
|
// i=1-2 - already included in the current desired replicas
|
||||||
|
// i=3 - not yet included in the current desired replicas, might have been expired while waiting in the queue
|
||||||
|
//
|
||||||
|
// i=3 is especially important here- If we didn't reset the expiration time of 3rd reservation,
|
||||||
|
// it might expire before a corresponding runner is created, due to the delay between the expiration timer starts and the runner is created.
|
||||||
|
//
|
||||||
|
// Why is there such delay? Because ARC implements the scale duration and expiration as such...
|
||||||
|
// The expiration timer starts when the reservation is created, while the runner is created only after the corresponding reservation fits within maxReplicas.
|
||||||
|
//
|
||||||
|
// We address that, by resetting the expiration time for fourth(i=3 in the above example) and subsequent reservations when the first reservation gets cancelled.
|
||||||
|
r.ExpirationTime = metav1.Time{Time: now.Add(scale.trigger.Duration.Duration)}
|
||||||
|
}
|
||||||
|
|
||||||
reservations = append(reservations, r)
|
reservations = append(reservations, r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -491,7 +491,7 @@ In case you have a more complex scenario, try writing two or more entries under
|
|||||||
|
|
||||||
The earlier entry is prioritized higher than later entries. So you usually define one-time overrides at the top of your list, then yearly, monthly, weekly, and lastly daily overrides.
|
The earlier entry is prioritized higher than later entries. So you usually define one-time overrides at the top of your list, then yearly, monthly, weekly, and lastly daily overrides.
|
||||||
|
|
||||||
A common use case for this may be to have 1 override to scale to 0 during the week outside of core business hours and another override to scale to 0 during all hours of the weekend.
|
A common use case for this may be to have 1 override to scale to 0 during non-working hours and another override to scale to 0 on weekends.
|
||||||
|
|
||||||
## Configuring automatic termination
|
## Configuring automatic termination
|
||||||
|
|
||||||
@@ -693,7 +693,7 @@ Note that this feature is currently intended for use with runner pods being term
|
|||||||
For example, a runner pod can be terminated prematurely by cluster-autoscaler when it's about to terminate the node on cluster scale down.
|
For example, a runner pod can be terminated prematurely by cluster-autoscaler when it's about to terminate the node on cluster scale down.
|
||||||
All the variants of RunnerDeployment and RunnerSet managed runner pods, including runners with dockerd sidecars, rootless and rootful dind runners are affected by it. For dind runner pods only, you can use this feature to fix or alleviate the issue.
|
All the variants of RunnerDeployment and RunnerSet managed runner pods, including runners with dockerd sidecars, rootless and rootful dind runners are affected by it. For dind runner pods only, you can use this feature to fix or alleviate the issue.
|
||||||
|
|
||||||
To be clear, an increase/decrease in the desired replicas of RunnerDeployment and RunnerSet will never result in worklfow jobs being termianted prematurely.
|
To be clear, an increase/decrease in the desired replicas of RunnerDeployment and RunnerSet will never result in worklfow jobs being terminated prematurely.
|
||||||
That's because it's handled BEFORE the runner pod is terminated, by ARC respective controller.
|
That's because it's handled BEFORE the runner pod is terminated, by ARC respective controller.
|
||||||
|
|
||||||
For anyone interested in improving it, adding a dedicated pod finalizer for this issue will never work.
|
For anyone interested in improving it, adding a dedicated pod finalizer for this issue will never work.
|
||||||
|
|||||||
@@ -1,211 +1 @@
|
|||||||
# Autoscaling Runner Scale Sets mode
|
301 - MOVED TO [../gha-runner-scale-set-controller/README.md](../gha-runner-scale-set-controller/README.md)
|
||||||
|
|
||||||
**⚠️ This mode is currently only available for a limited number of organizations.**
|
|
||||||
|
|
||||||
This new autoscaling mode brings numerous enhancements (described in the following sections) that will make your experience more reliable and secure.
|
|
||||||
|
|
||||||
## How it works
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
In addition to the increased reliability of the automatic scaling, we have worked on these improvements:
|
|
||||||
|
|
||||||
- No longer require cert-manager as a prerequisite for installing actions-runner-controller
|
|
||||||
- Reliable scale-up based on job demands and scale-down to zero runner pods
|
|
||||||
- Reduce API requests to `api.github.com`, no more API rate-limiting problems
|
|
||||||
- The GitHub Personal Access Token (PAT) or the GitHub App installation token is no longer passed to the runner pod for runner registration
|
|
||||||
- Maximum flexibility for customizing your runner pod template
|
|
||||||
|
|
||||||
### Demo
|
|
||||||
|
|
||||||
https://user-images.githubusercontent.com/568794/212668313-8946ddc5-60c1-461f-a73e-27f5e8c75720.mp4
|
|
||||||
|
|
||||||
## Setup
|
|
||||||
|
|
||||||
### Prerequisites
|
|
||||||
|
|
||||||
1. Create a K8s cluster, if not available.
|
|
||||||
- If you don't have a K8s cluster, you can install a local environment using minikube. See [installing minikube](https://minikube.sigs.k8s.io/docs/start/).
|
|
||||||
1. Install helm 3, if not available. See [installing Helm](https://helm.sh/docs/intro/install/).
|
|
||||||
|
|
||||||
### Install actions-runner-controller
|
|
||||||
|
|
||||||
1. Install actions-runner-controller using helm 3. For additional configuration options, see [values.yaml](https://github.com/actions/actions-runner-controller/blob/master/charts/actions-runner-controller-2/values.yaml)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
NAMESPACE="arc-systems"
|
|
||||||
helm install arc \
|
|
||||||
--namespace "${NAMESPACE}" \
|
|
||||||
--create-namespace \
|
|
||||||
oci://ghcr.io/actions/actions-runner-controller-charts/actions-runner-controller-2 \
|
|
||||||
--version 0.2.0
|
|
||||||
```
|
|
||||||
|
|
||||||
1. Generate a Personal Access Token (PAT) or create and install a GitHub App. See [Creating a personal access token](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token) and [Creating a GitHub App](https://docs.github.com/en/developers/apps/creating-a-github-app).
|
|
||||||
- ℹ For the list of required permissions, see [Authenticating to the GitHub API](https://github.com/actions/actions-runner-controller/blob/master/docs/authenticating-to-the-github-api.md#authenticating-to-the-github-api).
|
|
||||||
|
|
||||||
1. You're ready to install the autoscaling runner set. For additional configuration options, see [values.yaml](https://github.com/actions/actions-runner-controller/blob/master/charts/auto-scaling-runner-set/values.yaml)
|
|
||||||
- ℹ **Choose your installation name carefully**, you will use it as the value of `runs-on` in your workflow.
|
|
||||||
- ℹ **We recommend you choose a unique namespace in the following steps**. As a good security measure, it's best to have your runner pods created in a different namespace than the one containing the manager and listener pods.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Using a Personal Access Token (PAT)
|
|
||||||
INSTALLATION_NAME="arc-runner-set"
|
|
||||||
NAMESPACE="arc-runners"
|
|
||||||
GITHUB_CONFIG_URL="https://github.com/<your_enterprise/org/repo>"
|
|
||||||
GITHUB_PAT="<PAT>"
|
|
||||||
helm install "${INSTALLATION_NAME}" \
|
|
||||||
--namespace "${NAMESPACE}" \
|
|
||||||
--create-namespace \
|
|
||||||
--set githubConfigUrl="${GITHUB_CONFIG_URL}" \
|
|
||||||
--set githubConfigSecret.github_token="${GITHUB_PAT}" \
|
|
||||||
oci://ghcr.io/actions/actions-runner-controller-charts/auto-scaling-runner-set --version 0.2.0
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Using a GitHub App
|
|
||||||
INSTALLATION_NAME="arc-runner-set"
|
|
||||||
NAMESPACE="arc-runners"
|
|
||||||
GITHUB_CONFIG_URL="https://github.com/<your_enterprise/org/repo>"
|
|
||||||
GITHUB_APP_ID="<GITHUB_APP_ID>"
|
|
||||||
GITHUB_APP_INSTALLATION_ID="<GITHUB_APP_INSTALLATION_ID>"
|
|
||||||
GITHUB_APP_PRIVATE_KEY="<GITHUB_APP_PRIVATE_KEY>"
|
|
||||||
helm install arc-runner-set \
|
|
||||||
--namespace "${NAMESPACE}" \
|
|
||||||
--create-namespace \
|
|
||||||
--set githubConfigUrl="${GITHUB_CONFIG_URL}" \
|
|
||||||
--set githubConfigSecret.github_app_id="${GITHUB_APP_ID}" \
|
|
||||||
--set githubConfigSecret.github_app_installation_id="${GITHUB_APP_INSTALLATION_ID}" \
|
|
||||||
--set githubConfigSecret.github_app_private_key="${GITHUB_APP_PRIVATE_KEY}" \
|
|
||||||
oci://ghcr.io/actions/actions-runner-controller-charts/auto-scaling-runner-set --version 0.2.0
|
|
||||||
```
|
|
||||||
|
|
||||||
1. Check your installation. If everything went well, you should see the following:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ helm list -n "${NAMESPACE}"
|
|
||||||
|
|
||||||
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
|
|
||||||
arc arc-systems 1 2023-01-18 10:03:36.610534934 +0000 UTC deployed actions-runner-controller-2-0.2.0 preview
|
|
||||||
arc-runner-set arc-systems 1 2023-01-18 10:20:14.795285645 +0000 UTC deployed auto-scaling-runner-set-0.2.0 0.2.0
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ kubectl get pods -n "${NAMESPACE}"
|
|
||||||
|
|
||||||
NAME READY STATUS RESTARTS AGE
|
|
||||||
arc-actions-runner-controller-2-8c74b6f95-gr7zr 1/1 Running 0 20m
|
|
||||||
arc-runner-set-6cd58d58-listener 1/1 Running 0 21s
|
|
||||||
```
|
|
||||||
|
|
||||||
1. In a repository, create a simple test workflow as follows. The `runs-on` value should match the helm installation name you used in the previous step.
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
name: Test workflow
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test:
|
|
||||||
runs-on: arc-runner-set
|
|
||||||
steps:
|
|
||||||
- name: Hello world
|
|
||||||
run: echo "Hello world"
|
|
||||||
```
|
|
||||||
|
|
||||||
1. Run the workflow. You should see the runner pod being created and the workflow being executed.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ kubectl get pods -A
|
|
||||||
|
|
||||||
NAMESPACE NAME READY STATUS RESTARTS AGE
|
|
||||||
arc-systems arc-actions-runner-controller-2-8c74b6f95-gr7zr 1/1 Running 0 27m
|
|
||||||
arc-systems arc-runner-set-6cd58d58-listener 1/1 Running 0 7m52s
|
|
||||||
arc-runners arc-runner-set-rmrgw-runner-p9p5n 1/1 Running 0 21s
|
|
||||||
```
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Check the logs
|
|
||||||
|
|
||||||
You can check the logs of the controller pod using the following command:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Controller logs
|
|
||||||
$ kubectl logs -n "${NAMESPACE}" -l app.kubernetes.io/name=actions-runner-controller-2
|
|
||||||
|
|
||||||
# Runner set listener logs
|
|
||||||
kubectl logs -n "${NAMESPACE}" -l runner-scale-set-listener=arc-systems-arc-runner-set
|
|
||||||
```
|
|
||||||
|
|
||||||
### If you installed the autoscaling runner set, but the listener pod is not created
|
|
||||||
|
|
||||||
Verify that the secret you provided is correct and that the `githubConfigUrl` you provided is accurate.
|
|
||||||
|
|
||||||
## Changelog
|
|
||||||
|
|
||||||
### v0.2.0
|
|
||||||
|
|
||||||
#### Major changes
|
|
||||||
|
|
||||||
1. Added proxy support for the controller and the runner pods, see the new helm chart fields [#2286](https://github.com/actions/actions-runner-controller/pull/2286)
|
|
||||||
1. Added the abiilty to provide a pre-defined kubernetes secret for the auto scaling runner set helm chart [#2234](https://github.com/actions/actions-runner-controller/pull/2234)
|
|
||||||
1. Enhanced security posture by removing un-required permissions for the manager-role [#2260](https://github.com/actions/actions-runner-controller/pull/2260)
|
|
||||||
1. Enhanced our logging by returning an error when a runner group is defined in the values file but it's not created in GitHub [#2215](https://github.com/actions/actions-runner-controller/pull/2215)
|
|
||||||
1. Fixed helm charts issues that were preventing the use of DinD [#2291](https://github.com/actions/actions-runner-controller/pull/2291)
|
|
||||||
1. Fixed a bug that was preventing runner scale from being removed from the backend when they were deleted from the cluster [#2255](https://github.com/actions/actions-runner-controller/pull/2255) [#2223](https://github.com/actions/actions-runner-controller/pull/2223)
|
|
||||||
1. Fixed bugs with the helm chart definitions preventing certain values from being set [#2222](https://github.com/actions/actions-runner-controller/pull/2222)
|
|
||||||
1. Fixed a bug that prevented the configuration of a runner group for a runner scale set [#2216](https://github.com/actions/actions-runner-controller/pull/2216)
|
|
||||||
|
|
||||||
#### Log
|
|
||||||
|
|
||||||
- [1c7b7f4](https://github.com/actions/actions-runner-controller/commit/1c7b7f4) Bump arc-2 chart version and prepare 0.2.0 release [#2313](https://github.com/actions/actions-runner-controller/pull/2313)
|
|
||||||
- [73e22a1](https://github.com/actions/actions-runner-controller/commit/73e22a1) Disable metrics serving in proxy tests [#2307](https://github.com/actions/actions-runner-controller/pull/2307)
|
|
||||||
- [9b44f00](https://github.com/actions/actions-runner-controller/commit/9b44f00) Documentation corrections [#2116](https://github.com/actions/actions-runner-controller/pull/2116)
|
|
||||||
- [6b4250c](https://github.com/actions/actions-runner-controller/commit/6b4250c) Add support for proxy [#2286](https://github.com/actions/actions-runner-controller/pull/2286)
|
|
||||||
- [ced8822](https://github.com/actions/actions-runner-controller/commit/ced8822) Resolves the erroneous webhook scale down due to check runs [#2119](https://github.com/actions/actions-runner-controller/pull/2119)
|
|
||||||
- [44c06c2](https://github.com/actions/actions-runner-controller/commit/44c06c2) fix: case-insensitive webhook label matching [#2302](https://github.com/actions/actions-runner-controller/pull/2302)
|
|
||||||
- [4103fe3](https://github.com/actions/actions-runner-controller/commit/4103fe3) Use DOCKER_IMAGE_NAME instead of NAME to avoid conflict. [#2303](https://github.com/actions/actions-runner-controller/pull/2303)
|
|
||||||
- [a44fe04](https://github.com/actions/actions-runner-controller/commit/a44fe04) Fix manager crashloopback for ARC deployments without scaleset-related controllers [#2293](https://github.com/actions/actions-runner-controller/pull/2293)
|
|
||||||
- [274d0c8](https://github.com/actions/actions-runner-controller/commit/274d0c8) Added ability to configure log level from chart values [#2252](https://github.com/actions/actions-runner-controller/pull/2252)
|
|
||||||
- [256e08e](https://github.com/actions/actions-runner-controller/commit/256e08e) Ask runner to wait for docker daemon from DinD. [#2292](https://github.com/actions/actions-runner-controller/pull/2292)
|
|
||||||
- [f677fd5](https://github.com/actions/actions-runner-controller/commit/f677fd5) doc: Fix chart name for helm commands in docs [#2287](https://github.com/actions/actions-runner-controller/pull/2287)
|
|
||||||
- [d962714](https://github.com/actions/actions-runner-controller/commit/d962714) Fix helm chart when containerMode.type=dind. [#2291](https://github.com/actions/actions-runner-controller/pull/2291)
|
|
||||||
- [3886f28](https://github.com/actions/actions-runner-controller/commit/3886f28) Add EKS test environment Terraform templates [#2290](https://github.com/actions/actions-runner-controller/pull/2290)
|
|
||||||
- [dab9004](https://github.com/actions/actions-runner-controller/commit/dab9004) Added workflow to be triggered via rest api dispatch in e2e test [#2283](https://github.com/actions/actions-runner-controller/pull/2283)
|
|
||||||
- [dd8ec1a](https://github.com/actions/actions-runner-controller/commit/dd8ec1a) Add testserver package [#2281](https://github.com/actions/actions-runner-controller/pull/2281)
|
|
||||||
- [8e52a6d](https://github.com/actions/actions-runner-controller/commit/8e52a6d) EphemeralRunner: On cleanup, if pod is pending, delete from service [#2255](https://github.com/actions/actions-runner-controller/pull/2255)
|
|
||||||
- [9990243](https://github.com/actions/actions-runner-controller/commit/9990243) Early return if finalizer does not exist to make it more readable [#2262](https://github.com/actions/actions-runner-controller/pull/2262)
|
|
||||||
- [0891981](https://github.com/actions/actions-runner-controller/commit/0891981) Port ADRs from internal repo [#2267](https://github.com/actions/actions-runner-controller/pull/2267)
|
|
||||||
- [facae69](https://github.com/actions/actions-runner-controller/commit/facae69) Remove un-required permissions for the manager-role of the new `AutoScalingRunnerSet` [#2260](https://github.com/actions/actions-runner-controller/pull/2260)
|
|
||||||
- [8f62e35](https://github.com/actions/actions-runner-controller/commit/8f62e35) Add options to multi client [#2257](https://github.com/actions/actions-runner-controller/pull/2257)
|
|
||||||
- [55951c2](https://github.com/actions/actions-runner-controller/commit/55951c2) Add new workflow to automate runner updates [#2247](https://github.com/actions/actions-runner-controller/pull/2247)
|
|
||||||
- [c4297d2](https://github.com/actions/actions-runner-controller/commit/c4297d2) Avoid deleting scale set if annotation is not parsable or if it does not exist [#2239](https://github.com/actions/actions-runner-controller/pull/2239)
|
|
||||||
- [0774f06](https://github.com/actions/actions-runner-controller/commit/0774f06) ADR: automate runner updates [#2244](https://github.com/actions/actions-runner-controller/pull/2244)
|
|
||||||
- [92ab11b](https://github.com/actions/actions-runner-controller/commit/92ab11b) Use UUID v5 for client identifiers [#2241](https://github.com/actions/actions-runner-controller/pull/2241)
|
|
||||||
- [7414dc6](https://github.com/actions/actions-runner-controller/commit/7414dc6) Add Identifier to actions.Client [#2237](https://github.com/actions/actions-runner-controller/pull/2237)
|
|
||||||
- [34efb9d](https://github.com/actions/actions-runner-controller/commit/34efb9d) Add documentation to update ARC with prometheus CRDs needed by actions metrics server [#2209](https://github.com/actions/actions-runner-controller/pull/2209)
|
|
||||||
- [fbad561](https://github.com/actions/actions-runner-controller/commit/fbad561) Allow provide pre-defined kubernetes secret when helm-install AutoScalingRunnerSet [#2234](https://github.com/actions/actions-runner-controller/pull/2234)
|
|
||||||
- [a5cef7e](https://github.com/actions/actions-runner-controller/commit/a5cef7e) Resolve CI break due to bad merge. [#2236](https://github.com/actions/actions-runner-controller/pull/2236)
|
|
||||||
- [1f4fe46](https://github.com/actions/actions-runner-controller/commit/1f4fe46) Delete RunnerScaleSet on service when AutoScalingRunnerSet is deleted. [#2223](https://github.com/actions/actions-runner-controller/pull/2223)
|
|
||||||
- [067686c](https://github.com/actions/actions-runner-controller/commit/067686c) Fix typos and markdown structure in troubleshooting guide [#2148](https://github.com/actions/actions-runner-controller/pull/2148)
|
|
||||||
- [df12e00](https://github.com/actions/actions-runner-controller/commit/df12e00) Remove network requests from actions.NewClient [#2219](https://github.com/actions/actions-runner-controller/pull/2219)
|
|
||||||
- [cc26593](https://github.com/actions/actions-runner-controller/commit/cc26593) Skip CT when list-changed=false. [#2228](https://github.com/actions/actions-runner-controller/pull/2228)
|
|
||||||
- [835eac7](https://github.com/actions/actions-runner-controller/commit/835eac7) Fix helm charts when pass values file. [#2222](https://github.com/actions/actions-runner-controller/pull/2222)
|
|
||||||
- [01e9dd3](https://github.com/actions/actions-runner-controller/commit/01e9dd3) Update Validate ARC workflow to go 1.19 [#2220](https://github.com/actions/actions-runner-controller/pull/2220)
|
|
||||||
- [8038181](https://github.com/actions/actions-runner-controller/commit/8038181) Allow update runner group for AutoScalingRunnerSet [#2216](https://github.com/actions/actions-runner-controller/pull/2216)
|
|
||||||
- [219ba5b](https://github.com/actions/actions-runner-controller/commit/219ba5b) chore(deps): bump sigs.k8s.io/controller-runtime from 0.13.1 to 0.14.1 [#2132](https://github.com/actions/actions-runner-controller/pull/2132)
|
|
||||||
- [b09e3a2](https://github.com/actions/actions-runner-controller/commit/b09e3a2) Return error for non-existing runner group. [#2215](https://github.com/actions/actions-runner-controller/pull/2215)
|
|
||||||
- [7ea60e4](https://github.com/actions/actions-runner-controller/commit/7ea60e4) Fix intermittent image push failures to GHCR [#2214](https://github.com/actions/actions-runner-controller/pull/2214)
|
|
||||||
- [c8918f5](https://github.com/actions/actions-runner-controller/commit/c8918f5) Fix URL for authenticating using a GitHub app [#2206](https://github.com/actions/actions-runner-controller/pull/2206)
|
|
||||||
- [d57d17f](https://github.com/actions/actions-runner-controller/commit/d57d17f) Add support for custom CA in actions.Client [#2199](https://github.com/actions/actions-runner-controller/pull/2199)
|
|
||||||
- [6e69c75](https://github.com/actions/actions-runner-controller/commit/6e69c75) chore(deps): bump github.com/hashicorp/go-retryablehttp from 0.7.1 to 0.7.2 [#2203](https://github.com/actions/actions-runner-controller/pull/2203)
|
|
||||||
- [882bfab](https://github.com/actions/actions-runner-controller/commit/882bfab) Renaming autoScaling to autoscaling in tests matching the convention [#2201](https://github.com/actions/actions-runner-controller/pull/2201)
|
|
||||||
- [3327f62](https://github.com/actions/actions-runner-controller/commit/3327f62) Refactor actions.Client with options to help extensibility [#2193](https://github.com/actions/actions-runner-controller/pull/2193)
|
|
||||||
- [282f2dd](https://github.com/actions/actions-runner-controller/commit/282f2dd) chore(deps): bump github.com/onsi/gomega from 1.20.2 to 1.25.0 [#2169](https://github.com/actions/actions-runner-controller/pull/2169)
|
|
||||||
- [d67f808](https://github.com/actions/actions-runner-controller/commit/d67f808) Include nikola-jokic in CODEOWNERS file [#2184](https://github.com/actions/actions-runner-controller/pull/2184)
|
|
||||||
- [4932412](https://github.com/actions/actions-runner-controller/commit/4932412) Fix L0 test to make it more reliable. [#2178](https://github.com/actions/actions-runner-controller/pull/2178)
|
|
||||||
- [6da1cde](https://github.com/actions/actions-runner-controller/commit/6da1cde) Update runner version to 2.301.1 [#2182](https://github.com/actions/actions-runner-controller/pull/2182)
|
|
||||||
- [f9bae70](https://github.com/actions/actions-runner-controller/commit/f9bae70) Add distinct namespace best practice note [#2181](https://github.com/actions/actions-runner-controller/pull/2181)
|
|
||||||
- [05a3908](https://github.com/actions/actions-runner-controller/commit/05a3908) Add arc-2 quickstart guide [#2180](https://github.com/actions/actions-runner-controller/pull/2180)
|
|
||||||
- [606ed1b](https://github.com/actions/actions-runner-controller/commit/606ed1b) Add Repository information to Runner Status [#2093](https://github.com/actions/actions-runner-controller/pull/2093)
|
|
||||||
237
docs/preview/gha-runner-scale-set-controller/README.md
Normal file
237
docs/preview/gha-runner-scale-set-controller/README.md
Normal file
@@ -0,0 +1,237 @@
|
|||||||
|
# Autoscaling Runner Scale Sets mode
|
||||||
|
|
||||||
|
**⚠️ This mode is currently only available for a limited number of organizations.**
|
||||||
|
|
||||||
|
This new autoscaling mode brings numerous enhancements (described in the following sections) that will make your experience more reliable and secure.
|
||||||
|
|
||||||
|
## How it works
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
In addition to the increased reliability of the automatic scaling, we have worked on these improvements:
|
||||||
|
|
||||||
|
- No longer require cert-manager as a prerequisite for installing actions-runner-controller
|
||||||
|
- Reliable scale-up based on job demands and scale-down to zero runner pods
|
||||||
|
- Reduce API requests to `api.github.com`, no more API rate-limiting problems
|
||||||
|
- The GitHub Personal Access Token (PAT) or the GitHub App installation token is no longer passed to the runner pod for runner registration
|
||||||
|
- Maximum flexibility for customizing your runner pod template
|
||||||
|
|
||||||
|
### Demo
|
||||||
|
|
||||||
|
https://user-images.githubusercontent.com/568794/212668313-8946ddc5-60c1-461f-a73e-27f5e8c75720.mp4
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
1. Create a K8s cluster, if not available.
|
||||||
|
- If you don't have a K8s cluster, you can install a local environment using minikube. See [installing minikube](https://minikube.sigs.k8s.io/docs/start/).
|
||||||
|
1. Install helm 3, if not available. See [installing Helm](https://helm.sh/docs/intro/install/).
|
||||||
|
|
||||||
|
### Install actions-runner-controller
|
||||||
|
|
||||||
|
1. Install actions-runner-controller using helm 3. For additional configuration options, see [values.yaml](https://github.com/actions/actions-runner-controller/blob/master/charts/gha-runner-scale-set-controller/values.yaml)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
NAMESPACE="arc-systems"
|
||||||
|
helm install arc \
|
||||||
|
--namespace "${NAMESPACE}" \
|
||||||
|
--create-namespace \
|
||||||
|
oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set-controller \
|
||||||
|
--version 0.3.0
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Generate a Personal Access Token (PAT) or create and install a GitHub App. See [Creating a personal access token](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token) and [Creating a GitHub App](https://docs.github.com/en/developers/apps/creating-a-github-app).
|
||||||
|
- ℹ For the list of required permissions, see [Authenticating to the GitHub API](https://github.com/actions/actions-runner-controller/blob/master/docs/authenticating-to-the-github-api.md#authenticating-to-the-github-api).
|
||||||
|
|
||||||
|
1. You're ready to install the autoscaling runner set. For additional configuration options, see [values.yaml](https://github.com/actions/actions-runner-controller/blob/master/charts/gha-runner-scale-set/values.yaml)
|
||||||
|
- ℹ **Choose your installation name carefully**, you will use it as the value of `runs-on` in your workflow.
|
||||||
|
- ℹ **We recommend you choose a unique namespace in the following steps**. As a good security measure, it's best to have your runner pods created in a different namespace than the one containing the manager and listener pods.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Using a Personal Access Token (PAT)
|
||||||
|
INSTALLATION_NAME="arc-runner-set"
|
||||||
|
NAMESPACE="arc-runners"
|
||||||
|
GITHUB_CONFIG_URL="https://github.com/<your_enterprise/org/repo>"
|
||||||
|
GITHUB_PAT="<PAT>"
|
||||||
|
helm install "${INSTALLATION_NAME}" \
|
||||||
|
--namespace "${NAMESPACE}" \
|
||||||
|
--create-namespace \
|
||||||
|
--set githubConfigUrl="${GITHUB_CONFIG_URL}" \
|
||||||
|
--set githubConfigSecret.github_token="${GITHUB_PAT}" \
|
||||||
|
oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set --version 0.3.0
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Using a GitHub App
|
||||||
|
INSTALLATION_NAME="arc-runner-set"
|
||||||
|
NAMESPACE="arc-runners"
|
||||||
|
GITHUB_CONFIG_URL="https://github.com/<your_enterprise/org/repo>"
|
||||||
|
GITHUB_APP_ID="<GITHUB_APP_ID>"
|
||||||
|
GITHUB_APP_INSTALLATION_ID="<GITHUB_APP_INSTALLATION_ID>"
|
||||||
|
GITHUB_APP_PRIVATE_KEY="<GITHUB_APP_PRIVATE_KEY>"
|
||||||
|
helm install arc-runner-set \
|
||||||
|
--namespace "${NAMESPACE}" \
|
||||||
|
--create-namespace \
|
||||||
|
--set githubConfigUrl="${GITHUB_CONFIG_URL}" \
|
||||||
|
--set githubConfigSecret.github_app_id="${GITHUB_APP_ID}" \
|
||||||
|
--set githubConfigSecret.github_app_installation_id="${GITHUB_APP_INSTALLATION_ID}" \
|
||||||
|
--set githubConfigSecret.github_app_private_key="${GITHUB_APP_PRIVATE_KEY}" \
|
||||||
|
oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set --version 0.3.0
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Check your installation. If everything went well, you should see the following:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ helm list -n "${NAMESPACE}"
|
||||||
|
|
||||||
|
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
|
||||||
|
arc arc-systems 1 2023-01-18 10:03:36.610534934 +0000 UTC deployed gha-runner-scale-set-controller-0.3.0 preview
|
||||||
|
arc-runner-set arc-systems 1 2023-01-18 10:20:14.795285645 +0000 UTC deployed gha-runner-scale-set-0.3.0 0.3.0
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ kubectl get pods -n "${NAMESPACE}"
|
||||||
|
|
||||||
|
NAME READY STATUS RESTARTS AGE
|
||||||
|
arc-gha-runner-scale-set-controller-8c74b6f95-gr7zr 1/1 Running 0 20m
|
||||||
|
arc-runner-set-6cd58d58-listener 1/1 Running 0 21s
|
||||||
|
```
|
||||||
|
|
||||||
|
1. In a repository, create a simple test workflow as follows. The `runs-on` value should match the helm installation name you used in the previous step.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: Test workflow
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: arc-runner-set
|
||||||
|
steps:
|
||||||
|
- name: Hello world
|
||||||
|
run: echo "Hello world"
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Run the workflow. You should see the runner pod being created and the workflow being executed.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ kubectl get pods -A
|
||||||
|
|
||||||
|
NAMESPACE NAME READY STATUS RESTARTS AGE
|
||||||
|
arc-systems arc-gha-runner-scale-set-controller-8c74b6f95-gr7zr 1/1 Running 0 27m
|
||||||
|
arc-systems arc-runner-set-6cd58d58-listener 1/1 Running 0 7m52s
|
||||||
|
arc-runners arc-runner-set-rmrgw-runner-p9p5n 1/1 Running 0 21s
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Check the logs
|
||||||
|
|
||||||
|
You can check the logs of the controller pod using the following command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Controller logs
|
||||||
|
$ kubectl logs -n "${NAMESPACE}" -l app.kubernetes.io/name=gha-runner-scale-set-controller
|
||||||
|
|
||||||
|
# Runner set listener logs
|
||||||
|
kubectl logs -n "${NAMESPACE}" -l auto-scaling-runner-set-namespace=arc-systems -l auto-scaling-runner-set-name=arc-runner-set
|
||||||
|
```
|
||||||
|
|
||||||
|
### Naming error: `Name must have up to characters`
|
||||||
|
|
||||||
|
We are using some of the resources generated names as labels for other resources. Resource names have a max length of `263 characters` while labels are limited to `63 characters`. Given this constraint, we have to limit the resource names to `63 characters`.
|
||||||
|
|
||||||
|
Since part of the resource name is defined by you, we have to impose a limit on the amount of characters you can use for the installation and namespace names.
|
||||||
|
|
||||||
|
If you see these errors, you have to use shorter installation or namespace names.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
Error: INSTALLATION FAILED: execution error at (gha-runner-scale-set/templates/autoscalingrunnerset.yaml:5:5): Name must have up to 45 characters
|
||||||
|
|
||||||
|
Error: INSTALLATION FAILED: execution error at (gha-runner-scale-set/templates/autoscalingrunnerset.yaml:8:5): Namespace must have up to 63 characters
|
||||||
|
```
|
||||||
|
|
||||||
|
### If you installed the autoscaling runner set, but the listener pod is not created
|
||||||
|
|
||||||
|
Verify that the secret you provided is correct and that the `githubConfigUrl` you provided is accurate.
|
||||||
|
|
||||||
|
## Changelog
|
||||||
|
|
||||||
|
### v0.3.0
|
||||||
|
|
||||||
|
#### Major changes
|
||||||
|
|
||||||
|
1. Runner pods are more similar to hosted runners [#2348](https://github.com/actions/actions-runner-controller/pull/2348)
|
||||||
|
1. Add support for self-signed CA certificates [#2268](https://github.com/actions/actions-runner-controller/pull/2268)
|
||||||
|
1. Fixed trailing slashes in config URLs breaking installations [#2381](https://github.com/actions/actions-runner-controller/pull/2381)
|
||||||
|
1. Fixed a bug where the listener pod would ignore proxy settings from env [#2366](https://github.com/actions/actions-runner-controller/pull/2366)
|
||||||
|
1. Added runner set name field making it optionally configurable [#2279](https://github.com/actions/actions-runner-controller/pull/2279)
|
||||||
|
1. Name and namespace labels of listener pod have been split [#2341](https://github.com/actions/actions-runner-controller/pull/2341)
|
||||||
|
1. Added chart name constraints validation on AutoscalingRunnerSet install [#2347](https://github.com/actions/actions-runner-controller/pull/2347)
|
||||||
|
|
||||||
|
### v0.2.0
|
||||||
|
|
||||||
|
#### Major changes
|
||||||
|
|
||||||
|
1. Added proxy support for the controller and the runner pods, see the new helm chart fields [#2286](https://github.com/actions/actions-runner-controller/pull/2286)
|
||||||
|
1. Added the abiilty to provide a pre-defined kubernetes secret for the auto scaling runner set helm chart [#2234](https://github.com/actions/actions-runner-controller/pull/2234)
|
||||||
|
1. Enhanced security posture by removing un-required permissions for the manager-role [#2260](https://github.com/actions/actions-runner-controller/pull/2260)
|
||||||
|
1. Enhanced our logging by returning an error when a runner group is defined in the values file but it's not created in GitHub [#2215](https://github.com/actions/actions-runner-controller/pull/2215)
|
||||||
|
1. Fixed helm charts issues that were preventing the use of DinD [#2291](https://github.com/actions/actions-runner-controller/pull/2291)
|
||||||
|
1. Fixed a bug that was preventing runner scale from being removed from the backend when they were deleted from the cluster [#2255](https://github.com/actions/actions-runner-controller/pull/2255) [#2223](https://github.com/actions/actions-runner-controller/pull/2223)
|
||||||
|
1. Fixed bugs with the helm chart definitions preventing certain values from being set [#2222](https://github.com/actions/actions-runner-controller/pull/2222)
|
||||||
|
1. Fixed a bug that prevented the configuration of a runner group for a runner scale set [#2216](https://github.com/actions/actions-runner-controller/pull/2216)
|
||||||
|
|
||||||
|
#### Log
|
||||||
|
|
||||||
|
- [1c7b7f4](https://github.com/actions/actions-runner-controller/commit/1c7b7f4) Bump arc-2 chart version and prepare 0.2.0 release [#2313](https://github.com/actions/actions-runner-controller/pull/2313)
|
||||||
|
- [73e22a1](https://github.com/actions/actions-runner-controller/commit/73e22a1) Disable metrics serving in proxy tests [#2307](https://github.com/actions/actions-runner-controller/pull/2307)
|
||||||
|
- [9b44f00](https://github.com/actions/actions-runner-controller/commit/9b44f00) Documentation corrections [#2116](https://github.com/actions/actions-runner-controller/pull/2116)
|
||||||
|
- [6b4250c](https://github.com/actions/actions-runner-controller/commit/6b4250c) Add support for proxy [#2286](https://github.com/actions/actions-runner-controller/pull/2286)
|
||||||
|
- [ced8822](https://github.com/actions/actions-runner-controller/commit/ced8822) Resolves the erroneous webhook scale down due to check runs [#2119](https://github.com/actions/actions-runner-controller/pull/2119)
|
||||||
|
- [44c06c2](https://github.com/actions/actions-runner-controller/commit/44c06c2) fix: case-insensitive webhook label matching [#2302](https://github.com/actions/actions-runner-controller/pull/2302)
|
||||||
|
- [4103fe3](https://github.com/actions/actions-runner-controller/commit/4103fe3) Use DOCKER_IMAGE_NAME instead of NAME to avoid conflict. [#2303](https://github.com/actions/actions-runner-controller/pull/2303)
|
||||||
|
- [a44fe04](https://github.com/actions/actions-runner-controller/commit/a44fe04) Fix manager crashloopback for ARC deployments without scaleset-related controllers [#2293](https://github.com/actions/actions-runner-controller/pull/2293)
|
||||||
|
- [274d0c8](https://github.com/actions/actions-runner-controller/commit/274d0c8) Added ability to configure log level from chart values [#2252](https://github.com/actions/actions-runner-controller/pull/2252)
|
||||||
|
- [256e08e](https://github.com/actions/actions-runner-controller/commit/256e08e) Ask runner to wait for docker daemon from DinD. [#2292](https://github.com/actions/actions-runner-controller/pull/2292)
|
||||||
|
- [f677fd5](https://github.com/actions/actions-runner-controller/commit/f677fd5) doc: Fix chart name for helm commands in docs [#2287](https://github.com/actions/actions-runner-controller/pull/2287)
|
||||||
|
- [d962714](https://github.com/actions/actions-runner-controller/commit/d962714) Fix helm chart when containerMode.type=dind. [#2291](https://github.com/actions/actions-runner-controller/pull/2291)
|
||||||
|
- [3886f28](https://github.com/actions/actions-runner-controller/commit/3886f28) Add EKS test environment Terraform templates [#2290](https://github.com/actions/actions-runner-controller/pull/2290)
|
||||||
|
- [dab9004](https://github.com/actions/actions-runner-controller/commit/dab9004) Added workflow to be triggered via rest api dispatch in e2e test [#2283](https://github.com/actions/actions-runner-controller/pull/2283)
|
||||||
|
- [dd8ec1a](https://github.com/actions/actions-runner-controller/commit/dd8ec1a) Add testserver package [#2281](https://github.com/actions/actions-runner-controller/pull/2281)
|
||||||
|
- [8e52a6d](https://github.com/actions/actions-runner-controller/commit/8e52a6d) EphemeralRunner: On cleanup, if pod is pending, delete from service [#2255](https://github.com/actions/actions-runner-controller/pull/2255)
|
||||||
|
- [9990243](https://github.com/actions/actions-runner-controller/commit/9990243) Early return if finalizer does not exist to make it more readable [#2262](https://github.com/actions/actions-runner-controller/pull/2262)
|
||||||
|
- [0891981](https://github.com/actions/actions-runner-controller/commit/0891981) Port ADRs from internal repo [#2267](https://github.com/actions/actions-runner-controller/pull/2267)
|
||||||
|
- [facae69](https://github.com/actions/actions-runner-controller/commit/facae69) Remove un-required permissions for the manager-role of the new `AutoScalingRunnerSet` [#2260](https://github.com/actions/actions-runner-controller/pull/2260)
|
||||||
|
- [8f62e35](https://github.com/actions/actions-runner-controller/commit/8f62e35) Add options to multi client [#2257](https://github.com/actions/actions-runner-controller/pull/2257)
|
||||||
|
- [55951c2](https://github.com/actions/actions-runner-controller/commit/55951c2) Add new workflow to automate runner updates [#2247](https://github.com/actions/actions-runner-controller/pull/2247)
|
||||||
|
- [c4297d2](https://github.com/actions/actions-runner-controller/commit/c4297d2) Avoid deleting scale set if annotation is not parsable or if it does not exist [#2239](https://github.com/actions/actions-runner-controller/pull/2239)
|
||||||
|
- [0774f06](https://github.com/actions/actions-runner-controller/commit/0774f06) ADR: automate runner updates [#2244](https://github.com/actions/actions-runner-controller/pull/2244)
|
||||||
|
- [92ab11b](https://github.com/actions/actions-runner-controller/commit/92ab11b) Use UUID v5 for client identifiers [#2241](https://github.com/actions/actions-runner-controller/pull/2241)
|
||||||
|
- [7414dc6](https://github.com/actions/actions-runner-controller/commit/7414dc6) Add Identifier to actions.Client [#2237](https://github.com/actions/actions-runner-controller/pull/2237)
|
||||||
|
- [34efb9d](https://github.com/actions/actions-runner-controller/commit/34efb9d) Add documentation to update ARC with prometheus CRDs needed by actions metrics server [#2209](https://github.com/actions/actions-runner-controller/pull/2209)
|
||||||
|
- [fbad561](https://github.com/actions/actions-runner-controller/commit/fbad561) Allow provide pre-defined kubernetes secret when helm-install AutoScalingRunnerSet [#2234](https://github.com/actions/actions-runner-controller/pull/2234)
|
||||||
|
- [a5cef7e](https://github.com/actions/actions-runner-controller/commit/a5cef7e) Resolve CI break due to bad merge. [#2236](https://github.com/actions/actions-runner-controller/pull/2236)
|
||||||
|
- [1f4fe46](https://github.com/actions/actions-runner-controller/commit/1f4fe46) Delete RunnerScaleSet on service when AutoScalingRunnerSet is deleted. [#2223](https://github.com/actions/actions-runner-controller/pull/2223)
|
||||||
|
- [067686c](https://github.com/actions/actions-runner-controller/commit/067686c) Fix typos and markdown structure in troubleshooting guide [#2148](https://github.com/actions/actions-runner-controller/pull/2148)
|
||||||
|
- [df12e00](https://github.com/actions/actions-runner-controller/commit/df12e00) Remove network requests from actions.NewClient [#2219](https://github.com/actions/actions-runner-controller/pull/2219)
|
||||||
|
- [cc26593](https://github.com/actions/actions-runner-controller/commit/cc26593) Skip CT when list-changed=false. [#2228](https://github.com/actions/actions-runner-controller/pull/2228)
|
||||||
|
- [835eac7](https://github.com/actions/actions-runner-controller/commit/835eac7) Fix helm charts when pass values file. [#2222](https://github.com/actions/actions-runner-controller/pull/2222)
|
||||||
|
- [01e9dd3](https://github.com/actions/actions-runner-controller/commit/01e9dd3) Update Validate ARC workflow to go 1.19 [#2220](https://github.com/actions/actions-runner-controller/pull/2220)
|
||||||
|
- [8038181](https://github.com/actions/actions-runner-controller/commit/8038181) Allow update runner group for AutoScalingRunnerSet [#2216](https://github.com/actions/actions-runner-controller/pull/2216)
|
||||||
|
- [219ba5b](https://github.com/actions/actions-runner-controller/commit/219ba5b) chore(deps): bump sigs.k8s.io/controller-runtime from 0.13.1 to 0.14.1 [#2132](https://github.com/actions/actions-runner-controller/pull/2132)
|
||||||
|
- [b09e3a2](https://github.com/actions/actions-runner-controller/commit/b09e3a2) Return error for non-existing runner group. [#2215](https://github.com/actions/actions-runner-controller/pull/2215)
|
||||||
|
- [7ea60e4](https://github.com/actions/actions-runner-controller/commit/7ea60e4) Fix intermittent image push failures to GHCR [#2214](https://github.com/actions/actions-runner-controller/pull/2214)
|
||||||
|
- [c8918f5](https://github.com/actions/actions-runner-controller/commit/c8918f5) Fix URL for authenticating using a GitHub app [#2206](https://github.com/actions/actions-runner-controller/pull/2206)
|
||||||
|
- [d57d17f](https://github.com/actions/actions-runner-controller/commit/d57d17f) Add support for custom CA in actions.Client [#2199](https://github.com/actions/actions-runner-controller/pull/2199)
|
||||||
|
- [6e69c75](https://github.com/actions/actions-runner-controller/commit/6e69c75) chore(deps): bump github.com/hashicorp/go-retryablehttp from 0.7.1 to 0.7.2 [#2203](https://github.com/actions/actions-runner-controller/pull/2203)
|
||||||
|
- [882bfab](https://github.com/actions/actions-runner-controller/commit/882bfab) Renaming autoScaling to autoscaling in tests matching the convention [#2201](https://github.com/actions/actions-runner-controller/pull/2201)
|
||||||
|
- [3327f62](https://github.com/actions/actions-runner-controller/commit/3327f62) Refactor actions.Client with options to help extensibility [#2193](https://github.com/actions/actions-runner-controller/pull/2193)
|
||||||
|
- [282f2dd](https://github.com/actions/actions-runner-controller/commit/282f2dd) chore(deps): bump github.com/onsi/gomega from 1.20.2 to 1.25.0 [#2169](https://github.com/actions/actions-runner-controller/pull/2169)
|
||||||
|
- [d67f808](https://github.com/actions/actions-runner-controller/commit/d67f808) Include nikola-jokic in CODEOWNERS file [#2184](https://github.com/actions/actions-runner-controller/pull/2184)
|
||||||
|
- [4932412](https://github.com/actions/actions-runner-controller/commit/4932412) Fix L0 test to make it more reliable. [#2178](https://github.com/actions/actions-runner-controller/pull/2178)
|
||||||
|
- [6da1cde](https://github.com/actions/actions-runner-controller/commit/6da1cde) Update runner version to 2.301.1 [#2182](https://github.com/actions/actions-runner-controller/pull/2182)
|
||||||
|
- [f9bae70](https://github.com/actions/actions-runner-controller/commit/f9bae70) Add distinct namespace best practice note [#2181](https://github.com/actions/actions-runner-controller/pull/2181)
|
||||||
|
- [05a3908](https://github.com/actions/actions-runner-controller/commit/05a3908) Add arc-2 quickstart guide [#2180](https://github.com/actions/actions-runner-controller/pull/2180)
|
||||||
|
- [606ed1b](https://github.com/actions/actions-runner-controller/commit/606ed1b) Add Repository information to Runner Status [#2093](https://github.com/actions/actions-runner-controller/pull/2093)
|
||||||
@@ -58,12 +58,6 @@ func newActionsServer(t *testing.T, handler http.Handler, options ...actionsServ
|
|||||||
|
|
||||||
type actionsServerOption func(*actionsServer)
|
type actionsServerOption func(*actionsServer)
|
||||||
|
|
||||||
func withActionsToken(token string) actionsServerOption {
|
|
||||||
return func(s *actionsServer) {
|
|
||||||
s.token = token
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type actionsServer struct {
|
type actionsServer struct {
|
||||||
*httptest.Server
|
*httptest.Server
|
||||||
|
|
||||||
|
|||||||
@@ -198,6 +198,12 @@ func (c *Client) Identifier() string {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if c.rootCAs != nil {
|
||||||
|
// ignoring because this cert pool is intended not to come from SystemCertPool
|
||||||
|
// nolint:staticcheck
|
||||||
|
identifier += fmt.Sprintf("rootCAs:%q", c.rootCAs.Subjects())
|
||||||
|
}
|
||||||
|
|
||||||
return uuid.NewHash(sha256.New(), uuid.NameSpaceOID, []byte(identifier), 6).String()
|
return uuid.NewHash(sha256.New(), uuid.NameSpaceOID, []byte(identifier), 6).String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -95,8 +95,8 @@ func TestServerWithSelfSignedCertificates(t *testing.T) {
|
|||||||
cert, err := os.ReadFile(filepath.Join("testdata", "rootCA.crt"))
|
cert, err := os.ReadFile(filepath.Join("testdata", "rootCA.crt"))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
pool, err := actions.RootCAsFromConfigMap(map[string][]byte{"cert": cert})
|
pool := x509.NewCertPool()
|
||||||
require.NoError(t, err)
|
require.True(t, pool.AppendCertsFromPEM(cert))
|
||||||
|
|
||||||
client, err := actions.NewClient(configURL, auth, actions.WithRootCAs(pool))
|
client, err := actions.NewClient(configURL, auth, actions.WithRootCAs(pool))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -123,8 +123,8 @@ func TestServerWithSelfSignedCertificates(t *testing.T) {
|
|||||||
cert, err := os.ReadFile(filepath.Join("testdata", "intermediate.pem"))
|
cert, err := os.ReadFile(filepath.Join("testdata", "intermediate.pem"))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
pool, err := actions.RootCAsFromConfigMap(map[string][]byte{"cert": cert})
|
pool := x509.NewCertPool()
|
||||||
require.NoError(t, err)
|
require.True(t, pool.AppendCertsFromPEM(cert))
|
||||||
|
|
||||||
client, err := actions.NewClient(configURL, auth, actions.WithRootCAs(pool), actions.WithRetryMax(0))
|
client, err := actions.NewClient(configURL, auth, actions.WithRootCAs(pool), actions.WithRetryMax(0))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ type GitHubConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ParseGitHubConfigFromURL(in string) (*GitHubConfig, error) {
|
func ParseGitHubConfigFromURL(in string) (*GitHubConfig, error) {
|
||||||
u, err := url.Parse(in)
|
u, err := url.Parse(strings.Trim(in, "/"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -45,7 +45,7 @@ func ParseGitHubConfigFromURL(in string) (*GitHubConfig, error) {
|
|||||||
|
|
||||||
invalidURLError := fmt.Errorf("%q: %w", u.String(), ErrInvalidGitHubConfigURL)
|
invalidURLError := fmt.Errorf("%q: %w", u.String(), ErrInvalidGitHubConfigURL)
|
||||||
|
|
||||||
pathParts := strings.Split(strings.TrimPrefix(u.Path, "/"), "/")
|
pathParts := strings.Split(strings.Trim(u.Path, "/"), "/")
|
||||||
|
|
||||||
switch len(pathParts) {
|
switch len(pathParts) {
|
||||||
case 1: // Organization
|
case 1: // Organization
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package actions_test
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/actions/actions-runner-controller/github/actions"
|
"github.com/actions/actions-runner-controller/github/actions"
|
||||||
@@ -26,6 +27,16 @@ func TestGitHubConfig(t *testing.T) {
|
|||||||
IsHosted: true,
|
IsHosted: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
configURL: "https://github.com/org/repo/",
|
||||||
|
expected: &actions.GitHubConfig{
|
||||||
|
Scope: actions.GitHubScopeRepository,
|
||||||
|
Enterprise: "",
|
||||||
|
Organization: "org",
|
||||||
|
Repository: "repo",
|
||||||
|
IsHosted: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
configURL: "https://github.com/org",
|
configURL: "https://github.com/org",
|
||||||
expected: &actions.GitHubConfig{
|
expected: &actions.GitHubConfig{
|
||||||
@@ -46,6 +57,16 @@ func TestGitHubConfig(t *testing.T) {
|
|||||||
IsHosted: true,
|
IsHosted: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
configURL: "https://github.com/enterprises/my-enterprise/",
|
||||||
|
expected: &actions.GitHubConfig{
|
||||||
|
Scope: actions.GitHubScopeEnterprise,
|
||||||
|
Enterprise: "my-enterprise",
|
||||||
|
Organization: "",
|
||||||
|
Repository: "",
|
||||||
|
IsHosted: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
configURL: "https://www.github.com/org",
|
configURL: "https://www.github.com/org",
|
||||||
expected: &actions.GitHubConfig{
|
expected: &actions.GitHubConfig{
|
||||||
@@ -56,6 +77,16 @@ func TestGitHubConfig(t *testing.T) {
|
|||||||
IsHosted: true,
|
IsHosted: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
configURL: "https://www.github.com/org/",
|
||||||
|
expected: &actions.GitHubConfig{
|
||||||
|
Scope: actions.GitHubScopeOrganization,
|
||||||
|
Enterprise: "",
|
||||||
|
Organization: "org",
|
||||||
|
Repository: "",
|
||||||
|
IsHosted: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
configURL: "https://github.localhost/org",
|
configURL: "https://github.localhost/org",
|
||||||
expected: &actions.GitHubConfig{
|
expected: &actions.GitHubConfig{
|
||||||
@@ -76,11 +107,21 @@ func TestGitHubConfig(t *testing.T) {
|
|||||||
IsHosted: false,
|
IsHosted: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
configURL: "https://my-ghes.com/org/",
|
||||||
|
expected: &actions.GitHubConfig{
|
||||||
|
Scope: actions.GitHubScopeOrganization,
|
||||||
|
Enterprise: "",
|
||||||
|
Organization: "org",
|
||||||
|
Repository: "",
|
||||||
|
IsHosted: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.configURL, func(t *testing.T) {
|
t.Run(test.configURL, func(t *testing.T) {
|
||||||
parsedURL, err := url.Parse(test.configURL)
|
parsedURL, err := url.Parse(strings.Trim(test.configURL, "/"))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
test.expected.ConfigURL = parsedURL
|
test.expected.ConfigURL = parsedURL
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,13 @@ func WithCreateRunnerScaleSet(scaleSet *actions.RunnerScaleSet, err error) Optio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func WithUpdateRunnerScaleSet(scaleSet *actions.RunnerScaleSet, err error) Option {
|
||||||
|
return func(f *FakeClient) {
|
||||||
|
f.updateRunnerScaleSetResult.RunnerScaleSet = scaleSet
|
||||||
|
f.updateRunnerScaleSetResult.err = err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var defaultRunnerScaleSet = &actions.RunnerScaleSet{
|
var defaultRunnerScaleSet = &actions.RunnerScaleSet{
|
||||||
Id: 1,
|
Id: 1,
|
||||||
Name: "testset",
|
Name: "testset",
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/actions/actions-runner-controller/github/actions"
|
"github.com/actions/actions-runner-controller/github/actions"
|
||||||
|
"github.com/actions/actions-runner-controller/github/actions/testserver"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
@@ -95,9 +96,9 @@ func TestNewActionsServiceRequest(t *testing.T) {
|
|||||||
t.Run("manages authentication", func(t *testing.T) {
|
t.Run("manages authentication", func(t *testing.T) {
|
||||||
t.Run("client is brand new", func(t *testing.T) {
|
t.Run("client is brand new", func(t *testing.T) {
|
||||||
token := defaultActionsToken(t)
|
token := defaultActionsToken(t)
|
||||||
server := newActionsServer(t, nil, withActionsToken(token))
|
server := testserver.New(t, nil, testserver.WithActionsToken(token))
|
||||||
|
|
||||||
client, err := actions.NewClient(server.configURLForOrg("my-org"), defaultCreds)
|
client, err := actions.NewClient(server.ConfigURLForOrg("my-org"), defaultCreds)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
req, err := client.NewActionsServiceRequest(ctx, http.MethodGet, "my-path", nil)
|
req, err := client.NewActionsServiceRequest(ctx, http.MethodGet, "my-path", nil)
|
||||||
@@ -108,9 +109,9 @@ func TestNewActionsServiceRequest(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("admin token is about to expire", func(t *testing.T) {
|
t.Run("admin token is about to expire", func(t *testing.T) {
|
||||||
newToken := defaultActionsToken(t)
|
newToken := defaultActionsToken(t)
|
||||||
server := newActionsServer(t, nil, withActionsToken(newToken))
|
server := testserver.New(t, nil, testserver.WithActionsToken(newToken))
|
||||||
|
|
||||||
client, err := actions.NewClient(server.configURLForOrg("my-org"), defaultCreds)
|
client, err := actions.NewClient(server.ConfigURLForOrg("my-org"), defaultCreds)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
client.ActionsServiceAdminToken = "expiring-token"
|
client.ActionsServiceAdminToken = "expiring-token"
|
||||||
client.ActionsServiceAdminTokenExpiresAt = time.Now().Add(59 * time.Second)
|
client.ActionsServiceAdminTokenExpiresAt = time.Now().Add(59 * time.Second)
|
||||||
@@ -123,9 +124,9 @@ func TestNewActionsServiceRequest(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("token is currently valid", func(t *testing.T) {
|
t.Run("token is currently valid", func(t *testing.T) {
|
||||||
tokenThatShouldNotBeFetched := defaultActionsToken(t)
|
tokenThatShouldNotBeFetched := defaultActionsToken(t)
|
||||||
server := newActionsServer(t, nil, withActionsToken(tokenThatShouldNotBeFetched))
|
server := testserver.New(t, nil, testserver.WithActionsToken(tokenThatShouldNotBeFetched))
|
||||||
|
|
||||||
client, err := actions.NewClient(server.configURLForOrg("my-org"), defaultCreds)
|
client, err := actions.NewClient(server.ConfigURLForOrg("my-org"), defaultCreds)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
client.ActionsServiceAdminToken = "healthy-token"
|
client.ActionsServiceAdminToken = "healthy-token"
|
||||||
client.ActionsServiceAdminTokenExpiresAt = time.Now().Add(1 * time.Hour)
|
client.ActionsServiceAdminTokenExpiresAt = time.Now().Add(1 * time.Hour)
|
||||||
@@ -138,9 +139,9 @@ func TestNewActionsServiceRequest(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("builds the right URL including api version", func(t *testing.T) {
|
t.Run("builds the right URL including api version", func(t *testing.T) {
|
||||||
server := newActionsServer(t, nil)
|
server := testserver.New(t, nil)
|
||||||
|
|
||||||
client, err := actions.NewClient(server.configURLForOrg("my-org"), defaultCreds)
|
client, err := actions.NewClient(server.ConfigURLForOrg("my-org"), defaultCreds)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
req, err := client.NewActionsServiceRequest(ctx, http.MethodGet, "/my/path?name=banana", nil)
|
req, err := client.NewActionsServiceRequest(ctx, http.MethodGet, "/my/path?name=banana", nil)
|
||||||
@@ -157,9 +158,9 @@ func TestNewActionsServiceRequest(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("populates header", func(t *testing.T) {
|
t.Run("populates header", func(t *testing.T) {
|
||||||
server := newActionsServer(t, nil)
|
server := testserver.New(t, nil)
|
||||||
|
|
||||||
client, err := actions.NewClient(server.configURLForOrg("my-org"), defaultCreds, actions.WithUserAgent("my-agent"))
|
client, err := actions.NewClient(server.ConfigURLForOrg("my-org"), defaultCreds, actions.WithUserAgent("my-agent"))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
req, err := client.NewActionsServiceRequest(ctx, http.MethodGet, "/my/path", nil)
|
req, err := client.NewActionsServiceRequest(ctx, http.MethodGet, "/my/path", nil)
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package actions_test
|
package actions_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/x509"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/actions/actions-runner-controller/github/actions"
|
"github.com/actions/actions-runner-controller/github/actions"
|
||||||
@@ -108,4 +111,48 @@ func TestClient_Identifier(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("changes in TLS config", func(t *testing.T) {
|
||||||
|
configURL := "https://github.com/org/repo"
|
||||||
|
defaultCreds := &actions.ActionsAuth{
|
||||||
|
Token: "token",
|
||||||
|
}
|
||||||
|
|
||||||
|
noTlS, err := actions.NewClient(configURL, defaultCreds)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
poolFromCert := func(t *testing.T, path string) *x509.CertPool {
|
||||||
|
t.Helper()
|
||||||
|
f, err := os.ReadFile(path)
|
||||||
|
require.NoError(t, err)
|
||||||
|
pool := x509.NewCertPool()
|
||||||
|
require.True(t, pool.AppendCertsFromPEM(f))
|
||||||
|
return pool
|
||||||
|
}
|
||||||
|
|
||||||
|
root, err := actions.NewClient(
|
||||||
|
configURL,
|
||||||
|
defaultCreds,
|
||||||
|
actions.WithRootCAs(poolFromCert(t, filepath.Join("testdata", "rootCA.crt"))),
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
chain, err := actions.NewClient(
|
||||||
|
configURL,
|
||||||
|
defaultCreds,
|
||||||
|
actions.WithRootCAs(poolFromCert(t, filepath.Join("testdata", "intermediate.pem"))),
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
clients := []*actions.Client{
|
||||||
|
noTlS,
|
||||||
|
root,
|
||||||
|
chain,
|
||||||
|
}
|
||||||
|
identifiers := map[string]struct{}{}
|
||||||
|
for _, client := range clients {
|
||||||
|
identifiers[client.Identifier()] = struct{}{}
|
||||||
|
}
|
||||||
|
assert.Len(t, identifiers, len(clients), "all clients should have a unique identifier")
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package actions
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/x509"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -84,7 +83,7 @@ func (m *multiClient) GetClientFor(ctx context.Context, githubConfigURL string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
cachedClient, has := m.clients[key]
|
cachedClient, has := m.clients[key]
|
||||||
if has {
|
if has && cachedClient.rootCAs.Equal(client.rootCAs) {
|
||||||
m.logger.Info("using cache client", "githubConfigURL", githubConfigURL, "namespace", namespace)
|
m.logger.Info("using cache client", "githubConfigURL", githubConfigURL, "namespace", namespace)
|
||||||
return cachedClient, nil
|
return cachedClient, nil
|
||||||
}
|
}
|
||||||
@@ -141,19 +140,3 @@ func (m *multiClient) GetClientFromSecret(ctx context.Context, githubConfigURL,
|
|||||||
auth.AppCreds = &GitHubAppAuth{AppID: parsedAppID, AppInstallationID: parsedAppInstallationID, AppPrivateKey: appPrivateKey}
|
auth.AppCreds = &GitHubAppAuth{AppID: parsedAppID, AppInstallationID: parsedAppInstallationID, AppPrivateKey: appPrivateKey}
|
||||||
return m.GetClientFor(ctx, githubConfigURL, auth, namespace, options...)
|
return m.GetClientFor(ctx, githubConfigURL, auth, namespace, options...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func RootCAsFromConfigMap(configMapData map[string][]byte) (*x509.CertPool, error) {
|
|
||||||
caCertPool, err := x509.SystemCertPool()
|
|
||||||
if err != nil {
|
|
||||||
caCertPool = x509.NewCertPool()
|
|
||||||
}
|
|
||||||
|
|
||||||
for key, certData := range configMapData {
|
|
||||||
ok := caCertPool.AppendCertsFromPEM(certData)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("no certificates successfully parsed from key %s", key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return caCertPool, nil
|
|
||||||
}
|
|
||||||
|
|||||||
39
go.mod
39
go.mod
@@ -7,32 +7,34 @@ require (
|
|||||||
github.com/davecgh/go-spew v1.1.1
|
github.com/davecgh/go-spew v1.1.1
|
||||||
github.com/evanphx/json-patch v4.12.0+incompatible
|
github.com/evanphx/json-patch v4.12.0+incompatible
|
||||||
github.com/go-logr/logr v1.2.3
|
github.com/go-logr/logr v1.2.3
|
||||||
github.com/golang-jwt/jwt/v4 v4.4.1
|
github.com/golang-jwt/jwt/v4 v4.5.0
|
||||||
github.com/google/go-cmp v0.5.9
|
github.com/google/go-cmp v0.5.9
|
||||||
github.com/google/go-github/v47 v47.1.0
|
github.com/google/go-github/v47 v47.1.0
|
||||||
|
github.com/google/go-github/v50 v50.0.0
|
||||||
github.com/google/uuid v1.3.0
|
github.com/google/uuid v1.3.0
|
||||||
github.com/gorilla/mux v1.8.0
|
github.com/gorilla/mux v1.8.0
|
||||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79
|
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79
|
||||||
github.com/gruntwork-io/terratest v0.41.9
|
github.com/gruntwork-io/terratest v0.41.11
|
||||||
github.com/hashicorp/go-retryablehttp v0.7.2
|
github.com/hashicorp/go-retryablehttp v0.7.2
|
||||||
github.com/kelseyhightower/envconfig v1.4.0
|
github.com/kelseyhightower/envconfig v1.4.0
|
||||||
github.com/onsi/ginkgo v1.16.5
|
github.com/onsi/ginkgo v1.16.5
|
||||||
github.com/onsi/ginkgo/v2 v2.7.0
|
github.com/onsi/ginkgo/v2 v2.9.0
|
||||||
github.com/onsi/gomega v1.25.0
|
github.com/onsi/gomega v1.27.2
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/prometheus/client_golang v1.14.0
|
github.com/prometheus/client_golang v1.14.0
|
||||||
github.com/stretchr/testify v1.8.0
|
github.com/stretchr/testify v1.8.2
|
||||||
github.com/teambition/rrule-go v1.8.0
|
github.com/teambition/rrule-go v1.8.2
|
||||||
go.uber.org/multierr v1.7.0
|
go.uber.org/multierr v1.7.0
|
||||||
go.uber.org/zap v1.24.0
|
go.uber.org/zap v1.24.0
|
||||||
golang.org/x/net v0.6.0
|
golang.org/x/net v0.8.0
|
||||||
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783
|
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783
|
||||||
|
golang.org/x/sync v0.1.0
|
||||||
gomodules.xyz/jsonpatch/v2 v2.2.0
|
gomodules.xyz/jsonpatch/v2 v2.2.0
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
k8s.io/api v0.26.0
|
k8s.io/api v0.26.2
|
||||||
k8s.io/apimachinery v0.26.0
|
k8s.io/apimachinery v0.26.2
|
||||||
k8s.io/client-go v0.26.0
|
k8s.io/client-go v0.26.2
|
||||||
sigs.k8s.io/controller-runtime v0.14.1
|
sigs.k8s.io/controller-runtime v0.14.4
|
||||||
sigs.k8s.io/yaml v1.3.0
|
sigs.k8s.io/yaml v1.3.0
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -52,6 +54,7 @@ require (
|
|||||||
github.com/go-openapi/jsonreference v0.20.0 // indirect
|
github.com/go-openapi/jsonreference v0.20.0 // indirect
|
||||||
github.com/go-openapi/swag v0.19.14 // indirect
|
github.com/go-openapi/swag v0.19.14 // indirect
|
||||||
github.com/go-sql-driver/mysql v1.4.1 // indirect
|
github.com/go-sql-driver/mysql v1.4.1 // indirect
|
||||||
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
github.com/golang/protobuf v1.5.2 // indirect
|
github.com/golang/protobuf v1.5.2 // indirect
|
||||||
@@ -59,6 +62,7 @@ require (
|
|||||||
github.com/google/go-github/v45 v45.2.0 // indirect
|
github.com/google/go-github/v45 v45.2.0 // indirect
|
||||||
github.com/google/go-querystring v1.1.0 // indirect
|
github.com/google/go-querystring v1.1.0 // indirect
|
||||||
github.com/google/gofuzz v1.1.0 // indirect
|
github.com/google/gofuzz v1.1.0 // indirect
|
||||||
|
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
|
||||||
github.com/gruntwork-io/go-commons v0.8.0 // indirect
|
github.com/gruntwork-io/go-commons v0.8.0 // indirect
|
||||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||||
@@ -82,20 +86,21 @@ require (
|
|||||||
github.com/prometheus/procfs v0.8.0 // indirect
|
github.com/prometheus/procfs v0.8.0 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
github.com/stretchr/objx v0.4.0 // indirect
|
github.com/stretchr/objx v0.5.0 // indirect
|
||||||
github.com/urfave/cli v1.22.2 // indirect
|
github.com/urfave/cli v1.22.2 // indirect
|
||||||
go.uber.org/atomic v1.7.0 // indirect
|
go.uber.org/atomic v1.7.0 // indirect
|
||||||
golang.org/x/crypto v0.1.0 // indirect
|
golang.org/x/crypto v0.1.0 // indirect
|
||||||
golang.org/x/sys v0.5.0 // indirect
|
golang.org/x/sys v0.6.0 // indirect
|
||||||
golang.org/x/term v0.5.0 // indirect
|
golang.org/x/term v0.6.0 // indirect
|
||||||
golang.org/x/text v0.7.0 // indirect
|
golang.org/x/text v0.8.0 // indirect
|
||||||
golang.org/x/time v0.3.0 // indirect
|
golang.org/x/time v0.3.0 // indirect
|
||||||
|
golang.org/x/tools v0.6.0 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
google.golang.org/protobuf v1.28.1 // indirect
|
google.golang.org/protobuf v1.28.1 // indirect
|
||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
k8s.io/apiextensions-apiserver v0.26.0 // indirect
|
k8s.io/apiextensions-apiserver v0.26.1 // indirect
|
||||||
k8s.io/component-base v0.26.0 // indirect
|
k8s.io/component-base v0.26.1 // indirect
|
||||||
k8s.io/klog/v2 v2.80.1 // indirect
|
k8s.io/klog/v2 v2.80.1 // indirect
|
||||||
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect
|
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect
|
||||||
k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 // indirect
|
k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 // indirect
|
||||||
|
|||||||
83
go.sum
83
go.sum
@@ -121,12 +121,14 @@ github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/
|
|||||||
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
|
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
|
||||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
github.com/golang-jwt/jwt/v4 v4.4.1 h1:pC5DB52sCeK48Wlb9oPcdhnjkz1TKt1D/P7WKJ0kUcQ=
|
|
||||||
github.com/golang-jwt/jwt/v4 v4.4.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
github.com/golang-jwt/jwt/v4 v4.4.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||||
|
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
|
||||||
|
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
@@ -178,6 +180,8 @@ github.com/google/go-github/v45 v45.2.0 h1:5oRLszbrkvxDDqBCNj2hjDZMKmvexaZ1xw/FC
|
|||||||
github.com/google/go-github/v45 v45.2.0/go.mod h1:FObaZJEDSTa/WGCzZ2Z3eoCDXWJKMenWWTrd8jrta28=
|
github.com/google/go-github/v45 v45.2.0/go.mod h1:FObaZJEDSTa/WGCzZ2Z3eoCDXWJKMenWWTrd8jrta28=
|
||||||
github.com/google/go-github/v47 v47.1.0 h1:Cacm/WxQBOa9lF0FT0EMjZ2BWMetQ1TQfyurn4yF1z8=
|
github.com/google/go-github/v47 v47.1.0 h1:Cacm/WxQBOa9lF0FT0EMjZ2BWMetQ1TQfyurn4yF1z8=
|
||||||
github.com/google/go-github/v47 v47.1.0/go.mod h1:VPZBXNbFSJGjyjFRUKo9vZGawTajnWzC/YjGw/oFKi0=
|
github.com/google/go-github/v47 v47.1.0/go.mod h1:VPZBXNbFSJGjyjFRUKo9vZGawTajnWzC/YjGw/oFKi0=
|
||||||
|
github.com/google/go-github/v50 v50.0.0 h1:gdO1AeuSZZK4iYWwVbjni7zg8PIQhp7QfmPunr016Jk=
|
||||||
|
github.com/google/go-github/v50 v50.0.0/go.mod h1:Ev4Tre8QoKiolvbpOSG3FIi4Mlon3S2Nt9W5JYqKiwA=
|
||||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
@@ -192,6 +196,8 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf
|
|||||||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
|
||||||
|
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
@@ -202,8 +208,8 @@ github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB7
|
|||||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/gruntwork-io/go-commons v0.8.0 h1:k/yypwrPqSeYHevLlEDmvmgQzcyTwrlZGRaxEM6G0ro=
|
github.com/gruntwork-io/go-commons v0.8.0 h1:k/yypwrPqSeYHevLlEDmvmgQzcyTwrlZGRaxEM6G0ro=
|
||||||
github.com/gruntwork-io/go-commons v0.8.0/go.mod h1:gtp0yTtIBExIZp7vyIV9I0XQkVwiQZze678hvDXof78=
|
github.com/gruntwork-io/go-commons v0.8.0/go.mod h1:gtp0yTtIBExIZp7vyIV9I0XQkVwiQZze678hvDXof78=
|
||||||
github.com/gruntwork-io/terratest v0.41.9 h1:jyygu23iLcEFjGQhlvRx4R0EJVqOoriP+Ire4U9cZA0=
|
github.com/gruntwork-io/terratest v0.41.11 h1:EAHiK6PFWJCVkgW2yUompjSsZQzA0CfBcuqIaXtZdpk=
|
||||||
github.com/gruntwork-io/terratest v0.41.9/go.mod h1:qH1xkPTTGx30XkMHw8jAVIbzqheSjIa5IyiTwSV2vKI=
|
github.com/gruntwork-io/terratest v0.41.11/go.mod h1:qH1xkPTTGx30XkMHw8jAVIbzqheSjIa5IyiTwSV2vKI=
|
||||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
|
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
|
||||||
@@ -218,6 +224,7 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
|
|||||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
|
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
|
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
|
||||||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||||
@@ -286,12 +293,12 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
|
|||||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||||
github.com/onsi/ginkgo/v2 v2.7.0 h1:/XxtEV3I3Eif/HobnVx9YmJgk8ENdRsuUmM+fLCFNow=
|
github.com/onsi/ginkgo/v2 v2.9.0 h1:Tugw2BKlNHTMfG+CheOITkYvk4LAh6MFOvikhGVnhE8=
|
||||||
github.com/onsi/ginkgo/v2 v2.7.0/go.mod h1:yjiuMwPokqY1XauOgju45q3sJt6VzQ/Fict1LFVcsAo=
|
github.com/onsi/ginkgo/v2 v2.9.0/go.mod h1:4xkjoL/tZv4SMWeww56BU5kAt19mVB47gTWxmrTcxyk=
|
||||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||||
github.com/onsi/gomega v1.25.0 h1:Vw7br2PCDYijJHSfBOWhov+8cAnUf8MfMaIOV323l6Y=
|
github.com/onsi/gomega v1.27.2 h1:SKU0CXeKE/WVgIV1T61kSa3+IRE8Ekrv9rdXDwwTqnY=
|
||||||
github.com/onsi/gomega v1.25.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM=
|
github.com/onsi/gomega v1.27.2/go.mod h1:5mR3phAHpkAVIDkHEUBY6HGVsU+cpcEscrGPB4oPlZI=
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
@@ -339,8 +346,9 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
|
|||||||
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
|
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
|
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
|
||||||
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
@@ -348,10 +356,11 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
|
|||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/teambition/rrule-go v1.8.0 h1:a/IX5s56hGkFF+nRlJUooZU/45OTeeldBGL29nDKIHw=
|
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||||
github.com/teambition/rrule-go v1.8.0/go.mod h1:Ieq5AbrKGciP1V//Wq8ktsTXwSwJHDD5mD/wLBGl3p4=
|
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
|
github.com/teambition/rrule-go v1.8.2 h1:lIjpjvWTj9fFUZCmuoVDrKVOtdiyzbzc93qTmRVe/J8=
|
||||||
|
github.com/teambition/rrule-go v1.8.2/go.mod h1:Ieq5AbrKGciP1V//Wq8ktsTXwSwJHDD5mD/wLBGl3p4=
|
||||||
github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo=
|
github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo=
|
||||||
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
@@ -448,10 +457,8 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx
|
|||||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
|
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
|
||||||
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||||
golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q=
|
|
||||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
@@ -471,6 +478,8 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||||
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
@@ -518,16 +527,12 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
|
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
||||||
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.4.0 h1:O7UWfv5+A2qiuulQk30kVinPoMtoIPeVaKLEgLpVkvg=
|
golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw=
|
||||||
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
|
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||||
golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=
|
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
@@ -535,10 +540,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
|||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
|
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
|
||||||
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
|
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
@@ -588,6 +591,8 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc
|
|||||||
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
|
||||||
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
@@ -705,16 +710,16 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
|
|||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||||
k8s.io/api v0.26.0 h1:IpPlZnxBpV1xl7TGk/X6lFtpgjgntCg8PJ+qrPHAC7I=
|
k8s.io/api v0.26.2 h1:dM3cinp3PGB6asOySalOZxEG4CZ0IAdJsrYZXE/ovGQ=
|
||||||
k8s.io/api v0.26.0/go.mod h1:k6HDTaIFC8yn1i6pSClSqIwLABIcLV9l5Q4EcngKnQg=
|
k8s.io/api v0.26.2/go.mod h1:1kjMQsFE+QHPfskEcVNgL3+Hp88B80uj0QtSOlj8itU=
|
||||||
k8s.io/apiextensions-apiserver v0.26.0 h1:Gy93Xo1eg2ZIkNX/8vy5xviVSxwQulsnUdQ00nEdpDo=
|
k8s.io/apiextensions-apiserver v0.26.1 h1:cB8h1SRk6e/+i3NOrQgSFij1B2S0Y0wDoNl66bn8RMI=
|
||||||
k8s.io/apiextensions-apiserver v0.26.0/go.mod h1:7ez0LTiyW5nq3vADtK6C3kMESxadD51Bh6uz3JOlqWQ=
|
k8s.io/apiextensions-apiserver v0.26.1/go.mod h1:AptjOSXDGuE0JICx/Em15PaoO7buLwTs0dGleIHixSM=
|
||||||
k8s.io/apimachinery v0.26.0 h1:1feANjElT7MvPqp0JT6F3Ss6TWDwmcjLypwoPpEf7zg=
|
k8s.io/apimachinery v0.26.2 h1:da1u3D5wfR5u2RpLhE/ZtZS2P7QvDgLZTi9wrNZl/tQ=
|
||||||
k8s.io/apimachinery v0.26.0/go.mod h1:tnPmbONNJ7ByJNz9+n9kMjNP8ON+1qoAIIC70lztu74=
|
k8s.io/apimachinery v0.26.2/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I=
|
||||||
k8s.io/client-go v0.26.0 h1:lT1D3OfO+wIi9UFolCrifbjUUgu7CpLca0AD8ghRLI8=
|
k8s.io/client-go v0.26.2 h1:s1WkVujHX3kTp4Zn4yGNFK+dlDXy1bAAkIl+cFAiuYI=
|
||||||
k8s.io/client-go v0.26.0/go.mod h1:I2Sh57A79EQsDmn7F7ASpmru1cceh3ocVT9KlX2jEZg=
|
k8s.io/client-go v0.26.2/go.mod h1:u5EjOuSyBa09yqqyY7m3abZeovO/7D/WehVVlZ2qcqU=
|
||||||
k8s.io/component-base v0.26.0 h1:0IkChOCohtDHttmKuz+EP3j3+qKmV55rM9gIFTXA7Vs=
|
k8s.io/component-base v0.26.1 h1:4ahudpeQXHZL5kko+iDHqLj/FSGAEUnSVO0EBbgDd+4=
|
||||||
k8s.io/component-base v0.26.0/go.mod h1:lqHwlfV1/haa14F/Z5Zizk5QmzaVf23nQzCwVOQpfC8=
|
k8s.io/component-base v0.26.1/go.mod h1:VHrLR0b58oC035w6YQiBSbtsf0ThuSwXP+p5dD/kAWU=
|
||||||
k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4=
|
k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4=
|
||||||
k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
|
k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
|
||||||
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E=
|
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E=
|
||||||
@@ -724,8 +729,8 @@ k8s.io/utils v0.0.0-20221128185143-99ec85e7a448/go.mod h1:OLgZIPagt7ERELqWJFomSt
|
|||||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||||
sigs.k8s.io/controller-runtime v0.14.1 h1:vThDes9pzg0Y+UbCPY3Wj34CGIYPgdmspPm2GIpxpzM=
|
sigs.k8s.io/controller-runtime v0.14.4 h1:Kd/Qgx5pd2XUL08eOV2vwIq3L9GhIbJ5Nxengbd4/0M=
|
||||||
sigs.k8s.io/controller-runtime v0.14.1/go.mod h1:GaRkrY8a7UZF0kqFFbUKG7n9ICiTY5T55P1RiE3UZlU=
|
sigs.k8s.io/controller-runtime v0.14.4/go.mod h1:WqIdsAY6JBsjfc/CqO0CORmNtoCtE4S6qbPc9s68h+0=
|
||||||
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k=
|
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k=
|
||||||
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
|
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-logr/logr"
|
"github.com/go-logr/logr"
|
||||||
gogithub "github.com/google/go-github/v47/github"
|
gogithub "github.com/google/go-github/v50/github"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
|
||||||
"github.com/actions/actions-runner-controller/github"
|
"github.com/actions/actions-runner-controller/github"
|
||||||
@@ -59,11 +59,34 @@ func (reader *EventReader) ProcessWorkflowJobEvent(ctx context.Context, event in
|
|||||||
}
|
}
|
||||||
|
|
||||||
// collect labels
|
// collect labels
|
||||||
labels := make(prometheus.Labels)
|
var (
|
||||||
|
labels = make(prometheus.Labels)
|
||||||
|
keysAndValues = []interface{}{"job_id", fmt.Sprint(*e.WorkflowJob.ID)}
|
||||||
|
)
|
||||||
|
|
||||||
runsOn := strings.Join(e.WorkflowJob.Labels, `,`)
|
runsOn := strings.Join(e.WorkflowJob.Labels, `,`)
|
||||||
labels["runs_on"] = runsOn
|
labels["runs_on"] = runsOn
|
||||||
|
|
||||||
labels["job_name"] = *e.WorkflowJob.Name
|
labels["job_name"] = *e.WorkflowJob.Name
|
||||||
|
keysAndValues = append(keysAndValues, "job_name", *e.WorkflowJob.Name)
|
||||||
|
|
||||||
|
if e.Repo != nil {
|
||||||
|
if n := e.Repo.Name; n != nil {
|
||||||
|
labels["repository"] = *n
|
||||||
|
keysAndValues = append(keysAndValues, "repository", *n)
|
||||||
|
}
|
||||||
|
if n := e.Repo.FullName; n != nil {
|
||||||
|
labels["repository_full_name"] = *n
|
||||||
|
keysAndValues = append(keysAndValues, "repository_full_name", *n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if e.Org != nil {
|
||||||
|
if n := e.Org.Name; n != nil {
|
||||||
|
labels["organization"] = *e.Org.Name
|
||||||
|
keysAndValues = append(keysAndValues, "organization", *n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// switch on job status
|
// switch on job status
|
||||||
switch action := e.GetAction(); action {
|
switch action := e.GetAction(); action {
|
||||||
@@ -82,10 +105,11 @@ func (reader *EventReader) ProcessWorkflowJobEvent(ctx context.Context, event in
|
|||||||
reader.Log.Error(err, "reading workflow job log")
|
reader.Log.Error(err, "reading workflow job log")
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
reader.Log.Info("reading workflow_job logs",
|
reader.Log.WithValues("job_name", *e.WorkflowJob.Name, "job_id", fmt.Sprint(*e.WorkflowJob.ID), "repository", *e.Repo.Name, "repository_full_name", *e.Repo.FullName)
|
||||||
"job_name", *e.WorkflowJob.Name,
|
if len(*e.Org.Name) > 0 {
|
||||||
"job_id", fmt.Sprint(*e.WorkflowJob.ID),
|
reader.Log.WithValues("organization", *e.Org.Name)
|
||||||
)
|
}
|
||||||
|
reader.Log.Info("reading workflow_job logs")
|
||||||
}
|
}
|
||||||
|
|
||||||
githubWorkflowJobQueueDurationSeconds.With(labels).Observe(parseResult.QueueTime.Seconds())
|
githubWorkflowJobQueueDurationSeconds.With(labels).Observe(parseResult.QueueTime.Seconds())
|
||||||
@@ -101,15 +125,16 @@ func (reader *EventReader) ProcessWorkflowJobEvent(ctx context.Context, event in
|
|||||||
reader.Log.Error(err, "reading workflow job log")
|
reader.Log.Error(err, "reading workflow job log")
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
reader.Log.Info("reading workflow_job logs",
|
reader.Log.Info("reading workflow_job logs", keysAndValues...)
|
||||||
"job_name", *e.WorkflowJob.Name,
|
|
||||||
"job_id", fmt.Sprint(*e.WorkflowJob.ID),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if *e.WorkflowJob.Conclusion == "failure" {
|
if *e.WorkflowJob.Conclusion == "failure" {
|
||||||
failedStep := "null"
|
failedStep := "null"
|
||||||
for i, step := range e.WorkflowJob.Steps {
|
for i, step := range e.WorkflowJob.Steps {
|
||||||
|
conclusion := step.Conclusion
|
||||||
|
if conclusion == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// *step.Conclusion ~
|
// *step.Conclusion ~
|
||||||
// "success",
|
// "success",
|
||||||
@@ -120,11 +145,11 @@ func (reader *EventReader) ProcessWorkflowJobEvent(ctx context.Context, event in
|
|||||||
// "timed_out",
|
// "timed_out",
|
||||||
// "action_required",
|
// "action_required",
|
||||||
// null
|
// null
|
||||||
if *step.Conclusion == "failure" {
|
if *conclusion == "failure" {
|
||||||
failedStep = fmt.Sprint(i)
|
failedStep = fmt.Sprint(i)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if *step.Conclusion == "timed_out" {
|
if *conclusion == "timed_out" {
|
||||||
failedStep = fmt.Sprint(i)
|
failedStep = fmt.Sprint(i)
|
||||||
parseResult.ExitCode = "timed_out"
|
parseResult.ExitCode = "timed_out"
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ DIND_ROOTLESS_RUNNER_NAME ?= ${DOCKER_USER}/actions-runner-dind-rootless
|
|||||||
OS_IMAGE ?= ubuntu-22.04
|
OS_IMAGE ?= ubuntu-22.04
|
||||||
TARGETPLATFORM ?= $(shell arch)
|
TARGETPLATFORM ?= $(shell arch)
|
||||||
|
|
||||||
RUNNER_VERSION ?= 2.301.1
|
RUNNER_VERSION ?= 2.302.1
|
||||||
RUNNER_CONTAINER_HOOKS_VERSION ?= 0.2.0
|
RUNNER_CONTAINER_HOOKS_VERSION ?= 0.2.0
|
||||||
DOCKER_VERSION ?= 20.10.21
|
DOCKER_VERSION ?= 20.10.21
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
2.301.1
|
2.302.1
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ ARG RUNNER_VERSION
|
|||||||
ARG RUNNER_CONTAINER_HOOKS_VERSION=0.2.0
|
ARG RUNNER_CONTAINER_HOOKS_VERSION=0.2.0
|
||||||
# Docker and Docker Compose arguments
|
# Docker and Docker Compose arguments
|
||||||
ENV CHANNEL=stable
|
ENV CHANNEL=stable
|
||||||
ARG DOCKER_COMPOSE_VERSION=v2.6.0
|
ARG DOCKER_COMPOSE_VERSION=v2.16.0
|
||||||
ARG DUMB_INIT_VERSION=1.2.5
|
ARG DUMB_INIT_VERSION=1.2.5
|
||||||
|
|
||||||
# Other arguments
|
# Other arguments
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ ARG RUNNER_VERSION
|
|||||||
ARG RUNNER_CONTAINER_HOOKS_VERSION=0.2.0
|
ARG RUNNER_CONTAINER_HOOKS_VERSION=0.2.0
|
||||||
# Docker and Docker Compose arguments
|
# Docker and Docker Compose arguments
|
||||||
ENV CHANNEL=stable
|
ENV CHANNEL=stable
|
||||||
ARG DOCKER_COMPOSE_VERSION=v2.12.2
|
ARG DOCKER_COMPOSE_VERSION=v2.16.0
|
||||||
ARG DUMB_INIT_VERSION=1.2.5
|
ARG DUMB_INIT_VERSION=1.2.5
|
||||||
ARG RUNNER_USER_UID=1001
|
ARG RUNNER_USER_UID=1001
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ ARG RUNNER_CONTAINER_HOOKS_VERSION=0.2.0
|
|||||||
# Docker and Docker Compose arguments
|
# Docker and Docker Compose arguments
|
||||||
ARG CHANNEL=stable
|
ARG CHANNEL=stable
|
||||||
ARG DOCKER_VERSION=20.10.18
|
ARG DOCKER_VERSION=20.10.18
|
||||||
ARG DOCKER_COMPOSE_VERSION=v2.6.0
|
ARG DOCKER_COMPOSE_VERSION=v2.16.0
|
||||||
ARG DUMB_INIT_VERSION=1.2.5
|
ARG DUMB_INIT_VERSION=1.2.5
|
||||||
|
|
||||||
# Use 1001 and 121 for compatibility with GitHub-hosted runners
|
# Use 1001 and 121 for compatibility with GitHub-hosted runners
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ ARG RUNNER_CONTAINER_HOOKS_VERSION=0.2.0
|
|||||||
# Docker and Docker Compose arguments
|
# Docker and Docker Compose arguments
|
||||||
ARG CHANNEL=stable
|
ARG CHANNEL=stable
|
||||||
ARG DOCKER_VERSION=20.10.21
|
ARG DOCKER_VERSION=20.10.21
|
||||||
ARG DOCKER_COMPOSE_VERSION=v2.12.2
|
ARG DOCKER_COMPOSE_VERSION=v2.16.0
|
||||||
ARG DUMB_INIT_VERSION=1.2.5
|
ARG DUMB_INIT_VERSION=1.2.5
|
||||||
ARG RUNNER_USER_UID=1001
|
ARG RUNNER_USER_UID=1001
|
||||||
ARG DOCKER_GROUP_GID=121
|
ARG DOCKER_GROUP_GID=121
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ ARG RUNNER_CONTAINER_HOOKS_VERSION=0.2.0
|
|||||||
# Docker and Docker Compose arguments
|
# Docker and Docker Compose arguments
|
||||||
ARG CHANNEL=stable
|
ARG CHANNEL=stable
|
||||||
ARG DOCKER_VERSION=20.10.18
|
ARG DOCKER_VERSION=20.10.18
|
||||||
ARG DOCKER_COMPOSE_VERSION=v2.6.0
|
ARG DOCKER_COMPOSE_VERSION=v2.16.0
|
||||||
ARG DUMB_INIT_VERSION=1.2.5
|
ARG DUMB_INIT_VERSION=1.2.5
|
||||||
|
|
||||||
# Use 1001 and 121 for compatibility with GitHub-hosted runners
|
# Use 1001 and 121 for compatibility with GitHub-hosted runners
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ ARG RUNNER_CONTAINER_HOOKS_VERSION=0.2.0
|
|||||||
# Docker and Docker Compose arguments
|
# Docker and Docker Compose arguments
|
||||||
ARG CHANNEL=stable
|
ARG CHANNEL=stable
|
||||||
ARG DOCKER_VERSION=20.10.21
|
ARG DOCKER_VERSION=20.10.21
|
||||||
ARG DOCKER_COMPOSE_VERSION=v2.12.2
|
ARG DOCKER_COMPOSE_VERSION=v2.16.0
|
||||||
ARG DUMB_INIT_VERSION=1.2.5
|
ARG DUMB_INIT_VERSION=1.2.5
|
||||||
ARG RUNNER_USER_UID=1001
|
ARG RUNNER_USER_UID=1001
|
||||||
ARG DOCKER_GROUP_GID=121
|
ARG DOCKER_GROUP_GID=121
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ var (
|
|||||||
|
|
||||||
testResultCMNamePrefix = "test-result-"
|
testResultCMNamePrefix = "test-result-"
|
||||||
|
|
||||||
RunnerVersion = "2.301.1"
|
RunnerVersion = "2.302.1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// If you're willing to run this test via VS Code "run test" or "debug test",
|
// If you're willing to run this test via VS Code "run test" or "debug test",
|
||||||
@@ -398,6 +398,7 @@ type env struct {
|
|||||||
appID, appInstallationID, appPrivateKeyFile string
|
appID, appInstallationID, appPrivateKeyFile string
|
||||||
githubToken, testRepo, testOrg, testOrgRepo string
|
githubToken, testRepo, testOrg, testOrgRepo string
|
||||||
githubTokenWebhook string
|
githubTokenWebhook string
|
||||||
|
createSecretsUsingHelm string
|
||||||
testEnterprise string
|
testEnterprise string
|
||||||
testEphemeral string
|
testEphemeral string
|
||||||
scaleDownDelaySecondsAfterScaleOut int64
|
scaleDownDelaySecondsAfterScaleOut int64
|
||||||
@@ -533,6 +534,7 @@ func initTestEnv(t *testing.T, k8sMinorVer string, vars vars) *env {
|
|||||||
e.appInstallationID = testing.Getenv(t, "GITHUB_APP_INSTALLATION_ID")
|
e.appInstallationID = testing.Getenv(t, "GITHUB_APP_INSTALLATION_ID")
|
||||||
e.appPrivateKeyFile = testing.Getenv(t, "GITHUB_APP_PRIVATE_KEY_FILE")
|
e.appPrivateKeyFile = testing.Getenv(t, "GITHUB_APP_PRIVATE_KEY_FILE")
|
||||||
e.githubTokenWebhook = testing.Getenv(t, "WEBHOOK_GITHUB_TOKEN")
|
e.githubTokenWebhook = testing.Getenv(t, "WEBHOOK_GITHUB_TOKEN")
|
||||||
|
e.createSecretsUsingHelm = testing.Getenv(t, "CREATE_SECRETS_USING_HELM")
|
||||||
e.repoToCommit = testing.Getenv(t, "TEST_COMMIT_REPO")
|
e.repoToCommit = testing.Getenv(t, "TEST_COMMIT_REPO")
|
||||||
e.testRepo = testing.Getenv(t, "TEST_REPO", "")
|
e.testRepo = testing.Getenv(t, "TEST_REPO", "")
|
||||||
e.testOrg = testing.Getenv(t, "TEST_ORG", "")
|
e.testOrg = testing.Getenv(t, "TEST_ORG", "")
|
||||||
@@ -718,6 +720,7 @@ func (e *env) installActionsRunnerController(t *testing.T, repo, tag, testID, ch
|
|||||||
|
|
||||||
varEnv := []string{
|
varEnv := []string{
|
||||||
"WEBHOOK_GITHUB_TOKEN=" + e.githubTokenWebhook,
|
"WEBHOOK_GITHUB_TOKEN=" + e.githubTokenWebhook,
|
||||||
|
"CREATE_SECRETS_USING_HELM=" + e.createSecretsUsingHelm,
|
||||||
"TEST_ID=" + testID,
|
"TEST_ID=" + testID,
|
||||||
"NAME=" + repo,
|
"NAME=" + repo,
|
||||||
"VERSION=" + tag,
|
"VERSION=" + tag,
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user