From 50d4d12e88cb76b920ff939158fe2557f9ef22b3 Mon Sep 17 00:00:00 2001 From: Gavin Date: Thu, 11 Apr 2024 09:58:30 -0700 Subject: [PATCH 01/21] Convert to GHA, fix tests --- .classpath | 18 ++-- .codecov.yml | 30 ------- .github/codeql.yml | 52 +++++++++++ .github/dependabot.yml | 14 +++ .github/workflows/manual-build.yml | 11 +++ .github/workflows/pr_build.yml | 43 +++++++++ .github/workflows/release-main.yml | 25 ++++++ .github/workflows/test.yml | 87 +++++++++++++++++++ .travis.yml | 51 ----------- LICENSE.md | 2 +- README.md | 3 +- build.xml | 22 +++-- build/build_docker_image.sh | 9 -- build/push2dockerhub.sh | 32 ------- .../GravatarFieldValidatorFactory.java | 3 +- .../GravatarFieldValidatorFactoryTest.java | 2 +- .../integration/ServiceIntegrationTest.java | 1 - src/us/kbase/test/groups/util/UtilTest.java | 26 ++++-- 18 files changed, 282 insertions(+), 149 deletions(-) delete mode 100644 .codecov.yml create mode 100644 .github/codeql.yml create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/manual-build.yml create mode 100644 .github/workflows/pr_build.yml create mode 100644 .github/workflows/release-main.yml create mode 100644 .github/workflows/test.yml delete mode 100644 .travis.yml delete mode 100755 build/build_docker_image.sh delete mode 100755 build/push2dockerhub.sh diff --git a/.classpath b/.classpath index 65f47be6..5bd65dd8 100644 --- a/.classpath +++ b/.classpath @@ -1,7 +1,11 @@ - + + + + + @@ -43,13 +47,7 @@ - - - - - - @@ -59,5 +57,11 @@ + + + + + + diff --git a/.codecov.yml b/.codecov.yml deleted file mode 100644 index 42c0d62b..00000000 --- a/.codecov.yml +++ /dev/null @@ -1,30 +0,0 @@ -codecov: - notify: - require_ci_to_pass: yes - -coverage: - precision: 2 - round: down - range: "70...100" - - status: - project: no - patch: yes - changes: no - -parsers: - gcov: - branch_detection: - conditional: yes - loop: yes - method: no - macro: no - -comment: - layout: "header, diff" - behavior: default - require_changes: no - -ignore: - - "build" - - "deployment" diff --git a/.github/codeql.yml b/.github/codeql.yml new file mode 100644 index 00000000..9771ca0f --- /dev/null +++ b/.github/codeql.yml @@ -0,0 +1,52 @@ +name: "Code scanning - action" + +on: + push: + pull_request: + schedule: + - cron: '0 19 * * 0' + +jobs: + CodeQL-Build: + + # CodeQL runs on ubuntu-latest and windows-latest + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + with: + # We must fetch at least the immediate parents so that if this is + # a pull request then we can checkout the head. + fetch-depth: 2 + + # If this run was triggered by a pull request event, then checkout + # the head of the pull request instead of the merge commit. + - run: git checkout HEAD^2 + if: ${{ github.event_name == 'pull_request' }} + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + # Override language selection by uncommenting this and choosing your languages + # with: + # languages: go, javascript, csharp, python, cpp, java + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + # ℹī¸ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..2659fed2 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,14 @@ +version: 2 +updates: +- package-ecosystem: docker + directory: "/" + schedule: + interval: weekly + time: '11:00' + open-pull-requests-limit: 10 +- package-ecosystem: pip + directory: "/" + schedule: + interval: daily + time: '11:00' + open-pull-requests-limit: 10 diff --git a/.github/workflows/manual-build.yml b/.github/workflows/manual-build.yml new file mode 100644 index 00000000..944f9035 --- /dev/null +++ b/.github/workflows/manual-build.yml @@ -0,0 +1,11 @@ +--- +name: Manual Build & Push +on: + workflow_dispatch: +jobs: + build-push: + uses: kbase/.github/.github/workflows/reusable_build-push.yml@main + with: + name: '${{ github.event.repository.name }}-develop' + tags: br-${{ github.ref_name }} + secrets: inherit diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml new file mode 100644 index 00000000..0fa1c464 --- /dev/null +++ b/.github/workflows/pr_build.yml @@ -0,0 +1,43 @@ +--- +name: Pull Request Build, Tag, & Push +on: + pull_request: + branches: + - develop + - main + - master + types: + - opened + - reopened + - synchronize + - closed +jobs: + build-develop-open: + if: github.base_ref == 'develop' && github.event.pull_request.merged == false + uses: kbase/.github/.github/workflows/reusable_build.yml@main + secrets: inherit + build-develop-merge: + if: github.base_ref == 'develop' && github.event.pull_request.merged == true + uses: kbase/.github/.github/workflows/reusable_build-push.yml@main + with: + name: '${{ github.event.repository.name }}-develop' + tags: pr-${{ github.event.number }},latest + secrets: inherit + build-main-open: + if: (github.base_ref == 'main' || github.base_ref == 'master') && github.event.pull_request.merged == false + uses: kbase/.github/.github/workflows/reusable_build-push.yml@main + with: + name: '${{ github.event.repository.name }}' + tags: pr-${{ github.event.number }} + secrets: inherit + build-main-merge: + if: (github.base_ref == 'main' || github.base_ref == 'master') && github.event.pull_request.merged == true + uses: kbase/.github/.github/workflows/reusable_build-push.yml@main + with: + name: '${{ github.event.repository.name }}' + tags: pr-${{ github.event.number }},latest-rc + secrets: inherit + trivy-scans: + if: (github.base_ref == 'develop' || github.base_ref == 'main' || github.base_ref == 'master' ) && github.event.pull_request.merged == false + uses: kbase/.github/.github/workflows/reusable_trivy-scans.yml@main + secrets: inherit diff --git a/.github/workflows/release-main.yml b/.github/workflows/release-main.yml new file mode 100644 index 00000000..a2546781 --- /dev/null +++ b/.github/workflows/release-main.yml @@ -0,0 +1,25 @@ +--- +name: Release - Build & Push Image +on: + release: + branches: + - main + - master + types: [ published ] +jobs: + check-source-branch: + uses: kbase/.github/.github/workflows/reusable_validate-branch.yml@main + with: + build_branch: '${{ github.event.release.target_commitish }}' + validate-release-tag: + needs: check-source-branch + uses: kbase/.github/.github/workflows/reusable_validate-release-tag.yml@main + with: + release_tag: '${{ github.event.release.tag_name }}' + build-push: + needs: validate-release-tag + uses: kbase/.github/.github/workflows/reusable_build-push.yml@main + with: + name: '${{ github.event.repository.name }}' + tags: '${{ github.event.release.tag_name }},latest' + secrets: inherit diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..e74cb73e --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,87 @@ +name: KBase Groups tests + +on: + pull_request: + types: + - opened + - reopened + - synchronize + - ready_for_review + push: + # run workflow when merging to main or develop + branches: + - main + - master + - develop + +jobs: + + groups_tests: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + # the current production setup + - java: '8' + codecov: true + mongo: 'mongodb-linux-x86_64-3.6.13' + wired_tiger: 'false' + ant_test: 'test' + # test all code w/ java 11 + - java: '11' + codecov: true + mongo: 'mongodb-linux-x86_64-3.6.13' + wired_tiger: 'false' + ant_test: 'test' + # test the latest 3X version of mongo against just the mongo storage code + - java: '11' + mongo: 'mongodb-linux-x86_64-3.6.23' + wired_tiger: 'true' + ant_test: 'test_mongo_storage' + steps: + - uses: actions/checkout@v3 + + - name: Set up java + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: ${{matrix.java}} + + - name: Install dependencies and set up test config + shell: bash + run: | + export HOMEDIR=`pwd` + + # move to parent dir of homedir to install binaries etc + cd .. + + # set up jars + git clone https://github.com/kbase/jars + export JARSDIR=$(pwd)/jars/lib/jars/ + + # set up mongo + wget -q http://fastdl.mongodb.org/linux/${{matrix.mongo}}.tgz + tar xfz ${{matrix.mongo}}.tgz + export MONGOD=`pwd`/${{matrix.mongo}}/bin/mongod + + # set up test config + cd $HOMEDIR + cp -n test.cfg.example test.cfg + sed -i "s#^test.jars.dir.*#test.jars.dir=$JARSDIR#" test.cfg + sed -i "s#^test.temp.dir =.*#test.temp.dir=temp_test_dir#" test.cfg + sed -i "s#^test.mongo.exe.*#test.mongo.exe=$MONGOD#" test.cfg + sed -i "s#^test.mongo.useWiredTiger.*#test.mongo.useWiredTiger=${{matrix.wired_tiger}}#" test.cfg + cat test.cfg + + - name: Run tests + shell: bash + run: | + ant ${{matrix.ant_test}} + + - name: Upload coverage to Codecov + if: matrix.include.codecov + uses: codecov/codecov-action@v3 + with: + token: ${{ secrets.CODECOV_TOKEN }} + fail_ci_if_error: true diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 46211e94..00000000 --- a/.travis.yml +++ /dev/null @@ -1,51 +0,0 @@ -dist: trusty -sudo: required -language: java -jdk: - - openjdk8 - - oraclejdk8 -env: - - MONGODB_VER=mongodb-linux-x86_64-2.6.12 ANT_TEST=test WIRED_TIGER=false - - MONGODB_VER=mongodb-linux-x86_64-3.4.18 ANT_TEST=test_mongo_storage WIRED_TIGER=false - - MONGODB_VER=mongodb-linux-x86_64-3.4.18 ANT_TEST=test_mongo_storage WIRED_TIGER=true - - MONGODB_VER=mongodb-linux-x86_64-3.6.8 ANT_TEST=test_mongo_storage WIRED_TIGER=false - - MONGODB_VER=mongodb-linux-x86_64-3.6.8 ANT_TEST=test_mongo_storage WIRED_TIGER=true - -before_install: - - sudo apt-get -qq update - - sudo apt-get install -y ant-optional - -install: - - cd .. - - git clone https://github.com/kbase/jars - - export JARSDIR=`pwd`/jars/lib/jars/ - - cd - - -script: - - cd .. - - wget http://fastdl.mongodb.org/linux/$MONGODB_VER.tgz - - tar xfz $MONGODB_VER.tgz - - export MONGOD=`pwd`/$MONGODB_VER/bin/mongod - - cd - - - cp -n test.cfg.example test.cfg - - sed -i "s#^test.temp.dir=.*#test.temp.dir=temp_test_dir#" test.cfg - - sed -i "s#^test.mongo.exe.*#test.mongo.exe=$MONGOD#" test.cfg - - sed -i "s#^test.mongo.wired_tiger.*#test.mongo.wired_tiger=$WIRED_TIGER#" test.cfg - - sed -i "s#^test.jars.dir=.*#test.jars.dir=$JARSDIR#" test.cfg - - cat test.cfg - - ant $ANT_TEST - -jobs: - include: - - stage: deploy - env: # The following are secure declarations for DOCKER_USER, DOCKER_PASS - - secure: "FOUsz7GwzqjxmoaB2kAQ7T+5twy4F844ApklMSgRynemayqsEWhuEzygXQ+QwLO426s39QtqNgkwYkhTvfInzf+wpUMmTr4tXu0ljYueiEWDOE8CA5FjkPe10e6UWlTqfKPj9jZv2JMc0N3S8evRVTO4UeGjg70gk00QrPsxU7c5gxt7zrabQ0aBXFFswfbnrVcEZXwyqKYOszUxeI7n2bRkLtUSgpKgluPYOcRu8YN51G5yUakC/eHqXM7MtivzTA/fQNbQSB3Ga8O7EmT7zZrpVHPpjEQBkRAhiQLgxNJaoQsRTh31qmj4S0r2/i6fSb2CJftVu2OmlbuQHHyJJvliR6rFTdPKDMXYWTJ7zGjgT5K5DUb96Yix+vEi1lq48mKfjqy+akeqC6z9mXHXZc4aCaLVCOHKCsttH0tUZ+Mb4akfjFFZeVsQ0NTMskfDSisyMniZffAA3A0qRPhgQVFw1F4CeiOabjXBn1K4pLLtbx4lYFrmRPV89umYKOJXV9yt5pPA69dTgJqaUTAdvA1MoKgZ5OzEUzxcVLQlQi+nxUKcBOac705s2rfYuo5yEbrbHrIshBq6cMTgoEzgOfja9Mm6pdL8pmcxp1MyiVcOtvQjHgJ2RWb1TbdKar4ZHVs1U1DsEeB4u/C+o02yVfJBqufFPUxEc74cn7pMMuE=" - - secure: "XOdfRLxVxIwJxiwC0aiSGfzgNZVKXajqqil6mINuwuCTZAsGTvEyGsU9uy0QTsgjwIrg4USV3TQ0mEo74yQuUPBNKRUImn8ChKIsWkqY+8qbzm40WXQNZ/0DAM+NZ7vtrSXtNfP6Kvy8ffkntYt2zbUCAZDl5hyYzXL0WuAUWnINmwJ3SBTPPYbyvezSW9R1dTsL1xmY63exwqD8ebUslRRcRp3ssSnyLZ24kdqkWiCfbTvELqZkK4xhJ3WhNU0uTe7NHXZD0RDpNUOkHpFOuDJQvcYbp39ua3BpA6Atqtdhnz7n/kDj3osiKnAnDMtVdWodWePE2fOkXGlYobR0kGf2YXPIM4eH+3XstMb8XewmbqQeYPHs/y2Fn8bi7VlCjcvKNGUrEutit0nVINb1le86az08/Sf2wvpyOawTuGugJOdw1rRrEV6Eo1dM4DotIcYaywSP8R+GVh9fNb4rHIWaVq5jJT3rs55xe73417dVUDNcGg6qJ/sHvgxGorulVmKWzZrv6tTLpdq4+YNVzdQ71iD9rJqPbEWChVDDdtURjoW18jNynz4AVSDmzBFeWJobNnAxVpqn/2MlLEvCzar1X9w7dyp4KBTbLCb+1s5ZfJzO29tiaXSMrKLLbYsB5BTfHeMhQMy6m+jl26Z791zdatPZG7mL3ir9sdUAhXo=" - script: # Only push to dockerhub if this isn't a PR and we're updating master or develop - - docker pull kbase/kb_jre - - ant docker_image - - IMAGE_NAME=kbase/groups build/push2dockerhub.sh -after_success: - - ls test-reports - - bash <(curl -s https://codecov.io/bash) -f test-reports/coverage-report.xml - diff --git a/LICENSE.md b/LICENSE.md index a1fa12dc..deafd790 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,4 +1,4 @@ -Copyright (c) 2018 The KBase Project and its Contributors +Copyright (c) 2018-present The KBase Project and its Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/README.md b/README.md index 6f080d65..215d9ff7 100644 --- a/README.md +++ b/README.md @@ -943,7 +943,8 @@ field--param-image-exists=<'true' or any other value for false> ``` `strict-length` will cause the validator to throw an error if the field is not exactly 32 -characters, and is false by default. Gravatar allows for extra characters at the end of the hash. +characters, and is false by default. In some cases (such as adding a `.jpg` extension) +Gravatar allows for extra characters at the end of the hash. `image-exists` will cause the validator to throw an error if there is no [image associated with the hash (see Default Image)](https://en.gravatar.com/site/implement/images/), and is false diff --git a/build.xml b/build.xml index a97e42f7..39084fd0 100644 --- a/build.xml +++ b/build.xml @@ -91,19 +91,18 @@ - + - - + - - - - + + + + @@ -219,7 +218,14 @@ - + + + + + + + + diff --git a/build/build_docker_image.sh b/build/build_docker_image.sh deleted file mode 100755 index 1a43bcf5..00000000 --- a/build/build_docker_image.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -x - -export BRANCH=${TRAVIS_BRANCH:-`git symbolic-ref --short HEAD`} -export DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` -export COMMIT=${TRAVIS_COMMIT:-`git rev-parse --short HEAD`} -docker build --build-arg BUILD_DATE=$DATE \ - --build-arg VCS_REF=$COMMIT \ - --build-arg BRANCH=$BRANCH \ - -t kbase/groups:$COMMIT . diff --git a/build/push2dockerhub.sh b/build/push2dockerhub.sh deleted file mode 100755 index 1b37e11c..00000000 --- a/build/push2dockerhub.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash -# -# This script is intended to be run in the deploy stage of a travis build -# It checks to make sure that this is a not a PR, and that we have the secure -# environment variables available and then checks if this is either the master -# or develop branch, otherwise we don't push anything -# -# NOTE: IMAGE_NAME is expected to be passed in via the environment so that this -# script can be more general -# -# sychan@lbl.gov -# 8/31/2017 - -TAG=`if [ "$TRAVIS_BRANCH" == "master" ]; then echo "latest"; else echo $TRAVIS_BRANCH ; fi` -COMMIT=${TRAVIS_COMMIT:-`git rev-parse --short HEAD`} - -if ( [ "$TRAVIS_SECURE_ENV_VARS" == "true" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] ); then - # $TAG was set from TRAVIS_BRANCH, which is a little wonky on pull requests, - # but it should be okay since we should never get here on a PR - if ( [ "$TAG" == "latest" ] || [ "$TAG" == "develop" ] ) ; then - echo "Logging into Dockerhub as $DOCKER_USER" - docker login -u $DOCKER_USER -p $DOCKER_PASS && \ - docker tag $IMAGE_NAME:$COMMIT $IMAGE_NAME:$TAG && \ - echo "Pushing $IMAGE_NAME:$TAG" && \ - docker push $IMAGE_NAME:$TAG || \ - ( echo "Failed to login and push tagged image" && exit 1 ) - else - echo "Not pushing image for branch $TAG" - fi -else - echo "Not building image for pull requests or if secure variables unavailable" -fi diff --git a/src/us/kbase/groups/fieldvalidators/GravatarFieldValidatorFactory.java b/src/us/kbase/groups/fieldvalidators/GravatarFieldValidatorFactory.java index 42753665..718deb02 100644 --- a/src/us/kbase/groups/fieldvalidators/GravatarFieldValidatorFactory.java +++ b/src/us/kbase/groups/fieldvalidators/GravatarFieldValidatorFactory.java @@ -22,7 +22,8 @@ /** Validates that a gravatar hash is a valid MD5. * Include "strict-length": "true" in the configuration to enforce an exact 32 character MD5. - * If omitted, any extra characters are ignored (which is what Gravatar does). + * If omitted, any extra characters are ignored. This may will likely cause the validation to fail + * if "image-exists" is true and Gravatar doesn't know how to process the extra characters. * Include "image-exists": "true" in the configuration to enforce that an image is associated * with the hash (see Default Image section at https://en.gravatar.com/site/implement/images/). diff --git a/src/us/kbase/test/groups/fieldvalidators/GravatarFieldValidatorFactoryTest.java b/src/us/kbase/test/groups/fieldvalidators/GravatarFieldValidatorFactoryTest.java index da5d19c5..04c756b9 100644 --- a/src/us/kbase/test/groups/fieldvalidators/GravatarFieldValidatorFactoryTest.java +++ b/src/us/kbase/test/groups/fieldvalidators/GravatarFieldValidatorFactoryTest.java @@ -53,7 +53,7 @@ public void validateWithAccount() throws Exception { // if there's no error, the test passes v.validate(KNOWN_GOOD); // check that extra characters pass - v.validate(KNOWN_GOOD + "Z"); + v.validate(KNOWN_GOOD + ".jpg"); } @Test diff --git a/src/us/kbase/test/groups/integration/ServiceIntegrationTest.java b/src/us/kbase/test/groups/integration/ServiceIntegrationTest.java index 3837f0d6..4c8fbd5e 100644 --- a/src/us/kbase/test/groups/integration/ServiceIntegrationTest.java +++ b/src/us/kbase/test/groups/integration/ServiceIntegrationTest.java @@ -110,7 +110,6 @@ public static void beforeClass() throws Exception { // set up auth AUTH = new AuthController( - TestCommon.getJarsDir(), "localhost:" + MANAGER.mongo.getServerPort(), "GroupsServiceIntgrationTestAuth", TEMP_DIR); diff --git a/src/us/kbase/test/groups/util/UtilTest.java b/src/us/kbase/test/groups/util/UtilTest.java index be39ca18..f7d69178 100644 --- a/src/us/kbase/test/groups/util/UtilTest.java +++ b/src/us/kbase/test/groups/util/UtilTest.java @@ -1,6 +1,8 @@ package us.kbase.test.groups.util; import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.startsWith; +import static org.hamcrest.CoreMatchers.endsWith; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; @@ -229,13 +231,23 @@ FieldValidatorFactory.class, new GroupsConfigurationException( @Test public void loadClassWithInterfaceFailPrivateConstructor() throws Exception { - failLoadClassWithInterface(FailOnInstantiationPrivateConstructor.class.getName(), - FieldValidatorFactory.class, new GroupsConfigurationException( - "Module us.kbase.test.groups.util.FailOnInstantiation" + - "PrivateConstructor could not be instantiated: Class us.kbase.groups." + - "util.Util can not access a member of class us." + - "kbase.test.groups.util.FailOnInstantiationPrivateConstructor " + - "with modifiers \"private\"")); + try { + Util.loadClassWithInterface( + FailOnInstantiationPrivateConstructor.class.getName(), + FieldValidatorFactory.class); + fail("expected exception"); + } catch (GroupsConfigurationException got) { + assertThat("incorrect exception message", got.getMessage(), startsWith( + "Module us.kbase.test.groups.util.FailOnInstantiation" + + "PrivateConstructor could not be instantiated: " + )); + // trivial text changes from java 8 -> 11 + assertThat("incorrect exception message", got.getMessage(), endsWith( + "not access a member of class us." + + "kbase.test.groups.util.FailOnInstantiationPrivateConstructor " + + "with modifiers \"private\"" + )); + } } private void failLoadClassWithInterface( From 96b8a15f3768a3462e92a9295ac62efd781fd869 Mon Sep 17 00:00:00 2001 From: Gavin Date: Thu, 11 Apr 2024 10:10:37 -0700 Subject: [PATCH 02/21] Fix tests attempt 1 --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e74cb73e..38eb90ee 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -69,7 +69,7 @@ jobs: cd $HOMEDIR cp -n test.cfg.example test.cfg sed -i "s#^test.jars.dir.*#test.jars.dir=$JARSDIR#" test.cfg - sed -i "s#^test.temp.dir =.*#test.temp.dir=temp_test_dir#" test.cfg + sed -i "s#^test.temp.dir.*#test.temp.dir=temp_test_dir#" test.cfg sed -i "s#^test.mongo.exe.*#test.mongo.exe=$MONGOD#" test.cfg sed -i "s#^test.mongo.useWiredTiger.*#test.mongo.useWiredTiger=${{matrix.wired_tiger}}#" test.cfg cat test.cfg From 99a436cec36ddaa083bd11eead646759c38965ca Mon Sep 17 00:00:00 2001 From: Gavin Date: Thu, 11 Apr 2024 10:18:40 -0700 Subject: [PATCH 03/21] Fix tests attempt 2 --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 38eb90ee..3dbed854 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -69,7 +69,7 @@ jobs: cd $HOMEDIR cp -n test.cfg.example test.cfg sed -i "s#^test.jars.dir.*#test.jars.dir=$JARSDIR#" test.cfg - sed -i "s#^test.temp.dir.*#test.temp.dir=temp_test_dir#" test.cfg + sed -i "s#^test.temp.dir=.*#test.temp.dir=temp_test_dir#" test.cfg sed -i "s#^test.mongo.exe.*#test.mongo.exe=$MONGOD#" test.cfg sed -i "s#^test.mongo.useWiredTiger.*#test.mongo.useWiredTiger=${{matrix.wired_tiger}}#" test.cfg cat test.cfg From faffb27d40ae71e84f89db4045956bbfb3323fda Mon Sep 17 00:00:00 2001 From: Gavin Date: Thu, 11 Apr 2024 10:23:22 -0700 Subject: [PATCH 04/21] Fix codecov attempt #1 --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3dbed854..945d77d6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -80,7 +80,7 @@ jobs: ant ${{matrix.ant_test}} - name: Upload coverage to Codecov - if: matrix.include.codecov + if: matrix.codecov uses: codecov/codecov-action@v3 with: token: ${{ secrets.CODECOV_TOKEN }} From 25aafbe7e6c51cdda2110c255be8581689151c4d Mon Sep 17 00:00:00 2001 From: Gavin Date: Thu, 11 Apr 2024 14:51:47 -0700 Subject: [PATCH 05/21] Fix docker build --- Dockerfile | 14 ++++++++++---- docker-compose.yml | 46 ++++++++++------------------------------------ 2 files changed, 20 insertions(+), 40 deletions(-) diff --git a/Dockerfile b/Dockerfile index 78909750..103b3461 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,11 @@ +FROM kbase/sdkbase2 as build + +COPY . /tmp/groups +RUN cd /tmp \ + && git clone https://github.com/kbase/jars \ + && cd groups \ + && ant buildwar + FROM kbase/kb_jre:latest # These ARGs values are passed in via the docker build command @@ -5,10 +13,8 @@ ARG BUILD_DATE ARG VCS_REF ARG BRANCH=develop -RUN apt-get -y update && apt-get -y install ant git openjdk-8-jdk - -COPY deployment/ /kb/deployment/ -COPY jettybase/ /kb/deployment/jettybase/ +COPY --from=build /tmp/groups/deployment/ /kb/deployment/ +COPY --from=build /tmp/groups/jettybase/ /kb/deployment/jettybase/ # The BUILD_DATE value seem to bust the docker cache when the timestamp changes, move to # the end diff --git a/docker-compose.yml b/docker-compose.yml index beb4b9b3..2aaed1b7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,15 +5,18 @@ version: "3.1" # that is started up and polled services: kbase_groups: - image: kbase/groups:latest + build: . ports: - "8080:8080" environment: - mongo-host: localhost:27017 - mongo-db: dc_groups_test + mongo_host: "mongo:27017" + mongo_db: dc_groups_test auth_url: https://ci.kbase.us/services/auth workspace_url: https://ci.kbase.us/services/ws + catalog_url: https://ci.kbase.us/services/catalog + notifier_url: https://ci.kbase.us/services/feeds workspace_admin_token: faketoken_replace + notifier_token: faketoken_replace field_validator_configs: | field-foo-validator=us.kbase.groups.fieldvalidators.SimpleFieldValidatorFactory field-foo-is-numbered=true @@ -21,9 +24,7 @@ services: command: - "-multiline" - "-wait" - - "tcp://ci-mongo:27017" - - "-wait" - - "tcp://mongoinit:8080" + - "tcp://mongo:27017" - "-timeout" - "120s" - "-template" @@ -32,37 +33,10 @@ services: - "-Djetty.home=/usr/local/jetty" - "-jar" - "/usr/local/jetty/start.jar" - # If you needed to pass in context for template evaluation you would put something like - # these lines that tell dockerize to hit github for an INI style file for the context - # - "-env" - # - "https://raw.githubusercontent.com/kbase/mini_kb/master/deployment/conf/tauth2-minikb.yml" - # If the -env URL needs authentication you would use an -env-header directive that specified - # either the hard coded string for the header, or a path to a file that contains the header - # string ( used for working with docker secrets files) - # - "-env-header" - # - "AUTHORIZATION:authtokenvalue" - # or for a path to a secrets file: - # - "env-header" - # - "/run/secrets/authheader" - # If your server is using self-signed certs, or otherwise problematic for cert validation - # you can add the following flag: - # - "-validateCert=false" - depends_on: ["ci-mongo", "mongoinit"] + depends_on: ["mongo"] - mongoinit: - image: kbase/db_initialize:latest - entrypoint: - - "/kb/deployment/bin/dockerize.sh" - - "-wait" - - "tcp://ci-mongo:27017" - - "-timeout" - - "120s" - depends_on: [ "ci-mongo" ] - - ci-mongo: - image: mongo:2 - command: - - "--smallfiles" + mongo: + image: mongo:3.6 ports: - "27017:27017" From fdb619000c4d89ff3201fe7363a0edcc88874558 Mon Sep 17 00:00:00 2001 From: Gavin Date: Fri, 12 Apr 2024 20:56:57 -0700 Subject: [PATCH 06/21] Switch from Ant to Gradle --- .gitattributes | 9 + .github/workflows/test.yml | 19 +- Dockerfile | 27 +- RELEASE_NOTES.md | 4 + build.gradle | 167 +++++++++ build.xml | 361 ------------------- gradle/libs.versions.toml | 2 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 43453 bytes gradle/wrapper/gradle-wrapper.properties | 7 + gradlew | 249 +++++++++++++ settings.gradle | 8 + src/us/kbase/groups/config/GroupsConfig.java | 1 + 12 files changed, 472 insertions(+), 382 deletions(-) create mode 100644 .gitattributes create mode 100644 build.gradle delete mode 100644 build.xml create mode 100644 gradle/libs.versions.toml create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 settings.gradle diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..097f9f98 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,9 @@ +# +# https://help.github.com/articles/dealing-with-line-endings/ +# +# Linux start script should use lf +/gradlew text eol=lf + +# These are Windows script files and should use crlf +*.bat text eol=crlf + diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 945d77d6..079d5c0d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -24,21 +24,14 @@ jobs: include: # the current production setup - java: '8' - codecov: true mongo: 'mongodb-linux-x86_64-3.6.13' wired_tiger: 'false' - ant_test: 'test' + gradle_test: 'test' # test all code w/ java 11 - - java: '11' - codecov: true - mongo: 'mongodb-linux-x86_64-3.6.13' - wired_tiger: 'false' - ant_test: 'test' - # test the latest 3X version of mongo against just the mongo storage code - java: '11' mongo: 'mongodb-linux-x86_64-3.6.23' wired_tiger: 'true' - ant_test: 'test_mongo_storage' + gradle_test: 'test' steps: - uses: actions/checkout@v3 @@ -56,10 +49,6 @@ jobs: # move to parent dir of homedir to install binaries etc cd .. - # set up jars - git clone https://github.com/kbase/jars - export JARSDIR=$(pwd)/jars/lib/jars/ - # set up mongo wget -q http://fastdl.mongodb.org/linux/${{matrix.mongo}}.tgz tar xfz ${{matrix.mongo}}.tgz @@ -68,7 +57,6 @@ jobs: # set up test config cd $HOMEDIR cp -n test.cfg.example test.cfg - sed -i "s#^test.jars.dir.*#test.jars.dir=$JARSDIR#" test.cfg sed -i "s#^test.temp.dir=.*#test.temp.dir=temp_test_dir#" test.cfg sed -i "s#^test.mongo.exe.*#test.mongo.exe=$MONGOD#" test.cfg sed -i "s#^test.mongo.useWiredTiger.*#test.mongo.useWiredTiger=${{matrix.wired_tiger}}#" test.cfg @@ -77,10 +65,9 @@ jobs: - name: Run tests shell: bash run: | - ant ${{matrix.ant_test}} + gradle ${{matrix.gradle_test}} - name: Upload coverage to Codecov - if: matrix.codecov uses: codecov/codecov-action@v3 with: token: ${{ secrets.CODECOV_TOKEN }} diff --git a/Dockerfile b/Dockerfile index 103b3461..fd2899b7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,23 @@ FROM kbase/sdkbase2 as build -COPY . /tmp/groups -RUN cd /tmp \ - && git clone https://github.com/kbase/jars \ - && cd groups \ - && ant buildwar +WORKDIR /tmp/groups + +# dependencies take a while to D/L, so D/L & cache before the build so code changes don't cause +# a new D/L +# can't glob *gradle because of the .gradle dir +COPY build.gradle gradlew settings.gradle /tmp/groups/ +COPY gradle/ /tmp/groups/gradle/ +RUN ./gradlew dependencies + +# Now build the code +COPY deployment/ /tmp/groups/deployment/ +COPY jettybase/ /tmp/groups/jettybase/ +COPY src /tmp/groups/src/ +COPY war /tmp/groups/war/ +# for the git commit +COPY .git /tmp/groups/.git/ +RUN ./gradlew war + FROM kbase/kb_jre:latest @@ -15,6 +28,7 @@ ARG BRANCH=develop COPY --from=build /tmp/groups/deployment/ /kb/deployment/ COPY --from=build /tmp/groups/jettybase/ /kb/deployment/jettybase/ +COPY --from=build /tmp/groups/build/libs/groups.war /kb/deployment/jettybase/webapps/ROOT.war # The BUILD_DATE value seem to bust the docker cache when the timestamp changes, move to # the end @@ -30,6 +44,9 @@ ENV KB_DEPLOYMENT_CONFIG=/kb/deployment/conf/deployment.cfg RUN chmod -R a+rwx /kb/deployment/conf /kb/deployment/jettybase/ +# TODO BUILD update to no longer use dockerize and take env vars (e.g. like Collections). +# TODO BUILD Use subsections in the ini file / switch to TOML + ENTRYPOINT [ "/kb/deployment/bin/dockerize" ] # Here are some default params passed to dockerize. They would typically diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 6973d6b2..67576215 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,9 @@ # KBase Groups Service release notes +## 0.1.7 + +* The build tool has been switched from Ant to Gradle. + ## 0.1.6 ### Admin notes: diff --git a/build.gradle b/build.gradle new file mode 100644 index 00000000..7365ba76 --- /dev/null +++ b/build.gradle @@ -0,0 +1,167 @@ +/* + * This file was generated by the Gradle 'init' task. + */ + +plugins { + id 'java' + id 'war' + id 'jacoco' + id 'org.ajoberstar.grgit' version '4.1.1' +} + +// TODO NOW run tests from Eclipse w/o specifying classpath manually & remove sourceSets & classpath +// TODO NOW update any ant refs in docs to gradle + +repositories { + mavenCentral() +} + +task buildGitCommitFile { + doLast { + def commitId = grgit.head().id + // is there a variable for builddir/classes/java/main? + file("$buildDir/classes/java/main/us/kbase/groups/gitcommit").text = commitId + } +} + +compileJava { + // TODO BUILD remove when we no longer support java 8, use `options.release = 11` if needed + java.sourceCompatibility = JavaVersion.VERSION_1_8 + java.targetCompatibility = JavaVersion.VERSION_1_8 + finalizedBy buildGitCommitFile +} + +test { + /* + * TODO TEST Figure out why tests fail without this and remove. Might have something to do + * with the stfuLoggers() call in many of the tests, might kill logging for tests that + * require it + * Although it seems to make Mongo start up correctly as well which is odd + */ + forkEvery = 1 + /* + * TODO TEST split mongo wrapper tests out. + * Set up GHA to run the full test suite with a single version of mongo and run the + * mongo tests with matrixed mongo versions. + * Since the tests only take a minute or two this isn't high ROI. + */ + systemProperty "KBASE_GROUPS_TEST_CONFIG", "./test.cfg" + maxHeapSize = "3G" + testLogging { + exceptionFormat = 'full' + showStandardStreams = true + } + finalizedBy jacocoTestReport +} + +// TODO TEST add a test that starts the server in a docker container and checks some simple cmds + +jacocoTestReport { + reports { + xml.required = true + csv.required = true + } +} + +war { + webXml = file('war/web.xml') +} + +// Custom java project layout +sourceSets { + main { + java { + srcDirs = ["src"] + exclude '**/test/**' + } + } + test { + java { + srcDirs = ["src"] + include '**/test/**' + } + resources { + srcDirs = ["src"] + include "**/*wsjars" + } + } +} + +configurations { + // can't directly access testImplementation, so extend and access + testimpl.extendsFrom testImplementation +} + +def fromURL = { url, name -> + File file = new File("$buildDir/download/${name}.jar") + file.parentFile.mkdirs() + if (!file.exists()) { + new URL(url).withInputStream { downloadStream -> + file.withOutputStream { fileOut -> + fileOut << downloadStream + } + } + } + files(file.absolutePath) +} + +dependencies { + + compileOnly 'javax.servlet:javax.servlet-api:3.0.1' + + implementation fromURL( + 'https://github.com/kbase/jars/raw/master/lib/jars/kbase/auth/kbase-auth-0.4.4.jar', + 'kbase-auth-0.4.4' + ) + implementation fromURL( + 'https://github.com/kbase/jars/raw/master/lib/jars/kbase/workspace/WorkspaceClient-0.8.0.jar', + 'WorkspaceClient-0.8.0' + ) + implementation fromURL( + 'https://github.com/kbase/jars/raw/master/lib/jars/kbase/catalog/kbase-catalog-client-2.1.3.jar', + 'kbase-catalog-client-2.1.3' + ) + implementation fromURL( + 'https://github.com/kbase/jars/raw/master/lib/jars/kbase/common/kbase-common-0.0.25.jar', + 'kbase-common-0.0.25' + ) + // Pull from jars repo vs a maven repository to avoid the JNA dependency + // TODO DEPS Need to rework the java common logger to not use syslog4j at all since it's abandonware + // and has a ton of CVEs, even in the newer versions. + implementation fromURL( + 'https://github.com/kbase/jars/raw/master/lib/jars/syslog4j/syslog4j-0.9.46.jar', + 'syslog4j-0.9.46' + ) + implementation 'ch.qos.logback:logback-classic:1.1.2' + implementation 'org.ini4j:ini4j:0.5.2' + implementation 'org.mongodb:mongo-java-driver:3.8.2' + implementation 'org.apache.kafka:kafka-clients:2.1.0' + implementation 'com.google.guava:guava:18.0' + implementation 'org.slf4j:slf4j-api:1.7.25' + implementation 'com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:2.5.4' + implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.5.4' + implementation 'org.glassfish.jersey.containers:jersey-container-servlet:2.23.2' + implementation 'org.glassfish.jersey.media:jersey-media-json-jackson:2.23.2' + implementation 'com.github.zafarkhaja:java-semver:0.9.0' + + testImplementation fromURL( + 'https://github.com/kbase/jars/raw/master/lib/jars/kbase/auth2/kbase-auth2-test-shadow-all-0.7.0.jar', + 'kbase-auth2-test-shadow-all-0.7.0' + ) + testImplementation 'nl.jqno.equalsverifier:equalsverifier:3.1.10' + testImplementation 'junit:junit:4.12' + testImplementation 'org.mockito:mockito-core:3.0.0' + testImplementation('org.mock-server:mockserver-netty:5.4.1') { + // otherwise a newer jackson implementation is brought in and tests make a poo poo + // TODO BUILD on upgrade switch to the no dependencies version + exclude group: "com.fasterxml.jackson.core" + } + testImplementation 'org.eclipse.jetty:jetty-servlet:9.3.11.v20160721' +} + +task showTestClassPath { + doLast { + configurations.testimpl.each { println it } + } +} + diff --git a/build.xml b/build.xml deleted file mode 100644 index 39084fd0..00000000 --- a/build.xml +++ /dev/null @@ -1,361 +0,0 @@ - - - - Build file for the KBase Groups Service - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 00000000..4ac3234a --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,2 @@ +# This file was generated by the Gradle 'init' task. +# https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..e6441136f3d4ba8a0da8d277868979cfbc8ad796 GIT binary patch literal 43453 zcma&N1CXTcmMvW9vTb(Rwr$&4wr$(C?dmSu>@vG-+vuvg^_??!{yS%8zW-#zn-LkA z5&1^$^{lnmUON?}LBF8_K|(?T0Ra(xUH{($5eN!MR#ZihR#HxkUPe+_R8Cn`RRs(P z_^*#_XlXmGv7!4;*Y%p4nw?{bNp@UZHv1?Um8r6)Fei3p@ClJn0ECfg1hkeuUU@Or zDaPa;U3fE=3L}DooL;8f;P0ipPt0Z~9P0)lbStMS)ag54=uL9ia-Lm3nh|@(Y?B`; zx_#arJIpXH!U{fbCbI^17}6Ri*H<>OLR%c|^mh8+)*h~K8Z!9)DPf zR2h?lbDZQ`p9P;&DQ4F0sur@TMa!Y}S8irn(%d-gi0*WxxCSk*A?3lGh=gcYN?FGl z7D=Js!i~0=u3rox^eO3i@$0=n{K1lPNU zwmfjRVmLOCRfe=seV&P*1Iq=^i`502keY8Uy-WNPwVNNtJFx?IwAyRPZo2Wo1+S(xF37LJZ~%i)kpFQ3Fw=mXfd@>%+)RpYQLnr}B~~zoof(JVm^^&f zxKV^+3D3$A1G;qh4gPVjhrC8e(VYUHv#dy^)(RoUFM?o%W-EHxufuWf(l*@-l+7vt z=l`qmR56K~F|v<^Pd*p~1_y^P0P^aPC##d8+HqX4IR1gu+7w#~TBFphJxF)T$2WEa zxa?H&6=Qe7d(#tha?_1uQys2KtHQ{)Qco)qwGjrdNL7thd^G5i8Os)CHqc>iOidS} z%nFEDdm=GXBw=yXe1W-ShHHFb?Cc70+$W~z_+}nAoHFYI1MV1wZegw*0y^tC*s%3h zhD3tN8b=Gv&rj}!SUM6|ajSPp*58KR7MPpI{oAJCtY~JECm)*m_x>AZEu>DFgUcby z1Qaw8lU4jZpQ_$;*7RME+gq1KySGG#Wql>aL~k9tLrSO()LWn*q&YxHEuzmwd1?aAtI zBJ>P=&$=l1efe1CDU;`Fd+_;&wI07?V0aAIgc(!{a z0Jg6Y=inXc3^n!U0Atk`iCFIQooHqcWhO(qrieUOW8X(x?(RD}iYDLMjSwffH2~tB z)oDgNBLB^AJBM1M^c5HdRx6fBfka`(LD-qrlh5jqH~);#nw|iyp)()xVYak3;Ybik z0j`(+69aK*B>)e_p%=wu8XC&9e{AO4c~O1U`5X9}?0mrd*m$_EUek{R?DNSh(=br# z#Q61gBzEpmy`$pA*6!87 zSDD+=@fTY7<4A?GLqpA?Pb2z$pbCc4B4zL{BeZ?F-8`s$?>*lXXtn*NC61>|*w7J* z$?!iB{6R-0=KFmyp1nnEmLsA-H0a6l+1uaH^g%c(p{iT&YFrbQ$&PRb8Up#X3@Zsk zD^^&LK~111%cqlP%!_gFNa^dTYT?rhkGl}5=fL{a`UViaXWI$k-UcHJwmaH1s=S$4 z%4)PdWJX;hh5UoK?6aWoyLxX&NhNRqKam7tcOkLh{%j3K^4Mgx1@i|Pi&}<^5>hs5 zm8?uOS>%)NzT(%PjVPGa?X%`N2TQCKbeH2l;cTnHiHppPSJ<7y-yEIiC!P*ikl&!B z%+?>VttCOQM@ShFguHVjxX^?mHX^hSaO_;pnyh^v9EumqSZTi+#f&_Vaija0Q-e*| z7ulQj6Fs*bbmsWp{`auM04gGwsYYdNNZcg|ph0OgD>7O}Asn7^Z=eI>`$2*v78;sj-}oMoEj&@)9+ycEOo92xSyY344^ z11Hb8^kdOvbf^GNAK++bYioknrpdN>+u8R?JxG=!2Kd9r=YWCOJYXYuM0cOq^FhEd zBg2puKy__7VT3-r*dG4c62Wgxi52EMCQ`bKgf*#*ou(D4-ZN$+mg&7$u!! z-^+Z%;-3IDwqZ|K=ah85OLwkO zKxNBh+4QHh)u9D?MFtpbl)us}9+V!D%w9jfAMYEb>%$A;u)rrI zuBudh;5PN}_6J_}l55P3l_)&RMlH{m!)ai-i$g)&*M`eN$XQMw{v^r@-125^RRCF0 z^2>|DxhQw(mtNEI2Kj(;KblC7x=JlK$@78`O~>V!`|1Lm-^JR$-5pUANAnb(5}B}JGjBsliK4& zk6y(;$e&h)lh2)L=bvZKbvh@>vLlreBdH8No2>$#%_Wp1U0N7Ank!6$dFSi#xzh|( zRi{Uw%-4W!{IXZ)fWx@XX6;&(m_F%c6~X8hx=BN1&q}*( zoaNjWabE{oUPb!Bt$eyd#$5j9rItB-h*5JiNi(v^e|XKAj*8(k<5-2$&ZBR5fF|JA z9&m4fbzNQnAU}r8ab>fFV%J0z5awe#UZ|bz?Ur)U9bCIKWEzi2%A+5CLqh?}K4JHi z4vtM;+uPsVz{Lfr;78W78gC;z*yTch~4YkLr&m-7%-xc ztw6Mh2d>_iO*$Rd8(-Cr1_V8EO1f*^@wRoSozS) zy1UoC@pruAaC8Z_7~_w4Q6n*&B0AjOmMWa;sIav&gu z|J5&|{=a@vR!~k-OjKEgPFCzcJ>#A1uL&7xTDn;{XBdeM}V=l3B8fE1--DHjSaxoSjNKEM9|U9#m2<3>n{Iuo`r3UZp;>GkT2YBNAh|b z^jTq-hJp(ebZh#Lk8hVBP%qXwv-@vbvoREX$TqRGTgEi$%_F9tZES@z8Bx}$#5eeG zk^UsLBH{bc2VBW)*EdS({yw=?qmevwi?BL6*=12k9zM5gJv1>y#ML4!)iiPzVaH9% zgSImetD@dam~e>{LvVh!phhzpW+iFvWpGT#CVE5TQ40n%F|p(sP5mXxna+Ev7PDwA zamaV4m*^~*xV+&p;W749xhb_X=$|LD;FHuB&JL5?*Y2-oIT(wYY2;73<^#46S~Gx| z^cez%V7x$81}UWqS13Gz80379Rj;6~WdiXWOSsdmzY39L;Hg3MH43o*y8ibNBBH`(av4|u;YPq%{R;IuYow<+GEsf@R?=@tT@!}?#>zIIn0CoyV!hq3mw zHj>OOjfJM3F{RG#6ujzo?y32m^tgSXf@v=J$ELdJ+=5j|=F-~hP$G&}tDZsZE?5rX ztGj`!S>)CFmdkccxM9eGIcGnS2AfK#gXwj%esuIBNJQP1WV~b~+D7PJTmWGTSDrR` zEAu4B8l>NPuhsk5a`rReSya2nfV1EK01+G!x8aBdTs3Io$u5!6n6KX%uv@DxAp3F@{4UYg4SWJtQ-W~0MDb|j-$lwVn znAm*Pl!?Ps&3wO=R115RWKb*JKoexo*)uhhHBncEDMSVa_PyA>k{Zm2(wMQ(5NM3# z)jkza|GoWEQo4^s*wE(gHz?Xsg4`}HUAcs42cM1-qq_=+=!Gk^y710j=66(cSWqUe zklbm8+zB_syQv5A2rj!Vbw8;|$@C!vfNmNV!yJIWDQ>{+2x zKjuFX`~~HKG~^6h5FntRpnnHt=D&rq0>IJ9#F0eM)Y-)GpRjiN7gkA8wvnG#K=q{q z9dBn8_~wm4J<3J_vl|9H{7q6u2A!cW{bp#r*-f{gOV^e=8S{nc1DxMHFwuM$;aVI^ zz6A*}m8N-&x8;aunp1w7_vtB*pa+OYBw=TMc6QK=mbA-|Cf* zvyh8D4LRJImooUaSb7t*fVfih<97Gf@VE0|z>NcBwBQze);Rh!k3K_sfunToZY;f2 z^HmC4KjHRVg+eKYj;PRN^|E0>Gj_zagfRbrki68I^#~6-HaHg3BUW%+clM1xQEdPYt_g<2K+z!$>*$9nQ>; zf9Bei{?zY^-e{q_*|W#2rJG`2fy@{%6u0i_VEWTq$*(ZN37|8lFFFt)nCG({r!q#9 z5VK_kkSJ3?zOH)OezMT{!YkCuSSn!K#-Rhl$uUM(bq*jY? zi1xbMVthJ`E>d>(f3)~fozjg^@eheMF6<)I`oeJYx4*+M&%c9VArn(OM-wp%M<-`x z7sLP1&3^%Nld9Dhm@$3f2}87!quhI@nwd@3~fZl_3LYW-B?Ia>ui`ELg z&Qfe!7m6ze=mZ`Ia9$z|ARSw|IdMpooY4YiPN8K z4B(ts3p%2i(Td=tgEHX z0UQ_>URBtG+-?0E;E7Ld^dyZ;jjw0}XZ(}-QzC6+NN=40oDb2^v!L1g9xRvE#@IBR zO!b-2N7wVfLV;mhEaXQ9XAU+>=XVA6f&T4Z-@AX!leJ8obP^P^wP0aICND?~w&NykJ#54x3_@r7IDMdRNy4Hh;h*!u(Ol(#0bJdwEo$5437-UBjQ+j=Ic>Q2z` zJNDf0yO6@mr6y1#n3)s(W|$iE_i8r@Gd@!DWDqZ7J&~gAm1#~maIGJ1sls^gxL9LLG_NhU!pTGty!TbhzQnu)I*S^54U6Yu%ZeCg`R>Q zhBv$n5j0v%O_j{QYWG!R9W?5_b&67KB$t}&e2LdMvd(PxN6Ir!H4>PNlerpBL>Zvyy!yw z-SOo8caEpDt(}|gKPBd$qND5#a5nju^O>V&;f890?yEOfkSG^HQVmEbM3Ugzu+UtH zC(INPDdraBN?P%kE;*Ae%Wto&sgw(crfZ#Qy(<4nk;S|hD3j{IQRI6Yq|f^basLY; z-HB&Je%Gg}Jt@={_C{L$!RM;$$|iD6vu#3w?v?*;&()uB|I-XqEKqZPS!reW9JkLewLb!70T7n`i!gNtb1%vN- zySZj{8-1>6E%H&=V}LM#xmt`J3XQoaD|@XygXjdZ1+P77-=;=eYpoEQ01B@L*a(uW zrZeZz?HJsw_4g0vhUgkg@VF8<-X$B8pOqCuWAl28uB|@r`19DTUQQsb^pfqB6QtiT z*`_UZ`fT}vtUY#%sq2{rchyfu*pCg;uec2$-$N_xgjZcoumE5vSI{+s@iLWoz^Mf; zuI8kDP{!XY6OP~q5}%1&L}CtfH^N<3o4L@J@zg1-mt{9L`s^z$Vgb|mr{@WiwAqKg zp#t-lhrU>F8o0s1q_9y`gQNf~Vb!F%70f}$>i7o4ho$`uciNf=xgJ>&!gSt0g;M>*x4-`U)ysFW&Vs^Vk6m%?iuWU+o&m(2Jm26Y(3%TL; zA7T)BP{WS!&xmxNw%J=$MPfn(9*^*TV;$JwRy8Zl*yUZi8jWYF>==j~&S|Xinsb%c z2?B+kpet*muEW7@AzjBA^wAJBY8i|#C{WtO_or&Nj2{=6JTTX05}|H>N2B|Wf!*3_ z7hW*j6p3TvpghEc6-wufFiY!%-GvOx*bZrhZu+7?iSrZL5q9}igiF^*R3%DE4aCHZ zqu>xS8LkW+Auv%z-<1Xs92u23R$nk@Pk}MU5!gT|c7vGlEA%G^2th&Q*zfg%-D^=f z&J_}jskj|Q;73NP4<4k*Y%pXPU2Thoqr+5uH1yEYM|VtBPW6lXaetokD0u z9qVek6Q&wk)tFbQ8(^HGf3Wp16gKmr>G;#G(HRBx?F`9AIRboK+;OfHaLJ(P>IP0w zyTbTkx_THEOs%Q&aPrxbZrJlio+hCC_HK<4%f3ZoSAyG7Dn`=X=&h@m*|UYO-4Hq0 z-Bq&+Ie!S##4A6OGoC~>ZW`Y5J)*ouaFl_e9GA*VSL!O_@xGiBw!AF}1{tB)z(w%c zS1Hmrb9OC8>0a_$BzeiN?rkPLc9%&;1CZW*4}CDDNr2gcl_3z+WC15&H1Zc2{o~i) z)LLW=WQ{?ricmC`G1GfJ0Yp4Dy~Ba;j6ZV4r{8xRs`13{dD!xXmr^Aga|C=iSmor% z8hi|pTXH)5Yf&v~exp3o+sY4B^^b*eYkkCYl*T{*=-0HniSA_1F53eCb{x~1k3*`W zr~};p1A`k{1DV9=UPnLDgz{aJH=-LQo<5%+Em!DNN252xwIf*wF_zS^!(XSm(9eoj z=*dXG&n0>)_)N5oc6v!>-bd(2ragD8O=M|wGW z!xJQS<)u70m&6OmrF0WSsr@I%T*c#Qo#Ha4d3COcX+9}hM5!7JIGF>7<~C(Ear^Sn zm^ZFkV6~Ula6+8S?oOROOA6$C&q&dp`>oR-2Ym3(HT@O7Sd5c~+kjrmM)YmgPH*tL zX+znN>`tv;5eOfX?h{AuX^LK~V#gPCu=)Tigtq9&?7Xh$qN|%A$?V*v=&-2F$zTUv z`C#WyIrChS5|Kgm_GeudCFf;)!WH7FI60j^0o#65o6`w*S7R@)88n$1nrgU(oU0M9 zx+EuMkC>(4j1;m6NoGqEkpJYJ?vc|B zOlwT3t&UgL!pX_P*6g36`ZXQ; z9~Cv}ANFnJGp(;ZhS(@FT;3e)0)Kp;h^x;$*xZn*k0U6-&FwI=uOGaODdrsp-!K$Ac32^c{+FhI-HkYd5v=`PGsg%6I`4d9Jy)uW0y%) zm&j^9WBAp*P8#kGJUhB!L?a%h$hJgQrx!6KCB_TRo%9{t0J7KW8!o1B!NC)VGLM5! zpZy5Jc{`r{1e(jd%jsG7k%I+m#CGS*BPA65ZVW~fLYw0dA-H_}O zrkGFL&P1PG9p2(%QiEWm6x;U-U&I#;Em$nx-_I^wtgw3xUPVVu zqSuKnx&dIT-XT+T10p;yjo1Y)z(x1fb8Dzfn8e yu?e%!_ptzGB|8GrCfu%p?(_ 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
NnX)EH+Nua)3Y(c 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 '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +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 + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 00000000..751f4065 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,8 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * The settings file is used to specify which projects to include in your build. + * For more detailed information on multi-project builds, please refer to https://docs.gradle.org/8.7/userguide/multi_project_builds.html in the Gradle documentation. + */ + +rootProject.name = 'groups' diff --git a/src/us/kbase/groups/config/GroupsConfig.java b/src/us/kbase/groups/config/GroupsConfig.java index ef1213fa..b752f09b 100644 --- a/src/us/kbase/groups/config/GroupsConfig.java +++ b/src/us/kbase/groups/config/GroupsConfig.java @@ -133,6 +133,7 @@ private GroupsConfig( logger = new NullLogger(); } else { // may want to allow configuring the logger name, but YAGNI + JsonServerSyslog.setStaticUseSyslog(false); logger = new JsonServerSysLogAutoLogger(new JsonServerSyslog( LOG_NAME, null, JsonServerSyslog.LOG_LEVEL_INFO, true)); } From 644f76ba7c0dcfad20b4c7c8ed8ebadf1b25a053 Mon Sep 17 00:00:00 2001 From: Gavin Date: Mon, 15 Apr 2024 14:34:51 -0700 Subject: [PATCH 07/21] Can't get rid of jars until we swap to the new workspace controller --- .github/workflows/test.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 079d5c0d..b27498cc 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -49,6 +49,10 @@ jobs: # move to parent dir of homedir to install binaries etc cd .. + # set up jars + git clone https://github.com/kbase/jars + export JARSDIR=$(pwd)/jars/lib/jars/ + # set up mongo wget -q http://fastdl.mongodb.org/linux/${{matrix.mongo}}.tgz tar xfz ${{matrix.mongo}}.tgz @@ -57,6 +61,7 @@ jobs: # set up test config cd $HOMEDIR cp -n test.cfg.example test.cfg + sed -i "s#^test.jars.dir.*#test.jars.dir=$JARSDIR#" test.cfg sed -i "s#^test.temp.dir=.*#test.temp.dir=temp_test_dir#" test.cfg sed -i "s#^test.mongo.exe.*#test.mongo.exe=$MONGOD#" test.cfg sed -i "s#^test.mongo.useWiredTiger.*#test.mongo.useWiredTiger=${{matrix.wired_tiger}}#" test.cfg From 16a9afbb52817891d80386eca9d81ba02c989ebe Mon Sep 17 00:00:00 2001 From: Gavin Date: Fri, 12 Apr 2024 21:15:11 -0700 Subject: [PATCH 08/21] Use standard Gradle source locations --- .classpath | 67 ------------------- build.gradle | 21 ------ .../java}/us/kbase/groups/GitCommit.java | 0 .../us/kbase/groups/build/GroupsBuilder.java | 0 .../SDKClientCatalogHandler.java | 0 .../us/kbase/groups/config/GroupsConfig.java | 0 .../config/GroupsConfigurationException.java | 0 .../kbase/groups/core/CreateAndModTimes.java | 0 .../groups/core/CreateModAndExpireTimes.java | 0 .../java}/us/kbase/groups/core/FieldItem.java | 0 .../us/kbase/groups/core/GetGroupsParams.java | 0 .../kbase/groups/core/GetRequestsParams.java | 0 .../java}/us/kbase/groups/core/Group.java | 0 .../groups/core/GroupCreationParams.java | 0 .../kbase/groups/core/GroupHasRequests.java | 0 .../java}/us/kbase/groups/core/GroupID.java | 0 .../us/kbase/groups/core/GroupIDAndName.java | 0 .../groups/core/GroupIDNameMembership.java | 0 .../java}/us/kbase/groups/core/GroupName.java | 0 .../kbase/groups/core/GroupUpdateParams.java | 0 .../java}/us/kbase/groups/core/GroupUser.java | 0 .../java}/us/kbase/groups/core/GroupView.java | 0 .../java}/us/kbase/groups/core/Groups.java | 0 .../java}/us/kbase/groups/core/Name.java | 0 .../groups/core/OptionalGroupFields.java | 0 .../us/kbase/groups/core/OptionalString.java | 0 .../java}/us/kbase/groups/core/Token.java | 0 .../us/kbase/groups/core/UUIDGenerator.java | 0 .../us/kbase/groups/core/UserHandler.java | 0 .../java}/us/kbase/groups/core/UserName.java | 0 .../exceptions/AuthenticationException.java | 0 .../exceptions/ClosedRequestException.java | 0 .../groups/core/exceptions/ErrorType.java | 0 .../core/exceptions/GroupExistsException.java | 0 .../core/exceptions/GroupsException.java | 0 .../exceptions/IllegalParameterException.java | 0 .../IllegalResourceIDException.java | 0 .../exceptions/InvalidTokenException.java | 0 .../exceptions/MissingParameterException.java | 0 .../core/exceptions/NoDataException.java | 0 .../NoSuchCustomFieldException.java | 0 .../core/exceptions/NoSuchGroupException.java | 0 .../exceptions/NoSuchRequestException.java | 0 .../exceptions/NoSuchResourceException.java | 0 .../NoSuchResourceTypeException.java | 0 .../core/exceptions/NoSuchUserException.java | 0 .../exceptions/NoTokenProvidedException.java | 0 .../exceptions/RequestExistsException.java | 0 .../exceptions/ResourceExistsException.java | 0 .../exceptions/ResourceHandlerException.java | 0 .../exceptions/UnauthorizedException.java | 0 .../exceptions/UserIsMemberException.java | 0 .../core/fieldvalidation/CustomField.java | 0 .../fieldvalidation/FieldConfiguration.java | 0 .../core/fieldvalidation/FieldValidator.java | 0 .../FieldValidatorConfiguration.java | 0 .../FieldValidatorException.java | 0 .../FieldValidatorFactory.java | 0 .../core/fieldvalidation/FieldValidators.java | 0 .../IllegalFieldValueException.java | 0 .../fieldvalidation/NumberedCustomField.java | 0 .../core/notifications/Notifications.java | 0 .../notifications/NotificationsFactory.java | 0 .../groups/core/request/GroupRequest.java | 0 .../core/request/GroupRequestStatus.java | 0 .../core/request/GroupRequestStatusType.java | 0 .../core/request/GroupRequestUserAction.java | 0 .../core/request/GroupRequestWithActions.java | 0 .../kbase/groups/core/request/RequestID.java | 0 .../groups/core/request/RequestType.java | 0 .../groups/core/resource/ResourceAccess.java | 0 .../resource/ResourceAdministrativeID.java | 0 .../core/resource/ResourceDescriptor.java | 0 .../groups/core/resource/ResourceHandler.java | 0 .../groups/core/resource/ResourceID.java | 0 .../core/resource/ResourceInformation.java | 0 .../core/resource/ResourceInformationSet.java | 0 .../groups/core/resource/ResourceType.java | 0 .../EnumFieldValidatorFactory.java | 0 .../GravatarFieldValidatorFactory.java | 0 .../SimpleFieldValidatorFactory.java | 0 .../DirectFeedsServiceNotifierFactory.java | 0 .../KafkaFeedsNotifierFactory.java | 0 .../notifications/SLF4JNotifierFactory.java | 0 .../groups/service/AppEventListener.java | 0 .../java}/us/kbase/groups/service/Fields.java | 0 .../kbase/groups/service/GroupsService.java | 0 .../kbase/groups/service/JacksonFeature.java | 0 .../kbase/groups/service/LoggingFilter.java | 0 .../kbase/groups/service/SLF4JAutoLogger.java | 0 .../kbase/groups/service/api/APICommon.java | 0 .../groups/service/api/APIConstants.java | 0 .../us/kbase/groups/service/api/Fields.java | 0 .../kbase/groups/service/api/GroupsAPI.java | 0 .../groups/service/api/IncomingJSON.java | 0 .../kbase/groups/service/api/MemberAPI.java | 0 .../us/kbase/groups/service/api/NamesAPI.java | 0 .../kbase/groups/service/api/RequestAPI.java | 0 .../us/kbase/groups/service/api/Root.java | 0 .../groups/service/api/ServicePaths.java | 0 .../service/exceptions/ErrorMessage.java | 0 .../service/exceptions/ExceptionHandler.java | 0 .../kbase/groups/storage/GroupsStorage.java | 0 .../exceptions/GroupsStorageException.java | 0 .../exceptions/StorageInitException.java | 0 .../us/kbase/groups/storage/mongo/Fields.java | 0 .../storage/mongo/MongoGroupsStorage.java | 0 .../groups/userhandler/KBaseUserHandler.java | 0 .../us/kbase/groups/util/FileOpener.java | 0 .../java}/us/kbase/groups/util/Util.java | 0 .../SDKClientWorkspaceHandler.java | 0 .../workspacehandler/WorkspacePermission.java | 0 .../us/kbase/test/groups/MapBuilder.java | 0 .../test/groups/MongoStorageTestManager.java | 0 .../test/groups/StandaloneGroupsServer.java | 0 .../us/kbase/test/groups/TestCommon.java | 0 .../SDKClientCatalogHandlerTest.java | 0 .../test/groups/config/GroupsConfigTest.java | 0 .../workspace/WorkspaceController.java | 0 .../groups/core/CreateModExpireTimesTest.java | 0 .../kbase/test/groups/core/FieldItemTest.java | 0 .../test/groups/core/GetGroupsParamsTest.java | 0 .../groups/core/GetRequestParamsTest.java | 0 .../groups/core/GroupCreationParamsTest.java | 0 .../groups/core/GroupHasRequestsTest.java | 0 .../test/groups/core/GroupIDAndNameTest.java | 0 .../core/GroupIDNameMembershipTest.java | 0 .../kbase/test/groups/core/GroupIDTest.java | 0 .../kbase/test/groups/core/GroupNameTest.java | 0 .../us/kbase/test/groups/core/GroupTest.java | 0 .../groups/core/GroupUpdateParamsTest.java | 0 .../kbase/test/groups/core/GroupUserTest.java | 0 .../kbase/test/groups/core/GroupViewTest.java | 0 .../us/kbase/test/groups/core/GroupsTest.java | 0 .../us/kbase/test/groups/core/NameTest.java | 0 .../groups/core/OptionalGroupFieldsTest.java | 0 .../test/groups/core/OptionalStringTest.java | 0 .../us/kbase/test/groups/core/TokenTest.java | 0 .../kbase/test/groups/core/UserNameTest.java | 0 .../core/fieldvalidation/CustomFieldTest.java | 0 .../FieldConfigurationTest.java | 0 .../FieldValidatorConfigurationTest.java | 0 .../fieldvalidation/FieldValidatorsTest.java | 0 .../NumberedCustomFieldTest.java | 0 .../core/request/GroupRequestStatusTest.java | 0 .../request/GroupRequestStatusTypeTest.java | 0 .../groups/core/request/GroupRequestTest.java | 0 .../request/GroupRequestUserActionTest.java | 0 .../request/GroupRequestWithActionsTest.java | 0 .../groups/core/request/RequestIDTest.java | 0 .../groups/core/request/RequestTypeTest.java | 0 .../groups/core/resource/ResourceIDTest.java | 0 .../resource/ResourceInformationSetTest.java | 0 .../resource/ResourceInformationTest.java | 0 .../core/resource/ResourceTypeTest.java | 0 .../EnumFieldValidatorFactoryTest.java | 0 .../GravatarFieldValidatorFactoryTest.java | 0 .../SimpleFieldValidatorFactoryTest.java | 0 .../integration/ServiceIntegrationTest.java | 0 .../KafkaFeedsNotifierFactoryTest.java | 0 .../groups/service/LoggingFilterTest.java | 0 .../groups/service/api/APICommonTest.java | 0 .../groups/service/api/GroupsAPITest.java | 0 .../groups/service/api/IncomingJSONTest.java | 0 .../groups/service/api/MemberAPITest.java | 0 .../test/groups/service/api/NamesAPITest.java | 0 .../groups/service/api/RequestAPITest.java | 0 .../test/groups/service/api/RootTest.java | 0 .../service/exceptions/ErrorMessageTest.java | 0 .../exceptions/ExceptionHandlerTest.java | 0 ...oGroupsStorageDuplicateKeyCheckerTest.java | 0 .../mongo/MongoGroupsStorageOpsTest.java | 0 .../mongo/MongoGroupsStorageStartupTest.java | 0 .../test/groups/util/FailOnInstantiation.java | 0 ...ilOnInstantiationNoNullaryConstructor.java | 0 ...FailOnInstantiationPrivateConstructor.java | 0 .../us/kbase/test/groups/util/UtilTest.java | 0 .../SDKClientWorkspaceHandlerTest.java | 0 .../WorkspacePermissionTest.java | 0 .../test/groups/controllers/workspace/wsjars | 0 180 files changed, 88 deletions(-) delete mode 100644 .classpath rename src/{ => main/java}/us/kbase/groups/GitCommit.java (100%) rename src/{ => main/java}/us/kbase/groups/build/GroupsBuilder.java (100%) rename src/{ => main/java}/us/kbase/groups/cataloghandler/SDKClientCatalogHandler.java (100%) rename src/{ => main/java}/us/kbase/groups/config/GroupsConfig.java (100%) rename src/{ => main/java}/us/kbase/groups/config/GroupsConfigurationException.java (100%) rename src/{ => main/java}/us/kbase/groups/core/CreateAndModTimes.java (100%) rename src/{ => main/java}/us/kbase/groups/core/CreateModAndExpireTimes.java (100%) rename src/{ => main/java}/us/kbase/groups/core/FieldItem.java (100%) rename src/{ => main/java}/us/kbase/groups/core/GetGroupsParams.java (100%) rename src/{ => main/java}/us/kbase/groups/core/GetRequestsParams.java (100%) rename src/{ => main/java}/us/kbase/groups/core/Group.java (100%) rename src/{ => main/java}/us/kbase/groups/core/GroupCreationParams.java (100%) rename src/{ => main/java}/us/kbase/groups/core/GroupHasRequests.java (100%) rename src/{ => main/java}/us/kbase/groups/core/GroupID.java (100%) rename src/{ => main/java}/us/kbase/groups/core/GroupIDAndName.java (100%) rename src/{ => main/java}/us/kbase/groups/core/GroupIDNameMembership.java (100%) rename src/{ => main/java}/us/kbase/groups/core/GroupName.java (100%) rename src/{ => main/java}/us/kbase/groups/core/GroupUpdateParams.java (100%) rename src/{ => main/java}/us/kbase/groups/core/GroupUser.java (100%) rename src/{ => main/java}/us/kbase/groups/core/GroupView.java (100%) rename src/{ => main/java}/us/kbase/groups/core/Groups.java (100%) rename src/{ => main/java}/us/kbase/groups/core/Name.java (100%) rename src/{ => main/java}/us/kbase/groups/core/OptionalGroupFields.java (100%) rename src/{ => main/java}/us/kbase/groups/core/OptionalString.java (100%) rename src/{ => main/java}/us/kbase/groups/core/Token.java (100%) rename src/{ => main/java}/us/kbase/groups/core/UUIDGenerator.java (100%) rename src/{ => main/java}/us/kbase/groups/core/UserHandler.java (100%) rename src/{ => main/java}/us/kbase/groups/core/UserName.java (100%) rename src/{ => main/java}/us/kbase/groups/core/exceptions/AuthenticationException.java (100%) rename src/{ => main/java}/us/kbase/groups/core/exceptions/ClosedRequestException.java (100%) rename src/{ => main/java}/us/kbase/groups/core/exceptions/ErrorType.java (100%) rename src/{ => main/java}/us/kbase/groups/core/exceptions/GroupExistsException.java (100%) rename src/{ => main/java}/us/kbase/groups/core/exceptions/GroupsException.java (100%) rename src/{ => main/java}/us/kbase/groups/core/exceptions/IllegalParameterException.java (100%) rename src/{ => main/java}/us/kbase/groups/core/exceptions/IllegalResourceIDException.java (100%) rename src/{ => main/java}/us/kbase/groups/core/exceptions/InvalidTokenException.java (100%) rename src/{ => main/java}/us/kbase/groups/core/exceptions/MissingParameterException.java (100%) rename src/{ => main/java}/us/kbase/groups/core/exceptions/NoDataException.java (100%) rename src/{ => main/java}/us/kbase/groups/core/exceptions/NoSuchCustomFieldException.java (100%) rename src/{ => main/java}/us/kbase/groups/core/exceptions/NoSuchGroupException.java (100%) rename src/{ => main/java}/us/kbase/groups/core/exceptions/NoSuchRequestException.java (100%) rename src/{ => main/java}/us/kbase/groups/core/exceptions/NoSuchResourceException.java (100%) rename src/{ => main/java}/us/kbase/groups/core/exceptions/NoSuchResourceTypeException.java (100%) rename src/{ => main/java}/us/kbase/groups/core/exceptions/NoSuchUserException.java (100%) rename src/{ => main/java}/us/kbase/groups/core/exceptions/NoTokenProvidedException.java (100%) rename src/{ => main/java}/us/kbase/groups/core/exceptions/RequestExistsException.java (100%) rename src/{ => main/java}/us/kbase/groups/core/exceptions/ResourceExistsException.java (100%) rename src/{ => main/java}/us/kbase/groups/core/exceptions/ResourceHandlerException.java (100%) rename src/{ => main/java}/us/kbase/groups/core/exceptions/UnauthorizedException.java (100%) rename src/{ => main/java}/us/kbase/groups/core/exceptions/UserIsMemberException.java (100%) rename src/{ => main/java}/us/kbase/groups/core/fieldvalidation/CustomField.java (100%) rename src/{ => main/java}/us/kbase/groups/core/fieldvalidation/FieldConfiguration.java (100%) rename src/{ => main/java}/us/kbase/groups/core/fieldvalidation/FieldValidator.java (100%) rename src/{ => main/java}/us/kbase/groups/core/fieldvalidation/FieldValidatorConfiguration.java (100%) rename src/{ => main/java}/us/kbase/groups/core/fieldvalidation/FieldValidatorException.java (100%) rename src/{ => main/java}/us/kbase/groups/core/fieldvalidation/FieldValidatorFactory.java (100%) rename src/{ => main/java}/us/kbase/groups/core/fieldvalidation/FieldValidators.java (100%) rename src/{ => main/java}/us/kbase/groups/core/fieldvalidation/IllegalFieldValueException.java (100%) rename src/{ => main/java}/us/kbase/groups/core/fieldvalidation/NumberedCustomField.java (100%) rename src/{ => main/java}/us/kbase/groups/core/notifications/Notifications.java (100%) rename src/{ => main/java}/us/kbase/groups/core/notifications/NotificationsFactory.java (100%) rename src/{ => main/java}/us/kbase/groups/core/request/GroupRequest.java (100%) rename src/{ => main/java}/us/kbase/groups/core/request/GroupRequestStatus.java (100%) rename src/{ => main/java}/us/kbase/groups/core/request/GroupRequestStatusType.java (100%) rename src/{ => main/java}/us/kbase/groups/core/request/GroupRequestUserAction.java (100%) rename src/{ => main/java}/us/kbase/groups/core/request/GroupRequestWithActions.java (100%) rename src/{ => main/java}/us/kbase/groups/core/request/RequestID.java (100%) rename src/{ => main/java}/us/kbase/groups/core/request/RequestType.java (100%) rename src/{ => main/java}/us/kbase/groups/core/resource/ResourceAccess.java (100%) rename src/{ => main/java}/us/kbase/groups/core/resource/ResourceAdministrativeID.java (100%) rename src/{ => main/java}/us/kbase/groups/core/resource/ResourceDescriptor.java (100%) rename src/{ => main/java}/us/kbase/groups/core/resource/ResourceHandler.java (100%) rename src/{ => main/java}/us/kbase/groups/core/resource/ResourceID.java (100%) rename src/{ => main/java}/us/kbase/groups/core/resource/ResourceInformation.java (100%) rename src/{ => main/java}/us/kbase/groups/core/resource/ResourceInformationSet.java (100%) rename src/{ => main/java}/us/kbase/groups/core/resource/ResourceType.java (100%) rename src/{ => main/java}/us/kbase/groups/fieldvalidators/EnumFieldValidatorFactory.java (100%) rename src/{ => main/java}/us/kbase/groups/fieldvalidators/GravatarFieldValidatorFactory.java (100%) rename src/{ => main/java}/us/kbase/groups/fieldvalidators/SimpleFieldValidatorFactory.java (100%) rename src/{ => main/java}/us/kbase/groups/notifications/DirectFeedsServiceNotifierFactory.java (100%) rename src/{ => main/java}/us/kbase/groups/notifications/KafkaFeedsNotifierFactory.java (100%) rename src/{ => main/java}/us/kbase/groups/notifications/SLF4JNotifierFactory.java (100%) rename src/{ => main/java}/us/kbase/groups/service/AppEventListener.java (100%) rename src/{ => main/java}/us/kbase/groups/service/Fields.java (100%) rename src/{ => main/java}/us/kbase/groups/service/GroupsService.java (100%) rename src/{ => main/java}/us/kbase/groups/service/JacksonFeature.java (100%) rename src/{ => main/java}/us/kbase/groups/service/LoggingFilter.java (100%) rename src/{ => main/java}/us/kbase/groups/service/SLF4JAutoLogger.java (100%) rename src/{ => main/java}/us/kbase/groups/service/api/APICommon.java (100%) rename src/{ => main/java}/us/kbase/groups/service/api/APIConstants.java (100%) rename src/{ => main/java}/us/kbase/groups/service/api/Fields.java (100%) rename src/{ => main/java}/us/kbase/groups/service/api/GroupsAPI.java (100%) rename src/{ => main/java}/us/kbase/groups/service/api/IncomingJSON.java (100%) rename src/{ => main/java}/us/kbase/groups/service/api/MemberAPI.java (100%) rename src/{ => main/java}/us/kbase/groups/service/api/NamesAPI.java (100%) rename src/{ => main/java}/us/kbase/groups/service/api/RequestAPI.java (100%) rename src/{ => main/java}/us/kbase/groups/service/api/Root.java (100%) rename src/{ => main/java}/us/kbase/groups/service/api/ServicePaths.java (100%) rename src/{ => main/java}/us/kbase/groups/service/exceptions/ErrorMessage.java (100%) rename src/{ => main/java}/us/kbase/groups/service/exceptions/ExceptionHandler.java (100%) rename src/{ => main/java}/us/kbase/groups/storage/GroupsStorage.java (100%) rename src/{ => main/java}/us/kbase/groups/storage/exceptions/GroupsStorageException.java (100%) rename src/{ => main/java}/us/kbase/groups/storage/exceptions/StorageInitException.java (100%) rename src/{ => main/java}/us/kbase/groups/storage/mongo/Fields.java (100%) rename src/{ => main/java}/us/kbase/groups/storage/mongo/MongoGroupsStorage.java (100%) rename src/{ => main/java}/us/kbase/groups/userhandler/KBaseUserHandler.java (100%) rename src/{ => main/java}/us/kbase/groups/util/FileOpener.java (100%) rename src/{ => main/java}/us/kbase/groups/util/Util.java (100%) rename src/{ => main/java}/us/kbase/groups/workspacehandler/SDKClientWorkspaceHandler.java (100%) rename src/{ => main/java}/us/kbase/groups/workspacehandler/WorkspacePermission.java (100%) rename src/{ => test/java}/us/kbase/test/groups/MapBuilder.java (100%) rename src/{ => test/java}/us/kbase/test/groups/MongoStorageTestManager.java (100%) rename src/{ => test/java}/us/kbase/test/groups/StandaloneGroupsServer.java (100%) rename src/{ => test/java}/us/kbase/test/groups/TestCommon.java (100%) rename src/{ => test/java}/us/kbase/test/groups/cataloghandler/SDKClientCatalogHandlerTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/config/GroupsConfigTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/controllers/workspace/WorkspaceController.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/CreateModExpireTimesTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/FieldItemTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/GetGroupsParamsTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/GetRequestParamsTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/GroupCreationParamsTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/GroupHasRequestsTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/GroupIDAndNameTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/GroupIDNameMembershipTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/GroupIDTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/GroupNameTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/GroupTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/GroupUpdateParamsTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/GroupUserTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/GroupViewTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/GroupsTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/NameTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/OptionalGroupFieldsTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/OptionalStringTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/TokenTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/UserNameTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/fieldvalidation/CustomFieldTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/fieldvalidation/FieldConfigurationTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/fieldvalidation/FieldValidatorConfigurationTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/fieldvalidation/FieldValidatorsTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/fieldvalidation/NumberedCustomFieldTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/request/GroupRequestStatusTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/request/GroupRequestStatusTypeTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/request/GroupRequestTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/request/GroupRequestUserActionTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/request/GroupRequestWithActionsTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/request/RequestIDTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/request/RequestTypeTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/resource/ResourceIDTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/resource/ResourceInformationSetTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/resource/ResourceInformationTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/core/resource/ResourceTypeTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/fieldvalidators/EnumFieldValidatorFactoryTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/fieldvalidators/GravatarFieldValidatorFactoryTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/fieldvalidators/SimpleFieldValidatorFactoryTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/integration/ServiceIntegrationTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/notifications/KafkaFeedsNotifierFactoryTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/service/LoggingFilterTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/service/api/APICommonTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/service/api/GroupsAPITest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/service/api/IncomingJSONTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/service/api/MemberAPITest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/service/api/NamesAPITest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/service/api/RequestAPITest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/service/api/RootTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/service/exceptions/ErrorMessageTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/service/exceptions/ExceptionHandlerTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/storage/mongo/MongoGroupsStorageDuplicateKeyCheckerTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/storage/mongo/MongoGroupsStorageOpsTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/storage/mongo/MongoGroupsStorageStartupTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/util/FailOnInstantiation.java (100%) rename src/{ => test/java}/us/kbase/test/groups/util/FailOnInstantiationNoNullaryConstructor.java (100%) rename src/{ => test/java}/us/kbase/test/groups/util/FailOnInstantiationPrivateConstructor.java (100%) rename src/{ => test/java}/us/kbase/test/groups/util/UtilTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/workspacehandler/SDKClientWorkspaceHandlerTest.java (100%) rename src/{ => test/java}/us/kbase/test/groups/workspacehandler/WorkspacePermissionTest.java (100%) rename src/{ => test/resources}/us/kbase/test/groups/controllers/workspace/wsjars (100%) diff --git a/.classpath b/.classpath deleted file mode 100644 index 5bd65dd8..00000000 --- a/.classpath +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build.gradle b/build.gradle index 7365ba76..67319fe0 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,6 @@ plugins { id 'org.ajoberstar.grgit' version '4.1.1' } -// TODO NOW run tests from Eclipse w/o specifying classpath manually & remove sourceSets & classpath // TODO NOW update any ant refs in docs to gradle repositories { @@ -67,26 +66,6 @@ war { webXml = file('war/web.xml') } -// Custom java project layout -sourceSets { - main { - java { - srcDirs = ["src"] - exclude '**/test/**' - } - } - test { - java { - srcDirs = ["src"] - include '**/test/**' - } - resources { - srcDirs = ["src"] - include "**/*wsjars" - } - } -} - configurations { // can't directly access testImplementation, so extend and access testimpl.extendsFrom testImplementation diff --git a/src/us/kbase/groups/GitCommit.java b/src/main/java/us/kbase/groups/GitCommit.java similarity index 100% rename from src/us/kbase/groups/GitCommit.java rename to src/main/java/us/kbase/groups/GitCommit.java diff --git a/src/us/kbase/groups/build/GroupsBuilder.java b/src/main/java/us/kbase/groups/build/GroupsBuilder.java similarity index 100% rename from src/us/kbase/groups/build/GroupsBuilder.java rename to src/main/java/us/kbase/groups/build/GroupsBuilder.java diff --git a/src/us/kbase/groups/cataloghandler/SDKClientCatalogHandler.java b/src/main/java/us/kbase/groups/cataloghandler/SDKClientCatalogHandler.java similarity index 100% rename from src/us/kbase/groups/cataloghandler/SDKClientCatalogHandler.java rename to src/main/java/us/kbase/groups/cataloghandler/SDKClientCatalogHandler.java diff --git a/src/us/kbase/groups/config/GroupsConfig.java b/src/main/java/us/kbase/groups/config/GroupsConfig.java similarity index 100% rename from src/us/kbase/groups/config/GroupsConfig.java rename to src/main/java/us/kbase/groups/config/GroupsConfig.java diff --git a/src/us/kbase/groups/config/GroupsConfigurationException.java b/src/main/java/us/kbase/groups/config/GroupsConfigurationException.java similarity index 100% rename from src/us/kbase/groups/config/GroupsConfigurationException.java rename to src/main/java/us/kbase/groups/config/GroupsConfigurationException.java diff --git a/src/us/kbase/groups/core/CreateAndModTimes.java b/src/main/java/us/kbase/groups/core/CreateAndModTimes.java similarity index 100% rename from src/us/kbase/groups/core/CreateAndModTimes.java rename to src/main/java/us/kbase/groups/core/CreateAndModTimes.java diff --git a/src/us/kbase/groups/core/CreateModAndExpireTimes.java b/src/main/java/us/kbase/groups/core/CreateModAndExpireTimes.java similarity index 100% rename from src/us/kbase/groups/core/CreateModAndExpireTimes.java rename to src/main/java/us/kbase/groups/core/CreateModAndExpireTimes.java diff --git a/src/us/kbase/groups/core/FieldItem.java b/src/main/java/us/kbase/groups/core/FieldItem.java similarity index 100% rename from src/us/kbase/groups/core/FieldItem.java rename to src/main/java/us/kbase/groups/core/FieldItem.java diff --git a/src/us/kbase/groups/core/GetGroupsParams.java b/src/main/java/us/kbase/groups/core/GetGroupsParams.java similarity index 100% rename from src/us/kbase/groups/core/GetGroupsParams.java rename to src/main/java/us/kbase/groups/core/GetGroupsParams.java diff --git a/src/us/kbase/groups/core/GetRequestsParams.java b/src/main/java/us/kbase/groups/core/GetRequestsParams.java similarity index 100% rename from src/us/kbase/groups/core/GetRequestsParams.java rename to src/main/java/us/kbase/groups/core/GetRequestsParams.java diff --git a/src/us/kbase/groups/core/Group.java b/src/main/java/us/kbase/groups/core/Group.java similarity index 100% rename from src/us/kbase/groups/core/Group.java rename to src/main/java/us/kbase/groups/core/Group.java diff --git a/src/us/kbase/groups/core/GroupCreationParams.java b/src/main/java/us/kbase/groups/core/GroupCreationParams.java similarity index 100% rename from src/us/kbase/groups/core/GroupCreationParams.java rename to src/main/java/us/kbase/groups/core/GroupCreationParams.java diff --git a/src/us/kbase/groups/core/GroupHasRequests.java b/src/main/java/us/kbase/groups/core/GroupHasRequests.java similarity index 100% rename from src/us/kbase/groups/core/GroupHasRequests.java rename to src/main/java/us/kbase/groups/core/GroupHasRequests.java diff --git a/src/us/kbase/groups/core/GroupID.java b/src/main/java/us/kbase/groups/core/GroupID.java similarity index 100% rename from src/us/kbase/groups/core/GroupID.java rename to src/main/java/us/kbase/groups/core/GroupID.java diff --git a/src/us/kbase/groups/core/GroupIDAndName.java b/src/main/java/us/kbase/groups/core/GroupIDAndName.java similarity index 100% rename from src/us/kbase/groups/core/GroupIDAndName.java rename to src/main/java/us/kbase/groups/core/GroupIDAndName.java diff --git a/src/us/kbase/groups/core/GroupIDNameMembership.java b/src/main/java/us/kbase/groups/core/GroupIDNameMembership.java similarity index 100% rename from src/us/kbase/groups/core/GroupIDNameMembership.java rename to src/main/java/us/kbase/groups/core/GroupIDNameMembership.java diff --git a/src/us/kbase/groups/core/GroupName.java b/src/main/java/us/kbase/groups/core/GroupName.java similarity index 100% rename from src/us/kbase/groups/core/GroupName.java rename to src/main/java/us/kbase/groups/core/GroupName.java diff --git a/src/us/kbase/groups/core/GroupUpdateParams.java b/src/main/java/us/kbase/groups/core/GroupUpdateParams.java similarity index 100% rename from src/us/kbase/groups/core/GroupUpdateParams.java rename to src/main/java/us/kbase/groups/core/GroupUpdateParams.java diff --git a/src/us/kbase/groups/core/GroupUser.java b/src/main/java/us/kbase/groups/core/GroupUser.java similarity index 100% rename from src/us/kbase/groups/core/GroupUser.java rename to src/main/java/us/kbase/groups/core/GroupUser.java diff --git a/src/us/kbase/groups/core/GroupView.java b/src/main/java/us/kbase/groups/core/GroupView.java similarity index 100% rename from src/us/kbase/groups/core/GroupView.java rename to src/main/java/us/kbase/groups/core/GroupView.java diff --git a/src/us/kbase/groups/core/Groups.java b/src/main/java/us/kbase/groups/core/Groups.java similarity index 100% rename from src/us/kbase/groups/core/Groups.java rename to src/main/java/us/kbase/groups/core/Groups.java diff --git a/src/us/kbase/groups/core/Name.java b/src/main/java/us/kbase/groups/core/Name.java similarity index 100% rename from src/us/kbase/groups/core/Name.java rename to src/main/java/us/kbase/groups/core/Name.java diff --git a/src/us/kbase/groups/core/OptionalGroupFields.java b/src/main/java/us/kbase/groups/core/OptionalGroupFields.java similarity index 100% rename from src/us/kbase/groups/core/OptionalGroupFields.java rename to src/main/java/us/kbase/groups/core/OptionalGroupFields.java diff --git a/src/us/kbase/groups/core/OptionalString.java b/src/main/java/us/kbase/groups/core/OptionalString.java similarity index 100% rename from src/us/kbase/groups/core/OptionalString.java rename to src/main/java/us/kbase/groups/core/OptionalString.java diff --git a/src/us/kbase/groups/core/Token.java b/src/main/java/us/kbase/groups/core/Token.java similarity index 100% rename from src/us/kbase/groups/core/Token.java rename to src/main/java/us/kbase/groups/core/Token.java diff --git a/src/us/kbase/groups/core/UUIDGenerator.java b/src/main/java/us/kbase/groups/core/UUIDGenerator.java similarity index 100% rename from src/us/kbase/groups/core/UUIDGenerator.java rename to src/main/java/us/kbase/groups/core/UUIDGenerator.java diff --git a/src/us/kbase/groups/core/UserHandler.java b/src/main/java/us/kbase/groups/core/UserHandler.java similarity index 100% rename from src/us/kbase/groups/core/UserHandler.java rename to src/main/java/us/kbase/groups/core/UserHandler.java diff --git a/src/us/kbase/groups/core/UserName.java b/src/main/java/us/kbase/groups/core/UserName.java similarity index 100% rename from src/us/kbase/groups/core/UserName.java rename to src/main/java/us/kbase/groups/core/UserName.java diff --git a/src/us/kbase/groups/core/exceptions/AuthenticationException.java b/src/main/java/us/kbase/groups/core/exceptions/AuthenticationException.java similarity index 100% rename from src/us/kbase/groups/core/exceptions/AuthenticationException.java rename to src/main/java/us/kbase/groups/core/exceptions/AuthenticationException.java diff --git a/src/us/kbase/groups/core/exceptions/ClosedRequestException.java b/src/main/java/us/kbase/groups/core/exceptions/ClosedRequestException.java similarity index 100% rename from src/us/kbase/groups/core/exceptions/ClosedRequestException.java rename to src/main/java/us/kbase/groups/core/exceptions/ClosedRequestException.java diff --git a/src/us/kbase/groups/core/exceptions/ErrorType.java b/src/main/java/us/kbase/groups/core/exceptions/ErrorType.java similarity index 100% rename from src/us/kbase/groups/core/exceptions/ErrorType.java rename to src/main/java/us/kbase/groups/core/exceptions/ErrorType.java diff --git a/src/us/kbase/groups/core/exceptions/GroupExistsException.java b/src/main/java/us/kbase/groups/core/exceptions/GroupExistsException.java similarity index 100% rename from src/us/kbase/groups/core/exceptions/GroupExistsException.java rename to src/main/java/us/kbase/groups/core/exceptions/GroupExistsException.java diff --git a/src/us/kbase/groups/core/exceptions/GroupsException.java b/src/main/java/us/kbase/groups/core/exceptions/GroupsException.java similarity index 100% rename from src/us/kbase/groups/core/exceptions/GroupsException.java rename to src/main/java/us/kbase/groups/core/exceptions/GroupsException.java diff --git a/src/us/kbase/groups/core/exceptions/IllegalParameterException.java b/src/main/java/us/kbase/groups/core/exceptions/IllegalParameterException.java similarity index 100% rename from src/us/kbase/groups/core/exceptions/IllegalParameterException.java rename to src/main/java/us/kbase/groups/core/exceptions/IllegalParameterException.java diff --git a/src/us/kbase/groups/core/exceptions/IllegalResourceIDException.java b/src/main/java/us/kbase/groups/core/exceptions/IllegalResourceIDException.java similarity index 100% rename from src/us/kbase/groups/core/exceptions/IllegalResourceIDException.java rename to src/main/java/us/kbase/groups/core/exceptions/IllegalResourceIDException.java diff --git a/src/us/kbase/groups/core/exceptions/InvalidTokenException.java b/src/main/java/us/kbase/groups/core/exceptions/InvalidTokenException.java similarity index 100% rename from src/us/kbase/groups/core/exceptions/InvalidTokenException.java rename to src/main/java/us/kbase/groups/core/exceptions/InvalidTokenException.java diff --git a/src/us/kbase/groups/core/exceptions/MissingParameterException.java b/src/main/java/us/kbase/groups/core/exceptions/MissingParameterException.java similarity index 100% rename from src/us/kbase/groups/core/exceptions/MissingParameterException.java rename to src/main/java/us/kbase/groups/core/exceptions/MissingParameterException.java diff --git a/src/us/kbase/groups/core/exceptions/NoDataException.java b/src/main/java/us/kbase/groups/core/exceptions/NoDataException.java similarity index 100% rename from src/us/kbase/groups/core/exceptions/NoDataException.java rename to src/main/java/us/kbase/groups/core/exceptions/NoDataException.java diff --git a/src/us/kbase/groups/core/exceptions/NoSuchCustomFieldException.java b/src/main/java/us/kbase/groups/core/exceptions/NoSuchCustomFieldException.java similarity index 100% rename from src/us/kbase/groups/core/exceptions/NoSuchCustomFieldException.java rename to src/main/java/us/kbase/groups/core/exceptions/NoSuchCustomFieldException.java diff --git a/src/us/kbase/groups/core/exceptions/NoSuchGroupException.java b/src/main/java/us/kbase/groups/core/exceptions/NoSuchGroupException.java similarity index 100% rename from src/us/kbase/groups/core/exceptions/NoSuchGroupException.java rename to src/main/java/us/kbase/groups/core/exceptions/NoSuchGroupException.java diff --git a/src/us/kbase/groups/core/exceptions/NoSuchRequestException.java b/src/main/java/us/kbase/groups/core/exceptions/NoSuchRequestException.java similarity index 100% rename from src/us/kbase/groups/core/exceptions/NoSuchRequestException.java rename to src/main/java/us/kbase/groups/core/exceptions/NoSuchRequestException.java diff --git a/src/us/kbase/groups/core/exceptions/NoSuchResourceException.java b/src/main/java/us/kbase/groups/core/exceptions/NoSuchResourceException.java similarity index 100% rename from src/us/kbase/groups/core/exceptions/NoSuchResourceException.java rename to src/main/java/us/kbase/groups/core/exceptions/NoSuchResourceException.java diff --git a/src/us/kbase/groups/core/exceptions/NoSuchResourceTypeException.java b/src/main/java/us/kbase/groups/core/exceptions/NoSuchResourceTypeException.java similarity index 100% rename from src/us/kbase/groups/core/exceptions/NoSuchResourceTypeException.java rename to src/main/java/us/kbase/groups/core/exceptions/NoSuchResourceTypeException.java diff --git a/src/us/kbase/groups/core/exceptions/NoSuchUserException.java b/src/main/java/us/kbase/groups/core/exceptions/NoSuchUserException.java similarity index 100% rename from src/us/kbase/groups/core/exceptions/NoSuchUserException.java rename to src/main/java/us/kbase/groups/core/exceptions/NoSuchUserException.java diff --git a/src/us/kbase/groups/core/exceptions/NoTokenProvidedException.java b/src/main/java/us/kbase/groups/core/exceptions/NoTokenProvidedException.java similarity index 100% rename from src/us/kbase/groups/core/exceptions/NoTokenProvidedException.java rename to src/main/java/us/kbase/groups/core/exceptions/NoTokenProvidedException.java diff --git a/src/us/kbase/groups/core/exceptions/RequestExistsException.java b/src/main/java/us/kbase/groups/core/exceptions/RequestExistsException.java similarity index 100% rename from src/us/kbase/groups/core/exceptions/RequestExistsException.java rename to src/main/java/us/kbase/groups/core/exceptions/RequestExistsException.java diff --git a/src/us/kbase/groups/core/exceptions/ResourceExistsException.java b/src/main/java/us/kbase/groups/core/exceptions/ResourceExistsException.java similarity index 100% rename from src/us/kbase/groups/core/exceptions/ResourceExistsException.java rename to src/main/java/us/kbase/groups/core/exceptions/ResourceExistsException.java diff --git a/src/us/kbase/groups/core/exceptions/ResourceHandlerException.java b/src/main/java/us/kbase/groups/core/exceptions/ResourceHandlerException.java similarity index 100% rename from src/us/kbase/groups/core/exceptions/ResourceHandlerException.java rename to src/main/java/us/kbase/groups/core/exceptions/ResourceHandlerException.java diff --git a/src/us/kbase/groups/core/exceptions/UnauthorizedException.java b/src/main/java/us/kbase/groups/core/exceptions/UnauthorizedException.java similarity index 100% rename from src/us/kbase/groups/core/exceptions/UnauthorizedException.java rename to src/main/java/us/kbase/groups/core/exceptions/UnauthorizedException.java diff --git a/src/us/kbase/groups/core/exceptions/UserIsMemberException.java b/src/main/java/us/kbase/groups/core/exceptions/UserIsMemberException.java similarity index 100% rename from src/us/kbase/groups/core/exceptions/UserIsMemberException.java rename to src/main/java/us/kbase/groups/core/exceptions/UserIsMemberException.java diff --git a/src/us/kbase/groups/core/fieldvalidation/CustomField.java b/src/main/java/us/kbase/groups/core/fieldvalidation/CustomField.java similarity index 100% rename from src/us/kbase/groups/core/fieldvalidation/CustomField.java rename to src/main/java/us/kbase/groups/core/fieldvalidation/CustomField.java diff --git a/src/us/kbase/groups/core/fieldvalidation/FieldConfiguration.java b/src/main/java/us/kbase/groups/core/fieldvalidation/FieldConfiguration.java similarity index 100% rename from src/us/kbase/groups/core/fieldvalidation/FieldConfiguration.java rename to src/main/java/us/kbase/groups/core/fieldvalidation/FieldConfiguration.java diff --git a/src/us/kbase/groups/core/fieldvalidation/FieldValidator.java b/src/main/java/us/kbase/groups/core/fieldvalidation/FieldValidator.java similarity index 100% rename from src/us/kbase/groups/core/fieldvalidation/FieldValidator.java rename to src/main/java/us/kbase/groups/core/fieldvalidation/FieldValidator.java diff --git a/src/us/kbase/groups/core/fieldvalidation/FieldValidatorConfiguration.java b/src/main/java/us/kbase/groups/core/fieldvalidation/FieldValidatorConfiguration.java similarity index 100% rename from src/us/kbase/groups/core/fieldvalidation/FieldValidatorConfiguration.java rename to src/main/java/us/kbase/groups/core/fieldvalidation/FieldValidatorConfiguration.java diff --git a/src/us/kbase/groups/core/fieldvalidation/FieldValidatorException.java b/src/main/java/us/kbase/groups/core/fieldvalidation/FieldValidatorException.java similarity index 100% rename from src/us/kbase/groups/core/fieldvalidation/FieldValidatorException.java rename to src/main/java/us/kbase/groups/core/fieldvalidation/FieldValidatorException.java diff --git a/src/us/kbase/groups/core/fieldvalidation/FieldValidatorFactory.java b/src/main/java/us/kbase/groups/core/fieldvalidation/FieldValidatorFactory.java similarity index 100% rename from src/us/kbase/groups/core/fieldvalidation/FieldValidatorFactory.java rename to src/main/java/us/kbase/groups/core/fieldvalidation/FieldValidatorFactory.java diff --git a/src/us/kbase/groups/core/fieldvalidation/FieldValidators.java b/src/main/java/us/kbase/groups/core/fieldvalidation/FieldValidators.java similarity index 100% rename from src/us/kbase/groups/core/fieldvalidation/FieldValidators.java rename to src/main/java/us/kbase/groups/core/fieldvalidation/FieldValidators.java diff --git a/src/us/kbase/groups/core/fieldvalidation/IllegalFieldValueException.java b/src/main/java/us/kbase/groups/core/fieldvalidation/IllegalFieldValueException.java similarity index 100% rename from src/us/kbase/groups/core/fieldvalidation/IllegalFieldValueException.java rename to src/main/java/us/kbase/groups/core/fieldvalidation/IllegalFieldValueException.java diff --git a/src/us/kbase/groups/core/fieldvalidation/NumberedCustomField.java b/src/main/java/us/kbase/groups/core/fieldvalidation/NumberedCustomField.java similarity index 100% rename from src/us/kbase/groups/core/fieldvalidation/NumberedCustomField.java rename to src/main/java/us/kbase/groups/core/fieldvalidation/NumberedCustomField.java diff --git a/src/us/kbase/groups/core/notifications/Notifications.java b/src/main/java/us/kbase/groups/core/notifications/Notifications.java similarity index 100% rename from src/us/kbase/groups/core/notifications/Notifications.java rename to src/main/java/us/kbase/groups/core/notifications/Notifications.java diff --git a/src/us/kbase/groups/core/notifications/NotificationsFactory.java b/src/main/java/us/kbase/groups/core/notifications/NotificationsFactory.java similarity index 100% rename from src/us/kbase/groups/core/notifications/NotificationsFactory.java rename to src/main/java/us/kbase/groups/core/notifications/NotificationsFactory.java diff --git a/src/us/kbase/groups/core/request/GroupRequest.java b/src/main/java/us/kbase/groups/core/request/GroupRequest.java similarity index 100% rename from src/us/kbase/groups/core/request/GroupRequest.java rename to src/main/java/us/kbase/groups/core/request/GroupRequest.java diff --git a/src/us/kbase/groups/core/request/GroupRequestStatus.java b/src/main/java/us/kbase/groups/core/request/GroupRequestStatus.java similarity index 100% rename from src/us/kbase/groups/core/request/GroupRequestStatus.java rename to src/main/java/us/kbase/groups/core/request/GroupRequestStatus.java diff --git a/src/us/kbase/groups/core/request/GroupRequestStatusType.java b/src/main/java/us/kbase/groups/core/request/GroupRequestStatusType.java similarity index 100% rename from src/us/kbase/groups/core/request/GroupRequestStatusType.java rename to src/main/java/us/kbase/groups/core/request/GroupRequestStatusType.java diff --git a/src/us/kbase/groups/core/request/GroupRequestUserAction.java b/src/main/java/us/kbase/groups/core/request/GroupRequestUserAction.java similarity index 100% rename from src/us/kbase/groups/core/request/GroupRequestUserAction.java rename to src/main/java/us/kbase/groups/core/request/GroupRequestUserAction.java diff --git a/src/us/kbase/groups/core/request/GroupRequestWithActions.java b/src/main/java/us/kbase/groups/core/request/GroupRequestWithActions.java similarity index 100% rename from src/us/kbase/groups/core/request/GroupRequestWithActions.java rename to src/main/java/us/kbase/groups/core/request/GroupRequestWithActions.java diff --git a/src/us/kbase/groups/core/request/RequestID.java b/src/main/java/us/kbase/groups/core/request/RequestID.java similarity index 100% rename from src/us/kbase/groups/core/request/RequestID.java rename to src/main/java/us/kbase/groups/core/request/RequestID.java diff --git a/src/us/kbase/groups/core/request/RequestType.java b/src/main/java/us/kbase/groups/core/request/RequestType.java similarity index 100% rename from src/us/kbase/groups/core/request/RequestType.java rename to src/main/java/us/kbase/groups/core/request/RequestType.java diff --git a/src/us/kbase/groups/core/resource/ResourceAccess.java b/src/main/java/us/kbase/groups/core/resource/ResourceAccess.java similarity index 100% rename from src/us/kbase/groups/core/resource/ResourceAccess.java rename to src/main/java/us/kbase/groups/core/resource/ResourceAccess.java diff --git a/src/us/kbase/groups/core/resource/ResourceAdministrativeID.java b/src/main/java/us/kbase/groups/core/resource/ResourceAdministrativeID.java similarity index 100% rename from src/us/kbase/groups/core/resource/ResourceAdministrativeID.java rename to src/main/java/us/kbase/groups/core/resource/ResourceAdministrativeID.java diff --git a/src/us/kbase/groups/core/resource/ResourceDescriptor.java b/src/main/java/us/kbase/groups/core/resource/ResourceDescriptor.java similarity index 100% rename from src/us/kbase/groups/core/resource/ResourceDescriptor.java rename to src/main/java/us/kbase/groups/core/resource/ResourceDescriptor.java diff --git a/src/us/kbase/groups/core/resource/ResourceHandler.java b/src/main/java/us/kbase/groups/core/resource/ResourceHandler.java similarity index 100% rename from src/us/kbase/groups/core/resource/ResourceHandler.java rename to src/main/java/us/kbase/groups/core/resource/ResourceHandler.java diff --git a/src/us/kbase/groups/core/resource/ResourceID.java b/src/main/java/us/kbase/groups/core/resource/ResourceID.java similarity index 100% rename from src/us/kbase/groups/core/resource/ResourceID.java rename to src/main/java/us/kbase/groups/core/resource/ResourceID.java diff --git a/src/us/kbase/groups/core/resource/ResourceInformation.java b/src/main/java/us/kbase/groups/core/resource/ResourceInformation.java similarity index 100% rename from src/us/kbase/groups/core/resource/ResourceInformation.java rename to src/main/java/us/kbase/groups/core/resource/ResourceInformation.java diff --git a/src/us/kbase/groups/core/resource/ResourceInformationSet.java b/src/main/java/us/kbase/groups/core/resource/ResourceInformationSet.java similarity index 100% rename from src/us/kbase/groups/core/resource/ResourceInformationSet.java rename to src/main/java/us/kbase/groups/core/resource/ResourceInformationSet.java diff --git a/src/us/kbase/groups/core/resource/ResourceType.java b/src/main/java/us/kbase/groups/core/resource/ResourceType.java similarity index 100% rename from src/us/kbase/groups/core/resource/ResourceType.java rename to src/main/java/us/kbase/groups/core/resource/ResourceType.java diff --git a/src/us/kbase/groups/fieldvalidators/EnumFieldValidatorFactory.java b/src/main/java/us/kbase/groups/fieldvalidators/EnumFieldValidatorFactory.java similarity index 100% rename from src/us/kbase/groups/fieldvalidators/EnumFieldValidatorFactory.java rename to src/main/java/us/kbase/groups/fieldvalidators/EnumFieldValidatorFactory.java diff --git a/src/us/kbase/groups/fieldvalidators/GravatarFieldValidatorFactory.java b/src/main/java/us/kbase/groups/fieldvalidators/GravatarFieldValidatorFactory.java similarity index 100% rename from src/us/kbase/groups/fieldvalidators/GravatarFieldValidatorFactory.java rename to src/main/java/us/kbase/groups/fieldvalidators/GravatarFieldValidatorFactory.java diff --git a/src/us/kbase/groups/fieldvalidators/SimpleFieldValidatorFactory.java b/src/main/java/us/kbase/groups/fieldvalidators/SimpleFieldValidatorFactory.java similarity index 100% rename from src/us/kbase/groups/fieldvalidators/SimpleFieldValidatorFactory.java rename to src/main/java/us/kbase/groups/fieldvalidators/SimpleFieldValidatorFactory.java diff --git a/src/us/kbase/groups/notifications/DirectFeedsServiceNotifierFactory.java b/src/main/java/us/kbase/groups/notifications/DirectFeedsServiceNotifierFactory.java similarity index 100% rename from src/us/kbase/groups/notifications/DirectFeedsServiceNotifierFactory.java rename to src/main/java/us/kbase/groups/notifications/DirectFeedsServiceNotifierFactory.java diff --git a/src/us/kbase/groups/notifications/KafkaFeedsNotifierFactory.java b/src/main/java/us/kbase/groups/notifications/KafkaFeedsNotifierFactory.java similarity index 100% rename from src/us/kbase/groups/notifications/KafkaFeedsNotifierFactory.java rename to src/main/java/us/kbase/groups/notifications/KafkaFeedsNotifierFactory.java diff --git a/src/us/kbase/groups/notifications/SLF4JNotifierFactory.java b/src/main/java/us/kbase/groups/notifications/SLF4JNotifierFactory.java similarity index 100% rename from src/us/kbase/groups/notifications/SLF4JNotifierFactory.java rename to src/main/java/us/kbase/groups/notifications/SLF4JNotifierFactory.java diff --git a/src/us/kbase/groups/service/AppEventListener.java b/src/main/java/us/kbase/groups/service/AppEventListener.java similarity index 100% rename from src/us/kbase/groups/service/AppEventListener.java rename to src/main/java/us/kbase/groups/service/AppEventListener.java diff --git a/src/us/kbase/groups/service/Fields.java b/src/main/java/us/kbase/groups/service/Fields.java similarity index 100% rename from src/us/kbase/groups/service/Fields.java rename to src/main/java/us/kbase/groups/service/Fields.java diff --git a/src/us/kbase/groups/service/GroupsService.java b/src/main/java/us/kbase/groups/service/GroupsService.java similarity index 100% rename from src/us/kbase/groups/service/GroupsService.java rename to src/main/java/us/kbase/groups/service/GroupsService.java diff --git a/src/us/kbase/groups/service/JacksonFeature.java b/src/main/java/us/kbase/groups/service/JacksonFeature.java similarity index 100% rename from src/us/kbase/groups/service/JacksonFeature.java rename to src/main/java/us/kbase/groups/service/JacksonFeature.java diff --git a/src/us/kbase/groups/service/LoggingFilter.java b/src/main/java/us/kbase/groups/service/LoggingFilter.java similarity index 100% rename from src/us/kbase/groups/service/LoggingFilter.java rename to src/main/java/us/kbase/groups/service/LoggingFilter.java diff --git a/src/us/kbase/groups/service/SLF4JAutoLogger.java b/src/main/java/us/kbase/groups/service/SLF4JAutoLogger.java similarity index 100% rename from src/us/kbase/groups/service/SLF4JAutoLogger.java rename to src/main/java/us/kbase/groups/service/SLF4JAutoLogger.java diff --git a/src/us/kbase/groups/service/api/APICommon.java b/src/main/java/us/kbase/groups/service/api/APICommon.java similarity index 100% rename from src/us/kbase/groups/service/api/APICommon.java rename to src/main/java/us/kbase/groups/service/api/APICommon.java diff --git a/src/us/kbase/groups/service/api/APIConstants.java b/src/main/java/us/kbase/groups/service/api/APIConstants.java similarity index 100% rename from src/us/kbase/groups/service/api/APIConstants.java rename to src/main/java/us/kbase/groups/service/api/APIConstants.java diff --git a/src/us/kbase/groups/service/api/Fields.java b/src/main/java/us/kbase/groups/service/api/Fields.java similarity index 100% rename from src/us/kbase/groups/service/api/Fields.java rename to src/main/java/us/kbase/groups/service/api/Fields.java diff --git a/src/us/kbase/groups/service/api/GroupsAPI.java b/src/main/java/us/kbase/groups/service/api/GroupsAPI.java similarity index 100% rename from src/us/kbase/groups/service/api/GroupsAPI.java rename to src/main/java/us/kbase/groups/service/api/GroupsAPI.java diff --git a/src/us/kbase/groups/service/api/IncomingJSON.java b/src/main/java/us/kbase/groups/service/api/IncomingJSON.java similarity index 100% rename from src/us/kbase/groups/service/api/IncomingJSON.java rename to src/main/java/us/kbase/groups/service/api/IncomingJSON.java diff --git a/src/us/kbase/groups/service/api/MemberAPI.java b/src/main/java/us/kbase/groups/service/api/MemberAPI.java similarity index 100% rename from src/us/kbase/groups/service/api/MemberAPI.java rename to src/main/java/us/kbase/groups/service/api/MemberAPI.java diff --git a/src/us/kbase/groups/service/api/NamesAPI.java b/src/main/java/us/kbase/groups/service/api/NamesAPI.java similarity index 100% rename from src/us/kbase/groups/service/api/NamesAPI.java rename to src/main/java/us/kbase/groups/service/api/NamesAPI.java diff --git a/src/us/kbase/groups/service/api/RequestAPI.java b/src/main/java/us/kbase/groups/service/api/RequestAPI.java similarity index 100% rename from src/us/kbase/groups/service/api/RequestAPI.java rename to src/main/java/us/kbase/groups/service/api/RequestAPI.java diff --git a/src/us/kbase/groups/service/api/Root.java b/src/main/java/us/kbase/groups/service/api/Root.java similarity index 100% rename from src/us/kbase/groups/service/api/Root.java rename to src/main/java/us/kbase/groups/service/api/Root.java diff --git a/src/us/kbase/groups/service/api/ServicePaths.java b/src/main/java/us/kbase/groups/service/api/ServicePaths.java similarity index 100% rename from src/us/kbase/groups/service/api/ServicePaths.java rename to src/main/java/us/kbase/groups/service/api/ServicePaths.java diff --git a/src/us/kbase/groups/service/exceptions/ErrorMessage.java b/src/main/java/us/kbase/groups/service/exceptions/ErrorMessage.java similarity index 100% rename from src/us/kbase/groups/service/exceptions/ErrorMessage.java rename to src/main/java/us/kbase/groups/service/exceptions/ErrorMessage.java diff --git a/src/us/kbase/groups/service/exceptions/ExceptionHandler.java b/src/main/java/us/kbase/groups/service/exceptions/ExceptionHandler.java similarity index 100% rename from src/us/kbase/groups/service/exceptions/ExceptionHandler.java rename to src/main/java/us/kbase/groups/service/exceptions/ExceptionHandler.java diff --git a/src/us/kbase/groups/storage/GroupsStorage.java b/src/main/java/us/kbase/groups/storage/GroupsStorage.java similarity index 100% rename from src/us/kbase/groups/storage/GroupsStorage.java rename to src/main/java/us/kbase/groups/storage/GroupsStorage.java diff --git a/src/us/kbase/groups/storage/exceptions/GroupsStorageException.java b/src/main/java/us/kbase/groups/storage/exceptions/GroupsStorageException.java similarity index 100% rename from src/us/kbase/groups/storage/exceptions/GroupsStorageException.java rename to src/main/java/us/kbase/groups/storage/exceptions/GroupsStorageException.java diff --git a/src/us/kbase/groups/storage/exceptions/StorageInitException.java b/src/main/java/us/kbase/groups/storage/exceptions/StorageInitException.java similarity index 100% rename from src/us/kbase/groups/storage/exceptions/StorageInitException.java rename to src/main/java/us/kbase/groups/storage/exceptions/StorageInitException.java diff --git a/src/us/kbase/groups/storage/mongo/Fields.java b/src/main/java/us/kbase/groups/storage/mongo/Fields.java similarity index 100% rename from src/us/kbase/groups/storage/mongo/Fields.java rename to src/main/java/us/kbase/groups/storage/mongo/Fields.java diff --git a/src/us/kbase/groups/storage/mongo/MongoGroupsStorage.java b/src/main/java/us/kbase/groups/storage/mongo/MongoGroupsStorage.java similarity index 100% rename from src/us/kbase/groups/storage/mongo/MongoGroupsStorage.java rename to src/main/java/us/kbase/groups/storage/mongo/MongoGroupsStorage.java diff --git a/src/us/kbase/groups/userhandler/KBaseUserHandler.java b/src/main/java/us/kbase/groups/userhandler/KBaseUserHandler.java similarity index 100% rename from src/us/kbase/groups/userhandler/KBaseUserHandler.java rename to src/main/java/us/kbase/groups/userhandler/KBaseUserHandler.java diff --git a/src/us/kbase/groups/util/FileOpener.java b/src/main/java/us/kbase/groups/util/FileOpener.java similarity index 100% rename from src/us/kbase/groups/util/FileOpener.java rename to src/main/java/us/kbase/groups/util/FileOpener.java diff --git a/src/us/kbase/groups/util/Util.java b/src/main/java/us/kbase/groups/util/Util.java similarity index 100% rename from src/us/kbase/groups/util/Util.java rename to src/main/java/us/kbase/groups/util/Util.java diff --git a/src/us/kbase/groups/workspacehandler/SDKClientWorkspaceHandler.java b/src/main/java/us/kbase/groups/workspacehandler/SDKClientWorkspaceHandler.java similarity index 100% rename from src/us/kbase/groups/workspacehandler/SDKClientWorkspaceHandler.java rename to src/main/java/us/kbase/groups/workspacehandler/SDKClientWorkspaceHandler.java diff --git a/src/us/kbase/groups/workspacehandler/WorkspacePermission.java b/src/main/java/us/kbase/groups/workspacehandler/WorkspacePermission.java similarity index 100% rename from src/us/kbase/groups/workspacehandler/WorkspacePermission.java rename to src/main/java/us/kbase/groups/workspacehandler/WorkspacePermission.java diff --git a/src/us/kbase/test/groups/MapBuilder.java b/src/test/java/us/kbase/test/groups/MapBuilder.java similarity index 100% rename from src/us/kbase/test/groups/MapBuilder.java rename to src/test/java/us/kbase/test/groups/MapBuilder.java diff --git a/src/us/kbase/test/groups/MongoStorageTestManager.java b/src/test/java/us/kbase/test/groups/MongoStorageTestManager.java similarity index 100% rename from src/us/kbase/test/groups/MongoStorageTestManager.java rename to src/test/java/us/kbase/test/groups/MongoStorageTestManager.java diff --git a/src/us/kbase/test/groups/StandaloneGroupsServer.java b/src/test/java/us/kbase/test/groups/StandaloneGroupsServer.java similarity index 100% rename from src/us/kbase/test/groups/StandaloneGroupsServer.java rename to src/test/java/us/kbase/test/groups/StandaloneGroupsServer.java diff --git a/src/us/kbase/test/groups/TestCommon.java b/src/test/java/us/kbase/test/groups/TestCommon.java similarity index 100% rename from src/us/kbase/test/groups/TestCommon.java rename to src/test/java/us/kbase/test/groups/TestCommon.java diff --git a/src/us/kbase/test/groups/cataloghandler/SDKClientCatalogHandlerTest.java b/src/test/java/us/kbase/test/groups/cataloghandler/SDKClientCatalogHandlerTest.java similarity index 100% rename from src/us/kbase/test/groups/cataloghandler/SDKClientCatalogHandlerTest.java rename to src/test/java/us/kbase/test/groups/cataloghandler/SDKClientCatalogHandlerTest.java diff --git a/src/us/kbase/test/groups/config/GroupsConfigTest.java b/src/test/java/us/kbase/test/groups/config/GroupsConfigTest.java similarity index 100% rename from src/us/kbase/test/groups/config/GroupsConfigTest.java rename to src/test/java/us/kbase/test/groups/config/GroupsConfigTest.java diff --git a/src/us/kbase/test/groups/controllers/workspace/WorkspaceController.java b/src/test/java/us/kbase/test/groups/controllers/workspace/WorkspaceController.java similarity index 100% rename from src/us/kbase/test/groups/controllers/workspace/WorkspaceController.java rename to src/test/java/us/kbase/test/groups/controllers/workspace/WorkspaceController.java diff --git a/src/us/kbase/test/groups/core/CreateModExpireTimesTest.java b/src/test/java/us/kbase/test/groups/core/CreateModExpireTimesTest.java similarity index 100% rename from src/us/kbase/test/groups/core/CreateModExpireTimesTest.java rename to src/test/java/us/kbase/test/groups/core/CreateModExpireTimesTest.java diff --git a/src/us/kbase/test/groups/core/FieldItemTest.java b/src/test/java/us/kbase/test/groups/core/FieldItemTest.java similarity index 100% rename from src/us/kbase/test/groups/core/FieldItemTest.java rename to src/test/java/us/kbase/test/groups/core/FieldItemTest.java diff --git a/src/us/kbase/test/groups/core/GetGroupsParamsTest.java b/src/test/java/us/kbase/test/groups/core/GetGroupsParamsTest.java similarity index 100% rename from src/us/kbase/test/groups/core/GetGroupsParamsTest.java rename to src/test/java/us/kbase/test/groups/core/GetGroupsParamsTest.java diff --git a/src/us/kbase/test/groups/core/GetRequestParamsTest.java b/src/test/java/us/kbase/test/groups/core/GetRequestParamsTest.java similarity index 100% rename from src/us/kbase/test/groups/core/GetRequestParamsTest.java rename to src/test/java/us/kbase/test/groups/core/GetRequestParamsTest.java diff --git a/src/us/kbase/test/groups/core/GroupCreationParamsTest.java b/src/test/java/us/kbase/test/groups/core/GroupCreationParamsTest.java similarity index 100% rename from src/us/kbase/test/groups/core/GroupCreationParamsTest.java rename to src/test/java/us/kbase/test/groups/core/GroupCreationParamsTest.java diff --git a/src/us/kbase/test/groups/core/GroupHasRequestsTest.java b/src/test/java/us/kbase/test/groups/core/GroupHasRequestsTest.java similarity index 100% rename from src/us/kbase/test/groups/core/GroupHasRequestsTest.java rename to src/test/java/us/kbase/test/groups/core/GroupHasRequestsTest.java diff --git a/src/us/kbase/test/groups/core/GroupIDAndNameTest.java b/src/test/java/us/kbase/test/groups/core/GroupIDAndNameTest.java similarity index 100% rename from src/us/kbase/test/groups/core/GroupIDAndNameTest.java rename to src/test/java/us/kbase/test/groups/core/GroupIDAndNameTest.java diff --git a/src/us/kbase/test/groups/core/GroupIDNameMembershipTest.java b/src/test/java/us/kbase/test/groups/core/GroupIDNameMembershipTest.java similarity index 100% rename from src/us/kbase/test/groups/core/GroupIDNameMembershipTest.java rename to src/test/java/us/kbase/test/groups/core/GroupIDNameMembershipTest.java diff --git a/src/us/kbase/test/groups/core/GroupIDTest.java b/src/test/java/us/kbase/test/groups/core/GroupIDTest.java similarity index 100% rename from src/us/kbase/test/groups/core/GroupIDTest.java rename to src/test/java/us/kbase/test/groups/core/GroupIDTest.java diff --git a/src/us/kbase/test/groups/core/GroupNameTest.java b/src/test/java/us/kbase/test/groups/core/GroupNameTest.java similarity index 100% rename from src/us/kbase/test/groups/core/GroupNameTest.java rename to src/test/java/us/kbase/test/groups/core/GroupNameTest.java diff --git a/src/us/kbase/test/groups/core/GroupTest.java b/src/test/java/us/kbase/test/groups/core/GroupTest.java similarity index 100% rename from src/us/kbase/test/groups/core/GroupTest.java rename to src/test/java/us/kbase/test/groups/core/GroupTest.java diff --git a/src/us/kbase/test/groups/core/GroupUpdateParamsTest.java b/src/test/java/us/kbase/test/groups/core/GroupUpdateParamsTest.java similarity index 100% rename from src/us/kbase/test/groups/core/GroupUpdateParamsTest.java rename to src/test/java/us/kbase/test/groups/core/GroupUpdateParamsTest.java diff --git a/src/us/kbase/test/groups/core/GroupUserTest.java b/src/test/java/us/kbase/test/groups/core/GroupUserTest.java similarity index 100% rename from src/us/kbase/test/groups/core/GroupUserTest.java rename to src/test/java/us/kbase/test/groups/core/GroupUserTest.java diff --git a/src/us/kbase/test/groups/core/GroupViewTest.java b/src/test/java/us/kbase/test/groups/core/GroupViewTest.java similarity index 100% rename from src/us/kbase/test/groups/core/GroupViewTest.java rename to src/test/java/us/kbase/test/groups/core/GroupViewTest.java diff --git a/src/us/kbase/test/groups/core/GroupsTest.java b/src/test/java/us/kbase/test/groups/core/GroupsTest.java similarity index 100% rename from src/us/kbase/test/groups/core/GroupsTest.java rename to src/test/java/us/kbase/test/groups/core/GroupsTest.java diff --git a/src/us/kbase/test/groups/core/NameTest.java b/src/test/java/us/kbase/test/groups/core/NameTest.java similarity index 100% rename from src/us/kbase/test/groups/core/NameTest.java rename to src/test/java/us/kbase/test/groups/core/NameTest.java diff --git a/src/us/kbase/test/groups/core/OptionalGroupFieldsTest.java b/src/test/java/us/kbase/test/groups/core/OptionalGroupFieldsTest.java similarity index 100% rename from src/us/kbase/test/groups/core/OptionalGroupFieldsTest.java rename to src/test/java/us/kbase/test/groups/core/OptionalGroupFieldsTest.java diff --git a/src/us/kbase/test/groups/core/OptionalStringTest.java b/src/test/java/us/kbase/test/groups/core/OptionalStringTest.java similarity index 100% rename from src/us/kbase/test/groups/core/OptionalStringTest.java rename to src/test/java/us/kbase/test/groups/core/OptionalStringTest.java diff --git a/src/us/kbase/test/groups/core/TokenTest.java b/src/test/java/us/kbase/test/groups/core/TokenTest.java similarity index 100% rename from src/us/kbase/test/groups/core/TokenTest.java rename to src/test/java/us/kbase/test/groups/core/TokenTest.java diff --git a/src/us/kbase/test/groups/core/UserNameTest.java b/src/test/java/us/kbase/test/groups/core/UserNameTest.java similarity index 100% rename from src/us/kbase/test/groups/core/UserNameTest.java rename to src/test/java/us/kbase/test/groups/core/UserNameTest.java diff --git a/src/us/kbase/test/groups/core/fieldvalidation/CustomFieldTest.java b/src/test/java/us/kbase/test/groups/core/fieldvalidation/CustomFieldTest.java similarity index 100% rename from src/us/kbase/test/groups/core/fieldvalidation/CustomFieldTest.java rename to src/test/java/us/kbase/test/groups/core/fieldvalidation/CustomFieldTest.java diff --git a/src/us/kbase/test/groups/core/fieldvalidation/FieldConfigurationTest.java b/src/test/java/us/kbase/test/groups/core/fieldvalidation/FieldConfigurationTest.java similarity index 100% rename from src/us/kbase/test/groups/core/fieldvalidation/FieldConfigurationTest.java rename to src/test/java/us/kbase/test/groups/core/fieldvalidation/FieldConfigurationTest.java diff --git a/src/us/kbase/test/groups/core/fieldvalidation/FieldValidatorConfigurationTest.java b/src/test/java/us/kbase/test/groups/core/fieldvalidation/FieldValidatorConfigurationTest.java similarity index 100% rename from src/us/kbase/test/groups/core/fieldvalidation/FieldValidatorConfigurationTest.java rename to src/test/java/us/kbase/test/groups/core/fieldvalidation/FieldValidatorConfigurationTest.java diff --git a/src/us/kbase/test/groups/core/fieldvalidation/FieldValidatorsTest.java b/src/test/java/us/kbase/test/groups/core/fieldvalidation/FieldValidatorsTest.java similarity index 100% rename from src/us/kbase/test/groups/core/fieldvalidation/FieldValidatorsTest.java rename to src/test/java/us/kbase/test/groups/core/fieldvalidation/FieldValidatorsTest.java diff --git a/src/us/kbase/test/groups/core/fieldvalidation/NumberedCustomFieldTest.java b/src/test/java/us/kbase/test/groups/core/fieldvalidation/NumberedCustomFieldTest.java similarity index 100% rename from src/us/kbase/test/groups/core/fieldvalidation/NumberedCustomFieldTest.java rename to src/test/java/us/kbase/test/groups/core/fieldvalidation/NumberedCustomFieldTest.java diff --git a/src/us/kbase/test/groups/core/request/GroupRequestStatusTest.java b/src/test/java/us/kbase/test/groups/core/request/GroupRequestStatusTest.java similarity index 100% rename from src/us/kbase/test/groups/core/request/GroupRequestStatusTest.java rename to src/test/java/us/kbase/test/groups/core/request/GroupRequestStatusTest.java diff --git a/src/us/kbase/test/groups/core/request/GroupRequestStatusTypeTest.java b/src/test/java/us/kbase/test/groups/core/request/GroupRequestStatusTypeTest.java similarity index 100% rename from src/us/kbase/test/groups/core/request/GroupRequestStatusTypeTest.java rename to src/test/java/us/kbase/test/groups/core/request/GroupRequestStatusTypeTest.java diff --git a/src/us/kbase/test/groups/core/request/GroupRequestTest.java b/src/test/java/us/kbase/test/groups/core/request/GroupRequestTest.java similarity index 100% rename from src/us/kbase/test/groups/core/request/GroupRequestTest.java rename to src/test/java/us/kbase/test/groups/core/request/GroupRequestTest.java diff --git a/src/us/kbase/test/groups/core/request/GroupRequestUserActionTest.java b/src/test/java/us/kbase/test/groups/core/request/GroupRequestUserActionTest.java similarity index 100% rename from src/us/kbase/test/groups/core/request/GroupRequestUserActionTest.java rename to src/test/java/us/kbase/test/groups/core/request/GroupRequestUserActionTest.java diff --git a/src/us/kbase/test/groups/core/request/GroupRequestWithActionsTest.java b/src/test/java/us/kbase/test/groups/core/request/GroupRequestWithActionsTest.java similarity index 100% rename from src/us/kbase/test/groups/core/request/GroupRequestWithActionsTest.java rename to src/test/java/us/kbase/test/groups/core/request/GroupRequestWithActionsTest.java diff --git a/src/us/kbase/test/groups/core/request/RequestIDTest.java b/src/test/java/us/kbase/test/groups/core/request/RequestIDTest.java similarity index 100% rename from src/us/kbase/test/groups/core/request/RequestIDTest.java rename to src/test/java/us/kbase/test/groups/core/request/RequestIDTest.java diff --git a/src/us/kbase/test/groups/core/request/RequestTypeTest.java b/src/test/java/us/kbase/test/groups/core/request/RequestTypeTest.java similarity index 100% rename from src/us/kbase/test/groups/core/request/RequestTypeTest.java rename to src/test/java/us/kbase/test/groups/core/request/RequestTypeTest.java diff --git a/src/us/kbase/test/groups/core/resource/ResourceIDTest.java b/src/test/java/us/kbase/test/groups/core/resource/ResourceIDTest.java similarity index 100% rename from src/us/kbase/test/groups/core/resource/ResourceIDTest.java rename to src/test/java/us/kbase/test/groups/core/resource/ResourceIDTest.java diff --git a/src/us/kbase/test/groups/core/resource/ResourceInformationSetTest.java b/src/test/java/us/kbase/test/groups/core/resource/ResourceInformationSetTest.java similarity index 100% rename from src/us/kbase/test/groups/core/resource/ResourceInformationSetTest.java rename to src/test/java/us/kbase/test/groups/core/resource/ResourceInformationSetTest.java diff --git a/src/us/kbase/test/groups/core/resource/ResourceInformationTest.java b/src/test/java/us/kbase/test/groups/core/resource/ResourceInformationTest.java similarity index 100% rename from src/us/kbase/test/groups/core/resource/ResourceInformationTest.java rename to src/test/java/us/kbase/test/groups/core/resource/ResourceInformationTest.java diff --git a/src/us/kbase/test/groups/core/resource/ResourceTypeTest.java b/src/test/java/us/kbase/test/groups/core/resource/ResourceTypeTest.java similarity index 100% rename from src/us/kbase/test/groups/core/resource/ResourceTypeTest.java rename to src/test/java/us/kbase/test/groups/core/resource/ResourceTypeTest.java diff --git a/src/us/kbase/test/groups/fieldvalidators/EnumFieldValidatorFactoryTest.java b/src/test/java/us/kbase/test/groups/fieldvalidators/EnumFieldValidatorFactoryTest.java similarity index 100% rename from src/us/kbase/test/groups/fieldvalidators/EnumFieldValidatorFactoryTest.java rename to src/test/java/us/kbase/test/groups/fieldvalidators/EnumFieldValidatorFactoryTest.java diff --git a/src/us/kbase/test/groups/fieldvalidators/GravatarFieldValidatorFactoryTest.java b/src/test/java/us/kbase/test/groups/fieldvalidators/GravatarFieldValidatorFactoryTest.java similarity index 100% rename from src/us/kbase/test/groups/fieldvalidators/GravatarFieldValidatorFactoryTest.java rename to src/test/java/us/kbase/test/groups/fieldvalidators/GravatarFieldValidatorFactoryTest.java diff --git a/src/us/kbase/test/groups/fieldvalidators/SimpleFieldValidatorFactoryTest.java b/src/test/java/us/kbase/test/groups/fieldvalidators/SimpleFieldValidatorFactoryTest.java similarity index 100% rename from src/us/kbase/test/groups/fieldvalidators/SimpleFieldValidatorFactoryTest.java rename to src/test/java/us/kbase/test/groups/fieldvalidators/SimpleFieldValidatorFactoryTest.java diff --git a/src/us/kbase/test/groups/integration/ServiceIntegrationTest.java b/src/test/java/us/kbase/test/groups/integration/ServiceIntegrationTest.java similarity index 100% rename from src/us/kbase/test/groups/integration/ServiceIntegrationTest.java rename to src/test/java/us/kbase/test/groups/integration/ServiceIntegrationTest.java diff --git a/src/us/kbase/test/groups/notifications/KafkaFeedsNotifierFactoryTest.java b/src/test/java/us/kbase/test/groups/notifications/KafkaFeedsNotifierFactoryTest.java similarity index 100% rename from src/us/kbase/test/groups/notifications/KafkaFeedsNotifierFactoryTest.java rename to src/test/java/us/kbase/test/groups/notifications/KafkaFeedsNotifierFactoryTest.java diff --git a/src/us/kbase/test/groups/service/LoggingFilterTest.java b/src/test/java/us/kbase/test/groups/service/LoggingFilterTest.java similarity index 100% rename from src/us/kbase/test/groups/service/LoggingFilterTest.java rename to src/test/java/us/kbase/test/groups/service/LoggingFilterTest.java diff --git a/src/us/kbase/test/groups/service/api/APICommonTest.java b/src/test/java/us/kbase/test/groups/service/api/APICommonTest.java similarity index 100% rename from src/us/kbase/test/groups/service/api/APICommonTest.java rename to src/test/java/us/kbase/test/groups/service/api/APICommonTest.java diff --git a/src/us/kbase/test/groups/service/api/GroupsAPITest.java b/src/test/java/us/kbase/test/groups/service/api/GroupsAPITest.java similarity index 100% rename from src/us/kbase/test/groups/service/api/GroupsAPITest.java rename to src/test/java/us/kbase/test/groups/service/api/GroupsAPITest.java diff --git a/src/us/kbase/test/groups/service/api/IncomingJSONTest.java b/src/test/java/us/kbase/test/groups/service/api/IncomingJSONTest.java similarity index 100% rename from src/us/kbase/test/groups/service/api/IncomingJSONTest.java rename to src/test/java/us/kbase/test/groups/service/api/IncomingJSONTest.java diff --git a/src/us/kbase/test/groups/service/api/MemberAPITest.java b/src/test/java/us/kbase/test/groups/service/api/MemberAPITest.java similarity index 100% rename from src/us/kbase/test/groups/service/api/MemberAPITest.java rename to src/test/java/us/kbase/test/groups/service/api/MemberAPITest.java diff --git a/src/us/kbase/test/groups/service/api/NamesAPITest.java b/src/test/java/us/kbase/test/groups/service/api/NamesAPITest.java similarity index 100% rename from src/us/kbase/test/groups/service/api/NamesAPITest.java rename to src/test/java/us/kbase/test/groups/service/api/NamesAPITest.java diff --git a/src/us/kbase/test/groups/service/api/RequestAPITest.java b/src/test/java/us/kbase/test/groups/service/api/RequestAPITest.java similarity index 100% rename from src/us/kbase/test/groups/service/api/RequestAPITest.java rename to src/test/java/us/kbase/test/groups/service/api/RequestAPITest.java diff --git a/src/us/kbase/test/groups/service/api/RootTest.java b/src/test/java/us/kbase/test/groups/service/api/RootTest.java similarity index 100% rename from src/us/kbase/test/groups/service/api/RootTest.java rename to src/test/java/us/kbase/test/groups/service/api/RootTest.java diff --git a/src/us/kbase/test/groups/service/exceptions/ErrorMessageTest.java b/src/test/java/us/kbase/test/groups/service/exceptions/ErrorMessageTest.java similarity index 100% rename from src/us/kbase/test/groups/service/exceptions/ErrorMessageTest.java rename to src/test/java/us/kbase/test/groups/service/exceptions/ErrorMessageTest.java diff --git a/src/us/kbase/test/groups/service/exceptions/ExceptionHandlerTest.java b/src/test/java/us/kbase/test/groups/service/exceptions/ExceptionHandlerTest.java similarity index 100% rename from src/us/kbase/test/groups/service/exceptions/ExceptionHandlerTest.java rename to src/test/java/us/kbase/test/groups/service/exceptions/ExceptionHandlerTest.java diff --git a/src/us/kbase/test/groups/storage/mongo/MongoGroupsStorageDuplicateKeyCheckerTest.java b/src/test/java/us/kbase/test/groups/storage/mongo/MongoGroupsStorageDuplicateKeyCheckerTest.java similarity index 100% rename from src/us/kbase/test/groups/storage/mongo/MongoGroupsStorageDuplicateKeyCheckerTest.java rename to src/test/java/us/kbase/test/groups/storage/mongo/MongoGroupsStorageDuplicateKeyCheckerTest.java diff --git a/src/us/kbase/test/groups/storage/mongo/MongoGroupsStorageOpsTest.java b/src/test/java/us/kbase/test/groups/storage/mongo/MongoGroupsStorageOpsTest.java similarity index 100% rename from src/us/kbase/test/groups/storage/mongo/MongoGroupsStorageOpsTest.java rename to src/test/java/us/kbase/test/groups/storage/mongo/MongoGroupsStorageOpsTest.java diff --git a/src/us/kbase/test/groups/storage/mongo/MongoGroupsStorageStartupTest.java b/src/test/java/us/kbase/test/groups/storage/mongo/MongoGroupsStorageStartupTest.java similarity index 100% rename from src/us/kbase/test/groups/storage/mongo/MongoGroupsStorageStartupTest.java rename to src/test/java/us/kbase/test/groups/storage/mongo/MongoGroupsStorageStartupTest.java diff --git a/src/us/kbase/test/groups/util/FailOnInstantiation.java b/src/test/java/us/kbase/test/groups/util/FailOnInstantiation.java similarity index 100% rename from src/us/kbase/test/groups/util/FailOnInstantiation.java rename to src/test/java/us/kbase/test/groups/util/FailOnInstantiation.java diff --git a/src/us/kbase/test/groups/util/FailOnInstantiationNoNullaryConstructor.java b/src/test/java/us/kbase/test/groups/util/FailOnInstantiationNoNullaryConstructor.java similarity index 100% rename from src/us/kbase/test/groups/util/FailOnInstantiationNoNullaryConstructor.java rename to src/test/java/us/kbase/test/groups/util/FailOnInstantiationNoNullaryConstructor.java diff --git a/src/us/kbase/test/groups/util/FailOnInstantiationPrivateConstructor.java b/src/test/java/us/kbase/test/groups/util/FailOnInstantiationPrivateConstructor.java similarity index 100% rename from src/us/kbase/test/groups/util/FailOnInstantiationPrivateConstructor.java rename to src/test/java/us/kbase/test/groups/util/FailOnInstantiationPrivateConstructor.java diff --git a/src/us/kbase/test/groups/util/UtilTest.java b/src/test/java/us/kbase/test/groups/util/UtilTest.java similarity index 100% rename from src/us/kbase/test/groups/util/UtilTest.java rename to src/test/java/us/kbase/test/groups/util/UtilTest.java diff --git a/src/us/kbase/test/groups/workspacehandler/SDKClientWorkspaceHandlerTest.java b/src/test/java/us/kbase/test/groups/workspacehandler/SDKClientWorkspaceHandlerTest.java similarity index 100% rename from src/us/kbase/test/groups/workspacehandler/SDKClientWorkspaceHandlerTest.java rename to src/test/java/us/kbase/test/groups/workspacehandler/SDKClientWorkspaceHandlerTest.java diff --git a/src/us/kbase/test/groups/workspacehandler/WorkspacePermissionTest.java b/src/test/java/us/kbase/test/groups/workspacehandler/WorkspacePermissionTest.java similarity index 100% rename from src/us/kbase/test/groups/workspacehandler/WorkspacePermissionTest.java rename to src/test/java/us/kbase/test/groups/workspacehandler/WorkspacePermissionTest.java diff --git a/src/us/kbase/test/groups/controllers/workspace/wsjars b/src/test/resources/us/kbase/test/groups/controllers/workspace/wsjars similarity index 100% rename from src/us/kbase/test/groups/controllers/workspace/wsjars rename to src/test/resources/us/kbase/test/groups/controllers/workspace/wsjars From 45f065d960731f8c0f0e84d05c17bf063fc2d17d Mon Sep 17 00:00:00 2001 From: Gavin Date: Fri, 12 Apr 2024 21:31:12 -0700 Subject: [PATCH 09/21] Update docs --- README.md | 46 +++++++++++++++++++++++++++++++--------------- build.gradle | 2 -- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 215d9ff7..37e84e99 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,6 @@ Service for creating and managing groups of KBase users and associated Narratives. Build status (master): -[![Build Status](https://travis-ci.org/kbase/groups.svg?branch=master)](https://travis-ci.org/kbase/groups) [![codecov](https://codecov.io/gh/kbase/groups/branch/master/graph/badge.svg)](https://codecov.io/gh/kbase/groups) ## API Data structures @@ -983,24 +982,41 @@ that the fields be kept few and small in size. ## Requirements Java 8 (OpenJDK OK) -Apache Ant (http://ant.apache.org/) MongoDB 2.6+ (https://www.mongodb.com/) Jetty 9.3+ (http://www.eclipse.org/jetty/download.html) (see jetty-config.md for version used for testing) This repo (git clone https://github.com/kbase/groups) -The jars repo (git clone https://github.com/kbase/jars) -The two repos above need to be in the same parent folder. -## To start server +## Starting the server -start mongodb -if using mongo auth, create a mongo user -cd into the groups repo -`ant build` -copy `deploy.cfg.example` to `deploy.cfg` and fill in appropriately -`export KB_DEPLOYMENT_CONFIG=` -`cd jettybase` -`./jettybase$ java -jar -Djetty.http.port= /start.jar` +### Docker + +The provided `Dockerfile` can be used to build and run an image. See the deployment template +in `deployment/conf/.templates` for the environment variables available to configure the +service - the `deploy.cfg.example` file provides documentation for these variables. + +`docker-compose --build -d` can be used to start a MongoDB instance and groups +service pointed at the KBase environment of your choice. + +### Manually + +* Start mongodb +* If using mongo auth, create a mongo user +* `cd` into the groups repo + +```shell +./gradlew war +mkdir -p jettybase/webapps +cp build/libs/groups.war jettybase/webapps/ROOT.war +``` + +* copy `deploy.cfg.example` to `deploy.cfg` and fill in appropriately + +```shell +export KB_DEPLOYMENT_CONFIG= +cd jettybase +./jettybase$ java -jar -Djetty.port= /start.jar +``` ## Developer notes @@ -1016,14 +1032,14 @@ copy `deploy.cfg.example` to `deploy.cfg` and fill in appropriately * Releases * The master branch is the stable branch. Releases are made from the develop branch to the master branch. - * Update the version as per the semantic version rules in `src/us/kbase/groups/api/Root.java`. + * Update the version as per the semantic version rules in `src/main/java/us/kbase/groups/api/Root.java`. * Tag the version in git and github. ### Running tests * Copy `test.cfg.example` to `test.cfg` and fill in the values appropriately. * If it works as is start buying lottery tickets immediately. -* `ant test` +* `./gradlew test` ### UI diff --git a/build.gradle b/build.gradle index 67319fe0..cae312b7 100644 --- a/build.gradle +++ b/build.gradle @@ -9,8 +9,6 @@ plugins { id 'org.ajoberstar.grgit' version '4.1.1' } -// TODO NOW update any ant refs in docs to gradle - repositories { mavenCentral() } From 558aa152ca6a6cc5001ff46150d04c51a57a0d3d Mon Sep 17 00:00:00 2001 From: Gavin Date: Tue, 16 Apr 2024 09:01:04 -0700 Subject: [PATCH 10/21] Use published jars --- .github/workflows/test.yml | 5 - build.gradle | 54 +++--- .../groups/userhandler/KBaseUserHandler.java | 30 ++- .../test/groups/MongoStorageTestManager.java | 2 +- .../java/us/kbase/test/groups/TestCommon.java | 8 +- .../SDKClientCatalogHandlerTest.java | 2 +- .../workspace/WorkspaceController.java | 176 ------------------ .../integration/ServiceIntegrationTest.java | 8 +- .../test/groups/controllers/workspace/wsjars | 37 ---- test.cfg.example | 3 - 10 files changed, 49 insertions(+), 276 deletions(-) delete mode 100644 src/test/java/us/kbase/test/groups/controllers/workspace/WorkspaceController.java delete mode 100644 src/test/resources/us/kbase/test/groups/controllers/workspace/wsjars diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b27498cc..079d5c0d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -49,10 +49,6 @@ jobs: # move to parent dir of homedir to install binaries etc cd .. - # set up jars - git clone https://github.com/kbase/jars - export JARSDIR=$(pwd)/jars/lib/jars/ - # set up mongo wget -q http://fastdl.mongodb.org/linux/${{matrix.mongo}}.tgz tar xfz ${{matrix.mongo}}.tgz @@ -61,7 +57,6 @@ jobs: # set up test config cd $HOMEDIR cp -n test.cfg.example test.cfg - sed -i "s#^test.jars.dir.*#test.jars.dir=$JARSDIR#" test.cfg sed -i "s#^test.temp.dir=.*#test.temp.dir=temp_test_dir#" test.cfg sed -i "s#^test.mongo.exe.*#test.mongo.exe=$MONGOD#" test.cfg sed -i "s#^test.mongo.useWiredTiger.*#test.mongo.useWiredTiger=${{matrix.wired_tiger}}#" test.cfg diff --git a/build.gradle b/build.gradle index cae312b7..2d82ac9c 100644 --- a/build.gradle +++ b/build.gradle @@ -11,6 +11,14 @@ plugins { repositories { mavenCentral() + maven { + name = "Jitpack" + url = 'https://jitpack.io' + } + maven { + name = "Clojars" + url = "https://repo.clojars.org/" + } } task buildGitCommitFile { @@ -86,30 +94,29 @@ dependencies { compileOnly 'javax.servlet:javax.servlet-api:3.0.1' - implementation fromURL( - 'https://github.com/kbase/jars/raw/master/lib/jars/kbase/auth/kbase-auth-0.4.4.jar', - 'kbase-auth-0.4.4' - ) - implementation fromURL( - 'https://github.com/kbase/jars/raw/master/lib/jars/kbase/workspace/WorkspaceClient-0.8.0.jar', - 'WorkspaceClient-0.8.0' - ) implementation fromURL( 'https://github.com/kbase/jars/raw/master/lib/jars/kbase/catalog/kbase-catalog-client-2.1.3.jar', 'kbase-catalog-client-2.1.3' ) - implementation fromURL( - 'https://github.com/kbase/jars/raw/master/lib/jars/kbase/common/kbase-common-0.0.25.jar', - 'kbase-common-0.0.25' - ) - // Pull from jars repo vs a maven repository to avoid the JNA dependency - // TODO DEPS Need to rework the java common logger to not use syslog4j at all since it's abandonware - // and has a ton of CVEs, even in the newer versions. - implementation fromURL( - 'https://github.com/kbase/jars/raw/master/lib/jars/syslog4j/syslog4j-0.9.46.jar', - 'syslog4j-0.9.46' - ) + // TODO DEPS Need to rework the java common logger to not use syslog4j at all since it's + // abandonware and has a ton of CVEs, even in the newer versions. + implementation "org.syslog4j:syslog4j:0.9.46" implementation 'ch.qos.logback:logback-classic:1.1.2' + implementation("com.github.kbase:auth2_client_java:0.5.0") { + exclude group: 'com.fasterxml.jackson.core' // breaks everything if we upgrade + } + implementation("com.github.kbase:java_common:0.3.0") { + exclude group: 'net.java.dev.jna' // breaks mac builds, not needed + exclude group: 'org.eclipse.jetty.aggregate' // ugh, java common pollutes everything + exclude group: 'com.fasterxml.jackson.core' // breaks everything if we upgrade + exclude group: 'javax.servlet', module: 'servlet-api' // 2.5 vs 3.0.1 above + } + implementation('com.github.kbase.workspace_deluxe:workspace-client:0.15.0') { + exclude group: 'net.java.dev.jna' // breaks mac builds, not needed + exclude group: 'org.eclipse.jetty.aggregate' // ugh, java common pollutes everything + exclude group: 'com.fasterxml.jackson.core' // breaks everything if we upgrade + exclude group: 'javax.servlet', module: 'servlet-api' // 2.5 vs 3.0.1 above + } implementation 'org.ini4j:ini4j:0.5.2' implementation 'org.mongodb:mongo-java-driver:3.8.2' implementation 'org.apache.kafka:kafka-clients:2.1.0' @@ -121,10 +128,11 @@ dependencies { implementation 'org.glassfish.jersey.media:jersey-media-json-jackson:2.23.2' implementation 'com.github.zafarkhaja:java-semver:0.9.0' - testImplementation fromURL( - 'https://github.com/kbase/jars/raw/master/lib/jars/kbase/auth2/kbase-auth2-test-shadow-all-0.7.0.jar', - 'kbase-auth2-test-shadow-all-0.7.0' - ) + testImplementation "com.github.kbase:auth2:0.7.1" + testImplementation('com.github.kbase:java_test_utilities:0.1.0') { + exclude group: 'com.fasterxml.jackson.core' // breaks everything if we upgrade + } + testImplementation 'com.github.kbase.workspace_deluxe:workspace_deluxe-test-shadow-all:0.15.0' testImplementation 'nl.jqno.equalsverifier:equalsverifier:3.1.10' testImplementation 'junit:junit:4.12' testImplementation 'org.mockito:mockito-core:3.0.0' diff --git a/src/main/java/us/kbase/groups/userhandler/KBaseUserHandler.java b/src/main/java/us/kbase/groups/userhandler/KBaseUserHandler.java index 3ab942e6..cebc5ae4 100644 --- a/src/main/java/us/kbase/groups/userhandler/KBaseUserHandler.java +++ b/src/main/java/us/kbase/groups/userhandler/KBaseUserHandler.java @@ -3,17 +3,15 @@ import static com.google.common.base.Preconditions.checkNotNull; import java.io.IOException; -import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.Arrays; import org.slf4j.LoggerFactory; -import us.kbase.auth.AuthConfig; import us.kbase.auth.AuthException; import us.kbase.auth.AuthToken; -import us.kbase.auth.ConfigurableAuthService; +import us.kbase.auth.client.AuthClient; import us.kbase.groups.core.Token; import us.kbase.groups.core.UserHandler; import us.kbase.groups.core.UserName; @@ -31,13 +29,9 @@ public class KBaseUserHandler implements UserHandler { // TODO TEST - // note the configurable auth service handles its own caching. + // note the auth client handles its own caching. - private static final String GLOBUS_URL_SUFFIX = "api/legacy/globus"; - private static final String KBASE_URL_SUFFIX = "api/legacy/KBase/Sessions/Login"; - - private final URI rootAuthURI; - private final ConfigurableAuthService auth; + private final AuthClient auth; private final Token serviceToken; /** Create the handler. @@ -58,15 +52,14 @@ public KBaseUserHandler( AuthenticationException { checkNotNull(rootAuthURL, "rootAuthURL"); checkNotNull(serviceToken, "serviceToken"); - if (rootAuthURL.toString().endsWith("/")) { - this.rootAuthURI = rootAuthURL.toURI(); - } else { - this.rootAuthURI = new URL(rootAuthURL.toString() + "/").toURI(); + try { + auth = AuthClient.from(rootAuthURL.toURI()); + } catch (AuthException e) { + throw new AuthenticationException( + ErrorType.AUTHENTICATION_FAILED, + "Failed to contact the auth service: " + e.getMessage(), + e); } - auth = new ConfigurableAuthService(new AuthConfig() - .withAllowInsecureURLs(allowInsecureURL) - .withKBaseAuthServerURL(this.rootAuthURI.resolve(KBASE_URL_SUFFIX).toURL()) - .withGlobusAuthURL(this.rootAuthURI.resolve(GLOBUS_URL_SUFFIX).toURL())); this.serviceToken = serviceToken; getUser(this.serviceToken); // check token is valid } @@ -94,8 +87,7 @@ public boolean isValidUser(final UserName userName) throws AuthenticationExcepti checkNotNull(userName, "userName"); try { return auth.isValidUserName( - Arrays.asList(userName.getName()), - new AuthToken(serviceToken.getToken(), "fakeuser")) + Arrays.asList(userName.getName()), serviceToken.getToken()) .get(userName.getName()); } catch (IOException | AuthException e) { LoggerFactory.getLogger(getClass()).error("Unexpected auth service response", e); diff --git a/src/test/java/us/kbase/test/groups/MongoStorageTestManager.java b/src/test/java/us/kbase/test/groups/MongoStorageTestManager.java index 36d42b36..14b9d0a0 100644 --- a/src/test/java/us/kbase/test/groups/MongoStorageTestManager.java +++ b/src/test/java/us/kbase/test/groups/MongoStorageTestManager.java @@ -15,9 +15,9 @@ import com.mongodb.MongoClient; import com.mongodb.client.MongoDatabase; -import us.kbase.common.test.controllers.mongo.MongoController; import us.kbase.groups.core.resource.ResourceType; import us.kbase.groups.storage.mongo.MongoGroupsStorage; +import us.kbase.testutils.controllers.mongo.MongoController; public class MongoStorageTestManager { diff --git a/src/test/java/us/kbase/test/groups/TestCommon.java b/src/test/java/us/kbase/test/groups/TestCommon.java index 2b19fa85..64d94f14 100644 --- a/src/test/java/us/kbase/test/groups/TestCommon.java +++ b/src/test/java/us/kbase/test/groups/TestCommon.java @@ -40,15 +40,13 @@ import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.classic.spi.IThrowableProxy; import ch.qos.logback.core.AppenderBase; -import us.kbase.common.test.TestException; +import us.kbase.testutils.TestException; public class TestCommon { public static final String MONGOEXE = "test.mongo.exe"; public static final String MONGO_USE_WIRED_TIGER = "test.mongo.wired_tiger"; - public static final String JARS_PATH = "test.jars.dir"; - public static final String TEST_TEMP_DIR = "test.temp.dir"; public static final String KEEP_TEMP_DIR = "test.temp.dir.keep"; @@ -171,10 +169,6 @@ public static Path getMongoExe() { return Paths.get(getTestProperty(MONGOEXE)).toAbsolutePath().normalize(); } - public static Path getJarsDir() { - return Paths.get(getTestProperty(JARS_PATH)).toAbsolutePath().normalize(); - } - public static Path getTempDir() { return Paths.get(getTestProperty(TEST_TEMP_DIR)).toAbsolutePath().normalize(); } diff --git a/src/test/java/us/kbase/test/groups/cataloghandler/SDKClientCatalogHandlerTest.java b/src/test/java/us/kbase/test/groups/cataloghandler/SDKClientCatalogHandlerTest.java index 352592d7..4fdb4acb 100644 --- a/src/test/java/us/kbase/test/groups/cataloghandler/SDKClientCatalogHandlerTest.java +++ b/src/test/java/us/kbase/test/groups/cataloghandler/SDKClientCatalogHandlerTest.java @@ -30,7 +30,6 @@ import us.kbase.catalog.ModuleVersionInfo; import us.kbase.catalog.SelectOneModuleParams; import us.kbase.common.service.JsonClientException; -import us.kbase.common.test.TestException; import us.kbase.groups.cataloghandler.SDKClientCatalogHandler; import us.kbase.groups.core.UserName; import us.kbase.groups.core.exceptions.ResourceHandlerException; @@ -43,6 +42,7 @@ import us.kbase.groups.core.resource.ResourceInformationSet; import us.kbase.test.groups.MapBuilder; import us.kbase.test.groups.TestCommon; +import us.kbase.testutils.TestException; public class SDKClientCatalogHandlerTest { diff --git a/src/test/java/us/kbase/test/groups/controllers/workspace/WorkspaceController.java b/src/test/java/us/kbase/test/groups/controllers/workspace/WorkspaceController.java deleted file mode 100644 index 9e7c22e7..00000000 --- a/src/test/java/us/kbase/test/groups/controllers/workspace/WorkspaceController.java +++ /dev/null @@ -1,176 +0,0 @@ -package us.kbase.test.groups.controllers.workspace; - -import static us.kbase.common.test.controllers.ControllerCommon.findFreePort; -import static us.kbase.common.test.controllers.ControllerCommon.makeTempDirs; - -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Scanner; - -import org.apache.commons.io.FileUtils; -import org.bson.Document; -import org.ini4j.Ini; -import org.ini4j.Profile.Section; - -import com.mongodb.MongoClient; -import com.mongodb.client.MongoDatabase; - -import us.kbase.common.test.TestException; - - -/** Q&D Utility to run a Workspace server for the purposes of testing from - * Java. Ideally this'll be swapped out for a Docker container that runs automatically with - * kb-sdk test at some point. - * - * Initializes a GridFS backend and does not support handles. - * @author gaprice@lbl.gov - * - */ -public class WorkspaceController { - //TODO CODE move to workspace repo, follow auth controller pattern. Need some way of handling event listener configuration - - private final static String DATA_DIR = "temp_data"; - private static final String WS_CLASS = "us.kbase.workspace.WorkspaceServer"; - - private static final String JARS_FILE = "wsjars"; - - private final static List tempDirectories = new LinkedList(); - static { - tempDirectories.add(DATA_DIR); - } - - private final Path tempDir; - - private final Process workspace; - private final int port; - - public WorkspaceController( - final Path jarsDir, - final String mongoHost, - final String mongoDatabase, - final String adminUser, - final URL authServiceRootURL, - final Path rootTempDir) - throws Exception { - final String classpath = getClassPath(jarsDir); - tempDir = makeTempDirs(rootTempDir, "WorkspaceController-", tempDirectories); - port = findFreePort(); - final Path deployCfg = createDeployCfg( - mongoHost, mongoDatabase, authServiceRootURL, adminUser); - - try (final MongoClient mc = new MongoClient(mongoHost)) { - final MongoDatabase db = mc.getDatabase(mongoDatabase); - db.getCollection("settings").insertOne( - new Document("type_db", "WorkspaceController_types") - .append("backend", "gridFS")); - } - - final List command = new LinkedList(); - command.addAll(Arrays.asList("java", "-classpath", classpath, WS_CLASS, "" + port)); - final ProcessBuilder servpb = new ProcessBuilder(command) - .redirectErrorStream(true) - .redirectOutput(tempDir.resolve("workspace.log").toFile()); - - final Map env = servpb.environment(); - env.put("KB_DEPLOYMENT_CONFIG", deployCfg.toString()); - - workspace = servpb.start(); - Thread.sleep(5000); //wait for server to start up - } - - private Path createDeployCfg( - final String mongoHost, - final String mongoDatabase, - final URL authRootURL, - final String adminUser) - throws IOException { - final File iniFile = new File(tempDir.resolve("test.cfg").toString()); - System.out.println("Created temporary workspace config file: " + - iniFile.getAbsolutePath()); - final Ini ini = new Ini(); - Section ws = ini.add("Workspace"); - ws.add("mongodb-host", mongoHost); - ws.add("mongodb-database", mongoDatabase); - ws.add("auth-service-url", authRootURL.toString() + "/api/legacy/KBase"); - ws.add("auth-service-url-allow-insecure", "true"); - ws.add("globus-url", authRootURL.toString() + "/api/legacy/globus"); - ws.add("ws-admin", adminUser); - ws.add("temp-dir", tempDir.resolve("temp_data")); - ws.add("ignore-handle-service", "true"); - // search listener config - ini.store(iniFile); - return iniFile.toPath(); - } - - private String getClassPath(final Path jarsDir) - throws IOException { - final InputStream is = getClass().getResourceAsStream(JARS_FILE); - if (is == null) { - throw new TestException("No workspace versions file " + JARS_FILE); - } - final List classpath = new LinkedList<>(); - try (final Reader r = new InputStreamReader(is)) { - final BufferedReader br = new BufferedReader(r); - String line; - while ((line = br.readLine()) != null) { - if (!line.trim().isEmpty()) { - final Path jarPath = jarsDir.resolve(line); - if (Files.notExists(jarPath)) { - throw new TestException("Required jar does not exist: " + jarPath); - } - classpath.add(jarPath.toString()); - } - } - } - return String.join(":", classpath); - } - - public int getServerPort() { - return port; - } - - public Path getTempDir() { - return tempDir; - } - - public void destroy(boolean deleteTempFiles) throws IOException { - if (workspace != null) { - workspace.destroy(); - } - if (tempDir != null && deleteTempFiles) { - FileUtils.deleteDirectory(tempDir.toFile()); - } - } - - public static void main(String[] args) throws Exception { - WorkspaceController ac = new WorkspaceController( - Paths.get("/home/crusherofheads/localgit/jars"), - "localhost:27017", - "WSController", - "workspaceadmin", - new URL("https://ci.kbase.us/services/auth"), - Paths.get("workspacetesttemp")); - System.out.println(ac.getServerPort()); - System.out.println(ac.getTempDir()); - Scanner reader = new Scanner(System.in); - System.out.println("any char to shut down"); - //get user input for a - reader.next(); - ac.destroy(false); - reader.close(); - } - -} - diff --git a/src/test/java/us/kbase/test/groups/integration/ServiceIntegrationTest.java b/src/test/java/us/kbase/test/groups/integration/ServiceIntegrationTest.java index 4c8fbd5e..0267799f 100644 --- a/src/test/java/us/kbase/test/groups/integration/ServiceIntegrationTest.java +++ b/src/test/java/us/kbase/test/groups/integration/ServiceIntegrationTest.java @@ -42,7 +42,6 @@ import com.mongodb.client.MongoDatabase; import us.kbase.auth.AuthToken; -import us.kbase.common.test.RegexMatcher; import us.kbase.groups.core.exceptions.GroupsException; import us.kbase.groups.core.exceptions.IllegalParameterException; import us.kbase.groups.core.exceptions.NoSuchCustomFieldException; @@ -55,8 +54,9 @@ import us.kbase.test.groups.StandaloneGroupsServer; import us.kbase.test.groups.StandaloneGroupsServer.ServerThread; import us.kbase.test.groups.TestCommon; -import us.kbase.test.groups.controllers.workspace.WorkspaceController; import us.kbase.test.groups.service.api.RootTest; +import us.kbase.test.workspace.controllers.workspace.WorkspaceController; +import us.kbase.testutils.RegexMatcher; import us.kbase.workspace.WorkspaceClient; public class ServiceIntegrationTest { @@ -122,11 +122,11 @@ public static void beforeClass() throws Exception { // set up Workspace WS = new WorkspaceController( - TestCommon.getJarsDir(), "localhost:" + MANAGER.mongo.getServerPort(), "GroupsServiceIntegTestWSDB", + "GroupsServiceIntegTestWSDB_types", "user2", - authURL, + new URL(authURL.toString() + "/"), TEMP_DIR); WSDB = MANAGER.mc.getDatabase("GroupsServiceIntegTestWSDB"); diff --git a/src/test/resources/us/kbase/test/groups/controllers/workspace/wsjars b/src/test/resources/us/kbase/test/groups/controllers/workspace/wsjars deleted file mode 100644 index 317b088b..00000000 --- a/src/test/resources/us/kbase/test/groups/controllers/workspace/wsjars +++ /dev/null @@ -1,37 +0,0 @@ -kbase/workspace/WorkspaceService-0.8.2.jar - -kbase/common/kbase-common-0.0.24.jar -ini4j/ini4j-0.5.2.jar -jetty/jetty-all-7.0.0.jar -jna/jna-3.4.0.jar -servlet/servlet-api-2.5.jar -syslog4j/syslog4j-0.9.46.jar -joda/joda-time-2.2.jar - -junit/junit-4.12.jar -hamcrest/hamcrest-core-1.3.jar -kbase/auth/kbase-auth-0.4.4.jar -jackson/jackson-annotations-2.2.3.jar -jackson/jackson-core-2.2.3.jar -jackson/jackson-databind-2.2.3.jar - -kbase/shock/shock-client-0.0.14.jar -apache_commons/commons-logging-1.1.1.jar -apache_commons/http/httpclient-4.3.1.jar -apache_commons/http/httpcore-4.3.jar -apache_commons/http/httpmime-4.3.1.jar - -kbase/kidl/kbase-kidl-parser-1409261812-7863aef.jar -apache_commons/commons-codec-1.8.jar -apache_commons/commons-io-2.4.jar -apache_commons/commons-lang3-3.1.jar -mongo/mongo-java-driver-2.13.3.jar -jongo/jongo-0.5-early-20130912-1506.jar -bson4jackson/bson4jackson-2.2.0-2.2.0.jar -slf4j/slf4j-api-1.7.7.jar -logback/logback-core-1.1.2.jar -logback/logback-classic-1.1.2.jar -google/guava-14.0.1.jar -kbase/handle/HandleServiceClient-160803-b9de699.jar -kbase/handle/HandleManagerClient-160803-08c8da3.jar - diff --git a/test.cfg.example b/test.cfg.example index a39db114..2e6acd68 100644 --- a/test.cfg.example +++ b/test.cfg.example @@ -6,9 +6,6 @@ # path to the mongodb executable to use for the tests. test.mongo.exe=/path/to/mongodbexecutable -# path to the KBase jars directory, e.g. [path to parent folder]/jars/lib/jars -test.jars.dir=/path/to/jars/dir - # true to use wired tiger, anything else for false. test.mongo.wired_tiger=false From a149312bbd050f6ac3f77fb2978e10bcba7cd97a Mon Sep 17 00:00:00 2001 From: Gavin Date: Wed, 8 May 2024 16:07:41 -0700 Subject: [PATCH 11/21] Add tests for KBaseUserHandler --- .../us/kbase/groups/build/GroupsBuilder.java | 3 +- .../groups/userhandler/KBaseUserHandler.java | 23 +-- .../userhandler/KBaseUserHandlerTest.java | 148 ++++++++++++++++++ 3 files changed, 153 insertions(+), 21 deletions(-) create mode 100644 src/test/java/us/kbase/test/groups/userhandler/KBaseUserHandlerTest.java diff --git a/src/main/java/us/kbase/groups/build/GroupsBuilder.java b/src/main/java/us/kbase/groups/build/GroupsBuilder.java index 433b0faf..34c6441f 100644 --- a/src/main/java/us/kbase/groups/build/GroupsBuilder.java +++ b/src/main/java/us/kbase/groups/build/GroupsBuilder.java @@ -129,8 +129,7 @@ private Groups buildGroups(final GroupsConfig c, final GroupsStorage storage) // these handler creation methods may need changes if we want to allow alternate // implementations. YAGNI for now. try { - uh = new KBaseUserHandler( - c.getAuthURL(), c.getWorkspaceAdminToken(), c.isAllowInsecureURLs()); + uh = new KBaseUserHandler(c.getAuthURL(), c.getWorkspaceAdminToken()); } catch (IOException | URISyntaxException | AuthenticationException e) { //TODO CODE check for a bad login and note the workspace token failed or throw a better error from the handler throw new GroupsConfigurationException( diff --git a/src/main/java/us/kbase/groups/userhandler/KBaseUserHandler.java b/src/main/java/us/kbase/groups/userhandler/KBaseUserHandler.java index cebc5ae4..7b3f199c 100644 --- a/src/main/java/us/kbase/groups/userhandler/KBaseUserHandler.java +++ b/src/main/java/us/kbase/groups/userhandler/KBaseUserHandler.java @@ -27,8 +27,6 @@ */ public class KBaseUserHandler implements UserHandler { - // TODO TEST - // note the auth client handles its own caching. private final AuthClient auth; @@ -38,7 +36,6 @@ public class KBaseUserHandler implements UserHandler { * @param rootAuthURL the root url of the KBase authentication service. * @param serviceToken a service token for the KBase authentication service. This is used * to check that user names are valid. - * @param allowInsecureURL allow a non-https URL. * @throws IOException if the authentication service could not be contacted. * @throws URISyntaxException if the URL is not a valid URI. * @throws InvalidTokenException if the service token is invalid. @@ -46,8 +43,7 @@ public class KBaseUserHandler implements UserHandler { */ public KBaseUserHandler( final URL rootAuthURL, - final Token serviceToken, - final boolean allowInsecureURL) + final Token serviceToken) throws IOException, URISyntaxException, InvalidTokenException, AuthenticationException { checkNotNull(rootAuthURL, "rootAuthURL"); @@ -71,12 +67,12 @@ public UserName getUser(final Token token) try { final AuthToken user = auth.validateToken(token.getToken()); return new UserName(user.getUserName()); - } catch (IOException e) { + } catch (IOException e) { // no good way to test this throw new AuthenticationException(ErrorType.AUTHENTICATION_FAILED, "Failed contacting authentication server: " + e.getMessage(), e); } catch (AuthException e) { throw new InvalidTokenException(e.getMessage(), e); - } catch (MissingParameterException | IllegalParameterException e) { + } catch (MissingParameterException | IllegalParameterException e) { // can't test throw new RuntimeException( "The auth service is returning invalid usernames, something is very wrong", e); } @@ -89,21 +85,10 @@ public boolean isValidUser(final UserName userName) throws AuthenticationExcepti return auth.isValidUserName( Arrays.asList(userName.getName()), serviceToken.getToken()) .get(userName.getName()); - } catch (IOException | AuthException e) { + } catch (IOException | AuthException e) { // no good way to test this LoggerFactory.getLogger(getClass()).error("Unexpected auth service response", e); throw new AuthenticationException(ErrorType.AUTHENTICATION_FAILED, "Recieved unexpected response from authentication server.", e); } } - - public static void main(final String[] args) throws Exception { - final String token = args[0]; - final UserHandler uh = new KBaseUserHandler(new URL("https://ci.kbase.us/services/auth"), - new Token(token), false); - System.out.println(uh.getUser(new Token(token))); - - System.out.println(uh.isValidUser(new UserName("kkeller"))); - System.out.println(uh.isValidUser(new UserName("veryfakeindeed"))); - } - } diff --git a/src/test/java/us/kbase/test/groups/userhandler/KBaseUserHandlerTest.java b/src/test/java/us/kbase/test/groups/userhandler/KBaseUserHandlerTest.java new file mode 100644 index 00000000..2634548a --- /dev/null +++ b/src/test/java/us/kbase/test/groups/userhandler/KBaseUserHandlerTest.java @@ -0,0 +1,148 @@ +package us.kbase.test.groups.userhandler; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.UUID; + +import org.apache.commons.io.FileUtils; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import us.kbase.groups.core.Token; +import us.kbase.groups.core.UserName; +import us.kbase.groups.core.exceptions.AuthenticationException; +import us.kbase.groups.core.exceptions.ErrorType; +import us.kbase.groups.core.exceptions.InvalidTokenException; +import us.kbase.groups.userhandler.KBaseUserHandler; +import us.kbase.test.auth2.authcontroller.AuthController; +import us.kbase.test.groups.TestCommon; +import us.kbase.testutils.controllers.mongo.MongoController; + +public class KBaseUserHandlerTest { + + private static MongoController MONGO; + private static AuthController AUTH = null; + private static URL AUTHURL = null; + private static Path TEMP_DIR = null; + + private static String TOKEN1 = null; + private static String TOKEN2 = null; + + @BeforeClass + public static void beforeClass() throws Exception { + TestCommon.stfuLoggers(); + TEMP_DIR = TestCommon.getTempDir().resolve(KBaseUserHandlerTest.class.getSimpleName() + + UUID.randomUUID().toString()); + Files.createDirectories(TEMP_DIR); + + MONGO = new MongoController( + TestCommon.getMongoExe().toString(), + TEMP_DIR, + TestCommon.useWiredTigerEngine()); + + AUTH = new AuthController( + "localhost:" + MONGO.getServerPort(), + KBaseUserHandlerTest.class.getSimpleName() + "_test", + TEMP_DIR); + AUTHURL = new URL("http://localhost:" + AUTH.getServerPort() + "/testmode"); + System.out.println("started auth server at " + AUTHURL); + TestCommon.createAuthUser(AUTHURL, "user1", "display1"); + TOKEN1 = TestCommon.createLoginToken(AUTHURL, "user1"); + TestCommon.createAuthUser(AUTHURL, "user2", "display2"); + TOKEN2 = TestCommon.createLoginToken(AUTHURL, "user2"); + } + + @AfterClass + public static void afterClass() throws Exception { + final boolean deleteTempFiles = TestCommon.isDeleteTempFiles(); + if (AUTH != null) { + AUTH.destroy(deleteTempFiles); + } + if (MONGO != null) { + MONGO.destroy(deleteTempFiles); + } + if (TEMP_DIR != null && Files.exists(TEMP_DIR) && deleteTempFiles) { + FileUtils.deleteQuietly(TEMP_DIR.toFile()); + } + } + + @Test + public void getUser() throws Exception { + final KBaseUserHandler kuh = new KBaseUserHandler(AUTHURL, new Token(TOKEN2)); + + final UserName user = kuh.getUser(new Token(TOKEN1)); + assertThat("incorrect username", user, is(new UserName("user1"))); + } + + @Test + public void isValidUser() throws Exception { + final KBaseUserHandler kuh = new KBaseUserHandler(AUTHURL, new Token(TOKEN2)); + + assertThat("incorrect user valid", kuh.isValidUser(new UserName("user1")), is(true)); + assertThat("incorrect user valid", kuh.isValidUser(new UserName("user3")), is(false)); + } + + @Test + public void constructFailNulls() throws Exception { + failConstruct(null, new Token("t"), new NullPointerException("rootAuthURL")); + failConstruct(AUTHURL, null, new NullPointerException("serviceToken")); + } + + @Test + public void constructFailBadArgs() throws Exception { + failConstruct(new URL(AUTHURL.toString() + "/foo"), new Token(TOKEN1), + new AuthenticationException( + ErrorType.AUTHENTICATION_FAILED, + "Failed to contact the auth service: Auth service returned an error: " + + "HTTP 404 Not Found")); + failConstruct(AUTHURL, new Token("fake"), new InvalidTokenException( + "Auth service returned an error: 10020 Invalid token")); + } + + private void failConstruct(final URL url, final Token token, final Exception expected) { + try { + new KBaseUserHandler(url, token); + fail("expected exception"); + } catch (Exception got) { + TestCommon.assertExceptionCorrect(got, expected); + } + } + + @Test + public void getUserFail() throws Exception { + final KBaseUserHandler kuh = new KBaseUserHandler(AUTHURL, new Token(TOKEN2)); + + failGetUser(kuh, null, new NullPointerException("token")); + failGetUser(kuh, new Token("fake"), new InvalidTokenException( + "Auth service returned an error: 10020 Invalid token")); + } + + private void failGetUser( + final KBaseUserHandler kuh, + final Token token, + final Exception expected) { + try { + kuh.getUser(token); + fail("expected exception"); + } catch (Exception got) { + TestCommon.assertExceptionCorrect(got, expected); + } + } + + @Test + public void isValidUserFail() throws Exception { + final KBaseUserHandler kuh = new KBaseUserHandler(AUTHURL, new Token(TOKEN2)); + try { + kuh.isValidUser(null); + fail("expected exception"); + } catch (Exception got) { + TestCommon.assertExceptionCorrect(got, new NullPointerException("userName")); + } + } +} From b393f56b9c0e4025b654231b241a92ee3d529d25 Mon Sep 17 00:00:00 2001 From: Gavin Date: Wed, 15 May 2024 10:34:03 -0700 Subject: [PATCH 12/21] Bump version Also correct location of version in readme --- README.md | 3 ++- src/main/java/us/kbase/groups/service/api/Root.java | 2 +- src/test/java/us/kbase/test/groups/service/api/RootTest.java | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 37e84e99..7ad6d693 100644 --- a/README.md +++ b/README.md @@ -1032,7 +1032,8 @@ cd jettybase * Releases * The master branch is the stable branch. Releases are made from the develop branch to the master branch. - * Update the version as per the semantic version rules in `src/main/java/us/kbase/groups/api/Root.java`. + * Update the version as per the semantic version rules in + `src/main/java/us/kbase/groups/service/api/Root.java`. * Tag the version in git and github. ### Running tests diff --git a/src/main/java/us/kbase/groups/service/api/Root.java b/src/main/java/us/kbase/groups/service/api/Root.java index eb476c4d..c93c2695 100644 --- a/src/main/java/us/kbase/groups/service/api/Root.java +++ b/src/main/java/us/kbase/groups/service/api/Root.java @@ -26,7 +26,7 @@ public class Root { //TODO ZLATER ROOT add configurable contact email or link //TODO ZLATER swagger - private static final String VERSION = "0.1.6"; + private static final String VERSION = "0.1.7"; private static final String SERVER_NAME = "Groups service"; /** Return the root information. diff --git a/src/test/java/us/kbase/test/groups/service/api/RootTest.java b/src/test/java/us/kbase/test/groups/service/api/RootTest.java index 7414cf61..f5d9aa04 100644 --- a/src/test/java/us/kbase/test/groups/service/api/RootTest.java +++ b/src/test/java/us/kbase/test/groups/service/api/RootTest.java @@ -17,7 +17,7 @@ public class RootTest { - public static final String SERVER_VER = "0.1.6"; + public static final String SERVER_VER = "0.1.7"; private static final String GIT_ERR = "Missing git commit file gitcommit, should be in us.kbase.groups"; From 3b4e7e7a7b95314bae9f7f1d387d4bd99bd00a6d Mon Sep 17 00:00:00 2001 From: Sijie Date: Tue, 20 Aug 2024 15:11:21 -0700 Subject: [PATCH 13/21] add mongo7 into workflows matrix --- .github/workflows/test.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 079d5c0d..06f4beec 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,16 +22,12 @@ jobs: fail-fast: false matrix: include: - # the current production setup - java: '8' - mongo: 'mongodb-linux-x86_64-3.6.13' + mongo: 'mongodb-linux-x86_64-ubuntu2204-7.0.4' wired_tiger: 'false' - gradle_test: 'test' - # test all code w/ java 11 - java: '11' mongo: 'mongodb-linux-x86_64-3.6.23' wired_tiger: 'true' - gradle_test: 'test' steps: - uses: actions/checkout@v3 @@ -65,7 +61,7 @@ jobs: - name: Run tests shell: bash run: | - gradle ${{matrix.gradle_test}} + gradle test - name: Upload coverage to Codecov uses: codecov/codecov-action@v3 From 02e6488a331f729ff0d92cea47dd0a04ea4adb20 Mon Sep 17 00:00:00 2001 From: Sijie Date: Thu, 22 Aug 2024 16:47:31 -0700 Subject: [PATCH 14/21] upgrade mongo dependencies --- build.gradle | 5 ++++- .../java/us/kbase/groups/build/GroupsBuilder.java | 12 +++++++----- .../java/us/kbase/groups/service/GroupsService.java | 2 +- .../kbase/test/groups/MongoStorageTestManager.java | 5 +++-- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/build.gradle b/build.gradle index 2d82ac9c..15a0d3e4 100644 --- a/build.gradle +++ b/build.gradle @@ -118,7 +118,10 @@ dependencies { exclude group: 'javax.servlet', module: 'servlet-api' // 2.5 vs 3.0.1 above } implementation 'org.ini4j:ini4j:0.5.2' - implementation 'org.mongodb:mongo-java-driver:3.8.2' + implementation 'org.mongodb:mongodb-driver-core:4.11.1' + implementation 'org.mongodb:mongodb-driver-sync:4.11.1' + implementation 'org.mongodb:bson-record-codec:4.11.1' + implementation 'org.mongodb:bson:4.11.1' implementation 'org.apache.kafka:kafka-clients:2.1.0' implementation 'com.google.guava:guava:18.0' implementation 'org.slf4j:slf4j-api:1.7.25' diff --git a/src/main/java/us/kbase/groups/build/GroupsBuilder.java b/src/main/java/us/kbase/groups/build/GroupsBuilder.java index 34c6441f..ca05883f 100644 --- a/src/main/java/us/kbase/groups/build/GroupsBuilder.java +++ b/src/main/java/us/kbase/groups/build/GroupsBuilder.java @@ -9,8 +9,9 @@ import org.slf4j.LoggerFactory; import com.google.common.collect.ImmutableMap; -import com.mongodb.MongoClient; -import com.mongodb.MongoClientOptions; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import com.mongodb.MongoClientSettings; import com.mongodb.MongoCredential; import com.mongodb.MongoException; import com.mongodb.ServerAddress; @@ -106,15 +107,16 @@ public GroupsBuilder(final GroupsConfig cfg, final MongoClient mc) private MongoClient buildMongo(final GroupsConfig c) throws StorageInitException { //TODO ZLATER MONGO handle shards & replica sets + final MongoClientSettings.Builder mongoBuilder = MongoClientSettings.builder().applyToClusterSettings( + builder -> builder.hosts(Arrays.asList(new ServerAddress(c.getMongoHost())))); try { if (c.getMongoUser().isPresent()) { final MongoCredential creds = MongoCredential.createCredential( c.getMongoUser().get(), c.getMongoDatabase(), c.getMongoPwd().get()); // unclear if and when it's safe to clear the password - return new MongoClient(new ServerAddress(c.getMongoHost()), creds, - MongoClientOptions.builder().build()); + return MongoClients.create(mongoBuilder.credential(creds).build()); } else { - return new MongoClient(new ServerAddress(c.getMongoHost())); + return MongoClients.create(mongoBuilder.build()); } } catch (MongoException e) { LoggerFactory.getLogger(getClass()).error( diff --git a/src/main/java/us/kbase/groups/service/GroupsService.java b/src/main/java/us/kbase/groups/service/GroupsService.java index 2b4f6052..ef6acb29 100644 --- a/src/main/java/us/kbase/groups/service/GroupsService.java +++ b/src/main/java/us/kbase/groups/service/GroupsService.java @@ -4,7 +4,7 @@ import org.glassfish.jersey.server.ResourceConfig; import org.slf4j.LoggerFactory; -import com.mongodb.MongoClient; +import com.mongodb.client.MongoClient; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; diff --git a/src/test/java/us/kbase/test/groups/MongoStorageTestManager.java b/src/test/java/us/kbase/test/groups/MongoStorageTestManager.java index 14b9d0a0..6345280b 100644 --- a/src/test/java/us/kbase/test/groups/MongoStorageTestManager.java +++ b/src/test/java/us/kbase/test/groups/MongoStorageTestManager.java @@ -12,7 +12,8 @@ import org.bson.Document; import com.github.zafarkhaja.semver.Version; -import com.mongodb.MongoClient; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; import com.mongodb.client.MongoDatabase; import us.kbase.groups.core.resource.ResourceType; @@ -39,7 +40,7 @@ public MongoStorageTestManager(final String dbName) throws Exception { wiredTiger = TestCommon.useWiredTigerEngine(); System.out.println(String.format("Testing against mongo executable %s on port %s", TestCommon.getMongoExe(), mongo.getServerPort())); - mc = new MongoClient("localhost:" + mongo.getServerPort()); + mc = MongoClients.create("mongodb://localhost:" + mongo.getServerPort()); db = mc.getDatabase(dbName); final Document bi = db.runCommand(new Document("buildinfo", 1)); From 421b45a348ff1171b2d174a82e7b1f5775085268 Mon Sep 17 00:00:00 2001 From: Sijie Date: Thu, 22 Aug 2024 21:43:47 -0700 Subject: [PATCH 15/21] remove ns --- ...oGroupsStorageDuplicateKeyCheckerTest.java | 4 +- .../mongo/MongoGroupsStorageStartupTest.java | 111 ++++++++---------- 2 files changed, 49 insertions(+), 66 deletions(-) diff --git a/src/test/java/us/kbase/test/groups/storage/mongo/MongoGroupsStorageDuplicateKeyCheckerTest.java b/src/test/java/us/kbase/test/groups/storage/mongo/MongoGroupsStorageDuplicateKeyCheckerTest.java index 54594c80..6b1c2c48 100644 --- a/src/test/java/us/kbase/test/groups/storage/mongo/MongoGroupsStorageDuplicateKeyCheckerTest.java +++ b/src/test/java/us/kbase/test/groups/storage/mongo/MongoGroupsStorageDuplicateKeyCheckerTest.java @@ -131,7 +131,9 @@ public void unparseable() throws Exception { fail("expected exception"); } catch (InvocationTargetException ex) { TestCommon.assertExceptionCorrect((Exception) ex.getTargetException(), - new GroupsStorageException("Unable to parse duplicate key error: some ")); + new GroupsStorageException("Unable to parse duplicate key error: " + + "Write operation error on server 127.0.0.1:27017. " + + "Write error: WriteError{code=11000, message='some ")); } } diff --git a/src/test/java/us/kbase/test/groups/storage/mongo/MongoGroupsStorageStartupTest.java b/src/test/java/us/kbase/test/groups/storage/mongo/MongoGroupsStorageStartupTest.java index bee6fb9c..536c7f35 100644 --- a/src/test/java/us/kbase/test/groups/storage/mongo/MongoGroupsStorageStartupTest.java +++ b/src/test/java/us/kbase/test/groups/storage/mongo/MongoGroupsStorageStartupTest.java @@ -107,9 +107,10 @@ public void startUpWith2ConfigDocs() throws Exception { final Pattern errorPattern = Pattern.compile( "Failed to create index: Write failed with error code 11000 and error message " + - "'(exception: )?E11000 duplicate key error (index|collection): " + + "'(exception: )?(.*)E11000 duplicate key error (index|collection): " + "startUpWith2ConfigDocs.config( index: |\\.\\$)schema_1\\s+dup key: " + - "\\{ : \"schema\" \\}'"); + "(\\{ schema: \"schema\" \\}'|\\{ : \"schema\" \\}')"); + try { new MongoGroupsStorage(db, set()); fail("started mongo with bad config"); @@ -188,27 +189,21 @@ public void checkCollectionNames() throws Exception { @Test public void indexesConfig() { - final Set indexes = new HashSet<>(); - manager.db.getCollection("config").listIndexes() - .forEach((Consumer) indexes::add); + final Set indexes = getAndNormalizeIndexes("config"); assertThat("incorrect indexes", indexes, is(set( new Document("v", manager.indexVer) .append("unique", true) .append("key", new Document("schema", 1)) - .append("name", "schema_1") - .append("ns", "test_mongogroupsstorage.config"), + .append("name", "schema_1"), new Document("v", manager.indexVer) .append("key", new Document("_id", 1)) .append("name", "_id_") - .append("ns", "test_mongogroupsstorage.config") ))); } @Test public void indexesGroups() { - final Set indexes = new HashSet<>(); - manager.db.getCollection("groups").listIndexes() - .forEach((Consumer) indexes::add); + final Set indexes = getAndNormalizeIndexes("groups"); assertThat("incorrect indexes", indexes, is(getDefaultGroupsIndexes())); } @@ -218,28 +213,22 @@ private Set getDefaultGroupsIndexes() { new Document("v", manager.indexVer) .append("unique", true) .append("key", new Document("id", 1)) - .append("name", "id_1") - .append("ns", col), + .append("name", "id_1"), new Document("v", manager.indexVer) .append("key", new Document("own", 1).append("id", 1)) - .append("name", "own_1_id_1") - .append("ns", col), + .append("name", "own_1_id_1"), new Document("v", manager.indexVer) .append("key", new Document("admin", 1).append("id", 1)) - .append("name", "admin_1_id_1") - .append("ns", col), + .append("name", "admin_1_id_1"), new Document("v", manager.indexVer) .append("key", new Document("_id", 1)) - .append("name", "_id_") - .append("ns", col), + .append("name", "_id_"), new Document("v", manager.indexVer) .append("key", new Document("priv", 1).append("id", 1)) - .append("name", "priv_1_id_1") - .append("ns", col), + .append("name", "priv_1_id_1"), new Document("v", manager.indexVer) .append("key", new Document("memb.user", 1).append("id", 1)) .append("name", "memb.user_1_id_1") - .append("ns", col) ); } @@ -250,10 +239,8 @@ public void indexesGroupsWithResourceTypes() throws Exception { try { new MongoGroupsStorage( manager.db, Arrays.asList(new ResourceType("t1"), new ResourceType("t2"))); - final Set indexes = new HashSet<>(); - manager.db.getCollection("groups").listIndexes() - .forEach((Consumer) indexes::add); - + final Set indexes = getAndNormalizeIndexes("groups"); + final String col = "test_mongogroupsstorage.groups"; final Set expected = getDefaultGroupsIndexes(); for (final String t: set("t1", "t2")) { @@ -263,19 +250,16 @@ public void indexesGroupsWithResourceTypes() throws Exception { .append("key", new Document(resKey, 1) .append("own", 1) .append("id", 1)) - .append("name", resKey + "_1_own_1_id_1") - .append("ns", col), + .append("name", resKey + "_1_own_1_id_1"), new Document("v", manager.indexVer) .append("key", new Document(resKey, 1) .append("id", 1)) - .append("name", resKey + "_1_id_1") - .append("ns", col), + .append("name", resKey + "_1_id_1"), new Document("v", manager.indexVer) .append("key", new Document(resKey, 1) .append("priv", 1) .append("id", 1)) .append("name", resKey + "_1_priv_1_id_1") - .append("ns", col) )); } assertThat("incorrect indexes", indexes, is(expected)); @@ -287,75 +271,63 @@ public void indexesGroupsWithResourceTypes() throws Exception { @Test public void indexesRequests() { - final Set indexes = new HashSet<>(); - manager.db.getCollection("requests").listIndexes() - .forEach((Consumer) indexes::add); + final Set indexes = getAndNormalizeIndexes("requests"); final String col = "test_mongogroupsstorage.requests"; assertThat("incorrect indexes", indexes, is(set( new Document("v", manager.indexVer) .append("unique", true) .append("key", new Document("id", 1)) - .append("name", "id_1") - .append("ns", col), + .append("name", "id_1"), new Document("v", manager.indexVer) .append("key", new Document("gid", 1).append("type", 1).append("mod", 1)) - .append("name", "gid_1_type_1_mod_1") - .append("ns", col), + .append("name", "gid_1_type_1_mod_1"), new Document("v", manager.indexVer) .append("key", new Document("gid", 1) .append("status", 1) .append("type", 1) .append("mod", 1)) - .append("name", "gid_1_status_1_type_1_mod_1") - .append("ns", col), + .append("name", "gid_1_status_1_type_1_mod_1"), new Document("v", manager.indexVer) .append("key", new Document("requester", 1).append("mod", 1)) - .append("name", "requester_1_mod_1") - .append("ns", col), + .append("name", "requester_1_mod_1"), new Document("v", manager.indexVer) .append("key", new Document("requester", 1) .append("status", 1) .append("mod", 1)) - .append("name", "requester_1_status_1_mod_1") - .append("ns", col), + .append("name", "requester_1_status_1_mod_1"), new Document("v", manager.indexVer) .append("key", new Document("resaid", 1) .append("restype", 1) .append("type", 1) .append("mod", 1)) - .append("name", "resaid_1_restype_1_type_1_mod_1") - .append("ns", col), + .append("name", "resaid_1_restype_1_type_1_mod_1"), new Document("v", manager.indexVer) .append("key", new Document("resaid", 1) .append("restype", 1) .append("status", 1) .append("type", 1) .append("mod", 1)) - .append("name", "resaid_1_restype_1_status_1_type_1_mod_1") - .append("ns", col), + .append("name", "resaid_1_restype_1_status_1_type_1_mod_1"), new Document("v", manager.indexVer) .append("key", new Document("resrid", 1) .append("restype", 1) .append("type", 1) .append("mod", 1)) - .append("name", "resrid_1_restype_1_type_1_mod_1") - .append("ns", col), + .append("name", "resrid_1_restype_1_type_1_mod_1"), new Document("v", manager.indexVer) .append("key", new Document("resrid", 1) .append("restype", 1) .append("status", 1) .append("type", 1) .append("mod", 1)) - .append("name", "resrid_1_restype_1_status_1_type_1_mod_1") - .append("ns", col), + .append("name", "resrid_1_restype_1_status_1_type_1_mod_1"), new Document("v", manager.indexVer) .append("key", new Document("resrid", 1) .append("requester", 1) .append("restype", 1) .append("type", 1) .append("mod", 1)) - .append("name", "resrid_1_requester_1_restype_1_type_1_mod_1") - .append("ns", col), + .append("name", "resrid_1_requester_1_restype_1_type_1_mod_1"), new Document("v", manager.indexVer) .append("key", new Document("resrid", 1) .append("requester", 1) @@ -363,16 +335,14 @@ public void indexesRequests() { .append("status", 1) .append("type", 1) .append("mod", 1)) - .append("name", "resrid_1_requester_1_restype_1_status_1_type_1_mod_1") - .append("ns", col), + .append("name", "resrid_1_requester_1_restype_1_status_1_type_1_mod_1"), new Document("v", manager.indexVer) .append("key", new Document("resrid", 1) .append("gid", 1) .append("restype", 1) .append("type", 1) .append("mod", 1)) - .append("name", "resrid_1_gid_1_restype_1_type_1_mod_1") - .append("ns", col), + .append("name", "resrid_1_gid_1_restype_1_type_1_mod_1"), new Document("v", manager.indexVer) .append("key", new Document("resrid", 1) .append("gid", 1) @@ -380,23 +350,34 @@ public void indexesRequests() { .append("status", 1) .append("type", 1) .append("mod", 1)) - .append("name", "resrid_1_gid_1_restype_1_status_1_type_1_mod_1") - .append("ns", col), + .append("name", "resrid_1_gid_1_restype_1_status_1_type_1_mod_1"), new Document("v", manager.indexVer) .append("key", new Document("expire", 1)) - .append("name", "expire_1") - .append("ns", col), + .append("name", "expire_1"), new Document("v", manager.indexVer) .append("unique", true) .append("sparse", true) .append("key", new Document("charstr", 1)) - .append("name", "charstr_1") - .append("ns", col), + .append("name", "charstr_1"), new Document("v", manager.indexVer) .append("key", new Document("_id", 1)) .append("name", "_id_") - .append("ns", col) ))); } + + private Set getAndNormalizeIndexes(final String collectionName) { + final Set indexes = new HashSet<>(); + for (Document index: manager.db.getCollection(collectionName).listIndexes()) { + // In MongoDB 4.4, the listIndexes and the mongo shell helper method db.collection.getIndexes() + // no longer returns the namespace ns field in the index specification documents. + index.remove("ns"); + // some versions of Mongo return ints, some longs. Convert all to longs. + if (index.containsKey("expireAfterSeconds")) { + index.put("expireAfterSeconds", ((Number) index.get("expireAfterSeconds")).longValue()); + } + indexes.add(index); + } + return indexes; + } } From 15608b5df90632e15cdde85e7dfb22399d3ae020 Mon Sep 17 00:00:00 2001 From: Sijie Date: Thu, 22 Aug 2024 21:50:44 -0700 Subject: [PATCH 16/21] clean up test file --- .github/workflows/test.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 06f4beec..83beaa92 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -60,8 +60,7 @@ jobs: - name: Run tests shell: bash - run: | - gradle test + run: ./gradlew test - name: Upload coverage to Codecov uses: codecov/codecov-action@v3 From f0d9979af257684cc40da4bc51c26ed0af2d7a7a Mon Sep 17 00:00:00 2001 From: Sijie Date: Tue, 27 Aug 2024 15:14:44 -0700 Subject: [PATCH 17/21] add retryWrites --- RELEASE_NOTES.md | 6 ++++++ deploy.cfg.example | 4 ++++ deployment/conf/.templates/deployment.cfg.templ | 1 + .../java/us/kbase/groups/build/GroupsBuilder.java | 6 ++++-- .../java/us/kbase/groups/config/GroupsConfig.java | 12 +++++++++++- src/main/java/us/kbase/groups/service/api/Root.java | 2 +- .../kbase/test/groups/config/GroupsConfigTest.java | 8 ++++++++ 7 files changed, 35 insertions(+), 4 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 67576215..faffaada 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,11 @@ # KBase Groups Service release notes +## 0.1.8 + +* The MongoDB clients have been updated to the most recent version. +* Added the ``mongo-retrywrites`` configuration setting in ``deploy.cfg``, defaulting to + ``false``. + ## 0.1.7 * The build tool has been switched from Ant to Gradle. diff --git a/deploy.cfg.example b/deploy.cfg.example index 49547470..fc262f26 100644 --- a/deploy.cfg.example +++ b/deploy.cfg.example @@ -10,6 +10,10 @@ mongo-db= mongo-user= mongo-pwd= +# Whether to enable ('true') the MongoDB retryWrites parameter or not (anything other than 'true'). +# See https://www.mongodb.com/docs/manual/core/retryable-writes/ +mongo-retrywrites=false + # KBase Auth server root url. auth-url=https://ci.kbase.us/services/auth diff --git a/deployment/conf/.templates/deployment.cfg.templ b/deployment/conf/.templates/deployment.cfg.templ index 46f7e870..8dc4f5fe 100644 --- a/deployment/conf/.templates/deployment.cfg.templ +++ b/deployment/conf/.templates/deployment.cfg.templ @@ -3,6 +3,7 @@ mongo-host={{ default .Env.mongo_host "ci-mongo" }} mongo-db={{ default .Env.mongo_db "groups" }} mongo-user={{ default .Env.mongo_user "" }} mongo-pwd={{ default .Env.mongo_pwd "" }} +mongo-retrywrites={{ default .Env.mongo_retrywrites "false" }} auth-url={{ default .Env.auth_url "https://ci.kbase.us/services/auth" }} workspace-url={{ default .Env.workspace_url "https://ci.kbase.us/services/ws" }} workspace-admin-token={{ default .Env.workspace_admin_token ""}} diff --git a/src/main/java/us/kbase/groups/build/GroupsBuilder.java b/src/main/java/us/kbase/groups/build/GroupsBuilder.java index ca05883f..fd511d3b 100644 --- a/src/main/java/us/kbase/groups/build/GroupsBuilder.java +++ b/src/main/java/us/kbase/groups/build/GroupsBuilder.java @@ -107,8 +107,10 @@ public GroupsBuilder(final GroupsConfig cfg, final MongoClient mc) private MongoClient buildMongo(final GroupsConfig c) throws StorageInitException { //TODO ZLATER MONGO handle shards & replica sets - final MongoClientSettings.Builder mongoBuilder = MongoClientSettings.builder().applyToClusterSettings( - builder -> builder.hosts(Arrays.asList(new ServerAddress(c.getMongoHost())))); + final MongoClientSettings.Builder mongoBuilder = MongoClientSettings.builder() + .retryWrites(c.getMongoRetryWrites()) + .applyToClusterSettings(builder -> builder.hosts( + Arrays.asList(new ServerAddress(c.getMongoHost())))); try { if (c.getMongoUser().isPresent()) { final MongoCredential creds = MongoCredential.createCredential( diff --git a/src/main/java/us/kbase/groups/config/GroupsConfig.java b/src/main/java/us/kbase/groups/config/GroupsConfig.java index b752f09b..a9eeb021 100644 --- a/src/main/java/us/kbase/groups/config/GroupsConfig.java +++ b/src/main/java/us/kbase/groups/config/GroupsConfig.java @@ -54,6 +54,7 @@ public class GroupsConfig { private static final String KEY_MONGO_DB = "mongo-db"; private static final String KEY_MONGO_USER = "mongo-user"; private static final String KEY_MONGO_PWD = "mongo-pwd"; + private static final String KEY_MONGO_RETRY_WRITES = "mongo-retrywrites"; private static final String KEY_AUTH_URL = "auth-url"; private static final String KEY_WORKSPACE_URL = "workspace-url"; private static final String KEY_WORKSPACE_TOKEN = "workspace-admin-token"; @@ -81,6 +82,7 @@ public class GroupsConfig { private final String mongoDB; private final Optional mongoUser; private final Optional mongoPwd; + private final boolean mongoRetryWrites; private final URL authURL; private final URL workspaceURL; private final Token workspaceAdminToken; @@ -148,6 +150,7 @@ private GroupsConfig( notifierParameters = getParams(KEY_PREFIX_NOTIFIER_PARAMS, cfg); mongoHost = getString(KEY_MONGO_HOST, cfg, true); mongoDB = getString(KEY_MONGO_DB, cfg, true); + mongoRetryWrites = TRUE.equals(getString(KEY_MONGO_RETRY_WRITES, cfg)); mongoUser = Optional.fromNullable(getString(KEY_MONGO_USER, cfg)); Optional mongop = Optional.fromNullable(getString(KEY_MONGO_PWD, cfg)); if (mongoUser.isPresent() ^ mongop.isPresent()) { @@ -420,13 +423,20 @@ public String getMongoHost() { return mongoHost; } - /** Ge the MongoDB database to use. + /** Get the MongoDB database to use. * @return the database. */ public String getMongoDatabase() { return mongoDB; } + /** Get the retryWrites. + * @return the retryWrites. + */ + public boolean getMongoRetryWrites() { + return mongoRetryWrites; + } + /** Get the MongoDB user name, if any. If provided a password will also be provided. * @return the user name */ diff --git a/src/main/java/us/kbase/groups/service/api/Root.java b/src/main/java/us/kbase/groups/service/api/Root.java index c93c2695..61918375 100644 --- a/src/main/java/us/kbase/groups/service/api/Root.java +++ b/src/main/java/us/kbase/groups/service/api/Root.java @@ -26,7 +26,7 @@ public class Root { //TODO ZLATER ROOT add configurable contact email or link //TODO ZLATER swagger - private static final String VERSION = "0.1.7"; + private static final String VERSION = "0.1.8"; private static final String SERVER_NAME = "Groups service"; /** Return the root information. diff --git a/src/test/java/us/kbase/test/groups/config/GroupsConfigTest.java b/src/test/java/us/kbase/test/groups/config/GroupsConfigTest.java index 4196f3d2..e996a473 100644 --- a/src/test/java/us/kbase/test/groups/config/GroupsConfigTest.java +++ b/src/test/java/us/kbase/test/groups/config/GroupsConfigTest.java @@ -89,6 +89,7 @@ public void sysPropNoUserNoBools() throws Throwable { assertThat("incorrect mongo db", cfg.getMongoDatabase(), is("database")); assertThat("incorrect mongo user", cfg.getMongoUser(), is(Optional.absent())); assertThat("incorrect mongo pwd", cfg.getMongoPwd(), is(Optional.absent())); + assertThat("incorrect retry writes", cfg.getMongoRetryWrites(), is(false)); assertThat("incorrect auth url", cfg.getAuthURL(), is(new URL("http://auth.com"))); assertThat("incorrect catalog url", cfg.getCatalogURL(), is(new URL("http://cat.com"))); assertThat("incorrect ws url", cfg.getWorkspaceURL(), is(new URL("http://ws.com"))); @@ -116,6 +117,7 @@ public void sysPropNoUserNoBoolsWhitespaceFields() throws Throwable { "mongo-db=database\n" + "mongo-user=\n" + "mongo-pwd=\n" + + "mongo-retrywrites= false \n" + "notifier-factory= factoryclass \n" + "notifier-param-p1 = np1 \n" + "notifier-param-p2 = np2 \n" + @@ -165,6 +167,7 @@ public void sysPropNoUserNoBoolsWhitespaceFields() throws Throwable { assertThat("incorrect mongo db", cfg.getMongoDatabase(), is("database")); assertThat("incorrect mongo user", cfg.getMongoUser(), is(Optional.absent())); assertThat("incorrect mongo pwd", cfg.getMongoPwd(), is(Optional.absent())); + assertThat("incorrect retry writes", cfg.getMongoRetryWrites(), is(false)); assertThat("incorrect auth url", cfg.getAuthURL(), is(new URL("http://auth.com"))); assertThat("incorrect catalog url", cfg.getCatalogURL(), is(new URL("http://cat.com"))); assertThat("incorrect ws url", cfg.getWorkspaceURL(), is(new URL("http://ws.com"))); @@ -241,6 +244,7 @@ public void envVarWithUserWithBools() throws Throwable { "mongo-db=database\n" + "mongo-user=userfoo\n" + "mongo-pwd=somepwd\n" + + "mongo-retrywrites=true \n" + "notifier-factory= factoryclass \n" + "auth-url=https://auth.com\n" + "catalog-url= http://cat.com \n" + @@ -256,6 +260,7 @@ public void envVarWithUserWithBools() throws Throwable { assertThat("incorrect mongo host", cfg.getMongoHost(), is("mongo")); assertThat("incorrect mongo db", cfg.getMongoDatabase(), is("database")); + assertThat("incorrect retry writes", cfg.getMongoRetryWrites(), is(true)); assertThat("incorrect mongo user", cfg.getMongoUser(), is(Optional.of("userfoo"))); assertThat("incorrect mongo pwd", cfg.getMongoPwd().get(), equalTo("somepwd".toCharArray())); @@ -292,6 +297,7 @@ public void pathNoUserNoBoolsStdLogger() throws Throwable { assertThat("incorrect mongo db", cfg.getMongoDatabase(), is("database")); assertThat("incorrect mongo user", cfg.getMongoUser(), is(Optional.absent())); assertThat("incorrect mongo pwd", cfg.getMongoPwd(), is(Optional.absent())); + assertThat("incorrect retry writes", cfg.getMongoRetryWrites(), is(false)); assertThat("incorrect auth url", cfg.getAuthURL(), is(new URL("https://auth.com"))); assertThat("incorrect catalog url", cfg.getCatalogURL(), is(new URL("http://cat.com"))); assertThat("incorrect ws url", cfg.getWorkspaceURL(), is(new URL("https://ws.com"))); @@ -315,6 +321,7 @@ public void pathWithUserWithBoolsNullLogger() throws Throwable { "mongo-db=database\n" + "mongo-user=userfoo\n" + "mongo-pwd=somepwd\n" + + "mongo-retrywrites=true\n" + "notifier-factory= factoryclass \n" + "auth-url=https://auth.com\n" + "catalog-url= http://cat.com \n" + @@ -327,6 +334,7 @@ public void pathWithUserWithBoolsNullLogger() throws Throwable { assertThat("incorrect mongo host", cfg.getMongoHost(), is("mongo")); assertThat("incorrect mongo db", cfg.getMongoDatabase(), is("database")); + assertThat("incorrect retry writes", cfg.getMongoRetryWrites(), is(true)); assertThat("incorrect mongo user", cfg.getMongoUser(), is(Optional.of("userfoo"))); assertThat("incorrect mongo pwd", cfg.getMongoPwd().get(), equalTo("somepwd".toCharArray())); From 258749f983841333955273aa4a2d6dd48d26cc33 Mon Sep 17 00:00:00 2001 From: Sijie Date: Tue, 27 Aug 2024 15:25:02 -0700 Subject: [PATCH 18/21] bump service version in test --- src/test/java/us/kbase/test/groups/service/api/RootTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/us/kbase/test/groups/service/api/RootTest.java b/src/test/java/us/kbase/test/groups/service/api/RootTest.java index f5d9aa04..0a9af723 100644 --- a/src/test/java/us/kbase/test/groups/service/api/RootTest.java +++ b/src/test/java/us/kbase/test/groups/service/api/RootTest.java @@ -17,7 +17,7 @@ public class RootTest { - public static final String SERVER_VER = "0.1.7"; + public static final String SERVER_VER = "0.1.8"; private static final String GIT_ERR = "Missing git commit file gitcommit, should be in us.kbase.groups"; From 7ab4105413deda9287459472c5fa9e1bd6baf719 Mon Sep 17 00:00:00 2001 From: Sijie Date: Tue, 27 Aug 2024 15:42:36 -0700 Subject: [PATCH 19/21] update Javadoc comments getMongoRetryWrites() --- src/main/java/us/kbase/groups/config/GroupsConfig.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/us/kbase/groups/config/GroupsConfig.java b/src/main/java/us/kbase/groups/config/GroupsConfig.java index a9eeb021..47d9df30 100644 --- a/src/main/java/us/kbase/groups/config/GroupsConfig.java +++ b/src/main/java/us/kbase/groups/config/GroupsConfig.java @@ -430,8 +430,8 @@ public String getMongoDatabase() { return mongoDB; } - /** Get the retryWrites. - * @return the retryWrites. + /** Get whether the MongoDB retryWrites parameter should be set. + * @return True to set the retryWrites parameter when connecting to MongoDB, false otherwise. */ public boolean getMongoRetryWrites() { return mongoRetryWrites; From 83a025995513082946dc573f3e70763c1eece236 Mon Sep 17 00:00:00 2001 From: Sijie Date: Thu, 21 Nov 2024 14:40:45 -0800 Subject: [PATCH 20/21] merge the 0.1.8 changes into 0.1.7 --- RELEASE_NOTES.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index faffaada..f07b9c94 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,13 +1,10 @@ # KBase Groups Service release notes -## 0.1.8 +## 0.1.7 * The MongoDB clients have been updated to the most recent version. * Added the ``mongo-retrywrites`` configuration setting in ``deploy.cfg``, defaulting to ``false``. - -## 0.1.7 - * The build tool has been switched from Ant to Gradle. ## 0.1.6 From b0f6cfd3f825f42c391513e1ffdffc5183df2b3c Mon Sep 17 00:00:00 2001 From: Sijie Date: Thu, 21 Nov 2024 15:19:46 -0800 Subject: [PATCH 21/21] change version to 0.1.7 --- src/main/java/us/kbase/groups/service/api/Root.java | 2 +- src/test/java/us/kbase/test/groups/service/api/RootTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/us/kbase/groups/service/api/Root.java b/src/main/java/us/kbase/groups/service/api/Root.java index 61918375..c93c2695 100644 --- a/src/main/java/us/kbase/groups/service/api/Root.java +++ b/src/main/java/us/kbase/groups/service/api/Root.java @@ -26,7 +26,7 @@ public class Root { //TODO ZLATER ROOT add configurable contact email or link //TODO ZLATER swagger - private static final String VERSION = "0.1.8"; + private static final String VERSION = "0.1.7"; private static final String SERVER_NAME = "Groups service"; /** Return the root information. diff --git a/src/test/java/us/kbase/test/groups/service/api/RootTest.java b/src/test/java/us/kbase/test/groups/service/api/RootTest.java index 0a9af723..f5d9aa04 100644 --- a/src/test/java/us/kbase/test/groups/service/api/RootTest.java +++ b/src/test/java/us/kbase/test/groups/service/api/RootTest.java @@ -17,7 +17,7 @@ public class RootTest { - public static final String SERVER_VER = "0.1.8"; + public static final String SERVER_VER = "0.1.7"; private static final String GIT_ERR = "Missing git commit file gitcommit, should be in us.kbase.groups";