Created
February 1, 2017 10:43
-
-
Save ebuildy/9770009c39932990ff4013dac42ee923 to your computer and use it in GitHub Desktop.
Retrieve Gitlab projects with Docker container registry tags.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace AppBundle\Service; | |
class ContainerImageRepository | |
{ | |
/** | |
* URL to container registry. | |
* | |
* @var string | |
*/ | |
private $registryUrl; | |
/** | |
* URL to gitlab. | |
* | |
* @var string | |
*/ | |
private $gitlabUrl; | |
/** | |
* Hash of gitlab auth. | |
* | |
* @var string | |
*/ | |
private $gitlabAuthHash; | |
/** | |
* Private access token to gitlab. | |
* | |
* @var string | |
*/ | |
private $gitlabAccessToken; | |
/** | |
* @var null|\Psr\Log\LoggerInterface | |
*/ | |
private $logger = null; | |
public function __construct($registryUrl, $gitlabUrl, $gitlabAccessToken, $gitlabAuthHash) | |
{ | |
$this->registryUrl = $registryUrl; | |
$this->gitlabUrl = $gitlabUrl; | |
$this->gitlabAccessToken = $gitlabAccessToken; | |
$this->gitlabAuthHash = $gitlabAuthHash; | |
} | |
/** | |
* Set optional logger | |
* | |
* @param $logger | |
*/ | |
public function setLogger($logger) | |
{ | |
$this->logger = $logger; | |
} | |
/** | |
* Retrieve Gitlab project with container registry details. | |
* | |
* @return array | |
*/ | |
public function find() | |
{ | |
$repositories = []; | |
$projects = $this->getProjects(); | |
foreach($projects as $project) | |
{ | |
$repositories []= $project->path_with_namespace; | |
} | |
$authorizations = $this->getAuthorizations($repositories); | |
$repositoriesDetails = $this->getRegistryTags($repositories, $authorizations); | |
$results = []; | |
foreach($projects as $project) | |
{ | |
if ($project->container_registry_enabled === true && | |
isset($repositoriesDetails[$project->path_with_namespace])) | |
{ | |
$results[] = [ | |
'project' => $project, | |
'container_registry_tags' => $repositoriesDetails[$project->path_with_namespace] | |
]; | |
} | |
} | |
return $results; | |
} | |
/** | |
* Retrieve Gitlab projects. | |
* | |
* @return array | |
*/ | |
private function getProjects() | |
{ | |
$client = new \GuzzleHttp\Client(); | |
$httpQueries = []; | |
for($page = 1; $page < 5; $page++) | |
{ | |
$url = sprintf('%s/api/v3/projects/visible?%s', $this->gitlabUrl, http_build_query([ | |
'page' => $page, | |
'per_page' => '20' | |
])); | |
$httpQueries[$page] = new \GuzzleHttp\Psr7\Request('GET', $url, [ | |
'User-agent' => 'testy/1.0', | |
'Accept-Encoding' => 'gzip, deflate, sdch', | |
'Cache-Control' => 'max-age=0', | |
'PRIVATE-TOKEN' => $this->gitlabAccessToken | |
]); | |
} | |
$responses = \GuzzleHttp\Pool::batch($client, $httpQueries, ['concurrency' => 10]); | |
$projects = []; | |
foreach($responses as $repository => $response) | |
{ | |
if ($response instanceof \GuzzleHttp\Exception\ClientException) | |
{ | |
$this->log(\Psr\Log\LogLevel::ERROR, $response->getMessage()); | |
} | |
elseif ($response->getStatusCode() === 200) | |
{ | |
$buffer = \GuzzleHttp\json_decode((string) $response->getBody()); | |
if (!empty($buffer)) | |
{ | |
foreach($buffer as $project) | |
{ | |
if ($project->container_registry_enabled === true) | |
{ | |
$projects[] = $project; | |
} | |
} | |
} | |
} | |
} | |
return $projects; | |
} | |
/** | |
* Retrieve auth. token for each repository. | |
* | |
* @param $repositories | |
* @return array | |
*/ | |
private function getAuthorizations($repositories) | |
{ | |
$client = new \GuzzleHttp\Client(); | |
$httpQueries = []; | |
foreach($repositories as $repository) | |
{ | |
$url = sprintf('%s/jwt/auth?%s', $this->gitlabUrl, http_build_query([ | |
'client_id' => 'docker', | |
'service' => 'container_registry', | |
'offline_token' => 'true', | |
'scope' => sprintf('repository:%s:pull', $repository) | |
])); | |
$httpQueries[$repository] = new \GuzzleHttp\Psr7\Request('GET', $url, [ | |
'User-agent' => 'testy/1.0', | |
'Accept-Encoding' => 'gzip, deflate, sdch', | |
'Cache-Control' => 'max-age=0', | |
'Authorization' => sprintf('Basic %s', $this->gitlabAuthHash) | |
]); | |
} | |
$responses = \GuzzleHttp\Pool::batch($client, $httpQueries, ['concurrency' => 10]); | |
$auths = []; | |
foreach($responses as $repository => $response) | |
{ | |
if ($response instanceof \GuzzleHttp\Exception\ClientException) | |
{ | |
$this->log(\Psr\Log\LogLevel::ERROR, $response->getMessage()); | |
} | |
elseif ($response->getStatusCode() === 200) | |
{ | |
try { | |
$buffer = \GuzzleHttp\json_decode((string)$response->getBody()); | |
if (!empty($buffer) && isset($buffer->token)) { | |
$auths[$repository] = $buffer->token; | |
} | |
} | |
catch(\Exception $e) { | |
continue; | |
} | |
} | |
} | |
return $auths; | |
} | |
/** | |
* Retrieve container registry tags for each repository. | |
* | |
* @param $repositories | |
* @param $authorizations | |
* @return array | |
*/ | |
private function getRegistryTags($repositories, $authorizations) | |
{ | |
$client = new \GuzzleHttp\Client(); | |
$httpQueries = []; | |
foreach($repositories as $repository) | |
{ | |
if (isset($authorizations[$repository])) | |
{ | |
$url = sprintf('%s/v2/%s/tags/list', $this->registryUrl, $repository); | |
$httpQueries[$repository] = new \GuzzleHttp\Psr7\Request('GET', $url, [ | |
'User-agent' => 'testy/1.0', | |
'Accept-Encoding' => 'gzip, deflate, sdch', | |
'Cache-Control' => 'max-age=0', | |
'Authorization' => sprintf('Bearer %s', $authorizations[$repository]) | |
]); | |
} | |
} | |
$responses = \GuzzleHttp\Pool::batch($client, $httpQueries, ['concurrency' => 10]); | |
$results = []; | |
foreach($responses as $repository => $response) | |
{ | |
if ($response instanceof \GuzzleHttp\Exception\ClientException) | |
{ | |
$this->log(\Psr\Log\LogLevel::ERROR, $response->getMessage()); | |
} | |
elseif ($response->getStatusCode() === 200) | |
{ | |
$buffer = \GuzzleHttp\json_decode((string) $response->getBody()); | |
if (!empty($buffer) && isset($buffer->tags)) { | |
$results[$repository] = $buffer->tags; | |
} | |
} | |
} | |
return $results; | |
} | |
/** | |
* Decorate logger. | |
* | |
* @param $level | |
* @param $message | |
* @param array $context | |
*/ | |
private function log($level, $message, $context = []) | |
{ | |
if (!empty($this->logger)) | |
{ | |
$this->logger->log($level, $message, $context); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment