ey_services_api 0.3.3 → 0.3.4

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/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use 1.9.2
data/EYIntegratedGemfile CHANGED
@@ -4,7 +4,7 @@ source "http://rubygems.org"
4
4
  gemspec
5
5
 
6
6
  group :test, :development do
7
- gem 'ey_services_fake'
7
+ gemspec :path => "fake"
8
8
  gem 'rake'
9
9
 
10
10
  #private Gem deps of fake_awsm
data/Gemfile CHANGED
@@ -4,9 +4,8 @@ source "http://rubygems.org"
4
4
  gemspec
5
5
 
6
6
  group :test, :development do
7
- gem 'ey_services_fake'
7
+ gemspec :path => "fake"
8
8
 
9
9
  gem 'rake'
10
- gem 'rcov'
11
10
  gem 'guard-rspec'
12
11
  end
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "ey_services_fake/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "ey_services_fake"
7
+ s.version = EyServicesFake::VERSION
8
+ s.authors = ["Jacob Burkhart & Josh Lane"]
9
+ s.email = ["jacob@engineyard.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{A fake for use when writting tests against the ey_services_api}
12
+ s.description = %q{A fake for use when writting tests against the ey_services_api}
13
+
14
+ s.rubyforge_project = "ey_services_fake"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_dependency "sinatra"
22
+ s.add_dependency "cubbyhole", ">= 0.2.0"
23
+ end
@@ -0,0 +1,158 @@
1
+ module EyServicesFake
2
+ class MockBackend
3
+
4
+ def self.tresfiestas_fake
5
+ require 'ey_services_fake/tresfiestas_fake'
6
+ TresfiestasFake
7
+ end
8
+
9
+ def self.setup!(actors = {})
10
+ unless actors[:awsm]
11
+ require 'ey_services_fake/reacharound_awsm'
12
+ actors[:awsm] = ReacharoundAwsm.new
13
+ end
14
+ unless actors[:service_provider]
15
+ require 'ey_services_fake/mocking_bird_service'
16
+ actors[:service_provider] = MockingBirdService.new
17
+ end
18
+ unless actors[:tresfiestas]
19
+ actors[:tresfiestas] = tresfiestas_fake.new
20
+ end
21
+ new(actors)
22
+ end
23
+
24
+ def initialize(actors)
25
+ @actors = actors
26
+ end
27
+
28
+ def actor(role)
29
+ @actors[role] or raise "No actor registered as #{role}, I have #{@actors.keys.inspect}"
30
+ end
31
+
32
+ def reset!
33
+ @actors.values.each do |v|
34
+ v.reset!
35
+ end
36
+ end
37
+
38
+ def awsm
39
+ awsm_hash = actor(:tresfiestas).find_awsm
40
+ unless awsm_hash
41
+ awsm_hash = actor(:tresfiestas).create_awsm(actor(:awsm).base_url, actor(:awsm).app)
42
+ actor(:awsm).setup(awsm_hash[:auth_id], awsm_hash[:auth_key], actor(:tresfiestas).base_url, actor(:tresfiestas).app)
43
+ end
44
+ awsm_hash
45
+ end
46
+
47
+ def partner
48
+ partner_hash = actor(:tresfiestas).find_partner(sso_user)
49
+ unless partner_hash
50
+ partner_hash = actor(:tresfiestas).create_partner(sso_user, actor(:service_provider).base_url, actor(:service_provider).app)
51
+ @actors.values.each do |actor|
52
+ if actor.respond_to?(:service_provider_setup)
53
+ actor.service_provider_setup(partner_hash[:auth_id], partner_hash[:auth_key], actor(:service_provider).base_url, actor(:service_provider).app)
54
+ end
55
+ end
56
+ actor(:service_provider).setup(partner_hash[:auth_id], partner_hash[:auth_key], actor(:tresfiestas).base_url, actor(:tresfiestas).app)
57
+ end
58
+ partner_hash
59
+ end
60
+
61
+ def service
62
+ partner_hash = self.partner
63
+ service_hash = actor(:tresfiestas).find_service(partner_hash[:id])
64
+ unless service_hash
65
+ actor(:service_provider).register_service(partner_hash[:registration_url])
66
+ service_hash = actor(:tresfiestas).find_service(partner_hash[:id])
67
+ end
68
+ if actor(:tresfiestas).respond_to?(:document_service)
69
+ service_hash.merge!(:service_doc => actor(:tresfiestas).document_service(service_hash[:id]))
70
+ end
71
+ service_hash.merge(:partner => partner_hash)
72
+ end
73
+
74
+ def sso_user
75
+ actor(:awsm).sso_user #allows for nils (some implementations of AWSM may decide this is ok)
76
+ end
77
+
78
+ def sso_account
79
+ awsm #need to have setup awsm before you can create accounts!
80
+ sso_user_something = sso_user #the sso_user is a somehting, not necessarily a hash
81
+ sso_account_hash = actor(:awsm).find_sso_account(sso_user_something)
82
+ unless sso_account_hash
83
+ sso_account_hash = actor(:awsm).create_sso_account(sso_user_something)
84
+ end
85
+ sso_account_hash
86
+ end
87
+
88
+ def service_enablement
89
+ sso_account_hash = self.sso_account
90
+ service_hash = self.service
91
+ unless actor(:tresfiestas).service_available_for_account?(service_hash[:id], sso_account_hash[:id])
92
+ actor(:tresfiestas).make_service_available_for_account(service_hash[:id], sso_account_hash[:id])
93
+ end
94
+ {
95
+ :service => service_hash,
96
+ :sso_account => sso_account_hash,
97
+ }
98
+ end
99
+
100
+ def service_account
101
+ service_enablement_hash = self.service_enablement
102
+ sso_account_hash = service_enablement_hash[:sso_account]
103
+ service_hash = service_enablement_hash[:service]
104
+ service_account_hash = actor(:tresfiestas).find_service_account(service_hash[:id], sso_account_hash[:id])
105
+ unless service_account_hash
106
+ actor(:awsm).enable_service(service_hash[:id], sso_account_hash[:id])
107
+ service_account_hash = actor(:tresfiestas).find_service_account(service_hash[:id], sso_account_hash[:id])
108
+ end
109
+ service_account_hash.merge(:name => sso_account_hash[:name], :service => service_hash, :sso_account => sso_account_hash)
110
+ end
111
+
112
+ def destroy_service_account
113
+ actor(:awsm).disable_service(service_account[:id])
114
+ end
115
+
116
+ def app_deployment
117
+ app_deployment_hash = actor(:awsm).find_app_deployment(sso_account[:id])
118
+ unless app_deployment_hash
119
+ actor(:awsm).create_app_deployment(sso_account[:id], "myapp", "myenv", "production")
120
+ app_deployment_hash = actor(:awsm).find_app_deployment(sso_account[:id])
121
+ end
122
+ app_deployment_hash
123
+ end
124
+
125
+ def provisioned_service
126
+ service_account_hash = self.service_account
127
+ sso_account_hash = service_account_hash[:sso_account]
128
+ app_deployment_hash = self.app_deployment
129
+ provisioned_service_hash = actor(:tresfiestas).find_provisioned_service(service_account_hash[:id], app_deployment_hash[:id])
130
+ unless provisioned_service_hash
131
+ actor(:awsm).provision_service(sso_account_hash[:id], service_account_hash[:id], app_deployment_hash[:id])
132
+ provisioned_service_hash = actor(:tresfiestas).find_provisioned_service(service_account_hash[:id], app_deployment_hash[:id])
133
+ end
134
+ provisioned_service_hash.merge(:service_account => service_account_hash, :app_deployment => app_deployment_hash)
135
+ end
136
+
137
+ def destroy_provisioned_service
138
+ actor(:awsm).deprovision_service(provisioned_service[:id])
139
+ end
140
+
141
+ def latest_invoice
142
+ actor(:tresfiestas).latest_invoice
143
+ end
144
+
145
+ def latest_status_message
146
+ actor(:tresfiestas).latest_status_message
147
+ end
148
+
149
+ def send_message(message_url, message_type, message_subject, message_body = nil)
150
+ actor(:service_provider).send_message(message_url, message_type, message_subject, message_body)
151
+ end
152
+
153
+ def send_invoice(invoices_url, total_amount_cent, line_item_description)
154
+ actor(:service_provider).send_invoice(invoices_url, total_amount_cent, line_item_description)
155
+ end
156
+
157
+ end
158
+ end
@@ -0,0 +1,155 @@
1
+ require 'sinatra/base'
2
+
3
+ module EyServicesFake
4
+ class MockingBirdService
5
+ class Application < Sinatra::Base
6
+ enable :raise_errors
7
+ disable :dump_errors
8
+ disable :show_exceptions
9
+
10
+ delete '/api/1/some_provisioned_service' do
11
+ if MockingBirdService.service_deprovisioning_handler
12
+ instance_eval(&MockingBirdService.service_deprovisioning_handler)
13
+ else
14
+ {}.to_json
15
+ end
16
+ end
17
+
18
+ delete '/api/1/some_service_account' do
19
+ if MockingBirdService.service_account_cancel_handler
20
+ instance_eval(&MockingBirdService.service_account_cancel_handler)
21
+ else
22
+ {}.to_json
23
+ end
24
+ end
25
+
26
+ post '/api/1/service_accounts_callback' do
27
+ if MockingBirdService.service_account_creation_handler
28
+ instance_eval(&MockingBirdService.service_account_creation_handler)
29
+ else
30
+ service_account = EY::ServicesAPI::ServiceAccountCreation.from_request(request.body.read)
31
+ standard_response_params = MockingBirdService.service_account_creation_params
32
+ EY::ServicesAPI::ServiceAccountResponse.new(
33
+ :provisioned_services_url => standard_response_params[:provisioned_services_url],
34
+ :url => standard_response_params[:url],
35
+ :configuration_url => standard_response_params[:configuration_url],
36
+ :configuration_required => standard_response_params[:configuration_required],
37
+ :message => EY::ServicesAPI::Message.new(:message_type => "status", :subject => "some messages")
38
+ ).to_hash.to_json
39
+ end
40
+ end
41
+
42
+ post '/api/1/provisioned_services_callback' do
43
+ if MockingBirdService.service_provisioning_handler
44
+ instance_eval(&MockingBirdService.service_provisioning_handler)
45
+ else
46
+ provisioned_service = EY::ServicesAPI::ProvisionedServiceCreation.from_request(request.body.read)
47
+ standard_response_params = MockingBirdService.service_provisioned_params
48
+ EY::ServicesAPI::ProvisionedServiceResponse.new(
49
+ :url => standard_response_params[:url],
50
+ :vars => standard_response_params[:vars],
51
+ :configuration_required => false,
52
+ :configuration_url => standard_response_params[:configuration_url],
53
+ :message => EY::ServicesAPI::Message.new(:message_type => "status", :subject => "some provisioned service messages")
54
+ ).to_hash.to_json
55
+ end
56
+ end
57
+
58
+ get '/sso/some_service_account' do
59
+ "SSO Hello Service Account"
60
+ end
61
+
62
+ get '/sso/some_provisioned_service' do
63
+ "SSO Hello Provisioned Service"
64
+ end
65
+ end
66
+
67
+ class << self
68
+ attr_accessor :service_account_creation_handler
69
+ attr_accessor :service_provisioning_handler
70
+ attr_accessor :service_deprovisioning_handler
71
+ attr_accessor :service_account_cancel_handler
72
+ end
73
+
74
+ def reset!
75
+ MockingBirdService.service_account_creation_handler = nil
76
+ MockingBirdService.service_provisioning_handler = nil
77
+ MockingBirdService.service_deprovisioning_handler = nil
78
+ MockingBirdService.service_account_cancel_handler = nil
79
+ end
80
+
81
+ def app
82
+ Application
83
+ end
84
+
85
+ def setup(auth_id, auth_key, base_url = nil, backend = nil)
86
+ require 'ey_services_api'
87
+ connection = EY::ServicesAPI.setup!(:auth_id => auth_id, :auth_key => auth_key)
88
+ if backend
89
+ connection.backend = backend
90
+ end
91
+ end
92
+
93
+ def base_url
94
+ self.class.base_url
95
+ end
96
+ def self.base_url
97
+ "http://mock.service/"
98
+ end
99
+
100
+ def registration_params
101
+ self.class.registration_params
102
+ end
103
+ def self.registration_params
104
+ {
105
+ :name => "Mocking Bird",
106
+ :label => "mocking_bird",
107
+ :description => "a mock service",
108
+ :service_accounts_url => "#{base_url}api/1/service_accounts_callback",
109
+ :home_url => "#{base_url}",
110
+ :terms_and_conditions_url => "#{base_url}terms",
111
+ :vars => ["some_var", "other_var"]
112
+ }
113
+ end
114
+
115
+ def service_account_creation_params
116
+ self.class.service_account_creation_params
117
+ end
118
+ def self.service_account_creation_params
119
+ {
120
+ :provisioned_services_url => "#{base_url}api/1/provisioned_services_callback",
121
+ :url => "#{base_url}api/1/some_service_account",
122
+ :configuration_url => "#{base_url}sso/some_service_account",
123
+ :configuration_required => false
124
+ }
125
+ end
126
+
127
+ def service_provisioned_params
128
+ self.class.service_provisioned_params
129
+ end
130
+ def self.service_provisioned_params
131
+ {
132
+ :vars => {"some_var" => "value", "other_var" => "blah"},
133
+ :configuration_url => "#{base_url}sso/some_provisioned_service",
134
+ :configuration_required => false,
135
+ :url => "#{base_url}api/1/some_provisioned_service",
136
+ }
137
+ end
138
+
139
+ def register_service(registration_url)
140
+ EY::ServicesAPI.connection.register_service(registration_url, MockingBirdService.registration_params)
141
+ end
142
+
143
+ def send_message(message_url, message_type, message_subject, message_body)
144
+ message = EY::ServicesAPI::Message.new(:message_type => message_type, :subject => message_subject, :body => message_body)
145
+ EY::ServicesAPI.connection.send_message(message_url, message)
146
+ end
147
+
148
+ def send_invoice(invoices_url, total_amount_cent, line_item_description)
149
+ invoice = EY::ServicesAPI::Invoice.new(:total_amount_cents => total_amount_cent,
150
+ :line_item_description => line_item_description)
151
+ EY::ServicesAPI.connection.send_invoice(invoices_url, invoice)
152
+ end
153
+
154
+ end
155
+ end
@@ -0,0 +1,74 @@
1
+ require 'cubbyhole/base'
2
+
3
+ module EyServicesFake
4
+ class Model < Cubbyhole::Base
5
+ def self.inherited(klass)
6
+ decendants << klass
7
+ end
8
+ class << self
9
+ attr_accessor :current_id
10
+ end
11
+ self.current_id = 0
12
+ def self.next_id
13
+ Model.current_id += 1
14
+ end
15
+ def self.nuke_all
16
+ decendants.map(&:nuke)
17
+ end
18
+ def self.backend
19
+ @backend ||= Hash.new
20
+ end
21
+ def self.decendants
22
+ @decendants ||= []
23
+ end
24
+ def self.belongs_to(model, name, key)
25
+ search_context = self.to_s.split("::")
26
+ search_context.pop
27
+ search_context = eval(search_context.join("::").to_s)
28
+ self.class_eval do
29
+ define_method(name) do
30
+ klass = search_context.const_get(model)
31
+ klass.all.find{|s| self.send(key).to_i == s.id.to_i }
32
+ end
33
+ end
34
+ end
35
+ def self.has_many(model, name, key)
36
+ search_context = self.to_s.split("::")
37
+ search_context.pop
38
+ search_context = eval(search_context.join("::").to_s)
39
+ self.class_eval do
40
+ define_method(name) do
41
+ klass = search_context.const_get(model)
42
+ Cubbyhole::Collection.new(klass.all.select{|s| s.send(key).to_s == self.id.to_s })
43
+ end
44
+ end
45
+ end
46
+ end
47
+ class Partner < Model
48
+ has_many :Service, :services, :partner_id
49
+ end
50
+ class Service < Model
51
+ has_many :ServiceEnablement, :service_enablements, :service_id
52
+ has_many :ServiceAccount, :service_accounts, :service_id
53
+ belongs_to :Partner, :partner, :partner_id
54
+ end
55
+ class ServiceAccount < Model
56
+ has_many :ProvisionedService, :provisioned_services, :service_account_id
57
+ has_many :Message, :messages, :service_account_id
58
+ belongs_to :Service, :service, :service_id
59
+ has_many :Invoice, :invoices, :service_account_id
60
+ end
61
+ class ProvisionedService < Model
62
+ has_many :Message, :messages, :provisioned_service_id
63
+ belongs_to :ServiceAccount, :service_account, :service_account_id
64
+ end
65
+ class ServiceEnablement < Model; end
66
+ class Invoice < Model
67
+ belongs_to :ServiceAccount, :service_account, :service_account_id
68
+ end
69
+ class Message < Model
70
+ belongs_to :ServiceAccount, :service_account, :service_account_id
71
+ belongs_to :ProvisionedService, :provisioned_service, :provisioned_service_id
72
+ end
73
+ class Awsm < Model; end
74
+ end
@@ -0,0 +1,162 @@
1
+ require 'sinatra/base'
2
+ require 'ey_services_fake/models'
3
+
4
+ module EyServicesFake
5
+ class ReacharoundAwsm
6
+ class Application < Sinatra::Base
7
+ enable :raise_errors
8
+ disable :dump_errors
9
+ disable :show_exceptions
10
+
11
+ post '/dashboard_notifications_url' do
12
+ {}.to_json
13
+ end
14
+
15
+ end
16
+
17
+ def app
18
+ Application
19
+ end
20
+
21
+ def reset!
22
+ #no-op
23
+ end
24
+
25
+ def base_url
26
+ "http://cloud.engineyard.com"
27
+ end
28
+
29
+ class Account < EyServicesFake::Model; end
30
+ class AppDeployment < EyServicesFake::Model
31
+ belongs_to :App, :app, :app_id
32
+ belongs_to :Environment, :environment, :environment_id
33
+ end
34
+ class App < EyServicesFake::Model; end
35
+ class Environment < EyServicesFake::Model; end
36
+ class User < EyServicesFake::Model
37
+ has_many :Account, :accounts, :owner_id
38
+ end
39
+
40
+ def service_provider_setup(auth_id, auth_key, service_provider_url, service_provider_rackapp)
41
+ @connection = EY::ApiHMAC::AuthedConnection.new(auth_id, auth_key).tap{|c| c.backend = service_provider_rackapp}
42
+ end
43
+ def setup(auth_id, auth_key, tresfiestas_url, tresfiestas_rackapp)
44
+ #ignored... we don't talk to tresfiestas, we talk to service_provider
45
+ end
46
+
47
+ def sso_user
48
+ the_one_email = "the-one-user@example.com"
49
+ User.first(:email => the_one_email) || User.create(:email => the_one_email)
50
+ end
51
+
52
+ def find_sso_account(sso_user)
53
+ account = sso_user.accounts.first
54
+ account && {
55
+ :id => account.id,
56
+ :name => account.name,
57
+ }
58
+ end
59
+ def create_sso_account(sso_user)
60
+ Account.create(:owner_id => sso_user.id, :name => 'some-account')
61
+ find_sso_account(sso_user)
62
+ end
63
+
64
+ def find_app_deployment(sso_account_id)
65
+ app_deployment = AppDeployment.first(:account_id => sso_account_id)
66
+ app_deployment && {
67
+ :id => app_deployment.id,
68
+ :app => {
69
+ :id => app_deployment.app.id,
70
+ :name => app_deployment.app.name,
71
+ },
72
+ :environment => {
73
+ :id => app_deployment.environment.id,
74
+ :name => app_deployment.environment.name,
75
+ :framework_env => app_deployment.environment.framework_env,
76
+ :aws_region => app_deployment.environment.aws_region
77
+ }
78
+ }
79
+ end
80
+ def create_app_deployment(sso_account_id, app_name, env_name, framework_env)
81
+ app = App.create(:name => app_name)
82
+ env = Environment.create(:name => env_name, :framework_env => framework_env, :aws_region => 'us-east-1')
83
+ AppDeployment.create(:account_id => sso_account_id, :app_id => app.id, :environment_id => env.id)
84
+ end
85
+
86
+ #Normal implmentations of AWSM would not be posting to service_accounts_url;
87
+ #they would be posting to private API to say that they wish to create a service account
88
+ #but this is reacharound AWSM, and so it plays the role of tresfiestas internals here
89
+ # def enable_service(connection, sso_account, service_hash)
90
+ def enable_service(service_id, sso_account_id)
91
+ url_gen = EyServicesFake::URL_GEN
92
+ service_account = ServiceAccount.create(:sso_account_id => sso_account_id, :active => false, :service_id => service_id, :dashboard_notifications_url => "#{base_url}/dashboard_notifications_url")
93
+ service = Service.get(service_id)
94
+ creation_attributes = {
95
+ :name => Account.get(sso_account_id).name,
96
+ :url => url_gen.partner_service_account(service, service_account),
97
+ :messages_url => url_gen.messages(service, service_account),
98
+ :invoices_url => url_gen.invoices(service, service_account),
99
+ }
100
+ @connection.post(service.service_accounts_url, creation_attributes) do |result, location|
101
+ service_account.active = true
102
+ if result["service_account"]
103
+ service_account.provisioned_services_url = result["service_account"]['provisioned_services_url']
104
+ service_account.configuration_url = result["service_account"]['configuration_url']
105
+ service_account.url = result["service_account"]['url']
106
+ service_account.configuration_required = result["service_account"]['configuration_required']
107
+ end
108
+ if result["message"] && result["message"]["message_type"]
109
+ Message.create(
110
+ :service_account_id => service_account.id,
111
+ :message_type => result["message"]["message_type"],
112
+ :subject => result["message"]["subject"],
113
+ :body => result["message"]["body"])
114
+ end
115
+ service_account.save
116
+ end
117
+ end
118
+
119
+ def disable_service(service_account_id)
120
+ service_account = ServiceAccount.get(service_account_id)
121
+ @connection.delete(service_account.url)
122
+ end
123
+
124
+ def provision_service(sso_account_id, service_account_id, app_deployment_id)
125
+ url_gen = EyServicesFake::URL_GEN
126
+ provisioned_service = ProvisionedService.create(:app_deployment_id => app_deployment_id.to_i, :active => false, :service_account_id => service_account_id.to_i, :dashboard_notifications_url => "#{base_url}/dashboard_notifications_url")
127
+ service_account_object = ServiceAccount.get(service_account_id)
128
+ app_deployment = AppDeployment.get(app_deployment_id)
129
+ app = app_deployment.app
130
+ environment = app_deployment.environment
131
+ provision_attribtues = {
132
+ :url => url_gen.partner_provisioned_service(service_account_object, provisioned_service),
133
+ :messages_url => url_gen.messages(service_account_object.service, service_account_object, provisioned_service),
134
+ :app => {:id => app.id, :name => app.name},
135
+ :environment => {:id => environment.id, :name => environment.name, :framework_env => environment.framework_env, :aws_region => environment.aws_region},
136
+ }
137
+ @connection.post(service_account_object.provisioned_services_url, provision_attribtues) do |result, location|
138
+ provisioned_service.active = true
139
+ if result['provisioned_service']
140
+ provisioned_service.vars = result['provisioned_service']["vars"]
141
+ provisioned_service.configuration_url = result['provisioned_service']["configuration_url"]
142
+ provisioned_service.configuration_required = result['provisioned_service']["configuration_required"]
143
+ provisioned_service.url = result['provisioned_service']["url"]
144
+ if result["message"] && result["message"]["message_type"]
145
+ Message.create(
146
+ :provisioned_service_id => provisioned_service.id,
147
+ :message_type => result["message"]["message_type"],
148
+ :subject => result["message"]["subject"],
149
+ :body => result["message"]["body"])
150
+ end
151
+ end
152
+ provisioned_service.save
153
+ end
154
+ end
155
+
156
+ def deprovision_service(provisioned_service_id)
157
+ provisioned_service = ProvisionedService.get(provisioned_service_id)
158
+ @connection.delete(provisioned_service.url)
159
+ end
160
+
161
+ end
162
+ end
@@ -0,0 +1,137 @@
1
+ require 'ey_services_fake/url_generator'
2
+ require 'ey_services_fake/models'
3
+ require 'ey_services_fake/tresfiestas_fake_rack_app'
4
+
5
+ module EyServicesFake
6
+ BASE_URL = "http://services.engineyard.com"
7
+ URL_GEN = EyServicesFake::UrlGenerator.new(BASE_URL)
8
+
9
+ class TresfiestasFake
10
+
11
+ def reset!
12
+ Model.nuke_all
13
+ end
14
+
15
+ def base_url
16
+ BASE_URL
17
+ end
18
+
19
+ def app
20
+ TresfiestasFakeRackApp
21
+ end
22
+
23
+ def find_awsm
24
+ awsm_object = Awsm.first
25
+ awsm_object && {
26
+ :id => awsm_object.id,
27
+ :auth_id => awsm_object.auth_id,
28
+ :auth_key => awsm_object.auth_key,
29
+ }
30
+ end
31
+
32
+ def create_awsm(awsm_base_url, awsm_app)
33
+ Awsm.create(:auth_id => "789eef", :auth_key => "009abb")
34
+ app.awsm_connection = EY::ApiHMAC::AuthedConnection.new("789eef", "009abb")
35
+ app.awsm_connection.backend = awsm_app
36
+ find_awsm
37
+ end
38
+
39
+ def find_partner(sso_user)
40
+ partner_object = Partner.first
41
+ partner_object && {
42
+ :id => partner_object.id,
43
+ :name => partner_object.name,
44
+ :auth_id => partner_object.auth_id,
45
+ :auth_key => partner_object.auth_key,
46
+ :registration_url => URL_GEN.service_registration(partner_object),
47
+ }
48
+ end
49
+
50
+ def create_partner(sso_user, partner_base_url, partner_app)
51
+ Partner.create(:auth_id => "123edf", :auth_key => "abc456", :name => "Some-Partner")
52
+ app.partner_connection = EY::ApiHMAC::AuthedConnection.new("123edf", "abc456")
53
+ app.partner_connection.backend = partner_app
54
+ find_partner(sso_user)
55
+ end
56
+
57
+ def find_service(partner_id)
58
+ partner_object = Partner.get!(partner_id)
59
+ service_object = partner_object.services.first
60
+ service_object && {
61
+ :id => service_object.id,
62
+ :name => service_object.name,
63
+ :label => service_object.label,
64
+ :revenue_share => service_object.revenue_share,
65
+ :service_accounts_url => service_object.service_accounts_url
66
+ }
67
+ end
68
+
69
+ def service_available_for_account?(service_id, sso_account_id)
70
+ Service.get(service_id).service_enablements.first(:sso_account_id => sso_account_id.to_s)
71
+ end
72
+
73
+ def make_service_available_for_account(service_id, sso_account_id, reason = "test")
74
+ ServiceEnablement.create(:service_id => service_id.to_i, :sso_account_id => sso_account_id.to_s, :reason => reason)
75
+ end
76
+
77
+ def find_service_account(service_id, sso_account_id)
78
+ service_object = Service.get(service_id)
79
+ service_account_object = service_object.service_accounts.first(:sso_account_id => sso_account_id.to_s)
80
+ service_account_object && {
81
+ :id => service_account_object.id,
82
+ :url => URL_GEN.partner_service_account(service_object, service_account_object),
83
+ :messages_url => URL_GEN.messages(service_object, service_account_object),
84
+ :invoices_url => URL_GEN.invoices(service_object, service_account_object),
85
+ :pushed_service_account => {
86
+ :provisioned_services_url => service_account_object.provisioned_services_url,
87
+ :configuration_url => service_account_object.configuration_url,
88
+ :url => service_account_object.url,
89
+ :configuration_required => service_account_object.configuration_required,
90
+ }
91
+ }
92
+ end
93
+
94
+ def find_provisioned_service(service_account_id, app_deployment_id)
95
+ service_account = ServiceAccount.get(service_account_id)
96
+ provisioned_service = service_account.provisioned_services.first(:app_deployment_id => app_deployment_id)
97
+ provisioned_service && {
98
+ :id => provisioned_service.id,
99
+ :url => URL_GEN.partner_provisioned_service(service_account, provisioned_service),
100
+ :messages_url => URL_GEN.messages(service_account.service, service_account, provisioned_service),
101
+ :pushed_provisioned_service => {
102
+ :vars => provisioned_service.vars,
103
+ :configuration_url => provisioned_service.configuration_url,
104
+ :configuration_required => provisioned_service.configuration_required,
105
+ :url => provisioned_service.url
106
+ }
107
+ }
108
+ end
109
+
110
+ def latest_invoice
111
+ invoice = Invoice.last
112
+ {
113
+ :total_amount_cents => invoice.total_amount_cents,
114
+ :line_item_description => invoice.line_item_description,
115
+ :service_account_id => invoice.service_account_id,
116
+ }
117
+ end
118
+
119
+ def latest_status_message
120
+ if message = Message.last(:message_type => "status")
121
+ to_return = {
122
+ :id => message.id,
123
+ :subject => message.subject,
124
+ :body => message.body
125
+ }
126
+ if message.respond_to?(:service_account) && message.service_account
127
+ to_return[:service_account_id] = message.service_account.id
128
+ end
129
+ if message.respond_to?(:provisioned_service) && message.provisioned_service
130
+ to_return[:provisioned_service_id] = message.provisioned_service.id
131
+ end
132
+ to_return
133
+ end
134
+ end
135
+
136
+ end
137
+ end
@@ -0,0 +1,160 @@
1
+ require 'sinatra/base'
2
+
3
+ module EyServicesFake
4
+ class TresfiestasFakeRackApp < Sinatra::Base
5
+ enable :raise_errors
6
+ disable :dump_errors
7
+ disable :show_exceptions
8
+
9
+ class << self
10
+ attr_accessor :partner_connection
11
+ attr_accessor :awsm_connection
12
+ end
13
+
14
+ ################
15
+ # External API #
16
+ ################
17
+
18
+ get '/api/1/partners/:partner_id/services' do |partner_id|
19
+ partner = Partner.get!(partner_id)
20
+ to_return = []
21
+ partner.services.each do |service|
22
+ to_return << {"service" => service.attributes.merge('url' => URL_GEN.service(service)) }
23
+ end
24
+ to_return.to_json
25
+ end
26
+
27
+ #TODO: auth!
28
+ post '/api/1/partners/:partner_id/services' do |partner_id|
29
+ partner = Partner.get!(partner_id)
30
+ service_json = JSON.parse(request.body.read)["service"]
31
+ if service_json["name"].to_s.empty?
32
+ status 400
33
+ {:error_messages => ["Name can't be blank"]}.to_json
34
+ else
35
+ service = Service.create(service_json.merge(:partner_id => partner.id, :revenue_share => 0.3))
36
+ status 201
37
+ headers 'Location' => URL_GEN.service(service)
38
+ {}.to_json
39
+ end
40
+ end
41
+
42
+ get '/api/1/partners/:partner_id/services/:service_id' do |partner_id, service_id|
43
+ partner = Partner.get!(partner_id)
44
+ if service = partner.services.detect{ |s| s.id.to_s == service_id.to_s }
45
+ {"service" => service.attributes}.to_json
46
+ else
47
+ status 404
48
+ {}.to_json
49
+ end
50
+ end
51
+
52
+ put '/api/1/partners/:partner_id/services/:service_id' do |partner_id, service_id|
53
+ partner = Partner.get!(partner_id)
54
+ service = partner.services.detect{ |s| s.id.to_s == service_id.to_s }
55
+ update_params = JSON.parse(request.body.read)["service"]
56
+ if update_params.key?("name") && update_params["name"].to_s.empty?
57
+ status 400
58
+ {:error_messages => ["Name can't be blank"]}.to_json
59
+ else
60
+ service.update_attributes(update_params)
61
+ {}.to_json
62
+ end
63
+ end
64
+
65
+ delete '/api/1/partners/:partner_id/services/:service_id' do |partner_id, service_id|
66
+ partner = Partner.get!(partner_id)
67
+ service = partner.services.detect{ |s| s.id.to_s == service_id.to_s }
68
+ service.destroy
69
+ {}.to_json
70
+ end
71
+
72
+ put '/api/1/partners/:partner_id/services/:service_id/service_accounts/:service_account_id' do |partner_id, service_id, service_account_id|
73
+ partner = Partner.get!(partner_id)
74
+ service = partner.services.detect{ |s| s.id.to_s == service_id.to_s }
75
+ service_account = service.service_accounts.detect{ |sa| sa.id.to_s == service_account_id.to_s }
76
+ service_account_atts = JSON.parse(request.body.read)["service_account"]
77
+ service_account.update_attributes(service_account_atts)
78
+ {}.to_json
79
+ end
80
+
81
+ put '/api/1/service_accounts/:service_account_id/provisioned_service/:provisioned_service_id' do |service_account_id, provisioned_service_id|
82
+ service_account = ServiceAccount.get!(service_account_id)
83
+ provisioned_service = service_account.provisioned_services.detect{ |ps| ps.id.to_s == provisioned_service_id.to_s}
84
+ atts = JSON.parse(request.body.read)["provisioned_service"]
85
+ provisioned_service.update_attributes(atts)
86
+ {}.to_json
87
+ end
88
+
89
+ post '/api/1/partners/:partner_id/services/:service_id/service_accounts/:service_account_id/invoices' do |partner_id, service_id, service_account_id|
90
+ invoice_params = JSON.parse(request.body.read)["invoice"]
91
+ unless invoice_params['total_amount_cents'].is_a?(Fixnum)
92
+ status 400
93
+ return {:error_messages => ["Total Amount Cents must be an integer"]}.to_json
94
+ end
95
+ if invoice_params["line_item_description"].to_s.empty?
96
+ status 400
97
+ return {:error_messages => ["Line item description can't be blank"]}.to_json
98
+ end
99
+ if invoice_params['total_amount_cents'] < 0
100
+ status 400
101
+ return {:error_messages => ["Total amount cents must be greater than or equal to 0"]}.to_json
102
+ end
103
+ Invoice.create(invoice_params.merge(:service_account_id => service_account_id.to_i))
104
+ {}.to_json
105
+ end
106
+
107
+ post '/api/1/partners/:partner_id/services/:service_id/service_accounts/:service_account_id/messages' do |partner_id, service_id, service_account_id|
108
+ message_params = JSON.parse(request.body.read)["message"]
109
+ message_type = message_params['message_type']
110
+ subject = message_params['subject']
111
+
112
+ if subject.to_s.empty?
113
+ status 400
114
+ return {:error_messages => ["Subject can't be blank."]}.to_json
115
+ end
116
+
117
+ unless ['status', 'notification', 'alert'].include? message_type
118
+ status 400
119
+ return {:error_messages => ['Message type must be one of: status, notification or alert']}.to_json
120
+ end
121
+
122
+ service_account = ServiceAccount.get(service_account_id)
123
+ message = Message.create(message_params.merge(:service_account_id => service_account.id))
124
+ forward_service_account_message_to_awsm(service_account, message)
125
+ {}.to_json
126
+ end
127
+
128
+ def forward_service_account_message_to_awsm(service_account, message)
129
+ #no-op
130
+ end
131
+
132
+ post '/api/1/partners/:partner_id/services/:service_id/service_accounts/:service_account_id/provisioned_service/:provisioned_service_id/messages' do |partner_id, service_id, service_account_id, provisioned_service_id|
133
+ message_params = JSON.parse(request.body.read)["message"]
134
+ subject = message_params['subject']
135
+ message_type = message_params['message_type']
136
+
137
+ if subject.to_s.empty?
138
+ status 400
139
+ return {:error_messages => ["Subject can't be blank."]}.to_json
140
+ end
141
+
142
+ unless ['status', 'notification', 'alert'].include? message_type
143
+ status 400
144
+ return {:error_messages => ['Message type must be one of: status, notification or alert']}.to_json
145
+ end
146
+
147
+ message = Message.create(message_params.merge(:provisioned_service_id => provisioned_service_id.to_i))
148
+ provisioned_service = ProvisionedService.get(provisioned_service_id)
149
+ service_account = provisioned_service.service_account
150
+ message = Message.create(message_params.merge(:provisioned_service_id => provisioned_service.id))
151
+ forward_provisioned_service_message_to_awsm(provisioned_service, message)
152
+ {}.to_json
153
+ end
154
+
155
+ def forward_provisioned_service_message_to_awsm(provisioned_service, message)
156
+ #no-op
157
+ end
158
+
159
+ end
160
+ end
@@ -0,0 +1,37 @@
1
+ module EyServicesFake
2
+ class UrlGenerator
3
+
4
+ def initialize(base_url)
5
+ @base_url = base_url
6
+ end
7
+
8
+ def service_registration(partner)
9
+ "#{@base_url}/api/1/partners/#{partner.id}/services"
10
+ end
11
+
12
+ def service(service)
13
+ "#{@base_url}/api/1/partners/#{service.partner_id}/services/#{service.id}"
14
+ end
15
+
16
+ def partner_service_account(service, service_account)
17
+ "#{@base_url}/api/1/partners/#{service.partner_id}/services/#{service.id}/service_accounts/#{service_account.id}"
18
+ end
19
+
20
+ def messages(service, service_account, provisioned_service = nil)
21
+ if provisioned_service
22
+ "#{@base_url}/api/1/partners/#{service.partner_id}/services/#{service.id}/service_accounts/#{service_account.id}/provisioned_service/#{provisioned_service.id}/messages"
23
+ else
24
+ "#{@base_url}/api/1/partners/#{service.partner_id}/services/#{service.id}/service_accounts/#{service_account.id}/messages"
25
+ end
26
+ end
27
+
28
+ def invoices(service, service_account)
29
+ "#{@base_url}/api/1/partners/#{service.partner_id}/services/#{service.id}/service_accounts/#{service_account.id}/invoices"
30
+ end
31
+
32
+ def partner_provisioned_service(service_account, provisioned_service)
33
+ "#{@base_url}/api/1/service_accounts/#{service_account.id}/provisioned_service/#{provisioned_service.id}"
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,3 @@
1
+ module EyServicesFake
2
+ VERSION = "0.3.4"
3
+ end
@@ -1,5 +1,5 @@
1
1
  module EY
2
2
  module ServicesAPI
3
- VERSION = "0.3.3"
3
+ VERSION = "0.3.4"
4
4
  end
5
5
  end
data/script/ci CHANGED
@@ -8,9 +8,6 @@ case "$1" in
8
8
  "internal")
