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
8 changes: 7 additions & 1 deletion .github/workflows/deploy_images.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ on:
default: true
description: Build new image of save-orchestrator
required: false
sandbox:
type: boolean
default: true
description: Build new image of save-sandbox
required: false
preprocessor:
type: boolean
default: true
Expand All @@ -57,7 +62,7 @@ jobs:
name: Prepare to build
working-directory: save-cloud
run: |
echo GRADLE_TASKS=:api-gateway:bootBuildImage :save-backend:bootBuildImage :save-frontend:buildImage :save-orchestrator:bootBuildImage :save-preprocessor:bootBuildImage >> $GITHUB_ENV
echo GRADLE_TASKS=:api-gateway:bootBuildImage :save-backend:bootBuildImage :save-frontend:buildImage :save-orchestrator:bootBuildImage :save-sandbox:bootBuildImage :save-preprocessor:bootBuildImage >> $GITHUB_ENV
- if: github.event_name == 'workflow_dispatch'
name: Prepare to build from branch
working-directory: save-cloud
Expand All @@ -69,6 +74,7 @@ jobs:
if ${{ inputs.backend }} == 'true'; then GRADLE_TASKS+=":save-backend:bootBuildImage "; fi
if ${{ inputs.frontend }} == 'true'; then GRADLE_TASKS+=":save-frontend:buildImage "; fi
if ${{ inputs.orchestrator }} == 'true'; then GRADLE_TASKS+=":save-orchestrator:bootBuildImage "; fi
if ${{ inputs.sandbox }} == 'true'; then GRADLE_TASKS+=":save-sandbox:bootBuildImage "; fi
if ${{ inputs.preprocessor }} == 'true'; then GRADLE_TASKS+=":save-preprocessor:bootBuildImage "; fi
echo GRADLE_TASKS=$GRADLE_TASKS >> $GITHUB_ENV
- name: checkout save-core
Expand Down
2 changes: 2 additions & 0 deletions api-gateway/src/main/resources/application-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ gateway:
url: http://localhost:5800
frontend:
url: http://localhost:5810
sandbox:
url: http://localhost:5400
spring:
security:
oauth2:
Expand Down
10 changes: 10 additions & 0 deletions api-gateway/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ gateway:
url: http://frontend:5810
grafana:
url: http://grafana:9100
sandbox:
url: http://sandbox:5400
management:
endpoints:
web:
Expand Down Expand Up @@ -50,6 +52,14 @@ spring:
uri: ${gateway.grafana.url}
predicates:
- Path=/grafana/**
- id: sandbox-api_route
uri: ${gateway.sandbox.url}
predicates:
- Path=/sandbox/api/**
filters:
# If SESSION cookie is passed to downstream, it is then removed, because downstream discards it
- RemoveRequestHeader=Cookie
- ConvertAuthorizationHeader=

---
spring:
Expand Down
29 changes: 16 additions & 13 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,27 @@ plugins {
}

val profile = properties.getOrDefault("save.profile", "dev") as String
val databaseCredentials = getDatabaseCredentials(profile)

liquibase {
activities {
val commonArguments = mapOf(
"logLevel" to "info",
"contexts" to when (profile) {
"prod" -> "prod"
"dev" -> "dev"
else -> throw GradleException("Profile $profile not configured to map on a particular liquibase context")
}
)
// Configuring luiquibase
register("main") {
arguments = mapOf(
"changeLogFile" to "db/db.changelog-master.xml",
"url" to databaseCredentials.databaseUrl,
"username" to databaseCredentials.username,
"password" to databaseCredentials.password,
"logLevel" to "info",
"contexts" to when (profile) {
"prod" -> "prod"
"dev" -> "dev"
else -> throw GradleException("Profile $profile not configured to map on a particular liquibase context")
}
)
arguments = mapOf("changeLogFile" to "db/db.changelog-master.xml") +
getBackendDatabaseCredentials(profile).toLiquibaseArguments() +
commonArguments
}
register("sandbox") {
arguments = mapOf("changeLogFile" to "save-sandbox/db/db.changelog-sandbox.xml") +
getSandboxDatabaseCredentials(profile).toLiquibaseArguments() +
commonArguments
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,41 +14,52 @@ data class DatabaseCredentials(
val databaseUrl: String,
val username: String,
val password: String
)
) {
/**
* @return arguments for liquibase task
*/
fun toLiquibaseArguments(): Map<String, String> = mapOf(
"url" to "$databaseUrl?createDatabaseIfNotExist=true",
"username" to username,
"password" to password,
)
}

