17 Commits

Author SHA1 Message Date
b15827b7b1 Update siteworxpro/config version and modify repositories structure in composer.json
All checks were successful
🧪✨ Tests Workflow / License Check (push) Successful in 2m24s
🧪✨ Tests Workflow / Code Sniffer (push) Successful in 2m21s
🧪✨ Tests Workflow / Code Lint (push) Successful in 2m39s
🧪✨ Tests Workflow / Unit Tests (push) Successful in 2m29s
2025-09-27 08:54:52 -04:00
6e874927a5 Merge pull request 'I don't believe it' (#1) from build into master
All checks were successful
🧪✨ Tests Workflow / License Check (push) Successful in 1m24s
🧪✨ Tests Workflow / Unit Tests (push) Successful in 1m25s
🧪✨ Tests Workflow / Code Lint (push) Successful in 1m27s
🧪✨ Tests Workflow / Code Sniffer (push) Successful in 1m28s
Reviewed-on: Siteworxpro/Traefik-Redis-Api#1
2025-05-22 19:54:53 -04:00
640d5321da Merge branch 'master' into build
All checks were successful
🧪✨ Tests Workflow / Unit Tests (push) Successful in 1m23s
🧪✨ Tests Workflow / License Check (push) Successful in 2m37s
🧪✨ Tests Workflow / Code Lint (push) Successful in 2m36s
🧪✨ Tests Workflow / Code Sniffer (push) Successful in 2m39s
2025-05-22 19:49:38 -04:00
ef525f4332 I don't believe it
Some checks failed
🧪✨ Tests Workflow / Unit Tests (push) Has been cancelled
🧪✨ Tests Workflow / License Check (push) Has started running
🧪✨ Tests Workflow / Code Sniffer (push) Has started running
🧪✨ Tests Workflow / Code Lint (push) Has started running
2025-05-22 19:46:48 -04:00
edd09d9e97 Update README.md
All checks were successful
🧪✨ Tests Workflow / License Check (push) Successful in 2m50s
🧪✨ Tests Workflow / Code Lint (push) Successful in 2m52s
🧪✨ Tests Workflow / Unit Tests (push) Successful in 2m50s
🧪✨ Tests Workflow / Code Sniffer (push) Successful in 2m55s
2025-05-20 19:00:35 -04:00
6aad697954 Replace all whitespaces with tabs.
All checks were successful
🧪✨ Tests Workflow / License Check (push) Successful in 1m37s
🧪✨ Tests Workflow / Code Sniffer (push) Successful in 1m41s
🧪✨ Tests Workflow / Unit Tests (push) Successful in 1m42s
🧪✨ Tests Workflow / Code Lint (push) Successful in 1m45s
2025-05-13 21:17:37 -04:00
0ccaa37400 This is not a commit
All checks were successful
🧪✨ Tests Workflow / License Check (push) Successful in 7m18s
🧪✨ Tests Workflow / Code Lint (push) Successful in 7m19s
🧪✨ Tests Workflow / Unit Tests (push) Successful in 7m17s
🧪✨ Tests Workflow / Code Sniffer (push) Successful in 7m21s
2025-05-13 21:09:34 -04:00
76892bf456 It'd be nice if type errors caused the compiler to issue a type error 2025-05-13 21:04:40 -04:00
9e0e84b4d2 git please work 2025-05-12 16:03:09 -04:00
5587dffeeb I would rather be playing Factorio. 2025-05-12 15:23:04 -04:00
9c1445972d I transformed a bug into a feature. Once you learn how, you'll never forget it 2025-05-12 15:15:41 -04:00
28dcc6a20d And a commit that I don't know the reason of... 2025-05-12 14:43:47 -04:00
7f7af2f3b4 Is there an award for this? 2025-05-12 14:35:00 -04:00
b9f4b4500d For the statistics only 2025-05-12 13:35:16 -04:00
6e340e898f Revert "just testing, remember to revert" 2025-05-12 13:26:28 -04:00
3e232ab198 Fix PC Load Letter Error 2025-05-09 10:33:55 -04:00
f74d7f3895 I have no idea what Copilot was doing there. 2025-05-09 10:18:51 -04:00
24 changed files with 1475 additions and 387 deletions

View File

@@ -0,0 +1,44 @@
on:
create:
tags:
- '*'
name: 🏗️✨ Build Workflow
jobs:
Build:
name: 🖥️🔨 Build
runs-on: ubuntu-latest
steps:
- name: 🛡️ 🔒 Add Siteworx CA Certificates
run: |
curl -Ls https://siteworxpro.com/hosted/Siteworx+Root+CA.pem -o /usr/local/share/ca-certificates/sw.crt
update-ca-certificates
- name: 📖 🔍 Checkout Repository Code
uses: actions/checkout@v2
with:
fetch-depth: 1
- name: 🔑 🔐 Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: 🔑🛠️ Login to Siteworx Registry
uses: docker/login-action@v3
with:
username: ${{ vars.SITEWORX_USERNAME }}
password: ${{ secrets.SITEWORX_PASSWORD }}
registry: scr.siteworxpro.com
- name: 🏗️ 🔧 Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: 🐳 🔨 Build Backend Container
uses: docker/build-push-action@v6
with:
context: .
dockerfile: Dockerfile
tags: scr.siteworxpro.com/traefik-api:${{ gitea.ref_name }}