9
9
  echo "running internal tests"
10
10
  export BUNDLE_GEMFILE=EYIntegratedGemfile
11
- export LANG="en_US.utf-8"
12
- source use_ruby.sh
13
- use_ruby 1.9.2
14
11
  ;;
15
12
  "public")
16
13
  echo "running public tests"
metadata CHANGED
@@ -1,78 +1,59 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: ey_services_api
3
- version: !ruby/object:Gem::Version
4
- hash: 21
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.4
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 3
9
- - 3
10
- version: 0.3.3
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Jacob & Thorben & David & mkb & Josh & Others
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2012-03-02 00:00:00 Z
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
12
+ date: 2012-03-02 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
21
15
  name: rspec
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: &70182942688180 !ruby/object:Gem::Requirement
24
17
  none: false
25
- requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- hash: 3
29
- segments:
30
- - 0
31
- version: "0"
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
32
22
  type: :development
33
- version_requirements: *id001
34
- - !ruby/object:Gem::Dependency
35
- name: json
36
23
  prerelease: false
37
- requirement: &id002 !ruby/object:Gem::Requirement
24
+ version_requirements: *70182942688180
25
+ - !ruby/object:Gem::Dependency
26
+ name: json
27
+ requirement: &70182942686540 !ruby/object:Gem::Requirement
38
28
  none: false
39
- requirements:
40
- - - ">="
41
- - !ruby/object:Gem::Version
42
- hash: 3
43
- segments:
44
- - 0
45
- version: "0"
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
46
33
  type: :runtime
47
- version_requirements: *id002
48
- - !ruby/object:Gem::Dependency
49
- name: ey_api_hmac
50
34
  prerelease: false
51
- requirement: &id003 !ruby/object:Gem::Requirement
35
+ version_requirements: *70182942686540
36
+ - !ruby/object:Gem::Dependency
37
+ name: ey_api_hmac
38
+ requirement: &70182942685240 !ruby/object:Gem::Requirement
52
39
  none: false
53
- requirements:
54
- - - ">="
55
- - !ruby/object:Gem::Version
56
- hash: 19
57
- segments:
58
- - 0
59
- - 3
60
- - 0
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
61
43
  version: 0.3.0
62
44
  type: :runtime
63
- version_requirements: *id003
45
+ prerelease: false
46
+ version_requirements: *70182942685240
64
47
  description: API for Partner Services (talks to services.engineyard.com)
65
- email:
48
+ email:
66
49
  - jacob@engineyard.com
67
50
  executables: []
68
-
69
51
  extensions: []
70
-
71
52
  extra_rdoc_files: []
72
-
73
- files:
53
+ files:
74
54
  - .gitignore
