From b726e6475834c77144bab1df6fc7cb27fff56caa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20D=C3=A9loge?= Date: Mon, 28 Mar 2022 17:17:19 +0200 Subject: [PATCH] Some improvement with last version of Kubernetes API (#105) * Set content type to "application/json" for post request Allow illuminate/support 9+ * Remove beta in api add role,rolebinding and service account --- composer.json | 2 +- src/Client.php | 10 ++++- src/Collections/RoleBindingCollection.php | 41 +++++++++++++++++++ src/Collections/RoleCollection.php | 41 +++++++++++++++++++ src/Collections/ServiceAccountCollection.php | 41 +++++++++++++++++++ src/Models/CronJob.php | 2 +- src/Models/DaemonSet.php | 2 +- src/Models/HorizontalPodAutoscaler.php | 2 +- src/Models/Ingress.php | 2 +- src/Models/ReplicaSet.php | 2 +- src/Models/Role.php | 16 ++++++++ src/Models/RoleBinding.php | 16 ++++++++ src/Models/ServiceAccount.php | 12 ++++++ src/Repositories/RoleBindingRepository.php | 25 +++++++++++ src/Repositories/RoleRepository.php | 25 +++++++++++ src/Repositories/ServiceAccountRepository.php | 25 +++++++++++ src/RepositoryRegistry.php | 12 ++++-- tests/RepositoryRegistryTest.php | 2 +- tests/TestCase.php | 2 +- .../collections/RoleBindingCollectionTest.php | 28 +++++++++++++ tests/collections/RoleCollectionTest.php | 28 +++++++++++++ .../ServiceAccountCollectionTest.php | 28 +++++++++++++ tests/fixtures/cron-jobs/empty.json | 4 +- tests/fixtures/ingresses/empty.json | 4 +- tests/fixtures/replica-sets/empty.json | 4 +- tests/fixtures/roles-bindings/empty.json | 4 ++ tests/fixtures/roles/empty.json | 4 ++ tests/fixtures/services-accounts/empty.json | 4 ++ tests/models/CronJobTest.php | 2 +- tests/models/RoleBindingTest.php | 29 +++++++++++++ tests/models/RoleTest.php | 29 +++++++++++++ tests/models/ServiceAccountTest.php | 29 +++++++++++++ 32 files changed, 457 insertions(+), 20 deletions(-) create mode 100644 src/Collections/RoleBindingCollection.php create mode 100644 src/Collections/RoleCollection.php create mode 100644 src/Collections/ServiceAccountCollection.php create mode 100644 src/Models/Role.php create mode 100644 src/Models/RoleBinding.php create mode 100644 src/Models/ServiceAccount.php create mode 100644 src/Repositories/RoleBindingRepository.php create mode 100644 src/Repositories/RoleRepository.php create mode 100644 src/Repositories/ServiceAccountRepository.php create mode 100644 tests/collections/RoleBindingCollectionTest.php create mode 100644 tests/collections/RoleCollectionTest.php create mode 100644 tests/collections/ServiceAccountCollectionTest.php create mode 100644 tests/fixtures/roles-bindings/empty.json create mode 100644 tests/fixtures/roles/empty.json create mode 100644 tests/fixtures/services-accounts/empty.json create mode 100644 tests/models/RoleBindingTest.php create mode 100644 tests/models/RoleTest.php create mode 100644 tests/models/ServiceAccountTest.php diff --git a/composer.json b/composer.json index 6caaac4..31dc4ab 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ "php" : "^7.4|^8.0", "php-http/client-common": "^2.0", "php-http/discovery" : "^1.0", - "illuminate/support" : "^5.0|^6.0|^7.0|^8.0", + "illuminate/support" : "^5.0|^6.0|^7.0|^8.0|^9.0", "ratchet/pawl" : "^0.3", "symfony/yaml" : "^4.0|^5.0|^6.0", "softcreatr/jsonpath" : "^0.6" diff --git a/src/Client.php b/src/Client.php index 158d8a3..135f244 100644 --- a/src/Client.php +++ b/src/Client.php @@ -4,11 +4,13 @@ use InvalidArgumentException; use BadMethodCallException; use Maclof\Kubernetes\Exceptions\ApiServerException; +use Maclof\Kubernetes\Repositories\RoleBindingRepository; +use Maclof\Kubernetes\Repositories\RoleRepository; +use Maclof\Kubernetes\Repositories\ServiceAccountRepository; use Psr\Http\Client\ClientInterface; use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Exception\ParseException as YamlParseException; -use Http\Client\HttpClient; use Http\Client\Common\HttpMethodsClient; use Http\Client\Common\HttpMethodsClientInterface; use Http\Client\Exception\TransferException as HttpTransferException; @@ -64,6 +66,9 @@ * @method HorizontalPodAutoscalerRepository horizontalPodAutoscalers() * @method CertificateRepository certificates() * @method IssuersRepository issuers() + * @method ServiceAccountRepository serviceAccounts() + * @method RoleRepository roles() + * @method RoleBindingRepository roleBindings() */ class Client { @@ -381,6 +386,9 @@ public function sendRequest(string $method, string $uri, array $query = [], $bod try { $headers = $method === 'PATCH' ? $this->patchHeaders : []; + if ('POST' === $method) { + $headers['Content-Type'] = 'application/json'; + } if ($this->token) { $token = $this->token; diff --git a/src/Collections/RoleBindingCollection.php b/src/Collections/RoleBindingCollection.php new file mode 100644 index 0000000..f6994cf --- /dev/null +++ b/src/Collections/RoleBindingCollection.php @@ -0,0 +1,41 @@ + + */ +class RoleBindingCollection extends Collection +{ + /** + * @param array|RoleBinding> $items + */ + public function __construct(array $items) + { + parent::__construct($this->getServiceAccounts($items)); + } + + /** + * Get an array of serviceAccounts. + * + * @param array|RoleBinding> $items + * @return array + */ + protected function getServiceAccounts(array $items) + { + $final = []; + foreach ($items as &$item) { + if (!$item instanceof RoleBinding) { + $final[] = new RoleBinding($item); + } else { + $final[] = $item; + } + } + + return $final; + } +} diff --git a/src/Collections/RoleCollection.php b/src/Collections/RoleCollection.php new file mode 100644 index 0000000..92cf4ba --- /dev/null +++ b/src/Collections/RoleCollection.php @@ -0,0 +1,41 @@ + + */ +class RoleCollection extends Collection +{ + /** + * @param array|Role> $items + */ + public function __construct(array $items) + { + parent::__construct($this->getServiceAccounts($items)); + } + + /** + * Get an array of serviceAccounts. + * + * @param array|Role> $items + * @return array + */ + protected function getServiceAccounts(array $items) + { + $final = []; + foreach ($items as &$item) { + if (!$item instanceof Role) { + $final[] = new Role($item); + } else { + $final[] = $item; + } + } + + return $final; + } +} diff --git a/src/Collections/ServiceAccountCollection.php b/src/Collections/ServiceAccountCollection.php new file mode 100644 index 0000000..9f7aa75 --- /dev/null +++ b/src/Collections/ServiceAccountCollection.php @@ -0,0 +1,41 @@ + + */ +class ServiceAccountCollection extends Collection +{ + /** + * @param array|ServiceAccount> $items + */ + public function __construct(array $items) + { + parent::__construct($this->getServiceAccounts($items)); + } + + /** + * Get an array of serviceAccounts. + * + * @param array|ServiceAccount> $items + * @return array + */ + protected function getServiceAccounts(array $items) + { + $final = []; + foreach ($items as &$item) { + if (!$item instanceof ServiceAccount) { + $final[] = new ServiceAccount($item); + } else { + $final[] = $item; + } + } + + return $final; + } +} diff --git a/src/Models/CronJob.php b/src/Models/CronJob.php index b64d61f..2425596 100644 --- a/src/Models/CronJob.php +++ b/src/Models/CronJob.php @@ -5,5 +5,5 @@ class CronJob extends Model /** * The api version. */ - protected string $apiVersion = 'batch/v1beta1'; + protected string $apiVersion = 'batch/v1'; } diff --git a/src/Models/DaemonSet.php b/src/Models/DaemonSet.php index 4a85297..5df56d3 100644 --- a/src/Models/DaemonSet.php +++ b/src/Models/DaemonSet.php @@ -5,5 +5,5 @@ class DaemonSet extends Model /** * The api version. */ - protected string $apiVersion = 'extensions/v1beta1'; + protected string $apiVersion = 'apps/v1'; } diff --git a/src/Models/HorizontalPodAutoscaler.php b/src/Models/HorizontalPodAutoscaler.php index f24f970..3540c15 100644 --- a/src/Models/HorizontalPodAutoscaler.php +++ b/src/Models/HorizontalPodAutoscaler.php @@ -5,5 +5,5 @@ class HorizontalPodAutoscaler extends \Maclof\Kubernetes\Models\Model /** * The api version. */ - protected string $apiVersion = 'autoscaling/v2beta1'; + protected string $apiVersion = 'autoscaling/v2'; } diff --git a/src/Models/Ingress.php b/src/Models/Ingress.php index 804bcb1..02ffb78 100644 --- a/src/Models/Ingress.php +++ b/src/Models/Ingress.php @@ -5,5 +5,5 @@ class Ingress extends Model /** * The api version. */ - protected string $apiVersion = 'networking.k8s.io/v1beta1'; + protected string $apiVersion = 'networking.k8s.io/v1'; } diff --git a/src/Models/ReplicaSet.php b/src/Models/ReplicaSet.php index 5e91add..787d576 100644 --- a/src/Models/ReplicaSet.php +++ b/src/Models/ReplicaSet.php @@ -5,5 +5,5 @@ class ReplicaSet extends Model /** * The api version. */ - protected string $apiVersion = 'extensions/v1beta1'; + protected string $apiVersion = 'apps/v1'; } diff --git a/src/Models/Role.php b/src/Models/Role.php new file mode 100644 index 0000000..fd34446 --- /dev/null +++ b/src/Models/Role.php @@ -0,0 +1,16 @@ + + */ +class Role extends Model +{ + /** + * @var string + */ + protected string $apiVersion = 'rbac.authorization.k8s.io/v1'; +} diff --git a/src/Models/RoleBinding.php b/src/Models/RoleBinding.php new file mode 100644 index 0000000..fd09429 --- /dev/null +++ b/src/Models/RoleBinding.php @@ -0,0 +1,16 @@ + + */ +class RoleBinding extends Model +{ + /** + * @var string + */ + protected string $apiVersion = 'rbac.authorization.k8s.io/v1'; +} diff --git a/src/Models/ServiceAccount.php b/src/Models/ServiceAccount.php new file mode 100644 index 0000000..d50889b --- /dev/null +++ b/src/Models/ServiceAccount.php @@ -0,0 +1,12 @@ + + */ +class ServiceAccount extends Model +{ +} diff --git a/src/Repositories/RoleBindingRepository.php b/src/Repositories/RoleBindingRepository.php new file mode 100644 index 0000000..dfa2b73 --- /dev/null +++ b/src/Repositories/RoleBindingRepository.php @@ -0,0 +1,25 @@ + + */ +class RoleBindingRepository extends Repository +{ + protected string $uri = 'rolebindings'; + + /** + * @param array{items: array|RoleBinding>} $response + */ + protected function createCollection(array $response): Collection + { + return new RoleBindingCollection($response['items']); + } +} diff --git a/src/Repositories/RoleRepository.php b/src/Repositories/RoleRepository.php new file mode 100644 index 0000000..fac0659 --- /dev/null +++ b/src/Repositories/RoleRepository.php @@ -0,0 +1,25 @@ + + */ +class RoleRepository extends Repository +{ + protected string $uri = 'roles'; + + /** + * @param array{items: array|Role>} $response + */ + protected function createCollection(array $response): Collection + { + return new RoleCollection($response['items']); + } +} diff --git a/src/Repositories/ServiceAccountRepository.php b/src/Repositories/ServiceAccountRepository.php new file mode 100644 index 0000000..6334ddb --- /dev/null +++ b/src/Repositories/ServiceAccountRepository.php @@ -0,0 +1,25 @@ + + */ +class ServiceAccountRepository extends Repository +{ + protected string $uri = 'serviceaccounts'; + + /** + * @param array{items: array|ServiceAccount>} $response + */ + protected function createCollection(array $response): Collection + { + return new ServiceAccountCollection($response['items']); + } +} diff --git a/src/RepositoryRegistry.php b/src/RepositoryRegistry.php index f027792..a993ab0 100644 --- a/src/RepositoryRegistry.php +++ b/src/RepositoryRegistry.php @@ -20,30 +20,34 @@ class RepositoryRegistry implements \ArrayAccess, \Countable 'persistentVolume' => Repositories\PersistentVolumeRepository::class, 'persistentVolumeClaims' => Repositories\PersistentVolumeClaimRepository::class, 'namespaces' => Repositories\NamespaceRepository::class, + 'serviceAccounts' => Repositories\ServiceAccountRepository::class, // batch/v1 'jobs' => Repositories\JobRepository::class, - // batch/v2alpha1 + // batch/v2 'cronJobs' => Repositories\CronJobRepository::class, // apps/v1 'deployments' => Repositories\DeploymentRepository::class, - // extensions/v1beta1 + // extensions/v1 'daemonSets' => Repositories\DaemonSetRepository::class, 'ingresses' => Repositories\IngressRepository::class, - // autoscaling/v2beta1 + // autoscaling/v2 'horizontalPodAutoscalers' => Repositories\HorizontalPodAutoscalerRepository::class, // networking.k8s.io/v1 'networkPolicies' => Repositories\NetworkPolicyRepository::class, - // certmanager.k8s.io/v1alpha1 + // certmanager.k8s.io/v1 'certificates' => Repositories\CertificateRepository::class, 'issuers' => Repositories\IssuerRepository::class, + //rbac.authorization.k8s.io/v1 + 'roles' => Repositories\RoleRepository::class, + 'roleBindings' => Repositories\RoleBindingRepository::class, ]; public function __construct() diff --git a/tests/RepositoryRegistryTest.php b/tests/RepositoryRegistryTest.php index ba7f50f..05108aa 100644 --- a/tests/RepositoryRegistryTest.php +++ b/tests/RepositoryRegistryTest.php @@ -9,7 +9,7 @@ public function test_builtin_repositories(): void { $registry = new RepositoryRegistry(); - $this->assertCount(22, $registry); + $this->assertCount(25, $registry); } public function test_add_repository(): void diff --git a/tests/TestCase.php b/tests/TestCase.php index e247d06..f28f517 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -30,6 +30,6 @@ protected function getFixture(string $path): ?string // Fix for windows encoded fixtures. $contents = str_replace("\r\n", "\n", $contents); - return $contents; + return trim($contents, ' ' . PHP_EOL); } } diff --git a/tests/collections/RoleBindingCollectionTest.php b/tests/collections/RoleBindingCollectionTest.php new file mode 100644 index 0000000..edb91d9 --- /dev/null +++ b/tests/collections/RoleBindingCollectionTest.php @@ -0,0 +1,28 @@ +items); + + return $roleBindingCollection; + } + + public function test_get_items(): void + { + $roleBindingCollection = $this->getRoleBindingCollection(); + $items = $roleBindingCollection->toArray(); + + $this->assertTrue(is_array($items)); + $this->assertEquals(3, count($items)); + } +} diff --git a/tests/collections/RoleCollectionTest.php b/tests/collections/RoleCollectionTest.php new file mode 100644 index 0000000..308c3b5 --- /dev/null +++ b/tests/collections/RoleCollectionTest.php @@ -0,0 +1,28 @@ +items); + + return $roleCollection; + } + + public function test_get_items(): void + { + $roleCollection = $this->getRoleCollection(); + $items = $roleCollection->toArray(); + + $this->assertTrue(is_array($items)); + $this->assertEquals(3, count($items)); + } +} diff --git a/tests/collections/ServiceAccountCollectionTest.php b/tests/collections/ServiceAccountCollectionTest.php new file mode 100644 index 0000000..66f724a --- /dev/null +++ b/tests/collections/ServiceAccountCollectionTest.php @@ -0,0 +1,28 @@ +items); + + return $serviceAccountCollection; + } + + public function test_get_items(): void + { + $serviceAccountCollection = $this->getServiceAccountCollection(); + $items = $serviceAccountCollection->toArray(); + + $this->assertTrue(is_array($items)); + $this->assertEquals(3, count($items)); + } +} diff --git a/tests/fixtures/cron-jobs/empty.json b/tests/fixtures/cron-jobs/empty.json index 188bb4e..fd64460 100644 --- a/tests/fixtures/cron-jobs/empty.json +++ b/tests/fixtures/cron-jobs/empty.json @@ -1,4 +1,4 @@ { "kind": "CronJob", - "apiVersion": "batch/v1beta1" -} \ No newline at end of file + "apiVersion": "batch/v1" +} diff --git a/tests/fixtures/ingresses/empty.json b/tests/fixtures/ingresses/empty.json index 671e13e..fa19023 100644 --- a/tests/fixtures/ingresses/empty.json +++ b/tests/fixtures/ingresses/empty.json @@ -1,4 +1,4 @@ { "kind": "Ingress", - "apiVersion": "networking.k8s.io/v1beta1" -} \ No newline at end of file + "apiVersion": "networking.k8s.io/v1" +} diff --git a/tests/fixtures/replica-sets/empty.json b/tests/fixtures/replica-sets/empty.json index dc62ca7..d12ff16 100644 --- a/tests/fixtures/replica-sets/empty.json +++ b/tests/fixtures/replica-sets/empty.json @@ -1,4 +1,4 @@ { "kind": "ReplicaSet", - "apiVersion": "extensions/v1beta1" -} \ No newline at end of file + "apiVersion": "apps/v1" +} diff --git a/tests/fixtures/roles-bindings/empty.json b/tests/fixtures/roles-bindings/empty.json new file mode 100644 index 0000000..49760ea --- /dev/null +++ b/tests/fixtures/roles-bindings/empty.json @@ -0,0 +1,4 @@ +{ + "kind": "RoleBinding", + "apiVersion": "rbac.authorization.k8s.io/v1" +} diff --git a/tests/fixtures/roles/empty.json b/tests/fixtures/roles/empty.json new file mode 100644 index 0000000..cdd4f86 --- /dev/null +++ b/tests/fixtures/roles/empty.json @@ -0,0 +1,4 @@ +{ + "kind": "Role", + "apiVersion": "rbac.authorization.k8s.io/v1" +} diff --git a/tests/fixtures/services-accounts/empty.json b/tests/fixtures/services-accounts/empty.json new file mode 100644 index 0000000..b31b49f --- /dev/null +++ b/tests/fixtures/services-accounts/empty.json @@ -0,0 +1,4 @@ +{ + "kind": "ServiceAccount", + "apiVersion": "v1" +} diff --git a/tests/models/CronJobTest.php b/tests/models/CronJobTest.php index 2fd77ea..e34d4c8 100644 --- a/tests/models/CronJobTest.php +++ b/tests/models/CronJobTest.php @@ -31,7 +31,7 @@ public function test_set_api_version(): void { $cronJob = new CronJob; - $this->assertEquals($cronJob->getApiVersion(), 'batch/v1beta1'); + $this->assertEquals($cronJob->getApiVersion(), 'batch/v1'); $cronJob->setApiVersion('batch/v2alpha1'); $this->assertEquals($cronJob->getApiVersion(), 'batch/v2alpha1'); diff --git a/tests/models/RoleBindingTest.php b/tests/models/RoleBindingTest.php new file mode 100644 index 0000000..43c4cde --- /dev/null +++ b/tests/models/RoleBindingTest.php @@ -0,0 +1,29 @@ +getSchema(); + $fixture = $this->getFixture('roles-bindings/empty.json'); + + $this->assertEquals($schema, $fixture); + } + + public function test_get_metadata(): void + { + $roleBinding = new RoleBinding([ + 'metadata' => [ + 'name' => 'test', + ], + ]); + + $metadata = $roleBinding->getMetadata('name'); + + $this->assertEquals($metadata, 'test'); + } +} diff --git a/tests/models/RoleTest.php b/tests/models/RoleTest.php new file mode 100644 index 0000000..0fcf625 --- /dev/null +++ b/tests/models/RoleTest.php @@ -0,0 +1,29 @@ +getSchema(); + $fixture = $this->getFixture('roles/empty.json'); + + $this->assertEquals($schema, $fixture); + } + + public function test_get_metadata(): void + { + $role = new Role([ + 'metadata' => [ + 'name' => 'test', + ], + ]); + + $metadata = $role->getMetadata('name'); + + $this->assertEquals($metadata, 'test'); + } +} diff --git a/tests/models/ServiceAccountTest.php b/tests/models/ServiceAccountTest.php new file mode 100644 index 0000000..40a82ee --- /dev/null +++ b/tests/models/ServiceAccountTest.php @@ -0,0 +1,29 @@ +getSchema(); + $fixture = $this->getFixture('services-accounts/empty.json'); + + $this->assertEquals($schema, $fixture); + } + + public function test_get_metadata(): void + { + $serviceAccount = new ServiceAccount([ + 'metadata' => [ + 'name' => 'test', + ], + ]); + + $metadata = $serviceAccount->getMetadata('name'); + + $this->assertEquals($metadata, 'test'); + } +}