diff --git a/.devops/deploy-pipelines.yml b/.devops/deploy-pipelines.yml new file mode 100644 index 0000000..2aab5e2 --- /dev/null +++ b/.devops/deploy-pipelines.yml @@ -0,0 +1,181 @@ +# Build and push image to Azure Container Registry; Deploy to Azure Kubernetes Service +# https://docs.microsoft.com/azure/devops/pipelines/languages/docker + +parameters: + - name: 'executeBuild' + displayName: 'Launch docker build' + type: boolean + default: true + +trigger: + branches: + include: + - develop + - uat + - main + paths: + include: + - src/* + - build.gradle.kts + - helm/* + - Dockerfile + - settings.gradle.kts + +pr: none + +resources: + - repo: self + +variables: + + # vmImageNameDefault: 'ubuntu-latest' + vmImageNameDefault: ubuntu-22.04 + + imageRepository: '$(K8S_IMAGE_REPOSITORY_NAME)' + deployNamespace: '$(DEPLOY_NAMESPACE)' + helmReleaseName : '$(HELM_RELEASE_NAME)' + canDeploy: true + + ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/uat') }}: + environment: 'UAT' + dockerRegistryName: '$(UAT_CONTAINER_REGISTRY_NAME)' + dockerRegistryServiceConnection: '$(UAT_CONTAINER_REGISTRY_SERVICE_CONN)' + kubernetesServiceConnection: '$(UAT_KUBERNETES_SERVICE_CONN)' + containerRegistry: '$(UAT_CONTAINER_REGISTRY_NAME)' + selfHostedAgentPool: $(UAT_AGENT_POOL) + postmanEnvFile: p4pa_UAT.postman_environment.json + + ${{ elseif eq(variables['Build.SourceBranch'], 'refs/heads/main') }}: + environment: 'PROD' + dockerRegistryName: '$(PROD_CONTAINER_REGISTRY_NAME)' + dockerRegistryServiceConnection: '$(PROD_CONTAINER_REGISTRY_SERVICE_CONN)' + kubernetesServiceConnection: '$(PROD_KUBERNETES_SERVICE_CONN)' + containerRegistry: '$(PROD_CONTAINER_REGISTRY_NAME)' + selfHostedAgentPool: $(PROD_AGENT_POOL) + + ${{ else }}: + environment: 'DEV' + dockerRegistryName: '$(DEV_CONTAINER_REGISTRY_NAME)' + dockerRegistryServiceConnection: '$(DEV_CONTAINER_REGISTRY_SERVICE_CONN)' + kubernetesServiceConnection: '$(DEV_KUBERNETES_SERVICE_CONN)' + containerRegistry: '$(DEV_CONTAINER_REGISTRY_NAME)' + selfHostedAgentPool: $(DEV_AGENT_POOL) + postmanEnvFile: p4pa_DEV.postman_environment.json + +stages: + - stage: stage_build + condition: eq(variables.canDeploy, true) + displayName: 'Build and publish image to ${{ variables.environment }} registry' + jobs: + - job: job_build + displayName: Build + pool: + vmImage: $(vmImageNameDefault) + steps: + - task: Bash@3 + displayName: Get app version + name: getAppVersion + condition: and(succeeded(), eq(variables.canDeploy, true)) + inputs: + targetType: 'inline' + script: | + version=$(cat build.gradle.kts | grep "version = '.*'" | cut -d"'" -f2) + echo "Building $version version" + echo "##vso[task.setvariable variable=appVersion;isOutput=true]$version" + failOnStderr: true + + - task: Docker@2 + condition: and(succeeded(), ${{ parameters.executeBuild }}) + displayName: 'Build and publish $(imageRepository) image' + inputs: + containerRegistry: '$(dockerRegistryServiceConnection)' + repository: '$(imageRepository)' + command: 'buildAndPush' + tags: | + latest + $(Build.SourceVersion) + $(getAppVersion.appVersion) + + - task: PublishPipelineArtifact@1 + displayName: 'Publish manifests into pipeline artifacts' + condition: succeeded() + inputs: + targetPath: '$(Build.Repository.LocalPath)/helm' + artifact: 'helm' + publishLocation: 'pipeline' + - task: 'Bash@3' + displayName: 'Send message on Slack' + condition: in(variables['Agent.JobStatus'], 'SucceededWithIssues', 'Failed') + inputs: + targetType: 'inline' + script: > + curl -X POST \ + -H "Content-type: application/json" \ + --data '{"text": "*Attention: There is an error in pipeline $(System.DefinitionName) in step _build_!*\nCheck the logs for more details $(System.CollectionUri)$(System.TeamProject)/_build/results?buildId=$(Build.BuildId) to view the build results."}' \ + $(SLACK_WEBHOOK_URL) + - stage: stage_deploy + displayName: 'Deploy to ${{ variables.environment }} K8S' + dependsOn: [ stage_build ] + variables: + appVersion: $[ stageDependencies.stage_build.job_build.outputs['getAppVersion.appVersion'] ] + condition: and(succeeded(), eq(variables.canDeploy, true)) + jobs: + - deployment: job_deploy + displayName: 'Deploy' + pool: + name: $(selfHostedAgentPool) + environment: '$(environment)' + strategy: + runOnce: + deploy: + steps: + - download: none + - task: DownloadPipelineArtifact@2 + inputs: + buildType: 'current' + artifactName: 'helm' + targetPath: '$(Pipeline.Workspace)/helm' + - task: KubectlInstaller@0 + - task: Bash@3 + name: helm_dependency_build + displayName: Helm dependency build + inputs: + workingDirectory: '$(Pipeline.Workspace)/helm' + targetType: 'inline' + script: | + helm repo add pagopa-microservice https://pagopa.github.io/aks-microservice-chart-blueprint + helm dep build + failOnStderr: true + - bash: | + echo 'microservice-chart: + podAnnotations: + "build/buildNumber": "$(Build.BuildNumber)" + "build/appVersion": "$(appVersion)" + "build/sourceVersion": "$(Build.SourceVersion)"' > buildMetadata.yaml + displayName: Writing build metadata + + - task: HelmDeploy@0 + displayName: Helm upgrade + inputs: + kubernetesServiceEndpoint: ${{ variables.kubernetesServiceConnection }} + namespace: '$(deployNamespace)' + command: upgrade + chartType: filepath + chartPath: $(Pipeline.Workspace)/helm + chartName: ${{ variables.helmReleaseName }} + releaseName: ${{ variables.helmReleaseName }} + valueFile: "$(Pipeline.Workspace)/helm/values-${{ lower(variables.environment) }}.yaml" + install: true + waitForExecution: true + arguments: --timeout 5m0s + --values buildMetadata.yaml + - task: 'Bash@3' + displayName: 'Send message on Slack' + condition: in(variables['Agent.JobStatus'], 'SucceededWithIssues', 'Failed') + inputs: + targetType: 'inline' + script: > + curl -X POST \ + -H "Content-type: application/json" \ + --data '{"text": "*Attention: There is an error in pipeline $(System.DefinitionName) in step _deploy_!*\nCheck the logs for more details $(System.CollectionUri)$(System.TeamProject)/_build/results?buildId=$(Build.BuildId) to view the build results."}' \ + $(SLACK_WEBHOOK_URL) \ No newline at end of file diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..8af972c --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +/gradlew text eol=lf +*.bat text eol=crlf +*.jar binary diff --git a/.github/workflows/codereview.yml b/.github/workflows/codereview.yml new file mode 100644 index 0000000..67f164f --- /dev/null +++ b/.github/workflows/codereview.yml @@ -0,0 +1,48 @@ +name: P4PA-PDND-SERVICES - Code Review + +on: + push: + branches: + - main + - uat + - develop + pull_request: + types: + - opened + - edited + - synchronize +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.1.7 + with: + fetch-depth: 0 + + - name: Setup Java + uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 #v4.2.1 + with: + distribution: 'corretto' + java-version: 17 + + - name: Grant execute permission for gradlew + run: chmod +x ./gradlew + + - name: Build with Gradle + working-directory: ./ + run: ./gradlew clean build jacocoTestReport + + - name: Sonar Scan + working-directory: ./ + run: > + ./gradlew sonar + -Dorg.gradle.jvmargs=-Xmx4096M + -Dsonar.host.url=https://sonarcloud.io + -Dsonar.organization=${{ vars.SONARCLOUD_ORG }} + -Dsonar.projectKey=${{ vars.SONARCLOUD_PROJECT_KEY }} + -Dsonar.projectName="${{ vars.SONARCLOUD_PROJECT_NAME }}" + -Dsonar.token=${{ secrets.SONAR_TOKEN }} + -Dsonar.sources=src/main + -Dsonar.tests=src/test + -Dsonar.coverage.jacoco.xmlReportPaths=build/reports/jacoco/test/jacocoTestReport.xml diff --git a/.github/workflows/config/trivy.yaml b/.github/workflows/config/trivy.yaml new file mode 100644 index 0000000..298b3a3 --- /dev/null +++ b/.github/workflows/config/trivy.yaml @@ -0,0 +1,3 @@ +db: + repository: "public.ecr.aws/aquasecurity/trivy-db:2" + java-repository: "public.ecr.aws/aquasecurity/trivy-java-db:1" \ No newline at end of file diff --git a/.github/workflows/pr-title.yml b/.github/workflows/pr-title.yml index edabda9..e4d23f2 100644 --- a/.github/workflows/pr-title.yml +++ b/.github/workflows/pr-title.yml @@ -1,4 +1,4 @@ -name: Validate PR title +name: "Validate PR title" on: pull_request_target: @@ -14,7 +14,8 @@ jobs: steps: # Please look up the latest version from # https://github.com/amannn/action-semantic-pull-request/releases - - uses: amannn/action-semantic-pull-request@0723387faaf9b38adef4775cd42cfd5155ed6017 # v5.5.3 + # from https://github.com/amannn/action-semantic-pull-request/commits/main + - uses: amannn/action-semantic-pull-request@01d5fd8a8ebb9aafe902c40c53f0f4744f7381eb env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: @@ -30,7 +31,7 @@ jobs: requireScope: false # Configure additional validation for the subject based on a regex. # This example ensures the subject starts with an uppercase character. - subjectPattern: ^[A-Z].+$ + subjectPattern: ^.+$ # If `subjectPattern` is configured, you can use this property to override # the default error message that is shown when the pattern doesn't match. # The variables `subject` and `title` can be used within the message. @@ -52,4 +53,4 @@ jobs: validateSingleCommit: false # Related to `validateSingleCommit` you can opt-in to validate that the PR # title matches a single commit to avoid confusion. - validateSingleCommitMatchesPrTitle: false + validateSingleCommitMatchesPrTitle: false \ No newline at end of file diff --git a/.github/workflows/security-scan.yml b/.github/workflows/security-scan.yml new file mode 100644 index 0000000..239bc0d --- /dev/null +++ b/.github/workflows/security-scan.yml @@ -0,0 +1,70 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +# This workflow checks out code, builds an image, performs a container image +# vulnerability scan with Trivy tool, and integrates the results with GitHub Advanced Security +# code scanning feature. +name: Container Scan + +on: + pull_request: + # The branches below must be a subset of the branches above + branches: [ "develop", "uat", "main" ] + workflow_dispatch: + schedule: + - cron: '00 07 * * *' + +permissions: + contents: read + +jobs: + BuildAndScan: + permissions: + contents: read # for actions/checkout to fetch code + security-events: write # for github/codeql-action/upload-sarif to upload SARIF results + actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status + runs-on: ubuntu-latest + outputs: + CVE_CRITICAL: ${{env.CVE_CRITICAL}} + CVE_HIGH: ${{env.CVE_HIGH}} + CVE_MEDIUM: ${{env.CVE_MEDIUM}} + steps: + - name: Checkout the code + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1 + - name: Build the Docker image + run: docker build . --file Dockerfile --tag localbuild/testimage:latest + - name: Run the Trivy scan action itself with GitHub Advanced Security code scanning integration enabled + id: scan + uses: aquasecurity/trivy-action@0.28.0 #v0.28.0 + with: + trivy-config: 'config/trivy.yaml' + image-ref: "localbuild/testimage:latest" + format: 'sarif' + output: 'results.sarif' + - name: Upload Anchore Scan Report + uses: github/codeql-action/upload-sarif@99c9897648dded3fe63d6f328c46089dd57735ca #codeql bundle v2.17.0 + with: + sarif_file: 'results.sarif' + - name: CVE Description escaped extraction and print + run: | + SCAN_RESULTS=$(jq -r 'try .runs[0].tool.driver.rules | map(.help.text) | join("\\n")' results.sarif) + echo "CVE_CRITICAL=$(echo $SCAN_RESULTS | grep -o CRITICAL | wc -l)" >> $GITHUB_ENV + echo "CVE_HIGH=$(echo $SCAN_RESULTS | grep -o HIGH | wc -l)" >> $GITHUB_ENV + echo "CVE_MEDIUM=$(echo $SCAN_RESULTS | grep -o MEDIUM | wc -l)" >> $GITHUB_ENV + + echo $SCAN_RESULTS + - name: Fails if CVE HIGH or CRITICAL are detected + id: cve-threshold + if: env.CVE_HIGH > 0 || env.CVE_CRITICAL > 0 + run: exit 1 + SendSlackNotification: + needs: BuildAndScan + uses: ./.github/workflows/send-notification.yml + if: always() && (needs.BuildAndScan.outputs.CVE_HIGH > 0 || needs.BuildAndScan.outputs.CVE_CRITICAL > 0) + with: + CVE_CRITICAL: ${{needs.BuildAndScan.outputs.CVE_CRITICAL}} + CVE_HIGH: ${{needs.BuildAndScan.outputs.CVE_HIGH}} + CVE_MEDIUM: ${{needs.BuildAndScan.outputs.CVE_MEDIUM}} + secrets: inherit \ No newline at end of file diff --git a/.github/workflows/send-notification.yml b/.github/workflows/send-notification.yml new file mode 100644 index 0000000..5820a14 --- /dev/null +++ b/.github/workflows/send-notification.yml @@ -0,0 +1,49 @@ +name: "Send notification" + +on: + workflow_call: + inputs: + CVE_CRITICAL: + required: true + type: string + CVE_HIGH: + required: true + type: string + CVE_MEDIUM: + required: true + type: string + secrets: + SLACK_WEBHOOK_URL: + required: true + +jobs: + Notify: + name: Notify Slack + runs-on: ubuntu-latest + steps: + - name: Send notification to Slack + id: slack + uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 #v1.25.0 + with: + payload: | + { + "blocks": [ + { + "type": "header", + "text": { + "type": "plain_text", + "text": "[ ${{ github.event.repository.name }} ]" + } + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": " `CRITICAL` : *${{ inputs.CVE_CRITICAL }}*\n\n`HIGH` : *${{ inputs.CVE_HIGH }}*\n\n`MEDIUM` : *${{ inputs.CVE_MEDIUM }}*\n\n" + } + } + ] + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} + SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK \ No newline at end of file diff --git a/.gitignore b/.gitignore index e1a6165..b0e00b9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,11 @@ HELP.md -!**/src/main/**/target/ -!**/src/test/**/target/ - -#**/src/main/resources/application-local*.properties +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ +*.tgz +helm/charts ### STS ### .apt_generated @@ -12,12 +15,18 @@ HELP.md .settings .springBeans .sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ ### IntelliJ IDEA ### .idea *.iws *.iml *.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ ### NetBeans ### /nbproject/private/ @@ -25,108 +34,11 @@ HELP.md /dist/ /nbdist/ /.nb-gradle/ -build/ -!**/src/main/**/build/ -!**/src/test/**/build/ ### VS Code ### .vscode/ -###################### -# Maven -###################### -/log/ -/target/** -**/target/** -###################### -# Gradle -###################### -.gradle/ -/build/ - -###################### -# Package Files -###################### -*.jar -*.war -*.ear -*.db - -###################### -# Windows -###################### -# Windows image file caches -Thumbs.db - -# Folder config file -Desktop.ini - -###################### -# Mac OSX -###################### -.DS_Store -.svn - -# Thumbnails -._* - -# Files that might appear on external disk -.Spotlight-V100 -.Trashes - -###################### -# Directories -###################### -/bin/ -/deploy/ - -###################### -# Logs -###################### -*.log* - -###################### -# Others -###################### -*.class -*.*~ -*~ -.merge_file* - -###################### -# Gradle Wrapper -###################### -!gradle/wrapper/gradle-wrapper.jar - -###################### -# Maven Wrapper -###################### -!.mvn/wrapper/maven-wrapper.jar - -###################### -# ESLint -###################### -.eslintcache - -# Application resources -*/src/main/resources/application-local*.properties -*/src/main/resources/application-local*.yml -*/src/main/resources/application-local*.env - - -# Test jUnit -/output/ - -# Helm charts -*/helm/charts - -*/.java-version - ### Terraform ### **/.terraform/* *.tfstate *.tfstate.* - -### Local Sonar ### -**.scannerwork -**/sonar-project.properties diff --git a/.releaserc.json b/.releaserc.json index d1d92ca..20dd878 100644 --- a/.releaserc.json +++ b/.releaserc.json @@ -8,6 +8,12 @@ } ], "@semantic-release/release-notes-generator", - "@semantic-release/github" + [ + "@semantic-release/github", + { + "successComment": false, + "failComment": false + } + ] ] -} +} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..ee3557a --- /dev/null +++ b/Dockerfile @@ -0,0 +1,156 @@ +# syntax=docker/dockerfile:1.4 + +# +# 🎯 Version Management +# +ARG CORRETTO_VERSION="17-alpine3.19" +ARG CORRETTO_SHA="2122cb140fa94053abce343fb854d24f4c62ba3c1ac701882dce12980396b477" +ARG GRADLE_VERSION="8.10.2" +ARG GRADLE_DOWNLOAD_SHA256="31c55713e40233a8303827ceb42ca48a47267a0ad4bab9177123121e71524c26" +ARG APPINSIGHTS_VERSION="3.5.2" + +# 🌍 Timezone Configuration +ARG TZ="Europe/Rome" + +# 🔧 Build Configuration +ARG GRADLE_OPTS="-Dorg.gradle.daemon=false \ + -Dorg.gradle.parallel=true \ + -Dorg.gradle.caching=true \ + -Dorg.gradle.configureondemand=true \ + -Dorg.gradle.jvmargs=-Xmx2g" + +# 👤 App Configuration +ARG APP_USER="appuser" +ARG APP_GROUP="appgroup" +ARG APP_HOME="/app" +ARG GRADLE_HOME="/opt/gradle" + +# +# 📥 Base Setup Stage +# +FROM amazoncorretto:${CORRETTO_VERSION}@sha256:${CORRETTO_SHA} AS base +ARG APP_USER +ARG APP_GROUP + +# Install base packages +RUN apk add --no-cache \ + wget \ + unzip \ + bash \ + shadow + +# Create Gradle user +RUN groupadd --system --gid 1000 ${APP_GROUP} && \ + useradd --system --gid ${APP_GROUP} --uid 1000 --shell /bin/bash --create-home ${APP_USER} + +# +# 📦 Gradle Setup Stage +# +FROM base AS gradle-setup +ARG GRADLE_VERSION +ARG GRADLE_DOWNLOAD_SHA256 +ARG GRADLE_HOME +ARG GRADLE_OPTS +ARG APP_USER +ARG APP_GROUP + +# Set environment variables for Gradle +ENV GRADLE_OPTS="${GRADLE_OPTS}" +ENV GRADLE_HOME="${GRADLE_HOME}" +ENV PATH="${GRADLE_HOME}/bin:${PATH}" + +WORKDIR /tmp + +# Download and verify Gradle with progress bar +RUN echo "Downloading Gradle ${GRADLE_VERSION}..." && \ + wget --progress=bar:force --output-document=gradle.zip \ + "https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip" && \ + echo "Verifying download..." && \ + echo "${GRADLE_DOWNLOAD_SHA256} gradle.zip" | sha256sum -c - && \ + echo "Installing Gradle..." && \ + unzip -q gradle.zip && \ + mv "gradle-${GRADLE_VERSION}" "${GRADLE_HOME}" && \ + ln -s "${GRADLE_HOME}/bin/gradle" /usr/bin/gradle && \ + rm gradle.zip && \ + # Setup Gradle user directories + mkdir -p /home/${APP_USER}/.gradle && \ + chown --recursive ${APP_USER}:${APP_GROUP} /home/${APP_USER} && \ + # Verify installation + echo "Verifying Gradle installation..." && \ + gradle --version + +# Create Gradle volume +VOLUME /home/${APP_USER}/.gradle + +# +# 📚 Dependencies Stage +# +FROM gradle-setup AS dependencies + +WORKDIR /build + +# Copy build configuration +COPY --chown=${APP_USER}:${APP_GROUP} build.gradle.kts settings.gradle.kts ./ +COPY --chown=${APP_USER}:${APP_GROUP} gradle.lockfile ./ +COPY --chown=${APP_USER}:${APP_GROUP} openapi openapi/ + +# Generate OpenAPI stubs and download dependencies +RUN mkdir -p src/main/java && \ + chown -R ${APP_USER}:${APP_GROUP} /build && \ + chmod -R 775 /build + +USER ${APP_USER} + +RUN gradle openApiGenerate dependencies --no-daemon + +# +# 🏗️ Build Stage +# +FROM dependencies AS build + +# Copy source code +COPY --chown=${APP_USER}:${APP_GROUP} src src/ + +# Build application +RUN gradle bootJar --no-daemon + +# +# 🚀 Runtime Stage +# +FROM amazoncorretto:${CORRETTO_VERSION}@sha256:${CORRETTO_SHA} AS runtime +ARG APP_USER +ARG APP_GROUP +ARG APP_HOME +ARG APPINSIGHTS_VERSION +ARG TZ + +WORKDIR ${APP_HOME} + +# Set timezone environment variable +ENV TZ=${TZ} + +# 🛡️ Security Setup and Timezone +RUN apk upgrade --no-cache && \ + apk add --no-cache \ + tini \ + curl \ + # Configure timezone + ENV=TZ + tzdata && \ + # Create user and group + addgroup -S ${APP_GROUP} && \ + adduser -S ${APP_USER} -G ${APP_GROUP} + +# 📦 Copy Artifacts +COPY --from=build /build/build/libs/*.jar ${APP_HOME}/app.jar +ADD --chmod=644 https://github.com/microsoft/ApplicationInsights-Java/releases/download/${APPINSIGHTS_VERSION}/applicationinsights-agent-${APPINSIGHTS_VERSION}.jar ${APP_HOME}/applicationinsights-agent.jar + +# 📝 Set Permissions +RUN chown -R ${APP_USER}:${APP_GROUP} ${APP_HOME} + +# 🔌 Container Configuration +EXPOSE 8080 +USER ${APP_USER} + +# 🎬 Startup Configuration +ENTRYPOINT ["/sbin/tini", "--"] +CMD ["java", "-jar", "/app/app.jar"] \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..36663a4 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,117 @@ +plugins { + java + id("org.springframework.boot") version "3.3.5" + id("io.spring.dependency-management") version "1.1.6" + jacoco + id("org.sonarqube") version "5.1.0.4882" + id("com.github.ben-manes.versions") version "0.51.0" + id("org.openapi.generator") version "7.9.0" +} + +group = "it.gov.pagopa.payhub" +version = "0.0.1" +description = "p4pa-pdnd-services" + +java { + toolchain { + languageVersion = JavaLanguageVersion.of(17) + } +} + +configurations { + compileOnly { + extendsFrom(configurations.annotationProcessor.get()) + } +} + +repositories { + mavenCentral() +} + +val springDocOpenApiVersion = "2.6.0" +val openApiToolsVersion = "0.2.6" +val findbugsVersion = "3.0.2" + +dependencies { + implementation("org.springframework.boot:spring-boot-starter") + implementation("org.springframework.boot:spring-boot-starter-web") + implementation("org.springframework.boot:spring-boot-starter-actuator") + implementation("org.springframework.boot:spring-boot-starter-security") + implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:$springDocOpenApiVersion") + implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310") + implementation("org.openapitools:jackson-databind-nullable:$openApiToolsVersion") + implementation("com.google.code.findbugs:jsr305:$findbugsVersion") + + compileOnly("org.projectlombok:lombok") + annotationProcessor("org.projectlombok:lombok") + + // Testing + testImplementation("org.springframework.boot:spring-boot-starter-test") + testImplementation("org.springframework.security:spring-security-test") + testImplementation("org.mockito:mockito-core") + testImplementation ("org.projectlombok:lombok") +} + +tasks.withType { + useJUnitPlatform() + finalizedBy(tasks.jacocoTestReport) +} + +tasks.jacocoTestReport { + dependsOn(tasks.test) + reports { + xml.required = true + } +} + +val projectInfo = mapOf( + "artifactId" to project.name, + "version" to project.version +) + +tasks { + val processResources by getting(ProcessResources::class) { + filesMatching("**/application.yml") { + expand(projectInfo) + } + } +} + +configurations { + compileClasspath { + resolutionStrategy.activateDependencyLocking() + } +} + +tasks.compileJava { + dependsOn("openApiGenerate") +} + + +configure { + named("main") { + java.srcDir("$projectDir/build/generated/src/main/java") + } +} + +springBoot { + mainClass.value("it.gov.pagopa.payhub.pdnd.PayhubPdndApplication") +} + +openApiGenerate { + generatorName.set("spring") + inputSpec.set("$rootDir/openapi/p4pa-pdnd.openapi.yaml") + outputDir.set("$projectDir/build/generated") + apiPackage.set("it.gov.pagopa.payhub.controller.generated") + modelPackage.set("it.gov.pagopa.payhub.model.generated") + configOptions.set(mapOf( + "dateLibrary" to "java8", + "requestMappingMode" to "api_interface", + "useSpringBoot3" to "true", + "interfaceOnly" to "true", + "useTags" to "true", + "generateConstructorWithAllArgs" to "false", + "generatedConstructorWithRequiredArgs" to "false", + "additionalModelTypeAnnotations" to "@lombok.Data @lombok.Builder @lombok.AllArgsConstructor @lombok.RequiredArgsConstructor" + )) +} \ No newline at end of file diff --git a/gradle.lockfile b/gradle.lockfile new file mode 100644 index 0000000..103046d --- /dev/null +++ b/gradle.lockfile @@ -0,0 +1,64 @@ +# This is a Gradle generated file for dependency locking. +# Manual edits can break the build and are not advised. +# This file is expected to be part of source control. +ch.qos.logback:logback-classic:1.5.11=compileClasspath +ch.qos.logback:logback-core:1.5.11=compileClasspath +com.fasterxml.jackson.core:jackson-annotations:2.17.2=compileClasspath +com.fasterxml.jackson.core:jackson-core:2.17.2=compileClasspath +com.fasterxml.jackson.core:jackson-databind:2.17.2=compileClasspath +com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.17.2=compileClasspath +com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.17.2=compileClasspath +com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.2=compileClasspath +com.fasterxml.jackson.module:jackson-module-parameter-names:2.17.2=compileClasspath +com.fasterxml.jackson:jackson-bom:2.17.2=compileClasspath +com.google.code.findbugs:jsr305:3.0.2=compileClasspath +io.micrometer:micrometer-commons:1.13.6=compileClasspath +io.micrometer:micrometer-core:1.13.6=compileClasspath +io.micrometer:micrometer-jakarta9:1.13.6=compileClasspath +io.micrometer:micrometer-observation:1.13.6=compileClasspath +io.swagger.core.v3:swagger-annotations-jakarta:2.2.22=compileClasspath +io.swagger.core.v3:swagger-core-jakarta:2.2.22=compileClasspath +io.swagger.core.v3:swagger-models-jakarta:2.2.22=compileClasspath +jakarta.activation:jakarta.activation-api:2.1.3=compileClasspath +jakarta.annotation:jakarta.annotation-api:2.1.1=compileClasspath +jakarta.validation:jakarta.validation-api:3.0.2=compileClasspath +jakarta.xml.bind:jakarta.xml.bind-api:4.0.2=compileClasspath +org.apache.commons:commons-lang3:3.14.0=compileClasspath +org.apache.logging.log4j:log4j-api:2.23.1=compileClasspath +org.apache.logging.log4j:log4j-to-slf4j:2.23.1=compileClasspath +org.apache.tomcat.embed:tomcat-embed-core:10.1.31=compileClasspath +org.apache.tomcat.embed:tomcat-embed-el:10.1.31=compileClasspath +org.apache.tomcat.embed:tomcat-embed-websocket:10.1.31=compileClasspath +org.openapitools:jackson-databind-nullable:0.2.6=compileClasspath +org.projectlombok:lombok:1.18.34=compileClasspath +org.slf4j:jul-to-slf4j:2.0.16=compileClasspath +org.slf4j:slf4j-api:2.0.16=compileClasspath +org.springdoc:springdoc-openapi-starter-common:2.6.0=compileClasspath +org.springdoc:springdoc-openapi-starter-webmvc-api:2.6.0=compileClasspath +org.springdoc:springdoc-openapi-starter-webmvc-ui:2.6.0=compileClasspath +org.springframework.boot:spring-boot-actuator-autoconfigure:3.3.5=compileClasspath +org.springframework.boot:spring-boot-actuator:3.3.5=compileClasspath +org.springframework.boot:spring-boot-autoconfigure:3.3.5=compileClasspath +org.springframework.boot:spring-boot-starter-actuator:3.3.5=compileClasspath +org.springframework.boot:spring-boot-starter-json:3.3.5=compileClasspath +org.springframework.boot:spring-boot-starter-logging:3.3.5=compileClasspath +org.springframework.boot:spring-boot-starter-security:3.3.5=compileClasspath +org.springframework.boot:spring-boot-starter-tomcat:3.3.5=compileClasspath +org.springframework.boot:spring-boot-starter-web:3.3.5=compileClasspath +org.springframework.boot:spring-boot-starter:3.3.5=compileClasspath +org.springframework.boot:spring-boot:3.3.5=compileClasspath +org.springframework.security:spring-security-config:6.3.4=compileClasspath +org.springframework.security:spring-security-core:6.3.4=compileClasspath +org.springframework.security:spring-security-crypto:6.3.4=compileClasspath +org.springframework.security:spring-security-web:6.3.4=compileClasspath +org.springframework:spring-aop:6.1.14=compileClasspath +org.springframework:spring-beans:6.1.14=compileClasspath +org.springframework:spring-context:6.1.14=compileClasspath +org.springframework:spring-core:6.1.14=compileClasspath +org.springframework:spring-expression:6.1.14=compileClasspath +org.springframework:spring-jcl:6.1.14=compileClasspath +org.springframework:spring-web:6.1.14=compileClasspath +org.springframework:spring-webmvc:6.1.14=compileClasspath +org.webjars:swagger-ui:5.17.14=compileClasspath +org.yaml:snakeyaml:2.2=compileClasspath +empty= diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..a4b76b9 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..ccc1a9b --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists \ No newline at end of file diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..f5feea6 --- /dev/null +++ b/gradlew @@ -0,0 +1,252 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + 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 -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || 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/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..9d21a21 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/helm/.helmignore b/helm/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/helm/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/Chart.yaml b/helm/Chart.yaml new file mode 100644 index 0000000..2709212 --- /dev/null +++ b/helm/Chart.yaml @@ -0,0 +1,10 @@ +apiVersion: v2 +name: p4pa-pdnd-services +description: P4PA PDND SERVICES +type: application +version: 1.0.0 +appVersion: 1.0.0 +dependencies: + - name: microservice-chart + version: 5.9.0 + repository: "https://pagopa.github.io/aks-microservice-chart-blueprint" \ No newline at end of file diff --git a/helm/values-dev.yaml b/helm/values-dev.yaml new file mode 100644 index 0000000..b650303 --- /dev/null +++ b/helm/values-dev.yaml @@ -0,0 +1,36 @@ +microservice-chart: + image: + repository: p4paditncorecommonacr.azurecr.io/p4papdndservices + tag: latest + pullPolicy: Always + + ingress: + host: "hub.internal.dev.p4pa.pagopa.it" + + resources: + requests: + memory: "256Mi" + cpu: "40m" + limits: + memory: "4Gi" + cpu: "300m" + + autoscaling: + enable: false + # minReplica: 1 + # maxReplica: 1 + # pollingInterval: 30 # seconds + # cooldownPeriod: 300 # seconds + # triggers: + # - type: cpu + # metadata: + # type: Utilization # Allowed types are 'Utilization' or 'AverageValue' + # value: "70" + + envConfig: + ENV: "DEV" + JAVA_TOOL_OPTIONS: "-Xms128m -Xmx4g -Djava.util.concurrent.ForkJoinPool.common.parallelism=7 -javaagent:/app/applicationinsights-agent.jar -Dapplicationinsights.configuration.file=/mnt/file-config-external/appinsights-config/applicationinsights.json -agentlib:jdwp=transport=dt_socket,server=y,address=8001,suspend=n -Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.port=3002 -Dcom.sun.management.jmxremote.rmi.port=3003 -Djava.rmi.server.hostname=127.0.0.1 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false" + + keyvault: + name: "p4pa-d-payhub-kv" + tenantId: "7788edaf-0346-4068-9d79-c868aed15b3d" \ No newline at end of file diff --git a/helm/values-prod.yaml b/helm/values-prod.yaml new file mode 100644 index 0000000..dd30049 --- /dev/null +++ b/helm/values-prod.yaml @@ -0,0 +1,36 @@ +microservice-chart: + image: + repository: p4papitncorecommonacr.azurecr.io/p4papdndservices + tag: latest + pullPolicy: Always + + ingress: + host: "hub.internal.p4pa.pagopa.it" + + resources: + requests: + memory: "256Mi" + cpu: "40m" + limits: + memory: "4Gi" + cpu: "300m" + + autoscaling: + enable: false + # minReplica: 1 + # maxReplica: 1 + # pollingInterval: 30 # seconds + # cooldownPeriod: 300 # seconds + # triggers: + # - type: cpu + # metadata: + # type: Utilization # Allowed types are 'Utilization' or 'AverageValue' + # value: "70" + + envConfig: + ENV: "PROD" + JAVA_TOOL_OPTIONS: "-Xms128m -Xmx4g -Djava.util.concurrent.ForkJoinPool.common.parallelism=7 -javaagent:/app/applicationinsights-agent.jar -Dapplicationinsights.configuration.file=/mnt/file-config-external/appinsights-config/applicationinsights.json -agentlib:jdwp=transport=dt_socket,server=y,address=8001,suspend=n -Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.port=3002 -Dcom.sun.management.jmxremote.rmi.port=3003 -Djava.rmi.server.hostname=127.0.0.1 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false" + + keyvault: + name: "p4pa-p-payhub-kv" + tenantId: "7788edaf-0346-4068-9d79-c868aed15b3d" diff --git a/helm/values-uat.yaml b/helm/values-uat.yaml new file mode 100644 index 0000000..2a878cc --- /dev/null +++ b/helm/values-uat.yaml @@ -0,0 +1,36 @@ +microservice-chart: + image: + repository: p4pauitncorecommonacr.azurecr.io/p4papdndservices + tag: latest + pullPolicy: Always + + ingress: + host: "hub.internal.uat.p4pa.pagopa.it" + + resources: + requests: + memory: "256Mi" + cpu: "40m" + limits: + memory: "4Gi" + cpu: "300m" + + autoscaling: + enable: false + # minReplica: 1 + # maxReplica: 1 + # pollingInterval: 30 # seconds + # cooldownPeriod: 300 # seconds + # triggers: + # - type: cpu + # metadata: + # type: Utilization # Allowed types are 'Utilization' or 'AverageValue' + # value: "70" + + envConfig: + ENV: "UAT" + JAVA_TOOL_OPTIONS: "-Xms128m -Xmx4g -Djava.util.concurrent.ForkJoinPool.common.parallelism=7 -javaagent:/app/applicationinsights-agent.jar -Dapplicationinsights.configuration.file=/mnt/file-config-external/appinsights-config/applicationinsights.json -agentlib:jdwp=transport=dt_socket,server=y,address=8001,suspend=n -Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.port=3002 -Dcom.sun.management.jmxremote.rmi.port=3003 -Djava.rmi.server.hostname=127.0.0.1 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false" + + keyvault: + name: "p4pa-u-payhub-kv" + tenantId: "7788edaf-0346-4068-9d79-c868aed15b3d" diff --git a/helm/values.yaml b/helm/values.yaml new file mode 100644 index 0000000..e77227a --- /dev/null +++ b/helm/values.yaml @@ -0,0 +1,72 @@ +microservice-chart: + namespace: "payhub" + nameOverride: "" + fullnameOverride: "" + + livenessProbe: + httpGet: + path: /actuator/health/liveness + port: 8080 + initialDelaySeconds: 120 + failureThreshold: 15 + periodSeconds: 10 + + readinessProbe: + httpGet: + path: /actuator/health/readiness + port: 8080 + initialDelaySeconds: 120 + failureThreshold: 15 + periodSeconds: 10 + + deployment: + create: true + + service: + create: true + type: ClusterIP + port: 8080 + + ingress: + create: true + path: /p4papdnd/(.*) + + serviceAccount: + create: false + annotations: {} + name: "" + + podAnnotations: {} + + podSecurityContext: + seccompProfile: + type: RuntimeDefault + + securityContext: + allowPrivilegeEscalation: false + runAsNonRoot: true + runAsUser: 65534 + runAsGroup: 65534 + + externalConfigMapFiles: + create: true + configMaps: + - name: appinsights-config + key: applicationinsights.json + + envConfig: + APPLICATIONINSIGHTS_ROLE_NAME: "p4papdndservices" + APPLICATIONINSIGHTS_INSTRUMENTATION_LOGGING_LEVEL: "OFF" + APPLICATIONINSIGHTS_INSTRUMENTATION_MICROMETER_ENABLED: "false" + APPLICATIONINSIGHTS_PREVIEW_PROFILER_ENABLED: "false" + ENABLE_AUDIT_APPENDER: "TRUE" + + + envSecret: + APPLICATIONINSIGHTS_CONNECTION_STRING: appinsights-connection-string + + # nodeSelector: {} + + # tolerations: [] + + # affinity: {} diff --git a/openapi/p4pa-pdnd.openapi.yaml b/openapi/p4pa-pdnd.openapi.yaml new file mode 100644 index 0000000..6992bcd --- /dev/null +++ b/openapi/p4pa-pdnd.openapi.yaml @@ -0,0 +1,31 @@ +openapi: 3.0.1 +info: + title: Fake API + description: "Una semplice API di esempio" + version: "1.0.0" +paths: + /api/v1/greet: + get: + summary: "Ottieni un saluto" + description: "Endpoint di esempio che restituisce un saluto" + responses: + '200': + description: "Successo" + content: + application/json: + schema: + type: object + properties: + message: + type: string + example: "Hello, World!" + '500': + description: "Errore interno del server" + content: + application/json: + schema: + type: object + properties: + error: + type: string + example: "Errore interno del server" \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..f227674 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1 @@ +rootProject.name = "p4pa-pdnd-services" diff --git a/src/main/java/it/gov/pagopa/payhub/pdnd/PayhubPdndApplication.java b/src/main/java/it/gov/pagopa/payhub/pdnd/PayhubPdndApplication.java new file mode 100644 index 0000000..119f2b4 --- /dev/null +++ b/src/main/java/it/gov/pagopa/payhub/pdnd/PayhubPdndApplication.java @@ -0,0 +1,13 @@ +package it.gov.pagopa.payhub.pdnd; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class PayhubPdndApplication { + + public static void main(String[] args) { + SpringApplication.run(PayhubPdndApplication.class, args); + } + +} diff --git a/src/main/java/it/gov/pagopa/payhub/pdnd/config/SwaggerConfig.java b/src/main/java/it/gov/pagopa/payhub/pdnd/config/SwaggerConfig.java new file mode 100644 index 0000000..d8ad2ae --- /dev/null +++ b/src/main/java/it/gov/pagopa/payhub/pdnd/config/SwaggerConfig.java @@ -0,0 +1,35 @@ +package it.gov.pagopa.payhub.pdnd.config; + +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * The Class SwaggerConfig. + */ +@Configuration +public class SwaggerConfig { + + /** The title. */ + @Value("${swagger.title:${spring.application.name}}") + private String title; + + /** The description. */ + @Value("${swagger.description:Api and Models}") + private String description; + + /** The version. */ + @Value("${swagger.version:${spring.application.version}}") + private String version; + + @Bean + public OpenAPI customOpenAPI() { + return new OpenAPI().components(new Components()).info(new Info() + .title(title) + .description(description) + .version(version)); + } +} \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..18977c6 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,17 @@ +spring: + application: + name: ${artifactId} + version: ${version} + jmx.enabled: true +management: + endpoint: + health: + probes.enabled: true + group: + readiness.include: "*" + liveness.include: livenessState,diskSpace,ping + endpoints: + jmx: + exposure.include: "*" + web: + exposure.include: info, health \ No newline at end of file diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..c46c6d4 --- /dev/null +++ b/src/main/resources/logback-spring.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + ${CONSOLE_LOG_PATTERN} + + + + + + %msg%n + + + + + true + 20000 + 0 + + + + + true + 20000 + 0 + + + + + + + + + + + + diff --git a/src/test/java/it/gov/pagopa/payhub/pdnd/PayhubPdndApplicationTests.java b/src/test/java/it/gov/pagopa/payhub/pdnd/PayhubPdndApplicationTests.java new file mode 100644 index 0000000..1206415 --- /dev/null +++ b/src/test/java/it/gov/pagopa/payhub/pdnd/PayhubPdndApplicationTests.java @@ -0,0 +1,13 @@ +package it.gov.pagopa.payhub.pdnd; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class PayhubPdndApplicationTests { + + @Test + public void main() { + PayhubPdndApplication.main(new String[] {}); + } +}