Giter Club home page Giter Club logo

kubernetes-client's Introduction

Kubernetes Client

Build Status

A PHP client for managing a Kubernetes cluster.

Last tested with v1.9.6 on a production cloud hosted cluster.

Installation using Composer

$ composer require maclof/kubernetes-client

Supported API Features

v1

  • Nodes
  • Namespaces
  • Pods
  • Replica Sets
  • Replication Controllers
  • Services
  • Secrets
  • Events
  • Config Maps
  • Endpoints
  • Persistent Volume
  • Persistent Volume Claims

batch/v1

  • Jobs

batch/v1beta1

  • Cron Jobs

apps/v1

  • Deployments

extensions/v1beta1

  • Daemon Sets

networking.k8s.io/v1

  • Network Policies

networking.k8s.io/v1beta1

  • Ingresses

certmanager.k8s.io/v1alpha1

  • Certificates
  • Issuers

Basic Usage

<?php

require __DIR__ . '/vendor/autoload.php';

use Maclof\Kubernetes\Client;

$client = new Client([
	'master' => 'http://master.mycluster.com',
]);

// Find pods by label selector
$pods = $client->pods()->setLabelSelector([
	'name'    => 'test',
	'version' => 'a',
])->find();

// Both setLabelSelector and setFieldSelector can take an optional
// second parameter which lets you define inequality based selectors (ie using the != operator)
$pods = $client->pods()->setLabelSelector([
	'name'    => 'test'], 
	['env'     =>  'staging']
])->find();

// Find pods by field selector
$pods = $client->pods()->setFieldSelector([
	'metadata.name' => 'test',
])->find();

// Find first pod with label selector (same for field selector)
$pod = $client->pods()->setLabelSelector([
	'name' => 'test',
])->first();

Using JSONPath

It allows you to query status data.

$jobStartTime = $client->jobs()->find()->getJsonPath('$.status.startTime')[0];

Authentication Examples

Insecure HTTP

use Maclof\Kubernetes\Client;
$client = new Client([
	'master' => 'http://master.mycluster.com',
]);

Secure HTTPS (CA + Client Certificate Validation)

use Maclof\Kubernetes\Client;
use Http\Adapter\Guzzle6\Client as Guzzle6Client;
$httpClient = Guzzle6Client::createWithConfig([
	'verify' => '/etc/kubernetes/ssl/ca.crt',
	'cert' => '/etc/kubernetes/ssl/client.crt',
	'ssl_key' => '/etc/kubernetes/ssl/client.key',
]);
$client = new Client([
	'master' => 'https://master.mycluster.com',
], null, $httpClient);

Insecure HTTPS (CA Certificate Verification Disabled)

use Maclof\Kubernetes\Client;
use Http\Adapter\Guzzle6\Client as Guzzle6Client;
$httpClient = Guzzle6Client::createWithConfig([
	'verify' => false,
]);
$client = new Client([
	'master' => 'https://master.mycluster.com',
], null, $httpClient);

Using Basic Auth

use Maclof\Kubernetes\Client;
$client = new Client([
	'master' => 'https://master.mycluster.com',
	'username' => 'admin',
	'password' => 'abc123',
]);

Using a Service Account

use Maclof\Kubernetes\Client;
use Http\Adapter\Guzzle6\Client as Guzzle6Client;
$httpClient = Guzzle6Client::createWithConfig([
	'verify' => '/var/run/secrets/kubernetes.io/serviceaccount/ca.crt',
]);
$client = new Client([
	'master' => 'https://master.mycluster.com',
	'token' => '/var/run/secrets/kubernetes.io/serviceaccount/token',
], null, $httpClient);

Parsing a kubeconfig file

use Maclof\Kubernetes\Client;

// Parsing from the file data directly
$config = Client::parseKubeConfig('kubeconfig yaml data');

// Parsing from the file path
$config = Client::parseKubeConfigFile('~/.kube/config.yml');

// Example config that may be returned
// You would then feed these options into the http/kubernetes client constructors.
$config = [
	'master' => 'https://master.mycluster.com',
	'ca_cert' => '/temp/path/ca.crt',
	'client_cert' => '/temp/path/client.crt',
	'client_key' => '/temp/path/client.key',
];

Extending a library

Custom repositories

use Maclof\Kubernetes\Client;

$repositories = new RepositoryRegistry();
$repositories['things'] = MyApp\Kubernetes\Repository\ThingRepository::class;

$client = new Client([
	'master' => 'https://master.mycluster.com',
], $repositories);

$client->things(); //ThingRepository

Usage Examples

Create/Update a Replication Controller

