Page MenuHomePhabricator

D13984.diff
No OneTemporary

D13984.diff

diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -7,7 +7,7 @@
*/
return array(
'names' => array(
- 'core.pkg.css' => 'aced76a5',
+ 'core.pkg.css' => '203c9d69',
'core.pkg.js' => 'a590b451',
'darkconsole.pkg.js' => 'e7393ebb',
'differential.pkg.css' => '2de124c9',
@@ -129,7 +129,7 @@
'rsrc/css/phui/phui-document.css' => '0267054b',
'rsrc/css/phui/phui-feed-story.css' => 'b7b26d23',
'rsrc/css/phui/phui-fontkit.css' => 'cb8ae7ad',
- 'rsrc/css/phui/phui-form-view.css' => '621b21c5',
+ 'rsrc/css/phui/phui-form-view.css' => '07bafa88',
'rsrc/css/phui/phui-form.css' => 'afdb2c6e',
'rsrc/css/phui/phui-header-view.css' => '55bb32dd',
'rsrc/css/phui/phui-icon.css' => 'b0a6b1b6',
@@ -782,7 +782,7 @@
'phui-font-icon-base-css' => '3dad2ae3',
'phui-fontkit-css' => 'cb8ae7ad',
'phui-form-css' => 'afdb2c6e',
- 'phui-form-view-css' => '621b21c5',
+ 'phui-form-view-css' => '07bafa88',
'phui-header-view-css' => '55bb32dd',
'phui-icon-view-css' => 'b0a6b1b6',
'phui-image-mask-css' => '5a8b09c8',
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -816,6 +816,8 @@
'DrydockConstants' => 'applications/drydock/constants/DrydockConstants.php',
'DrydockController' => 'applications/drydock/controller/DrydockController.php',
'DrydockCreateBlueprintsCapability' => 'applications/drydock/capability/DrydockCreateBlueprintsCapability.php',
+ 'DrydockCustomAttributes' => 'applications/drydock/util/DrydockCustomAttributes.php',
+ 'DrydockCustomAttributesTestCase' => 'applications/drydock/util/__tests__/DrydockCustomAttributesTestCase.php',
'DrydockDAO' => 'applications/drydock/storage/DrydockDAO.php',
'DrydockDefaultEditCapability' => 'applications/drydock/capability/DrydockDefaultEditCapability.php',
'DrydockDefaultViewCapability' => 'applications/drydock/capability/DrydockDefaultViewCapability.php',
@@ -2901,6 +2903,7 @@
'PhabricatorStandardCustomFieldRemarkup' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldRemarkup.php',
'PhabricatorStandardCustomFieldSelect' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldSelect.php',
'PhabricatorStandardCustomFieldText' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldText.php',
+ 'PhabricatorStandardCustomFieldTextarea' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldTextarea.php',
'PhabricatorStandardCustomFieldUsers' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldUsers.php',
'PhabricatorStandardPageView' => 'view/page/PhabricatorStandardPageView.php',
'PhabricatorStandardSelectCustomFieldDatasource' => 'infrastructure/customfield/datasource/PhabricatorStandardSelectCustomFieldDatasource.php',
@@ -4500,6 +4503,8 @@
'DrydockConstants' => 'Phobject',
'DrydockController' => 'PhabricatorController',
'DrydockCreateBlueprintsCapability' => 'PhabricatorPolicyCapability',
+ 'DrydockCustomAttributes' => 'Phobject',
+ 'DrydockCustomAttributesTestCase' => 'PhabricatorTestCase',
'DrydockDAO' => 'PhabricatorLiskDAO',
'DrydockDefaultEditCapability' => 'PhabricatorPolicyCapability',
'DrydockDefaultViewCapability' => 'PhabricatorPolicyCapability',
@@ -6976,6 +6981,7 @@
'PhabricatorStandardCustomFieldRemarkup' => 'PhabricatorStandardCustomField',
'PhabricatorStandardCustomFieldSelect' => 'PhabricatorStandardCustomField',
'PhabricatorStandardCustomFieldText' => 'PhabricatorStandardCustomField',
+ 'PhabricatorStandardCustomFieldTextarea' => 'PhabricatorStandardCustomField',
'PhabricatorStandardCustomFieldUsers' => 'PhabricatorStandardCustomFieldPHIDs',
'PhabricatorStandardPageView' => 'PhabricatorBarePageView',
'PhabricatorStandardSelectCustomFieldDatasource' => 'PhabricatorTypeaheadDatasource',
diff --git a/src/applications/drydock/blueprint/DrydockBlueprintImplementation.php b/src/applications/drydock/blueprint/DrydockBlueprintImplementation.php
--- a/src/applications/drydock/blueprint/DrydockBlueprintImplementation.php
+++ b/src/applications/drydock/blueprint/DrydockBlueprintImplementation.php
@@ -60,8 +60,30 @@
return $this;
}
+ public function supportsAutomaticCustomAttributes() {
+ return true;
+ }
+
public function getFieldSpecifications() {
- return array();
+ if ($this->supportsAutomaticCustomAttributes()) {
+ return array(
+ 'attr-header' => array(
+ 'name' => pht('Custom Attributes'),
+ 'type' => 'header',
+ ),
+ 'attributes' => array(
+ 'name' => pht('Attributes'),
+ 'type' => 'textarea',
+ 'caption' => pht(
+ 'A newline separated list of custom blueprint '.
+ 'attributes. Each attribute should be specified in '.
+ 'a key=value format.'),
+ 'monospace' => true,
+ ),
+ );
+ } else {
+ return array();
+ }
}
public function getDetail($key, $default = null) {
@@ -81,6 +103,16 @@
$scope = $this->pushActiveScope($resource, $lease);
+ if ($this->supportsAutomaticCustomAttributes()) {
+ $custom_match = DrydockCustomAttributes::hasRequirements(
+ $lease->getAttributes(),
+ $this->getDetail('attributes', ''));
+
+ if (!$custom_match) {
+ return false;
+ }
+ }
+
return $this->canAllocateLease($resource, $lease);
}
diff --git a/src/applications/drydock/blueprint/DrydockMinMaxBlueprintImplementation.php b/src/applications/drydock/blueprint/DrydockMinMaxBlueprintImplementation.php
--- a/src/applications/drydock/blueprint/DrydockMinMaxBlueprintImplementation.php
+++ b/src/applications/drydock/blueprint/DrydockMinMaxBlueprintImplementation.php
@@ -94,6 +94,6 @@
'overallocate the lease to an existing resource and '.
'exceed the limit specified here.'),
),
- );
+ ) + parent::getFieldSpecifications();
}
}
diff --git a/src/applications/drydock/util/DrydockCustomAttributes.php b/src/applications/drydock/util/DrydockCustomAttributes.php
new file mode 100644
--- /dev/null
+++ b/src/applications/drydock/util/DrydockCustomAttributes.php
@@ -0,0 +1,48 @@
+<?php
+
+final class DrydockCustomAttributes extends Phobject {
+
+ public static function parse($text) {
+ if ($text === null || trim($text) === '') {
+ return array();
+ }
+
+ $pairs = phutil_split_lines($text);
+ $attributes = array();
+
+ foreach ($pairs as $line) {
+ $kv = explode('=', $line, 2);
+ if (count($kv) === 0) {
+ continue;
+ } else if (count($kv) === 1) {
+ $attributes['attr_'.$kv[0]] = true;
+ } else {
+ $attributes['attr_'.$kv[0]] = trim($kv[1]);
+ }
+ }
+
+ return $attributes;
+ }
+
+ public static function hasRequirements($attributes, $provided) {
+ $provided = self::parse($provided);
+
+ foreach ($attributes as $key => $value) {
+ // Only compare custom attributes.
+ if (substr($key, 0, 5) === 'attr_') {
+ if ($value === true) {
+ if (!array_key_exists($provided, $key)) {
+ return false;
+ }
+ } else {
+ if (idx($provided, $key) !== $value) {
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+}
diff --git a/src/applications/drydock/util/__tests__/DrydockCustomAttributesTestCase.php b/src/applications/drydock/util/__tests__/DrydockCustomAttributesTestCase.php
new file mode 100644
--- /dev/null
+++ b/src/applications/drydock/util/__tests__/DrydockCustomAttributesTestCase.php
@@ -0,0 +1,27 @@
+<?php
+
+final class DrydockCustomAttributesTestCase extends PhabricatorTestCase {
+
+ public function testNullAttributes() {
+ $result = DrydockCustomAttributes::parse(null);
+ $this->assertEqual(array(), $result);
+ }
+
+ public function testEmptyAttributes() {
+ $result = DrydockCustomAttributes::parse('');
+ $this->assertEqual(array(), $result);
+ }
+
+ public function testSingleAttribute() {
+ $result = DrydockCustomAttributes::parse('abc=123');
+ $this->assertEqual(array('attr_abc' => '123'), $result);
+ }
+
+ public function testMultipleAttributes() {
+ $result = DrydockCustomAttributes::parse("abc=123\nxyz=456");
+ $this->assertEqual(array(
+ 'attr_abc' => '123',
+ 'attr_xyz' => '456',
+ ), $result);
+ }
+}
diff --git a/src/applications/drydock/worker/DrydockAllocatorWorker.php b/src/applications/drydock/worker/DrydockAllocatorWorker.php
--- a/src/applications/drydock/worker/DrydockAllocatorWorker.php
+++ b/src/applications/drydock/worker/DrydockAllocatorWorker.php
@@ -220,6 +220,16 @@
continue;
}
+ if ($candidate_blueprint->supportsAutomaticCustomAttributes()) {
+ $custom_match = DrydockCustomAttributes::hasRequirements(
+ $lease->getAttributes(),
+ $candidate_blueprint->getDetail('attributes', ''));
+ if (!$custom_match) {
+ unset($blueprints[$key]);
+ continue;
+ }
+ }
+
if (!$candidate_blueprint->canAllocateResourceForLease($lease)) {
unset($blueprints[$key]);
continue;
diff --git a/src/applications/harbormaster/step/HarbormasterLeaseHostBuildStepImplementation.php b/src/applications/harbormaster/step/HarbormasterLeaseHostBuildStepImplementation.php
--- a/src/applications/harbormaster/step/HarbormasterLeaseHostBuildStepImplementation.php
+++ b/src/applications/harbormaster/step/HarbormasterLeaseHostBuildStepImplementation.php
@@ -32,13 +32,16 @@
$artifact = count($artifacts) > 0 ? head($artifacts) : null;
if ($artifact === null) {
+ $custom_attributes = DrydockCustomAttributes::parse(
+ idx($settings, 'attributes', ''));
+
// Create the lease.
$lease = id(new DrydockLease())
->setResourceType('host')
->setAttributes(
array(
'platform' => $settings['platform'],
- ))
+ ) + $custom_attributes)
->queueForActivation();
// Create the associated artifact.
@@ -87,6 +90,14 @@
'type' => 'text',
'required' => true,
),
+ 'attributes' => array(
+ 'name' => pht('Required Attributes'),
+ 'type' => 'textarea',
+ 'caption' => pht(
+ 'A newline separated list of required host attributes. Each '.
+ 'attribute should be specified in a key=value format.'),
+ 'monospace' => true,
+ ),
);
}
diff --git a/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldTextarea.php b/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldTextarea.php
new file mode 100644
--- /dev/null
+++ b/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldTextarea.php
@@ -0,0 +1,74 @@
+<?php
+
+final class PhabricatorStandardCustomFieldTextarea
+ extends PhabricatorStandardCustomField {
+
+ public function getFieldType() {
+ return 'textarea';
+ }
+
+ public function renderEditControl(array $handles) {
+ $monospace = $this->getFieldConfigValue('monospace', false);
+ $custom_class =
+ $monospace ? 'aphront-form-control-textarea-monospace' : null;
+
+ return id(new AphrontFormTextAreaControl())
+ ->setLabel($this->getFieldName())
+ ->setName($this->getFieldKey())
+ ->setCaption($this->getCaption())
+ ->setValue($this->getFieldValue())
+ ->setCustomClass($custom_class);
+ }
+
+ public function getStyleForPropertyView() {
+ return 'block';
+ }
+
+ public function getApplicationTransactionRemarkupBlocks(
+ PhabricatorApplicationTransaction $xaction) {
+ return array(
+ $xaction->getNewValue(),
+ );
+ }
+
+ public function renderPropertyViewValue(array $handles) {
+ $value = $this->getFieldValue();
+
+ if (!strlen($value)) {
+ return null;
+ }
+
+ return phutil_tag(
+ 'pre',
+ array(),
+ $value);
+ }
+
+ public function getApplicationTransactionTitle(
+ PhabricatorApplicationTransaction $xaction) {
+ $author_phid = $xaction->getAuthorPHID();
+
+ // TODO: Expose fancy transactions.
+
+ return pht(
+ '%s edited %s.',
+ $xaction->renderHandleLink($author_phid),
+ $this->getFieldName());
+ }
+
+ public function shouldAppearInHerald() {
+ return true;
+ }
+
+ public function getHeraldFieldConditions() {
+ return array(
+ HeraldAdapter::CONDITION_CONTAINS,
+ HeraldAdapter::CONDITION_NOT_CONTAINS,
+ HeraldAdapter::CONDITION_IS,
+ HeraldAdapter::CONDITION_IS_NOT,
+ HeraldAdapter::CONDITION_REGEXP,
+ );
+ }
+
+
+}
diff --git a/webroot/rsrc/css/phui/phui-form-view.css b/webroot/rsrc/css/phui/phui-form-view.css
--- a/webroot/rsrc/css/phui/phui-form-view.css
+++ b/webroot/rsrc/css/phui/phui-form-view.css
@@ -154,6 +154,10 @@
height: 24em;
}
+.aphront-form-control-textarea-monospace {
+ font-family: monospace;
+}
+
.aphront-form-control-select .aphront-form-input {
padding-top: 2px;
}

File Metadata

Mime Type
text/plain
Expires
Sat, Apr 19, 12:12 PM (6 d, 13 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7710670
Default Alt Text
D13984.diff (13 KB)

Event Timeline