tapis_job-1.4.1-alpha1/src/TapisProvider/TapisJobProvider.php
src/TapisProvider/TapisJobProvider.php
<?php
namespace Drupal\tapis_job\TapisProvider;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Config\ImmutableConfig;
use Drupal\Core\Database\Database;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\Url;
use Drupal\jwt\JsonWebToken\JsonWebToken;
use Drupal\jwt\Transcoder\JwtTranscoderInterface;
use Drupal\tapis_app\DrupalIds as AppDrupalIds;
use Drupal\tapis_app\TapisProvider\TapisAppProviderInterface;
use Drupal\tapis_auth\TapisProvider\TapisTokenProviderInterface;
use Drupal\tapis_job\Entity\TapisJob;
use Drupal\tapis_job\Exception\TapisJobException;
use Drupal\tapis_system\DrupalIds as SystemDrupalIds;
use Drupal\tapis_system\TapisProvider\TapisSystemProviderInterface;
use Drupal\tapis_tenant\TapisProvider\TapisSiteTenantProviderInterface;
use GuzzleHttp\ClientInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides functionality to interact with the Tapis API for Tapis Job.
*
* This class is responsible for creating, updating, and deleting Tapis Job
* through the Tapis API.
*
* @package Drupal\tapis_app\TapisProvider
*/
class TapisJobProvider implements TapisJobProviderInterface {
const TAPIS_API_VERSION = 'v3';
/**
* The HTTP client used for making requests.
*
* @var \GuzzleHttp\ClientInterface
*/
protected ClientInterface $httpClient;
/**
* The Tapis token provider.
*
* @var \Drupal\tapis_auth\TapisProvider\TapisTokenProviderInterface
*/
protected TapisTokenProviderInterface $tapisTokenProvider;
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountProxyInterface
*/
protected AccountProxyInterface $currentUser;
/**
* The Tapis system provider.
*
* @var \Drupal\tapis_system\TapisProvider\TapisSystemProviderInterface
*/
protected TapisSystemProviderInterface $tapisSystemProvider;
/**
* The Tapis tenant provider.
*
* @var \Drupal\tapis_tenant\TapisProvider\TapisSiteTenantProviderInterface
*/
protected TapisSiteTenantProviderInterface $tapisSiteTenantProvider;
/**
* The configuration factory.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface|\Drupal\Core\Config\ImmutableConfig
*/
protected ConfigFactoryInterface|ImmutableConfig $config;
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected EntityTypeManagerInterface $entityTypeManager;
/**
* The JWT transcoder service.
*
* @var \Drupal\jwt\Transcoder\JwtTranscoderInterface
*/
protected JwtTranscoderInterface $jwtTranscoder;
/**
* The logger.
*
* @var \Psr\Log\LoggerInterface
*/
protected $logger;
/**
* The Tapis app provider.
*
* @var \Drupal\tapis_app\TapisProvider\TapisAppProviderInterface
*/
protected TapisAppProviderInterface $tapisAppProvider;
/**
* TapisJobProvider constructor.
*
* @param \GuzzleHttp\ClientInterface $httpClient
* The HTTP client.
* @param \Drupal\tapis_auth\TapisProvider\TapisTokenProviderInterface $tapisTokenProvider
* The Tapis token provider.
* @param \Drupal\Core\Session\AccountProxyInterface $currentUser
* The current user.
* @param \Drupal\tapis_tenant\TapisProvider\TapisSiteTenantProviderInterface $tapisSiteTenantProvider
* The Tapis site tenant provider.
* @param \Drupal\tapis_system\TapisProvider\TapisSystemProviderInterface $tapisSystemProvider
* The Tapis system provider.
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The configuration factory.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
* The entity type manager.
* @param \Drupal\jwt\Transcoder\JwtTranscoderInterface $jwt_transcoder
* The JWT transcoder service.
* @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $loggerFactory
* The logger factory service.
* @param \Drupal\tapis_app\TapisProvider\TapisAppProviderInterface $tapisAppProvider
* The Tapis app provider.
*/
public function __construct(
ClientInterface $httpClient,
TapisTokenProviderInterface $tapisTokenProvider,
AccountProxyInterface $currentUser,
TapisSiteTenantProviderInterface $tapisSiteTenantProvider,
TapisSystemProviderInterface $tapisSystemProvider,
ConfigFactoryInterface $config_factory,
EntityTypeManagerInterface $entityTypeManager,
JwtTranscoderInterface $jwt_transcoder,
LoggerChannelFactoryInterface $loggerFactory,
TapisAppProviderInterface $tapisAppProvider
) {
$this->httpClient = $httpClient;
$this->tapisTokenProvider = $tapisTokenProvider;
$this->currentUser = $currentUser;
$this->tapisSiteTenantProvider = $tapisSiteTenantProvider;
$this->tapisSystemProvider = $tapisSystemProvider;
$this->config = $config_factory->get('tapis_job.config');
$this->entityTypeManager = $entityTypeManager;
$this->jwtTranscoder = $jwt_transcoder;
$this->logger = $loggerFactory->get('tapis_job');
$this->tapisAppProvider = $tapisAppProvider;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('http_client'),
$container->get('tapis_auth.tapis_token_provider'),
$container->get("current_user"),
$container->get("tapis_tenant.tapis_site_tenant_provider"),
$container->get("tapis_system.tapis_system_provider"),
$container->get('config.factory'),
$container->get('entity_type.manager'),
$container->get('jwt.transcoder'),
$container->get('logger.factory'),
$container->get('tapis_app.tapis_app_provider'),
);
}
/**
* {@inheritDoc}
* @throws \Drupal\tapis_job\Exception\TapisJobException|\GuzzleHttp\Exception\GuzzleException
*/
public function backupJobFilesBeforeRestart($tenantId, $systemTapisId, $originalJobUUID, $originalJobExecDir, $uid = -1) {
if ($uid === -1) {
$uid = $this->currentUser->id();
}
$userJWT = $this->tapisTokenProvider->getUserToken($tenantId, $uid);
$tenantInfo = $this->tapisSiteTenantProvider->getTenantInfo($tenantId);
$tapis_api_endpoint = $tenantInfo['tapis_api_endpoint'];
$tapis_tenant_id = $tenantInfo['tapis_id'];
// first, make the backup directory for the original job
// (ignore if it exists)
$originalJobBackupDir = rtrim($originalJobExecDir, '/') . '/tapis_job_history/' . $originalJobUUID;
$tapis_api_url = "$tapis_api_endpoint/" . self::TAPIS_API_VERSION . "/files/ops/$systemTapisId";
$response = $this->httpClient->request('POST', $tapis_api_url, [
'json' => [
'path' => $originalJobBackupDir,
],
'headers' => ['X-Tapis-Token' => $userJWT],
'http_errors' => FALSE,
]);
$response_body = json_decode($response->getBody(), TRUE);
if ($response->getStatusCode() !== 200) {
if (is_array($response_body) && isset($response_body['message'])) {
$message = $response_body['message'];
} else {
// Optionally, include the raw body or a default message
$message = $response->getBody()->getContents() ?: '<br>Please try again later.';
}
throw new TapisJobException("An error occurred when backing up the original Tapis job (uuid: $originalJobUUID) before restarting it, in the '$tapis_tenant_id' tenant: $message");
}
// now, move the following files from
// the original job directory to the backup directory
// note: each of these files may or may not exist
// the mapping is from src path to dest path
// (relative to the backup directory)
$files_to_backup = [
'job_proxy_info.txt' => 'ospjob_proxy_info.txt',
'job.log' => 'ospjob.log',
'outputs/ospjob.log' => 'ospjob.log',
'outputs/tapisjob.out' => 'tapisjob.out',
'ospjob_proxy_info.txt' => 'ospjob_proxy_info.txt',
'tapisjob.sh' => 'tapisjob.sh',
'tapisjob.env' => 'tapisjob.env',
];
foreach ($files_to_backup as $src_file => $dest_file) {
$file_src_path = rtrim($originalJobExecDir, '/') . '/' . $src_file;
$file_dest_path = rtrim($originalJobBackupDir, '/') . '/' . $dest_file;
$tapis_api_url = "$tapis_api_endpoint/" . self::TAPIS_API_VERSION . "/files/ops/$systemTapisId/$file_src_path";
$response = $this->httpClient->request('PUT', $tapis_api_url, [
'json' => [
'operation' => 'MOVE',
'newPath' => $file_dest_path,
],
'headers' => ['X-Tapis-Token' => $userJWT],
'http_errors' => FALSE,
]);
$response_body = json_decode($response->getBody(), TRUE);
// Ignore 404 errors, since the source file may not always exist.
if ($response->getStatusCode() !== 200 && $response->getStatusCode() !== 404) {
if (is_array($response_body) && isset($response_body['message'])) {
$message = $response_body['message'];
} else {
// Optionally, include the raw body or a default message
$message = $response->getBody()->getContents() ?: '<br>Please try again later.';
}
throw new TapisJobException("An error occurred when backing up a file ($src_file => $dest_file) from the original Tapis job (uuid: $originalJobUUID) before restarting it, in the '$tapis_tenant_id' tenant: $message");
}
}
}
/**
* {@inheritDoc}
*/
public function generateJWTForJob($tenantId, array $claims) {
// $config = \Drupal::config('tapis_job.config');
$jwt_secret_key_id = $this->config->get("webhook_jwt_secret_key_id");
if (!$jwt_secret_key_id) {
return NULL;
}
$tenantInfo = $this->tapisSiteTenantProvider->getTenantInfo($tenantId);
$tapis_api_endpoint = $tenantInfo['tapis_api_endpoint'];
$tapis_tenant_id = $tenantInfo['tapis_id'];
// A JWT secret key has been configured, so use it to sign the JWT token.
// $jwt_secret_key = \Drupal::entityTypeManager()->getStorage('key')->load($jwt_secret_key_id);
/** @var \Drupal\key\Entity\Key $jwt_secret_key */
$jwt_secret_key = $this->entityTypeManager->getStorage('key')->load($jwt_secret_key_id);
$jwt_secret_key_value = $jwt_secret_key->getKeyValue();
// Sign the JWT token.
// $jwt_transcoder = \Drupal::service('jwt.transcoder');.
$this->jwtTranscoder->setKey($jwt_secret_key);
$raw_json_web_token = new JsonWebToken();
$raw_json_web_token->setClaim('iss', $tapis_api_endpoint);
$raw_json_web_token->setClaim('aud', $tapis_api_endpoint);
$raw_json_web_token->setClaim('iat', time());
$raw_json_web_token->setClaim('jti', uniqid());
$raw_json_web_token->setClaim('tenantId', $tapis_tenant_id);
foreach ($claims as $claim_key => $claim_value) {
$raw_json_web_token->setClaim($claim_key, $claim_value);
}
$jwt_token = $this->jwtTranscoder->encode($raw_json_web_token);
return $jwt_token;
}
/**
* {@inheritDoc}
* @throws \Drupal\tapis_job\Exception\TapisJobException|\GuzzleHttp\Exception\GuzzleException
*/
public function subscribeToJobEvents($tenantId, $jobUuid, $uid = -1) {
if ($uid === -1) {
$uid = $this->currentUser->id();
}
$userJWT = $this->tapisTokenProvider->getUserToken($tenantId, $uid);
$tenantInfo = $this->tapisSiteTenantProvider->getTenantInfo($tenantId);
$tapis_api_endpoint = $tenantInfo['tapis_api_endpoint'];
$tapis_tenant_id = $tenantInfo['tapis_id'];
// Get the Drupal absolute url for the 'tapis_job.tapis_webhook' route.
$webhook_query_params = [];
$jwt_token = $this->generateJWTForJob($tenantId,
[
'jobUuid' => $jobUuid,
'sub' => $jobUuid,
]
);
if ($jwt_token) {
// A JWT secret key has been configured, so include it in the webhook URL
// that Tapis will use to send job status updates to us.
$webhook_query_params['token'] = $jwt_token;
}
$webhook_route_url = Url::fromRoute('tapis_job.tapis_webhook', [],
[
'https' => TRUE,
'absolute' => TRUE,
]
)->toString();
if (!empty($webhook_query_params)) {
$webhook_route_url .= '?' . http_build_query($webhook_query_params);
}
$tapis_api_url = "$tapis_api_endpoint/" . self::TAPIS_API_VERSION . "/jobs/subscribe/$jobUuid";
// Include an empty 'file' parameter string
// within the multipart/form-data request.
$response = $this->httpClient->request('POST', $tapis_api_url, [
'headers' => [
'X-Tapis-Token' => $userJWT,
],
'http_errors' => FALSE,
'json' => [
'description' => 'Tapis Job Event Subscription',
'enabled' => TRUE,
'eventCategoryFilter' => 'JOB_NEW_STATUS',
'deliveryTargets' => [
[
'deliveryMethod' => 'WEBHOOK',
'deliveryAddress' => $webhook_route_url,
],
],
],
]);
$response_body = json_decode($response->getBody(), TRUE);
// Log the response array as a string.
// \Drupal::logger('tapis_job')->debug(print_r($response_body, TRUE));.
$this->logger->debug(print_r($response_body, TRUE));
// @todo Figure out how to handle Tapis api call errors
if ($response->getStatusCode() !== 200) {
if (is_array($response_body) && isset($response_body['message'])) {
$message = $response_body['message'];
} else {
// Optionally, include the raw body or a default message
$message = $response->getBody()->getContents() ?: '<br>Please try again later.';
}
throw new TapisJobException("An error occurred when subscribing to the status of the Tapis job (uuid: $jobUuid) in the '$tapis_tenant_id' tenant: $message");
}
}
/**
* {@inheritDoc}
* @throws \Drupal\tapis_job\Exception\TapisJobException|\GuzzleHttp\Exception\GuzzleException
*/
public function uploadFileToSystem($tenantId, $systemTapisId, $filepath, $file_content, int $uid = -1, int $systemOwnerUid = -1) {
if ($uid === -1) {
$uid = $this->currentUser->id();
}
$userJWT = $this->tapisTokenProvider->getUserToken($tenantId, $uid);
if ($systemOwnerUid === -1) {
$systemOwnerUid = $this->currentUser->id();
}
$systemOwnerJWT = $this->tapisTokenProvider->getUserToken($tenantId, $systemOwnerUid);
$tenantInfo = $this->tapisSiteTenantProvider->getTenantInfo($tenantId);
$tapis_api_endpoint = $tenantInfo['tapis_api_endpoint'];
$tapis_tenant_id = $tenantInfo['tapis_id'];
// First make an api call on behalf of the system owner
// to grant read & modify permissions to the user if uid != systemOwnerUid.
if ($uid !== $systemOwnerUid) {
$tapis_api_url = "$tapis_api_endpoint/" . self::TAPIS_API_VERSION . "/files/permissions/$systemTapisId/$filepath";
$response = $this->httpClient->request(
'POST',
$tapis_api_url,
[
'headers' => ['X-Tapis-Token' => $systemOwnerJWT],
'json' => [
'username' => $this->tapisTokenProvider->getTapisUsername($tenantId, $uid),
"permission" => "MODIFY",
],
"http_errors" => FALSE,
]
);
if ($response->getStatusCode() !== 200) {
$response_body = json_decode($response->getBody(), TRUE);
if (is_array($response_body) && isset($response_body['message'])) {
$message = $response_body['message'];
} else {
// Optionally, include the raw body or a default message
$message = $response->getBody()->getContents() ?: '<br>Please try again later.';
}
throw new TapisJobException("An error occurred when granting permissions for uploading a file to the system (system id: $systemTapisId) in the '$tapis_tenant_id' tenant: $message");
}
}
$tapis_api_url = "$tapis_api_endpoint/" . self::TAPIS_API_VERSION . "/files/ops/$systemTapisId/$filepath";
// Include an empty 'file' parameter string
// within the multipart/form-data request.
$response = $this->httpClient->request('POST', $tapis_api_url, [
'headers' => [
'X-Tapis-Token' => $userJWT,
],
'http_errors' => FALSE,
'multipart' => [
[
'Content-Type' => 'multipart/form-data',
'name' => 'file',
'contents' => $file_content,
],
],
]);
$response_body = json_decode($response->getBody(), TRUE);
// Log the response array as a string.
// \Drupal::logger('tapis_job')->debug(print_r($response_body, TRUE));.
$this->logger->debug(print_r($response_body, TRUE));
// @todo Figure out how to handle Tapis api call errors
if ($response->getStatusCode() !== 200) {
if (is_array($response_body) && isset($response_body['message'])) {
$message = $response_body['message'];
} else {
// Optionally, include the raw body or a default message
$message = $response->getBody()->getContents() ?: '<br>Please try again later.';
}
throw new TapisJobException("An error occurred when uploading a file to the system (system id: $systemTapisId) in the '$tapis_tenant_id' tenant: $message");
}
return $response_body;
}
/**
* {@inheritDoc}
* @throws \Drupal\tapis_job\Exception\TapisJobException|\GuzzleHttp\Exception\GuzzleException
*/
public function submitJob($tenantId, array $tapisDefinition, $uid = -1) {
// @todo Need to figure out which user we should use to create the app under, within Tapis (e.g., service account vs per-user account)
if ($uid === -1) {
$uid = $this->currentUser->id();
}
$userJWT = $this->tapisTokenProvider->getUserToken($tenantId, $uid);
$tenantInfo = $this->tapisSiteTenantProvider->getTenantInfo($tenantId);
$tapis_tenant_id = $tenantInfo['tapis_id'];
$tapis_api_endpoint = $tenantInfo['tapis_api_endpoint'];
$tapis_api_url = "$tapis_api_endpoint/" . self::TAPIS_API_VERSION . "/jobs/submit";
$response = $this->httpClient->request('POST', $tapis_api_url,
[
'headers' => ['X-Tapis-Token' => $userJWT],
'json' => $tapisDefinition,
"http_errors" => FALSE,
]);
$response_body = json_decode($response->getBody(), TRUE);
// Log the response array as a string.
// \Drupal::logger('tapis_job')->debug(print_r($response_body, TRUE));.
$this->logger->debug(print_r($response_body, TRUE));
// @todo Figure out how to handle Tapis api call errors
if ($response->getStatusCode() !== 200 && $response->getStatusCode() !== 201) {
if (is_array($response_body) && isset($response_body['message'])) {
$message = $response_body['message'];
} else {
// Optionally, include the raw body or a default message
$message = $response->getBody()->getContents() ?: '<br>Please try again later.';
}
throw new TapisJobException("An error occurred when submitting a job in the Tapis '$tapis_tenant_id' tenant: $message");
}
return $response_body['result'];
}
/**
* {@inheritDoc}
* @throws \Drupal\tapis_job\Exception\TapisJobException|\GuzzleHttp\Exception\GuzzleException
*/
public function getJobSystemOutputList($tenantId, $jobUuid, $outputPath = "", $jobOwnerUid = -1, $systemOwnerUid = -1) {
if ($jobOwnerUid === -1) {
$jobOwnerUid = $this->currentUser->id();
}
if ($systemOwnerUid === -1) {
$systemOwnerUid = $this->currentUser->id();
}
$userJWT = $this->tapisTokenProvider->getUserToken($tenantId, $systemOwnerUid);
$tenantInfo = $this->tapisSiteTenantProvider->getTenantInfo($tenantId);
$tapis_api_endpoint = $tenantInfo['tapis_api_endpoint'];
// First, get the job's execSystemOutputDir.
$job = $this->getJob($tenantId, $jobUuid, $jobOwnerUid);
$system_jobs_directory = rtrim($job['execSystemOutputDir'], '/') . '/' . ltrim($outputPath, '/');
$systemTapisId = $job['execSystemId'];
$tapis_api_url = "$tapis_api_endpoint/" . self::TAPIS_API_VERSION . "/files/ops/$systemTapisId/$system_jobs_directory";
$response = $this->httpClient->request('GET', $tapis_api_url,
[
'headers' => ['X-Tapis-Token' => $userJWT],
'http_errors' => FALSE,
]
);
$response_body = json_decode($response->getBody(), TRUE);
// Log the response array as a string.
// \Drupal::logger('tapis_job')->debug(print_r($response_body, TRUE));.
$this->logger->debug(print_r($response_body, TRUE));
// @todo Figure out how to handle Tapis api call errors
if ($response->getStatusCode() !== 200) {
if (is_array($response_body) && isset($response_body['message'])) {
$message = $response_body['message'];
} else {
// Optionally, include the raw body or a default message
$message = $response->getBody()->getContents() ?: '<br>Please try again later.';
}
throw new TapisJobException("An error occurred when getting the output file list ($outputPath) from the Tapis job ($jobUuid) in the Tapis '$tenantId' tenant: $message");
}
return $response_body['result'];
}
/**
* {@inheritDoc}
* @throws \Drupal\tapis_job\Exception\TapisJobException|\GuzzleHttp\Exception\GuzzleException
*/
public function getJob($tenantId, $jobUuid, $uid = -1) {
if ($uid === -1) {
$uid = $this->currentUser->id();
}
$userJWT = $this->tapisTokenProvider->getUserToken($tenantId, $uid);
$tenantInfo = $this->tapisSiteTenantProvider->getTenantInfo($tenantId);
$tapis_api_endpoint = $tenantInfo['tapis_api_endpoint'];
$tenant_tapis_id = $tenantInfo['tapis_id'];
$tapis_api_url = "$tapis_api_endpoint/" . self::TAPIS_API_VERSION . "/jobs/$jobUuid";
$response = $this->httpClient->request('GET', $tapis_api_url,
[
'headers' => ['X-Tapis-Token' => $userJWT],
"http_errors" => FALSE,
]
);
$response_body = json_decode($response->getBody(), TRUE);
// Log the response array as a string.
// $this->logger->debug(print_r($response_body, TRUE));
// @todo Figure out how to handle Tapis api call errors
if ($response->getStatusCode() !== 200) {
if (is_array($response_body) && isset($response_body['message'])) {
$message = $response_body['message'];
} else {
// Optionally, include the raw body or a default message
$message = $response->getBody()->getContents() ?: '<br>Please try again later.';
}
throw new TapisJobException("An error occurred when getting a Tapis job ($jobUuid) from the Tapis '$tenant_tapis_id' tenant: $message");
}
return $response_body['result'];
}
/**
* {@inheritDoc}
* @throws \Drupal\tapis_job\Exception\TapisJobException|\GuzzleHttp\Exception\GuzzleException
*/
public function getJobStatus($tenantId, $jobUuid, $uid = -1) {
if ($uid === -1) {
$uid = $this->currentUser->id();
}
$userJWT = $this->tapisTokenProvider->getUserToken($tenantId, $uid);
$tenantInfo = $this->tapisSiteTenantProvider->getTenantInfo($tenantId);
$tapis_api_endpoint = $tenantInfo['tapis_api_endpoint'];
$tapis_tenant_id = $tenantInfo['tapis_id'];
$tapis_api_url = "$tapis_api_endpoint/" . self::TAPIS_API_VERSION . "/jobs/$jobUuid/status";
$response = $this->httpClient->request('GET', $tapis_api_url,
[
'headers' => ['X-Tapis-Token' => $userJWT],
"http_errors" => FALSE,
]
);
$response_body = json_decode($response->getBody(), TRUE);
// Log the response array as a string.
// \Drupal::logger('tapis_job')->debug(print_r($response_body, TRUE));.
$this->logger->debug(print_r($response_body, TRUE));
// @todo Figure out how to handle Tapis api call errors
if ($response->getStatusCode() !== 200) {
if (is_array($response_body) && isset($response_body['message'])) {
$message = $response_body['message'];
} else {
// Optionally, include the raw body or a default message
$message = $response->getBody()->getContents() ?: '<br>Please try again later.';
}
throw new TapisJobException("An error occurred when getting the status for Tapis job ($jobUuid) from the Tapis '$tapis_tenant_id' tenant: $message");
}
return $response_body['result']['status'];
}
/**
* {@inheritDoc}
* @throws \Drupal\tapis_job\Exception\TapisJobException|\GuzzleHttp\Exception\GuzzleException
*/
public function getJobHistory($tenantId, $jobUuid, $uid = -1) {
if ($uid === -1) {
$uid = $this->currentUser->id();
}
$userJWT = $this->tapisTokenProvider->getUserToken($tenantId, $uid);
$tenantInfo = $this->tapisSiteTenantProvider->getTenantInfo($tenantId);
$tapis_api_endpoint = $tenantInfo['tapis_api_endpoint'];
$tapis_tenant_id = $tenantInfo['tapis_id'];
$tapis_api_url = "$tapis_api_endpoint/" . self::TAPIS_API_VERSION . "/jobs/$jobUuid/history";
$response = $this->httpClient->request('GET', $tapis_api_url,
[
'headers' => ['X-Tapis-Token' => $userJWT],
"http_errors" => FALSE,
]
);
$response_body = json_decode($response->getBody(), TRUE);
// Log the response array as a string.
// \Drupal::logger('tapis_job')->debug(print_r($response_body, TRUE));.
$this->logger->debug(print_r($response_body, TRUE));
// @todo Figure out how to handle Tapis api call errors
if ($response->getStatusCode() !== 200) {
if (is_array($response_body) && isset($response_body['message'])) {
$message = $response_body['message'];
} else {
// Optionally, include the raw body or a default message
$message = $response->getBody()->getContents() ?: '<br>Please try again later.';
}
throw new TapisJobException("An error occurred when getting the history for Tapis job ($jobUuid) from the Tapis '$tapis_tenant_id' tenant: $message");
}
return $response_body['result'];
}
/**
* {@inheritDoc}
* @throws \Drupal\tapis_job\Exception\TapisJobException|\GuzzleHttp\Exception\GuzzleException
*/
public function cancelJob($tenantId, $jobUuid, $uid = -1) {
// @todo Implement cancelJob() method.
if ($uid === -1) {
$uid = $this->currentUser->id();
}
$userJWT = $this->tapisTokenProvider->getUserToken($tenantId, $uid);
$tenantInfo = $this->tapisSiteTenantProvider->getTenantInfo($tenantId);
$tapis_api_endpoint = $tenantInfo['tapis_api_endpoint'];
$tenant_tapis_id = $tenantInfo['tapis_id'];
$tapis_api_url = "$tapis_api_endpoint/" . self::TAPIS_API_VERSION . "/jobs/$jobUuid/cancel";
$response = $this->httpClient->request('POST', $tapis_api_url,
[
'http_errors' => FALSE,
'headers' => ['X-Tapis-Token' => $userJWT],
]
);
$response_body = json_decode($response->getBody(), TRUE);
// Log the response array as a string.
// \Drupal::logger('tapis_job')->debug(print_r($response_body, TRUE));.
$this->logger->debug(print_r($response_body, TRUE));
// @todo Figure out how to handle Tapis api call errors
if ($response->getStatusCode() !== 200 && $response->getStatusCode() !== 409) {
if (is_array($response_body) && isset($response_body['message'])) {
$message = $response_body['message'];
} else {
// Optionally, include the raw body or a default message
$message = $response->getBody()->getContents() ?: '<br>Please try again later.';
}
throw new TapisJobException("An error occurred when cancelling the Tapis job ($jobUuid) in the Tapis '$tenant_tapis_id' tenant: $message");
}
return $response_body['result'];
}
/**
* {@inheritDoc}
* @throws \Drupal\tapis_job\Exception\TapisJobException|\GuzzleHttp\Exception\GuzzleException
*/
public function getJobOutputDownload($tenantId, $jobUuid, $outputPath = "", $compress = FALSE, $uid = -1) {
if ($uid === -1) {
$uid = $this->currentUser->id();
}
$userJWT = $this->tapisTokenProvider->getUserToken($tenantId, $uid);
$tenantInfo = $this->tapisSiteTenantProvider->getTenantInfo($tenantId);
$tapis_api_endpoint = $tenantInfo['tapis_api_endpoint'];
$tenant_tapis_id = $tenantInfo['tapis_id'];
// Remove any leading slashes, since we'll add it ourselves in the URL.
if (str_starts_with($outputPath, "/")) {
$outputPath = substr($outputPath, 1);
}
$compress_param = "false";
if ($compress) {
$compress_param = "true";
}
$tapis_api_url = "$tapis_api_endpoint/" . self::TAPIS_API_VERSION . "/jobs/$jobUuid/output/download/$outputPath?compress=$compress_param&allowIfRunning=true";
$response = $this->httpClient->request('GET', $tapis_api_url,
[
'headers' => ['X-Tapis-Token' => $userJWT],
'stream' => TRUE,
'http_errors' => FALSE,
]
);
// @todo Figure out how to handle Tapis api call errors
if ($response->getStatusCode() !== 200) {
throw new TapisJobException("An error occurred when downloading an output file ($outputPath) from the Tapis job ($jobUuid) in the Tapis '$tenant_tapis_id' tenant.");
}
return $response->getBody();
}
/**
* {@inheritDoc}
* @throws \Drupal\tapis_job\Exception\TapisJobException|\GuzzleHttp\Exception\GuzzleException
*/
public function getJobOutputList($tenantId, $jobUuid, $outputPath = "", $uid = -1, $skip = -1, $limit = -1) {
if ($uid === -1) {
$uid = $this->currentUser->id();
}
// \Drupal::logger('tapis_job')->debug("User $uid for getJobOutputList");
$this->logger->debug("User $uid for getJobOutputList");
$userJWT = $this->tapisTokenProvider->getUserToken($tenantId, $uid);
$tenantInfo = $this->tapisSiteTenantProvider->getTenantInfo($tenantId);
$tapis_api_endpoint = $tenantInfo['tapis_api_endpoint'];
$tenant_tapis_id = $tenantInfo['tapis_id'];
$tapis_api_url = "$tapis_api_endpoint/" . self::TAPIS_API_VERSION . "/jobs/$jobUuid/output/list/$outputPath?allowIfRunning=true";
if ($skip !== -1) {
$tapis_api_url .= "&skip=$skip";
}
if ($limit !== -1) {
$tapis_api_url .= "&limit=$limit";
}
// \Drupal::logger('tapis_job')->debug($tapis_api_url);
$this->logger->debug($tapis_api_url);
$response = $this->httpClient->request('GET', $tapis_api_url,
[
'headers' => ['X-Tapis-Token' => $userJWT],
'http_errors' => FALSE,
]
);
$response_body = json_decode($response->getBody(), TRUE);
// Log the response array as a string.
// \Drupal::logger('tapis_job')->debug(print_r($response_body, TRUE));.
$this->logger->debug(print_r($response_body, TRUE));
// @todo Figure out how to handle Tapis api call errors
if ($response->getStatusCode() !== 200) {
if (is_array($response_body) && isset($response_body['message'])) {
$message = $response_body['message'];
} else {
// Optionally, include the raw body or a default message
$message = $response->getBody()->getContents() ?: '<br>Please try again later.';
}
throw new TapisJobException("An error occurred when getting the output file list ($outputPath) from the Tapis job ($jobUuid) in the Tapis '$tenant_tapis_id' tenant: $message");
}
return $response_body['result'];
}
/**
* {@inheritDoc}
*
* @throws \GuzzleHttp\Exception\GuzzleException
* Throws the exception for the tapis job and http client.
*/
public function getJobOutputs($tenantId,
$execSystemId,
$outputPath = "",
$recurse = "true",
$uid = -1,
$skip = -1,
$limit = -1) {
if ($uid === -1) {
$uid = $this->currentUser->id();
}
$this->logger->debug("User $uid for getJobOutputs");
$userJWT = $this->tapisTokenProvider->getUserToken($tenantId, $uid);
$tenantInfo = $this->tapisSiteTenantProvider->getTenantInfo($tenantId);
$tapis_api_endpoint = $tenantInfo['tapis_api_endpoint'];
$tenant_tapis_id = $tenantInfo['tapis_id'];
$tapis_api_url = "$tapis_api_endpoint/" . self::TAPIS_API_VERSION . "/files/ops/" .
$execSystemId . "/" . $outputPath . "?recurse=$recurse";
if ($skip !== -1) {
$tapis_api_url .= "&offset=$skip";
}
if ($limit !== -1) {
$tapis_api_url .= "&limit=$limit";
}
$response = $this->httpClient->request('GET', $tapis_api_url,
[
'headers' => ['X-Tapis-Token' => $userJWT],
'http_errors' => FALSE,
'timeout' => 0,
]
);
$response_body = json_decode($response->getBody(), TRUE);
// Log the response array as a string.
$this->logger->debug(print_r($response_body, TRUE));
$response_body['status_code'] = $response->getStatusCode();
return $response_body;
}
/**
* {@inheritDoc}
*
* @throws \Drupal\tapis_job\Exception\TapisJobException
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function getJobOutputFileDownload($tenantId,
$jobUuid,
$execSystemId,
$outputPath = "",
$zip = FALSE,
$uid = -1) {
if ($uid === -1) {
$uid = $this->currentUser->id();
}
$userJWT = $this->tapisTokenProvider->getUserToken($tenantId, $uid);
$tenantInfo = $this->tapisSiteTenantProvider->getTenantInfo($tenantId);
$tapis_api_endpoint = $tenantInfo['tapis_api_endpoint'];
$tenant_tapis_id = $tenantInfo['tapis_id'];
// Remove any leading slashes, since we'll add it ourselves in the URL.
if (str_starts_with($outputPath, "/")) {
$outputPath = substr($outputPath, 1);
}
$zip_param = "false";
if ($zip) {
$zip_param = "true";
}
$tapis_api_url = "$tapis_api_endpoint/" . self::TAPIS_API_VERSION .
"/files/content/$execSystemId/$outputPath?zip=$zip_param";
$response = $this->httpClient->request('GET', $tapis_api_url,
[
'headers' => ['X-Tapis-Token' => $userJWT],
// 'stream' => TRUE,
'http_errors' => FALSE,
'timeout' => 0,
]
);
// @todo Figure out how to handle Tapis api call errors
if ($response->getStatusCode() !== 200) {
throw new TapisJobException("An error occurred when downloading an output file ($outputPath) from the Tapis job ($jobUuid) in the Tapis '$tenant_tapis_id' tenant.");
}
return $response->getBody();
}
/**
* {@inheritDoc}
* @throws \Drupal\tapis_job\Exception\TapisJobException|\GuzzleHttp\Exception\GuzzleException
*/
public function redeemSatelliteToken($tenantId, $jobUuid, $token, int $jobOwnerUid = -1, int $systemOwnerUid = -1) {
if ($jobOwnerUid === -1) {
$jobOwnerUid = $this->currentUser->id();
}
if ($systemOwnerUid === -1) {
$systemOwnerUid = $this->currentUser->id();
}
$tenantInfo = $this->tapisSiteTenantProvider->getTenantInfo($tenantId);
$tapis_tenant_id = $tenantInfo['tapis_id'];
$jobOwnerJWT = $this->tapisTokenProvider->getUserToken($tenantId, $jobOwnerUid);
$systemOwnerJWT = $this->tapisTokenProvider->getUserToken($tenantId, $systemOwnerUid);
// Step 1. get the job metadata from tapis using the uuid.
$job_metadata = $this->getJob($tenantId, $jobUuid);
// Ensure that it's in the RUNNING state.
if ($job_metadata['status'] !== 'RUNNING') {
throw new TapisJobException("The job ($jobUuid) in the '$tapis_tenant_id' tenant is not in the RUNNING state, so cannot create a new access link for it.");
}
// Step 2. get the job's execSystemId and execSystemOutputDir
// and compute the path to the token file.
$execSystemId = $job_metadata['execSystemId'];
$execSystemInputDir = $job_metadata['execSystemInputDir'];
$token_filepath = rtrim($execSystemInputDir, '/') . '/' . ltrim(".revssh/$token.token", '/');
// Step 3. make the system owner grant MODIFY permissions to the job owner
// on the token file path.
$tapis_api_endpoint = $tenantInfo['tapis_api_endpoint'];
$tapis_api_url = "$tapis_api_endpoint/" . self::TAPIS_API_VERSION . "/files/ops/$execSystemId/$token_filepath";
if ($jobOwnerUid !== $systemOwnerUid) {
$tapis_api_url = "$tapis_api_endpoint/" . self::TAPIS_API_VERSION . "/files/permissions/$execSystemId/$token_filepath";
$response = $this->httpClient->request(
'POST',
$tapis_api_url,
[
'headers' => ['X-Tapis-Token' => $systemOwnerJWT],
'json' => [
'username' => $this->tapisTokenProvider->getTapisUsername($tenantId, $jobOwnerUid),
"permission" => "MODIFY",
],
"http_errors" => FALSE,
]
);
if ($response->getStatusCode() !== 200) {
$response_body = json_decode($response->getBody(), TRUE);
if (is_array($response_body) && isset($response_body['message'])) {
$message = $response_body['message'];
} else {
// Optionally, include the raw body or a default message
$message = $response->getBody()->getContents() ?: '<br>Please try again later.';
}
throw new TapisJobException("An error occurred when redeeming a new access link for Tapis job ($jobUuid) from the Tapis '$tapis_tenant_id' tenant: $message");
}
}
// Step 4. Use the Tapis Files API to insert a new empty $token.token file
// within "$execSystemInputDir/.revssh".
$tapis_api_url = "$tapis_api_endpoint/" . self::TAPIS_API_VERSION . "/files/ops/$execSystemId/$token_filepath";
// Include an empty 'file' parameter string
// within the multipart/form-data request.
$response = $this->httpClient->request('POST', $tapis_api_url, [
'headers' => ['X-Tapis-Token' => $jobOwnerJWT],
'http_errors' => FALSE,
'multipart' => [
[
'name' => 'file',
'contents' => '',
],
],
]);
$response_body = json_decode($response->getBody(), TRUE);
// Log the response array as a string.
// \Drupal::logger('tapis_job')->debug(print_r($response_body, TRUE));.
$this->logger->debug(print_r($response_body, TRUE));
// @todo Figure out how to handle Tapis api call errors
if ($response->getStatusCode() !== 200) {
if (is_array($response_body) && isset($response_body['message'])) {
$message = $response_body['message'];
} else {
// Optionally, include the raw body or a default message
$message = $response->getBody()->getContents() ?: '<br>Please try again later.';
}
throw new TapisJobException("An error occurred when redeeming a new access link for Tapis job ($jobUuid) from the Tapis '$tapis_tenant_id' tenant: $message");
}
}
/**
* {@inheritDoc}
* @throws \Drupal\tapis_job\Exception\TapisJobException|\GuzzleHttp\Exception\GuzzleException
*/
public function deleteSatelliteToken($tenantId, $token, $jobUuid = NULL, $jobOwnerUid = -1, $systemOwnerUid = -1) {
$tenantInfo = $this->tapisSiteTenantProvider->getTenantInfo($tenantId);
$satellite_proxy = $tenantInfo['satellite_proxy_url'];
$tapis_tenant_id = $tenantInfo['tapis_id'];
// 1. if jobUuid is provided, delete the token file
// from the job's input directory/.revssh using the Tapis Files API
if ($jobUuid !== NULL) {
if ($jobOwnerUid === -1) {
$jobOwnerUid = $this->currentUser->id();
}
if ($systemOwnerUid === -1) {
$systemOwnerUid = $this->currentUser->id();
}
$job_userJWT = $this->tapisTokenProvider->getUserToken($tenantId, $jobOwnerUid);
$system_userJWT = $this->tapisTokenProvider->getUserToken($tenantId, $systemOwnerUid);
$job_metadata = $this->getJob($tenantId, $jobUuid, $jobOwnerUid);
$execSystemId = $job_metadata['execSystemId'];
$execSystemInputDir = $job_metadata['execSystemInputDir'];
$token_filepath = rtrim($execSystemInputDir, '/') . '/' . ltrim(".revssh/$token.token", '/');
$tapis_api_endpoint = $tenantInfo['tapis_api_endpoint'];
if ($jobOwnerUid !== $systemOwnerUid) {
$tapis_api_url = "$tapis_api_endpoint/" . self::TAPIS_API_VERSION . "/files/permissions/$execSystemId/$token_filepath";
$response = $this->httpClient->request(
'POST',
$tapis_api_url,
[
'headers' => ['X-Tapis-Token' => $system_userJWT],
'json' => [
'username' => $this->tapisTokenProvider->getTapisUsername($tenantId, $jobOwnerUid),
"permission" => "MODIFY",
],
"http_errors" => FALSE,
]
);
if ($response->getStatusCode() !== 200) {
$response_body = json_decode($response->getBody(), TRUE);
if (is_array($response_body) && isset($response_body['message'])) {
$message = $response_body['message'];
} else {
// Optionally, include the raw body or a default message
$message = $response->getBody()->getContents() ?: '<br>Please try again later.';
}
throw new TapisJobException("An error occurred when redeeming a new access link for Tapis job ($jobUuid) from the Tapis '$tapis_tenant_id' tenant: $message");
}
}
$tapis_api_url = "$tapis_api_endpoint/" . self::TAPIS_API_VERSION . "/files/ops/$execSystemId/$token_filepath";
$response = $this->httpClient->request('DELETE', $tapis_api_url,
[
'headers' => ['X-Tapis-Token' => $system_userJWT],
"http_errors" => FALSE,
]
);
$response_body = json_decode($response->getBody(), TRUE);
// Log the response array as a string.
// \Drupal::logger('tapis_job')->debug(print_r($response_body, TRUE));.
$this->logger->debug(print_r($response_body, TRUE));
// @todo Figure out how to handle Tapis api call errors
}
$delete_link_url = "$satellite_proxy/destroytoken.cgi";
$response = $this->httpClient->request('GET', $delete_link_url, [
'query' => [
'token' => $token,
],
'http_errors' => FALSE,
]);
// @todo Figure out how to handle api call errors
// if ($response->getStatusCode() !== 200) {
// throw new TapisJobException("An error occurred when unregistering
// a job proxy id ('$jobProxyId') with the Satellite proxy
// in the tenant '$tenantId'.");
// }.
}
/**
* {@inheritDoc}
*/
public function deleteAllAccessLinksForJob($jobId) {
// $jobAccessLinkStorage = \Drupal::entityTypeManager()
// ->getStorage('job_access_link');
$jobAccessLinkStorage = $this->entityTypeManager->getStorage('job_access_link');
$ids = $jobAccessLinkStorage->getQuery()
->accessCheck(FALSE)
->condition('job.target_id', $jobId)
->execute();
foreach ($ids as $id) {
$jobAccessLinkStorage->load($id)->delete();
}
}
/**
* {@inheritDoc}
*/
public function deleteAccessLink($jobAccessLinkId) {
// $jobAccessLink = \Drupal::entityTypeManager()
// ->getStorage('job_access_link')->load($jobAccessLinkId);
$jobAccessLink = $this->entityTypeManager->getStorage('job_access_link')->load($jobAccessLinkId);
$jobAccessLink->delete();
}
/**
* {@inheritDoc}
*/
public function createNewAccessLink($tenantId, TapisJob $job, $uid = -1) {
if ($uid === -1) {
// $uid = \Drupal::currentUser()->id();
$uid = $this->currentUser->id();
}
$app = $job->get("app")->first();
if ($app) {
$proxyId = $this->createNewSatelliteToken($tenantId);
// $jobAccessLink = \Drupal::entityTypeManager()
$jobAccessLink = $this->entityTypeManager
->getStorage('job_access_link')
->create(
[
'job' => ['target_id' => $job->id()],
'proxyId' => $proxyId,
'uid' => ['target_id' => $uid],
]
);
$jobAccessLink->save();
return $jobAccessLink;
}
return NULL;
}
/**
* {@inheritDoc}
*/
public function createNewSatelliteToken($tenantId) {
$tenantInfo = $this->tapisSiteTenantProvider->getTenantInfo($tenantId);
$satellite_proxy_url = $tenantInfo['satellite_proxy_url'];
$tenant_tapis_id = $tenantInfo['tapis_id'];
$create_job_proxyid_url = "$satellite_proxy_url/getlink_v2.cgi?prefix=app-$tenant_tapis_id-";
$response = $this->httpClient->request('GET', $create_job_proxyid_url, [
'http_errors' => FALSE,
]);
// The response will be a plain text of the form:
// Your token is
// <token>
// get the plain text response body and parse out the token.
$response_body = $response->getBody()->getContents();
$token = trim(str_replace("Your token is", "", $response_body));
return $token;
}
/**
* {@inheritDoc}
*/
public function createAccessLink($tenantId, $job, $proxyId, $uid = -1) {
if ($uid === -1) {
// $uid = \Drupal::currentUser()->id();
$uid = $this->currentUser->id();
}
$app = $job->get("app")->first();
if ($app) {
// $jobAccessLink = \Drupal::entityTypeManager()
$jobAccessLink = $this->entityTypeManager
->getStorage('job_access_link')
->create(
[
'job' => ['target_id' => $job->id()],
'proxyId' => $proxyId,
'uid' => ['target_id' => $uid],
]
);
$jobAccessLink->save();
return $jobAccessLink;
}
return NULL;
}
/**
* {@inheritDoc}
*/
public function getJobAccessLinksForJob($job) {
// $jobAccessLinkStorage = \Drupal::entityTypeManager()
// ->getStorage('job_access_link');
$jobAccessLinkStorage = $this->entityTypeManager->getStorage('job_access_link');
$ids = $jobAccessLinkStorage->getQuery()
->accessCheck(FALSE)
// Type = bundle id (machine name)
->condition('job.target_id', $job->id())
// Sorted by time of creation.
->sort('created', 'ASC')
->execute();
if (count($ids) <= 0) {
// No job access links are available for this job!
return NULL;
}
return $jobAccessLinkStorage->loadMultiple($ids);
}
/**
* {@inheritDoc}
*/
public function getAJobAccessLinkForJob($job) {
// $jobAccessLinkStorage = \Drupal::entityTypeManager()
// ->getStorage('job_access_link');
$jobAccessLinkStorage = $this->entityTypeManager->getStorage('job_access_link');
$ids = $jobAccessLinkStorage->getQuery()
->accessCheck(FALSE)
// Type = bundle id (machine name)
->condition('job.target_id', $job->id())
// Sorted by time of creation.
->sort('created', 'ASC')
->execute();
if (count($ids) <= 0) {
// No job access links are available for this job!
return NULL;
}
$jobAccessLinkId = current($ids);
return $jobAccessLinkStorage->load($jobAccessLinkId);
}
/**
* {@inheritDoc}
*/
public function getAllJobNames($uid = -1) {
if ($uid === -1) {
$uid = $this->currentUser->id();
}
$jobNames = [];
$connection = Database::getConnection();
$select = $connection->select('tapis_job', 't');
$select->addField('t', 'label', 'label');
$select->condition('t.uid', $uid, '=');
$result = $select->execute()->fetchAll();
if (count($result) > 0) {
foreach ($result as $item) {
$jobNames[] = $item->label;
}
}
return $jobNames;
}
/**
* Custom function to check if a value is an integer.
*/
private function isIntVal($data): bool {
if (is_int($data) === TRUE) {
return TRUE;
}
if (is_string($data) === TRUE && is_numeric($data) === TRUE) {
return (!str_contains($data, '.'));
}
return FALSE;
}
/**
* {@inheritDoc}
*/
private function incrementLastNumber($prefix, $jobNames) {
$numbers = [];
// Automatically escape special characters in the prefix.
$escapedPrefix = preg_quote($prefix, '/');
// Iterate through the job names.
foreach ($jobNames as $jobName) {
// Check if the job name starts with "Job_".
if (preg_match('/^' . $escapedPrefix . '/', $jobName)) {
// Split the job name by "Job_".
$parts = preg_split('/^' . $escapedPrefix . '/', $jobName);
// Get the second value (the part after "Job_")
$secondValue = $parts[1];
// Check if the second value is an integer.
if ($this->isIntVal($secondValue)) {
$numbers[] = intval($secondValue);
}
}
}
// Find the highest number
// Increment the highest number and append it to the base name.
if (!empty($numbers)) {
$highestNumber = max($numbers) + 1;
}
else {
$highestNumber = 1;
}
return $highestNumber;
}
/**
* Function to generate a unique job name.
*/
public function generateUniqueJobName($userJobName) {
$jobNames = $this->getAllJobNames();
$userJobName = trim($userJobName);
if (in_array($userJobName, $jobNames)) {
// Extract the base job name and the number from the user's job name
// Split the string by the last underscore.
$parts = preg_split('/.*\K_/', $userJobName);
$baseName = $parts[0];
$number = 1;
if (count($parts) === 2) {
// Output the parts.
if (!$this->isIntVal($parts[1])) {
$baseName = $userJobName;
}
if (in_array($baseName, $jobNames)) {
// Find the highest number appended to the job name.
$number = $this->incrementLastNumber($baseName . "_", $jobNames);
}
else {
$baseName = $userJobName;
}
}
else {
// Find the highest number appended to the job name.
$number = $this->incrementLastNumber($baseName . "_", $jobNames);
}
return $baseName . "_" . $number;
}
return $userJobName;
}
/**
* {@inheritDoc}
*/
public function checkAccessForAppAndSystem($node) {
$tapis_app_system_id = $node->get(AppDrupalIds::APP_DEFAULT_SYSTEM)
->getValue()[0]['target_id'];
$tapis_app_system_node = $this->entityTypeManager->getStorage('node')
->load($tapis_app_system_id);
$tenantId = $node->get(AppDrupalIds::APP_TENANT)
->first()
->getValue()['target_id'];
$tapisSystemId = $tapis_app_system_node->get(SystemDrupalIds::SYSTEM_TAPIS_ID)
->first()
->getValue()['value'];
$tapisSystemOwner = $tapis_app_system_node->get(SystemDrupalIds::SYSTEM_OWNER)
->first()
->getValue()['target_id'];
// Get the system credential to use for this user and system,
// get its loginUser value, and replace [loginUser] with it.
$systemCredentialIds = $this->entityTypeManager->getStorage("tapis_system_credential")
->getQuery()
->condition("uid", $this->currentUser->id())
->condition("system", $tapis_app_system_id)
->accessCheck(FALSE)
->execute();
$system = $this->tapisSystemProvider->getSystem($tenantId, $tapisSystemId, $tapisSystemOwner);
if ($system['isDynamicEffectiveUser'] && empty($systemCredentialIds)) {
// If there are no system credentials for this user and system,
// display an error message and set the form state to rebuild and return.
return FALSE;
}
$isPublic = $system['isPublic'];
$sharedWithUsers = $system['sharedWithUsers'];
$tapisAppOwner = $node->get(AppDrupalIds::APP_OWNER)
->first()
->getValue()['target_id'];
// Added the app owner into the shared list for the system.
$userName = $this->tapisTokenProvider->getTapisUsername($tenantId, $tapisAppOwner);
if (!$isPublic && !in_array($userName, $sharedWithUsers)) {
$this->tapisSystemProvider->shareSystemWithUser($tenantId, $tapisSystemId, $tapisAppOwner, $tapisSystemOwner);
}
// Added the current user into the shared list for the system.
$userName = $this->tapisTokenProvider->getTapisUsername($tenantId, $this->currentUser->id());
if (!$isPublic && !in_array($userName, $sharedWithUsers)) {
$this->tapisSystemProvider->shareSystemWithUser($tenantId, $tapisSystemId, $this->currentUser->id(), $tapisSystemOwner);
}
$tapisAppId = $node->get(AppDrupalIds::APP_TAPIS_ID)
->first()
->getValue()['value'];
$tapisAppVersion = $node->get(AppDrupalIds::APP_VERSION)
->first()
->getValue()['value'];
$tapisAppObject = $this->tapisAppProvider->getAppVersion($tenantId, $tapisAppId, $tapisAppVersion, $tapisAppOwner);
$isPublic = $tapisAppObject['isPublic'];
$sharedWithUsers = $tapisAppObject['sharedWithUsers'];
if (!$isPublic && !in_array($userName, $sharedWithUsers)) {
$this->tapisAppProvider->shareAppWithUser($tenantId, $tapisAppId, $this->currentUser->id(), $tapisAppOwner);
}
return TRUE;
}
}
