diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..ae91dbe --- /dev/null +++ b/Dockerfile @@ -0,0 +1,30 @@ +# Multi-stage Dockerfile for Spring Boot Application +FROM maven:3.9-eclipse-temurin-17 AS build +WORKDIR /app + +# Copy dependency files first for better caching +COPY pom.xml . +RUN mvn dependency:go-offline -B + +# Copy source code and build +COPY src ./src +RUN mvn clean package -DskipTests + +# Runtime stage - lean JRE for Spring Boot executable JAR (~200MB vs ~500MB Tomcat) +FROM mcr.microsoft.com/openjdk/jdk:17-ubuntu +WORKDIR /app + +# Create non-root user for security +RUN groupadd -g 1001 appuser && useradd -u 1001 -g appuser -s /bin/sh appuser && \ + chown -R appuser:appuser /app +USER appuser + +COPY --from=build /app/target/*.jar app.jar + +EXPOSE 8080 + +# Health check +HEALTHCHECK --interval=30s --timeout=3s --start-period=30s --retries=3 \ + CMD wget --no-verbose --tries=1 --spider http://localhost:8080/actuator/health || exit 1 + +CMD ["java", "-jar", "app.jar"] diff --git a/catalog-info.yaml b/catalog-info.yaml new file mode 100644 index 0000000..f920f95 --- /dev/null +++ b/catalog-info.yaml @@ -0,0 +1,59 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + annotations: + backstage.io/kubernetes-label-selector: app=vetclinic + backstage.io/kubernetes-namespace: dev + backstage.io/techdocs-ref: dir:. + gitea.kyndemo.live/repo-slug: demo-platform/vetclinic + grafana/alert-label-selector: app=vetclinic + grafana/dashboard-selector: uid == 'app-vetclinic' + grafana/grafana-instance: default + humanitec.dev/orgId: skillful-wild-chicken-2617 + humanitec.dev/projectId: vetclinic + prometheus.io/path: /actuator/prometheus + prometheus.io/port: '8080' + prometheus.io/scrape: 'true' + description: Modernized vetclinic service + links: + - icon: web + title: Live Application + url: https://vetclinic.kyndemo.live + - icon: github + title: Source Repository + url: https://gitea.kyndemo.live/demo-platform/vetclinic + - icon: dashboard + title: Humanitec Console + url: https://console.humanitec.dev/orgs/skillful-wild-chicken-2617/projects/vetclinic/environments/dev + - icon: code + title: CI/CD Pipelines + url: https://gitea.kyndemo.live/demo-platform/vetclinic/actions + - icon: dashboard + title: Grafana Dashboard + url: https://grafana.kyndemo.live/d/app-vetclinic + name: vetclinic + tags: + - java + - spring-boot + - maven + - golden-path + - humanitec-v2 + - platform-orchestrator + - score +spec: + lifecycle: production + owner: group:default/platform-engineering + system: vetclinic-system + type: website +--- +apiVersion: backstage.io/v1alpha1 +kind: System +metadata: + annotations: + humanitec.dev/orgId: skillful-wild-chicken-2617 + humanitec.dev/projectId: vetclinic + description: System grouping for the vetclinic application + name: vetclinic-system +spec: + domain: platform + owner: group:default/platform-engineering diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 0000000..ffded87 --- /dev/null +++ b/docs/api.md @@ -0,0 +1,25 @@ +# API Reference + +## Endpoints + +### Health Check + +``` +GET /health +``` + +**Response:** +```json +{"status": "UP", "service": "vetclinic"} +``` + +### Root + +``` +GET / +``` + +**Response:** +```json +{"service": "vetclinic", "description": "Modernized vetclinic service", "version": "1.0.0"} +``` diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..bcbe6e5 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,15 @@ +# Architecture + +## Service Design + +vetclinic is a microservice following cloud-native patterns. + +## Technology Stack + +- **Runtime**: Java Spring Boot +- **Deployment**: Humanitec Platform Orchestrator +- **CI/CD**: Gitea Actions → ACR → Humanitec + +## Dependencies + +See `score.yaml` for external resource dependencies. diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..0b5db96 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,32 @@ +# vetclinic + +Modernized vetclinic service + +## Overview + +This service is built with **Java Spring Boot** and follows the Golden Path architecture patterns. + +### Key Features + +- 🚀 Production-ready configuration +- 📊 Prometheus metrics exposed +- 🏥 Health check endpoints +- 🔒 Security scanning in CI/CD +- 📦 Containerized deployment + +## Quick Start + +```bash +git clone https://gitea.kyndemo.live/kyndryl-demos/vetclinic.git +cd vetclinic +``` + +## Monitoring + +- **Metrics**: Prometheus metrics at `/metrics` +- **Health**: `/health` +- **Grafana**: [View Dashboard](https://grafana.kyndemo.live/d/app-vetclinic) + +## Support + +Contact the Platform Engineering team. diff --git a/docs/migration-plan.md b/docs/migration-plan.md new file mode 100644 index 0000000..9c739ac --- /dev/null +++ b/docs/migration-plan.md @@ -0,0 +1,41 @@ +# Modernization Plan for vetclinic + +## Application Type +Java Application + +## Selected Modernization Strategy +- **Migration Approach**: containerize-optimize +- **Target Platform**: kubernetes-humanitec +- **Observability**: ENABLED (Prometheus metrics, health checks, tracing) +- **Security Scanning**: ENABLED (Trivy vulnerability scanning) + +## Discovery Summary +### Discovery Report + +#### Application Overview +The application appears to be a Java-based web application built using the Spring Boot framework. It includes both Maven and Gradle build files, suggesting flexibility in build tool usage. The presence of `spring-petclinic` indicates that this might be a sample or reference application for Spring Boot. + +#### Technology Stack +- **Programming Language:** Java +- **Framework:** Spring Boot +- **Build Tools:** Maven (`pom.xml`) and Gradle (`build.gradle`... + +## Generated Artifacts +1. **Dockerfile**: Optimized with health checks and metrics endpoints +2. **score.yaml**: Platform-agnostic environment intent optimized for kubernetes-humanitec with Prometheus metrics resources +3. **CI Workflow**: Automated build/push to ACR with Trivy security scanning + +## Next Steps +1. Review and customize generated artifacts +2. Test container build and run +3. Deploy to development environment using score.yaml +4. Validate application functionality +5. Promote to staging/production via Humanitec + +## Migration Strategy Details + +### Containerize Optimize +Add cloud-native patterns: health checks, metrics, optimized base images. + +### Platform: kubernetes-humanitec +score.yaml is the single environment intent. Use Humanitec Platform Orchestrator for deployment. diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..54cf02b --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,13 @@ +site_name: vetclinic +site_description: Modernized vetclinic service + +nav: + - Home: index.md + - Architecture: architecture.md + - API Reference: api.md + +plugins: + - techdocs-core + +theme: + name: material diff --git a/openapi.yaml b/openapi.yaml new file mode 100644 index 0000000..6bab003 --- /dev/null +++ b/openapi.yaml @@ -0,0 +1,188 @@ +openapi: 3.0.3 +info: + title: vetclinic + description: Modernized vetclinic service + version: 1.0.0 +servers: +- url: https://vetclinic.kyndemo.live + description: Production +- url: http://localhost:8080 + description: Local development +paths: + /health: + get: + summary: Health check + operationId: getHealth + tags: + - System + responses: + '200': + description: Healthy + /vets.html: + get: + summary: GET /vets.html + operationId: getVets.html + responses: + '200': + description: Success + '400': + description: Bad request + /owners/{ownerId}/owners/{ownerId}: + get: + summary: GET /owners/{ownerId}/owners/{ownerId} + operationId: getOwners_ownerId_owners_ownerId + responses: + '200': + description: Success + '400': + description: Bad request + parameters: + - name: ownerId + in: path + required: true + schema: + type: string + - name: ownerId + in: path + required: true + schema: + type: string + /owners/{ownerId}/pets/new: + get: + summary: GET /owners/{ownerId}/pets/new + operationId: getOwners_ownerId_pets_new + responses: + '200': + description: Success + '400': + description: Bad request + parameters: + - name: ownerId + in: path + required: true + schema: + type: string + /owners/{ownerId}/pets/{petId}/edit: + get: + summary: GET /owners/{ownerId}/pets/{petId}/edit + operationId: getOwners_ownerId_pets_petId_edit + responses: + '200': + description: Success + '400': + description: Bad request + parameters: + - name: ownerId + in: path + required: true + schema: + type: string + - name: petId + in: path + required: true + schema: + type: string + /owners/{ownerId}/pets/{petId}/visits/new: + get: + summary: GET /owners/{ownerId}/pets/{petId}/visits/new + operationId: getOwners_ownerId_pets_petId_visits_new + responses: + '200': + description: Success + '400': + description: Bad request + parameters: + - name: ownerId + in: path + required: true + schema: + type: string + - name: petId + in: path + required: true + schema: + type: string + /owners/new: + get: + summary: GET /owners/new + operationId: getOwners_new + responses: + '200': + description: Success + '400': + description: Bad request + /owners/find: + get: + summary: GET /owners/find + operationId: getOwners_find + responses: + '200': + description: Success + '400': + description: Bad request + /owners: + get: + summary: GET /owners + operationId: getOwners + responses: + '200': + description: Success + '400': + description: Bad request + /owners/{ownerId}/edit: + get: + summary: GET /owners/{ownerId}/edit + operationId: getOwners_ownerId_edit + responses: + '200': + description: Success + '400': + description: Bad request + parameters: + - name: ownerId + in: path + required: true + schema: + type: string + /owners/{ownerId}: + get: + summary: GET /owners/{ownerId} + operationId: getOwners_ownerId + responses: + '200': + description: Success + '400': + description: Bad request + parameters: + - name: ownerId + in: path + required: true + schema: + type: string + /: + get: + summary: GET / + operationId: getRoot + responses: + '200': + description: Success + '400': + description: Bad request + /oups: + get: + summary: GET /oups + operationId: getOups + responses: + '200': + description: Success + '400': + description: Bad request + /actuator/prometheus: + get: + summary: Prometheus metrics + operationId: getMetrics + tags: + - System + responses: + '200': + description: text/plain; Prometheus exposition format diff --git a/score.yaml b/score.yaml new file mode 100644 index 0000000..b722034 --- /dev/null +++ b/score.yaml @@ -0,0 +1,23 @@ +apiVersion: score.dev/v1b1 +containers: + vetclinic: + image: . +metadata: + annotations: + prometheus.io/path: /actuator/prometheus + prometheus.io/port: '8080' + prometheus.io/scrape: 'true' + labels: + app: vetclinic + backstage.io/kubernetes-id: vetclinic + name: vetclinic +resources: + dns: + type: dns + env: + type: environment +service: + ports: + http: + port: 8080 + targetPort: 8080