ey_services_api 0.3.3 → 0.3.4

Sign up to get free protection for your applications and to get access to all the features.
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