Beispiel #1
0
 /**
  * Finds cost centres by key
  * It searches by name or billing number
  *
  * @param   string    $key  optional Search key
  * @return  ArrayCollection Returns collection of the CostCentreEntity objects
  */
 public function findByKey($key = null)
 {
     if (is_null($key) || $key === '') {
         return $this->all();
     }
     $collection = new ArrayCollection();
     $ccEntity = new CostCentreEntity();
     $rs = $this->db->Execute("\n            SELECT " . $ccEntity->fields('c') . "\n            FROM " . $ccEntity->table('c') . "\n            WHERE c.`name` LIKE ?\n            OR EXISTS (\n                SELECT 1 FROM cc_properties cp\n                WHERE `cp`.cc_id = `c`.`cc_id`\n                AND `cp`.`name` = ? AND `cp`.`value` LIKE ?\n            )\n        ", ['%' . $key . '%', CostCentrePropertyEntity::NAME_BILLING_CODE, '%' . $key . '%']);
     while ($rec = $rs->FetchRow()) {
         $item = new CostCentreEntity();
         $item->load($rec);
         $collection->append($item);
     }
     return $collection;
 }
Beispiel #2
0
 /**
  * Gets a list of environments by key
  *
  * @param  string $query Search query
  * @return array  Returns array of environments
  */
 private function getEnvironmentsList($query = null)
 {
     $envs = [];
     $environments = $this->user->getEnvironments($query);
     if (count($environments) > 0) {
         $iterator = ChartPeriodIterator::create('month', gmdate('Y-m-01'), null, 'UTC');
         //It calculates usage for all provided enviroments
         $usage = $this->getContainer()->analytics->usage->getFarmData($this->user->getAccountId(), [], $iterator->getStart(), $iterator->getEnd(), [TagEntity::TAG_ID_ENVIRONMENT, TagEntity::TAG_ID_FARM]);
         //It calculates usage for previous period same days
         $prevusage = $this->getContainer()->analytics->usage->getFarmData($this->user->getAccountId(), [], $iterator->getPreviousStart(), $iterator->getPreviousEnd(), [TagEntity::TAG_ID_ENVIRONMENT, TagEntity::TAG_ID_FARM]);
         foreach ($environments as $env) {
             if (isset($usage['data'][$env['id']]['data'])) {
                 $envs[$env['id']]['topSpender'] = $this->getFarmTopSpender($usage['data'][$env['id']]['data']);
             } else {
                 $envs[$env['id']]['topSpender'] = null;
             }
             $envs[$env['id']]['name'] = $env['name'];
             $envs[$env['id']]['envId'] = $env['id'];
             $ccId = \Scalr_Environment::init()->loadById($env['id'])->getPlatformConfigValue(\Scalr_Environment::SETTING_CC_ID);
             if (!empty($ccId)) {
                 $envs[$env['id']]['ccId'] = $ccId;
                 $envs[$env['id']]['ccName'] = CostCentreEntity::findPk($ccId)->name;
             }
             $totalCost = round(isset($usage['data'][$env['id']]) ? $usage['data'][$env['id']]['cost'] : 0, 2);
             $prevCost = round(isset($prevusage['data'][$env['id']]) ? $prevusage['data'][$env['id']]['cost'] : 0, 2);
             $envs[$env['id']] = $this->getWrappedUsageData(['iterator' => $iterator, 'usage' => $totalCost, 'prevusage' => $prevCost]) + $envs[$env['id']];
         }
     }
     return array_values($envs);
 }
Beispiel #3
0
 public function _billingCode($from, $to, $action)
 {
     switch ($action) {
         case static::ACT_CONVERT_TO_OBJECT:
             /* @var $from CostCentreEntity */
             $to->billingCode = $from->getProperty(CostCentrePropertyEntity::NAME_BILLING_CODE);
             break;
         case static::ACT_CONVERT_TO_ENTITY:
             /** @var $to CostCentreEntity */
             throw new NotYetImplementedException();
             break;
         case static::ACT_GET_FILTER_CRITERIA:
             $cc = new CostCentreEntity();
             $property = new CostCentrePropertyEntity();
             return [AbstractEntity::STMT_FROM => $cc->table() . " LEFT JOIN " . $property->table() . " ON {$property->columnCcId} = {$cc->columnCcId}", AbstractEntity::STMT_WHERE => "{$property->columnName} = '" . CostCentrePropertyEntity::NAME_BILLING_CODE . "' AND {$property->columnValue} = " . $property->qstr('value', $from->billingCode)];
     }
 }
Beispiel #4
0
 public function defaultAction()
 {
     $ccs = array();
     $projects = array();
     foreach (CostCentreEntity::find([['archived' => 0]]) as $cc) {
         $ccs[$cc->ccId] = $cc->name;
     }
     foreach (ProjectEntity::find([['archived' => 0]]) as $project) {
         $projects[$project->projectId] = $project->name;
     }
     $this->response->page('ui/admin/analytics/notifications/view.js', array('notifications.ccs' => NotificationEntity::findBySubjectType(NotificationEntity::SUBJECT_TYPE_CC)->getArrayCopy(), 'notifications.projects' => NotificationEntity::findBySubjectType(NotificationEntity::SUBJECT_TYPE_PROJECT)->getArrayCopy(), 'reports' => ReportEntity::all()->getArrayCopy(), 'ccs' => $ccs, 'projects' => $projects), array(), array('ui/admin/analytics/notifications/view.css'));
 }
Beispiel #5
0
 public function defaultAction()
 {
     $ccs = array();
     $projects = array();
     foreach (CostCentreEntity::find([['archived' => 0]]) as $cc) {
         $ccs[$cc->ccId] = $cc->name;
     }
     foreach (ProjectEntity::find([['archived' => 0]]) as $project) {
         $projects[$project->projectId] = $project->name;
     }
     $this->response->page('ui/analytics/notifications/view.js', array('notifications.ccs' => array('enabled' => SettingEntity::getValue(SettingEntity::ID_NOTIFICATIONS_CCS_ENABLED), 'items' => NotificationEntity::findBySubjectType(NotificationEntity::SUBJECT_TYPE_CC)), 'notifications.projects' => array('enabled' => SettingEntity::getValue(SettingEntity::ID_NOTIFICATIONS_PROJECTS_ENABLED), 'items' => NotificationEntity::findBySubjectType(NotificationEntity::SUBJECT_TYPE_PROJECT)), 'reports' => array('enabled' => SettingEntity::getValue(SettingEntity::ID_REPORTS_ENABLED), 'items' => ReportEntity::all()), 'ccs' => $ccs, 'projects' => $projects), array(), array());
 }
Beispiel #6
0
 /**
  * Gets specified Script taking into account both scope and authentication token
  *
  * @param   string  $ccId  Unique identifier of the Cost-Center
  *
  * @return CostCentreEntity Returns the Project Entity on success
  *
  * @throws ApiErrorException
  *
  */
 public function getCostCenter($ccId)
 {
     /* @var $cc CostCentreEntity */
     $cc = CostCentreEntity::findPk($ccId);
     if (!$cc) {
         throw new ApiErrorException(404, ErrorMessage::ERR_OBJECT_NOT_FOUND, "Requested Cost Center either does not exist or is not owned by your environment.");
     }
     if (!$this->hasPermissions($cc)) {
         //Checks entity level write access permissions
         throw new ApiErrorException(403, ErrorMessage::ERR_PERMISSION_VIOLATION, "Insufficient permissions");
     }
     return $cc;
 }
Beispiel #7
0
 public function defaultAction()
 {
     $ccs = [];
     $projects = [];
     foreach (CostCentreEntity::find([['archived' => 0]]) as $cc) {
         /* @var $cc CostCentreEntity */
         $ccs[$cc->ccId] = $cc->name;
     }
     foreach (ProjectEntity::find([['archived' => 0]]) as $project) {
         /* @var $project ProjectEntity */
         $projects[$project->projectId] = $project->name;
     }
     $this->response->page('ui/admin/analytics/notifications/view.js', ['notifications.ccs' => NotificationEntity::findBySubjectType(NotificationEntity::SUBJECT_TYPE_CC)->getArrayCopy(), 'notifications.projects' => NotificationEntity::find([['subjectType' => NotificationEntity::SUBJECT_TYPE_PROJECT], ['accountId' => null]])->getArrayCopy(), 'reports' => ReportEntity::find([['accountId' => null]])->getArrayCopy(), 'ccs' => $ccs, 'projects' => $projects], [], ['ui/admin/analytics/notifications/view.css']);
 }
 /**
  * @test
  */
 public function textComplex()
 {
     $ccs = $this->listCostCenters();
     $adapter = $this->getAdapter('costCenter');
     foreach ($ccs as $cc) {
         foreach ($adapter->getRules()[ApiEntityAdapter::RULE_TYPE_FILTERABLE] as $property) {
             foreach ($this->listCostCenters([$property => $cc->{$property}]) as $filteredProject) {
                 $this->assertEquals($cc->{$property}, $filteredProject->{$property});
             }
         }
         $response = $this->getCostCenter($cc->id);
         $this->assertEquals(200, $response->status, $this->printResponseError($response));
         $dbProject = CostCentreEntity::findPk($cc->id);
         $this->assertObjectEqualsEntity($response->getBody()->data, $dbProject, $adapter);
     }
 }
