Skip to content

Commit

Permalink
WOR-1141 Set up landing zone web endpoints (#313)
Browse files Browse the repository at this point in the history
* WOR-1141 Set up landing zone web endpoints

* Isolate gradle scripts

* Add version endpoint.

* Exclude swagger generated code from spotless analysis

* Add landing zone create endpoint with tests

* Add endpoint to check result of landing zone create operation

* Add all existing landing zone endpoints

* Add unit tests for landing zone controller

* Add security to swagger/config to serve static content

* Fix artifactory conflict

* PR comments: unauthenticated-> public controller. sh file permission.

* Refactor test code.
  • Loading branch information
sergiygetlin authored Nov 15, 2023
1 parent 5533cf4 commit e9c0822
Show file tree
Hide file tree
Showing 36 changed files with 2,527 additions and 20 deletions.
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
plugins {
id 'com.jfrog.artifactory' version '5.1.10' apply false
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ plugins {

id 'com.diffplug.spotless'
id 'com.github.spotbugs'
id 'org.hidetake.swagger.generator'
}

boolean isGithubAction = System.getenv().containsKey("GITHUB_ACTIONS")
Expand Down Expand Up @@ -41,6 +42,8 @@ repositories {
dependencies {
compileOnly "com.google.code.findbugs:annotations:3.0.1"
implementation 'org.slf4j:slf4j-api:1.7.35'
implementation 'io.swagger.core.v3:swagger-annotations:2.1.12'
swaggerCodegen 'io.swagger.codegen.v3:swagger-codegen-cli:3.0.31'

testImplementation 'ch.qos.logback:logback-classic:1.2.10'
testImplementation 'org.hamcrest:hamcrest:2.2'
Expand Down Expand Up @@ -68,6 +71,7 @@ if (hasProperty("buildScan")) {
spotless {
java {
targetExclude "${buildDir}/**"
targetExclude "**/swagger-code/**"
googleJavaFormat()
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
plugins {
id 'bio.terra.landingzone.java-common-conventions'
id 'java-library'
}
2 changes: 2 additions & 0 deletions client/.swagger-codegen-ignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
**
!**/src/**
48 changes: 48 additions & 0 deletions client/artifactory.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// This and the test below makes sure the build will fail reasonably if you try
// to publish without the environment variables defined.
def artifactory_username = System.getenv("ARTIFACTORY_USERNAME")
def artifactory_password = System.getenv("ARTIFACTORY_PASSWORD")

gradle.taskGraph.whenReady { taskGraph ->
if (taskGraph.hasTask(artifactoryPublish) &&
(artifactory_username == null || artifactory_password == null)) {
throw new GradleException("Set env vars ARTIFACTORY_USERNAME and ARTIFACTORY_PASSWORD to publish")
}
}

java {
// Builds sources into the published package as part of the 'assemble' task.
withSourcesJar()
}

publishing {
publications {
billingProfileManagerClientLibrary(MavenPublication) {
artifactId = "landing-zone-service-client"
from components.java
versionMapping {
usage("java-runtime") {
fromResolutionResult()
}
}
}
}
}

artifactory {
publish {
contextUrl = "https://broadinstitute.jfrog.io/broadinstitute/"
repository {
repoKey = "libs-snapshot-local" // The Artifactory repository key to publish to
username = "${artifactory_username}" // The publisher user name
password = "${artifactory_password}" // The publisher password
}
defaults {
// This is how we tell the Artifactory Plugin which artifacts should be published to Artifactory.
// Reference to Gradle publications defined in the build script.
publications("landingZoneServiceClientLibrary")
publishArtifacts = true
publishPom = true
}
}
}
18 changes: 18 additions & 0 deletions client/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import org.springframework.boot.gradle.plugin.SpringBootPlugin

plugins {
id 'bio.terra.landingzone.java-library-conventions'
id 'maven-publish'
id 'io.spring.dependency-management'
id 'com.jfrog.artifactory'
id 'org.hidetake.swagger.generator'
}

dependencyManagement {
imports {
mavenBom(SpringBootPlugin.BOM_COORDINATES)
}
}

apply from: 'artifactory.gradle'
apply from: 'swagger.gradle'
44 changes: 44 additions & 0 deletions client/swagger.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
dependencies {
// Version controlled by dependency management plugin
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310'
implementation 'org.glassfish.jersey.core:jersey-client'
implementation 'org.glassfish.jersey.media:jersey-media-json-jackson'
implementation 'org.glassfish.jersey.media:jersey-media-multipart'

implementation 'io.swagger.core.v3:swagger-annotations'
swaggerCodegen 'io.swagger.codegen.v3:swagger-codegen-cli'
}

def artifactGroup = "${group}.lz.futureservice"

generateSwaggerCode {
inputFile = file('../service/src/main/resources/api/service_openapi.yaml')
language = 'java'
library = 'jersey2'

// For Swagger Codegen v3 on Java 16+
// See https://github.com/swagger-api/swagger-codegen/issues/10966
jvmArgs = ['--add-opens=java.base/java.util=ALL-UNNAMED']

components = [
apiDocs : false, apiTests: false,
modelDocs: false, modelTests: false
]

additionalProperties = [
modelPackage : "${artifactGroup}.model",
apiPackage : "${artifactGroup}.api",
invokerPackage: "${artifactGroup}.client",
dateLibrary : 'java11',
java8 : true
]

rawOptions = ['--ignore-file-override', "${projectDir}/.swagger-codegen-ignore"]
}

idea.module.generatedSourceDirs = [file("${generateSwaggerCode.outputDir}/src/main/java")]
sourceSets.main.java.srcDir "${generateSwaggerCode.outputDir}/src/main/java"
compileJava.dependsOn generateSwaggerCode
sourcesJar.dependsOn generateSwaggerCode
//why this is required?
spotlessJava.dependsOn generateSwaggerCode
2 changes: 1 addition & 1 deletion library/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ plugins {
id 'com.google.cloud.tools.jib'
id 'com.srcclr.gradle'
id 'org.sonarqube'
id 'com.jfrog.artifactory' version '5.1.10'
id 'com.jfrog.artifactory'
id 'org.liquibase.gradle' version '2.2.0'
}

Expand Down
16 changes: 14 additions & 2 deletions service/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,27 @@ plugins {
id 'de.undercouch.download'
id 'com.google.cloud.tools.jib'
id 'com.srcclr.gradle'
id 'com.gorylenko.gradle-git-properties' version '2.4.1'
}

apply from: 'publishing.gradle'
project.ext {
includeDir = "$projectDir/gradle"
resourceDir = "${projectDir}/src/main/resources"
}

apply(from: "$includeDir/generators.gradle")
apply(from: "$includeDir/publishing.gradle")

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation project(':library')
implementation group: "org.springframework.boot", name: "spring-boot-starter-web"
implementation group: "org.springframework.boot", name: "spring-boot-starter-validation"
implementation group: "org.springframework.boot", name: "spring-boot-starter-data-jdbc"

//implementation group: "org.liquibase", name: "liquibase-core", version: "4.8.0"

testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation group: "org.hamcrest", name: "hamcrest", version: "2.2"
}

test {
Expand Down
50 changes: 50 additions & 0 deletions service/gradle/generators.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
dependencies {
implementation 'io.swagger.core.v3:swagger-annotations'
runtimeOnly 'org.webjars.npm:swagger-ui-dist:4.5.0'
swaggerCodegen 'io.swagger.codegen.v3:swagger-codegen-cli'

// Versioned by Spring:
implementation 'javax.validation:validation-api'
implementation 'org.webjars:webjars-locator-core'

annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
}

def artifactGroup = "${group}.lz.futureservice"

generateSwaggerCode {
inputFile = file('src/main/resources/api/service_openapi.yaml')
language = 'spring'
components = ['models', 'apis']
// For Swagger Codegen v3 on Java 16+
// See https://github.com/swagger-api/swagger-codegen/issues/10966
jvmArgs = ['--add-opens=java.base/java.util=ALL-UNNAMED']
additionalProperties = [
modelPackage : "${artifactGroup}.generated.model",
apiPackage : "${artifactGroup}.generated.api",
modelNamePrefix : "Api",
dateLibrary : 'java8',
java8 : true,
interfaceOnly : 'true',
useTags : 'true',
springBootVersion: dependencyManagement.managedVersions['org.springframework.boot:spring-boot']
]
}

String swaggerOutputSrc = "${generateSwaggerCode.outputDir}/src/main/java"

idea.module.generatedSourceDirs = [file(swaggerOutputSrc)]
sourceSets.main.java.srcDir swaggerOutputSrc
compileJava.dependsOn generateSwaggerCode
//why this is required?
spotlessJava.dependsOn generateSwaggerCode

// see https://github.com/n0mer/gradle-git-properties
gitProperties {
keys = []
gitPropertiesName = "version.properties"
customProperty('landingzone.version.gitTag', { it.describe(tags: true) })
customProperty('landingzone.version.gitHash', { it.head().abbreviatedId })
customProperty('landingzone.version.github', { "https://github.com/DataBiosphere/terra-landing-zone-service/tree/${it.describe(tags: true)}" })
customProperty('landingzone.version.build', version)
}
File renamed without changes.
4 changes: 4 additions & 0 deletions service/local-dev/local-postgres-init.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
CREATE DATABASE landingzone_db;
CREATE ROLE landingzoneuser WITH LOGIN ENCRYPTED PASSWORD 'landingzonepwd';
CREATE DATABASE landingzone_stairway_db;
CREATE ROLE landingzonestairwayuser WITH LOGIN ENCRYPTED PASSWORD 'landingzonestairwaypwd';
50 changes: 50 additions & 0 deletions service/local-dev/run_postgres.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#!/usr/bin/env bash
# Start up a postgres container with initial user/database setup.
POSTGRES_VERSION=13.1

start() {
echo "attempting to remove old $CONTAINER container..."
docker rm -f $CONTAINER

# start up postgres
echo "starting up postgres container..."
BASEDIR=$(dirname "$0")
docker create --name $CONTAINER --rm -e POSTGRES_PASSWORD=password -p "$POSTGRES_PORT:5432" postgres:$POSTGRES_VERSION
docker cp $BASEDIR/local-postgres-init.sql $CONTAINER:/docker-entrypoint-initdb.d/docker_postgres_init.sql
docker start $CONTAINER

# validate postgres
echo "running postgres validation..."
docker exec $CONTAINER sh -c "$(cat $BASEDIR/sql_validate.sh)"
if [ 0 -eq $? ]; then
echo "postgres validation succeeded."
else
echo "postgres validation failed."
exit 1
fi

}

stop() {
echo "Stopping docker $CONTAINER container..."
docker stop $CONTAINER || echo "postgres stop failed. container already stopped."
docker rm -v $CONTAINER
exit 0
}

CONTAINER=postgres_lz
COMMAND=$1
POSTGRES_PORT=${2:-"5432"}

if [ ${#@} == 0 ]; then
echo "Usage: $0 stop|start"
exit 1
fi

if [ $COMMAND = "start" ]; then
start
elif [ $COMMAND = "stop" ]; then
stop
else
exit 1
fi
6 changes: 6 additions & 0 deletions service/local-dev/sql_validate.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/bash

# validate postgres
echo "sleeping for 5 seconds during postgres boot..."
sleep 5
PGPASSWORD=dbpwd psql --username landingzoneuser -d landingzone_db -c "SELECT VERSION();SELECT NOW()"

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package bio.terra.lz.futureservice.app;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;

// temporarily disable autoconfiguration since we don't have any related db yet.
// this prevents from running application
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@ComponentScan(
basePackages = {
// Dependencies for Stairway
"bio.terra.common.kubernetes",
// Scan for iam token handling
"bio.terra.common.iam",
// Stairway initialization and status
"bio.terra.common.stairway",
// Scan all landing zone service packages; from 'library' module
"bio.terra.landingzone",
// Scan for Liquibase migration components & configs
"bio.terra.common.migrate",
// future lz service
"bio.terra.lz.futureservice"
})
public class LandingZoneApplication {

public static void main(String[] args) {
SpringApplication.run(LandingZoneApplication.class, args);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package bio.terra.lz.futureservice.app;

import bio.terra.common.migrate.LiquibaseMigrator;
import bio.terra.landingzone.library.LandingZoneMain;
import org.springframework.context.ApplicationContext;

public class StartupInitializer {
public static void initialize(ApplicationContext applicationContext) {
LiquibaseMigrator migrateService = applicationContext.getBean(LiquibaseMigrator.class);

// Initialize Terra Landing Zone library
LandingZoneMain.initialize(applicationContext, migrateService);
}
}
Loading

0 comments on commit e9c0822

Please sign in to comment.