From 8f5ec08e5d063b789fd9d2fc9bb96942614d70b2 Mon Sep 17 00:00:00 2001 From: Microclimate User Date: Mon, 19 Mar 2018 16:07:25 +0000 Subject: [PATCH] Initial commit of stockquote --- .bluemix/deploy.json | 59 +++ .bluemix/pipeline.yml | 48 +++ .bluemix/scripts/container_build.sh | 96 +++++ .bluemix/scripts/kube_deploy.sh | 69 +++ .bluemix/toolchain.yml | 52 +++ .cfignore | 7 + .dockerignore | 10 + .gitignore | 15 + Dockerfile | 14 + Dockerfile-build | 60 +++ Dockerfile-lang | 13 + Dockerfile-tools | 12 + Jenkinsfile | 6 + README.md | 65 +++ chart/stockquote/Chart.yaml | 4 + .../stockquote/templates/basedeployment.yaml | 36 ++ chart/stockquote/templates/deployment.yaml | 66 +++ chart/stockquote/templates/hpa.yaml | 27 ++ chart/stockquote/templates/istio.yaml | 19 + chart/stockquote/templates/service.yaml | 15 + chart/stockquote/values.yaml | 36 ++ cli-config.yml | 47 +++ manifest.yml | 9 + manifests/kube.deploy.yml | 44 ++ pom.xml | 393 ++++++++++++++++++ .../java/application/rest/HealthEndpoint.java | 24 ++ .../application/rest/JaxrsApplication.java | 9 + .../java/application/rest/RootEndpoint.java | 22 + .../java/application/rest/v1/Example.java | 27 ++ src/main/liberty/config/jvm.options | 1 + src/main/liberty/config/jvmbx.options | 1 + src/main/liberty/config/server.xml | 17 + src/main/webapp/WEB-INF/beans.xml | 0 src/main/webapp/WEB-INF/ibm-web-ext.xml | 8 + src/test/java/it/HealthEndpointIT.java | 40 ++ 35 files changed, 1371 insertions(+) create mode 100644 .bluemix/deploy.json create mode 100644 .bluemix/pipeline.yml create mode 100644 .bluemix/scripts/container_build.sh create mode 100644 .bluemix/scripts/kube_deploy.sh create mode 100644 .bluemix/toolchain.yml create mode 100644 .cfignore create mode 100644 .dockerignore create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 Dockerfile-build create mode 100644 Dockerfile-lang create mode 100644 Dockerfile-tools create mode 100644 Jenkinsfile create mode 100644 README.md create mode 100644 chart/stockquote/Chart.yaml create mode 100644 chart/stockquote/templates/basedeployment.yaml create mode 100644 chart/stockquote/templates/deployment.yaml create mode 100644 chart/stockquote/templates/hpa.yaml create mode 100644 chart/stockquote/templates/istio.yaml create mode 100644 chart/stockquote/templates/service.yaml create mode 100644 chart/stockquote/values.yaml create mode 100644 cli-config.yml create mode 100644 manifest.yml create mode 100644 manifests/kube.deploy.yml create mode 100644 pom.xml create mode 100644 src/main/java/application/rest/HealthEndpoint.java create mode 100644 src/main/java/application/rest/JaxrsApplication.java create mode 100644 src/main/java/application/rest/RootEndpoint.java create mode 100644 src/main/java/application/rest/v1/Example.java create mode 100644 src/main/liberty/config/jvm.options create mode 100644 src/main/liberty/config/jvmbx.options create mode 100644 src/main/liberty/config/server.xml create mode 100644 src/main/webapp/WEB-INF/beans.xml create mode 100644 src/main/webapp/WEB-INF/ibm-web-ext.xml create mode 100644 src/test/java/it/HealthEndpointIT.java diff --git a/.bluemix/deploy.json b/.bluemix/deploy.json new file mode 100644 index 0000000..3d66c56 --- /dev/null +++ b/.bluemix/deploy.json @@ -0,0 +1,59 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Sample Deploy Stage", + "longDescription": "The Delivery Pipeline automates continuous deployment.", + "type": "object", + "properties": { + "dev-region": { + "description": "The bluemix region", + "type": "string" + }, + "dev-organization": { + "description": "The bluemix org", + "type": "string" + }, + "dev-space": { + "description": "The bluemix space", + "type": "string" + }, + "app-name": { + "description": "app name", + "type": "string" + } + }, + "required": ["dev-region", "dev-organization", "dev-space", "app-name"], + "form": [{ + "type": "validator", + "url": "/devops/setup/bm-helper/helper.html" + }, + { + "type": "text", + "readonly": false, + "title": "App Name", + "key": "app-name" + }, { + "type": "table", + "columnCount": 3, + "widths": ["28%", "28%", "28%"], + "items": [{ + "type": "label", + "title": "Region" + }, { + "type": "label", + "title": "Organization" + }, { + "type": "label", + "title": "Space" + }, { + "type": "select", + "key": "dev-region" + }, { + "type": "select", + "key": "dev-organization" + }, { + "type": "select", + "key": "dev-space", + "readonly": false + }] + }] +} diff --git a/.bluemix/pipeline.yml b/.bluemix/pipeline.yml new file mode 100644 index 0000000..dcf7596 --- /dev/null +++ b/.bluemix/pipeline.yml @@ -0,0 +1,48 @@ +stages: +- name: Build Stage + inputs: + - type: git + branch: master + service: ${REPO} + triggers: + - type: commit + jobs: + - name: Build + type: builder + build_type: shell + script: | + #!/bin/bash + export JAVA_HOME=$JAVA8_HOME + mvn install -DskipTests + - name: Post Build + type: builder + artifact_dir: '' + build_type: shell + script: |- + #!/bin/bash + if [[ -f post_build.sh ]]; then + chmod +x post_build.sh; + echo "executing the post_build script"; + sh post_build.sh; + else + echo "the post_build script does not exist"; + fi +- name: Deploy Stage + inputs: + - type: job + stage: Build Stage + job: Build + triggers: + - type: stage + jobs: + - name: Deploy + type: deployer + target: + region_id: ${REGION_ID} + organization: ${CF_ORGANIZATION} + space: ${CF_SPACE} + application: ${CF_APP} + script: |- + #!/bin/bash + cf push "${CF_APP}" -p target/MyProject-1.0-SNAPSHOT.zip + # cf logs "${CF_APP}" --recent diff --git a/.bluemix/scripts/container_build.sh b/.bluemix/scripts/container_build.sh new file mode 100644 index 0000000..5ea302e --- /dev/null +++ b/.bluemix/scripts/container_build.sh @@ -0,0 +1,96 @@ +#!/bin/bash +#set -x + +echo -e "Build environment variables:" +echo "REGISTRY_URL=${REGISTRY_URL}" +echo "REGISTRY_NAMESPACE=${REGISTRY_NAMESPACE}" +echo "IMAGE_NAME=${IMAGE_NAME}" +echo "CHART_NAME=${CHART_NAME}" +echo "BUILD_NUMBER=${BUILD_NUMBER}" +echo "ARCHIVE_DIR=${ARCHIVE_DIR}" + +# Learn more about the available environment variables at: +# https://console.bluemix.net/docs/services/ContinuousDelivery/pipeline_deploy_var.html#deliverypipeline_environment + +# To review or change build options use: +# bx cr build --help + +echo "==========================================================" +echo "Checking for Dockerfile at the repository root" +if [ -f Dockerfile ]; then + echo "Dockerfile found" +else + echo "Dockerfile not found" + exit 1 +fi + +echo "==========================================================" +echo "Checking registry current plan and quota" +bx cr plan +bx cr quota +echo "If needed, discard older images using: bx cr image-rm" + +# TODO this check for namespace is not enough, namespace has to be unique per region. +# This only checks for existence of namespace in user's account. When creating namespace, +# need to handle case where it's already taken, and perhaps generate a unique one. +# Rules for namespace: +# The namespace must be unique and not taken in registry region. +# The namespace must be 4-30 characters long. +# The namespace must start with at least one letter or number. +# The namespace can only contain lowercase letters, numbers or underscores (_). +#echo "Checking registry namespace: ${REGISTRY_NAMESPACE}" +#ns=$( bx cr namespaces | grep ${REGISTRY_NAMESPACE} ||: ) +#if [ -z $ns ]; then +# echo "Registry namespace ${REGISTRY_NAMESPACE} not found, creating it." +# bx cr namespace-add ${REGISTRY_NAMESPACE} +# echo "Registry namespace ${REGISTRY_NAMESPACE} created." +#else +# echo "Registry namespace ${REGISTRY_NAMESPACE} found." +#fi + +echo -e "Existing images in registry" +bx cr images + +echo "==========================================================" +echo -e "Building container image: ${IMAGE_NAME}:${BUILD_NUMBER}" +set -x +bx cr build -t $REGISTRY_URL/$REGISTRY_NAMESPACE/$IMAGE_NAME:$BUILD_NUMBER . +set +x +bx cr image-inspect $REGISTRY_URL/$REGISTRY_NAMESPACE/$IMAGE_NAME:$BUILD_NUMBER + +echo "==========================================================" +echo "Copying artifacts needed for deployment and testing" + +echo -e "Checking archive dir presence" +mkdir -p $ARCHIVE_DIR + +# IMAGE_NAME from build.properties is used by Vulnerability Advisor job to reference the image qualified location in registry +echo "IMAGE_NAME=${REGISTRY_URL}/${REGISTRY_NAMESPACE}/${IMAGE_NAME}:${BUILD_NUMBER}" >> $ARCHIVE_DIR/build.properties + +# RELEASE_NAME from build.properties is used in Helm Chart deployment to set the release name +echo "RELEASE_NAME=${CHART_NAME}" >> $ARCHIVE_DIR/build.properties + +# REGISTRY_HOST from build.properties is used to create imagePullSecret, ex: registry.ng.bluemix.net +echo "REGISTRY_HOST=${REGISTRY_URL}" >> $ARCHIVE_DIR/build.properties + +# Copy scripts (incl. deploy scripts) +if [ ! -d $ARCHIVE_DIR/$SCRIPTS_DIR ]; then # no need to copy if working in ./ already + echo "Copying scripts to ${ARCHIVE_DIR}/${SCRIPTS_DIR}" + mkdir -p $ARCHIVE_DIR/$SCRIPTS_DIR + cp -r $SCRIPTS_DIR/ $ARCHIVE_DIR/$SCRIPTS_DIR/ +fi + +if [ -f ./chart/${CHART_NAME}/values.yaml ]; then + #Update Helm chart values.yml with image name and tag + echo "UPDATING CHART VALUES:" + sed -i "s~^\([[:blank:]]*\)repository:.*$~\1repository: ${REGISTRY_URL}/${REGISTRY_NAMESPACE}/${IMAGE_NAME}~" ./chart/${CHART_NAME}/values.yaml + sed -i "s~^\([[:blank:]]*\)tag:.*$~\1tag: ${BUILD_NUMBER}~" ./chart/${CHART_NAME}/values.yaml + cat ./chart/${CHART_NAME}/values.yaml + if [ ! -d $ARCHIVE_DIR/chart/ ]; then # no need to copy if working in ./ already + echo "Copying chart to ${ARCHIVE_DIR}" + cp -r ./chart/ $ARCHIVE_DIR/ + fi +else + echo -e "${red}Helm chart values for Kubernetes deployment (/chart/${CHART_NAME}/values.yaml) not found.${no_color}" + exit 1 +fi \ No newline at end of file diff --git a/.bluemix/scripts/kube_deploy.sh b/.bluemix/scripts/kube_deploy.sh new file mode 100644 index 0000000..58d697e --- /dev/null +++ b/.bluemix/scripts/kube_deploy.sh @@ -0,0 +1,69 @@ +#!/bin/bash +#set -x + +#View build properties +cat build.properties + +echo "Check cluster availability" +ip_addr=$(bx cs workers $PIPELINE_KUBERNETES_CLUSTER_NAME | grep normal | awk '{ print $2 }') +if [ -z $ip_addr ]; then + echo "$PIPELINE_KUBERNETES_CLUSTER_NAME not created or workers not ready" + exit 1 +fi + +echo "Check cluster target namespace" +if ! kubectl get namespace $CLUSTER_NAMESPACE; then + echo "$CLUSTER_NAMESPACE cluster namespace does not exist, creating it" + kubectl create namespace $CLUSTER_NAMESPACE +fi + +echo "create ${IMAGE_PULL_SECRET_NAME} imagePullSecret if it does not exist" +if ! kubectl get secret ${IMAGE_PULL_SECRET_NAME} --namespace $CLUSTER_NAMESPACE; then + echo "${IMAGE_PULL_SECRET_NAME} not found in $CLUSTER_NAMESPACE, creating it" + # for Container Registry, docker username is 'token' and email does not matter + kubectl --namespace $CLUSTER_NAMESPACE create secret docker-registry $IMAGE_PULL_SECRET_NAME --docker-server=$REGISTRY_HOST --docker-password=$IMAGE_REGISTRY_TOKEN --docker-username=token --docker-email=a@b.com +fi + +echo "enable default serviceaccount to use the pull secret" +kubectl patch -n $CLUSTER_NAMESPACE serviceaccount/default -p '{"imagePullSecrets":[{"name":"'"$IMAGE_PULL_SECRET_NAME"'"}]}' +echo "Namespace $CLUSTER_NAMESPACE is now authorized to pull from the private image registry" +echo "default serviceAccount:" +kubectl get serviceAccount default -o yaml + +# Check Helm/Tiller +echo "CHECKING TILLER (Helm's server component)" +helm init --upgrade +while true; do + tiller_deployed=$(kubectl --namespace=kube-system get pods | grep tiller | grep Running | grep 1/1 ) + if [[ "${tiller_deployed}" != "" ]]; then + echo "Tiller ready." + break; + fi + echo "Waiting for Tiller to be ready." + sleep 1 +done +helm version + +echo "CHART_NAME: $CHART_NAME" +echo "RELEASE_NAME: $RELEASE_NAME" + +echo "CHECKING CHART (lint)" +helm lint ${RELEASE_NAME} ./chart/${CHART_NAME} + +echo "DRY RUN DEPLOYING into: $PIPELINE_KUBERNETES_CLUSTER_NAME/$CLUSTER_NAMESPACE." +helm upgrade ${RELEASE_NAME} ./chart/${CHART_NAME} --namespace $CLUSTER_NAMESPACE --install --debug --dry-run + +echo "DEPLOYING into: $PIPELINE_KUBERNETES_CLUSTER_NAME/$CLUSTER_NAMESPACE." +helm upgrade ${RELEASE_NAME} ./chart/${CHART_NAME} --namespace $CLUSTER_NAMESPACE --install + +echo "" +echo "DEPLOYED SERVICE:" +kubectl describe services ${CHART_NAME} --namespace $CLUSTER_NAMESPACE + +echo "" +echo "DEPLOYED PODS:" +kubectl describe pods --selector app=${CHART_NAME}-selector --namespace $CLUSTER_NAMESPACE + +port=$(kubectl get services --namespace $CLUSTER_NAMESPACE | grep ${CHART_NAME} | sed 's/.*:\([0-9]*\).*/\1/g') +echo "" +echo "VIEW THE APPLICATION AT: http://$ip_addr:$port" \ No newline at end of file diff --git a/.bluemix/toolchain.yml b/.bluemix/toolchain.yml new file mode 100644 index 0000000..ff8a7f2 --- /dev/null +++ b/.bluemix/toolchain.yml @@ -0,0 +1,52 @@ +name: Continuous Delivery Toolchain +description: "This toolchain includes tools to develop and deploy your app. Depending on your app, when you create the toolchain, the GitHub repository will either be empty or will contain source code from your app.\n\nThis toolchain uses tools that are part of the Continuous Delivery service. If an instance of that service isn't already in your organization, when you click **Create**, it is automatically added at no cost to you. For more information and terms, see the [Bluemix catalog](/catalog/services/continuous-delivery/).\n\nTo get started, click **Create**." +version: 0.2 +required: + - deploy + - repo + +toolchain: + name: stockquote + +# Github repos +repo: + service_id: hostedgit + parameters: + repo_url: "{{#zip_url}}{{zip_url}}{{/zip_url}}{{^zip_url}}{{repository}}{{/zip_url}}" + repo_name: "{{toolchain.name}}" + type: clone + has_issues: true + enable_traceability: true + +# Pipelines +build: + service_id: pipeline + parameters: + name: "{{name}}" + ui-pipeline: true + configuration: + content: $file(pipeline.yml) + env: + REPO: "repo" + CF_APP: "{{deploy.parameters.app-name}}" + CF_SPACE: "{{deploy.parameters.dev-space}}" + CF_ORGANIZATION: "{{deploy.parameters.dev-organization}}" + REGION_ID: "{{deploy.parameters.dev-region}}" + execute: true + services: ["repo"] + hidden: ["form"] + +#Web IDE +webide: + service_id: orion + +#Deployment +deploy: + schema: + $ref: deploy.json + service-category: pipeline + parameters: + app-name: stockquote + dev-space: "{{space}}" + dev-organization: "{{organization}}" + dev-region: "{{region}}" diff --git a/.cfignore b/.cfignore new file mode 100644 index 0000000..132f5ad --- /dev/null +++ b/.cfignore @@ -0,0 +1,7 @@ +/.classpath +/.project +/.settings +/src/main/liberty/config/server.env +target/ +mc-target/ +build/ \ No newline at end of file diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..f48e3e8 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,10 @@ +#Ignore Liberty server files +target/liberty/wlp/usr/servers/defaultServer/logs +target/liberty/wlp/usr/servers/defaultServer/workarea +target/liberty/wlp/usr/servers/defaultServer/.classCache +target/liberty/wlp/usr/servers/defaultServer/.pid +mc-target/liberty/wlp/usr/servers/defaultServer/logs +mc-target/liberty/wlp/usr/servers/defaultServer/workarea +mc-target/liberty/wlp/usr/servers/defaultServer/.classCache +mc-target/liberty/wlp/usr/servers/defaultServer/.pid + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..56ca59b --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +/target +/mc-target +/.m2 +/load-test/*/ + + +/.classpath +/.project +/.settings + +/caches +/local.properties +.*.swp +.DS_Store +/src/main/liberty/config/server.env diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..0af4bb8 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,14 @@ +FROM websphere-liberty:webProfile7 +MAINTAINER IBM Java engineering at IBM Cloud +COPY /target/liberty/wlp/usr/servers/defaultServer /config/ +COPY /target/liberty/wlp/usr/shared/resources /config/resources/ +COPY /src/main/liberty/config/jvmbx.options /config/jvm.options +RUN installUtility install --acceptLicense defaultServer +# Upgrade to production license if URL to JAR provided +ARG LICENSE_JAR_URL +RUN \ + if [ $LICENSE_JAR_URL ]; then \ + wget $LICENSE_JAR_URL -O /tmp/license.jar \ + && java -jar /tmp/license.jar -acceptLicense /opt/ibm \ + && rm /tmp/license.jar; \ + fi diff --git a/Dockerfile-build b/Dockerfile-build new file mode 100644 index 0000000..0e1398f --- /dev/null +++ b/Dockerfile-build @@ -0,0 +1,60 @@ +RUN apt-get update && apt-get install -y vim + +ENV JAVA_VERSION 1.8.0_sr5fp6 + +RUN set -eux; \ + ARCH="$(dpkg --print-architecture)"; \ + case "${ARCH}" in \ + amd64|x86_64) \ + ESUM='b5e2824313e62d647c7c7c7c8a6eb8704e445e915da460d379aedd30e6835030'; \ + YML_FILE='sdk/linux/x86_64/index.yml'; \ + ;; \ + i386) \ + ESUM='5e2fd0cafeab9c72e8eb038eb22cf911a18607298a47cd3d4684179610ec364c'; \ + YML_FILE='sdk/linux/i386/index.yml'; \ + ;; \ + ppc64el|ppc64le) \ + ESUM='c2dc7e1cf3db66f7ea0497b48ecb79048a553eaa82d5595a43c9bd7542610b0b'; \ + YML_FILE='sdk/linux/ppc64le/index.yml'; \ + ;; \ + s390) \ + ESUM='5f3f12fefe36502954d69fb1178c2a8bcd88624bc77c4c7bafd9193adcc79398'; \ + YML_FILE='sdk/linux/s390/index.yml'; \ + ;; \ + s390x) \ + ESUM='116fbee3c36425056d6310dd6ef54ce3debdd7150fa57e28caf39f04108b3edc'; \ + YML_FILE='sdk/linux/s390x/index.yml'; \ + ;; \ + *) \ + echo "Unsupported arch: ${ARCH}"; \ + exit 1; \ + ;; \ + esac; \ + BASE_URL="https://public.dhe.ibm.com/ibmdl/export/pub/systems/cloud/runtimes/java/meta/"; \ + wget -q -U UA_IBM_JAVA_Docker -O /tmp/index.yml ${BASE_URL}/${YML_FILE}; \ + JAVA_URL=$(cat /tmp/index.yml | sed -n '/'${JAVA_VERSION}'/{n;p}' | sed -n 's/\s*uri:\s//p' | tr -d '\r'); \ + wget -q -U UA_IBM_JAVA_Docker -O /tmp/ibm-java.bin ${JAVA_URL}; \ + echo "${ESUM} /tmp/ibm-java.bin" | sha256sum -c -; \ + echo "INSTALLER_UI=silent" > /tmp/response.properties; \ + echo "USER_INSTALL_DIR=/root/java" >> /tmp/response.properties; \ + echo "LICENSE_ACCEPTED=TRUE" >> /tmp/response.properties; \ + mkdir -p /root/java; \ + chmod +x /tmp/ibm-java.bin; \ + /tmp/ibm-java.bin -i silent -f /tmp/response.properties; \ + rm -f /tmp/response.properties; \ + rm -f /tmp/index.yml; \ + rm -f /tmp/ibm-java.bin; \ + cd /root/java/jre/lib; \ + rm -rf icc; + +RUN mkdir -p /opt/mvn; \ + MAVEN_VERSION=$(wget -qO- https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/maven-metadata.xml | sed -n 's/\s*\(.*\)<.*>/\1/p'); \ + wget -q -U UA_IBM_JAVA_Docker -O /opt/mvn/apache-maven-${MAVEN_VERSION}-bin.tar.gz https://search.maven.org/remotecontent?filepath=org/apache/maven/apache-maven/${MAVEN_VERSION}/apache-maven-${MAVEN_VERSION}-bin.tar.gz; \ + tar xf /opt/mvn/apache-maven-${MAVEN_VERSION}-bin.tar.gz -C /opt/mvn; \ + mv /opt/mvn/apache-maven-${MAVEN_VERSION} /opt/mvn/apache-maven; \ + rm -f /opt/mvn/apache-maven-${MAVEN_VERSION}-bin.tar.gz; + +RUN mkdir -m 777 -p /config/resources + +ENV JAVA_HOME=/root/java \ + PATH=/root/java/jre/bin:/opt/mvn/apache-maven/bin:$PATH diff --git a/Dockerfile-lang b/Dockerfile-lang new file mode 100644 index 0000000..80223a5 --- /dev/null +++ b/Dockerfile-lang @@ -0,0 +1,13 @@ +FROM websphere-liberty:webProfile7 +MAINTAINER IBM Java engineering at IBM Cloud + +RUN mkdir -m 777 -p /config/resources + +# Upgrade to production license if URL to JAR provided +ARG LICENSE_JAR_URL +RUN \ + if [ $LICENSE_JAR_URL ]; then \ + wget $LICENSE_JAR_URL -O /tmp/license.jar \ + && java -jar /tmp/license.jar -acceptLicense /opt/ibm \ + && rm /tmp/license.jar; \ + fi diff --git a/Dockerfile-tools b/Dockerfile-tools new file mode 100644 index 0000000..d4633e4 --- /dev/null +++ b/Dockerfile-tools @@ -0,0 +1,12 @@ +FROM ibmjava:8-sdk + +MAINTAINER IBM Java engineering at IBM Cloud + +RUN apt-get update && apt-get install -y maven + +ENV PATH /project/target/liberty/wlp/bin/:$PATH + +ARG bx_dev_userid=root +RUN BX_DEV_USERID=$bx_dev_userid +RUN if [ $bx_dev_userid != "root" ]; then useradd -ms /bin/bash $bx_dev_userid; fi + diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..cf9a5f7 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,6 @@ +#!groovy + +@Library('MicroserviceBuilder') _ +microserviceBuilderPipeline { + image = 'stockquote' +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..def51dc --- /dev/null +++ b/README.md @@ -0,0 +1,65 @@ +## Liberty App Accelerator +This project was generated by the [Liberty app accelerator](http://ibm.biz/appaccelerator) + +[![](https://img.shields.io/badge/bluemix-powered-blue.svg)](https://bluemix.net) +[![Platform](https://img.shields.io/badge/platform-java-lightgrey.svg?style=flat)](https://www.ibm.com/developerworks/learn/java/) + +### Table of Contents +* [Summary](#summary) +* [Requirements](#requirements) +* [Configuration](#configuration) +* [Project contents](#project-contents) +* [Run](#run) +* [Notices](#notices) + +### Summary + +The Liberty App Accelerator provides a starting point for creating applications running on [WebSphere Liberty](https://developer.ibm.com/wasdev/). + +To deploy this application to IBM Cloud using a toolchain click the **Create Toolchain** button. +[![Create Toolchain](https://console.ng.bluemix.net/devops/graphics/create_toolchain_button.png)](https://console.ng.bluemix.net/devops/setup/deploy/) + +### Requirements +* [Maven](https://maven.apache.org/install.html) +* Java 8: Any compliant JVM should work. + * [Java 8 JDK from Oracle](http://www.oracle.com/technetwork/java/javase/downloads/index.html) + * [Java 8 JDK from IBM (AIX, Linux, z/OS, IBM i)](http://www.ibm.com/developerworks/java/jdk/), + or [Download a Liberty server package](https://developer.ibm.com/assets/wasdev/#filter/assetTypeFilters=PRODUCT) + that contains the IBM JDK (Windows, Linux) + +### Configuration +The application is configured to provide various technologies and features. These capabilities are provided through dependencies in the pom.xml file and Liberty features enabled in the server config file found in `src/main/liberty/config/server.xml`. + +### Project contents +The context root is set in the `src/main/webapp/WEB-INF/ibm-web-ext.xml` file. The ports are set in the pom.xml file. + +* **MicroProfile** : The [MicroProfile project](http://microprofile.io/) is an open community with the aim of optimizing Enterprise Java for a microservices architecture. MicroProfile will be evolving with guidance from the community. For the complete feature documentation, see the [microProfile-1.2](http://www.ibm.com/support/knowledgecenter/en/SSEQTP_liberty/com.ibm.websphere.wlp.nd.multiplatform.doc/ae/rwlp_feature_microProfile-1.2.html) feature description in IBM Knowledge Center. If you want to share your thoughts you can post straight to the [MicroProfile Google group](https://groups.google.com/forum/#!forum/microprofile). + +The project contains IBM Cloud specific files that are used to deploy the application as part of an IBM Cloud DevOps flow. The `.bluemix` directory contains files used to define the IBM Cloud toolchain and pipeline for your application. The `manifest.yml` file specifies the name of your application in IBM Cloud, the timeout value during deployment and which services to bind to. + +### Run + +To build and run the application: +1. `mvn install` +1. `mvn liberty:run-server` + + +To deploy the application to IBM Cloud: +1. `mvn install -Pbluemix -Dcf.org=[your email address] -Dcf.username=[your username] -Dcf.password=[your password]` + +The application will be deployed to the following url: [http://LibertyProject.mybluemix.net/LibertyProject/] + +Alternatively use the Toolchain button above. + +### Endpoints + +The context root is set in the `src/main/webapp/WEB-INF/ibm-web-ext.xml` file. The ports are set in the pom.xml file. + +### Notices + +This project was generated using: +* generator-java v3.1.0 +* java-common v2.3.0 +* generator-ibm-service-enablement v0.5.0 +* generator-ibm-cloud-enablement v0.0.114 +* generator-liberty v6.0.2 diff --git a/chart/stockquote/Chart.yaml b/chart/stockquote/Chart.yaml new file mode 100644 index 0000000..e05b693 --- /dev/null +++ b/chart/stockquote/Chart.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +description: A Helm chart for Kubernetes +name: stockquote +version: 1.0.0 diff --git a/chart/stockquote/templates/basedeployment.yaml b/chart/stockquote/templates/basedeployment.yaml new file mode 100644 index 0000000..f3081cf --- /dev/null +++ b/chart/stockquote/templates/basedeployment.yaml @@ -0,0 +1,36 @@ +{{ if .Values.base.enabled }} +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: "{{ .Chart.Name }}-basedeployment" + labels: + chart: '{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}' +spec: + replicas: {{ .Values.base.replicaCount }} + revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} + template: + metadata: + labels: + app: "{{ .Chart.Name }}-selector" + version: "base" + spec: + containers: + - name: "{{ .Chart.Name }}" + image: "{{ .Values.image.repository }}:{{ .Values.base.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} +{{ if .Values.istio.enabled }} +{{ else }} + readinessProbe: + httpGet: + path: /stockquote/health + port: 9080 + initialDelaySeconds: 20 +{{ end }} + resources: + requests: + cpu: "{{ .Values.image.resources.requests.cpu }}" + memory: "{{ .Values.image.resources.requests.memory }}" + env: + - name: PORT + value: "{{ .Values.service.servicePort }}" +{{ end }} diff --git a/chart/stockquote/templates/deployment.yaml b/chart/stockquote/templates/deployment.yaml new file mode 100644 index 0000000..c1e2509 --- /dev/null +++ b/chart/stockquote/templates/deployment.yaml @@ -0,0 +1,66 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: "{{ .Chart.Name }}-deployment" + labels: + chart: '{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}' +spec: + replicas: {{ .Values.replicaCount }} + revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} + template: + metadata: + labels: + app: "{{ .Chart.Name }}-selector" + version: "current" + spec: + containers: + - name: "{{ .Chart.Name }}" + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} +{{ if .Values.istio.enabled }} +{{ else }} + readinessProbe: + httpGet: + path: /stockquote/health + port: 9080 + initialDelaySeconds: 20 +{{ end }} + resources: + requests: + cpu: "{{ .Values.image.resources.requests.cpu }}" + memory: "{{ .Values.image.resources.requests.memory }}" + env: + - name: PORT + value: "{{ .Values.service.servicePort }}" + - name: APPLICATION_NAME + value: "{{ .Release.Name }}" + - name: IBM_APM_SERVER_URL + valueFrom: + secretKeyRef: + name: apm-server-config + key: ibm_apm_server_url + optional: true + - name: IBM_APM_KEYFILE + valueFrom: + secretKeyRef: + name: apm-server-config + key: ibm_apm_keyfile + optional: true + - name: IBM_APM_KEYFILE_PASSWORD + valueFrom: + secretKeyRef: + name: apm-server-config + key: ibm_apm_keyfile_password + optional: true + - name: IBM_APM_INGRESS_URL + valueFrom: + secretKeyRef: + name: apm-server-config + key: ibm_apm_ingress_url + optional: true + - name: IBM_APM_ACCESS_TOKEN + valueFrom: + secretKeyRef: + name: apm-server-config + key: ibm_apm_access_token + optional: true diff --git a/chart/stockquote/templates/hpa.yaml b/chart/stockquote/templates/hpa.yaml new file mode 100644 index 0000000..3942f11 --- /dev/null +++ b/chart/stockquote/templates/hpa.yaml @@ -0,0 +1,27 @@ +{{ if .Values.hpa.enabled }} +{{ if and (eq .Capabilities.KubeVersion.Major "1") (ge .Capabilities.KubeVersion.Minor "8") }} +apiVersion: autoscaling/v2beta1 +{{ else }} +apiVersion: autoscaling/v2alpha1 +{{ end }} +kind: HorizontalPodAutoscaler +metadata: + name: "{{ .Chart.Name }}-hpa-policy" + namespace: +spec: + scaleTargetRef: + apiVersion: apps/v1beta1 + kind: Deployment + name: "{{ .Chart.Name }}-deployment" + minReplicas: {{ .Values.hpa.minReplicas }} + maxReplicas: {{ .Values.hpa.maxReplicas }} + metrics: + - type: Resource + resource: + name: cpu + targetAverageUtilization: {{ .Values.hpa.metrics.cpu.targetAverageUtilization }} + - type: Resource + resource: + name: memory + targetAverageUtilization: {{ .Values.hpa.metrics.memory.targetAverageUtilization }} +{{ end }} \ No newline at end of file diff --git a/chart/stockquote/templates/istio.yaml b/chart/stockquote/templates/istio.yaml new file mode 100644 index 0000000..7ee841b --- /dev/null +++ b/chart/stockquote/templates/istio.yaml @@ -0,0 +1,19 @@ +{{ if .Values.istio.enabled }} +apiVersion: config.istio.io/v1alpha2 +kind: RouteRule +metadata: + name: "{{ .Chart.Name }}-default" +spec: + destination: + name: "{{ .Chart.Name }}-service" + precedence: 1 + route: + - labels: + version: "current" + weight: {{ .Values.istio.weight }} +{{ if .Values.base.enabled }} + - labels: + version: "base" + weight: {{ .Values.base.weight }} +{{ end }} +{{ end }} \ No newline at end of file diff --git a/chart/stockquote/templates/service.yaml b/chart/stockquote/templates/service.yaml new file mode 100644 index 0000000..870fb23 --- /dev/null +++ b/chart/stockquote/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: "{{ .Chart.Name }}-service" + labels: + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" +spec: + type: {{ .Values.service.type }} + ports: + - name: http + port: {{ .Values.service.servicePort }} + - name: https + port: {{ .Values.service.servicePortHttps }} + selector: + app: "{{ .Chart.Name }}-selector" \ No newline at end of file diff --git a/chart/stockquote/values.yaml b/chart/stockquote/values.yaml new file mode 100644 index 0000000..5ee3e8f --- /dev/null +++ b/chart/stockquote/values.yaml @@ -0,0 +1,36 @@ +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +replicaCount: 1 +revisionHistoryLimit: 1 +image: + repository: stockquote + tag: v1.0.0 + pullPolicy: IfNotPresent + resources: + requests: + cpu: 200m + memory: 300Mi +service: + name: Node + type: NodePort + servicePort: 9080 + servicePortHttps: 9443 +hpa: + enabled: false + minReplicas: 1 + maxReplicas: 2 + metrics: + cpu: + targetAverageUtilization: 70 + memory: + targetAverageUtilization: 70 +services: +base: + enabled: false + replicaCount: 1 + image: + tag : v0.9.9 + weight: 100 +istio: + enabled: false + weight: 100 diff --git a/cli-config.yml b/cli-config.yml new file mode 100644 index 0000000..05184fd --- /dev/null +++ b/cli-config.yml @@ -0,0 +1,47 @@ +# The IBM version of this configuration +version : 0.0.2 + +# The container name used for the run container +container-name-run : "stockquote" + +# The container name used for the tools container +container-name-tools : "bx-dev-stockquote-tools" + +# The project root in the run container to mount to host-path-run +container-path-run : "/project" +# The project root in the tools container that will be mounted to host-path-tools +container-path-tools : "/project" + +# The name of the Dockerfile used to create the run container +dockerfile-run : "Dockerfile" +# The name of the Dockerfile used to create the tools container +dockerfile-tools : "Dockerfile-tools" + +# The name of image to create from dockerfile-run +image-name-run : "stockquote" +# The name of image to create from dockerfile-tools +image-name-tools : "bx-dev-java-maven-tools" + +# The project root on the host for the run container to mount to container-path-run +host-path-run : "target" + +# The command to build the code and docker image for RUN +build-cmd-run : "mvn install -Dmaven.repo.local=/project/.m2/repository" + +# The command to execute tests for the code in the tools container +test-cmd : "mvn install -Dmaven.repo.local=/project/.m2/repository" + +# The command to build the code and docker image for DEBUG +build-cmd-debug : "mvn install -Dmaven.repo.local=/project/.m2/repository" + +# The command to execute debug of the code in the tools container +debug-cmd : "server debug" + +# The port mappings between the host and the container in the form [host:container] +container-port-map : "9080:9080,9443:9443" + +# The port mappings between the host and the container for the debug port in the form [host:container] +container-port-map-debug : "7777:7777" + +# The relative path to the helm chart used for Kubernetes deployment +chart-path : "chart/stockquote" diff --git a/manifest.yml b/manifest.yml new file mode 100644 index 0000000..21a55aa --- /dev/null +++ b/manifest.yml @@ -0,0 +1,9 @@ +--- +applications: +- instances: 1 + timeout: 180 + name: LibertyProject + buildpack: liberty-for-java + path: ./target/MyProject-1.0-SNAPSHOT.zip + memory: 512M + random-route: true diff --git a/manifests/kube.deploy.yml b/manifests/kube.deploy.yml new file mode 100644 index 0000000..5003a93 --- /dev/null +++ b/manifests/kube.deploy.yml @@ -0,0 +1,44 @@ +apiVersion: v1 +kind: Service +metadata: + name: "stockquote-service" +spec: + # if your cluster supports it, uncomment the following to automatically create + # an external load-balanced IP for the frontend service. + #type: LoadBalancer + type: NodePort + ports: + # the port that this service should serve on + - name: http + port: 9080 + - name: https + port: 9443 + + selector: + app: "stockquote-selector" +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: "stockquote-deployment" +spec: + # this replicas value is default + # modify it according to your case + replicas: 1 + template: + metadata: + labels: + app: "stockquote-selector" + spec: + containers: + - name: stockquote + image: stockquote:latest + readinessProbe: + httpGet: + path: /stockquote/health + port: 9080 + initialDelaySeconds: 20 + # resources: + # requests: + # cpu: 100m + # memory: 100Mi diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..8836fef --- /dev/null +++ b/pom.xml @@ -0,0 +1,393 @@ + + 4.0.0 + + projects + stockquote + 1.0-SNAPSHOT + war + + + net.wasdev.wlp.maven.parent + liberty-maven-app-parent + 2.1 + + + + + oss.sonatype.org-snapshot + http://oss.sonatype.org/content/repositories/snapshots + + false + + + true + + + + + UTF-8 + UTF-8 + 1.8 + 1.8 + + stockquote + 9080 + 9443 + ${app.name} + ${project.build.directory}/${project.artifactId}-${project.version}.zip + usr + + mybluemix.net + https://api.ng.bluemix.net + dev + ${cf.host}.${cf.context}/${warContext} + + + + + + + ${app.name} + + + + + junit + junit + 4.12 + test + + + org.apache.cxf + cxf-rt-rs-client + 3.1.11 + test + + + org.glassfish + javax.json + 1.0.4 + test + + + com.ibm.runtimetools + javametrics-agent + 1.1.0 + provided + + + com.ibm.runtimetools + javametrics-dash + 1.1.0 + provided + war + + + org.eclipse.microprofile + microprofile + 1.2 + provided + pom + + + com.ibm.websphere.appserver.api + com.ibm.websphere.appserver.api.jaxrs20 + 1.0.18 + provided + + + com.ibm.websphere.appserver.api + com.ibm.websphere.appserver.api.json + 1.0.18 + provided + + + javax.ws.rs + javax.ws.rs-api + 2.0.1 + provided + + + + + + + org.apache.maven.plugins + maven-war-plugin + 2.6 + + false + pom.xml + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.18.1 + + + test + default-test + + + **/it/** + + ${project.build.directory}/test-reports/unit + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.0.1 + + + copy-javametrics-dash + package + + copy-dependencies + + + true + ${project.build.directory}/liberty/wlp/usr/servers/defaultServer/dropins + javametrics-dash + + + + copy-javametrics-agent + package + + copy-dependencies + + + true + ${project.build.directory}/liberty/wlp/usr/servers/defaultServer/resources/ + javametrics-agent + + + + copy-javametrics-asm + package + + copy-dependencies + + + ${project.build.directory}/liberty/wlp/usr/servers/defaultServer/resources/asm + org.ow2.asm + asm,asm-commons + + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + 2.18.1 + + + integration-test + integration-test + + integration-test + + + + **/it/** + + + ${testServerHttpPort} + ${warContext} + + + + + verify-results + + verify + + + + + ${project.build.directory}/test-reports/it/failsafe-summary.xml + ${project.build.directory}/test-reports/it + + + + + + + + runnable + + ${project.build.directory}/${app.name}.jar + runnable + + + + bluemix + + + + org.apache.maven.plugins + maven-enforcer-plugin + 1.4.1 + + + enforce-bluemix-credentials + initialize + + enforce + + + + + cf.org + The cf.org property must be + provided with the bluemix + profile. + + + cf.username + The cf.username property + must be provided with the + bluemix profile. + + + cf.password + The cf.password property + must be provided with the + bluemix profile. + + + + + + + + org.cloudfoundry + cf-maven-plugin + 1.1.3 + + ${cf.target} + ${cf.org} + ${cf.space} + ${cf.username} + ${cf.password} + ${cf.host} + 512 + + + + push + package + + push + + + ${package.file} + + + + + + + + + liberty + + + libertyEnv + !microclimate + + + + + + + net.wasdev.wlp.maven.plugins + liberty-maven-plugin + 2.1.1 + true + + false + + + com.ibm.websphere.appserver.runtime + wlp-webProfile7 + 17.0.0.4 + zip + + ${basedir}/src/main/liberty/config/server.xml + ${basedir}/src/main/liberty/config/server.env + ${basedir}/src/main/liberty/config/jvm.options + ${package.file} + ${packaging.type} + + ${testServerHttpPort} + ${testServerHttpsPort} + + project + + + + install-feature + prepare-package + + install-feature + + + + true + + target/liberty-alt-output-dir + + + + + + + + + microclimate + + + libertyEnv + microclimate + + + + ${microclimateOutputDir} + + + + net.wasdev.wlp.maven.plugins + liberty-maven-plugin + 2.1.1 + true + + true + apps + /opt/ibm/wlp + ${project.build.directory}/liberty/wlp/usr + ${basedir}/src/main/liberty/config/server.xml + ${basedir}/src/main/liberty/config/server.env + ${basedir}/src/main/liberty/config/jvm.options + ${package.file} + ${packaging.type} + + ${testServerHttpPort} + ${testServerHttpsPort} + + project + + + + + + + diff --git a/src/main/java/application/rest/HealthEndpoint.java b/src/main/java/application/rest/HealthEndpoint.java new file mode 100644 index 0000000..820c58f --- /dev/null +++ b/src/main/java/application/rest/HealthEndpoint.java @@ -0,0 +1,24 @@ +package application.rest; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Application; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +@Path("health") +public class HealthEndpoint { + + @GET + @Produces(MediaType.APPLICATION_JSON) + public Response healthcheck() { + /* + if (!healthy) { + return Response.status(503).entity("{\"status\":\"DOWN\"}").build(); + } + */ + return Response.ok("{\"status\":\"UP\"}").build(); + } + +} diff --git a/src/main/java/application/rest/JaxrsApplication.java b/src/main/java/application/rest/JaxrsApplication.java new file mode 100644 index 0000000..0c502f9 --- /dev/null +++ b/src/main/java/application/rest/JaxrsApplication.java @@ -0,0 +1,9 @@ +package application.rest; + +import javax.ws.rs.ApplicationPath; +import javax.ws.rs.core.Application; + +@ApplicationPath("/") +public class JaxrsApplication extends Application { + +} diff --git a/src/main/java/application/rest/RootEndpoint.java b/src/main/java/application/rest/RootEndpoint.java new file mode 100644 index 0000000..f6f2f43 --- /dev/null +++ b/src/main/java/application/rest/RootEndpoint.java @@ -0,0 +1,22 @@ +package application.rest; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +@Path("/") +public class RootEndpoint { + + @GET + @Produces(MediaType.APPLICATION_JSON) + public Response listResources(@Context UriInfo uriInfo) { + String healthURL = (uriInfo.getAbsolutePath() + "/health").replaceAll("(? list = new ArrayList<>(); + //return a simple list of strings + list.add("Congratulations, your application is up and running"); + return Response.ok(list.toString()).build(); + } + + +} diff --git a/src/main/liberty/config/jvm.options b/src/main/liberty/config/jvm.options new file mode 100644 index 0000000..836319b --- /dev/null +++ b/src/main/liberty/config/jvm.options @@ -0,0 +1 @@ +-javaagent:resources/javametrics-agent.jar diff --git a/src/main/liberty/config/jvmbx.options b/src/main/liberty/config/jvmbx.options new file mode 100644 index 0000000..4aea859 --- /dev/null +++ b/src/main/liberty/config/jvmbx.options @@ -0,0 +1 @@ +-javaagent:/opt/ibm/wlp/usr/servers/defaultServer/resources/javametrics-agent.jar diff --git a/src/main/liberty/config/server.xml b/src/main/liberty/config/server.xml new file mode 100644 index 0000000..e7ffe3f --- /dev/null +++ b/src/main/liberty/config/server.xml @@ -0,0 +1,17 @@ + + + + microprofile-1.2 + jndi-1.0 + jsp-2.3 + servlet-3.1 + managedBeans-1.0 + websocket-1.1 + + + + + + + diff --git a/src/main/webapp/WEB-INF/beans.xml b/src/main/webapp/WEB-INF/beans.xml new file mode 100644 index 0000000..e69de29 diff --git a/src/main/webapp/WEB-INF/ibm-web-ext.xml b/src/main/webapp/WEB-INF/ibm-web-ext.xml new file mode 100644 index 0000000..eaf6d3f --- /dev/null +++ b/src/main/webapp/WEB-INF/ibm-web-ext.xml @@ -0,0 +1,8 @@ + + + + diff --git a/src/test/java/it/HealthEndpointIT.java b/src/test/java/it/HealthEndpointIT.java new file mode 100644 index 0000000..39f5f5a --- /dev/null +++ b/src/test/java/it/HealthEndpointIT.java @@ -0,0 +1,40 @@ +package it; + +import static org.junit.Assert.assertTrue; + +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.core.Response; + +import org.junit.Test; + +public class HealthEndpointIT { + + private String port = System.getProperty("liberty.test.port"); + private String warContext = System.getProperty("war.context"); + private String endpoint = "/health"; + private String url = "http://localhost:" + port + "/" + warContext + endpoint; + + @Test + public void testEndpoint() throws Exception { + System.out.println("Testing endpoint " + url); + int maxCount = 30; + int responseCode = makeRequest(); + for(int i = 0; (responseCode != 200) && (i < maxCount); i++) { + System.out.println("Response code : " + responseCode + ", retrying ... (" + i + " of " + maxCount + ")"); + Thread.sleep(5000); + responseCode = makeRequest(); + } + assertTrue("Incorrect response code: " + responseCode, responseCode == 200); + } + + private int makeRequest() { + Client client = ClientBuilder.newClient(); + Invocation.Builder invoBuild = client.target(url).request(); + Response response = invoBuild.get(); + int responseCode = response.getStatus(); + response.close(); + return responseCode; + } +}