Beispiel #9
0
 /**
  * Edit project action
  *
  * @param string $projectId
  * @throws Scalr_UI_Exception_NotFound
  */
 public function editAction($projectId = null)
 {
     $scope = $this->request->getScope();
     $this->request->restrictAccess(Acl::RESOURCE_ANALYTICS_ACCOUNT, Acl::PERM_ANALYTICS_ACCOUNT_MANAGE_PROJECTS);
     if (!empty($projectId)) {
         $project = $this->getContainer()->analytics->projects->get($projectId);
         if ($project->shared != ProjectEntity::SHARED_WITHIN_ACCOUNT || $project->accountId != $this->user->getAccountId()) {
             throw new Scalr_Exception_InsufficientPermissions();
         }
         $cc = $project->getCostCenter();
         $projectData = $this->getProjectData($project, true);
         //Check whether it can be removed
         try {
             $projectData['removable'] = $project->checkRemoval();
         } catch (AnalyticsException $e) {
             $projectData['removable'] = false;
             $projectData['warning'] = $e->getMessage();
         }
     } else {
         if ($scope == 'environment') {
             $cc = $this->getContainer()->analytics->ccs->get($this->getEnvironment()->getPlatformConfigValue(\Scalr_Environment::SETTING_CC_ID));
         }
         $projectData = [];
     }
     $ccs = [];
     if ($scope == 'environment') {
         $accountCcs = AccountCostCenterEntity::findOne([['accountId' => $this->user->getAccountId()], ['ccId' => $cc->ccId]]);
         if ($accountCcs instanceof AccountCostCenterEntity) {
             $ccs[$cc->ccId] = ['ccId' => $cc->ccId, 'name' => $cc->name, 'billingCode' => $cc->getProperty(CostCentrePropertyEntity::NAME_BILLING_CODE)];
         }
     } elseif ($scope == 'account') {
         foreach ($this->user->getEnvironments() as $row) {
             $env = \Scalr_Environment::init()->loadById($row['id']);
             $ccEntity = CostCentreEntity::findPk($env->getPlatformConfigValue(\Scalr_Environment::SETTING_CC_ID));
             /* @var $ccEntity \Scalr\Stats\CostAnalytics\Entity\CostCentreEntity */
             if ($ccEntity) {
                 $accountCcs = AccountCostCenterEntity::findOne([['accountId' => $env->clientId], ['ccId' => $ccEntity->ccId]]);
                 if ($accountCcs instanceof AccountCostCenterEntity) {
                     $ccs[$ccEntity->ccId] = ['ccId' => $ccEntity->ccId, 'name' => $ccEntity->name, 'billingCode' => $ccEntity->getProperty(CostCentrePropertyEntity::NAME_BILLING_CODE)];
                 }
             }
         }
     }
     $this->response->page('ui/admin/analytics/projects/edit.js', array('project' => $projectData, 'ccs' => $ccs, 'scope' => 'account'));
 }
Beispiel #10
0
 /**
  * Gets specified Script taking into account both scope and authentication token
  *
  * @param   string  $ccId  Unique identifier of the Cost-Center
  *
  * @return CostCentreEntity Returns the Project Entity on success
  *
  * @throws ApiErrorException
  *
  */
 public function getCostCenter($ccId)
 {
     //TODO: correct ACL resource
     $this->checkPermissions(Acl::RESOURCE_ANALYTICS_PROJECTS);
     if ($ccId != $this->getEnvironmentCostCenterId()) {
         throw new ApiErrorException(404, ErrorMessage::ERR_OBJECT_NOT_FOUND, "Requested Cost Center either does not exist or is not owned by your environment.");
     }
     /* @var $cc CostCentreEntity */
     $cc = CostCentreEntity::findPk($ccId);
     if (!$cc) {
         throw new ApiErrorException(404, ErrorMessage::ERR_OBJECT_NOT_FOUND, "Requested Cost Center either does not exist or is not owned by your environment.");
     }
     if (!$this->hasPermissions($cc)) {
         //Checks entity level write access permissions
         throw new ApiErrorException(403, ErrorMessage::ERR_PERMISSION_VIOLATION, "Insufficient permissions");
     }
     return $cc;
 }