75
55
  - .rspec
56
+ - .rvmrc
76
57
  - CHANGELOG
77
58
  - EYIntegratedGemfile
78
59
  - Gemfile
@@ -81,6 +62,15 @@ files:
81
62
  - Rakefile
82
63
  - ci.yml
83
64
  - ey_services_api.gemspec
65
+ - fake/ey_services_fake.gemspec
66
+ - fake/lib/ey_services_fake/mock_backend.rb
67
+ - fake/lib/ey_services_fake/mocking_bird_service.rb
68
+ - fake/lib/ey_services_fake/models.rb
69
+ - fake/lib/ey_services_fake/reacharound_awsm.rb
70
+ - fake/lib/ey_services_fake/tresfiestas_fake.rb
71
+ - fake/lib/ey_services_fake/tresfiestas_fake_rack_app.rb
72
+ - fake/lib/ey_services_fake/url_generator.rb
73
+ - fake/lib/ey_services_fake/version.rb
84
74
  - lib/ey_services_api.rb
85
75
  - lib/ey_services_api/api_struct.rb
86
76
  - lib/ey_services_api/connection.rb
@@ -100,40 +90,31 @@ files:
100
90
  - spec/service_account_creation_spec.rb
101
91
  - spec/service_spec.rb
102
92
  - spec/spec_helper.rb