The below example uses an array to specify the replication controller's attributes. You can specify the attributes either as an array, JSON encoded string or a YAML encoded string. The second parameter to the model constructor is the data type and defaults to array.

use Maclof\Kubernetes\Models\ReplicationController;

$replicationController = new ReplicationController([
	'metadata' => [
		'name' => 'nginx-test',
		'labels' => [
			'name' => 'nginx-test',
		],
	],
	'spec' => [
		'replicas' => 1,
		'template' => [
			'metadata' => [
				'labels' => [
					'name' => 'nginx-test',
				],
			],
			'spec' => [
				'containers' => [
					[
						'name'  => 'nginx',
						'image' => 'nginx',
						'ports' => [
							[
								'containerPort' => 80,
								'protocol'      => 'TCP',
							],
						],
					],
				],
			],
		],
	],
]);

if ($client->replicationControllers()->exists($replicationController->getMetadata('name'))) {
	$client->replicationControllers()->update($replicationController);
} else {
	$client->replicationControllers()->create($replicationController);
}

Delete a Replication Controller

$replicationController = $client->replicationControllers()->setLabelSelector([
	'name' => 'nginx-test',
])->first();
$client->replicationControllers()->delete($replicationController);

You can also specify options when performing a deletion, eg. to perform cascading delete

use Maclof\Kubernetes\Models\DeleteOptions;

$client->replicationControllers()->delete(
	$replicationController,
	new DeleteOptions(['propagationPolicy' => 'Background'])
);

See the API documentation for an explanation of the options:

https://kubernetes.io/docs/api-reference/v1.6/#deleteoptions-v1-meta

kubernetes-client's People

Contributors

avimoto avatar brucedevcom avatar danijelk avatar dasann avatar dhemeier avatar frenchcomp avatar glennschmidt avatar gregy avatar jeroen-g avatar jeroeny avatar jjtroberts avatar josefschabasser avatar leo108 avatar leonboot avatar luceos avatar lxm avatar m24te28 avatar maclof avatar maspeng avatar michaelbutler avatar mwadon avatar patriceckhart avatar phbergsmann avatar pierredup avatar shanefrightidentos avatar softcreatr avatar steache avatar sz-po avatar tvass avatar weechow avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kubernetes-client's Issues

Use multiple configMapRef settings

Hello! We're trying to launch a cronjob that needs multiple configMapRef settings, but if we declare:

                     'envFrom' => [
                        'configMapRef' => 'configmap-1',
                        'configMapRef' => 'configmap-2',
                      ]

only the second configMapRef is used. How can we make it so that we have multiple entries? In the k8s YAML this works perfectly:

            envFrom:
              - configMapRef:
                  name: configmap-1
              - configMapRef:
                  name: configmap-2

Cert Manager Domains LE SSL Addition using Laravel Jobs

Bumped into this excellent repository on my quest for a way to have Laravel set jobs in queue for new domains to get a Let's Encrypt SSL certtificate as well as deal with renewals.. So far been doing this with another ACME 2 package and jobs on a VPS and was looking for Kubernetes Cert Manager to do this based on Laravel PHP Jobs.

Does seem Kubernetes Client allows us to work with Certificates and Certificate Issuers as well. So am I correct to think we could use this package to ask the Cert Manager to issue another LE SSL certificate using Laravel Schedule and Jobs? And recommended ways to do this?

issue on update Service , empty loadBalance error

i created a service, when i query it by the api, i printed the return, its like this:
{"kind":"ServiceList","apiVersion":"v1","metadata":{"selfLink":"/api/v1/namespaces/hujie/services","resourceVersion":"2181987"},"items":[{"metadata":{"name":"redis-master","namespace":"hujie","selfLink":"/api/v1/namespaces/hujie/services/redis-master","uid":"cc37eaf4-6e1e-11e8-82d7-d4ae526f781c","resourceVersion":"2180527","creationTimestamp":"2018-06-12T08:58:38Z"},"spec":{"ports":[{"protocol":"TCP","port":6379,"targetPort":6379,"nodePort":31003}],"selector":{"tier":"redis"},"clusterIP":"10.68.87.72","type":"NodePort","sessionAffinity":"None","externalTrafficPolicy":"Cluster"},"status":{"loadBalancer":{}}}]}

you see the loadBalancer is an empty object like {}.

but when you json_decode($bodyResponse,true), it will become an empty array , and it is not an empty object anymore.

Then i want edit it, change its port and update it

$service = $client->services()->setFieldSelector([ 'metadata.name' => 'redis-master',])->first();  
$values = $service->toArray();
var_export($values);

//edit
$values['spec']['ports'][0]['nodePort'] = 31003;