Beispiel #11
0
 /**
  * Checks if user has access to project or cost center
  *
  * @param   string $projectId optional Id of the project
  * @param   string $ccId      optional Id of the cost center
  * @return  boolean           Returns false if user is not lead of the subject
  */
 public function isSubjectLead($projectId = null, $ccId = null)
 {
     if (!empty($projectId)) {
         $project = ProjectEntity::findPk($projectId);
         if (empty($project) || $project->getProperty(ProjectPropertyEntity::NAME_LEAD_EMAIL) !== $this->getEmail()) {
             return false;
         }
     } else {
         if (!empty($ccId)) {
             $ccs = CostCentreEntity::findPk($ccId);
             if (empty($ccs) || $ccs->getProperty(CostCentrePropertyEntity::NAME_LEAD_EMAIL) !== $this->getEmail()) {
                 return false;
             }
         }
     }
     return true;
 }
 /**
  * {@inheritdoc}
  * @see \Scalr\System\Pcntl\ProcessInterface::OnStartForking()
  */
 public function OnStartForking()
 {
     if (!\Scalr::getContainer()->analytics->enabled) {
         die("Terminating the process as Cost analytics is disabled in the config.\n");
     }
     $this->console->out("%s (UTC) Start Analytics Notifications process", gmdate('Y-m-d'));
     if (SettingEntity::getValue(SettingEntity::ID_NOTIFICATIONS_CCS_ENABLED) || SettingEntity::getValue(SettingEntity::ID_NOTIFICATIONS_PROJECTS_ENABLED)) {
         $this->console->out('Calculating data for projects notifications');
         $quarters = new Quarters(SettingEntity::getQuarters());
         $date = $quarters->getPeriodForDate('yesterday');
         $formatedTitle = 'Q' . $quarters->getQuarterForDate('now') . ' budget (' . (new \DateTime('now', new \DateTimeZone('UTC')))->format('M j, Y') . ')';
         $projects = ProjectEntity::find();
         foreach ($projects as $project) {
             $periodProjectData = \Scalr::getContainer()->analytics->usage->getProjectPeriodData($project->projectId, 'quarter', $date->start->format('Y-m-d'), $date->end->format('Y-m-d'));
             $projectAnalytics[$project->projectId] = ['budget' => $periodProjectData['totals']['budget'], 'name' => $project->name, 'trends' => $periodProjectData['totals']['trends'], 'forecastCost' => $periodProjectData['totals']['forecastCost'], 'interval' => $periodProjectData['interval'], 'jsonVersion' => '1.0.0', 'farms' => []];
             if (!empty($periodProjectData['totals']['farms'])) {
                 foreach ($periodProjectData['totals']['farms'] as $farm) {
                     $projectAnalytics[$project->projectId]['farms'][] = ['id' => $farm['id'], 'name' => $farm['name'], 'median' => $farm['median'] / 7, 'cost' => $farm['cost'], 'costPct' => $farm['costPct']];
                 }
                 if (count($projectAnalytics[$project->projectId]['farms'] > 1)) {
                     usort($projectAnalytics[$project->projectId]['farms'], array($this, 'sortItems'));
                     if (count($projectAnalytics[$project->projectId]['farms'] > 6)) {
                         array_splice($projectAnalytics[$project->projectId]['farms'], 6, count($projectAnalytics[$project->projectId]['farms']));
                     }
                 }
             }
             $projectAnalytics[$project->projectId]['date'] = $formatedTitle;
             if ($project->archived) {
                 continue;
             }
             if (SettingEntity::getValue(SettingEntity::ID_NOTIFICATIONS_PROJECTS_ENABLED)) {
                 $projectNotifications = NotificationEntity::findBySubjectType(NotificationEntity::SUBJECT_TYPE_PROJECT);
                 foreach ($projectNotifications as $notification) {
                     $this->saveNotificationData('project', $notification, $project->projectId, $projectAnalytics);
                 }
             }
         }
     }
     if (SettingEntity::getValue(SettingEntity::ID_NOTIFICATIONS_CCS_ENABLED)) {
         $this->console->out('Calculating data for cost center notifications');
         $ccs = CostCentreEntity::find();
         foreach ($ccs as $cc) {
             if ($cc->archived) {
                 continue;
             }
             $periodCostCenterData = \Scalr::getContainer()->analytics->usage->getCostCenterPeriodData($cc->ccId, 'quarter', $date->start->format('Y-m-d'), $date->end->format('Y-m-d'));
             $ccAnalytics[$cc->ccId] = ['budget' => $periodCostCenterData['totals']['budget'], 'name' => $cc->name, 'trends' => $periodCostCenterData['totals']['trends'], 'forecastCost' => $periodCostCenterData['totals']['forecastCost'], 'interval' => $periodCostCenterData['interval'], 'jsonVersion' => '1.0.0', 'projects' => []];
             if (!empty($periodCostCenterData['totals']['projects'])) {
                 foreach ($periodCostCenterData['totals']['projects'] as $key => $project) {
                     if (!empty($project['id'])) {
                         $projectBudget = $projectAnalytics[$project['id']]['budget'];
                         $projectBudget['name'] = $project['name'];
                         $projectBudget['id'] = $project['id'];
                         $projectBudget['median'] = $project['median'] / 7;
                         $ccAnalytics[$cc->ccId]['projects'][] = $projectBudget;
                     } else {
                         $otherProjectsKey = $key;
                     }
                 }
                 if (isset($otherProjectsKey)) {
                     $ccAnalytics[$cc->ccId]['projects'][] = ['id' => '', 'budgetSpent' => $periodCostCenterData['totals']['projects'][$otherProjectsKey]['cost'], 'median' => $periodCostCenterData['totals']['projects'][$otherProjectsKey]['median'] / 7, 'name' => $periodCostCenterData['totals']['projects'][$otherProjectsKey]['name'], 'estimateOverspend' => null];
                     unset($otherProjectsKey);
                 }
                 if (count($ccAnalytics[$cc->ccId]['projects'] > 1)) {
                     usort($ccAnalytics[$cc->ccId]['projects'], array($this, 'sortItems'));
                     if (count($ccAnalytics[$cc->ccId]['projects'] > 6)) {
                         array_splice($ccAnalytics[$cc->ccId]['projects'], 6, count($ccAnalytics[$cc->ccId]['projects']));
                     }
                 }
             }
             $ccAnalytics[$cc->ccId]['date'] = $formatedTitle;
             $ccsNotifications = NotificationEntity::findBySubjectType(NotificationEntity::SUBJECT_TYPE_CC);
             foreach ($ccsNotifications as $notification) {
                 $this->saveNotificationData('cc', $notification, $cc->ccId, $ccAnalytics);
             }
         }
     }
     if (SettingEntity::getValue(SettingEntity::ID_REPORTS_ENABLED)) {
         $this->console->out('Calculating data for reports');
         $reports = ReportEntity::find();
         foreach ($reports as $report) {
             switch ($report->period) {
                 case ReportEntity::PERIOD_DAILY:
                     $period = 'custom';
                     $start = (new \DateTime('yesterday', new \DateTimeZone('UTC')))->format('Y-m-d');
                     $end = $start;
                     $startForecast = (new \DateTime('first day of this month', new \DateTimeZone('UTC')))->format('Y-m-d');
                     $endForecast = (new \DateTime('last day of this month', new \DateTimeZone('UTC')))->format('Y-m-d');
                     if ($startForecast == (new \DateTime('now', new \DateTimeZone('UTC')))->format('Y-m-d')) {
                         $startForecast = (new \DateTime('first day of last month', new \DateTimeZone('UTC')))->format('Y-m-d');
                         $endForecast = (new \DateTime('last day of last month', new \DateTimeZone('UTC')))->format('Y-m-d');
                     }
                     $periodForecast = 'month';
                     $formatedTitle = (new \DateTime($start, new \DateTimeZone('UTC')))->format('M j');
                     break;
                 case ReportEntity::PERIOD_MONTHLY:
                     $period = 'month';
                     $start = (new \DateTime('first day of last month', new \DateTimeZone('UTC')))->format('Y-m-d');
                     $end = (new \DateTime('last day of last month', new \DateTimeZone('UTC')))->format('Y-m-d');
                     $quarters = new Quarters(SettingEntity::getQuarters());
                     $currentQuarter = $quarters->getQuarterForDate(new \DateTime($start, new \DateTimeZone('UTC')));
                     $currentYear = (new \DateTime($start, new \DateTimeZone('UTC')))->format('Y');
                     $date = $quarters->getPeriodForQuarter($currentQuarter, $currentYear);
                     $formatedTitle = (new \DateTime($start, new \DateTimeZone('UTC')))->format('M Y');
                     $startForecast = $date->start->format('Y-m-d');
                     $endForecast = $date->end->format('Y-m-d');
                     $periodForecast = 'quarter';
                     break;
                 case ReportEntity::PERIOD_QUARTELY:
                     $period = 'quarter';
                     $quarters = new Quarters(SettingEntity::getQuarters());
                     $currentQuarter = $quarters->getQuarterForDate(new \DateTime('yesterday', new \DateTimeZone('UTC')));
                     $currentYear = (new \DateTime('yesterday', new \DateTimeZone('UTC')))->format('Y');
                     if ($currentQuarter === 1) {
                         $quarter = 4;
                         $year = $currentYear - 1;
                     } else {
                         $quarter = $currentQuarter - 1;
                         $year = $currentYear;
                     }
                     $date = $quarters->getPeriodForQuarter($quarter, $year);
                     $start = $date->start->format('Y-m-d');
                     $end = $date->end->format('Y-m-d');
                     $formatedTitle = 'Q' . $quarter . ' ' . $year;
                     $startForecast = $currentYear . '-01-01';
                     $endForecast = $currentYear . '-12-31';
                     $periodForecast = 'year';
                     break;
                 case ReportEntity::PERIOD_WEEKLY:
                     $period = 'week';
                     $end = (new \DateTime('yesterday', new \DateTimeZone('UTC')))->modify('last saturday')->format('Y-m-d');
                     $start = (new \DateTime($end, new \DateTimeZone('UTC')))->modify('last sunday')->format('Y-m-d');
                     $formatedTitle = (new \DateTime($start, new \DateTimeZone('UTC')))->format('M j') . ' - ' . (new \DateTime($end, new \DateTimeZone('UTC')))->format('M j');
                     $startForecast = (new \DateTime('first day of this month', new \DateTimeZone('UTC')))->format('Y-m-d');
                     $endForecast = (new \DateTime('last day of this month', new \DateTimeZone('UTC')))->format('Y-m-d');
                     if ($startForecast == (new \DateTime('now', new \DateTimeZone('UTC')))->format('Y-m-d')) {
                         $startForecast = (new \DateTime('first day of last month', new \DateTimeZone('UTC')))->format('Y-m-d');
                         $endForecast = (new \DateTime('last day of last month', new \DateTimeZone('UTC')))->format('Y-m-d');
                     }
                     $periodForecast = 'month';
                     break;
             }
             if ($report->subjectType === ReportEntity::SUBJECT_TYPE_CC) {
                 $getPeriodicSubjectData = 'getCostCenterPeriodData';
                 $subjectEntityName = 'Scalr\\Stats\\CostAnalytics\\Entity\\CostCentre';
                 $subjectId = 'ccId';
             } else {
                 if ($report->subjectType === ReportEntity::SUBJECT_TYPE_PROJECT) {
                     $getPeriodicSubjectData = 'getProjectPeriodData';
                     $subjectEntityName = 'Scalr\\Stats\\CostAnalytics\\Entity\\Project';
                     $subjectId = 'projectId';
                 } else {
                     $periodData = \Scalr::getContainer()->analytics->usage->getDashboardPeriodData($period, $start, $end);
                     $periodDataForecast = \Scalr::getContainer()->analytics->usage->getDashboardPeriodData($periodForecast, $startForecast, $endForecast);
                     $periodData['period'] = $period;
                     $periodData['forecastPeriod'] = $periodForecast;
                     $periodData['totals']['forecastCost'] = $periodDataForecast['totals']['forecastCost'];
                     $periodData['totals']['trends'] = $periodDataForecast['totals']['trends'];
                     $periodData['name'] = 'Cloud Cost Report';
                     $periodData['jsonVersion'] = '1.0.0';
                     $periodData['totals']['clouds'] = $this->changeCloudNames($periodData['totals']['clouds']);
                     $periodData['date'] = $formatedTitle;
                     $periodData['totals']['budget']['budget'] = null;
                     if ($period == 'quarter') {
                         $periodData['totals']['budget'] = ['quarter' => $quarter, 'year' => $year, 'quarterStartDate' => $start, 'quarterEndDate' => $end];
                     } else {
                         if ($period == 'month') {
                             $periodData['totals']['budget'] = ['quarter' => $currentQuarter];
                         }
                     }
                     unset($periodData['projects'], $periodData['budget']['projects']);
                     if (count($periodData['costcenters'] > 1)) {
                         uasort($periodData['costcenters'], array($this, 'sortItems'));
                         if (count($periodData['costcenters'] > 6)) {
                             array_splice($periodData['costcenters'], 6, count($periodData['costcenters']));
                         }
                     }
                     if (count($periodData['totals']['clouds'] > 1)) {
                         usort($periodData['totals']['clouds'], array($this, 'sortItems'));
                     }
                     $entity = ReportPayloadEntity::init([$report->subjectType, $report->subjectId, $period], $periodData, $start);
                     if (!ReportPayloadEntity::findPk($entity->uuid)) {
                         $payload = json_decode($entity->payload, true);
                         \Scalr::getContainer()->mailer->setSubject('Summary report.')->setContentType('text/html')->sendTemplate(SCALR_TEMPLATES_PATH . '/emails/report_summary.html.php', $payload, $report->emails);
                         $this->console->out('Summary report email has been sent');
                         $payload['date'] = $entity->created->format('Y-m-d');
                         $entity->payload = json_encode($payload);
                         $entity->save();
                     }
                 }
             }
             unset($currentQuarter, $currentYear);
             if (!empty($report->subjectType) && !empty($report->subjectId)) {
                 $subject = call_user_func($subjectEntityName . 'Entity::findPk', $report->subjectId);
                 if ($subject->archived) {
                     continue;
                 }
                 $this->saveReportData($getPeriodicSubjectData, $subjectEntityName, ['period' => $period, 'start' => $start, 'end' => $end], ['period' => $periodForecast, 'start' => $startForecast, 'end' => $endForecast], $report->subjectId, $report->subjectType, $report->emails, $formatedTitle);
             } else {
                 if (!empty($report->subjectType)) {
                     $subjects = call_user_func($subjectEntityName . 'Entity::find');
                     foreach ($subjects as $subject) {
                         if ($subject->archived) {
                             continue;
                         }
                         $this->saveReportData($getPeriodicSubjectData, $subjectEntityName, ['period' => $period, 'start' => $start, 'end' => $end], ['period' => $periodForecast, 'start' => $startForecast, 'end' => $endForecast], $subject->{$subjectId}, $report->subjectType, $report->emails, $formatedTitle);
                     }
                 }
             }
         }
     }
     $this->console->out('Done');
     exit;
 }
