squall 0.0.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. data/.gitignore +10 -0
  2. data/.rspec +2 -0
  3. data/.rvmrc +1 -0
  4. data/.travis.yml +7 -0
  5. data/Gemfile +3 -0
  6. data/Gemfile.lock +100 -0
  7. data/LICENSE +1 -1
  8. data/README.md +69 -0
  9. data/Rakefile +48 -42
  10. data/lib/squall/base.rb +96 -0
  11. data/lib/squall/config.rb +26 -0
  12. data/lib/squall/exception.rb +13 -0
  13. data/lib/squall/hypervisor.rb +46 -16
  14. data/lib/squall/ip_address.rb +13 -0
  15. data/lib/squall/network.rb +42 -0
  16. data/lib/squall/params.rb +50 -0
  17. data/lib/squall/role.rb +56 -0
  18. data/lib/squall/statistic.rb +10 -0
  19. data/lib/squall/template.rb +22 -0
  20. data/lib/squall/transaction.rb +16 -0
  21. data/lib/squall/user.rb +87 -0
  22. data/lib/squall/version.rb +3 -0
  23. data/lib/squall/virtual_machine.rb +169 -41
  24. data/lib/squall.rb +76 -20
  25. data/spec/params_spec.rb +195 -0
  26. data/spec/spec_helper.rb +47 -0
  27. data/spec/squall/base_spec.rb +135 -0
  28. data/spec/squall/config_spec.rb +44 -0
  29. data/spec/squall/hypervisor_spec.rb +143 -0
  30. data/spec/squall/ip_address_spec.rb +32 -0
  31. data/spec/squall/network_spec.rb +121 -0
  32. data/spec/squall/role_spec.rb +123 -0
  33. data/spec/squall/statistic_spec.rb +23 -0
  34. data/spec/squall/template_spec.rb +59 -0
  35. data/spec/squall/transaction_spec.rb +42 -0
  36. data/spec/squall/user_spec.rb +195 -0
  37. data/spec/squall/virtual_machine_spec.rb +471 -0
  38. data/spec/squall_spec.rb +67 -0
  39. data/spec/vcr_cassettes/hypervisor/create.yml +77 -0
  40. data/spec/vcr_cassettes/hypervisor/delete.yml +77 -0
  41. data/spec/vcr_cassettes/hypervisor/edit.yml +79 -0
  42. data/spec/vcr_cassettes/hypervisor/list.yml +40 -0
  43. data/spec/vcr_cassettes/hypervisor/reboot.yml +77 -0
  44. data/spec/vcr_cassettes/hypervisor/show.yml +77 -0
  45. data/spec/vcr_cassettes/ipaddress/list.yml +77 -0
  46. data/spec/vcr_cassettes/network/create.yml +196 -0
  47. data/spec/vcr_cassettes/network/delete.yml +77 -0
  48. data/spec/vcr_cassettes/network/edit.yml +233 -0
  49. data/spec/vcr_cassettes/network/list.yml +40 -0
  50. data/spec/vcr_cassettes/role/create.yml +77 -0
  51. data/spec/vcr_cassettes/role/delete.yml +77 -0
  52. data/spec/vcr_cassettes/role/edit.yml +139 -0
  53. data/spec/vcr_cassettes/role/list.yml +40 -0
  54. data/spec/vcr_cassettes/role/permissions.yml +40 -0
  55. data/spec/vcr_cassettes/role/show.yml +77 -0
  56. data/spec/vcr_cassettes/statistic/usage_statistics.yml +40 -0
  57. data/spec/vcr_cassettes/template/download.yml +40 -0
  58. data/spec/vcr_cassettes/template/list.yml +40 -0
  59. data/spec/vcr_cassettes/template/make_public.yml +77 -0
  60. data/spec/vcr_cassettes/transaction/list.yml +40 -0
  61. data/spec/vcr_cassettes/transaction/show.yml +77 -0
  62. data/spec/vcr_cassettes/user/activate.yml +40 -0
  63. data/spec/vcr_cassettes/user/create.yml +116 -0
  64. data/spec/vcr_cassettes/user/delete.yml +77 -0
  65. data/spec/vcr_cassettes/user/edit_role.yml +116 -0
  66. data/spec/vcr_cassettes/user/generate_api_key.yml +40 -0
  67. data/spec/vcr_cassettes/user/list.yml +40 -0
  68. data/spec/vcr_cassettes/user/show.yml +77 -0
  69. data/spec/vcr_cassettes/user/stats.yml +40 -0
  70. data/spec/vcr_cassettes/user/suspend.yml +40 -0
  71. data/spec/vcr_cassettes/user/virtual_machines.yml +79 -0
  72. data/spec/vcr_cassettes/virtual_machine/build.yml +77 -0
  73. data/spec/vcr_cassettes/virtual_machine/change_owner.yml +108 -0
  74. data/spec/vcr_cassettes/virtual_machine/change_password.yml +77 -0
  75. data/spec/vcr_cassettes/virtual_machine/create.yml +40 -0
  76. data/spec/vcr_cassettes/virtual_machine/delete.yml +77 -0
  77. data/spec/vcr_cassettes/virtual_machine/edit.yml +77 -0
  78. data/spec/vcr_cassettes/virtual_machine/list.yml +40 -0
  79. data/spec/vcr_cassettes/virtual_machine/migrate.yml +116 -0
  80. data/spec/vcr_cassettes/virtual_machine/reboot.yml +77 -0
  81. data/spec/vcr_cassettes/virtual_machine/resize.yml +77 -0
  82. data/spec/vcr_cassettes/virtual_machine/show.yml +77 -0
  83. data/spec/vcr_cassettes/virtual_machine/shutdown.yml +77 -0
  84. data/spec/vcr_cassettes/virtual_machine/startup.yml +77 -0
  85. data/spec/vcr_cassettes/virtual_machine/stop.yml +77 -0
  86. data/spec/vcr_cassettes/virtual_machine/suspend.yml +77 -0
  87. data/spec/vcr_cassettes/virtual_machine/unlock.yml +77 -0
  88. data/spec/vcr_cassettes/virtual_machine/unsuspend.yml +77 -0
  89. data/squall.gemspec +25 -62
  90. metadata +224 -42
  91. data/.document +0 -5
  92. data/README.rdoc +0 -17
  93. data/VERSION.yml +0 -5
  94. data/lib/squall/client.rb +0 -87
  95. data/test/fixtures/virtual_machines.json +0 -1
  96. data/test/fixtures/virtual_machines_1.json +0 -1
  97. data/test/helper.rb +0 -31
  98. data/test/test_client.rb +0 -152
  99. data/test/test_squall.rb +0 -12
  100. data/test/test_virtual_machine.rb +0 -98
