diff --git a/.github/workflows/build.from.main.branch.deploy.to.dev.yml b/.github/workflows/build.from.main.branch.deploy.to.dev.yml index 8b5f894..d24b232 100644 --- a/.github/workflows/build.from.main.branch.deploy.to.dev.yml +++ b/.github/workflows/build.from.main.branch.deploy.to.dev.yml @@ -17,7 +17,7 @@ env: IMAGE_REGISTRY_USER: ${{ github.actor }} IMAGE_REGISTRY_PASSWORD: ${{ github.token }} - SPRING_BOOT_IMAGE_NAME: educ-grad-assessment-api-dc + SPRING_BOOT_IMAGE_NAME: educ-grad-assessment-api REPO_NAME: "educ-grad-assessment-api" APP_DOMAIN: ${{ vars.APP_DOMAIN }} @@ -42,7 +42,7 @@ jobs: steps: - name: Check out repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Determine image tags if: env.TAG == '' @@ -50,7 +50,7 @@ jobs: echo "TAG=latest ${GITHUB_SHA::12}" | tee -a $GITHUB_ENV - name: Login to Docker Hub - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: registry: ${{ vars.DOCKER_ARTIFACTORY_REPO }} username: ${{ vars.DOCKER_ARTIFACTORY_USERNAME }} @@ -95,16 +95,23 @@ jobs: oc login --token=${{ env.OPENSHIFT_TOKEN }} --server=${{ env.OPENSHIFT_SERVER }} oc project ${{ env.OPENSHIFT_NAMESPACE }} # Cancel any rollouts in progress - oc rollout cancel dc/${{ env.SPRING_BOOT_IMAGE_NAME }} 2> /dev/null \ + oc rollout cancel deployment/${{ env.SPRING_BOOT_IMAGE_NAME }} 2> /dev/null \ || true && echo "No rollout in progress" # tag image stream oc -n ${{ env.OPENSHIFT_NAMESPACE }} tag ${{ steps.push-image.outputs.registry-path }} ${{ env.REPO_NAME }}:${{ env.TAG }} # Process and apply deployment template - oc process -f tools/openshift/api.dc.yaml -p IS_NAMESPACE=${{ env.OPENSHIFT_NAMESPACE }} -p REPO_NAME=${{ env.REPO_NAME }} \ - -p TAG_NAME=${{ env.TAG }} -p HOST_ROUTE=${{ env.REPO_NAME }}-${{ env.OPENSHIFT_NAMESPACE }}.${{ env.APP_DOMAIN }} \ - -p MIN_REPLICAS=${{ env.MIN_REPLICAS }} -p MAX_REPLICAS=${{ env.MAX_REPLICAS }} -p MIN_CPU=${{ env.MIN_CPU }} \ - -p MAX_CPU=${{ env.MAX_CPU }} -p MIN_MEM=${{ env.MIN_MEM }} -p MAX_MEM=${{ env.MAX_MEM }} | oc apply -f - + oc process -f tools/openshift/api.dc.yaml \ + -p IS_NAMESPACE=${{ env.OPENSHIFT_NAMESPACE }} \ + -p REPO_NAME=${{ env.REPO_NAME }} \ + -p TAG_NAME=${{ env.TAG }} \ + -p HOST_ROUTE=${{ env.REPO_NAME }}-${{ env.OPENSHIFT_NAMESPACE }}.${{ env.APP_DOMAIN }} \ + -p MIN_REPLICAS=${{ env.MIN_REPLICAS }} \ + -p MAX_REPLICAS=${{ env.MAX_REPLICAS }} \ + -p MIN_CPU=${{ env.MIN_CPU }} \ + -p MAX_CPU=${{ env.MAX_CPU }} \ + -p MIN_MEM=${{ env.MIN_MEM }} \ + -p MAX_MEM=${{ env.MAX_MEM }} | oc apply -f - # UPDATE Configmaps curl -s https://raw.githubusercontent.com/bcgov/${{ env.REPO_NAME }}/${{ env.BRANCH }}/tools/config/update-configmap.sh \ @@ -129,11 +136,10 @@ jobs: ${{ vars.APP_LOG_LEVEL }} # Start rollout (if necessary) and follow it - oc rollout latest dc/${{ env.SPRING_BOOT_IMAGE_NAME }} 2> /dev/null \ - || true && echo "Rollout in progress" - oc logs -f dc/${{ env.SPRING_BOOT_IMAGE_NAME }} + oc rollout restart deployment/${{ env.SPRING_BOOT_IMAGE_NAME }} + # Get status, returns 0 if rollout is successful - oc rollout status dc/${{ env.SPRING_BOOT_IMAGE_NAME }} + oc rollout status deployment/${{ env.SPRING_BOOT_IMAGE_NAME }} # now hit it with a zap scan - name: ZAP Scan diff --git a/.github/workflows/build.from.release.branch.deploy.to.dev.yml b/.github/workflows/build.from.release.branch.deploy.to.dev.yml index 8c0280a..1790b70 100644 --- a/.github/workflows/build.from.release.branch.deploy.to.dev.yml +++ b/.github/workflows/build.from.release.branch.deploy.to.dev.yml @@ -17,7 +17,7 @@ env: IMAGE_REGISTRY_USER: ${{ github.actor }} IMAGE_REGISTRY_PASSWORD: ${{ github.token }} - SPRING_BOOT_IMAGE_NAME: educ-grad-assessment-api-dc + SPRING_BOOT_IMAGE_NAME: educ-grad-assessment-api REPO_NAME: "educ-grad-assessment-api" APP_DOMAIN: ${{ vars.APP_DOMAIN }} @@ -48,7 +48,7 @@ jobs: steps: - name: Check out repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: grad-release @@ -58,7 +58,7 @@ jobs: echo "TAG=latest ${GITHUB_SHA::12}" | tee -a $GITHUB_ENV - name: Login to Docker Hub - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: registry: ${{ vars.DOCKER_ARTIFACTORY_REPO }} username: ${{ vars.DOCKER_ARTIFACTORY_USERNAME }} @@ -103,16 +103,23 @@ jobs: oc login --token=${{ env.OPENSHIFT_TOKEN }} --server=${{ env.OPENSHIFT_SERVER }} oc project ${{ env.OPENSHIFT_NAMESPACE }} # Cancel any rollouts in progress - oc rollout cancel dc/${{ env.SPRING_BOOT_IMAGE_NAME }} 2> /dev/null \ + oc rollout cancel deployment/${{ env.SPRING_BOOT_IMAGE_NAME }} 2> /dev/null \ || true && echo "No rollout in progress" # tag image stream oc -n ${{ env.OPENSHIFT_NAMESPACE }} tag ${{ steps.push-image.outputs.registry-path }} ${{ env.REPO_NAME }}:${{ env.TAG }} # Process and apply deployment template - oc process -f tools/openshift/api.dc.yaml -p IS_NAMESPACE=${{ env.OPENSHIFT_NAMESPACE }} -p REPO_NAME=${{ env.REPO_NAME }} \ - -p TAG_NAME=${{ env.TAG }} -p HOST_ROUTE=${{ env.REPO_NAME }}-${{ env.OPENSHIFT_NAMESPACE }}.${{ env.APP_DOMAIN }} \ - -p MIN_REPLICAS=${{ env.MIN_REPLICAS }} -p MAX_REPLICAS=${{ env.MAX_REPLICAS }} -p MIN_CPU=${{ env.MIN_CPU }} \ - -p MAX_CPU=${{ env.MAX_CPU }} -p MIN_MEM=${{ env.MIN_MEM }} -p MAX_MEM=${{ env.MAX_MEM }} | oc apply -f - + oc process -f tools/openshift/api.dc.yaml \ + -p IS_NAMESPACE=${{ env.OPENSHIFT_NAMESPACE }} \ + -p REPO_NAME=${{ env.REPO_NAME }} \ + -p TAG_NAME=${{ env.TAG }} \ + -p HOST_ROUTE=${{ env.REPO_NAME }}-${{ env.OPENSHIFT_NAMESPACE }}.${{ env.APP_DOMAIN }} \ + -p MIN_REPLICAS=${{ env.MIN_REPLICAS }} \ + -p MAX_REPLICAS=${{ env.MAX_REPLICAS }} \ + -p MIN_CPU=${{ env.MIN_CPU }} \ + -p MAX_CPU=${{ env.MAX_CPU }} \ + -p MIN_MEM=${{ env.MIN_MEM }} \ + -p MAX_MEM=${{ env.MAX_MEM }} | oc apply -f - # UPDATE Configmaps curl -s https://raw.githubusercontent.com/bcgov/${{ env.REPO_NAME }}/${{ env.BRANCH }}/tools/config/update-configmap.sh \ @@ -137,11 +144,10 @@ jobs: ${{ vars.APP_LOG_LEVEL }} # Start rollout (if necessary) and follow it - oc rollout latest dc/${{ env.SPRING_BOOT_IMAGE_NAME }} 2> /dev/null \ - || true && echo "Rollout in progress" - oc logs -f dc/${{ env.SPRING_BOOT_IMAGE_NAME }} + oc rollout restart deployment/${{ env.SPRING_BOOT_IMAGE_NAME }} + # Get status, returns 0 if rollout is successful - oc rollout status dc/${{ env.SPRING_BOOT_IMAGE_NAME }} + oc rollout status deployment/${{ env.SPRING_BOOT_IMAGE_NAME }} # now hit it with a zap scan - name: ZAP Scan diff --git a/.github/workflows/create_tag.yml b/.github/workflows/create_tag.yml index cceb16e..8b10b12 100644 --- a/.github/workflows/create_tag.yml +++ b/.github/workflows/create_tag.yml @@ -36,10 +36,10 @@ jobs: steps: - name: Check out repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Create tag - uses: actions/github-script@v5 + uses: actions/github-script@v7 with: script: | github.rest.git.createRef({ @@ -55,7 +55,7 @@ jobs: oc: 4 # https://github.com/redhat-actions/oc-login#readme - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Tag in OpenShift run: | set -eux diff --git a/.github/workflows/deploy_latest_test.yml b/.github/workflows/deploy_latest_test.yml new file mode 100644 index 0000000..1f1bf17 --- /dev/null +++ b/.github/workflows/deploy_latest_test.yml @@ -0,0 +1,89 @@ +name: Deploy latest to TEST + +env: + # 🖊️ EDIT your repository secrets to log into your OpenShift cluster and set up the context. + # See https://github.com/redhat-actions/oc-login#readme for how to retrieve these values. + # To get a permanent token, refer to https://github.com/redhat-actions/oc-login/wiki/Using-a-Service-Account-for-GitHub-Actions + OPENSHIFT_SERVER: ${{ vars.OPENSHIFT_SERVER }} + OPENSHIFT_TOKEN: ${{ secrets.OPENSHIFT_TOKEN }} + OPENSHIFT_NAMESPACE: ${{ vars.GRAD_NAMESPACE }}-test + COMMON_NAMESPACE: ${{ vars.COMMON_NAMESPACE }} + BUSINESS_NAMESPACE: ${{ vars.GRAD_BUSINESS_NAMESPACE }} + + SPRING_BOOT_IMAGE_NAME: educ-grad-assessment-api + + REPO_NAME: "educ-grad-assessment-api" + APP_DOMAIN: ${{ vars.APP_DOMAIN }} + GRAD_NAMESPACE: ${{ vars.GRAD_NAMESPACE }} + TAG: "latest" + BRANCH: "grad-release" + MIN_CPU: "20m" + MAX_CPU: "100m" + MIN_MEM: "250Mi" + MAX_MEM: "1024Mi" + MIN_REPLICAS: "3" + MAX_REPLICAS: "5" + +on: + # https://docs.github.com/en/actions/reference/events-that-trigger-workflows + workflow_dispatch: + +jobs: + deploy-to-openshift-test: + name: Deploy to OpenShift TEST + runs-on: ubuntu-22.04 + environment: test + + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Install oc + uses: redhat-actions/openshift-tools-installer@v1 + with: + oc: 4 + + # https://github.com/redhat-actions/oc-login#readme + - uses: actions/checkout@v4 + - name: Deploy + run: | + set -eux + # Login to OpenShift and select project + oc login --token=${{ env.OPENSHIFT_TOKEN }} --server=${{ env.OPENSHIFT_SERVER }} + oc project ${{ env.OPENSHIFT_NAMESPACE }} + # Cancel any rollouts in progress + oc rollout cancel deployment/${{ env.SPRING_BOOT_IMAGE_NAME }} 2> /dev/null \ + || true && echo "No rollout in progress" + + oc tag ${{ env.GRAD_NAMESPACE }}-dev/${{ env.REPO_NAME }}:latest \ + ${{ env.GRAD_NAMESPACE }}-test/${{ env.REPO_NAME }}:latest + + # Process and apply deployment template + oc process -f tools/openshift/api.dc.yaml \ + -p IS_NAMESPACE=${{ env.OPENSHIFT_NAMESPACE }} \ + -p REPO_NAME=${{ env.REPO_NAME }} \ + -p TAG_NAME=latest \ + -p HOST_ROUTE=${{ env.REPO_NAME }}-${{ env.OPENSHIFT_NAMESPACE }}.${{ env.APP_DOMAIN }} \ + -p MIN_REPLICAS=${{ env.MIN_REPLICAS }} \ + -p MAX_REPLICAS=${{ env.MAX_REPLICAS }} \ + -p MIN_CPU=${{ env.MIN_CPU }} \ + -p MAX_CPU=${{ env.MAX_CPU }} \ + -p MIN_MEM=${{ env.MIN_MEM }} \ + -p MAX_MEM=${{ env.MAX_MEM }} | oc apply -f - + + # UPDATE Configmaps + curl -s https://raw.githubusercontent.com/bcgov/${{ env.REPO_NAME }}/${{ env.BRANCH }}/tools/config/update-configmap.sh \ + | bash /dev/stdin \ + test \ + ${{ env.REPO_NAME }} \ + ${{ env.GRAD_NAMESPACE }} \ + ${{ env.COMMON_NAMESPACE }} \ + ${{ env.BUSINESS_NAMESPACE }} \ + ${{ secrets.SPLUNK_TOKEN }} \ + ${{ vars.APP_LOG_LEVEL }} + + # Start rollout (if necessary) and follow it + oc rollout restart deployment/${{ env.SPRING_BOOT_IMAGE_NAME }} + + # Get status, returns 0 if rollout is successful + oc rollout status deployment/${{ env.SPRING_BOOT_IMAGE_NAME }} diff --git a/.github/workflows/deploy_prod.yml b/.github/workflows/deploy_prod.yml index 1962bbc..f04a9ea 100644 --- a/.github/workflows/deploy_prod.yml +++ b/.github/workflows/deploy_prod.yml @@ -10,7 +10,7 @@ env: COMMON_NAMESPACE: ${{ vars.COMMON_NAMESPACE }} BUSINESS_NAMESPACE: ${{ vars.GRAD_BUSINESS_NAMESPACE }} - SPRING_BOOT_IMAGE_NAME: educ-grad-assessment-api-dc + SPRING_BOOT_IMAGE_NAME: educ-grad-assessment-api REPO_NAME: "educ-grad-assessment-api" APP_DOMAIN: ${{ vars.APP_DOMAIN }} @@ -34,13 +34,9 @@ jobs: runs-on: ubuntu-22.04 environment: prod - outputs: - ROUTE: ${{ steps.deploy-and-expose.outputs.route }} - SELECTOR: ${{ steps.deploy-and-expose.outputs.selector }} - steps: - name: Check out repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Get latest tag uses: actions-ecosystem/action-get-latest-tag@v1 @@ -52,7 +48,7 @@ jobs: oc: 4 # https://github.com/redhat-actions/oc-login#readme - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Deploy run: | set -eux @@ -60,17 +56,24 @@ jobs: oc login --token=${{ env.OPENSHIFT_TOKEN }} --server=${{ env.OPENSHIFT_SERVER }} oc project ${{ env.OPENSHIFT_NAMESPACE }} # Cancel any rollouts in progress - oc rollout cancel dc/${{ env.SPRING_BOOT_IMAGE_NAME }} 2> /dev/null \ + oc rollout cancel deployment/${{ env.SPRING_BOOT_IMAGE_NAME }} 2> /dev/null \ || true && echo "No rollout in progress" oc tag ${{ env.GRAD_NAMESPACE }}-test/${{ env.REPO_NAME }}:${{ steps.get-latest-tag.outputs.tag }} \ ${{ env.GRAD_NAMESPACE }}-prod/${{ env.REPO_NAME }}:${{ steps.get-latest-tag.outputs.tag }} # Process and apply deployment template - oc process -f tools/openshift/api.dc.yaml -p IS_NAMESPACE=${{ env.OPENSHIFT_NAMESPACE }} -p REPO_NAME=${{ env.REPO_NAME }} \ - -p TAG_NAME=${{ steps.get-latest-tag.outputs.tag }} -p HOST_ROUTE=${{ env.REPO_NAME }}-${{ env.OPENSHIFT_NAMESPACE }}.${{ env.APP_DOMAIN }} \ - -p MIN_REPLICAS=${{ env.MIN_REPLICAS }} -p MAX_REPLICAS=${{ env.MAX_REPLICAS }} -p MIN_CPU=${{ env.MIN_CPU }} -p MAX_CPU=${{ env.MAX_CPU }} \ - -p MIN_MEM=${{ env.MIN_MEM }} -p MAX_MEM=${{ env.MAX_MEM }} | oc apply -f - + oc process -f tools/openshift/api.dc.yaml \ + -p IS_NAMESPACE=${{ env.OPENSHIFT_NAMESPACE }} \ + -p REPO_NAME=${{ env.REPO_NAME }} \ + -p TAG_NAME=${{ steps.get-latest-tag.outputs.tag }} \ + -p HOST_ROUTE=${{ env.REPO_NAME }}-${{ env.OPENSHIFT_NAMESPACE }}.${{ env.APP_DOMAIN }} \ + -p MIN_REPLICAS=${{ env.MIN_REPLICAS }} \ + -p MAX_REPLICAS=${{ env.MAX_REPLICAS }} \ + -p MIN_CPU=${{ env.MIN_CPU }} \ + -p MAX_CPU=${{ env.MAX_CPU }} \ + -p MIN_MEM=${{ env.MIN_MEM }} \ + -p MAX_MEM=${{ env.MAX_MEM }} | oc apply -f - # UPDATE Configmaps curl -s https://raw.githubusercontent.com/bcgov/${{ env.REPO_NAME }}/${{ env.BRANCH }}/tools/config/update-configmap.sh \ @@ -84,8 +87,7 @@ jobs: ${{ vars.APP_LOG_LEVEL }} # Start rollout (if necessary) and follow it - oc rollout latest dc/${{ env.SPRING_BOOT_IMAGE_NAME }} 2> /dev/null \ - || true && echo "Rollout in progress" - oc logs -f dc/${{ env.SPRING_BOOT_IMAGE_NAME }} + oc rollout restart deployment/${{ env.SPRING_BOOT_IMAGE_NAME }} + # Get status, returns 0 if rollout is successful - oc rollout status dc/${{ env.SPRING_BOOT_IMAGE_NAME }} + oc rollout status deployment/${{ env.SPRING_BOOT_IMAGE_NAME }} diff --git a/.github/workflows/deploy_test.yml b/.github/workflows/deploy_test.yml index 5109e1c..39a8737 100644 --- a/.github/workflows/deploy_test.yml +++ b/.github/workflows/deploy_test.yml @@ -10,7 +10,7 @@ env: COMMON_NAMESPACE: ${{ vars.COMMON_NAMESPACE }} BUSINESS_NAMESPACE: ${{ vars.GRAD_BUSINESS_NAMESPACE }} - SPRING_BOOT_IMAGE_NAME: educ-grad-assessment-api-dc + SPRING_BOOT_IMAGE_NAME: educ-grad-assessment-api REPO_NAME: "educ-grad-assessment-api" APP_DOMAIN: ${{ vars.APP_DOMAIN }} @@ -34,13 +34,9 @@ jobs: runs-on: ubuntu-22.04 environment: test - outputs: - ROUTE: ${{ steps.deploy-and-expose.outputs.route }} - SELECTOR: ${{ steps.deploy-and-expose.outputs.selector }} - steps: - name: Check out repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Get latest tag uses: actions-ecosystem/action-get-latest-tag@v1 @@ -52,7 +48,7 @@ jobs: oc: 4 # https://github.com/redhat-actions/oc-login#readme - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Deploy run: | set -eux @@ -60,17 +56,24 @@ jobs: oc login --token=${{ env.OPENSHIFT_TOKEN }} --server=${{ env.OPENSHIFT_SERVER }} oc project ${{ env.OPENSHIFT_NAMESPACE }} # Cancel any rollouts in progress - oc rollout cancel dc/${{ env.SPRING_BOOT_IMAGE_NAME }} 2> /dev/null \ + oc rollout cancel deployment/${{ env.SPRING_BOOT_IMAGE_NAME }} 2> /dev/null \ || true && echo "No rollout in progress" oc tag ${{ env.GRAD_NAMESPACE }}-dev/${{ env.REPO_NAME }}:${{ steps.get-latest-tag.outputs.tag }} \ ${{ env.GRAD_NAMESPACE }}-test/${{ env.REPO_NAME }}:${{ steps.get-latest-tag.outputs.tag }} # Process and apply deployment template - oc process -f tools/openshift/api.dc.yaml -p IS_NAMESPACE=${{ env.OPENSHIFT_NAMESPACE }} -p REPO_NAME=${{ env.REPO_NAME }} \ - -p TAG_NAME=${{ steps.get-latest-tag.outputs.tag }} -p HOST_ROUTE=${{ env.REPO_NAME }}-${{ env.OPENSHIFT_NAMESPACE }}.${{ env.APP_DOMAIN }} \ - -p MIN_REPLICAS=${{ env.MIN_REPLICAS }} -p MAX_REPLICAS=${{ env.MAX_REPLICAS }} -p MIN_CPU=${{ env.MIN_CPU }} -p MAX_CPU=${{ env.MAX_CPU }} \ - -p MIN_MEM=${{ env.MIN_MEM }} -p MAX_MEM=${{ env.MAX_MEM }} | oc apply -f - + oc process -f tools/openshift/api.dc.yaml \ + -p IS_NAMESPACE=${{ env.OPENSHIFT_NAMESPACE }} \ + -p REPO_NAME=${{ env.REPO_NAME }} \ + -p TAG_NAME=${{ steps.get-latest-tag.outputs.tag }} \ + -p HOST_ROUTE=${{ env.REPO_NAME }}-${{ env.OPENSHIFT_NAMESPACE }}.${{ env.APP_DOMAIN }} \ + -p MIN_REPLICAS=${{ env.MIN_REPLICAS }} \ + -p MAX_REPLICAS=${{ env.MAX_REPLICAS }} \ + -p MIN_CPU=${{ env.MIN_CPU }} \ + -p MAX_CPU=${{ env.MAX_CPU }} \ + -p MIN_MEM=${{ env.MIN_MEM }} \ + -p MAX_MEM=${{ env.MAX_MEM }} | oc apply -f - # UPDATE Configmaps curl -s https://raw.githubusercontent.com/bcgov/${{ env.REPO_NAME }}/${{ env.BRANCH }}/tools/config/update-configmap.sh \ @@ -84,8 +87,7 @@ jobs: ${{ vars.APP_LOG_LEVEL }} # Start rollout (if necessary) and follow it - oc rollout latest dc/${{ env.SPRING_BOOT_IMAGE_NAME }} 2> /dev/null \ - || true && echo "Rollout in progress" - oc logs -f dc/${{ env.SPRING_BOOT_IMAGE_NAME }} + oc rollout restart deployment/${{ env.SPRING_BOOT_IMAGE_NAME }} + # Get status, returns 0 if rollout is successful - oc rollout status dc/${{ env.SPRING_BOOT_IMAGE_NAME }} + oc rollout status deployment/${{ env.SPRING_BOOT_IMAGE_NAME }} diff --git a/.github/workflows/on.pr.yml b/.github/workflows/on.pr.yml index 61c367c..40950dd 100644 --- a/.github/workflows/on.pr.yml +++ b/.github/workflows/on.pr.yml @@ -17,14 +17,15 @@ jobs: working-directory: api steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - name: Set up JDK 18 - uses: actions/setup-java@v1 + uses: actions/setup-java@v4 with: + distribution: 'corretto' java-version: 18 - - uses: actions/cache@v1 + - uses: actions/cache@v4 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-5Jun-${{ hashFiles('**/pom.xml') }} @@ -33,7 +34,7 @@ jobs: - name: Run unit tests run: mvn -f pom.xml clean package - name: Run Trivy vulnerability scanner in repo mode - uses: aquasecurity/trivy-action@0.2.5 + uses: aquasecurity/trivy-action@0.29.0 with: scan-type: 'fs' ignore-unfixed: true @@ -41,11 +42,11 @@ jobs: output: 'trivy-results.sarif' severity: 'CRITICAL' - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@v2 + uses: github/codeql-action/upload-sarif@v3 with: sarif_file: 'trivy-results.sarif' - name: Cache SonarCloud packages - uses: actions/cache@v1 + uses: actions/cache@v4 with: path: ~/.sonar/cache key: ${{ runner.os }}-sonar diff --git a/api/pom.xml b/api/pom.xml index ca36e8d..5c9808b 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -6,7 +6,7 @@ ca.bc.gov.educ educ-grad-assessment-api - 1.8.41 + 1.8.42 educ-grad-assessment-api Ministry of Education GRAD Assessment API @@ -18,7 +18,8 @@ src/main/java/ca/bc/gov/educ/api/assessment/exception/**, src/main/java/ca/bc/gov/educ/api/assessment/model/**, src/main/java/ca/bc/gov/educ/api/assessment/config/**, - src/main/java/ca/bc/gov/educ/api/assessment/util/** + src/main/java/ca/bc/gov/educ/api/assessment/util/**, + src/main/java/ca/bc/gov/educ/api/assessment/controller/APIMetadataController.java diff --git a/api/src/main/java/ca/bc/gov/educ/api/assessment/config/WebSecurityConfiguration.java b/api/src/main/java/ca/bc/gov/educ/api/assessment/config/WebSecurityConfiguration.java index 19ae3eb..37de8cd 100644 --- a/api/src/main/java/ca/bc/gov/educ/api/assessment/config/WebSecurityConfiguration.java +++ b/api/src/main/java/ca/bc/gov/educ/api/assessment/config/WebSecurityConfiguration.java @@ -26,7 +26,8 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { "/api/v1/api-docs/**", "/actuator/health", "/actuator/prometheus", - "/health") + "/health", + "/api/v1/metadata") .permitAll() .anyRequest().authenticated() ) diff --git a/api/src/main/java/ca/bc/gov/educ/api/assessment/controller/APIMetadataController.java b/api/src/main/java/ca/bc/gov/educ/api/assessment/controller/APIMetadataController.java new file mode 100644 index 0000000..94b4ef2 --- /dev/null +++ b/api/src/main/java/ca/bc/gov/educ/api/assessment/controller/APIMetadataController.java @@ -0,0 +1,205 @@ +package ca.bc.gov.educ.api.assessment.controller; + +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.info.Info; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import lombok.With; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.YamlPropertiesFactoryBean; +import org.springframework.context.ApplicationContext; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.core.io.ClassPathResource; +import org.springframework.lang.Nullable; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.util.*; + +import static java.util.Optional.ofNullable; + +@CrossOrigin +@RestController +@RequestMapping("/api/v1") +@OpenAPIDefinition( + info = @Info(title = "API for Metadata", description = "API for Metadata", version = "1"), + security = {@SecurityRequirement(name = "OAUTH2", + scopes = {})}) +class APIMetadataController { + private final ApplicationContext context; + + @Autowired + public APIMetadataController(ApplicationContext context) { + this.context = context; + } + + @GetMapping("/metadata") + @Operation(summary = "API Metadata", description = "API Metadata", tags = {"Metadata"}) + @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "OK")}) + String generateMetadata() { + final var controllers = new ArrayList(); + for (String controllerName : context.getBeanNamesForAnnotation(RestController.class)) { + if (StringUtils.equalsAnyIgnoreCase(controllerName, "OpenApiResource", + "SwaggerConfigResource", this.getClass().getSimpleName())) + continue; + final var controllerBean = context.getBean(controllerName); + final var baseApiPath = getApiPath( + AnnotationUtils.findAnnotation(controllerBean.getClass(), RequestMapping.class)); + final var controllerSecurityInfo = new ControllerInfo(StringUtils.capitalize(controllerName), new ArrayList<>()); + for (Method method : controllerBean.getClass().getMethods()) { + getMethodInfo(method) + .map(m -> m.withPrefixedApiPath(baseApiPath)) + .ifPresent(m -> controllerSecurityInfo.methods().add(m)); + } + controllers.add(controllerSecurityInfo); + } + String htmlTemplate = """ + + + + + + + + {EndpointDetailsHTML} + {DownstreamEndpointsHTML} + + + """; + return htmlTemplate.replace("{EndpointDetailsHTML}", getEndpointDetailsHTML(controllers)) + .replace("{DownstreamEndpointsHTML}", getDownstreamEndpointsHTML()); + } + + @With + private record ControllerInfo(String name, List methods) { + } + + @With + private record MethodInfo(String httpMethod, String apiPath, String security, String functionName) { + public MethodInfo withPrefixedApiPath(String prefixedApiPath) { + return withApiPath(prefixedApiPath + this.apiPath); + } + } + + private static Optional getMethodInfo(Method method) { + return Optional.ofNullable(AnnotationUtils.findAnnotation(method, GetMapping.class)) + .or(() -> ofNullable(AnnotationUtils.findAnnotation(method, PostMapping.class))) + .or(() -> ofNullable(AnnotationUtils.findAnnotation(method, DeleteMapping.class))) + .or(() -> ofNullable(AnnotationUtils.findAnnotation(method, PutMapping.class))) + .map(annotation -> AnnotationUtils.getAnnotationAttributes(method, annotation)) + .map(attributes -> new MethodInfo( + attributes.annotationType() + .getSimpleName() + .replace("Mapping", "") + .toUpperCase(), + getApiPath(attributes.getStringArray("value")), + ofNullable(AnnotationUtils.findAnnotation(method, PreAuthorize.class)) + .map(p -> p.value().replace("hasAuthority('", "") + .replace("') and", "") + .replace("')", "") + .replace("SCOPE_", "") + ) + .orElse(""), + method.getName() + )); + } + + private static String getApiPath(@Nullable RequestMapping requestMapping) { + return ofNullable(requestMapping) + .map(RequestMapping::value) + .map(APIMetadataController::getApiPath) + .orElse(""); + } + + private static String getApiPath(@Nullable String... array) { + return ofNullable(array) + .map(arr -> arr.length > 0 ? arr[0] : null) + .orElse(""); + } + + private static String getEndpointDetailsHTML(List controllers) { + HashSet scopes = new HashSet<>(); + StringBuilder endpointDetailsHTML = new StringBuilder(); + endpointDetailsHTML.append(""); + for (ControllerInfo controller : controllers) { + endpointDetailsHTML.append("") + .append(controller.name()) + .append("") + .append("") + .append("") + .append(" ") + .append("Endpoint") + .append("Scopes") + .append("Method"); + for (MethodInfo method : controller.methods()) { + endpointDetailsHTML.append("") + .append("") + .append(method.httpMethod()).append("") + .append("").append(method.apiPath()).append("") + .append("").append(method.security()).append("") + .append("").append(method.functionName()).append("()") + .append(""); + if (method.security().contains(" ")) { + scopes.addAll(Arrays.stream(method.security().split(" ")).toList()); + } else + scopes.add(method.security()); + } + endpointDetailsHTML.append(""); + } + endpointDetailsHTML.append("All Scopes"); + endpointDetailsHTML.append(""); + + for (String scope : scopes.stream().sorted().toList()) { + endpointDetailsHTML.append("").append("") + .append(scope).append("").append(""); + } + endpointDetailsHTML.append(""); + return endpointDetailsHTML.toString(); + } + + private String getDownstreamEndpointsHTML() { + StringBuilder downstreamEndpointsHTML = new StringBuilder(); + downstreamEndpointsHTML.append("Downstream Api calls"); + downstreamEndpointsHTML.append(""); + + YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean(); + yaml.setResources(new ClassPathResource("application.yaml")); + Properties properties = yaml.getObject(); + + assert properties != null; + for (Map.Entry entry : properties.entrySet()) { + if (entry.getKey().toString().startsWith("endpoint.")) { + downstreamEndpointsHTML.append("") + .append("").append(entry.getValue().toString()).append("") + .append(""); + } + } + downstreamEndpointsHTML.append(""); + return downstreamEndpointsHTML.toString(); + } +} \ No newline at end of file diff --git a/api/src/main/java/ca/bc/gov/educ/api/assessment/model/dto/BaseDTO.java b/api/src/main/java/ca/bc/gov/educ/api/assessment/model/dto/BaseDTO.java new file mode 100644 index 0000000..85954e2 --- /dev/null +++ b/api/src/main/java/ca/bc/gov/educ/api/assessment/model/dto/BaseDTO.java @@ -0,0 +1,13 @@ +package ca.bc.gov.educ.api.assessment.model.dto; + +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +@Data +public class BaseDTO { + private String createUser; + private String createDate; + @NotBlank(message = "updateUser must not be null or empty") + private String updateUser; + private String updateDate; +} diff --git a/api/src/main/java/ca/bc/gov/educ/api/assessment/model/dto/School.java b/api/src/main/java/ca/bc/gov/educ/api/assessment/model/dto/School.java index b6b8226..652b136 100644 --- a/api/src/main/java/ca/bc/gov/educ/api/assessment/model/dto/School.java +++ b/api/src/main/java/ca/bc/gov/educ/api/assessment/model/dto/School.java @@ -5,85 +5,39 @@ @Data @Component -public class School { - - private String minCode; - private String schoolName; - private String districtName; - private String transcriptEligibility; - private String certificateEligibility; - private String independentDesignation; - private String mailerType; - private String address1; - private String address2; - private String city; - private String provCode; - private String provinceName; - private String countryCode; - private String countryName; - private String postal; - private String independentAffiliation; - private String openFlag; - private String signatureDistrict; +public class School extends BaseDTO{ + + private String schoolId; + private String districtId; + private String mincode; + private String independentAuthorityId; + private String schoolNumber; + private String faxNumber; + private String phoneNumber; + private String email; + private String website; + private String displayName; + private String displayNameNoSpecialChars; + private String schoolReportingRequirementCode; + private String schoolOrganizationCode; + private String schoolCategoryCode; + private String facilityTypeCode; + private String openedDate; + private String closedDate; + private boolean canIssueTranscripts; + private boolean canIssueCertificates; - public String getSchoolName() { - return schoolName != null ? schoolName.trim(): null; - } - - public String getDistrictName() { - return districtName != null ? districtName.trim(): null; - } - - public String getAddress1() { - return address1 != null ? address1.trim(): null; - } - - public String getAddress2() { - return address2 != null ? address2.trim(): null; - } - - public String getCity() { - return city != null ? city.trim(): null; - } - - public String getProvinceName() { - return provinceName != null ? provinceName.trim(): null; - } - - public String getCountryName() { - return countryName != null ? countryName.trim(): null; - } - - public String getPostal() { - return postal != null ? postal.trim(): null; - } - - public String getIndependentDesignation() { - return independentDesignation != null ? independentDesignation.trim(): null; - } - - public String getIndependentAffiliation() { - return independentAffiliation != null ? independentAffiliation.trim(): null; - } - - public String getOpenFlag() { - return openFlag != null ? openFlag.trim(): null; - } - - public String getSignatureDistrict() { - return signatureDistrict != null ? signatureDistrict.trim(): null; - } - - @Override public String toString() { - return "School [minCode=" + minCode + ", schoolName=" + schoolName + ", districtName=" + districtName - + ", transcriptEligibility=" + transcriptEligibility + ", certificateEligibility=" - + certificateEligibility + ", independentDesignation=" + independentDesignation + ", mailerType=" - + mailerType + ", address1=" + address1 + ", address2=" + address2 + ", city=" + city + ", provCode=" - + provCode + ", provinceName=" + provinceName + ", countryCode=" + countryCode + ", countryName=" - + countryName + ", postal=" + postal + ", independentAffiliation=" + independentAffiliation - + ", openFlag=" + openFlag + ", signatureDistrict=" + signatureDistrict + "]"; + return String.format("School [ schoolId:%s, districtId:%s, mincode:%s, independentAuthorityId:%s, schoolNumber:%s, " + + "faxNumber:%s, phoneNumber:%s, email:%s, website:%s, displayName:%s, displayNameNoSpecialChars:%s, " + + "schoolReportingRequirementCode:%s, schoolOrganizationCode:%s, schoolCategoryCode:%s, facilityTypeCode:%s, " + + "openedDate:%s, closedDate:%s, canIssueTranscripts:%s, canIssueCertificates:%s, createUser:%s, createDate:%s, " + + "updateUser:%s, updateDate:%s ]", + schoolId, districtId, mincode, independentAuthorityId, schoolNumber, faxNumber, phoneNumber, email, website, + displayName, displayNameNoSpecialChars, schoolReportingRequirementCode, schoolOrganizationCode, schoolCategoryCode, + facilityTypeCode, openedDate, closedDate, canIssueTranscripts, canIssueCertificates, getCreateUser(), getCreateDate(), + getUpdateUser(), getUpdateDate()); } diff --git a/api/src/main/java/ca/bc/gov/educ/api/assessment/model/dto/StudentAssessment.java b/api/src/main/java/ca/bc/gov/educ/api/assessment/model/dto/StudentAssessment.java index e24f0e7..52e5f42 100644 --- a/api/src/main/java/ca/bc/gov/educ/api/assessment/model/dto/StudentAssessment.java +++ b/api/src/main/java/ca/bc/gov/educ/api/assessment/model/dto/StudentAssessment.java @@ -18,8 +18,6 @@ public class StudentAssessment { private Assessment assessmentDetails; private String wroteFlag; private String mincodeAssessment; - private String mincodeAssessmentName; - private boolean hasMoreInfo; public String getPen() { return pen != null ? pen.trim():null; diff --git a/api/src/main/java/ca/bc/gov/educ/api/assessment/service/StudentAssessmentService.java b/api/src/main/java/ca/bc/gov/educ/api/assessment/service/StudentAssessmentService.java index ab59343..9ce8137 100644 --- a/api/src/main/java/ca/bc/gov/educ/api/assessment/service/StudentAssessmentService.java +++ b/api/src/main/java/ca/bc/gov/educ/api/assessment/service/StudentAssessmentService.java @@ -1,20 +1,15 @@ package ca.bc.gov.educ.api.assessment.service; - import ca.bc.gov.educ.api.assessment.model.dto.Assessment; -import ca.bc.gov.educ.api.assessment.model.dto.School; import ca.bc.gov.educ.api.assessment.model.dto.StudentAssessment; import ca.bc.gov.educ.api.assessment.model.transformer.AssessmentTransformer; import ca.bc.gov.educ.api.assessment.model.transformer.StudentAssessmentTransformer; import ca.bc.gov.educ.api.assessment.repository.AssessmentRepository; import ca.bc.gov.educ.api.assessment.repository.StudentAssessmentRepository; -import ca.bc.gov.educ.api.assessment.util.EducAssessmentApiConstants; -import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import org.springframework.web.reactive.function.client.WebClient; import java.text.MessageFormat; import java.util.ArrayList; @@ -38,12 +33,6 @@ public class StudentAssessmentService { @Autowired AssessmentTransformer assessmentTransformer; - @Autowired - WebClient webClient; - - @Autowired - EducAssessmentApiConstants constants; - /** * Get all student assessments by PEN populated in Student Assessment DTO * @@ -91,18 +80,6 @@ private void populateFields(List studentAssessmentList, Strin sA.setAssessmentName(assessment.getAssessmentName()); sA.setAssessmentDetails(assessment); } - - if (StringUtils.isNotBlank(sA.getMincodeAssessment())) { - School schObj = webClient.get() - .uri(String.format(constants.getSchoolNameByMincodeUrl(), sA.getMincodeAssessment())) - .headers(h -> h.setBearerAuth(accessToken)) - .retrieve() - .bodyToMono(School.class) - .block(); - if (schObj != null) - sA.setMincodeAssessmentName(schObj.getSchoolName()); - sA.setHasMoreInfo(true); - } }); } } diff --git a/api/src/main/java/ca/bc/gov/educ/api/assessment/util/EducAssessmentApiConstants.java b/api/src/main/java/ca/bc/gov/educ/api/assessment/util/EducAssessmentApiConstants.java index 4fdb6fd..f3c0b05 100644 --- a/api/src/main/java/ca/bc/gov/educ/api/assessment/util/EducAssessmentApiConstants.java +++ b/api/src/main/java/ca/bc/gov/educ/api/assessment/util/EducAssessmentApiConstants.java @@ -46,9 +46,6 @@ public class EducAssessmentApiConstants { @Value("${endpoint.grad-program-api.rule-detail.url}") private String ruleDetailOfProgramManagementApiUrl; - @Value("${endpoint.grad-trax-api.school-name-by-mincode.url}") - private String schoolNameByMincodeUrl; - // Splunk LogHelper Enabled @Value("${splunk.log-helper.enabled}") private boolean splunkLogHelperEnabled; diff --git a/api/src/main/resources/application.yaml b/api/src/main/resources/application.yaml index 6ec02a2..154e22f 100644 --- a/api/src/main/resources/application.yaml +++ b/api/src/main/resources/application.yaml @@ -88,11 +88,8 @@ springdoc: path: /api/v1/api-docs-ui.html operationsSorter: alpha -#Ebdpoints +#Endpoints endpoint: - grad-trax-api: - school-name-by-mincode: - url: ${GRAD_TRAX_API}api/v1/trax/school/%s grad-program-api: rule-detail: url : ${GRAD_PROGRAM_API}api/v1/program/programrules/%s diff --git a/api/src/test/java/ca/bc/gov/educ/api/assessment/model/transformer/StudentAssessmentTransformerTest.java b/api/src/test/java/ca/bc/gov/educ/api/assessment/model/transformer/StudentAssessmentTransformerTest.java index 6e58834..ef40540 100644 --- a/api/src/test/java/ca/bc/gov/educ/api/assessment/model/transformer/StudentAssessmentTransformerTest.java +++ b/api/src/test/java/ca/bc/gov/educ/api/assessment/model/transformer/StudentAssessmentTransformerTest.java @@ -43,7 +43,6 @@ public void testTransformToDTO() { studentAssessment.setAssessmentCode("assmt"); studentAssessment.setAssessmentName("assessment name"); studentAssessment.setMincodeAssessment("12345678"); - studentAssessment.setMincodeAssessmentName("Test school"); studentAssessment.setAssessmentDetails(assessment); StudentAssessmentId studentAssessmentId = new StudentAssessmentId(); @@ -76,7 +75,6 @@ public void testTransformOptionalToDTO() { studentAssessment.setAssessmentCode("assmt"); studentAssessment.setAssessmentName("assessment name"); studentAssessment.setMincodeAssessment("12345678"); - studentAssessment.setMincodeAssessmentName("Test school"); studentAssessment.setAssessmentDetails(assessment); StudentAssessmentId studentAssessmentId = new StudentAssessmentId(); @@ -109,7 +107,6 @@ public void testTransformToEntity() { studentAssessment.setAssessmentCode("assmt"); studentAssessment.setAssessmentName("assessment name"); studentAssessment.setMincodeAssessment("12345678"); - studentAssessment.setMincodeAssessmentName("Test school"); studentAssessment.setAssessmentDetails(assessment); StudentAssessmentId studentAssessmentId = new StudentAssessmentId(); diff --git a/api/src/test/java/ca/bc/gov/educ/api/assessment/service/StudentAssessmentServiceTest.java b/api/src/test/java/ca/bc/gov/educ/api/assessment/service/StudentAssessmentServiceTest.java index 4854b0a..9dd6cbd 100644 --- a/api/src/test/java/ca/bc/gov/educ/api/assessment/service/StudentAssessmentServiceTest.java +++ b/api/src/test/java/ca/bc/gov/educ/api/assessment/service/StudentAssessmentServiceTest.java @@ -11,21 +11,16 @@ import ca.bc.gov.educ.api.assessment.util.EducAssessmentApiConstants; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Mock; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.web.reactive.function.client.WebClient; -import reactor.core.publisher.Mono; import java.util.List; import java.util.Optional; -import java.util.function.Consumer; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; @RunWith(SpringRunner.class) @@ -51,22 +46,6 @@ public class StudentAssessmentServiceTest { @Autowired AssessmentTransformer assessmentTransformer; - @MockBean - WebClient webClient; - - @SuppressWarnings("rawtypes") - @Mock - private WebClient.RequestHeadersSpec requestHeadersMock; - @SuppressWarnings("rawtypes") - @Mock - private WebClient.RequestHeadersUriSpec requestHeadersUriMock; - @Mock - private WebClient.RequestBodySpec requestBodyMock; - @Mock - private WebClient.RequestBodyUriSpec requestBodyUriMock; - @Mock - private WebClient.ResponseSpec responseMock; - @Test public void testGetStudentAssessmentList() { // ID @@ -85,25 +64,18 @@ public void testGetStudentAssessmentList() { assessment.setAssessmentName("asdas"); School school = new School(); - school.setMinCode("12345678"); - school.setSchoolName("Test School"); + school.setMincode("12345678"); + school.setDisplayName("Test School"); when(studentAssessmentRepo.findByPen(studentAssessmentId.getPen())).thenReturn(List.of(studentAssessmentEntity)); when(assessmentRepo.findByAssessmentCode("LTE10")).thenReturn(Optional.of(assessment)); - when(this.webClient.get()).thenReturn(this.requestHeadersUriMock); - when(this.requestHeadersUriMock.uri(String.format(constants.getSchoolNameByMincodeUrl(), studentAssessmentEntity.getMincodeAssessment()))).thenReturn(this.requestHeadersMock); - when(this.requestHeadersMock.headers(any(Consumer.class))).thenReturn(this.requestHeadersMock); - when(this.requestHeadersMock.retrieve()).thenReturn(this.responseMock); - when(this.responseMock.bodyToMono(School.class)).thenReturn(Mono.just(school)); - var result = studentAssessmentService.getStudentAssessmentList(studentAssessmentId.getPen(), "accessToken", true); //GRAD2 - 1929 - Refactoring/Linting - Used isNotEmpty() instead of isEmpty().isFalse(), and chained isNotNull() and isNotEmpty() assertThat(result).isNotNull().isNotEmpty(); StudentAssessment responseStudentAssessment = result.get(0); assertThat(responseStudentAssessment.getAssessmentCode()).isEqualTo(assessment.getAssessmentCode()); assertThat(responseStudentAssessment.getSpecialCase()).isEqualTo(studentAssessmentEntity.getSpecialCase()); - assertThat(responseStudentAssessment.getMincodeAssessmentName()).isEqualTo(school.getSchoolName()); } @Test @@ -124,24 +96,17 @@ public void testGetStudentAssessment() { assessment.setAssessmentName("asdas"); School school = new School(); - school.setMinCode("12345678"); - school.setSchoolName("Test School"); + school.setMincode("12345678"); + school.setDisplayName("Test School"); when(studentAssessmentRepo.findByAssessmentKeyPenAndAssessmentKeyAssessmentCode(studentAssessmentId.getPen(), studentAssessmentId.getAssessmentCode())).thenReturn(List.of(studentAssessmentEntity)); when(assessmentRepo.findByAssessmentCode("LTE10")).thenReturn(Optional.of(assessment)); - when(this.webClient.get()).thenReturn(this.requestHeadersUriMock); - when(this.requestHeadersUriMock.uri(String.format(constants.getSchoolNameByMincodeUrl(), studentAssessmentEntity.getMincodeAssessment()))).thenReturn(this.requestHeadersMock); - when(this.requestHeadersMock.headers(any(Consumer.class))).thenReturn(this.requestHeadersMock); - when(this.requestHeadersMock.retrieve()).thenReturn(this.responseMock); - when(this.responseMock.bodyToMono(School.class)).thenReturn(Mono.just(school)); - var result = studentAssessmentService.getStudentAssessment(studentAssessmentId.getPen(), studentAssessmentId.getAssessmentCode(), "accessToken", true); //GRAD2 - 1929 - Refactoring/Linting - Used isNotEmpty() instead of isEmpty().isFalse(), and chained isNotNull() and isNotEmpty() assertThat(result).isNotNull().isNotEmpty(); StudentAssessment responseStudentAssessment = result.get(0); assertThat(responseStudentAssessment.getAssessmentCode()).isEqualTo(assessment.getAssessmentCode()); assertThat(responseStudentAssessment.getSpecialCase()).isEqualTo(studentAssessmentEntity.getSpecialCase()); - assertThat(responseStudentAssessment.getMincodeAssessmentName()).isEqualTo(school.getSchoolName()); } } diff --git a/api/src/test/resources/application.yaml b/api/src/test/resources/application.yaml index ddb74b5..05d01a9 100644 --- a/api/src/test/resources/application.yaml +++ b/api/src/test/resources/application.yaml @@ -68,10 +68,7 @@ springdoc: #Ebdpoints endpoint: - grad-trax-api: - school-name-by-mincode: - url: https://educ-grad-trax-api-77c02f-dev.apps.silver.devops.gov.bc.ca/api/v1/trax/school/%s - grad-program-api: + grad-program-api: rule-detail: url : https://educ-grad-program-api-77c02f-dev.apps.silver.devops.gov.bc.ca/api/v1/program/programrules/%s diff --git a/tools/bruno/EDUC-GRAD-ASSESSMENT-API/Assessment Requirements/Create an Assessment Requirement.bru b/tools/bruno/EDUC-GRAD-ASSESSMENT-API/Assessment Requirements/Create an Assessment Requirement.bru new file mode 100644 index 0000000..609952e --- /dev/null +++ b/tools/bruno/EDUC-GRAD-ASSESSMENT-API/Assessment Requirements/Create an Assessment Requirement.bru @@ -0,0 +1,34 @@ +meta { + name: Create an Assessment Requirement + type: http + seq: 2 +} + +post { + url: {{baseUrl}}/api/v1/assessment/requirement + body: json + auth: none +} + +body:json { + { + "createUser": "", + "createDate": "", + "updateUser": "", + "updateDate": "", + "assessmentRequirementId": "", + "assessmentCode": "", + "ruleCode": { + "createUser": "", + "createDate": "", + "updateUser": "", + "updateDate": "", + "assmtRequirementCode": "", + "label": "", + "description": "", + "effectiveDate": "", + "expiryDate": "" + }, + "assessmentName": "" + } +} diff --git a/tools/bruno/EDUC-GRAD-ASSESSMENT-API/Assessment Requirements/Find All Assessment Requirements by Rule.bru b/tools/bruno/EDUC-GRAD-ASSESSMENT-API/Assessment Requirements/Find All Assessment Requirements by Rule.bru new file mode 100644 index 0000000..8778fbc --- /dev/null +++ b/tools/bruno/EDUC-GRAD-ASSESSMENT-API/Assessment Requirements/Find All Assessment Requirements by Rule.bru @@ -0,0 +1,17 @@ +meta { + name: Find All Assessment Requirements by Rule + type: http + seq: 4 +} + +get { + url: {{baseUrl}}/api/v1/assessment/requirement/rule + body: none + auth: none +} + +params:query { + rule: + ~pageNo: + ~pageSize: +} diff --git a/tools/bruno/EDUC-GRAD-ASSESSMENT-API/Assessment Requirements/Find All Assessment Requirements.bru b/tools/bruno/EDUC-GRAD-ASSESSMENT-API/Assessment Requirements/Find All Assessment Requirements.bru new file mode 100644 index 0000000..378a1e9 --- /dev/null +++ b/tools/bruno/EDUC-GRAD-ASSESSMENT-API/Assessment Requirements/Find All Assessment Requirements.bru @@ -0,0 +1,18 @@ +meta { + name: Find All Assessment Requirements + type: http + seq: 1 +} + +get { + url: {{baseUrl}}/api/v1/assessment/requirement + body: none + auth: none +} + +params:query { + ~pageNo: + ~pageSize: +} + + diff --git a/tools/bruno/EDUC-GRAD-ASSESSMENT-API/Assessment Requirements/Find all Assessment Requirements by Assessment Code list.bru b/tools/bruno/EDUC-GRAD-ASSESSMENT-API/Assessment Requirements/Find all Assessment Requirements by Assessment Code list.bru new file mode 100644 index 0000000..05cf35e --- /dev/null +++ b/tools/bruno/EDUC-GRAD-ASSESSMENT-API/Assessment Requirements/Find all Assessment Requirements by Assessment Code list.bru @@ -0,0 +1,17 @@ +meta { + name: Find all Assessment Requirements by Assessment Code list + type: http + seq: 3 +} + +post { + url: {{baseUrl}}/api/v1/assessment/requirement/assessment-list + body: json + auth: none +} + +body:json { + { + "assessmentCodes": [] + } +} diff --git a/tools/bruno/EDUC-GRAD-ASSESSMENT-API/Assessment/Find All Assessment.bru b/tools/bruno/EDUC-GRAD-ASSESSMENT-API/Assessment/Find All Assessment.bru new file mode 100644 index 0000000..859c50c --- /dev/null +++ b/tools/bruno/EDUC-GRAD-ASSESSMENT-API/Assessment/Find All Assessment.bru @@ -0,0 +1,11 @@ +meta { + name: Find All Assessment + type: http + seq: 1 +} + +get { + url: {{baseUrl}}/api/v1/assessment + body: none + auth: none +} diff --git a/tools/bruno/EDUC-GRAD-ASSESSMENT-API/Assessment/Find an Assessment Detail by Code.bru b/tools/bruno/EDUC-GRAD-ASSESSMENT-API/Assessment/Find an Assessment Detail by Code.bru new file mode 100644 index 0000000..55e397b --- /dev/null +++ b/tools/bruno/EDUC-GRAD-ASSESSMENT-API/Assessment/Find an Assessment Detail by Code.bru @@ -0,0 +1,15 @@ +meta { + name: Find an Assessment Detail by Code + type: http + seq: 2 +} + +get { + url: {{baseUrl}}/api/v1/assessment/:assmtCode + body: none + auth: none +} + +params:path { + assmtCode: +} diff --git a/tools/bruno/EDUC-GRAD-ASSESSMENT-API/Courses/Find Assessment Algorithm Data by pen.bru b/tools/bruno/EDUC-GRAD-ASSESSMENT-API/Courses/Find Assessment Algorithm Data by pen.bru new file mode 100644 index 0000000..17a97a9 --- /dev/null +++ b/tools/bruno/EDUC-GRAD-ASSESSMENT-API/Courses/Find Assessment Algorithm Data by pen.bru @@ -0,0 +1,17 @@ +meta { + name: Find Assessment Algorithm Data by pen + type: http + seq: 1 +} + +get { + url: {{baseUrl}}/api/v1/assessment/assessment-algorithm/pen/:pen + body: none + auth: none +} + +params:path { + pen: +} + + diff --git a/tools/bruno/EDUC-GRAD-ASSESSMENT-API/Student Assessments/Find All Student Assessments by PEN.bru b/tools/bruno/EDUC-GRAD-ASSESSMENT-API/Student Assessments/Find All Student Assessments by PEN.bru new file mode 100644 index 0000000..66bdfad --- /dev/null +++ b/tools/bruno/EDUC-GRAD-ASSESSMENT-API/Student Assessments/Find All Student Assessments by PEN.bru @@ -0,0 +1,21 @@ +meta { + name: Find All Student Assessments by PEN + type: http + seq: 2 +} + +get { + url: {{baseUrl}}/api/v1/assessment/pen/:pen + body: none + auth: none +} + +params:query { + ~sortForUI: +} + +params:path { + pen: +} + + diff --git a/tools/bruno/EDUC-GRAD-ASSESSMENT-API/Student Assessments/Find Student Assessments by Assessment Code and PEN.bru b/tools/bruno/EDUC-GRAD-ASSESSMENT-API/Student Assessments/Find Student Assessments by Assessment Code and PEN.bru new file mode 100644 index 0000000..da7c4b3 --- /dev/null +++ b/tools/bruno/EDUC-GRAD-ASSESSMENT-API/Student Assessments/Find Student Assessments by Assessment Code and PEN.bru @@ -0,0 +1,22 @@ +meta { + name: Find Student Assessments by Assessment Code and PEN + type: http + seq: 1 +} + +get { + url: {{baseUrl}}/api/v1/assessment/:assmtCode/pen/:pen + body: none + auth: none +} + +params:query { + ~sortForUI: +} + +params:path { + assmtCode: + pen: +} + + diff --git a/tools/bruno/EDUC-GRAD-ASSESSMENT-API/bruno.json b/tools/bruno/EDUC-GRAD-ASSESSMENT-API/bruno.json new file mode 100644 index 0000000..2afab8f --- /dev/null +++ b/tools/bruno/EDUC-GRAD-ASSESSMENT-API/bruno.json @@ -0,0 +1,9 @@ +{ + "version": "1", + "name": "EDUC-GRAD-ASSESSMENT-API", + "type": "collection", + "ignore": [ + "node_modules", + ".git" + ] +} \ No newline at end of file diff --git a/tools/bruno/EDUC-GRAD-ASSESSMENT-API/collection.bru b/tools/bruno/EDUC-GRAD-ASSESSMENT-API/collection.bru new file mode 100644 index 0000000..8831ef0 --- /dev/null +++ b/tools/bruno/EDUC-GRAD-ASSESSMENT-API/collection.bru @@ -0,0 +1,21 @@ +headers { + Authorization: Bearer {{token}} +} + +auth { + mode: oauth2 +} + +auth:oauth2 { + grant_type: client_credentials + access_token_url: {{tokenRootUrl}}/auth/realms/master/protocol/openid-connect/token + client_id: {{clientId}} + client_secret: {{secret}} + scope: +} + +script:post-response { + if(req.getAuthMode() == 'oauth2' && res.body.access_token) { + bru.setVar('token', res.body.access_token); + } +} diff --git a/tools/bruno/EDUC-GRAD-ASSESSMENT-API/environments/dev.bru b/tools/bruno/EDUC-GRAD-ASSESSMENT-API/environments/dev.bru new file mode 100644 index 0000000..fd3eb34 --- /dev/null +++ b/tools/bruno/EDUC-GRAD-ASSESSMENT-API/environments/dev.bru @@ -0,0 +1,8 @@ +vars { + baseUrl: https://educ-grad-assessment-api-77c02f-dev.apps.silver.devops.gov.bc.ca + tokenRootUrl: https://soam-dev.apps.silver.devops.gov.bc.ca +} +vars:secret [ + clientId, + secret +] diff --git a/tools/bruno/EDUC-GRAD-ASSESSMENT-API/environments/local.bru b/tools/bruno/EDUC-GRAD-ASSESSMENT-API/environments/local.bru new file mode 100644 index 0000000..f983cd9 --- /dev/null +++ b/tools/bruno/EDUC-GRAD-ASSESSMENT-API/environments/local.bru @@ -0,0 +1,8 @@ +vars { + baseUrl: http://localhost:8082 + tokenRootUrl: https://soam-dev.apps.silver.devops.gov.bc.ca +} +vars:secret [ + clientId, + secret +] diff --git a/tools/bruno/EDUC-GRAD-ASSESSMENT-API/environments/prod.bru b/tools/bruno/EDUC-GRAD-ASSESSMENT-API/environments/prod.bru new file mode 100644 index 0000000..1cfe664 --- /dev/null +++ b/tools/bruno/EDUC-GRAD-ASSESSMENT-API/environments/prod.bru @@ -0,0 +1,8 @@ +vars { + baseUrl: http://localhost:8888 + tokenRootUrl: https://soam-prod.apps.silver.devops.gov.bc.ca +} +vars:secret [ + clientId, + secret +] diff --git a/tools/bruno/EDUC-GRAD-ASSESSMENT-API/environments/test.bru b/tools/bruno/EDUC-GRAD-ASSESSMENT-API/environments/test.bru new file mode 100644 index 0000000..18a1bd1 --- /dev/null +++ b/tools/bruno/EDUC-GRAD-ASSESSMENT-API/environments/test.bru @@ -0,0 +1,8 @@ +vars { + baseUrl: http://localhost:8888 + tokenRootUrl: https://soam-test.apps.silver.devops.gov.bc.ca +} +vars:secret [ + clientId, + secret +] diff --git a/tools/config/update-configmap.sh b/tools/config/update-configmap.sh index 7e95963..2e83311 100644 --- a/tools/config/update-configmap.sh +++ b/tools/config/update-configmap.sh @@ -54,8 +54,13 @@ echo Creating config map "$APP_NAME"-config-map oc create -n "$GRAD_NAMESPACE"-"$envValue" configmap "$APP_NAME"-config-map \ --from-literal=APP_LOG_LEVEL="$APP_LOG_LEVEL" \ --from-literal=ENABLE_FLYWAY="true" \ - --from-literal=GRAD_PROGRAM_API="http://educ-grad-program-api.$GRAD_NAMESPACE-$envValue.svc.cluster.local:8080/" \ - --from-literal=GRAD_TRAX_API="http://educ-grad-trax-api.$GRAD_NAMESPACE-$envValue.svc.cluster.local:8080/" \ + --from-literal=GRAD_PROGRAM_API="http://educ-grad-program-api.$GRAD_NAMESPACE-$envValue.svc.cluster.local:8080/" \ + --from-literal=GRAD_TRAX_API="http://educ-grad-trax-api.$GRAD_NAMESPACE-$envValue.svc.cluster.local:8080/" \ + --from-literal=CONNECTION_TIMEOUT='30000' \ + --from-literal=MAXIMUM_POOL_SIZE='10' \ + --from-literal=MIN_IDLE='10' \ + --from-literal=IDLE_TIMEOUT='300000' \ + --from-literal=MAX_LIFETIME='420000' \ --dry-run=client -o yaml | oc apply -f - echo diff --git a/tools/openshift/api.dc.yaml b/tools/openshift/api.dc.yaml index abbee25..ceb3469 100644 --- a/tools/openshift/api.dc.yaml +++ b/tools/openshift/api.dc.yaml @@ -6,29 +6,27 @@ labels: metadata: name: "${REPO_NAME}-deploy-template" objects: - - apiVersion: v1 - kind: DeploymentConfig + - apiVersion: apps/v1 + kind: Deployment metadata: labels: app: "${REPO_NAME}" app.kubernetes.io/part-of: GRAD-Backend-API app.openshift.io/runtime: spring-boot - name: "${REPO_NAME}-dc" + name: "${REPO_NAME}" spec: - replicas: 1 - revisionHistoryLimit: 1 - triggers: [] + replicas: ${{MIN_REPLICAS}} selector: - app: "${REPO_NAME}" - deploymentConfig: "${REPO_NAME}-dc" + matchLabels: + app: "${REPO_NAME}" strategy: - resources: {} - type: Rolling + rollingUpdate: + maxUnavailable: 25% + maxSurge: 25% template: metadata: labels: app: "${REPO_NAME}" - deploymentConfig: "${REPO_NAME}-dc" spec: containers: - image: image-registry.openshift-image-registry.svc:5000/${IS_NAMESPACE}/${REPO_NAME}:${TAG_NAME} @@ -129,16 +127,15 @@ objects: protocol: TCP selector: app: "${REPO_NAME}" - deploymentconfig: "${REPO_NAME}-dc" - apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: "${REPO_NAME}-cpu-autoscaler" spec: scaleTargetRef: - apiVersion: apps.openshift.io/v1 - kind: DeploymentConfig - name: "${REPO_NAME}-dc" + apiVersion: apps/v1 + kind: Deployment + name: "${REPO_NAME}" minReplicas: ${{MIN_REPLICAS}} maxReplicas: ${{MAX_REPLICAS}} metrics: