diff --git a/labs/lab9-solution/project/Makefile b/labs/lab9-solution/project/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..3d2da20b6b3bb5ee7e2c543e7a9af72d71d97780 --- /dev/null +++ b/labs/lab9-solution/project/Makefile @@ -0,0 +1,29 @@ +help: + @echo "build build the app" + @echo "deploy deploy the app" + @echo "run run the app" + @echo "logs display the app's logs" + @echo "clean clean the app" + +build: + docker buildx build -t md2html md2html + docker buildx build -t logger logger + docker buildx build -t web web + docker network create web-net + docker network create proc-net + +deploy: + docker run -d -p 2000:12345 -h logger --network proc-net --name logger --rm logger + docker run -d -p 3000:80 -h web --network web-net --name web --rm --mount type=bind,src=$$(pwd)/data,dst=/data web + +logs: + curl localhost:2000/logs + +run: + docker run -h md2html --network proc-net --name md2html --rm --mount type=bind,src=$$(pwd)/data,dst=/data md2html + +clean: + docker rm -f web logger + docker image rm -f md2html logger + docker network rm -f proc-net web-net + rm -f data/output/* diff --git a/labs/lab9-solution/project/data/input/aliens.md b/labs/lab9-solution/project/data/input/aliens.md new file mode 100644 index 0000000000000000000000000000000000000000..a1b494ea24261cb7c86d610414f43fc07c98db6d --- /dev/null +++ b/labs/lab9-solution/project/data/input/aliens.md @@ -0,0 +1,27 @@ +# They Came at 2:03 AM + +It started with a **low hum**, like a refrigerator from across the galaxy. +*Martin* had been up late, coding in his garage, when the noise made his keyboard rattle. + +He stepped outside, barefoot, wrapped in a hoodie that still smelled like *burnt coffee*. +Above the cornfield, something was hovering. Not spinning. Not blinking. Just... *waiting*. + +He reached for his phone. **No signal.** +No time to post it, tweet it, or even record it. + +The object descended a few feet - smooth and silent, shaped like a *teardrop made of dark glass*. + +A hatch hissed open. Light poured out, **too bright** and **too quiet**. +Then *they* stepped out. Tall. Unmoving. Featureless. + +Martin did what no one in every alien movie ever seemed to do: + +> He sat down and waved. + +**"Hi,"** he said. *"I'm Martin. I suck at sleeping."* + +The taller one tilted its head. +A thin beam projected a sentence into the dirt: + +```text +ARE YOU THE ONE WHO BUILT THE SIGNAL? diff --git a/labs/lab9-solution/project/data/input/cat.md b/labs/lab9-solution/project/data/input/cat.md new file mode 100644 index 0000000000000000000000000000000000000000..15f970be6e7cf71eef361d3370ed84bdde296435 --- /dev/null +++ b/labs/lab9-solution/project/data/input/cat.md @@ -0,0 +1,18 @@ +# The Cat Who Understood Time + +Milo wasn't an ordinary cat. Sure, he looked the part-fuzzy ears, twitchy tail, eyes like marbles in moonlight-but there was something about the way he stared at clocks. + +Ever since Ava adopted him from the dusty shelter near the train station, she noticed his peculiar habits. He'd perch beneath her antique grandfather clock at **exactly 11:11 AM**, every day. When the chimes rang, he'd close his eyes, purr once, and vanish into the shadows of the hallway. + +One rainy Tuesday, Ava followed him. He slipped under the kitchen cupboard, and to her amazement, a soft shimmer of blue light outlined the floorboards. She reached forward, hand trembling. + +> "What you think is lost," she remembered her grandmother once saying, +> "is sometimes only waiting to be found-just elsewhere in time." + +When she pushed open the loose plank, she found a spiral staircase leading *down*. Milo was waiting, tail flicking, as if to say: *Finally.* + +At the bottom, glowing softly in a chamber of forgotten gears, stood a **time machine**. It was labeled in scratchy etching: `Property of T. Whiskers`. + +Ava turned to Milo. He blinked once. She understood. + +They weren't going back upstairs. Not yet. diff --git a/labs/lab9-solution/project/data/input/plan9.md b/labs/lab9-solution/project/data/input/plan9.md new file mode 100644 index 0000000000000000000000000000000000000000..dbfae4d2778885689bb1f2231948def24f325d27 --- /dev/null +++ b/labs/lab9-solution/project/data/input/plan9.md @@ -0,0 +1,20 @@ +# Plan 9 from Bell Labs + +**Plan 9** is an operating system developed by **Bell Labs** as the conceptual successor to Unix. Designed in the late 1980s and early 1990s, it was created by some of the same minds behind Unix: *Ken Thompson*, *Dennis Ritchie*, and *Rob Pike*, among others. + +Unlike traditional operating systems, Plan 9 treats **everything as a file**, and more importantly, it **exports resources as files** via its powerful `9P` protocol. This makes **distributed computing** a natural part of the environment, not an afterthought. + +## Key Concepts + +- *Everything is a file* - including GUI elements and network interfaces. +- *Namespaces* are customizable per process. +- *9P Protocol* allows seamless resource sharing between systems. +- *Union directories* let you overlay file systems cleanly. + +## Example: Mounting a Window + +Here's how you'd mount a remote graphical window server: + +```sh +mount -c /srv/graphics /dev/draw +``` diff --git a/labs/lab9-solution/project/logger/Dockerfile b/labs/lab9-solution/project/logger/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..5fb4ce2a2ee3ee8d54c8eb7574fb76395cea76c3 --- /dev/null +++ b/labs/lab9-solution/project/logger/Dockerfile @@ -0,0 +1,9 @@ +FROM alpine:3.21 + +RUN apk update +RUN apk add python3 py3-flask + +COPY logger_api.py / +WORKDIR / + +ENTRYPOINT ["python", "logger_api.py"] \ No newline at end of file diff --git a/labs/lab9-solution/project/logger/logger_api.py b/labs/lab9-solution/project/logger/logger_api.py new file mode 100644 index 0000000000000000000000000000000000000000..68b77d8e4d79b08a3a2b804c0ed14bf0213b2ef0 --- /dev/null +++ b/labs/lab9-solution/project/logger/logger_api.py @@ -0,0 +1,26 @@ +from flask import Flask, request, jsonify +from flask import Response + +logs = [] + +app = Flask(__name__) + +@app.route('/log', methods=['POST']) +def receive_message(): + data = request.get_json() + + if not data or 'message' not in data: + return jsonify({'error': 'Missing "message" field'}), 400 + + msg = data['message'] + print(f"DEBUG: message: {msg}") + logs.append(msg) + + return Response(status=200) + +@app.route('/logs', methods=['GET']) +def dump_messages(): + return jsonify(logs), 200 + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=12345) diff --git a/labs/lab9-solution/project/md2html/Dockerfile b/labs/lab9-solution/project/md2html/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..15676707aa546d6c4993485ae847004e131f248c --- /dev/null +++ b/labs/lab9-solution/project/md2html/Dockerfile @@ -0,0 +1,19 @@ +FROM ubuntu:24.04 + +WORKDIR /build +COPY Makefile /build +COPY md2html.c /build + +RUN apt-get update -y +RUN apt-get install -y gcc make libcmark-dev curl \ + && make \ + && mv md2html /usr/bin \ + && rm -rf /build \ + && apt-get remove -y gcc make libcmark-dev \ + && apt autoremove -y +RUN apt-get install -y libcmark0.30.2 + +WORKDIR / +COPY --chmod=755 convert.sh / + +CMD ["/convert.sh"] \ No newline at end of file diff --git a/labs/lab9-solution/project/md2html/Makefile b/labs/lab9-solution/project/md2html/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..42c0032e357cdb32acb3534b036bcc9c91002fec --- /dev/null +++ b/labs/lab9-solution/project/md2html/Makefile @@ -0,0 +1,5 @@ +md2html: md2html.c + gcc $< -o $@ -lcmark + +clean: + rm -f md2html diff --git a/labs/lab9-solution/project/md2html/convert.sh b/labs/lab9-solution/project/md2html/convert.sh new file mode 100644 index 0000000000000000000000000000000000000000..24ec725fa180a66ba8c3cc228a58bd6edb35b23f --- /dev/null +++ b/labs/lab9-solution/project/md2html/convert.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +for i in /data/input/*.md; do + f=$(basename $i).html + md2html $i > /data/output/$f + curl -X POST http://logger:12345/log -H "Content-Type: application/json" -d "{\"message\": \"$f\"}" +done \ No newline at end of file diff --git a/labs/lab9-solution/project/md2html/md2html.c b/labs/lab9-solution/project/md2html/md2html.c new file mode 100644 index 0000000000000000000000000000000000000000..a6cfc7c14319ad01d07df9b6e5e98eaeeb9081d7 --- /dev/null +++ b/labs/lab9-solution/project/md2html/md2html.c @@ -0,0 +1,33 @@ +#include <stdio.h> +#include <stdlib.h> +#include <cmark.h> + +int main(int argc, char *argv[]) { + if (argc != 2) { + fprintf(stderr, "Usage: %s <markdown-file>\n", argv[0]); + return 1; + } + + // Open and read the Markdown file + FILE *fp = fopen(argv[1], "rb"); + if (!fp) { + perror("fopen"); + return 1; + } + + fseek(fp, 0, SEEK_END); + long len = ftell(fp); + fseek(fp, 0, SEEK_SET); + char *md = malloc(len + 1); + fread(md, 1, len, fp); + md[len] = '\0'; + fclose(fp); + + // Convert to HTML + char *html = cmark_markdown_to_html(md, len, CMARK_OPT_DEFAULT); + printf("%s\n", html); + + free(md); + free(html); + return 0; +} diff --git a/labs/lab9-solution/project/web/Dockerfile b/labs/lab9-solution/project/web/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..b88c847ccbf03c6b2a4f3065014aceedde91da56 --- /dev/null +++ b/labs/lab9-solution/project/web/Dockerfile @@ -0,0 +1,8 @@ +FROM debian:bookworm + +RUN apt-get update -y +RUN apt-get install -y nginx + +COPY default /etc/nginx/sites-enabled + +CMD ["nginx", "-g", "daemon off;"] diff --git a/labs/lab9-solution/project/web/default b/labs/lab9-solution/project/web/default new file mode 100644 index 0000000000000000000000000000000000000000..e7712e539008962bd3d705a1301683ee9307bb36 --- /dev/null +++ b/labs/lab9-solution/project/web/default @@ -0,0 +1,91 @@ +## +# You should look at the following URL's in order to grasp a solid understanding +# of Nginx configuration files in order to fully unleash the power of Nginx. +# https://www.nginx.com/resources/wiki/start/ +# https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/ +# https://wiki.debian.org/Nginx/DirectoryStructure +# +# In most cases, administrators will remove this file from sites-enabled/ and +# leave it as reference inside of sites-available where it will continue to be +# updated by the nginx packaging team. +# +# This file will automatically load configuration files provided by other +# applications, such as Drupal or Wordpress. These applications will be made +# available underneath a path with that package name, such as /drupal8. +# +# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples. +## + +# Default server configuration +# +server { + listen 80 default_server; + listen [::]:80 default_server; + + # SSL configuration + # + # listen 443 ssl default_server; + # listen [::]:443 ssl default_server; + # + # Note: You should disable gzip for SSL traffic. + # See: https://bugs.debian.org/773332 + # + # Read up on ssl_ciphers to ensure a secure configuration. + # See: https://bugs.debian.org/765782 + # + # Self signed certs generated by the ssl-cert package + # Don't use them in a production server! + # + # include snippets/snakeoil.conf; + + root /data/output; + + # Add index.php to the list if you are using PHP + index index.html index.htm index.nginx-debian.html; + + server_name _; + + location / { + # First attempt to serve request as file, then + # as directory, then fall back to displaying a 404. + try_files $uri $uri/ =404; + } + + # pass PHP scripts to FastCGI server + # + #location ~ \.php$ { + # include snippets/fastcgi-php.conf; + # + # # With php-fpm (or other unix sockets): + # fastcgi_pass unix:/run/php/php7.4-fpm.sock; + # # With php-cgi (or other tcp sockets): + # fastcgi_pass 127.0.0.1:9000; + #} + + # deny access to .htaccess files, if Apache's document root + # concurs with nginx's one + # + #location ~ /\.ht { + # deny all; + #} +} + + +# Virtual Host configuration for example.com +# +# You can move that to a different file under sites-available/ and symlink that +# to sites-enabled/ to enable it. +# +#server { +# listen 80; +# listen [::]:80; +# +# server_name example.com; +# +# root /var/www/example.com; +# index index.html; +# +# location / { +# try_files $uri $uri/ =404; +# } +#}