diff --git a/src/App/AbstractApp.php b/src/App/AbstractApp.php index bf7e67c..a7ed4b5 100644 --- a/src/App/AbstractApp.php +++ b/src/App/AbstractApp.php @@ -63,4 +63,18 @@ public function config(): array { return $this->config; } + + public function readFile(string $filePath): string + { + $appClass = new \ReflectionObject($this); + $appDir = dirname($appClass->getFileName()); + $path = $appDir.'/Resources/'.ltrim($filePath, '/'); + if (!file_exists($path)) { + throw new \InvalidArgumentException( + sprintf('File "%s" does not exist', $path) + ); + } + + return file_get_contents($path); + } } diff --git a/src/Core/AbstractManifest.php b/src/Core/AbstractManifest.php index be9f941..85db138 100644 --- a/src/Core/AbstractManifest.php +++ b/src/Core/AbstractManifest.php @@ -4,6 +4,7 @@ use Dealroadshow\K8S\Framework\App\AppInterface; use Dealroadshow\K8S\Framework\Config\ConfigAwareTrait; +use Dealroadshow\K8S\Framework\Util\Str; abstract class AbstractManifest implements ManifestInterface { @@ -11,6 +12,11 @@ abstract class AbstractManifest implements ManifestInterface protected AppInterface $app; + public function fileNameWithoutExtension(): string + { + return static::shortName().'.'.Str::asDNSSubdomain(static::kind()); + } + public function metadata(MetadataConfigurator $meta): void { } diff --git a/src/Core/ConfigMap/AbstractConfigMap.php b/src/Core/ConfigMap/AbstractConfigMap.php index fff1e63..5fa8f4d 100644 --- a/src/Core/ConfigMap/AbstractConfigMap.php +++ b/src/Core/ConfigMap/AbstractConfigMap.php @@ -2,6 +2,7 @@ namespace Dealroadshow\K8S\Framework\Core\ConfigMap; +use Dealroadshow\K8S\API\ConfigMap; use Dealroadshow\K8S\Data\Collection\StringMap; use Dealroadshow\K8S\Framework\Core\AbstractManifest; @@ -14,4 +15,9 @@ public function data(StringMap $data): void public function binaryData(StringMap $binaryData): void { } + + public static function kind(): string + { + return ConfigMap::KIND; + } } diff --git a/src/Core/CronJob/AbstractCronJob.php b/src/Core/CronJob/AbstractCronJob.php index 895992b..85c83b3 100644 --- a/src/Core/CronJob/AbstractCronJob.php +++ b/src/Core/CronJob/AbstractCronJob.php @@ -35,4 +35,9 @@ public function suspend(): ?bool public function configureCronJob(CronJob $cronJob): void { } + + public static function kind(): string + { + return CronJob::KIND; + } } diff --git a/src/Core/Deployment/AbstractDeployment.php b/src/Core/Deployment/AbstractDeployment.php index 15f7e67..a75e2b2 100644 --- a/src/Core/Deployment/AbstractDeployment.php +++ b/src/Core/Deployment/AbstractDeployment.php @@ -26,6 +26,11 @@ public function imagePullSecrets(ImagePullSecretsConfigurator $secrets): void { } + public static function kind(): string + { + return Deployment::KIND; + } + public function nodeSelector(StringMap $nodeSelector): void { } diff --git a/src/Core/Ingress/AbstractIngress.php b/src/Core/Ingress/AbstractIngress.php index a984962..df13022 100644 --- a/src/Core/Ingress/AbstractIngress.php +++ b/src/Core/Ingress/AbstractIngress.php @@ -17,4 +17,9 @@ public function backend(IngressBackendFactory $factory): ?IngressBackend public function configureIngress(Ingress $ingress): void { } + + public static function kind(): string + { + return Ingress::KIND; + } } diff --git a/src/Core/Job/AbstractJob.php b/src/Core/Job/AbstractJob.php index 40c6194..b22b867 100644 --- a/src/Core/Job/AbstractJob.php +++ b/src/Core/Job/AbstractJob.php @@ -81,4 +81,9 @@ public function configurePodSpec(PodSpec $spec): void public function configureJob(Job $job): void { } + + public static function kind(): string + { + return Job::KIND; + } } diff --git a/src/Core/ManifestInterface.php b/src/Core/ManifestInterface.php index 8978711..ddfae9d 100644 --- a/src/Core/ManifestInterface.php +++ b/src/Core/ManifestInterface.php @@ -6,6 +6,7 @@ interface ManifestInterface extends AppAwareInterface, ConfigAwareInterface, MetadataAwareInterface { + public static function kind(): string; public static function shortName(): string; public function fileNameWithoutExtension(): string; } diff --git a/src/Core/Secret/AbstractSecret.php b/src/Core/Secret/AbstractSecret.php index a039b17..897d3cf 100644 --- a/src/Core/Secret/AbstractSecret.php +++ b/src/Core/Secret/AbstractSecret.php @@ -2,6 +2,7 @@ namespace Dealroadshow\K8S\Framework\Core\Secret; +use Dealroadshow\K8S\API\Secret; use Dealroadshow\K8S\Data\Collection\StringMap; use Dealroadshow\K8S\Framework\Core\AbstractManifest; @@ -14,4 +15,9 @@ public function data(StringMap $data): void public function stringData(StringMap $stringData): void { } + + public static function kind(): string + { + return Secret::KIND; + } } diff --git a/src/Core/Service/AbstractService.php b/src/Core/Service/AbstractService.php index 9904480..a17909c 100644 --- a/src/Core/Service/AbstractService.php +++ b/src/Core/Service/AbstractService.php @@ -25,4 +25,9 @@ public function type(ServiceTypeConfigurator $type): void public function configureService(Service $service): void { } + + public static function kind(): string + { + return Service::KIND; + } } diff --git a/src/Middleware/ManifestMethodMiddlewareInterface.php b/src/Middleware/ManifestMethodMiddlewareInterface.php index 9742046..a08ea85 100644 --- a/src/Middleware/ManifestMethodMiddlewareInterface.php +++ b/src/Middleware/ManifestMethodMiddlewareInterface.php @@ -8,7 +8,21 @@ interface ManifestMethodMiddlewareInterface { const NO_RETURN_VALUE = 'MANIFEST_MIDDLEWARE_NO_RETURN_VALUE'; - public function beforeMethodCall(ManifestInterface $manifest, string $methodName, array $params, &$returnValue); + public function beforeMethodCall( + ManifestInterface $manifest, + string $methodName, + array $params, + mixed &$returnValue + ); + + public function afterMethodCall( + ManifestInterface $manifest, + string $methodName, + array $params, + mixed $returnedValue, + mixed &$returnValue + ); + public function supports(ManifestInterface $manifest, string $methodName, array $params): bool; public static function priority(): int; } diff --git a/src/Middleware/ManifestMiddlewareService.php b/src/Middleware/ManifestMiddlewareService.php index 3328d0d..623ba78 100644 --- a/src/Middleware/ManifestMiddlewareService.php +++ b/src/Middleware/ManifestMiddlewareService.php @@ -27,4 +27,19 @@ public function beforeMethodCall(ManifestInterface $manifest, string $methodName return ManifestMethodMiddlewareInterface::NO_RETURN_VALUE; } + + public function afterMethodCall(ManifestInterface $manifest, string $methodName, array $params, mixed $returnedValue): mixed + { + foreach ($this->middlewares as $middleware) { + if ($middleware->supports($manifest, $methodName, $params)) { + $returnValue = ManifestMethodMiddlewareInterface::NO_RETURN_VALUE; + $middleware->afterMethodCall($manifest, $methodName, $params, $returnedValue, $returnValue); + if (ManifestMethodMiddlewareInterface::NO_RETURN_VALUE !== $returnValue) { + return $returnValue; + } + } + } + + return ManifestMethodMiddlewareInterface::NO_RETURN_VALUE; + } } diff --git a/src/Proxy/ManifestProxyFactory.php b/src/Proxy/ManifestProxyFactory.php index 2c58d4d..7a148f9 100644 --- a/src/Proxy/ManifestProxyFactory.php +++ b/src/Proxy/ManifestProxyFactory.php @@ -17,7 +17,7 @@ public function makeProxy(ManifestInterface $manifest): ManifestInterface { $factory = new ProxyFactory(); - $closure = function( + $prefixClosure = function( ManifestInterface $proxy, ManifestInterface $wrapped, string $method, @@ -32,15 +32,33 @@ public function makeProxy(ManifestInterface $manifest): ManifestInterface return $result; }; - $closures = []; + $suffixClosure = function( + ManifestInterface $proxy, + ManifestInterface $wrapped, + string $method, + array $params, + mixed $returnedValue, + bool &$returnEarly + ) { + $result = $this->middlewareService->afterMethodCall($wrapped, $method, $params, $returnedValue); + if (ManifestMethodMiddlewareInterface::NO_RETURN_VALUE !== $result) { + $returnEarly = true; + } + + return $result; + }; + + $prefixClosures = []; + $suffixClosures = []; $class = new \ReflectionClass($manifest); foreach ($class->getMethods() as $method) { if ($method->isFinal() || $method->isPrivate() || $method->isConstructor() || $method->isDestructor()) { continue; } - $closures[$method->getName()] = $closure; + $prefixClosures[$method->getName()] = $prefixClosure; + $suffixClosures[$method->getName()] = $suffixClosure; } - return $factory->createProxy($manifest, $closures); + return $factory->createProxy($manifest, $prefixClosures, $suffixClosures); } } diff --git a/src/Util/Str.php b/src/Util/Str.php new file mode 100644 index 0000000..ee5b461 --- /dev/null +++ b/src/Util/Str.php @@ -0,0 +1,81 @@ +getNamespaceName(); + + return trim($namespace, '\\'); + } + + public static function asDir(object $object): string + { + $reflection = new \ReflectionObject($object); + + return dirname($reflection->getFileName()); + } + + public static function asDNSSubdomain(string $str): string + { + $camel2dash = strtolower( + preg_replace('/([a-zA-Z])(?=[A-Z])/', '$1-', $str) + ); + $valid = preg_replace('/([^\w\-]|[_])+/', '', $camel2dash); + + if (0 === strlen($valid)) { + throw new \InvalidArgumentException( + sprintf('String "%s" cannot be converted DNS subdomain representation', $str) + ); + } + if (253 < strlen($valid)) { + throw new \InvalidArgumentException( + sprintf( + 'String "%s" DNS subdomain representation is too long (must be less than 253 characters)', + $str + ) + ); + } + + return $valid; + } + + public static function isValidDNSSubdomain(string $str): bool + { + return 253 > strlen($str) && 0 !== preg_match('/^[a-z0-9]+[a-z0-9\-.]+[a-z0-9]$/', $str); + } +}