initial
This commit is contained in:
commit
ccf654ce8a
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace podmanImageManager;
|
||||||
|
|
||||||
|
use \objectStructs\objectStructs;
|
||||||
|
|
||||||
|
class image extends objectStructs
|
||||||
|
{
|
||||||
|
/** @var imageAnnotations */
|
||||||
|
public $annotations;
|
||||||
|
/** @var imageConfig */
|
||||||
|
public $config;
|
||||||
|
/** @var string name of image */
|
||||||
|
public $image;
|
||||||
|
|
||||||
|
public function __construct($vars)
|
||||||
|
{
|
||||||
|
$this->imageName = (isset($vars['image']) ? $vars['image'] :
|
||||||
|
(isset($vars['name']) ? $vars['name'] :
|
||||||
|
(iiset($vars['imageName'] ? $vars['imageName'] : "" ) ) ) ) ;
|
||||||
|
if (isset( $vars['imageBasic']->annotations) )
|
||||||
|
$annotations = $vars['imageBasic']->annotations;
|
||||||
|
elseif (isset($vars['annotations']))
|
||||||
|
$annotations = $vars['annotations'];
|
||||||
|
|
||||||
|
$this->annotations = new imageAnnotations($annotations);
|
||||||
|
if (isset($vars['imageConfig']))
|
||||||
|
$this->config = new imageConfig($vars['imageConfig']);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace podmanImageManager;
|
||||||
|
|
||||||
|
|
||||||
|
use objectStructs\objectStructs;
|
||||||
|
|
||||||
|
class imageAnnotations extends objectStructs
|
||||||
|
{
|
||||||
|
/** @var string */
|
||||||
|
public $purpose;
|
||||||
|
/** @var string */
|
||||||
|
public $hostController;
|
||||||
|
/** @var string */
|
||||||
|
public $clientController;
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace podmanImageManager;
|
||||||
|
|
||||||
|
|
||||||
|
use objectStructs\objectStructs;
|
||||||
|
|
||||||
|
class imageConfig extends objectStructs
|
||||||
|
{
|
||||||
|
/** @var string */
|
||||||
|
public $created;
|
||||||
|
/** @var string */
|
||||||
|
public $author;
|
||||||
|
/** @var string */
|
||||||
|
public $architecture;
|
||||||
|
/** @var string */
|
||||||
|
public $os;
|
||||||
|
/** @var imageConfigConfig */
|
||||||
|
public $config;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* created] => 2020-04-23T00:50:14.871449584Z
|
||||||
|
[author] => Cooini, LLC
|
||||||
|
[architecture] => amd64
|
||||||
|
[os] => linux
|
||||||
|
|
||||||
|
|
||||||
|
[rootfs] => stdClass Object
|
||||||
|
(
|
||||||
|
[type] => layers
|
||||||
|
[diff_ids] => Array
|
||||||
|
(
|
||||||
|
[0] => sha256:7402c41ceaacfdd10fcdc3c64e67ed61797dadad8adaf081e9e9bea71e0eafc2
|
||||||
|
)
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
[history] => Array
|
||||||
|
(
|
||||||
|
[0] => stdClass Object
|
||||||
|
(
|
||||||
|
[created] => 2020-04-23T00:50:14.871449584Z
|
||||||
|
[created_by] => /bin/sh
|
||||||
|
[author] => Cooini, LLC
|
||||||
|
)
|
||||||
|
|
||||||
|
)
|
||||||
|
*/
|
|
@ -0,0 +1,63 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace podmanImageManager;
|
||||||
|
|
||||||
|
|
||||||
|
use objectStructs\objectStructs;
|
||||||
|
|
||||||
|
class imageConfigConfig extends objectStructs
|
||||||
|
{
|
||||||
|
/** @var \stdClass */
|
||||||
|
public $ExposedPorts;
|
||||||
|
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* [config] => stdClass Object
|
||||||
|
(
|
||||||
|
[ExposedPorts] => stdClass Object
|
||||||
|
(
|
||||||
|
[443/tcp] => stdClass Object
|
||||||
|
(
|
||||||
|
)
|
||||||
|
|
||||||
|
[80/tcp] => stdClass Object
|
||||||
|
(
|
||||||
|
)
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
[Env] => Array
|
||||||
|
(
|
||||||
|
[0] => domain=example.com
|
||||||
|
[1] => domainAliases=example.com-iniapp.generic.host
|
||||||
|
)
|
||||||
|
|
||||||
|
[Entrypoint] => Array
|
||||||
|
(
|
||||||
|
[0] => /bin/sh
|
||||||
|
[1] => -c
|
||||||
|
[2] => /usr/local/hosting/container/start.sh
|
||||||
|
)
|
||||||
|
|
||||||
|
[Cmd] => Array
|
||||||
|
(
|
||||||
|
[0] => /usr/local/hosting/container/start.sh
|
||||||
|
)
|
||||||
|
|
||||||
|
[Volumes] => stdClass Object
|
||||||
|
(
|
||||||
|
[/var/www/vhosts/example.com] => stdClass Object
|
||||||
|
(
|
||||||
|
)
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
[Labels] => stdClass Object
|
||||||
|
(
|
||||||
|
[io.buildah.version] => 1.11.6
|
||||||
|
)
|
||||||
|
|
||||||
|
)
|
||||||
|
*/
|
|
@ -0,0 +1,230 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace podmanImageManager;
|
||||||
|
|
||||||
|
|
||||||
|
interface podmanImageManagerInterface
|
||||||
|
{
|
||||||
|
public function getImages( string $repo );
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @version 0.1
|
||||||
|
*/
|
||||||
|
class podmanImageManager implements podmanImageManagerInterface
|
||||||
|
{
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function doRequest($URL, $PostFields=null, $Headers=array(), $json=false )
|
||||||
|
{
|
||||||
|
// This gets or posts to a page via curl and returns the body and headers via array.
|
||||||
|
|
||||||
|
$curl = curl_init(); // Init curl
|
||||||
|
if (!empty($PostFields))
|
||||||
|
{
|
||||||
|
// Post string is NOT empty, so clets do post
|
||||||
|
curl_setopt($curl, CURLOPT_POST, 1); // Set post field count
|
||||||
|
curl_setopt($curl, CURLOPT_POSTFIELDS, ($json ? json_encode($PostFields) : $PostFields)) ; // Set post fields
|
||||||
|
}
|
||||||
|
//####### SET SETTINGS #########
|
||||||
|
|
||||||
|
curl_setopt( $curl, CURLOPT_HTTPHEADER,
|
||||||
|
$Headers
|
||||||
|
);
|
||||||
|
curl_setopt($curl, CURLOPT_URL, $URL);
|
||||||
|
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); // This returns the page to us at curl_exec
|
||||||
|
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
|
||||||
|
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
|
||||||
|
curl_setopt($curl, CURLOPT_HEADER, true); // Get Headers -- used for any redirects
|
||||||
|
|
||||||
|
curl_setopt($curl, CURLOPT_USERAGENT, "iniApp-client 0.1"); // Spoof the user-agent to be the browser that the user is on (and accessing the php script)
|
||||||
|
curl_setopt($curl, CURLOPT_FRESH_CONNECT, true);
|
||||||
|
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 250);
|
||||||
|
/*#############################
|
||||||
|
GET PAGE
|
||||||
|
##############################*/
|
||||||
|
|
||||||
|
$result = curl_exec($curl); // Get page
|
||||||
|
if ($result == false)
|
||||||
|
{
|
||||||
|
throw new \Exception("Error at image registry API: ".curl_errno($curl). " : " .curl_error($curl));
|
||||||
|
} // if curl was good.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
list($Headers, $TheBody) = explode("\r\n\r\n", $result, 2); // Separate headers and Body
|
||||||
|
|
||||||
|
$http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE); // Get HTTP code
|
||||||
|
curl_close($curl); // Close connection
|
||||||
|
|
||||||
|
if ($http_code == 200)
|
||||||
|
{
|
||||||
|
$Response = ($json ? json_decode($TheBody) : $TheBody);
|
||||||
|
if ($Response)
|
||||||
|
{
|
||||||
|
return $Response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw new \Exception(__FUNCTION__." HTTP Error at request:".$http_code . "<br><br>$TheBody");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $ImageName image name including repo address
|
||||||
|
*/
|
||||||
|
public function getImage(string $ImageNameComplete, $imageTag='latest')
|
||||||
|
{
|
||||||
|
$RepoURL = "https://".$ImageNameComplete;
|
||||||
|
if (preg_match("/\b(?:(?:https?|ftp):\/\/|www\.)[-a-z0-9+&@#\/%?=~_|!:,.;]*[-a-z0-9+&@#\/%=~_|]/", $RepoURL) ) {
|
||||||
|
//Good URL, now lets work it
|
||||||
|
$URLbits = parse_url($RepoURL);
|
||||||
|
if ($URLbits)
|
||||||
|
{
|
||||||
|
$imageName = ltrim($URLbits['path'], "/");
|
||||||
|
$registry = $URLbits['host'] .":".$URLbits['port'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$tagsURL = "https://".$registry. "/v2/".$imageName."/tags/list";
|
||||||
|
try {
|
||||||
|
$TagsRaw = $this->doRequest($tagsURL, null, null, true);
|
||||||
|
}
|
||||||
|
catch (\Exception $e)
|
||||||
|
{
|
||||||
|
throw new \Exception("Exception getting tags:".$e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($TagsRaw and isset($TagsRaw->tags))
|
||||||
|
{
|
||||||
|
//echo "<br> tags<br><pre>".print_r($TagsRaw,true)."</pre>";
|
||||||
|
|
||||||
|
$ImagesReturn = array();
|
||||||
|
foreach($TagsRaw->tags as $tag)
|
||||||
|
{
|
||||||
|
$ImageManifestURL = "https://".$registry."/v2/".$imageName."/manifests/".$tag;
|
||||||
|
// echo $ImageManifestURL;
|
||||||
|
try {
|
||||||
|
$ImageRaw = $this->doRequest($ImageManifestURL, null, array('Accept: application/vnd.oci.image.manifest.v1+json'),true);
|
||||||
|
// echo "<br> image maniest<br><pre>".print_r($ImageRaw,true)."</pre>";
|
||||||
|
}
|
||||||
|
catch (\Exception $e)
|
||||||
|
{
|
||||||
|
throw new \Exception("Exception getting image manifest:".$e->getMessage());
|
||||||
|
}
|
||||||
|
if (isset($ImageRaw->config->digest))
|
||||||
|
{
|
||||||
|
$ImageConfigURL = "https://".$registry."/v2/".$imageName."/blobs/".$ImageRaw->config->digest;
|
||||||
|
// echo $ImageConfigURL;
|
||||||
|
$ImageConfigRaw = $this->doRequest($ImageConfigURL, null, null,true );
|
||||||
|
//echo "<br> image config<br><pre>".print_r($ImageConfigRaw,true)."</pre>";
|
||||||
|
|
||||||
|
try {
|
||||||
|
$Image = new image( array('name'=>$ImageNameComplete, 'imageBasic'=>$ImageRaw, 'imageConfig'=>$ImageConfigRaw));
|
||||||
|
if ($Image)
|
||||||
|
{
|
||||||
|
if ($imageTag === $tag )
|
||||||
|
return $Image;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw new \Exception("Image object failed to create while fetching");
|
||||||
|
}
|
||||||
|
catch (\Exception $e)
|
||||||
|
{
|
||||||
|
throw new \Exception("Exception creating image object:".$e->getMessage());
|
||||||
|
}
|
||||||
|
//echo "<br> image <br><pre>".print_r($Image,true)."</pre>";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw new \Exception("Could not find image config digest");
|
||||||
|
} // tags loop
|
||||||
|
} // if tags exist
|
||||||
|
else
|
||||||
|
throw new \Exception("Could not get tags for image");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $repo
|
||||||
|
* @return image[]
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public function getImages(string $repo )
|
||||||
|
{
|
||||||
|
//podman.registry.generic.host:5000/httpdphp7
|
||||||
|
$cache = $this->getCache($repo);
|
||||||
|
if ($cache)
|
||||||
|
{
|
||||||
|
return $cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not cached, continue ;
|
||||||
|
|
||||||
|
$ImagesReturn = array();
|
||||||
|
$URL = 'https://'.$repo.'/v2/_catalog';
|
||||||
|
if (preg_match("/\b(?:(?:https?|ftp):\/\/|www\.)[-a-z0-9+&@#\/%?=~_|!:,.;]*[-a-z0-9+&@#\/%=~_|]/", $URL) )
|
||||||
|
{
|
||||||
|
$Images = $this->doRequest( $URL, null, null, true );
|
||||||
|
if (isset($Images->repositories) )
|
||||||
|
{
|
||||||
|
foreach($Images->repositories as $imageName)
|
||||||
|
{
|
||||||
|
$Image = $this->getImage($repo ."/". $imageName);
|
||||||
|
if ($Image)
|
||||||
|
$ImagesReturn[$imageName] = $Image;
|
||||||
|
|
||||||
|
} //Images loop
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw new \Exception("Images not valid");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new \Exception("Repo not valid");
|
||||||
|
}
|
||||||
|
|
||||||
|
$cache = $this->setCache($repo, $ImagesReturn);
|
||||||
|
return $ImagesReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getCache($name)
|
||||||
|
{
|
||||||
|
$CacheDIr = __DIR__ . "/cache";
|
||||||
|
$name = str_replace(array('.',":"),'-',$name);
|
||||||
|
if (file_exists( $CacheDIr . "/".$name ) and is_readable($CacheDIr . "/".$name))
|
||||||
|
{
|
||||||
|
if ( (mktime() - filectime($CacheDIr . "/".$name) <= 60) )
|
||||||
|
{
|
||||||
|
$data = file_get_contents($CacheDIr . "/".$name);
|
||||||
|
return unserialize( $data );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function setCache($name, $Object)
|
||||||
|
{
|
||||||
|
$CacheDIr = __DIR__ . "/cache";
|
||||||
|
if (! file_exists($CacheDIr))
|
||||||
|
mkdir($CacheDIr);
|
||||||
|
if (file_exists($CacheDIr))
|
||||||
|
{
|
||||||
|
$name = str_replace(array('.',":"),'-',$name);
|
||||||
|
return file_put_contents( $CacheDIr . "/".$name, serialize( $Object ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw new \Exception("Image cache directory does not exist and could not create");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue