Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 39 additions & 10 deletions front/assets/js/common/api/services/pmk_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -392,11 +392,11 @@ export async function createNode(k8sClusterId, nsId, Create_Node_Config_Arr) {

var obj = Create_Node_Config_Arr[0];

// 2. 필수 필드 검증
if (!obj.name || !obj.specId || !obj.imageId || !obj.sshKeyId || !obj.minNodeSize || !obj.maxNodeSize || !obj.onAutoScaling) {
// 2. 필수 필드 검증 (min/maxNodeSize는 autoScaling OFF 시 없을 수 있으므로 제외)
if (!obj.name || !obj.specId || !obj.imageId) {
console.error('Missing required fields:', obj);
webconsolejs["common/util"].showToast('Missing required fields for node creation', 'error');
return;
return false;
}

// 3. 데이터 준비 (기본값 포함)
Expand All @@ -406,13 +406,13 @@ export async function createNode(k8sClusterId, nsId, Create_Node_Config_Arr) {
k8sClusterId: k8sClusterId,
},
request: {
"desiredNodeSize": obj.desiredNodeSize || "1",
"desiredNodeSize": parseInt(obj.desiredNodeSize) || 1,
"imageId": obj.imageId,
"maxNodeSize": obj.maxNodeSize || obj.desiredNodeSize || "1",
"minNodeSize": obj.minNodeSize || obj.desiredNodeSize || "1",
"maxNodeSize": parseInt(obj.maxNodeSize) || parseInt(obj.desiredNodeSize) || 1,
"minNodeSize": parseInt(obj.minNodeSize) || parseInt(obj.desiredNodeSize) || 1,
"name": obj.name,
"onAutoScaling": obj.onAutoScaling || "false",
"rootDiskSize": obj.rootDiskSize || "",
"rootDiskSize": parseInt(obj.rootDiskSize) || 0,
"rootDiskType": obj.rootDiskType || "",
"specId": obj.specId,
"sshKeyId": obj.sshKeyId
Expand Down Expand Up @@ -486,14 +486,43 @@ export async function getAvailablek8sClusterNodeImage(providerName, regionName)
};

var controller = "/api/" + "mc-infra-manager/" + "GetAvailableK8sNodeImage";
const response = webconsolejs["common/api/http"].commonAPIPost(
const response = await webconsolejs["common/api/http"].commonAPIPost(
controller,
data
)
var imageList = response
return imageList
return response.data.responseData


}

// connectionName에 맞는 K8s 노드 spec을 동적 조회 (RecommendK8sNode)
// connectionName이 일치하는 첫 번째 specId를 반환; 없거나 오류 시 ""
export async function getRecommendedK8sSpecId(connectionName) {
const data = {
request: {
limit: 200
}
};

var controller = "/api/" + "mc-infra-manager/" + "RecommendK8sNode";
try {
const response = await webconsolejs["common/api/http"].commonAPIPost(
controller,
data
);

if (!response || !response.data || !response.data.responseData) {
return "";
}

const specs = response.data.responseData;
if (!Array.isArray(specs)) return "";

const matched = specs.find(spec => spec.connectionName === connectionName);
return matched ? (matched.id || "") : "";
} catch (e) {
return "";
}
}

// // MCIS 상태를 UI에서 표현하는 방식으로 변경
Expand Down
141 changes: 46 additions & 95 deletions front/assets/js/pages/operation/manage/pmk.js
Original file line number Diff line number Diff line change
Expand Up @@ -1605,109 +1605,87 @@ export async function deployPmkDynamic() {
const isNodeGroupVisible = nodeGroupForm && nodeGroupForm.style.display !== "none";

try {
// 사전 검증을 위한 commonSpec 결정
let commonSpec = "";
let commonImage = "";
let k8sVersion = "";

if (isNodeGroupVisible) {
// NodeGroup이 있는 경우: 선택된 spec 사용
// NodeGroup이 있는 경우: 선택된 spec으로 사전 검증 후 배포
commonSpec = $("#nodegroup_commonSpecId_dynamic").val();
commonImage = $("#nodegroup_image_dynamic").val();
if (!commonSpec) {
webconsolejs['common/util'].showToast('Please select NodeGroup spec', 'warning');
return;
}

const checkResult = await webconsolejs["common/api/services/pmk_api"].checkK8sClusterDynamic(
selectedWorkspaceProject.nsId,
commonSpec
);
if (!checkResult || checkResult.status !== 200) {
webconsolejs['common/util'].showToast('Failed to pre-validate. Please check the settings', 'error');
return;
}
} else {
// NodeGroup이 없는 경우: API를 통해 동적으로 spec과 image 가져오기
// NodeGroup이 없는 경우: K8s 버전 + specId 동적 조회 후 control plane만 생성
const providerName = clusterData.provider;
const regionMatch = clusterData.region.match(/\[.*?\]\s*(.+)/);
const regionName = regionMatch ? regionMatch[1] : '';
const regionName = regionMatch ? regionMatch[1].trim() : '';

if (!providerName || !regionName) {
webconsolejs['common/util'].showToast('Please select both Provider and Region', 'warning');
return;
}

const specsResponse = await webconsolejs["common/api/services/pmk_api"]
// K8s 버전 조회
const versions = await webconsolejs["common/api/services/pmk_api"]
.getAvailableK8sClusterVersion(providerName, regionName);

const imagesResponse = await webconsolejs["common/api/services/pmk_api"]
.getAvailablek8sClusterNodeImage(providerName, regionName);

if (specsResponse && specsResponse.data && specsResponse.data.responseData) {
const specs = specsResponse.data.responseData;
if (Array.isArray(specs) && specs.length > 0) {
commonSpec = specs[0];
} else if (typeof specs === 'object' && specs.version) {
commonSpec = specs.version[0] || "";
}
if (versions && Array.isArray(versions) && versions.length > 0) {
k8sVersion = versions[0].id || "";
}

if (imagesResponse && imagesResponse.data && imagesResponse.data.responseData) {
const images = imagesResponse.data.responseData;
if (Array.isArray(images) && images.length > 0) {
commonImage = images[0];
} else if (typeof images === 'object' && images.image) {
commonImage = images.image[0] || "default";
}
}

if (!commonImage || commonImage === "") {
commonImage = "default";
// provider 컨텍스트용 specId: RecommendK8sNode 조회 → 없으면 CSP별 하드코딩 fallback
commonSpec = await webconsolejs["common/api/services/pmk_api"]
.getRecommendedK8sSpecId(clusterData.connection);
if (!commonSpec) {
const K8S_DEFAULT_SPEC = {
'aws': 't3.medium',
'azure': 'Standard_B2s',
'gcp': 'n1-standard-2',
'alibaba': 'ecs.c1.small',
'ncp': 'SVR.VSVR.STAND.C002.M004.NET.SSD.B050.G002',
'nhncloud': 'm2.c4m8',
'ibm': 'cx2-4x8',
};
const sepIdx = clusterData.connection.indexOf('-');
const csp = clusterData.connection.substring(0, sepIdx).toLowerCase();
const region = clusterData.connection.substring(sepIdx + 1);
const instanceType = K8S_DEFAULT_SPEC[csp] || 't3.medium';
commonSpec = `${csp}+${region}+${instanceType}`;
}

if (!commonSpec || commonSpec === "") {
webconsolejs['common/util'].showToast('Could not retrieve K8s specification for the selected Provider and Region', 'error');
return;
}
commonImage = "default";
}

// 사전 검증 API 호출 (동기 - 결과 확인 필요)
const checkResult = await webconsolejs["common/api/services/pmk_api"].checkK8sClusterDynamic(
selectedWorkspaceProject.nsId,
commonSpec
);

if (!checkResult || checkResult.status !== 200) {
webconsolejs['common/util'].showToast('Failed to pre-validate. Please check the settings', 'error');
return;
}

// 실제 클러스터 생성 데이터 준비
let createData;

// Azure provider인 경우 테스트용 하드코딩된 값 사용
if (clusterData.provider.toLowerCase() === 'azure') {
createData = {
imageId: "default",
specId: "azure+koreacentral+standard_b4ms",
name: clusterData.name, // 폼에서 입력한 값 사용
nodeGroupName: isNodeGroupVisible ? $("#nodegroup_name_dynamic").val() : "k8sng01" // 폼에서 입력한 값이 있으면 사용, 없으면 기본값
};
} else {
// 다른 provider는 기존 로직 사용
createData = {
imageId: commonImage,
specId: commonSpec,
connectionName: clusterData.connection,
name: clusterData.name,
nodeGroupName: isNodeGroupVisible ? $("#nodegroup_name_dynamic").val() : ""
};
}
// 클러스터 생성 데이터 준비
const createData = {
imageId: commonImage || "default",
specId: commonSpec,
connectionName: clusterData.connection,
name: clusterData.name,
nodeGroupName: isNodeGroupVisible ? $("#nodegroup_name_dynamic").val() : ""
};

// commonImage가 없으면 "default"로 설정
if (!createData.commonImage || createData.commonImage === "") {
createData.commonImage = "default";
if (k8sVersion) {
createData.version = k8sVersion;
}

// NodeGroup이 있는 경우 추가 정보 설정
if (isNodeGroupVisible) {
// NodeGroup 필수 필드 검증
if (!createData.nodeGroupName) {
webconsolejs['common/util'].showToast('Please input NodeGroup name', 'warning');
return;
}
// AutoScaling On일 때만 min/max 포함
const autoScalingVal = $("#nodegroup_autoscaling_dynamic").val();
createData.onAutoScaling = autoScalingVal || "false";
if (autoScalingVal === "true") {
Expand All @@ -1722,33 +1700,6 @@ export async function deployPmkDynamic() {
}
}

// available k8sversion 조회
if(clusterData.provider.toLowerCase() === 'alibaba'){
//createData.k8sVersion = "1.33.3-aliyun.1";
//createData.k8sVersion = "1.33";//(사용못함 format 안맞음)
//createData.k8sVersion = "1.31.9-aliyun.1";//
//createData.k8sVersion = "1.22.15-aliyun.1";
// createData.k8sVersion = "1.32.7-aliyun.1";
createData.k8sVersion = "1.32.7-aliyun.1";
}
// const k8sVersionList = await webconsolejs["common/api/services/pmk_api"].getAvailableK8sVersionList(
// selectedWorkspaceProject.nsId
// );
// if (k8sVersionList && k8sVersionList.status === 200) {
// console.log(k8sVersionList);
// }
// // 가져온 k8sversion 중 가장 최신 버전 선택
// if (k8sVersionList && k8sVersionList.data && k8sVersionList.data.responseData && k8sVersionList.data.responseData.length > 0) {
// const latestK8sVersion = k8sVersionList.data.responseData[0];
// if (!latestK8sVersion) {
// if(clusterData.provider.toLowerCase() === 'alibaba'){
// latestK8sVersion = "1.33.3-aliyun.1";
// }
// }else{
// createData.k8sVersion = latestK8sVersion;
// }
// }

// 동적 클러스터 생성 API 호출 (비동기 - 결과를 기다리지 않음)
webconsolejs["common/api/services/pmk_api"].createK8sClusterDynamic(
selectedWorkspaceProject.nsId,
Expand Down
13 changes: 7 additions & 6 deletions front/assets/js/partials/operation/manage/clustercreate.js
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,7 @@ export async function displayNewNodeForm() {
webconsolejs["partials/operation/manage/clustercreate"].callbackNodegroupServerRecommendation
);
}
// provider 필터는 pmk_serverrecommendation.js의 shown.bs.modal 핸들러가 selectedPmkObj로 처리
});
}

Expand Down Expand Up @@ -486,14 +487,14 @@ export async function createNode() {
var selectedNsId = selectedWorkspaceProject.nsId;
var k8sClusterId = webconsolejs["pages/operation/manage/pmk"].selectedPmkObj[0].id

// NodeGroup 생성 요청만 보내고 결과를 기다리지 않음 (fire and forget)
webconsolejs["common/api/services/pmk_api"].createNode(
k8sClusterId,
selectedNsId,
const result = await webconsolejs["common/api/services/pmk_api"].createNode(
k8sClusterId,
selectedNsId,
Create_Node_Config_Arr
);

// 즉시 메시지 표시

if (result === false) return;

webconsolejs['common/util'].showToast('NodeGroup creation request has been sent', 'info');

// NodeGroup Configuration 폼 닫기
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,25 @@ export function selectOSTypePmk(osType) {
export function updateGPUStatusPmk() {
var gpuCheckbox = document.getElementById('assist_gpu_image-pmk');
var gpuValue = document.getElementById('gpu_image_value-pmk');

if (gpuCheckbox.checked) {
gpuValue.value = 'true';
} else {
gpuValue.value = 'false';
}
}

export function updateK8sStatusPmk() {
var k8sCheckbox = document.getElementById('assist_k8s_image-pmk');
var k8sValue = document.getElementById('k8s_image_value-pmk');

if (k8sCheckbox.checked) {
k8sValue.value = 'true';
} else {
k8sValue.value = 'false';
}
}

function initRecommendImageTablePmk() {
// 기존 테이블이 있으면 제거
if (recommendImageTablePmk) {
Expand Down Expand Up @@ -192,7 +203,8 @@ export async function getRecommendImageInfoPmk() {

var osType = $("#assist_os_type-pmk").val()
var isGPUImage = $("#gpu_image_value-pmk").val()

var isK8sImage = $("#k8s_image_value-pmk").val()

// 전역 변수에서 정보 가져오기
var specId = window.selectedPmkSpecInfo.id; // spec의 전체 ID (예: "aws+ap-northeast-2+t2.small")
var provider = window.selectedPmkSpecInfo.provider;
Expand All @@ -206,18 +218,21 @@ export async function getRecommendImageInfoPmk() {

// API 호출을 위한 파라미터 구성
var searchParams = {
providerName: provider, // 개별 전달
regionName: region, // 개별 전달
matchedSpecId: specId, // 유지
// isKubernetesImage: true, // PMK 필수
providerName: provider,
regionName: region,
matchedSpecId: specId,
maxResults: 100
};

// 선택적 파라미터
if (osType && osType.trim() !== "") {
searchParams.osType = osType.trim();
}


if (isK8sImage === "true") {
searchParams.isKubernetesImage = true;
}

// GPU 이미지가 필요한 경우에만 추가
if (isGPUImage === "true") {
searchParams.isGPUImage = true;
Expand Down Expand Up @@ -384,6 +399,9 @@ if (!webconsolejs['partials/operation/manage/pmk_imagerecommendation'].setImageS
if (!webconsolejs['partials/operation/manage/pmk_imagerecommendation'].filterByProviderPmk) {
webconsolejs['partials/operation/manage/pmk_imagerecommendation'].filterByProviderPmk = filterByProviderPmk;
}
if (!webconsolejs['partials/operation/manage/pmk_imagerecommendation'].updateK8sStatusPmk) {
webconsolejs['partials/operation/manage/pmk_imagerecommendation'].updateK8sStatusPmk = updateK8sStatusPmk;
}
if (!webconsolejs['partials/operation/manage/pmk_imagerecommendation'].updateGPUStatusPmk) {
webconsolejs['partials/operation/manage/pmk_imagerecommendation'].updateGPUStatusPmk = updateGPUStatusPmk;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export function initServerRecommendationPmk(callbackfunction) {
modalEl.addEventListener('shown.bs.modal', function () {
const provider = document.getElementById('cluster_provider_dynamic')?.value
|| document.getElementById('cluster_provider')?.value
|| webconsolejs["pages/operation/manage/pmk"]?.selectedPmkObj?.[0]?.provider
|| '';
const badge = document.getElementById('spec-provider-badge-pmk');
const hidden = document.getElementById('spec-provider-value-pmk');
Expand Down
Loading
Loading