Commit cd1052d3 authored by Jon Pugh's avatar Jon Pugh

Improving Context Properties:

- Creating a class Aegir\Provision\Property.
- Adding a static Provision::newPropery() method to allow easy creation.
- Implementing the new class in ServerContext::option_documentation()
- Make getHomeDir() and getScriptUser() static so we can call from anywhere
parent 471ffe50
......@@ -8,6 +8,7 @@ use Aegir\Provision\Context;
use Aegir\Provision\Context\PlatformContext;
use Aegir\Provision\Context\ServerContext;
use Aegir\Provision\Context\SiteContext;
use Aegir\Provision\Property;
use Aegir\Provision\Provision;
use Aegir\Provision\Service;
use Symfony\Component\Console\Exception\InvalidOptionException;
......@@ -263,11 +264,16 @@ class SaveCommand extends Command
$class = '\Aegir\Provision\Context\\' . ucfirst($this->input->getOption('context_type')) . "Context";
$options = $class::option_documentation();
$properties = $this->askForRequiredContexts();
foreach ($options as $name => $description) {
foreach ($options as $name => $property) {
if (!empty($properties[$name])) {
continue;
}
// Allows option_documentation to return array of strings for simple properties.
if ( !$property instanceof Property) {
$property = Provision::newProperty($property);
}
// If option does not exist, ask for it.
if (!empty($this->input->getOption($name))) {
......@@ -275,7 +281,7 @@ class SaveCommand extends Command
$this->io->comment("Using option {$name}={$properties[$name]}");
}
else {
$properties[$name] = $this->io->ask("$name ($description)");
$properties[$name] = $this->io->ask("{$name}({$property->description})", $property->default, $property->validate);
}
}
return $properties;
......
......@@ -153,7 +153,7 @@ class Config extends ProvisionConfig
*
* @return string
*/
protected function getHomeDir()
static public function getHomeDir()
{
$home = getenv('HOME');
if (!$home) {
......@@ -171,7 +171,7 @@ class Config extends ProvisionConfig
/**
* Determine the user running provision.
*/
public function getScriptUser() {
static public function getScriptUser() {
$real_script_user = posix_getpwuid(posix_geteuid());
return $real_script_user['name'];
}
......
......@@ -2,7 +2,10 @@
namespace Aegir\Provision\Context;
use Aegir\Provision\Console\Config;
use Aegir\Provision\ContextProvider;
use Aegir\Provision\Property;
use Aegir\Provision\Provision;
use Symfony\Component\Config\Definition\ConfigurationInterface;
/**
......@@ -20,18 +23,43 @@ class ServerContext extends ContextProvider implements ConfigurationInterface
*/
public $type = 'server';
const TYPE = 'server';
/**
* @return string|Property[]
*/
static function option_documentation()
{
$options = [
'remote_host' => 'server: host name; default localhost',
'script_user' => 'server: OS user name; default current user',
'aegir_root' => 'server: Aegir root; default '.getenv('HOME'),
'master_url' => 'server: Hostmaster URL',
return [
'remote_host' =>
Provision::newProperty()
->description('server: host name')
->required(TRUE)
->default('localhost')
->validate(function($remote_host) {
// If remote_host doesn't resolve to anything, warn the user.
$ip = gethostbynamel($remote_host);
if (empty($ip)) {
throw new \RuntimeException("Hostname $remote_host does not resolve to an IP address. Please try again.");
}
return $remote_host;
}),
'script_user' =>
Provision::newProperty()
->description('server: OS user name')
->required(TRUE)
->default(Config::getScriptUser()),
'aegir_root' =>
Provision::newProperty()
->description('server: aegir user home directory')
->required(TRUE)
->default(Config::getHomeDir()),
// @TODO: Why do server contexts need a master_url?
'master_url' =>
Provision::newProperty()
->description('server: Hostmaster URL')
->required(FALSE)
];
return $options;
}
......
<?php
namespace Aegir\Provision;
/**
* Class Property
*
* Use this to create dynamic properties for contexts.
*
* For example:
*
* <?php
* static function option_documentation()
* {
* return [
* 'remote_host' =>
* Provision::newProperty()
* ->description('server: host name')
* ->required(TRUE)
* ->default('localhost'),
* ->validate(function($remote_host) {
* // If remote_host doesn't resolve to anything, warn the user.
* $ip = gethostbynamel($remote_host);
* if (empty($ip)) {
* throw new \RuntimeException("Hostname $remote_host does not resolve to an IP address. Please try again.");
* }
* return $remote_host;
* }),
* ];
* }
* ?>
*
* @package Aegir\Provision
*/
class Property {
public $description = '';
public $default = NULL;
public $required = FALSE;
public $validate;
/**
* Allow "backwards" compatibility: return the description when converting to a string.
* @return string
*/
function __toString()
{
return $this->description;
}
/**
* Property constructor.
*
* Set description and default validate callable.
*
* @param null $description
*/
public function __construct($description = NULL) {
$this->description($description);
$this->validate(function ($answer) {
if ($this->required && empty($answer)) {
throw new \RuntimeException('Property is required.');
}
else {
return $answer;
}
});
return $this;
}
/**
* Set the description of this property.
*
* @param string $description
*
* @return $this
*/
public function description($description) {
$this->description = $description;
return $this;
}
/**
* Set the default value of this property.
*
* If value is callable, will set the return value of the callable as the default value.
*
* @param string|callable $default
*
* @return $this
*/
public function default($default) {
if (is_callable($default)) {
$this->default = $default();
}
else {
$this->default = $default;
}
return $this;
}
/**
* Set if this Property is required or not.
*
* @param bool $required
*
* @return $this
*/
public function required($required = TRUE) {
$this->required = $required;
return $this;
}
/**
* Set the validation function for this property.
*
* @param callable $callable
*
* @return $this
*/
public function validate($callable) {
$this->validate = $callable;
return $this;
}
}
\ No newline at end of file
......@@ -428,8 +428,11 @@ class Provision implements ConfigAwareInterface, ContainerAwareInterface, Logger
public function getScriptUid() {
return posix_getuid();
}
public function newTask() {
static public function newTask() {
return new Task();
}
static public function newProperty($description = '') {
return new Property($description);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment