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.
- data/.gitignore +4 -0
- data/.travis.yml +14 -0
- data/Gemfile +4 -0
- data/README.md +120 -0
- data/Rakefile +23 -0
- data/changelog.txt +4 -0
- data/heroku-api.gemspec +23 -0
- data/lib/heroku-api.rb +1 -0
- data/lib/heroku/api.rb +85 -0
- data/lib/heroku/api/addons.rb +47 -0
- data/lib/heroku/api/apps.rb +62 -0
- data/lib/heroku/api/collaborators.rb +33 -0
- data/lib/heroku/api/config_vars.rb +33 -0
- data/lib/heroku/api/domains.rb +33 -0
- data/lib/heroku/api/errors.rb +9 -0
- data/lib/heroku/api/keys.rb +42 -0
- data/lib/heroku/api/logs.rb +18 -0
- data/lib/heroku/api/mock.rb +176 -0
- data/lib/heroku/api/mock/addons.rb +153 -0
- data/lib/heroku/api/mock/apps.rb +184 -0
- data/lib/heroku/api/mock/cache/get_addons.json +1 -0
- data/lib/heroku/api/mock/collaborators.rb +55 -0
- data/lib/heroku/api/mock/config_vars.rb +46 -0
- data/lib/heroku/api/mock/domains.rb +71 -0
- data/lib/heroku/api/mock/keys.rb +46 -0
- data/lib/heroku/api/mock/logs.rb +20 -0
- data/lib/heroku/api/mock/processes.rb +191 -0
- data/lib/heroku/api/mock/releases.rb +124 -0
- data/lib/heroku/api/mock/stacks.rb +84 -0
- data/lib/heroku/api/processes.rb +77 -0
- data/lib/heroku/api/releases.rb +33 -0
- data/lib/heroku/api/stacks.rb +22 -0
- data/lib/heroku/api/vendor/okjson.rb +559 -0
- data/lib/heroku/api/version.rb +5 -0
- data/test/test_addons.rb +169 -0
- data/test/test_apps.rb +119 -0
- data/test/test_collaborators.rb +73 -0
- data/test/test_config_vars.rb +54 -0
- data/test/test_domains.rb +63 -0
- data/test/test_helper.rb +35 -0
- data/test/test_keys.rb +39 -0
- data/test/test_logs.rb +20 -0
- data/test/test_processes.rb +245 -0
- data/test/test_releases.rb +91 -0
- data/test/test_stacks.rb +49 -0
- 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
|