diff --git a/catalog-info.yaml b/catalog-info.yaml new file mode 100644 index 0000000..fcb832f --- /dev/null +++ b/catalog-info.yaml @@ -0,0 +1,86 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + annotations: + backstage.io/kubernetes-label-selector: app=mohamed-node-mod-1 + backstage.io/kubernetes-namespace: dev + backstage.io/techdocs-ref: dir:. + gitea.kyndemo.live/repo-slug: demo-platform/mohamed-node-mod-1 + grafana/alert-label-selector: app=mohamed-node-mod-1 + grafana/dashboard-selector: uid == 'app-mohamed-node-mod-1' + grafana/grafana-instance: default + humanitec.dev/orgId: skillful-wild-chicken-2617 + humanitec.dev/projectId: mohamed-node-mod-1 + prometheus.io/path: /metrics + prometheus.io/port: '3000' + prometheus.io/scrape: 'true' + description: Modernized mohamed-node-mod-1 service + links: + - icon: web + title: Live API + url: https://mohamed-node-mod-1.kyndemo.live + - icon: code + title: API Specification + url: https://gitea.kyndemo.live/demo-platform/mohamed-node-mod-1/raw/branch/main/openapi.yaml + - icon: github + title: Source Repository + url: https://gitea.kyndemo.live/demo-platform/mohamed-node-mod-1 + - icon: dashboard + title: Humanitec Console + url: https://console.humanitec.dev/orgs/skillful-wild-chicken-2617/projects/mohamed-node-mod-1/environments/dev + - icon: code + title: CI/CD Pipelines + url: https://gitea.kyndemo.live/demo-platform/mohamed-node-mod-1/actions + - icon: dashboard + title: Grafana Dashboard + url: https://grafana.kyndemo.live/d/app-mohamed-node-mod-1 + name: mohamed-node-mod-1 + tags: + - nodejs + - express + - golden-path + - humanitec-v2 + - platform-orchestrator + - score +spec: + lifecycle: production + owner: group:default/platform-engineering + providesApis: + - api:default/mohamed-node-mod-1-api + system: mohamed-node-mod-1-system + type: service +--- +apiVersion: backstage.io/v1alpha1 +kind: System +metadata: + annotations: + humanitec.dev/orgId: skillful-wild-chicken-2617 + humanitec.dev/projectId: mohamed-node-mod-1 + description: System grouping for the mohamed-node-mod-1 application + name: mohamed-node-mod-1-system +spec: + domain: platform + owner: group:default/platform-engineering +--- +apiVersion: backstage.io/v1alpha1 +kind: API +metadata: + annotations: + backstage.io/techdocs-ref: dir:. + gitea.kyndemo.live/repo-slug: demo-platform/mohamed-node-mod-1 + description: OpenAPI definition for mohamed-node-mod-1 + name: mohamed-node-mod-1-api + tags: + - nodejs + - express + - golden-path + - humanitec-v2 + - platform-orchestrator + - score +spec: + definition: + $text: https://gitea.kyndemo.live/demo-platform/mohamed-node-mod-1/raw/branch/main/openapi.yaml + lifecycle: production + owner: group:default/platform-engineering + system: mohamed-node-mod-1-system + type: openapi diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 0000000..fb65e96 --- /dev/null +++ b/docs/api.md @@ -0,0 +1,25 @@ +# API Reference + +## Endpoints + +### Health Check + +``` +GET /health +``` + +**Response:** +```json +{"status": "UP", "service": "mohamed-node-mod-1"} +``` + +### Root + +``` +GET / +``` + +**Response:** +```json +{"service": "mohamed-node-mod-1", "description": "Modernized mohamed-node-mod-1 service", "version": "1.0.0"} +``` diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..2f64346 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,15 @@ +# Architecture + +## Service Design + +mohamed-node-mod-1 is a microservice following cloud-native patterns. + +## Technology Stack + +- **Runtime**: Node.js Express +- **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..39966c8 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,32 @@ +# mohamed-node-mod-1 + +Modernized mohamed-node-mod-1 service + +## Overview + +This service is built with **Node.js Express** 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/mohamed-node-mod-1.git +cd mohamed-node-mod-1 +``` + +## Monitoring + +- **Metrics**: Prometheus metrics at `/metrics` +- **Health**: `/health` +- **Grafana**: [View Dashboard](https://grafana.kyndemo.live/d/app-mohamed-node-mod-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..50653a3 --- /dev/null +++ b/docs/migration-plan.md @@ -0,0 +1,51 @@ +# Modernization Plan for mohamed-node-mod-1 + +## Application Type +Nodejs 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 +- **Path**: `/tmp/modernize_mj1ov94n` +- **Type**: Node.js application +- **Language**: TypeScript +- **Build Tools**: npm +- **Linting/Formatting**: ESLint, Prettier + +#### Technology Stack +- **Framework**: Express.js +- **Database Client**: Prisma +- **Authentication**: JSON Web Tokens (JWT) +- **Other Utilities**: + - Axios (HTTP client) + - bcryptjs (Password hashing) + - cors (Cross-Origin Resource Sharing) + - body-parser (Request body parsing) + - s... + +## 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..c1cdde4 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,13 @@ +site_name: mohamed-node-mod-1 +site_description: Modernized mohamed-node-mod-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..3f16311 --- /dev/null +++ b/openapi.yaml @@ -0,0 +1,350 @@ +openapi: 3.0.3 +info: + title: mohamed-node-mod-1 + description: Modernized mohamed-node-mod-1 service + version: 1.0.0 +servers: +- url: https://mohamed-node-mod-1.kyndemo.live + description: Production +- url: http://localhost:3000 + description: Local development +paths: + /health: + get: + summary: Health check + operationId: getHealth + tags: + - System + responses: + '200': + description: Healthy + /api/articles: + get: + summary: GET /api/articles + operationId: getApi_articles + responses: + '200': + description: Success + '400': + description: Bad request + '401': + description: Unauthorized + post: + summary: POST /api/articles + operationId: postApi_articles + responses: + '200': + description: Success + '400': + description: Bad request + '401': + description: Unauthorized + requestBody: + required: true + content: + application/json: + schema: + type: object + /api/articles/feed: + get: + summary: GET /api/articles/feed + operationId: getApi_articles_feed + responses: + '200': + description: Success + '400': + description: Bad request + '401': + description: Unauthorized + /api/articles/{slug}: + get: + summary: GET /api/articles/{slug} + operationId: getApi_articles_slug + responses: + '200': + description: Success + '400': + description: Bad request + '401': + description: Unauthorized + parameters: + - name: slug + in: path + required: true + schema: + type: string + put: + summary: PUT /api/articles/{slug} + operationId: putApi_articles_slug + responses: + '200': + description: Success + '400': + description: Bad request + '401': + description: Unauthorized + parameters: + - name: slug + in: path + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + delete: + summary: DELETE /api/articles/{slug} + operationId: deleteApi_articles_slug + responses: + '200': + description: Success + '400': + description: Bad request + '401': + description: Unauthorized + parameters: + - name: slug + in: path + required: true + schema: + type: string + /api/articles/{slug}/comments: + get: + summary: GET /api/articles/{slug}/comments + operationId: getApi_articles_slug_comments + responses: + '200': + description: Success + '400': + description: Bad request + '401': + description: Unauthorized + parameters: + - name: slug + in: path + required: true + schema: + type: string + post: + summary: POST /api/articles/{slug}/comments + operationId: postApi_articles_slug_comments + responses: + '200': + description: Success + '400': + description: Bad request + '401': + description: Unauthorized + parameters: + - name: slug + in: path + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + /api/articles/{slug}/comments/{id}: + delete: + summary: DELETE /api/articles/{slug}/comments/{id} + operationId: deleteApi_articles_slug_comments_id + responses: + '200': + description: Success + '400': + description: Bad request + '401': + description: Unauthorized + parameters: + - name: slug + in: path + required: true + schema: + type: string + - name: id + in: path + required: true + schema: + type: string + /api/articles/{slug}/favorite: + post: + summary: POST /api/articles/{slug}/favorite + operationId: postApi_articles_slug_favorite + responses: + '200': + description: Success + '400': + description: Bad request + '401': + description: Unauthorized + parameters: + - name: slug + in: path + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + delete: + summary: DELETE /api/articles/{slug}/favorite + operationId: deleteApi_articles_slug_favorite + responses: + '200': + description: Success + '400': + description: Bad request + '401': + description: Unauthorized + parameters: + - name: slug + in: path + required: true + schema: + type: string + /api/profiles/{username}: + get: + summary: GET /api/profiles/{username} + operationId: getApi_profiles_username + responses: + '200': + description: Success + '400': + description: Bad request + '401': + description: Unauthorized + parameters: + - name: username + in: path + required: true + schema: + type: string + /api/profiles/{username}/follow: + post: + summary: POST /api/profiles/{username}/follow + operationId: postApi_profiles_username_follow + responses: + '200': + description: Success + '400': + description: Bad request + '401': + description: Unauthorized + parameters: + - name: username + in: path + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + delete: + summary: DELETE /api/profiles/{username}/follow + operationId: deleteApi_profiles_username_follow + responses: + '200': + description: Success + '400': + description: Bad request + '401': + description: Unauthorized + parameters: + - name: username + in: path + required: true + schema: + type: string + /api/tags: + get: + summary: GET /api/tags + operationId: getApi_tags + responses: + '200': + description: Success + '400': + description: Bad request + '401': + description: Unauthorized + /api/user: + get: + summary: GET /api/user + operationId: getApi_user + responses: + '200': + description: Success + '400': + description: Bad request + '401': + description: Unauthorized + put: + summary: PUT /api/user + operationId: putApi_user + responses: + '200': + description: Success + '400': + description: Bad request + '401': + description: Unauthorized + requestBody: + required: true + content: + application/json: + schema: + type: object + /api/users: + post: + summary: POST /api/users + operationId: postApi_users + responses: + '200': + description: Success + '400': + description: Bad request + '401': + description: Unauthorized + requestBody: + required: true + content: + application/json: + schema: + type: object + /api/users/login: + post: + summary: POST /api/users/login + operationId: postApi_users_login + responses: + '200': + description: Success + '400': + description: Bad request + '401': + description: Unauthorized + requestBody: + required: true + content: + application/json: + schema: + type: object + /metrics: + 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..115379b --- /dev/null +++ b/score.yaml @@ -0,0 +1,29 @@ +apiVersion: score.dev/v1b1 +containers: + mohamed-node-mod-1: + image: . + variables: + DATABASE_URL: postgresql://${resources.db.username}:${resources.db.password}@${resources.db.host}:${resources.db.port}/${resources.db.name} + NODE_ENV: production + PORT: '3000' +metadata: + annotations: + prometheus.io/path: /metrics + prometheus.io/port: '3000' + prometheus.io/scrape: 'true' + labels: + app: mohamed-node-mod-1 + backstage.io/kubernetes-id: mohamed-node-mod-1 + name: mohamed-node-mod-1 +resources: + db: + type: postgres + dns: + type: dns + env: + type: environment +service: + ports: + http: + port: 3000 + targetPort: 3000