renoki-co/php-k8s

View on GitHub
src/Kinds/K8sResource.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php

namespace RenokiCo\PhpK8s\Kinds;

use Closure;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Support\Jsonable;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use RenokiCo\PhpK8s\Exceptions\KubernetesAPIException;
use RenokiCo\PhpK8s\K8s;
use RenokiCo\PhpK8s\KubernetesCluster;
use RenokiCo\PhpK8s\Traits\Resource\HasAnnotations;
use RenokiCo\PhpK8s\Traits\Resource\HasAttributes;
use RenokiCo\PhpK8s\Traits\Resource\HasEvents;
use RenokiCo\PhpK8s\Traits\Resource\HasKind;
use RenokiCo\PhpK8s\Traits\Resource\HasLabels;
use RenokiCo\PhpK8s\Traits\Resource\HasName;
use RenokiCo\PhpK8s\Traits\Resource\HasNamespace;
use RenokiCo\PhpK8s\Traits\Resource\HasVersion;
use RenokiCo\PhpK8s\Traits\RunsClusterOperations;

class K8sResource implements Arrayable, Jsonable
{
    use HasAnnotations;
    use HasAttributes;
    use HasEvents;
    use HasKind;
    use HasLabels;
    use HasName;
    use HasNamespace;
    use HasVersion;
    use RunsClusterOperations;

    /**
     * Create a new resource.
     *
     * @param  \RenokiCo\PhpK8s\KubernetesCluster|null  $cluster
     * @param  array  $attributes
     * @return void
     */
    public function __construct($cluster = null, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->original = $attributes;

        if ($cluster instanceof KubernetesCluster) {
            $this->onCluster($cluster);
        }
    }

    /**
     * Register the current resource in macros.
     *
     * @param  string|null  $name
     * @return void
     */
    public static function register(string $name = null): void
    {
        K8s::registerCrd(static::class, $name);
    }

    /**
     * This method should be used only for CRDs.
     * It returns an internal macro name to help transition from YAML to resource
     * when importing YAML.
     *
     * @param  string|null  $kind
     * @param  string|null  $defaultVersion
     * @return string
     */
    public static function getUniqueCrdMacro(string $kind = null, string $defaultVersion = null): string
    {
        $kind = $kind ?: static::getKind();
        $defaultVersion = $defaultVersion ?: static::getDefaultVersion();

        return Str::of($kind.explode('/', $defaultVersion)[0])->camel()->slug();
    }

    /**
     * Get the plural resource name.
     *
     * @return string
     */
    public static function getPlural()
    {
        return strtolower(Str::plural(static::getKind()));
    }

    /**
     * Check if the current resource exists.
     *
     * @param  array  $query
     * @return bool
     */
    public function exists(array $query = ['pretty' => 1]): bool
    {
        try {
            $this->get($query);
        } catch (KubernetesAPIException $e) {
            if ($e->getCode() === 404) {
                return false;
            }

            throw $e;
        }

        return true;
    }

    /**
     * Get a resource by name.
     *
     * @param  string  $name
     * @param  array  $query
     * @return \RenokiCo\PhpK8s\Kinds\K8sResource
     */
    public function getByName(string $name, array $query = ['pretty' => 1])
    {
        return $this->whereName($name)->get($query);
    }

    /**
     * Get the instance as an array.
     * Optionally, you can specify the Kind attribute to replace.
     *
     * @param  string|null  $kind
     * @return array
     */
    public function toArray(string $kind = null)
    {
        $attributes = $this->attributes;

        // Make sure to also include the namespace.
        if (static::$namespaceable) {
            Arr::set($attributes, 'metadata.namespace', $this->getNamespace());
        }

        $instanceToArray = array_merge($attributes, [
            'kind' => $kind ?: $this::getKind(),
            'apiVersion' => $this->getApiVersion(),
        ]);

        ksort($instanceToArray);

        return $instanceToArray;
    }

    /**
     * Convert the object to its JSON representation.
     * Optionally, you can specify the Kind attribute to replace.
     *
     * @param  int  $options
     * @param  string|null  $kind
     * @return string
     */
    public function toJson($options = 0, string $kind = null)
    {
        return json_encode($this->toArray($kind), $options);
    }

