squall 0.0.3 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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