Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15530341
D13984.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
13 KB
Referenced Files
None
Subscribers
None
D13984.id.diff
View Options
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
Details
Attached
Mime Type
text/plain
Expires
Thu, Apr 24, 3:22 AM (2 d, 10 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7710670
Default Alt Text
D13984.id.diff (13 KB)
Attached To
Mode
D13984: [drydock/core] Support custom attributes on all blueprints
Attached
Detach File
Event Timeline
Log In to Comment