    /**
     * Convert the object to its JSON representation, but
     * escaping [] for {}. Optionally, you can specify
     * the Kind attribute to replace.
     *
     * @param  string|null  $kind
     * @return string
     */
    public function toJsonPayload(string $kind = null)
    {
        $attributes = $this->toJson(JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES, $kind);

        $attributes = str_replace(': []', ': {}', $attributes);

        $attributes = str_replace('"allowedTopologies": {}', '"allowedTopologies": []', $attributes);
        $attributes = str_replace('"mountOptions": {}', '"mountOptions": []', $attributes);
        $attributes = str_replace('"accessModes": {}', '"accessModes": []', $attributes);

        return $attributes;
    }

    /**
     * Watch the specific resource by name.
     *
     * @param  Closure  $callback
     * @param  array  $query
     * @return mixed
     *
     * @throws \RenokiCo\PhpK8s\Exceptions\KubernetesWatchException
     */
    public function watchByName(string $name, Closure $callback, array $query = ['pretty' => 1])
    {
        return $this->whereName($name)->watch($callback, $query);
    }

    /**
     * Get logs for a specific container.
     *
     * @param  string  $container
     * @param  array  $query
     * @return string
     *
     * @throws \RenokiCo\PhpK8s\Exceptions\KubernetesLogsException
     * @throws \RenokiCo\PhpK8s\Exceptions\KubernetesAPIException
     */
    public function containerLogs(string $container, array $query = ['pretty' => 1])
    {
        return $this->logs(array_merge($query, ['container' => $container]));
    }

    /**
     * Watch the specific resource by name.
     *
     * @param  string  $name
     * @param  Closure  $callback
     * @param  array  $query
     * @return string
     *
     * @throws \RenokiCo\PhpK8s\Exceptions\KubernetesLogsException
     * @throws \RenokiCo\PhpK8s\Exceptions\KubernetesAPIException
     */
    public function logsByName(string $name, array $query = ['pretty' => 1])
    {
        return $this->whereName($name)->logs($query);
    }

    /**
     * Watch the specific resource by name.
     *
     * @param  string  $name
     * @param  string  $container
     * @param  Closure  $callback
     * @param  array  $query
     * @return string
     *
     * @throws \RenokiCo\PhpK8s\Exceptions\KubernetesLogsException
     * @throws \RenokiCo\PhpK8s\Exceptions\KubernetesAPIException
     */
    public function containerLogsByName(string $name, string $container, array $query = ['pretty' => 1])
    {
        return $this->whereName($name)->containerLogs($container, $query);
    }

    /**
     * Watch the specific resource's container logs until the closure returns true or false.
     *
     * @param  string  $container
     * @param  Closure  $callback
     * @param  array  $query
     * @return mixed
     *
     * @throws \RenokiCo\PhpK8s\Exceptions\KubernetesWatchException
     * @throws \RenokiCo\PhpK8s\Exceptions\KubernetesLogsException
     */
    public function watchContainerLogs(string $container, Closure $callback, array $query = ['pretty' => 1])
    {
        return $this->watchLogs($callback, array_merge($query, ['container' => $container]));
    }

    /**
     * Watch the specific resource's logs by name.
     *
     * @param  Closure  $callback
     * @param  array  $query
     * @return mixed
     *
     * @throws \RenokiCo\PhpK8s\Exceptions\KubernetesWatchException
     * @throws \RenokiCo\PhpK8s\Exceptions\KubernetesLogsException
     */
    public function watchLogsByName(string $name, Closure $callback, array $query = ['pretty' => 1])
    {
        return $this->whereName($name)->watchLogs($callback, $query);
    }

    /**
     * Watch the specific resource's container logs by names.
     *
     * @param  string  $name
     * @param  string  $container
     * @param  Closure  $callback
     * @param  array  $query
     * @return mixed
     *
     * @throws \RenokiCo\PhpK8s\Exceptions\KubernetesWatchException
     * @throws \RenokiCo\PhpK8s\Exceptions\KubernetesLogsException
     */
    public function watchContainerLogsByName(string $name, string $container, Closure $callback, array $query = ['pretty' => 1])
    {
        return $this->whereName($name)->watchContainerLogs($container, $callback, $query);
    }
}