ci: Disable GitHub Actions workflow temporarily
This commit is contained in:
parent
331cba42aa
commit
9ab564da60
16 changed files with 15954 additions and 771 deletions
|
|
@ -466,6 +466,545 @@ class UnsandboxAsync {
|
|||
return $this->makeRequest('DELETE', "/snapshots/{$snapshotId}", $publicKey, $secretKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock a snapshot to prevent deletion.
|
||||
*
|
||||
* @param string $snapshotId Snapshot ID to lock
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return PromiseInterface Resolves to response array with lock confirmation
|
||||
*/
|
||||
public function lockSnapshot(string $snapshotId, ?string $publicKey = null, ?string $secretKey = null): PromiseInterface {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('POST', "/snapshots/{$snapshotId}/lock", $publicKey, $secretKey, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock a snapshot to allow deletion.
|
||||
*
|
||||
* @param string $snapshotId Snapshot ID to unlock
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return PromiseInterface Resolves to response array with unlock confirmation
|
||||
*/
|
||||
public function unlockSnapshot(string $snapshotId, ?string $publicKey = null, ?string $secretKey = null): PromiseInterface {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('POST', "/snapshots/{$snapshotId}/unlock", $publicKey, $secretKey, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone a snapshot to create a new session or service.
|
||||
*
|
||||
* @param string $snapshotId Snapshot ID to clone
|
||||
* @param string|null $name Optional name for the new resource
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @param array $opts Optional parameters: 'type' (session|service), 'shell', 'ports'
|
||||
* @return PromiseInterface Resolves to response array with cloned resource info
|
||||
*/
|
||||
public function cloneSnapshot(
|
||||
string $snapshotId,
|
||||
?string $name = null,
|
||||
?string $publicKey = null,
|
||||
?string $secretKey = null,
|
||||
array $opts = []
|
||||
): PromiseInterface {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
|
||||
$data = [];
|
||||
if ($name !== null) {
|
||||
$data['name'] = $name;
|
||||
}
|
||||
if (isset($opts['type'])) {
|
||||
$data['type'] = $opts['type'];
|
||||
}
|
||||
if (isset($opts['shell'])) {
|
||||
$data['shell'] = $opts['shell'];
|
||||
}
|
||||
if (isset($opts['ports'])) {
|
||||
$data['ports'] = $opts['ports'];
|
||||
}
|
||||
|
||||
return $this->makeRequest('POST', "/snapshots/{$snapshotId}/clone", $publicKey, $secretKey, $data);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Session Methods
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* List all active sessions for the authenticated account.
|
||||
*
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return PromiseInterface Resolves to list of session arrays
|
||||
*/
|
||||
public function listSessions(?string $publicKey = null, ?string $secretKey = null): PromiseInterface {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('GET', '/sessions', $publicKey, $secretKey)->then(function (array $response) {
|
||||
return $response['sessions'] ?? [];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get details of a specific session.
|
||||
*
|
||||
* @param string $sessionId Session ID
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return PromiseInterface Resolves to session details
|
||||
*/
|
||||
public function getSession(string $sessionId, ?string $publicKey = null, ?string $secretKey = null): PromiseInterface {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('GET', "/sessions/{$sessionId}", $publicKey, $secretKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new interactive session.
|
||||
*
|
||||
* @param string $language Programming language or shell (e.g., "bash", "python3")
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @param array $opts Optional parameters: 'network_mode', 'ttl', 'shell', 'multiplexer', 'vcpu'
|
||||
* @return PromiseInterface Resolves to session info including session_id and container_name
|
||||
*/
|
||||
public function createSession(
|
||||
string $language,
|
||||
?string $publicKey = null,
|
||||
?string $secretKey = null,
|
||||
array $opts = []
|
||||
): PromiseInterface {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
|
||||
$data = [
|
||||
'network_mode' => $opts['network_mode'] ?? 'zerotrust',
|
||||
'ttl' => $opts['ttl'] ?? 3600,
|
||||
];
|
||||
if (!empty($language)) {
|
||||
$data['shell'] = $language;
|
||||
}
|
||||
if (isset($opts['shell'])) {
|
||||
$data['shell'] = $opts['shell'];
|
||||
}
|
||||
if (isset($opts['multiplexer'])) {
|
||||
$data['multiplexer'] = $opts['multiplexer'];
|
||||
}
|
||||
if (isset($opts['vcpu']) && $opts['vcpu'] > 1) {
|
||||
$data['vcpu'] = $opts['vcpu'];
|
||||
}
|
||||
if (isset($opts['input_files'])) {
|
||||
$data['input_files'] = $opts['input_files'];
|
||||
}
|
||||
|
||||
return $this->makeRequest('POST', '/sessions', $publicKey, $secretKey, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete (terminate) a session.
|
||||
*
|
||||
* @param string $sessionId Session ID to delete
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return PromiseInterface Resolves to response array with deletion confirmation
|
||||
*/
|
||||
public function deleteSession(string $sessionId, ?string $publicKey = null, ?string $secretKey = null): PromiseInterface {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('DELETE', "/sessions/{$sessionId}", $publicKey, $secretKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Freeze a session to pause execution and reduce resource usage.
|
||||
*
|
||||
* @param string $sessionId Session ID to freeze
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return PromiseInterface Resolves to response array with freeze confirmation
|
||||
*/
|
||||
public function freezeSession(string $sessionId, ?string $publicKey = null, ?string $secretKey = null): PromiseInterface {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('POST', "/sessions/{$sessionId}/freeze", $publicKey, $secretKey, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unfreeze a session to resume execution.
|
||||
*
|
||||
* @param string $sessionId Session ID to unfreeze
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return PromiseInterface Resolves to response array with unfreeze confirmation
|
||||
*/
|
||||
public function unfreezeSession(string $sessionId, ?string $publicKey = null, ?string $secretKey = null): PromiseInterface {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('POST', "/sessions/{$sessionId}/unfreeze", $publicKey, $secretKey, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Boost a session's resources (increase vCPU, memory is derived: vcpu * 2048MB).
|
||||
*
|
||||
* @param string $sessionId Session ID to boost
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @param int $vcpu Number of vCPUs (default: 2)
|
||||
* @return PromiseInterface Resolves to response array with boost confirmation
|
||||
*/
|
||||
public function boostSession(
|
||||
string $sessionId,
|
||||
?string $publicKey = null,
|
||||
?string $secretKey = null,
|
||||
int $vcpu = 2
|
||||
): PromiseInterface {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('POST', "/sessions/{$sessionId}/boost", $publicKey, $secretKey, ['vcpu' => $vcpu]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove boost from a session (return to base resources).
|
||||
*
|
||||
* @param string $sessionId Session ID to unboost
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return PromiseInterface Resolves to response array with unboost confirmation
|
||||
*/
|
||||
public function unboostSession(string $sessionId, ?string $publicKey = null, ?string $secretKey = null): PromiseInterface {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('POST', "/sessions/{$sessionId}/unboost", $publicKey, $secretKey, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a shell command in an active session.
|
||||
*
|
||||
* Note: This is for one-shot commands. For interactive sessions, use WebSocket connection.
|
||||
*
|
||||
* @param string $sessionId Session ID
|
||||
* @param string $command Command to execute
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return PromiseInterface Resolves to response array with command output
|
||||
*/
|
||||
public function shellSession(
|
||||
string $sessionId,
|
||||
string $command,
|
||||
?string $publicKey = null,
|
||||
?string $secretKey = null
|
||||
): PromiseInterface {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('POST', "/sessions/{$sessionId}/shell", $publicKey, $secretKey, ['command' => $command]);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Service Methods
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* List all services for the authenticated account.
|
||||
*
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return PromiseInterface Resolves to list of service arrays
|
||||
*/
|
||||
public function listServices(?string $publicKey = null, ?string $secretKey = null): PromiseInterface {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('GET', '/services', $publicKey, $secretKey)->then(function (array $response) {
|
||||
return $response['services'] ?? [];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new persistent service.
|
||||
*
|
||||
* @param string $name Service name
|
||||
* @param array|string $ports Port(s) to expose (array of ints or comma-separated string)
|
||||
* @param string $bootstrap Bootstrap command or URL
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @param array $opts Optional parameters: 'network_mode', 'vcpu', 'service_type', 'custom_domains', 'bootstrap_content', 'input_files'
|
||||
* @return PromiseInterface Resolves to service info including service_id
|
||||
*/
|
||||
public function createService(
|
||||
string $name,
|
||||
$ports,
|
||||
string $bootstrap,
|
||||
?string $publicKey = null,
|
||||
?string $secretKey = null,
|
||||
array $opts = []
|
||||
): PromiseInterface {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
|
||||
// Convert ports to array if string
|
||||
if (is_string($ports)) {
|
||||
$ports = array_map('intval', explode(',', $ports));
|
||||
}
|
||||
|
||||
$data = [
|
||||
'name' => $name,
|
||||
'ports' => $ports,
|
||||
'bootstrap' => $bootstrap,
|
||||
];
|
||||
|
||||
if (isset($opts['network_mode'])) {
|
||||
$data['network_mode'] = $opts['network_mode'];
|
||||
}
|
||||
if (isset($opts['vcpu']) && $opts['vcpu'] > 1) {
|
||||
$data['vcpu'] = $opts['vcpu'];
|
||||
}
|
||||
if (isset($opts['service_type'])) {
|
||||
$data['service_type'] = $opts['service_type'];
|
||||
}
|
||||
if (isset($opts['custom_domains'])) {
|
||||
$data['custom_domains'] = $opts['custom_domains'];
|
||||
}
|
||||
if (isset($opts['bootstrap_content'])) {
|
||||
$data['bootstrap_content'] = $opts['bootstrap_content'];
|
||||
}
|
||||
if (isset($opts['input_files'])) {
|
||||
$data['input_files'] = $opts['input_files'];
|
||||
}
|
||||
|
||||
return $this->makeRequest('POST', '/services', $publicKey, $secretKey, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get details of a specific service.
|
||||
*
|
||||
* @param string $serviceId Service ID
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return PromiseInterface Resolves to service details
|
||||
*/
|
||||
public function getService(string $serviceId, ?string $publicKey = null, ?string $secretKey = null): PromiseInterface {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('GET', "/services/{$serviceId}", $publicKey, $secretKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a service (e.g., resize vCPU).
|
||||
*
|
||||
* @param string $serviceId Service ID
|
||||
* @param array $opts Update parameters: 'vcpu', 'name', etc.
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return PromiseInterface Resolves to updated service details
|
||||
*/
|
||||
public function updateService(
|
||||
string $serviceId,
|
||||
array $opts,
|
||||
?string $publicKey = null,
|
||||
?string $secretKey = null
|
||||
): PromiseInterface {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('PATCH', "/services/{$serviceId}", $publicKey, $secretKey, $opts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete (destroy) a service.
|
||||
*
|
||||
* @param string $serviceId Service ID to delete
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return PromiseInterface Resolves to response array with deletion confirmation
|
||||
*/
|
||||
public function deleteService(string $serviceId, ?string $publicKey = null, ?string $secretKey = null): PromiseInterface {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('DELETE', "/services/{$serviceId}", $publicKey, $secretKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Freeze a service to pause execution and reduce resource usage.
|
||||
*
|
||||
* @param string $serviceId Service ID to freeze
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return PromiseInterface Resolves to response array with freeze confirmation
|
||||
*/
|
||||
public function freezeService(string $serviceId, ?string $publicKey = null, ?string $secretKey = null): PromiseInterface {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('POST', "/services/{$serviceId}/freeze", $publicKey, $secretKey, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unfreeze a service to resume execution.
|
||||
*
|
||||
* @param string $serviceId Service ID to unfreeze
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return PromiseInterface Resolves to response array with unfreeze confirmation
|
||||
*/
|
||||
public function unfreezeService(string $serviceId, ?string $publicKey = null, ?string $secretKey = null): PromiseInterface {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('POST', "/services/{$serviceId}/unfreeze", $publicKey, $secretKey, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock a service to prevent deletion.
|
||||
*
|
||||
* @param string $serviceId Service ID to lock
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return PromiseInterface Resolves to response array with lock confirmation
|
||||
*/
|
||||
public function lockService(string $serviceId, ?string $publicKey = null, ?string $secretKey = null): PromiseInterface {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('POST', "/services/{$serviceId}/lock", $publicKey, $secretKey, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock a service to allow deletion.
|
||||
*
|
||||
* @param string $serviceId Service ID to unlock
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return PromiseInterface Resolves to response array with unlock confirmation
|
||||
*/
|
||||
public function unlockService(string $serviceId, ?string $publicKey = null, ?string $secretKey = null): PromiseInterface {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('POST', "/services/{$serviceId}/unlock", $publicKey, $secretKey, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bootstrap logs for a service.
|
||||
*
|
||||
* @param string $serviceId Service ID
|
||||
* @param bool $all If true, get all logs; if false, get last 9000 lines
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return PromiseInterface Resolves to response array with log content
|
||||
*/
|
||||
public function getServiceLogs(
|
||||
string $serviceId,
|
||||
bool $all = false,
|
||||
?string $publicKey = null,
|
||||
?string $secretKey = null
|
||||
): PromiseInterface {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
$path = "/services/{$serviceId}/logs" . ($all ? '?all=true' : '');
|
||||
return $this->makeRequest('GET', $path, $publicKey, $secretKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get environment vault status for a service.
|
||||
*
|
||||
* @param string $serviceId Service ID
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return PromiseInterface Resolves to response array with vault status (has_vault, count, updated_at)
|
||||
*/
|
||||
public function getServiceEnv(string $serviceId, ?string $publicKey = null, ?string $secretKey = null): PromiseInterface {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('GET', "/services/{$serviceId}/env", $publicKey, $secretKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set environment vault for a service.
|
||||
*
|
||||
* @param string $serviceId Service ID
|
||||
* @param string $env Environment content in .env format (KEY=VALUE\nKEY2=VALUE2)
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return PromiseInterface Resolves to response array with update confirmation
|
||||
*/
|
||||
public function setServiceEnv(
|
||||
string $serviceId,
|
||||
string $env,
|
||||
?string $publicKey = null,
|
||||
?string $secretKey = null
|
||||
): PromiseInterface {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequestRaw('PUT', "/services/{$serviceId}/env", $publicKey, $secretKey, $env, 'text/plain');
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete environment vault for a service.
|
||||
*
|
||||
* @param string $serviceId Service ID
|
||||
* @param array|null $keys Optional specific keys to delete; if null, deletes entire vault
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return PromiseInterface Resolves to response array with deletion confirmation
|
||||
*/
|
||||
public function deleteServiceEnv(
|
||||
string $serviceId,
|
||||
?array $keys = null,
|
||||
?string $publicKey = null,
|
||||
?string $secretKey = null
|
||||
): PromiseInterface {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('DELETE', "/services/{$serviceId}/env", $publicKey, $secretKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Export environment vault for a service (returns .env format).
|
||||
*
|
||||
* @param string $serviceId Service ID
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return PromiseInterface Resolves to response array with env content
|
||||
*/
|
||||
public function exportServiceEnv(string $serviceId, ?string $publicKey = null, ?string $secretKey = null): PromiseInterface {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('POST', "/services/{$serviceId}/env/export", $publicKey, $secretKey, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Redeploy a service (re-run bootstrap script).
|
||||
*
|
||||
* @param string $serviceId Service ID
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return PromiseInterface Resolves to response array with redeploy confirmation
|
||||
*/
|
||||
public function redeployService(string $serviceId, ?string $publicKey = null, ?string $secretKey = null): PromiseInterface {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('POST', "/services/{$serviceId}/redeploy", $publicKey, $secretKey, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a command in a running service container.
|
||||
*
|
||||
* @param string $serviceId Service ID
|
||||
* @param string $command Command to execute
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @param int $timeout Timeout in milliseconds (default: 30000)
|
||||
* @return PromiseInterface Resolves to response array with command output (stdout, stderr, exit_code)
|
||||
*/
|
||||
public function executeInService(
|
||||
string $serviceId,
|
||||
string $command,
|
||||
?string $publicKey = null,
|
||||
?string $secretKey = null,
|
||||
int $timeout = 30000
|
||||
): PromiseInterface {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
|
||||
return $this->makeRequest('POST', "/services/{$serviceId}/execute", $publicKey, $secretKey, [
|
||||
'command' => $command,
|
||||
'timeout' => $timeout,
|
||||
])->then(function (array $response) use ($publicKey, $secretKey) {
|
||||
// If we got a job_id, poll until completion
|
||||
$jobId = $response['job_id'] ?? null;
|
||||
if ($jobId) {
|
||||
return $this->waitForJob($jobId, $publicKey, $secretKey);
|
||||
}
|
||||
return $response;
|
||||
});
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Key Validation
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* Validate API keys.
|
||||
*
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return PromiseInterface Resolves to response array with validation result
|
||||
*/
|
||||
public function validateKeys(?string $publicKey = null, ?string $secretKey = null): PromiseInterface {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('POST', '/keys/validate', $publicKey, $secretKey, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get path to ~/.unsandbox directory, creating if necessary.
|
||||
*
|
||||
|
|
@ -660,6 +1199,58 @@ class UnsandboxAsync {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an authenticated HTTP request with raw body content (non-JSON) asynchronously.
|
||||
*
|
||||
* @param string $method HTTP method (PUT, POST, etc.)
|
||||
* @param string $path API endpoint path
|
||||
* @param string $publicKey API public key
|
||||
* @param string $secretKey API secret key
|
||||
* @param string $body Raw request body
|
||||
* @param string $contentType Content type header (e.g., 'text/plain')
|
||||
* @return PromiseInterface Resolves to decoded JSON response array
|
||||
*/
|
||||
private function makeRequestRaw(string $method, string $path, string $publicKey, string $secretKey, string $body, string $contentType = 'text/plain'): PromiseInterface {
|
||||
$timestamp = time();
|
||||
|
||||
$signature = $this->signRequest($secretKey, $timestamp, $method, $path, $body);
|
||||
|
||||
$headers = [
|
||||
'Authorization' => 'Bearer ' . $publicKey,
|
||||
'X-Timestamp' => (string)$timestamp,
|
||||
'X-Signature' => $signature,
|
||||
'Content-Type' => $contentType,
|
||||
];
|
||||
|
||||
$options = [
|
||||
'headers' => $headers,
|
||||
'body' => $body,
|
||||
];
|
||||
|
||||
return $this->httpClient->requestAsync($method, $path, $options)->then(
|
||||
function ($response) {
|
||||
$body = (string)$response->getBody();
|
||||
$decoded = json_decode($body, true);
|
||||
if ($decoded === null && json_last_error() !== JSON_ERROR_NONE) {
|
||||
throw new AsyncApiException("Invalid JSON response: " . json_last_error_msg());
|
||||
}
|
||||
return $decoded;
|
||||
},
|
||||
function ($exception) {
|
||||
if ($exception instanceof RequestException) {
|
||||
$response = $exception->getResponse();
|
||||
if ($response !== null) {
|
||||
$body = (string)$response->getBody();
|
||||
$decoded = json_decode($body, true);
|
||||
$errorMessage = $decoded['error'] ?? $decoded['message'] ?? "HTTP " . $response->getStatusCode();
|
||||
throw new AsyncApiException($errorMessage, $response->getStatusCode(), $decoded, $exception);
|
||||
}
|
||||
}
|
||||
throw new AsyncApiException($exception->getMessage(), 0, null, $exception);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get path to languages cache file.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -442,6 +442,602 @@ class Unsandbox {
|
|||
return $this->makeRequest('DELETE', "/snapshots/{$snapshotId}", $publicKey, $secretKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock a snapshot to prevent deletion.
|
||||
*
|
||||
* @param string $snapshotId Snapshot ID to lock
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return array Response array with lock confirmation
|
||||
* @throws CredentialsException Missing credentials
|
||||
* @throws ApiException API request failed
|
||||
*/
|
||||
public function lockSnapshot(string $snapshotId, ?string $publicKey = null, ?string $secretKey = null): array {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('POST', "/snapshots/{$snapshotId}/lock", $publicKey, $secretKey, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock a snapshot to allow deletion.
|
||||
*
|
||||
* @param string $snapshotId Snapshot ID to unlock
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return array Response array with unlock confirmation
|
||||
* @throws CredentialsException Missing credentials
|
||||
* @throws ApiException API request failed
|
||||
*/
|
||||
public function unlockSnapshot(string $snapshotId, ?string $publicKey = null, ?string $secretKey = null): array {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('POST', "/snapshots/{$snapshotId}/unlock", $publicKey, $secretKey, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone a snapshot to create a new session or service.
|
||||
*
|
||||
* @param string $snapshotId Snapshot ID to clone
|
||||
* @param string|null $name Optional name for the new resource
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @param array $opts Optional parameters: 'type' (session|service), 'shell', 'ports'
|
||||
* @return array Response array with cloned resource info
|
||||
* @throws CredentialsException Missing credentials
|
||||
* @throws ApiException API request failed
|
||||
*/
|
||||
public function cloneSnapshot(
|
||||
string $snapshotId,
|
||||
?string $name = null,
|
||||
?string $publicKey = null,
|
||||
?string $secretKey = null,
|
||||
array $opts = []
|
||||
): array {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
|
||||
$data = [];
|
||||
if ($name !== null) {
|
||||
$data['name'] = $name;
|
||||
}
|
||||
if (isset($opts['type'])) {
|
||||
$data['type'] = $opts['type'];
|
||||
}
|
||||
if (isset($opts['shell'])) {
|
||||
$data['shell'] = $opts['shell'];
|
||||
}
|
||||
if (isset($opts['ports'])) {
|
||||
$data['ports'] = $opts['ports'];
|
||||
}
|
||||
|
||||
return $this->makeRequest('POST', "/snapshots/{$snapshotId}/clone", $publicKey, $secretKey, $data);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Session Methods
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* List all active sessions for the authenticated account.
|
||||
*
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return array List of session arrays
|
||||
* @throws CredentialsException Missing credentials
|
||||
* @throws ApiException API request failed
|
||||
*/
|
||||
public function listSessions(?string $publicKey = null, ?string $secretKey = null): array {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
$response = $this->makeRequest('GET', '/sessions', $publicKey, $secretKey);
|
||||
return $response['sessions'] ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get details of a specific session.
|
||||
*
|
||||
* @param string $sessionId Session ID
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return array Session details
|
||||
* @throws CredentialsException Missing credentials
|
||||
* @throws ApiException API request failed
|
||||
*/
|
||||
public function getSession(string $sessionId, ?string $publicKey = null, ?string $secretKey = null): array {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('GET', "/sessions/{$sessionId}", $publicKey, $secretKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new interactive session.
|
||||
*
|
||||
* @param string $language Programming language or shell (e.g., "bash", "python3")
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @param array $opts Optional parameters: 'network_mode', 'ttl', 'shell', 'multiplexer', 'vcpu'
|
||||
* @return array Session info including session_id and container_name
|
||||
* @throws CredentialsException Missing credentials
|
||||
* @throws ApiException API request failed
|
||||
*/
|
||||
public function createSession(
|
||||
string $language,
|
||||
?string $publicKey = null,
|
||||
?string $secretKey = null,
|
||||
array $opts = []
|
||||
): array {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
|
||||
$data = [
|
||||
'network_mode' => $opts['network_mode'] ?? 'zerotrust',
|
||||
'ttl' => $opts['ttl'] ?? 3600,
|
||||
];
|
||||
if (!empty($language)) {
|
||||
$data['shell'] = $language;
|
||||
}
|
||||
if (isset($opts['shell'])) {
|
||||
$data['shell'] = $opts['shell'];
|
||||
}
|
||||
if (isset($opts['multiplexer'])) {
|
||||
$data['multiplexer'] = $opts['multiplexer'];
|
||||
}
|
||||
if (isset($opts['vcpu']) && $opts['vcpu'] > 1) {
|
||||
$data['vcpu'] = $opts['vcpu'];
|
||||
}
|
||||
if (isset($opts['input_files'])) {
|
||||
$data['input_files'] = $opts['input_files'];
|
||||
}
|
||||
|
||||
return $this->makeRequest('POST', '/sessions', $publicKey, $secretKey, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete (terminate) a session.
|
||||
*
|
||||
* @param string $sessionId Session ID to delete
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return array Response array with deletion confirmation
|
||||
* @throws CredentialsException Missing credentials
|
||||
* @throws ApiException API request failed
|
||||
*/
|
||||
public function deleteSession(string $sessionId, ?string $publicKey = null, ?string $secretKey = null): array {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('DELETE', "/sessions/{$sessionId}", $publicKey, $secretKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Freeze a session to pause execution and reduce resource usage.
|
||||
*
|
||||
* @param string $sessionId Session ID to freeze
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return array Response array with freeze confirmation
|
||||
* @throws CredentialsException Missing credentials
|
||||
* @throws ApiException API request failed
|
||||
*/
|
||||
public function freezeSession(string $sessionId, ?string $publicKey = null, ?string $secretKey = null): array {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('POST', "/sessions/{$sessionId}/freeze", $publicKey, $secretKey, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unfreeze a session to resume execution.
|
||||
*
|
||||
* @param string $sessionId Session ID to unfreeze
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return array Response array with unfreeze confirmation
|
||||
* @throws CredentialsException Missing credentials
|
||||
* @throws ApiException API request failed
|
||||
*/
|
||||
public function unfreezeSession(string $sessionId, ?string $publicKey = null, ?string $secretKey = null): array {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('POST', "/sessions/{$sessionId}/unfreeze", $publicKey, $secretKey, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Boost a session's resources (increase vCPU, memory is derived: vcpu * 2048MB).
|
||||
*
|
||||
* @param string $sessionId Session ID to boost
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @param int $vcpu Number of vCPUs (default: 2)
|
||||
* @return array Response array with boost confirmation
|
||||
* @throws CredentialsException Missing credentials
|
||||
* @throws ApiException API request failed
|
||||
*/
|
||||
public function boostSession(
|
||||
string $sessionId,
|
||||
?string $publicKey = null,
|
||||
?string $secretKey = null,
|
||||
int $vcpu = 2
|
||||
): array {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('POST', "/sessions/{$sessionId}/boost", $publicKey, $secretKey, ['vcpu' => $vcpu]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove boost from a session (return to base resources).
|
||||
*
|
||||
* @param string $sessionId Session ID to unboost
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return array Response array with unboost confirmation
|
||||
* @throws CredentialsException Missing credentials
|
||||
* @throws ApiException API request failed
|
||||
*/
|
||||
public function unboostSession(string $sessionId, ?string $publicKey = null, ?string $secretKey = null): array {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('POST', "/sessions/{$sessionId}/unboost", $publicKey, $secretKey, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a shell command in an active session.
|
||||
*
|
||||
* Note: This is for one-shot commands. For interactive sessions, use WebSocket connection.
|
||||
*
|
||||
* @param string $sessionId Session ID
|
||||
* @param string $command Command to execute
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return array Response array with command output
|
||||
* @throws CredentialsException Missing credentials
|
||||
* @throws ApiException API request failed
|
||||
*/
|
||||
public function shellSession(
|
||||
string $sessionId,
|
||||
string $command,
|
||||
?string $publicKey = null,
|
||||
?string $secretKey = null
|
||||
): array {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('POST', "/sessions/{$sessionId}/shell", $publicKey, $secretKey, ['command' => $command]);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Service Methods
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* List all services for the authenticated account.
|
||||
*
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return array List of service arrays
|
||||
* @throws CredentialsException Missing credentials
|
||||
* @throws ApiException API request failed
|
||||
*/
|
||||
public function listServices(?string $publicKey = null, ?string $secretKey = null): array {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
$response = $this->makeRequest('GET', '/services', $publicKey, $secretKey);
|
||||
return $response['services'] ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new persistent service.
|
||||
*
|
||||
* @param string $name Service name
|
||||
* @param array|string $ports Port(s) to expose (array of ints or comma-separated string)
|
||||
* @param string $bootstrap Bootstrap command or URL
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @param array $opts Optional parameters: 'network_mode', 'vcpu', 'service_type', 'custom_domains', 'bootstrap_content', 'input_files'
|
||||
* @return array Service info including service_id
|
||||
* @throws CredentialsException Missing credentials
|
||||
* @throws ApiException API request failed
|
||||
*/
|
||||
public function createService(
|
||||
string $name,
|
||||
$ports,
|
||||
string $bootstrap,
|
||||
?string $publicKey = null,
|
||||
?string $secretKey = null,
|
||||
array $opts = []
|
||||
): array {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
|
||||
// Convert ports to array if string
|
||||
if (is_string($ports)) {
|
||||
$ports = array_map('intval', explode(',', $ports));
|
||||
}
|
||||
|
||||
$data = [
|
||||
'name' => $name,
|
||||
'ports' => $ports,
|
||||
'bootstrap' => $bootstrap,
|
||||
];
|
||||
|
||||
if (isset($opts['network_mode'])) {
|
||||
$data['network_mode'] = $opts['network_mode'];
|
||||
}
|
||||
if (isset($opts['vcpu']) && $opts['vcpu'] > 1) {
|
||||
$data['vcpu'] = $opts['vcpu'];
|
||||
}
|
||||
if (isset($opts['service_type'])) {
|
||||
$data['service_type'] = $opts['service_type'];
|
||||
}
|
||||
if (isset($opts['custom_domains'])) {
|
||||
$data['custom_domains'] = $opts['custom_domains'];
|
||||
}
|
||||
if (isset($opts['bootstrap_content'])) {
|
||||
$data['bootstrap_content'] = $opts['bootstrap_content'];
|
||||
}
|
||||
if (isset($opts['input_files'])) {
|
||||
$data['input_files'] = $opts['input_files'];
|
||||
}
|
||||
|
||||
return $this->makeRequest('POST', '/services', $publicKey, $secretKey, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get details of a specific service.
|
||||
*
|
||||
* @param string $serviceId Service ID
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return array Service details
|
||||
* @throws CredentialsException Missing credentials
|
||||
* @throws ApiException API request failed
|
||||
*/
|
||||
public function getService(string $serviceId, ?string $publicKey = null, ?string $secretKey = null): array {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('GET', "/services/{$serviceId}", $publicKey, $secretKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a service (e.g., resize vCPU).
|
||||
*
|
||||
* @param string $serviceId Service ID
|
||||
* @param array $opts Update parameters: 'vcpu', 'name', etc.
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return array Updated service details
|
||||
* @throws CredentialsException Missing credentials
|
||||
* @throws ApiException API request failed
|
||||
*/
|
||||
public function updateService(
|
||||
string $serviceId,
|
||||
array $opts,
|
||||
?string $publicKey = null,
|
||||
?string $secretKey = null
|
||||
): array {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('PATCH', "/services/{$serviceId}", $publicKey, $secretKey, $opts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete (destroy) a service.
|
||||
*
|
||||
* @param string $serviceId Service ID to delete
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return array Response array with deletion confirmation
|
||||
* @throws CredentialsException Missing credentials
|
||||
* @throws ApiException API request failed
|
||||
*/
|
||||
public function deleteService(string $serviceId, ?string $publicKey = null, ?string $secretKey = null): array {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('DELETE', "/services/{$serviceId}", $publicKey, $secretKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Freeze a service to pause execution and reduce resource usage.
|
||||
*
|
||||
* @param string $serviceId Service ID to freeze
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return array Response array with freeze confirmation
|
||||
* @throws CredentialsException Missing credentials
|
||||
* @throws ApiException API request failed
|
||||
*/
|
||||
public function freezeService(string $serviceId, ?string $publicKey = null, ?string $secretKey = null): array {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('POST', "/services/{$serviceId}/freeze", $publicKey, $secretKey, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unfreeze a service to resume execution.
|
||||
*
|
||||
* @param string $serviceId Service ID to unfreeze
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return array Response array with unfreeze confirmation
|
||||
* @throws CredentialsException Missing credentials
|
||||
* @throws ApiException API request failed
|
||||
*/
|
||||
public function unfreezeService(string $serviceId, ?string $publicKey = null, ?string $secretKey = null): array {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('POST', "/services/{$serviceId}/unfreeze", $publicKey, $secretKey, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock a service to prevent deletion.
|
||||
*
|
||||
* @param string $serviceId Service ID to lock
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return array Response array with lock confirmation
|
||||
* @throws CredentialsException Missing credentials
|
||||
* @throws ApiException API request failed
|
||||
*/
|
||||
public function lockService(string $serviceId, ?string $publicKey = null, ?string $secretKey = null): array {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('POST', "/services/{$serviceId}/lock", $publicKey, $secretKey, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock a service to allow deletion.
|
||||
*
|
||||
* @param string $serviceId Service ID to unlock
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return array Response array with unlock confirmation
|
||||
* @throws CredentialsException Missing credentials
|
||||
* @throws ApiException API request failed
|
||||
*/
|
||||
public function unlockService(string $serviceId, ?string $publicKey = null, ?string $secretKey = null): array {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('POST', "/services/{$serviceId}/unlock", $publicKey, $secretKey, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bootstrap logs for a service.
|
||||
*
|
||||
* @param string $serviceId Service ID
|
||||
* @param bool $all If true, get all logs; if false, get last 9000 lines
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return array Response array with log content
|
||||
* @throws CredentialsException Missing credentials
|
||||
* @throws ApiException API request failed
|
||||
*/
|
||||
public function getServiceLogs(
|
||||
string $serviceId,
|
||||
bool $all = false,
|
||||
?string $publicKey = null,
|
||||
?string $secretKey = null
|
||||
): array {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
$path = "/services/{$serviceId}/logs" . ($all ? '?all=true' : '');
|
||||
return $this->makeRequest('GET', $path, $publicKey, $secretKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get environment vault status for a service.
|
||||
*
|
||||
* @param string $serviceId Service ID
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return array Response array with vault status (has_vault, count, updated_at)
|
||||
* @throws CredentialsException Missing credentials
|
||||
* @throws ApiException API request failed
|
||||
*/
|
||||
public function getServiceEnv(string $serviceId, ?string $publicKey = null, ?string $secretKey = null): array {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('GET', "/services/{$serviceId}/env", $publicKey, $secretKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set environment vault for a service.
|
||||
*
|
||||
* @param string $serviceId Service ID
|
||||
* @param string $env Environment content in .env format (KEY=VALUE\nKEY2=VALUE2)
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return array Response array with update confirmation
|
||||
* @throws CredentialsException Missing credentials
|
||||
* @throws ApiException API request failed
|
||||
*/
|
||||
public function setServiceEnv(
|
||||
string $serviceId,
|
||||
string $env,
|
||||
?string $publicKey = null,
|
||||
?string $secretKey = null
|
||||
): array {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequestRaw('PUT', "/services/{$serviceId}/env", $publicKey, $secretKey, $env, 'text/plain');
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete environment vault for a service.
|
||||
*
|
||||
* @param string $serviceId Service ID
|
||||
* @param array|null $keys Optional specific keys to delete; if null, deletes entire vault
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return array Response array with deletion confirmation
|
||||
* @throws CredentialsException Missing credentials
|
||||
* @throws ApiException API request failed
|
||||
*/
|
||||
public function deleteServiceEnv(
|
||||
string $serviceId,
|
||||
?array $keys = null,
|
||||
?string $publicKey = null,
|
||||
?string $secretKey = null
|
||||
): array {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('DELETE', "/services/{$serviceId}/env", $publicKey, $secretKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Export environment vault for a service (returns .env format).
|
||||
*
|
||||
* @param string $serviceId Service ID
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return array Response array with env content
|
||||
* @throws CredentialsException Missing credentials
|
||||
* @throws ApiException API request failed
|
||||
*/
|
||||
public function exportServiceEnv(string $serviceId, ?string $publicKey = null, ?string $secretKey = null): array {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('POST', "/services/{$serviceId}/env/export", $publicKey, $secretKey, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Redeploy a service (re-run bootstrap script).
|
||||
*
|
||||
* @param string $serviceId Service ID
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return array Response array with redeploy confirmation
|
||||
* @throws CredentialsException Missing credentials
|
||||
* @throws ApiException API request failed
|
||||
*/
|
||||
public function redeployService(string $serviceId, ?string $publicKey = null, ?string $secretKey = null): array {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('POST', "/services/{$serviceId}/redeploy", $publicKey, $secretKey, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a command in a running service container.
|
||||
*
|
||||
* @param string $serviceId Service ID
|
||||
* @param string $command Command to execute
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @param int $timeout Timeout in milliseconds (default: 30000)
|
||||
* @return array Response array with command output (stdout, stderr, exit_code)
|
||||
* @throws CredentialsException Missing credentials
|
||||
* @throws ApiException API request failed
|
||||
*/
|
||||
public function executeInService(
|
||||
string $serviceId,
|
||||
string $command,
|
||||
?string $publicKey = null,
|
||||
?string $secretKey = null,
|
||||
int $timeout = 30000
|
||||
): array {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
|
||||
$response = $this->makeRequest('POST', "/services/{$serviceId}/execute", $publicKey, $secretKey, [
|
||||
'command' => $command,
|
||||
'timeout' => $timeout,
|
||||
]);
|
||||
|
||||
// If we got a job_id, poll until completion
|
||||
$jobId = $response['job_id'] ?? null;
|
||||
if ($jobId) {
|
||||
return $this->waitForJob($jobId, $publicKey, $secretKey);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Key Validation
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* Validate API keys.
|
||||
*
|
||||
* @param string|null $publicKey Optional API key
|
||||
* @param string|null $secretKey Optional API secret
|
||||
* @return array Response array with validation result
|
||||
* @throws CredentialsException Missing credentials
|
||||
* @throws ApiException API request failed
|
||||
*/
|
||||
public function validateKeys(?string $publicKey = null, ?string $secretKey = null): array {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('POST', '/keys/validate', $publicKey, $secretKey, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get path to ~/.unsandbox directory, creating if necessary.
|
||||
*
|
||||
|
|
@ -616,6 +1212,14 @@ class Unsandbox {
|
|||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
|
||||
break;
|
||||
case 'PUT':
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
|
||||
break;
|
||||
case 'PATCH':
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH');
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
|
||||
break;
|
||||
case 'DELETE':
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
|
||||
break;
|
||||
|
|
@ -647,6 +1251,61 @@ class Unsandbox {
|
|||
return $decoded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an authenticated HTTP request with raw body content (non-JSON).
|
||||
*
|
||||
* @param string $method HTTP method (PUT, POST, etc.)
|
||||
* @param string $path API endpoint path
|
||||
* @param string $publicKey API public key
|
||||
* @param string $secretKey API secret key
|
||||
* @param string $body Raw request body
|
||||
* @param string $contentType Content type header (e.g., 'text/plain')
|
||||
* @return array Decoded JSON response
|
||||
* @throws ApiException On network errors or non-2xx response
|
||||
*/
|
||||
private function makeRequestRaw(string $method, string $path, string $publicKey, string $secretKey, string $body, string $contentType = 'text/plain'): array {
|
||||
$url = self::API_BASE . $path;
|
||||
$timestamp = time();
|
||||
|
||||
$signature = $this->signRequest($secretKey, $timestamp, $method, $path, $body);
|
||||
|
||||
$headers = [
|
||||
'Authorization: Bearer ' . $publicKey,
|
||||
'X-Timestamp: ' . $timestamp,
|
||||
'X-Signature: ' . $signature,
|
||||
'Content-Type: ' . $contentType,
|
||||
];
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 120);
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
$error = curl_error($ch);
|
||||
curl_close($ch);
|
||||
|
||||
if ($response === false) {
|
||||
throw new ApiException("cURL error: {$error}");
|
||||
}
|
||||
|
||||
$decoded = json_decode($response, true);
|
||||
if ($decoded === null && json_last_error() !== JSON_ERROR_NONE) {
|
||||
throw new ApiException("Invalid JSON response: " . json_last_error_msg());
|
||||
}
|
||||
|
||||
if ($httpCode >= 400) {
|
||||
$errorMessage = $decoded['error'] ?? $decoded['message'] ?? "HTTP {$httpCode}";
|
||||
throw new ApiException($errorMessage, $httpCode, $decoded);
|
||||
}
|
||||
|
||||
return $decoded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get path to languages cache file.
|
||||
*
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue