mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-20 05:42:40 +01:00
Implement support for leasing from Drydock hosts in Harbormaster
Summary: This adds LeaseHostBuildStepImplementation for getting leases on hosts in Drydock via Harbormaster. It stores the resulting lease in an artifact. There is also a few bug fixes as well. Test Plan: Created a build plan with a "Lease Host" build step. Ran the build plan and saw the build pass and the artifact in the database. Reviewers: epriestley, #blessed_reviewers Reviewed By: epriestley CC: Korvin, epriestley, aran Maniphest Tasks: T1049, T4111 Differential Revision: https://secure.phabricator.com/D7706
This commit is contained in:
parent
53250d84df
commit
d8d1173f52
8 changed files with 190 additions and 9 deletions
|
@ -775,6 +775,7 @@ phutil_register_library_map(array(
|
|||
'JavelinUIExample' => 'applications/uiexample/examples/JavelinUIExample.php',
|
||||
'JavelinViewExample' => 'applications/uiexample/examples/JavelinViewExample.php',
|
||||
'JavelinViewExampleServerView' => 'applications/uiexample/examples/JavelinViewExampleServerView.php',
|
||||
'LeaseHostBuildStepImplementation' => 'applications/harbormaster/step/LeaseHostBuildStepImplementation.php',
|
||||
'LegalpadConstants' => 'applications/legalpad/constants/LegalpadConstants.php',
|
||||
'LegalpadController' => 'applications/legalpad/controller/LegalpadController.php',
|
||||
'LegalpadDAO' => 'applications/legalpad/storage/LegalpadDAO.php',
|
||||
|
@ -3154,6 +3155,7 @@ phutil_register_library_map(array(
|
|||
'JavelinUIExample' => 'PhabricatorUIExample',
|
||||
'JavelinViewExample' => 'PhabricatorUIExample',
|
||||
'JavelinViewExampleServerView' => 'AphrontView',
|
||||
'LeaseHostBuildStepImplementation' => 'BuildStepImplementation',
|
||||
'LegalpadController' => 'PhabricatorController',
|
||||
'LegalpadDAO' => 'PhabricatorLiskDAO',
|
||||
'LegalpadDocument' =>
|
||||
|
|
|
@ -57,13 +57,14 @@ abstract class BuildStepImplementation {
|
|||
}
|
||||
|
||||
/**
|
||||
* Loads the settings for this build step implementation from a build target.
|
||||
* Loads the settings for this build step implementation from a build
|
||||
* step or target.
|
||||
*/
|
||||
public final function loadSettings(HarbormasterBuildTarget $build_target) {
|
||||
public final function loadSettings($build_object) {
|
||||
$this->settings = array();
|
||||
$this->validateSettingDefinitions();
|
||||
foreach ($this->getSettingDefinitions() as $name => $opt) {
|
||||
$this->settings[$name] = $build_target->getDetail($name);
|
||||
$this->settings[$name] = $build_object->getDetail($name);
|
||||
}
|
||||
return $this->settings;
|
||||
}
|
||||
|
@ -94,4 +95,57 @@ abstract class BuildStepImplementation {
|
|||
public function getSettingRemarkupInstructions() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of artifacts produced by this command.
|
||||
*
|
||||
* Something like:
|
||||
*
|
||||
* return array(
|
||||
* 'some_name_input_by_user' => 'host');
|
||||
*
|
||||
* Future steps will calculate all available artifact mappings
|
||||
* before them and filter on the type.
|
||||
*
|
||||
* @return array The mappings of artifact names to their types.
|
||||
*/
|
||||
public function getArtifactMappings() {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all artifacts made available by previous build steps.
|
||||
*/
|
||||
public static function getAvailableArtifacts(
|
||||
HarbormasterBuildStep $current_build_step,
|
||||
$artifact_type) {
|
||||
|
||||
$build_plan_phid = $current_build_step->getBuildPlanPHID();
|
||||
|
||||
$build_plan = id(new HarbormasterBuildPlanQuery())
|
||||
->withPHIDs(array($build_plan_phid))
|
||||
->executeOne();
|
||||
|
||||
$build_steps = $build_plan->loadOrderedBuildSteps();
|
||||
|
||||
$previous_implementations = array();
|
||||
for ($i = 0; $i < count($build_steps); $i++) {
|
||||
if ($build_steps[$i]->getPHID() === $current_build_step->getPHID()) {
|
||||
break;
|
||||
}
|
||||
$previous_implementations[$i] = $build_steps[$i]->getStepImplementation();
|
||||
}
|
||||
|
||||
$artifact_arrays = mpull($previous_implementations, 'getArtifactMappings');
|
||||
$artifacts = array();
|
||||
foreach ($artifact_arrays as $array) {
|
||||
foreach ($array as $name => $type) {
|
||||
if ($type !== $artifact_type) {
|
||||
continue;
|
||||
}
|
||||
$artifacts[$name] = $type;
|
||||
}
|
||||
}
|
||||
return $artifacts;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
|
||||
final class LeaseHostBuildStepImplementation
|
||||
extends BuildStepImplementation {
|
||||
|
||||
public function getName() {
|
||||
return pht('Lease Host');
|
||||
}
|
||||
|
||||
public function getGenericDescription() {
|
||||
return pht('Obtain a lease on a Drydock host for performing builds.');
|
||||
}
|
||||
|
||||
public function getDescription() {
|
||||
$settings = $this->getSettings();
|
||||
|
||||
return pht(
|
||||
'Obtain a lease on a Drydock host whose platform is \'%s\'.',
|
||||
$settings['platform']);
|
||||
}
|
||||
|
||||
public function execute(
|
||||
HarbormasterBuild $build,
|
||||
HarbormasterBuildTarget $build_target) {
|
||||
|
||||
$settings = $this->getSettings();
|
||||
|
||||
// Create the lease.
|
||||
$lease = new DrydockLease();
|
||||
$lease->setResourceType('host');
|
||||
$lease->setAttributes(
|
||||
array('platform' => $settings['platform']));
|
||||
$lease->queueForActivation();
|
||||
|
||||
// Wait until the lease is fulfilled.
|
||||
// TODO: This will throw an exception if the lease can't be fulfilled;
|
||||
// we should treat that as build failure not build error.
|
||||
$lease->waitUntilActive();
|
||||
|
||||
// Create the associated artifact.
|
||||
$artifact = $build->createArtifact(
|
||||
$build_target,
|
||||
$settings['name'],
|
||||
'host');
|
||||
$artifact->setArtifactData(array(
|
||||
'drydock-lease' => $lease->getID()));
|
||||
$artifact->save();
|
||||
}
|
||||
|
||||
public function validateSettings() {
|
||||
$settings = $this->getSettings();
|
||||
|
||||
if ($settings['name'] === null || !is_string($settings['name'])) {
|
||||
return false;
|
||||
}
|
||||
if ($settings['platform'] === null || !is_string($settings['platform'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getSettingDefinitions() {
|
||||
return array(
|
||||
'name' => array(
|
||||
'name' => 'Artifact Name',
|
||||
'description' =>
|
||||
'The name of the artifact to reference in future build steps.',
|
||||
'type' => BuildStepImplementation::SETTING_TYPE_STRING),
|
||||
'platform' => array(
|
||||
'name' => 'Platform',
|
||||
'description' => 'The platform of the host.',
|
||||
'type' => BuildStepImplementation::SETTING_TYPE_STRING));
|
||||
}
|
||||
|
||||
}
|
|
@ -106,6 +106,19 @@ final class HarbormasterBuild extends HarbormasterDAO
|
|||
return $log;
|
||||
}
|
||||
|
||||
public function createArtifact(
|
||||
HarbormasterBuildTarget $build_target,
|
||||
$artifact_key,
|
||||
$artifact_type) {
|
||||
|
||||
$artifact =
|
||||
HarbormasterBuildArtifact::initializeNewBuildArtifact($build_target);
|
||||
$artifact->setArtifactKey($artifact_key);
|
||||
$artifact->setArtifactType($artifact_type);
|
||||
$artifact->save();
|
||||
return $artifact;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for and handles build cancellation. If this method returns
|
||||
* true, the caller should stop any current operations and return control
|
||||
|
|
|
@ -3,12 +3,18 @@
|
|||
final class HarbormasterBuildArtifact extends HarbormasterDAO
|
||||
implements PhabricatorPolicyInterface {
|
||||
|
||||
protected $buildablePHID;
|
||||
protected $buildTargetPHID;
|
||||
protected $artifactType;
|
||||
protected $artifactIndex;
|
||||
protected $artifactKey;
|
||||
protected $artifactData = array();
|
||||
|
||||
public static function initializeNewBuildArtifact(
|
||||
HarbormasterBuildTarget $build_target) {
|
||||
return id(new HarbormasterBuildArtifact())
|
||||
->setBuildTargetPHID($build_target->getPHID());
|
||||
}
|
||||
|
||||
public function getConfiguration() {
|
||||
return array(
|
||||
self::CONFIG_SERIALIZATION => array(
|
||||
|
@ -27,7 +33,8 @@ final class HarbormasterBuildArtifact extends HarbormasterDAO
|
|||
}
|
||||
|
||||
public function setArtifactKey($key) {
|
||||
$this->artifactIndex = PhabricatorHash::digestForIndex($key);
|
||||
$this->artifactIndex =
|
||||
PhabricatorHash::digestForIndex($this->buildTargetPHID.$key);
|
||||
$this->artifactKey = $key;
|
||||
return $this;
|
||||
}
|
||||
|
|
|
@ -36,6 +36,19 @@ final class HarbormasterBuildPlan extends HarbormasterDAO
|
|||
return $this->assertAttached($this->buildSteps);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a standard, ordered list of build steps for this build plan.
|
||||
*
|
||||
* This method should be used to load build steps for a given build plan
|
||||
* so that the ordering is consistent.
|
||||
*/
|
||||
public function loadOrderedBuildSteps() {
|
||||
return id(new HarbormasterBuildStepQuery())
|
||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||
->withBuildPlanPHIDs(array($this->getPHID()))
|
||||
->execute();
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorSubscribableInterface )----------------------------------- */
|
||||
|
||||
|
|
|
@ -41,6 +41,25 @@ final class HarbormasterBuildStep extends HarbormasterDAO
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function getStepImplementation() {
|
||||
if ($this->className === null) {
|
||||
throw new Exception("No implementation set for the given step.");
|
||||
}
|
||||
|
||||
static $implementations = null;
|
||||
if ($implementations === null) {
|
||||
$implementations = BuildStepImplementation::getImplementations();
|
||||
}
|
||||
|
||||
$class = $this->className;
|
||||
if (!in_array($class, $implementations)) {
|
||||
throw new Exception(
|
||||
"Class name '".$class."' does not extend BuildStepImplementation.");
|
||||
}
|
||||
$implementation = newv($class, array());
|
||||
$implementation->loadSettings($this);
|
||||
return $implementation;
|
||||
}
|
||||
|
||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||
|
||||
|
|
|
@ -38,10 +38,7 @@ final class HarbormasterBuildWorker extends PhabricatorWorker {
|
|||
$buildable = $build->getBuildable();
|
||||
$plan = $build->getBuildPlan();
|
||||
|
||||
$steps = id(new HarbormasterBuildStepQuery())
|
||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||
->withBuildPlanPHIDs(array($plan->getPHID()))
|
||||
->execute();
|
||||
$steps = $plan->loadOrderedBuildSteps();
|
||||
|
||||
// Perform the build.
|
||||
foreach ($steps as $step) {
|
||||
|
|
Loading…
Reference in a new issue