Skip to content

Commit

Permalink
OPHYK-214 Make Docker image of varda-rekisterointi
Browse files Browse the repository at this point in the history
Main changes to before:

* Write access log to stdout
* Write audit log to stdout
* Remove unused url-alb property
  • Loading branch information
rce committed Dec 23, 2024
1 parent 5de1a6a commit 17737e5
Show file tree
Hide file tree
Showing 22 changed files with 313 additions and 720 deletions.
5 changes: 5 additions & 0 deletions infra/src/cdk-app-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,10 @@ function makeUbuntuTestProject(
type: codebuild.BuildEnvironmentVariableType.PARAMETER_STORE,
value: "/gradle/github-packages-gradle-properties",
},
MVN_SETTINGSXML: {
type: codebuild.BuildEnvironmentVariableType.PARAMETER_STORE,
value: `/mvn/settingsxml`,
},
TZ: {
type: codebuild.BuildEnvironmentVariableType.PLAINTEXT,
value: "Europe/Helsinki",
Expand All @@ -353,6 +357,7 @@ function makeUbuntuTestProject(
"sudo apt-get install -y libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libnss3 libxss1 libasound2 libxtst6 xauth xvfb", // For Cypress/Chromium
`git checkout ${tag}`,
"mkdir -p ~/.gradle && echo $GITHUB_PACKAGES_GRADLE_PROPERTIES | base64 -d > ~/.gradle/gradle.properties",
"echo $MVN_SETTINGSXML > ./varda-rekisterointi/settings.xml",
]
},
build: {
Expand Down
159 changes: 155 additions & 4 deletions infra/src/cdk-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,12 @@ class CdkApp extends cdk.App {
const vardaRekisterointiDatabaseStack = new VardRekisterointiDatabaseStack(this, "VardaRekisterointiDatabase", vpc, ecsStack.cluster, bastion, alarmTopic, stackProps);
const organisaatioDatabaseStack = new OrganisaatioDatabaseStack(this, "Database", vpc, ecsStack.cluster, bastion, alarmTopic, stackProps);
createHealthCheckStacks(this, alarmsToSlackLambda)
new ApplicationStack(this, "OrganisaatioApplication", vpc, hostedZone, alarmTopic, {
new VardaRekisterointiApplicationStack(this, "VardaRekisterointiApplication", vpc, hostedZone, {
database: vardaRekisterointiDatabaseStack.database,
ecsCluster: ecsStack.cluster,
...stackProps,
});
new OrganisaatioApplicationStack(this, "OrganisaatioApplication", vpc, hostedZone, alarmTopic, {
database: organisaatioDatabaseStack.database,
exportBucket: organisaatioDatabaseStack.exportBucket,
ecsCluster: ecsStack.cluster,
Expand Down Expand Up @@ -301,20 +306,20 @@ class VardRekisterointiDatabaseStack extends cdk.Stack {
}
}

type ApplicationStackProps = cdk.StackProps & {
type OrganisaatioApplicationStackProps = cdk.StackProps & {
database: rds.DatabaseCluster
ecsCluster: ecs.Cluster
exportBucket: s3.Bucket
}

class ApplicationStack extends cdk.Stack {
class OrganisaatioApplicationStack extends cdk.Stack {
constructor(
scope: constructs.Construct,
id: string,
vpc: ec2.IVpc,
hostedZone: route53.IHostedZone,
alarmTopic: sns.ITopic,
props: ApplicationStackProps,
props: OrganisaatioApplicationStackProps,
) {
super(scope, id, props);

Expand Down Expand Up @@ -538,5 +543,151 @@ class ApplicationStack extends cdk.Stack {
}
}

type VardaRekisterointiApplicationStackProps = cdk.StackProps & {
database: rds.DatabaseCluster
ecsCluster: ecs.Cluster
}

class VardaRekisterointiApplicationStack extends cdk.Stack {
constructor(
scope: constructs.Construct,
id: string,
vpc: ec2.IVpc,
hostedZone: route53.IHostedZone,
props: VardaRekisterointiApplicationStackProps,
) {
super(scope, id, props);

const logGroup = new logs.LogGroup(this, "AppLogGroup", {
logGroupName: "Organisaatio/varda-rekisterointi",
retention: logs.RetentionDays.INFINITE,
});

const dockerImage = new ecr_assets.DockerImageAsset(this, "AppImage", {
directory: path.join(__dirname, "../../varda-rekisterointi"),
file: "Dockerfile",
platform: ecr_assets.Platform.LINUX_ARM64,
});

const taskDefinition = new ecs.FargateTaskDefinition(
this,
"TaskDefinition",
{
cpu: 512,
memoryLimitMiB: 2048,
runtimePlatform: {
operatingSystemFamily: ecs.OperatingSystemFamily.LINUX,
cpuArchitecture: ecs.CpuArchitecture.ARM64,
},
});

const appPort = 8080;
taskDefinition.addContainer("AppContainer", {
image: ecs.ContainerImage.fromDockerImageAsset(dockerImage),
logging: new ecs.AwsLogDriver({ logGroup, streamPrefix: "app" }),
environment: {
ENV: getEnvironment(),
postgresql_host: props.database.clusterEndpoint.hostname,
postgresql_port: props.database.clusterEndpoint.port.toString(),
postgresql_db: "vardarekisterointi",
aws_region: this.region,
},
secrets: {
postgresql_username: ecs.Secret.fromSecretsManager(
props.database.secret!,
"username"
),
postgresql_password: ecs.Secret.fromSecretsManager(
props.database.secret!,
"password"
),
palvelukayttaja_username: this.ssmSecret("PalvelukayttajaUsername"),
palvelukayttaja_password: this.ssmSecret("PalvelukayttajaPassword"),
varda_rekisterointi_valtuudet_client_id: this.ssmSecret("ValtuudetClientId"),
varda_rekisterointi_valtuudet_api_key: this.ssmSecret("ValtuudetApiKey"),
varda_rekisterointi_valtuudet_oauth_password: this.ssmSecret("ValtuudetOauthPassword"),
varda_rekisterointi_rekisterointi_ui_username: this.ssmSecret("RekisterointiUiUsername"),
varda_rekisterointi_rekisterointi_ui_password: this.ssmSecret("RekisterointiUiPassword"),
},
portMappings: [
{
name: "vardareisterointi",
containerPort: appPort,
appProtocol: ecs.AppProtocol.http,
},
],
});

const conf = getConfig();
const service = new ecs.FargateService(this, "Service", {
cluster: props.ecsCluster,
taskDefinition,
desiredCount: conf.vardaRekisterointiCapacity,
minHealthyPercent: 100,
maxHealthyPercent: 200,
vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
healthCheckGracePeriod: cdk.Duration.minutes(5),
});
service.connections.allowToDefaultPort(props.database);

const alb = new elasticloadbalancingv2.ApplicationLoadBalancer(
this,
"LoadBalancer",
{
vpc,
internetFacing: true,
}
);

const albHostname = `vardarekisterointi.${hostedZone.zoneName}`;

new route53.ARecord(this, "ALBARecord", {
zone: hostedZone,
recordName: albHostname,
target: route53.RecordTarget.fromAlias(
new route53_targets.LoadBalancerTarget(alb)
),
});

const albCertificate = new certificatemanager.Certificate(
this,
"AlbCertificate",
{
domainName: albHostname,
validation:
certificatemanager.CertificateValidation.fromDns(hostedZone),
}
);

const listener = alb.addListener("Listener", {
protocol: elasticloadbalancingv2.ApplicationProtocol.HTTPS,
port: 443,
open: true,
certificates: [albCertificate],
});

listener.addTargets("ServiceTarget", {
port: appPort,
targets: [service],
healthCheck: {
enabled: true,
interval: cdk.Duration.seconds(10),
path: "/varda-rekisterointi/actuator/health",
port: appPort.toString(),
},
});
}

ssmSecret(name: string): ecs.Secret {
return ecs.Secret.fromSsmParameter(
ssm.StringParameter.fromSecureStringParameterAttributes(
this,
`Param${name}`,
{ parameterName: `/vardarekisterointi/${name}` }
)
);
}
}

const app = new CdkApp({});
app.synth();
5 changes: 5 additions & 0 deletions infra/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const defaultConfig = {
virkailijaHost: "",
minCapacity: 1,
maxCapacity: 1,
vardaRekisterointiCapacity: 0,
};

export type Config = typeof defaultConfig;
Expand Down Expand Up @@ -32,19 +33,23 @@ export function getConfig(): Config {
export const hahtuva: Config = {
...defaultConfig,
virkailijaHost: "virkailija.hahtuvaopintopolku.fi",
vardaRekisterointiCapacity: 0,
};

export const dev: Config = {
...defaultConfig,
virkailijaHost: "virkailija.untuvaopintopolku.fi",
vardaRekisterointiCapacity: 0,
};

export const qa: Config = {
...defaultConfig,
virkailijaHost: "virkailija.testiopintopolku.fi",
vardaRekisterointiCapacity: 0,
};

export const prod: Config = {
...defaultConfig,
virkailijaHost: "virkailija.opintopolku.fi",
vardaRekisterointiCapacity: 0,
};
2 changes: 2 additions & 0 deletions varda-rekisterointi/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
target/
node_modules/
117 changes: 0 additions & 117 deletions varda-rekisterointi/.mvn/wrapper/MavenWrapperDownloader.java

This file was deleted.

Binary file removed varda-rekisterointi/.mvn/wrapper/maven-wrapper.jar
Binary file not shown.
2 changes: 0 additions & 2 deletions varda-rekisterointi/.mvn/wrapper/maven-wrapper.properties

This file was deleted.

30 changes: 30 additions & 0 deletions varda-rekisterointi/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
FROM maven:3.9.8-amazoncorretto-21-al2023 AS build
WORKDIR /app

RUN dnf install -y nodejs20 \
&& alternatives --install /usr/bin/node node /usr/bin/node-20 90 \
&& alternatives --install /usr/bin/npm npm /usr/bin/npm-20 90 \
&& alternatives --install /usr/bin/npx npx /usr/bin/npx-20 90

COPY package.json .
COPY package-lock.json .
RUN npm ci

COPY . .
RUN npm run build
RUN mvn clean package -s settings.xml -DskipTests

FROM amazoncorretto:21
WORKDIR /app

COPY --from=build /app/target/varda-rekisterointi.jar varda-rekisterointi.jar
COPY --chmod=755 <<"EOF" /app/entrypoint.sh
#!/usr/bin/env bash
set -o errexit -o nounset -o pipefail

exec java \
-Dspring.config.additional-location=classpath:/config/aws.yml,classpath:/config/$ENV.yml \
-jar varda-rekisterointi.jar
EOF

ENTRYPOINT [ "/app/entrypoint.sh" ]
Loading

0 comments on commit 17737e5

Please sign in to comment.