Skip to content

Commit

Permalink
Merge pull request #100 from hyun357123/main
Browse files Browse the repository at this point in the history
resolve conflict
  • Loading branch information
hyun357123 authored Nov 20, 2024
2 parents 83a7766 + 1f6951f commit d846339
Show file tree
Hide file tree
Showing 101 changed files with 4,653 additions and 1,685 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"java.compile.nullAnalysis.mode": "automatic",
"java.dependency.packagePresentation": "hierarchical"
"java.dependency.packagePresentation": "hierarchical",
"java.configuration.updateBuildConfiguration": "automatic"
}
17 changes: 17 additions & 0 deletions applicationFE/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,11 @@ dependencies {
implementation 'io.kubernetes:client-java-api:20.0.0'
implementation 'io.kubernetes:client-java-extended:20.0.0'

implementation 'com.github.docker-java:docker-java:3.3.0'
implementation 'com.github.docker-java:docker-java-transport-httpclient5:3.3.0'

implementation 'io.github.cdancy:jenkins-rest:1.0.1:all'


}

Expand Down
3 changes: 3 additions & 0 deletions src/main/java/kr/co/mcmp/ApplicationManagerApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.scheduling.annotation.EnableScheduling;

import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.io.UnsupportedEncodingException;
Expand All @@ -11,6 +13,7 @@
@EnableSwagger2
@SpringBootApplication
@EnableFeignClients
@EnableScheduling
public class ApplicationManagerApplication {

public static void main(String[] args) throws GeneralSecurityException, UnsupportedEncodingException {
Expand Down
152 changes: 124 additions & 28 deletions src/main/java/kr/co/mcmp/ape/cbtumblebug/api/CbtumblebugRestApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClientException;
import org.springframework.web.util.UriComponentsBuilder;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import kr.co.mcmp.ape.cbtumblebug.dto.K8sClusterDto;
Expand All @@ -25,8 +28,9 @@
import kr.co.mcmp.ape.cbtumblebug.dto.MciResponse;
import kr.co.mcmp.ape.cbtumblebug.dto.NamespaceDto;
import kr.co.mcmp.ape.cbtumblebug.dto.NamespaceResponse;
import kr.co.mcmp.ape.cbtumblebug.dto.MciAccessInfoDto;
import kr.co.mcmp.ape.cbtumblebug.dto.Spec;
import kr.co.mcmp.ape.cbtumblebug.dto.VmDto;
import kr.co.mcmp.ape.cbtumblebug.dto.VmAccessInfo;
import kr.co.mcmp.ape.cbtumblebug.exception.CbtumblebugException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -50,6 +54,10 @@ public class CbtumblebugRestApi {

private final CbtumblebugRestClient restClient;

private boolean isTumblebugReady = false;
private long lastCheckTime = 0;
private static final long CHECK_INTERVAL = 60000; // 1 minute

private HttpHeaders createCommonHeaders() {
HttpHeaders headers = new HttpHeaders();
String auth = cbtumblebugId + ":" + cbtumblebugPass;
Expand All @@ -66,7 +74,7 @@ private String createApiUrl(String endpoint) {

return apiUrl;
}

/*
public boolean checkTumblebug() {
log.info("Checking if Tumblebug is ready");
String apiUrl = createApiUrl("/tumblebug/readyz");
Expand All @@ -79,16 +87,104 @@ public boolean checkTumblebug() {
log.error("Tumblebug connection failed", e);
return false;
}
}
}
private <T> T executeWithConnectionCheck(String operationName, Supplier<T> apiCall) {
if (!checkTumblebug()) {
log.error("Tumblebug에 연결할 수 없습니다. {} 작업을 수행할 수 없습니다.", operationName);
throw new CbtumblebugException("Tumblebug 연결 실패");
}
return apiCall.get();
}
*/

public boolean checkTumblebug() {
long currentTime = System.currentTimeMillis();
if (currentTime - lastCheckTime > CHECK_INTERVAL || !isTumblebugReady) {
log.info("Checking if Tumblebug is ready");
String apiUrl = createApiUrl("/tumblebug/readyz");
HttpHeaders headers = createCommonHeaders();
try {
ResponseEntity<String> response = restClient.request(apiUrl, headers, null, HttpMethod.GET, new ParameterizedTypeReference<String>() {});
isTumblebugReady = response.getStatusCode().is2xxSuccessful();
lastCheckTime = currentTime;
} catch (Exception e) {
log.error("Tumblebug connection failed", e);
isTumblebugReady = false;
}
}
return isTumblebugReady;
}

public <T> T executeWithConnectionCheck(String operationName, Supplier<T> apiCall) {
if (!checkTumblebug()) {
throw new CbtumblebugException("Tumblebug is not ready");
}
return apiCall.get();
}


public String executeMciCommand(String nsId, String mciId, String command, String subGroupId, String vmId) {
log.info("Executing command on MCI: {}, VM: {}", mciId, vmId);
return executeWithConnectionCheck("executeMciCommand", () -> {
try {
String apiUrl = createApiUrl(String.format("/tumblebug/ns/%s/cmd/mci/%s", nsId, mciId));
HttpHeaders headers = createCommonHeaders();

// 요청 본문 생성
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("command", Collections.singletonList(command));

// 쿼리 파라미터 추가
if (subGroupId != null && !subGroupId.isEmpty()) {
apiUrl += "?subGroupId=" + subGroupId;
}
if (vmId != null && !vmId.isEmpty()) {
apiUrl += (apiUrl.contains("?") ? "&" : "?") + "vmId=" + vmId;
}

String jsonBody = new ObjectMapper().writeValueAsString(requestBody);

ResponseEntity<String> response = restClient.request(
apiUrl,
headers,
jsonBody,
HttpMethod.POST,
new ParameterizedTypeReference<String>() {}
);

if (response.getStatusCode().is2xxSuccessful()) {
String responseBody = response.getBody();
log.info("command result: {}", response.getBody());
ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.readTree(responseBody);
JsonNode resultsNode = rootNode.path("results");
if (resultsNode.isArray() && resultsNode.size() > 0) {
JsonNode firstResult = resultsNode.get(0);
String stdout = firstResult.path("stdout").path("0").asText();
String stderr = firstResult.path("stderr").path("0").asText();
if (!stderr.isEmpty()) {
log.warn("Command execution produced stderr: {}", stderr);
}
return stdout;
} else {
throw new CbtumblebugException("Unexpected response format");
}
} else {
throw new CbtumblebugException("MCI command execution failed. Status code: " + response.getStatusCodeValue());
}

} catch (JsonProcessingException e) {
log.error("Error serializing request body", e);
throw new CbtumblebugException("Failed to serialize request body: " + e.getMessage());
} catch (RestClientException e) {
log.error("Error executing command on MCI", e);
throw new CbtumblebugException("Failed to execute command on MCI: " + e.getMessage());
}
});
}

public List<NamespaceDto> getAllNamespace() {
log.info("Fetching all namespaces");
return executeWithConnectionCheck("getAllNamespace", () ->{
Expand All @@ -109,15 +205,27 @@ public List<MciDto> getMcisByNamespace(String namespace) {
});
}

// public String getK8sClusterInfo(){
// log.info("Fetching all K8sClusterInfo");
// return executeWithConnectionCheck("getK8sClusterInfo", () ->{
// String apiUrl = createApiUrl("/k8sClusterInfo");
// HttpHeaders headers = createCommonHeaders();
// ResponseEntity<String> response = restClient.request(apiUrl, headers, headers, HttpMethod.GET, new ParameterizedTypeReference<String>() {});
// return response.getBody() != null ? response.getBody() : null;
// });
// }
public MciAccessInfoDto getSSHKeyForMci(String namespace, String mciId) {
log.info("Fetching SSH Key for MCI: {} in namespace: {}", mciId, namespace);
return executeWithConnectionCheck("getSSHKeyForMci", () -> {
String apiUrl = createApiUrl(String.format("/tumblebug/ns/%s/mci/%s", namespace, mciId));
HttpHeaders headers = createCommonHeaders();

UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(apiUrl)
.queryParam("option", "accessinfo")
.queryParam("accessInfoOption", "showSshKey");

ResponseEntity<MciAccessInfoDto> response = restClient.request(
builder.toUriString(),
headers,
null,
HttpMethod.GET,
new ParameterizedTypeReference<MciAccessInfoDto>() {}
);

return response.getBody();
});
}

public List<K8sClusterDto> getAllK8sClusters(String namespace){
log.info("Fetching K8s Clusters by namespace: {}", namespace);
Expand Down Expand Up @@ -179,21 +287,22 @@ public Spec getSpecBySpecId(String nsId, String specId) {
HttpMethod.GET,
new ParameterizedTypeReference<Spec>() {}
);
log.info("Spec : {}" , response.getBody().toString());
return response.getBody();
});
}

public VmDto getVmInfo(String nsId, String mciId, String vmId) {
public VmAccessInfo getVmInfo(String nsId, String mciId, String vmId) {
log.info("Fetching VM info for VM ID: {}", vmId);
return executeWithConnectionCheck("getVmInfo", () -> {
String apiUrl = createApiUrl(String.format("/tumblebug/ns/%s/mci/%s/vm/%s", nsId, mciId, vmId));
HttpHeaders headers = createCommonHeaders();
ResponseEntity<VmDto> response = restClient.request(
ResponseEntity<VmAccessInfo> response = restClient.request(
apiUrl,
headers,
null,
HttpMethod.GET,
new ParameterizedTypeReference<VmDto>() {}
new ParameterizedTypeReference<VmAccessInfo>() {}
);
return response.getBody();
});
Expand Down Expand Up @@ -228,18 +337,5 @@ public K8sSpec lookupSpec(String connectionName, String cspResourceId) {

return response.getBody();
});
// String apiUrl = "http://localhost:1323/tumblebug/lookupSpec";
// String requestBody = String.format("{\"connectionName\": \"%s\", \"cspResourceId\": \"%s\"}", connectionName, cspResourceId);

// HttpHeaders headers = createCommonHeaders();
// ResponseEntity<K8sSpec> response = restClient.request(
// apiUrl,
// headers,
// requestBody,
// HttpMethod.POST,
// new ParameterizedTypeReference<K8sSpec>() {}
// );

// return response.getBody();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import java.util.List;

import kr.co.mcmp.response.ResponseWrapper;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
Expand All @@ -16,8 +16,8 @@
import kr.co.mcmp.ape.cbtumblebug.dto.NamespaceDto;
import kr.co.mcmp.ape.cbtumblebug.dto.Spec;
import kr.co.mcmp.ape.cbtumblebug.service.CbtumblebugService;
import kr.co.mcmp.response.ResponseWrapper;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.RequestParam;


@Tag(name="tumblebug", description = "Tumblebug API queries")
Expand All @@ -30,38 +30,44 @@ public class CbtumblebugController {

@GetMapping("/ns")
@Operation(summary = "Retrieve all namespaces", description = "Fetches all registered namespaces.")
public ResponseWrapper<List<NamespaceDto>> getAllNamespaces() {
return new ResponseWrapper<>(cbtumblebugService.getAllNamespaces()) ;
public ResponseEntity<ResponseWrapper<List<NamespaceDto>>> getAllNamespaces() {
List<NamespaceDto> result = cbtumblebugService.getAllNamespaces();
return ResponseEntity.ok(new ResponseWrapper<>(result));
}

@GetMapping("/ns/{nsId}/mci")
@Operation(summary = "Retrieve MCIS for a specific namespace", description = "Fetches all MCIS belonging to the specified namespace.")
public ResponseWrapper<List<MciDto>> getMicsByNamespace(@Parameter(description = "Namespace ID", required = true)
public ResponseEntity<ResponseWrapper<List<MciDto>>> getMicsByNamespace(@Parameter(description = "Namespace ID", required = true)
@PathVariable String nsId) {
return new ResponseWrapper<>(cbtumblebugService.getMcisByNamespace(nsId));
List<MciDto> result = cbtumblebugService.getMcisByNamespace(nsId);
return ResponseEntity.ok(new ResponseWrapper<>(result));
}

@GetMapping("/ns/{nsId}/mci/{mciId}")
@Operation(summary = "Retrieve a specific MCI", description = "Fetches the specified MCI.")
public ResponseWrapper<MciDto> getMicByMciId(@PathVariable String nsId, @PathVariable String mciId) {
return new ResponseWrapper<>(cbtumblebugService.getMciByMciId(nsId, mciId));
public ResponseEntity<ResponseWrapper<MciDto>> getMicByMciId(@PathVariable String nsId, @PathVariable String mciId) {
MciDto result = cbtumblebugService.getMciByMciId(nsId, mciId);
return ResponseEntity.ok(new ResponseWrapper<>(result));
}

@GetMapping("/ns/{nsId}/k8scluster")
@Operation(summary = "Retrieve k8sclusters for a specific namespace", description = "Fetches all k8sclusters belonging to the specified namespace.")
public ResponseWrapper<List<K8sClusterDto>> getK8sCluster(@PathVariable String nsId) {
return new ResponseWrapper<>(cbtumblebugService.getAllK8sClusters(nsId));
public ResponseEntity<ResponseWrapper<List<K8sClusterDto>>> getK8sCluster(@PathVariable String nsId) {
List<K8sClusterDto> result = cbtumblebugService.getAllK8sClusters(nsId);
return ResponseEntity.ok(new ResponseWrapper<>(result));
}

@GetMapping("/ns/{nsId}/k8scluster/{clusterName}")
@Operation(summary = "Retrieve a specific k8scluster", description = "Fetches the specified k8scluster.")
public ResponseWrapper<K8sClusterDto> getK8sClusterByName(@PathVariable String nsId, @PathVariable String clusterName) {
return new ResponseWrapper<>(cbtumblebugService.getK8sClusterByName(nsId, clusterName));
public ResponseEntity<ResponseWrapper<K8sClusterDto>> getK8sClusterByName(@PathVariable String nsId, @PathVariable String clusterName) {
K8sClusterDto result = cbtumblebugService.getK8sClusterByName(nsId, clusterName);
return ResponseEntity.ok(new ResponseWrapper<>(result));
}

@GetMapping("/ns/{nsId}/resources/spec/{specId}")
public ResponseWrapper<Spec> getMethodName(@PathVariable String nsId, @PathVariable String specId) {
return new ResponseWrapper<>(cbtumblebugService.getSpecBySpecId(nsId, specId));
public ResponseEntity<ResponseWrapper<Spec>> getMethodName(@PathVariable String nsId, @PathVariable String specId) {
Spec result = cbtumblebugService.getSpecBySpecId(nsId, specId);
return ResponseEntity.ok(new ResponseWrapper<>(result));
}


Expand Down
Loading

0 comments on commit d846339

Please sign in to comment.