Skip to content

PHP8, Guzzle 7 and new Endpoints #21

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,13 @@ client.key
.c9
.env
.directory

# IDE & System
.DS_Store
/.idea
/.vscode
.phpstorm.meta.php
.phpunit.result.cache
Thumbs.db
/*.iml

9 changes: 5 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
language: php
sudo: false
php:
- 5.5
- 5.6
- 7.0
- 7.3
- 7.4
- 8.0
- 8.1
cache:
directories:
- $HOME/.composer/cache
Expand All @@ -12,4 +13,4 @@ before_install:
install:
- travis_retry composer update --no-interaction --prefer-source
script:
- composer test
- composer test
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,19 @@ Via Composer
$ composer require dhope0000/lxd
```

For usage of this library any httpclient library is needed. If you don't already use one in your project, please install one in advance.

``` bash
$ composer require php-http/guzzle7-adapter
```

## Install for usage with Guzzle 6

``` bash
$ composer require php-http/guzzle6-adapter
$ composer require dhope0000/lxd "^0.24"
```

## Usage

See the [`docs`](./docs) for more information.
Expand Down
10 changes: 5 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,18 @@
}
],
"require": {
"php": "~5.5|~7.0",
"php": "^7.3 || ^8.0",
"psr/http-message": "^1.0",
"php-http/httplug": "^1.0",
"php-http/discovery": "^1.0",
"php-http/httplug": "^2.2",
"php-http/discovery": "^1.12",
"php-http/client-implementation": "^1.0",
"php-http/client-common": "^1.1",
"php-http/client-common": "^2.3",
"php-http/cache-plugin": "^1.6"
},
"require-dev": {
"phpunit/phpunit": "4.*",
"mockery/mockery": "^0.9.5",
"php-http/guzzle6-adapter": "^1.0",
"php-http/guzzle7-adapter": "^1.0",
"guzzlehttp/psr7": "^1.2",
"php-http/mock-client": "^0.3",
"squizlabs/php_codesniffer": "^2.6"
Expand Down
33 changes: 18 additions & 15 deletions src/Endpoint/InstaceBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -573,7 +573,7 @@ public function remove($name, $wait = false)
* @param bool $record Whether to store stdout and stderr
* @param array $environment An associative array, the key will be the environment variable name
* @param bool $wait Wait for operation to finish
* @return object
* @return array|string
*/
public function execute($name, $command, $record = false, array $environment = [], $wait = false)
{
Expand Down Expand Up @@ -601,21 +601,24 @@ public function execute($name, $command, $record = false, array $environment = [
$response = $this->post($this->getEndpoint().$name.'/exec', $opts, $config);

if ($wait) {
$response = $this->client->operations->wait($response['id']);
$logs = [];
$output = $response['metadata']['output'];
$return = $response['metadata']['return'];
unset($response);

foreach ($output as $log) {
$response['output'][] = str_replace(
'/'.$this->client->getApiVersion().$this->getEndpoint().$name.'/logs/',
'',
$log
);
$waitResponse = $this->client->operations->wait($response['id']);

if ($record === true) {
$output = isset($waitResponse['metadata']['output']) ? $waitResponse['metadata']['output'] : [];
$return = $waitResponse['metadata']['return'];
unset($waitResponse);
$response = [];

foreach ($output as $log) {
$response['output'][] = str_replace(
'/' . $this->client->getApiVersion() . $this->getEndpoint() . $name . '/logs/',
'',
$log
);
}

$response['return'] = $return;
}

$response['return'] = $return;
}

return $response;
Expand Down
18 changes: 18 additions & 0 deletions src/Endpoint/Instance/Logs.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
namespace Opensaucesystems\Lxd\Endpoint\Instance;

use Opensaucesystems\Lxd\Endpoint\AbstractEndpoint;
use Opensaucesystems\Lxd\Exception\InvalidEndpointException;
use Opensaucesystems\Lxd\Helpers\Str;

class Logs extends AbstractEndpoint
{
Expand Down Expand Up @@ -62,4 +64,20 @@ public function remove($name, $log)
{
return $this->delete($this->getEndpoint().$name.'/logs/'.$log);
}

public function __get($endpoint)
{
$className = basename(str_replace('\\', '/', get_class($this)));
$class = __NAMESPACE__.'\\'.$className.'\\'.Str::studly($endpoint);

if (class_exists($class)) {
$class = new $class($this->client);
$class->setEndpoint($this->getEndpoint());
return $class;
} else {
throw new InvalidEndpointException(
'Endpoint '.$class.', not implemented.'
);
}
}
}
65 changes: 65 additions & 0 deletions src/Endpoint/Instance/Logs/ExecOutput.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

namespace Opensaucesystems\Lxd\Endpoint\Instance\Logs;

use Opensaucesystems\Lxd\Endpoint\AbstractEndpoint;

class ExecOutput extends AbstractEndpoint
{
private $endpoint;

protected function getEndpoint()
{
return $this->endpoint;
}

public function setEndpoint(string $endpoint)
{
$this->endpoint = $endpoint;
}

/**
* List of exec record-output logs for a container
*
* @param string $name Name of container
* @return array
*/
public function all($name)
{
$logs = [];

foreach ($this->get($this->getEndpoint().$name.'/logs/exec-output/') as $log) {
$logs[] = str_replace(
'/'.$this->client->getApiVersion().$this->getEndpoint().$name.'/logs/exec-output/',
'',
$log
);
}

return $logs;
}

/**
* Get the contents of a particular exec record-output log file
*
* @param string $name Name of container
* @param string $log Name of log
* @return object
*/
public function read($name, $log)
{
return $this->get($this->getEndpoint().$name.'/logs/exec-output/'.$log);
}

/**
* Remove a particular exec record-output log file
*
* @param string $name Name of container
* @param string $log Name of log
* @return object
*/
public function remove($name, $log)
{
return $this->delete($this->getEndpoint().$name.'/logs/exec-output/'.$log);
}
}
38 changes: 38 additions & 0 deletions src/Helpers/Str.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

namespace Opensaucesystems\Lxd\Helpers;

/**
* Inspired by Laravel
* https://github.com/illuminate/support/blob/master/Str.php
*/
class Str
{
/**
* The cache of studly-cased words.
*
* @var array
*/
protected static $studlyCache = [];

/**
* Convert a value to studly caps case.
*
* @param string $value
* @return string
*/
public static function studly($value)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed? PSR says we shouldn't have class names with "-" or "_" so it seems like an un-needed code path?

Copy link
Author

@renky renky Aug 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Class name is ...\Logs\ExecOutput - but to use it in the code you need to do something like that:
$client->containers->logs->exec_output->read
and I don't want to do ...->execOutput->read - thats looking aweful :) so it needs a possibility to come from exec_output to ExecOutput... studly is the best option for it...

finally id also like to add a Trait that contains the __get method - so it can be used everywhere - but for now it would be a to big refactoring...

{
$key = $value;

if (isset(static::$studlyCache[$key])) {
return static::$studlyCache[$key];
}

$words = explode(' ', str_replace(['-', '_'], ' ', $value));

$studlyWords = array_map(function ($word) { return ucfirst($word); }, $words);

return static::$studlyCache[$key] = implode($studlyWords);
}
}
3 changes: 2 additions & 1 deletion src/HttpClient/Plugin/LxdExceptionThower.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Opensaucesystems\Lxd\HttpClient\Plugin;

use Http\Client\Common\Plugin;
use Http\Promise\Promise;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Http\Client\Exception\HttpException;
Expand All @@ -21,7 +22,7 @@ class LxdExceptionThower implements Plugin
/**
* {@inheritdoc}
*/
public function handleRequest(RequestInterface $request, callable $next, callable $first)
public function handleRequest(RequestInterface $request, callable $next, callable $first): Promise
{
$promise = $next($request);

Expand Down
3 changes: 2 additions & 1 deletion src/HttpClient/Plugin/PathPrepend.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Opensaucesystems\Lxd\HttpClient\Plugin;

use Http\Client\Common\Plugin;
use Http\Promise\Promise;
use Psr\Http\Message\RequestInterface;

/**
Expand All @@ -25,7 +26,7 @@ public function __construct($path)
/**
* {@inheritdoc}
*/
public function handleRequest(RequestInterface $request, callable $next, callable $first)
public function handleRequest(RequestInterface $request, callable $next, callable $first): Promise
{
$currentPath = $request->getUri()->getPath();
$uri = $request->getUri()->withPath($this->path.$currentPath);
Expand Down
3 changes: 2 additions & 1 deletion src/HttpClient/Plugin/PathTrimEnd.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
namespace Opensaucesystems\Lxd\HttpClient\Plugin;

use Http\Client\Common\Plugin;
use Http\Promise\Promise;
use Psr\Http\Message\RequestInterface;

/**
Expand All @@ -23,7 +24,7 @@ public function __construct($trim = '/')
/**
* {@inheritdoc}
*/
public function handleRequest(RequestInterface $request, callable $next, callable $first)
public function handleRequest(RequestInterface $request, callable $next, callable $first): Promise
{
$trimPath = rtrim($request->getUri()->getPath(), $this->trim);
$uri = $request->getUri()->withPath($trimPath);
Expand Down
12 changes: 5 additions & 7 deletions tests/ClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@

use Mockery;
use Opensaucesystems\Lxd\Client;
use PHPUnit\Framework\TestCase;

class ClientTest extends \PHPUnit_Framework_TestCase
class ClientTest extends TestCase
{
protected function tearDown()
protected function tearDown(): void
{
Mockery::close();
}
Expand Down Expand Up @@ -66,17 +67,14 @@ public function testSetUrl()
$this->assertEquals($url, $client->getUrl());
}

/**
* Test that endpoint doesn't exist
*
* @expectedException \Opensaucesystems\Lxd\Exception\InvalidEndpointException
*/
public function testInvalidEndpointException()
{
$httpClient = Mockery::mock('\Http\Client\HttpClient');

$client = new Client($httpClient);

$this->expectException(\Opensaucesystems\Lxd\Exception\InvalidEndpointException::class);

$client->nonEndpoint;
}
}
Loading