Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F2892861
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Advanced/Developer...
View Handle
View Hovercard
Size
19 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/resources/sql/autopatches/20140108.ddbpname.1.sql b/resources/sql/autopatches/20140108.ddbpname.1.sql
new file mode 100644
index 0000000000..3fe80875db
--- /dev/null
+++ b/resources/sql/autopatches/20140108.ddbpname.1.sql
@@ -0,0 +1,2 @@
+ALTER TABLE {$NAMESPACE}_drydock.drydock_blueprint
+ ADD blueprintName VARCHAR(255) NOT NULL AFTER className;
diff --git a/resources/sql/autopatches/20140108.ddbpname.2.php b/resources/sql/autopatches/20140108.ddbpname.2.php
new file mode 100644
index 0000000000..ca7e3ef8b2
--- /dev/null
+++ b/resources/sql/autopatches/20140108.ddbpname.2.php
@@ -0,0 +1,23 @@
+<?php
+
+echo "Adding names to Drydock blueprints.\n";
+
+$table = new DrydockBlueprint();
+$conn_w = $table->establishConnection('w');
+$iterator = new LiskMigrationIterator($table);
+foreach ($iterator as $blueprint) {
+ $id = $blueprint->getID();
+
+ echo "Populating blueprint {$id}...\n";
+
+ if (!strlen($blueprint->getBlueprintName())) {
+ queryfx(
+ $conn_w,
+ 'UPDATE %T SET blueprintName = %s WHERE id = %d',
+ $table->getTableName(),
+ pht('Blueprint %s', $id),
+ $id);
+ }
+}
+
+echo "Done.\n";
diff --git a/src/applications/drydock/blueprint/DrydockPreallocatedHostBlueprintImplementation.php b/src/applications/drydock/blueprint/DrydockPreallocatedHostBlueprintImplementation.php
index 554b969307..86a2b15d9d 100644
--- a/src/applications/drydock/blueprint/DrydockPreallocatedHostBlueprintImplementation.php
+++ b/src/applications/drydock/blueprint/DrydockPreallocatedHostBlueprintImplementation.php
@@ -1,123 +1,123 @@
<?php
final class DrydockPreallocatedHostBlueprintImplementation
extends DrydockBlueprintImplementation {
public function isEnabled() {
return true;
}
public function getBlueprintName() {
- return pht('Remote Host (Preallocated)');
+ return pht('Preallocated Remote Hosts');
}
public function getDescription() {
return pht('Allows Drydock to run on specific remote hosts you configure.');
}
public function canAllocateMoreResources(array $pool) {
return false;
}
protected function executeAllocateResource(DrydockLease $lease) {
throw new Exception("Preallocated hosts can't be dynamically allocated.");
}
protected function canAllocateLease(
DrydockResource $resource,
DrydockLease $lease) {
return
$lease->getAttribute('platform') === $resource->getAttribute('platform');
}
protected function shouldAllocateLease(
DrydockResource $resource,
DrydockLease $lease,
array $other_leases) {
return true;
}
protected function executeAcquireLease(
DrydockResource $resource,
DrydockLease $lease) {
// Because preallocated resources are manually created, we should verify
// we have all the information we need.
PhutilTypeSpec::checkMap(
$resource->getAttributesForTypeSpec(
array('platform', 'host', 'port', 'credential', 'path')),
array(
'platform' => 'string',
'host' => 'string',
'port' => 'string', // Value is a string from the command line
'credential' => 'string',
'path' => 'string',
));
$v_platform = $resource->getAttribute('platform');
$v_path = $resource->getAttribute('path');
// Similar to DrydockLocalHostBlueprint, we create a folder
// on the remote host that the lease can use.
$lease_id = $lease->getID();
// Can't use DIRECTORY_SEPERATOR here because that is relevant to
// the platform we're currently running on, not the platform we are
// remoting to.
$separator = '/';
if ($v_platform === 'windows') {
$separator = '\\';
}
// Clean up the directory path a little.
$base_path = rtrim($v_path, '/');
$base_path = rtrim($base_path, '\\');
$full_path = $base_path.$separator.$lease_id;
$cmd = $lease->getInterface('command');
if ($v_platform !== 'windows') {
$cmd->execx('mkdir %s', $full_path);
} else {
// Windows is terrible. The mkdir command doesn't even support putting
// the path in quotes. IN QUOTES. ARGUHRGHUGHHGG!! Do some terribly
// inaccurate sanity checking since we can't safely escape the path.
if (preg_match('/^[A-Z]\\:\\\\[a-zA-Z0-9\\\\\\ ]/', $full_path) === 0) {
throw new Exception(
'Unsafe path detected for Windows platform: "'.$full_path.'".');
}
$cmd->execx('mkdir %C', $full_path);
}
$lease->setAttribute('path', $full_path);
}
public function getType() {
return 'host';
}
public function getInterface(
DrydockResource $resource,
DrydockLease $lease,
$type) {
switch ($type) {
case 'command':
return id(new DrydockSSHCommandInterface())
->setConfiguration(array(
'host' => $resource->getAttribute('host'),
'port' => $resource->getAttribute('port'),
'credential' => $resource->getAttribute('credential'),
'platform' => $resource->getAttribute('platform')));
case 'filesystem':
return id(new DrydockSFTPFilesystemInterface())
->setConfiguration(array(
'host' => $resource->getAttribute('host'),
'port' => $resource->getAttribute('port'),
'credential' => $resource->getAttribute('credential')));
}
throw new Exception("No interface of type '{$type}'.");
}
}
diff --git a/src/applications/drydock/controller/DrydockBlueprintEditController.php b/src/applications/drydock/controller/DrydockBlueprintEditController.php
index a749c317bd..aa3c5be4a0 100644
--- a/src/applications/drydock/controller/DrydockBlueprintEditController.php
+++ b/src/applications/drydock/controller/DrydockBlueprintEditController.php
@@ -1,121 +1,144 @@
<?php
final class DrydockBlueprintEditController extends DrydockBlueprintController {
private $id;
public function willProcessRequest(array $data) {
$this->id = idx($data, 'id');
}
public function processRequest() {
$request = $this->getRequest();
$viewer = $request->getUser();
if ($this->id) {
$blueprint = id(new DrydockBlueprintQuery())
->setViewer($viewer)
->withIDs(array($this->id))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$blueprint) {
return new Aphront404Response();
}
$impl = $blueprint->getImplementation();
$cancel_uri = $this->getApplicationURI('blueprint/'.$this->id.'/');
} else {
$class = $request->getStr('class');
$impl = DrydockBlueprintImplementation::getNamedImplementation($class);
if (!$impl || !$impl->isEnabled()) {
return new Aphront400Response();
}
- $blueprint = new DrydockBlueprint();
+ $blueprint = DrydockBlueprint::initializeNewBlueprint($viewer);
$blueprint->setClassName($class);
$cancel_uri = $this->getApplicationURI('blueprint/');
}
+ $v_name = $blueprint->getBlueprintName();
+ $e_name = true;
+ $errors = array();
if ($request->isFormPost()) {
$v_view_policy = $request->getStr('viewPolicy');
$v_edit_policy = $request->getStr('editPolicy');
+ $v_name = $request->getStr('name');
+ if (!strlen($v_name)) {
+ $e_name = pht('Required');
+ $errors[] = pht('You must name this blueprint.');
+ }
- // TODO: Should we use transactions here?
+ // TODO: We should use transactions here.
$blueprint->setViewPolicy($v_view_policy);
$blueprint->setEditPolicy($v_edit_policy);
+ $blueprint->setBlueprintName($v_name);
- $blueprint->save();
+ if (!$errors) {
+ $blueprint->save();
- $id = $blueprint->getID();
- $save_uri = $this->getApplicationURI("blueprint/{$id}/");
+ $id = $blueprint->getID();
+ $save_uri = $this->getApplicationURI("blueprint/{$id}/");
- return id(new AphrontRedirectResponse())->setURI($save_uri);
+ return id(new AphrontRedirectResponse())->setURI($save_uri);
+ }
+ }
+
+ $error_view = null;
+ if ($errors) {
+ $error_view = id(new AphrontErrorView())->setErrors($errors);
}
$policies = id(new PhabricatorPolicyQuery())
->setViewer($viewer)
->setObject($blueprint)
->execute();
$form = id(new AphrontFormView())
->setUser($viewer)
->addHiddenInput('class', $request->getStr('class'))
+ ->appendChild(
+ id(new AphrontFormTextControl())
+ ->setLabel(pht('Name'))
+ ->setName('name')
+ ->setValue($v_name)
+ ->setError($e_name))
->appendChild(
id(new AphrontFormStaticControl())
->setLabel(pht('Blueprint Type'))
->setValue($impl->getBlueprintName()))
->appendChild(
id(new AphrontFormPolicyControl())
->setName('viewPolicy')
->setPolicyObject($blueprint)
->setCapability(PhabricatorPolicyCapability::CAN_VIEW)
->setPolicies($policies))
->appendChild(
id(new AphrontFormPolicyControl())
->setName('editPolicy')
->setPolicyObject($blueprint)
->setCapability(PhabricatorPolicyCapability::CAN_EDIT)
->setPolicies($policies));
$crumbs = $this->buildApplicationCrumbs();
if ($blueprint->getID()) {
$title = pht('Edit Blueprint');
$header = pht('Edit Blueprint %d', $blueprint->getID());
$crumbs->addTextCrumb(pht('Blueprint %d', $blueprint->getID()));
$crumbs->addTextCrumb(pht('Edit'));
$submit = pht('Save Blueprint');
} else {
$title = pht('New Blueprint');
$header = pht('New Blueprint');
$crumbs->addTextCrumb(pht('New Blueprint'));
$submit = pht('Create Blueprint');
}
$form->appendChild(
id(new AphrontFormSubmitControl())
->setValue($submit)
->addCancelButton($cancel_uri));
$box = id(new PHUIObjectBoxView())
->setHeaderText($header)
+ ->setFormError($error_view)
->setForm($form);
return $this->buildApplicationPage(
array(
$crumbs,
$box,
),
array(
'title' => $title,
'device' => true,
));
}
}
diff --git a/src/applications/drydock/controller/DrydockBlueprintListController.php b/src/applications/drydock/controller/DrydockBlueprintListController.php
index 7dd1cb12cb..bdc1953c69 100644
--- a/src/applications/drydock/controller/DrydockBlueprintListController.php
+++ b/src/applications/drydock/controller/DrydockBlueprintListController.php
@@ -1,66 +1,62 @@
<?php
final class DrydockBlueprintListController extends DrydockBlueprintController
implements PhabricatorApplicationSearchResultsControllerInterface {
private $queryKey;
public function shouldAllowPublic() {
return true;
}
public function willProcessRequest(array $data) {
$this->queryKey = idx($data, 'queryKey');
}
public function processRequest() {
$request = $this->getRequest();
$controller = id(new PhabricatorApplicationSearchController($request))
->setQueryKey($this->queryKey)
->setSearchEngine(new DrydockBlueprintSearchEngine())
->setNavigation($this->buildSideNavView());
return $this->delegateToController($controller);
}
public function renderResultsList(
array $blueprints,
PhabricatorSavedQuery $query) {
assert_instances_of($blueprints, 'DrydockBlueprint');
$viewer = $this->getRequest()->getUser();
$view = new PHUIObjectItemListView();
foreach ($blueprints as $blueprint) {
$item = id(new PHUIObjectItemView())
- ->setHeader($blueprint->getClassName())
+ ->setHeader($blueprint->getBlueprintName())
->setHref($this->getApplicationURI('/blueprint/'.$blueprint->getID()))
->setObjectName(pht('Blueprint %d', $blueprint->getID()));
- if ($blueprint->getImplementation()->isEnabled()) {
- $item->addAttribute(pht('Enabled'));
- $item->setBarColor('green');
- } else {
- $item->addAttribute(pht('Disabled'));
- $item->setBarColor('red');
+ if (!$blueprint->getImplementation()->isEnabled()) {
+ $item->setDisabled(true);
}
- $item->addAttribute($blueprint->getImplementation()->getDescription());
+ $item->addAttribute($blueprint->getImplementation()->getBlueprintName());
$view->addItem($item);
}
return $view;
}
public function buildApplicationCrumbs() {
$crumbs = parent::buildApplicationCrumbs();
$crumbs->addAction(
id(new PHUIListItemView())
->setName(pht('New Blueprint'))
->setHref($this->getApplicationURI('/blueprint/create/'))
->setIcon('create'));
return $crumbs;
}
}
diff --git a/src/applications/drydock/controller/DrydockBlueprintViewController.php b/src/applications/drydock/controller/DrydockBlueprintViewController.php
index 8526f42d9c..d9b22479a8 100644
--- a/src/applications/drydock/controller/DrydockBlueprintViewController.php
+++ b/src/applications/drydock/controller/DrydockBlueprintViewController.php
@@ -1,108 +1,110 @@
<?php
final class DrydockBlueprintViewController extends DrydockBlueprintController {
private $id;
public function willProcessRequest(array $data) {
$this->id = $data['id'];
}
public function processRequest() {
$request = $this->getRequest();
$viewer = $request->getUser();
$blueprint = id(new DrydockBlueprintQuery())
->setViewer($viewer)
->withIDs(array($this->id))
->executeOne();
if (!$blueprint) {
return new Aphront404Response();
}
- $title = 'Blueprint '.$blueprint->getID().' '.$blueprint->getClassName();
+ $title = $blueprint->getBlueprintName();
$header = id(new PHUIHeaderView())
- ->setHeader($title);
+ ->setHeader($title)
+ ->setUser($viewer)
+ ->setPolicyObject($blueprint);
$actions = $this->buildActionListView($blueprint);
$properties = $this->buildPropertyListView($blueprint, $actions);
$blueprint_uri = 'blueprint/'.$blueprint->getID().'/';
$blueprint_uri = $this->getApplicationURI($blueprint_uri);
$resources = id(new DrydockResourceQuery())
->withBlueprintPHIDs(array($blueprint->getPHID()))
->setViewer($viewer)
->execute();
$resource_list = $this->buildResourceListView($resources);
$resource_list->setNoDataString(pht('This blueprint has no resources.'));
$pager = new AphrontPagerView();
$pager->setURI(new PhutilURI($blueprint_uri), 'offset');
$pager->setOffset($request->getInt('offset'));
$crumbs = $this->buildApplicationCrumbs();
$crumbs->setActionList($actions);
$crumbs->addTextCrumb(pht('Blueprint %d', $blueprint->getID()));
$object_box = id(new PHUIObjectBoxView())
->setHeader($header)
->addPropertyList($properties);
return $this->buildApplicationPage(
array(
$crumbs,
$object_box,
$resource_list
),
array(
'device' => true,
'title' => $title,
));
}
private function buildActionListView(DrydockBlueprint $blueprint) {
$viewer = $this->getRequest()->getUser();
$view = id(new PhabricatorActionListView())
->setUser($viewer)
->setObjectURI($this->getRequest()->getRequestURI())
->setObject($blueprint);
$uri = '/blueprint/edit/'.$blueprint->getID().'/';
$uri = $this->getApplicationURI($uri);
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$blueprint,
PhabricatorPolicyCapability::CAN_EDIT);
$view->addAction(
id(new PhabricatorActionView())
->setHref($uri)
->setName(pht('Edit Blueprint'))
->setIcon('edit')
->setWorkflow(!$can_edit)
->setDisabled(!$can_edit));
return $view;
}
private function buildPropertyListView(
DrydockBlueprint $blueprint,
PhabricatorActionListView $actions) {
$view = new PHUIPropertyListView();
$view->setActionList($actions);
$view->addProperty(
- pht('Implementation'),
- $blueprint->getClassName());
+ pht('Type'),
+ $blueprint->getImplementation()->getBlueprintName());
return $view;
}
}
diff --git a/src/applications/drydock/storage/DrydockBlueprint.php b/src/applications/drydock/storage/DrydockBlueprint.php
index 06f2375563..2e61e8e2db 100644
--- a/src/applications/drydock/storage/DrydockBlueprint.php
+++ b/src/applications/drydock/storage/DrydockBlueprint.php
@@ -1,80 +1,85 @@
<?php
final class DrydockBlueprint extends DrydockDAO
implements PhabricatorPolicyInterface {
- protected $phid;
protected $className;
+ protected $blueprintName;
protected $viewPolicy;
protected $editPolicy;
- protected $details;
+ protected $details = array();
private $implementation = self::ATTACHABLE;
+ public static function initializeNewBlueprint(PhabricatorUser $actor) {
+ return id(new DrydockBlueprint())
+ ->setBlueprintName('');
+ }
+
public function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_SERIALIZATION => array(
'details' => self::SERIALIZATION_JSON,
)
) + parent::getConfiguration();
}
public function generatePHID() {
return PhabricatorPHID::generateNewPHID(
DrydockPHIDTypeBlueprint::TYPECONST);
}
public function getImplementation() {
$class = $this->className;
$implementations =
DrydockBlueprintImplementation::getAllBlueprintImplementations();
if (!isset($implementations[$class])) {
throw new Exception(
"Invalid class name for blueprint (got '".$class."')");
}
return id(new $class())->attachInstance($this);
}
public function attachImplementation(DrydockBlueprintImplementation $impl) {
$this->implementation = $impl;
return $this;
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
);
}
public function getPolicy($capability) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
return $this->getViewPolicy();
case PhabricatorPolicyCapability::CAN_EDIT:
return $this->getEditPolicy();
}
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
case PhabricatorPolicyCapability::CAN_EDIT:
return $viewer->getIsAdmin();
}
}
public function describeAutomaticCapability($capability) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
return pht('Administrators can always view blueprints.');
case PhabricatorPolicyCapability::CAN_EDIT:
return pht('Administrators can always edit blueprints.');
}
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Jan 19, 17:28 (1 w, 5 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1126960
Default Alt Text
(19 KB)
Attached To
Mode
rP Phorge
Attached
Detach File
Event Timeline
Log In to Comment