153
.gitea/workflows/tests.yml Normal file
View File

@@ -0,0 +1,153 @@
on:
push:
branches:
- "*"
name: 🧪✨ Tests Workflow
jobs:
LicenseCheck:
name: License Check
runs-on: ubuntu-latest
steps:
- name: 🛡️ 🔒 Add Siteworx CA Certificates
run: |
curl -Ls https://siteworxpro.com/hosted/Siteworx+Root+CA.pem -o /usr/local/share/ca-certificates/sw.crt
update-ca-certificates
- name: 📖 🔍 Checkout Repository Code
uses: actions/checkout@v2
with:
fetch-depth: 1
- name: 🔑 🔐 Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Install Composer Libraries
run: |
docker run --rm \
--volumes-from ${{ env.JOB_CONTAINER_NAME }} \
-w ${{ github.workspace }} \
siteworxpro/composer \
install --ignore-platform-reqs --no-interaction --prefer-dist --optimize-autoloader
- name: Run License Check
run: |
docker run --rm \
--volumes-from ${{ env.JOB_CONTAINER_NAME }} \
-w ${{ github.workspace }} \
siteworxpro/composer \
run tests:license
CodeLint:
name: Code Lint
runs-on: ubuntu-latest
steps:
- name: 🛡️ 🔒 Add Siteworx CA Certificates
run: |
curl -Ls https://siteworxpro.com/hosted/Siteworx+Root+CA.pem -o /usr/local/share/ca-certificates/sw.crt
update-ca-certificates
- name: 📖 🔍 Checkout Repository Code
uses: actions/checkout@v2
with:
fetch-depth: 1
- name: 🔑 🔐 Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Install Composer Libraries
run: |
docker run --rm \
--volumes-from ${{ env.JOB_CONTAINER_NAME }} \
-w ${{ github.workspace }} \
siteworxpro/composer \
install --ignore-platform-reqs --no-interaction --prefer-dist --optimize-autoloader
- name: Run Code Lint
run: |
docker run --rm \
--volumes-from ${{ env.JOB_CONTAINER_NAME }} \
-w ${{ github.workspace }} \
siteworxpro/composer \
run tests:lint
CodeSniffer:
name: Code Sniffer
runs-on: ubuntu-latest
steps:
- name: 🛡️ 🔒 Add Siteworx CA Certificates
run: |
curl -Ls https://siteworxpro.com/hosted/Siteworx+Root+CA.pem -o /usr/local/share/ca-certificates/sw.crt
update-ca-certificates
- name: 📖 🔍 Checkout Repository Code
uses: actions/checkout@v2
with:
fetch-depth: 1
- name: 🔑 🔐 Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Install Composer Libraries
run: |
docker run --rm \
--volumes-from ${{ env.JOB_CONTAINER_NAME }} \
-w ${{ github.workspace }} \
siteworxpro/composer \
install --ignore-platform-reqs --no-interaction --prefer-dist --optimize-autoloader
- name: Run Code Sniffer
run: |
docker run --rm \
--volumes-from ${{ env.JOB_CONTAINER_NAME }} \
-w ${{ github.workspace }} \
siteworxpro/composer \
run tests:phpstan
UnitTests:
name: Unit Tests
runs-on: ubuntu-latest
steps:
- name: 🛡️ 🔒 Add Siteworx CA Certificates
run: |
curl -Ls https://siteworxpro.com/hosted/Siteworx+Root+CA.pem -o /usr/local/share/ca-certificates/sw.crt
update-ca-certificates
- name: 📖 🔍 Checkout Repository Code
uses: actions/checkout@v2
with:
fetch-depth: 1
- name: 🔑 🔐 Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Install Composer Libraries
run: |
docker run --rm \
--volumes-from ${{ env.JOB_CONTAINER_NAME }} \
-w ${{ github.workspace }} \
siteworxpro/composer \
install --ignore-platform-reqs --no-interaction --prefer-dist --optimize-autoloader
- name: Run Unit Tests
run: |
docker run --rm \
--volumes-from ${{ env.JOB_CONTAINER_NAME }} \
-w ${{ github.workspace }} \
siteworxpro/composer \
run tests:unit

View File

@@ -5,6 +5,8 @@ include:
inputs:
registry: scr.siteworxpro.com
registryUser: $CI_REGISTRY_USER
dockerHubUser: $CI_DOCKER_HUB_USER
dockerHubPat: $CI_DOCKER_HUB_PAT
registryPassword: $CI_REGISTRY_PASSWORD
platform: "linux/amd64,linux/arm64"
stage: build

View File

@@ -14,8 +14,11 @@ Unit Tests:
script: |
echo "Running unit tests..."
composer run tests:unit:coverage
coverage: '/^\s*Lines:\s*\d+.\d+\%/'
artifacts:
expire_in: 1 day
reports:
junit: tests/reports/junit.xml
paths:
- tests/reports/

View File

@@ -1,5 +1,5 @@
# Use the RoadRunner image as a base for the first stage
FROM ghcr.io/roadrunner-server/roadrunner:2024.3.5 AS roadrunner
FROM ghcr.io/roadrunner-server/roadrunner:2025.1.1 AS roadrunner
# Use the official Composer image as the base for the library stage
FROM siteworxpro/composer AS library
@@ -17,7 +17,7 @@ FROM php:8.4.6-alpine AS php
# Move the production PHP configuration file to the default location
RUN mv /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini \
&& apk add libpq-dev linux-headers --no-cache \
&& docker-php-ext-install pdo_pgsql sockets \
&& docker-php-ext-install sockets \
&& rm -rf /var/cache/apk/*
# Set the working directory to /app

View File

@@ -1,8 +1,6 @@
# Traefik Redis Provider API
[![pipeline status](https://git.siteworxpro.com/rrise/traefik-redis-provider-api/badges/master/pipeline.svg)](https://git.siteworxpro.com/rrise/traefik-redis-provider-api/-/commits/master)
[![Latest Release](https://git.siteworxpro.com/rrise/traefik-redis-provider-api/-/badges/release.svg)](https://git.siteworxpro.com/rrise/traefik-redis-provider-api/-/releases)
![Gitea Tests](https://gitea.siteworxpro.com//Siteworxpro/Traefik-Redis-Api/actions/workflows/tests.yml/badge.svg?branch=master)
[Traefik](https://traefik.io/traefik/) is a modern HTTP reverse proxy and load balancer that makes deploying microservices easy. This project provides
an api manager for the [Redis provider](https://doc.traefik.io/traefik/providers/redis/) for Traefik, allowing you to use Redis as a dynamic configuration backend.
@@ -19,7 +17,7 @@ an api manager for the [Redis provider](https://doc.traefik.io/traefik/providers
- `REDIS_DATABASE`: The database number to use. Default is `0`.
- `HTTP_PORT`: The port to run the HTTP server on. Default is `9501`.
```shell
docker run --rm -it -p 9501:9501 scr.siteworxpro.com/traefik-api:v1.1.0
docker run --rm -it -p 9501:9501 scr.siteworxpro.com/traefik-api:v1.3.0
```
## Usage

View File

@@ -15,7 +15,7 @@
"nyholm/psr7": "^1.8",
"illuminate/support": "^v12.10.2",
"roadrunner-php/app-logger": "^1.2",
"siteworxpro/config": "^1.1",
"siteworxpro/config": "^1.1.1",
"predis/predis": "^3.0"
},
"require-dev": {
@@ -33,18 +33,18 @@
"composer run-script tests:phpstan"
],
"tests:unit": [
"phpunit --colors=always --display-deprecations tests "
"phpunit --colors=always --display-deprecations tests"
],
"tests:unit:coverage": [
"phpunit --colors=always --display-deprecations --coverage-html tests/reports/html tests "
"phpunit --coverage-text --colors=never --display-deprecations --log-junit tests/reports/junit.xml --coverage-html tests/reports/html tests "
],
"tests:lint": [
"phpcs ./src --standard=PSR12 --colors -v",
"phpcs ./tests --standard=PSR12 --colors -v"
"phpcs ./src/**/*.php --standard=PSR12 --colors -v",
"phpcs ./tests/**/*.php --standard=PSR12 --colors -v"
],
"tests:lint:fix": [
"phpcbf ./src --standard=PSR12 --colors -v",
"phpcbf ./tests --standard=PSR12 --colors -v"
"phpcbf ./src/**/*.php --standard=PSR12 --colors -v",
"phpcbf ./tests/**/*.php --standard=PSR12 --colors -v"
],
"tests:license": [
"composer-license-checker"
@@ -53,16 +53,10 @@
"phpstan analyse --level 4 ./src/ -c phpstan.neon"
]
},
"repositories": {
"git.siteworxpro.com/24": {
"repositories": [
{
"type": "composer",
"url": "https://git.siteworxpro.com/api/v4/group/24/-/packages/composer/packages.json",
"options": {
"ssl": {
"verify_peer": false,
"allow_self_signed": true
}
}
"url": "https://gitea.siteworxpro.com/api/packages/php-packages/composer"
}
}
]
}

955
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -2,15 +2,15 @@ volumes:
redisdata: {}
services:
composer-runtime:
ports:
- "9501:9501"
volumes:
- .:/app
image: siteworxpro/composer
entrypoint: "/bin/sh -c 'while true; do sleep 30; done;'"
environment:
PHP_IDE_CONFIG: serverName=localhost
dev-runtime:
ports:
- "9501:9501"

View File

@@ -4,10 +4,10 @@ declare(strict_types=1);
namespace Siteworxpro\App\Controllers;
use Illuminate\Support\Facades\Log;
use League\Route\Http\Exception\NotFoundException;
use Nyholm\Psr7\ServerRequest;
use Psr\Http\Message\ResponseInterface;
use Siteworxpro\App\Facades\Logger;
use Siteworxpro\App\Traefik\ProtocolEnum;
abstract class Controller implements ControllerInterface
@@ -19,7 +19,7 @@ abstract class Controller implements ControllerInterface
try {
return ProtocolEnum::fromString($protocol);
} catch (\InvalidArgumentException $e) {
Log::error($e->getMessage());
Logger::error($e->getMessage());
return ProtocolEnum::HTTP;
}

