aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Christopher Baklid <[email protected]>2018-05-22 22:12:43 +0200
committerGravatar Christopher Baklid <[email protected]>2018-05-22 22:12:43 +0200
commitf689ce549689b3192ce1f7510804495acfd7869d (patch)
tree56ac7af58d1b9a8ea59a943e711e337a10220cdd
parentDelete test.py (diff)
adds webapp and docker-compose for more proof of concept
-rw-r--r--.dockerignore15
-rw-r--r--Pipfile10
-rw-r--r--Pipfile.lock183
-rw-r--r--README.md36
-rw-r--r--docker-compose.yml18
-rw-r--r--docker/Dockerfile12
-rw-r--r--runner/consume.py68
-rw-r--r--snekbox/config.py (renamed from runner/config.py)4
-rw-r--r--snekbox/consume.py75
-rw-r--r--snekbox/publish.py (renamed from runner/publish.py)36
-rw-r--r--tox.ini6
-rw-r--r--webapp/rmq.py48
-rw-r--r--webapp/templates/index.html64
-rw-r--r--webapp/webapp.py39
14 files changed, 511 insertions, 103 deletions
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..210f85f
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,15 @@
+.venv
+scripts
+htmlcov
+__pycache__
+.vagrant
+.pytest_cache
+.git
+.github
+.cache
+Vagrantfile
+.coverage
+.coveragerc
+.gitignore
+.travis.yml
+docker
diff --git a/Pipfile b/Pipfile
index bb59655..bce2f66 100644
--- a/Pipfile
+++ b/Pipfile
@@ -7,6 +7,11 @@ name = "pypi"
pika = "*"
[dev-packages]
+docker = "*"
+flask = "*"
+flask-sockets = "*"
+gevent = "==1.2.2"
+gevent-websocket = "*"
[requires]
python_version = "3.6"
@@ -14,5 +19,6 @@ python_version = "3.6"
[scripts]
consume = "python consume.py"
publish = "python publish.py"
-build = "docker build -t runner:latest -f docker/Dockerfile ."
-docker = "docker run --network=host runner"
+build = "docker build -t pythondiscord/snekbox:latest -f docker/Dockerfile ."
+compose = "docker-compose up"
+webapp = "PYTHONPATH=/vagrant/discord-python/snekbox python webapp/webapp.py"
diff --git a/Pipfile.lock b/Pipfile.lock
index 00a32d2..885f9c1 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
- "sha256": "7374d59c23f8adb4d87cd3533f6a7e8f95cc7d7e2e1f5bc1c9dcb49a02459bbd"
+ "sha256": "0a745b21e4db904bb3575c80d627ab80a3418bcb42e6e5c3695e914b88756114"
},
"pipfile-spec": 6,
"requires": {
@@ -25,5 +25,184 @@
"version": "==0.11.2"
}
},
- "develop": {}
+ "develop": {
+ "certifi": {
+ "hashes": [
+ "sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7",
+ "sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0"
+ ],
+ "version": "==2018.4.16"
+ },
+ "chardet": {
+ "hashes": [
+ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
+ "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
+ ],
+ "version": "==3.0.4"
+ },
+ "click": {
+ "hashes": [
+ "sha256:29f99fc6125fbc931b758dc053b3114e55c77a6e4c6c3a2674a2dc986016381d",
+ "sha256:f15516df478d5a56180fbf80e68f206010e6d160fc39fa508b65e035fd75130b"
+ ],
+ "version": "==6.7"
+ },
+ "docker": {
+ "hashes": [
+ "sha256:43b45b92bed372161a5d4f3c7137e16b30d93845e99a00bc727938e52850694e",
+ "sha256:dc5cc0971a0d36fe94c5ce89bd4adb6c892713500af7b0818708229c3199911a"
+ ],
+ "index": "pypi",
+ "version": "==3.3.0"
+ },
+ "docker-pycreds": {
+ "hashes": [
+ "sha256:764a7ea2f6484bc5de5bf0c060f08b41a1118cf1acb987626b3ff45f3cc40dac",
+ "sha256:e3732a03610a00461a716997670c7010bf1c214a3edc440f7d6a2a3a830ecd9d"
+ ],
+ "version": "==0.2.3"
+ },
+ "flask": {
+ "hashes": [
+ "sha256:2271c0070dbcb5275fad4a82e29f23ab92682dc45f9dfbc22c02ba9b9322ce48",
+ "sha256:a080b744b7e345ccfcbc77954861cb05b3c63786e93f2b3875e0913d44b43f05"
+ ],
+ "index": "pypi",
+ "version": "==1.0.2"
+ },
+ "flask-sockets": {
+ "hashes": [
+ "sha256:072927da8edca0e81e024f5787e643c87d80b351b714de95d723becb30e0643b",
+ "sha256:350a76d55f5889f64afd2ca9b32f262680b7960965f0830365576307d30cfe1e"
+ ],
+ "index": "pypi",
+ "version": "==0.2.1"
+ },
+ "gevent": {
+ "hashes": [
+ "sha256:0901975628790e8a57fc92bb7062e5b856edea48c8de9caf36cfda14eae07329",
+ "sha256:1af93825db5753550fa8ff5ab2f2132e8733170b3f8d38347b34fa4a984cb624",
+ "sha256:2ff045a91509c35664c27a849c8cbf742a227f587b7cdbc88301e9c85dcaedff",
+ "sha256:33fa6759eabc9176ddbe0d29b66867a82e19a61f06eb7cfabbac35343c0ecf24",
+ "sha256:35790f1a3c8e431ada3471b70bb2105050009ea4beb15cbe41b86bc716a7ffa9",
+ "sha256:4791c8ae9c57d6f153354736e1ccab1e2baf6c8d9ae5a77a9ac90f41e2966b2d",
+ "sha256:4f098002126ebef7f2907188b6c8b09e5193161ce968847d9e6a8bc832b0db9a",
+ "sha256:552719cec4721673b8c7d2f9de666e3f7591b9b182f801ecaef1c76e638052aa",
+ "sha256:59e9237af027f8db85e5d78a9da2e328ae96f01d67a0d62abcecad3db7876908",
+ "sha256:60109741377367eef8ded9283a1bf629621b73acaf3e1e8aac9d1a0f50fa0f05",
+ "sha256:6892fabc9051e8c0a171d543b6536859aabeb6d169db79b2f45d64dc2a15808c",
+ "sha256:70558dd45c7a1f8046ba45792e489dd0f409bd8a3b7a0635ca9d3055223b3dff",
+ "sha256:74bce0c30bb2240e3d5d515ba8cb3eadf840c2bde7109a1979c7a26c9d0f5a6a",
+ "sha256:7f93b67b680f4a921f517294048d05f8f6f0ed5962b78d6685a6cf0fcd7d8202",
+ "sha256:81cb24e0f7bd9888596364e8d8ed0d65c2547c84884c67bb46d956faeed67396",
+ "sha256:833bebdc36bfeeedefc200ca9aee9b8eddd80f56b63ca1e886e18b97b1240edd",
+ "sha256:8a710eddb3e9e5f22bdbd458b5f211b94f59409ecd6896f15b9fee2cba266a59",
+ "sha256:9b492bb1a043540abb6e54fdb5537531e24962ca49c09f3b47dc4f9c37f6297c",
+ "sha256:a0ed8ba787b9c0c1c565c2675d71652e6c1e2d4e91f53530860d0303e867fe85",
+ "sha256:a16db4f56699ef07f0249b953ff949aae641e50b2bdc4710f11c0d8d9089b296",
+ "sha256:a66cf99f08da65c501826a19e30f5a6e7ba942fdd79baba5ce2d51eebaa13444",
+ "sha256:b67a10799923f9fed546ca5f8b93a2819c71a60132d7a97b4a13fbdab66b278a",
+ "sha256:b7e0e6400c2f3ce78a9ae1cdd55b53166feedd003d60c033863881227129a4d3",
+ "sha256:c35b29de49211014ec66d056fd4f9ba7a04795e2a654697f72879c0cf365d6d4",
+ "sha256:c9dd6534c46ed782e2d7236767cd07115cb29ce8670c2fc0794f264de9024fe0",
+ "sha256:de13a8e378103af84a8bf6015ad1d2761d46f29b8393e8dd6d9bb7cb51bbb713",
+ "sha256:deafd70d04ab62428d4e291e8e2c0fb22f38690e6a9f23a67ee6c304087634da",
+ "sha256:df52e06a2754c2d905aad75a7dc06a732c804d9edbc87f06f47c8f483ba98bca",
+ "sha256:fce894a64db3911897cdad6c37fbb23dfb18b7bf8b9cb8c00a8ea0a7253651c9"
+ ],
+ "index": "pypi",
+ "version": "==1.2.2"
+ },
+ "gevent-websocket": {
+ "hashes": [
+ "sha256:17b67d91282f8f4c973eba0551183fc84f56f1c90c8f6b6b30256f31f66f5242",
+ "sha256:7eaef32968290c9121f7c35b973e2cc302ffb076d018c9068d2f5ca8b2d85fb0"
+ ],
+ "index": "pypi",
+ "version": "==0.10.1"
+ },
+ "greenlet": {
+ "hashes": [
+ "sha256:09ef2636ea35782364c830f07127d6c7a70542b178268714a9a9ba16318e7e8b",
+ "sha256:0fef83d43bf87a5196c91e73cb9772f945a4caaff91242766c5916d1dd1381e4",
+ "sha256:1b7df09c6598f5cfb40f843ade14ed1eb40596e75cd79b6fa2efc750ba01bb01",
+ "sha256:1fff21a2da5f9e03ddc5bd99131a6b8edf3d7f9d6bc29ba21784323d17806ed7",
+ "sha256:42118bf608e0288e35304b449a2d87e2ba77d1e373e8aa221ccdea073de026fa",
+ "sha256:50643fd6d54fd919f9a0a577c5f7b71f5d21f0959ab48767bd4bb73ae0839500",
+ "sha256:58798b5d30054bb4f6cf0f712f08e6092df23a718b69000786634a265e8911a9",
+ "sha256:5b49b3049697aeae17ef7bf21267e69972d9e04917658b4e788986ea5cc518e8",
+ "sha256:75c413551a436b462d5929255b6dc9c0c3c2b25cbeaee5271a56c7fda8ca49c0",
+ "sha256:769b740aeebd584cd59232be84fdcaf6270b8adc356596cdea5b2152c82caaac",
+ "sha256:ad2383d39f13534f3ca5c48fe1fc0975676846dc39c2cece78c0f1f9891418e0",
+ "sha256:b417bb7ff680d43e7bd7a13e2e08956fa6acb11fd432f74c97b7664f8bdb6ec1",
+ "sha256:b6ef0cabaf5a6ecb5ac122e689d25ba12433a90c7b067b12e5f28bdb7fb78254",
+ "sha256:c2de19c88bdb0366c976cc125dca1002ec1b346989d59524178adfd395e62421",
+ "sha256:c7b04a6dc74087b1598de8d713198de4718fa30ec6cbb84959b26426c198e041",
+ "sha256:f8f2a0ae8de0b49c7b5b2daca4f150fdd9c1173e854df2cce3b04123244f9f45",
+ "sha256:fcfadaf4bf68a27e5dc2f42cbb2f4b4ceea9f05d1d0b8f7787e640bed2801634"
+ ],
+ "version": "==0.4.13"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f",
+ "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4"
+ ],
+ "version": "==2.6"
+ },
+ "itsdangerous": {
+ "hashes": [
+ "sha256:cbb3fcf8d3e33df861709ecaf89d9e6629cff0a217bc2848f1b41cd30d360519"
+ ],
+ "version": "==0.24"
+ },
+ "jinja2": {
+ "hashes": [
+ "sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd",
+ "sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4"
+ ],
+ "version": "==2.10"
+ },
+ "markupsafe": {
+ "hashes": [
+ "sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665"
+ ],
+ "version": "==1.0"
+ },
+ "requests": {
+ "hashes": [
+ "sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b",
+ "sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e"
+ ],
+ "version": "==2.18.4"
+ },
+ "six": {
+ "hashes": [
+ "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9",
+ "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"
+ ],
+ "version": "==1.11.0"
+ },
+ "urllib3": {
+ "hashes": [
+ "sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b",
+ "sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f"
+ ],
+ "version": "==1.22"
+ },
+ "websocket-client": {
+ "hashes": [
+ "sha256:188b68b14fdb2d8eb1a111f21b9ffd2dbf1dbc4e4c1d28cf2c37cdbf1dd1cae6",
+ "sha256:a453dc4dfa6e0db3d8fd7738a308a88effe6240c59f3226eb93e8f020c216149"
+ ],
+ "version": "==0.47.0"
+ },
+ "werkzeug": {
+ "hashes": [
+ "sha256:c3fd7a7d41976d9f44db327260e263132466836cef6f91512889ed60ad26557c",
+ "sha256:d5da73735293558eb1651ee2fddc4d0dedcfa06538b8813a2e20011583c9e49b"
+ ],
+ "version": "==0.14.1"
+ }
+ }
}
diff --git a/README.md b/README.md
index 3fed9cf..37c904a 100644
--- a/README.md
+++ b/README.md
@@ -3,20 +3,20 @@ Python sandbox runners for executing code in isolation
# Dependencies
-| dep | version (or greater) |
-|--------|----------------------|
-| python | 3.6.5 |
-| pip | 10.0.1 |
-| pipenv | 2018.05.18 |
-| docker | 18.03.1-ce |
-
+| dep | version (or greater) |
+|----------------|:---------------------|
+| python | 3.6.5 |
+| pip | 10.0.1 |
+| pipenv | 2018.05.18 |
+| docker | 18.03.1-ce |
+| docker-compose | 1.21.2 |
## Setup local test
install python packages
```bash
-pipenv sync
+pipenv sync --dev
```
Start a rabbitmq instance and get the container IP
@@ -55,3 +55,23 @@ docker logs snekbox -f
#terminal 2
pipenv run python runner/publish.py
```
+
+## Docker compose
+
+Start both rabbitmq and a consumer with docker-compose
+
+```bash
+docker-compose up
+```
+
+## Try the webapp
+
+After getting docker-compose to run the rabbitmq server and the consumer
+
+try running the webapp in another terminal
+
+```bash
+pipenv run python webapp/webapp.py
+```
+
+and then open up the page: http://localhost:5000 (or whatever address it's running on)
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..11dad71
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,18 @@
+version: '3'
+services:
+ pdrmq:
+ hostname: "pdrmq"
+ image: rabbitmq:3.7.5-alpine
+ networks:
+ - sneknet
+
+ pdsnekbox:
+ hostname: "pdsnekbox"
+ image: pythondiscord/snekbox:latest
+ networks:
+ - sneknet
+ environment:
+ RMQ_HOST: pdrmq
+
+networks:
+ sneknet:
diff --git a/docker/Dockerfile b/docker/Dockerfile
index cbf1b49..47be8b1 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -7,15 +7,15 @@ ENV PIPENV_VENV_IN_PROJECT=1
ENV PIPENV_IGNORE_VIRTUALENVS=1
ENV PIPENV_NOSPIN=1
ENV PIPENV_HIDE_EMOJIS=1
-ENV PYTHONPATH=/runner
+ENV PYTHONPATH=/snekbox
RUN pip install pipenv
-RUN mkdir -p /runner
-COPY Pipfile /runner
-COPY Pipfile.lock /runner
-COPY runner /runner
-WORKDIR /runner
+RUN mkdir -p /snekbox
+COPY Pipfile /snekbox
+COPY Pipfile.lock /snekbox
+COPY snekbox /snekbox
+WORKDIR /snekbox
RUN pipenv sync
diff --git a/runner/consume.py b/runner/consume.py
deleted file mode 100644
index 0e4d79a..0000000
--- a/runner/consume.py
+++ /dev/null
@@ -1,68 +0,0 @@
-import pika
-import traceback
-import sys
-from io import StringIO
-
-from config import (
- USERNAME,
- PASSWORD,
- HOST,
- PORT,
- EXCHANGE,
- EXCHANGE_TYPE,
- QUEUE,
- ROUTING_KEY,
-)
-
-def execute(snippet):
- old_stdout = sys.stdout
- redirected_output = sys.stdout = StringIO()
- failed = False
- try:
- exec(snippet)
- except Exception as e:
- failed = e
- finally:
- sys.stdout = old_stdout
-
- if failed:
- return failed
- return redirected_output.getvalue()
-
-
-def message_handler(ch, method, properties, body):
- msg = body.decode('utf-8')
-
- # Execute code snippets here
- print(f"incoming: {msg}", flush=True)
- result = execute(msg)
- print(result, flush=True)
-
- ch.basic_ack(delivery_tag = method.delivery_tag)
-
-def rabbitmq_consume():
- credentials = pika.PlainCredentials(USERNAME, PASSWORD)
- connection = pika.BlockingConnection(pika.ConnectionParameters(HOST, PORT, '/', credentials))
-
- channel = connection.channel()
- channel.queue_declare(queue=QUEUE, durable=False)
- channel.basic_qos(prefetch_count=1)
- channel.basic_consume(message_handler, queue=QUEUE)
-
- try:
- print(f"""Connecting to
- host: {HOST}
- port: {PORT}
- exchange: {EXCHANGE}
- queue: {QUEUE}""", flush=True)
-
- channel.start_consuming()
-
- except Exception:
- exc = traceback.format_exc()
- print(exc, flush=True)
-
- finally:
- connection.close()
-
-rabbitmq_consume()
diff --git a/runner/config.py b/snekbox/config.py
index 75b3c28..d0bd4f6 100644
--- a/runner/config.py
+++ b/snekbox/config.py
@@ -1,6 +1,8 @@
+import os
+
USERNAME = 'guest'
PASSWORD = 'guest'
-HOST = '172.17.0.2'
+HOST = os.environ.get('RMQ_HOST', '172.17.0.2')
PORT = 5672
EXCHANGE = 'exchange'
EXCHANGE_TYPE = 'direct'
diff --git a/snekbox/consume.py b/snekbox/consume.py
new file mode 100644
index 0000000..d44a018
--- /dev/null
+++ b/snekbox/consume.py
@@ -0,0 +1,75 @@
+import traceback
+import sys
+import time
+import pika
+import io
+
+from pika.exceptions import ConnectionClosed
+
+from config import USERNAME
+from config import PASSWORD
+from config import HOST
+from config import PORT
+from config import EXCHANGE
+from config import QUEUE
+
+def execute(snippet):
+ old_stdout = sys.stdout
+ redirected_output = sys.stdout = io.StringIO()
+ failed = False
+ try:
+ exec(snippet)
+ except Exception as e:
+ failed = e
+ finally:
+ sys.stdout = old_stdout
+
+ if failed:
+ return failed
+ return redirected_output.getvalue()
+
+
+def message_handler(ch, method, properties, body):
+ msg = body.decode('utf-8')
+
+ # Execute code snippets here
+ print(f"incoming: {msg}", flush=True)
+ result = execute(msg)
+ print(result, flush=True)
+
+ ch.basic_ack(delivery_tag = method.delivery_tag)
+
+def rabbitmq_consume():
+
+ while True:
+ credentials = pika.PlainCredentials(USERNAME, PASSWORD)
+ con_params = pika.ConnectionParameters(HOST, PORT, '/', credentials)
+
+ try:
+ connection = pika.BlockingConnection(con_params)
+
+ try:
+ channel = connection.channel()
+ channel.queue_declare(queue=QUEUE, durable=False)
+ channel.basic_qos(prefetch_count=1)
+ channel.basic_consume(message_handler, queue=QUEUE)
+
+ print(f"""Connected to \nhost: {HOST}\nport: {PORT}\nexchange: {EXCHANGE}\nqueue: {QUEUE}""", flush=True)
+
+ channel.start_consuming()
+
+ except:
+ exc = traceback.format_exc()
+ print(exc, flush=True)
+
+ finally:
+ connection.close()
+
+ except ConnectionClosed:
+ print(f"Connection lost, reconnecting to {HOST}", flush=True)
+ pass
+
+ time.sleep(2)
+
+if __name__ == '__main__':
+ rabbitmq_consume()
diff --git a/runner/publish.py b/snekbox/publish.py
index fc18d03..0598976 100644
--- a/runner/publish.py
+++ b/snekbox/publish.py
@@ -1,14 +1,22 @@
import pika
-from config import (
- USERNAME,
- PASSWORD,
- HOST,
- PORT,
- EXCHANGE,
- EXCHANGE_TYPE,
- QUEUE,
- ROUTING_KEY,
-)
+from config import USERNAME
+from config import PASSWORD
+from config import HOST
+from config import PORT
+from config import EXCHANGE
+from config import EXCHANGE_TYPE
+from config import QUEUE
+from config import ROUTING_KEY
+
+try:
+ import docker
+ client = docker.from_env()
+ containers = client.containers.get('snekbox_pdrmq_1')
+ print("Attempting to get rabbitmq host automatically")
+ HOST = list(containers.attrs.get('NetworkSettings').get('Networks').values())[0]['IPAddress']
+ print(f"found {HOST}")
+except:
+ pass
def send(message):
credentials = pika.PlainCredentials(USERNAME, PASSWORD)
@@ -28,15 +36,11 @@ def send(message):
)
if result:
- print(f"""Connecting to
- host: {HOST}
- port: {PORT}
- exchange: {EXCHANGE}
- queue: {QUEUE}""", flush=True)
+ print(f"""Connecting to\nhost: {HOST}\nport: {PORT}\nexchange: {EXCHANGE}\nqueue: {QUEUE}""", flush=True)
print(f"Sent: '{message}'")
else:
print("not delivered")
connection.close()
-send('print "bacon is delicious"')
+#send('print("bacon is delicious")')
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..88ac396
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,6 @@
+[flake8]
+max-line-length=120
+application_import_names=snekbox
+ignore=P102,B311,W503,E226,S311
+exclude=__pycache__, venv, .venv, tests
+import-order-style=pycharm
diff --git a/webapp/rmq.py b/webapp/rmq.py
new file mode 100644
index 0000000..80d418a
--- /dev/null
+++ b/webapp/rmq.py
@@ -0,0 +1,48 @@
+import os
+import pika
+
+USERNAME = 'guest'
+PASSWORD = 'guest'
+HOST = os.environ.get('RMQ_HOST', '172.17.0.2')
+PORT = 5672
+EXCHANGE = 'exchange'
+EXCHANGE_TYPE = 'direct'
+QUEUE = 'text'
+ROUTING_KEY = 'bacon'
+
+try:
+ import docker
+ client = docker.from_env()
+ containers = client.containers.get('snekbox_pdrmq_1')
+ print("Attempting to get rabbitmq host automatically")
+ HOST = list(containers.attrs.get('NetworkSettings').get('Networks').values())[0]['IPAddress']
+ print(f"found {HOST}")
+except:
+ pass
+
+def send(message):
+ credentials = pika.PlainCredentials(USERNAME, PASSWORD)
+ connection = pika.BlockingConnection(pika.ConnectionParameters(HOST, PORT, '/', credentials))
+ properties = pika.BasicProperties(content_type='text/plain', delivery_mode=1)
+
+ channel = connection.channel()
+ channel.queue_declare(queue=QUEUE, durable=False)
+ channel.exchange_declare(exchange=EXCHANGE, exchange_type=EXCHANGE_TYPE)
+ channel.queue_bind(exchange=EXCHANGE, queue=QUEUE, routing_key=ROUTING_KEY)
+
+ result = channel.basic_publish(
+ exchange=EXCHANGE,
+ routing_key=ROUTING_KEY,
+ body=message,
+ properties=properties
+ )
+
+ if result:
+ print(f"""Connecting to\nhost: {HOST}\nport: {PORT}\nexchange: {EXCHANGE}\nqueue: {QUEUE}""", flush=True)
+ print(f"Sent: '{message}'")
+ else:
+ print("not delivered")
+
+ connection.close()
+
+#send('print("bacon is delicious")')
diff --git a/webapp/templates/index.html b/webapp/templates/index.html
new file mode 100644
index 0000000..f2213ff
--- /dev/null
+++ b/webapp/templates/index.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>WebSocket Test</title>
+<script language="javascript" type="text/javascript">
+
+var output;
+
+function init(){
+ output = document.getElementById("output");
+ testWebSocket();
+}
+
+function testWebSocket(){
+ var here = window.location.host;
+ var wsUri = `ws://${here}/ws`;
+ websocket = new WebSocket(wsUri);
+ websocket.onopen = function(evt) { onOpen(evt) };
+ websocket.onclose = function(evt) { onClose(evt) };
+ websocket.onmessage = function(evt) { onMessage(evt) };
+ websocket.onerror = function(evt) { onError(evt) };
+}
+
+function onOpen(evt){
+ writeToScreen("CONNECTED");
+}
+
+function onClose(evt){
+ writeToScreen("DISCONNECTED");
+}
+
+function onMessage(evt){
+ writeToScreen('<span style="color: blue;">RESPONSE: ' + evt.data+'</span>');
+ websocket.close();
+}
+
+function onError(evt){
+ writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
+}
+
+function sendMessage(message){
+ writeToScreen("SENT: " + message);
+ websocket.send(message);
+}
+
+function writeToScreen(message){
+ var pre = document.createElement("p");
+ pre.style.wordWrap = "break-word";
+ pre.innerHTML = message;
+ output.appendChild(pre);
+}
+
+function sendFromInput(){
+ var msg = document.getElementById("field1").value;
+ sendMessage(msg)
+}
+
+window.addEventListener("load", init, false);
+
+</script>
+
+<input type="text" id="field1" value="print('fsdf')"><br>
+<button onclick="sendFromInput()">Send</button>
+
+<div id="output"></div>
diff --git a/webapp/webapp.py b/webapp/webapp.py
new file mode 100644
index 0000000..676fc27
--- /dev/null
+++ b/webapp/webapp.py
@@ -0,0 +1,39 @@
+import traceback
+
+from rmq import send as rmq_send
+from flask import Flask
+from flask import render_template
+from flask_sockets import Sockets
+
+app = Flask(__name__)
+sockets = Sockets(app)
+
+def index():
+ return render_template('index.html')
+
+def websocket_route(ws):
+ try:
+ while not ws.closed:
+ message = ws.receive()
+
+ if not message:
+ continue
+ print(f"received '{message}'")
+
+ rmq_send(message)
+
+ except:
+ print(traceback.format_exec())
+
+ finally:
+ if not ws.closed:
+ ws.close()
+
+if __name__ == '__main__':
+ #app.run(host='0.0.0.0', port=5000, debug=True)
+ from gevent import pywsgi
+ from geventwebsocket.handler import WebSocketHandler
+ server = pywsgi.WSGIServer(('0.0.0.0', 5000), app, handler_class=WebSocketHandler)
+ server.serve_forever()