summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOwen Jacobson <owen@grimoire.ca>2017-10-11 19:39:04 -0400
committerOwen Jacobson <owen@grimoire.ca>2017-10-11 19:39:56 -0400
commit49fda3601248d939b0cfff1bff5a18800e498bdc (patch)
treede97903cdb154a9ba11d8d2b603c2b90c45aa8a0
The HTML is kind of jank
-rw-r--r--.gitignore2
-rw-r--r--LICENSE.md21
-rw-r--r--Procfile1
-rw-r--r--app.py37
-rwxr-xr-xbin/web67
-rw-r--r--requirements.txt18
-rw-r--r--runtime.txt1
-rw-r--r--templates/index.html37
-rw-r--r--tests.py10
-rw-r--r--things-to-check.yml35
10 files changed, 229 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..4df23a4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+/.venv/
+*.pyc
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000..7ac9dc8
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,21 @@
+Copyright (c) 2017 the authors. Please see the Git history, or contact
+agora-discussion@agoranomic.org for information about the authorship of this
+project.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/Procfile b/Procfile
new file mode 100644
index 0000000..bb58ffb
--- /dev/null
+++ b/Procfile
@@ -0,0 +1 @@
+web: bin/web
diff --git a/app.py b/app.py
new file mode 100644
index 0000000..05a41bd
--- /dev/null
+++ b/app.py
@@ -0,0 +1,37 @@
+from apistar import Include, Route, annotate, render_template
+from apistar.frameworks.wsgi import WSGIApp as App
+from apistar.handlers import docs_urls, static_urls
+from apistar.renderers import HTMLRenderer
+import random
+import yaml
+
+with open('things-to-check.yml', 'r') as things_file:
+ things = yaml.safe_load(things_file)
+
+@annotate(renderers=[HTMLRenderer()])
+def random_thing(item: int = None):
+ if item is None:
+ item = random.randrange(len(things))
+ return render_template('index.html',
+ item=item,
+ thing=things[item],
+ )
+
+
+routes = [
+ Route('/', 'GET', random_thing),
+ Include('/docs', docs_urls),
+ Include('/static', static_urls),
+]
+
+settings = {
+ 'TEMPLATES': {
+ 'ROOT_DIR': 'templates', # Include the 'templates/' directory.
+ 'PACKAGE_DIRS': ['apistar'] # Include the built-in apistar templates.
+ }
+}
+
+app = App(
+ routes=routes,
+ settings=settings,
+)
diff --git a/bin/web b/bin/web
new file mode 100755
index 0000000..3d96f71
--- /dev/null
+++ b/bin/web
@@ -0,0 +1,67 @@
+#!/bin/bash -e
+
+# See "Running in Production" in the API Star documentation at
+# <https://github.com/encode/apistar#running-in-production>
+
+# In development, gunicorn can automatically reload code as you edit it. To
+# enable this feature, export `GUNICORN_CMD_ARGS='--reload'` before running
+# this script.
+#
+# See:
+# * <http://docs.gunicorn.org/en/stable/settings.html>
+# * <http://docs.gunicorn.org/en/stable/settings.html#reload>
+
+# If the `PORT` environment variable is set, we're probably running on a
+# platform like Heroku that expects the application to bind to it. Otherwise,
+# default to port 5000. gunicorn will print the value on startup either way,
+# allowing administrators and developers to determine the server's base URL.
+#
+# See:
+# * <https://devcenter.heroku.com/articles/runtime-principles#web-servers>
+# * <https://devcenter.heroku.com/articles/dynos#web-dynos>
+
+PORT=${PORT:-5000}
+
+# Run the application with gunicorn. Note that the API Star documentation
+# recommends setting `--workers`. We omit this option: on our target platform,
+# this is controlled automatically using the `WEB_CONCURRENCY` environment
+# variable, which has a computed default based on the resources available at
+# runtime. Falling back to gunicorn's default configuration is safe enough, as
+# an administrator who discovers this is the wrong configuration can easily set
+# `WEB_CONCURRENCY` to override it.
+#
+# See:
+# * <https://devcenter.heroku.com/articles/python-gunicorn#basic-configuration>
+# * <http://docs.gunicorn.org/en/stable/settings.html#workers>
+#
+# The API Star documentation also recommends the Meinheld worker type. However,
+# deploying Meinheld to Heroku causes the application to fail on startup:
+#
+# Error: class uri 'meinheld.gmeinheld.MeinheldWorker' invalid or not found:
+# [Traceback (most recent call last):
+# File "/app/.heroku/python/lib/python3.6/site-packages/gunicorn/util.py", line 134, in load_class
+# File "/app/.heroku/python/lib/python3.6/importlib/__init__.py", line 126, in import_module
+# mod = import_module('.'.join(components))
+# return _bootstrap._gcd_import(name[level:], package, level)
+# File "<frozen importlib._bootstrap>", line 978, in _gcd_import
+# File "<frozen importlib._bootstrap>", line 936, in _find_and_load_unlocked
+# File "<frozen importlib._bootstrap>", line 961, in _find_and_load
+# File "<frozen importlib._bootstrap>", line 205, in _call_with_frames_removed
+# File "<frozen importlib._bootstrap>", line 950, in _find_and_load_unlocked
+# File "<frozen importlib._bootstrap>", line 655, in _load_unlocked
+# File "<frozen importlib._bootstrap>", line 205, in _call_with_frames_removed
+# File "<frozen importlib._bootstrap_external>", line 678, in exec_module
+# File "/app/.heroku/python/lib/python3.6/site-packages/meinheld/__init__.py", line 1, in <module>
+# from meinheld.server import *
+# File "<frozen importlib._bootstrap>", line 978, in _gcd_import
+# File "<frozen importlib._bootstrap>", line 961, in _find_and_load
+# ImportError: libpython3.6m.so.1.0: cannot open shared object file: No such file or directory
+# ]
+#
+# The `libpython3.6m.so` library does not appear to be present. As we don't need
+# to squeeze every ounce of performance out of this application, I've removed
+# the Meinheld worker and opened a support ticket to get an explanation from
+# Heroku.
+
+exec gunicorn app:app \
+ --bind="0.0.0.0:${PORT}"
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..ce5bb01
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,18 @@
+apistar==0.3.9
+certifi==2017.7.27.1
+chardet==3.0.4
+coreapi==2.3.3
+coreschema==0.0.4
+gunicorn==19.7.1
+idna==2.6
+itypes==1.1.0
+Jinja2==2.9.6
+MarkupSafe==1.0
+py==1.4.34
+pytest==3.2.3
+PyYAML==3.12
+requests==2.18.4
+uritemplate==3.0.0
+urllib3==1.22
+Werkzeug==0.12.2
+whitenoise==3.3.1
diff --git a/runtime.txt b/runtime.txt
new file mode 100644
index 0000000..cfa5aa5
--- /dev/null
+++ b/runtime.txt
@@ -0,0 +1 @@
+python-3.6.2
diff --git a/templates/index.html b/templates/index.html
new file mode 100644
index 0000000..a827efe
--- /dev/null
+++ b/templates/index.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Have you checked {{ thing }}?</title>
+ <style>
+ body {
+ background: #dddde7;
+ font-color: #888;
+ font-family: Helvetica, sans-serif;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ height: 100%;
+ }
+
+ section {
+ width: 600px;
+ margin: auto;
+ }
+
+ p {
+ font-size: 24px;
+ }
+
+ a {
+ text-decoration: none;
+ }
+ </style>
+</head>
+<body>
+ <section>
+ <p>Have you checked {{ thing }}?</p>
+ <p><a href="">That wasn't it, suggest something else.</a></p>
+ <p><a href="?item={{ item }}">Share this troubleshooting suggestion.</a></p>
+ </section>
+</body>
+</html>
diff --git a/tests.py b/tests.py
new file mode 100644
index 0000000..9d52baa
--- /dev/null
+++ b/tests.py
@@ -0,0 +1,10 @@
+from apistar.test import TestClient
+from app import app, welcome
+
+
+def test_welcome():
+ """
+ Testing a view directly.
+ """
+ data = welcome()
+ assert data == {'message': 'Welcome to API Star!'}
diff --git a/things-to-check.yml b/things-to-check.yml
new file mode 100644
index 0000000..29ecb37
--- /dev/null
+++ b/things-to-check.yml
@@ -0,0 +1,35 @@
+---
+# Insert new items at the bottom. The index into this list is the item's
+# permalink.
+#
+# Yes, this is HTML and no, I don't care about injection.
+- permissions
+- cabling
+- for a full disk
+- the cache
+- for a version conflict
+- for a duplex mismatch
+- the firewall rules
+- <code>resolv.conf</code>
+- <code>/etc/hosts</code>
+- DNS
+- <code>CR/LF</code>
+- setuid/setgid bits
+- the default gateway
+- for IP conflicts
+- the logs
+- the port number
+- for a zonefile dot
+- I/O dammit
+- the mounts
+- the power
+- for the wrong whitespace
+- if it reloaded into bad config
+- IP forwarding
+- the trailing slash
+- the MAC address
+- if the filesystem is out of inodes
+- the line length
+- if you're on the wrong wifi network
+- if the vpn timed out
+- if that's the wrong host