parent
28aade2280
commit
92250f29d8
@ -0,0 +1,57 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: autoflow-server
|
||||||
|
namespace: autoflow
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: autoflow-server
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: autoflow-server
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: autoflow-server
|
||||||
|
# [수정] 외부 레지스트리 주소를 제거하고 로컬 태그만 사용
|
||||||
|
image: autoflow-server:latest
|
||||||
|
# [추가] 외부에서 이미지를 다운로드하지 않고 로컬 이미지를 사용하도록 강제
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
ports:
|
||||||
|
- containerPort: 8080
|
||||||
|
env:
|
||||||
|
- name: RDS_HOSTNAME
|
||||||
|
# [수정 필요] Outpost 내부 RDS의 Private IP 또는 DNS를 입력하세요.
|
||||||
|
value: "INTERNAL_RDS_IP_HERE"
|
||||||
|
- name: RDS_USERNAME
|
||||||
|
value: "admin"
|
||||||
|
- name: RDS_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: autoflow-secrets
|
||||||
|
key: rds-password
|
||||||
|
- name: JWT_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: autoflow-secrets
|
||||||
|
key: jwt-secret
|
||||||
|
- name: S3_BUCKET_NAME
|
||||||
|
# [수정 필요] Outpost 내 생성한 S3 버킷 명을 입력하세요.
|
||||||
|
value: "autoflow-outpost-bucket"
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: autoflow-server-svc
|
||||||
|
namespace: autoflow
|
||||||
|
spec:
|
||||||
|
# Outpost EKS 환경에 따라 LoadBalancer 또는 NodePort를 선택하세요.
|
||||||
|
type: LoadBalancer
|
||||||
|
selector:
|
||||||
|
app: autoflow-server
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 80
|
||||||
|
targetPort: 8080
|
||||||
@ -0,0 +1,105 @@
|
|||||||
|
package kr.re.etri.autoflow.service.storage;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.nio.file.StandardCopyOption;
|
||||||
|
|
||||||
|
@Service("storageProvider")
|
||||||
|
@ConditionalOnProperty(name = "storage.provider", havingValue = "filesystem")
|
||||||
|
public class FileSystemStorageProvider implements StorageProvider {
|
||||||
|
|
||||||
|
@Value("${storage.local.base-path:./storage}")
|
||||||
|
private String basePath;
|
||||||
|
|
||||||
|
@Value("${storage.local.default-bucket:mlpipeline}")
|
||||||
|
private String defaultBucket;
|
||||||
|
|
||||||
|
private String getTargetDir(String bucketName) {
|
||||||
|
String bucket = (bucketName == null || bucketName.isEmpty()) ? defaultBucket : bucketName;
|
||||||
|
return Paths.get(basePath, bucket).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void uploadFile(String bucketName, String objectName, InputStream is, String contentType, long size, String type) throws Exception {
|
||||||
|
String targetDir = getTargetDir(bucketName);
|
||||||
|
Path targetPath = Paths.get(targetDir, objectName);
|
||||||
|
|
||||||
|
Files.createDirectories(targetPath.getParent());
|
||||||
|
Files.copy(is, targetPath, StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void uploadFileToDefault(String objectName, InputStream is, String contentType, long size) throws Exception {
|
||||||
|
uploadFile(null, objectName, is, contentType, size, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] downloadFile(String bucketName, String objectName, String type) throws Exception {
|
||||||
|
String targetDir = getTargetDir(bucketName);
|
||||||
|
Path targetPath = Paths.get(targetDir, objectName);
|
||||||
|
|
||||||
|
return Files.readAllBytes(targetPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] downloadFileFromDefault(String objectName) throws Exception {
|
||||||
|
return downloadFile(null, objectName, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File downloadFileToServer(String bucketName, String objectName, String localPath, String type) throws Exception {
|
||||||
|
String targetDir = getTargetDir(bucketName);
|
||||||
|
Path sourcePath = Paths.get(targetDir, objectName);
|
||||||
|
|
||||||
|
File localDir = new File(localPath);
|
||||||
|
if (!localDir.exists()) localDir.mkdirs();
|
||||||
|
|
||||||
|
String fileName = Paths.get(objectName).getFileName().toString();
|
||||||
|
Path destinationPath = Paths.get(localPath, fileName);
|
||||||
|
|
||||||
|
Files.copy(sourcePath, destinationPath, StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
|
||||||
|
return destinationPath.toFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String readYamlText(String bucketName, String objectName, String type) throws Exception {
|
||||||
|
byte[] bytes = downloadFile(bucketName, objectName, type);
|
||||||
|
return new String(bytes, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String readYamlTextFromDefault(String objectName) throws Exception {
|
||||||
|
return readYamlText(null, objectName, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteFile(String bucketName, String objectName, String type) throws Exception {
|
||||||
|
String targetDir = getTargetDir(bucketName);
|
||||||
|
Path targetPath = Paths.get(targetDir, objectName);
|
||||||
|
|
||||||
|
Files.deleteIfExists(targetPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteFileFromDefault(String objectName) throws Exception {
|
||||||
|
deleteFile(null, objectName, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFileUrl(String bucketName, String objectName, String type) {
|
||||||
|
// 로컬 파일 경로를 URL로 반환하거나 상대 경로로 반환
|
||||||
|
// 프론트엔드에서 접근 가능한 경로여야 할 경우 추가적인 서블릿 설정이 필요할 수 있음
|
||||||
|
String targetDir = getTargetDir(bucketName);
|
||||||
|
return Paths.get(targetDir, objectName).toAbsolutePath().toUri().toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
# AWS Production Configuration
|
||||||
|
server.port = 8080
|
||||||
|
server.servlet.context-path=/autoflow-server-mgmt
|
||||||
|
|
||||||
|
spring.profiles.active=prod
|
||||||
|
|
||||||
|
# RDS MariaDB Configuration
|
||||||
|
# Replace with your RDS endpoint
|
||||||
|
spring.datasource.url=jdbc:mariadb://${RDS_HOSTNAME}:3306/autoflow
|
||||||
|
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
|
||||||
|
spring.datasource.username=${RDS_USERNAME}
|
||||||
|
spring.datasource.password=${RDS_PASSWORD}
|
||||||
|
|
||||||
|
spring.jpa.database-platform=org.hibernate.dialect.MariaDBDialect
|
||||||
|
spring.jpa.hibernate.ddl-auto=none
|
||||||
|
spring.sql.init.mode=never
|
||||||
|
|
||||||
|
# App Properties (JWT) - Should be injected via env variables in K8s
|
||||||
|
cuuva.app.jwtCookieName=cuuva-jwt
|
||||||
|
cuuva.app.jwtRefreshCookieName=cuuva-jwt-refresh
|
||||||
|
cuuva.app.jwtSecret=${JWT_SECRET}
|
||||||
|
|
||||||
|
# Storage Provider (S3)
|
||||||
|
storage.provider=s3
|
||||||
|
cloud.aws.region.static=ap-northeast-2
|
||||||
|
cloud.aws.s3.bucket=${S3_BUCKET_NAME}
|
||||||
|
# IAM Role should be used instead of hardcoded keys in EKS
|
||||||
|
# cloud.aws.credentials.access-key=${AWS_ACCESS_KEY}
|
||||||
|
# cloud.aws.credentials.secret-key=${AWS_SECRET_KEY}
|
||||||
|
|
||||||
|
# Swagger UI
|
||||||
|
springdoc.swagger-ui.path=/swagger-ui
|
||||||
|
springdoc.swagger-ui.config-url=/autoflow-server-mgmt/v3/api-docs/swagger-config
|
||||||
|
springdoc.swagger-ui.url=/autoflow-server-mgmt/v3/api-docs
|
||||||
|
springdoc.swagger-ui.doc-expansion=none
|
||||||
|
springdoc.swagger-ui.disable-swagger-default-url=true
|
||||||
|
|
||||||
|
# Multipart limit
|
||||||
|
spring.servlet.multipart.max-file-size=500MB
|
||||||
|
spring.servlet.multipart.max-request-size=500MB
|
||||||
Loading…
Reference in new issue