Beispiel #13
0
 /**
  * Gets parent Cost Center
  *
  * @return CostCentreEntity Returns cost centre entity
  */
 public function getCostCenter()
 {
     if ($this->_cc === null || $this->_cc->ccId != $this->ccId) {
         $this->_cc = CostCentreEntity::findPk($this->ccId);
     }
     return $this->_cc;
 }
Beispiel #14
0
 /**
  * @test
  */
 public function textAccountComplex()
 {
     $ccsArch = $this->createCostCenter(['name' => $this->getTestName(), 'archived' => CostCentreEntity::ARCHIVED]);
     $ccs = $this->listCostCenters([], false);
     $adapter = $this->getAdapter('costCenter');
     $filterable = $adapter->getRules()[ApiEntityAdapter::RULE_TYPE_FILTERABLE];
     foreach ($ccs as $cc) {
         foreach ($filterable as $property) {
             $filterValue = $cc->{$property};
             $listResult = $this->listCostCenters([$property => $filterValue], false);
             if (!static::isRecursivelyEmpty($filterValue)) {
                 foreach ($listResult as $filtered) {
                     $this->assertEquals($filterValue, $filtered->{$property}, "Property '{$property}' mismatch");
                 }
             }
         }
         $response = $this->getCostCenter($cc->id, false);
         $this->assertEquals(200, $response->status, $this->printResponseError($response));
         /* @var $dbCc CostCentreEntity */
         $dbCc = CostCentreEntity::findPk($cc->id);
         /* @var $acCs AccountCostCenterEntity */
         $acCs = AccountCostCenterEntity::findOne([['ccId' => $dbCc->ccId]]);
         $this->assertFalse($dbCc->archived);
         $this->assertEquals($this->getUser()->accountId, $acCs->accountId);
         $this->assertObjectEqualsEntity($response->getBody()->data, $dbCc, $adapter);
     }
     $filterByName = $this->listCostCenters(['name' => $ccsArch->name], false);
     $this->assertNotEmpty($filterByName);
     foreach ($filterByName as $cc) {
         $this->assertObjectEqualsEntity($cc, $ccsArch, $adapter);
         $this->assertNotContains($cc, $ccs, "List of Cost Centers shouldn't  have an archived project", false, false);
     }
     $filterByBillingCode = $this->listCostCenters(['billingCode' => $ccsArch->getProperty(CostCentrePropertyEntity::NAME_BILLING_CODE)], false);
     $this->assertNotEmpty($filterByBillingCode);
     foreach ($filterByBillingCode as $cc) {
         $this->assertObjectEqualsEntity($cc, $ccsArch, $adapter);
         $this->assertNotContains($cc, $ccs, "List of Cost Centers shouldn't  have an archived project", false, false);
     }
 }
Beispiel #15
0
 /**
  * xMoveProjectsAction
  *
  * @param JsonData $projects Projects that should be moved
  * @throws AnalyticsException
  * @throws Exception
  * @throws \Scalr\Exception\ModelException
  */
 public function xMoveProjectsAction(JsonData $projects = null)
 {
     $envChange = [];
     $accountChange = [];
     $projectChange = [];
     $ccEntityCache = [];
     $collisions = [];
     foreach ($projects as $project) {
         $projectEntity = ProjectEntity::findPk($project['projectId']);
         /* @var $projectEntity ProjectEntity */
         if (empty($ccEntity)) {
             $ccEntity = $projectEntity->getCostCenter();
         }
         if ($ccEntity->ccId == $project['ccId']) {
             continue;
         }
         if (empty($ccEntityCache[$project['ccId']])) {
             $newCcEntity = CostCentreEntity::findPk($project['ccId']);
             /* @var $newCcEntity CostCentreEntity */
             if (!$newCcEntity) {
                 throw new Exception(sprintf("Cost center with id %s has not been found.", $project['ccId']), 404);
             }
             $ccEntityCache[$project['ccId']] = $newCcEntity->ccId;
         }
         $farms[$projectEntity->projectId] = $projectEntity->getFarmsList();
         foreach ($farms[$projectEntity->projectId] as $farmId => $farmName) {
             $farmEntity = Farm::findPk($farmId);
             /* @var $farmEntity Farm */
             if (empty($accountChange[$farmEntity->accountId])) {
                 $accountCss = AccountCostCenterEntity::findOne([['accountId' => $farmEntity->accountId], ['ccId' => $newCcEntity->ccId]]);
                 if (!$accountCss) {
                     $accountChange[$farmEntity->accountId] = $newCcEntity->ccId;
                 }
             }
             if (empty($envChange[$farmEntity->envId])) {
                 $project['name'] = $projectEntity->name;
                 $envChange[$farmEntity->envId] = $project;
             } else {
                 if ($envChange[$farmEntity->envId]['ccId'] != $project['ccId']) {
                     if (!in_array($projectEntity->name, $collisions)) {
                         $collisions[] = $projectEntity->name;
                     }
                     if (!in_array($envChange[$farmEntity->envId]['name'], $collisions)) {
                         $collisions[] = $envChange[$farmEntity->envId]['name'];
                     }
                     continue;
                 }
             }
         }
         $projectEntity->ccId = $project['ccId'];
         $projectChange[$projectEntity->projectId] = $projectEntity;
     }
     $remainningEnvs = [];
     $projectsCount = count($projectChange);
     if ($projectsCount) {
         if (isset($ccEntity)) {
             $envList = $ccEntity->getEnvironmentsList();
             foreach ($envList as $envId => $name) {
                 if (isset($envChange[$envId])) {
                     $ccProjects = $this->getContainer()->analytics->projects->getUsedInEnvironment($envId);
                     foreach ($ccProjects as $project) {
                         /* @var $project ProjectEntity */
                         if (!isset($farms[$project->projectId])) {
                             $farms[$project->projectId] = $project->getFarmsList();
                         }
                         if (count($farms[$project->projectId]) > 0 && !isset($projectChange[$project->projectId])) {
                             if (!in_array($envId, $remainningEnvs)) {
                                 $remainningEnvs[] = $envId;
                             }
                         }
                     }
                 }
             }
         }
         $this->db->BeginTrans();
         try {
             foreach ($accountChange as $accountId => $ccId) {
                 $accountCss = new AccountCostCenterEntity($accountId, $ccId);
                 $accountCss->save();
             }
             if (empty($remainningEnvs) && empty($collisions)) {
                 foreach ($envChange as $envId => $data) {
                     $envProp = EnvironmentProperty::findOne([['envId' => $envId], ['name' => EnvironmentProperty::SETTING_CC_ID]]);
                     /* @var $envProp EnvironmentProperty */
                     $envProp->value = $data['ccId'];
                     $envProp->save();
                 }
             }
             foreach ($projectChange as $project) {
                 /* @var $project ProjectEntity */
                 $project->save();
             }
             $this->db->CommitTrans();
         } catch (Exception $e) {
             $this->db->RollbackTrans();
             throw $e;
         }
     }
     if (count($collisions) > 0) {
         $this->response->warning(sprintf("%d Project%s %s been moved however collision occurred. Projects '%s' are used in the Farms from the same Environment however they have been moved to different Cost Centers.", $projectsCount, $projectsCount > 1 ? 's' : '', $projectsCount > 1 ? 'have' : 'has', implode("', '", $collisions)));
     } else {
         if (count($remainningEnvs) > 0) {
             $this->response->warning(sprintf("%d Project%s %s been moved however some Projects don't correspond to Cost Centers assigned to Environments '%s'.", $projectsCount, $projectsCount > 1 ? 's' : '', $projectsCount > 1 ? 'have' : 'has', implode("', '", $remainningEnvs)));
         } else {
             $this->response->success(sprintf("%d Project%s %s been moved to other Cost Center.", $projectsCount, $projectsCount > 1 ? 's' : '', $projectsCount > 1 ? 'have' : 'has'));
         }
     }
 }
Beispiel #16
0
 /**
  * Gets the list of the Cost Centers which correspond to Account
  *
  * @return  \Scalr\Model\Collections\ArrayCollection  Returns collection of the entities
  */
 public function getCostCenters()
 {
     $ccs = new ArrayCollection();
     foreach (AccountCostCenterEntity::findByAccountId($this->id) as $accountCc) {
         $cc = CostCentreEntity::findPk($accountCc->ccId);
         if (!$cc instanceof CostCentreEntity) {
             continue;
         }
         $ccs->append($cc);
     }
     return $ccs;
 }
