Add Dockerfile, K8s manifests, and ArgoCD app for OpenShift deployment
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1 +1,2 @@
|
||||
node_modules/\nserver.log
|
||||
node_modules/
|
||||
server.log
|
||||
|
||||
11
Dockerfile
Normal file
11
Dockerfile
Normal file
@@ -0,0 +1,11 @@
|
||||
FROM node:22-alpine
|
||||
WORKDIR /app
|
||||
COPY package.json package-lock.json ./
|
||||
RUN npm ci --omit=dev
|
||||
COPY server.js ./
|
||||
COPY public/ ./public/
|
||||
RUN mkdir -p /app/data && chgrp -R 0 /app && chmod -R g=u /app
|
||||
ENV DATA_DIR=/app/data
|
||||
EXPOSE 3333
|
||||
USER 1001
|
||||
CMD ["node", "server.js"]
|
||||
20
bootstrap/argo-app.yaml
Normal file
20
bootstrap/argo-app.yaml
Normal file
@@ -0,0 +1,20 @@
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: clawrizon
|
||||
namespace: openshift-gitops
|
||||
spec:
|
||||
project: default
|
||||
source:
|
||||
repoURL: https://gitea.apilab.us/cscott/priority-horizon
|
||||
targetRevision: main
|
||||
path: manifests
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
namespace: clawrizon
|
||||
syncPolicy:
|
||||
automated:
|
||||
prune: true
|
||||
selfHeal: true
|
||||
syncOptions:
|
||||
- CreateNamespace=false
|
||||
@@ -57,7 +57,7 @@
|
||||
{
|
||||
"id": 10,
|
||||
"column": "now",
|
||||
"text": "Clawd: Add service/route for this (git first)",
|
||||
"text": "✅ Clawd: Git + Gitea done. Route next?",
|
||||
"order": 3
|
||||
}
|
||||
],
|
||||
|
||||
21
manifests/buildconfig.yaml
Normal file
21
manifests/buildconfig.yaml
Normal file
@@ -0,0 +1,21 @@
|
||||
apiVersion: build.openshift.io/v1
|
||||
kind: BuildConfig
|
||||
metadata:
|
||||
name: clawrizon
|
||||
namespace: clawrizon
|
||||
spec:
|
||||
source:
|
||||
type: Git
|
||||
git:
|
||||
uri: https://gitea.apilab.us/cscott/priority-horizon
|
||||
ref: main
|
||||
strategy:
|
||||
type: Docker
|
||||
dockerStrategy:
|
||||
dockerfilePath: Dockerfile
|
||||
output:
|
||||
to:
|
||||
kind: ImageStreamTag
|
||||
name: clawrizon:latest
|
||||
triggers:
|
||||
- type: ConfigChange
|
||||
47
manifests/deployment.yaml
Normal file
47
manifests/deployment.yaml
Normal file
@@ -0,0 +1,47 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: clawrizon
|
||||
namespace: clawrizon
|
||||
labels:
|
||||
app: clawrizon
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: clawrizon
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: clawrizon
|
||||
spec:
|
||||
containers:
|
||||
- name: clawrizon
|
||||
image: image-registry.openshift-image-registry.svc:5000/clawrizon/clawrizon:latest
|
||||
ports:
|
||||
- containerPort: 3333
|
||||
env:
|
||||
- name: DATA_DIR
|
||||
value: /app/data
|
||||
resources:
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
limits:
|
||||
cpu: 200m
|
||||
memory: 256Mi
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /app/data
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
runAsNonRoot: true
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
volumes:
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: clawrizon-data
|
||||
5
manifests/imagestream.yaml
Normal file
5
manifests/imagestream.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
apiVersion: image.openshift.io/v1
|
||||
kind: ImageStream
|
||||
metadata:
|
||||
name: clawrizon
|
||||
namespace: clawrizon
|
||||
4
manifests/namespace.yaml
Normal file
4
manifests/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: clawrizon
|
||||
12
manifests/pvc.yaml
Normal file
12
manifests/pvc.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: clawrizon-data
|
||||
namespace: clawrizon
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
storageClassName: local-nvme-retain
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
||||
16
manifests/route.yaml
Normal file
16
manifests/route.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
apiVersion: route.openshift.io/v1
|
||||
kind: Route
|
||||
metadata:
|
||||
name: clawrizon
|
||||
namespace: clawrizon
|
||||
spec:
|
||||
host: clawrizon.apps.lab.apilab.us
|
||||
to:
|
||||
kind: Service
|
||||
name: clawrizon
|
||||
weight: 100
|
||||
port:
|
||||
targetPort: 3333
|
||||
tls:
|
||||
termination: edge
|
||||
insecureEdgeTerminationPolicy: Redirect
|
||||
12
manifests/service.yaml
Normal file
12
manifests/service.yaml
Normal file
@@ -0,0 +1,12 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: clawrizon
|
||||
namespace: clawrizon
|
||||
spec:
|
||||
selector:
|
||||
app: clawrizon
|
||||
ports:
|
||||
- port: 3333
|
||||
targetPort: 3333
|
||||
protocol: TCP
|
||||
13
server.js
13
server.js
@@ -3,7 +3,14 @@ const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const app = express();
|
||||
const DATA_FILE = path.join(__dirname, 'data.json');
|
||||
const DATA_DIR = process.env.DATA_DIR || __dirname;
|
||||
const DATA_FILE = path.join(DATA_DIR, 'data.json');
|
||||
|
||||
// Seed data.json if it does not exist
|
||||
if (!fs.existsSync(DATA_FILE)) {
|
||||
fs.mkdirSync(DATA_DIR, { recursive: true });
|
||||
fs.writeFileSync(DATA_FILE, JSON.stringify({ notes: [], nextId: 1 }, null, 2));
|
||||
}
|
||||
|
||||
app.use(express.json());
|
||||
app.use(express.static(path.join(__dirname, 'public')));
|
||||
@@ -42,7 +49,6 @@ app.patch('/api/notes/:id', (req, res) => {
|
||||
if (req.body.column !== undefined) note.column = req.body.column;
|
||||
if (req.body.order !== undefined) note.order = req.body.order;
|
||||
if (req.body.reorder) {
|
||||
// reorder: [{id, order}, ...]
|
||||
req.body.reorder.forEach(r => {
|
||||
const n = data.notes.find(x => x.id === r.id);
|
||||
if (n) { n.order = r.order; if (r.column) n.column = r.column; }
|
||||
@@ -61,10 +67,9 @@ app.delete('/api/notes/:id', (req, res) => {
|
||||
res.json({ ok: true });
|
||||
});
|
||||
|
||||
// Bulk reorder endpoint
|
||||
app.put('/api/reorder', (req, res) => {
|
||||
const data = readData();
|
||||
const { items } = req.body; // [{id, column, order}]
|
||||
const { items } = req.body;
|
||||
if (!items) return res.status(400).json({ error: 'items required' });
|
||||
items.forEach(r => {
|
||||
const n = data.notes.find(x => x.id === r.id);
|
||||
|
||||
Reference in New Issue
Block a user