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..e25cad5 --- /dev/null +++ b/catalog-info.yaml @@ -0,0 +1,113 @@ +apiVersion: backstage.io/v1alpha1 +kind: System +metadata: + annotations: + backstage.io/kubernetes-label-selector: app.kubernetes.io/managed-by=backstage + backstage.io/kubernetes-namespace: demo-apps + backstage.io/techdocs-ref: dir:. + gitea.kyndemo.live/repo-slug: demo-platform/test-ab-1 + grafana.com/alert-label-selector: app=test-ab-1 + grafana.com/dashboard-url: https://grafana.kyndemo.live/d/otel-app-observability-v2/opentelemetry-application-observability?orgId=1&var-app=test-ab-1 + grafana/alert-label-selector: app=test-ab-1 + grafana/dashboard-selector: uid == 'otel-app-observability-v2' + grafana/grafana-instance: default + humanitec.dev/orgId: skillful-wild-chicken-2617 + humanitec.dev/projectId: cjot-platform + description: System grouping for the modernized test-ab-1 application + labels: + app.kubernetes.io/managed-by: backstage + backstage.io/environment: production + links: + - icon: web + title: Live Application + url: https://test-ab-1.kyndemo.live + - icon: github + title: Repository + url: https://gitea.kyndemo.live/demo-platform/test-ab-1 + - icon: dashboard + title: Humanitec Console + url: https://console.humanitec.dev/orgs/skillful-wild-chicken-2617/projects/cjot-platform/environments/dev?app=test-ab-1 + - icon: dashboard + title: Grafana Dashboard + url: https://grafana.kyndemo.live/d/otel-app-observability-v2/opentelemetry-application-observability?orgId=1&var-app=test-ab-1 + name: test-ab-1-system + tags: + - modernized + - humanitec-v2 + - opentelemetry + title: test-ab-1 System +spec: + dependsOn: + - resource:default/otel-collector + - resource:default/otel-operator + - resource:default/k6-operator + domain: platform + owner: platform-engineering +--- +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + annotations: + backstage.io/kubernetes-label-selector: app=test-ab-1 + backstage.io/kubernetes-namespace: demo-apps + backstage.io/techdocs-ref: dir:. + chaos-mesh/enabled: 'true' + gitea.kyndemo.live/repo-slug: demo-platform/test-ab-1 + grafana.com/alert-label-selector: app=test-ab-1 + grafana.com/dashboard-url: https://grafana.kyndemo.live/d/otel-app-observability-v2/opentelemetry-application-observability?orgId=1&var-app=test-ab-1 + grafana/alert-label-selector: app=test-ab-1 + grafana/dashboard-selector: uid == 'otel-app-observability-v2' + grafana/grafana-instance: default + humanitec.dev/orgId: skillful-wild-chicken-2617 + humanitec.dev/projectId: cjot-platform + k6/enabled: 'true' + k6/target-port: '8080' + k6/target-service: test-ab-1 + k6/test-configmap: k6-test-test-ab-1 + modernization.kyndryl.com/source: https://github.com/spring-projects/spring-petclinic + modernization.kyndryl.com/strategy: ai-containerization + prometheus.io/path: /actuator/prometheus + prometheus.io/port: '8080' + prometheus.io/scrape: 'true' + description: Modernized application from https://github.com/spring-projects/spring-petclinic + labels: + app.kubernetes.io/managed-by: backstage + backstage.io/environment: production + links: + - icon: web + title: Live Application + url: https://test-ab-1.kyndemo.live + - icon: github + title: Source Repository + url: https://gitea.kyndemo.live/demo-platform/test-ab-1 + - icon: dashboard + title: Humanitec Console + url: https://console.humanitec.dev/orgs/skillful-wild-chicken-2617/projects/cjot-platform/environments/dev?app=test-ab-1 + - icon: code + title: CI/CD Pipelines + url: https://gitea.kyndemo.live/demo-platform/test-ab-1/actions + - icon: dashboard + title: Grafana Dashboard + url: https://grafana.kyndemo.live/d/otel-app-observability-v2/opentelemetry-application-observability?orgId=1&var-app=test-ab-1 + name: test-ab-1 + tags: + - modernized + - ai-generated + - java + - spring-boot + - humanitec-v2 + - platform-orchestrator + - score + - opentelemetry + - load-testing + - k6 + - chaos-engineering + - chaos-mesh +spec: + dependsOn: + - resource:default/otel-collector + - resource:default/k6-operator + lifecycle: production + owner: platform-engineering + system: test-ab-1-system + type: service diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 0000000..ce1e114 --- /dev/null +++ b/docs/api.md @@ -0,0 +1,25 @@ +# API Reference + +## Endpoints + +### Health Check + +``` +GET /health +``` + +**Response:** +```json +{"status": "UP", "service": "test-ab-1"} +``` + +### Root + +``` +GET / +``` + +**Response:** +```json +{"service": "test-ab-1", "description": "Modernized test-ab-1 service", "version": "1.0.0"} +``` diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..1acb7a3 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,15 @@ +# Architecture + +## Service Design + +test-ab-1 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..e46f921 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,32 @@ +# test-ab-1 + +Modernized test-ab-1 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/test-ab-1.git +cd test-ab-1 +``` + +## Monitoring + +- **Metrics**: Prometheus metrics at `/metrics` +- **Health**: `/health` +- **Grafana**: [View Dashboard](https://grafana.kyndemo.live/d/app-test-ab-1) + +## Support + +Contact the Platform Engineering team. diff --git a/docs/migration-plan.md b/docs/migration-plan.md new file mode 100644 index 0000000..c0f61e3 --- /dev/null +++ b/docs/migration-plan.md @@ -0,0 +1,41 @@ +# Modernization Plan for test-ab-1 + +## 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 project, specifically using the Spring Boot framework. The presence of `pom.xml` and `build.gradle` indicates support for both Maven and Gradle build systems. The application includes typical Spring Boot starter dependencies and is structured to support web development, data persistence, caching, and validation. + +#### Technology Stack +- **Language:** Java +- **Framework:** Spring Boot +- **Build Tools:** Mav... + +## Generated Artifacts +1. **Dockerfile**: Optimized with health checks and metrics endpoints +2. **score.yaml**: Platform intent with service ports and DNS resource +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..eed0b87 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,13 @@ +site_name: test-ab-1 +site_description: Modernized test-ab-1 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..cc48836 --- /dev/null +++ b/openapi.yaml @@ -0,0 +1,188 @@ +openapi: 3.0.3 +info: + title: test-ab-1 + description: Modernized test-ab-1 service + version: 1.0.0 +servers: +- url: https://test-ab-1.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..95c3a20 --- /dev/null +++ b/score.yaml @@ -0,0 +1,28 @@ +apiVersion: score.dev/v1b1 +containers: + test-ab-1: + image: . + variables: + OTEL_SERVICE_NAME: test-ab-1 + OTEL_EXPORTER_OTLP_ENDPOINT: http://otel-collector.monitoring.svc.cluster.local:4318 + OTEL_RESOURCE_ATTRIBUTES: app=test-ab-1 +metadata: + annotations: + prometheus.io/path: /actuator/prometheus + prometheus.io/port: '8080' + prometheus.io/scrape: 'true' + instrumentation.opentelemetry.io/inject-java: monitoring/otel-instrumentation + labels: + app: test-ab-1 + backstage.io/kubernetes-id: test-ab-1 + name: test-ab-1 +resources: + dns: + type: dns + env: + type: environment +service: + ports: + http: + port: 8080 + targetPort: 8080