* executor basics added to repo
This commit is contained in:
27
src/App/Action/CiExecutorAction.php
Normal file
27
src/App/Action/CiExecutorAction.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Action;
|
||||
|
||||
use App\Response\JsonCorsResponse;
|
||||
use App\Service\CiExecutorService;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class CiExecutorAction extends AbstractAction
|
||||
{
|
||||
|
||||
/**
|
||||
* @var CiExecutorService
|
||||
*/
|
||||
private $ciExecutorService;
|
||||
|
||||
public function __construct(CiExecutorService $ciExecutorService)
|
||||
{
|
||||
$this->ciExecutorService = $ciExecutorService;
|
||||
}
|
||||
|
||||
public function getList(ServerRequestInterface $request, ResponseInterface $response, callable $next = null)
|
||||
{
|
||||
return new JsonCorsResponse($this->ciExecutorService->debug());
|
||||
}
|
||||
}
|
||||
15
src/App/Action/CiExecutorFactory.php
Normal file
15
src/App/Action/CiExecutorFactory.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace App\Action;
|
||||
|
||||
use App\Service\CiExecutorService;
|
||||
use Interop\Container\ContainerInterface;
|
||||
|
||||
class CiExecutorFactory
|
||||
{
|
||||
public function __invoke(ContainerInterface $container)
|
||||
{
|
||||
$service = $container->get(CiExecutorService::class);
|
||||
return new CiExecutorAction($service);
|
||||
}
|
||||
}
|
||||
27
src/App/Action/CiStreamAction.php
Normal file
27
src/App/Action/CiStreamAction.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Action;
|
||||
|
||||
use App\Response\JsonCorsResponse;
|
||||
use App\Service\CiExecutorService;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class CiStreamAction extends AbstractAction
|
||||
{
|
||||
|
||||
/**
|
||||
* @var CiExecutorService
|
||||
*/
|
||||
private $ciExecutorService;
|
||||
|
||||
public function __construct(CiExecutorService $ciExecutorService)
|
||||
{
|
||||
$this->ciExecutorService = $ciExecutorService;
|
||||
}
|
||||
|
||||
public function getList(ServerRequestInterface $request, ResponseInterface $response, callable $next = null)
|
||||
{
|
||||
return new JsonCorsResponse($this->ciExecutorService->getCiStreams());
|
||||
}
|
||||
}
|
||||
15
src/App/Action/CiStreamFactory.php
Normal file
15
src/App/Action/CiStreamFactory.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace App\Action;
|
||||
|
||||
use App\Service\CiExecutorService;
|
||||
use Interop\Container\ContainerInterface;
|
||||
|
||||
class CiStreamFactory
|
||||
{
|
||||
public function __invoke(ContainerInterface $container)
|
||||
{
|
||||
$service = $container->get(CiExecutorService::class);
|
||||
return new CiStreamAction($service);
|
||||
}
|
||||
}
|
||||
27
src/App/Action/JcatPackageAction.php
Normal file
27
src/App/Action/JcatPackageAction.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Action;
|
||||
|
||||
use App\Response\JsonCorsResponse;
|
||||
use App\Service\CiExecutorService;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class JcatPackageAction extends AbstractAction
|
||||
{
|
||||
|
||||
/**
|
||||
* @var CiExecutorService
|
||||
*/
|
||||
private $ciExecutorService;
|
||||
|
||||
public function __construct(CiExecutorService $ciExecutorService)
|
||||
{
|
||||
$this->ciExecutorService = $ciExecutorService;
|
||||
}
|
||||
|
||||
public function getList(ServerRequestInterface $request, ResponseInterface $response, callable $next = null)
|
||||
{
|
||||
return new JsonCorsResponse($this->ciExecutorService->getJcatPackages());
|
||||
}
|
||||
}
|
||||
15
src/App/Action/JcatPackageFactory.php
Normal file
15
src/App/Action/JcatPackageFactory.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace App\Action;
|
||||
|
||||
use App\Service\CiExecutorService;
|
||||
use Interop\Container\ContainerInterface;
|
||||
|
||||
class JcatPackageFactory
|
||||
{
|
||||
public function __invoke(ContainerInterface $container)
|
||||
{
|
||||
$service = $container->get(CiExecutorService::class);
|
||||
return new JcatPackageAction($service);
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ class CiConfig implements JsonSerializable
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="CiConfigItem", mappedBy="dailyConfig", cascade={"persist", "remove"}, orphanRemoval=true)
|
||||
* @var CiConfigItem[]
|
||||
*/
|
||||
private $configItems;
|
||||
|
||||
@@ -51,7 +52,7 @@ class CiConfig implements JsonSerializable
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @return CiConfigItem[]|ArrayCollection
|
||||
*/
|
||||
public function getConfigItems()
|
||||
{
|
||||
|
||||
783
src/App/Service/CiExecutorService.php
Normal file
783
src/App/Service/CiExecutorService.php
Normal file
@@ -0,0 +1,783 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use App\Entity\CiConfig;
|
||||
use App\Entity\CiConfigItem;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Symfony\Component\CssSelector\CssSelectorConverter;
|
||||
use Zend\Cache\Storage\Adapter\Filesystem;
|
||||
use Zend\Http\Client;
|
||||
use Zend\Json\Json;
|
||||
|
||||
class CiExecutorService
|
||||
{
|
||||
|
||||
const JENKINS_REDIRECT_URL = "http://jvirtu1.tsp.eth.ericsson.se/jenkins";
|
||||
const NODE_STATUS_PATH = '/computer';
|
||||
const CONFIG_1_PATH = '/me/my-views/view/Configuration/job/Config_1_edvidan';
|
||||
const CONFIG_2_PATH = '/me/my-views/view/Configuration/job/manual_config_2_edvidan';
|
||||
const ADD_JCAT_PATH = '/view/Tools/job/JCAT_deploy_handler_tool';
|
||||
|
||||
const JCAT_DEPLOY_SOURCE_URL = 'http://jcat.tsp.eth.ericsson.se/www/autotest/deploy';
|
||||
|
||||
const JCAT_CACHE_KEY = "jcat";
|
||||
const PACKAGE_CACHE_KEY = "packages";
|
||||
const STREAM_CACHE_KEY = "stream";
|
||||
|
||||
private $testTypeMap = [
|
||||
'isDoRollbackBefore' => 'rollback_before',
|
||||
'isDoForcedRollback' => 'ForcedRollback',
|
||||
'isDoUpgrade' => 'upgrade',
|
||||
'isDoDummyUpgrade' => 'SystemDummy',
|
||||
'isDoLrt' => 'lrt',
|
||||
'isDoDsv' => 'cwosdsv',
|
||||
// 'isDoNmDsv' => '',
|
||||
'isDoForcedRollbackDummy' => 'ForcedRollbackDummy',
|
||||
'isDoRollbackAfter' => 'rollback_after',
|
||||
];
|
||||
|
||||
private $jenkinsBaseUrl = null;
|
||||
|
||||
/**
|
||||
* @var EntityManager
|
||||
*/
|
||||
private $entityManager;
|
||||
|
||||
/**
|
||||
* @var Client
|
||||
*/
|
||||
private $httpClient;
|
||||
|
||||
/**
|
||||
* @var CiNodeService
|
||||
*/
|
||||
private $nodeService;
|
||||
|
||||
/**
|
||||
* CiExecutorService constructor.
|
||||
* @param EntityManager $entityManager
|
||||
* @param Client $httpClient
|
||||
* @param CiNodeService $nodeService
|
||||
*/
|
||||
public function __construct(EntityManager $entityManager, Client $httpClient, CiNodeService $nodeService)
|
||||
{
|
||||
$this->entityManager = $entityManager;
|
||||
$this->httpClient = $httpClient;
|
||||
$this->nodeService = $nodeService;
|
||||
$this->jenkinsBaseUrl = $this->getActiveJenkinsUrl();
|
||||
}
|
||||
|
||||
public function debug()
|
||||
{
|
||||
/** @var CiConfig $config */
|
||||
$config = $this->entityManager->find(CiConfig::class, 20170317);
|
||||
return $this->runTest($config->getConfigItems()->first());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get available jcat versions from config2 page
|
||||
*
|
||||
* @param bool $cached
|
||||
* @return array
|
||||
*/
|
||||
public function getJcatPackages($cached = true)
|
||||
{
|
||||
if (!$cached) {
|
||||
$config2Html = $this->getConfig2Html();
|
||||
$staplerTokens = $this->getStaplerTokens($config2Html, "JCAT_TYPE");
|
||||
return $this->getJcatVersions($staplerTokens['url'], $staplerTokens['token']);
|
||||
// return $this->getJcatVersions($config2Html);
|
||||
}
|
||||
|
||||
$cache = $this->getCache(self::JCAT_CACHE_KEY);
|
||||
$result = $cache->getItem(self::PACKAGE_CACHE_KEY, $success);
|
||||
if(!$success) {
|
||||
$config2Html = $this->getConfig2Html();
|
||||
$staplerTokens = $this->getStaplerTokens($config2Html, "JCAT_TYPE");
|
||||
$packages =$this->getJcatVersions($staplerTokens['url'], $staplerTokens['token']);
|
||||
// $packages =$this->getJcatVersions($config2Html);
|
||||
$cache->setItem(self::PACKAGE_CACHE_KEY, serialize($packages));
|
||||
} else {
|
||||
$packages = unserialize($result);
|
||||
}
|
||||
return $packages;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $cached
|
||||
* @return array|mixed
|
||||
*/
|
||||
public function getCiStreams($cached = true)
|
||||
{
|
||||
if (!$cached) {
|
||||
$config2Html = $this->getConfig2Html();
|
||||
return $this->getStreams($config2Html);
|
||||
}
|
||||
|
||||
$cache = $this->getCache(self::STREAM_CACHE_KEY);
|
||||
$result = $cache->getItem(self::STREAM_CACHE_KEY, $success);
|
||||
if(!$success) {
|
||||
$config2Html = $this->getConfig2Html();
|
||||
$streams =$this->getStreams($config2Html);
|
||||
$cache->setItem(self::STREAM_CACHE_KEY, serialize($streams));
|
||||
} else {
|
||||
$streams = unserialize($result);
|
||||
}
|
||||
return $streams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a daily configuration from the database.
|
||||
* This method is meant to be called periodically from cron
|
||||
*
|
||||
* @todo implement locking mechanism, so cli task won't start if there is a job already running
|
||||
* @param CiConfig $ciConfig
|
||||
*/
|
||||
public function executePendingTests(CiConfig $ciConfig)
|
||||
{
|
||||
foreach ($ciConfig->getConfigItems() as $configItem) {
|
||||
$this->runTest($configItem);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a single test configuration item in a daily job
|
||||
*
|
||||
* @param CiConfigItem $configItem
|
||||
* @return array|bool
|
||||
*/
|
||||
public function runTest(CiConfigItem $configItem)
|
||||
{
|
||||
$nodes = $this->nodeService->getTestNodeList($configItem->getNodes());
|
||||
|
||||
// @todo implement marking of "sub-job" to track if a node already has the tests going
|
||||
// $availableNodes = array_filter($nodes, function($node) {
|
||||
// return $this->isNodeOnline($node) && $this->isNodeIdle($node);
|
||||
// });
|
||||
//
|
||||
// if(0 == count($availableNodes)) {
|
||||
// return false;
|
||||
// }
|
||||
// @todo remove this part, and check for sub-job success that also needs to be saved, if any node fails, all nodes fail now
|
||||
foreach($nodes as $node) {
|
||||
if(!$this->isNodeOnline($node) || !$this->isNodeIdle($node)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Build Config1 and wait till it's finished
|
||||
// @todo reorganize this into config1build?
|
||||
$config1Status = $this->buildConfigOne($nodes);
|
||||
$config1JobId = $this->getConfig1JobId();
|
||||
while(!$this->isConfig1Built($config1JobId)) {
|
||||
sleep(2);
|
||||
set_time_limit(30);
|
||||
}
|
||||
|
||||
// Get the generated config2 page and parse it for required data
|
||||
$config2Html = $this->getConfig2Html();
|
||||
$streams = $this->getStreams($config2Html);
|
||||
$staplerTokens = $this->getStaplerTokens($config2Html, "STREAM");
|
||||
if(true === ($streamExists = in_array($configItem->getStream(), $streams))) {
|
||||
$package = $this->getPackage($configItem->getStream(), $staplerTokens['url'], $staplerTokens['token']);
|
||||
} else {
|
||||
$package = false;
|
||||
}
|
||||
$jcatVersions = $this->getJcatVersions($staplerTokens['url'], $staplerTokens['token']);
|
||||
|
||||
// Check if the desired JCAT version is available, try to create it if it's not
|
||||
if(!in_array($configItem->getJcat(), $jcatVersions)) {
|
||||
// wait for jcat package to become available
|
||||
$this->addJcatPackageToJenkins($configItem->getJcat());
|
||||
$jcatDeployJobId = $this->getJcatDeployJobId();
|
||||
while(!$this->isJcatPackageDeployed($jcatDeployJobId)) {
|
||||
sleep(2);
|
||||
set_time_limit(30);
|
||||
}
|
||||
// @todo check if we have to rebuild config1 or can just proceed with knowing the right parameters
|
||||
}
|
||||
|
||||
$nodeBases = [];
|
||||
$nodeTraffics = [];
|
||||
foreach($nodes as $type => $typeNodes) {
|
||||
foreach($typeNodes as $node => $backupPostfix) {
|
||||
if(false === strpos($node, "-")) {
|
||||
$nodeBaseName = sprintf("%s_%s", $node, $backupPostfix);
|
||||
$nodeBases[$node] = in_array($nodeBaseName, $this->getNodeBaseNames($config2Html, $node)) ? $nodeBaseName : false;
|
||||
$nodeTraffics[$node] = $this->getNodeTrafficConfigs($config2Html, $node);
|
||||
} else {
|
||||
list($zone1, $zone2) = explode("-", $node);
|
||||
$zone1BaseName = sprintf("%s_%s", $zone1, $backupPostfix);
|
||||
$zone2BaseName = sprintf("%s_%s", $zone2, $backupPostfix);
|
||||
$nodeBases[$zone1] = in_array($zone1BaseName, $this->getNodeBaseNames($config2Html, $zone1)) ? $zone1BaseName : false;
|
||||
$nodeBases[$zone2] = in_array($zone2BaseName, $this->getNodeBaseNames($config2Html, $zone2)) ? $zone2BaseName : false;
|
||||
$nodeTraffics[$node] = $this->getNodeTrafficConfigs($config2Html, str_replace("-", "_", $node));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->buildConfigTwo($configItem, $package, $nodes, $nodeBases, $nodeTraffics);
|
||||
|
||||
return [
|
||||
"config1ok"=> $config1Status,
|
||||
// "stapler" => $staplerTokens,
|
||||
// "packages" => $package,
|
||||
"jcat" => $jcatVersions,
|
||||
"bases" => $nodeBases,
|
||||
"traffic" => $nodeTraffics,
|
||||
"configsOk" => $this->config1PreCheck(),
|
||||
"active.jenkins" => $this->getActiveJenkinsUrl(),
|
||||
"jcat.exists" => $this->getJcatDeployUrl("TSP_JCAT-138.0_CORE"),
|
||||
"jcat.nodes" => $this->getAvailableJcatTargetNodes(),
|
||||
"cwis8.on" => $this->isNodeOnline("cwis8"),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks is both Config1 and Config2 jobs are idle.
|
||||
* We can only start building new configs if there is no job running at the moment.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function config1PreCheck(): bool
|
||||
{
|
||||
$config1JobId = $this->getConfig1JobId();
|
||||
$this->httpClient->setUri($this->jenkinsBaseUrl . self::CONFIG_1_PATH . "/${config1JobId}/api/json");
|
||||
$this->httpClient->resetParameters(false, false);
|
||||
$request = $this->httpClient->getRequest();
|
||||
$request->setMethod('GET');
|
||||
$response = $this->httpClient->send();
|
||||
$body = $response->getBody();
|
||||
$parsedResponse = Json::decode($body);
|
||||
if($parsedResponse->building == true) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$config2JobId = $this->getConfig2JobId();
|
||||
$this->httpClient->setUri($this->jenkinsBaseUrl . self::CONFIG_1_PATH . "/${config2JobId}/api/json");
|
||||
$this->httpClient->resetParameters(false, false);
|
||||
$request = $this->httpClient->getRequest();
|
||||
$request->setMethod('GET');
|
||||
$response = $this->httpClient->send();
|
||||
$body = $response->getBody();
|
||||
$parsedResponse = Json::decode($body);
|
||||
if($parsedResponse->building == true) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $nodes
|
||||
* @return bool
|
||||
* @todo build uri parameters OR switch to the other uri for api stuff
|
||||
*/
|
||||
private function buildConfigOne($nodes): bool
|
||||
{
|
||||
$appendParams = [];
|
||||
foreach($nodes as $type => $typeNodes) {
|
||||
foreach($typeNodes as $node => $basePostfix) {
|
||||
$appendParams[] = sprintf("%s=%s", $type, $node);
|
||||
}
|
||||
}
|
||||
$this->httpClient->setUri($this->jenkinsBaseUrl . self::CONFIG_1_PATH . '/buildWithParameters?delay=0sec&' . implode("&", $appendParams));
|
||||
$this->httpClient->resetParameters(false, false);
|
||||
$request = $this->httpClient->getRequest();
|
||||
$request->setMethod('POST');
|
||||
$response = $this->httpClient->send();
|
||||
sleep(2);
|
||||
return $response->isSuccess();
|
||||
}
|
||||
|
||||
private function getConfig1JobId()
|
||||
{
|
||||
return $this->getJobId($this->jenkinsBaseUrl . self::CONFIG_1_PATH);
|
||||
}
|
||||
|
||||
private function getConfig2JobId()
|
||||
{
|
||||
return $this->getJobId($this->jenkinsBaseUrl . self::CONFIG_2_PATH);
|
||||
}
|
||||
|
||||
private function getJobId($uri)
|
||||
{
|
||||
$this->httpClient->setUri($uri . '/api/json');
|
||||
$this->httpClient->resetParameters(false, false);
|
||||
$request = $this->httpClient->getRequest();
|
||||
$request->setMethod('GET');
|
||||
$response = $this->httpClient->send();
|
||||
$body = $response->getBody();
|
||||
$parsedResponse = Json::decode($body);
|
||||
return $parsedResponse->lastBuild->number;
|
||||
}
|
||||
|
||||
private function isConfig1Built(int $jobId): bool
|
||||
{
|
||||
$this->httpClient->setUri($this->jenkinsBaseUrl . self::CONFIG_1_PATH . "/${jobId}/api/json");
|
||||
$this->httpClient->resetParameters(false, false);
|
||||
$request = $this->httpClient->getRequest();
|
||||
$request->setMethod('GET');
|
||||
$response = $this->httpClient->send();
|
||||
$body = $response->getBody();
|
||||
$parsedResponse = Json::decode($body);
|
||||
if($parsedResponse->building == false) {
|
||||
if ($parsedResponse->result == 'SUCCESS') {
|
||||
return true;
|
||||
}
|
||||
throw new \Exception("Build failed with result: " . $parsedResponse->result);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
* @todo investigate why GET method on the config page returns HTTP405
|
||||
*/
|
||||
private function getConfig2Html(): string
|
||||
{
|
||||
$this->httpClient->setUri($this->jenkinsBaseUrl . self::CONFIG_2_PATH . "/build");
|
||||
$this->httpClient->resetParameters(false, false);
|
||||
$request = $this->httpClient->getRequest();
|
||||
$request->setMethod('GET');
|
||||
$response = $this->httpClient->send();
|
||||
if($response->getStatusCode() == 401) {
|
||||
throw new \Exception("Not authenticated");
|
||||
}
|
||||
return $response->getBody();
|
||||
}
|
||||
|
||||
private function getStaplerTokens($config2Body, $blockName = "STREAM")
|
||||
{
|
||||
if(0 === ($didMatch = preg_match(sprintf('#referencedParameters\.push\("%s"\);.*?makeStaplerProxy\(\'(.*?)\',\'(.*?)\'.*?// Create Jenkins proxy#msi', $blockName), $config2Body, $matches))) {
|
||||
throw new \Exception("Couldn't match stapler tokens in response body");
|
||||
}
|
||||
return [
|
||||
'url' => $matches[1],
|
||||
'token' => $matches[2],
|
||||
];
|
||||
}
|
||||
|
||||
private function getStreams($config2Body)
|
||||
{
|
||||
$cssToXpathConverter = new CssSelectorConverter();
|
||||
$xpathQuery = $cssToXpathConverter->toXPath('input[value=STREAM]');
|
||||
|
||||
$domDocument = new \DOMDocument();
|
||||
$domDocument->loadHTML($config2Body);
|
||||
|
||||
$xpath = new \DOMXPath($domDocument);
|
||||
$element = $xpath->query($xpathQuery);
|
||||
|
||||
if($element->length == 0) {
|
||||
throw new \Exception("Can't find STREAM");
|
||||
}
|
||||
|
||||
if($element[0]->nextSibling->nodeName != "select") {
|
||||
throw new \Exception("Can't find STREAM dropdown");
|
||||
}
|
||||
|
||||
$streams = [];
|
||||
foreach ($element[0]->nextSibling->childNodes as $option) {
|
||||
$streams[] = $option->textContent;
|
||||
}
|
||||
|
||||
sort($streams, SORT_NATURAL);
|
||||
return array_values(array_filter(array_unique($streams), function($item){
|
||||
return $item != "" && $item != "none";
|
||||
}));
|
||||
}
|
||||
|
||||
private function getPackage($stream, $url, $token): string
|
||||
{
|
||||
$this->httpClient->setUri($this->jenkinsBaseUrl . $url . '/doUpdate');
|
||||
$this->httpClient->resetParameters(false, false);
|
||||
$headers = $this->httpClient->getRequest()->getHeaders();
|
||||
$headers->addHeaderLine("Crumb", $token);
|
||||
$headers->addHeaderLine("Content-type", "application/x-stapler-method-invocation;charset=UTF-8");
|
||||
$request = $this->httpClient->getRequest();
|
||||
$request->setMethod('POST');
|
||||
$request->setContent(sprintf('["STREAM=%s"]', $stream));
|
||||
$updateResponse = $this->httpClient->send();
|
||||
if(!$updateResponse->isSuccess()) {
|
||||
throw new \Exception("Stapler doUpdate error");
|
||||
}
|
||||
sleep(1);
|
||||
$this->httpClient->setUri($this->jenkinsBaseUrl . $url . '/getChoicesForUI');
|
||||
$request->setContent("[]");
|
||||
$choicesResponse = $this->httpClient->send();
|
||||
if(!$choicesResponse->isSuccess()) {
|
||||
throw new \Exception("Stapler getChoicesForUI error");
|
||||
}
|
||||
$packages = Json::decode($choicesResponse->getBody());
|
||||
if($packages[0][0] == "Script error") {
|
||||
throw new \Exception("STREAM stapler script error");
|
||||
}
|
||||
return array_shift($packages[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $url
|
||||
* @param $token
|
||||
* @return mixed
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function getJcatVersions($url, $token)
|
||||
{
|
||||
// v1
|
||||
// $cssToXpathConverter = new CssSelectorConverter();
|
||||
// $xpathQuery = $cssToXpathConverter->toXPath('input[value=JCAT_DIR__MAIN]');
|
||||
//
|
||||
// $domDocument = new \DOMDocument();
|
||||
// $domDocument->loadHTML($config2Body);
|
||||
//
|
||||
// $xpath = new \DOMXPath($domDocument);
|
||||
// $element = $xpath->query($xpathQuery);
|
||||
//
|
||||
// if($element->length == 0) {
|
||||
// throw new \Exception("Can't find JCAT_DIR__MAIN");
|
||||
// }
|
||||
//
|
||||
// if($element[0]->nextSibling->nodeName != "select") {
|
||||
// throw new \Exception("Can't find JCAT dropdown");
|
||||
// }
|
||||
//
|
||||
// $jcatVersions = [];
|
||||
// foreach ($element[0]->nextSibling->childNodes as $option) {
|
||||
// $jcatVersions[] = $option->textContent;
|
||||
// }
|
||||
//
|
||||
// rsort($jcatVersions, SORT_NATURAL);
|
||||
// return array_values(array_filter(array_unique($jcatVersions), function($item){return $item != "";}));
|
||||
|
||||
// v2
|
||||
$this->httpClient->setUri($this->jenkinsBaseUrl . $url . '/doUpdate');
|
||||
$this->httpClient->resetParameters(false, false);
|
||||
$headers = $this->httpClient->getRequest()->getHeaders();
|
||||
$headers->addHeaderLine("Crumb", $token);
|
||||
$headers->addHeaderLine("Content-type", "application/x-stapler-method-invocation;charset=UTF-8");
|
||||
$request = $this->httpClient->getRequest();
|
||||
$request->setMethod('POST');
|
||||
$request->setContent('["JCAT_TYPE=INSTALLED"]');
|
||||
$updateResponse = $this->httpClient->send();
|
||||
if(!$updateResponse->isSuccess()) {
|
||||
throw new \Exception("Stapler doUpdate error");
|
||||
}
|
||||
sleep(1);
|
||||
$this->httpClient->setUri($this->jenkinsBaseUrl . $url . '/getChoicesForUI');
|
||||
$request->setContent("[]");
|
||||
$choicesResponse = $this->httpClient->send();
|
||||
if(!$choicesResponse->isSuccess()) {
|
||||
throw new \Exception("Stapler getChoicesForUI error");
|
||||
}
|
||||
$jcats = Json::decode($choicesResponse->getBody());
|
||||
rsort($jcats[0]);
|
||||
if($jcats[0][0] == "Script error") {
|
||||
throw new \Exception("JCAT stapler script error");
|
||||
}
|
||||
return $jcats[0];
|
||||
}
|
||||
|
||||
private function getNodeBaseNames($config2Body, $nodeName)
|
||||
{
|
||||
$cssToXpathConverter = new CssSelectorConverter();
|
||||
$xpathQuery = $cssToXpathConverter->toXPath(sprintf('input[value=%s_BASE_BACKUP]', $nodeName));
|
||||
|
||||
$domDocument = new \DOMDocument();
|
||||
$domDocument->loadHTML($config2Body);
|
||||
|
||||
$xpath = new \DOMXPath($domDocument);
|
||||
$element = $xpath->query($xpathQuery);
|
||||
|
||||
if($element->length == 0) {
|
||||
throw new \Exception(sprintf("Can't find %s_BASE_BACKUP", $nodeName));
|
||||
}
|
||||
|
||||
if($element[0]->nextSibling->nodeName != "select") {
|
||||
throw new \Exception(sprintf("Can't find %s_BASE_BACKUP dropdown", $nodeName));
|
||||
}
|
||||
|
||||
$baseNames = [];
|
||||
foreach ($element[0]->nextSibling->childNodes as $option) {
|
||||
$baseNames[] = $option->textContent;
|
||||
}
|
||||
|
||||
rsort($baseNames, SORT_NATURAL);
|
||||
return array_filter($baseNames, function($item){return $item != "";});
|
||||
}
|
||||
|
||||
private function getNodeTrafficConfigs($config2Body, $nodeName)
|
||||
{
|
||||
$cssToXpathConverter = new CssSelectorConverter();
|
||||
$xpathQuery = $cssToXpathConverter->toXPath(sprintf('input[value=%s_TRAFFIC]', $nodeName));
|
||||
|
||||
$domDocument = new \DOMDocument();
|
||||
$domDocument->loadHTML($config2Body);
|
||||
|
||||
$xpath = new \DOMXPath($domDocument);
|
||||
$element = $xpath->query($xpathQuery);
|
||||
|
||||
if($element->length == 0) {
|
||||
throw new \Exception(sprintf("Can't find %s_TRAFFIC", $nodeName));
|
||||
}
|
||||
|
||||
if($element[0]->nextSibling->nodeName != "select") {
|
||||
throw new \Exception(sprintf("Can't find %s_TRAFFIC dropdown", $nodeName));
|
||||
}
|
||||
|
||||
$trafficConfigs = [];
|
||||
foreach ($element[0]->nextSibling->childNodes as $option) {
|
||||
$trafficConfigs[] = $option->textContent;
|
||||
}
|
||||
|
||||
rsort($trafficConfigs, SORT_NATURAL);
|
||||
return array_filter($trafficConfigs, function($item){return $item != "";});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param CiConfigItem $configItem
|
||||
* @param bool|string $package
|
||||
* @param array $nodes
|
||||
* @param array $nodeBases
|
||||
* @param array $nodeTraffics
|
||||
* @return bool
|
||||
*/
|
||||
private function buildConfigTwo(CiConfigItem $configItem, $package, array $nodes, array $nodeBases, array $nodeTraffics)
|
||||
{
|
||||
$params = [];
|
||||
if(false === $package) {
|
||||
// stream doesn't exist, have to be created as new. enforces test to be nightly
|
||||
$params[] = "MODE=nightly";
|
||||
$params[] = "NEW_STREAM=" . $configItem->getStream();
|
||||
} else {
|
||||
$params[] = "MODE=" . ($configItem->isNightly() ? 'nightly' : 'manual');
|
||||
$params[] = "STREAM=" . $configItem->getStream();
|
||||
$params[] = "PACKAGE_NAME=" . $configItem->getStream();
|
||||
}
|
||||
$params[] = "RECIPIENTS=PDLSPCORED@pdl.internal.ericsson.com";
|
||||
$params[] = "JCAT_DIR__MAIN=" . $configItem->getJcat();
|
||||
$params[] = "JCAT_DIR__UPGRADE=" . $configItem->getJcat();
|
||||
|
||||
foreach($nodes as $node) {
|
||||
if(false === strpos($node, "-")) {
|
||||
$params[] = sprintf("%s_BASE_BACKUP=%s_%s", $node, $node, $nodeBases[$node]);
|
||||
} else {
|
||||
list($zone1, $zone2) = explode("-", $node);
|
||||
$params[] = sprintf("%s_BASE_BACKUP=%s_%s",$zone1, $zone1, $nodeBases[$zone1]);
|
||||
$params[] = sprintf("%s_BASE_BACKUP=%s_%s",$zone2, $zone2, $nodeBases[$zone2]);
|
||||
}
|
||||
|
||||
// todo create suites parameters
|
||||
foreach ($this->testTypeMap as $callable => $paramName) {
|
||||
if($configItem->$callable()) {
|
||||
$params[] = sprintf("%s_SUITES=%s", $node, $paramName);
|
||||
}
|
||||
}
|
||||
|
||||
$params[] = sprintf("%s_TRAFFIC=%s", $node, $nodeTraffics[$node]);
|
||||
}
|
||||
|
||||
$this->httpClient->setUri($this->jenkinsBaseUrl . self::CONFIG_2_PATH . '/buildWithParameters?delay=0sec&' . implode("&", $params));
|
||||
$this->httpClient->resetParameters(false, false);
|
||||
$request = $this->httpClient->getRequest();
|
||||
$request->setMethod('POST');
|
||||
$response = $this->httpClient->send();
|
||||
sleep(2);
|
||||
return $response->isSuccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $namespace
|
||||
* @return Filesystem
|
||||
*/
|
||||
private function getCache(string $namespace): Filesystem
|
||||
{
|
||||
$cache = new Filesystem();
|
||||
$cache->getOptions()
|
||||
->setCacheDir("data/cache")
|
||||
->setTtl(3600)
|
||||
->setNamespace($namespace)
|
||||
;
|
||||
return $cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns uri of jcat deploy or boolean FALSE, if it can't find/guess it.
|
||||
*
|
||||
* @param string $jcatVersion The jcat version in the format of TSP-JCATxxx.y[type]
|
||||
* @return bool|string
|
||||
*/
|
||||
private function getJcatDeployUrl(string $jcatVersion)
|
||||
{
|
||||
preg_match('#TSP_JCAT-([0-9]{3,}\.[0-9]+)(.*)?#', $jcatVersion, $matches);
|
||||
|
||||
$version = $matches[1];
|
||||
$deployType = trim($matches[2],"_");
|
||||
unset($matches);
|
||||
|
||||
// package has no type specified, or type is COMMON
|
||||
if($deployType == "" || $deployType == "COMMON") {
|
||||
$uri = self::JCAT_DEPLOY_SOURCE_URL . sprintf("/JCAT-%s/TSP_JCAT-%s.tar.gz", $version, $version);
|
||||
$this->httpClient->setUri($uri);
|
||||
$this->httpClient->resetParameters(false, false);
|
||||
$request = $this->httpClient->getRequest();
|
||||
$request->setMethod('HEAD');
|
||||
$response = $this->httpClient->send();
|
||||
if($response->isOk()) {
|
||||
return $uri;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// package type specified exists on jcat server
|
||||
$uri = self::JCAT_DEPLOY_SOURCE_URL . sprintf("/JCAT-%s-%s/TSP_JCAT-%s-%s.tar.gz", $deployType, $version, $deployType, $version);
|
||||
$this->httpClient->setUri($uri);
|
||||
$this->httpClient->resetParameters(false, false);
|
||||
$request = $this->httpClient->getRequest();
|
||||
$request->setMethod('HEAD');
|
||||
$response = $this->httpClient->send();
|
||||
if($response->isOk()) {
|
||||
return $uri;
|
||||
}
|
||||
|
||||
// package type specified exists with 'TSP' prefix on jcat server
|
||||
$uri = self::JCAT_DEPLOY_SOURCE_URL . sprintf("/JCAT-TSP%s-%s/TSP_JCAT-TSP%s-%s.tar.gz", $deployType, $version, $deployType, $version);
|
||||
$this->httpClient->setUri($uri);
|
||||
$this->httpClient->resetParameters(false, false);
|
||||
$request = $this->httpClient->getRequest();
|
||||
$request->setMethod('HEAD');
|
||||
$response = $this->httpClient->send();
|
||||
if($response->isOk()) {
|
||||
return $uri;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private function addJcatPackageToJenkins($jcatVersion)
|
||||
{
|
||||
$availableJcatTargetNodes = $this->getAvailableJcatTargetNodes();
|
||||
$jcatDeployUri = $this->getJcatDeployUrl($jcatVersion);
|
||||
$appendParams = [
|
||||
"NEW_DEPLOY_NAME=$jcatVersion",
|
||||
"NEW_DEPLOY_URL=$jcatDeployUri",
|
||||
"ACTION=add",
|
||||
];
|
||||
foreach($availableJcatTargetNodes as $node) {
|
||||
$appendParams[] = "NODES=$node";
|
||||
}
|
||||
$this->httpClient->setUri($this->jenkinsBaseUrl . self::ADD_JCAT_PATH . '/buildWithParameters?delay=0sec&' . implode("&", $appendParams));
|
||||
$this->httpClient->resetParameters(false, false);
|
||||
$request = $this->httpClient->getRequest();
|
||||
$request->setMethod('POST');
|
||||
$response = $this->httpClient->send();
|
||||
return $response->isSuccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns last started jcat deploy creator jobId
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function getJcatDeployJobId(): ?int
|
||||
{
|
||||
return $this->getJobId($this->jenkinsBaseUrl . self::ADD_JCAT_PATH);
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo check if build result is instant or 'inQueue' reflects build state at all
|
||||
* @param int $jobId
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function isJcatPackageDeployed(int $jobId): bool
|
||||
{
|
||||
$this->httpClient->setUri($this->jenkinsBaseUrl . self::ADD_JCAT_PATH . "/${jobId}/api/json");
|
||||
$this->httpClient->resetParameters(false, false);
|
||||
$request = $this->httpClient->getRequest();
|
||||
$request->setMethod('GET');
|
||||
$response = $this->httpClient->send();
|
||||
$body = $response->getBody();
|
||||
$parsedResponse = Json::decode($body);
|
||||
if($parsedResponse->inQueue == false) {
|
||||
if ($parsedResponse->lastBuild->number == $parsedResponse->lastSuccessfulBuild->number) {
|
||||
return true;
|
||||
}
|
||||
throw new \Exception("Build failed.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private function getAvailableJcatTargetNodes()
|
||||
{
|
||||
$this->httpClient->setUri($this->jenkinsBaseUrl . self::ADD_JCAT_PATH . "/build");
|
||||
$this->httpClient->resetParameters(false, false);
|
||||
$response = $this->httpClient->send();
|
||||
$jcatHandlerPageBody = $response->getBody();
|
||||
|
||||
$cssToXpathConverter = new CssSelectorConverter();
|
||||
$xpathQuery = $cssToXpathConverter->toXPath('input[value=NODES]');
|
||||
|
||||
$domDocument = new \DOMDocument();
|
||||
$domDocument->loadHTML($jcatHandlerPageBody);
|
||||
|
||||
$xpath = new \DOMXPath($domDocument);
|
||||
$element = $xpath->query($xpathQuery);
|
||||
|
||||
if($element->length == 0) {
|
||||
throw new \Exception("Can't find NODES");
|
||||
}
|
||||
|
||||
if($element[0]->nextSibling->nodeName != "select") {
|
||||
throw new \Exception("Can't find NODES dropdown");
|
||||
}
|
||||
|
||||
$trafficConfigs = [];
|
||||
foreach ($element[0]->nextSibling->childNodes as $option) {
|
||||
$trafficConfigs[] = $option->textContent;
|
||||
}
|
||||
|
||||
sort($trafficConfigs, SORT_NATURAL);
|
||||
return $trafficConfigs;
|
||||
}
|
||||
|
||||
private function getActiveJenkinsUrl(): string
|
||||
{
|
||||
$this->httpClient->setUri(self::JENKINS_REDIRECT_URL);
|
||||
$this->httpClient->resetParameters(false, false);
|
||||
$this->httpClient->setOptions(['maxredirects' => 0]);
|
||||
$request = $this->httpClient->getRequest();
|
||||
$request->setMethod('HEAD');
|
||||
$response = $this->httpClient->send();
|
||||
if($response->isRedirect()) {
|
||||
$this->httpClient->setOptions(['maxredirects' => 5]);
|
||||
return rtrim($response->getHeaders()->get("location")->getFieldValue(), "/");
|
||||
}
|
||||
throw new \Exception("Jenkins redirect url is not working, return code was: " . $response->getStatusCode());
|
||||
}
|
||||
|
||||
public function isNodeOnline(string $node): bool
|
||||
{
|
||||
$this->httpClient->setUri($this->jenkinsBaseUrl . self::NODE_STATUS_PATH . "/${node}/api/json");
|
||||
$this->httpClient->resetParameters(false, false);
|
||||
$request = $this->httpClient->getRequest();
|
||||
$request->setMethod('GET');
|
||||
$response = $this->httpClient->send();
|
||||
$body = $response->getBody();
|
||||
$parsedResponse = Json::decode($body);
|
||||
return !$parsedResponse->offline;
|
||||
}
|
||||
|
||||
public function isNodeIdle(string $node): bool
|
||||
{
|
||||
$this->httpClient->setUri($this->jenkinsBaseUrl . self::NODE_STATUS_PATH . "/${node}/api/json");
|
||||
$this->httpClient->resetParameters(false, false);
|
||||
$request = $this->httpClient->getRequest();
|
||||
$request->setMethod('GET');
|
||||
$response = $this->httpClient->send();
|
||||
$body = $response->getBody();
|
||||
$parsedResponse = Json::decode($body);
|
||||
return $parsedResponse->idle;
|
||||
}
|
||||
}
|
||||
19
src/App/Service/CiExecutorServiceFactory.php
Normal file
19
src/App/Service/CiExecutorServiceFactory.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use Interop\Container\ContainerInterface;
|
||||
use Zend\Http\Client;
|
||||
|
||||
class CiExecutorServiceFactory
|
||||
{
|
||||
public function __invoke(ContainerInterface $container)
|
||||
{
|
||||
$nodeService = $container->get(CiNodeService::class);
|
||||
$entityManager = $container->get('doctrine.entity_manager.orm_default');
|
||||
$config = $container->get('config');
|
||||
$httpClient = new Client();
|
||||
$httpClient->setAuth($config['ci.auth']['user'], $config['ci.auth']['pass']);
|
||||
return new CiExecutorService($entityManager, $httpClient, $nodeService);
|
||||
}
|
||||
}
|
||||
155
src/App/Service/CiNodeService.php
Normal file
155
src/App/Service/CiNodeService.php
Normal file
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
class CiNodeService
|
||||
{
|
||||
|
||||
private $nodes = [
|
||||
[
|
||||
"name" => 'esx4b', "type" => 'esx', "size" => 1, "team" => "detoqs",
|
||||
"bases" => ["7101_base_Jenkins_CI_20161006"], "defaultBase" => "7101_base_Jenkins_CI_20161006", "canAutoStart" => true,
|
||||
],
|
||||
[
|
||||
"name" => 'esx10a', "type" => 'esx', "size" => 1, "team" => "detoqs",
|
||||
"bases" => [], "defaultBase" => "", "canAutoStart" => true,
|
||||
],
|
||||
[
|
||||
"name" => 'esx10b', "type" => 'esx', "size" => 1, "team" => "detoqs",
|
||||
"bases" => [], "defaultBase" => "", "canAutoStart" => true,
|
||||
],
|
||||
[
|
||||
"name" => 'asumi', "type" => 'esx', "size" => 1, "team" => "detoqs",
|
||||
"bases" => [], "defaultBase" => "", "canAutoStart" => true,
|
||||
],
|
||||
[
|
||||
"name" => 'michiyo', "type" => 'esx', "size" => 1, "team" => "detoqs",
|
||||
"bases" => [], "defaultBase" => "", "canAutoStart" => true,
|
||||
],
|
||||
[
|
||||
"name" => 'sakura', "type" => 'esx', "size" => 1, "team" => "detoqs",
|
||||
"bases" => [], "defaultBase" => "", "canAutoStart" => true,
|
||||
],
|
||||
[
|
||||
"name" => 'takumi', "type" => 'esx', "size" => 1, "team" => "detoqs",
|
||||
"bases" => ["7000_base_Jenkins_CI_20160701"], "defaultBase" => "7000_base_Jenkins_CI_20160701", "canAutoStart" => true,
|
||||
],
|
||||
[
|
||||
"name" => 'cwsled', "type" => 'maia', "size" => 1, "team" => "taurus",
|
||||
"bases" => [], "defaultBase" => "", "canAutoStart" => false,
|
||||
],
|
||||
[
|
||||
"name" => 'g8z1', "type" => 'nsp5', "size" => 1, "team" => "detoqs",
|
||||
"bases" => [], "defaultBase" => "", "canAutoStart" => true,
|
||||
],
|
||||
[
|
||||
"name" => 'to22', "type" => 'nsp5', "size" => 1, "team" => "detoqs",
|
||||
"bases" => [], "defaultBase" => "", "canAutoStart" => true,
|
||||
],
|
||||
[
|
||||
"name" => 'cwis8', "type" => 'nsp6', "size" => 3, "team" => "vikinx",
|
||||
"bases" => [], "defaultBase" => "", "canAutoStart" => true,
|
||||
],
|
||||
[
|
||||
"name" => 'cwis9', "type" => 'nsp6', "size" => 3, "team" => "oorio",
|
||||
"bases" => [], "defaultBase" => "", "canAutoStart" => true,
|
||||
],
|
||||
[
|
||||
"name" => 'ivis1', "type" => 'nsp6', "size" => 1, "team" => "vikinx",
|
||||
"bases" => [], "defaultBase" => "", "canAutoStart" => true,
|
||||
],
|
||||
[
|
||||
"name" => 'ivis2', "type" => 'nsp6', "size" => 1, "team" => "oorio",
|
||||
"bases" => [], "defaultBase" => "", "canAutoStart" => true,
|
||||
],
|
||||
[
|
||||
"name" => 'nmis1', "type" => 'nsp6', "size" => 2, "team" => "unknown",
|
||||
"bases" => [], "defaultBase" => "", "canAutoStart" => true,
|
||||
],
|
||||
[
|
||||
"name" => 'tina', "type" => 'nsp6', "size" => 1, "team" => "oorio",
|
||||
"bases" => [], "defaultBase" => "", "canAutoStart" => true,
|
||||
],
|
||||
[
|
||||
"name" => 'alla', "type" => 'nsp6.1', "size" => 3, "team" => "unknown",
|
||||
"bases" => [], "defaultBase" => "", "canAutoStart" => true,
|
||||
],
|
||||
[
|
||||
"name" => 'katyusa', "type" => 'nsp6.1', "size" => 2, "team" => "unknown",
|
||||
"bases" => [], "defaultBase" => "", "canAutoStart" => true,
|
||||
],
|
||||
[
|
||||
"name" => 'elena', "type" => 'nsp6.1', "size" => 2, "team" => "oorio",
|
||||
"bases" => [], "defaultBase" => "", "canAutoStart" => true,
|
||||
],
|
||||
[
|
||||
"name" => 'natasha', "type" => 'nsp6.1', "size" => 2, "team" => "trex",
|
||||
"bases" => ["7101_base_Jenkins_CI_20161217"], "defaultBase" => "7101_base_Jenkins_CI_20161217", "canAutoStart" => true,
|
||||
],
|
||||
[
|
||||
"name" => 'mazsola-tade', "type" => 'nsp6.1', "size" => 1, "team" => "vikinx",
|
||||
"bases" => ["7111_base_Jenkins_CI_20170130"], "defaultBase" => "7111_base_Jenkins_CI_20170130", "canAutoStart" => true,
|
||||
],
|
||||
[
|
||||
"name" => 'pikkolo', "type" => 'nsp6.1', "size" => 1, "team" => "taurus",
|
||||
"bases" => [], "defaultBase" => "", "canAutoStart" => true,
|
||||
],
|
||||
[
|
||||
"name" => 'sonia', "type" => 'nsp6.1', "size" => 1, "team" => "trex",
|
||||
"bases" => [], "defaultBase" => "", "canAutoStart" => true,
|
||||
],
|
||||
[
|
||||
"name" => 'tatiana', "type" => 'nsp6.1', "size" => 2, "team" => "taurus",
|
||||
"bases" => [], "defaultBase" => "", "canAutoStart" => true,
|
||||
],
|
||||
[
|
||||
"name" => 'opossum', "type" => 'gep5', "size" => 1, "team" => "taurus",
|
||||
"bases" => [], "defaultBase" => "", "canAutoStart" => true,
|
||||
],
|
||||
[
|
||||
"name" => 'petymeg', "type" => 'gep5', "size" => 2, "team" => "vikinx",
|
||||
"bases" => [], "defaultBase" => "", "canAutoStart" => true,
|
||||
],
|
||||
[
|
||||
"name" => 'gicnode4', "type" => 'gep5', "size" => 2, "team" => "oorio",
|
||||
"bases" => [], "defaultBase" => "", "canAutoStart" => false,
|
||||
],
|
||||
[
|
||||
"name" => 'gicnode10', "type" => 'gep5', "size" => 1, "team" => "trex",
|
||||
"bases" => [], "defaultBase" => "", "canAutoStart" => false,
|
||||
],
|
||||
[
|
||||
"name" => 'gicnode19', "type" => 'gep5', "size" => 2, "team" => "trex",
|
||||
"bases" => [], "defaultBase" => "", "canAutoStart" => false,
|
||||
],
|
||||
];
|
||||
|
||||
public function getNodes(): array
|
||||
{
|
||||
return $this->nodes;
|
||||
}
|
||||
|
||||
public function getNode($node): ?array
|
||||
{
|
||||
return array_pop(array_filter($this->nodes, function($item) use ($node) {
|
||||
return $item['name'] == $node;
|
||||
}));
|
||||
}
|
||||
|
||||
public function getTestNodeList(array $nodes): ?array
|
||||
{
|
||||
$filteredNodes = array_filter($this->nodes, function($item) use ($nodes) {
|
||||
return in_array($item['name'], $nodes);
|
||||
});
|
||||
|
||||
$result = [];
|
||||
foreach ($filteredNodes as $filteredNode) {
|
||||
$type = strtoupper($filteredNode['type']);
|
||||
if(!isset($result[$type])) {
|
||||
$result[$type] = [];
|
||||
}
|
||||
$result[$type][$filteredNode['name']] = $filteredNode['defaultBase'];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user