diff --git a/db.json b/db.json new file mode 100644 index 000000000..82b82dda6 --- /dev/null +++ b/db.json @@ -0,0 +1,6 @@ +{ + "posts": [ + { "id": 1, "title": "Hello World" }, + { "id": 2, "title": "GitOps is cool!" } + ] +} \ No newline at end of file diff --git a/dockerfile b/dockerfile new file mode 100644 index 000000000..80a66e6e8 --- /dev/null +++ b/dockerfile @@ -0,0 +1,13 @@ + +FROM node:18 + +WORKDIR /app + +COPY package*.json ./ +RUN npm install + +COPY . . + +EXPOSE 3000 + +CMD ["npx", "json-server", "db.json", "--host", "0.0.0.0", "--port", "3000"] diff --git a/k8s/manifests/README.md b/k8s/manifests/README.md new file mode 100644 index 000000000..e8d913584 --- /dev/null +++ b/k8s/manifests/README.md @@ -0,0 +1,37 @@ +# βš™οΈ GitOps with ArgoCD – JSON Server Demo + +This project demonstrates a **GitOps workflow using ArgoCD** to automatically deploy a simple `json-server` application to a Kubernetes cluster. + +πŸ“Œ **Showcase Ready** β€” You can include this in your resume or portfolio to demonstrate your understanding of: +- Kubernetes deployment workflows +- GitOps principles +- ArgoCD for continuous delivery +- Docker-based microservices + +--- + +## πŸ” What This Project Demonstrates + +- 🎯 Deploying a demo app (`json-server`) using ArgoCD +- πŸ“‚ Managing Kubernetes manifests declaratively from Git +- πŸ”„ Continuous sync between Git and the cluster +- πŸ›  Rollbacks, health checks, and namespace scoping +- πŸ”§ Manual + automatic deployment syncing + +--- + +## πŸ—‚ Project Structure + +- β”œβ”€β”€ manifests/ +- β”‚ β”œβ”€β”€ deployment.yaml +- β”‚ └── service.yaml +- └── Dockerfile + + +--- + +## πŸš€ Quick Start Instructions + +### 🧩 ArgoCD Setup + +If you haven’t installed ArgoCD yet, follow the [Setup Guide](./setup.md). diff --git a/k8s/manifests/argocd-app.yml b/k8s/manifests/argocd-app.yml new file mode 100644 index 000000000..55e662451 --- /dev/null +++ b/k8s/manifests/argocd-app.yml @@ -0,0 +1,20 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: json-server-app + namespace: argocd +spec: + project: default + source: + repoURL: 'https://github.com/sthitajoshi/json-server' + targetRevision: HEAD + path: k8s/manifests + destination: + server: 'https://kubernetes.default.svc' + namespace: default + syncPolicy: + automated: + prune: true + selfHeal: true + syncOptions: + - CreateNamespace=true diff --git a/k8s/manifests/deployment.yml b/k8s/manifests/deployment.yml new file mode 100644 index 000000000..b344d5a68 --- /dev/null +++ b/k8s/manifests/deployment.yml @@ -0,0 +1,20 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: json-server + namespace: json-server +spec: + replicas: 1 + selector: + matchLabels: + app: json-server + template: + metadata: + labels: + app: json-server + spec: + containers: + - name: json-server + image: shtita09/json-server-demo:latest + ports: + - containerPort: 3000 \ No newline at end of file diff --git a/k8s/manifests/services.yml b/k8s/manifests/services.yml new file mode 100644 index 000000000..9d24dab6b --- /dev/null +++ b/k8s/manifests/services.yml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: json-server-service + namespace: json-server +spec: + selector: + app: json-server + ports: + - protocol: TCP + port: 80 + targetPort: 3000 + type: NodePort \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 60d0c463e..f98d3246b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0-beta.3", "license": "SEE LICENSE IN ./LICENSE", "dependencies": { - "@tinyhttp/app": "^2.4.0", + "@tinyhttp/app": "^2.5.2", "@tinyhttp/cors": "^2.0.1", "@tinyhttp/logger": "^2.0.0", "chalk": "^5.3.0", @@ -17,6 +17,7 @@ "dot-prop": "^9.0.0", "eta": "^3.5.0", "inflection": "^3.0.0", + "json-server": "^1.0.0-beta.3", "json5": "^2.2.3", "lowdb": "^7.0.1", "milliparsec": "^4.0.0", @@ -786,15 +787,15 @@ } }, "node_modules/@tinyhttp/app": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@tinyhttp/app/-/app-2.4.0.tgz", - "integrity": "sha512-vOPiCemQRJq5twnl06dde6XnWiNbVMdVRFJWW/yC/9G0qgvV2TvzNNTxrdlz6YmyB7vIC7Fg3qS6m6gx8RbBNQ==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@tinyhttp/app/-/app-2.5.2.tgz", + "integrity": "sha512-DcB3Y8GQppLQlO2VxRYF7LzTEAoZb+VRQXuIsErcu2fNaM1xdx6NQZDso5rlZUiaeg6KYYRfU34N4XkZbv6jSA==", "license": "MIT", "dependencies": { "@tinyhttp/cookie": "2.1.1", - "@tinyhttp/proxy-addr": "2.2.0", - "@tinyhttp/req": "2.2.4", - "@tinyhttp/res": "2.2.4", + "@tinyhttp/proxy-addr": "2.2.1", + "@tinyhttp/req": "2.2.5", + "@tinyhttp/res": "2.2.5", "@tinyhttp/router": "2.2.3", "header-range-parser": "1.1.3", "regexparam": "^2.0.2" @@ -882,9 +883,9 @@ } }, "node_modules/@tinyhttp/forwarded": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@tinyhttp/forwarded/-/forwarded-2.1.1.tgz", - "integrity": "sha512-nO3kq0R1LRl2+CAMlnggm22zE6sT8gfvGbNvSitV6F9eaUSurHP0A8YZFMihSkugHxK+uIegh1TKrqgD8+lyGQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@tinyhttp/forwarded/-/forwarded-2.1.2.tgz", + "integrity": "sha512-9H/eulJ68ElY/+zYpTpNhZ7vxGV+cnwaR6+oQSm7bVgZMyuQfgROW/qvZuhmgDTIxnGMXst+Ba4ij6w6Krcs3w==", "license": "MIT", "engines": { "node": ">=12.20.0" @@ -905,12 +906,12 @@ } }, "node_modules/@tinyhttp/proxy-addr": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@tinyhttp/proxy-addr/-/proxy-addr-2.2.0.tgz", - "integrity": "sha512-WM/PPL9xNvrs7/8Om5nhKbke5FHrP3EfjOOR+wBnjgESfibqn0K7wdUTnzSLp1lBmemr88os1XvzwymSgaibyA==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@tinyhttp/proxy-addr/-/proxy-addr-2.2.1.tgz", + "integrity": "sha512-BicqMqVI91hHq2BQmnqJUh0FQUnx7DncwSGgu2ghlh+JZG2rHK2ZN/rXkfhrx1rrUw6hnd0L36O8GPMh01+dDQ==", "license": "MIT", "dependencies": { - "@tinyhttp/forwarded": "2.1.1", + "@tinyhttp/forwarded": "2.1.2", "ipaddr.js": "^2.2.0" }, "engines": { @@ -918,9 +919,9 @@ } }, "node_modules/@tinyhttp/req": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@tinyhttp/req/-/req-2.2.4.tgz", - "integrity": "sha512-lQAZIAo0NOeghxFOZS57tQzxpHSPPLs9T68Krq2BncEBImKwqaDKUt7M9Y5Kb+rvC/GwIL3LeErhkg7f5iG4IQ==", + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@tinyhttp/req/-/req-2.2.5.tgz", + "integrity": "sha512-trfsXwtmsNjMcGKcLJ+45h912kLRqBQCQD06ams3Tq0kf4gHLxjHjoYOC1Z9yGjOn81XllRx8wqvnvr+Kbe3gw==", "license": "MIT", "dependencies": { "@tinyhttp/accepts": "2.2.3", @@ -933,16 +934,16 @@ } }, "node_modules/@tinyhttp/res": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@tinyhttp/res/-/res-2.2.4.tgz", - "integrity": "sha512-ETBRShnO19oJyIg2XQHQoofXPWeTXPAuwnIVYkU8WaftvXd/Vz4y5+WFQDHUzKlmdGOw5fAFnrEU7pIVMeFeVA==", + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@tinyhttp/res/-/res-2.2.5.tgz", + "integrity": "sha512-yBsqjWygpuKAVz4moWlP4hqzwiDDqfrn2mA0wviJAcgvGiyOErtlQwXY7aj3aPiCpURvxvEFO//Gdy6yV+xEpA==", "license": "MIT", "dependencies": { "@tinyhttp/content-disposition": "2.2.2", "@tinyhttp/cookie": "2.1.1", "@tinyhttp/cookie-signature": "2.1.1", "@tinyhttp/encode-url": "2.1.1", - "@tinyhttp/req": "2.2.4", + "@tinyhttp/req": "2.2.5", "@tinyhttp/send": "2.2.3", "@tinyhttp/vary": "^0.1.3", "es-escape-html": "^0.1.1", @@ -2458,6 +2459,33 @@ "dev": true, "license": "MIT" }, + "node_modules/json-server": { + "version": "1.0.0-beta.3", + "resolved": "https://registry.npmjs.org/json-server/-/json-server-1.0.0-beta.3.tgz", + "integrity": "sha512-DwE69Ep5ccwIJZBUIWEENC30Yj8bwr4Ax9W9VoIWAYnB8Sj4ReptscO8/DRHv/nXwVlmb3Bk73Ls86+VZdYkkA==", + "license": "SEE LICENSE IN ./LICENSE", + "dependencies": { + "@tinyhttp/app": "^2.4.0", + "@tinyhttp/cors": "^2.0.1", + "@tinyhttp/logger": "^2.0.0", + "chalk": "^5.3.0", + "chokidar": "^4.0.1", + "dot-prop": "^9.0.0", + "eta": "^3.5.0", + "inflection": "^3.0.0", + "json5": "^2.2.3", + "lowdb": "^7.0.1", + "milliparsec": "^4.0.0", + "sirv": "^2.0.4", + "sort-on": "^6.1.0" + }, + "bin": { + "json-server": "lib/bin.js" + }, + "engines": { + "node": ">=18.3" + } + }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", @@ -2691,9 +2719,9 @@ "license": "MIT" }, "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", "license": "MIT", "engines": { "node": ">= 0.6" diff --git a/package.json b/package.json index a0cfb2993..2182e37c3 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "typescript-eslint": "^8.6.0" }, "dependencies": { - "@tinyhttp/app": "^2.4.0", + "@tinyhttp/app": "^2.5.2", "@tinyhttp/cors": "^2.0.1", "@tinyhttp/logger": "^2.0.0", "chalk": "^5.3.0", @@ -54,6 +54,7 @@ "dot-prop": "^9.0.0", "eta": "^3.5.0", "inflection": "^3.0.0", + "json-server": "^1.0.0-beta.3", "json5": "^2.2.3", "lowdb": "^7.0.1", "milliparsec": "^4.0.0", diff --git a/setup.md b/setup.md new file mode 100644 index 000000000..0dc41c1a4 --- /dev/null +++ b/setup.md @@ -0,0 +1,13 @@ +# Install ArgoCD on Kubernetes + +# 1. Create ArgoCD namespace +kubectl create namespace argocd + +# 2. Install ArgoCD +kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml + +# 3. Expose ArgoCD UI (optional, for local testing) +kubectl port-forward svc/argocd-server -n argocd 8080:443 + +# 4. Get the initial admin password +kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d