@@ -0,0 +1,10 @@
1
+ module Squall
2
+ # OnApp Statistic
3
+ class Statistic < Base
4
+ # Returns statitics for a given VirtualMachine
5
+ def daily_stats(id)
6
+ response = request(:get, "/usage_statistics.json")
7
+ response.first['vm_hourly_stat']
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,22 @@
1
+ module Squall
2
+ # OnApp Template
3
+ class Template < Base
4
+ # Return a list of available Templates
5
+ def list
6
+ response = request(:get, '/templates.json')
7
+ response.collect { |temp| temp['image_template'] }
8
+ end
9
+
10
+ # Make a Template public so that it can be downloaded
11
+ # via a HTTP url
12
+ def make_public(id)
13
+ response = request(:post, "/templates/#{id}/make_public.json")
14
+ response.first[1]
15
+ end
16
+
17
+ # Download a Template image
18
+ def download(id)
19
+ response = request(:get, "/templates.json?remote_template_id=#{id}")
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,16 @@
1
+ module Squall
2
+ # OnApp Transaction
3
+ class Transaction < Base
4
+ # Returns a list of all Transactions.
5
+ def list
6
+ response = request :get, '/transactions.json'
7
+ response.collect { |t| t['transaction'] }
8
+ end
9
+
10
+ # Return a Hash for the given Transaction
11
+ def show(id)
12
+ response = request :get, "/transactions/#{id}.json"
13
+ response['transaction']
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,87 @@
1
+ module Squall
2
+ # OnApp User
3
+ class User < Base
4
+ # Return a list of all users
5
+ def list
6
+ response = request(:get, '/users.json')
7
+ response.collect { |user| user['user']}
8
+ end
9
+
10
+
11
+ # Create a new User
12
+ #
13
+ # ==== Options
14
+ #
15
+ # * +options+ - Params for creating the User
16
+ #
17
+ # ==== Example
18
+ #
19
+ # create :login => 'bob',
20
+ # :email => 'something@example.com',
21
+ # :password => 'secret',
22
+ # :first_name => 'Bob',
23
+ # :last_name => 'Smith',
24
+ # :group_id => 1
25
+ def create(options = {})
26
+ params.required(:login, :email, :password).accepts(:first_name, :last_name, :group_id).validate!(options)
27
+ request(:post, '/users.json', default_params(options))
28
+ end
29
+
30
+ # Return a Hash of the given User
31
+ def show(id)
32
+ response = request(:get, "/users/#{id}.json")
33
+ response.first[1]
34
+ end
35
+
36
+ # Create a new API Key for a User
37
+ def generate_api_key(id)
38
+ request(:post, "/users/#{id}/make_new_api_key.json")
39
+ end
40
+
41
+ # Suspend a User
42
+ def suspend(id)
43
+ response = request(:get, "/users/#{id}/suspend.json")
44
+ response.first[1]
45
+ end
46
+
47
+ # Activate a user
48
+ def activate(id)
49
+ response = request(:get, "/users/#{id}/activate_user.json")
50
+ response.first[1]
51
+ end
52
+ alias_method :unsuspend, :activate
53
+
54
+ # Delete a user
55
+ def delete(id)
56
+ response = request(:delete, "/users/#{id}.json")
57
+ success
58
+ end
59
+
60
+ # Get the stats for a User
61
+ def stats(id)
62
+ response = request(:get, "/users/#{id}/vm_stats.json")
63
+ response.first['vm_stats']
64
+ end
65
+
66
+ # Return a list of VirtualMachines for a User
67
+ def virtual_machines(id)
68
+ response = request(:get, "/users/#{id}/virtual_machines.json")
69
+ response.collect { |vm| vm['virtual_machine']}
70
+ end
71
+
72
+ # Edit a role for a user
73
+ #
74
+ # ==== Options
75
+ #
76
+ # * +id+ - id of the User
77
+ # * +roles+ - A single Role id or Array of Roles
78
+ #
79
+ # ==== Example
80
+ #
81
+ # edit_role 1, 2 # Role 2
82
+ # edit_role 1, [1,2] # Role 1 & 2
83
+ def edit_role(id, *roles)
84
+ request(:put, "/users/#{id}.json", default_params(:role_ids => roles))
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,3 @@
1
+ module Squall
2
+ VERSION = '1.0.0'
3
+ end
@@ -1,59 +1,187 @@
1
1
  module Squall