Beispiel #17
0
 public function applyGlobalVarsToValue($value)
 {
     if (empty($this->globalVariablesCache)) {
         $formats = \Scalr::config("scalr.system.global_variables.format");
         $at = new Entity\Account\Team();
         $ft = new Entity\FarmTeam();
         $teams = Entity\Account\Team::find([\Scalr\Model\AbstractEntity::STMT_FROM => "{$at->table()} JOIN {$ft->table()} ON {$ft->columnTeamId} = {$at->columnId}", \Scalr\Model\AbstractEntity::STMT_WHERE => "{$ft->columnFarmId} = '{$this->ID}'"])->map(function ($t) {
             return $t->name;
         });
         $systemVars = array('env_id' => $this->EnvID, 'env_name' => $this->GetEnvironmentObject()->name, 'farm_team' => join(",", $teams), 'farm_id' => $this->ID, 'farm_name' => $this->Name, 'farm_hash' => $this->Hash, 'farm_owner_email' => $this->createdByUserEmail);
         if (\Scalr::getContainer()->analytics->enabled) {
             $projectId = $this->GetSetting(Entity\FarmSetting::PROJECT_ID);
             if ($projectId) {
                 $project = ProjectEntity::findPk($projectId);
                 /* @var $project ProjectEntity */
                 $systemVars['project_id'] = $projectId;
                 $systemVars['project_bc'] = $project->getProperty(ProjectPropertyEntity::NAME_BILLING_CODE);
                 $systemVars['project_name'] = $project->name;
                 $ccId = $project->ccId;
             }
             if ($ccId) {
                 $cc = CostCentreEntity::findPk($ccId);
                 if ($cc) {
                     /* @var $cc CostCentreEntity */
                     $systemVars['cost_center_id'] = $ccId;
                     $systemVars['cost_center_bc'] = $cc->getProperty(CostCentrePropertyEntity::NAME_BILLING_CODE);
                     $systemVars['cost_center_name'] = $cc->name;
                 } else {
                     throw new Exception("Cost center {$ccId} not found");
                 }
             }
         }
         // Get list of Server system vars
         foreach ($systemVars as $name => $val) {
             $name = "SCALR_" . strtoupper($name);
             $val = trim($val);
             if (isset($formats[$name])) {
                 $val = @sprintf($formats[$name], $val);
             }
             $this->globalVariablesCache[$name] = $val;
         }
         // Add custom variables
         $gv = new Scalr_Scripting_GlobalVariables($this->ClientID, $this->EnvID, ScopeInterface::SCOPE_FARM);
         $vars = $gv->listVariables(0, $this->ID);
         foreach ($vars as $v) {
             $this->globalVariablesCache[$v['name']] = $v['value'];
         }
     }
     //Parse variable
     $keys = array_keys($this->globalVariablesCache);
     $keys = array_map(function ($item) {
         return '{' . $item . '}';
     }, $keys);
     $values = array_values($this->globalVariablesCache);
     $retval = str_replace($keys, $values, $value);
     // Strip undefined variables & return value
     return preg_replace("/{[A-Za-z0-9_-]+}/", "", $retval);
 }
Beispiel #18
0
 /**
  * Creates default Cost Center for the Hosted Scalr new account
  *
  * @param    Scalr_Account      $account  The account object
  * @param    Scalr_Account_User $user     optional The account owner user
  * @return   CostCentreEntity   Returns a new Cost Center
  */
 public function createHostedScalrAccountCostCenter(Scalr_Account $account, Scalr_Account_User $user = null)
 {
     if (!$user instanceof Scalr_Account_User) {
         $user = $account->getOwner();
     }
     //New Cost Center should be created in account share mode
     $cc = new CostCentreEntity();
     $cc->ccId = \Scalr::GenerateUID();
     $cc->accountId = $account->id;
     $cc->createdByEmail = $user->getEmail();
     $cc->name = "Cost Center " . $account->name . " (" . $account->id . ")";
     $cc->createdById = $user->id;
     $cc->save();
     $cc->saveProperty(CostCentrePropertyEntity::NAME_BILLING_CODE, "CC-" . $account->name);
     $cc->saveProperty(CostCentrePropertyEntity::NAME_DESCRIPTION, "This Cost Center was added automatically.");
     $cc->saveProperty(CostCentrePropertyEntity::NAME_LEAD_EMAIL, $user->getEmail());
     $cc->saveProperty(CostCentrePropertyEntity::NAME_LOCKED, false);
     //A new Project which corresponds to Cost Center (in account share mode as well)
     $project = new ProjectEntity();
     $project->projectId = \Scalr::GenerateUID();
     $project->ccId = $cc->ccId;
     $project->name = "Project " . $account->name . " (" . $account->id . ")";
     $project->accountId = $account->id;
     $project->createdByEmail = $user->getEmail();
     $project->shared = ProjectEntity::SHARED_WITHIN_ACCOUNT;
     $project->createdById = $user->id;
     $project->save();
     $project->saveProperty(ProjectPropertyEntity::NAME_BILLING_CODE, "PR-" . $account->name);
     $project->saveProperty(ProjectPropertyEntity::NAME_DESCRIPTION, "This Project was added automatically.");
     $project->saveProperty(ProjectPropertyEntity::NAME_LEAD_EMAIL, $user->getEmail());
     if (\Scalr::getContainer()->analytics->enabled) {
         \Scalr::getContainer()->analytics->tags->syncValue($account->id, TagEntity::TAG_ID_COST_CENTRE, $cc->ccId, $cc->name);
         \Scalr::getContainer()->analytics->tags->syncValue($account->id, TagEntity::TAG_ID_PROJECT, $project->projectId, $project->name);
     }
     return $cc;
 }
Beispiel #19
0
 /**
  * xGetPeriodLogAction
  *
  * @param   string    $mode      The mode (week, month, quarter, year)
  * @param   string    $startDate The start date of the period in UTC ('Y-m-d')
  * @param   string    $endDate   The end date of the period in UTC ('Y-m-d')
  * @param   string    $type      Type of the data gathered in log file (farms, clouds, projects)
  * @param   string    $ccId      optional The identifier of the cost center
  * @param   string    $projectId optional The identifier of the project
  */
 public function xGetPeriodCsvAction($mode, $startDate, $endDate, $type, $ccId = null, $projectId = null)
 {
     $name = 'Cloud';
     if (!empty($ccId) && empty($projectId)) {
         $data = $this->getContainer()->analytics->usage->getCostCenterPeriodData($ccId, $mode, $startDate, $endDate);
         $entity = CostCentreEntity::findPk($ccId);
         if ($type !== 'clouds') {
             $name = 'Project';
             $extraFields = 'Cost Center name;Billing code;Lead email address;';
         }
     } else {
         if (!empty($projectId)) {
             $data = $this->getContainer()->analytics->usage->getProjectPeriodData($projectId, $mode, $startDate, $endDate);
             $entity = ProjectEntity::findPk($projectId);
             if ($type !== 'clouds') {
                 $name = 'Farm';
                 $extraFields = 'Project name;Billing code;Lead email address;';
             }
         } else {
             throw new \InvalidArgumentException(sprintf("Method %s requires both ccId or projectId to be specified.", __METHOD__));
         }
     }
     $extraData = [$entity->name, $entity->getProperty('billing.code'), $entity->getProperty('lead.email')];
     $head[] = $name;
     $end[] = "Total spent";
     if (isset($extraFields)) {
         $head = array_merge($head, $extraData);
         $end = array_merge($end, $extraData);
     }
     $totals = 0;
     foreach ($data['timeline'] as $timeline) {
         $totals += $timeline['cost'];
         $head[] = $timeline['label'];
         $end[] = $timeline['cost'];
     }
     $head[] = 'Total';
     $end[] = $totals;
     $temp = tmpfile();
     fputcsv($temp, $head);
     foreach ($data[$type] as $item) {
         $row = [];
         $row[] = $item['name'];
         $dataCost = [];
         foreach ($data['timeline'] as $key => $value) {
             $dataCost[] = isset($item['data'][$key]['cost']) ? $item['data'][$key]['cost'] : 0;
         }
         $itemTotal = array_sum($dataCost);
         if (isset($extraFields)) {
             $row = array_merge($row, $extraData);
         }
         $row = array_merge($row, $dataCost);
         $row[] = $itemTotal;
         fputcsv($temp, $row);
     }
     fputcsv($temp, $end);
     $metadata = stream_get_meta_data($temp);
     $label = Scalr_Util_DateTime::convertTz(time(), 'M_j_Y_H:i:s');
     $fileName = $entity->name . '.' . $entity->getProperty('billing.code') . '.' . $type . '.' . $label;
     $bad = array_merge(array_map('chr', range(0, 31)), ["<", ">", ":", '"', "/", "\\", "|", "?", "*"]);
     $fileName = str_replace($bad, "", $fileName);
     $this->response->setHeader('Content-Encoding', 'utf-8');
     $this->response->setHeader('Content-Type', 'text/csv', true);
     $this->response->setHeader('Expires', 'Mon, 10 Jan 1997 08:00:00 GMT');
     $this->response->setHeader('Pragma', 'no-cache');
     $this->response->setHeader('Cache-Control', 'no-store, no-cache, must-revalidate');
     $this->response->setHeader('Cache-Control', 'post-check=0, pre-check=0');
     $this->response->setHeader('Content-Disposition', 'attachment; filename=' . $fileName . ".csv");
     $this->response->setResponse(file_get_contents($metadata['uri']));
     fclose($temp);
 }