103
- homepage: ""
93
+ homepage: ''
104
94
  licenses: []
105
-
106
95
  post_install_message:
107
96
  rdoc_options: []
108
-
109
- require_paths:
97
+ require_paths:
110
98
  - lib
111
- required_ruby_version: !ruby/object:Gem::Requirement
99
+ required_ruby_version: !ruby/object:Gem::Requirement
112
100
  none: false
113
- requirements:
114
- - - ">="
115
- - !ruby/object:Gem::Version
116
- hash: 3
117
- segments:
118
- - 0
119
- version: "0"
120
- required_rubygems_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ! '>='
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
121
106
  none: false
122
- requirements:
123
- - - ">="
124
- - !ruby/object:Gem::Version
125
- hash: 3
126
- segments:
127
- - 0
128
- version: "0"
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
129
111
  requirements: []
130
-
131
112
  rubyforge_project: ey_services_api
132
- rubygems_version: 1.8.10
113
+ rubygems_version: 1.8.12
133
114
  signing_key:
134
115
  specification_version: 3
135
116
  summary: API for Partner Services (talks to services.engineyard.com)
136
- test_files:
117
+ test_files:
137
118
  - spec/invoice_spec.rb
138
119
  - spec/message_spec.rb
139
120
  - spec/provisioned_service_creation_spec.rb