2
- class VirtualMachine < Client
3
-
4
- URI_PREFIX = 'virtual_machines'
5
- VALID_PARAMS = [:primary_network_id,
6
- :cpus,
7
- :label,
8
- :cpu_shares,
9
- :template_id,
10
- :swap_disk_size,
11
- :memory,
12
- :required_virtual_machine_build,
13
- :hypervisor_id,
14
- :required_ip_address_assignment,
15
- :rate_limit,
16
- :primary_disk_size,
17
- :hostname,
18
- :initial_root_password ]
19
-
2
+ # OnApp VirtualMachine
3
+ class VirtualMachine < Base
4
+ # Return a list of VirtualMachines
20
5
  def list
21
- if get(URI_PREFIX)
22
- @message.collect { |res| res['virtual_machine'] }
23
- else
24
- []
25
- end
6
+ response = request(:get, '/virtual_machines.json')
7
+ response.collect { |v| v['virtual_machine'] }
26
8
  end
27
9
 
10
+ # Return a Hash for the given VirtualMachine
28
11
  def show(id)
29
- get("#{URI_PREFIX}/#{id}") ? @message['virtual_machine'] : false
12
+ response = request(:get, "/virtual_machines/#{id}.json")
13
+ response.first[1]
30
14
  end
31
15
 