Beispiel #20
0
 /**
  * Finds projects by key
  * It searches by name or billing number
  *
  * @param   string    $key  optional Search key
  * @return  ArrayCollection Returns collection of the ProjectEntity objects
  */
 public function findByKey($key = null)
 {
     if (is_null($key) || $key === '') {
         return $this->all();
     }
     $collection = new ArrayCollection();
     $projectEntity = new ProjectEntity();
     //Includes archived projects
     $projectPropertyEntity = new ProjectPropertyEntity();
     //Cost center entity
     $ccEntity = new CostCentreEntity();
     $rs = $this->db->Execute("\n            SELECT " . $projectEntity->fields('p') . ", " . $ccEntity->fields('c', true) . "\n            FROM " . $projectEntity->table('p') . "\n            LEFT JOIN " . $ccEntity->table('c') . " ON c.`cc_id` = p.`cc_id`\n            WHERE p.`name` LIKE ?\n            OR EXISTS (\n                SELECT 1 FROM " . $projectPropertyEntity->table('pp') . "\n                WHERE `pp`.project_id = `p`.`project_id`\n                AND `pp`.`name` = ? AND `pp`.`value` LIKE ?\n            )\n        ", ['%' . $key . '%', ProjectPropertyEntity::NAME_BILLING_CODE, '%' . $key . '%']);
     while ($rec = $rs->FetchRow()) {
         $item = new ProjectEntity();
         $item->load($rec);
         if ($rec['c_cc_id']) {
             $cc = new CostCentreEntity();
             $cc->load($rec, 'c');
             $item->setCostCenter($cc);
         }
         $collection->append($item);
     }
     return $collection;
 }
Beispiel #21
0
 protected function isApplied1($stage)
 {
     return CostCentreEntity::findPk(Usage::DEFAULT_CC_ID) !== null && ProjectEntity::findPk(Usage::DEFAULT_PROJECT_ID) !== null;
 }
Beispiel #22
0
 protected function run7($stage)
 {
     if ($this->getCountOfAccountTagValues(TagEntity::TAG_ID_COST_CENTRE) && $this->console->confirm('Would you like to remove old cost centres from account_tag_values?')) {
         $this->console->out("Removing old cost centres");
         $this->db->Execute("DELETE FROM account_tag_values WHERE tag_id = ?", array(TagEntity::TAG_ID_COST_CENTRE));
     }
     $this->console->out('Populating cost centres to the dictionary');
     foreach (CostCentreEntity::all() as $ccEntity) {
         /* @var $ccEntity CostCentreEntity */
         $this->db->Execute("\n                INSERT IGNORE `account_tag_values` (`account_id`, `tag_id`, `value_id`, `value_name`)\n                VALUES (?, ?, ?, ?)\n            ", [$ccEntity->accountId ?: 0, TagEntity::TAG_ID_COST_CENTRE, $ccEntity->ccId, $ccEntity->name]);
     }
 }
Beispiel #23
0
 /**
  *
  * @return array
  */
 public function GetScriptingVars()
 {
     $dbFarmRole = $this->GetFarmRoleObject();
     $roleId = $dbFarmRole->RoleID;
     $dbRole = DBRole::loadById($roleId);
     $isDbMsr = $dbRole->getDbMsrBehavior();
     if ($isDbMsr) {
         $isMaster = $this->GetProperty(Scalr_Db_Msr::REPLICATION_MASTER);
     } else {
         $isMaster = $this->GetProperty(\SERVER_PROPERTIES::DB_MYSQL_MASTER);
     }
     $retval = array('image_id' => $dbRole->__getNewRoleObject()->getImage($this->platform, $dbFarmRole->CloudLocation)->imageId, 'external_ip' => $this->remoteIp, 'internal_ip' => $this->localIp, 'role_name' => $dbRole->name, 'isdbmaster' => $isMaster, 'instance_index' => $this->index, 'instance_farm_index' => $this->farmIndex, 'server_type' => $this->type, 'server_hostname' => $this->GetProperty(Scalr_Role_Behavior::SERVER_BASE_HOSTNAME), 'server_id' => $this->serverId, 'farm_id' => $this->farmId, 'farm_role_id' => $this->farmRoleId, 'farm_role_alias' => $this->GetFarmRoleObject()->Alias, 'farm_name' => $this->GetFarmObject()->Name, 'farm_hash' => $this->GetFarmObject()->Hash, 'farm_owner_email' => $this->GetFarmObject()->createdByUserEmail, 'farm_team' => $this->GetFarmObject()->teamId ? (new Scalr_Account_Team())->loadById($this->GetFarmObject()->teamId)->name : '', 'behaviors' => implode(",", $dbRole->getBehaviors()), 'env_id' => $this->GetEnvironmentObject()->id, 'env_name' => $this->GetEnvironmentObject()->name, 'cloud_location' => $this->GetCloudLocation(), 'cloud_server_id' => $this->GetCloudServerID());
     if ($this->cloudLocationZone) {
         $retval['cloud_location_zone'] = $this->cloudLocationZone;
     }
     if ($this->platform == SERVER_PLATFORMS::EC2) {
         $retval['instance_id'] = $this->GetProperty(EC2_SERVER_PROPERTIES::INSTANCE_ID);
         $retval['ami_id'] = $this->GetProperty(EC2_SERVER_PROPERTIES::AMIID);
         $retval['region'] = $this->GetProperty(EC2_SERVER_PROPERTIES::REGION);
         $retval['avail_zone'] = $this->GetProperty(EC2_SERVER_PROPERTIES::AVAIL_ZONE);
         if ($dbFarmRole->GetSetting(Entity\FarmRoleSetting::AWS_ELB_ENABLED)) {
             $elbId = $dbFarmRole->GetSetting(Entity\FarmRoleSetting::AWS_ELB_ID);
             $retval['aws_elb_name'] = $elbId;
         }
     }
     if (\Scalr::getContainer()->analytics->enabled) {
         $ccId = $this->GetProperty(\SERVER_PROPERTIES::ENV_CC_ID);
         if ($ccId) {
             $cc = CostCentreEntity::findPk($ccId);
             if ($cc) {
                 /* @var $cc CostCentreEntity */
                 $retval['cost_center_id'] = $ccId;
                 $retval['cost_center_bc'] = $cc->getProperty(CostCentrePropertyEntity::NAME_BILLING_CODE);
                 $retval['cost_center_name'] = $cc->name;
             } else {
                 throw new Exception("Cost center {$ccId} not found");
             }
         }
         $projectId = $this->GetProperty(\SERVER_PROPERTIES::FARM_PROJECT_ID);
         if ($projectId) {
             $project = ProjectEntity::findPk($projectId);
             /* @var $project ProjectEntity */
             $retval['project_id'] = $projectId;
             $retval['project_bc'] = $project->getProperty(ProjectPropertyEntity::NAME_BILLING_CODE);
             $retval['project_name'] = $project->name;
         }
     }
     return $retval;
 }
Beispiel #24
0
 public function xSaveAction()
 {
     if (!$this->user->isAccountSuperAdmin() && !$this->request->isAllowed(Acl::RESOURCE_ENV_CLOUDS_ENVIRONMENT)) {
         throw new Scalr_Exception_InsufficientPermissions();
     }
     $params = array('envId' => array('type' => 'int'), 'teams' => array('type' => 'json'));
     if ($this->user->isAccountOwner() || $this->user->isAccountSuperAdmin()) {
         $params['name'] = array('type' => 'string', 'validator' => array(Scalr_Validator::REQUIRED => true, Scalr_Validator::NOHTML => true));
     }
     $this->request->defineParams($params);
     $this->request->validate();
     if ($this->getContainer()->analytics->enabled) {
         if ($this->getParam('ccId')) {
             if (!$this->getContainer()->analytics->ccs->get($this->getParam('ccId'))) {
                 $this->request->addValidationErrors('ccId', 'Invalid cost center ID');
             }
         } else {
             $this->request->addValidationErrors('ccId', 'Cost center is required field');
         }
     }
     if ($this->request->isValid()) {
         $isNew = false;
         if (!$this->getParam('envId')) {
             //create new environment
             if (!$this->user->isAccountOwner() && !$this->user->isAccountSuperAdmin()) {
                 throw new Scalr_Exception_InsufficientPermissions();
             }
             $this->user->getAccount()->validateLimit(Scalr_Limits::ACCOUNT_ENVIRONMENTS, 1);
             $env = $this->user->getAccount()->createEnvironment($this->getParam('name'));
             $isNew = true;
         } else {
             $env = Scalr_Environment::init()->loadById($this->getParam('envId'));
         }
         $this->user->getPermissions()->validate($env);
         if (!$this->user->isAccountSuperAdmin() && !$this->user->getAclRolesByEnvironment($env->id)->isAllowed(Acl::RESOURCE_ENV_CLOUDS_ENVIRONMENT)) {
             throw new Scalr_Exception_InsufficientPermissions();
         }
         //set name, status and defaultPriority
         if ($this->user->isAccountOwner() || $this->user->isAccountSuperAdmin()) {
             $env->name = $this->getParam('name');
         }
         if ($this->user->canManageAcl()) {
             $env->status = $this->getParam('status') == Scalr_Environment::STATUS_ACTIVE ? Scalr_Environment::STATUS_ACTIVE : Scalr_Environment::STATUS_INACTIVE;
             $env->defaultPriority = $this->getParam('defaultPriority');
         }
         $env->save();
         if ($this->user->canManageAcl()) {
             if ($this->getContainer()->analytics->enabled && $this->getParam('ccId')) {
                 $oldCcId = $env->getPlatformConfigValue(Scalr_Environment::SETTING_CC_ID);
                 $env->setPlatformConfig(array(Scalr_Environment::SETTING_CC_ID => $this->getParam('ccId')));
                 if ($isNew || $oldCcId != $this->getParam('ccId')) {
                     $cc = CostCentreEntity::findPk($this->getParam('ccId'));
                     $email = $cc->getProperty(CostCentrePropertyEntity::NAME_LEAD_EMAIL);
                     $emailData = ['envName' => $env->name, 'ccName' => $cc->name];
                     if (!empty($email)) {
                         \Scalr::getContainer()->mailer->sendTemplate(SCALR_TEMPLATES_PATH . '/emails/analytics_on_cc_add.eml.php', $emailData, $email);
                     }
                 }
                 if ($isNew || empty($oldCcId)) {
                     $this->getContainer()->analytics->events->fireAssignCostCenterEvent($env, $this->getParam('ccId'));
                 } elseif ($oldCcId != $this->getParam('ccId')) {
                     $this->getContainer()->analytics->events->fireReplaceCostCenterEvent($env, $this->getParam('ccId'), $oldCcId);
                 }
             }
             //set teams
             if ($this->getContainer()->config->get('scalr.auth_mode') == 'ldap') {
                 $teams = array_map('trim', $this->getParam('teams'));
                 $ldapGroups = null;
                 if ($this->getContainer()->config->get('scalr.connections.ldap.user')) {
                     $ldap = $this->getContainer()->ldap(null, null);
                     $ldapGroups = $ldap->getGroupsDetails($teams);
                     foreach ($teams as $team) {
                         if (!isset($ldapGroups[$team])) {
                             throw new \Exception(sprintf("Team '%s' is not found on the directory server", $team));
                         }
                     }
                 }
                 $env->clearTeams();
                 foreach ($teams as $name) {
                     $name = trim($name);
                     if ($name) {
                         $id = $this->db->GetOne('SELECT id FROM account_teams WHERE name = ? AND account_id = ? LIMIT 1', array($name, $this->user->getAccountId()));
                         if (!$id) {
                             $team = new Scalr_Account_Team();
                             $team->name = $name;
                             $team->accountId = $this->user->getAccountId();
                             if ($ldapGroups !== null && $ldapGroups[$name] != $name) {
                                 $team->description = $ldapGroups[$name];
                             }
                             $team->save();
                             $id = $team->id;
                         } elseif ($ldapGroups !== null) {
                             // Update team description
                             $team = new Scalr_Account_Team();
                             $team->loadById($id);
                             if ($team->description != $ldapGroups[$name] && $ldapGroups[$name] != $name) {
                                 $team->description = $ldapGroups[$name];
                                 $team->save();
                             }
                         }
                         $env->addTeam($id);
                     }
                 }
                 if ($this->getContainer()->config->get('scalr.connections.ldap.user')) {
                     $user = strtok($this->user->getEmail(), '@');
                     $ldap = $this->getContainer()->ldap($user, null);
                     if ($ldap->isValidUsername()) {
                         $this->user->applyLdapGroups($ldap->getUserGroups());
                     }
                 }
             } else {
                 $env->clearTeams();
                 foreach ($this->getParam('teams') as $id) {
                     $env->addTeam($id);
                 }
             }
         }
         $this->response->success($isNew ? 'Environment successfully created' : 'Environment saved');
         $env = Scalr_Environment::init()->loadById($env->id);
         //reload env to be sure we have actual params
         $teams = array();
         foreach ($env->getTeams() as $teamId) {
             if ($this->getContainer()->config->get('scalr.auth_mode') == 'ldap') {
                 $team = new Scalr_Account_Team();
                 $team->loadById($teamId);
                 $teams[] = $team->name;
             } else {
                 $teams[] = $teamId;
             }
         }
         $this->response->data(array('env' => array('id' => $env->id, 'name' => $env->name, 'status' => $env->status, 'defaultPriority' => $env->defaultPriority, 'platforms' => $env->getEnabledPlatforms(), 'teams' => $teams, 'ccId' => $env->getPlatformConfigValue(Scalr_Environment::SETTING_CC_ID))));
     } else {
         $this->response->failure($this->request->getValidationErrorsMessage(), true);
     }
 }
Beispiel #25
0
 /**
  * {@inheritdoc}
  * @see \Scalr\Model\AbstractEntity::save()
  */
 public function save()
 {
     //Checks data integrity.
     $criteria = [['name' => $this->name]];
     if ($this->ccId) {
         $criteria[] = ['ccId' => ['$ne' => $this->ccId]];
     }
     //The name of the cost centre should be unique withing the global
     $item = CostCentreEntity::findOne($criteria);
     if ($item) {
         throw new AnalyticsException(sprintf('A Cost Center with this name already exists. Please choose another name.'));
     }
     parent::save();
     if ($this->ccId && \Scalr::getContainer()->analytics->enabled) {
         \Scalr::getContainer()->analytics->tags->syncValue($this->accountId ?: 0, \Scalr\Stats\CostAnalytics\Entity\TagEntity::TAG_ID_COST_CENTRE, $this->ccId, $this->name);
     }
 }
Beispiel #26
0
 public function xSaveAction()
 {
     $this->request->defineParams(array('ccId' => ['type' => 'string'], 'projectId' => ['type' => 'string'], 'year' => ['type' => 'int'], 'quarters' => ['type' => 'json'], 'selectedQuarter' => ['type' => 'string']));
     $year = $this->getParam('year');
     $selectedQuarter = $this->getParam('selectedQuarter');
     if ($selectedQuarter !== 'year' && ($selectedQuarter < 1 || $selectedQuarter > 4)) {
         throw new OutOfBoundsException(sprintf("Invalid selectedQuarter number."));
     }
     $quarterReq = [];
     foreach ($this->getParam('quarters') as $q) {
         if (!isset($q['quarter'])) {
             throw new InvalidArgumentException(sprintf("Missing quarter property for quarters data set in the request."));
         }
         if ($q['quarter'] < 1 || $q['quarter'] > 4) {
             throw new OutOfRangeException(sprintf("Quarter value should be between 1 and 4."));
         }
         if (!isset($q['budget'])) {
             throw new InvalidArgumentException(sprintf("Missing budget property for quarters data set in the request."));
         }
         $quarterReq[$q['quarter']] = $q;
     }
     if ($this->getParam('projectId')) {
         $subjectType = QuarterlyBudgetEntity::SUBJECT_TYPE_PROJECT;
         $subjectId = $this->getParam('projectId');
     } else {
         if ($this->getParam('ccId')) {
             $subjectType = QuarterlyBudgetEntity::SUBJECT_TYPE_CC;
             $subjectId = $this->getParam('ccId');
         } else {
             throw new InvalidArgumentException(sprintf('Either ccId or projectId must be provided with the request.'));
         }
     }
     if (!preg_match("/^[[:xdigit:]-]{36}\$/", $subjectId)) {
         throw new InvalidArgumentException(sprintf("Invalid UUID has been passed."));
     }
     if (!preg_match('/^\\d{4}$/', $year)) {
         throw new InvalidArgumentException(sprintf("Invalid year has been passed."));
     }
     //Fetches the previous state of the entities from database
     if ($subjectType == QuarterlyBudgetEntity::SUBJECT_TYPE_CC) {
         $collection = QuarterlyBudgetEntity::getCcBudget($year, $subjectId);
     } else {
         $collection = QuarterlyBudgetEntity::getProjectBudget($year, $subjectId);
     }
     $quarters = new Quarters(SettingEntity::getQuarters(true));
     //Updates|creates entities
     for ($quarter = 1; $quarter <= 4; ++$quarter) {
         if (!isset($quarterReq[$quarter])) {
             continue;
         }
         $period = $quarters->getPeriodForQuarter($quarter, $year);
         //Checks if period has already been closed and forbids update
         if ($period->end->format('Y-m-d') < gmdate('Y-m-d')) {
             continue;
         }
         $entity = current($collection->filterByQuarter($quarter));
         if ($entity instanceof QuarterlyBudgetEntity) {
             //We should update an entity
             $entity->budget = abs((double) $quarterReq[$quarter]['budget']);
         } else {
             //We should create a new one.
             $entity = new QuarterlyBudgetEntity($year, $quarter);
             $entity->subjectType = $subjectType;
             $entity->subjectId = $subjectId;
             $entity->budget = abs((double) $quarterReq[$quarter]['budget']);
         }
         $entity->save();
     }
     if ($selectedQuarter == 'year') {
         $selectedPeriod = $quarters->getPeriodForYear($year);
     } else {
         $selectedPeriod = $quarters->getPeriodForQuarter($selectedQuarter, $year);
     }
     if ($subjectType == QuarterlyBudgetEntity::SUBJECT_TYPE_PROJECT) {
         $data = $this->getProjectData(ProjectEntity::findPk($subjectId), $selectedPeriod, true);
         $budgetInfo = $this->getBudgetInfo($year, $data['ccId'], $data['projectId']);
     } else {
         $data = $this->getCostCenterData(CostCentreEntity::findPk($subjectId), $selectedPeriod);
         $budgetInfo = $this->getBudgetInfo($year, $subjectId);
     }
     $this->response->data(['data' => $data, 'budgetInfo' => $budgetInfo]);
     $this->response->success('Budget changes have been saved');
 }
