diff --git a/resources/sql/autopatches/20150930.drydock.log.1.sql b/resources/sql/autopatches/20150930.drydock.log.1.sql new file mode 100644 --- /dev/null +++ b/resources/sql/autopatches/20150930.drydock.log.1.sql @@ -0,0 +1,25 @@ +TRUNCATE {$NAMESPACE}_drydock.drydock_log; + +ALTER TABLE {$NAMESPACE}_drydock.drydock_log + DROP resourceID; + +ALTER TABLE {$NAMESPACE}_drydock.drydock_log + DROP leaseID; + +ALTER TABLE {$NAMESPACE}_drydock.drydock_log + DROP message; + +ALTER TABLE {$NAMESPACE}_drydock.drydock_log + ADD blueprintPHID VARBINARY(64); + +ALTER TABLE {$NAMESPACE}_drydock.drydock_log + ADD resourcePHID VARBINARY(64); + +ALTER TABLE {$NAMESPACE}_drydock.drydock_log + ADD leasePHID VARBINARY(64); + +ALTER TABLE {$NAMESPACE}_drydock.drydock_log + ADD type VARCHAR(64) NOT NULL COLLATE {$COLLATE_TEXT}; + +ALTER TABLE {$NAMESPACE}_drydock.drydock_log + ADD data LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT}; diff --git a/src/applications/drydock/application/PhabricatorDrydockApplication.php b/src/applications/drydock/application/PhabricatorDrydockApplication.php --- a/src/applications/drydock/application/PhabricatorDrydockApplication.php +++ b/src/applications/drydock/application/PhabricatorDrydockApplication.php @@ -47,7 +47,7 @@ return array( '/drydock/' => array( '' => 'DrydockConsoleController', - 'blueprint/' => array( + '(?Pblueprint)/' => array( '(?:query/(?P[^/]+)/)?' => 'DrydockBlueprintListController', '(?P[1-9]\d*)/' => array( '' => 'DrydockBlueprintViewController', @@ -55,29 +55,32 @@ 'DrydockBlueprintDisableController', 'resources/(?:query/(?P[^/]+)/)?' => 'DrydockResourceListController', + 'logs/(?:query/(?P[^/]+)/)?' => + 'DrydockLogListController', ), 'create/' => 'DrydockBlueprintCreateController', 'edit/(?:(?P[1-9]\d*)/)?' => 'DrydockBlueprintEditController', ), - 'resource/' => array( + '(?Presource)/' => array( '(?:query/(?P[^/]+)/)?' => 'DrydockResourceListController', '(?P[1-9]\d*)/' => array( '' => 'DrydockResourceViewController', 'release/' => 'DrydockResourceReleaseController', 'leases/(?:query/(?P[^/]+)/)?' => 'DrydockLeaseListController', + 'logs/(?:query/(?P[^/]+)/)?' => + 'DrydockLogListController', ), ), - 'lease/' => array( + '(?Please)/' => array( '(?:query/(?P[^/]+)/)?' => 'DrydockLeaseListController', '(?P[1-9]\d*)/' => array( '' => 'DrydockLeaseViewController', 'release/' => 'DrydockLeaseReleaseController', + 'logs/(?:query/(?P[^/]+)/)?' => + 'DrydockLogListController', ), ), - 'log/' => array( - '(?:query/(?P[^/]+)/)?' => 'DrydockLogListController', - ), ), ); } 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 @@ -250,46 +250,6 @@ /* -( Logging )------------------------------------------------------------ */ - /** - * @task log - */ - protected function logException(Exception $ex) { - $this->log($ex->getMessage()); - } - - - /** - * @task log - */ - protected function log($message) { - self::writeLog(null, null, $message); - } - - - /** - * @task log - */ - public static function writeLog( - DrydockResource $resource = null, - DrydockLease $lease = null, - $message = null) { - - $log = id(new DrydockLog()) - ->setEpoch(time()) - ->setMessage($message); - - if ($resource) { - $log->setResourceID($resource->getID()); - } - - if ($lease) { - $log->setLeaseID($lease->getID()); - } - - $log->save(); - } - - public static function getAllBlueprintImplementations() { return id(new PhutilClassMapQuery()) ->setAncestorClass(__CLASS__) diff --git a/src/applications/drydock/controller/DrydockBlueprintViewController.php b/src/applications/drydock/controller/DrydockBlueprintViewController.php --- a/src/applications/drydock/controller/DrydockBlueprintViewController.php +++ b/src/applications/drydock/controller/DrydockBlueprintViewController.php @@ -56,11 +56,19 @@ new DrydockBlueprintTransactionQuery()); $timeline->setShouldTerminate(true); + $log_query = id(new DrydockLogQuery()) + ->withBlueprintPHIDs(array($blueprint->getPHID())); + + $log_box = $this->buildLogBox( + $log_query, + $this->getApplicationURI("blueprint/{$id}/logs/query/all/")); + return $this->buildApplicationPage( array( $crumbs, $object_box, $resource_box, + $log_box, $timeline, ), array( diff --git a/src/applications/drydock/controller/DrydockController.php b/src/applications/drydock/controller/DrydockController.php --- a/src/applications/drydock/controller/DrydockController.php +++ b/src/applications/drydock/controller/DrydockController.php @@ -85,4 +85,31 @@ ->addRawContent($table); } + protected function buildLogBox(DrydockLogQuery $query, $all_uri) { + $viewer = $this->getViewer(); + + $logs = $query + ->setViewer($viewer) + ->setLimit(100) + ->execute(); + + $log_table = id(new DrydockLogListView()) + ->setUser($viewer) + ->setLogs($logs) + ->render(); + + $log_header = id(new PHUIHeaderView()) + ->setHeader(pht('Logs')) + ->addActionLink( + id(new PHUIButtonView()) + ->setTag('a') + ->setHref($all_uri) + ->setIconFont('fa-search') + ->setText(pht('View All Logs'))); + + return id(new PHUIObjectBoxView()) + ->setHeader($log_header) + ->setTable($log_table); + } + } diff --git a/src/applications/drydock/controller/DrydockLeaseViewController.php b/src/applications/drydock/controller/DrydockLeaseViewController.php --- a/src/applications/drydock/controller/DrydockLeaseViewController.php +++ b/src/applications/drydock/controller/DrydockLeaseViewController.php @@ -15,7 +15,8 @@ return new Aphront404Response(); } - $lease_uri = $this->getApplicationURI('lease/'.$lease->getID().'/'); + $id = $lease->getID(); + $lease_uri = $this->getApplicationURI("lease/{$id}/"); $title = pht('Lease %d', $lease->getID()); @@ -29,20 +30,12 @@ $actions = $this->buildActionListView($lease); $properties = $this->buildPropertyListView($lease, $actions); - $pager = new PHUIPagerView(); - $pager->setURI(new PhutilURI($lease_uri), 'offset'); - $pager->setOffset($request->getInt('offset')); + $log_query = id(new DrydockLogQuery()) + ->withLeasePHIDs(array($lease->getPHID())); - $logs = id(new DrydockLogQuery()) - ->setViewer($viewer) - ->withLeaseIDs(array($lease->getID())) - ->executeWithOffsetPager($pager); - - $log_table = id(new DrydockLogListView()) - ->setUser($viewer) - ->setLogs($logs) - ->render(); - $log_table->appendChild($pager); + $log_box = $this->buildLogBox( + $log_query, + $this->getApplicationURI("lease/{$id}/logs/query/all/")); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb($title, $lease_uri); @@ -56,10 +49,6 @@ ->addPropertyList($locks, pht('Slot Locks')) ->addPropertyList($commands, pht('Commands')); - $log_box = id(new PHUIObjectBoxView()) - ->setHeaderText(pht('Lease Logs')) - ->setTable($log_table); - return $this->buildApplicationPage( array( $crumbs, diff --git a/src/applications/drydock/controller/DrydockLogController.php b/src/applications/drydock/controller/DrydockLogController.php --- a/src/applications/drydock/controller/DrydockLogController.php +++ b/src/applications/drydock/controller/DrydockLogController.php @@ -3,13 +3,60 @@ abstract class DrydockLogController extends DrydockController { + private $blueprint; + private $resource; + private $lease; + + public function setBlueprint(DrydockBlueprint $blueprint) { + $this->blueprint = $blueprint; + return $this; + } + + public function getBlueprint() { + return $this->blueprint; + } + + public function setResource(DrydockResource $resource) { + $this->resource = $resource; + return $this; + } + + public function getResource() { + return $this->resource; + } + + public function setLease(DrydockLease $lease) { + $this->lease = $lease; + return $this; + } + + public function getLease() { + return $this->lease; + } + public function buildSideNavView() { $nav = new AphrontSideNavFilterView(); $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); - id(new DrydockLogSearchEngine()) - ->setViewer($this->getRequest()->getUser()) - ->addNavigationItems($nav->getMenu()); + $engine = id(new DrydockLogSearchEngine()) + ->setViewer($this->getRequest()->getUser()); + + $blueprint = $this->getBlueprint(); + if ($blueprint) { + $engine->setBlueprint($blueprint); + } + + $resource = $this->getResource(); + if ($resource) { + $engine->setResource($resource); + } + + $lease = $this->getLease(); + if ($lease) { + $engine->setLease($lease); + } + + $engine->addNavigationItems($nav->getMenu()); $nav->selectFilter(null); @@ -18,9 +65,54 @@ protected function buildApplicationCrumbs() { $crumbs = parent::buildApplicationCrumbs(); - $crumbs->addTextCrumb( - pht('Logs'), - $this->getApplicationURI('log/')); + + $blueprint = $this->getBlueprint(); + $resource = $this->getResource(); + $lease = $this->getLease(); + if ($blueprint) { + $id = $blueprint->getID(); + + $crumbs->addTextCrumb( + pht('Blueprints'), + $this->getApplicationURI('blueprint/')); + + $crumbs->addTextCrumb( + $blueprint->getBlueprintName(), + $this->getApplicationURI("blueprint/{$id}/")); + + $crumbs->addTextCrumb( + pht('Logs'), + $this->getApplicationURI("blueprint/{$id}/logs/")); + } else if ($resource) { + $id = $resource->getID(); + + $crumbs->addTextCrumb( + pht('Resources'), + $this->getApplicationURI('resource/')); + + $crumbs->addTextCrumb( + $resource->getName(), + $this->getApplicationURI("resource/{$id}/")); + + $crumbs->addTextCrumb( + pht('Logs'), + $this->getApplicationURI("resource/{$id}/logs/")); + } else if ($lease) { + $id = $lease->getID(); + + $crumbs->addTextCrumb( + pht('Leases'), + $this->getApplicationURI('lease/')); + + $crumbs->addTextCrumb( + $lease->getLeaseName(), + $this->getApplicationURI("lease/{$id}/")); + + $crumbs->addTextCrumb( + pht('Logs'), + $this->getApplicationURI("lease/{$id}/logs/")); + } + return $crumbs; } diff --git a/src/applications/drydock/controller/DrydockLogListController.php b/src/applications/drydock/controller/DrydockLogListController.php --- a/src/applications/drydock/controller/DrydockLogListController.php +++ b/src/applications/drydock/controller/DrydockLogListController.php @@ -8,11 +8,53 @@ public function handleRequest(AphrontRequest $request) { $viewer = $request->getViewer(); - $querykey = $request->getURIData('queryKey'); + $engine = new DrydockLogSearchEngine(); + + $id = $request->getURIData('id'); + $type = $request->getURIData('type'); + switch ($type) { + case 'blueprint': + $blueprint = id(new DrydockBlueprintQuery()) + ->setViewer($viewer) + ->withIDs(array($id)) + ->executeOne(); + if (!$blueprint) { + return new Aphront404Response(); + } + $engine->setBlueprint($blueprint); + $this->setBlueprint($blueprint); + break; + case 'resource': + $resource = id(new DrydockResourceQuery()) + ->setViewer($viewer) + ->withIDs(array($id)) + ->executeOne(); + if (!$resource) { + return new Aphront404Response(); + } + $engine->setResource($resource); + $this->setResource($resource); + break; + case 'lease': + $lease = id(new DrydockLeaseQuery()) + ->setViewer($viewer) + ->withIDs(array($id)) + ->executeOne(); + if (!$lease) { + return new Aphront404Response(); + } + $engine->setLease($lease); + $this->setLease($lease); + break; + default: + return new Aphront404Response(); + } + + $query_key = $request->getURIData('queryKey'); $controller = id(new PhabricatorApplicationSearchController()) - ->setQueryKey($querykey) - ->setSearchEngine(new DrydockLogSearchEngine()) + ->setQueryKey($query_key) + ->setSearchEngine($engine) ->setNavigation($this->buildSideNavView()); return $this->delegateToController($controller); diff --git a/src/applications/drydock/controller/DrydockResourceViewController.php b/src/applications/drydock/controller/DrydockResourceViewController.php --- a/src/applications/drydock/controller/DrydockResourceViewController.php +++ b/src/applications/drydock/controller/DrydockResourceViewController.php @@ -29,23 +29,15 @@ $actions = $this->buildActionListView($resource); $properties = $this->buildPropertyListView($resource, $actions); - $resource_uri = 'resource/'.$resource->getID().'/'; - $resource_uri = $this->getApplicationURI($resource_uri); + $id = $resource->getID(); + $resource_uri = $this->getApplicationURI("resource/{$id}/"); - $pager = new PHUIPagerView(); - $pager->setURI(new PhutilURI($resource_uri), 'offset'); - $pager->setOffset($request->getInt('offset')); + $log_query = id(new DrydockLogQuery()) + ->withResourcePHIDs(array($resource->getPHID())); - $logs = id(new DrydockLogQuery()) - ->setViewer($viewer) - ->withResourceIDs(array($resource->getID())) - ->executeWithOffsetPager($pager); - - $log_table = id(new DrydockLogListView()) - ->setUser($viewer) - ->setLogs($logs) - ->render(); - $log_table->appendChild($pager); + $log_box = $this->buildLogBox( + $log_query, + $this->getApplicationURI("resource/{$id}/logs/query/all/")); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Resource %d', $resource->getID())); @@ -61,10 +53,6 @@ $lease_box = $this->buildLeaseBox($resource); - $log_box = id(new PHUIObjectBoxView()) - ->setHeaderText(pht('Resource Logs')) - ->setTable($log_table); - return $this->buildApplicationPage( array( $crumbs, diff --git a/src/applications/drydock/query/DrydockLogQuery.php b/src/applications/drydock/query/DrydockLogQuery.php --- a/src/applications/drydock/query/DrydockLogQuery.php +++ b/src/applications/drydock/query/DrydockLogQuery.php @@ -2,112 +2,125 @@ final class DrydockLogQuery extends DrydockQuery { - private $resourceIDs; - private $leaseIDs; + private $blueprintPHIDs; + private $resourcePHIDs; + private $leasePHIDs; - public function withResourceIDs(array $ids) { - $this->resourceIDs = $ids; + public function withBlueprintPHIDs(array $phids) { + $this->blueprintPHIDs = $phids; return $this; } - public function withLeaseIDs(array $ids) { - $this->leaseIDs = $ids; + public function withResourcePHIDs(array $phids) { + $this->resourcePHIDs = $phids; return $this; } + public function withLeasePHIDs(array $phids) { + $this->leasePHIDs = $phids; + return $this; + } + + public function newResultObject() { + return new DrydockLog(); + } + protected function loadPage() { - $table = new DrydockLog(); - $conn_r = $table->establishConnection('r'); - - $data = queryfx_all( - $conn_r, - 'SELECT log.* FROM %T log %Q %Q %Q', - $table->getTableName(), - $this->buildWhereClause($conn_r), - $this->buildOrderClause($conn_r), - $this->buildLimitClause($conn_r)); - - return $table->loadAllFromArray($data); + return $this->loadStandardPage($this->newResultObject()); } - protected function willFilterPage(array $logs) { - $resource_ids = array_filter(mpull($logs, 'getResourceID')); - if ($resource_ids) { + protected function didFilterPage(array $logs) { + $blueprint_phids = array_filter(mpull($logs, 'getBlueprintPHID')); + if ($blueprint_phids) { + $blueprints = id(new DrydockBlueprintQuery()) + ->setParentQuery($this) + ->setViewer($this->getViewer()) + ->withPHIDs($blueprint_phids) + ->execute(); + $blueprints = mpull($blueprints, null, 'getPHID'); + } else { + $blueprints = array(); + } + + foreach ($logs as $key => $log) { + $blueprint = null; + $blueprint_phid = $log->getBlueprintPHID(); + if ($blueprint_phid) { + $blueprint = idx($blueprints, $blueprint_phid); + } + $log->attachBlueprint($blueprint); + } + + $resource_phids = array_filter(mpull($logs, 'getResourcePHID')); + if ($resource_phids) { $resources = id(new DrydockResourceQuery()) ->setParentQuery($this) ->setViewer($this->getViewer()) - ->withIDs(array_unique($resource_ids)) + ->withPHIDs($resource_phids) ->execute(); + $resources = mpull($resources, null, 'getPHID'); } else { $resources = array(); } foreach ($logs as $key => $log) { $resource = null; - if ($log->getResourceID()) { - $resource = idx($resources, $log->getResourceID()); - if (!$resource) { - unset($logs[$key]); - continue; - } + $resource_phid = $log->getResourcePHID(); + if ($resource_phid) { + $resource = idx($resources, $resource_phid); } $log->attachResource($resource); } - $lease_ids = array_filter(mpull($logs, 'getLeaseID')); - if ($lease_ids) { + $lease_phids = array_filter(mpull($logs, 'getLeasePHID')); + if ($lease_phids) { $leases = id(new DrydockLeaseQuery()) ->setParentQuery($this) ->setViewer($this->getViewer()) - ->withIDs(array_unique($lease_ids)) + ->withPHIDs($lease_phids) ->execute(); + $leases = mpull($leases, null, 'getPHID'); } else { $leases = array(); } foreach ($logs as $key => $log) { $lease = null; - if ($log->getLeaseID()) { - $lease = idx($leases, $log->getLeaseID()); - if (!$lease) { - unset($logs[$key]); - continue; - } + $lease_phid = $log->getLeasePHID(); + if ($lease_phid) { + $lease = idx($leases, $lease_phid); } $log->attachLease($lease); } - // These logs are meaningless and their policies aren't computable. They - // shouldn't exist, but throw them away if they do. - foreach ($logs as $key => $log) { - if (!$log->getResource() && !$log->getLease()) { - unset($logs[$key]); - } - } - return $logs; } - protected function buildWhereClause(AphrontDatabaseConnection $conn_r) { - $where = array(); + protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { + $where = parent::buildWhereClauseParts($conn); - if ($this->resourceIDs !== null) { + if ($this->blueprintPHIDs !== null) { $where[] = qsprintf( - $conn_r, - 'resourceID IN (%Ld)', - $this->resourceIDs); + $conn, + 'blueprintPHID IN (%Ls)', + $this->blueprintPHIDs); } - if ($this->leaseIDs !== null) { + if ($this->resourcePHIDs !== null) { $where[] = qsprintf( - $conn_r, - 'leaseID IN (%Ld)', - $this->leaseIDs); + $conn, + 'resourcePHID IN (%Ls)', + $this->resourcePHIDs); } - $where[] = $this->buildPagingClause($conn_r); + if ($this->leasePHIDs !== null) { + $where[] = qsprintf( + $conn, + 'leasePHID IN (%Ls)', + $this->leasePHIDs); + } - return $this->formatWhereClause($where); + return $where; } } diff --git a/src/applications/drydock/query/DrydockLogSearchEngine.php b/src/applications/drydock/query/DrydockLogSearchEngine.php --- a/src/applications/drydock/query/DrydockLogSearchEngine.php +++ b/src/applications/drydock/query/DrydockLogSearchEngine.php @@ -2,83 +2,104 @@ final class DrydockLogSearchEngine extends PhabricatorApplicationSearchEngine { - public function getResultTypeDescription() { - return pht('Drydock Logs'); + private $blueprint; + private $resource; + private $lease; + + public function setBlueprint(DrydockBlueprint $blueprint) { + $this->blueprint = $blueprint; + return $this; } - public function getApplicationClassName() { - return 'PhabricatorDrydockApplication'; + public function getBlueprint() { + return $this->blueprint; } - public function buildSavedQueryFromRequest(AphrontRequest $request) { - $query = new PhabricatorSavedQuery(); + public function setResource(DrydockResource $resource) { + $this->resource = $resource; + return $this; + } - $query->setParameter( - 'resourcePHIDs', - $this->readListFromRequest($request, 'resources')); - $query->setParameter( - 'leasePHIDs', - $this->readListFromRequest($request, 'leases')); + public function getResource() { + return $this->resource; + } - return $query; + public function setLease(DrydockLease $lease) { + $this->lease = $lease; + return $this; } - public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) { - $resource_phids = $saved->getParameter('resourcePHIDs', array()); - $lease_phids = $saved->getParameter('leasePHIDs', array()); + public function getLease() { + return $this->lease; + } - // TODO: Change logs to use PHIDs instead of IDs. - $resource_ids = array(); - $lease_ids = array(); + public function canUseInPanelContext() { + // Prevent use on Dashboard panels since all log queries currently need a + // parent object and these don't seem particularly useful in any case. + return false; + } - if ($resource_phids) { - $resource_ids = id(new DrydockResourceQuery()) - ->setViewer(PhabricatorUser::getOmnipotentUser()) - ->withPHIDs($resource_phids) - ->execute(); - $resource_ids = mpull($resource_ids, 'getID'); - } + public function getResultTypeDescription() { + return pht('Drydock Logs'); + } - if ($lease_phids) { - $lease_ids = id(new DrydockLeaseQuery()) - ->setViewer(PhabricatorUser::getOmnipotentUser()) - ->withPHIDs($lease_phids) - ->execute(); - $lease_ids = mpull($lease_ids, 'getID'); - } + public function getApplicationClassName() { + return 'PhabricatorDrydockApplication'; + } + public function newQuery() { $query = new DrydockLogQuery(); - if ($resource_ids) { - $query->withResourceIDs($resource_ids); + + $blueprint = $this->getBlueprint(); + if ($blueprint) { + $query->withBlueprintPHIDs(array($blueprint->getPHID())); + } + + $resource = $this->getResource(); + if ($resource) { + $query->withResourcePHIDs(array($resource->getPHID())); } - if ($lease_ids) { - $query->withLeaseIDs($lease_ids); + + $lease = $this->getLease(); + if ($lease) { + $query->withLeasePHIDs(array($lease->getPHID())); } return $query; } - public function buildSearchForm( - AphrontFormView $form, - PhabricatorSavedQuery $saved) { + protected function buildQueryFromParameters(array $map) { + $query = $this->newQuery(); - $form - ->appendControl( - id(new AphrontFormTokenizerControl()) - ->setDatasource(new DrydockResourceDatasource()) - ->setName('resources') - ->setLabel(pht('Resources')) - ->setValue($saved->getParameter('resourcePHIDs', array()))) - ->appendControl( - id(new AphrontFormTokenizerControl()) - ->setDatasource(new DrydockLeaseDatasource()) - ->setName('leases') - ->setLabel(pht('Leases')) - ->setValue($saved->getParameter('leasePHIDs', array()))); + return $query; + } + + protected function buildCustomSearchFields() { + return array(); } protected function getURI($path) { - return '/drydock/log/'.$path; + $blueprint = $this->getBlueprint(); + if ($blueprint) { + $id = $blueprint->getID(); + return "/drydock/blueprint/{$id}/logs/{$path}"; + } + + $resource = $this->getResource(); + if ($resource) { + $id = $resource->getID(); + return "/drydock/resource/{$id}/logs/{$path}"; + } + + $lease = $this->getLease(); + if ($lease) { + $id = $lease->getID(); + return "/drydock/lease/{$id}/logs/{$path}"; + } + + throw new Exception( + pht( + 'Search engine has no blueprint, resource, or lease.')); } protected function getBuiltinQueryNames() { diff --git a/src/applications/drydock/storage/DrydockLease.php b/src/applications/drydock/storage/DrydockLease.php --- a/src/applications/drydock/storage/DrydockLease.php +++ b/src/applications/drydock/storage/DrydockLease.php @@ -347,6 +347,9 @@ $viewer = PhabricatorUser::getOmnipotentUser(); $need_update = false; + // TODO: This is just a placeholder to get some data in the table. + $this->logEvent('activated'); + $commands = id(new DrydockCommandQuery()) ->setViewer($viewer) ->withTargetPHIDs(array($this->getPHID())) @@ -371,6 +374,24 @@ } } + public function logEvent($type, array $data = array()) { + $log = id(new DrydockLog()) + ->setEpoch(PhabricatorTime::getNow()) + ->setType($type) + ->setData($data); + + $log->setLeasePHID($this->getPHID()); + + $resource = $this->getResource(); + if ($resource) { + $log->setResourcePHID($resource->getPHID()); + $log->setBlueprintPHID($resource->getBlueprintPHID()); + } + + return $log->save(); + } + + /* -( PhabricatorPolicyInterface )----------------------------------------- */ diff --git a/src/applications/drydock/storage/DrydockLog.php b/src/applications/drydock/storage/DrydockLog.php --- a/src/applications/drydock/storage/DrydockLog.php +++ b/src/applications/drydock/storage/DrydockLog.php @@ -3,28 +3,38 @@ final class DrydockLog extends DrydockDAO implements PhabricatorPolicyInterface { - protected $resourceID; - protected $leaseID; + protected $blueprintPHID; + protected $resourcePHID; + protected $leasePHID; protected $epoch; - protected $message; + protected $type; + protected $data = array(); + private $blueprint = self::ATTACHABLE; private $resource = self::ATTACHABLE; private $lease = self::ATTACHABLE; protected function getConfiguration() { return array( self::CONFIG_TIMESTAMPS => false, + self::CONFIG_SERIALIZATION => array( + 'data' => self::SERIALIZATION_JSON, + ), self::CONFIG_COLUMN_SCHEMA => array( - 'resourceID' => 'id?', - 'leaseID' => 'id?', - 'message' => 'text', + 'blueprintPHID' => 'phid?', + 'resourcePHID' => 'phid?', + 'leasePHID' => 'phid?', + 'type' => 'text64', ), self::CONFIG_KEY_SCHEMA => array( - 'resourceID' => array( - 'columns' => array('resourceID', 'epoch'), + 'key_blueprint' => array( + 'columns' => array('blueprintPHID', 'type'), + ), + 'key_resource' => array( + 'columns' => array('resourcePHID', 'type'), ), - 'leaseID' => array( - 'columns' => array('leaseID', 'epoch'), + 'key_lease' => array( + 'columns' => array('leasePHID', 'type'), ), 'epoch' => array( 'columns' => array('epoch'), @@ -33,6 +43,15 @@ ) + parent::getConfiguration(); } + public function attachBlueprint(DrydockBlueprint $blueprint = null) { + $this->blueprint = $blueprint; + return $this; + } + + public function getBlueprint() { + return $this->assertAttached($this->blueprint); + } + public function attachResource(DrydockResource $resource = null) { $this->resource = $resource; return $this; @@ -51,6 +70,22 @@ return $this->assertAttached($this->lease); } + public function isComplete() { + if ($this->getBlueprintPHID() && !$this->getBlueprint()) { + return false; + } + + if ($this->getResourcePHID() && !$this->getResource()) { + return false; + } + + if ($this->getLeasePHID() && !$this->getLease()) { + return false; + } + + return true; + } + /* -( PhabricatorPolicyInterface )----------------------------------------- */ @@ -62,21 +97,19 @@ } public function getPolicy($capability) { - if ($this->getResource()) { - return $this->getResource()->getPolicy($capability); - } - return $this->getLease()->getPolicy($capability); + // NOTE: We let you see that logs exist no matter what, but don't actually + // show you log content unless you can see all of the associated objects. + return PhabricatorPolicies::getMostOpenPolicy(); } public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { - if ($this->getResource()) { - return $this->getResource()->hasAutomaticCapability($capability, $viewer); - } - return $this->getLease()->hasAutomaticCapability($capability, $viewer); + return false; } public function describeAutomaticCapability($capability) { - return pht('Logs inherit the policy of their resources.'); + return pht( + 'To view log details, you must be able to view the associated '. + 'blueprint, resource and lease.'); } } diff --git a/src/applications/drydock/view/DrydockLogListView.php b/src/applications/drydock/view/DrydockLogListView.php --- a/src/applications/drydock/view/DrydockLogListView.php +++ b/src/applications/drydock/view/DrydockLogListView.php @@ -18,28 +18,45 @@ $rows = array(); foreach ($logs as $log) { - $resource_uri = '/drydock/resource/'.$log->getResourceID().'/'; - $lease_uri = '/drydock/lease/'.$log->getLeaseID().'/'; + $blueprint_phid = $log->getBlueprintPHID(); + if ($blueprint_phid) { + $blueprint = $viewer->renderHandle($blueprint_phid); + } else { + $blueprint = null; + } + + $resource_phid = $log->getResourcePHID(); + if ($resource_phid) { + $resource = $viewer->renderHandle($resource_phid); + } else { + $resource = null; + } + + $lease_phid = $log->getLeasePHID(); + if ($lease_phid) { + $lease = $viewer->renderHandle($lease_phid); + } else { + $lease = null; + } - $resource_name = $log->getResourceID(); - if ($log->getResourceID() !== null) { - $resource_name = $log->getResource()->getName(); + if ($log->isComplete()) { + // TODO: This is a placeholder. + $type = $log->getType(); + $data = print_r($log->getData(), true); + } else { + $type = phutil_tag('em', array(), pht('Restricted')); + $data = phutil_tag( + 'em', + array(), + pht('You do not have permission to view this log event.')); } $rows[] = array( - phutil_tag( - 'a', - array( - 'href' => $resource_uri, - ), - $resource_name), - phutil_tag( - 'a', - array( - 'href' => $lease_uri, - ), - $log->getLeaseID()), - $log->getMessage(), + $blueprint, + $resource, + $lease, + $type, + $data, phabricator_datetime($log->getEpoch(), $viewer), ); } @@ -48,22 +65,19 @@ $table->setDeviceReadyTable(true); $table->setHeaders( array( + pht('Blueprint'), pht('Resource'), pht('Lease'), - pht('Message'), + pht('Type'), + pht('Data'), pht('Date'), )); - $table->setShortHeaders( - array( - pht('R'), - pht('L'), - pht('Message'), - '', - )); $table->setColumnClasses( array( '', '', + '', + '', 'wide', '', ));