Tanzu Changes
This commit is contained in:
142
README.md
142
README.md
@@ -26,9 +26,9 @@ java -jar build/libs/cf-uploader-1.0.0.jar
|
||||
|
||||
The application will start on `http://localhost:8080`
|
||||
|
||||
## API Endpoint
|
||||
## API Endpoints
|
||||
|
||||
### Deploy Application to Cloud Foundry
|
||||
### 1. Deploy Application to Cloud Foundry
|
||||
|
||||
**Endpoint:** `POST /api/cf/deploy`
|
||||
|
||||
@@ -39,7 +39,7 @@ The application will start on `http://localhost:8080`
|
||||
- `jarFile` (file): The Java application JAR file
|
||||
- `manifest` (file): Cloud Foundry manifest.yml file
|
||||
|
||||
### Sample cURL Request
|
||||
#### Sample cURL Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/api/cf/deploy \
|
||||
@@ -56,7 +56,7 @@ curl -X POST http://localhost:8080/api/cf/deploy \
|
||||
-F 'manifest=@/path/to/manifest.yml'
|
||||
```
|
||||
|
||||
### Sample Request with Skip SSL Validation
|
||||
#### Sample Request with Skip SSL Validation
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/api/cf/deploy \
|
||||
@@ -73,6 +73,115 @@ curl -X POST http://localhost:8080/api/cf/deploy \
|
||||
-F 'manifest=@./manifest.yml'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. List Applications
|
||||
|
||||
**Endpoint:** `POST /api/cf/apps`
|
||||
|
||||
**Content-Type:** `application/json`
|
||||
|
||||
Lists all applications in the specified organization and space.
|
||||
|
||||
#### Sample cURL Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/api/cf/apps \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"apiEndpoint": "https://api.cf.example.com",
|
||||
"username": "your-username",
|
||||
"password": "your-password",
|
||||
"organization": "your-org",
|
||||
"space": "your-space",
|
||||
"appName": "",
|
||||
"skipSslValidation": false
|
||||
}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. List Routes
|
||||
|
||||
**Endpoint:** `POST /api/cf/routes`
|
||||
|
||||
**Content-Type:** `application/json`
|
||||
|
||||
Lists all routes in the specified organization and space.
|
||||
|
||||
#### Sample cURL Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/api/cf/routes \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"apiEndpoint": "https://api.cf.example.com",
|
||||
"username": "your-username",
|
||||
"password": "your-password",
|
||||
"organization": "your-org",
|
||||
"space": "your-space",
|
||||
"appName": "",
|
||||
"skipSslValidation": false
|
||||
}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. Get Application Details
|
||||
|
||||
**Endpoint:** `POST /api/cf/app/{appName}`
|
||||
|
||||
**Content-Type:** `application/json`
|
||||
|
||||
Gets detailed information about a specific application.
|
||||
|
||||
#### Sample cURL Request
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/api/cf/app/my-app \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"apiEndpoint": "https://api.cf.example.com",
|
||||
"username": "your-username",
|
||||
"password": "your-password",
|
||||
"organization": "your-org",
|
||||
"space": "your-space",
|
||||
"appName": "",
|
||||
"skipSslValidation": false
|
||||
}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5. Get Application Logs
|
||||
|
||||
**Endpoint:** `POST /api/cf/logs/{appName}?recent=true`
|
||||
|
||||
**Content-Type:** `application/json`
|
||||
|
||||
**Query Parameters:**
|
||||
- `recent` (optional, default: `true`): If true, gets recent logs; if false, tails logs
|
||||
|
||||
Gets logs for a specific application.
|
||||
|
||||
#### Sample cURL Request (Recent Logs)
|
||||
|
||||
```bash
|
||||
curl -X POST "http://localhost:8080/api/cf/logs/my-app?recent=true" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"apiEndpoint": "https://api.cf.example.com",
|
||||
"username": "your-username",
|
||||
"password": "your-password",
|
||||
"organization": "your-org",
|
||||
"space": "your-space",
|
||||
"appName": "",
|
||||
"skipSslValidation": false
|
||||
}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Sample Manifest File (manifest.yml)
|
||||
|
||||
```yaml
|
||||
@@ -88,7 +197,9 @@ applications:
|
||||
SPRING_PROFILES_ACTIVE: production
|
||||
```
|
||||
|
||||
## Request Parameters
|
||||
## Common Request Parameters
|
||||
|
||||
All endpoints require the following CF credentials and target information:
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
@@ -97,9 +208,11 @@ applications:
|
||||
| `password` | String | Yes | CF password |
|
||||
| `organization` | String | Yes | Target CF organization |
|
||||
| `space` | String | Yes | Target CF space |
|
||||
| `appName` | String | Yes | Application name |
|
||||
| `appName` | String | No* | Application name (required only for `/deploy` endpoint) |
|
||||
| `skipSslValidation` | Boolean | Yes | Skip SSL certificate validation |
|
||||
|
||||
**Note:** Even though `appName` is not used by utility endpoints (`/apps`, `/routes`, `/app/{appName}`, `/logs/{appName}`), it must still be included in the JSON request body (can be empty string). The organization and space determine which apps/routes are listed or queried.
|
||||
|
||||
## Response Format
|
||||
|
||||
### Success Response
|
||||
@@ -147,13 +260,16 @@ cf.cli.path=
|
||||
|
||||
## Features
|
||||
|
||||
- RESTful API for CF deployments
|
||||
- Automatic CF CLI binary management (Linux, macOS, Windows)
|
||||
- Secure password handling (masked in logs)
|
||||
- Configurable timeout for long-running deployments
|
||||
- Comprehensive error handling
|
||||
- Multipart file upload support up to 500MB
|
||||
- Automatic cleanup of temporary files
|
||||
- **Application Deployment**: Deploy JAR files to Cloud Foundry with manifest support
|
||||
- **Application Management**: List apps, view details, and access logs
|
||||
- **Route Management**: List all routes in your CF space
|
||||
- **Automatic CF CLI Management**: Bundled CF CLI binaries for Linux, macOS, and Windows
|
||||
- **Secure Password Handling**: Passwords are masked in all log output
|
||||
- **Comprehensive Logging**: Detailed DEBUG-level logging for troubleshooting deployments
|
||||
- **Configurable Timeouts**: Adjustable timeout for long-running deployments (default: 600s)
|
||||
- **Large File Support**: Multipart file upload support up to 500MB
|
||||
- **Automatic Cleanup**: Temporary files are automatically cleaned up after operations
|
||||
- **Error Handling**: Comprehensive exception handling with detailed error messages
|
||||
|
||||
## Error Handling
|
||||
|
||||
|
||||
39
build.gradle
39
build.gradle
@@ -42,6 +42,8 @@ task downloadCfCli {
|
||||
def resourcesDir = file("$projectDir/src/main/resources/cf-cli")
|
||||
resourcesDir.mkdirs()
|
||||
|
||||
// Download for all platforms (useful for local development on different OSes)
|
||||
// For production Tanzu deployment, only Linux binary will be used
|
||||
def downloads = [
|
||||
[os: 'linux', url: "https://packages.cloudfoundry.org/stable?release=linux64-binary&version=${cfCliVersion}&source=github-rel", ext: 'tgz', executable: 'cf'],
|
||||
[os: 'macos', url: "https://packages.cloudfoundry.org/stable?release=macosx64-binary&version=${cfCliVersion}&source=github-rel", ext: 'tgz', executable: 'cf'],
|
||||
@@ -81,5 +83,42 @@ task downloadCfCli {
|
||||
}
|
||||
}
|
||||
|
||||
// Task to download only Linux CF CLI (for production Tanzu builds)
|
||||
task downloadCfCliLinuxOnly {
|
||||
group = 'build'
|
||||
description = 'Downloads CF CLI binary for Linux only (production builds)'
|
||||
|
||||
doLast {
|
||||
def cfCliVersion = '8.7.10'
|
||||
def resourcesDir = file("$projectDir/src/main/resources/cf-cli")
|
||||
resourcesDir.mkdirs()
|
||||
|
||||
def download = [os: 'linux', url: "https://packages.cloudfoundry.org/stable?release=linux64-binary&version=${cfCliVersion}&source=github-rel", ext: 'tgz', executable: 'cf']
|
||||
|
||||
def osDir = file("${resourcesDir}/${download.os}")
|
||||
osDir.mkdirs()
|
||||
|
||||
def archiveFile = file("${osDir}/cf-cli.${download.ext}")
|
||||
|
||||
if (!archiveFile.exists()) {
|
||||
println "Downloading CF CLI for Linux..."
|
||||
ant.get(src: download.url, dest: archiveFile, verbose: true)
|
||||
|
||||
println "Extracting CF CLI for Linux..."
|
||||
copy {
|
||||
from tarTree(resources.gzip(archiveFile))
|
||||
into osDir
|
||||
}
|
||||
|
||||
archiveFile.delete()
|
||||
println "CF CLI for Linux downloaded and extracted successfully"
|
||||
} else {
|
||||
println "CF CLI for Linux already exists, skipping download"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure CF CLI is downloaded before building
|
||||
// Use downloadCfCli for local development (all platforms)
|
||||
// Use downloadCfCliLinuxOnly for production Tanzu builds (Linux only)
|
||||
processResources.dependsOn downloadCfCli
|
||||
|
||||
@@ -11,10 +11,7 @@ import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@RestController
|
||||
@@ -60,6 +57,67 @@ public class CfDeployController {
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/apps")
|
||||
public ResponseEntity<String> listApps(@RequestBody String requestJson) {
|
||||
try {
|
||||
log.info("Received request to list apps");
|
||||
CfDeployRequest request = objectMapper.readValue(requestJson, CfDeployRequest.class);
|
||||
String output = cfCliService.listApps(request);
|
||||
return ResponseEntity.ok(output);
|
||||
} catch (Exception e) {
|
||||
log.error("Error listing apps", e);
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.body("Failed to list apps: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/routes")
|
||||
public ResponseEntity<String> listRoutes(@RequestBody String requestJson) {
|
||||
try {
|
||||
log.info("Received request to list routes");
|
||||
CfDeployRequest request = objectMapper.readValue(requestJson, CfDeployRequest.class);
|
||||
String output = cfCliService.listRoutes(request);
|
||||
return ResponseEntity.ok(output);
|
||||
} catch (Exception e) {
|
||||
log.error("Error listing routes", e);
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.body("Failed to list routes: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/app/{appName}")
|
||||
public ResponseEntity<String> getAppDetails(
|
||||
@PathVariable String appName,
|
||||
@RequestBody String requestJson) {
|
||||
try {
|
||||
log.info("Received request to get details for app: {}", appName);
|
||||
CfDeployRequest request = objectMapper.readValue(requestJson, CfDeployRequest.class);
|
||||
String output = cfCliService.getAppDetails(request, appName);
|
||||
return ResponseEntity.ok(output);
|
||||
} catch (Exception e) {
|
||||
log.error("Error getting app details for: {}", appName, e);
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.body("Failed to get app details: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/logs/{appName}")
|
||||
public ResponseEntity<String> getAppLogs(
|
||||
@PathVariable String appName,
|
||||
@RequestParam(defaultValue = "true") boolean recent,
|
||||
@RequestBody String requestJson) {
|
||||
try {
|
||||
log.info("Received request to get {} logs for app: {}", recent ? "recent" : "tail", appName);
|
||||
CfDeployRequest request = objectMapper.readValue(requestJson, CfDeployRequest.class);
|
||||
String output = cfCliService.getAppLogs(request, appName, recent);
|
||||
return ResponseEntity.ok(output);
|
||||
} catch (Exception e) {
|
||||
log.error("Error getting logs for: {}", appName, e);
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.body("Failed to get app logs: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void validateFiles(MultipartFile jarFile, MultipartFile manifest) {
|
||||
if (jarFile.isEmpty()) {
|
||||
throw new IllegalArgumentException("JAR file is empty");
|
||||
|
||||
@@ -39,28 +39,41 @@ public class CfCliService {
|
||||
public CfDeployResponse deployApplication(CfDeployRequest request, MultipartFile jarFile, MultipartFile manifest) {
|
||||
Path tempDir = null;
|
||||
try {
|
||||
log.info("=== Starting deployment for app: {} ===", request.getAppName());
|
||||
log.info("Target: {}/{}/{}", request.getApiEndpoint(), request.getOrganization(), request.getSpace());
|
||||
|
||||
tempDir = Files.createTempDirectory("cf-deploy-");
|
||||
log.info("Created temporary directory: {}", tempDir);
|
||||
|
||||
Path jarPath = tempDir.resolve(jarFile.getOriginalFilename());
|
||||
Path manifestPath = tempDir.resolve("manifest.yml");
|
||||
|
||||
log.debug("Copying uploaded files - JAR: {}, Manifest: {}", jarFile.getOriginalFilename(), manifest.getOriginalFilename());
|
||||
log.debug("JAR file size: {} bytes", jarFile.getSize());
|
||||
log.debug("Manifest file size: {} bytes", manifest.getSize());
|
||||
|
||||
Files.copy(jarFile.getInputStream(), jarPath, StandardCopyOption.REPLACE_EXISTING);
|
||||
Files.copy(manifest.getInputStream(), manifestPath, StandardCopyOption.REPLACE_EXISTING);
|
||||
|
||||
log.info("Copied JAR and manifest files to temporary directory");
|
||||
log.info("Successfully copied JAR: {} ({} bytes) to {}", jarFile.getOriginalFilename(), jarFile.getSize(), jarPath);
|
||||
log.info("Successfully copied manifest to {}", manifestPath);
|
||||
log.debug("JAR absolute path: {}", jarPath.toAbsolutePath());
|
||||
log.debug("JAR file exists: {}", Files.exists(jarPath));
|
||||
log.debug("JAR file is readable: {}", Files.isReadable(jarPath));
|
||||
|
||||
StringBuilder output = new StringBuilder();
|
||||
|
||||
login(request, output);
|
||||
pushApplication(request, tempDir, output);
|
||||
pushApplication(request, tempDir, jarPath, output);
|
||||
logout(output);
|
||||
|
||||
log.info("Deployment completed successfully for app: {}", request.getAppName());
|
||||
log.info("=== Deployment completed successfully for app: {} ===", request.getAppName());
|
||||
return CfDeployResponse.success(output.toString());
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Deployment failed for app: {}", request.getAppName(), e);
|
||||
log.error("=== Deployment failed for app: {} ===", request.getAppName());
|
||||
log.error("Error type: {}", e.getClass().getName());
|
||||
log.error("Error message: {}", e.getMessage(), e);
|
||||
return CfDeployResponse.failure(e.getMessage(), e.toString());
|
||||
} finally {
|
||||
if (tempDir != null) {
|
||||
@@ -94,7 +107,7 @@ public class CfCliService {
|
||||
log.info("Successfully logged into Cloud Foundry");
|
||||
}
|
||||
|
||||
private void pushApplication(CfDeployRequest request, Path workingDir, StringBuilder output) throws Exception {
|
||||
private void pushApplication(CfDeployRequest request, Path workingDir, Path jarPath, StringBuilder output) throws Exception {
|
||||
log.info("Pushing application: {}", request.getAppName());
|
||||
|
||||
List<String> command = new ArrayList<>();
|
||||
@@ -103,6 +116,8 @@ public class CfCliService {
|
||||
command.add(request.getAppName());
|
||||
command.add("-f");
|
||||
command.add("manifest.yml");
|
||||
command.add("-p");
|
||||
command.add(jarPath.toAbsolutePath().toString());
|
||||
|
||||
executeCommand(command, output, false, workingDir.toFile());
|
||||
log.info("Successfully pushed application: {}", request.getAppName());
|
||||
@@ -127,6 +142,7 @@ public class CfCliService {
|
||||
ProcessBuilder processBuilder = new ProcessBuilder(command);
|
||||
if (workingDir != null) {
|
||||
processBuilder.directory(workingDir);
|
||||
log.debug("Working directory: {}", workingDir.getAbsolutePath());
|
||||
}
|
||||
processBuilder.redirectErrorStream(true);
|
||||
|
||||
@@ -137,50 +153,70 @@ public class CfCliService {
|
||||
maskedCommand.set(i + 1, "********");
|
||||
}
|
||||
}
|
||||
log.debug("Executing command: {}", String.join(" ", maskedCommand));
|
||||
log.info("Executing CF CLI command: {}", String.join(" ", maskedCommand));
|
||||
} else {
|
||||
log.debug("Executing command: {}", String.join(" ", command));
|
||||
log.info("Executing CF CLI command: {}", String.join(" ", command));
|
||||
}
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
Process process = processBuilder.start();
|
||||
log.debug("Process started with PID: {}", process.pid());
|
||||
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
|
||||
String line;
|
||||
int lineCount = 0;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
lineCount++;
|
||||
output.append(line).append("\n");
|
||||
log.debug("CF CLI output: {}", line);
|
||||
log.info("CF CLI: {}", line);
|
||||
}
|
||||
log.debug("Command produced {} lines of output", lineCount);
|
||||
}
|
||||
|
||||
boolean finished = process.waitFor(timeout, TimeUnit.SECONDS);
|
||||
long duration = System.currentTimeMillis() - startTime;
|
||||
|
||||
if (!finished) {
|
||||
log.error("Command execution timed out after {} seconds", timeout);
|
||||
process.destroyForcibly();
|
||||
throw new RuntimeException("Command execution timed out after " + timeout + " seconds");
|
||||
}
|
||||
|
||||
int exitCode = process.exitValue();
|
||||
log.info("Command completed in {}ms with exit code: {}", duration, exitCode);
|
||||
|
||||
if (exitCode != 0) {
|
||||
log.error("Command failed with exit code: {}", exitCode);
|
||||
log.error("Command output:\n{}", output.toString());
|
||||
throw new RuntimeException("Command failed with exit code: " + exitCode);
|
||||
}
|
||||
}
|
||||
|
||||
private String getCfCliExecutable() throws IOException {
|
||||
if (cfCliPath != null && !cfCliPath.isEmpty()) {
|
||||
log.info("Using custom CF CLI path: {}", cfCliPath);
|
||||
return cfCliPath;
|
||||
}
|
||||
|
||||
String os = getOperatingSystem();
|
||||
String executable = os.equals("windows") ? "cf.exe" : "cf";
|
||||
|
||||
log.info("Detected operating system: {}", os);
|
||||
log.debug("CF CLI executable name: {}", executable);
|
||||
|
||||
String resourcePath = String.format("/cf-cli/%s/%s", os, executable);
|
||||
File tempFile = File.createTempFile("cf-cli-", os.equals("windows") ? ".exe" : "");
|
||||
tempFile.deleteOnExit();
|
||||
|
||||
log.debug("Extracting CF CLI from resource path: {}", resourcePath);
|
||||
|
||||
try (var inputStream = getClass().getResourceAsStream(resourcePath)) {
|
||||
if (inputStream == null) {
|
||||
throw new IOException("CF CLI binary not found for OS: " + os);
|
||||
log.error("CF CLI binary not found in resources for OS: {}. Expected path: {}", os, resourcePath);
|
||||
throw new IOException("CF CLI binary not found for OS: " + os + " at path: " + resourcePath);
|
||||
}
|
||||
Files.copy(inputStream, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
log.debug("CF CLI extracted to temporary file: {}", tempFile.getAbsolutePath());
|
||||
}
|
||||
|
||||
if (!os.equals("windows")) {
|
||||
@@ -189,14 +225,16 @@ public class CfCliService {
|
||||
perms.add(PosixFilePermission.OWNER_WRITE);
|
||||
perms.add(PosixFilePermission.OWNER_EXECUTE);
|
||||
Files.setPosixFilePermissions(tempFile.toPath(), perms);
|
||||
log.debug("Set executable permissions on CF CLI binary");
|
||||
}
|
||||
|
||||
log.debug("Using CF CLI executable: {}", tempFile.getAbsolutePath());
|
||||
log.info("Using CF CLI executable: {}", tempFile.getAbsolutePath());
|
||||
return tempFile.getAbsolutePath();
|
||||
}
|
||||
|
||||
private String getOperatingSystem() {
|
||||
String osName = System.getProperty("os.name").toLowerCase();
|
||||
log.debug("System OS name property: {}", osName);
|
||||
if (osName.contains("win")) {
|
||||
return "windows";
|
||||
} else if (osName.contains("mac")) {
|
||||
@@ -222,4 +260,97 @@ public class CfCliService {
|
||||
log.warn("Failed to clean up temporary directory: {}", tempDir, e);
|
||||
}
|
||||
}
|
||||
|
||||
public String listApps(CfDeployRequest request) {
|
||||
try {
|
||||
log.info("Listing applications for org: {}, space: {}", request.getOrganization(), request.getSpace());
|
||||
StringBuilder output = new StringBuilder();
|
||||
|
||||
login(request, output);
|
||||
|
||||
List<String> command = new ArrayList<>();
|
||||
command.add(getCfCliExecutable());
|
||||
command.add("apps");
|
||||
|
||||
executeCommand(command, output, false);
|
||||
logout(output);
|
||||
|
||||
log.info("Successfully retrieved apps list");
|
||||
return output.toString();
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to list apps", e);
|
||||
throw new RuntimeException("Failed to list apps: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public String listRoutes(CfDeployRequest request) {
|
||||
try {
|
||||
log.info("Listing routes for org: {}, space: {}", request.getOrganization(), request.getSpace());
|
||||
StringBuilder output = new StringBuilder();
|
||||
|
||||
login(request, output);
|
||||
|
||||
List<String> command = new ArrayList<>();
|
||||
command.add(getCfCliExecutable());
|
||||
command.add("routes");
|
||||
|
||||
executeCommand(command, output, false);
|
||||
logout(output);
|
||||
|
||||
log.info("Successfully retrieved routes list");
|
||||
return output.toString();
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to list routes", e);
|
||||
throw new RuntimeException("Failed to list routes: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public String getAppDetails(CfDeployRequest request, String appName) {
|
||||
try {
|
||||
log.info("Getting details for app: {} in org: {}, space: {}", appName, request.getOrganization(), request.getSpace());
|
||||
StringBuilder output = new StringBuilder();
|
||||
|
||||
login(request, output);
|
||||
|
||||
List<String> command = new ArrayList<>();
|
||||
command.add(getCfCliExecutable());
|
||||
command.add("app");
|
||||
command.add(appName);
|
||||
|
||||
executeCommand(command, output, false);
|
||||
logout(output);
|
||||
|
||||
log.info("Successfully retrieved app details for: {}", appName);
|
||||
return output.toString();
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to get app details for: {}", appName, e);
|
||||
throw new RuntimeException("Failed to get app details: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public String getAppLogs(CfDeployRequest request, String appName, boolean recent) {
|
||||
try {
|
||||
log.info("Getting {} logs for app: {}", recent ? "recent" : "tail", appName);
|
||||
StringBuilder output = new StringBuilder();
|
||||
|
||||
login(request, output);
|
||||
|
||||
List<String> command = new ArrayList<>();
|
||||
command.add(getCfCliExecutable());
|
||||
command.add("logs");
|
||||
command.add(appName);
|
||||
if (recent) {
|
||||
command.add("--recent");
|
||||
}
|
||||
|
||||
executeCommand(command, output, false);
|
||||
logout(output);
|
||||
|
||||
log.info("Successfully retrieved logs for: {}", appName);
|
||||
return output.toString();
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to get logs for: {}", appName, e);
|
||||
throw new RuntimeException("Failed to get app logs: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user