Skip to content

Commit

Permalink
Add workflow to test OAuth2
Browse files Browse the repository at this point in the history
Follow-up to:
* #956
* #1346

UAA service, RabbitMQ mounts for UAA

Source code checkout happens _after_ service containers are started

Use conventional-actions/docker-run@v1

Start adding test project for OAuth2

Converting OAuth2 test program to Xunit

Run OAuth2 tests using `dotnet test`

Refactor test to use async/await when available

Remove TestApplications/OAuth2

Simplify APIApproval a bit
  • Loading branch information
lukebakken committed Oct 6, 2023
1 parent 55fc05a commit 68afa42
Show file tree
Hide file tree
Showing 38 changed files with 595 additions and 406 deletions.
25 changes: 25 additions & 0 deletions .ci/oauth2/common.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/bash

readonly docker_name_prefix='rabbitmq-dotnet-client-oauth2'

if [[ -d $GITHUB_WORKSPACE ]]
then
echo "[INFO] GITHUB_WORKSPACE is set: '$GITHUB_WORKSPACE'"
else
GITHUB_WORKSPACE="$(readlink --canonicalize-existing "$script_dir/../..")"
echo "[INFO] set GITHUB_WORKSPACE to: '$GITHUB_WORKSPACE'"
fi

set -o xtrace
set -o nounset

readonly mode="${1:-uaa}"
case $mode in
keycloak|uaa)
echo "[INFO] test mode is '$mode'";;
*)
echo "[ERROR] invalid test mode: '$mode'" 1>&2
exit 64
;;
esac

152 changes: 152 additions & 0 deletions .ci/oauth2/setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
#!/bin/bash

set -o errexit
set -o pipefail

script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
readonly script_dir
echo "[INFO] script_dir: '$script_dir'"

source "$script_dir/common.sh"

declare -r uaa_image_version='75.21.0'
declare -r keycloak_image_version='20.0'
declare -r docker_network="$docker_name_prefix-net"
declare -r rabbitmq_docker_name="$docker_name_prefix-rabbitmq"

function err_todo
{
echo '[ERROR] TODO' 1>&2
exit 69
}

function mode_is_uaa
{
[[ $mode == 'uaa' ]]
}

function mode_is_keycloak
{
[[ $mode == 'keycloak' ]]
}

function create_network
{
docker network inspect "$docker_network" >/dev/null 2>&1 || docker network create "$docker_network"
}

function oauth_service_is_not_running
{
if mode_is_uaa
then
[[ "$(curl -s localhost:8080/info | jq -r '.app.version')" != "$uaa_image_version" ]]
else
[[ "$(curl -s localhost:8080/health | jq -r '.status')" != 'UP' ]]
fi
}

function start_rabbitmq
{
docker rm --force "$rabbitmq_docker_name" 2>/dev/null || echo "[INFO] $rabbitmq_docker_name was not running"
docker run --detach --name "$rabbitmq_docker_name" \
--network "$docker_network" \
--publish 5672:5672 \
--publish 15672:15672 \
--volume "$GITHUB_WORKSPACE/projects/OAuth2Test/enabled_plugins:/etc/rabbitmq/enabled_plugins" \
--volume "$GITHUB_WORKSPACE/projects/OAuth2Test/$mode/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf:ro" \
--volume "$GITHUB_WORKSPACE/projects/OAuth2Test/$mode/signing-key/signing-key.pem:/etc/rabbitmq/signing-key.pem:ro" \
rabbitmq:3-management
}

function wait_rabbitmq
{
set +o errexit
set +o xtrace

declare -i count=12
while (( count > 0 )) && [[ "$(docker inspect --format='{{.State.Running}}' "$rabbitmq_docker_name")" != 'true' ]]
do
echo '[WARNING] RabbitMQ container is not yet running...'
sleep 5
(( count-- ))
done

declare -i count=12
while (( count > 0 )) && ! docker exec "$rabbitmq_docker_name" epmd -names | grep -F 'name rabbit'
do
echo '[WARNING] epmd is not reporting rabbit name just yet...'
sleep 5
(( count-- ))
done

docker exec "$rabbitmq_docker_name" rabbitmqctl await_startup

set -o errexit
set -o xtrace
}

function start_oauth_service
{
if mode_is_uaa
then
readonly uaa_docker_name="$docker_name_prefix-uaa"
docker rm --force "$uaa_docker_name" 2>/dev/null || echo "[INFO] $uaa_docker_name was not running"
docker run --detach --name "$uaa_docker_name" \
--network "$docker_network" \
--publish 8080:8080 \
--env 'UAA_CONFIG_PATH=/uaa' \
--env 'JAVA_OPTS=-Djava.security.egd=file:/dev/./urandom' \
--volume "$GITHUB_WORKSPACE/projects/OAuth2Test/uaa:/uaa" \
"cloudfoundry/uaa:$uaa_image_version"
else
readonly keycloak_docker_name="$docker_name_prefix-keycloak"
docker rm --force "$keycloak_docker_name" 2>/dev/null || echo "[INFO] $keycloak_docker_name was not running"
docker run --detach --name "$keycloak_docker_name" \
--network "$docker_network" \
--publish 8080:8080 \
--env 'KEYCLOAK_ADMIN=admin' \
--env 'KEYCLOAK_ADMIN_PASSWORD=admin' \
--env KC_HEALTH_ENABLED=true \
--volume "$GITHUB_WORKSPACE/projects/OAuth2Test/keycloak/import:/opt/keycloak/data/import" \
"quay.io/keycloak/keycloak:$keycloak_image_version" start-dev --metrics-enabled=true --import-realm
fi
}

function wait_oauth_service
{
echo '[INFO] start waiting for OAuth service...'
sleep 10

set +o errexit
set +o xtrace

declare -i count=24
while ((count > 0)) && oauth_service_is_not_running
do
echo '[WARNING] OAuth service is not yet running...'
sleep 10
(( count-- ))
done

if (( count == 0 ))
then
if oauth_service_is_not_running
then
echo '[ERROR] OAUTH SERVICE DID NOT START' 1>&2
docker ps --all
exit 1
fi
fi

set -o errexit
set -o xtrace
}

create_network

start_rabbitmq &
start_oauth_service &
wait

wait_rabbitmq
wait_oauth_service
30 changes: 30 additions & 0 deletions .ci/oauth2/teardown.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/bin/bash

set -o errexit
set -o pipefail

script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
readonly script_dir
echo "[INFO] script_dir: '$script_dir'"

source "$script_dir/common.sh"

function docker_stop
{
local -r name="$1"
local -r docker_name="$docker_name_prefix-$name"

set +o errexit
if docker stop "$docker_name"
then
docker rm "$docker_name"
fi
set -o errexit
}

docker_stop rabbitmq
docker_stop uaa
docker_stop keycloak

declare -r docker_network="$docker_name_prefix-net"
docker network rm --force "$docker_network"
15 changes: 15 additions & 0 deletions .ci/oauth2/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash

set -o errexit
set -o pipefail
set -o xtrace

script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
readonly script_dir
echo "[INFO] script_dir: '$script_dir'"

source "$script_dir/common.sh"

export OAUTH2_MODE="$mode"