//re-create an update object
$service_upd = new Service($values);

//and update
$client->services()->update($service_upd);

i got an error:

Exception 'Maclof\Kubernetes\Exceptions\BadRequestException' with message '{"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"Service in version "v1" cannot be handled as a Service: v1.Service: Status: v1.ServiceStatus: LoadBalancer: readObjectStart: expect { or n, parsing 822 ...lancer": [... at {\n "kind": "Service",\n "apiVersion": "v1",\n "metadata": {\n "name": "redis-master-rename",\n "namespace": "hujie",\n "selfLink": "\/api\/v1\/namespaces\/hujie\/services\/redis-master",\n "uid": "cc37eaf4-6e1e-11e8-82d7-d4ae526f781c",\n "resourceVersion": "2175754",\n "creationTimestamp": "2018-06-12T08:58:38Z"\n },\n "spec": {\n "ports": [\n {\n "protocol": "TCP",\n "port": 6379,\n "targetPort": 6379,\n "nodePort": 31002\n }\n ],\n "selector": {\n "tier": "redis"\n },\n "clusterIP": "10.68.87.72",\n "type": "NodePort",\n "sessionAffinity": "None",\n "externalTrafficPolicy": "Cluster"\n },\n "status": {\n "loadBalancer": []\n }\n}","reason":"BadRequest","code":400}

see ? the loadBalancer was an object when the query returns, and when we decode it and encode it, it becomes an array . and the update failed.

still, i can not use JSON_FORCE_OBJECT to fix it, that might cause some other problem.

Model->getMetadata TypeError

Hello
I have an error with the function, it can return an array not only a string
For exemple if you call it with ->getMetadata('labels')

"Return value of Maclof\Kubernetes\Models\Model::getMetadata() must be of the type string or null, array returned"

public function getMetadata(string $key): ?string

Thank you

Add License

Hi, can you please clarify the license of this awesome project?

Guzzle Dependency / Websocket Requirements

Instead of having Guzzle and Ratchet as hard dependencies, should there instead be other interfaces used so we can use other HTTP clients or websocket clients?

For HTTP clients this is a little more straight forward since PSR-18 exists for that reason. For websockets, something else would have to be made since there is no standardization, but there are competing clients.

One of my use cases for a separate websocket client is so I could use the Swoole websocket client in place of ratchet. Could potentially just create an interface in this library, and then separate out the ratchet implementation into its own repo. Thoughts?

Pod exec broken since 0.22.0

The exec function for pod repositories has been broken since version 0.22.0, instead of command output you get:

[
     "kind" => "Status",
     "apiVersion" => "v1",
     "metadata" => [],
     "status" => "Failure",
     "message" => "Upgrade request required",
     "reason" => "BadRequest",
     "code" => 400,
   ]

From what I can see the issue seems to be in Client.php, it seems like it's waiting for a HttpTransferException to be thrown before running the function to upgrade the request, but for whatever reason the exception isn't being thrown.

How to handle a stream response for a job request?

Looking at: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.10/#-strong-read-operations-strong--43

There is a watch flag that says Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.

I need functionality so that I will get the response when the job has finished. Is it possible to achieve this with the API here? Any code examples would be great.

Custom repo documentation invalid; No 3rd argument in Client constructor

I am trying to add support for Istio Gateway and VirtualService.

Based on the Custom Repositories section of README.md, I should be able to add Repository classes to my project and bootstrap them like so: (At least this is how I'm interpreting I should be able to add support for Gateway and VirtualService, correct me if I'm wrong)

$repositories['things'] = MyApp\Kubernetes\Repository\ThingRepository::class;

$client = new Client([
    'master' => 'https://master.mycluster.com','
], null, $repositories);

$client->things(); //ThingRepository

The problem is there is no 3rd argument supported for the constructor.

How can I add support for kinds not supported by default?

Enlarging Capacity of a PVC fails

Can you help me?

`
$client = $this->client();

    $pvc = new PersistentVolumeClaim([
        'apiVersion' => 'v1',
        'kind' => 'PersistentVolumeClaim',
        'metadata' => [
            'name' => $identifier . '-pv-claim',
            'labels' => [
                'app' => $identifier,
            ],
        ],
        'spec' => [
            'accessModes' => ['ReadWriteOnce'],
            'resources' => [
                'requests' => [
                    'storage' => $storageCapacity . 'Gi'
                ]
            ]
        ]
    ]);

    if ($client->persistentVolumeClaims()->exists($pvc->getMetadata('name'))) {
        $client->persistentVolumeClaims()->update($pvc);
    } else {
        $client->persistentVolumeClaims()->create($pvc);
    }

`

