nova_spec.rb 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. require 'puppet'
  2. require 'spec_helper'
  3. require 'puppet/provider/nova'
  4. require 'rspec/mocks'
  5. describe Puppet::Provider::Nova do
  6. def klass
  7. described_class
  8. end
  9. let :credential_hash do
  10. {
  11. 'auth_uri' => 'https://192.168.56.210:35357/v2.0/',
  12. 'project_name' => 'admin_tenant',
  13. 'username' => 'admin',
  14. 'password' => 'password',
  15. 'region_name' => 'Region1',
  16. }
  17. end
  18. let :auth_endpoint do
  19. 'https://192.168.56.210:35357/v2.0/'
  20. end
  21. let :credential_error do
  22. /Nova types will not work/
  23. end
  24. after :each do
  25. klass.reset
  26. end
  27. describe 'when determining credentials' do
  28. it 'should fail if config is empty' do
  29. conf = {}
  30. klass.expects(:nova_conf).returns(conf)
  31. expect do
  32. klass.nova_credentials
  33. end.to raise_error(Puppet::Error, credential_error)
  34. end
  35. it 'should fail if config does not have keystone_authtoken section.' do
  36. conf = {'foo' => 'bar'}
  37. klass.expects(:nova_conf).returns(conf)
  38. expect do
  39. klass.nova_credentials
  40. end.to raise_error(Puppet::Error, credential_error)
  41. end
  42. it 'should fail if config does not contain all auth params' do
  43. conf = {'keystone_authtoken' => {'invalid_value' => 'foo'}}
  44. klass.expects(:nova_conf).returns(conf)
  45. expect do
  46. klass.nova_credentials
  47. end.to raise_error(Puppet::Error, credential_error)
  48. end
  49. it 'should use specified uri in the auth endpoint' do
  50. conf = {'keystone_authtoken' => credential_hash}
  51. klass.expects(:nova_conf).returns(conf)
  52. expect(klass.get_auth_endpoint).to eq(auth_endpoint)
  53. end
  54. end
  55. describe 'when invoking the nova cli' do
  56. it 'should set auth credentials in the environment' do
  57. authenv = {
  58. :OS_AUTH_URL => auth_endpoint,
  59. :OS_USERNAME => credential_hash['username'],
  60. :OS_PROJECT_NAME => credential_hash['project_name'],
  61. :OS_PASSWORD => credential_hash['password'],
  62. :OS_REGION_NAME => credential_hash['region_name'],
  63. }
  64. klass.expects(:get_nova_credentials).with().returns(credential_hash)
  65. klass.expects(:withenv).with(authenv)
  66. klass.auth_nova('test_retries')
  67. end
  68. ['[Errno 111] Connection refused',
  69. '(HTTP 400)'].reverse.each do |valid_message|
  70. it "should retry when nova cli returns with error #{valid_message}" do
  71. klass.expects(:get_nova_credentials).with().returns({})
  72. klass.expects(:sleep).with(10).returns(nil)
  73. klass.expects(:nova).twice.with(['test_retries']).raises(
  74. Exception, valid_message).then.returns('')
  75. klass.auth_nova('test_retries')
  76. end
  77. end
  78. end
  79. describe 'when parse a string line' do
  80. it 'should return the same string' do
  81. res = klass.str2hash("zone1")
  82. expect(res).to eq("zone1")
  83. end
  84. it 'should return the string without quotes' do
  85. res = klass.str2hash("'zone1'")
  86. expect(res).to eq("zone1")
  87. end
  88. it 'should return the same string' do
  89. res = klass.str2hash("z o n e1")
  90. expect(res).to eq("z o n e1")
  91. end
  92. it 'should return a hash' do
  93. res = klass.str2hash("a=b")
  94. expect(res).to eq({"a"=>"b"})
  95. end
  96. it 'should return a hash with containing spaces' do
  97. res = klass.str2hash("a b = c d")
  98. expect(res).to eq({"a b "=>" c d"})
  99. end
  100. it 'should return the same string' do
  101. res = klass.str2list("zone1")
  102. expect(res).to eq("zone1")
  103. end
  104. it 'should return a list of strings' do
  105. res = klass.str2list("zone1, zone2")
  106. expect(res).to eq(["zone1", "zone2"])
  107. end
  108. it 'should return a list of strings' do
  109. res = klass.str2list("zo n e1, zone2 ")
  110. expect(res).to eq(["zo n e1", "zone2"])
  111. end
  112. it 'should return a hash with multiple keys' do
  113. res = klass.str2list("a=b, c=d")
  114. expect(res).to eq({"a"=>"b", "c"=>"d"})
  115. end
  116. it 'should return a single hash' do
  117. res = klass.str2list("a=b")
  118. expect(res).to eq({"a"=>"b"})
  119. end
  120. end
  121. describe 'when parsing cli output' do
  122. it 'should return a list with hashes' do
  123. output = <<-EOT
  124. +----+-------+-------------------+
  125. | Id | Name | Availability Zone |
  126. +----+-------+-------------------+
  127. | 1 | haha | haha2 |
  128. | 2 | haha2 | - |
  129. +----+-------+-------------------+
  130. EOT
  131. res = klass.cliout2list(output)
  132. expect(res).to eq([{"Id"=>"1", "Name"=>"haha", "Availability Zone"=>"haha2"},
  133. {"Id"=>"2", "Name"=>"haha2", "Availability Zone"=>""}])
  134. end
  135. it 'should return a list with hashes' do
  136. output = <<-EOT
  137. +----+-------+-------------------+-------+--------------------------------------------------+
  138. | Id | Name | Availability Zone | Hosts | Metadata |
  139. +----+-------+-------------------+-------+--------------------------------------------------+
  140. | 16 | agg94 | my_-zone1 | | 'a=b', 'availability_zone= my_-zone1', 'x_q-r=y' |
  141. +----+-------+-------------------+-------+--------------------------------------------------+
  142. EOT
  143. res = klass.cliout2list(output)
  144. expect(res).to eq([{"Id"=>"16",
  145. "Name"=>"agg94",
  146. "Availability Zone"=>"my_-zone1",
  147. "Hosts"=>"",
  148. "Metadata"=> {
  149. "a"=>"b",
  150. "availability_zone"=>" my_-zone1",
  151. "x_q-r"=>"y"
  152. }
  153. }])
  154. end
  155. it 'should return a empty list' do
  156. output = <<-EOT
  157. +----+------+-------------------+
  158. | Id | Name | Availability Zone |
  159. +----+------+-------------------+
  160. +----+------+-------------------+
  161. EOT
  162. res = klass.cliout2list(output)
  163. expect(res).to eq([])
  164. end
  165. it 'should return a empty list because no input available' do
  166. output = <<-EOT
  167. EOT
  168. res = klass.cliout2list(output)
  169. expect(res).to eq([])
  170. end
  171. it 'should return a list with hashes' do
  172. output = <<-EOT
  173. +----+----------------+-------------------+
  174. | Id | Name | Availability Zone |
  175. +----+----------------+-------------------+
  176. | 6 | my | zone1 |
  177. | 8 | my2 | - |
  178. +----+----------------+-------------------+
  179. EOT
  180. res = klass.cliout2list(output)
  181. expect(res).to eq([{"Id"=>"6", "Name"=>"my", "Availability Zone"=>"zone1"},
  182. {"Id"=>"8", "Name"=>"my2", "Availability Zone"=>""}])
  183. end
  184. end
  185. describe 'when parsing cli output with cells enabled' do
  186. it 'should return a list with hashes' do
  187. output = <<-EOT
  188. +-------------+----------------+-------------------+
  189. | Id | Name | Availability Zone |
  190. +-------------+----------------+-------------------+
  191. | api!cell@1 | api!cell@haha | haha2 |
  192. | api!cell@2 | api!cell@haha2 | - |
  193. +-------------+----------------+-------------------+
  194. EOT
  195. res = klass.cliout2list(output)
  196. expect(res).to eq([{"Id"=>"api!cell@1", "Name"=>"api!cell@haha", "Availability Zone"=>"haha2"},
  197. {"Id"=>"api!cell@2", "Name"=>"api!cell@haha2", "Availability Zone"=>""}])
  198. end
  199. it 'should return a list with hashes' do
  200. output = <<-EOT
  201. +-------------+----------------+-------------------+-------+--------------------------------------------------+
  202. | Id | Name | Availability Zone | Hosts | Metadata |
  203. +-------------+----------------+-------------------+-------+--------------------------------------------------+
  204. | api!cell@16 | api!cell@agg94 | my_-zone1 | | 'a=b', 'availability_zone= my_-zone1', 'x_q-r=y' |
  205. +-------------+----------------+-------------------+-------+--------------------------------------------------+
  206. EOT
  207. res = klass.cliout2list(output)
  208. expect(res).to eq([{"Id"=>"api!cell@16",
  209. "Name"=>"api!cell@agg94",
  210. "Availability Zone"=>"my_-zone1",
  211. "Hosts"=>"",
  212. "Metadata"=> {
  213. "a"=>"b",
  214. "availability_zone"=>" my_-zone1",
  215. "x_q-r"=>"y"
  216. }
  217. }])
  218. end
  219. it 'should return a empty list' do
  220. output = <<-EOT
  221. +----+------+-------------------+
  222. | Id | Name | Availability Zone |
  223. +----+------+-------------------+
  224. +----+------+-------------------+
  225. EOT
  226. res = klass.cliout2list(output)
  227. expect(res).to eq([])
  228. end
  229. it 'should return a empty list because no input available' do
  230. output = <<-EOT
  231. EOT
  232. res = klass.cliout2list(output)
  233. expect(res).to eq([])
  234. end
  235. it 'should return a list with hashes' do
  236. output = <<-EOT
  237. +-------------+-------------------------+-------------------+
  238. | Id | Name | Availability Zone |
  239. +-------------+-------------------------+-------------------+
  240. | api!cell@6 | api!cell@my | zone1 |
  241. | api!cell@8 | api!cell@my2 | - |
  242. +-------------+-------------------------+-------------------+
  243. EOT
  244. res = klass.cliout2list(output)
  245. expect(res).to eq([{"Id"=>"api!cell@6", "Name"=>"api!cell@my", "Availability Zone"=>"zone1"},
  246. {"Id"=>"api!cell@8", "Name"=>"api!cell@my2", "Availability Zone"=>""}])
  247. end
  248. end
  249. end