diff --git a/movies/Jenkinsfile b/movies/Jenkinsfile new file mode 100644 index 0000000..9af1622 --- /dev/null +++ b/movies/Jenkinsfile @@ -0,0 +1,140 @@ +pipeline { + options { + // set a timeout of 60 minutes for this pipeline + timeout(time: 60, unit: 'MINUTES') + } + agent { + node { + //TODO: Add label for the Maven jenkins agent + } + } + + environment { + //TODO: Customize these variables for your environment + DEV_PROJECT = "youruser-movies-dev" + STAGE_PROJECT = "youruser-movies-stage" + APP_GIT_URL = "https://github.com/youruser/DO288-apps" + NEXUS_SERVER = "http://nexus-common.apps.cluster.domain.example.com/repository/java" + + // DO NOT CHANGE THE GLOBAL VARS BELOW THIS LINE + APP_NAME = "movies" + } + + + stages { + + stage('Compilation Check') { + steps { + echo '### Checking for compile errors ###' + sh ''' + cd ${APP_NAME} + mvn -s settings.xml -B clean compile + ''' + } + } + + stage('Run Unit Tests') { + steps { + echo '### Running unit tests ###' + sh ''' + cd ${APP_NAME} + mvn -s settings.xml -B clean test + ''' + } + } + + stage('Static Code Analysis') { + steps { + echo '### Running pmd on code ###' + sh ''' + cd ${APP_NAME} + mvn -s settings.xml -B clean pmd:check + ''' + } + } + + stage('Create fat JAR') { + steps { + echo '### Creating fat JAR ###' + sh ''' + cd ${APP_NAME} + mvn -s settings.xml -B clean package -DskipTests=true + ''' + } + } + + stage('Launch new app in DEV env') { + steps { + echo '### Cleaning existing resources in DEV env ###' + sh ''' + oc delete all -l app=${APP_NAME} -n ${DEV_PROJECT} + oc delete all -l build=${APP_NAME} -n ${DEV_PROJECT} + sleep 5 + oc new-build java:8 --name=${APP_NAME} --binary=true -n ${DEV_PROJECT} + ''' + + echo '### Creating a new app in DEV env ###' + script { + openshift.withCluster() { + openshift.withProject(env.DEV_PROJECT) { + openshift.selector("bc", "${APP_NAME}").startBuild("--from-file=${APP_NAME}/target/${APP_NAME}.jar", "--wait=true", "--follow=true") + } + } + } + // TODO: Create a new OpenShift application based on the ${APP_NAME}:latest image stream + // TODO: Expose the ${APP_NAME} service for external access + } + } + + stage('Wait for deployment in DEV env') { + //TODO: Watch deployment until pod is in 'Running' state + } + + stage('Promote to Staging Env') { + steps { + timeout(time: 60, unit: 'MINUTES') { + input message: "Promote to Staging?" + } + script { + openshift.withCluster() { + // TODO: Tag the ${APP_NAME}:latest image stream in the dev env as ${APP_NAME}:stage in staging + } + } + } + } + + stage('Deploy to Staging Env') { + steps { + echo '### Cleaning existing resources in Staging ###' + sh ''' + oc project ${STAGE_PROJECT} + oc delete all -l app=${APP_NAME} + sleep 5 + ''' + + echo '### Creating a new app in Staging ###' + // TODO: Create a new app in staging + } + } + + stage('Wait for deployment in Staging') { + steps { + sh "oc get route ${APP_NAME} -n ${STAGE_PROJECT} -o jsonpath='{ .spec.host }' --loglevel=4 > routehost" + + script { + routeHost = readFile('routehost').trim() + + openshift.withCluster() { + openshift.withProject( "${STAGE_PROJECT}" ) { + def deployment = openshift.selector("dc", "${APP_NAME}").rollout() + openshift.selector("dc", "${APP_NAME}").related('pods').untilEach(1) { + return (it.object().status.phase == "Running") + } + } + echo "Deployment to Staging env is complete. Access the API endpoint at the URL http://${routeHost}/movies." + } + } + } + } + } +} diff --git a/movies/pom.xml b/movies/pom.xml new file mode 100644 index 0000000..2c26f6a --- /dev/null +++ b/movies/pom.xml @@ -0,0 +1,55 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.1.6.RELEASE + + + com.redhat + movies + 1.0.0 + movies + Demo project for Spring Boot + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + movies + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-pmd-plugin + 3.12.0 + + + /category/java/bestpractices.xml + + true + true + + + + + + \ No newline at end of file diff --git a/movies/settings.xml b/movies/settings.xml new file mode 100644 index 0000000..b981b62 --- /dev/null +++ b/movies/settings.xml @@ -0,0 +1,12 @@ + + + + + internal-repository + Maven Repository Manager for classroom + + http://nexus-common.apps.cluster.domain.example.com/repository/java + * + + + diff --git a/movies/src/main/java/com/redhat/movies/Movie.java b/movies/src/main/java/com/redhat/movies/Movie.java new file mode 100644 index 0000000..9e08faf --- /dev/null +++ b/movies/src/main/java/com/redhat/movies/Movie.java @@ -0,0 +1,43 @@ +package com.redhat.movies; + +import java.io.Serializable; + +public class Movie implements Serializable { + + private static final long serialVersionUID = -3240337073623122124L; + + private Integer movieId; + private String name; + private String genre; + + public Movie(Integer movieId, String name, String genre) { + this.movieId = movieId; + this.name = name; + this.genre = genre; + } + + public Integer getMovieId() { + return movieId; + } + + public void setMovieId(Integer movieId) { + this.movieId = movieId; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getGenre() { + return genre; + } + + public void setGenre(String genre) { + this.genre = genre; + } + +} \ No newline at end of file diff --git a/movies/src/main/java/com/redhat/movies/MoviesApplication.java b/movies/src/main/java/com/redhat/movies/MoviesApplication.java new file mode 100644 index 0000000..ffdfdff --- /dev/null +++ b/movies/src/main/java/com/redhat/movies/MoviesApplication.java @@ -0,0 +1,13 @@ +package com.redhat.movies; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class MoviesApplication { + + public static void main(String[] args) { + SpringApplication.run(MoviesApplication.class, args); + } + +} diff --git a/movies/src/main/java/com/redhat/movies/MoviesController.java b/movies/src/main/java/com/redhat/movies/MoviesController.java new file mode 100644 index 0000000..d16c9b7 --- /dev/null +++ b/movies/src/main/java/com/redhat/movies/MoviesController.java @@ -0,0 +1,39 @@ +package com.redhat.movies; + +import java.util.ArrayList; +import java.util.List; +import java.io.File; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/") +public class MoviesController { + + private List movies; + private String status = "OK"; + private String flag = "READY"; + + @GetMapping("/movies") + public List getAllMovies() { + + //Generate fake static data + movies = new ArrayList(); + movies.add(new Movie(1,"The Godfather","Crime/Thriller")); + movies.add(new Movie(2,"Star Wars","Sci-Fi")); + movies.add(new Movie(3,"The Mask","Comedy")); + movies.add(new Movie(4,"Die Hard","Action")); + movies.add(new Movie(5,"The Exorcist","Horror")); + movies.add(new Movie(6,"The Silence of the Lambs","Drama")); + + return movies; + } + + @GetMapping("/status") + public String getStatus() { + return status; + } + +} diff --git a/movies/src/main/resources/application.properties b/movies/src/main/resources/application.properties new file mode 100644 index 0000000..d8f4060 --- /dev/null +++ b/movies/src/main/resources/application.properties @@ -0,0 +1 @@ +spring.jackson.serialization.indent_output=true diff --git a/movies/src/test/java/com/redhat/movies/MoviesApplicationTests.java b/movies/src/test/java/com/redhat/movies/MoviesApplicationTests.java new file mode 100644 index 0000000..095cdd9 --- /dev/null +++ b/movies/src/test/java/com/redhat/movies/MoviesApplicationTests.java @@ -0,0 +1,68 @@ +package com.redhat.movies; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = MoviesApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class MoviesApplicationTests { + + @Autowired + private TestRestTemplate restTemplate; + + @LocalServerPort + private int port; + + @Test + public void contextLoads() { + } + + @Test + public void testNotNullResponse() { + HttpHeaders headers = new HttpHeaders(); + HttpEntity entity = new HttpEntity(null, headers); + + ResponseEntity response = restTemplate.exchange("http://localhost:" + port + "/movies", HttpMethod.GET, + entity, String.class); + + Assert.assertNotNull(response.getBody()); + } + + @Test + public void testGetAllMovies() { + + ResponseEntity > response = restTemplate.exchange("http://localhost:" + port + "/movies", + HttpMethod.GET, null, new ParameterizedTypeReference > () {}); + + List movies = response.getBody(); + Assert.assertNotNull(movies); + Assert.assertEquals(7, movies.size()); + Assert.assertEquals("The Godfather", movies.get(0).getName()); + } + + @Test + public void testGetStatus() { + HttpHeaders headers = new HttpHeaders(); + HttpEntity entity = new HttpEntity(null, headers); + + ResponseEntity response = restTemplate.exchange("http://localhost:" + port + "/status", HttpMethod.GET, + entity, String.class); + + Assert.assertNotNull(response.getBody()); + Assert.assertEquals("Ready", response.getBody()); + } + +}