Page MenuHomePhorge

No OneTemporary

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

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)

Event Timeline