Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: 41f804c813
Fetching contributors…

Cannot retrieve contributors at this time

457 lines (417 sloc) 13.965 kb
<?php
/**
* LICENSE: Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* PHP version 5
*
* @category Microsoft
* @package WindowsAzure
* @author Azure PHP SDK <azurephpsdk@microsoft.com>
* @copyright 2012 Microsoft Corporation
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link http://pear.php.net/package/azure-sdk-for-php
*/
namespace WindowsAzure;
require_once '../WindowsAzure/WindowsAzure.php';
require_once '../defaults.php';
use WindowsAzure\Common\Internal\Utilities;
use WindowsAzure\Common\Internal\Serialization\XmlSerializer;
use WindowsAzure\Common\Configuration;
use WindowsAzure\Blob\BlobSettings;
use WindowsAzure\Blob\BlobService;
use WindowsAzure\Blob\Models\CreateContainerOptions;
use WindowsAzure\Blob\Models\PublicAccessType;
use WindowsAzure\Common\ServiceException;
use WindowsAzure\Blob\Models\CreateBlobOptions;
/**
* Manages a PEAR channel.
*
* @category Microsoft
* @package WindowsAzure
* @author Azure PHP SDK <azurephpsdk@microsoft.com>
* @copyright 2012 Microsoft Corporation
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @version Release: @package_version@
* @link http://pear.php.net/package/azure-sdk-for-php
*/
class ChannelManager
{
/**
* @var BlobRestProxy
*/
private static $_blobRestProxy;
/**
* Creates new blob REST proxy.
*
* @return BlobRestProxy
*/
private static function _createBlobRestProxy()
{
$config = new Configuration();
$config->setProperty(BlobSettings::ACCOUNT_KEY, getenv('CHANNEL_STORAGE_SERVICE_KEY'));
$config->setProperty(BlobSettings::ACCOUNT_NAME, CHANNEL_STORAGE_SERVICE_NAME);
$config->setProperty(BlobSettings::URI, CHANNEL_URL);
return BlobService::create($config);
}
/**
* Channel manager main entry.
*
* @return none
*/
public static function main()
{
self::$_blobRestProxy = self::_createBlobRestProxy();
if ( isset($_GET['release'])
|| (isset($_SERVER['argv'])
&& @$_SERVER['argv'][1] == 'release')
) {
// Ship a new release
self::_downloadChannel();
self::_addPackage();
self::_uploadChannel();
self::_verifyInstall();
} else {
// Prompt user to manage channel
self::_manageChannel();
}
}
/**
* Command line interaction with user to manage the channel by letting user to:
* 1) Get the channel (either by creation of new one or download existing one).
* 2) Prompt user to remove old package.
* 3) Prompt user to add current package.
* 4) Upload the channel back.
* 5) Verify that latest package is installable.
*
* @return none
*/
private static function _manageChannel()
{
$answer = self::_promptMsg('Create new channel? [n]:', true);
switch ($answer) {
case 'y':
self::_createNewChannel();
self::_uploadChannel();
self::_executeCommand('pear channel-discover ' . CHANNEL_NAME);
break;
case 'n':
case '':
self::_downloadChannel();
break;
}
do {
$answer = self::_promptMsg('Want to remove exisitng package? [n]:', true);
switch ($answer) {
case 'y':
self::_removePackage();
break;
}
} while ($answer == 'y');
$answer = self::_promptMsg('Want to add current package? [y]:', true);
switch ($answer) {
case 'y':
case '':
self::_addPackage();
break;
}
self::_uploadChannel();
self::_verifyInstall();
}
/**
* Creates new channel and removes existing channel files by:
* 1) Removes existing channel files on the cloud.
* 2) Constructs pirum.xml contents.
* 3) Cleans previous files if any and create new channel directory.
* 4) Writes pirum.xml.
* 5) Generates the channel files.
*
* @return none
*/
private static function _createNewChannel()
{
echo "Removing old channel files if any...\n";
self::_clearContainer(CHANNEL_MAIN_CONTAINER, self::$_blobRestProxy);
self::_clearContainer(CHANNEL_GET_CONTAINER, self::$_blobRestProxy);
self::_clearContainer(CHANNEL_REST_CONTAINER, self::$_blobRestProxy);
$xmlSerializer = new XmlSerializer();
$properties = array(XmlSerializer::ROOT_NAME => 'server');
$fileArray = array(
'name' => CHANNEL_NAME,
'summary' => CHANNEL_SUMMARY,
'alias' => CHANNEL_ALIAS,
'url' => CHANNEL_URL
);
$fileContents = $xmlSerializer->serialize($fileArray, $properties);
$dirName = CHANNEL_DIR_NAME;
self::_createDir(CHANNEL_DIR_NAME);
$filePath = dirname(__FILE__) . DIRECTORY_SEPARATOR . $dirName;
$filePath .= DIRECTORY_SEPARATOR . 'pirum.xml';
file_put_contents($filePath, $fileContents);
self::_executeCommand("pirum build $dirName/");
}
/**
* Tries to install the new released package.
*
* @return none
*/
private static function _verifyInstall()
{
echo "Test installing the package...\n";
self::_executeCommand('pear uninstall WindowsAzure/WindowsAzure');
self::_executeCommand('pear channel-update WindowsAzure');
self::_executeCommand('pear clear-cache');
self::_executeCommand('pear install WindowsAzure/WindowsAzure');
}
/**
* Deletes all the Blobs in a specified container.
*
* @param string $container The container name.
*
* @return none
*/
private static function _clearContainer($container)
{
$blobs = self::$_blobRestProxy->listBlobs($container);
$blobs = $blobs->getBlobs();
foreach ($blobs as $blob) {
self::$_blobRestProxy->deleteBlob($container, $blob->getName());
}
}
/**
* Downloads all the Blobs in a container to a specified directory.
*
* @param string $containerName The container name.
* @param string $dirName The directory name.
*
* @return none
*/
private static function _downloadContainerInDir($containerName, $dirName)
{
self::_createDir($dirName);
$blobs = self::$_blobRestProxy->listBlobs($containerName);
$blobs = $blobs->getBlobs();
foreach ($blobs as $blob) {
$name = $blob->getName();
$blob = self::$_blobRestProxy->getBlob($containerName, $name);
$file = $dirName . '/' . $name;
$dir = dirname($file);
if (!is_dir($dir)) {
mkdir($dir, 0777, true);
}
file_put_contents($file, stream_get_contents($blob->getContentStream()));
}
}
/**
* Downloads the channel files.
*
* @return none
*/
private static function _downloadChannel()
{
echo "Downloading the channel files...\n";
self::_downloadContainerInDir(CHANNEL_MAIN_CONTAINER, CHANNEL_DIR_NAME);
self::_downloadContainerInDir(CHANNEL_GET_CONTAINER, CHANNEL_DIR_NAME . '/get');
self::_downloadContainerInDir(CHANNEL_REST_CONTAINER, CHANNEL_DIR_NAME . '/rest');
}
/**
* Uploads the channel files to blob storage.
*
* @return none
*
* @throws \Exception
*/
private static function _uploadChannel()
{
$names = array();
self::_rscandir('channel', $names);
$contents = array_map('file_get_contents', $names);
echo "Uploading channel files to the cloud...\n";
self::_tryCreateContainer(CHANNEL_MAIN_CONTAINER);
self::_tryCreateContainer(CHANNEL_GET_CONTAINER);
self::_tryCreateContainer(CHANNEL_REST_CONTAINER);
$channelDir = 'channel/';
$getDir = $channelDir . 'get/';
$restDir = $channelDir . 'rest/';
for ($i = 0; $i < count($names); $i++) {
$options = new CreateBlobOptions();
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$options->setContentType(finfo_file($finfo, $names[$i]));
if (strpos($names[$i], $getDir) !== false) {
$names[$i] = str_replace($getDir, '', $names[$i]);
$container = CHANNEL_GET_CONTAINER;
} else if (strpos($names[$i], $restDir) !== false) {
$names[$i] = str_replace($restDir, '', $names[$i]);
$container = CHANNEL_REST_CONTAINER;
} else if (strpos($names[$i], $channelDir) !== false) {
$names[$i] = str_replace($channelDir, '', $names[$i]);
$container = CHANNEL_MAIN_CONTAINER;
} else {
throw new \Exception('incorrect file path.');
}
self::$_blobRestProxy->createBlockBlob(
$container,
$names[$i],
$contents[$i],
$options
);
}
}
/**
* Scans a directory and returns all files under it recursively.
*
* @param string $dir The directory path.
* @param array &$files The directory files.
*
* @return none
*/
private static function _rscandir($dir, &$files) {
foreach(glob($dir . '/*') as $file) {
if(is_dir($file))
self::_rscandir($file, $files);
else
$files[] = $file;
}
}
/**
* Tries to create new container if it does not exist.
*
* @param string $container The container name.
*
* @return none
*/
private static function _tryCreateContainer($container)
{
try {
$options = new CreateContainerOptions();
$options->setPublicAccess(PublicAccessType::BLOBS_ONLY);
self::$_blobRestProxy->createContainer($container, $options);
} catch (ServiceException $e) {
if ($e->getCode() != 409) {
print_r($e);
exit();
}
}
}
/**
* Adds new package.
*
* @return none
*/
private static function _addPackage()
{
self::_executeCommand('php ..\package.php make');
self::_executeCommand('pear package ..\package.xml');
$files = glob('*.tgz');
$name = $files[count($files) - 1];
self::_executeCommand("pirum add channel $name");
}
/**
* Removes existing package.
*
* @return none
*/
private static function _removePackage()
{
$files = glob('channel/get/*.tgz');
if (empty($files)) {
echo "No packages to remove.\n";
} else {
$files = array_map('basename', $files);
$msg = '';
for ($i = 0; $i < count($files); $i++) {
$msg .= ($i + 1) . '. ' . $files[$i] . "\n";
}
$answer = self::_promptMsg($msg . 'Choose package to remove:');
$name = $files[$answer - 1];
self::_executeCommand("pirum remove channel $name");
}
}
/**
* Creates new directory and removes existing one.
*
* @param string $dirName The directory name.
*
* @return none
*/
private static function _createDir($dirName)
{
// Clear previous files if any
self::_rrmdir($dirName);
// Create new directory
mkdir($dirName);
}
/**
* Executes cmdline command.
*
* @param string $command The command to execute.
*
* @return none
*/
private static function _executeCommand($command)
{
exec($command, $output, $failed);
echo implode("\n", $output) . "\n";
if ($failed) {
echo "Something went wrong. Exit\n";
exit();
}
}
/**
* Removes a whole directory with all files inside it.
*
* @param string $dir The directory path.
*
* @return none
*/
private static function _rrmdir($dir)
{
foreach(glob($dir . '/*') as $file) {
if(is_dir($file)) {
self::_rrmdir($file);
} else {
unlink($file);
}
}
if (is_dir($dir)) {
rmdir($dir);
}
}
/**
* Prompts message to the uers and return back the input.
*
* @param string $msg The message to display.
* @param boolean $isYesNoMsg Flag to indicate if this is Y/N question.
*
* @return string
*/
private static function _promptMsg($msg, $isYesNoMsg = false)
{
if ($isYesNoMsg) {
do {
echo $msg;
$line = trim(fgets(STDIN));
$line = strtolower($line);
$line = empty($line) ? $line : $line[0];
if ($line == '' || $line == 'y' || $line == 'n') {
break;
}
} while (true);
} else {
echo $msg;
$line = trim(fgets(STDIN));
}
return $line;
}
}
// Start the script
ChannelManager::main();
?>
Jump to Line
Something went wrong with that request. Please try again.