diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..61dc49ce --- /dev/null +++ b/Dockerfile @@ -0,0 +1,18 @@ +# Use Node.js as base image +FROM node:18-alpine + +# Set working directory +WORKDIR /app + +# Copy package.json and install dependencies +COPY package.json package-lock.json ./ +RUN npm install + +# Copy backend source code +COPY . . + +# Expose the backend port +EXPOSE 5000 + +# Start the backend +CMD ["node", "server.js"] diff --git a/Porject Image.png b/Porject Image.png deleted file mode 100644 index a41d0980..00000000 Binary files a/Porject Image.png and /dev/null differ diff --git a/README.md b/README.md index 46280439..e57ce8aa 100644 --- a/README.md +++ b/README.md @@ -76,3 +76,8 @@ npm install dotenv-webpack ### Open new Terminal npm start + +minikube start +minikube service my-processor-service --url +minikube tunnel +kubectl get svc my-processor-service \ No newline at end of file diff --git a/admin-user.yml b/admin-user.yml new file mode 100644 index 00000000..23c11905 --- /dev/null +++ b/admin-user.yml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: admin-user +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: +- kind: ServiceAccount + name: admin-user + namespace: kubernetes-dashboard \ No newline at end of file diff --git a/kube-dash.yml b/kube-dash.yml new file mode 100644 index 00000000..219059ba --- /dev/null +++ b/kube-dash.yml @@ -0,0 +1,5 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: admin-user + namespace: kubernetes-dashboard \ No newline at end of file diff --git a/kyube-crd.yml b/kyube-crd.yml index b17e44da..6894fbba 100644 --- a/kyube-crd.yml +++ b/kyube-crd.yml @@ -1,22 +1,22 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: - name: processors.example.com # Plural name of the resource in the API group + name: processors.example.com spec: - group: example.com # API group + group: example.com names: - plural: processors # Plural name for the resource - singular: processor # Singular name for the resource - kind: Processor # Kind name (CamelCase) - shortNames: # Optional short name aliases + plural: processors + singular: processor + kind: Processor + shortNames: - proc - scope: Namespaced # Can be Namespaced or Cluster + scope: Namespaced versions: - name: v1 served: true storage: true schema: - openAPIV3Schema: # Schema validation for the custom resource + openAPIV3Schema: type: object properties: spec: @@ -37,7 +37,7 @@ spec: description: "Email of the owner" runtime: type: string - enum: ["python3.10", "java21"] # Enforce specific runtime values + enum: ["python3.10", "java21"] description: "Runtime environment (e.g., python3.10, java21)" tags: type: array @@ -54,7 +54,7 @@ spec: type: string nullable: true description: "Optional repository URL" - additionalPrinterColumns: # Additional columns for `kubectl get` + additionalPrinterColumns: - name: Service Name type: string jsonPath: .spec.serviceName diff --git a/multi-port-service.yml b/multi-port-service.yml new file mode 100644 index 00000000..acb6893c --- /dev/null +++ b/multi-port-service.yml @@ -0,0 +1,39 @@ +apiVersion: v1 +kind: Service +metadata: + name: my-processor-service +spec: + selector: + app: my-processor + type: LoadBalancer + ports: + - name: text-processor + port: 8080 + targetPort: 8080 + - name: image-processor + port: 8081 + targetPort: 8081 + - name: video-processor + port: 8082 + targetPort: 8082 + - name: audio-processor + port: 8083 + targetPort: 8083 + - name: pdf-processor + port: 8084 + targetPort: 8084 + - name: csv-processor + port: 8085 + targetPort: 8085 + - name: json-processor + port: 8086 + targetPort: 8086 + - name: xml-processor + port: 8087 + targetPort: 8087 + - name: excel-processor + port: 8088 + targetPort: 8088 + - name: markdown-processor + port: 8089 + targetPort: 8089 \ No newline at end of file diff --git a/my-processor-deployment.yaml b/my-processor-deployment.yaml new file mode 100644 index 00000000..36cbf393 --- /dev/null +++ b/my-processor-deployment.yaml @@ -0,0 +1,737 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-processor-deployment + labels: + app: my-processor +spec: + replicas: 1 + selector: + matchLabels: + app: my-processor + template: + metadata: + labels: + app: my-processor + spec: + containers: + + # 1) text-processor + - name: text-processor + image: docker.io/library/openjdk:21-jdk-slim + env: + - name: NAME + value: "Text Processor" + - name: SERVICENAME + value: "text-processor-service" + - name: OWNERNAME + value: "Alice" + - name: OWNEREMAIL + value: "alice@example.com" + - name: RUNTIME + value: "java21" + - name: TAGS + value: "text,processing" + - name: DESCRIPTION + value: "Processes textual data" + - name: ACTSON + value: "text/plain" + - name: REPOURL + value: "https://github.com/alice/text-processor" + ports: + - containerPort: 8080 + command: ["/bin/bash"] + args: + - -c + - | + echo "Starting text-processor on port 8080" + cat < SimpleHttpServer.java + import com.sun.net.httpserver.HttpServer; + import com.sun.net.httpserver.HttpHandler; + import com.sun.net.httpserver.HttpExchange; + import java.io.IOException; + import java.io.OutputStream; + import java.net.InetSocketAddress; + + public class SimpleHttpServer { + public static void main(String[] args) throws IOException { + int port = 8080; + HttpServer server = HttpServer.create(new InetSocketAddress(port), 0); + server.createContext("/", new MyHandler()); + server.setExecutor(null); + System.out.println("Serving text-processor on port " + port); + server.start(); + } + + static class MyHandler implements HttpHandler { + @Override + public void handle(HttpExchange t) throws IOException { + String response = "{" + + "\"name\":\"" + System.getenv("NAME") + "\"," + + "\"serviceName\":\"" + System.getenv("SERVICENAME") + "\"," + + "\"ownerName\":\"" + System.getenv("OWNERNAME") + "\"," + + "\"ownerEmail\":\"" + System.getenv("OWNEREMAIL") + "\"," + + "\"runtime\":\"" + System.getenv("RUNTIME") + "\"," + + "\"tags\":\"" + System.getenv("TAGS") + "\"," + + "\"description\":\"" + System.getenv("DESCRIPTION") + "\"," + + "\"actsOn\":\"" + System.getenv("ACTSON") + "\"," + + "\"repoURL\":\"" + System.getenv("REPOURL") + "\"" + + "}"; + t.sendResponseHeaders(200, response.length()); + try (OutputStream os = t.getResponseBody()) { + os.write(response.getBytes()); + } + } + } + } + EOF + javac SimpleHttpServer.java + java SimpleHttpServer + + # 2) image-processor + - name: image-processor + image: docker.io/library/openjdk:21-jdk-slim + env: + - name: NAME + value: "Image Processor" + - name: SERVICENAME + value: "image-processor-service" + - name: OWNERNAME + value: "Alice" + - name: OWNEREMAIL + value: "alice@example.com" + - name: RUNTIME + value: "java21" + - name: TAGS + value: "image,processing,jpeg" + - name: DESCRIPTION + value: "Processes image files to apply transformations or analysis." + - name: ACTSON + value: "image/jpeg" + - name: REPOURL + value: "https://github.com/alice/image-processor" + ports: + - containerPort: 8081 + command: ["/bin/bash"] + args: + - -c + - | + echo "Starting image-processor on port 8081" + cat < SimpleHttpServer.java + import com.sun.net.httpserver.HttpServer; + import com.sun.net.httpserver.HttpHandler; + import com.sun.net.httpserver.HttpExchange; + import java.io.IOException; + import java.io.OutputStream; + import java.net.InetSocketAddress; + + public class SimpleHttpServer { + public static void main(String[] args) throws IOException { + int port = 8081; + HttpServer server = HttpServer.create(new InetSocketAddress(port), 0); + server.createContext("/", new MyHandler()); + server.setExecutor(null); + System.out.println("Serving image-processor on port " + port); + server.start(); + } + + static class MyHandler implements HttpHandler { + @Override + public void handle(HttpExchange t) throws IOException { + String response = "{" + + "\"name\":\"" + System.getenv("NAME") + "\"," + + "\"serviceName\":\"" + System.getenv("SERVICENAME") + "\"," + + "\"ownerName\":\"" + System.getenv("OWNERNAME") + "\"," + + "\"ownerEmail\":\"" + System.getenv("OWNEREMAIL") + "\"," + + "\"runtime\":\"" + System.getenv("RUNTIME") + "\"," + + "\"tags\":\"" + System.getenv("TAGS") + "\"," + + "\"description\":\"" + System.getenv("DESCRIPTION") + "\"," + + "\"actsOn\":\"" + System.getenv("ACTSON") + "\"," + + "\"repoURL\":\"" + System.getenv("REPOURL") + "\"" + + "}"; + t.sendResponseHeaders(200, response.length()); + try (OutputStream os = t.getResponseBody()) { + os.write(response.getBytes()); + } + } + } + } + EOF + javac SimpleHttpServer.java + java SimpleHttpServer + + # 3) video-processor + - name: video-processor + image: docker.io/library/openjdk:21-jdk-slim + env: + - name: NAME + value: "Video Processor" + - name: SERVICENAME + value: "video-processor-service" + - name: OWNERNAME + value: "Bob" + - name: OWNEREMAIL + value: "bob@example.com" + - name: RUNTIME + value: "java21" + - name: TAGS + value: "video,processing,mp4" + - name: DESCRIPTION + value: "Processes video files for transcoding and metadata extraction." + - name: ACTSON + value: "video/mp4" + - name: REPOURL + value: "https://github.com/bob/video-processor" + ports: + - containerPort: 8082 + command: ["/bin/bash"] + args: + - -c + - | + echo "Starting video-processor on port 8082" + cat < SimpleHttpServer.java + import com.sun.net.httpserver.HttpServer; + import com.sun.net.httpserver.HttpHandler; + import com.sun.net.httpserver.HttpExchange; + import java.io.IOException; + import java.io.OutputStream; + import java.net.InetSocketAddress; + + public class SimpleHttpServer { + public static void main(String[] args) throws IOException { + int port = 8082; + HttpServer server = HttpServer.create(new InetSocketAddress(port), 0); + server.createContext("/", new MyHandler()); + server.setExecutor(null); + System.out.println("Serving video-processor on port " + port); + server.start(); + } + + static class MyHandler implements HttpHandler { + @Override + public void handle(HttpExchange t) throws IOException { + String response = "{" + + "\"name\":\"" + System.getenv("NAME") + "\"," + + "\"serviceName\":\"" + System.getenv("SERVICENAME") + "\"," + + "\"ownerName\":\"" + System.getenv("OWNERNAME") + "\"," + + "\"ownerEmail\":\"" + System.getenv("OWNEREMAIL") + "\"," + + "\"runtime\":\"" + System.getenv("RUNTIME") + "\"," + + "\"tags\":\"" + System.getenv("TAGS") + "\"," + + "\"description\":\"" + System.getenv("DESCRIPTION") + "\"," + + "\"actsOn\":\"" + System.getenv("ACTSON") + "\"," + + "\"repoURL\":\"" + System.getenv("REPOURL") + "\"" + + "}"; + t.sendResponseHeaders(200, response.length()); + try (OutputStream os = t.getResponseBody()) { + os.write(response.getBytes()); + } + } + } + } + EOF + javac SimpleHttpServer.java + java SimpleHttpServer + + # 4) audio-processor + - name: audio-processor + image: docker.io/library/openjdk:21-jdk-slim + env: + - name: NAME + value: "Audio Processor" + - name: SERVICENAME + value: "audio-processor-service" + - name: OWNERNAME + value: "Charlie" + - name: OWNEREMAIL + value: "charlie@example.com" + - name: RUNTIME + value: "java21" + - name: TAGS + value: "audio,mp3,processing" + - name: DESCRIPTION + value: "Processes audio files to enhance sound quality and extract features." + - name: ACTSON + value: "audio/mpeg" + - name: REPOURL + value: "https://github.com/charlie/audio-processor" + ports: + - containerPort: 8083 + command: ["/bin/bash"] + args: + - -c + - | + echo "Starting audio-processor on port 8083" + cat < SimpleHttpServer.java + import com.sun.net.httpserver.HttpServer; + import com.sun.net.httpserver.HttpHandler; + import com.sun.net.httpserver.HttpExchange; + import java.io.IOException; + import java.io.OutputStream; + import java.net.InetSocketAddress; + + public class SimpleHttpServer { + public static void main(String[] args) throws IOException { + int port = 8083; + HttpServer server = HttpServer.create(new InetSocketAddress(port), 0); + server.createContext("/", new MyHandler()); + server.setExecutor(null); + System.out.println("Serving audio-processor on port " + port); + server.start(); + } + + static class MyHandler implements HttpHandler { + @Override + public void handle(HttpExchange t) throws IOException { + String response = "{" + + "\"name\":\"" + System.getenv("NAME") + "\"," + + "\"serviceName\":\"" + System.getenv("SERVICENAME") + "\"," + + "\"ownerName\":\"" + System.getenv("OWNERNAME") + "\"," + + "\"ownerEmail\":\"" + System.getenv("OWNEREMAIL") + "\"," + + "\"runtime\":\"" + System.getenv("RUNTIME") + "\"," + + "\"tags\":\"" + System.getenv("TAGS") + "\"," + + "\"description\":\"" + System.getenv("DESCRIPTION") + "\"," + + "\"actsOn\":\"" + System.getenv("ACTSON") + "\"," + + "\"repoURL\":\"" + System.getenv("REPOURL") + "\"" + + "}"; + t.sendResponseHeaders(200, response.length()); + try (OutputStream os = t.getResponseBody()) { + os.write(response.getBytes()); + } + } + } + } + EOF + javac SimpleHttpServer.java + java SimpleHttpServer + + # 5) pdf-processor + - name: pdf-processor + image: docker.io/library/openjdk:21-jdk-slim + env: + - name: NAME + value: "PDF Processor" + - name: SERVICENAME + value: "pdf-processor-service" + - name: OWNERNAME + value: "Diana" + - name: OWNEREMAIL + value: "diana@example.com" + - name: RUNTIME + value: "java21" + - name: TAGS + value: "pdf,processing,text" + - name: DESCRIPTION + value: "Processes PDF files to extract text and metadata." + - name: ACTSON + value: "application/pdf" + - name: REPOURL + value: "https://github.com/diana/pdf-processor" + ports: + - containerPort: 8084 + command: ["/bin/bash"] + args: + - -c + - | + echo "Starting pdf-processor on port 8084" + cat < SimpleHttpServer.java + import com.sun.net.httpserver.HttpServer; + import com.sun.net.httpserver.HttpHandler; + import com.sun.net.httpserver.HttpExchange; + import java.io.IOException; + import java.io.OutputStream; + import java.net.InetSocketAddress; + + public class SimpleHttpServer { + public static void main(String[] args) throws IOException { + int port = 8084; + HttpServer server = HttpServer.create(new InetSocketAddress(port), 0); + server.createContext("/", new MyHandler()); + server.setExecutor(null); + System.out.println("Serving pdf-processor on port " + port); + server.start(); + } + + static class MyHandler implements HttpHandler { + @Override + public void handle(HttpExchange t) throws IOException { + String response = "{" + + "\"name\":\"" + System.getenv("NAME") + "\"," + + "\"serviceName\":\"" + System.getenv("SERVICENAME") + "\"," + + "\"ownerName\":\"" + System.getenv("OWNERNAME") + "\"," + + "\"ownerEmail\":\"" + System.getenv("OWNEREMAIL") + "\"," + + "\"runtime\":\"" + System.getenv("RUNTIME") + "\"," + + "\"tags\":\"" + System.getenv("TAGS") + "\"," + + "\"description\":\"" + System.getenv("DESCRIPTION") + "\"," + + "\"actsOn\":\"" + System.getenv("ACTSON") + "\"," + + "\"repoURL\":\"" + System.getenv("REPOURL") + "\"" + + "}"; + t.sendResponseHeaders(200, response.length()); + try (OutputStream os = t.getResponseBody()) { + os.write(response.getBytes()); + } + } + } + } + EOF + javac SimpleHttpServer.java + java SimpleHttpServer + + # 6) csv-processor + - name: csv-processor + image: docker.io/library/openjdk:21-jdk-slim + env: + - name: NAME + value: "CSV Processor" + - name: SERVICENAME + value: "csv-processor-service" + - name: OWNERNAME + value: "Eve" + - name: OWNEREMAIL + value: "eve@example.com" + - name: RUNTIME + value: "java21" + - name: TAGS + value: "csv,data,processing" + - name: DESCRIPTION + value: "Processes CSV files for data cleaning and transformation." + - name: ACTSON + value: "text/csv" + - name: REPOURL + value: "https://github.com/eve/csv-processor" + ports: + - containerPort: 8085 + command: ["/bin/bash"] + args: + - -c + - | + echo "Starting csv-processor on port 8085" + cat < SimpleHttpServer.java + import com.sun.net.httpserver.HttpServer; + import com.sun.net.httpserver.HttpHandler; + import com.sun.net.httpserver.HttpExchange; + import java.io.IOException; + import java.io.OutputStream; + import java.net.InetSocketAddress; + + public class SimpleHttpServer { + public static void main(String[] args) throws IOException { + int port = 8085; + HttpServer server = HttpServer.create(new InetSocketAddress(port), 0); + server.createContext("/", new MyHandler()); + server.setExecutor(null); + System.out.println("Serving csv-processor on port " + port); + server.start(); + } + + static class MyHandler implements HttpHandler { + @Override + public void handle(HttpExchange t) throws IOException { + String response = "{" + + "\"name\":\"" + System.getenv("NAME") + "\"," + + "\"serviceName\":\"" + System.getenv("SERVICENAME") + "\"," + + "\"ownerName\":\"" + System.getenv("OWNERNAME") + "\"," + + "\"ownerEmail\":\"" + System.getenv("OWNEREMAIL") + "\"," + + "\"runtime\":\"" + System.getenv("RUNTIME") + "\"," + + "\"tags\":\"" + System.getenv("TAGS") + "\"," + + "\"description\":\"" + System.getenv("DESCRIPTION") + "\"," + + "\"actsOn\":\"" + System.getenv("ACTSON") + "\"," + + "\"repoURL\":\"" + System.getenv("REPOURL") + "\"" + + "}"; + t.sendResponseHeaders(200, response.length()); + try (OutputStream os = t.getResponseBody()) { + os.write(response.getBytes()); + } + } + } + } + EOF + javac SimpleHttpServer.java + java SimpleHttpServer + + # 7) json-processor + - name: json-processor + image: docker.io/library/openjdk:21-jdk-slim + env: + - name: NAME + value: "JSON Processor" + - name: SERVICENAME + value: "json-processor-service" + - name: OWNERNAME + value: "Frank" + - name: OWNEREMAIL + value: "frank@example.com" + - name: RUNTIME + value: "java21" + - name: TAGS + value: "json,api,processing" + - name: DESCRIPTION + value: "Processes JSON files to validate and transform API payloads." + - name: ACTSON + value: "application/json" + - name: REPOURL + value: "https://github.com/frank/json-processor" + ports: + - containerPort: 8086 + command: ["/bin/bash"] + args: + - -c + - | + echo "Starting json-processor on port 8086" + cat < SimpleHttpServer.java + import com.sun.net.httpserver.HttpServer; + import com.sun.net.httpserver.HttpHandler; + import com.sun.net.httpserver.HttpExchange; + import java.io.IOException; + import java.io.OutputStream; + import java.net.InetSocketAddress; + + public class SimpleHttpServer { + public static void main(String[] args) throws IOException { + int port = 8086; + HttpServer server = HttpServer.create(new InetSocketAddress(port), 0); + server.createContext("/", new MyHandler()); + server.setExecutor(null); + System.out.println("Serving json-processor on port " + port); + server.start(); + } + + static class MyHandler implements HttpHandler { + @Override + public void handle(HttpExchange t) throws IOException { + String response = "{" + + "\"name\":\"" + System.getenv("NAME") + "\"," + + "\"serviceName\":\"" + System.getenv("SERVICENAME") + "\"," + + "\"ownerName\":\"" + System.getenv("OWNERNAME") + "\"," + + "\"ownerEmail\":\"" + System.getenv("OWNEREMAIL") + "\"," + + "\"runtime\":\"" + System.getenv("RUNTIME") + "\"," + + "\"tags\":\"" + System.getenv("TAGS") + "\"," + + "\"description\":\"" + System.getenv("DESCRIPTION") + "\"," + + "\"actsOn\":\"" + System.getenv("ACTSON") + "\"," + + "\"repoURL\":\"" + System.getenv("REPOURL") + "\"" + + "}"; + t.sendResponseHeaders(200, response.length()); + try (OutputStream os = t.getResponseBody()) { + os.write(response.getBytes()); + } + } + } + } + EOF + javac SimpleHttpServer.java + java SimpleHttpServer + + # 8) xml-processor + - name: xml-processor + image: docker.io/library/openjdk:21-jdk-slim + env: + - name: NAME + value: "XML Processor" + - name: SERVICENAME + value: "xml-processor-service" + - name: OWNERNAME + value: "Grace" + - name: OWNEREMAIL + value: "grace@example.com" + - name: RUNTIME + value: "java21" + - name: TAGS + value: "xml,parsing,processing" + - name: DESCRIPTION + value: "Processes XML files for data extraction and transformation." + - name: ACTSON + value: "application/xml" + - name: REPOURL + value: "https://github.com/grace/xml-processor" + ports: + - containerPort: 8087 + command: ["/bin/bash"] + args: + - -c + - | + echo "Starting xml-processor on port 8087" + cat < SimpleHttpServer.java + import com.sun.net.httpserver.HttpServer; + import com.sun.net.httpserver.HttpHandler; + import com.sun.net.httpserver.HttpExchange; + import java.io.IOException; + import java.io.OutputStream; + import java.net.InetSocketAddress; + + public class SimpleHttpServer { + public static void main(String[] args) throws IOException { + int port = 8087; + HttpServer server = HttpServer.create(new InetSocketAddress(port), 0); + server.createContext("/", new MyHandler()); + server.setExecutor(null); + System.out.println("Serving xml-processor on port " + port); + server.start(); + } + + static class MyHandler implements HttpHandler { + @Override + public void handle(HttpExchange t) throws IOException { + String response = "{" + + "\"name\":\"" + System.getenv("NAME") + "\"," + + "\"serviceName\":\"" + System.getenv("SERVICENAME") + "\"," + + "\"ownerName\":\"" + System.getenv("OWNERNAME") + "\"," + + "\"ownerEmail\":\"" + System.getenv("OWNEREMAIL") + "\"," + + "\"runtime\":\"" + System.getenv("RUNTIME") + "\"," + + "\"tags\":\"" + System.getenv("TAGS") + "\"," + + "\"description\":\"" + System.getenv("DESCRIPTION") + "\"," + + "\"actsOn\":\"" + System.getenv("ACTSON") + "\"," + + "\"repoURL\":\"" + System.getenv("REPOURL") + "\"" + + "}"; + t.sendResponseHeaders(200, response.length()); + try (OutputStream os = t.getResponseBody()) { + os.write(response.getBytes()); + } + } + } + } + EOF + javac SimpleHttpServer.java + java SimpleHttpServer + + # 9) excel-processor + - name: excel-processor + image: docker.io/library/openjdk:21-jdk-slim + env: + - name: NAME + value: "Excel Processor" + - name: SERVICENAME + value: "excel-processor-service" + - name: OWNERNAME + value: "Hank" + - name: OWNEREMAIL + value: "hank@example.com" + - name: RUNTIME + value: "java21" + - name: TAGS + value: "excel,xls,processing" + - name: DESCRIPTION + value: "Processes Excel files to extract and manipulate data." + - name: ACTSON + value: "application/vnd.ms-excel" + - name: REPOURL + value: "https://github.com/hank/excel-processor" + ports: + - containerPort: 8088 + command: ["/bin/bash"] + args: + - -c + - | + echo "Starting excel-processor on port 8088" + cat < SimpleHttpServer.java + import com.sun.net.httpserver.HttpServer; + import com.sun.net.httpserver.HttpHandler; + import com.sun.net.httpserver.HttpExchange; + import java.io.IOException; + import java.io.OutputStream; + import java.net.InetSocketAddress; + + public class SimpleHttpServer { + public static void main(String[] args) throws IOException { + int port = 8088; + HttpServer server = HttpServer.create(new InetSocketAddress(port), 0); + server.createContext("/", new MyHandler()); + server.setExecutor(null); + System.out.println("Serving excel-processor on port " + port); + server.start(); + } + + static class MyHandler implements HttpHandler { + @Override + public void handle(HttpExchange t) throws IOException { + String response = "{" + + "\"name\":\"" + System.getenv("NAME") + "\"," + + "\"serviceName\":\"" + System.getenv("SERVICENAME") + "\"," + + "\"ownerName\":\"" + System.getenv("OWNERNAME") + "\"," + + "\"ownerEmail\":\"" + System.getenv("OWNEREMAIL") + "\"," + + "\"runtime\":\"" + System.getenv("RUNTIME") + "\"," + + "\"tags\":\"" + System.getenv("TAGS") + "\"," + + "\"description\":\"" + System.getenv("DESCRIPTION") + "\"," + + "\"actsOn\":\"" + System.getenv("ACTSON") + "\"," + + "\"repoURL\":\"" + System.getenv("REPOURL") + "\"" + + "}"; + t.sendResponseHeaders(200, response.length()); + try (OutputStream os = t.getResponseBody()) { + os.write(response.getBytes()); + } + } + } + } + EOF + javac SimpleHttpServer.java + java SimpleHttpServer + + # 10) markdown-processor + - name: markdown-processor + image: docker.io/library/openjdk:21-jdk-slim + env: + - name: NAME + value: "Markdown Processor" + - name: SERVICENAME + value: "markdown-processor-service" + - name: OWNERNAME + value: "Ivy" + - name: OWNEREMAIL + value: "ivy@example.com" + - name: RUNTIME + value: "java21" + - name: TAGS + value: "markdown,text,processing" + - name: DESCRIPTION + value: "Processes Markdown files to render and validate content." + - name: ACTSON + value: "text/markdown" + - name: REPOURL + value: "https://github.com/ivy/markdown-processor" + ports: + - containerPort: 8089 + command: ["/bin/bash"] + args: + - -c + - | + echo "Starting markdown-processor on port 8089" + cat < SimpleHttpServer.java + import com.sun.net.httpserver.HttpServer; + import com.sun.net.httpserver.HttpHandler; + import com.sun.net.httpserver.HttpExchange; + import java.io.IOException; + import java.io.OutputStream; + import java.net.InetSocketAddress; + + public class SimpleHttpServer { + public static void main(String[] args) throws IOException { + int port = 8089; + HttpServer server = HttpServer.create(new InetSocketAddress(port), 0); + server.createContext("/", new MyHandler()); + server.setExecutor(null); + System.out.println("Serving markdown-processor on port " + port); + server.start(); + } + + static class MyHandler implements HttpHandler { + @Override + public void handle(HttpExchange t) throws IOException { + String response = "{" + + "\"name\":\"" + System.getenv("NAME") + "\"," + + "\"serviceName\":\"" + System.getenv("SERVICENAME") + "\"," + + "\"ownerName\":\"" + System.getenv("OWNERNAME") + "\"," + + "\"ownerEmail\":\"" + System.getenv("OWNEREMAIL") + "\"," + + "\"runtime\":\"" + System.getenv("RUNTIME") + "\"," + + "\"tags\":\"" + System.getenv("TAGS") + "\"," + + "\"description\":\"" + System.getenv("DESCRIPTION") + "\"," + + "\"actsOn\":\"" + System.getenv("ACTSON") + "\"," + + "\"repoURL\":\"" + System.getenv("REPOURL") + "\"" + + "}"; + t.sendResponseHeaders(200, response.length()); + try (OutputStream os = t.getResponseBody()) { + os.write(response.getBytes()); + } + } + } + } + EOF + javac SimpleHttpServer.java + java SimpleHttpServer diff --git a/package-lock.json b/package-lock.json index e93c44da..d81eb67b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,16 +13,23 @@ "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", + "axios": "^1.7.9", + "babel-preset-react-app": "^10.0.1", "bootstrap": "^3.4.1", "cors": "^2.8.5", "dotenv": "^16.4.7", "express": "^4.21.2", + "fs": "^0.0.1-security", + "https": "^1.0.0", "mongoose": "^8.9.4", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.28.0", "react-scripts": "5.0.1", "web-vitals": "^2.1.4" + }, + "devDependencies": { + "@babel/plugin-proposal-private-property-in-object": "^7.21.11" } }, "node_modules/@adobe/css-tools": { @@ -639,9 +646,18 @@ } }, "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.0-placeholder-for-preset-env.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", - "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "version": "7.21.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz", + "integrity": "sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-property-in-object instead.", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.21.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, "engines": { "node": ">=6.9.0" }, @@ -1867,6 +1883,18 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/preset-env/node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/preset-env/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -4844,6 +4872,31 @@ "node": ">=4" } }, + "node_modules/axios": { + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", + "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axios/node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/axobject-query": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", @@ -5052,6 +5105,7 @@ "version": "10.0.1", "resolved": "https://registry.npmjs.org/babel-preset-react-app/-/babel-preset-react-app-10.0.1.tgz", "integrity": "sha512-b0D9IZ1WhhCWkrTXyFuIIgqGzSkRIH5D5AmB0bXbzYAB1OBAwHcUeyWW2LorutLWF5btNo/N7r/cIdmvvKJlYg==", + "license": "MIT", "dependencies": { "@babel/core": "^7.16.0", "@babel/plugin-proposal-class-properties": "^7.16.0", @@ -5796,6 +5850,7 @@ "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", "dependencies": { "object-assign": "^4", "vary": "^1" @@ -7611,6 +7666,7 @@ "version": "4.21.2", "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", @@ -8093,6 +8149,12 @@ "node": ">= 0.6" } }, + "node_modules/fs": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", + "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==", + "license": "ISC" + }, "node_modules/fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", @@ -8701,6 +8763,12 @@ } } }, + "node_modules/https": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https/-/https-1.0.0.tgz", + "integrity": "sha512-4EC57ddXrkaF0x83Oj8sM6SLQHAWXw90Skqu2M4AEWENZ3F02dFJE/GARA8igO79tcgYqGrD7ae4f5L3um2lgg==", + "license": "ISC" + }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -13009,6 +13077,12 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", diff --git a/package.json b/package.json index 88440e2f..60ab1478 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,10 @@ "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", + "axios": "^1.7.9", + "babel-preset-react-app": "^10.0.1", + "fs": "^0.0.1-security", + "https": "^1.0.0", "bootstrap": "^3.4.1", "cors": "^2.8.5", "dotenv": "^16.4.7", @@ -40,6 +44,9 @@ "last 1 safari version" ] }, + "devDependencies": { + "@babel/plugin-proposal-private-property-in-object": "^7.21.11" + }, "description": "This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).", "main": "index.js", "author": "", diff --git a/resources/controller.yml b/resources/controller.yml new file mode 100644 index 00000000..5b9b9c54 --- /dev/null +++ b/resources/controller.yml @@ -0,0 +1,18 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: processor-operator +spec: + replicas: 1 + selector: + matchLabels: + app: processor-operator + template: + metadata: + labels: + app: processor-operator + spec: + containers: + - name: operator + image: your-operator-image:latest + diff --git a/src/App.js b/src/App.js index 7dff4513..aa282ae4 100644 --- a/src/App.js +++ b/src/App.js @@ -8,7 +8,7 @@ import { import Header from "./View/Header/Header"; import Content from "./View/Content/Content"; import Description from "./View/Description/Description"; -import WelcomePage from "./View/Authentication/WelcomePage"; // Welcome page +import WelcomePage from "./View/Authentication/WelcomePage"; import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; const App = () => { @@ -38,7 +38,7 @@ const App = () => {
- {showWelcomePage ? ( + {showWelcomePage ? ( setShowWelcomePage(false)} /> ) : ( diff --git a/src/Controller/Menu/__pycache__/MenuModel.cpython-310.pyc b/src/Controller/Menu/__pycache__/MenuModel.cpython-310.pyc new file mode 100644 index 00000000..ebdfecac Binary files /dev/null and b/src/Controller/Menu/__pycache__/MenuModel.cpython-310.pyc differ diff --git a/src/Model/Menu/MenuModel.py b/src/Model/Menu/MenuModel.py new file mode 100644 index 00000000..0bc288c2 --- /dev/null +++ b/src/Model/Menu/MenuModel.py @@ -0,0 +1,9 @@ +options = [ + "Option-1", + "Option-2", + "Option-3", + "Option-4", + "Option-5", + "Option-6", + "Option-7", +] diff --git a/src/View/Authentication/Authentication.js b/src/View/Authentication/Authentication.js new file mode 100644 index 00000000..07e454ec --- /dev/null +++ b/src/View/Authentication/Authentication.js @@ -0,0 +1,63 @@ +const express = require("express"); +const mongoose = require("mongoose"); +const Employee = require("./AuthenticationDB"); + +const app = express(); +const cors = require('cors'); +app.use(cors()); + +app.use(express.json()); // Middleware to parse JSON bodies + +// Database Connection +async function connectDB() { + await mongoose.connect( + "mongodb+srv://marketplace:abcd%401234@marketplace.gsv4e.mongodb.net/marketplaceDB" + ); +} +connectDB(); + +// Middleware for validating request body +async function authMiddleware(req, res, next) { + const { email, password } = req.body; + if (!email || !password) { + return res.status(400).json({ error: "Email and Password are required." }); + } + next(); +} + +// Error Handler Middleware +function errorHandler(err, req, res, next) { + console.error(err.stack); + res.status(500).json({ error: "An internal server error occurred." }); +} + +// Login Route +app.post("/login", authMiddleware, async (req, res, next) => { + const { email, password } = req.body; + + try { + // Find employee by email + const employee = await Employee.findOne({ email }); + if (!employee) { + return res.status(400).json({ error: "Invalid Email." }); + } + + // Validate password + if (employee.password !== password) { + return res.status(400).json({ error: "Invalid Password." }); + } + + res.status(200).json({ message: "Login successful!" }); + } catch (err) { + next(err); // Pass errors to the error handler + } +}); + +// Use error handler middleware +app.use(errorHandler); + +// Start the server +const PORT = 3001; +app.listen(PORT, () => { + console.log(`Server is running on http://localhost:${PORT}`); +}); diff --git a/src/View/Authentication/AuthenticationDB.js b/src/View/Authentication/AuthenticationDB.js new file mode 100644 index 00000000..ad6285a8 --- /dev/null +++ b/src/View/Authentication/AuthenticationDB.js @@ -0,0 +1,20 @@ +const mongoose = require("mongoose"); + +// Employee Schema +const employeeSchema = new mongoose.Schema({ + email: { + type: String, + required: true, + unique: true, + }, + password: { + type: String, + required: true, + }, + level: { + type: String, + }, +}); + +// Export the Employee model +module.exports = mongoose.model("Employee", employeeSchema); diff --git a/src/View/Authentication/Login.css b/src/View/Authentication/Login.css new file mode 100644 index 00000000..c1a98e69 --- /dev/null +++ b/src/View/Authentication/Login.css @@ -0,0 +1,82 @@ +/* Overall popup container */ +.login-popup-container { + display: flex; + justify-content: center; + align-items: center; + height: 100vh; + background-color: rgba(0, 0, 0, 0.7); /* Semi-transparent background */ + position: fixed; + top: 0; + left: 0; + width: 100%; + z-index: 1000; + } + + /* Popup form styling */ + .login-popup-form { + background: #333; + padding: 20px; + border-radius: 10px; + width: 300px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3); + } + + .login-popup-form h2 { + color: #fff; + text-align: center; + margin-bottom: 20px; + } + + .form-group { + margin-bottom: 15px; + } + + .form-group label { + color: #ccc; + font-size: 14px; + } + + .form-group input { + width: 94%; + padding: 8px; + border: 1px solid #555; + border-radius: 5px; + background: #444; + color: #fff; + } + + /* Buttons container */ + .form-buttons { + display: flex; + justify-content: space-between; + margin-bottom: 5%; + } + + /* Styling the buttons */ + .login-button, + .cancel-button { + width: 45%; + padding: 10px; + border: none; + border-radius: 5px; + font-size: 14px; + color: #fff; + cursor: pointer; + } + + .login-button { + background-color: #007bff; + } + + .cancel-button { + background-color: #ff4c4c; + } + + .login-button:hover { + background-color: #0056b3; + } + + .cancel-button:hover { + background-color: #d11a1a; + } + \ No newline at end of file diff --git a/src/View/Authentication/Login.js b/src/View/Authentication/Login.js new file mode 100644 index 00000000..03195109 --- /dev/null +++ b/src/View/Authentication/Login.js @@ -0,0 +1,100 @@ +import React, { useState } from "react"; +import { useNavigate } from "react-router-dom"; // Import useNavigate +import "./Login.css"; + +const LoginPopup = ({ onLogin }) => { + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); + const [error, setError] = useState(""); + const [success, setSuccess] = useState(""); + const navigate = useNavigate(); // Initialize useNavigate + + const handleCancel = () => { + setEmail(""); + setPassword(""); + setError(""); + setSuccess(""); + alert("Action canceled!"); + // Close popup or redirect, if needed + }; + + const handleLogin = async (e) => { + e.preventDefault(); + + try { + // Send POST request to backend + const response = await fetch("http://localhost:3001/login", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ email, password }), + }); + + const data = await response.json(); + + if (response.ok) { + setSuccess("Login successful!"); + setError(""); // Clear any previous errors + console.log("Login successful:", data); + + // Notify parent component of successful login + onLogin(); + + // Redirect to the home page + navigate("/"); + } else { + setError(data.error || "Login failed. Please try again."); + setSuccess(""); // Clear any previous success message + } + } catch (err) { + console.error("Error during login:", err); + setError("An error occurred. Please try again later."); + } + }; + + return ( +
+
+

Login

+
+ + setEmail(e.target.value)} + placeholder="Enter your email" + required + /> +
+
+ + setPassword(e.target.value)} + placeholder="Enter your password" + required + /> +
+
+ + +
+ {/* Display success or error messages */} + {success &&

{success}

} + {error &&

{error}

} +
+
+ ); +}; + +export default LoginPopup; diff --git a/src/View/KubernetesContainers/KubernetesContainers.js b/src/View/KubernetesContainers/KubernetesContainers.js new file mode 100644 index 00000000..9ce293af --- /dev/null +++ b/src/View/KubernetesContainers/KubernetesContainers.js @@ -0,0 +1,54 @@ +import React, { useState, useEffect } from "react"; + +const Processors = () => { + const [processors, setProcessors] = useState([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + // Fetch data from the Flask API + fetch("http://127.0.0.1:8001/apis/example.com/v1/namespaces/default/processors") + .then((response) => response.json()) + .then((data) => { + setProcessors(data.items || []); // Adjust based on the API response + setLoading(false); + }) + .catch((error) => { + console.error("Error fetching processors:", error); + setLoading(false); + }); + }, []); + + if (loading) { + return

Loading processors...

; + } + + return ( +
+

Processors

+ + + + + + + + + + + + {processors.map((processor, index) => ( + + + + + + + + ))} + +
NameService NameOwner NameRuntimeDescription
{processor.metadata.name}{processor.spec.serviceName}{processor.spec.ownerName}{processor.spec.runtime}{processor.spec.description}
+
+ ); +}; + +export default Processors;