Keycloak - Scalability benchmark #76
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Keycloak - Scalability benchmark | |
on: | |
workflow_dispatch: | |
inputs: | |
clusterName: | |
description: 'Name of the cluster' | |
type: string | |
default: 'gh-keycloak' | |
scenarioName: | |
description: 'Name of the benchmark scenario to run' | |
type: choice | |
options: | |
- 'authentication.ClientSecret' | |
- 'authentication.AuthorizationCode' | |
numberOfEntitiesInRealm: | |
description: 'Number of entities for the scenario' | |
type: string | |
default: '10000' | |
maxWaitEntityCreation: | |
description: 'Maximum number of seconds to wait for creation of entities' | |
type: string | |
default: '900' | |
numberOfEntitiesUsedInTest: | |
description: 'Number of entities used in test (default: all entities)' | |
type: string | |
initialUsersPerSecond: | |
description: 'Initial users per second' | |
type: string | |
# the number of the first iteration should be large enough to warm up all the nodes | |
default: '20' | |
skipCreateDeployment: | |
description: 'Skip creating Keycloak deployment' | |
type: boolean | |
default: false | |
skipCreateDataset: | |
description: 'Skip creating dataset' | |
type: boolean | |
default: false | |
skipDeleteProject: | |
description: 'Skip deleting project' | |
type: boolean | |
default: false | |
concurrency: cluster_${{ github.event.inputs.clusterName || format('gh-{0}', github.repository_owner) }} | |
env: | |
PROJECT_PREFIX: runner- # same as default | |
PROJECT: runner-keycloak | |
jobs: | |
run: | |
name: Run Benchmark | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v3 | |
- name: Setup ROSA CLI | |
uses: ./.github/actions/rosa-cli-setup | |
with: | |
aws-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
aws-default-region: ${{ vars.AWS_DEFAULT_REGION }} | |
rosa-token: ${{ secrets.ROSA_TOKEN }} | |
- name: Login to OpenShift cluster | |
uses: ./.github/actions/oc-keycloak-login | |
with: | |
clusterName: ${{ inputs.clusterName || format('gh-{0}', github.repository_owner) }} | |
- name: Set up JDK | |
uses: actions/setup-java@v3 | |
with: | |
distribution: 'temurin' | |
java-version: '17' | |
cache: 'maven' | |
- name: Cache Maven Wrapper | |
uses: actions/cache@v3 | |
with: | |
path: | | |
.mvn/wrapper/maven-wrapper.jar | |
key: ${{ runner.os }}-maven-wrapper-${{ hashFiles('**/maven-wrapper.properties') }} | |
restore-keys: | | |
${{ runner.os }}-maven-wrapper- | |
- name: Build with Maven | |
run: | | |
./mvnw -B clean package -DskipTests -pl benchmark | |
tar xfvz benchmark/target/keycloak-benchmark-*.tar.gz | |
mv keycloak-benchmark-* keycloak-benchmark | |
- name: Allow cluster to scale | |
if: ${{ !inputs.skipCreateDeployment }} | |
run: rosa edit machinepool -c ${{ inputs.clusterName }} --min-replicas 3 --max-replicas 10 scaling | |
- name: Create Keycloak deployment | |
if: ${{ !inputs.skipCreateDeployment }} | |
uses: ./.github/actions/keycloak-create-deployment | |
with: | |
projectPrefix: ${{ env.PROJECT_PREFIX }} | |
disableStickySessions: true | |
podCpuRequests: 4 | |
podCpuLimit: 4 | |
- name: Create Keycloak dataset with "${{ inputs.numberOfEntitiesInRealm }}" clients | |
if: "!inputs.skipCreateDataset && inputs.scenarioName == 'authentication.ClientSecret'" | |
uses: ./.github/actions/keycloak-create-dataset | |
with: | |
project: ${{ env.PROJECT }} | |
clients: ${{ inputs.numberOfEntitiesInRealm }} | |
maxWaitEntityCreation: ${{ inputs.maxWaitEntityCreation }} | |
- name: Create Keycloak dataset with "${{ inputs.numberOfEntitiesInRealm }}" users | |
if: "!inputs.skipCreateDataset && inputs.scenarioName == 'authentication.AuthorizationCode'" | |
uses: ./.github/actions/keycloak-create-dataset | |
with: | |
project: ${{ env.PROJECT }} | |
users: ${{ inputs.numberOfEntitiesInRealm }} | |
maxWaitEntityCreation: ${{ inputs.maxWaitEntityCreation }} | |
- name: Get URLs | |
uses: ./.github/actions/get-keycloak-url | |
with: | |
project: ${{ env.PROJECT }} | |
- name: Run "authentication.ClientSecret" scalability scenario | |
if: inputs.scenarioName == 'authentication.ClientSecret' | |
id: kcb-client-secret | |
run: | | |
bin/kcb.sh --scenario=keycloak.scenario."${{ inputs.scenarioName }}" \ | |
--server-url=${{ env.KEYCLOAK_URL }} \ | |
--users-per-sec=${{ inputs.initialUsersPerSecond }} \ | |
--increment=32 \ | |
--measurement=60 \ | |
--realm-name=realm-0 \ | |
--clients-per-realm=${{ inputs.numberOfEntitiesUsedInTest || inputs.numberOfEntitiesInRealm }} | |
working-directory: keycloak-benchmark | |
- name: Run "authentication.AuthorizationCode" scalability scenario | |
if: inputs.scenarioName == 'authentication.AuthorizationCode' | |
id: kcb-authorization-code | |
run: | | |
bin/kcb.sh --scenario=keycloak.scenario."${{ inputs.scenarioName }}" \ | |
--server-url=${{ env.KEYCLOAK_URL }} \ | |
--users-per-sec=${{ inputs.initialUsersPerSecond }} \ | |
--increment=32 \ | |
--measurement=60 \ | |
--realm-name=realm-0 \ | |
--users-per-realm=${{ inputs.numberOfEntitiesUsedInTest || inputs.numberOfEntitiesInRealm }} | |
working-directory: keycloak-benchmark | |
- name: Archive Gatling reports | |
if: ${{ always() }} | |
uses: actions/upload-artifact@v3 | |
with: | |
name: gatling-results | |
path: keycloak-benchmark/results | |
retention-days: 5 | |
- name: Archive Summary | |
uses: actions/upload-artifact@v3 | |
if: inputs.scenarioName == 'authentication.ClientSecret' | |
with: | |
name: summary | |
path: ${{ steps.kcb-client-secret.outputs.kcb_result }} | |
retention-days: 5 | |
- name: Archive Summary | |
uses: actions/upload-artifact@v3 | |
if: inputs.scenarioName == 'authentication.AuthorizationCode' | |
with: | |
name: summary | |
path: ${{ steps.kcb-authorization-code.outputs.kcb_result }} | |
retention-days: 5 | |
- name: Delete Keycloak deployment | |
if: ${{ (success() || failure()) && !inputs.skipDeleteProject }} | |
uses: ./.github/actions/keycloak-delete-deployment | |
with: | |
project: ${{ env.PROJECT }} | |
- name: Scale down the cluster | |
if: ${{ (success() || failure()) && !inputs.skipDeleteProject }} | |
run: rosa edit machinepool -c ${{ inputs.clusterName }} --min-replicas 0 --max-replicas 0 scaling | |
archive: | |
name: Commit results to Git repository | |
runs-on: ubuntu-latest | |
permissions: | |
contents: write | |
needs: | |
- run | |
steps: | |
- name: Checkout repository for results | |
uses: actions/checkout@v3 | |
with: | |
ref: 'result-data' | |
- uses: actions/download-artifact@v3 | |
with: | |
name: summary | |
- name: Commit result-summary | |
shell: bash | |
env: | |
GITHUB_OAUTH: ${{ secrets.GITHUB_TOKEN }} | |
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
run: | | |
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
git config --global user.name "github-actions[bot]" | |
DATE_FOLDER=scalability/$(date +"%Y/%m/%d") | |
mkdir -p ${DATE_FOLDER} | |
mv *.json ${DATE_FOLDER} | |
git add . | |
git commit -m "generated" | |
git push | |
- name: Trigger data aggregation | |
if: github.repository == 'keycloak/keycloak-benchmark' | |
env: | |
GH_TOKEN: ${{ github.token }} | |
# manually trigger the run, as a push with a standard GitHub action token doesn't trigger any workflow run on GitHub | |
run: gh workflow run -R keycloak/keycloak-benchmark aggregate-results.yaml --ref result-data | |