diff --git a/.gitignore b/.gitignore index 231eace6bba04501e2dbe859ad3cac3ce1bcdbf6..ac5cec03f49d231c3858414751c3aafc01cef7b0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,10 @@ target/ !.mvn/wrapper/maven-wrapper.jar +# ignore local development files +docker-compose.yml +/*.properties + ### STS ### .classpath .factorypath diff --git a/.versionrc b/.versionrc new file mode 100644 index 0000000000000000000000000000000000000000..9a4ab851845efd5d5410a969950a79133dc63195 --- /dev/null +++ b/.versionrc @@ -0,0 +1,7 @@ +{ + "tagPrefix": "", + "commitUrlFormat": "https://transfer.hft-stuttgart.de/gitlab/HFTSoftwareProject/MoDoCoT-Backend/-/commit/{{hash}}", + "compareUrlFormat": "https://transfer.hft-stuttgart.de/gitlab/HFTSoftwareProject/MoDoCoT-Backend/-/compare/{{previousTag}}...{{currentTag}}", + "issueUrlFormat": "https://transfer.hft-stuttgart.de/gitlab/HFTSoftwareProject/MoDoCoT-Backend/-/issues/{{id}}" +} + diff --git a/Dockerfile b/Dockerfile index 4d9f575be5a2759ea13783dbc080b9b9e244b572..91f97b8d4d2308e17779c802b8b5739a18de5c15 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,27 +1,18 @@ #Dockerfile #base image -FROM alpine +FROM openjdk:11-jre-slim -#Proxy -ENV http_proxy 'http://proxy.hft-stuttgart.de:80' -ENV https_proxy 'http://proxy.hft-stuttgart.de:80' - - -#jdk11 -RUN apk add openjdk11 git - -VOLUME /tmp -ADD target/modocot-backend-1.0.2-SNAPSHOT.jar app.jar -RUN sh -c 'touch /app.jar' +ADD target/modocot-backend.jar app.jar # Prepare environment. # Create needed folders -RUN mkdir /home/modocot && \ - mkdir /home/modocot/libs +RUN mkdir /modocot && \ + mkdir /modocot/data && \ + mkdir /modocot/config + +VOLUME /modocot/data -# Download needed libs for compilation -ADD https://repo1.maven.org/maven2/junit/junit/4.13/junit-4.13.jar /home/modocot/libs/junit.jar -ADD https://repo1.maven.org/maven2/org/hamcrest/hamcrest-core/2.2/hamcrest-core-2.2.jar /home/modocot/libs/hamcrest.jar +env SPRING_CONFIG_ADDITIONAL_LOCATION "file:/home/modocot/config/" -ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-Dspring.profiles.active=server","-jar","/app.jar"] +ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] diff --git a/Jenkinsfile b/Jenkinsfile index 76219504679a0e83c7cede3af3965f5d442c4630..43d4e95746d198e268f0fd8a1cf572465c440d89 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,49 +1,73 @@ + +def version = "" + pipeline { + environment { registry = "hftstuttgart/modocot-backend" registryCredential = 'Dockerhub' dockerImage = '' } + agent any + tools { jdk 'Java11' maven 'Maven_Home' } + stages { - stage('Checkout') { + stage('prepare') { steps { - echo 'Checkout Repository..' - git branch: 'master', - url: 'https://transfer.hft-stuttgart.de/gitlab/HFTSoftwareProject/MoDoCoT-Backend.git' + checkout ([ + $class: 'GitSCM', + branches: scm.branches, + extensions: scm.extensions + [[$class: 'CloneOption', noTags: false, reference: '', shallow: false]], + userRemoteConfigs: scm.userRemoteConfigs + ]) + script { + version = sh(script: 'git describe --tags --always', returnStdout: true).trim() + echo sh(script: 'env|sort', returnStdout: true) + } + } } - stage('Build') { + + stage('compile') { steps { - echo 'Maven Build..' - sh 'mvn clean package -DskipTests=false' + sh 'mvn clean package' } } - stage('Docker Build..') { - steps{ + + stage('build Docker image') { + steps { script { - dockerImage = docker.build registry + ":latest" + dockerImage = docker.build registry } } } - stage('Push to Dockerhub..') { - steps{ - script { - docker.withRegistry( '', registryCredential ) { - dockerImage.push() - } - } + + stage('push development image') { + steps { + script { + docker.withRegistry( '', registryCredential ) { + dockerImage.push("${env.GIT_BRANCH}") } } + } + } - stage('ShellScript') { + stage('release') { + when { + expression { version ==~ /[0-9]+.[0-9]+.[0-9]+/ } + } steps { - echo 'Exectue Shellscript..' - sh 'chmod 744 restart_modocot_backend.sh && ./restart_modocot_backend.sh' + script { + docker.withRegistry( '', registryCredential ) { + dockerImage.push("latest") + dockerImage.push("${version}") + } + } } } } diff --git a/development-templates/custom.yml b/development-templates/custom.yml new file mode 100644 index 0000000000000000000000000000000000000000..6da28d90f0ea07fbef4400ac005f5d3eda505ead --- /dev/null +++ b/development-templates/custom.yml @@ -0,0 +1,14 @@ +version: '3' + +services: + backend: + build: + context: . + environment: + - DOCKER_HOST=unix:///var/run/docker.sock + container_name: modocot-devel-backend + ports: + - 127.0.0.1:8080:8080 + volumes: + - '/var/run/docker.sock:/var/run/docker.sock' + - '/tmp/modocot-tests:/tmp/modocot-tests' diff --git a/mvnw b/mvnw deleted file mode 100644 index a1ba1bf554bb63c401f90c6a472c21470ed4e164..0000000000000000000000000000000000000000 --- a/mvnw +++ /dev/null @@ -1,233 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven2 Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # - # Look for the Apple JDKs first to preserve the existing behaviour, and then look - # for the new JDKs provided by Oracle. - # - if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then - # - # Apple JDKs - # - export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home - fi - - if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then - # - # Apple JDKs - # - export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home - fi - - if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then - # - # Oracle JDKs - # - export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home - fi - - if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then - # - # Apple JDKs - # - export JAVA_HOME=`/usr/libexec/java_home` - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Migwn, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" - # TODO classpath? -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`which java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` -fi - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - local basedir=$(pwd) - local wdir=$(pwd) - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - wdir=$(cd "$wdir/.."; pwd) - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)} -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# Provide a "standardized" way to retrieve the CLI args that will -# work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" -export MAVEN_CMD_LINE_ARGS - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} "$@" diff --git a/mvnw.cmd b/mvnw.cmd deleted file mode 100644 index 2b934e89dd1d9872b747047fa696477264a86ad8..0000000000000000000000000000000000000000 --- a/mvnw.cmd +++ /dev/null @@ -1,145 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM http://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven2 Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -set MAVEN_CMD_LINE_ARGS=%* - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" - -set WRAPPER_JAR="".\.mvn\wrapper\maven-wrapper.jar"" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS% -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% \ No newline at end of file diff --git a/pom.xml b/pom.xml index 61c952f736f1ecc364477da363aea1dcdb42ed3c..347604f69e91df65f64f45fe00664973a297cfec 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ de.hftstuttgart modocot-backend - 1.0.2-SNAPSHOT + 2.0.0 jar Modocot-Backend @@ -20,34 +20,18 @@ UTF-8 UTF-8 11 - - - hftstuttgart - - true - com.github.zeripath - java-gitea-api - 1.7.4 - - - com.fasterxml.jackson.dataformat - jackson-dataformat-xml - 2.9.8 - - - - org.json - json - 20180130 + com.github.docker-java + docker-java-core + 3.2.6 - org.freemarker - freemarker - 2.3.30 + com.github.docker-java + docker-java-transport-httpclient5 + 3.2.6 org.springframework.boot @@ -58,33 +42,17 @@ spring-boot-starter-test test + - junit - junit - 4.13 + org.eclipse.jgit + org.eclipse.jgit + 5.7.0.202003110725-r log4j log4j 1.2.17 - - com.google.code.gson - gson - 2.8.6 - - - - com.google.guava - guava - 29.0-jre - - - - org.eclipse.jgit - org.eclipse.jgit - 5.7.0.202003110725-r - org.apache.logging.log4j log4j-api @@ -98,19 +66,12 @@ + ${project.artifactId} org.springframework.boot spring-boot-maven-plugin - - org.apache.maven.plugins - maven-surefire-plugin - 3.0.0-M3 - - ${skipTests} - - - \ No newline at end of file + diff --git a/restart_modocot_backend.sh b/restart_modocot_backend.sh deleted file mode 100644 index 162d6a72a5bbd5e109381a1f54cd8164996bafb9..0000000000000000000000000000000000000000 --- a/restart_modocot_backend.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -# Stop the running backend -docker stop modocot-backend - -# Delete the existing container -docker rm modocot-backend - -# Pull the new version from DockerHub -docker pull hftstuttgart/modocot-backend - -# Build the container and start it -docker run --name modocot-backend -p 8888:8081 hftstuttgart/modocot-backend:latest & diff --git a/src/log4j2.xml b/src/log4j2.xml deleted file mode 100644 index 1b0e59d095a41159edc4b57a9f21c034b306a1a5..0000000000000000000000000000000000000000 --- a/src/log4j2.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/java/de/hftstuttgart/ModocotBackendApplication.java b/src/main/java/de/hftstuttgart/ModocotBackendApplication.java index b20a5c0de6aa7f45e0029d211d5a008f19bd38c8..fcbbfd966ae9010dec60818575161c7ecaa29585 100644 --- a/src/main/java/de/hftstuttgart/ModocotBackendApplication.java +++ b/src/main/java/de/hftstuttgart/ModocotBackendApplication.java @@ -1,86 +1,13 @@ package de.hftstuttgart; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.SerializerProvider; -import org.junit.ComparisonFailure; -import org.junit.runner.notification.Failure; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Primary; -import org.springframework.context.annotation.PropertySource; -import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; - -import javax.tools.Diagnostic; -import javax.tools.JavaFileObject; -import java.io.File; -import java.io.IOException; -import java.net.URI; -import java.util.Locale; @SpringBootApplication -@PropertySource("classpath:git-credentials.properties") public class ModocotBackendApplication { public static void main(String[] args) { SpringApplication.run(ModocotBackendApplication.class, args); } - /** - * Configuration for the Jackson JSON serializer - */ - @Bean - @Primary - public Jackson2ObjectMapperBuilder jacksonConfiguration() { - Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); - builder.indentOutput(true) - .serializationInclusion(JsonInclude.Include.NON_NULL) // Don’t include null values in the JSON - .serializerByType(Diagnostic.class, new DiagnosticSerializer()) - .serializerByType(Failure.class, new FailureSerializer()); - return builder; - } - - /** - * Custom serializer for the {@link Diagnostic} class used by Jackson - */ - private class DiagnosticSerializer extends JsonSerializer { - @Override - public void serialize(Diagnostic diagnostic, JsonGenerator gen, SerializerProvider serializerProvider) throws IOException { - gen.writeStartObject(); - gen.writeStringField("code", diagnostic.getCode()); - gen.writeNumberField("columnNumber", diagnostic.getColumnNumber()); - gen.writeStringField("kind", diagnostic.getKind().toString()); - gen.writeNumberField("lineNumber", diagnostic.getLineNumber()); - gen.writeStringField("message", diagnostic.getMessage(Locale.ENGLISH)); - gen.writeNumberField("position", diagnostic.getPosition()); - - URI uri = ((JavaFileObject) diagnostic.getSource()).toUri(); - gen.writeStringField("javaFileName", new File(uri).getName()); - gen.writeNumberField("startPosition", diagnostic.getStartPosition()); - gen.writeNumberField("endPosition", diagnostic.getEndPosition()); - gen.writeEndObject(); - } - } - - /** - * Custom serializer for the {@link Failure} class used by Jackson - */ - private class FailureSerializer extends JsonSerializer { - @Override - public void serialize(Failure failure, JsonGenerator gen, SerializerProvider serializerProvider) throws IOException { - gen.writeStartObject(); - gen.writeStringField("testHeader", failure.getTestHeader()); - gen.writeStringField("message", failure.getMessage()); - gen.writeStringField("trace", failure.getTrace()); - - Throwable exception = failure.getException(); - if (exception instanceof ComparisonFailure) { - gen.writeStringField("expected", ((ComparisonFailure) exception).getExpected()); - gen.writeStringField("actual", ((ComparisonFailure) exception).getActual()); - } - gen.writeEndObject(); - } - } } diff --git a/src/main/java/de/hftstuttgart/config/ModocotProperties.java b/src/main/java/de/hftstuttgart/config/ModocotProperties.java deleted file mode 100644 index 5ab5f6dd7f60da2586fceb7ab5eb77c8b0613787..0000000000000000000000000000000000000000 --- a/src/main/java/de/hftstuttgart/config/ModocotProperties.java +++ /dev/null @@ -1,88 +0,0 @@ -package de.hftstuttgart.config; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class ModocotProperties { - - private final String dockerHostIp; - private final String jenkinsApiToken; - private final String jenkinsBaseUrl; - private final String modocotParentDirectory; - private final String modocotAssignmentFolderPrefix; - private final String modocotTestFolderName; - private final String gitTeaBasePath; - private final String gitTeaUsername; - private final String gitTeaPassword; - private final String gitTeaDefaultCommitMessage; - private final String gitTeaOrigin; - - public ModocotProperties(@Value("${docker.hostIp}") String dockerHostIp, - @Value("${jenkins.api.token}") String jenkinsApiToken, - @Value("${jenkins.url}") String jenkinsBaseUrl, - @Value("${modocot.dir.parent}") String modocotParentDirectory, - @Value("${modocot.dir.assignment.prefix}") String modocotAssignmentFolderPrefix, - @Value("${modocot.dir.test.folder.name}") String modocotTestFolderName, - @Value("${gitTea.basePath}") String gitTeaBasePath, - @Value("${gitTea.username}") String gitTeaUsername, - @Value("${gitTea.password}") String gitTeaPassword, - @Value("${gitTea.defaultCommitMessage}") String gitTeaDefaultCommitMessage, - @Value("${gitTea.defaultOrigin}") String gitTeaOrigin) { - this.dockerHostIp = dockerHostIp; - this.jenkinsApiToken = jenkinsApiToken; - this.jenkinsBaseUrl = jenkinsBaseUrl; - this.modocotParentDirectory = modocotParentDirectory; - this.modocotAssignmentFolderPrefix = modocotAssignmentFolderPrefix; - this.modocotTestFolderName = modocotTestFolderName; - this.gitTeaBasePath = gitTeaBasePath; - this.gitTeaUsername = gitTeaUsername; - this.gitTeaPassword = gitTeaPassword; - this.gitTeaDefaultCommitMessage = gitTeaDefaultCommitMessage; - this.gitTeaOrigin = gitTeaOrigin; - } - - public String getDockerHostIp() { - return dockerHostIp; - } - - public String getJenkinsApiToken() { - return jenkinsApiToken; - } - - public String getJenkinsBaseUrl() { - return jenkinsBaseUrl; - } - - public String getModocotParentDirectory() { - return modocotParentDirectory; - } - - public String getModocotAssignmentFolderPrefix() { - return modocotAssignmentFolderPrefix; - } - - public String getModocotTestFolderName() { - return modocotTestFolderName; - } - - public String getGitTeaBasePath() { - return gitTeaBasePath; - } - - public String getGitTeaUsername() { - return gitTeaUsername; - } - - public String getGitTeaPassword() { - return gitTeaPassword; - } - - public String getGitTeaDefaultCommitMessage() { - return gitTeaDefaultCommitMessage; - } - - public String getGitTeaOrigin() { - return gitTeaOrigin; - } -} diff --git a/src/main/java/de/hftstuttgart/config/ProxySetup.java b/src/main/java/de/hftstuttgart/config/ProxySetup.java new file mode 100644 index 0000000000000000000000000000000000000000..3cd0b81fea749c257a1eb3a0fec31aa33e00ce2d --- /dev/null +++ b/src/main/java/de/hftstuttgart/config/ProxySetup.java @@ -0,0 +1,81 @@ +package de.hftstuttgart.config; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; + +import java.io.IOException; +import java.net.*; +import java.util.*; +import java.util.stream.Collectors; + +@Configuration +/** + * Configures Proxy once on startup + */ +public class ProxySetup extends ProxySelector +{ + private static final Logger LOG = LogManager.getLogger(ProxySetup.class); + + List noProxy; + List setProxy; + Set noProxyHosts; + + public ProxySetup(Environment env) { + + String ignoredHostNames = env.getProperty("proxy.ignoredHostNames"); + if (Objects.isNull(ignoredHostNames)) { + ignoredHostNames = ""; + } + + String proxy = env.getProperty("proxy"); + + LOG.info("Configuring Proxy"); + noProxy = Collections.singletonList(Proxy.NO_PROXY); + + if (Objects.nonNull(proxy)) { + String[] proxyValues = proxy.split(":"); + Proxy p = new Proxy( + Proxy.Type.HTTP, + new InetSocketAddress(proxyValues[0], Integer.parseInt(proxyValues[1]))); + setProxy = Collections.singletonList(p); + + LOG.info(String.format("set proxy: %s", p.address().toString())); + } + + noProxyHosts = Arrays.stream(ignoredHostNames.split(",")) + .map(String::toLowerCase) + .collect(Collectors.toCollection(HashSet::new)); + + LOG.info(String.format("Hosts to be ignored: %s", noProxyHosts)); + + ProxySelector.setDefault(this); + } + + @Override + public List select(URI uri) { + + LOG.debug(String.format("Proxy selection for URI: %s", uri.getHost())); + + // No proxy for given hosts + if (noProxyHosts.contains(uri.getHost().toLowerCase())) { + LOG.debug(String.format("Proxy disabled for host %s", uri.getHost())); + return noProxy; + } + + // no proxy if no proxy was set + if (Objects.nonNull(setProxy)) { + LOG.debug(String.format("Proxy used for host %s", uri.getHost())); + return setProxy; + } + + LOG.debug("No proxy configured to choose from"); + return noProxy; + } + + @Override + public void connectFailed(URI uri, SocketAddress socketAddress, IOException e) { + LOG.error(String.format("connection to %s failed with %s", uri.getHost(), e.getMessage())); + } +} diff --git a/src/main/java/de/hftstuttgart/dockertests/app.war b/src/main/java/de/hftstuttgart/dockertests/app.war deleted file mode 100644 index 8142e006e4d4c144223c7a058ec9c5202cdb6a6f..0000000000000000000000000000000000000000 Binary files a/src/main/java/de/hftstuttgart/dockertests/app.war and /dev/null differ diff --git a/src/main/java/de/hftstuttgart/dockertests/app/Hello_World.class b/src/main/java/de/hftstuttgart/dockertests/app/Hello_World.class deleted file mode 100644 index d2de4f5b61a5efb0ffa9bcd9f39c4b0b28816d52..0000000000000000000000000000000000000000 Binary files a/src/main/java/de/hftstuttgart/dockertests/app/Hello_World.class and /dev/null differ diff --git a/src/main/java/de/hftstuttgart/dockertests/app/Hello_World.class.zip b/src/main/java/de/hftstuttgart/dockertests/app/Hello_World.class.zip deleted file mode 100644 index bd81b4fdb651acff5185a34fed6b0adba6ec7a2c..0000000000000000000000000000000000000000 Binary files a/src/main/java/de/hftstuttgart/dockertests/app/Hello_World.class.zip and /dev/null differ diff --git a/src/main/java/de/hftstuttgart/dockertests/app/Hello_World_Test.class b/src/main/java/de/hftstuttgart/dockertests/app/Hello_World_Test.class deleted file mode 100644 index 5d7134d4fa092dcad011060c66b160f14ba62e7b..0000000000000000000000000000000000000000 Binary files a/src/main/java/de/hftstuttgart/dockertests/app/Hello_World_Test.class and /dev/null differ diff --git a/src/main/java/de/hftstuttgart/dockertests/app/Hello_World_Test.class.zip b/src/main/java/de/hftstuttgart/dockertests/app/Hello_World_Test.class.zip deleted file mode 100644 index af6da35507cbaec57aa20dab6efda575a1011829..0000000000000000000000000000000000000000 Binary files a/src/main/java/de/hftstuttgart/dockertests/app/Hello_World_Test.class.zip and /dev/null differ diff --git a/src/main/java/de/hftstuttgart/dockertests/app/META-INF/MANIFEST.MF b/src/main/java/de/hftstuttgart/dockertests/app/META-INF/MANIFEST.MF deleted file mode 100644 index 87e05e14230f56aad4347cc2e5cb21ece04dc9de..0000000000000000000000000000000000000000 --- a/src/main/java/de/hftstuttgart/dockertests/app/META-INF/MANIFEST.MF +++ /dev/null @@ -1,3 +0,0 @@ -Manifest-Version: 1.0 -Created-By: 11.0.7 (Oracle Corporation) - diff --git a/src/main/java/de/hftstuttgart/dockertests/app/META-INF/war-tracker b/src/main/java/de/hftstuttgart/dockertests/app/META-INF/war-tracker deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/src/main/java/de/hftstuttgart/dockertests/app/index.html b/src/main/java/de/hftstuttgart/dockertests/app/index.html deleted file mode 100644 index 3c34854be75e7d8761030664528335cf2b1d895c..0000000000000000000000000000000000000000 --- a/src/main/java/de/hftstuttgart/dockertests/app/index.html +++ /dev/null @@ -1,9 +0,0 @@ - - - - Example - - -

Hello World

- - \ No newline at end of file diff --git a/src/main/java/de/hftstuttgart/dockertests/app/junit-platform-console-standalone-1.6.2.jar b/src/main/java/de/hftstuttgart/dockertests/app/junit-platform-console-standalone-1.6.2.jar deleted file mode 100644 index b47f57abad34340d62dff9340533e4702adb1ddc..0000000000000000000000000000000000000000 Binary files a/src/main/java/de/hftstuttgart/dockertests/app/junit-platform-console-standalone-1.6.2.jar and /dev/null differ diff --git a/src/main/java/de/hftstuttgart/dockertests/filetest.txt b/src/main/java/de/hftstuttgart/dockertests/filetest.txt deleted file mode 100644 index 4d8bb0e66e3065c8f5832cbba614cc329eebe078..0000000000000000000000000000000000000000 --- a/src/main/java/de/hftstuttgart/dockertests/filetest.txt +++ /dev/null @@ -1 +0,0 @@ -Bind mount persistance data through bind Mount diff --git a/src/main/java/de/hftstuttgart/exceptions/CorruptedZipFileException.java b/src/main/java/de/hftstuttgart/exceptions/CorruptedZipFileException.java deleted file mode 100644 index 991a66e7ab81bffad3b60dd7df68a8ebb7c30422..0000000000000000000000000000000000000000 --- a/src/main/java/de/hftstuttgart/exceptions/CorruptedZipFileException.java +++ /dev/null @@ -1,14 +0,0 @@ -package de.hftstuttgart.exceptions; - -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ResponseStatus; - -/** - * Created by Marcel Bochtler on 28.11.16. - */ -@ResponseStatus(HttpStatus.BAD_REQUEST) -public class CorruptedZipFileException extends RuntimeException { - public CorruptedZipFileException(String s) { - super(s); - } -} diff --git a/src/main/java/de/hftstuttgart/exceptions/NoZipFileException.java b/src/main/java/de/hftstuttgart/exceptions/NoZipFileException.java deleted file mode 100644 index b3e5aa29e43f5ae3ab1e839ed96a9b64328f686d..0000000000000000000000000000000000000000 --- a/src/main/java/de/hftstuttgart/exceptions/NoZipFileException.java +++ /dev/null @@ -1,14 +0,0 @@ -package de.hftstuttgart.exceptions; - -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ResponseStatus; - -/** - * Created by Marcel Bochtler on 29.11.16. - */ -@ResponseStatus(HttpStatus.BAD_REQUEST) -public class NoZipFileException extends RuntimeException { - public NoZipFileException(String message) { - super(message); - } -} diff --git a/src/main/java/de/hftstuttgart/models/JenkinsJobData.java b/src/main/java/de/hftstuttgart/models/JenkinsJobData.java deleted file mode 100644 index 9a641737ae0f20677d4bd7851c9121c25840a37c..0000000000000000000000000000000000000000 --- a/src/main/java/de/hftstuttgart/models/JenkinsJobData.java +++ /dev/null @@ -1,66 +0,0 @@ -package de.hftstuttgart.models; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; -import de.hftstuttgart.utils.BuildState; - -import java.util.List; - -@JsonInclude -public class JenkinsJobData { - - public JenkinsJobData() { - } - - public String getClassData() { - return classData; - } - - public List getJobs() { - return jobs; - } - - @JsonProperty("_class") - private String classData; - - private List jobs; - - @JsonProperty("jobs") - public void unpackingJobs(List jobs) { - this.jobs = jobs; - } - - public static class Job { - - @JsonProperty("_class") - private String jobClassData; - @JsonProperty("name") - private String name; - @JsonProperty("color") - private BuildState color; - - public String getJobClassData() { - return jobClassData; - } - - public void setJobClassData(String jobClassData) { - this.jobClassData = jobClassData; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public BuildState getColor() { - return color; - } - - public void setColor(BuildState color) { - this.color = color; - } - } -} diff --git a/src/main/java/de/hftstuttgart/models/LegacyMoodleResult.java b/src/main/java/de/hftstuttgart/models/LegacyMoodleResult.java new file mode 100644 index 0000000000000000000000000000000000000000..dbe0bb5353ae8595decd302bf07c182a3e49f9d2 --- /dev/null +++ b/src/main/java/de/hftstuttgart/models/LegacyMoodleResult.java @@ -0,0 +1,72 @@ +package de.hftstuttgart.models; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +public class LegacyMoodleResult { + + public List testResults; + public List compilationErrors; + + public static LegacyMoodleResult convertToModdleResult(ModocotResultSummary summary) { + LegacyMoodleTestResult tests = new LegacyMoodleTestResult(); + tests.failureCount = summary.failureCount; + tests.testCount = summary.testCount; + tests.successfulTests = summary.successes.stream() + .map(s -> s.name) + .collect(Collectors.toList()); + tests.testFailures = summary.failures.stream() + .map(f -> { + LegacyMoodleTestFailure failure = new LegacyMoodleTestFailure(); + failure.testHeader = f.name; + failure.message = f.failureReason; + failure.trace = f.stacktrace; + + return failure; + }) + .collect(Collectors.toList()); + + List compilationErrors; + compilationErrors = summary.compilationErrors.stream() + .map(f -> { + LegacyMoodleCompilationError cError = new LegacyMoodleCompilationError(); + cError.javaFileName = f.name; + cError.message = f.failureReason; + cError.lineNumber = f.lineNumber; + cError.columnNumber = f.columnNumber; + cError.position = f.position; + + return cError; + }) + .collect(Collectors.toList()); + + LegacyMoodleResult result = new LegacyMoodleResult(); + result.testResults = Collections.singletonList(tests); + result.compilationErrors = compilationErrors; + + return result; + } + + private static class LegacyMoodleTestResult { + public String testName = "UnitTests"; + public int testCount; + public int failureCount; + public List successfulTests; + public List testFailures; + } + + private static class LegacyMoodleTestFailure { + public String testHeader; + public String message; + public String trace; + } + + private static class LegacyMoodleCompilationError { + public String message; + public String javaFileName; + public int lineNumber; + public int columnNumber; + public int position; + } +} diff --git a/src/main/java/de/hftstuttgart/models/ModocotResult.java b/src/main/java/de/hftstuttgart/models/ModocotResult.java new file mode 100644 index 0000000000000000000000000000000000000000..a211b7e45a2e3941e0de2df4962c9798af90bed3 --- /dev/null +++ b/src/main/java/de/hftstuttgart/models/ModocotResult.java @@ -0,0 +1,22 @@ +package de.hftstuttgart.models; + +public class ModocotResult +{ + public String name; + public int state; + + public String failureType; + public String failureReason; + public String stacktrace; + + public int columnNumber; + public int lineNumber; + public int position; + + public static enum State + { + SUCCESS, + FAILURE, + UNKNOWN + } +} diff --git a/src/main/java/de/hftstuttgart/models/ModocotResultSummary.java b/src/main/java/de/hftstuttgart/models/ModocotResultSummary.java new file mode 100644 index 0000000000000000000000000000000000000000..96f15f6e0364229a0de763f9fd041303a56f7246 --- /dev/null +++ b/src/main/java/de/hftstuttgart/models/ModocotResultSummary.java @@ -0,0 +1,16 @@ +package de.hftstuttgart.models; + +import java.util.Set; + +public class ModocotResultSummary +{ + public long timestamp; + public int testCount; + public int failureCount; + public int successCount; + public String globalStacktrace; + + public Set successes; + public Set failures; + public Set compilationErrors; +} diff --git a/src/main/java/de/hftstuttgart/models/TestResult.java b/src/main/java/de/hftstuttgart/models/TestResult.java deleted file mode 100644 index 27c8cfbaeac1629f97506486d309436937ac2941..0000000000000000000000000000000000000000 --- a/src/main/java/de/hftstuttgart/models/TestResult.java +++ /dev/null @@ -1,64 +0,0 @@ -package de.hftstuttgart.models; - -import org.junit.runner.notification.Failure; - -import java.util.List; - -public class TestResult { - - private String testName; - private int testCount; - private int failureCount; - private List successfulTests; - private List testFailures; - - public String getTestName() { - return testName; - } - - public void setTestName(String testName) { - this.testName = testName; - } - - public int getTestCount() { - return testCount; - } - - public void setTestCount(int testCount) { - this.testCount = testCount; - } - - public int getFailureCount() { - return failureCount; - } - - public void setFailureCount(int failureCount) { - this.failureCount = failureCount; - } - - public List getSuccessfulTests() { - return successfulTests; - } - - public void setSuccessfulTests(List successfulTests) { - this.successfulTests = successfulTests; - } - - public List getTestFailures() { - return testFailures; - } - - public void setTestFailures(List testFailures) { - this.testFailures = testFailures; - } - - @Override - public String toString() { - return "TestResult{" + - "testName='" + testName + '\'' + - ", testCount=" + testCount + - ", failureCount=" + failureCount + - ", testFailures=" + testFailures + - '}'; - } -} diff --git a/src/main/java/de/hftstuttgart/models/UserResult.java b/src/main/java/de/hftstuttgart/models/UserResult.java deleted file mode 100644 index 3c0d696b1b35c5689660ab9fb23e0c4f7ba07fa8..0000000000000000000000000000000000000000 --- a/src/main/java/de/hftstuttgart/models/UserResult.java +++ /dev/null @@ -1,34 +0,0 @@ -package de.hftstuttgart.models; - -import javax.tools.Diagnostic; -import java.util.List; - -public class UserResult { - - private List testResults; - private List compilationErrors; - - public UserResult(List testResults) { - - this.testResults = testResults; - } - - - public List getTestResults() { - return testResults; - } - - public void setTestResults(List testResults) { - this.testResults = testResults; - } - - public List getCompilationErrors() { - return compilationErrors; - } - - public void setCompilationErrors(List compilationErrors) { - this.compilationErrors = compilationErrors; - } - - -} diff --git a/src/main/java/de/hftstuttgart/rest/v1/jenkins/RestAPIController.java b/src/main/java/de/hftstuttgart/rest/v1/jenkins/RestAPIController.java deleted file mode 100644 index 3bfa00331f8c7b4d66057a2302200099fc5fb97c..0000000000000000000000000000000000000000 --- a/src/main/java/de/hftstuttgart/rest/v1/jenkins/RestAPIController.java +++ /dev/null @@ -1,30 +0,0 @@ -package de.hftstuttgart.rest.v1.jenkins; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -import java.util.HashMap; -import java.util.Map; - -@RestController -public class RestAPIController { - - private static final Logger LOG = LogManager.getLogger(RestAPIController.class); - - public static final Map JOB_MAP = new HashMap<>(); - - @PostMapping("/v1/uploaduserresults") - public void uploadsResults(@RequestParam("jobID") String jobId, @RequestBody String userResult) { - LOG.info("result: " + userResult); - if (!JOB_MAP.containsKey(jobId)) { - String keys = String.join(", ", JOB_MAP.keySet()); - throw new IllegalArgumentException( - String.format("Key %s does not exist in JOB_MAP, available Keys: [%s]", jobId, keys)); - } - JOB_MAP.put(jobId, userResult); - } -} \ No newline at end of file diff --git a/src/main/java/de/hftstuttgart/rest/v1/task/TaskUpload.java b/src/main/java/de/hftstuttgart/rest/v1/task/TaskUpload.java index 6d402e65c3351d41a017299b5528add5a0109672..83d70b326fab2814bd4ba9e8c78152f89856956d 100644 --- a/src/main/java/de/hftstuttgart/rest/v1/task/TaskUpload.java +++ b/src/main/java/de/hftstuttgart/rest/v1/task/TaskUpload.java @@ -1,15 +1,17 @@ package de.hftstuttgart.rest.v1.task; -import de.hftstuttgart.config.ModocotProperties; -import de.hftstuttgart.rest.v1.jenkins.RestAPIController; -import de.hftstuttgart.utils.BackendUtil; -import de.hftstuttgart.utils.BuildState; -import de.hftstuttgart.utils.GitTeaUtil; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.dockerjava.api.model.Bind; +import com.github.dockerjava.api.model.Volume; +import de.hftstuttgart.models.LegacyMoodleResult; +import de.hftstuttgart.models.ModocotResultSummary; +import de.hftstuttgart.rest.v1.unittest.UnitTestUpload; +import de.hftstuttgart.utils.DockerUtil; +import de.hftstuttgart.utils.FileUtil; import de.hftstuttgart.utils.JGitUtil; -import de.hftstuttgart.utils.TaskUploadUtils; -import de.hftstuttgart.utils.UnzipUtil; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.springframework.core.env.Environment; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; @@ -17,10 +19,12 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import javax.servlet.annotation.MultipartConfig; -import java.io.File; -import java.io.IOException; -import java.util.List; -import java.util.UUID; +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * Rest controller for everything related to the TASK files @@ -31,98 +35,173 @@ import java.util.UUID; public class TaskUpload { private static final Logger LOG = LogManager.getLogger(TaskUpload.class); - private final ModocotProperties modocotProperties; - private final TaskUploadUtils taskUploadUtils; private final JGitUtil jGitUtil; + private final DockerUtil dockerUtil; private final String assignmentBasePath; - private final GitTeaUtil gitTeaUtil; + private final Path testTmpPathHost; + private final Path testTmpPathModocot; - public TaskUpload(ModocotProperties modocotProperties, - TaskUploadUtils taskUploadUtils, - JGitUtil jGitUtil, - GitTeaUtil gitTeaUtil) { - this.modocotProperties = modocotProperties; - this.taskUploadUtils = taskUploadUtils; + public TaskUpload( + Environment env, + JGitUtil jGitUtil, + DockerUtil dockerUtil + ) { this.jGitUtil = jGitUtil; - this.gitTeaUtil = gitTeaUtil; - this.assignmentBasePath = - this.modocotProperties.getModocotParentDirectory() - + File.separator - + this.modocotProperties.getModocotAssignmentFolderPrefix(); - } - - @RequestMapping(method = RequestMethod.POST) - public String uploadAndTestFile(@RequestParam("taskFile") MultipartFile taskFileRef, - @RequestParam("assignmentId") String assignmentId) throws IOException, InterruptedException { - String jobId = assignmentId + "_" + UUID.randomUUID(); - String subFolderPath = this.assignmentBasePath + assignmentId; - - LOG.info("subFolderPath: " + subFolderPath); - File workDirectory = new File(subFolderPath); - workDirectory.mkdirs(); - - LOG.info("created new File"); - File file = new File(subFolderPath, String.valueOf(UUID.randomUUID())); + this.dockerUtil = dockerUtil; - taskFileRef.transferTo(file); - List unzippedFiles = UnzipUtil.unzip(file); + // set base path for assignments to be stored + Path p = Paths.get( + env.getProperty("modocot.dir"), + env.getProperty("modocot.dir.test.folder.name")); + this.assignmentBasePath = p.toAbsolutePath().toString(); - if (file.exists()) file.delete(); - - startFileRead(assignmentId, subFolderPath, unzippedFiles); - - BuildState buildState = this.taskUploadUtils.startTask(jobId, subFolderPath); + // set path of temporary directory on host and inside our container + this.testTmpPathHost = Paths.get(env.getProperty("host.tests.tmp.dir")); + this.testTmpPathModocot = Paths.get(env.getProperty("modocot.tests.tmp.dir")); + } - if (buildState != BuildState.BLUE) { - String jenkinsError = this.taskUploadUtils.getJenkinsConsoleOutput(jobId); - LOG.error(jenkinsError); - RestAPIController.JOB_MAP.remove(jobId); - this.gitTeaUtil.deleteRepository(jobId); - this.taskUploadUtils.deleteJenkinsJob(jobId); - return jenkinsError; + @RequestMapping(method = RequestMethod.POST) + public LegacyMoodleResult uploadAndTestFile(@RequestParam("taskFile") MultipartFile taskFileRef, + @RequestParam("assignmentId") String assignmentId + ) throws IOException, InterruptedException { + LOG.info("submission for testing received"); + + LOG.debug("creating new temporary directory"); + Path workDirectory = Files.createTempDirectory(testTmpPathModocot, "modocot"); + LOG.debug(String.format("working dir for test is: %s", workDirectory.toAbsolutePath().toString())); + + // define paths for the test, the submission and where the result is to be expected afterwards + Path testPath = Paths.get(workDirectory.toAbsolutePath().toString(), "test"); + Path srcPath = Paths.get(workDirectory.toAbsolutePath().toString(), "src"); + Path resultPath = Paths.get(workDirectory.toAbsolutePath().toString(), "result"); + + // clone stored test to tmpdir + LOG.debug("copying pre-downloaded unitttest repo"); + FileUtil.copyFolder( + Paths.get( + assignmentBasePath, + assignmentId + ), + testPath + ); + + LOG.debug("copy test config"); + Files.copy( + Paths.get( + assignmentBasePath, + assignmentId + ".txt" + ), + Paths.get( + workDirectory.toAbsolutePath().toString(), + "config.txt" + ) + ); + + // clone student code to tmpdir + Pattern pattern = Pattern.compile(UnitTestUpload.modocotDueConfigRegex); + Matcher config = null; + + LOG.debug("reading task file"); + // open received file in a try-with + try (BufferedReader br = new BufferedReader( + new InputStreamReader( + taskFileRef.getInputStream()))) { + String line; + + // as long as we haven't found a configuration and have lines left, search + while (config == null && (line = br.readLine()) != null) { + Matcher matcher = pattern.matcher(line); + if (matcher.matches()) { + LOG.debug(String.format("found modocot line: %s", line)); + config = matcher; + } + } + } catch (IOException e) { + LOG.error("Error while reading repo config", e); + } + finally { + if (config == null) { + throw new RuntimeException("couldn't find repo config for unittest clone"); + } } - Thread.sleep(3000); - - String userResult = RestAPIController.JOB_MAP.remove(jobId); - - this.gitTeaUtil.deleteRepository(jobId); - - this.taskUploadUtils.deleteJenkinsJob(jobId); + LOG.debug("calling repo clone"); + jGitUtil.cloneRepository(config, srcPath.toAbsolutePath().toString()); + + Files.createDirectory(resultPath); + + LOG.info("starting unittest"); + pattern = Pattern.compile(UnitTestUpload.modocotTestConfigRegex); + config = null; + + LOG.debug("reading test config"); + // open test config and read it in again, important to know with which docker image the test should be run + try (BufferedReader br = new BufferedReader( + new InputStreamReader( + new FileInputStream(Paths.get(workDirectory.toAbsolutePath().toString(), "config.txt").toFile())))) { + String line; + while (config == null && (line = br.readLine()) != null) { + Matcher matcher = pattern.matcher(line); + if (matcher.matches()) { + LOG.debug(String.format("found modocot line: %s", line)); + config = matcher; + } + } + } catch (IOException e) { + LOG.error("Error while reading test config", e); + } + finally { + if (config == null) { + throw new RuntimeException("couldn't find test config for unittest"); + } + } - if (!this.taskUploadUtils.isValidJSON(userResult)) { - throw new IllegalArgumentException("userResult from JUnitTestLauncher is invalid: " + userResult); + // define the paths to mount as Binds from Host to the test-container + Path testPathHost = Paths.get( + testTmpPathHost.toAbsolutePath().toString(), + workDirectory.getName(workDirectory.getNameCount()-1).toString(), + testPath.getName(testPath.getNameCount()-1).toString() + ); + Path srcPathHost = Paths.get( + testTmpPathHost.toAbsolutePath().toString(), + workDirectory.getName(workDirectory.getNameCount()-1).toString(), + srcPath.getName(srcPath.getNameCount()-1).toString() + ); + Path resultPathHost = Paths.get( + testTmpPathHost.toAbsolutePath().toString(), + workDirectory.getName(workDirectory.getNameCount()-1).toString(), + resultPath.getName(resultPath.getNameCount()-1).toString() + ); + + // start test-container with professor given image and bind mounts for test, submission and result + dockerUtil.runContainer( + config.group(4), + new Bind(testPathHost.toAbsolutePath().toString(), new Volume("/modocot/test")), + new Bind(srcPathHost.toAbsolutePath().toString(), new Volume("/modocot/src")), + new Bind(resultPathHost.toAbsolutePath().toString(), new Volume("/modocot/result")) + ); + + // define expected result file + File resultFile = Paths.get(resultPath.toAbsolutePath().toString(), "result.json").toFile(); + + // check if result file is there + if (!resultFile.exists() || !resultFile.isFile()) { + LOG.error(String.format("couln't find result file in %s", resultFile.getAbsolutePath())); + throw new RuntimeException("no resultfile found"); } - return userResult; - } + LOG.debug("parse results json"); + ObjectMapper objectMapper = new ObjectMapper(); + ModocotResultSummary resultSummary = objectMapper.readValue( + resultFile.toURI().toURL(), + ModocotResultSummary.class); - /** - * Extracting all lines from repo.txt and cloning extracted repository - * - * @param assignmentId String assignmentId - * @param subFolderPath working-directory - * @param unzippedFiles List of all Files from {@link MultipartFile} - */ - private void startFileRead(String assignmentId, String subFolderPath, List unzippedFiles) { - boolean gotRepoFile = unzippedFiles.stream().anyMatch(zipFile -> zipFile.getName().equalsIgnoreCase("repo.txt")); - if (gotRepoFile) { - List lines = BackendUtil.extractLinesFromRepoFile(unzippedFiles, "repo.txt"); - String repoUrl = (lines.size() > 0 && !lines.get(0).equals("")) ? - lines.get(0) : ""; - String credentials = (lines.size() > 1 && !lines.get(1).equals("")) ? - lines.get(1) : null; - File unit = new File(subFolderPath + "/src/UnitTests"); - unit.mkdirs(); - File task = new File(subFolderPath + "/src/Test"); - task.mkdirs(); - - this.jGitUtil.cloneRepository("http://" + this.modocotProperties.getDockerHostIp() - + ":3000/" + this.modocotProperties.getGitTeaUsername() + "/" - + assignmentId + ".git", - unit, null, true, false); - this.jGitUtil.cloneRepository(repoUrl, task, credentials, credentials != null, true); - } + // convert to moddle plugin readable format and return to moodle + LOG.debug("convert to moodle understandable format"); + LegacyMoodleResult moodleResult = LegacyMoodleResult.convertToModdleResult(resultSummary); + + LOG.info("submission tested successfully"); + return moodleResult; } } diff --git a/src/main/java/de/hftstuttgart/rest/v1/unittest/UnitTestUpload.java b/src/main/java/de/hftstuttgart/rest/v1/unittest/UnitTestUpload.java index 92a9357f86dc54f127fffa7b60d2fa3bc3349b89..6a6fcdd36376bd636c7ee3c7a0e9bd47fa8027e2 100644 --- a/src/main/java/de/hftstuttgart/rest/v1/unittest/UnitTestUpload.java +++ b/src/main/java/de/hftstuttgart/rest/v1/unittest/UnitTestUpload.java @@ -1,15 +1,10 @@ package de.hftstuttgart.rest.v1.unittest; -import de.hftstuttgart.config.ModocotProperties; -import de.hftstuttgart.utils.BackendUtil; -import de.hftstuttgart.utils.FileUtil; -import de.hftstuttgart.utils.GitTeaUtil; import de.hftstuttgart.utils.JGitUtil; -import de.hftstuttgart.utils.UnzipUtil; -import io.gitea.model.Repository; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.eclipse.jgit.transport.PushResult; +import org.springframework.core.env.Environment; +import org.springframework.util.FileSystemUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; @@ -17,13 +12,11 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import javax.servlet.annotation.MultipartConfig; -import java.io.File; -import java.io.IOException; -import java.util.List; -import java.util.Objects; -import java.util.UUID; -import java.util.stream.Collectors; -import java.util.stream.Stream; +import java.io.*; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * Rest controller for anything related to the TEST files. @@ -34,93 +27,77 @@ import java.util.stream.Stream; public class UnitTestUpload { private static final Logger LOG = LogManager.getLogger(UnitTestUpload.class); + public final static String modocotTestConfigRegex = "^modocot::(.*)::(.*|none)::(.*|none)::(.*)$"; + public final static String modocotDueConfigRegex = "^modocot::(.*)::(.*|none)::(.*|none)$"; - private final ModocotProperties modocotProperties; - private final GitTeaUtil gitTeaUtil; private final JGitUtil jGitUtil; private final String assignmentBasePath; - public UnitTestUpload(ModocotProperties modocotProperties, - GitTeaUtil gitTeaUtil, - JGitUtil jGitUtil) { - this.modocotProperties = modocotProperties; - this.gitTeaUtil = gitTeaUtil; + public UnitTestUpload(Environment env, JGitUtil jGitUtil) { this.jGitUtil = jGitUtil; - this.assignmentBasePath = - modocotProperties.getModocotParentDirectory() - + File.separator - + modocotProperties.getModocotAssignmentFolderPrefix(); + + Path p = Paths.get(env.getProperty("modocot.dir"), env.getProperty("modocot.dir.test.folder.name")); + this.assignmentBasePath = p.toAbsolutePath().toString(); } /** * Create a subfolder for the specific assignment. * This is called when the teacher creates an assignment and uploads the JUnit test files * - * @param unitTestFileRef The zip file which contains the JUnit tests + * @param unitTestFileRef The text file which contains the JUnit tests meta data * @param assignmentId ID of the created assignment. Generated by Moodle */ @RequestMapping(method = RequestMethod.POST) - public void uploadUnitTestFile(@RequestParam("unitTestFile") MultipartFile unitTestFileRef, @RequestParam("assignmentId") String assignmentId) throws IOException { - - // path to the directory in which we will be working - String subFolderPath = this.assignmentBasePath + assignmentId; - - LOG.info("work-directory: " + subFolderPath); - // creating the work-directory - File workDirectory = new File(subFolderPath); - workDirectory.mkdirs(); - - // creating the file which the unitTestFileRef will be transferred into - File file = new File(subFolderPath, String.valueOf(UUID.randomUUID())); - - // transferring MultipartFile into temporary file + public void uploadUnitTestFile( + @RequestParam("unitTestFile") MultipartFile unitTestFileRef, + @RequestParam("assignmentId") String assignmentId + ) throws IOException { + LOG.info("received new assignment"); + + File file = Paths.get( + this.assignmentBasePath, + assignmentId + ".txt") + .toFile(); + file.mkdirs(); + + // save assignment config unitTestFileRef.transferTo(file); - - // unzipping temporary file to work-directory - List zipFiles = UnzipUtil.unzip(file); - - // unzipping temporary file (not needed anymore) - if (file.exists()) file.delete(); - - // check if any extracted files are named repo.txt - if (zipFiles.stream().anyMatch(zipFile -> zipFile.getName().equalsIgnoreCase("repo.txt"))) { - // reading all from the repo.txt - List lines = BackendUtil.extractLinesFromRepoFile(zipFiles, "repo.txt"); - // either set the first line of repo.txt or "" - String repoUrl = (lines.size() > 0 && !lines.get(0).equals("")) ? - lines.get(0) : ""; - LOG.info("repoUrl: " + repoUrl); - // either set the second line of repo.txt or null - String credentials = ((lines.size() > 1) && !lines.get(1).equals("")) ? - lines.get(1) : null; - LOG.info("credentials: " + credentials); - // cloning repository repoUrl into work-directory, using credentials from second line in repo.txt - this.jGitUtil.cloneRepository(repoUrl, workDirectory, credentials, credentials != null,true); - } - - Stream.of(Objects.requireNonNull(workDirectory.listFiles())) - .forEach(fi -> System.out.println(fi.getAbsolutePath())); - - if(this.gitTeaUtil.repositoryExists(assignmentId)) { - this.gitTeaUtil.deleteRepository(assignmentId); + LOG.debug(String.format("saved config file to: %s", file.getAbsolutePath())); + + Pattern pattern = Pattern.compile(this.modocotTestConfigRegex); + Matcher config = null; + + LOG.debug("reading test configuration file"); + // open saved config in a try-with + try (BufferedReader br = new BufferedReader( + new InputStreamReader( + new FileInputStream(file)))) { + String line; + + // search for a modocot URI while none is found and there are lines left + while (config == null && (line = br.readLine()) != null) { + Matcher matcher = pattern.matcher(line); + if (matcher.matches()) { + LOG.debug(String.format("found modocot test line: %s", line)); + config = matcher; + } + } + } catch (IOException e) { + LOG.error("Error while reading repo config", e); } - // creating repository on internal giTea, name = assignmentId - Repository repo = this.gitTeaUtil.createRepository(assignmentId); - System.out.println(repo); - // giTea runs in docker and returns CloneUrl as localhost, replacing localhost with docker-host ip - repo.setCloneUrl(repo.getCloneUrl().replace("localhost", modocotProperties.getDockerHostIp())); - - // committing everything in work-directory and push to created repository - Iterable pushResults = this.jGitUtil.commitAllAndPush(workDirectory, repo, false); - if (pushResults != null) { - for (PushResult pushResult : pushResults) { - LOG.info("Push-Result: " + pushResult.getMessages()); + finally { + if (config == null) { + throw new RuntimeException("couldn't find repo config for unittest clone"); } } - // deleting created work-directory - FileUtil.deleteFolderRecursively(workDirectory); - LOG.info("Uploaded unit test file: " + workDirectory); + LOG.debug("calling test repo clone"); + // cloning assignment repo to persistent space + jGitUtil.cloneRepository( + config, + Paths.get(this.assignmentBasePath, assignmentId).toAbsolutePath().toString()); + + LOG.info(String.format("stored new assignment: %s", file.getAbsolutePath())); } /** @@ -133,10 +110,21 @@ public class UnitTestUpload { */ @RequestMapping(method = RequestMethod.DELETE) public void deleteUnitTestFiles(@RequestParam("assignmentId") String assignmentId) { - String path = this.assignmentBasePath + assignmentId; - File dir = new File(path); - if (dir.exists()) { - FileUtil.deleteFolderRecursively(dir); - } + LOG.info(String.format("received deletion order for assignment %s", assignmentId)); + + // deleting config file + File file = Paths.get( + this.assignmentBasePath, + assignmentId + ".txt") + .toFile(); + file.delete(); + + // deleting local copy of repository + file = Paths.get( + this.assignmentBasePath, + assignmentId).toFile(); + FileSystemUtils.deleteRecursively(file); + + LOG.info(String.format("assignment %s deletion complete", assignmentId)); } } diff --git a/src/main/java/de/hftstuttgart/utils/BackendUtil.java b/src/main/java/de/hftstuttgart/utils/BackendUtil.java deleted file mode 100644 index 428c7dcb26d7d005228859130c3a3577b61ba1a1..0000000000000000000000000000000000000000 --- a/src/main/java/de/hftstuttgart/utils/BackendUtil.java +++ /dev/null @@ -1,40 +0,0 @@ -package de.hftstuttgart.utils; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.List; -import java.util.stream.Collectors; - -public class BackendUtil { - - /** - * Loop through all {@link File}s in {@code filesFromZipFile} and find {@link File} {@code fileNameToSearchFor}.
- * And return a {@link List} of Strings for each line in file {@code fileNameToSearchFor} - * - * @param filesFromZipFile all files which get extracted from previous zipFile - * @param fileNameToSearchFor search for specific name - * @return {@link List} of Strings for each line in file {@code fileNameToSearchFor} - */ - public static List extractLinesFromRepoFile(List filesFromZipFile, String fileNameToSearchFor) { - if(filesFromZipFile.size() < 1 && fileNameToSearchFor != null) { - throw new IllegalArgumentException(); - } - List lines = null; - for (File file : filesFromZipFile) { - if (file.getName().equalsIgnoreCase(fileNameToSearchFor)) { - try { - FileInputStream fis = new FileInputStream(file); - BufferedReader br = new BufferedReader(new InputStreamReader(fis)); - lines = br.lines().collect(Collectors.toList()); - br.close(); - if (file.exists()) - file.delete(); - } catch (IOException ignored) { } - } - } - return lines; - } -} diff --git a/src/main/java/de/hftstuttgart/utils/BuildState.java b/src/main/java/de/hftstuttgart/utils/BuildState.java deleted file mode 100644 index 718b165f98531bc1e9e1bc5bb5dab2210e27cba4..0000000000000000000000000000000000000000 --- a/src/main/java/de/hftstuttgart/utils/BuildState.java +++ /dev/null @@ -1,17 +0,0 @@ -package de.hftstuttgart.utils; - -import com.fasterxml.jackson.annotation.JsonProperty; - -public enum BuildState { - @JsonProperty("blue") BLUE, - @JsonProperty("notbuilt") NOTBUILT, - @JsonProperty("notbuilt_anime") NOTBUILT_ANMIE, - @JsonProperty("red") RED, - @JsonProperty("yellow") YELLOW, - @JsonProperty("grey") GREY, - @JsonProperty("disabled") DISABLED, - @JsonProperty("aborted") ABORTED, - @JsonProperty("aborted_anime") ABORTED_ANIME, - @JsonProperty("grey_anime") GREY_ANIME - -} diff --git a/src/main/java/de/hftstuttgart/utils/DockerUtil.java b/src/main/java/de/hftstuttgart/utils/DockerUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..7c9183c68a08edbbc9af15190cca2f8c461270f0 --- /dev/null +++ b/src/main/java/de/hftstuttgart/utils/DockerUtil.java @@ -0,0 +1,75 @@ +package de.hftstuttgart.utils; + +import com.github.dockerjava.api.DockerClient; +import com.github.dockerjava.api.command.CreateContainerResponse; +import com.github.dockerjava.api.model.Bind; +import com.github.dockerjava.api.model.HostConfig; +import com.github.dockerjava.core.DefaultDockerClientConfig; +import com.github.dockerjava.core.DockerClientConfig; +import com.github.dockerjava.core.DockerClientImpl; +import com.github.dockerjava.httpclient5.ApacheDockerHttpClient; +import com.github.dockerjava.transport.DockerHttpClient; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Component; + +import java.io.IOException; + +@Component +public class DockerUtil { + private static final Logger LOG = LogManager.getLogger(DockerUtil.class); + + private DockerClient dockerClient; + + public DockerUtil(Environment env) { + LOG.info("initializing Docker tools"); + LOG.debug("create docker client config"); + DockerClientConfig dockerClientConfig = DefaultDockerClientConfig.createDefaultConfigBuilder().build(); + + LOG.debug("create docker http client"); + DockerHttpClient httpClient = new ApacheDockerHttpClient.Builder() + .dockerHost(dockerClientConfig.getDockerHost()) + .sslConfig(dockerClientConfig.getSSLConfig()) + .build(); + + LOG.debug("create docker client"); + dockerClient = DockerClientImpl.getInstance(dockerClientConfig, httpClient); + } + + public int runContainer(String image, Bind... binds) throws InterruptedException, IOException + { + LOG.debug(String.format("pull image: %s", image)); + dockerClient.pullImageCmd(image) + .start() + .awaitCompletion() + .close(); + + LOG.debug("creating container"); + CreateContainerResponse containerResponse = dockerClient.createContainerCmd("testcontainer") + .withImage(image) + .withHostConfig( + HostConfig.newHostConfig() + .withBinds(binds)) + .exec(); + LOG.debug(String.format("container created: %s", containerResponse.getId())); + + LOG.debug(String.format("starting container %s", containerResponse.getId())); + dockerClient.startContainerCmd(containerResponse.getId()).exec(); + + LOG.debug(String.format("waiting for completion of container %s", containerResponse.getId())); + int ret = dockerClient + .waitContainerCmd(containerResponse.getId()) + .start() + .awaitCompletion() + .awaitStatusCode(); + LOG.debug(String.format("container completed with status %d", ret)); + + LOG.debug(String.format("deleting container %s", containerResponse.getId())); + dockerClient.removeContainerCmd(containerResponse.getId()) + .withRemoveVolumes(true) + .exec(); + + return ret; + } +} diff --git a/src/main/java/de/hftstuttgart/utils/FileUtil.java b/src/main/java/de/hftstuttgart/utils/FileUtil.java index 98d088c7a6566074245b9aa3ecf144b042f2ca08..0e4f01dea1ef75b4d3ef9fba56d1229d4aab47af 100644 --- a/src/main/java/de/hftstuttgart/utils/FileUtil.java +++ b/src/main/java/de/hftstuttgart/utils/FileUtil.java @@ -1,6 +1,9 @@ package de.hftstuttgart.utils; import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; /** * Helper Class for all file related tasks. @@ -27,4 +30,14 @@ public class FileUtil { folder.delete(); } + public static void copyFolder(Path src, Path dst) throws IOException { + Files.walk(src) + .forEach(source -> { + try { + Files.copy(source, dst.resolve(src.relativize(source))); + } catch (IOException e) { + throw new RuntimeException(e.getMessage(), e); + } + }); + } } diff --git a/src/main/java/de/hftstuttgart/utils/GitTeaUtil.java b/src/main/java/de/hftstuttgart/utils/GitTeaUtil.java deleted file mode 100644 index 3fe9d47e140edeb5c46bd42d6e13e9d0519c9512..0000000000000000000000000000000000000000 --- a/src/main/java/de/hftstuttgart/utils/GitTeaUtil.java +++ /dev/null @@ -1,88 +0,0 @@ -package de.hftstuttgart.utils; - -import de.hftstuttgart.config.ModocotProperties; -import io.gitea.ApiClient; -import io.gitea.ApiException; -import io.gitea.Configuration; -import io.gitea.api.RepositoryApi; -import io.gitea.api.UserApi; -import io.gitea.auth.HttpBasicAuth; -import io.gitea.model.CreateRepoOption; -import io.gitea.model.Repository; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.springframework.stereotype.Component; - -@Component -public class GitTeaUtil { - - private static final Logger LOG = LogManager.getLogger(GitTeaUtil.class); - - private final ModocotProperties modocotProperties; - - public GitTeaUtil(ModocotProperties modocotProperties) { - this.modocotProperties = modocotProperties; - } - - /** - * Create Git-Repository with name {@code repositoryName} on internal Git-Server - * - * @param repositoryName name of new Repository - * @return newly created Repository - */ - public Repository createRepository(String repositoryName) { - setupAuth(); - Repository repo = null; - try { - repo = new UserApi() - .createCurrentUserRepo(new CreateRepoOption().name(repositoryName)); - } catch (ApiException e) { - LOG.error(String.format("Error while creating repository: %s", repositoryName), e); - } - if (repo != null) { - LOG.info("Created repository {} on {}", repositoryName, repo.getCloneUrl()); - } else { - throw new IllegalStateException("Repository is null"); - } - return repo; - } - - /** - * Delete Git-Repository with name {@code repositoryName} on internal Git-Server - * - * @param repositoryName name of new Repository - */ - public void deleteRepository(String repositoryName) { - setupAuth(); - try { - new RepositoryApi().repoDelete(this.modocotProperties.getGitTeaUsername(), repositoryName); - } catch (ApiException e) { - LOG.error("Error while deleting repository:" + e.getMessage()); - } - } - - /** - * Check if a Git-Repository with the given name exists. - * - * @param repositoryName name of the Repository - */ - public boolean repositoryExists(String repositoryName) { - setupAuth(); - Repository repository = null; - try { - repository = new RepositoryApi().repoGet(this.modocotProperties.getGitTeaUsername(), repositoryName); - } catch (ApiException e) { - LOG.error("Error while deleting repository:" + e.getMessage()); - } - return repository != null; - } - - private void setupAuth() { - ApiClient defaultClient = Configuration.getDefaultApiClient(); - - defaultClient.setBasePath(this.modocotProperties.getGitTeaBasePath()); - HttpBasicAuth basicAuth = (HttpBasicAuth) defaultClient.getAuthentication("BasicAuth"); - basicAuth.setUsername(this.modocotProperties.getGitTeaUsername()); - basicAuth.setPassword(this.modocotProperties.getGitTeaPassword()); - } -} diff --git a/src/main/java/de/hftstuttgart/utils/JGitUtil.java b/src/main/java/de/hftstuttgart/utils/JGitUtil.java index c4722c1ccc877ad1eaa27194b119469dcb3dc73b..b3cd18d30262cb84d8404d531e3235a6840b00c5 100644 --- a/src/main/java/de/hftstuttgart/utils/JGitUtil.java +++ b/src/main/java/de/hftstuttgart/utils/JGitUtil.java @@ -1,189 +1,53 @@ package de.hftstuttgart.utils; -import de.hftstuttgart.config.ModocotProperties; -import io.gitea.model.Repository; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.eclipse.jgit.api.CloneCommand; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.errors.GitAPIException; -import org.eclipse.jgit.transport.PushResult; -import org.eclipse.jgit.transport.URIish; import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; import org.springframework.stereotype.Component; +import org.springframework.util.FileSystemUtils; import java.io.File; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.Proxy; -import java.net.ProxySelector; -import java.net.SocketAddress; -import java.net.URI; -import java.util.Arrays; -import java.util.List; +import java.util.regex.Matcher; @Component public class JGitUtil { private static final Logger LOG = LogManager.getLogger(JGitUtil.class); - private final ModocotProperties modocotProperties; + public JGitUtil() {} - public JGitUtil(ModocotProperties modocotProperties) { - this.modocotProperties = modocotProperties; - } + public void cloneRepository(Matcher config, String targetPath) { + LOG.debug(String.format("cloning repository: %s", config.group(1))); - /** - * Clone Repository from {@code uriToClone} into Directory {@code cloneDirectory}, and using token {@code token}.
- * {@code boolean proxy} determines, if a proxy should be used - * - * @param uriToClone Repository cloneUrl - * @param cloneDirectory {@link File} directory in which Repository should be cloned into - * @param token AuthToken, when cloning Repository. If {@code null} use {@code ModocotProperties} - * @param proxy boolean if a proxy should be used - */ - public void cloneRepository(String uriToClone, File cloneDirectory, String token, boolean useToken, boolean proxy) { - if (!cloneDirectory.isDirectory()) { - String error = String.format("%s is not a directory, cannot clone", cloneDirectory.getAbsolutePath()); - LOG.error(error); - throw new IllegalArgumentException(error); - } - LOG.info(String.format("Cloning all files from %s into %s", uriToClone, cloneDirectory.getAbsolutePath())); - try { - deleteDotGitFolder(cloneDirectory); - UsernamePasswordCredentialsProvider credProvider = null; - LOG.info("using token: " + useToken); - if (useToken) { - LOG.info("token: " + token); - if (token != null) { - LOG.info("Using token: " + token); - String[] credentials = token.split(":"); - credProvider = new UsernamePasswordCredentialsProvider(credentials[0], credentials[1]); - } else { - LOG.info("Using credentials: " + this.modocotProperties.getGitTeaUsername() + ", " + this.modocotProperties.getGitTeaPassword()); - credProvider = new UsernamePasswordCredentialsProvider( - this.modocotProperties.getGitTeaUsername(), - this.modocotProperties.getGitTeaPassword()); - } - } - LOG.info("Starting cloning, url: " + uriToClone); - setProxy(proxy); - if (useToken) { - Git.cloneRepository() - .setCredentialsProvider(credProvider) - .setURI(uriToClone) - .setDirectory(cloneDirectory) - .call() - .close(); - } else { - Git.cloneRepository() - .setURI(uriToClone) - .setDirectory(cloneDirectory) - .call() - .close(); - } - } catch (GitAPIException e) { - LOG.error(String.format("Error while cloning from %s", uriToClone), e); + File targetDirectory = new File(targetPath); + if (targetDirectory.exists()) { + LOG.debug("clone target directory existing yet, deleting now"); + FileSystemUtils.deleteRecursively(targetDirectory); } - } - /** - * Commit {@code directory} and push all files to the given {@code repository}. - * - * @param directory {@link File} directory to commit - * @param repository {@link Repository} Repository to push to - * @param proxy boolean if a proxy should be used - * @return {@code Iterable} - */ - public Iterable commitAllAndPush(File directory, Repository repository, boolean proxy) { - if (!directory.isDirectory()) { - String error = String.format("%s is not a directory, cannot commit or push", directory.getAbsolutePath()); - LOG.error(error); - throw new IllegalArgumentException(error); - } - LOG.info(String.format("Committing all files in: %s and pushing them to: %s", directory.getAbsolutePath(), repository.getCloneUrl())); try { - deleteDotGitFolder(directory); - // "git init" new repository - Git.init() - .setDirectory(directory) - .call(); - - // open new repository - Git git = Git.open(directory); - - // "git add ." on repository - git.add() - .addFilepattern(".") - .call(); - - // "git commit -m %gitTeaCommitMessage%" on repository - git.commit() - .setMessage(this.modocotProperties.getGitTeaDefaultCommitMessage()) - .call(); - - // add new remote from repository - git.remoteAdd() - .setName(this.modocotProperties.getGitTeaOrigin()) - .setUri(new URIish(repository.getCloneUrl())) - .call(); - // "git push" to new origin - setProxy(proxy); - return git.push() - .setCredentialsProvider(new UsernamePasswordCredentialsProvider( - this.modocotProperties.getGitTeaUsername(), - this.modocotProperties.getGitTeaPassword())) - .call(); - - } catch (Exception e) { - LOG.error(String.format("Error while committing to repo: %s from file: %s", repository, directory.getAbsolutePath()), e); - } - return null; - } + LOG.debug("preparing clone"); + CloneCommand cloneCommand = Git.cloneRepository() + .setDirectory(targetDirectory) + .setURI(config.group(1)); + + if (!config.group(2).equals("none") && !config.group(3).equals("none")) { + LOG.debug("setting credentials"); + cloneCommand.setCredentialsProvider( + new UsernamePasswordCredentialsProvider(config.group(2), config.group(3))); + } - private void deleteDotGitFolder(File directory) { - File temp = new File(directory.getPath() + "/src/UnitTests/.git"); - if (temp.exists() && temp.isDirectory() && temp.canWrite()) { - FileUtil.deleteFolderRecursively(temp); + LOG.debug("cloning..."); + cloneCommand.call() + .close(); } - temp = new File(directory.getPath() + "/src/.git"); - if (temp.exists() && temp.isDirectory() && temp.canWrite()) { - FileUtil.deleteFolderRecursively(temp); + catch (GitAPIException e) { + LOG.error(String.format("Error while cloning from %s", config.group(1)), e); } - temp = new File(directory.getPath() + "/.git"); - if (temp.exists() && temp.isDirectory() && temp.canWrite()) { - FileUtil.deleteFolderRecursively(temp); - } - } - - private void setProxy(boolean proxy) { - if (proxy) { - ProxySelector.setDefault(new ProxySelector() { - final ProxySelector delegate = ProxySelector.getDefault(); - @Override - public List select(URI uri) { - // Filter the URIs to be proxied - if (uri.toString().contains("https")) { - return Arrays.asList(new Proxy(Proxy.Type.HTTP, InetSocketAddress - .createUnresolved("proxy.hft-stuttgart.de", 80))); - } - if (uri.toString().contains("http")) { - return Arrays.asList(new Proxy(Proxy.Type.HTTP, InetSocketAddress - .createUnresolved("proxy.hft-stuttgart.de", 80))); - } - // revert to the default behaviour - return delegate == null ? Arrays.asList(Proxy.NO_PROXY) - : delegate.select(uri); - } - - @Override - public void connectFailed(URI uri, SocketAddress sa, IOException ioe) { - if (uri == null || sa == null || ioe == null) { - throw new IllegalArgumentException( - "Arguments can't be null."); - } - } - }); - } + LOG.debug(String.format("cloned from %s to %s", config.group(1), targetDirectory)); } } diff --git a/src/main/java/de/hftstuttgart/utils/RestCall.java b/src/main/java/de/hftstuttgart/utils/RestCall.java deleted file mode 100644 index 6dce14bedf1d7b750b9de5221fdbd7df52390511..0000000000000000000000000000000000000000 --- a/src/main/java/de/hftstuttgart/utils/RestCall.java +++ /dev/null @@ -1,35 +0,0 @@ -package de.hftstuttgart.utils; - -import de.hftstuttgart.config.ModocotProperties; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.tomcat.util.codec.binary.Base64; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Component; -import org.springframework.web.client.RestTemplate; - -@Component -public class RestCall { - - private static final Logger LOG = LogManager.getLogger(RestCall.class); - - private final ModocotProperties modocotProperties; - - public RestCall(ModocotProperties modocotProperties) { - this.modocotProperties = modocotProperties; - } - - public ResponseEntity exchange(String specificUrl, HttpMethod method, T body, Class responseType, Object... uriVariables) { - RestTemplate restTemplate = new RestTemplate(); - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_XML); - headers.add("Authorization", "Basic " + new String(Base64.encodeBase64((this.modocotProperties.getJenkinsApiToken()).getBytes()))); - headers.add("user", "admin"); - LOG.info(method.toString() + ", to: " + this.modocotProperties.getJenkinsBaseUrl() + specificUrl); - return restTemplate.exchange(this.modocotProperties.getJenkinsBaseUrl() + specificUrl, method, new HttpEntity<>(body, headers), responseType, uriVariables); - } -} diff --git a/src/main/java/de/hftstuttgart/utils/TaskUploadUtils.java b/src/main/java/de/hftstuttgart/utils/TaskUploadUtils.java deleted file mode 100644 index a287a8209d9fb41ecfeedb57639ef6e090fc8a28..0000000000000000000000000000000000000000 --- a/src/main/java/de/hftstuttgart/utils/TaskUploadUtils.java +++ /dev/null @@ -1,177 +0,0 @@ -package de.hftstuttgart.utils; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.ObjectMapper; -import de.hftstuttgart.config.ModocotProperties; -import de.hftstuttgart.models.JenkinsJobData; -import de.hftstuttgart.rest.v1.jenkins.RestAPIController; -import freemarker.template.Configuration; -import freemarker.template.Template; -import freemarker.template.TemplateException; -import freemarker.template.Version; -import io.gitea.model.Repository; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.springframework.http.HttpMethod; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Component; - -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.StringWriter; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.HashMap; -import java.util.Map; - -@Component -public class TaskUploadUtils { - - private static final Logger LOG = LogManager.getLogger(TaskUploadUtils.class); - private final GitTeaUtil gitTeaUtil; - private final ModocotProperties modocotProperties; - private final JGitUtil jGitUtil; - private final RestCall restCall; - - public TaskUploadUtils(GitTeaUtil gitTeaUtil, - ModocotProperties modocotProperties, - JGitUtil jGitUtil, - RestCall restCall) { - this.gitTeaUtil = gitTeaUtil; - this.modocotProperties = modocotProperties; - this.jGitUtil = jGitUtil; - this.restCall = restCall; - } - - /** - * Start jenkinsJob and return its BuildStatus after completion - * - * @param jobId String jenkinsJobId - * @param subFolderPath workingDirectory - * @return Jenkins BuildStatus - */ - public BuildState startTask(String jobId, String subFolderPath) throws IOException, InterruptedException { - // we clone the Student submission to /Test subfolder and then copy those files into the working directory - File f = new File(subFolderPath + "/src/Test"); - for (File fi : f.listFiles()) { - Files.move(Paths.get(fi.getPath()), Paths.get(subFolderPath + "/src/" + fi.getName())); - } - if (f.exists()) f.delete(); - - File temp = new File(subFolderPath + "/src/UnitTests/.git"); - if (temp.exists() && temp.isDirectory() && temp.canWrite()) { - FileUtil.deleteFolderRecursively(temp); - } - temp = new File(subFolderPath + "/src/.git"); - if (temp.exists() && temp.isDirectory() && temp.canWrite()) { - FileUtil.deleteFolderRecursively(temp); - } - - // creating the jobId.json containing the jobId - FileWriter fileWriter = new FileWriter(subFolderPath + "/src/jobId.json"); - fileWriter.write(new ObjectMapper().readTree("{\"jobId\":\"" + jobId + "\"}").toString()); - fileWriter.close(); - - // creating repository with name jobId - Repository repository = this.gitTeaUtil.createRepository(jobId); - repository.setCloneUrl(repository.getCloneUrl().replace("localhost", modocotProperties.getDockerHostIp())); - - // committing work-directory and pushing all files to repository - this.jGitUtil.commitAllAndPush(new File(subFolderPath), repository, false); - - FileUtil.deleteFolderRecursively(new File(subFolderPath)); - - // persisting the jobId - RestAPIController.JOB_MAP.put(jobId, null); - - createJenkinsJob(jobId, repository.getCloneUrl()); - buildJenkinsJob(jobId); - - // waiting for jenkinsJob to finish then returning its BuildStatus - int timeout = 0; - BuildState buildState = getJenkinsBuildState(jobId); - while (buildState != BuildState.BLUE && buildState != BuildState.RED) { - buildState = getJenkinsBuildState(jobId); - if (timeout >= 100) break; - Thread.sleep(6000); - timeout++; - } - return buildState; - } - - public void deleteJenkinsJob(String jobId) { - LOG.info("deleteJenkinsJob jobId: " + jobId); - ResponseEntity response = this.restCall.exchange("job/" + jobId + "/doDelete", HttpMethod.POST, null, String.class); - } - - - private BuildState getJenkinsBuildState(String jenkinsJob) { - LOG.info("getJenkinsBuildState jenkinsJob: " + jenkinsJob); - ResponseEntity response = this.restCall.exchange("api/json?tree=jobs[name,color]", HttpMethod.GET, null, JenkinsJobData.class); - - if (response.getBody() == null) { - throw new NullPointerException("Jenkins Response was null"); - } - - return response.getBody() - .getJobs() - .stream() - .filter(job -> job.getName().equals(jenkinsJob)) - .findFirst() - .get() - .getColor(); - - } - - public String getJenkinsConsoleOutput(String jenkinsJob) { - ResponseEntity response = this.restCall.exchange("job/" + jenkinsJob + "/lastBuild/consoleText", HttpMethod.GET, null, String.class); - return response.getBody(); - } - - private void buildJenkinsJob(String user) { - LOG.info("buildJenkinsJob user: " + user); - ResponseEntity response = this.restCall.exchange("job/" + user + "/build", HttpMethod.POST, null, String.class); - } - - private void createJenkinsJob(String gitUser, String gitUrl) { - LOG.info("createJenkinsJob gitUser: " + gitUser + ", gitUrl: " + gitUrl); - ResponseEntity response = this.restCall.exchange("createItem?name=" + gitUser, HttpMethod.POST, createXmlFile(gitUser, gitUrl), String.class); - } - - private String createXmlFile(String gitUser, String gitUrl) { - // fill data map for template - Map templateData = new HashMap<>(); - templateData.put("gitUser", gitUser); - templateData.put("gitUrl", gitUrl); - - // freemarker create config - Configuration cfg = new Configuration(new Version("2.3.30")); - cfg.setClassForTemplateLoading(this.getClass(), "/templates"); - cfg.setDefaultEncoding("UTF-8"); - - // fuse config and data - StringWriter out = new StringWriter(); - try { - Template template = cfg.getTemplate("JenkinsFile.ftl"); - template.process(templateData, out); - LOG.info(String.format("Template created with gitUrl: %s and gitUser: %s", gitUrl, gitUser)); - } catch (IOException | TemplateException e) { - e.printStackTrace(); - } - return out.getBuffer().toString(); - } - - public boolean isValidJSON(final String json) { - boolean valid = false; - try { - final JsonParser parser = new ObjectMapper().getFactory().createParser(json); - while (parser.nextToken() != null) { - } - valid = true; - } catch (IOException e) { - LOG.error("Json is invalid", e); - } - return valid; - } -} diff --git a/src/main/java/de/hftstuttgart/utils/UnzipUtil.java b/src/main/java/de/hftstuttgart/utils/UnzipUtil.java deleted file mode 100644 index 50a61aae299db1691d391c6f4e155c1d42f334a8..0000000000000000000000000000000000000000 --- a/src/main/java/de/hftstuttgart/utils/UnzipUtil.java +++ /dev/null @@ -1,83 +0,0 @@ -package de.hftstuttgart.utils; - -import de.hftstuttgart.exceptions.CorruptedZipFileException; -import de.hftstuttgart.exceptions.NoZipFileException; -import org.apache.log4j.Logger; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.zip.ZipEntry; -import java.util.zip.ZipException; -import java.util.zip.ZipInputStream; - -/** - * Created by Marcel Bochtler on 13.11.16. - * Based on: https://www.mkyong.com/java/how-to-decompress-files-from-a-zip-file/ - */ -public class UnzipUtil { - - private static final Logger LOG = Logger.getLogger(UnzipUtil.class); - - /** - * Unzips files and saves them to the disk. - * Checks if the zip file is valid. - */ - public static List unzip(File zipFile) throws IOException { - - String outputFolder = zipFile.getParentFile().getAbsolutePath(); - List unzippedFiles = new ArrayList<>(); - - byte[] buffer = new byte[1024]; - - //create output directory is not exists - File folder = new File(zipFile.getAbsolutePath()); - if (!folder.exists()) { - folder.mkdir(); - } - - try (ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(zipFile))) { - ZipEntry zipEntry = zipInputStream.getNextEntry(); - - if (zipEntry == null) { - String message = "The file " + zipFile.getAbsolutePath() + " does not seem be a zip file"; - LOG.error(message); - throw new NoZipFileException(message); - } - - while (zipEntry != null) { - String fileName = zipEntry.getName(); - File unzippedFile = new File(outputFolder + File.separator + fileName); - LOG.info("Unzipped file: " + unzippedFile.getName()); - - // create all non exists folders - // else we will hit FileNotFoundException for compressed folder - new File(unzippedFile.getParent()).mkdirs(); - - FileOutputStream fos = new FileOutputStream(unzippedFile); - int length; - while ((length = zipInputStream.read(buffer)) > 0) { - fos.write(buffer, 0, length); - } - - fos.close(); - zipEntry = zipInputStream.getNextEntry(); - unzippedFiles.add(unzippedFile); - } - - if (zipFile.exists()) { - zipFile.delete(); - } - - return unzippedFiles; - - } catch (ZipException ze) { - String msg = "Failed to unzip file " + zipFile; - LOG.error(msg); - throw new CorruptedZipFileException(msg); - } - } -} diff --git a/src/main/resources/application-debug.properties b/src/main/resources/application-debug.properties new file mode 100644 index 0000000000000000000000000000000000000000..e8812078465dc6cb680d88b0dbd11e2b5f48fa61 --- /dev/null +++ b/src/main/resources/application-debug.properties @@ -0,0 +1 @@ +logging.level.de.hftstuttgart=TRACE diff --git a/src/main/resources/application-server.properties b/src/main/resources/application-server.properties deleted file mode 100644 index af2743a533622ae0f32d5e7630d37cc3815c9fe5..0000000000000000000000000000000000000000 --- a/src/main/resources/application-server.properties +++ /dev/null @@ -1,26 +0,0 @@ -# Multipart settings -spring.http.multipart.enabled=true -spring.http.multipart.max-file-size=5Mb - -server.port=8081 - -docker.hostIp=10.40.10.144 - -jenkins.api.token=dome:1194017120ee74c91ee314e6f796e7b2ae -jenkins.url=http://${docker.hostIp}:8080/ - - -############################################### -# Modocot properties -############################################### - -# Holds the uploaded Zip-Files -modocot.dir.parent=/home/modocot -modocot.dir.assignment.prefix=Assignment_ -modocot.dir.test.folder.name=UnitTests - -gitTea.basePath=http://${docker.hostIp}:3000/api/v1 -gitTea.username=giteaUser -gitTea.password=giteaUser1! -gitTea.defaultCommitMessage=Commit all changes including additions -gitTea.defaultOrigin=origin \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index e5b383692fb2a268660505e7a222f6cfccd77594..cdaac83fe6f9f203698163c272547f692dc9473c 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -2,24 +2,12 @@ spring.http.multipart.enabled=true spring.http.multipart.max-file-size=5Mb -server.port=8081 - -docker.hostIp=10.0.2.15 - -jenkins.api.token=token:114e49fcd53d583f81113697a64d0e7630 -jenkins.url=http://${docker.hostIp}:8080/ - ############################################### # Modocot properties ############################################### # Holds the uploaded Zip-Files -modocot.dir.parent=/home/doom/modocot/ -modocot.dir.assignment.prefix=Assignment_ +modocot.tests.tmp.dir=/tmp/modocot-tests +host.tests.tmp.dir=${modocot.tests.tmp.dir} +modocot.dir=/modocot/data modocot.dir.test.folder.name=UnitTests - -gitTea.basePath=http://${docker.hostIp}:3000/api/v1 -gitTea.username=giteaUser -gitTea.password=giteaUser1! -gitTea.defaultCommitMessage=Commit all changes including additions -gitTea.defaultOrigin=origin diff --git a/src/main/resources/git-credentials.properties b/src/main/resources/git-credentials.properties deleted file mode 100644 index dc90ad822710b57a06640eabfa12a1da52b55ce4..0000000000000000000000000000000000000000 --- a/src/main/resources/git-credentials.properties +++ /dev/null @@ -1,2 +0,0 @@ -modocot.git.username=username -modocot.git.password=password \ No newline at end of file diff --git a/src/main/resources/templates/JenkinsFile.ftl b/src/main/resources/templates/JenkinsFile.ftl deleted file mode 100644 index 8cb515391afe340e41c287059d21f7149b868764..0000000000000000000000000000000000000000 --- a/src/main/resources/templates/JenkinsFile.ftl +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - Pipeline for User: ${gitUser} - false - - - - 2 - - - ${gitUrl} - giteaUser - - - - - */master - - - false - - - - src/Jenkinsfile - true - - - false - \ No newline at end of file diff --git a/src/main/resources/templates/JenkinsLocalTestFile.ftl b/src/main/resources/templates/JenkinsLocalTestFile.ftl deleted file mode 100644 index eeda8887750e3aa285259658afe5568994a88176..0000000000000000000000000000000000000000 --- a/src/main/resources/templates/JenkinsLocalTestFile.ftl +++ /dev/null @@ -1,18 +0,0 @@ - - - ${gitUser} ${gitUrl} - false - - - - - true - false - false - false - - false - - - - \ No newline at end of file diff --git a/src/test/java/de/hftstuttgart/rest/v1/unittest/IntegrationTest.java b/src/test/java/de/hftstuttgart/rest/v1/unittest/IntegrationTest.java deleted file mode 100644 index 56da99873df9e25971747c5edaa2a265f099001d..0000000000000000000000000000000000000000 --- a/src/test/java/de/hftstuttgart/rest/v1/unittest/IntegrationTest.java +++ /dev/null @@ -1,108 +0,0 @@ -package de.hftstuttgart.rest.v1.unittest; - -import org.junit.Before; -import org.junit.Ignore; -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.mock.web.MockMultipartFile; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import org.springframework.web.context.WebApplicationContext; - -import java.io.File; -import java.io.FileInputStream; - -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public class IntegrationTest { - - @Autowired - private WebApplicationContext webApplicationContext; - - MockMvc mockMvc; - - @Before - public void setup() throws Exception { - mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); - } - - @Test - @Ignore - public void validUnitTestFileTest() throws Exception { - - // Upload tests - File unitTestFile = new File(Thread.currentThread().getContextClassLoader().getResource("tests.zip").getFile()); - MockMultipartFile testFileMock = new MockMultipartFile("unitTestFile", new FileInputStream(unitTestFile)); - mockMvc.perform(MockMvcRequestBuilders.fileUpload("/v1/unittest") - .file(testFileMock) - .param("assignmentId", "111")) - .andExpect(status().is(200)); - - // Upload tasks - File taskFile = new File(Thread.currentThread().getContextClassLoader().getResource("tasks.zip").getFile()); - MockMultipartFile taskFileMock = new MockMultipartFile("taskFile", new FileInputStream(taskFile)); - mockMvc.perform(MockMvcRequestBuilders.fileUpload("/v1/task") - .file(taskFileMock) - .param("assignmentId", "111")) - .andExpect(status().is(200)) - .andExpect(content().string(("{\n" + - " \"testResults\" : [ {\n" + - " \"testName\" : \"CalculatorTest\",\n" + - " \"testCount\" : 5,\n" + - " \"failureCount\" : 0,\n" + - " \"successfulTests\" : [ \"add\", \"div\", \"sub\", \"sum\", \"mult\" ],\n" + - " \"testFailures\" : [ ]\n" + - " } ],\n" + - " \"compilationErrors\" : [ ]\n" + - "}") - .replaceAll("\\n|\\r\\n", System.getProperty("line.separator")))); - } - - @Test - @Ignore - public void corruptedZipTest() throws Exception { - - File file = new File(Thread.currentThread().getContextClassLoader().getResource("corrupted.zip").getFile()); - MockMultipartFile mockFile = new MockMultipartFile("unitTestFile", new FileInputStream(file)); - - mockMvc.perform(MockMvcRequestBuilders.fileUpload("/v1/unittest") - .file(mockFile) - .param("assignmentId", "222")) - .andExpect(status().is(400)); - } - - @Test - @Ignore - public void renamedTxtFileTest() throws Exception { - - File file = new File(Thread.currentThread().getContextClassLoader().getResource("textfile.zip").getFile()); - MockMultipartFile mockFile = new MockMultipartFile("unitTestFile", new FileInputStream(file)); - - mockMvc.perform(MockMvcRequestBuilders.fileUpload("/v1/unittest") - .file(mockFile) - .param("assignmentId", "333")) - .andExpect(status().is(400)); - - } - - @Test - @Ignore - public void noAssignmentIdTest() throws Exception { - - File file = new File(Thread.currentThread().getContextClassLoader().getResource("textfile.zip").getFile()); - MockMultipartFile mockFile = new MockMultipartFile("unitTestFile", new FileInputStream(file)); - - mockMvc.perform(MockMvcRequestBuilders.fileUpload("/v1/unittest") - .file(mockFile)) - .andExpect(status().is(400)); - - } - -} diff --git a/src/test/resources/corrupted.zip b/src/test/resources/corrupted.zip deleted file mode 100644 index c1a3499985e71dca75b4ff39881101774c0962e9..0000000000000000000000000000000000000000 Binary files a/src/test/resources/corrupted.zip and /dev/null differ diff --git a/src/test/resources/tasks.zip b/src/test/resources/tasks.zip deleted file mode 100644 index 8010049bbfecb50ab67c3a5cea8cec4b938b380a..0000000000000000000000000000000000000000 Binary files a/src/test/resources/tasks.zip and /dev/null differ diff --git a/src/test/resources/tests.zip b/src/test/resources/tests.zip deleted file mode 100644 index f3690a0624e6aafb6e5dc0bdbf96fe838763ac7d..0000000000000000000000000000000000000000 Binary files a/src/test/resources/tests.zip and /dev/null differ diff --git a/src/test/resources/textfile.zip b/src/test/resources/textfile.zip deleted file mode 100644 index bc2a4803bf412abea5ca4d88e63bf94ff0598abe..0000000000000000000000000000000000000000 --- a/src/test/resources/textfile.zip +++ /dev/null @@ -1,3 +0,0 @@ - -asdfsadfasdf -asdfasdfsadf