{"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"PersistentVolumeClaim "site-5400133060-pv-claim" is invalid: spec: Forbidden: is immutable after creation except resources.requests for bound claims","reason":"Invalid","details":{"name":"site-5400133060-pv-claim","kind":"PersistentVolumeClaim","causes":[{"reason":"FieldValueForbidden","message":"Forbidden: is immutable after creation except resources.requests for bound claims","field":"spec"}]},"code":422}

Service Account Authentication

I tested a script from within a pod using a service account, i.e.

$client = new Client([
    'master'  => 'https://master.mycluster.com',
    'ca_cert' => '/var/run/secrets/kubernetes.io/serviceaccount/ca.crt',
    'token'   => '/var/run/secrets/kubernetes.io/serviceaccount/token',
]);

However I got a GuzzleHttp\Exception\ClientException with the standard "Unauthorized" message.

A basic test with curl from the pod worked, i.e.

curl -v --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" https://kubernetes/

So I echoed the contents of the createGuzzleClient options:

Array
(
    [headers] => Array
        (
            [Content-Type] => application/json
            [Authorization] => Bearer /var/run/secrets/kubernetes.io/serviceaccount/token
        )

    [verify] => /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
    [base_uri] => https://kubernetes
)

Should the contents of the token be shown in [Authorization] as opposed to the filename?

I ask because I worked around the problem by passing the contents of the token as opposed to the filename.

$client = new Client([
    'master'  => 'https://master.mycluster.com',
    'ca_cert' => '/var/run/secrets/kubernetes.io/serviceaccount/ca.crt',
    'token'   => file_get_contents('/var/run/secrets/kubernetes.io/serviceaccount/token'),
]);

Yaml vs array

Not sure if already supported but been digging through code and not seen anyway of doing this yet (let me know if it already works!)

Readme details how to build a replication controller (or any other item) through an array, but for the purposes of being compatible outside PHP I would rather work purely with YAML.
I plan to write, manage and save YAML files through my app and would rather be able to pass in a pure YAML template instead of an array.
That way I could if needed edit yamls with a text editor and run manually on exact same config with kubectl.

If not YAML then could potentially use json instead, just a personal preference for yaml over json.
Key is being able to load/output configuration via a text file and then use the client as normal.

Add Namespaces

Hey,

currently I work on a project and need to manage namespaces. I would suggest to implement the relevant endpoint/model/repo methods to this library.

What do you guys think?
When okay I would develop the needed stuff and create a merge request.

I get cURL error 3

I get cURL error 3: (see https://curl.haxx.se/libcurl/c/libcurl-errors.html)
after I do
new PersistentVolumeClaim([

this is my php. For weeks it works fine:

$pvc = new PersistentVolumeClaim([
            'apiVersion' => 'v1',
            'kind' => 'PersistentVolumeClaim',
            'metadata' => [
                'name' => 'site-'.$uniqueId.'-pv-claim',
                'labels' => [
                    'app' => 'site-'.$uniqueId.'',
                ],
            ],
            'spec' => [
                'accessModes' => ['ReadWriteOnce'],
                'resources' => [
                    'requests' => [
                        'storage' => '5Gi'
                    ]
                ]
            ]
        ]);

        if ($client->persistentVolumeClaims()->exists($pvc->getMetadata('name'))) {
            $client->persistentVolumeClaims()->update($pvc);
        } else {
            $client->persistentVolumeClaims()->create($pvc);
        }

Update Ingress support for kubernetes version 1.18

I got an error when trying the library with Kubernetes version 1.18, digging up it seems that the API call has changed from "extensions" to "networking.k8s.io" on the Ingress resource spec. The Ingress Model class should be updated to match this. Btw good job with the library I use it for a variety of projects. Regards

Repository watch method is broken

I have been trying to use the watch method from the Deployment repo but found that it isn't working as expected.

The issue is due to the Client class looking up the wrong variable when determining if the stream option has been passed.

Using empty is causing the undefined variable error to fail silently. It might be better to do something like this

if (array_key_exists('stream', $requestOptions) && $requestOptions['stream'] === true) {
     return $response;
}

Once I got this working and the stream outputting, I then had a problem with Guzzle terminating the stream abruptly:

  Unable to read from stream

  at vendor/guzzlehttp/psr7/src/Stream.php:230
    226▕         }
    227▕
    228▕         $string = fread($this->stream, $length);
    229▕         if (false === $string) {
  ➜ 230▕             throw new \RuntimeException('Unable to read from stream');
    231▕         }
    232▕
    233▕         return $string;
    234▕     }

      +2 vendor frames

Certificate kind

Hello, I apologize if this question feels out of place but I am not sure where else to ask. I've used your API to develop an app and find myself somewhat stuck on trying to deploy "Certificate kind" of yaml files.

For reference, my app relies on this: https://github.com/ahmetb/gke-letsencrypt/blob/master/50-get-a-certificate.md which is the process I've implemented for generating SSL certificates using letsencrypt.

This process relies on deploying these kind: Certificate yaml files and I am trying to figure out how I could achieve the same using your API.

I appreciate the direction and apologize if the question is out of place. This is my first kubernetes project so I am in a learning curve at the moment.

Thanks!

api version for ingress

I want to use the api version networking.k8s.io/v1 for Ingress.

Tried to extend the model and define the api version. But ends in an error:

{"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"the API version in the data (networking.k8s.io/v1) does not match the expected API version (networking.k8s.io/v1beta1)","reason":"BadRequest","code":400}

conflict with laravel 6.0

  • Installation request for maclof/kubernetes-client ^0.14.3 -> satisfiable by maclof/kubernetes-client[0.14.3].
    • Conclusion: don't install laravel/framework v6.0.1
    • maclof/kubernetes-client 0.14.3 requires illuminate/support ~5.0 -> satisfiable by illuminate/support[5.0.x-dev, 5.1.x-dev, 5.2.x-dev, 5.3.x-dev, 5.4.x-dev, 5.5.x-dev, 5.6.x-dev, 5.7.17, 5.7.18, 5.7.19, 5.7.x-dev, 5.8.x-dev, v5.0.0, v5.0.22, v5.0.25, v5.0.26, v5.0.28, v5.0.33, v5.0.4, v5.1.1, v5.1.13, v5.1.16, v5.1.2, v5.1.20, v5.1.22, v5.1.25, v5.1.28, v5.1.30, v5.1.31, v5.1.41, v5.1.6, v5.1.8, v5.2.0, v5.2.19, v5.2.21, v5.2.24, v5.2.25, v5.2.26, v5.2.27, v5.2.28, v5.2.31, v5.2.32, v5.2.37, v5.2.43, v5.2.45, v5.2.6, v5.2.7, v5.3.0, v5.3.16, v5.3.23, v5.3.4, v5.4.0, v5.4.13, v5.4.17, v5.4.19, v5.4.27, v5.4.36, v5.4.9, v5.5.0, v5.5.16, v5.5.17, v5.5.2, v5.5.28, v5.5.33, v5.5.34, v5.5.35, v5.5.36, v5.5.37, v5.5.39, v5.5.40, v5.5.41, v5.5.43, v5.5.44, v5.6.0, v5.6.1, v5.6.10, v5.6.11, v5.6.12, v5.6.13, v5.6.14, v5.6.15, v5.6.16, v5.6.17, v5.6.19, v5.6.2, v5.6.20, v5.6.21, v5.6.22, v5.6.23, v5.6.24, v5.6.25, v5.6.26, v5.6.27, v5.6.28, v5.6.29, v5.6.3, v5.6.30, v5.6.31, v5.6.32, v5.6.33, v5.6.34, v5.6.35, v5.6.36, v5.6.37, v5.6.38, v5.6.39, v5.6.4, v5.6.5, v5.6.6, v5.6.7, v5.6.8, v5.6.9, v5.7.0, v5.7.1, v5.7.10, v5.7.11, v5.7.15, v5.7.2, v5.7.20, v5.7.21, v5.7.22, v5.7.23, v5.7.26, v5.7.27, v5.7.28, v5.7.3, v5.7.4, v5.7.5, v5.7.6, v5.7.7, v5.7.8, v5.7.9, v5.8.0, v5.8.11, v5.8.12, v5.8.14, v5.8.15, v5.8.17, v5.8.18, v5.8.19, v5.8.2, v5.8.20, v5.8.22, v5.8.24, v5.8.27, v5.8.28, v5.8.29, v5.8.3, v5.8.30, v5.8.31, v5.8.32, v5.8.33, v5.8.34, v5.8.35, v5.8.4, v5.8.8, v5.8.9].
    • illuminate/support 5.2.x-dev conflicts with laravel/framework[v6.0.1].
    • illuminate/support 5.3.x-dev conflicts with laravel/framework[v6.0.1].
    • illuminate/support 5.4.x-dev conflicts with laravel/framework[v6.0.1].
    • illuminate/support 5.5.x-dev conflicts with laravel/framework[v6.0.1].
    • illuminate/support v5.2.43 conflicts with laravel/framework[v6.0.1].
    • illuminate/support v5.2.45 conflicts with laravel/framework[v6.0.1].
    • illuminate/support v5.3.0 conflicts with laravel/framework[v6.0.1].
    • illuminate/support v5.3.16 conflicts with laravel/framework[v6.0.1].

using kubeconfig results in empty guzzle client

Hello!

I realized 2 things:
First, there is a typo in src/Client.php on line 202:

$this->cientKey = null;

should be

$this->clientKey = null;

Second, using setOptionsFromKubeconfig or setOptionsFromKubeconfigFile result in an empty guzzleClient because it is initialized in the constructor (with empty options array) before setOptions on line 351 (which is resetting all options, but not re-initializing guzzleClient). This can be prevented by adding $this->guzzleClient = $this->createGuzzleClient(); to the end of setOptionsFromKubeconfig.

Best regards
Josef

README for service account appears to be wrong

Use of a service account in the latest release suggests the following:

use Maclof\Kubernetes\Client;
use Http\Adapter\Guzzle6\Client as Guzzle6Client;
$httpClient = Guzzle6Client::createWithConfig([
	'verify' => '/var/run/secrets/kubernetes.io/serviceaccount/ca.crt',
]);
$client = new Client([
	'master' => 'https://master.mycluster.com',
	'token' => '/var/run/secrets/kubernetes.io/serviceaccount/token',
], null, $httpClient);

However Client constructor is

	public function __construct(array $options = array(), GuzzleClient $guzzleClient = null, RepositoryRegistry $repositoryRegistry = null)

So the example is using Guzzle6Client::createWithConfig to get a Http\Adapter\Guzzle6\Client object.
This implements implements Http\Client\HttpClient, Http\Client\HttpAsyncClient which in tern implements Psr\Http\Client\ClientInterface and Psr\Http\Client\HttpAsyncClient
It is then passing this as the 3rd parameter which is expecting a RepositoryRegistry which definitely looks wrong

It looks like this should instead be the second parameter?
But even that looks a little wrong as the doc suggests \GuzzleHttp\Client but is type hinted to GuzzleHttp\Client\GuzzleClient which implements \GuzzleHttp\ClientInterface

The default behaviour does indeed make a \GuzzleHttp\Client\GuzzleClient via createGuzzleClient, so it seems like this would be right.
The Http\Adapter\Guzzle6\Client seems to make and use a GuzzleClient internally, but this isn't accessible to Maclof\Kubernetes\Client

So should the use of the adapter just be removed, and instead a guzzle client just be passed right in?

illuminate/support version can be 4.x

Wondering if there is a reason illuminate/support is required to be 5.x?

I'm currently using this in production with illuminate/support v4 and haven't run into any issues. I'm not super familiar with composer, but was wondering if it would be possible to change the version requirement for illuminate/support to allow 4.x but install 5.x if it's not already a part of the project.

Problem with writing to files

With pod exec I execute various commands.

['touch', 'cron/daily/100-backup']
['chmod', '775', 'cron/daily/100-backup']

These also work without any problems.

But when I execute the following command, I get bash: echo hi >> /data/cron/daily/100-backup: No such file or directory even though it exists:
['bash', '-c', '"echo hi >> /data/cron/daily/100-backup"']

Can you help me?

How to use the Kubernetes php client library

I am working on some dashboard changes for my final year project but I am stuck. I cloned the dashboard files into my go path directory but I am not familiar with cleint-go. How can I use the php client libraries for dahsboard development. A detailed instruction would be helpful please.

Model with yaml attribute type can not be created since 0.23

I'm currently updating our dependency from 0.22 to 0.24 and there seems to an issue since 0.23: The class src/Models/Model takes (with typehint) array $attributes = [] but expects it to be a string in case of $attributeType === 'yaml'. This creates issues in our code when we instantiate new CronJobs.

Allow change of namespace on runtime

Hey,

the namespace feature works great. But I found another problem, when you work with different namespaces at runtime. For Example I do the following:

// Initialize Client with `default` namespace:
$client = new Client([
	'master' => 'http://master.mycluster.com',
        'namespace' => 'test',
]);

// do something, in my example I create a new namespace
// Next I want to use the newly created namespace.
// Currently not possible :-(

So to resolve this problem I temporarily created a method to change the namespaceSetting in Client.php (you can also use setOptions() but then you must pass all options again):

    /**
     * Set the current namespace
     *
     * @param string $namespace
     */
	public function setNamespace($namespace)
    {
        if (isset($namespace))
        {
            $this->namespace = trim($namespace);
        }
    }

This solution is not perfect. In my opinion, the namespace setting can be set on different positions:

Reading data from api:

  1. Collection call: $pods = $client->pods('NAMESPACE')->find()
  2. Model methods, like setLabelSelector(): $pods = $client->pods()->setNamespace('NAMESPACE')->find()
  3. Direct API-Call: $pods = $client->pods()->find('NAMESAPCE')

Create/Update data:

  1. Same solutions as read
  2. Handle namespace same as kubectl do: simply create a new model with metadata->namespace Attribute and use this to get the correct API-Endpoint

What solution would you suggest? Then I can implement the option.

Allow override of apiVersion

Different models require different apiVersion strings depending on the Kubernetes server version.

eg. CronJob needs batch/v2alpha1 for <=1.9 but batch/v1beta1 for 1.10+

If the library doesn't do this automatically, it should expose some way for the versions to be set by the user.

Call to undefined method Http\Client\Exception\RequestException::getResponse() (/var/www/vendor/maclof/kubernetes-client/src/Client.php:427)

I did upgrade to the latest version of kubernetes client, after that I'm getting this error:

Error: [Error] Call to undefined method Http\Client\Exception\RequestException::getResponse() (/var/www/vendor/maclof/kubernetes-client/src/Client.php:427)
#0 /var/www/vendor/maclof/kubernetes-client/src/Repositories/Repository.php(79): Maclof\Kubernetes\Client->sendRequest('GET', '/deployments', Array, NULL, true, 'apps/v1', Array)
#1 /var/www/vendor/maclof/kubernetes-client/src/Repositories/Repository.php(255): Maclof\Kubernetes\Repositories\Repository->sendRequest('GET', '/deployments', Array, NULL, true)
#2 /var/www/vendor/maclof/kubernetes-client/src/Repositories/Repository.php(265): Maclof\Kubernetes\Repositories\Repository->find()
#3 /var/www/vendor/maclof/kubernetes-client/src/Repositories/Repository.php(305): Maclof\Kubernetes\Repositories\Repository->first()
#4 /var/www/vendor/maclof/kubernetes-client/src/Repositories/Repository.php(146): Maclof\Kubernetes\Repositories\Repository->exists('peoplecounter-5...')

it appears that guzzle giving an exception that it is unable to connect due ssl errors. so it is not possible to call getResponse on that exception.

I've logged the error on the exception there. it says: "cURL error 60: SSL certificate problem: unable to get local issuer certificate".

pod exec not work

code

$k8sClient->setNamespace('dev');
$pods = $k8sClient->pods()->setLabelSelector(['app' => 'dev-router'])->find();

foreach($pods as $pod) {
	$arr = $pod->toArray();
	if($arr['status']['phase'] == 'Running') {
		print_r($k8sClient->pods()->exec($pod, ['cat','/etc/nginx/nginx.conf']));break;
	}
}

return 400 Bad Request with message Upgrade request required

{"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"Upgrade request required","reason":"BadRe (truncated...)

BaseUri doesn't work properly.

If kubernetes master url contains path like http://localhost/kubernetes/ then baseUri doesn't work properly because it calls http://localhost/v1/api/... instead of http://localhost/kubernetes/v1/api/... in Client.php:

public function sendRequest($method, $uri, $query = [], $body = [], $namespace = true, $apiVersion = null)
{
  $baseUri = $apiVersion ? '/apis/' . $apiVersion : '/api/' . $this->apiVersion;

Declaration of PersistentVolumeRepository::sendRequest() must be compatible with Repository::sendRequest()

I found the following error:

PHP Fatal error: Declaration of Maclof\Kubernetes\Repositories\PersistentVolumeRepository::sendRequest($method, $uri, $query = [], $body = [], $namespace = false) must be compatible with Maclof\Kubernetes\Repositories\Repository::sendRequest($method, $uri, $query = [], $body = [], $namespace = true, array $requestOptions = []) in /var/www/html/vendor/maclof/kubernetes-client/src/Repositories/Persistent VolumeRepository.php on line 28

That is, the last argument array $requestOptions = [] is missing in PersistentVolumeRepository::sendRequest()

PersistentVolumeRepository::sendRequest($method, $uri, $query = [], $body = [], $namespace = false)

must be compatible with:

Repository::sendRequest($method, $uri, $query = [], $body = [], $namespace = true, array $requestOptions = [])

Thanks

Immutable Collection operations not working properly

Whenever the \Illuminate\Support\Collection is trying to create a new static(...), for example in the map method, since you've extended the Collection with your own something seems to go wrong.

Here's an example:

<?php

use Maclof\Kubernetes\Client;
use Maclof\Kubernetes\Models\NamespaceModel;

require __DIR__ . '/../vendor/autoload.php';

$client = new Client();
// configure client...

$client
    ->namespaces()
    ->find()
    ->map(fn(NamespaceModel $ns) => $ns->getMetadata('name'));

will result in:

PHP Fatal error:  Uncaught InvalidArgumentException: Attributes are not an array. in /path/to/repo/vendor/maclof/kubernetes-client/src/Models/Model.php:54
Stack trace:
#0 /path/to/repo/vendor/maclof/kubernetes-client/src/Collections/NamespaceCollection.php(30): Maclof\Kubernetes\Models\Model->__construct()
#1 /path/to/repo/vendor/maclof/kubernetes-client/src/Collections/NamespaceCollection.php(14): Maclof\Kubernetes\Collections\NamespaceCollection->getNamespaces()
#2 /path/to/repo/vendor/illuminate/collections/Collection.php(644): Maclof\Kubernetes\Collections\NamespaceCollection->__construct()
#3 /path/to/repo/src/index.php(17): Illuminate\Support\Collection->map()
#4 {main}
  thrown in /path/to/repo/vendor/maclof/kubernetes-client/src/Models/Model.php on line 54

I think the issue is the get<ResourceType> method in the corresponding collections.
A possible solution might be to convert the raw data to models before constructing the collection.

Authenticating to Google Cloud Kubernetes

I struggle with setting up authentication to our GKE cluster. Neither using the credentials provided in the Cloud Console (username/password) nor IAM service account certificates (ca_cert/client_cert/client_key) seem to work, both result in a 403 response saying system: anonymous has been denied access.
Which credentials does your library require, and where do I need to obtain them?

upgrade requests don't work if using kubeconfig file/data

Hi!

I know, this comes a bit late. I found another issue with setOptionsFromKubeconfig. On line 338, the CA certificate is assigned to $options['verify'] which will break upgrade requests. If it is assigned to $options['ca_cert'], upgrade requests work fine.

Please change line 338 from

$options['verify'] = $this->getTempFilePath('ca-cert.pem', base64_decode($cluster['certificate-authority-data'], true));

to

$options['ca_cert'] = $this->getTempFilePath('ca-cert.pem', base64_decode($cluster['certificate-authority-data'], true));

I tested this with kubeconfig files generated with azure-cli (az aks get-credentials).

Best regards
Josef

ServiceCollection with IlluminateCollection bug

IlluminateCollection functions like 'filter' not working on ServiceCollection class:

example:

$services = $client->services()->find()->filter(function($item) {
  return $item->toArray()['spec']['type'] === 'NodePort';
});

in Collection.php:

return new static(...);

in ServiceCollection.php (no items property):

public function __construct(array $data)
{
  parent::__construct($this->getServices(isset($data['items']) ? $data['items'] : []));

The readme doesn't seem to be updated.

Thank you for updating.
When I checked if ingress could work with k8s: 1.23 (ingress api v1), it worked fine.
When I checked the source code (ingress.php), the api was v1.
But when I look at the readme, the ingress is networking.k8s.io/v1beta1.
I would appreciate it if you could update the remad me.

PHP 8.1 Compatibility

Description:

Currently when using this library with PHP 8.1 the following type error occures:

NOTICE: PHP message: PHP Fatal error: During inheritance of ArrayAccess: Uncaught ErrorException: Return type of Maclof\Kubernetes\RepositoryRegistry::offsetExists($method) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/www/backend/vendor/maclof/kubernetes-client/src/RepositoryRegistry.php:54

Possible solutions:

  • drop support for PHP up to version 7.3 (end of life by now) and use native return types which are available since PHP 7.4 (favorite ^^)
  • provide PHP attribute ReturnTypeWillChange

Pod exec issue

This command don't work

$exec = $client->pods()->exec($pods[$i], [
                        'command' => ['updateneos </dev/null &>/dev/null &'],
                        'stdout'  => true,
                        'stderr'  => true,
                    ]);

this works fine, but the command should be executed in the background an I need </dev/null &>/dev/null &

$exec = $client->pods()->exec($pods[$i], [
                        'command' => ['updateneos'],
                        'stdout'  => true,
                        'stderr'  => true,
                    ]);

How can I do that?

兼容问题

Declaration of Maclof\Kubernetes\Repositories\PersistentVolumeRepository::sendRequest($method, $uri, $query = Array, $body = Array, $namespace = false) should be compatible with Maclof\Kubernetes\Repositories\Repository::sendRequest($method, $uri, $query = Array, $body = Array, $namespace = true, array $requestOptions = Array)

/vendor/maclof/kubernetes-client/src/Repositories/PersistentVolumeRepository.php

Drop support for Guzzle 5

Let me know your thoughts on this one, I personally don't use Guzzle 5 anymore and it's a bit of a pain keeping backwards support.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.