dotnet test --environment OAUTH2_MODE="$mode" "$GITHUB_WORKSPACE/projects/OAuth2Test/OAuth2Test.csproj" --logger "console;verbosity=detailed" --framework "net6.0"
32 changes: 32 additions & 0 deletions .github/workflows/oauth2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: rabbitmq-dotnet-client-oauth2

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
build-test:
strategy:
matrix:
oauth2-provider: [ uaa, keycloak ]
name: oauth2-${{ matrix.oauth2-provider }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
submodules: true
- uses: actions/setup-dotnet@v3
with:
dotnet-version: 6.x
- uses: actions/cache@v3
with:
path: |
~/.nuget/packages
~/.local/share/NuGet/v3-cache
key: ${{ runner.os }}-v0-nuget-${{ hashFiles('**/*.csproj') }}
restore-keys: |
${{ runner.os }}-v0-nuget-
- run: ${{ github.workspace }}/.ci/oauth2/setup.sh ${{ matrix.oauth2-provider }}
- run: ${{ github.workspace }}/.ci/oauth2/test.sh ${{ matrix.oauth2-provider }}
1 change: 1 addition & 0 deletions Build.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<ProjectReference Include="projects/TestApplications/CreateChannel/CreateChannel.csproj" />
<ProjectReference Include="projects/TestApplications/MassPublish/MassPublish.csproj" />
<ProjectReference Include="projects/Unit/Unit.csproj" />
<ProjectReference Include="projects/OAuth2Test/OAuth2Test.csproj" />
</ItemGroup>

</Project>
8 changes: 7 additions & 1 deletion RabbitMQDotNetClient.sln
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestApplications", "TestApp
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CreateChannel", "projects\TestApplications\CreateChannel\CreateChannel.csproj", "{4A589408-F3A3-40E1-A6DF-F5E620F7CA31}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RabbitMQ.Client.OAuth2", "projects\RabbitMQ.Client.OAuth2\RabbitMQ.Client.OAuth2.csproj", "{794C7B31-0E9A-44A4-B285-0F3CAF6209F1}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RabbitMQ.Client.OAuth2", "projects\RabbitMQ.Client.OAuth2\RabbitMQ.Client.OAuth2.csproj", "{794C7B31-0E9A-44A4-B285-0F3CAF6209F1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OAuth2Test", "projects\OAuth2Test\OAuth2Test.csproj", "{897D13F0-AF06-444A-9072-CF7E809A4A2C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -51,6 +53,10 @@ Global
{794C7B31-0E9A-44A4-B285-0F3CAF6209F1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{794C7B31-0E9A-44A4-B285-0F3CAF6209F1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{794C7B31-0E9A-44A4-B285-0F3CAF6209F1}.Release|Any CPU.Build.0 = Release|Any CPU
{897D13F0-AF06-444A-9072-CF7E809A4A2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{897D13F0-AF06-444A-9072-CF7E809A4A2C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{897D13F0-AF06-444A-9072-CF7E809A4A2C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{897D13F0-AF06-444A-9072-CF7E809A4A2C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
63 changes: 63 additions & 0 deletions projects/OAuth2Test/APIApproval.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// This source code is dual-licensed under the Apache License, version
// 2.0, and the Mozilla Public License, version 2.0.
//
// The APL v2.0:
//
//---------------------------------------------------------------------------
// Copyright (c) 2007-2020 VMware, Inc.
//
// 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
//
// https://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.
//---------------------------------------------------------------------------
//
// The MPL v2.0:
//
//---------------------------------------------------------------------------
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
//
// Copyright (c) 2007-2020 VMware, Inc. All rights reserved.
//---------------------------------------------------------------------------

using System;
using System.Threading.Tasks;
using PublicApiGenerator;
using VerifyTests;
using VerifyXunit;
using Xunit;

namespace OAuth2Test
{
[UsesVerify]
public class APIApproval
{
private static readonly ApiGeneratorOptions opts = new ApiGeneratorOptions
{
ExcludeAttributes = new[]
{
"System.Runtime.Versioning.TargetFrameworkAttribute",
"System.Reflection.AssemblyMetadataAttribute"
}
};

[Fact]
public Task Approve()
{
Type apiType = typeof(RabbitMQ.Client.OAuth2.IOAuth2Client);
string publicApi = apiType.Assembly.GeneratePublicApi(opts);
var settings = new VerifySettings();
settings.DisableDiff();
return Verifier.Verify(publicApi, settings);
}
}
}
39 changes: 39 additions & 0 deletions projects/OAuth2Test/OAuth2Test.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup Condition="$([MSBuild]::IsOSPlatform('Windows'))">
<TargetFrameworks>net6.0;net472</TargetFrameworks>
</PropertyGroup>

<PropertyGroup Condition="!$([MSBuild]::IsOSPlatform('Windows'))">
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>

<PropertyGroup>
<AssemblyOriginatorKeyFile>../rabbit.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
<LangVersion>latest</LangVersion>
<ReleaseVersion>7.0</ReleaseVersion>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="../RabbitMQ.Client/RabbitMQ.Client.csproj" />
<ProjectReference Include="../RabbitMQ.Client.OAuth2/RabbitMQ.Client.OAuth2.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.1" />
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="PublicApiGenerator" Version="11.0.0" />
<PackageReference Include="xunit" Version="2.5.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.0" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="System.Text.Json" Version="7.0.2" />
<PackageReference Include="WireMock.Net" Version="1.5.24" />
<PackageReference Include="Verify.Xunit" Version="20.8.0" />
<PackageReference Include="Xunit.SkippableFact" Version="1.4.13" />
</ItemGroup>

</Project>
Loading

0 comments on commit 68afa42

Please sign in to comment.