heroku-api 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. data/.gitignore +4 -0
  2. data/.travis.yml +14 -0
  3. data/Gemfile +4 -0
  4. data/README.md +120 -0
  5. data/Rakefile +23 -0
  6. data/changelog.txt +4 -0
  7. data/heroku-api.gemspec +23 -0
  8. data/lib/heroku-api.rb +1 -0
  9. data/lib/heroku/api.rb +85 -0
  10. data/lib/heroku/api/addons.rb +47 -0
  11. data/lib/heroku/api/apps.rb +62 -0
  12. data/lib/heroku/api/collaborators.rb +33 -0
  13. data/lib/heroku/api/config_vars.rb +33 -0
  14. data/lib/heroku/api/domains.rb +33 -0
  15. data/lib/heroku/api/errors.rb +9 -0
  16. data/lib/heroku/api/keys.rb +42 -0
  17. data/lib/heroku/api/logs.rb +18 -0
  18. data/lib/heroku/api/mock.rb +176 -0
  19. data/lib/heroku/api/mock/addons.rb +153 -0
  20. data/lib/heroku/api/mock/apps.rb +184 -0
  21. data/lib/heroku/api/mock/cache/get_addons.json +1 -0
  22. data/lib/heroku/api/mock/collaborators.rb +55 -0
  23. data/lib/heroku/api/mock/config_vars.rb +46 -0
  24. data/lib/heroku/api/mock/domains.rb +71 -0
  25. data/lib/heroku/api/mock/keys.rb +46 -0
  26. data/lib/heroku/api/mock/logs.rb +20 -0
  27. data/lib/heroku/api/mock/processes.rb +191 -0
  28. data/lib/heroku/api/mock/releases.rb +124 -0
  29. data/lib/heroku/api/mock/stacks.rb +84 -0
  30. data/lib/heroku/api/processes.rb +77 -0
  31. data/lib/heroku/api/releases.rb +33 -0
  32. data/lib/heroku/api/stacks.rb +22 -0
  33. data/lib/heroku/api/vendor/okjson.rb +559 -0
  34. data/lib/heroku/api/version.rb +5 -0
  35. data/test/test_addons.rb +169 -0
  36. data/test/test_apps.rb +119 -0
  37. data/test/test_collaborators.rb +73 -0
  38. data/test/test_config_vars.rb +54 -0
  39. data/test/test_domains.rb +63 -0
  40. data/test/test_helper.rb +35 -0
  41. data/test/test_keys.rb +39 -0
  42. data/test/test_logs.rb +20 -0
  43. data/test/test_processes.rb +245 -0
  44. data/test/test_releases.rb +91 -0
  45. data/test/test_stacks.rb +49 -0
  46. metadata +134 -0
@@ -0,0 +1 @@
1
+ [{"price_unit":"month","url":"https://addons.heroku.com/addons/logentries:test","state":"beta","beta":false,"name":"logentries:test","id":"https://addons.heroku.com/addons/logentries:test","description":"Logentries Test","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/pgbackups:auto-year","state":"beta","beta":false,"name":"pgbackups:auto-year","id":"https://addons.heroku.com/addons/pgbackups:auto-year","description":"PG Backups Auto - One Year Retention","price_cents":10000},{"state":"public","url":null,"beta":false,"name":"shared-database:5mb","description":"Shared Database 5MB"},{"price_unit":"month","url":"https://addons.heroku.com/addons/sendgrid:platinum","state":"public","beta":false,"name":"sendgrid:platinum","id":"https://addons.heroku.com/addons/sendgrid:platinum","description":"SendGrid Platinum","price_cents":39995},{"price_unit":"month","url":"https://addons.heroku.com/addons/redistogo:medium","state":"public","beta":false,"name":"redistogo:medium","id":"https://addons.heroku.com/addons/redistogo:medium","description":"Redis To Go Medium","price_cents":11000},{"price_unit":"month","url":"https://addons.heroku.com/addons/justonedb:lambda","state":"public","beta":false,"name":"justonedb:lambda","id":"https://addons.heroku.com/addons/justonedb:lambda","description":"JustOneDB - NewSQL Cloud Database Lambda","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/zerigo_dns:basic","state":"public","beta":false,"name":"zerigo_dns:basic","id":"https://addons.heroku.com/addons/zerigo_dns:basic","description":"Zerigo DNS Zerigo Basic","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/mongolab:starter","state":"public","beta":false,"name":"mongolab:starter","id":"https://addons.heroku.com/addons/mongolab:starter","description":"MongoLab Starter","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/moonshadosms:max","state":"public","beta":false,"name":"moonshadosms:max","id":"https://addons.heroku.com/addons/moonshadosms:max","description":"Moonshado SMS Max","price_cents":35000},{"price_unit":"month","url":"https://addons.heroku.com/addons/heroku-postgresql:mecha","state":"public","beta":false,"name":"heroku-postgresql:mecha","id":"https://addons.heroku.com/addons/heroku-postgresql:mecha","description":"Heroku Postgres Mecha","price_cents":640000},{"price_unit":"month","url":"https://addons.heroku.com/addons/flying_sphinx:ceramic","state":"public","beta":false,"name":"flying_sphinx:ceramic","id":"https://addons.heroku.com/addons/flying_sphinx:ceramic","description":"Flying Sphinx Ceramic","price_cents":5500},{"price_unit":"month","url":"https://addons.heroku.com/addons/loggly:capybara","state":"public","beta":false,"name":"loggly:capybara","id":"https://addons.heroku.com/addons/loggly:capybara","description":"Loggly Capybara","price_cents":59900},{"price_unit":"month","url":"https://addons.heroku.com/addons/cloudant:oxygen","state":"public","beta":false,"name":"cloudant:oxygen","id":"https://addons.heroku.com/addons/cloudant:oxygen","description":"Cloudant Oxygen","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/rabbitmq:test","state":"beta","beta":false,"name":"rabbitmq:test","id":"https://addons.heroku.com/addons/rabbitmq:test","description":"RabbitMQ Test","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/statsmix:basic","state":"public","beta":false,"name":"statsmix:basic","id":"https://addons.heroku.com/addons/statsmix:basic","description":"StatsMix Basic","price_cents":1900},{"price_unit":"month","url":"https://addons.heroku.com/addons/moonshadosms:plus","state":"public","beta":false,"name":"moonshadosms:plus","id":"https://addons.heroku.com/addons/moonshadosms:plus","description":"Moonshado SMS Plus","price_cents":2000},{"price_unit":"month","url":"https://addons.heroku.com/addons/justonedb:double_charmed_xi","state":"public","beta":false,"name":"justonedb:double_charmed_xi","id":"https://addons.heroku.com/addons/justonedb:double_charmed_xi","description":"JustOneDB - NewSQL Cloud Database Double Charmed Xi","price_cents":49900},{"price_unit":"month","url":"https://addons.heroku.com/addons/custom_domains:basic","state":"public","beta":false,"name":"custom_domains:basic","id":"https://addons.heroku.com/addons/custom_domains:basic","description":"Custom Domains Custom Domain","price_cents":0},{"state":"public","url":null,"beta":false,"name":"flying_sphinx:marble","description":"Flying Sphinx Marble"},{"price_unit":"month","url":"https://addons.heroku.com/addons/justonedb:charmed_xi","state":"public","beta":false,"name":"justonedb:charmed_xi","id":"https://addons.heroku.com/addons/justonedb:charmed_xi","description":"JustOneDB - NewSQL Cloud Database Charmed Xi","price_cents":34900},{"price_unit":"month","url":"https://addons.heroku.com/addons/hoptoad:plus","state":"public","beta":false,"name":"hoptoad:plus","id":"https://addons.heroku.com/addons/hoptoad:plus","description":"Airbrake Plus","price_cents":700},{"state":"public","url":null,"beta":false,"name":"newrelic:silver","description":"New Relic RPM Silver"},{"price_unit":"month","url":"https://addons.heroku.com/addons/mwiki:test","state":"beta","beta":false,"name":"mwiki:test","id":"https://addons.heroku.com/addons/mwiki:test","description":"mWiki Test","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/zencoder:dev","state":"public","beta":false,"name":"zencoder:dev","id":"https://addons.heroku.com/addons/zencoder:dev","description":"Zencoder Developer","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/treasure-data:test","state":"public","beta":true,"name":"treasure-data:test","id":"https://addons.heroku.com/addons/treasure-data:test","description":"Treasure Data Hadoop Test","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/stackmob:gold","state":"public","beta":false,"name":"stackmob:gold","id":"https://addons.heroku.com/addons/stackmob:gold","description":"Stackmob Gold","price_cents":8900},{"price_unit":"month","url":"https://addons.heroku.com/addons/moonshadosms:free","state":"public","beta":false,"name":"moonshadosms:free","id":"https://addons.heroku.com/addons/moonshadosms:free","description":"Moonshado SMS Free","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/memcache:5mb","state":"public","beta":false,"name":"memcache:5mb","id":"https://addons.heroku.com/addons/memcache:5mb","description":"Memcache 5 MB","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/dbinsights:basic","state":"public","beta":false,"name":"dbinsights:basic","id":"https://addons.heroku.com/addons/dbinsights:basic","description":"DbInsights Basic","price_cents":2000},{"price_unit":"month","url":"https://addons.heroku.com/addons/iron_worker:venti","state":"public","beta":false,"name":"iron_worker:venti","id":"https://addons.heroku.com/addons/iron_worker:venti","description":"IronWorker Venti","price_cents":10800},{"price_unit":"month","url":"https://addons.heroku.com/addons/hoptoad:basic","state":"public","beta":false,"name":"hoptoad:basic","id":"https://addons.heroku.com/addons/hoptoad:basic","description":"Airbrake Basic","price_cents":200},{"price_unit":"month","url":"https://addons.heroku.com/addons/flying_sphinx:granite","state":"public","beta":false,"name":"flying_sphinx:granite","id":"https://addons.heroku.com/addons/flying_sphinx:granite","description":"Flying Sphinx Granite","price_cents":15000},{"price_unit":"month","url":"https://addons.heroku.com/addons/iron_mq:cast","state":"public","beta":false,"name":"iron_mq:cast","id":"https://addons.heroku.com/addons/iron_mq:cast","description":"IronMQ Cast","price_cents":4999},{"price_unit":"month","url":"https://addons.heroku.com/addons/zencoder:20k","state":"public","beta":false,"name":"zencoder:20k","id":"https://addons.heroku.com/addons/zencoder:20k","description":"Zencoder 20,000 Minutes","price_cents":60000},{"price_unit":"month","url":"https://addons.heroku.com/addons/tddium:standard","state":"public","beta":false,"name":"tddium:standard","id":"https://addons.heroku.com/addons/tddium:standard","description":"Tddium Standard","price_cents":5000},{"price_unit":"month","url":"https://addons.heroku.com/addons/rhoconnect:basic","state":"public","beta":false,"name":"rhoconnect:basic","id":"https://addons.heroku.com/addons/rhoconnect:basic","description":"RhoConnect Basic","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/pandastream:sandbox","state":"public","beta":false,"name":"pandastream:sandbox","id":"https://addons.heroku.com/addons/pandastream:sandbox","description":"Panda Stream Sandbox","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/memcache:250mb","state":"public","beta":false,"name":"memcache:250mb","id":"https://addons.heroku.com/addons/memcache:250mb","description":"Memcache 250 MB","price_cents":4000},{"price_unit":"month","url":"https://addons.heroku.com/addons/justonedb:xi","state":"public","beta":false,"name":"justonedb:xi","id":"https://addons.heroku.com/addons/justonedb:xi","description":"JustOneDB - NewSQL Cloud Database Xi","price_cents":19900},{"price_unit":"month","url":"https://addons.heroku.com/addons/cron:daily","state":"public","beta":false,"name":"cron:daily","id":"https://addons.heroku.com/addons/cron:daily","description":"Cron Daily Cron","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/tripwire:test","state":"beta","beta":false,"name":"tripwire:test","id":"https://addons.heroku.com/addons/tripwire:test","description":"Tripwire Test","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/zencoder:1k","state":"public","beta":false,"name":"zencoder:1k","id":"https://addons.heroku.com/addons/zencoder:1k","description":"Zencoder 1,000 Minutes","price_cents":4000},{"state":"public","url":null,"beta":false,"name":"simple_worker:grande","description":"Appoxy SimpleWorker Grande"},{"price_unit":"month","url":"https://addons.heroku.com/addons/pusher:bootstrap","state":"public","beta":false,"name":"pusher:bootstrap","id":"https://addons.heroku.com/addons/pusher:bootstrap","description":"Pusher Bootstrap","price_cents":1900},{"price_unit":"month","url":"https://addons.heroku.com/addons/pandastream:quad","state":"public","beta":false,"name":"pandastream:quad","id":"https://addons.heroku.com/addons/pandastream:quad","description":"Panda Stream Quad","price_cents":39600},{"state":"public","url":"https://addons.heroku.com/bundles","beta":false,"name":"bundles:single","description":"Single Bundle"},{"price_unit":"month","url":"https://addons.heroku.com/addons/memcache:10gb","state":"pass_only","beta":false,"name":"memcache:10gb","id":"https://addons.heroku.com/addons/memcache:10gb","description":"Memcache 10 GB","price_cents":80000},{"price_unit":"month","url":"https://addons.heroku.com/addons/moonshadosms:basic","state":"public","beta":false,"name":"moonshadosms:basic","id":"https://addons.heroku.com/addons/moonshadosms:basic","description":"Moonshado SMS Basic","price_cents":500},{"price_unit":"month","url":"https://addons.heroku.com/addons/loggly:beaver","state":"public","beta":false,"name":"loggly:beaver","id":"https://addons.heroku.com/addons/loggly:beaver","description":"Loggly Beaver","price_cents":29900},{"price_unit":"month","url":"https://addons.heroku.com/addons/cleardb:drift","state":"public","beta":false,"name":"cleardb:drift","id":"https://addons.heroku.com/addons/cleardb:drift","description":"ClearDB MySQL Database Drift","price_cents":4999},{"price_unit":"month","url":"https://addons.heroku.com/addons/custom_error_pages","state":"public","beta":true,"name":"custom_error_pages","id":"https://addons.heroku.com/addons/custom_error_pages","description":"Custom Error Pages Custom Error Pages","price_cents":10000},{"price_unit":"month","url":"https://addons.heroku.com/addons/zencoder:40k","state":"public","beta":false,"name":"zencoder:40k","id":"https://addons.heroku.com/addons/zencoder:40k","description":"Zencoder 40,000 Minutes","price_cents":120000},{"price_unit":"month","url":"https://addons.heroku.com/addons/zencoder:4k","state":"public","beta":false,"name":"zencoder:4k","id":"https://addons.heroku.com/addons/zencoder:4k","description":"Zencoder 4,000 Minutes","price_cents":12000},{"price_unit":"month","url":"https://addons.heroku.com/addons/websolr:palladium","state":"public","beta":false,"name":"websolr:palladium","id":"https://addons.heroku.com/addons/websolr:palladium","description":"Websolr Palladium","price_cents":20000},{"state":"public","url":null,"beta":false,"name":"simple_worker:tall","description":"Appoxy SimpleWorker Tall"},{"price_unit":"month","url":"https://addons.heroku.com/addons/sendgrid:bronze","state":"public","beta":false,"name":"sendgrid:bronze","id":"https://addons.heroku.com/addons/sendgrid:bronze","description":"SendGrid Bronze","price_cents":995},{"price_unit":"month","url":"https://addons.heroku.com/addons/newrelic:standard","state":"public","beta":false,"name":"newrelic:standard","id":"https://addons.heroku.com/addons/newrelic:standard","description":"New Relic Standard","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/iron_worker:grande","state":"public","beta":false,"name":"iron_worker:grande","id":"https://addons.heroku.com/addons/iron_worker:grande","description":"IronWorker Grande","price_cents":7200},{"price_unit":"month","url":"https://addons.heroku.com/addons/deployhooks:basecamp","state":"public","beta":false,"name":"deployhooks:basecamp","id":"https://addons.heroku.com/addons/deployhooks:basecamp","description":"Deploy Hooks Basecamp Hook","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/statsmix:developer","state":"public","beta":false,"name":"statsmix:developer","id":"https://addons.heroku.com/addons/statsmix:developer","description":"StatsMix Developer","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/custom_domains:wildcard","state":"public","beta":false,"name":"custom_domains:wildcard","id":"https://addons.heroku.com/addons/custom_domains:wildcard","description":"Custom Domains Wildcard domains","price_cents":500},{"price_unit":"month","url":"https://addons.heroku.com/addons/releases:advanced","state":"beta","beta":false,"name":"releases:advanced","id":"https://addons.heroku.com/addons/releases:advanced","description":"Release Management Advanced","price_cents":10000},{"price_unit":"month","url":"https://addons.heroku.com/addons/pubnub:popular","state":"public","beta":false,"name":"pubnub:popular","id":"https://addons.heroku.com/addons/pubnub:popular","description":"PubNub Popular","price_cents":24999},{"price_unit":"month","url":"https://addons.heroku.com/addons/cloudmailin:professional","state":"public","beta":false,"name":"cloudmailin:professional","id":"https://addons.heroku.com/addons/cloudmailin:professional","description":"CloudMailIn Professional","price_cents":4500},{"state":"public","url":null,"beta":false,"name":"legacy-database:ronin","description":"Legacy Database Ronin"},{"state":"public","url":null,"beta":false,"name":"legacy-database:fugu","description":"Legacy Database Fugu"},{"price_unit":"month","url":"https://addons.heroku.com/addons/logging:expanded","state":"public","beta":false,"name":"logging:expanded","id":"https://addons.heroku.com/addons/logging:expanded","description":"Logging Expanded","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/restful_metrics:test","state":"public","beta":true,"name":"restful_metrics:test","id":"https://addons.heroku.com/addons/restful_metrics:test","description":"RESTful Metrics Test","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/logging:advanced","state":"public","beta":false,"name":"logging:advanced","id":"https://addons.heroku.com/addons/logging:advanced","description":"Logging Advanced","price_cents":10000},{"price_unit":"month","url":"https://addons.heroku.com/addons/zerigo_dns:tier1","state":"public","beta":false,"name":"zerigo_dns:tier1","id":"https://addons.heroku.com/addons/zerigo_dns:tier1","description":"Zerigo DNS Zerigo Tier 1","price_cents":700},{"price_unit":"month","url":"https://addons.heroku.com/addons/ssl:sni","state":"public","beta":false,"name":"ssl:sni","id":"https://addons.heroku.com/addons/ssl:sni","description":"SSL SNI SSL","price_cents":500},{"price_unit":"month","url":"https://addons.heroku.com/addons/cloudmailin:microplus","state":"public","beta":false,"name":"cloudmailin:microplus","id":"https://addons.heroku.com/addons/cloudmailin:microplus","description":"CloudMailIn Micro Plus","price_cents":1700},{"price_unit":"month","url":"https://addons.heroku.com/addons/rhoconnect:enterprise","state":"public","beta":false,"name":"rhoconnect:enterprise","id":"https://addons.heroku.com/addons/rhoconnect:enterprise","description":"RhoConnect Enterprise","price_cents":49900},{"price_unit":"month","url":"https://addons.heroku.com/addons/redistogo:small","state":"public","beta":false,"name":"redistogo:small","id":"https://addons.heroku.com/addons/redistogo:small","description":"Redis To Go Small","price_cents":2500},{"price_unit":"month","url":"https://addons.heroku.com/addons/mailgun:basic","state":"public","beta":false,"name":"mailgun:basic","id":"https://addons.heroku.com/addons/mailgun:basic","description":"Mailgun Basic","price_cents":1900},{"price_unit":"month","url":"https://addons.heroku.com/addons/zerigo_dns:tier2","state":"public","beta":false,"name":"zerigo_dns:tier2","id":"https://addons.heroku.com/addons/zerigo_dns:tier2","description":"Zerigo DNS Zerigo Tier 2","price_cents":2000},{"price_unit":"month","url":"https://addons.heroku.com/addons/loggly:mole","state":"public","beta":false,"name":"loggly:mole","id":"https://addons.heroku.com/addons/loggly:mole","description":"Loggly Mole","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/chargify:start","state":"public","beta":false,"name":"chargify:start","id":"https://addons.heroku.com/addons/chargify:start","description":"Chargify Start","price_cents":9900},{"price_unit":"month","url":"https://addons.heroku.com/addons/blitline:test","state":"beta","beta":false,"name":"blitline:test","id":"https://addons.heroku.com/addons/blitline:test","description":"Blitline Test","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/tddium:starter","state":"public","beta":false,"name":"tddium:starter","id":"https://addons.heroku.com/addons/tddium:starter","description":"Tddium Starter","price_cents":700},{"price_unit":"month","url":"https://addons.heroku.com/addons/heroku-postgresql:ronin","state":"public","beta":false,"name":"heroku-postgresql:ronin","id":"https://addons.heroku.com/addons/heroku-postgresql:ronin","description":"Heroku Postgres Ronin","price_cents":20000},{"state":"public","url":"https://addons.heroku.com/bundles","beta":false,"name":"bundles:unlimited","description":"Unlimited Bundles"},{"price_unit":"month","url":"https://addons.heroku.com/addons/mailgun:pro","state":"public","beta":false,"name":"mailgun:pro","id":"https://addons.heroku.com/addons/mailgun:pro","description":"Mailgun Pro","price_cents":7900},{"price_unit":"month","url":"https://addons.heroku.com/addons/tddium:plus","state":"public","beta":false,"name":"tddium:plus","id":"https://addons.heroku.com/addons/tddium:plus","description":"Tddium Plus","price_cents":8000},{"state":"public","url":null,"beta":false,"name":"simple_worker:starter","description":"Appoxy SimpleWorker Starter"},{"price_unit":"month","url":"https://addons.heroku.com/addons/redistogo:mini","state":"public","beta":false,"name":"redistogo:mini","id":"https://addons.heroku.com/addons/redistogo:mini","description":"Redis To Go Mini","price_cents":500},{"state":"public","url":null,"beta":false,"name":"redistogo:rho.small.vm","description":"Redis To Go Rho Mobile Small VM"},{"price_unit":"month","url":"https://addons.heroku.com/addons/cloudmailin:micro","state":"public","beta":false,"name":"cloudmailin:micro","id":"https://addons.heroku.com/addons/cloudmailin:micro","description":"CloudMailIn Micro","price_cents":900},{"price_unit":"month","url":"https://addons.heroku.com/addons/loggly:gopher","state":"public","beta":false,"name":"loggly:gopher","id":"https://addons.heroku.com/addons/loggly:gopher","description":"Loggly Gopher","price_cents":9900},{"price_unit":"month","url":"https://addons.heroku.com/addons/cron:hourly","state":"public","beta":false,"name":"cron:hourly","id":"https://addons.heroku.com/addons/cron:hourly","description":"Cron Hourly Cron","price_cents":300},{"price_unit":"month","url":"https://addons.heroku.com/addons/mongohq:free","state":"public","beta":false,"name":"mongohq:free","id":"https://addons.heroku.com/addons/mongohq:free","description":"MongoHQ MongoHQ Free","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/memcache:50gb","state":"pass_only","beta":false,"name":"memcache:50gb","id":"https://addons.heroku.com/addons/memcache:50gb","description":"Memcache 50 GB","price_cents":350000},{"price_unit":"month","url":"https://addons.heroku.com/addons/pandastream:solo","state":"public","beta":false,"name":"pandastream:solo","id":"https://addons.heroku.com/addons/pandastream:solo","description":"Panda Stream Solo","price_cents":9900},{"price_unit":"month","url":"https://addons.heroku.com/addons/neo4j:test","state":"public","beta":true,"name":"neo4j:test","id":"https://addons.heroku.com/addons/neo4j:test","description":"Neo4j Test","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/deployhooks:http","state":"public","beta":false,"name":"deployhooks:http","id":"https://addons.heroku.com/addons/deployhooks:http","description":"Deploy Hooks HTTP Post Hook","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/chargify:max","state":"public","beta":false,"name":"chargify:max","id":"https://addons.heroku.com/addons/chargify:max","description":"Chargify Max","price_cents":99900},{"price_unit":"month","url":"https://addons.heroku.com/addons/mongohq:small","state":"public","beta":false,"name":"mongohq:small","id":"https://addons.heroku.com/addons/mongohq:small","description":"MongoHQ MongoHQ Small","price_cents":1500},{"price_unit":"month","url":"https://addons.heroku.com/addons/papertrail:test","state":"beta","beta":false,"name":"papertrail:test","id":"https://addons.heroku.com/addons/papertrail:test","description":"Papertrail Test","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/framey:test","state":"beta","beta":false,"name":"framey:test","id":"https://addons.heroku.com/addons/framey:test","description":"Framey Test","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/redistogo:super","state":"pass_only","beta":false,"name":"redistogo:super","id":"https://addons.heroku.com/addons/redistogo:super","description":"Redis To Go Super","price_cents":100000},{"price_unit":"month","url":"https://addons.heroku.com/addons/websolr:platinum","state":"public","beta":false,"name":"websolr:platinum","id":"https://addons.heroku.com/addons/websolr:platinum","description":"Websolr Platinum","price_cents":10000},{"price_unit":"month","url":"https://addons.heroku.com/addons/tddium:pro","state":"public","beta":false,"name":"tddium:pro","id":"https://addons.heroku.com/addons/tddium:pro","description":"Tddium Pro","price_cents":15000},{"price_unit":"month","url":"https://addons.heroku.com/addons/scheduler:standard","state":"public","beta":false,"name":"scheduler:standard","id":"https://addons.heroku.com/addons/scheduler:standard","description":"Heroku Scheduler Standard","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/pusher:sandbox","state":"public","beta":false,"name":"pusher:sandbox","id":"https://addons.heroku.com/addons/pusher:sandbox","description":"Pusher Sandbox","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/pandastream:duo","state":"public","beta":false,"name":"pandastream:duo","id":"https://addons.heroku.com/addons/pandastream:duo","description":"Panda Stream Duo","price_cents":19800},{"price_unit":"month","url":"https://addons.heroku.com/addons/cloudant:helium","state":"public","beta":false,"name":"cloudant:helium","id":"https://addons.heroku.com/addons/cloudant:helium","description":"Cloudant Helium","price_cents":11900},{"price_unit":"month","url":"https://addons.heroku.com/addons/dyn:lite10","state":"public","beta":false,"name":"dyn:lite10","id":"https://addons.heroku.com/addons/dyn:lite10","description":"DynECT Managed DNS Lite 10","price_cents":3000},{"price_unit":"month","url":"https://addons.heroku.com/addons/pubnub:minimal","state":"public","beta":false,"name":"pubnub:minimal","id":"https://addons.heroku.com/addons/pubnub:minimal","description":"PubNub Minimal","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/heroku-postgresql:ika","state":"public","beta":false,"name":"heroku-postgresql:ika","id":"https://addons.heroku.com/addons/heroku-postgresql:ika","description":"Heroku Postgres Ika","price_cents":80000},{"price_unit":"month","url":"https://addons.heroku.com/addons/cloudmailin:premium","state":"public","beta":false,"name":"cloudmailin:premium","id":"https://addons.heroku.com/addons/cloudmailin:premium","description":"CloudMailIn Premium","price_cents":8500},{"price_unit":"month","url":"https://addons.heroku.com/addons/securekey:fortnightly","state":"beta","beta":false,"name":"securekey:fortnightly","id":"https://addons.heroku.com/addons/securekey:fortnightly","description":"Secure Key Fortnightly","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/zencoder:2k","state":"public","beta":false,"name":"zencoder:2k","id":"https://addons.heroku.com/addons/zencoder:2k","description":"Zencoder 2,000 Minutes","price_cents":8000},{"price_unit":"month","url":"https://addons.heroku.com/addons/websolr:tungsten","state":"public","beta":false,"name":"websolr:tungsten","id":"https://addons.heroku.com/addons/websolr:tungsten","description":"Websolr Tungsten","price_cents":40000},{"price_unit":"month","url":"https://addons.heroku.com/addons/rhoconnect:premium","state":"public","beta":false,"name":"rhoconnect:premium","id":"https://addons.heroku.com/addons/rhoconnect:premium","description":"RhoConnect Premium","price_cents":9900},{"price_unit":"month","url":"https://addons.heroku.com/addons/ranger:recon","state":"public","beta":false,"name":"ranger:recon","id":"https://addons.heroku.com/addons/ranger:recon","description":"Ranger Recon","price_cents":500},{"price_unit":"month","url":"https://addons.heroku.com/addons/apigee:basic","state":"public","beta":false,"name":"apigee:basic","id":"https://addons.heroku.com/addons/apigee:basic","description":"Apigee For Twitter Basic","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/docraptor:test","state":"public","beta":true,"name":"docraptor:test","id":"https://addons.heroku.com/addons/docraptor:test","description":"DocRaptor Test","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/cloudmailin:developer","state":"public","beta":false,"name":"cloudmailin:developer","id":"https://addons.heroku.com/addons/cloudmailin:developer","description":"CloudMailIn Developer","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/cloudant:argon","state":"public","beta":false,"name":"cloudant:argon","id":"https://addons.heroku.com/addons/cloudant:argon","description":"Cloudant Argon","price_cents":1500},{"price_unit":"month","url":"https://addons.heroku.com/addons/redistogo:mega","state":"pass_only","beta":false,"name":"redistogo:mega","id":"https://addons.heroku.com/addons/redistogo:mega","description":"Redis To Go Mega","price_cents":400000},{"price_unit":"month","url":"https://addons.heroku.com/addons/stillalive:plus","state":"public","beta":false,"name":"stillalive:plus","id":"https://addons.heroku.com/addons/stillalive:plus","description":"StillAlive Plus","price_cents":2500},{"price_unit":"month","url":"https://addons.heroku.com/addons/sendgrid:gold","state":"public","beta":false,"name":"sendgrid:gold","id":"https://addons.heroku.com/addons/sendgrid:gold","description":"SendGrid Gold","price_cents":19995},{"price_unit":"month","url":"https://addons.heroku.com/addons/pgbackups:auto-month","state":"public","beta":false,"name":"pgbackups:auto-month","id":"https://addons.heroku.com/addons/pgbackups:auto-month","description":"PG Backups Auto - One Month Retention","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/blitz:1000","state":"public","beta":false,"name":"blitz:1000","id":"https://addons.heroku.com/addons/blitz:1000","description":"Blitz 1000","price_cents":79900},{"price_unit":"month","url":"https://addons.heroku.com/addons/justonedb:sigma","state":"public","beta":false,"name":"justonedb:sigma","id":"https://addons.heroku.com/addons/justonedb:sigma","description":"JustOneDB - NewSQL Cloud Database Sigma","price_cents":1900},{"price_unit":"month","url":"https://addons.heroku.com/addons/boxcar:test","state":"beta","beta":false,"name":"boxcar:test","id":"https://addons.heroku.com/addons/boxcar:test","description":"Boxcar Push Notifications Test","price_cents":0},{"state":"public","url":null,"beta":false,"name":"shared-database:20gb","description":"Shared Database 20GB"},{"price_unit":"month","url":"https://addons.heroku.com/addons/pusher:bigboy","state":"public","beta":false,"name":"pusher:bigboy","id":"https://addons.heroku.com/addons/pusher:bigboy","description":"Pusher Big Boy","price_cents":19900},{"price_unit":"month","url":"https://addons.heroku.com/addons/dbinsights:standard","state":"public","beta":false,"name":"dbinsights:standard","id":"https://addons.heroku.com/addons/dbinsights:standard","description":"DbInsights Standard","price_cents":4000},{"price_unit":"month","url":"https://addons.heroku.com/addons/loggly:squirrel","state":"public","beta":false,"name":"loggly:squirrel","id":"https://addons.heroku.com/addons/loggly:squirrel","description":"Loggly Squirrel","price_cents":4900},{"price_unit":"month","url":"https://addons.heroku.com/addons/ssl:piggyback","state":"public","beta":false,"name":"ssl:piggyback","id":"https://addons.heroku.com/addons/ssl:piggyback","description":"SSL Piggyback SSL","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/loggly:woodchuck","state":"public","beta":false,"name":"loggly:woodchuck","id":"https://addons.heroku.com/addons/loggly:woodchuck","description":"Loggly Woodchuck","price_cents":14900},{"price_unit":"month","url":"https://addons.heroku.com/addons/iron_mq:steel","state":"public","beta":false,"name":"iron_mq:steel","id":"https://addons.heroku.com/addons/iron_mq:steel","description":"IronMQ Steel","price_cents":14999},{"price_unit":"month","url":"https://addons.heroku.com/addons/mongolab:small","state":"public","beta":false,"name":"mongolab:small","id":"https://addons.heroku.com/addons/mongolab:small","description":"MongoLab Small","price_cents":1000},{"price_unit":"month","url":"https://addons.heroku.com/addons/zencoder:10k","state":"public","beta":false,"name":"zencoder:10k","id":"https://addons.heroku.com/addons/zencoder:10k","description":"Zencoder 10,000 Minutes","price_cents":30000},{"price_unit":"month","url":"https://addons.heroku.com/addons/tddium:mega","state":"public","beta":false,"name":"tddium:mega","id":"https://addons.heroku.com/addons/tddium:mega","description":"Tddium Mega","price_cents":30000},{"price_unit":"month","url":"https://addons.heroku.com/addons/stillalive:basic","state":"public","beta":false,"name":"stillalive:basic","id":"https://addons.heroku.com/addons/stillalive:basic","description":"StillAlive Basic","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/redistogo:large","state":"public","beta":false,"name":"redistogo:large","id":"https://addons.heroku.com/addons/redistogo:large","description":"Redis To Go Large","price_cents":30000},{"state":"public","url":"http://getexceptional.com/","beta":false,"name":"exceptional:basic","description":"Exceptional Basic"},{"price_unit":"month","url":"https://addons.heroku.com/addons/heroku-postgresql:fugu","state":"public","beta":false,"name":"heroku-postgresql:fugu","id":"https://addons.heroku.com/addons/heroku-postgresql:fugu","description":"Heroku Postgres Fugu","price_cents":40000},{"state":"public","url":null,"beta":false,"name":"redistogo:rho.large.vm","description":"Redis To Go Rho Mobile Large VM"},{"state":"public","url":null,"beta":false,"name":"legacy-database:zilla","description":"Legacy Database Zilla"},{"price_unit":"dyno_hour","url":"https://addons.heroku.com/addons/newrelic:professional","state":"public","beta":false,"name":"newrelic:professional","id":"https://addons.heroku.com/addons/newrelic:professional","description":"New Relic Professional","price_cents":6},{"price_unit":"month","url":"https://addons.heroku.com/addons/exceptional:premium","state":"public","beta":false,"name":"exceptional:premium","id":"https://addons.heroku.com/addons/exceptional:premium","description":"Exceptional Exceptional Premium","price_cents":900},{"price_unit":"month","url":"https://addons.heroku.com/addons/parse:test","state":"beta","beta":false,"name":"parse:test","id":"https://addons.heroku.com/addons/parse:test","description":"Parse Test","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/statsmix:pro","state":"public","beta":false,"name":"statsmix:pro","id":"https://addons.heroku.com/addons/statsmix:pro","description":"StatsMix Pro","price_cents":9900},{"price_unit":"month","url":"https://addons.heroku.com/addons/stackmob:bronze","state":"public","beta":false,"name":"stackmob:bronze","id":"https://addons.heroku.com/addons/stackmob:bronze","description":"Stackmob Bronze","price_cents":500},{"price_unit":"month","url":"https://addons.heroku.com/addons/cloudmailin:starter","state":"public","beta":false,"name":"cloudmailin:starter","id":"https://addons.heroku.com/addons/cloudmailin:starter","description":"CloudMailIn Starter","price_cents":2500},{"price_unit":"month","url":"https://addons.heroku.com/addons/apigee_facebook:basic","state":"public","beta":true,"name":"apigee_facebook:basic","id":"https://addons.heroku.com/addons/apigee_facebook:basic","description":"Apigee for Facebook Basic","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/websolr:chromium","state":"public","beta":false,"name":"websolr:chromium","id":"https://addons.heroku.com/addons/websolr:chromium","description":"Websolr Chromium","price_cents":5000},{"price_unit":"month","url":"https://addons.heroku.com/addons/pgbackups:plus","state":"public","beta":false,"name":"pgbackups:plus","id":"https://addons.heroku.com/addons/pgbackups:plus","description":"PG Backups Plus","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/pgbackups:auto-week","state":"public","beta":false,"name":"pgbackups:auto-week","id":"https://addons.heroku.com/addons/pgbackups:auto-week","description":"PG Backups Auto - One Week Retention","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/chargify:developer","state":"public","beta":false,"name":"chargify:developer","id":"https://addons.heroku.com/addons/chargify:developer","description":"Chargify Developer","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/mongohq:large","state":"public","beta":false,"name":"mongohq:large","id":"https://addons.heroku.com/addons/mongohq:large","description":"MongoHQ MongoHQ Large","price_cents":4900},{"price_unit":"month","url":"https://addons.heroku.com/addons/flying_sphinx:wooden","state":"public","beta":false,"name":"flying_sphinx:wooden","id":"https://addons.heroku.com/addons/flying_sphinx:wooden","description":"Flying Sphinx Wooden","price_cents":1200},{"price_unit":"month","url":"https://addons.heroku.com/addons/deployhooks:campfire","state":"public","beta":false,"name":"deployhooks:campfire","id":"https://addons.heroku.com/addons/deployhooks:campfire","description":"Deploy Hooks Campfire Hook","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/raydash:test","state":"beta","beta":false,"name":"raydash:test","id":"https://addons.heroku.com/addons/raydash:test","description":"Raydash Test","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/websolr:titanium","state":"public","beta":false,"name":"websolr:titanium","id":"https://addons.heroku.com/addons/websolr:titanium","description":"Websolr Titanium","price_cents":80000},{"price_unit":"month","url":"https://addons.heroku.com/addons/sendgrid:silver","state":"public","beta":false,"name":"sendgrid:silver","id":"https://addons.heroku.com/addons/sendgrid:silver","description":"SendGrid Silver","price_cents":7995},{"price_unit":"month","url":"https://addons.heroku.com/addons/heroku-postgresql:zilla","state":"public","beta":false,"name":"heroku-postgresql:zilla","id":"https://addons.heroku.com/addons/heroku-postgresql:zilla","description":"Heroku Postgres Zilla","price_cents":160000},{"price_unit":"month","url":"https://addons.heroku.com/addons/mongohq:micro","state":"public","beta":false,"name":"mongohq:micro","id":"https://addons.heroku.com/addons/mongohq:micro","description":"MongoHQ MongoHQ Micro","price_cents":500},{"price_unit":"month","url":"https://addons.heroku.com/addons/logging:basic","state":"public","beta":false,"name":"logging:basic","id":"https://addons.heroku.com/addons/logging:basic","description":"Logging Basic","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/spacialdb:test","state":"beta","beta":false,"name":"spacialdb:test","id":"https://addons.heroku.com/addons/spacialdb:test","description":"SpacialDB Test","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/stackmob:iron","state":"public","beta":false,"name":"stackmob:iron","id":"https://addons.heroku.com/addons/stackmob:iron","description":"Stackmob Iron","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/pubnub:common","state":"public","beta":false,"name":"pubnub:common","id":"https://addons.heroku.com/addons/pubnub:common","description":"PubNub Common","price_cents":8999},{"price_unit":"month","url":"https://addons.heroku.com/addons/pubnub:starter","state":"public","beta":false,"name":"pubnub:starter","id":"https://addons.heroku.com/addons/pubnub:starter","description":"PubNub Starter","price_cents":4999},{"price_unit":"month","url":"https://addons.heroku.com/addons/progstr:test","state":"public","beta":true,"name":"progstr:test","id":"https://addons.heroku.com/addons/progstr:test","description":"Progstr Logger Test","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/cloudant:krypton","state":"public","beta":false,"name":"cloudant:krypton","id":"https://addons.heroku.com/addons/cloudant:krypton","description":"Cloudant Krypton","price_cents":39900},{"price_unit":"month","url":"https://addons.heroku.com/addons/cleardb:ignite","state":"public","beta":false,"name":"cleardb:ignite","id":"https://addons.heroku.com/addons/cleardb:ignite","description":"ClearDB MySQL Database Ignite","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/ticketly:test","state":"beta","beta":false,"name":"ticketly:test","id":"https://addons.heroku.com/addons/ticketly:test","description":"Ticketly Test","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/websolr:cobalt","state":"public","beta":false,"name":"websolr:cobalt","id":"https://addons.heroku.com/addons/websolr:cobalt","description":"Websolr Cobalt","price_cents":2000},{"price_unit":"month","url":"https://addons.heroku.com/addons/stackmob:silver","state":"public","beta":false,"name":"stackmob:silver","id":"https://addons.heroku.com/addons/stackmob:silver","description":"Stackmob Silver","price_cents":1900},{"price_unit":"month","url":"https://addons.heroku.com/addons/pusher:startup","state":"public","beta":false,"name":"pusher:startup","id":"https://addons.heroku.com/addons/pusher:startup","description":"Pusher Startup","price_cents":4900},{"price_unit":"month","url":"https://addons.heroku.com/addons/chargify:grow","state":"public","beta":false,"name":"chargify:grow","id":"https://addons.heroku.com/addons/chargify:grow","description":"Chargify Grow","price_cents":34900},{"price_unit":"month","url":"https://addons.heroku.com/addons/blitz:250","state":"public","beta":false,"name":"blitz:250","id":"https://addons.heroku.com/addons/blitz:250","description":"Blitz 250","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/mongolab:medium","state":"public","beta":false,"name":"mongolab:medium","id":"https://addons.heroku.com/addons/mongolab:medium","description":"MongoLab Medium","price_cents":2000},{"state":"public","url":null,"beta":false,"name":"simple_worker:venti","description":"Appoxy SimpleWorker Venti"},{"price_unit":"month","url":"https://addons.heroku.com/addons/sendgrid:starter","state":"public","beta":false,"name":"sendgrid:starter","id":"https://addons.heroku.com/addons/sendgrid:starter","description":"SendGrid Starter","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/iron_worker:starter","state":"public","beta":false,"name":"iron_worker:starter","id":"https://addons.heroku.com/addons/iron_worker:starter","description":"IronWorker Starter","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/iron_mq:ore","state":"public","beta":false,"name":"iron_mq:ore","id":"https://addons.heroku.com/addons/iron_mq:ore","description":"IronMQ Ore","price_cents":999},{"price_unit":"month","url":"https://addons.heroku.com/addons/deployhooks:irc","state":"public","beta":false,"name":"deployhooks:irc","id":"https://addons.heroku.com/addons/deployhooks:irc","description":"Deploy Hooks IRC Hook","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/releases:basic","state":"public","beta":true,"name":"releases:basic","id":"https://addons.heroku.com/addons/releases:basic","description":"Release Management Basic","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/cleardb:punch","state":"public","beta":false,"name":"cleardb:punch","id":"https://addons.heroku.com/addons/cleardb:punch","description":"ClearDB MySQL Database Punch","price_cents":999},{"price_unit":"month","url":"https://addons.heroku.com/addons/ssl:ip","state":"public","beta":false,"name":"ssl:ip","id":"https://addons.heroku.com/addons/ssl:ip","description":"SSL IP Based Custom SSL","price_cents":10000},{"price_unit":"month","url":"https://addons.heroku.com/addons/stillalive:starter","state":"public","beta":false,"name":"stillalive:starter","id":"https://addons.heroku.com/addons/stillalive:starter","description":"StillAlive Starter","price_cents":700},{"price_unit":"month","url":"https://addons.heroku.com/addons/moonshadosms:premium","state":"public","beta":false,"name":"moonshadosms:premium","id":"https://addons.heroku.com/addons/moonshadosms:premium","description":"Moonshado SMS Premium","price_cents":10000},{"price_unit":"month","url":"https://addons.heroku.com/addons/cloudant:neon","state":"public","beta":false,"name":"cloudant:neon","id":"https://addons.heroku.com/addons/cloudant:neon","description":"Cloudant Neon","price_cents":3900},{"price_unit":"month","url":"https://addons.heroku.com/addons/memcache:1gb","state":"pass_only","beta":false,"name":"memcache:1gb","id":"https://addons.heroku.com/addons/memcache:1gb","description":"Memcache 1 GB","price_cents":9000},{"price_unit":"month","url":"https://addons.heroku.com/addons/dbinsights:starter","state":"public","beta":false,"name":"dbinsights:starter","id":"https://addons.heroku.com/addons/dbinsights:starter","description":"DbInsights Starter","price_cents":500},{"price_unit":"month","url":"https://addons.heroku.com/addons/blitz:5000","state":"public","beta":false,"name":"blitz:5000","id":"https://addons.heroku.com/addons/blitz:5000","description":"Blitz 5000","price_cents":129900},{"price_unit":"month","url":"https://addons.heroku.com/addons/xeround:500mb","state":"public","beta":false,"name":"xeround:500mb","id":"https://addons.heroku.com/addons/xeround:500mb","description":"Xeround Cloud DB 500MB","price_cents":7000},{"state":"public","url":null,"beta":false,"name":"pusher:custom_10k","description":"Pusher Custom_10K"},{"price_unit":"month","url":"https://addons.heroku.com/addons/iron_worker:tall","state":"public","beta":false,"name":"iron_worker:tall","id":"https://addons.heroku.com/addons/iron_worker:tall","description":"IronWorker Tall","price_cents":3600},{"price_unit":"month","url":"https://addons.heroku.com/addons/mailgun:starter","state":"public","beta":false,"name":"mailgun:starter","id":"https://addons.heroku.com/addons/mailgun:starter","description":"Mailgun Starter","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/mongolab:large","state":"public","beta":false,"name":"mongolab:large","id":"https://addons.heroku.com/addons/mongolab:large","description":"MongoLab Large","price_cents":4000},{"price_unit":"month","url":"https://addons.heroku.com/addons/zencoder:100k","state":"public","beta":false,"name":"zencoder:100k","id":"https://addons.heroku.com/addons/zencoder:100k","description":"Zencoder 100,000 Minutes","price_cents":200000},{"price_unit":"month","url":"https://addons.heroku.com/addons/redistogo:nano","state":"public","beta":false,"name":"redistogo:nano","id":"https://addons.heroku.com/addons/redistogo:nano","description":"Redis To Go Nano","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/pgbackups:basic","state":"public","beta":false,"name":"pgbackups:basic","id":"https://addons.heroku.com/addons/pgbackups:basic","description":"PG Backups Basic","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/chargify:launch","state":"public","beta":false,"name":"chargify:launch","id":"https://addons.heroku.com/addons/chargify:launch","description":"Chargify Launch","price_cents":3900},{"price_unit":"month","url":"https://addons.heroku.com/addons/cleardb:scream","state":"public","beta":false,"name":"cleardb:scream","id":"https://addons.heroku.com/addons/cleardb:scream","description":"ClearDB MySQL Database Scream","price_cents":9999},{"price_unit":"month","url":"https://addons.heroku.com/addons/iron_mq:rust","state":"public","beta":false,"name":"iron_mq:rust","id":"https://addons.heroku.com/addons/iron_mq:rust","description":"IronMQ Rust","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/dyn:lite50","state":"public","beta":false,"name":"dyn:lite50","id":"https://addons.heroku.com/addons/dyn:lite50","description":"DynECT Managed DNS Lite 50","price_cents":9500},{"price_unit":"month","url":"https://addons.heroku.com/addons/mongolab:x-large","state":"public","beta":false,"name":"mongolab:x-large","id":"https://addons.heroku.com/addons/mongolab:x-large","description":"MongoLab X-Large","price_cents":6500},{"price_unit":"month","url":"https://addons.heroku.com/addons/amazon_rds","state":"public","beta":false,"name":"amazon_rds","id":"https://addons.heroku.com/addons/amazon_rds","description":"Amazon RDS Amazon RDS Integration","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/mailgun:hv","state":"public","beta":false,"name":"mailgun:hv","id":"https://addons.heroku.com/addons/mailgun:hv","description":"Mailgun Pro High Volume","price_cents":19900},{"price_unit":"month","url":"https://addons.heroku.com/addons/eshq:test","state":"beta","beta":false,"name":"eshq:test","id":"https://addons.heroku.com/addons/eshq:test","description":"EventSource HQ Test","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/tddium:basic","state":"public","beta":false,"name":"tddium:basic","id":"https://addons.heroku.com/addons/tddium:basic","description":"Tddium Basic","price_cents":2000},{"price_unit":"month","url":"https://addons.heroku.com/addons/ssl:hostname","state":"public","beta":false,"name":"ssl:hostname","id":"https://addons.heroku.com/addons/ssl:hostname","description":"SSL Hostname Based SSL","price_cents":2000},{"price_unit":"month","url":"https://addons.heroku.com/addons/deployhooks:email","state":"public","beta":false,"name":"deployhooks:email","id":"https://addons.heroku.com/addons/deployhooks:email","description":"Deploy Hooks Email Hook","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/heroku-postgresql:baku","state":"public","beta":false,"name":"heroku-postgresql:baku","id":"https://addons.heroku.com/addons/heroku-postgresql:baku","description":"Heroku Postgres Baku","price_cents":320000},{"price_unit":"month","url":"https://addons.heroku.com/addons/tronprint:test","state":"public","beta":true,"name":"tronprint:test","id":"https://addons.heroku.com/addons/tronprint:test","description":"Tronprint Test","price_cents":0},{"price_unit":"month","url":"https://addons.heroku.com/addons/statsmix:standard","state":"public","beta":false,"name":"statsmix:standard","id":"https://addons.heroku.com/addons/statsmix:standard","description":"StatsMix Standard","price_cents":4900},{"price_unit":"month","url":"https://addons.heroku.com/addons/ranger:elite","state":"public","beta":false,"name":"ranger:elite","id":"https://addons.heroku.com/addons/ranger:elite","description":"Ranger Elite","price_cents":2500},{"price_unit":"month","url":"https://addons.heroku.com/addons/memcache:100mb","state":"public","beta":false,"name":"memcache:100mb","id":"https://addons.heroku.com/addons/memcache:100mb","description":"Memcache 100 MB","price_cents":2000},{"price_unit":"month","url":"https://addons.heroku.com/addons/dyn:lite25","state":"public","beta":false,"name":"dyn:lite25","id":"https://addons.heroku.com/addons/dyn:lite25","description":"DynECT Managed DNS Lite 25","price_cents":6000},{"state":"public","url":null,"beta":false,"name":"legacy-database:ninja","description":"Legacy Database Ninja"}]
@@ -0,0 +1,55 @@
1
+ module Heroku
2
+ class API
3
+ module Mock
4
+
5
+ # stub DELETE /apps/:app/collaborators/:email
6
+ Excon.stub(:expects => 200, :method => :delete, :path => %r{^/apps/([^/]+)/collaborators/([^/]+)$}) do |params|
7
+ request_params, mock_data = parse_stub_params(params)
8
+ app, email, _ = request_params[:captures][:path]
9
+ with_mock_app(mock_data, app) do
10
+ if collaborator_data = get_mock_collaborator(mock_data, app, email)
11
+ mock_data[:collaborators][app].delete(collaborator_data)
12
+ {
13
+ :body => "#{email} has been removed as collaborator on #{app}",
14
+ :status => 200
15
+ }
16
+ else
17
+ { :body => 'User not found.', :status => 404 }
18
+ end
19
+ end
20
+ end
21
+
22
+ # stub GET /apps/:app/:collaborators
23
+ Excon.stub(:expects => 200, :method => :get, :path => %r{^/apps/([^/]+)/collaborators}) do |params|
24
+ request_params, mock_data = parse_stub_params(params)
25
+ app, _ = request_params[:captures][:path]
26
+ with_mock_app(mock_data, app) do
27
+ {
28
+ :body => Heroku::API::OkJson.encode(mock_data[:collaborators][app]),
29
+ :status => 200
30
+ }
31
+ end
32
+ end
33
+
34
+ # stub POST /apps/:app/collaborators
35
+ Excon.stub(:expects => 200, :method => :post, :path => %r{^/apps/([^/]+)/collaborators}) do |params|
36
+ request_params, mock_data = parse_stub_params(params)
37
+ app, _ = request_params[:captures][:path]
38
+ email = request_params[:query]['collaborator[email]']
39
+ with_mock_app(mock_data, app) do
40
+ mock_data[:collaborators][app] |= [{'access' => 'edit', 'email' => email}]
41
+ {
42
+ :body => "#{email} added as a collaborator on #{app}.",
43
+ :status => 200
44
+ }
45
+ # Existing user response
46
+ #{
47
+ # :body => "#{email} added as a collaborator on #{app}",
48
+ # :status => 200
49
+ #}
50
+ end
51
+ end
52
+
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,46 @@
1
+ module Heroku
2
+ class API
3
+ module Mock
4
+
5
+ # stub DELETE /apps/:app/config_vars/:key
6
+ Excon.stub(:expects => 200, :method => :delete, :path => %r{^/apps/([^/]+)/config_vars/([^/]+)$}) do |params|
7
+ request_params, mock_data = parse_stub_params(params)
8
+ app, key, _ = request_params[:captures][:path]
9
+ with_mock_app(mock_data, app) do
10
+ mock_data[:config_vars][app].delete(key)
11
+ {
12
+ :body => Heroku::API::OkJson.encode(mock_data[:config_vars][app]),
13
+ :status => 200
14
+ }
15
+ end
16
+ end
17
+
18
+ # stub GET /apps/:app/config_vars
19
+ Excon.stub(:expects => 200, :method => :get, :path => %r{^/apps/([^/]+)/config_vars$}) do |params|
20
+ request_params, mock_data = parse_stub_params(params)
21
+ app, _ = request_params[:captures][:path]
22
+ with_mock_app(mock_data, app) do
23
+ {
24
+ :body => Heroku::API::OkJson.encode(mock_data[:config_vars][app]),
25
+ :status => 200
26
+ }
27
+ end
28
+ end
29
+
30
+ # stub PUT /apps/:app/config_vars
31
+ Excon.stub(:expects => 200, :method => :put, :path => %r{^/apps/([^/]+)/config_vars$}) do |params|
32
+ request_params, mock_data = parse_stub_params(params)
33
+ app, _ = request_params[:captures][:path]
34
+ with_mock_app(mock_data, app) do
35
+ new_config_vars = request_params[:body]
36
+ mock_data[:config_vars][app].merge!(new_config_vars)
37
+ {
38
+ :body => Heroku::API::OkJson.encode(mock_data[:config_vars][app]),
39
+ :status => 200
40
+ }
41
+ end
42
+ end
43
+
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,71 @@
1
+ module Heroku
2
+ class API
3
+ module Mock
4
+
5
+ # stub DELETE /apps/:app/domains/:domain
6
+ Excon.stub(:expects => 200, :method => :delete, :path => %r{^/apps/([^/]+)/domains/([^/]+)$} ) do |params|
7
+ request_params, mock_data = parse_stub_params(params)
8
+ app, domain, _ = request_params[:captures][:path]
9
+ domain = CGI.unescape(domain)
10
+ with_mock_app(mock_data, app) do |app_data|
11
+ if domain = get_mock_app_domain(mock_data, app, domain)
12
+ mock_data[:domains][app].delete(domain)
13
+ {
14
+ :body => {},
15
+ :status => 200
16
+ }
17
+ else
18
+ {
19
+ :body => 'Domain not found.',
20
+ :status => 404
21
+ }
22
+ end
23
+ end
24
+ end
25
+
26
+ # stub GET /apps/:app/domains
27
+ Excon.stub(:expects => 200, :method => :get, :path => %r{^/apps/([^/]+)/domains$} ) do |params|
28
+ request_params, mock_data = parse_stub_params(params)
29
+ app, _ = request_params[:captures][:path]
30
+ with_mock_app(mock_data, app) do |app_data|
31
+ {
32
+ :body => Heroku::API::OkJson.encode(mock_data[:domains][app]),
33
+ :status => 200
34
+ }
35
+ end
36
+ end
37
+
38
+ # stub POST /apps/:app/domains
39
+ Excon.stub(:expects => 201, :method => :post, :path => %r{^/apps/([^/]+)/domains$} ) do |params|
40
+ request_params, mock_data = parse_stub_params(params)
41
+ app, _ = request_params[:captures][:path]
42
+ domain = request_params[:query]['domain_name[domain]']
43
+ with_mock_app(mock_data, app) do |app_data|
44
+ if ['custom_domains:basic', 'custom_domains:wildcard'].any? {|addon| get_mock_app_addon(mock_data, app, addon)}
45
+ unless get_mock_app_domain(mock_data, app, domain)
46
+ mock_data[:domains][app] << {
47
+ 'app_id' => app_data['id'],
48
+ 'base_domain' => domain.split('.')[-2..-1].join('.'),
49
+ 'created_at' => timestamp,
50
+ 'domain' => domain,
51
+ 'default' => nil,
52
+ 'id' => rand(999999),
53
+ 'updated_at' => timestamp
54
+ }
55
+ end
56
+ {
57
+ :body => Heroku::API::OkJson.encode('domain' => domain),
58
+ :status => 201
59
+ }
60
+ else
61
+ {
62
+ :body => Heroku::API::OkJson.encode([["base","Please install the Custom Domains addon before adding domains to your app"]]),
63
+ :status => 422
64
+ }
65
+ end
66
+ end
67
+ end
68
+
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,46 @@
1
+ module Heroku
2
+ class API
3
+ module Mock
4
+
5
+ # stub DELETE /user/keys/:key
6
+ Excon.stub(:expects => 200, :method => :delete, :path => %r{^/user/keys/([^/]+)}) do |params|
7
+ request_params, mock_data = parse_stub_params(params)
8
+ key, _ = request_params[:captures][:path]
9
+ key = CGI.unescape(key).gsub('%2E', '.')
10
+ if key_data = get_mock_key(mock_data, key)
11
+ mock_data[:keys].delete(key_data)
12
+ { :status => 200 }
13
+ else
14
+ { :body => "Key not found.", :status => 404 }
15
+ end
16
+ end
17
+
18
+ # stub DELETE /user/keys
19
+ Excon.stub(:expects => 200, :method => :delete, :path => %r{^/user/keys}) do |params|
20
+ request_params, mock_data = parse_stub_params(params)
21
+ mock_data[:keys] = []
22
+ { :status => 200}
23
+ end
24
+
25
+ # stub GET /user/keys
26
+ Excon.stub(:expects => 200, :method => :get, :path => %r{^/user/keys}) do |params|
27
+ request_params, mock_data = parse_stub_params(params)
28
+ {
29
+ :body => Heroku::API::OkJson.encode(mock_data[:keys]),
30
+ :status => 200
31
+ }
32
+ end
33
+
34
+ # stub POST /user/keys
35
+ Excon.stub(:expects => 200, :method => :post, :path => %r{^/user/keys}) do |params|
36
+ request_params, mock_data = parse_stub_params(params)
37
+ mock_data[:keys] |= [{
38
+ 'email' => 'email@example.com',
39
+ 'contents' => request_params[:body]
40
+ }]
41
+ { :status => 200 }
42
+ end
43
+
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,20 @@
1
+ module Heroku
2
+ class API
3
+ module Mock
4
+
5
+ # stub GET /apps/:app/logs
6
+ Excon.stub(:expects => 200, :method => :get, :path => %r{^/apps/([^/]+)/logs}) do |params|
7
+ request_params, mock_data = parse_stub_params(params)
8
+ app, _ = request_params[:captures][:path]
9
+ with_mock_app(mock_data, app) do
10
+ uuid = [SecureRandom.hex(4), SecureRandom.hex(2), SecureRandom.hex(2), SecureRandom.hex(2), SecureRandom.hex(6)].join('-')
11
+ {
12
+ :body => "https://logplex.heroku.com/sessions/#{uuid}?srv=#{Time.now.to_i}",
13
+ :status => 200
14
+ }
15
+ end
16
+ end
17
+
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,191 @@
1
+ module Heroku
2
+ class API
3
+ module Mock
4
+
5
+ # stub GET /apps/:app/ps
6
+ Excon.stub(:expects => 200, :method => :get, :path => %r{^/apps/([^/]+)/ps}) do |params|
7
+ request_params, mock_data = parse_stub_params(params)
8
+ app, _ = request_params[:captures][:path]
9
+ with_mock_app(mock_data, app) do |app_data|
10
+ {
11
+ :body => Heroku::API::OkJson.encode(get_mock_processes(mock_data, app)),
12
+ :status => 200
13
+ }
14
+ end
15
+ end
16
+
17
+ # stub POST /apps/:app/ps
18
+ Excon.stub(:expects => 200, :method => :post, :path => %r{^/apps/([^/]+)/ps\/?$}) do |params|
19
+ request_params, mock_data = parse_stub_params(params)
20
+ app, _ = request_params[:captures][:path]
21
+ with_mock_app(mock_data, app) do |app_data|
22
+ attached = request_params[:query].has_key?('attach') && request_params[:query]['attach'].to_s == 'true'
23
+ command = request_params[:query].has_key?('command') && request_params[:query]['command']
24
+ rendezvous_url = if attached
25
+ "s1.runtime.heroku.com:5000/#{SecureRandom.hex(32)}"
26
+ end
27
+ max_run_id = mock_data[:ps][app].map { |process| process['process'].split('run.').last.to_i}.max
28
+ data = {
29
+ 'action' => 'complete',
30
+ 'attached' => attached,
31
+ 'command' => command,
32
+ 'elapsed' => 0,
33
+ 'pretty_state' => 'completed for 0s',
34
+ 'process' => "run.#{max_run_id + 1}",
35
+ 'rendezvous_url' => rendezvous_url,
36
+ 'slug' => 'NONE',
37
+ 'state' => 'created',
38
+ 'transitioned_at' => timestamp,
39
+ 'type' => 'Ps',
40
+ 'upid' => rand(99999999).to_s
41
+ }
42
+ mock_data[:ps][app] << data
43
+ {
44
+ :body => Heroku::API::OkJson.encode(data),
45
+ :status => 200,
46
+ }
47
+ end
48
+ end
49
+
50
+ # stub POST /apps/:app/ps/restart
51
+ Excon.stub(:expects => 200, :method => :post, :path => %r{^/apps/([^/]+)/ps/restart}) do |params|
52
+ request_params, mock_data = parse_stub_params(params)
53
+ app, _ = request_params[:captures][:path]
54
+ with_mock_app(mock_data, app) do |app_data|
55
+ ps = request_params[:query].has_key?('ps') && request_params[:query]['ps']
56
+ type = request_params[:query].has_key?('type') && request_params[:query]['type']
57
+ if !ps && !type
58
+ mock_data[:ps][app].select {|process| process['state'] != 'complete'}.each do |process|
59
+ process['transitioned_at'] = timestamp
60
+ end
61
+ elsif ps
62
+ mock_data[:ps][app].select {|process| process['process'] == 'ps' && process['state'] != 'complete'}.each do |process|
63
+ process['transitioned_at'] = timestamp
64
+ end
65
+ elsif type
66
+ mock_data[:ps][app].select {|process| process['process'] =~ %r{^#{type}\.\d+} && process['state'] != 'complete'}.each do |process|
67
+ process['transitioned_at'] = timestamp
68
+ end
69
+ end
70
+ {
71
+ :body => 'ok',
72
+ :status => 200
73
+ }
74
+ end
75
+ end
76
+
77
+ # stub POST /apps/:app/ps/scale
78
+ Excon.stub(:expects => 200, :method => :post, :path => %r{^/apps/([^/]+)/ps/scale}) do |params|
79
+ request_params, mock_data = parse_stub_params(params)
80
+ app, _ = request_params[:captures][:path]
81
+ with_mock_app(mock_data, app) do |app_data|
82
+ request_params[:query]
83
+ type = request_params[:query].has_key?('type') && request_params[:query]['type']
84
+ qty = request_params[:query].has_key?('qty') && request_params[:query]['qty']
85
+ if app_data['stack'] == 'cedar'
86
+ if type == 'web'
87
+ current_qty = mock_data[:ps][app].count {|process| process['process'] =~ %r{^web\.\d+}}
88
+
89
+ if qty >= current_qty
90
+ (qty - current_qty).times do
91
+ max_web_id = mock_data[:ps][app].map {|process| process['process'].split('web.').last.to_i}.max
92
+ data = mock_data[:ps][app].first.dup # copy of web.1
93
+ data.merge({
94
+ 'process' => "web.#{max_web_id + 1}",
95
+ 'transitioned_at' => timestamp,
96
+ 'upid' => rand(99999999).to_s
97
+ })
98
+ mock_data[:ps][app] << data
99
+ end
100
+ elsif qty < current_qty
101
+ (current_qty - qty).times do
102
+ max_web_id = mock_data[:ps][app].map {|process| process['process'].split('web.').last.to_i}.max
103
+ process = mock_data[:ps][app].detect {|process| process['process'] == "web.#{max_web_id}"}
104
+ mock_data[:ps][app].delete(process)
105
+ end
106
+ end
107
+ {
108
+ :body => qty.to_s,
109
+ :status => 200
110
+ }
111
+ else
112
+ {
113
+ :body => Heroku::API::OkJson.encode('error' => "No such type as #{type}") ,
114
+ :status => 422
115
+ }
116
+ end
117
+ else
118
+ {
119
+ :body => Heroku::API::OkJson.encode('error' => "That feature is not available on this app's stack"),
120
+ :status => 422
121
+ }
122
+ end
123
+ end
124
+ end
125
+
126
+ # stub POST /apps/:app/ps/stop
127
+ Excon.stub(:expects => 200, :method => :post, :path => %r{^/apps/([^/]+)/ps/stop}) do |params|
128
+ request_params, mock_data = parse_stub_params(params)
129
+ app, _ = request_params[:captures][:path]
130
+ with_mock_app(mock_data, app) do |app_data|
131
+ ps = request_params[:query].has_key?('ps') && request_params[:query]['ps']
132
+ type = request_params[:query].has_key?('type') && request_params[:query]['type']
133
+ if !ps && !type
134
+ {
135
+ :body => Heroku::API::OkJson.encode({'error' => 'Missing process argument'}),
136
+ :status => 422
137
+ }
138
+ else
139
+ {
140
+ :body => 'ok',
141
+ :status => 200
142
+ }
143
+ end
144
+ end
145
+ end
146
+
147
+ # stub PUT /apps/:app/dynos
148
+ Excon.stub(:expects => 200, :method => :put, :path => %r{^/apps/([^/]+)/dynos}) do |params|
149
+ request_params, mock_data = parse_stub_params(params)
150
+ app, _ = request_params[:captures][:path]
151
+ with_mock_app(mock_data, app) do |app_data|
152
+ dynos = request_params[:query].has_key?('dynos') && request_params[:query]['dynos'].to_i
153
+ unless app_data['stack'] == 'cedar'
154
+ app_data['dynos'] = dynos
155
+ {
156
+ :body => Heroku::API::OkJson.encode({'name' => app, 'dynos' => dynos}),
157
+ :status => 200
158
+ }
159
+ else
160
+ {
161
+ :body => Heroku::API::OkJson.encode({'error' => "For Cedar apps, use `heroku scale web=#{dynos}`"}),
162
+ :status => 422
163
+ }
164
+ end
165
+ end
166
+ end
167
+
168
+ # stub PUT /apps/:app/workers
169
+ Excon.stub(:expects => 200, :method => :put, :path => %r{^/apps/([^/]+)/workers}) do |params|
170
+ request_params, mock_data = parse_stub_params(params)
171
+ app, _ = request_params[:captures][:path]
172
+ with_mock_app(mock_data, app) do |app_data|
173
+ workers = request_params[:query].has_key?('workers') && request_params[:query]['workers'].to_i
174
+ unless app_data['stack'] == 'cedar'
175
+ app_data['workers'] = workers
176
+ {
177
+ :body => Heroku::API::OkJson.encode({'name' => app, 'workers' => workers}),
178
+ :status => 200
179
+ }
180
+ else
181
+ {
182
+ :body => Heroku::API::OkJson.encode({'error' => "For Cedar apps, use `heroku scale worker=#{workers}`"}),
183
+ :status => 422
184
+ }
185
+ end
186
+ end
187
+ end
188
+
189
+ end
190
+ end
191
+ end
@@ -0,0 +1,124 @@
1
+ module Heroku
2
+ class API
3
+ module Mock
4
+
5
+ # stub GET /apps/:app/releases
6
+ Excon.stub(:expects => 200, :method => :get, :path => %r{^/apps/([^/]+)/releases} ) do |params|
7
+ request_params, mock_data = parse_stub_params(params)
8
+ app, _ = request_params[:captures][:path]
9
+ with_mock_app(mock_data, app) do |app_data|
10
+ if get_mock_app_addon(mock_data, app, 'releases:basic')
11
+ {
12
+ :body => mock_data[:releases][app][-2..-1],
13
+ :status => 200
14
+ }
15
+ elsif get_mock_app_addon(mock_data, app, 'releases:advanced')
16
+ {
17
+ :body => mock_data[:releases][app],
18
+ :status => 200
19
+ }
20
+ else
21
+ {
22
+ :body => Heroku::API::OkJson.encode({'error' => 'Please install the Release Management add-on to access release history'}),
23
+ :status => 422
24
+ }
25
+ end
26
+ end
27
+ end
28
+
29
+ # stub GET /apps/:app/releases/:release
30
+ Excon.stub(:expects => 200, :method => :get, :path => %r{^/apps/([^/]+)/releases/([^/]+)} ) do |params|
31
+ request_params, mock_data = parse_stub_params(params)
32
+ app, release_name, _ = request_params[:captures][:path]
33
+ with_mock_app(mock_data, app) do |app_data|
34
+ if ['releases:basic', 'releases:advanced'].any? {|addon| get_mock_app_addon(mock_data, app, addon)}
35
+ releases = if get_mock_app_addon(mock_data, app, 'releases:basic')
36
+ mock_data[:releases][app][-2..-1]
37
+ elsif get_mock_app_addon(mock_data, app, 'releases:advanced')
38
+ mock_data[:releases][app]
39
+ end
40
+ if release_data = releases.detect {|release| release['name'] == release_name}
41
+ {
42
+ :body => Heroku::API::OkJson.encode(release_data),
43
+ :status => 200
44
+ }
45
+ else
46
+ {
47
+ :body => 'Record not found.',
48
+ :status => 404
49
+ }
50
+ end
51
+ else
52
+ {
53
+ :body => Heroku::API::OkJson.encode({'error' => 'Please install the Release Management add-on to access release history'}),
54
+ :status => 422
55
+ }
56
+ end
57
+ end
58
+ end
59
+
60
+ # stub POST /apps/:app/releases/:release
61
+ Excon.stub(:expects => 200, :method => :post, :path => %r{^/apps/([^/]+)/releases} ) do |params|
62
+ request_params, mock_data = parse_stub_params(params)
63
+ app, _ = request_params[:captures][:path]
64
+ release_name = request_params[:query]['rollback']
65
+ with_mock_app(mock_data, app) do |app_data|
66
+ if ['releases:basic', 'releases:advanced'].any? {|addon| get_mock_app_addon(mock_data, app, addon)}
67
+ releases = if get_mock_app_addon(mock_data, app, 'releases:basic')
68
+ mock_data[:releases][app][-2..-1]
69
+ elsif get_mock_app_addon(mock_data, app, 'releases:advanced')
70
+ mock_data[:releases][app]
71
+ end
72
+ if release_data = releases.detect {|release| release['name'] == release_name}
73
+ if release_data['addons'] == mock_data[:releases][app].last['addons']
74
+ version = mock_data[:releases][app].map {|release| release['name'][1..-1].to_i}.max || 0
75
+ env = if get_mock_app(mock_data, app)['stack'] == 'cedar'
76
+ {
77
+ 'BUNDLE_WITHOUT' => 'development:test',
78
+ 'DATABASE_URL' => 'postgres://username:password@ec2-123-123-123-123.compute-1.amazonaws.com/username',
79
+ 'LANG' => 'en_US.UTF-8',
80
+ 'RACK_ENV' => 'production',
81
+ 'SHARED_DATABASE_URL' => 'postgres://username:password@ec2-123-123-123-123.compute-1.amazonaws.com/username'
82
+ }
83
+ else
84
+ {}
85
+ end
86
+ mock_data[:releases][app] << {
87
+ 'addons' => mock_data[:addons][app].map {|addon| addon['name']},
88
+ 'commit' => nil,
89
+ 'created_at' => timestamp,
90
+ 'descr' => "Rollback to #{release_name}",
91
+ 'env' => env,
92
+ 'name' => "v#{version + 1}",
93
+ 'pstable' => { 'web' => '' },
94
+ 'user' => 'email@example.com'
95
+ }
96
+
97
+ {
98
+ :body => release_data['name'],
99
+ :status => 200
100
+ }
101
+ else
102
+ {
103
+ :body => Heroku::API::OkJson.encode({'error' => 'Cannot rollback to a release that had a different set of addons installed'}),
104
+ :status => 422
105
+ }
106
+ end
107
+ else
108
+ {
109
+ :body => 'Record not found.',
110
+ :status => 404
111
+ }
112
+ end
113
+ else
114
+ {
115
+ :body => Heroku::API::OkJson.encode({'error' => 'Please install the Release Management add-on to access release history'}),
116
+ :status => 422
117
+ }
118
+ end
119
+ end
120
+ end
121
+
122
+ end
123
+ end
124
+ end