-
Notifications
You must be signed in to change notification settings - Fork 33
Expand file tree
/
Copy pathDockerContainerClient.php
More file actions
135 lines (116 loc) · 4.33 KB
/
Copy pathDockerContainerClient.php
File metadata and controls
135 lines (116 loc) · 4.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
<?php
declare(strict_types=1);
namespace Testcontainers\ContainerClient;
use Composer\InstalledVersions;
use Docker\Docker as DockerClient;
use Docker\DockerClientFactory;
use Http\Client\Common\Plugin\HeaderDefaultsPlugin;
use Http\Client\Common\PluginClient;
use Psr\Http\Client\ClientInterface;
class DockerContainerClient
{
/**
* @var DockerClient|null Singleton instance of DockerClient
*/
private static ?DockerClient $dockerClient = null;
/**
* @var (callable(): ClientInterface)|null Factory for the base HTTP client.
* When null, DockerClientFactory::createFromEnv() is used.
*/
private static $httpClientFactory = null;
/**
* @var (callable(ClientInterface): DockerClient)|null Factory for the Docker client.
* When null, DockerClient::create() is used.
*/
private static $dockerClientFactory = null;
private function __construct()
{
}
/**
* Returns the singleton DockerClient instance.
*
* @return DockerClient The singleton DockerClient instance.
* @throws \RuntimeException If the DockerClient instance could not be created.
*/
public static function getDockerClient(): DockerClient
{
if (self::$dockerClient === null) {
$version = static::resolveVersion();
$baseHttpClient = self::createHttpClient();
$httpClient = new PluginClient(
$baseHttpClient,
[new HeaderDefaultsPlugin(['User-Agent' => 'tc-php/' . $version])]
);
self::$dockerClient = self::createDockerClient($httpClient);
}
return self::$dockerClient;
}
/**
* Resolves the package version string used in the User-Agent header.
*
* Returns the pretty version of the installed package, with the
* '+no-version-set' build-metadata suffix stripped. Falls back to
* 'unknown' if the package is not found in the Composer runtime data.
*
* @param string $package Composer package name to resolve; override in tests
* to exercise the OutOfBoundsException fallback path.
*/
protected static function resolveVersion(string $package = 'testcontainers/testcontainers'): string
{
try {
$version = InstalledVersions::getPrettyVersion($package) ?? 'unknown';
} catch (\OutOfBoundsException) {
$version = 'unknown';
}
return str_replace('+no-version-set', '', $version);
}
/**
* Returns the base HTTP client, using the injected factory if set.
*/
private static function createHttpClient(): ClientInterface
{
return self::$httpClientFactory !== null
? (self::$httpClientFactory)()
: DockerClientFactory::createFromEnv();
}
/**
* Builds the DockerClient from the given HTTP client, using the injected factory if set.
*/
private static function createDockerClient(ClientInterface $httpClient): DockerClient
{
return self::$dockerClientFactory !== null
? (self::$dockerClientFactory)($httpClient)
: DockerClient::create($httpClient);
}
/**
* Injects a DockerClient instance for testing or special use cases.
* Note: clients injected via this method will not have the tc-php User-Agent header applied automatically.
*
* @param DockerClient $client The DockerClient instance to set.
*/
public static function setDockerClient(DockerClient $client): void
{
self::$dockerClient = $client;
}
/**
* Resets the injectable factories to their defaults.
* For use in tests only — do not call in production code.
*
* @param (callable(): ClientInterface)|null $httpClientFactory
* @param (callable(ClientInterface): DockerClient)|null $dockerClientFactory
*/
public static function setFactories(?callable $httpClientFactory, ?callable $dockerClientFactory): void
{
self::$httpClientFactory = $httpClientFactory;
self::$dockerClientFactory = $dockerClientFactory;
}
/**
* Resets the injectable factories to their defaults (both null).
* For use in tests only — do not call in production code.
*/
public static function resetFactories(): void
{
self::$httpClientFactory = null;
self::$dockerClientFactory = null;
}
}