Permalink
Browse files

Merge branch 'release-1.1'

  • Loading branch information...
kyleconroy committed Jul 20, 2010
2 parents 201813b + ce26d91 commit a652bd611976cb7c51dd2284b3cec2930dc7be0d
Showing with 9,622 additions and 4,006 deletions.
  1. +19 −0 LICENSE
  2. +37 −0 README.md
  3. +19 −4 app.yaml
  4. +23 −8 config.py
  5. +93 −12 examples/stashboard.py
  6. +1 −1 { → examples}/widget/example.html
  7. 0 { → examples}/widget/output.html
  8. +64 −65 handlers/api.py
  9. +18 −3 handlers/restful.py
  10. +20 −11 handlers/site.py
  11. +15 −3 main.py
  12. +12 −83 markdown/restapi.markdown
  13. +62 −7 models.py
  14. +75 −0 runner.py
  15. BIN static/css/images/progress_bar.gif
  16. BIN static/css/images/ui-bg_glass_100_fdf5ce_1x400.png
  17. +59 −64 static/css/jqueryui.css
  18. +40 −12 static/css/style.css
  19. BIN static/favicon.ico
  20. BIN static/images/logo.png
  21. BIN static/images/poweredbystash.png
  22. BIN static/images/small-information.png
  23. +751 −0 static/js/common.js
  24. +0 −41 static/js/local-jquery-ui.js
  25. +0 −154 static/js/local-jquery.js
  26. +0 −98 static/js/stashboard.js
  27. +110 −0 static/widget/statusalert.js
  28. +51 −0 testing/install_data.py
  29. +119 −0 testing/qunit/qunit.css
  30. +1,089 −0 testing/qunit/qunit.js
  31. +9 −0 testing/setup.md
  32. +330 −0 testing/tests/services.js
  33. +0 −47 tests/install_data.py
  34. +0 −16 tests/unit_tests.py
  35. +9 −0 utils/external/dateutil/__init__.py
  36. +92 −0 utils/external/dateutil/easter.py
  37. +886 −0 utils/external/dateutil/parser.py
  38. +432 −0 utils/external/dateutil/relativedelta.py
  39. +1,097 −0 utils/external/dateutil/rrule.py
  40. +951 −0 utils/external/dateutil/tz.py
  41. +180 −0 utils/external/dateutil/tzwin.py
  42. +87 −0 utils/external/dateutil/zoneinfo/__init__.py
  43. BIN utils/external/dateutil/zoneinfo/zoneinfo-2010g.tar.gz
  44. +2,648 −2,628 utils/external/status_images.py
  45. +20 −0 utils/slugify.py
  46. +16 −126 views/default/_legend.html
  47. +29 −30 views/default/base.html
  48. +3 −2 views/default/basic/_legend.html
  49. +8 −5 views/default/basic/base.html
  50. +9 −6 views/default/basic/index.html
  51. +2 −4 views/default/basic/service.html
  52. +6 −1 views/default/documentation.html
  53. +2 −175 views/default/index.html
  54. +67 −197 views/default/restapi.html
  55. +62 −203 views/default/service.html
View
19 LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2010 Twilio Inc.
+
+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.
View
@@ -0,0 +1,37 @@
+# Stashboard
+
+## About
+
+Stashboard was written by Twilio to provide status information on our phone, SMS, and Communication APIs. We open sourced the code and to provide a generic status page designed to be customized by any hosted services company to provide customers up-to-date status information. The code can be downloaded, customized with your logo, and run on any Google App Engine account.
+
+## Installation
+
+First, install the App Engine SDK for Python.
+
+Next, download and extract Stashboard to your computer.
+
+### Run Locally
+
+Open the SDK, choose File > Add Existing Application..., select the stashboard folder you downloaded above and choose a port. Press Run and navigate to http://localhost:{port} to see your Stashboard installation.
+
+### Deploy to AppSpot
+
+Before you can deploy Stashboard, you will need to create an application on App Engine.
+
+Once your application is registered, open app.yaml in the Stashboard directory and change application-id to the name of your newly created application.
+
+Hit the 'Deploy' button, wait a couple of seconds, and then naviagate to http://{app-name}.appspot.com to enjoy your new status dashboard
+
+## Basic View
+
+By default, Stashboard exposes a rich client, utilizing AJAX and jQuery. If instead you just want a basic read only view, change the `rich_client` attribute to `False` in `config.py`.
+
+## REST API
+
+Full documentation of the REST API can be found at <http://stashboard.appspot.com/documentation/rest>
+
+## Future
+
+Future plans include RSS feeds, Web Hook integration, and a richer support for different status page views.
+
+
View
@@ -1,17 +1,32 @@
-application: ismywebservicedown
-version: 3
+application: stashboard
+version: 1
runtime: python
api_version: 1
+derived_file_type:
+- python_precompiled
+
handlers:
-- url: /static
- static_dir: static
+# URLS for testing
+#- url: /tests
+# static_dir: testing
+# login: required
+
+#- url: /runner
+# script: runner.py
+# login: required
+
+- url: /css
+ static_dir: static/css
- url: /images
static_dir: static/images
- url: /js
static_dir: static/js
+
+- url: /widget
+ static_dir: static/widget
- url: /favicon\.ico
static_files: static/favicon.ico
View
@@ -1,34 +1,49 @@
+# Copyright (c) 2010 Twilio Inc.
+#
+# 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.
+
import os
import logging
-# Stupid error
from google.appengine.dist import use_library
use_library('django', '1.1')
APP_ROOT_DIR = os.path.abspath(os.path.dirname(__file__))
#Stashboard version
-VERSION = "1.0.0"
+VERSION = "1.1.0"
# If we're debugging, turn the cache off, etc.
# Set to true if we want to have our webapp print stack traces, etc
DEBUG = os.environ['SERVER_SOFTWARE'].startswith('Dev')
logging.info("Starting application in DEBUG mode: %s", DEBUG)
-# Don't change default_blog or default_page to prevent conflicts when merging # Bloog source code updates.
-# Do change blog or page dictionaries at the bottom of this config module.
-
SITE = {
"html_type": "text/html",
"charset": "utf-8",
- "title": "Is My Webservice Down?",
+ "title": "Stashboard",
"author": "Kyle Conroy",
# This must be the email address of a registered administrator for the
# application due to mail api restrictions.
"email": "kyle.j.conroy@gmail.com",
"description": "A RESTful Status Tracker on top of App Engine.",
- "root_url": "http://ismywebservicedown.appspot.com",
- "master_atom_url": "/feeds/atom.xml",
+ "root_url": "http://stashboard.appspot.com",
"template_path": os.path.join(APP_ROOT_DIR, "views/default"),
"rich_client": True, #If false, the website will go into a simplified read-only view
}
View
@@ -1,7 +1,7 @@
import oauth2 as oauth
import json
import urllib
-from random import choice
+import unittest
oauth_key = '1/PGS5Fvp5hmtUTlHnLyWDVHc8mPrev6IGwa7kicolTT8'
oauth_secret = 'MnqTu_kS47zCs0p0xr9w3H02'
@@ -18,25 +18,107 @@
# Create our client.
client = oauth.Client(consumer, token=token)
-data = urllib.urlencode({
- "name": "An Example Service",
- "description": "An example service, created using the StashBoard API",
-})
+class ServicesTest(unittest.TestCase):
+
+ def testMissingServiceName(self):
+ "should return 400 Bad Data"
+ data = urllib.urlencode({
+ "description": "An example service API",
+ })
+
+ resp, content = client.request(base_url + "/services",
+ "POST", body=data)
+
+ self.assertEquals(resp.status, 400)
+
+ def testMissingServiceDescription(self):
+ "should return 400 Bad Data"
+ data = urllib.urlencode({
+ "name": "Some Random Name",
+ })
+
+ resp, content = client.request(base_url + "/services",
+ "POST", body=data)
+
+ self.assertEquals(resp.status, 400)
+
+ def testMissingServiceData(self):
+ "should return 400 Bad Data"
+ resp, content = client.request(base_url + "/services", "POST")
+ self.assertEquals(resp.status, 400)
+
+ def testDelete(self):
+ "should return 405 Method Not Allowed"
+ resp, content = client.request(base_url + "/services", "DELETE")
+ self.assertEquals(resp.status, 405)
+
+ def testPut(self):
+ "should return 411 Content Length Required"
+ resp, content = client.request(base_url + "/services", "PUT")
+ self.assertEquals(resp.status, 411)
+
+ def testPutWithData(self):
+ "should return 405 Method Not Allowed"
+ data = urllib.urlencode({
+ "name": "Some Random Name",
+ })
+ resp, content = client.request(base_url + "/services",
+ "PUT", body=data)
+ self.assertEquals(resp.status, 405)
+
+ def testServiceLifeCycle(self):
+ "should return 200 and a newly created status"
+ data = urllib.urlencode({
+ "name": "What a service",
+ "description": "An example service API",
+ })
+
+ resp, content = client.request(base_url + "/services", "POST", body=data)
+ service = json.loads(content)
+
+ self.assertEquals(resp.status, 200)
+ self.assertEquals(service["name"], "What a service")
+ self.assertEquals(service["description"], "An example service API")
+
+ resp, content = client.request(base_url + "/services/" + service["id"], "GET")
+ service = json.loads(content)
+
+ self.assertEquals(resp.status, 200)
+ self.assertEquals(service["name"], "What a service")
+ self.assertEquals(service["description"], "An example service API")
+
+ # Update service
+ data = urllib.urlencode({
+ "description": "An example service API woohoo",
+ })
+
+ resp, content = client.request(base_url + "/services/" + service["id"],
+ "POST", body=data)
+ service = json.loads(content)
+
+ self.assertEquals(resp.status, 200)
+ self.assertEquals(service["name"], "What a service")
+ self.assertEquals(service["description"], "An example service API woohoo")
+
+ # Delete service
+ resp, content = client.request(base_url + "/services/" + service["id"],
+ "DELETE")
+ service = json.loads(content)
-# The OAuth Client request works just like httplib2 for the most part.
+ self.assertEquals(resp.status, 200)
+ self.assertEquals(service["name"], "What a service")
+ self.assertEquals(service["description"], "An example service API woohoo")
-# POST to the Services Resource to create a new service. Save the response for
-# later
-resp, content = client.request(base_url + "/services", "POST", body=data)
-service = json.loads(content)
+if __name__ == '__main__':
+ unittest.main()
# GET the list of possible status images
resp, content = client.request(base_url + "/status-images", "GET")
data = json.loads(content)
images = data["images"]
# Pick a random image for our status
-image = choice(images)
+image = images[0]
# POST to the Statuses Resources to create a new Status
data = urllib.urlencode({
@@ -58,4 +140,3 @@
resp, content = client.request(service["url"] + "/events", "POST", body=data)
event = json.loads(content)
-print event
@@ -3,7 +3,7 @@
<head>
<title>HellO!</title>
- <script type="text/javascript" src="http://localhost:8080/js/stashboard.js"></script>
+ <script type="text/javascript" src="../static/js/stashboard.js"></script>
</head>
<body>
</body>
File renamed without changes.
Oops, something went wrong.

0 comments on commit a652bd6

Please sign in to comment.