32
- def edit(id, params = {})
33
- valid_options!(VALID_PARAMS, params)
34
- put("#{URI_PREFIX}/#{id}", { :virtual_machine => params })
16
+ # Create a new VirtualMachine
17
+ #
18
+ # ==== Options
19
+ #
20
+ # * +options+ - Params for creating the VirtualMachine
21
+ #
22
+ # ==== Example
23
+ #
24
+ # params = {
25
+ # :label => 'testmachine',
26
+ # :hypervisor_id => 5,
27
+ # :hostname => 'testmachine',
28
+ # :memory => 512,
29
+ # :cpus => 1,
30
+ # :cpu_shares => 10,
31
+ # :primary_disk_size => 10
32
+ # }
33
+ #
34
+ # create params
35
+ def create(options = {})
36
+ required = [:label, :hypervisor_id, :hostname, :memory, :cpus, :cpu_shares, :primary_disk_size]
37
+ optional = [:cpu_shares,
38
+ :swap_disk_size,
39
+ :primary_network_id,
40
+ :required_automatic_backup,
41
+ :rate_limit,
42
+ :required_ip_address_assignment,
43
+ :required_virtual_machine_build,
44
+ :admin_note,
45
+ :note,
46
+ :allowed_hot_migrate,
47
+ :template_id,
48
+ :initial_root_password
49
+ ]
50
+ params.required(required).accepts(optional).validate! options
51
+ response = request(:post, '/virtual_machines.json', default_params(options))
52
+ response['virtual_machine']
35
53
  end
36
54
 
37
- def create(params = {})
38
- required = [ :memory, :cpus, :label, :template_id, :hypervisor_id, :initial_root_password ]
39
- required_options!(required, params)
40
- post(URI_PREFIX, { :virtual_machine => params })
55
+ # Build a VirtualMachine
56
+ #
57
+ # ==== Options
58
+ #
59
+ # * +id+
60
+ # * +options+ - :template_id, :required_startup
61
+ def build(id, options = {})
62
+ params.accepts(:template_id, :required_startup).validate! options
63
+ response = request(:post, "/virtual_machines/#{id}/build.json", default_params(options))
64
+ response.first[1]
41
65
  end
42
66
 
43
- def destroy(id)
44
- delete("#{URI_PREFIX}/#{id}")
67
+ # Edit a new VirtualMachine
68
+ #
69
+ # ==== Options
70
+ #
71
+ # * +options+ - Params for editing the VirtualMachine
72
+ #
73
+ # ==== Example
74
+ #
75
+ # params = {
76
+ # :label => 'testmachine',
77
+ # :hypervisor_id => 5,
78
+ # :hostname => 'testmachine',
79
+ # :memory => 512,
80
+ # :cpus => 1,
81
+ # :cpu_shares => 10,
82
+ # :primary_disk_size => 10
83
+ # }
84
+ #
85
+ # edit params
86
+ def edit(id, options = {})
87
+ optional = [:label,
88
+ :hypervisor_id,
89
+ :hostname,
90
+ :memory,
91
+ :cpus,
92
+ :cpu_shares,
93
+ :primary_disk_size,
94
+ :cpu_shares,
95
+ :swap_disk_size,
96
+ :primary_network_id,
97
+ :required_automatic_backup,
98
+ :rate_limit,
99
+ :required_ip_address_assignment,
100
+ :required_virtual_machine_build,
101
+ :admin_note,
102
+ :note,
103
+ :allowed_hot_migrate,
104
+ :template_id,
105
+ :initial_root_password
106
+ ]
107
+ params.accepts(optional).validate! options
108
+ request(:put, "/virtual_machines/#{id}.json", default_params(options))
45
109
  end
46
110
 
47
- def reboot(id)
48
- post("#{URI_PREFIX}/#{id}/reboot")
111
+ # Change the owner of a VirtualMachine
112
+ #
113
+ # ==== Options
114
+ # * +id+ - id of the VirtualMachine
115
+ # * +user_id+ - id of the target User
116
+ def change_owner(id, user_id)
117
+ response = request(:post, "/virtual_machines/#{id}/change_owner.json", :query => { :user_id => user_id })
118
+ response['virtual_machine']
119
+ end
120
+
121
+ # Change the password
122
+ def change_password(id, password)
123
+ response = request(:post, "/virtual_machines/#{id}/reset_password.json", :query => { :new_password => password })
124
+ response['virtual_machine']
125
+ end
126
+
127
+ # Migrate a VirtualMachine to a new Hypervisor
128
+ #
129
+ # ==== Options
130
+ #
131
+ # * +id+
132
+ # * +options+ - :destination, :cold_migrate_on_rollback
133
+ def migrate(id, options = {})
134
+ params.required(:destination).accepts(:cold_migrate_on_rollback).validate! options
135
+ response = request(:post, "/virtual_machines/#{id}/migrate.json", :query => options )
49
136
  end
