diff --git a/examples/voting-app/load-generator.py b/examples/voting-app/load-generator.py new file mode 100755 index 00000000..afddde0c --- /dev/null +++ b/examples/voting-app/load-generator.py @@ -0,0 +1,35 @@ +import requests +import time + +# The URL to send the POST requests to +host = "prod.app.localhost" +url = "http://127.0.0.1/" + +# Headers to be included in the POST requests +headers = { + "Origin": f"http://{host}", + "Host": host, +} + +# Data to be sent in the POST requests +data_options = ["option1", "option2"] +data_index = 0 + + +# Function to send a burst of 5 POST requests +def send_burst(data): + print(f"New burst of {data}") + for _ in range(5): + response = None + try: + response = requests.post(url, headers=headers, data={"vote": data}) + print(f"Sent '{data}' - Response status code: {response.status_code}") + except requests.exceptions.RequestException as e: + print(f"Error sending '{data}' - {e}") + + +# Send bursts of 5 POST requests every 5 seconds, alternating between 'Cats' and 'Dogs' +while True: + send_burst(data_options[data_index]) + data_index = (data_index + 1) % 2 + time.sleep(5) diff --git a/examples/voting-app/shell.nix b/examples/voting-app/shell.nix new file mode 100644 index 00000000..b082bd69 --- /dev/null +++ b/examples/voting-app/shell.nix @@ -0,0 +1,27 @@ +{pkgs, ...}: let + pyEnv = pkgs.python3.buildEnv.override { + extraLibs = [pkgs.python3Packages.click pkgs.python3Packages.requests]; + ignoreCollisions = true; + }; + + pname = "demo-load-generator"; + demo-load-genarator = pkgs.stdenv.mkDerivation { + inherit pname; + version = "1.0.0"; + + src = ./.; + + installPhase = '' + mkdir -p $out/bin + echo "#!${pyEnv}/bin/python3" > $out/bin/${pname} + cat load-generator.py >> $out/bin/${pname} + chmod +x $out/bin/${pname} + ''; + }; +in + pkgs.mkShell { + buildInputs = [ + demo-load-genarator + pyEnv + ]; + } diff --git a/examples/voting-app/voting-app-ui/Dockerfile b/examples/voting-app/voting-app-ui/Dockerfile new file mode 100644 index 00000000..032b37ca --- /dev/null +++ b/examples/voting-app/voting-app-ui/Dockerfile @@ -0,0 +1,12 @@ +FROM python:3.9-slim + +WORKDIR /app + +COPY . . + +RUN pip install Flask redis + +EXPOSE 5000 + +CMD ["python", "app.py"] + diff --git a/examples/voting-app/voting-app-ui/Dockerfile-v2 b/examples/voting-app/voting-app-ui/Dockerfile-v2 new file mode 100644 index 00000000..cee5a378 --- /dev/null +++ b/examples/voting-app/voting-app-ui/Dockerfile-v2 @@ -0,0 +1,14 @@ +FROM python:3.9-slim + +WORKDIR /app + +COPY . . + +RUN pip install Flask redis + +ENV APP_VERSION v2 + +EXPOSE 5000 + +CMD ["python", "app.py"] + diff --git a/examples/voting-app/voting-app-ui/app.py b/examples/voting-app/voting-app-ui/app.py new file mode 100644 index 00000000..accb3b3b --- /dev/null +++ b/examples/voting-app/voting-app-ui/app.py @@ -0,0 +1,94 @@ +from flask import Flask, render_template, request, redirect, url_for +import redis +import os + +app = Flask(__name__) + +redis_server = os.environ["REDIS"] + +# Initialize Redis +r = redis.Redis(host=redis_server, port=6379) + +# Getting app version +if "APP_VERSION" in os.environ and os.environ["APP_VERSION"]: + app_version = os.environ["APP_VERSION"] +else: + app_version = "v1" + +print("app_version is: " + app_version) + +if "OPTION1" in os.environ and os.environ["OPTION1"]: + option1 = os.environ["OPTION1"] +else: + option1 = "Option 1" + +if "OPTION2" in os.environ and os.environ["OPTION2"]: + option2 = os.environ["OPTION2"] +else: + option2 = "Option 2" + +if "OPTION3" in os.environ and os.environ["OPTION3"] and app_version != "v1": + option3 = os.environ["OPTION3"] +elif app_version != "v1": + option3 = "Option 3" + +if "TITLE" in os.environ and os.environ["TITLE"]: + title = os.environ["TITLE"] +else: + title = "Vote For Your Favorite Option" + +# Set up initial vote counts +# TODO: implement this on redis proxy +if not r.exists("option1"): + r.set("option1", 0) +if not r.exists("option2"): + r.set("option2", 0) + +if app_version == "v1": + if not r.exists("option3"): + r.set("option3", 0) + + +@app.route("/", methods=["GET", "POST"]) +def index(): + if request.method == "POST": + vote = request.form["vote"] + if vote == "option1": + r.incr("option1") + elif vote == "option2": + r.incr("option2") + elif vote == "option3" and app_version != "v1": + r.incr("option3") + return redirect(url_for("index")) + + # Get current vote counts + option1_votes = int(r.get("option1") or 0) + option2_votes = int(r.get("option2") or 0) + if app_version != "v1": + option3_votes = int(r.get("option3") or 0) + + if app_version != "v1": + return render_template( + "index.html", + option1_votes=option1_votes, + option2_votes=option2_votes, + option3_votes=option3_votes, + title=title, + option1=option1, + option2=option2, + option3=option3, + ) + else: + return render_template( + "index.html", + option1_votes=option1_votes, + option2_votes=option2_votes, + title=title, + option1=option1, + option2=option2, + ) + + + +if __name__ == "__main__": + app.run(debug=True, host="0.0.0.0", port=80) diff --git a/examples/voting-app/voting-app-ui/templates/index.html b/examples/voting-app/voting-app-ui/templates/index.html new file mode 100644 index 00000000..0babd41c --- /dev/null +++ b/examples/voting-app/voting-app-ui/templates/index.html @@ -0,0 +1,142 @@ + + +
+ + +