View File

@@ -8,7 +8,7 @@ use Nyholm\Psr7\ServerRequest;
use Psr\Http\Message\ResponseInterface;
use Siteworxpro\App\Http\JsonResponseFactory;
use Siteworxpro\App\Traefik\EntityEnum;
use Siteworxpro\App\Traefik\RedisClient;
use Siteworxpro\App\Facades\RedisClient;
class MiddlewaresController extends Controller
{

View File

@@ -8,7 +8,7 @@ use Nyholm\Psr7\ServerRequest;
use Psr\Http\Message\ResponseInterface;
use Siteworxpro\App\Http\JsonResponseFactory;
use Siteworxpro\App\Traefik\EntityEnum;
use Siteworxpro\App\Traefik\RedisClient;
use Siteworxpro\App\Facades\RedisClient;
class RoutesController extends Controller
{

View File

@@ -8,7 +8,7 @@ use Nyholm\Psr7\ServerRequest;
use Psr\Http\Message\ResponseInterface;
use Siteworxpro\App\Http\JsonResponseFactory;
use Siteworxpro\App\Traefik\EntityEnum;
use Siteworxpro\App\Traefik\RedisClient;
use Siteworxpro\App\Facades\RedisClient;
class ServicesController extends Controller
{

View File

@@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
namespace Siteworxpro\App\Facades;
use Illuminate\Support\Facades\Facade;
use Siteworxpro\App\Traefik\EntityEnum;
use Siteworxpro\App\Traefik\ProtocolEnum;
use Siteworxpro\App\Traefik\RedisClient as RedisClientConcrete;
/**
* Facade for RedisClient.
*
* This class provides a static interface to the RedisClientConcrete class.
*
* @method static void createOrReplace(string $name, array $data, EntityEnum $entity, ProtocolEnum $type = ProtocolEnum::HTTP) // @codingStandardsIgnoreLine
* @method static bool deleteAllKeys(string $name, EntityEnum $entity, ProtocolEnum $protocol = ProtocolEnum::HTTP)
* @method static array getAllMiddlewares(ProtocolEnum $protocol = ProtocolEnum::HTTP)
* @method static array getMiddleware(string $name, ProtocolEnum $protocol = ProtocolEnum::HTTP)
* @method static array getAllRouters(ProtocolEnum $protocol = ProtocolEnum::HTTP)
* @method static array getRouter(string $name, ProtocolEnum $protocol = ProtocolEnum::HTTP)
* @method static array getAllServices(ProtocolEnum $protocol = ProtocolEnum::HTTP)
* @method static array getService(string $name, ProtocolEnum $protocol = ProtocolEnum::HTTP)
*/
class RedisClient extends Facade
{
public static function getFacadeRoot(): RedisClientConcrete
{
if (self::$resolvedInstance !== null) {
$client = self::resolveFacadeInstance(self::getFacadeAccessor());
if ($client instanceof RedisClientConcrete) {
return $client;
}
}
return new RedisClientConcrete();
}
protected static function getFacadeAccessor(): string
{
return RedisClientConcrete::class;
}
}

View File

@@ -20,7 +20,7 @@ class RedisClient
* @param ProtocolEnum $type
* @return void
*/
public static function createOrReplace(
public function createOrReplace(
string $name,
array $data,
EntityEnum $entity,
@@ -47,7 +47,7 @@ class RedisClient
* @param ProtocolEnum $protocol
* @return bool
*/
public static function deleteAllKeys(
public function deleteAllKeys(
string $name,
EntityEnum $entity,
ProtocolEnum $protocol = ProtocolEnum::HTTP
@@ -66,33 +66,33 @@ class RedisClient
* @param ProtocolEnum $type
* @return array
*/
public static function getMiddleware(string $name, ProtocolEnum $type = ProtocolEnum::HTTP): array
public function getMiddleware(string $name, ProtocolEnum $type = ProtocolEnum::HTTP): array
{
$pattern = 'traefik/' . $type->getValue() . '/' . EntityEnum::MIDDLEWARE->getValue() . "/$name/*";
return self::fetchValuesToArray($pattern);
return $this->fetchValuesToArray($pattern);
}
/**
* @param ProtocolEnum $type
* @return array
*/
public static function getAllMiddlewares(ProtocolEnum $type = ProtocolEnum::HTTP): array
public function getAllMiddlewares(ProtocolEnum $type = ProtocolEnum::HTTP): array
{
$pattern = 'traefik/' . $type->getValue() . '/' . EntityEnum::MIDDLEWARE->getValue() . '/*';
return self::getUniqueKeys($pattern, 3);
return $this->getUniqueKeys($pattern);
}
/**
* @param ProtocolEnum $type
* @return array
*/
public static function getAllServices(ProtocolEnum $type = ProtocolEnum::HTTP): array
public function getAllServices(ProtocolEnum $type = ProtocolEnum::HTTP): array
{
$pattern = 'traefik/' . $type->getValue() . '/' . EntityEnum::SERVICE->getValue() . '/*';
return self::getUniqueKeys($pattern, 3);
return $this->getUniqueKeys($pattern);
}
/**
@@ -100,22 +100,22 @@ class RedisClient
* @param ProtocolEnum $type
* @return array
*/
public static function getService(string $serviceName, ProtocolEnum $type = ProtocolEnum::HTTP): array
public function getService(string $serviceName, ProtocolEnum $type = ProtocolEnum::HTTP): array
{
$pattern = 'traefik/' . $type->getValue() . '/' . EntityEnum::SERVICE->getValue() . "/$serviceName/*";
return self::fetchValuesToArray($pattern);
return $this->fetchValuesToArray($pattern);
}
/**
* @param ProtocolEnum $type
* @return array
*/
public static function getAllRouters(ProtocolEnum $type = ProtocolEnum::HTTP): array
public function getAllRouters(ProtocolEnum $type = ProtocolEnum::HTTP): array
{
$pattern = 'traefik/' . $type->getValue() . '/' . EntityEnum::ROUTER->getValue() . '/*';
return self::getUniqueKeys($pattern, 3);
return $this->getUniqueKeys($pattern);
}
/**
@@ -123,27 +123,26 @@ class RedisClient
* @param ProtocolEnum $type
* @return array
*/
public static function getRouter(string $name, ProtocolEnum $type = ProtocolEnum::HTTP): array
public function getRouter(string $name, ProtocolEnum $type = ProtocolEnum::HTTP): array
{
$pattern = 'traefik/' . $type->getValue() . '/' . EntityEnum::ROUTER->getValue() . "/$name/*";
return self::fetchValuesToArray($pattern);
return $this->fetchValuesToArray($pattern);
}
/**
* @param string $pattern
* @param int $position
* @return array
*/
private static function getUniqueKeys(string $pattern, int $position): array
private function getUniqueKeys(string $pattern): array
{
$values = new Collection();
$redis = Redis::getFacadeRoot();
foreach (new Keyspace($redis, $pattern) as $key) {
$parts = explode('/', $key);
if (isset($parts[$position])) {
$values->push($parts[$position]);
if (isset($parts[3])) {
$values->push($parts[3]);
}
}
@@ -154,7 +153,7 @@ class RedisClient
* @param string $pattern
* @return array
*/
private static function fetchValuesToArray(string $pattern): array
private function fetchValuesToArray(string $pattern): array
{
$redis = Redis::getFacadeRoot();
@@ -174,7 +173,7 @@ class RedisClient
* @param array $data
* @return array
*/
public static function flattenToDotArray(array $data): array
public function flattenToDotArray(array $data): array
{
$collection = new Collection($data);

View File

@@ -0,0 +1,75 @@
<?php
declare(strict_types=1);
namespace Siteworxpro\Tests\Controllers;
use League\Route\Http\Exception\NotFoundException;
use Nyholm\Psr7\ServerRequest;
use PHPUnit\Framework\MockObject\Exception;
use Psr\Log\LoggerInterface;
use Siteworxpro\App\Controllers\Controller;
use Siteworxpro\App\Facades\Logger;
use Siteworxpro\App\Traefik\ProtocolEnum;
use Siteworxpro\Tests\Unit;
class ControllerTest extends Unit
{
/**
* @throws NotFoundException
*/
public function testGet(): void
{
$fooController = new FooController();
$request = new ServerRequest('GET', '/foo');
$this->expectException(NotFoundException::class);
$fooController->get($request);
}
/**
* @throws NotFoundException
*/
public function testPost(): void
{
$fooController = new FooController();
$request = new ServerRequest('GET', '/foo');
$this->expectException(NotFoundException::class);
$fooController->post($request);
}
/**
* @throws NotFoundException
*/
public function testDelete(): void
{
$fooController = new FooController();
$request = new ServerRequest('GET', '/foo');
$this->expectException(NotFoundException::class);
$fooController->delete($request);
}
/**
* @throws NotFoundException
*/
public function testPatch(): void
{
$fooController = new FooController();
$request = new ServerRequest('GET', '/foo');
$this->expectException(NotFoundException::class);
$fooController->patch($request);
}
}
// This is a dummy controller for testing purposes
// @codingStandardsIgnoreLine
class FooController extends Controller
{
}

View File

@@ -0,0 +1,145 @@
<?php
declare(strict_types=1);
namespace Siteworxpro\Tests\Controllers;
use Nyholm\Psr7\ServerRequest;
use Siteworxpro\App\Controllers\MiddlewaresController;
use Siteworxpro\App\Facades\RedisClient;
use Siteworxpro\App\Traefik\EntityEnum;
use Siteworxpro\App\Traefik\ProtocolEnum;
use Siteworxpro\Tests\Unit;
class MiddlewareControllerTest extends Unit
{
/**
* @throws \JsonException
*/
public function testGet(): void
{
$request = new ServerRequest('GET', '/middlewares');
$request = $request->withAttribute('protocol', 'http');
RedisClient::expects('getAllMiddlewares')
->with(ProtocolEnum::HTTP)
->andReturn(['middleware1', 'middleware2']);
$controller = new MiddlewaresController();
$response = $controller->get($request);
$this->assertEquals(200, $response->getStatusCode());
$this->assertEquals('["middleware1","middleware2"]', (string)$response->getBody());
$this->assertEquals('application/json', $response->getHeaderLine('Content-Type'));
}
/**
* @throws \JsonException
*/
public function testGetInd(): void
{
$request = new ServerRequest('GET', '/middlewares/foo');
$request = $request
->withAttribute('protocol', 'http')
->withAttribute('id', 'foo');
RedisClient::expects('getMiddleware')
->with('foo', ProtocolEnum::HTTP)
->andReturn([
'traefik/http/middlewares/foo' => 'bar',
]);
$controller = new MiddlewaresController();
$response = $controller->get($request);
$this->assertEquals(200, $response->getStatusCode());
$this->assertEquals('{"traefik\/http\/middlewares\/foo":"bar"}', (string)$response->getBody());
$this->assertEquals('application/json', $response->getHeaderLine('Content-Type'));
}
/**
* @throws \JsonException
*/
public function testPost(): void
{
$request = new ServerRequest('POST', '/middlewares');
$request = $request
->withAttribute('protocol', 'http')
->withAttribute('id', 'foo')
->withParsedBody(['foo' => 'bar']);
RedisClient::expects('createOrReplace')
->with('foo', ['foo' => 'bar'], EntityEnum::MIDDLEWARE, ProtocolEnum::HTTP)
->andReturn(true);
$controller = new MiddlewaresController();
$response = $controller->post($request);
$this->assertEquals(200, $response->getStatusCode());
$this->assertEquals('{"message":"Middleware added successfully"}', (string)$response->getBody());
}
public function testPostValidationFailure(): void
{
$request = new ServerRequest('POST', '/middlewares');
$request = $request
->withAttribute('protocol', 'http')
->withAttribute('id', 'foo')
->withParsedBody([]);
RedisClient::expects('createOrReplace')
->never();
$controller = new MiddlewaresController();
$response = $controller->post($request);
$this->assertEquals(400, $response->getStatusCode());
$this->assertEquals('{"error":"Middleware is invalid"}', (string)$response->getBody());
}
/**
* @throws \JsonException
*/
public function testDelete(): void
{
$request = new ServerRequest('DELETE', '/middlewares/foo');
$request = $request
->withAttribute('protocol', 'http')
->withAttribute('id', 'foo');
RedisClient::expects('deleteAllKeys')
->with('foo', EntityEnum::MIDDLEWARE, ProtocolEnum::HTTP)
->andReturn(true);
$controller = new MiddlewaresController();
$response = $controller->delete($request);
$this->assertEquals(200, $response->getStatusCode());
$this->assertEquals('{"message":"Middleware deleted successfully"}', (string)$response->getBody());
}
/**
* @throws \JsonException
*/
public function testDeleteValidationFailure(): void
{
$request = new ServerRequest('DELETE', '/middlewares');
$request = $request
->withAttribute('protocol', 'http')
->withAttribute('id', '');
RedisClient::expects('deleteAllKeys')
->never();
$controller = new MiddlewaresController();
$response = $controller->delete($request);
$this->assertEquals(400, $response->getStatusCode());
$this->assertEquals('{"error":"Middleware is invalid"}', (string)$response->getBody());
}
}

View File

@@ -0,0 +1,159 @@
<?php
declare(strict_types=1);
namespace Siteworxpro\Tests\Controllers;
use Nyholm\Psr7\ServerRequest;
use Siteworxpro\App\Controllers\RoutesController;
use Siteworxpro\App\Facades\RedisClient;
use Siteworxpro\App\Traefik\EntityEnum;
use Siteworxpro\App\Traefik\ProtocolEnum;
use Siteworxpro\Tests\Unit;
class RoutesControllerTest extends Unit
{
/**
* @throws \JsonException
*/
public function testGet(): void
{
$request = new ServerRequest('GET', '/routes');
$request = $request->withAttribute('protocol', 'http');
RedisClient::expects('getAllRouters')
->with(ProtocolEnum::HTTP)
->andReturn(['route1', 'route2']);
$controller = new RoutesController();
$response = $controller->get($request);
$this->assertEquals(200, $response->getStatusCode());
$this->assertEquals('["route1","route2"]', (string)$response->getBody());
$this->assertEquals('application/json', $response->getHeaderLine('Content-Type'));
}
/**
* @throws \JsonException
*/
public function testGetInd(): void
{
$request = new ServerRequest('GET', '/routes/foo');
$request = $request
->withAttribute('protocol', 'http')
->withAttribute('id', 'foo');
RedisClient::expects('getRouter')
->with('foo', ProtocolEnum::HTTP)
->andReturn([
'traefik/http/routers/foo' => 'bar',
]);
$controller = new RoutesController();
$response = $controller->get($request);
$this->assertEquals(200, $response->getStatusCode());
$this->assertEquals('{"traefik\/http\/routers\/foo":"bar"}', (string)$response->getBody());
$this->assertEquals('application/json', $response->getHeaderLine('Content-Type'));
}
/**
* @throws \JsonException
*/
public function testDelete(): void
{
$request = new ServerRequest('DELETE', '/routes/foo');
$request = $request
->withAttribute('protocol', 'http')
->withAttribute('id', 'foo');
RedisClient::expects('deleteAllKeys')
->with('foo', EntityEnum::ROUTER, ProtocolEnum::HTTP)
->andReturn(true);
$controller = new RoutesController();
$response = $controller->delete($request);
$this->assertEquals(200, $response->getStatusCode());
$this->assertEquals('{"message":"Router deleted successfully"}', (string)$response->getBody());
}
/**
* @throws \JsonException
*/
public function testPost(): void
{
$request = new ServerRequest('POST', '/routes/foo');
$request = $request
->withAttribute('protocol', 'http')
->withAttribute('id', 'foo')
->withParsedBody([
'service' => 'my-service',
'rule' => 'Host(`example.com`)',
]);
RedisClient::expects('createOrReplace')
->with(
'foo',
[
'service' => 'my-service',
'rule' => 'Host(`example.com`)',
],
EntityEnum::ROUTER,
ProtocolEnum::HTTP
)
->andReturn(true);
$controller = new RoutesController();
$response = $controller->post($request);
$this->assertEquals(200, $response->getStatusCode());
$this->assertEquals('{"message":"Router created successfully"}', (string)$response->getBody());
}
/**
* @throws \JsonException
*/
public function testPostWithoutService(): void
{
$request = new ServerRequest('POST', '/routes/foo');
$request = $request
->withAttribute('protocol', 'http')
->withAttribute('id', 'foo')
->withParsedBody([
'rule' => 'Host(`example.com`)',
]);
$controller = new RoutesController();
$response = $controller->post($request);
$this->assertEquals(400, $response->getStatusCode());
$this->assertEquals('{"error":"Service is required"}', (string)$response->getBody());
}
/**
* @throws \JsonException
*/
public function testPostWithoutRule(): void
{
$request = new ServerRequest('POST', '/routes/foo');
$request = $request
->withAttribute('protocol', 'http')
->withAttribute('id', 'foo')
->withParsedBody([
'service' => 'my-service',
]);
$controller = new RoutesController();
$response = $controller->post($request);
$this->assertEquals(400, $response->getStatusCode());
$this->assertEquals('{"error":"Rule is required"}', (string)$response->getBody());
}
}

View File

@@ -0,0 +1,162 @@
<?php
declare(strict_types=1);
namespace Siteworxpro\Tests\Controllers;
use Nyholm\Psr7\ServerRequest;
use Siteworxpro\App\Controllers\ServicesController;
use Siteworxpro\App\Facades\RedisClient;
use Siteworxpro\App\Traefik\EntityEnum;
use Siteworxpro\App\Traefik\ProtocolEnum;
use Siteworxpro\Tests\Unit;
class ServicesControllerTest extends Unit
{
/**
* @throws \JsonException
*/
public function testGet(): void
{
$request = new ServerRequest('GET', '/services');
$request = $request->withAttribute('protocol', 'http');
RedisClient::expects('getAllServices')
->with(ProtocolEnum::HTTP)
->andReturn(['service1', 'service2']);
$controller = new ServicesController();
$response = $controller->get($request);
$this->assertEquals(200, $response->getStatusCode());
$this->assertEquals('["service1","service2"]', (string)$response->getBody());
$this->assertEquals('application/json', $response->getHeaderLine('Content-Type'));
}
/**
* @throws \JsonException
*/
public function testGetInd(): void
{
$request = new ServerRequest('GET', '/services/foo');
$request = $request
->withAttribute('protocol', 'http')
->withAttribute('id', 'foo');
RedisClient::expects('getService')
->with('foo', ProtocolEnum::HTTP)
->andReturn([
'traefik/http/services/foo' => 'bar',
]);
$controller = new ServicesController();
$response = $controller->get($request);
$this->assertEquals(200, $response->getStatusCode());
$this->assertEquals('{"traefik\/http\/services\/foo":"bar"}', (string)$response->getBody());
$this->assertEquals('application/json', $response->getHeaderLine('Content-Type'));
}
/**
* @throws \JsonException
*/
public function testPost(): void
{
$request = new ServerRequest('POST', '/services/foo');
$request = $request
->withAttribute('protocol', 'http')
->withAttribute('id', 'foo')
->withParsedBody([
'loadbalancer' => [
'servers' => [
['url' => 'https://example.com'],
],
],
]);
RedisClient::expects('createOrReplace')
->with(
'foo',
[
'loadbalancer' => [
'servers' => [
['url' => 'https://example.com'],
],
],
],
EntityEnum::SERVICE,
ProtocolEnum::HTTP
)
->andReturn(true);
$controller = new ServicesController();
$response = $controller->post($request);
$this->assertEquals(200, $response->getStatusCode());
$this->assertEquals('{"message":"Service updated successfully"}', (string)$response->getBody());
$this->assertEquals('application/json', $response->getHeaderLine('Content-Type'));
}
/**
* @throws \JsonException
*/
public function testPostValidation(): void
{
$request = new ServerRequest('POST', '/services/foo');
$request = $request
->withAttribute('protocol', 'http')
->withAttribute('id', 'foo')
->withParsedBody([]);
RedisClient::expects('createOrReplace')
->with(
'foo',
[],
EntityEnum::SERVICE,
ProtocolEnum::HTTP
)
->andReturn(true);
$controller = new ServicesController();
$response = $controller->post($request);
$this->assertEquals(400, $response->getStatusCode());
$this->assertEquals('{"error":"loadbalancer is required"}', (string)$response->getBody());
}
/**
* @throws \JsonException
*/
public function testDelete(): void
{
$request = new ServerRequest('DELETE', '/services/foo');
$request = $request
->withAttribute('protocol', 'http')
->withAttribute('id', 'foo');
RedisClient::expects('deleteAllKeys')
->with('foo', EntityEnum::SERVICE, ProtocolEnum::HTTP)
->andReturn(true);
$controller = new ServicesController();
$response = $controller->delete($request);
$this->assertEquals(200, $response->getStatusCode());
$this->assertEquals('{"message":"Service deleted successfully"}', (string)$response->getBody());
}
/**
* @throws \JsonException
*/
public function testDeleteValidation(): void
{
$request = new ServerRequest('DELETE', '/services');
$request = $request
->withAttribute('protocol', 'http')
->withAttribute('id', null);
RedisClient::expects('deleteAllKeys')
->with(null, EntityEnum::SERVICE, ProtocolEnum::HTTP)
->andReturn(true);
$controller = new ServicesController();
$response = $controller->delete($request);
$this->assertEquals(400, $response->getStatusCode());
$this->assertEquals('{"error":"Service name is required"}', (string)$response->getBody());
}
}

View File

@@ -48,7 +48,7 @@ class MiddlewareServiceTest extends Unit
'/middlewares/foo/headers/customrequestheaders/X-Forwarded-Proto',
]]);
$services = RedisClient::getAllMiddlewares($protocolEnum);
$services = new RedisClient()->getAllMiddlewares($protocolEnum);
$this->assertCount(1, $services);
$this->assertSame('foo', $services[0]);
}
@@ -101,7 +101,7 @@ class MiddlewareServiceTest extends Unit
'/middlewares/foo/headers/customrequestheaders/X-Forwarded-Proto')
->andReturn('http');
$middleware = RedisClient::getMiddleware('foo', $protocolEnum);
$middleware = new RedisClient()->getMiddleware('foo', $protocolEnum);
$this->assertCount(4, $middleware['headers']['customrequestheaders']);
$this->assertSame('foo.localhost', $middleware['headers']['customrequestheaders']['Host']);

View File

@@ -7,19 +7,13 @@ namespace Siteworxpro\Tests\Traefik;
use Mockery;
use Predis\Command\FactoryInterface;
use Siteworxpro\App\Facades\Redis;
use Siteworxpro\App\Facades\RedisClient;
use Siteworxpro\App\Traefik\EntityEnum;
use Siteworxpro\App\Traefik\ProtocolEnum;
use Siteworxpro\App\Traefik\RedisClient;
use Siteworxpro\Tests\Unit;
class RedisClientRoutersTest extends Unit
{
protected function tearDown(): void
{
parent::tearDown();
Mockery::close();
}
private function createTest(ProtocolEnum $protocol): void
{
$commandFactory = Mockery::mock(FactoryInterface::class)

View File

@@ -54,7 +54,7 @@ class RedisClientServiceTest extends Unit
->once()
->andReturn(true);
RedisClient::createOrReplace('foo', [
new RedisClient()->createOrReplace('foo', [
'loadbalancer' => [
'servers' => [
'server1' => [
@@ -103,7 +103,7 @@ class RedisClientServiceTest extends Unit
->with('traefik/' . $protocol->getValue() . '/services/foo/loadbalancer/servers/server1/url')
->andReturn('http://foo.localhost:80');
$services = RedisClient::getService('foo', $protocol);
$services = new RedisClient()->getService('foo', $protocol);
$this->assertIsArray($services);
$this->assertArrayHasKey('loadbalancer', $services);
@@ -135,7 +135,7 @@ class RedisClientServiceTest extends Unit
'traefik/' . $protocol->getValue() . '/services/bar/loadbalancer/servers/server2/url',
]]);
$services = RedisClient::getAllServices($protocol);
$services = new RedisClient()->getAllServices($protocol);
$this->assertIsArray($services);
$this->assertCount(2, $services);

View File

@@ -6,8 +6,10 @@ namespace Siteworxpro\Tests;
use Illuminate\Container\Container;
use Illuminate\Support\Facades\Facade;
use Illuminate\Support\Facades\Redis;
use PHPUnit\Framework\TestCase;
use Siteworxpro\App\Facades\Config;
use Siteworxpro\App\Facades\RedisClient;
abstract class Unit extends TestCase
{
@@ -19,7 +21,12 @@ abstract class Unit extends TestCase
protected function tearDown(): void
{
parent::tearDown();
Config::clearResolvedInstances();
Redis::clearResolvedInstances();
RedisClient::clearResolvedInstances();
Facade::setFacadeApplication(null);
}
}

View File

@@ -1 +1,2 @@
html/
html/
junit.xml