From fe9006dcadfc00605f012d2bc5492132c436c50c Mon Sep 17 00:00:00 2001 From: Ravi Srinivasan <rsriniva@redhat.com> Date: Fri, 12 Jul 2019 09:25:16 +0200 Subject: [PATCH] Added movies microservice for Ch 8 EoC Lab --- movies/src/main/java/com/redhat/movies/Movie.java | 43 ++++++ movies/src/main/resources/application.properties | 1 movies/src/main/java/com/redhat/movies/MoviesApplication.java | 13 + movies/pom.xml | 55 +++++++ movies/src/main/java/com/redhat/movies/MoviesController.java | 39 +++++ movies/Jenkinsfile | 140 ++++++++++++++++++++ movies/settings.xml | 12 + movies/src/test/java/com/redhat/movies/MoviesApplicationTests.java | 68 +++++++++ 8 files changed, 371 insertions(+), 0 deletions(-) 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 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-parent</artifactId> + <version>2.1.6.RELEASE</version> + <relativePath /> <!-- lookup parent from repository --> + </parent> + <groupId>com.redhat</groupId> + <artifactId>movies</artifactId> + <version>1.0.0</version> + <name>movies</name> + <description>Demo project for Spring Boot</description> + + <properties> + <java.version>1.8</java.version> + </properties> + + <dependencies> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-web</artifactId> + </dependency> + + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-test</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <finalName>movies</finalName> + <plugins> + <plugin> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-maven-plugin</artifactId> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-pmd-plugin</artifactId> + <version>3.12.0</version> + <configuration> + <rulesets> + <ruleset>/category/java/bestpractices.xml</ruleset> + </rulesets> + <failOnViolation>true</failOnViolation> + <printFailingErrors>true</printFailingErrors> + </configuration> + </plugin> + </plugins> + </build> + +</project> \ 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 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<settings> + <mirrors> + <mirror> + <id>internal-repository</id> + <name>Maven Repository Manager for classroom</name> + <!-- // TODO: Change the url attribute to the nexus proxy server URL for your environment. --> + <url>http://nexus-common.apps.cluster.domain.example.com/repository/java</url> + <mirrorOf>*</mirrorOf> + </mirror> + </mirrors> +</settings> 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<Movie> movies; + private String status = "OK"; + private String flag = "READY"; + + @GetMapping("/movies") + public List<Movie> getAllMovies() { + + //Generate fake static data + movies = new ArrayList<Movie>(); + 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<String> entity = new HttpEntity<String>(null, headers); + + ResponseEntity<String> response = restTemplate.exchange("http://localhost:" + port + "/movies", HttpMethod.GET, + entity, String.class); + + Assert.assertNotNull(response.getBody()); + } + + @Test + public void testGetAllMovies() { + + ResponseEntity <List<Movie>> response = restTemplate.exchange("http://localhost:" + port + "/movies", + HttpMethod.GET, null, new ParameterizedTypeReference <List<Movie>> () {}); + + List <Movie> 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<String> entity = new HttpEntity<String>(null, headers); + + ResponseEntity<String> response = restTemplate.exchange("http://localhost:" + port + "/status", HttpMethod.GET, + entity, String.class); + + Assert.assertNotNull(response.getBody()); + Assert.assertEquals("Ready", response.getBody()); + } + +} -- Gitblit v1.9.3