50
137
 
51
- def search(pattern, *fields)
52
- fields = [:label] if fields.empty?
53
- valid_options!(VALID_PARAMS, fields)
54
- list.select do |vm|
55
- fields.detect { |field| vm.has_key?(field.to_s) && vm[field.to_s].to_s.match(/#{pattern}/) }
56
- end
138
+ # Delete a VirtualMachine
139
+ def delete(id)
140
+ request(:delete, "/virtual_machines/#{id}.json")
141
+ end
142
+
143
+ # Resize a VirtualMachine's memory
144
+ def resize(id, options = {})
145
+ params.required(:memory).accepts(:allow_migration).validate! options
146
+ response = request(:post, "/virtual_machines/#{id}/resize.json", default_params(options))
147
+ response['virtual_machine']
148
+ end
149
+
150
+ # Suspend/Unsuspend a VirtualMachine
151
+ def suspend(id)
152
+ response = request(:post, "/virtual_machines/#{id}/suspend.json")
153
+ response['virtual_machine']
154
+ end
155
+ alias_method :unsuspend, :suspend
156
+
157
+ # Unlock a VirtualMachine
158
+ def unlock(id)
159
+ response = request(:post, "/virtual_machines/#{id}/unlock.json")
160
+ response['virtual_machine']
161
+ end
162
+
163
+ # Boot a VirtualMachine
164
+ def startup(id)
165
+ response = request(:post, "/virtual_machines/#{id}/startup.json")
166
+ response['virtual_machine']
167
+ end
168
+
169
+ # Shutdown a VirtualMachine
170
+ def shutdown(id)
171
+ response = request(:post, "/virtual_machines/#{id}/shutdown.json")
172
+ response['virtual_machine']
173
+ end
174
+
175
+ # Stop a VirtualMachine
176
+ def stop(id)
177
+ response = request(:post, "/virtual_machines/#{id}/stop.json")
178
+ response['virtual_machine']
179
+ end
180
+
181
+ # Reboot a VirtualMachine
182
+ def reboot(id)
183
+ response = request(:post, "/virtual_machines/#{id}/reboot.json")
184
+ response['virtual_machine']
57
185
  end
58
186
  end
59
187
  end
data/lib/squall.rb CHANGED
@@ -1,26 +1,82 @@
1
- require 'rubygems'
2
- require 'json'
3
- require 'rest_client'
4
- require 'open-uri'
1
+ require 'httparty'
5
2
 
6
- [:client, :virtual_machine, :hypervisor].each do |f|
7
- require File.join(File.dirname(__FILE__), 'squall', f.to_s)
8
- end
3
+ require 'squall/version'
4
+ require 'squall/exception'
9
5
 
10
6
  module Squall
11
- class << self
12
-
13
- # Sepcifies the login and url for making requests
14
- #
15
- # example:
16
- #
17
- # Squall.config(api_user, api_password, api_url)
18
- #
19
- attr_accessor :api_endpoint, :api_user, :api_password
20
- def config(api_user, api_password, api_url)
21
- @api_user = api_user
22
- @api_password = api_password
23
- @api_endpoint = URI.parse(api_url)
7
+ autoload :Params, 'squall/params'
8
+ autoload :Hypervisor, 'squall/hypervisor'
9
+ autoload :Config, 'squall/config'
10
+ autoload :Base, 'squall/base'
11
+ autoload :User, 'squall/user'
12
+ autoload :Role, 'squall/role'
13
+ autoload :Network, 'squall/network'
14
+ autoload :IpAddress, 'squall/ip_address'
15
+ autoload :Template, 'squall/template'
16
+ autoload :VirtualMachine, 'squall/virtual_machine'
17
+ autoload :Statistic, 'squall/statistic'
18
+ autoload :Transaction, 'squall/transaction'
19
+
20
+ extend self
21
+
22
+ # Config
23
+ attr_accessor :configuration
24
+
25
+ # Config
26
+ attr_accessor :configuration_file
27
+
28
+ # The path to your squall.yml
29
+ self.configuration ||= Squall::Config.new
30
+
31
+ # Specificy the config via block
32
+ #
33
+ # ==== Attributes
34
+ #
35
+ # * +base_uri+ - URL of your OnApp instance
36
+ # * +username+ - API username
37
+ # * +password+ - API Password
38
+ #
39
+ # ==== Example
40
+ #
41
+ # Squall.config do |c|
42
+ # c.base_uri 'http://onapp.myserver.com'
43
+ # c.username 'myuser'
44
+ # c.password 'mypass'
45
+ # end
46
+ def config
47
+ yield self.configuration if block_given?
48
+ self.configuration.config
49
+ end
50
+
51
+ # Load the config from a YAML file
52
+ #
53
+ # ==== Options
54
+ #
55
+ # * +file+ - Path to the YAML file (default is ~/.squall.yml)
56
+ #
57
+ # ==== Example
58
+ #
59
+ # Squall.config_file # (loads ~/.squall.yml)
60
+ #
61
+ # Squall.config_file '/path/to/squall.yml'
62
+ #
63
+ def config_file(file = nil)
64
+ file = File.expand_path(File.expand_path(File.join(ENV['HOME'], '.squall.yml'))) if file.nil?
65
+ if File.exists?(file)
66
+ self.configuration_file = file
67
+ else
68
+ raise ArgumentError, "Config file doesn't exist '#{file}'"
69
+ end
70
+ config do |c|
71
+ conf = YAML::load_file(file)
72
+ c.base_uri conf['base_uri']
73
+ c.username conf['username']
74
+ c.password conf['password']
24
75
  end
25
76
  end
77
+
78
+ # Reset the config (aka, clear it)
79
+ def reset_config
80
+ self.configuration = Squall::Config.new
81
+ end
26
82
  end
@@ -0,0 +1,195 @@
1
+ require 'spec_helper'
2
+
3
+ describe Squall::Params do
4
+ before(:each) do
5
+ @params = Squall::Params.new
6
+ end
7
+
8
+ describe "#new" do
9
+ it "sets @valid to {}" do
10
+ @params.valid.should be_empty
11
+ end
12
+
13
+ it "sets @optional to {}" do
14
+ @params.optional.should be_empty
15
+ end
16
+ end
17
+
18
+ describe "#required" do
19
+ it "stores keys in @valid with an Array" do
20
+ params = [:one, :two]
21
+ @params.required params
22
+ @params.valid.size.should == 2
23
+ @params.valid.should include(:one, :two)
24
+ end
25
+
26
+ it "stores uniq keys only" do
27
+ @params.required :one, :one
28
+ @params.valid.size.should == 1
29
+ @params.valid.should include(:one)
30
+ end
31
+
32
+ it "adds @valid to @optional" do
33
+ params = [:one, :two]
34
+ @params.required params
35
+ @params.valid.size.should == 2
36
+ @params.optional.size.should == 2
37
+
38
+ @params.valid.should include(:one, :two)
39
+ @params.optional.should include(:one, :two)
40
+ end
41
+
42
+ it "returns self" do
43
+ @params.required([:one, :two]).should be_a(Squall::Params)
44
+ end
45
+
46
+ it "resets @valid" do
47
+ params = [:one, :two]
48
+ @params.required params
49
+ @params.valid.size.should == 2
50
+ @params.valid.should include(:one, :two)
51
+
52
+ params = [:three, :four]
53
+ @params.required params
54
+ @params.valid.size.should == 2
55
+ @params.valid.should include(:three, :four)
56
+ end
57
+ end
58
+
59
+ describe "#accepts" do
60
+ it "stores keys in @optional with an Array" do
61
+ params = [:one, :two]
62
+ @params.accepts params
63
+ @params.optional.size.should == 2
64
+ @params.optional.should include(:one, :two)
65
+ end
66
+
67
+ it "stores uniq keys only" do
68
+ @params.accepts :one, :one
69
+ @params.optional.size.should == 1
70
+ @params.optional.should include(:one)
71
+ end
72
+
73
+ it "doesn't reset @valid" do
74
+ @params.required(:two)
75
+ @params.accepts(:one)
76
+
77
+ @params.optional.uniq.size.should be(2)
78
+ @params.optional.uniq.should include(:one, :two)
79
+ end
80
+
81
+
82
+ it "returns self" do
83
+ @params.accepts([:one, :two]).should be_a(Squall::Params)
84
+ end
85
+
86
+ it "resets @optional" do
87
+ params = [:one, :two]
88
+ @params.accepts params
89
+ @params.optional.size.should == 2
90
+ @params.optional.should include(:one, :two)
91
+
92
+ params = [:three, :four]
93
+ @params.accepts params
94
+ @params.optional.size.should == 4
95
+ @params.optional.should include(:three, :four)
96
+ end
97
+ end
98
+
99
+ describe "#validate_required!" do
100
+ describe "Array param input" do
101
+ it "raises an error with missing options" do
102
+ params = [:one, :two]
103
+ @params.required params
104
+ expect { @params.validate_required!(:three) }.to raise_error(ArgumentError)
105
+ end
106
+
107
+ it "does not raise an error with valid" do
108
+ params = [:one, :two]
109
+ @params.required params
110
+ @params.validate_required!(:one, :two)
111
+ end
112
+
113
+ it "does not raise an error when empty" do
114
+ @params.required []
115
+ @params.validate_required! :whatever
116
+ end
117
+ end
118
+
119
+ describe "Hash param input" do
120
+ it "raises an error with missing options" do
121
+ params = [:one, :two]
122
+ @params.required params
123
+ expect { @params.validate_required!({:three => 'three'}) }.to raise_error(ArgumentError)
124
+ end
125
+
126
+ it "does not raise an error with valid" do
127
+ params = [:one, :two]
128
+ @params.required params
129
+ @params.validate_required!(:one => 1, :two => 2)
130
+ end
131
+ end
132
+
133
+ describe "String param input" do
134
+ it "raises an error with missing options" do
135
+ params = [:one, :two]
136
+ @params.required params
137
+ expect { @params.validate_required!({'three' => 'three'}) }.to raise_error(ArgumentError)
138
+ end
139
+
140
+ it "does not raise an error with valid" do
141
+ params = [:one, :two]
142
+ @params.required params
143
+ @params.validate_required!('one' => 1, 'two' => 2)
144
+ end
145
+ end
146
+
147
+ describe "Chained execution" do
148
+ it "raises an error with missing options" do
149
+ params = [:one, :two]
150
+ expect { @params.required(params).validate_required!({'three' => 'three'}) }.to raise_error(ArgumentError)
151
+ end
152
+
153
+ it "does not raise an error with valid" do
154
+ params = [:one, :two]
155
+ @params.required(params).validate_required!('one' => 1, 'two' => 2)
156
+ end
157
+ end
158
+ end
159
+
160
+ describe "#validate_optionals!" do
161
+ it "raises an error with unknown params" do
162
+ @params.accepts :one, :two
163
+ expect { @params.validate_optionals!({:three => 3}) }.to raise_error(ArgumentError)
164
+ end
165
+
166
+ it "allows a known param" do
167
+ @params.accepts :one
168
+ @params.validate_optionals!({:one => 1}).should be_true
169
+ end
170
+
171
+ it "allows multiple known param" do
172
+ @params.accepts :one, :two
173
+ @params.validate_optionals!({:one => 1, :two => 2}).should be_true
174
+ end
175
+
176
+ it "allows 2 of 3 known param" do
177
+ @params.accepts :one, :two, :three
178
+ @params.validate_optionals!({:one => 1, :two => 2}).should be_true
179
+ end
180
+ end
181
+
182
+ describe "#validate!" do
183
+ it "calls #validate_required!" do
184
+ @params.valid = [:one, :two]
185
+ @params.should_receive(:validate_required!).with(:one, :two)
186
+ @params.validate!(:one, :two)
187
+ end
188
+
189
+ it "calls #validate_optionals!" do
190
+ @params.optional = [:one, :two]
191
+ @params.should_receive(:validate_optionals!).with(:one, :two)
192
+ @params.validate!(:one, :two)
193
+ end
194
+ end
195
+ end