Beispiel #27
0
 /**
  * Gets cost centre properties and parameters
  *
  * @param   CostCentreEntity $cc          Cost centre entity
  * @param   string           $calculate   optional Whether response should be adjusted with cost usage data
  * @return  array Returns cost centre properties and parameters
  */
 private function getCostCenterData(CostCentreEntity $cc, $calculate = false)
 {
     $ret = array('ccId' => $cc->ccId, 'name' => $cc->name, 'billingCode' => $cc->getProperty(CostCentrePropertyEntity::NAME_BILLING_CODE), 'description' => $cc->getProperty(CostCentrePropertyEntity::NAME_DESCRIPTION), 'leadEmail' => $cc->getProperty(CostCentrePropertyEntity::NAME_LEAD_EMAIL), 'locked' => $cc->getProperty(CostCentrePropertyEntity::NAME_LOCKED) ? 1 : 0, 'created' => $cc->created->format('Y-m-d'), 'createdByEmail' => $cc->createdByEmail, 'archived' => $cc->archived, 'envCount' => count($cc->getEnvironmentsList()), 'projectsCount' => count($cc->getProjects()));
     if ($calculate) {
         $iterator = ChartPeriodIterator::create('month', gmdate('Y-m-01'), null, 'UTC');
         $usage = $this->getContainer()->analytics->usage->get(['ccId' => $cc->ccId], $iterator->getStart(), $iterator->getEnd());
         //It calculates usage for previous period same days
         $prevusage = $this->getContainer()->analytics->usage->get(['ccId' => $cc->ccId], $iterator->getPreviousStart(), $iterator->getPreviousEnd());
         $ret = $this->getWrappedUsageData(['ccId' => $cc->ccId, 'iterator' => $iterator, 'usage' => $usage['cost'], 'prevusage' => $prevusage['cost']]) + $ret;
     }
     return $ret;
 }
Beispiel #28
0
 /**
  * Initializes default cost centres and projects according to fixtures
  *
  * @return void
  */
 public function initDefault()
 {
     $fixture = $this->fixture();
     foreach ($fixture as $i => $c) {
         $ccId = key($c);
         $cc = CostCentreEntity::findPk($ccId);
         if (!$cc) {
             $cc = new CostCentreEntity();
             $cc->ccId = $ccId;
             $cc->name = sprintf('Cost center %02d', $i + 1);
             $cc->save();
             $cc->saveProperty(CostCentrePropertyEntity::NAME_DESCRIPTION, 'This is the automatically added cost center');
             $cc->saveProperty(CostCentrePropertyEntity::NAME_BILLING_CODE, sprintf('CC-%02d', $i));
             $cc->saveProperty(CostCentrePropertyEntity::NAME_LEAD_EMAIL, '');
             $this->cadb->Execute("\n                    INSERT IGNORE `account_tag_values` (`account_id`, `tag_id`, `value_id`, `value_name`)\n                    VALUES (0, ?, ?, ?)\n                ", [TagEntity::TAG_ID_COST_CENTRE, $cc->ccId, $cc->name]);
         }
         foreach ($fixture[$i][$ccId] as $j => $projectId) {
             $pr = ProjectEntity::findPk($projectId);
             if (!$pr) {
                 $pr = new ProjectEntity();
                 $pr->projectId = $projectId;
                 $pr->ccId = $ccId;
                 $pr->name = sprintf('Project %d%d', $i, $j + 1);
                 $pr->save();
                 $pr->saveProperty(ProjectPropertyEntity::NAME_DESCRIPTION, 'This is the automatically generated project');
                 $pr->saveProperty(ProjectPropertyEntity::NAME_BILLING_CODE, sprintf('PR-%02d-%02d', $i, $j));
                 $pr->saveProperty(ProjectPropertyEntity::NAME_LEAD_EMAIL, '');
                 $this->cadb->Execute("\n                        INSERT IGNORE `account_tag_values` (`account_id`, `tag_id`, `value_id`, `value_name`)\n                        VALUES (0, ?, ?, ?)\n                    ", [TagEntity::TAG_ID_PROJECT, $pr->projectId, $pr->name]);
             }
         }
     }
     //Assigns cost centre to each environment
     $res = $this->db->Execute("SELECT id FROM client_environments");
     while ($rec = $res->FetchRow()) {
         try {
             $environment = \Scalr_Environment::init()->loadById($rec['id']);
         } catch (Exception $e) {
             continue;
         }
         $environment->setPlatformConfig(array(\Scalr_Environment::SETTING_CC_ID => $this->autoCostCentre($environment->id)));
     }
     //Assigns project to each farm
     $res = $this->db->Execute("SELECT id, env_id, clientid FROM farms");
     while ($rec = $res->FetchRow()) {
         try {
             $dbFarm = DBFarm::LoadByID($rec['id']);
         } catch (Exception $e) {
             continue;
         }
         $dbFarm->SetSetting(DBFarm::SETTING_PROJECT_ID, $this->autoProject($dbFarm->EnvID, $dbFarm->ID));
     }
     //Initializes servers properties
     $res = $this->db->Execute("\n            SELECT DISTINCT s.server_id, s.env_id, s.farm_id\n            FROM servers s\n            LEFT JOIN server_properties p ON p.server_id = s.server_id AND p.name = ?\n            LEFT JOIN server_properties p2 ON p2.server_id = s.server_id AND p2.name = ?\n            WHERE p.server_id IS NULL OR p.`value` IS NULL\n            OR (s.farm_id IS NOT NULL AND (p2.server_id IS NULL OR p2.`value` IS NULL))\n        ", [SERVER_PROPERTIES::ENV_CC_ID, SERVER_PROPERTIES::FARM_PROJECT_ID]);
     while ($rec = $res->FetchRow()) {
         $ccid = $this->autoCostCentre($rec['env_id']);
         $this->db->Execute("\n                INSERT `server_properties` (`server_id`, `name`, `value`)\n                VALUE (?, ?, ?)\n                ON DUPLICATE KEY UPDATE `value` = IFNULL(`value`, ?)\n            ", [$rec['server_id'], SERVER_PROPERTIES::ENV_CC_ID, $ccid, $ccid]);
         //Farm may not exist for bundle task servers
         if ($rec['farm_id']) {
             $projectid = $this->autoProject($rec['env_id'], $rec['farm_id']);
             $this->db->Execute("\n                    INSERT `server_properties` (`server_id`, `name`, `value`)\n                    VALUE (?, ?, ?)\n                    ON DUPLICATE KEY UPDATE `value` = IFNULL(`value`, ?)\n                ", [$rec['server_id'], SERVER_PROPERTIES::FARM_PROJECT_ID, $projectid, $projectid]);
         }
     }
 }
Beispiel #29
0
 /**
  * Gets budget data for specified CC and period
  *
  * @param   CostCentreEntity $cc
  * @param   QuarterPeriod    $period
  * @return  array Returns budget data
  */
 private function getCostCenterData(CostCentreEntity $cc, QuarterPeriod $period)
 {
     $ret = array('ccId' => $cc->ccId, 'name' => $cc->name, 'billingCode' => $cc->getProperty(CostCentrePropertyEntity::NAME_BILLING_CODE), 'description' => $cc->getProperty(CostCentrePropertyEntity::NAME_DESCRIPTION));
     $budget = $this->getBudgetUsedPercentage(['ccId' => $cc->ccId, 'period' => $period, 'getRelationDependentBudget' => true]);
     foreach (['budget', 'budgetRemain', 'budgetRemainPct', 'budgetSpent', 'budgetSpentPct', 'budgetOverspend', 'budgetOverspendPct', 'relationDependentBudget'] as $field) {
         $ret[$field] = $budget[$field];
     }
     return $ret;
 }
Beispiel #30
0
 /**
  * Finds cost centres by key
  * It searches by name or billing number
  *
  * @param   string    $key          optional Search key
  * @param   array     $criteria     optional Search criteria
  * @param   bool      $ignoreCache  optional Should it ignore cache or not
  * @return  ArrayCollection Returns collection of the CostCentreEntity objects
  */
 public function findByKey($key = null, $criteria = null, $ignoreCache = false)
 {
     if (is_null($key) || $key === '') {
         return $this->all(false, $criteria, $ignoreCache);
     }
     $collection = new ArrayCollection();
     $ccEntity = new CostCentreEntity();
     $ccPropertyEntity = new CostCentrePropertyEntity();
     $projectEntity = new ProjectEntity();
     $where = '';
     $join = '';
     $this->parseFindCriteria($criteria, $join, $where);
     $rs = $this->db->Execute("\n            SELECT " . $ccEntity->fields('c') . "\n            FROM " . $ccEntity->table('c') . " " . $join . "\n            WHERE (c.`name` LIKE ?\n            OR EXISTS (\n                SELECT 1 FROM " . $ccPropertyEntity->table('cp') . "\n                WHERE `cp`.cc_id = `c`.`cc_id`\n                AND `cp`.`name` = ? AND `cp`.`value` LIKE ?\n            ))\n            " . $where . "\n        ", ['%' . $key . '%', CostCentrePropertyEntity::NAME_BILLING_CODE, '%' . $key . '%']);
     while ($rec = $rs->FetchRow()) {
         $item = new CostCentreEntity();
         $item->load($rec);
         $collection->append($item);
     }
     return $collection;
 }