/**
* @param profile a profile to get credentials for
* @return an instance of [DatabaseCredentials] for [profile] in backend
*/
fun Project.getBackendDatabaseCredentials(profile: String): DatabaseCredentials = getDatabaseCredentials("save-backend", profile)

/**
* @param profile a profile to get credentials for
* @return an instance of [DatabaseCredentials] for [profile]
* @return an instance of [DatabaseCredentials] for [profile] in sandbox
*/
@Suppress("AVOID_NULL_CHECKS")
fun Project.getDatabaseCredentials(profile: String): DatabaseCredentials {
fun Project.getSandboxDatabaseCredentials(profile: String): DatabaseCredentials = getDatabaseCredentials("save-sandbox", profile)

private fun Project.getDatabaseCredentials(projectName: String, profile: String): DatabaseCredentials {
val props = java.util.Properties()
// Branch for other environments, e.g. local deployment or server deployment
file("$projectName/src/main/resources/application-$profile.properties").inputStream().use(props::load)
if (File("${System.getenv("HOME")}/secrets").exists()) {
file("${System.getenv("HOME")}/secrets").inputStream().use(props::load)
}
val databaseUrl: String = props.getProperty("spring.datasource.url")

val secretsPath = System.getenv("DB_SECRETS_PATH")
if (secretsPath != null) {
System.getenv("DATABASE_SECRETS_PATH")?.let { secretsPath ->
// Branch for environment with explicit file with database credentials, e.g. Kubernetes Secrets
val url = file("$secretsPath/spring.datasource.url").readText()
val username = file("$secretsPath/spring.datasource.username").readText()
val password = file("$secretsPath/spring.datasource.password").readText()
return DatabaseCredentials(url, username, password)
} else {
// Branch for other environments, e.g. local deployment or server deployment
file("save-backend/src/main/resources/application-$profile.properties").inputStream().use(props::load)
if (File("${System.getenv("HOME")}/secrets").exists()) {
file("${System.getenv("HOME")}/secrets").inputStream().use(props::load)
}
return DatabaseCredentials(databaseUrl, username, password)
}

val databaseUrl: String
val username: String
val password: String

if (profile == "prod") {
databaseUrl = props.getProperty("spring.datasource.url")
username = props.getProperty("username")
password = props.getProperty("password")
} else {
databaseUrl = props.getProperty("datasource.dev.url")
username = props.getProperty("spring.datasource.username")
password = props.getProperty("spring.datasource.password")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ fun Project.createStackDeployTask(profile: String) {
| - "3306:3306"
| environment:
| - "MYSQL_ROOT_PASSWORD=123"
| - "MYSQL_DATABASE=save_cloud"
| zookeeper:
| image: confluentinc/cp-zookeeper:latest
| environment:
Expand Down Expand Up @@ -105,6 +104,7 @@ fun Project.createStackDeployTask(profile: String) {
FRONTEND_TAG=${defaultVersionOrProperty("frontend.dockerTag")}
GATEWAY_TAG=${defaultVersionOrProperty("gateway.dockerTag")}
ORCHESTRATOR_TAG=${defaultVersionOrProperty("orchestrator.dockerTag")}
SANDBOX_TAG=${defaultVersionOrProperty("sandbox.dockerTag")}
PREPROCESSOR_TAG=${defaultVersionOrProperty("preprocessor.dockerTag")}
PROFILE=$profile
""".trimIndent()
Expand Down Expand Up @@ -140,6 +140,7 @@ fun Project.createStackDeployTask(profile: String) {
Files.createDirectories(configsDir.resolve("backend"))
Files.createDirectories(configsDir.resolve("gateway"))
Files.createDirectories(configsDir.resolve("orchestrator"))
Files.createDirectories(configsDir.resolve("sandbox"))
Files.createDirectories(configsDir.resolve("preprocessor"))
}
description =
Expand Down Expand Up @@ -225,6 +226,7 @@ fun Project.createStackDeployTask(profile: String) {
"up",
"-d",
"orchestrator",
"sandbox",
"backend",
"frontend",
"preprocessor"
Expand All @@ -243,7 +245,7 @@ fun Project.createStackDeployTask(profile: String) {
project(componentName).tasks.named<BootBuildImage>("bootBuildImage")
dependsOn(buildTask)
val serviceName = when (componentName) {
"save-backend", "save-frontend", "save-orchestrator", "save-preprocessor" -> "save_${componentName.substringAfter("save-")}"
"save-backend", "save-frontend", "save-orchestrator", "save-sandbox", "save-preprocessor" -> "save_${componentName.substringAfter("save-")}"
"api-gateway" -> "save_gateway"
else -> error("Wrong component name $componentName")
}
Expand Down
26 changes: 21 additions & 5 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,34 @@ services:
labels:
- "prometheus-job=save-orchestrator"
logging: *loki-logging-jvm
sandbox:
image: ghcr.io/saveourtool/save-sandbox:${SANDBOX_TAG}
user: root # to access host's docker socket
environment:
- "SPRING_PROFILES_ACTIVE=${PROFILE},docker-secrets"
secrets:
- db_username
- db_password
ports:
- "5400:5400"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
- /home/saveu/configs/sandbox:/home/cnb/config
- save-fs-storage:/home/cnb/files
- save-tmp-resources:/tmp
extra_hosts:
- "host.docker.internal:host-gateway"
deploy:
labels:
- "prometheus-job=save-sandbox"
logging: *loki-logging-jvm
backend:
image: ghcr.io/saveourtool/save-backend:${BACKEND_TAG}
environment:
- "SPRING_PROFILES_ACTIVE=${PROFILE},secure,docker-secrets"
- "MYSQL_USER=/run/secrets/db_username"
- "MYSQL_PASSWORD_FILE=/run/secrets/db_password"
secrets:
- db_username
- db_password
- db_url
volumes:
- save-fs-storage:/home/cnb/files
- /home/saveu/configs/backend:/home/cnb/config
Expand Down Expand Up @@ -144,5 +162,3 @@ secrets:
external: true
db_username:
external: true
db_url:
external: true
1 change: 1 addition & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ spring-boot-starter-test = { module = "org.springframework.boot:spring-boot-star
spring-boot-starter-data-jpa = { module = "org.springframework.boot:spring-boot-starter-data-jpa" }
spring-boot-starter-quartz = { module = "org.springframework.boot:spring-boot-starter-quartz" }
spring-boot-starter-security = { module = "org.springframework.boot:spring-boot-starter-security" }
spring-boot = { module = "org.springframework.boot:spring-boot" }
spring-boot-configuration-processor = { module = "org.springframework.boot:spring-boot-configuration-processor", version.ref = "spring-boot" }
spring-security-core = { module = "org.springframework.security:spring-security-core" }
spring-security-oauth2-client = { module = "org.springframework.security:spring-security-oauth2-client" }
Expand Down
2 changes: 1 addition & 1 deletion save-backend/src/main/resources/META-INF/spring.factories
Original file line number Diff line number Diff line change
@@ -1 +1 @@
org.springframework.boot.env.EnvironmentPostProcessor=com.saveourtool.save.backend.postprocessor.DockerSecretsDatabaseProcessor
org.springframework.boot.env.EnvironmentPostProcessor=com.saveourtool.save.spring.postprocessor.DockerSecretsDatabaseProcessor
3 changes: 0 additions & 3 deletions save-backend/src/main/resources/application-dev.properties
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
spring.liquibase.enabled=false
# `mysql` is resolved when running mysql in docker-compose, change to `datasource.dev.url` if running backend via `bootRun` or from IDE
spring.datasource.url=jdbc:mysql://localhost:3306/save_cloud
datasource.dev.url=jdbc:mysql://localhost:3306/save_cloud
spring.datasource.username=root
spring.datasource.password=123
backend.url=http://host.docker.internal:${server.port}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
spring.liquibase.enabled=false
spring.datasource.url=jdbc:mysql://192.168.0.250:3306/save_cloud
spring.quartz.job-store-type=jdbc
spring.quartz.jdbc.initialize-schema=ALWAYS
3 changes: 2 additions & 1 deletion save-backend/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ backend.preprocessorUrl=http://preprocessor:5200
backend.orchestratorUrl=http://orchestrator:5100
backend.initialBatchSize=100
backend.fileStorage.location=/home/cnb/files
server.port = 5800
server.port=5800
server.error.path=/error
management.endpoints.web.exposure.include=health,info,prometheus,quartz
server.error.include-message=always
Expand All @@ -20,3 +20,4 @@ spring.jpa.properties.hibernate.order_updates=true
logging.level.org.hibernate.engine.internal.StatisticalLoggingSessionEventListener=WARN
spring.cloud.kubernetes.enabled=false
spring.codec.max-in-memory-size=100MB
spring.liquibase.enabled=false
3 changes: 1 addition & 2 deletions save-cloud-charts/save-cloud/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ api-gateway acts as an entrypoint and svc/gateway is actually a LoadBalancer.

## Prerequisites
* save-backend expects the following secrets to be set under the secret `db-secrets` (`kubectl create secret generic db-secrets <...>`,
also see Secrets section in dev profile in [mysql-deployment.yaml](templates/mysql-deployment.yaml) as a reference):
* `spring.datasource.url`
also see Secrets section in dev profile in [mysql-deployment.yaml](templates/mysql-deployment.yaml) as a reference):
* `spring.datasource.username`
* `spring.datasource.password`

Expand Down
10 changes: 5 additions & 5 deletions save-cloud-charts/save-cloud/templates/backend-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ spec:
env:
{{- include "spring-boot.common.env" (merge (dict "service" .Values.backend) .) | nindent 12 }}
- name: DATABASE_SECRETS_PATH
value: {{ .Values.backend.dbPasswordFile }}
value: {{ .Values.mysql.dbPasswordFile }}
- name: JAVA_TOOL_OPTIONS
value: -XX:ReservedCodeCacheSize=48M
volumeMounts:
- {{ include "spring-boot.config-volume-mount" . | indent 14 | trim }}
- name: fs-storage
mountPath: /home/cnb/files
- name: database-secret
mountPath: {{ .Values.backend.dbPasswordFile }}
mountPath: {{ .Values.mysql.dbPasswordFile }}
{{- include "spring-boot.management" .Values.backend | nindent 10 }}
resources:
limits:
Expand Down Expand Up @@ -62,7 +62,7 @@ spec:
runAsUser: 1001
runAsGroup: 1001
args:
- --url=$(DB_URL)
- --url=$(DB_URL)?createDatabaseIfNotExist=true
- --changeLogFile=db/db.changelog-master.xml
- --username=$(DB_USERNAME)
- --password=$(DB_PASSWORD)
Expand All @@ -82,7 +82,7 @@ spec:
valueFrom:
secretKeyRef:
name: db-secrets
key: spring.datasource.url
key: spring.datasource.backend-url
- name: DB_USERNAME
valueFrom:
secretKeyRef:
Expand All @@ -96,7 +96,7 @@ spec:
volumeMounts:
- mountPath: /liquibase/changelog
name: migrations-data
- mountPath: {{ .Values.backend.dbPasswordFile }}
- mountPath: {{ .Values.mysql.dbPasswordFile }}
name: database-secret
{{ end }}
volumes:
Expand Down
9 changes: 4 additions & 5 deletions save-cloud-charts/save-cloud/templates/mysql-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ kind: Secret
metadata:
name: db-secrets
stringData:
spring.datasource.url: 'jdbc:mysql://mysql-service:3306/{{ .Values.mysql.schema }}'
spring.datasource.backend-url: 'jdbc:mysql://mysql-service:3306/{{ .Values.mysql.backend_schema }}'
spring.datasource.sandbox-url: 'jdbc:mysql://mysql-service:3306/{{ .Values.mysql.sandbox_schema }}'
spring.datasource.username: root
spring.datasource.password: '123'
spring.datasource.password: {{ .Values.mysql.root_password }}

---
{{ end }}
Expand Down Expand Up @@ -36,9 +37,7 @@ spec:
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: '123'
- name: MYSQL_DATABASE
value: save_cloud
value: {{ .Values.mysql.root_password }}
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
Expand Down
Loading