feat: add --show-freeze-page and --no-show-freeze-page CLI flags
Add CLI support for toggling the show_freeze_page service setting, which controls whether frozen services display an HTML payment page or return a JSON error response. Updated 18 SDK implementations + CLI_SPEC.md documentation.
This commit is contained in:
parent
1b76be5277
commit
eeb1dcb3dc
19 changed files with 438 additions and 2 deletions
|
|
@ -165,6 +165,10 @@ un service --snapshot ID # Create snapshot
|
|||
| `--destroy ID` | Delete service |
|
||||
| `--lock ID` | Prevent deletion |
|
||||
| `--unlock ID` | Allow deletion |
|
||||
| `--auto-unfreeze ID` | Enable auto-unfreeze on HTTP request |
|
||||
| `--no-auto-unfreeze ID` | Disable auto-unfreeze |
|
||||
| `--show-freeze-page ID` | Show payment page when frozen (default) |
|
||||
| `--no-show-freeze-page ID` | Return JSON error when frozen |
|
||||
| `--resize ID` | Resize (with --vcpu) |
|
||||
| `--redeploy ID` | Re-run bootstrap |
|
||||
| `--execute ID CMD` | Run command |
|
||||
|
|
|
|||
|
|
@ -3411,6 +3411,67 @@ static int set_unfreeze_on_demand(const UnsandboxCredentials *creds, const char
|
|||
return 0;
|
||||
}
|
||||
|
||||
// Set show_freeze_page for a service (controls whether frozen services show payment page or JSON error)
|
||||
static int set_show_freeze_page(const UnsandboxCredentials *creds, const char *service_id, int enabled) {
|
||||
CURL *curl = curl_easy_init();
|
||||
if (!curl) return 1;
|
||||
|
||||
struct ResponseBuffer response = {0};
|
||||
response.data = malloc(1);
|
||||
response.size = 0;
|
||||
|
||||
char url[512];
|
||||
snprintf(url, sizeof(url), "%s/services/%s", API_BASE, service_id);
|
||||
|
||||
char path[256];
|
||||
snprintf(path, sizeof(path), "/services/%s", service_id);
|
||||
|
||||
char body[128];
|
||||
snprintf(body, sizeof(body), "{\"show_freeze_page\":%s}", enabled ? "true" : "false");
|
||||
|
||||
struct curl_slist *headers = NULL;
|
||||
headers = add_hmac_auth_headers(headers, creds, "PATCH", path, body);
|
||||
headers = curl_slist_append(headers, "Content-Type: application/json");
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PATCH");
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body);
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
|
||||
|
||||
CURLcode res = curl_easy_perform(curl);
|
||||
|
||||
long http_code = 0;
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
|
||||
|
||||
curl_slist_free_all(headers);
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
if (res != CURLE_OK) {
|
||||
fprintf(stderr, "Error: %s\n", curl_easy_strerror(res));
|
||||
free(response.data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (http_code == 404) {
|
||||
fprintf(stderr, "Error: Service not found\n");
|
||||
free(response.data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (http_code != 200) {
|
||||
fprintf(stderr, "Error: HTTP %ld\n", http_code);
|
||||
if (response.data) fprintf(stderr, "%s\n", response.data);
|
||||
free(response.data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("\033[32mFreeze page %s\033[0m\n", enabled ? "enabled" : "disabled");
|
||||
free(response.data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Resize a service (change vCPU/memory live)
|
||||
static int resize_service(const UnsandboxCredentials *creds, const char *service_id, int vcpu) {
|
||||
CURL *curl = curl_easy_init();
|
||||
|
|
@ -5897,6 +5958,8 @@ void print_usage(const char *prog) {
|
|||
fprintf(stderr, " --unlock ID Unlock a service to allow deletion\n");
|
||||
fprintf(stderr, " --auto-unfreeze ID Enable auto-unfreeze on HTTP request\n");
|
||||
fprintf(stderr, " --no-auto-unfreeze ID Disable auto-unfreeze on HTTP request\n");
|
||||
fprintf(stderr, " --show-freeze-page ID Enable freeze page (show payment page when frozen)\n");
|
||||
fprintf(stderr, " --no-show-freeze-page ID Disable freeze page (return JSON error when frozen)\n");
|
||||
fprintf(stderr, " --resize ID Resize service vCPU/memory (requires --vcpu)\n");
|
||||
fprintf(stderr, " --redeploy ID Re-run bootstrap script (optional: --bootstrap or --bootstrap-file)\n");
|
||||
fprintf(stderr, " --execute ID CMD Run a command in a running service\n");
|
||||
|
|
@ -9068,6 +9131,8 @@ int main(int argc, char *argv[]) {
|
|||
int do_unlock = 0;
|
||||
int do_auto_unfreeze = 0;
|
||||
int do_no_auto_unfreeze = 0;
|
||||
int do_show_freeze_page = 0;
|
||||
int do_no_show_freeze_page = 0;
|
||||
int do_resize = 0;
|
||||
int do_redeploy = 0;
|
||||
int do_execute = 0;
|
||||
|
|
@ -9229,6 +9294,14 @@ int main(int argc, char *argv[]) {
|
|||
do_no_auto_unfreeze = 1;
|
||||
i++;
|
||||
service_id = argv[i];
|
||||
} else if (strcmp(argv[i], "--show-freeze-page") == 0 && i + 1 < argc) {
|
||||
do_show_freeze_page = 1;
|
||||
i++;
|
||||
service_id = argv[i];
|
||||
} else if (strcmp(argv[i], "--no-show-freeze-page") == 0 && i + 1 < argc) {
|
||||
do_no_show_freeze_page = 1;
|
||||
i++;
|
||||
service_id = argv[i];
|
||||
} else if (strcmp(argv[i], "--resize") == 0 && i + 1 < argc) {
|
||||
do_resize = 1;
|
||||
i++;
|
||||
|
|
@ -9426,6 +9499,10 @@ int main(int argc, char *argv[]) {
|
|||
ret = set_unfreeze_on_demand(creds, service_id, 1);
|
||||
} else if (do_no_auto_unfreeze) {
|
||||
ret = set_unfreeze_on_demand(creds, service_id, 0);
|
||||
} else if (do_show_freeze_page) {
|
||||
ret = set_show_freeze_page(creds, service_id, 1);
|
||||
} else if (do_no_show_freeze_page) {
|
||||
ret = set_show_freeze_page(creds, service_id, 0);
|
||||
} else if (do_resize) {
|
||||
if (vcpu < 1 || vcpu > 8) {
|
||||
fprintf(stderr, "Error: --vcpu must be 1-8 for resize\n");
|
||||
|
|
|
|||
|
|
@ -419,6 +419,18 @@ class Un
|
|||
return;
|
||||
}
|
||||
|
||||
if (args.ServiceShowFreezePage != null)
|
||||
{
|
||||
var payload = new Dictionary<string, object>
|
||||
{
|
||||
["show_freeze_page"] = args.ServiceShowFreezePageEnabled
|
||||
};
|
||||
ApiRequest($"/services/{args.ServiceShowFreezePage}", "PATCH", payload, publicKey, secretKey);
|
||||
string status = args.ServiceShowFreezePageEnabled ? "enabled" : "disabled";
|
||||
Console.WriteLine($"{GREEN}Show-freeze-page {status} for service: {args.ServiceShowFreezePage}{RESET}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.ServiceDestroy != null)
|
||||
{
|
||||
ApiRequest($"/services/{args.ServiceDestroy}", "DELETE", null, publicKey, secretKey);
|
||||
|
|
@ -1163,6 +1175,8 @@ class Un
|
|||
public string ServiceDumpFile = null;
|
||||
public string ServiceUnfreezeOnDemand = null;
|
||||
public bool ServiceUnfreezeOnDemandEnabled = true;
|
||||
public string ServiceShowFreezePage = null;
|
||||
public bool ServiceShowFreezePageEnabled = true;
|
||||
public bool ServiceCreateUnfreezeOnDemand = false;
|
||||
public string EnvFile = null;
|
||||
public string EnvAction = null;
|
||||
|
|
@ -1222,6 +1236,8 @@ class Un
|
|||
else if (arg == "--dump-file") result.ServiceDumpFile = args[++i];
|
||||
else if (arg == "--unfreeze-on-demand") result.ServiceUnfreezeOnDemand = args[++i];
|
||||
else if (arg == "--unfreeze-on-demand-enabled") result.ServiceUnfreezeOnDemandEnabled = args[++i].ToLower() == "true";
|
||||
else if (arg == "--show-freeze-page") result.ServiceShowFreezePage = args[++i];
|
||||
else if (arg == "--show-freeze-page-enabled") result.ServiceShowFreezePageEnabled = args[++i].ToLower() == "true";
|
||||
else if (arg == "--with-unfreeze-on-demand") result.ServiceCreateUnfreezeOnDemand = true;
|
||||
else if (arg == "--extend") result.KeyExtend = true;
|
||||
else if (!arg.StartsWith("-")) result.SourceFile = arg;
|
||||
|
|
@ -1264,6 +1280,8 @@ Service options:
|
|||
--unfreeze ID Unfreeze service
|
||||
--unfreeze-on-demand ID Set unfreeze-on-demand for service
|
||||
--unfreeze-on-demand-enabled BOOL Enable/disable (default: true)
|
||||
--show-freeze-page ID Set show-freeze-page for service
|
||||
--show-freeze-page-enabled BOOL Enable/disable (default: true)
|
||||
--with-unfreeze-on-demand Enable unfreeze-on-demand when creating service
|
||||
--destroy ID Destroy service
|
||||
--execute ID Execute command in service
|
||||
|
|
|
|||
|
|
@ -104,6 +104,8 @@ class Args {
|
|||
String? serviceUnfreezeOnDemand;
|
||||
bool serviceUnfreezeOnDemandEnabled = true;
|
||||
bool serviceCreateUnfreezeOnDemand = false;
|
||||
String? serviceShowFreezePage;
|
||||
bool serviceShowFreezePageEnabled = true;
|
||||
bool keyExtend = false;
|
||||
String? envFile;
|
||||
String? envAction;
|
||||
|
|
@ -657,6 +659,14 @@ Future<void> cmdService(Args args) async {
|
|||
return;
|
||||
}
|
||||
|
||||
if (args.serviceShowFreezePage != null) {
|
||||
final payload = {'show_freeze_page': args.serviceShowFreezePageEnabled};
|
||||
await apiRequestCurl('/services/${args.serviceShowFreezePage}', 'PATCH', jsonEncode(payload), publicKey, secretKey);
|
||||
final status = args.serviceShowFreezePageEnabled ? 'enabled' : 'disabled';
|
||||
print('${green}Show-freeze-page $status for service: ${args.serviceShowFreezePage}$reset');
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.serviceDestroy != null) {
|
||||
await apiRequestCurl('/services/${args.serviceDestroy}', 'DELETE', null, publicKey, secretKey);
|
||||
print('${green}Service destroyed: ${args.serviceDestroy}$reset');
|
||||
|
|
@ -1114,6 +1124,12 @@ Args parseArgs(List<String> argv) {
|
|||
case '--with-unfreeze-on-demand':
|
||||
args.serviceCreateUnfreezeOnDemand = true;
|
||||
break;
|
||||
case '--show-freeze-page':
|
||||
args.serviceShowFreezePage = argv[++i];
|
||||
break;
|
||||
case '--show-freeze-page-enabled':
|
||||
args.serviceShowFreezePageEnabled = argv[++i].toLowerCase() == 'true';
|
||||
break;
|
||||
case '--extend':
|
||||
args.keyExtend = true;
|
||||
break;
|
||||
|
|
@ -1228,6 +1244,8 @@ Service options:
|
|||
--unfreeze-on-demand ID Set unfreeze-on-demand for service
|
||||
--unfreeze-on-demand-enabled BOOL Enable/disable (default: true)
|
||||
--with-unfreeze-on-demand Enable unfreeze-on-demand when creating service
|
||||
--show-freeze-page ID Set show-freeze-page for service
|
||||
--show-freeze-page-enabled BOOL Enable/disable (default: true)
|
||||
--destroy ID Destroy service
|
||||
--execute ID Execute command in service
|
||||
--command CMD Command to execute (with --execute)
|
||||
|
|
|
|||
|
|
@ -351,6 +351,15 @@ void CmdService(Args args)
|
|||
return;
|
||||
}
|
||||
|
||||
if (args.ServiceShowFreezePage != null)
|
||||
{
|
||||
var payload = new Dictionary<string, object> { ["show_freeze_page"] = args.ServiceShowFreezePageEnabled };
|
||||
await ApiRequestAsync($"/services/{args.ServiceShowFreezePage}", new HttpMethod("PATCH"), payload, publicKey, secretKey);
|
||||
string status = args.ServiceShowFreezePageEnabled ? "enabled" : "disabled";
|
||||
Console.WriteLine($"{GREEN}Show-freeze-page {status} for service: {args.ServiceShowFreezePage}{RESET}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.ServiceDestroy != null)
|
||||
{
|
||||
ApiRequest($"/services/{args.ServiceDestroy}", HttpMethod.Delete, null, publicKey, secretKey);
|
||||
|
|
@ -934,6 +943,8 @@ Args ParseArgs(string[] args)
|
|||
else if (arg == "--dump-file") result.ServiceDumpFile = args[++i];
|
||||
else if (arg == "--unfreeze-on-demand") result.ServiceUnfreezeOnDemand = args[++i];
|
||||
else if (arg == "--unfreeze-on-demand-enabled") result.ServiceUnfreezeOnDemandEnabled = args[++i].ToLower() == "true";
|
||||
else if (arg == "--show-freeze-page") result.ServiceShowFreezePage = args[++i];
|
||||
else if (arg == "--show-freeze-page-enabled") result.ServiceShowFreezePageEnabled = args[++i].ToLower() == "true";
|
||||
else if (arg == "--with-unfreeze-on-demand") result.ServiceCreateUnfreezeOnDemand = true;
|
||||
else if (arg == "--extend") result.KeyExtend = true;
|
||||
else if (arg == "--delete")
|
||||
|
|
@ -1016,6 +1027,8 @@ Service options:
|
|||
--snapshot ID Create snapshot from service
|
||||
--unfreeze-on-demand ID Set unfreeze-on-demand for service
|
||||
--unfreeze-on-demand-enabled BOOL Enable/disable (default: true)
|
||||
--show-freeze-page ID Set show-freeze-page for service
|
||||
--show-freeze-page-enabled BOOL Enable/disable (default: true)
|
||||
--with-unfreeze-on-demand Enable unfreeze-on-demand when creating service
|
||||
--destroy ID Destroy service
|
||||
--execute ID Execute command in service
|
||||
|
|
@ -1081,6 +1094,8 @@ class Args
|
|||
public string? ServiceDumpBootstrap, ServiceDumpFile;
|
||||
public string? ServiceUnfreezeOnDemand;
|
||||
public bool ServiceUnfreezeOnDemandEnabled = true;
|
||||
public string? ServiceShowFreezePage;
|
||||
public bool ServiceShowFreezePageEnabled = true;
|
||||
public bool ServiceCreateUnfreezeOnDemand;
|
||||
public string? EnvFile, EnvAction, EnvTarget;
|
||||
public bool KeyExtend;
|
||||
|
|
|
|||
|
|
@ -1325,6 +1325,24 @@ func SetUnfreezeOnDemand(creds *Credentials, serviceID string, enabled bool) <-c
|
|||
return resultChan
|
||||
}
|
||||
|
||||
// SetShowFreezePage enables or disables the freeze page display for a service.
|
||||
// When enabled, frozen services show a branded "waking up" page instead of an error.
|
||||
// Returns a channel that receives exactly one ServiceResult then closes.
|
||||
func SetShowFreezePage(creds *Credentials, serviceID string, enabled bool) <-chan ServiceResult {
|
||||
resultChan := make(chan ServiceResult, 1)
|
||||
|
||||
go func() {
|
||||
defer close(resultChan)
|
||||
|
||||
response, err := makeRequest("PATCH", fmt.Sprintf("/services/%s", serviceID), creds, map[string]interface{}{
|
||||
"show_freeze_page": enabled,
|
||||
})
|
||||
resultChan <- ServiceResult{Data: response, Err: err}
|
||||
}()
|
||||
|
||||
return resultChan
|
||||
}
|
||||
|
||||
// GetServiceLogs retrieves logs from a service.
|
||||
// Returns a channel that receives exactly one ServiceResult then closes.
|
||||
//
|
||||
|
|
|
|||
|
|
@ -1545,6 +1545,30 @@ public class UnsandboxAsync {
|
|||
return makeRequestWithMethod("PATCH", "/services/" + serviceId, creds[0], creds[1], data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set show-freeze-page for a service.
|
||||
*
|
||||
* <p>When enabled, visitors to a frozen service will see a branded "frozen" page
|
||||
* instead of an error. This improves UX for services that use unfreeze-on-demand.
|
||||
*
|
||||
* @param serviceId Service ID to configure
|
||||
* @param enabled True to show freeze page, false to hide it
|
||||
* @param publicKey Optional API key
|
||||
* @param secretKey Optional API secret
|
||||
* @return CompletableFuture containing response map with update confirmation
|
||||
*/
|
||||
public static CompletableFuture<Map<String, Object>> setShowFreezePage(
|
||||
String serviceId,
|
||||
boolean enabled,
|
||||
String publicKey,
|
||||
String secretKey
|
||||
) {
|
||||
String[] creds = resolveCredentials(publicKey, secretKey);
|
||||
Map<String, Object> data = new LinkedHashMap<>();
|
||||
data.put("show_freeze_page", enabled);
|
||||
return makeRequestWithMethod("PATCH", "/services/" + serviceId, creds[0], creds[1], data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bootstrap logs for a service.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1566,6 +1566,33 @@ public class Un {
|
|||
return makeRequestWithMethod("PATCH", "/services/" + serviceId, creds[0], creds[1], data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set show-freeze-page for a service.
|
||||
*
|
||||
* <p>When enabled, visitors to a frozen service will see a branded "frozen" page
|
||||
* instead of an error. This improves UX for services that use unfreeze-on-demand.
|
||||
*
|
||||
* @param serviceId Service ID to configure
|
||||
* @param enabled True to show freeze page, false to hide it
|
||||
* @param publicKey Optional API key
|
||||
* @param secretKey Optional API secret
|
||||
* @return Response map with update confirmation
|
||||
* @throws IOException on network errors
|
||||
* @throws CredentialsException if credentials cannot be found
|
||||
* @throws ApiException if API returns an error
|
||||
*/
|
||||
public static Map<String, Object> setShowFreezePage(
|
||||
String serviceId,
|
||||
boolean enabled,
|
||||
String publicKey,
|
||||
String secretKey
|
||||
) throws IOException {
|
||||
String[] creds = resolveCredentials(publicKey, secretKey);
|
||||
Map<String, Object> data = new LinkedHashMap<>();
|
||||
data.put("show_freeze_page", enabled);
|
||||
return makeRequestWithMethod("PATCH", "/services/" + serviceId, creds[0], creds[1], data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bootstrap logs for a service.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
* freezeSession, unfreezeSession, boostSession, unboostSession, shellSession,
|
||||
* // Service management
|
||||
* listServices, createService, getService, updateService, deleteService,
|
||||
* freezeService, unfreezeService, lockService, unlockService, setUnfreezeOnDemand,
|
||||
* freezeService, unfreezeService, lockService, unlockService, setUnfreezeOnDemand, setShowFreezePage,
|
||||
* getServiceLogs, getServiceEnv, setServiceEnv, deleteServiceEnv,
|
||||
* exportServiceEnv, redeployService, executeInService,
|
||||
* // Snapshot management
|
||||
|
|
@ -1176,6 +1176,22 @@ async function setUnfreezeOnDemand(serviceId, enabled, publicKey, secretKey) {
|
|||
return makeRequest('PATCH', `/services/${serviceId}`, publicKey, secretKey, { unfreeze_on_demand: enabled });
|
||||
}
|
||||
|
||||
/**
|
||||
* Set show-freeze-page for a service.
|
||||
*
|
||||
* When enabled, frozen services will show a "frozen" page to visitors instead of an error.
|
||||
*
|
||||
* Args:
|
||||
* serviceId: Service ID to update
|
||||
* enabled: true to enable, false to disable
|
||||
*
|
||||
* Returns: Promise<Object> (update confirmation)
|
||||
*/
|
||||
async function setShowFreezePage(serviceId, enabled, publicKey, secretKey) {
|
||||
[publicKey, secretKey] = resolveCredentials(publicKey, secretKey);
|
||||
return makeRequest('PATCH', `/services/${serviceId}`, publicKey, secretKey, { show_freeze_page: enabled });
|
||||
}
|
||||
|
||||
/**
|
||||
* Get service logs.
|
||||
*
|
||||
|
|
@ -1434,6 +1450,7 @@ export {
|
|||
lockService,
|
||||
unlockService,
|
||||
setUnfreezeOnDemand,
|
||||
setShowFreezePage,
|
||||
getServiceLogs,
|
||||
getServiceEnv,
|
||||
setServiceEnv,
|
||||
|
|
@ -1493,6 +1510,7 @@ export default {
|
|||
lockService,
|
||||
unlockService,
|
||||
setUnfreezeOnDemand,
|
||||
setShowFreezePage,
|
||||
getServiceLogs,
|
||||
getServiceEnv,
|
||||
setServiceEnv,
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
* freezeSession, unfreezeSession, boostSession, unboostSession, shellSession,
|
||||
* // Service management
|
||||
* listServices, createService, getService, updateService, deleteService,
|
||||
* freezeService, unfreezeService, lockService, unlockService, setUnfreezeOnDemand,
|
||||
* freezeService, unfreezeService, lockService, unlockService, setUnfreezeOnDemand, setShowFreezePage,
|
||||
* getServiceLogs, getServiceEnv, setServiceEnv, deleteServiceEnv,
|
||||
* exportServiceEnv, redeployService, executeInService,
|
||||
* // Snapshot management
|
||||
|
|
@ -1160,6 +1160,22 @@ async function setUnfreezeOnDemand(serviceId, enabled, publicKey, secretKey) {
|
|||
return makeRequest('PATCH', `/services/${serviceId}`, publicKey, secretKey, { unfreeze_on_demand: enabled });
|
||||
}
|
||||
|
||||
/**
|
||||
* Set show-freeze-page for a service.
|
||||
*
|
||||
* When enabled, frozen services will show a "frozen" page to visitors instead of an error.
|
||||
*
|
||||
* Args:
|
||||
* serviceId: Service ID to update
|
||||
* enabled: true to enable, false to disable
|
||||
*
|
||||
* Returns: Promise<Object> (update confirmation)
|
||||
*/
|
||||
async function setShowFreezePage(serviceId, enabled, publicKey, secretKey) {
|
||||
[publicKey, secretKey] = resolveCredentials(publicKey, secretKey);
|
||||
return makeRequest('PATCH', `/services/${serviceId}`, publicKey, secretKey, { show_freeze_page: enabled });
|
||||
}
|
||||
|
||||
/**
|
||||
* Get service logs.
|
||||
*
|
||||
|
|
@ -1663,6 +1679,7 @@ export {
|
|||
lockService,
|
||||
unlockService,
|
||||
setUnfreezeOnDemand,
|
||||
setShowFreezePage,
|
||||
getServiceLogs,
|
||||
getServiceEnv,
|
||||
setServiceEnv,
|
||||
|
|
|
|||
|
|
@ -105,6 +105,8 @@ data class Args(
|
|||
var serviceResize: String? = null,
|
||||
var serviceUnfreezeOnDemand: String? = null,
|
||||
var serviceUnfreezeOnDemandValue: Boolean? = null,
|
||||
var serviceShowFreezePage: String? = null,
|
||||
var serviceshowFreezePageValue: Boolean? = null,
|
||||
var keyExtend: Boolean = false,
|
||||
var envFile: String? = null,
|
||||
var envAction: String? = null,
|
||||
|
|
@ -376,6 +378,17 @@ fun cmdService(args: Args) {
|
|||
return
|
||||
}
|
||||
|
||||
if (args.serviceShowFreezePage != null) {
|
||||
if (args.serviceshowFreezePageValue == null) {
|
||||
System.err.println("${RED}Error: --show-freeze-page requires true or false${RESET}")
|
||||
exitProcess(1)
|
||||
}
|
||||
val payload = mapOf("show_freeze_page" to args.serviceshowFreezePageValue!!)
|
||||
apiRequestPatch("/services/${args.serviceShowFreezePage}", payload, publicKey, secretKey)
|
||||
println("${GREEN}Service show_freeze_page set to ${args.serviceshowFreezePageValue}: ${args.serviceShowFreezePage}${RESET}")
|
||||
return
|
||||
}
|
||||
|
||||
if (args.serviceExecute != null) {
|
||||
val payload = mutableMapOf<String, Any>("command" to args.serviceCommand!!)
|
||||
val result = apiRequest("/services/${args.serviceExecute}/execute", "POST", payload, publicKey, secretKey)
|
||||
|
|
@ -1164,6 +1177,12 @@ fun parseArgs(args: Array<String>): Args {
|
|||
result.serviceUnfreezeOnDemandValue = args[++i].toBoolean()
|
||||
}
|
||||
}
|
||||
"--show-freeze-page" -> {
|
||||
result.serviceShowFreezePage = args[++i]
|
||||
if (i + 1 < args.size && (args[i + 1] == "true" || args[i + 1] == "false")) {
|
||||
result.serviceshowFreezePageValue = args[++i].toBoolean()
|
||||
}
|
||||
}
|
||||
"--execute" -> result.serviceExecute = args[++i]
|
||||
"--command" -> result.serviceCommand = args[++i]
|
||||
"--dump-bootstrap" -> result.serviceDumpBootstrap = args[++i]
|
||||
|
|
@ -1264,6 +1283,7 @@ Service options:
|
|||
--destroy ID Destroy service
|
||||
--resize ID Resize service (requires --vcpu N)
|
||||
--unfreeze-on-demand ID true|false Enable/disable auto-unfreeze on HTTP request
|
||||
--show-freeze-page ID true|false Enable/disable showing freeze page when frozen
|
||||
--execute ID Execute command in service
|
||||
--command CMD Command to execute (with --execute)
|
||||
--dump-bootstrap ID Dump bootstrap script
|
||||
|
|
|
|||
|
|
@ -744,6 +744,17 @@ sub cmd_service {
|
|||
return;
|
||||
}
|
||||
|
||||
if ($options->{set_show_freeze_page}) {
|
||||
my $enabled = ($options->{set_show_freeze_page_enabled} &&
|
||||
($options->{set_show_freeze_page_enabled} eq 'true' || $options->{set_show_freeze_page_enabled} eq '1'))
|
||||
? JSON::PP::true : JSON::PP::false;
|
||||
my $payload = { show_freeze_page => $enabled };
|
||||
api_request("/services/$options->{set_show_freeze_page}", 'PATCH', $payload, $public_key, $secret_key);
|
||||
my $status = $enabled ? 'enabled' : 'disabled';
|
||||
print "${GREEN}Show-freeze-page $status for service: $options->{set_show_freeze_page}${RESET}\n";
|
||||
return;
|
||||
}
|
||||
|
||||
if ($options->{execute}) {
|
||||
my $payload = { command => $options->{command} };
|
||||
my $result = api_request("/services/$options->{execute}/execute", 'POST', $payload, $public_key, $secret_key);
|
||||
|
|
@ -1187,6 +1198,9 @@ sub main {
|
|||
} elsif ($arg eq '--set-unfreeze-on-demand') {
|
||||
$options{set_unfreeze_on_demand} = $ARGV[++$i];
|
||||
$options{set_unfreeze_on_demand_enabled} = $ARGV[++$i] if defined $ARGV[$i + 1];
|
||||
} elsif ($arg eq '--set-show-freeze-page') {
|
||||
$options{set_show_freeze_page} = $ARGV[++$i];
|
||||
$options{set_show_freeze_page_enabled} = $ARGV[++$i] if defined $ARGV[$i + 1];
|
||||
} elsif ($arg =~ /^-/) {
|
||||
print STDERR "${RED}Unknown option: $arg${RESET}\n";
|
||||
exit 1;
|
||||
|
|
@ -1279,6 +1293,8 @@ Service options:
|
|||
--command CMD Command to execute (with --execute)
|
||||
--dump-bootstrap ID Dump bootstrap script
|
||||
--dump-file FILE File to save bootstrap (with --dump-bootstrap)
|
||||
--set-unfreeze-on-demand ID BOOL Enable/disable auto-unfreeze on HTTP request
|
||||
--set-show-freeze-page ID BOOL Enable/disable showing freeze page when frozen
|
||||
|
||||
Key options:
|
||||
--extend Open browser to extend/renew key
|
||||
|
|
|
|||
|
|
@ -877,6 +877,20 @@ class UnsandboxAsync {
|
|||
return $this->makeRequest('PATCH', "/services/{$serviceId}", $publicKey, $secretKey, ['unfreeze_on_demand' => $enabled]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set show_freeze_page flag for a service.
|
||||
*
|
||||
* @param string $serviceId Service ID
|
||||
* @param bool $enabled Whether to enable show freeze page
|
||||
* @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 setShowFreezePage(string $serviceId, bool $enabled, ?string $publicKey = null, ?string $secretKey = null): PromiseInterface {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('PATCH', "/services/{$serviceId}", $publicKey, $secretKey, ['show_freeze_page' => $enabled]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bootstrap logs for a service.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1199,6 +1199,22 @@ class Unsandbox {
|
|||
return $this->makeRequest('PATCH', "/services/{$serviceId}", $publicKey, $secretKey, ['unfreeze_on_demand' => $enabled]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set show_freeze_page flag for a service.
|
||||
*
|
||||
* @param string $serviceId Service ID
|
||||
* @param bool $enabled Whether to enable show freeze page
|
||||
* @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 setShowFreezePage(string $serviceId, bool $enabled, ?string $publicKey = null, ?string $secretKey = null): array {
|
||||
[$publicKey, $secretKey] = $this->resolveCredentials($publicKey, $secretKey);
|
||||
return $this->makeRequest('PATCH', "/services/{$serviceId}", $publicKey, $secretKey, ['show_freeze_page' => $enabled]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bootstrap logs for a service.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ Library Usage:
|
|||
lock_service,
|
||||
unlock_service,
|
||||
set_unfreeze_on_demand,
|
||||
set_show_freeze_page,
|
||||
get_service_logs,
|
||||
get_service_env,
|
||||
set_service_env,
|
||||
|
|
@ -1316,6 +1317,42 @@ async def set_unfreeze_on_demand(
|
|||
)
|
||||
|
||||
|
||||
async def set_show_freeze_page(
|
||||
service_id: str,
|
||||
enabled: bool,
|
||||
public_key: Optional[str] = None,
|
||||
secret_key: Optional[str] = None,
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Enable or disable freeze page display for a service.
|
||||
|
||||
When disabled, frozen services return a JSON error response instead of
|
||||
displaying the payment/unfreeze page to visitors.
|
||||
|
||||
Args:
|
||||
service_id: Service ID to configure
|
||||
enabled: True to show freeze page, False to return JSON error
|
||||
public_key: Optional API key
|
||||
secret_key: Optional API secret
|
||||
|
||||
Returns:
|
||||
Response dict with update confirmation
|
||||
|
||||
Raises:
|
||||
aiohttp.ClientError: Network errors
|
||||
ValueError: Invalid response format
|
||||
CredentialsError: Missing credentials
|
||||
"""
|
||||
public_key, secret_key = _resolve_credentials(public_key, secret_key)
|
||||
return await _make_request(
|
||||
"PATCH",
|
||||
f"/services/{service_id}",
|
||||
public_key,
|
||||
secret_key,
|
||||
{"show_freeze_page": enabled},
|
||||
)
|
||||
|
||||
|
||||
async def get_service_logs(
|
||||
service_id: str,
|
||||
all_logs: bool = False,
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ Library Usage:
|
|||
lock_service,
|
||||
unlock_service,
|
||||
set_unfreeze_on_demand,
|
||||
set_show_freeze_page,
|
||||
get_service_logs,
|
||||
get_service_env,
|
||||
set_service_env,
|
||||
|
|
@ -1330,6 +1331,42 @@ def set_unfreeze_on_demand(
|
|||
)
|
||||
|
||||
|
||||
def set_show_freeze_page(
|
||||
service_id: str,
|
||||
enabled: bool,
|
||||
public_key: Optional[str] = None,
|
||||
secret_key: Optional[str] = None,
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Enable or disable freeze page display for a service.
|
||||
|
||||
When disabled, frozen services return a JSON error response instead of
|
||||
displaying the payment/unfreeze page to visitors.
|
||||
|
||||
Args:
|
||||
service_id: Service ID to configure
|
||||
enabled: True to show freeze page, False to return JSON error
|
||||
public_key: Optional API key
|
||||
secret_key: Optional API secret
|
||||
|
||||
Returns:
|
||||
Response dict with update confirmation
|
||||
|
||||
Raises:
|
||||
requests.RequestException: Network errors
|
||||
ValueError: Invalid response format
|
||||
CredentialsError: Missing credentials
|
||||
"""
|
||||
public_key, secret_key = _resolve_credentials(public_key, secret_key)
|
||||
return _make_request(
|
||||
"PATCH",
|
||||
f"/services/{service_id}",
|
||||
public_key,
|
||||
secret_key,
|
||||
{"show_freeze_page": enabled},
|
||||
)
|
||||
|
||||
|
||||
def get_service_logs(
|
||||
service_id: str,
|
||||
all_logs: bool = False,
|
||||
|
|
|
|||
|
|
@ -943,6 +943,27 @@ module UnAsync
|
|||
end
|
||||
end
|
||||
|
||||
# Set show-freeze-page for a service
|
||||
#
|
||||
# When enabled, frozen services show a freeze page instead of 502 error.
|
||||
#
|
||||
# @param service_id [String] Service ID to update
|
||||
# @param enabled [Boolean] Whether to enable show-freeze-page
|
||||
# @param public_key [String, nil] Optional API key
|
||||
# @param secret_key [String, nil] Optional API secret
|
||||
# @return [Future<Hash>] Future resolving to response hash with update confirmation
|
||||
# @raise [CredentialsError] If no credentials found (on .value)
|
||||
# @raise [APIError] If API request fails (on .value)
|
||||
#
|
||||
# @example
|
||||
# UnAsync.set_show_freeze_page(service_id, true).value
|
||||
def set_show_freeze_page(service_id, enabled, public_key: nil, secret_key: nil)
|
||||
Future.new do
|
||||
pk, sk = resolve_credentials(public_key, secret_key)
|
||||
make_request_sync('PATCH', "/services/#{service_id}", pk, sk, { show_freeze_page: enabled })
|
||||
end
|
||||
end
|
||||
|
||||
# Get service logs (bootstrap output)
|
||||
#
|
||||
# @param service_id [String] Service ID to get logs for
|
||||
|
|
|
|||
|
|
@ -1054,6 +1054,25 @@ module Un
|
|||
make_request('PATCH', "/services/#{service_id}", pk, sk, { unfreeze_on_demand: enabled })
|
||||
end
|
||||
|
||||
# Set show-freeze-page for a service
|
||||
#
|
||||
# When enabled, frozen services show a freeze page instead of 502 error.
|
||||
#
|
||||
# @param service_id [String] Service ID to update
|
||||
# @param enabled [Boolean] Whether to enable show-freeze-page
|
||||
# @param public_key [String, nil] Optional API key
|
||||
# @param secret_key [String, nil] Optional API secret
|
||||
# @return [Hash] Response hash with update confirmation
|
||||
# @raise [CredentialsError] If no credentials found
|
||||
# @raise [APIError] If API request fails
|
||||
#
|
||||
# @example
|
||||
# Un.set_show_freeze_page(service_id, true)
|
||||
def set_show_freeze_page(service_id, enabled, public_key: nil, secret_key: nil)
|
||||
pk, sk = resolve_credentials(public_key, secret_key)
|
||||
make_request('PATCH', "/services/#{service_id}", pk, sk, { show_freeze_page: enabled })
|
||||
end
|
||||
|
||||
# Get service logs (bootstrap output)
|
||||
#
|
||||
# @param service_id [String] Service ID to get logs for
|
||||
|
|
|
|||
|
|
@ -143,6 +143,8 @@ interface Args {
|
|||
imageClone: string | null;
|
||||
unfreezeOnDemand: boolean | null;
|
||||
setUnfreezeOnDemand: string | null;
|
||||
showFreezePage: boolean | null;
|
||||
setShowFreezePage: string | null;
|
||||
}
|
||||
|
||||
interface ApiKeys {
|
||||
|
|
@ -697,6 +699,14 @@ async function cmdService(args: Args): Promise<void> {
|
|||
return;
|
||||
}
|
||||
|
||||
if (args.setShowFreezePage) {
|
||||
const enabled = args.showFreezePage === true;
|
||||
const payload = { show_freeze_page: enabled };
|
||||
await apiRequest(`/services/${args.setShowFreezePage}`, "PATCH", payload, keys);
|
||||
console.log(`${GREEN}Show freeze page ${enabled ? 'enabled' : 'disabled'} for service ${args.setShowFreezePage}${RESET}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.execute) {
|
||||
const payload = { command: args.command_arg };
|
||||
const result = await apiRequest(`/services/${args.execute}/execute`, "POST", payload, keys);
|
||||
|
|
@ -1023,6 +1033,8 @@ function parseArgs(argv: string[]): Args {
|
|||
imageClone: null,
|
||||
unfreezeOnDemand: null,
|
||||
setUnfreezeOnDemand: null,
|
||||
showFreezePage: null,
|
||||
setShowFreezePage: null,
|
||||
};
|
||||
|
||||
let i = 2;
|
||||
|
|
@ -1189,6 +1201,12 @@ function parseArgs(argv: string[]): Args {
|
|||
} else if (arg === '--set-unfreeze-on-demand' && i + 1 < argv.length) {
|
||||
args.setUnfreezeOnDemand = argv[++i];
|
||||
i++;
|
||||
} else if (arg === '--show-freeze-page') {
|
||||
args.showFreezePage = true;
|
||||
i++;
|
||||
} else if (arg === '--set-show-freeze-page' && i + 1 < argv.length) {
|
||||
args.setShowFreezePage = argv[++i];
|
||||
i++;
|
||||
} else if (!arg.startsWith('-')) {
|
||||
args.sourceFile = arg;
|
||||
i++;
|
||||
|
|
@ -1272,6 +1290,8 @@ Service options:
|
|||
--dump-file FILE File to save bootstrap (with --dump-bootstrap)
|
||||
--unfreeze-on-demand Enable unfreeze on demand (with --name or --set-unfreeze-on-demand)
|
||||
--set-unfreeze-on-demand ID Set unfreeze on demand for service
|
||||
--show-freeze-page Enable show freeze page (with --name or --set-show-freeze-page)
|
||||
--set-show-freeze-page ID Set show freeze page for service
|
||||
|
||||
Image options:
|
||||
--list List all images
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue