miasma 0.2.16 → 0.2.18

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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/lib/miasma/models/storage.rb +2 -2
  4. data/lib/miasma/types/api.rb +32 -25
  5. data/lib/miasma/version.rb +1 -1
  6. data/miasma.gemspec +1 -1
  7. data/test/spec.rb +20 -0
  8. data/test/specs/cassettes/aws_buckets_all.yml +45 -0
  9. data/test/specs/cassettes/aws_load_balancer_balancer_after_destroy.yml +85 -0
  10. data/test/specs/cassettes/aws_load_balancer_balancer_before_create.yml +271 -0
  11. data/test/specs/cassettes/aws_load_balancer_balancer_direct_fetch.yml +89 -0
  12. data/test/specs/cassettes/aws_load_balancer_balancers_all.yml +45 -0
  13. data/test/specs/cassettes/aws_server_after_destroy.yml +155 -0
  14. data/test/specs/cassettes/aws_server_before_create.yml +470 -0
  15. data/test/specs/cassettes/aws_servers_all.yml +44 -0
  16. data/test/specs/cassettes/aws_servers_create.yml +824 -0
  17. data/test/specs/cassettes/aws_stack_create.yml +603 -0
  18. data/test/specs/cassettes/aws_stacks_after_destroy.yml +148 -0
  19. data/test/specs/cassettes/aws_stacks_all.yml +99 -0
  20. data/test/specs/cassettes/aws_stacks_before_create.yml +300 -0
  21. data/test/specs/cassettes/aws_stacks_direct_fetch.yml +108 -0
  22. data/test/specs/cassettes/aws_storage_bucket.yml +429 -0
  23. data/test/specs/cassettes/open_stack_server_after_destroy.yml +83 -0
  24. data/test/specs/cassettes/open_stack_server_before_create.yml +138 -0
  25. data/test/specs/cassettes/open_stack_servers_all.yml +34 -0
  26. data/test/specs/cassettes/open_stack_servers_create.yml +296 -0
  27. data/test/specs/cassettes/open_stack_stack_create.yml +338 -0
  28. data/test/specs/cassettes/open_stack_stacks_after_destroy.yml +73 -0
  29. data/test/specs/cassettes/open_stack_stacks_all.yml +34 -0
  30. data/test/specs/cassettes/open_stack_stacks_before_create.yml +227 -0
  31. data/test/specs/cassettes/open_stack_stacks_direct_fetch.yml +39 -0
  32. data/test/specs/cassettes/rackspace_identity_seed.yml +38 -0
  33. data/test/specs/cassettes/rackspace_server_after_destroy.yml +88 -0
  34. data/test/specs/cassettes/rackspace_server_before_create.yml +143 -0
  35. data/test/specs/cassettes/rackspace_servers_create.yml +313 -0
  36. data/test/specs/cassettes/rackspace_stack_create.yml +289 -0
  37. data/test/specs/cassettes/rackspace_stacks_after_destroy.yml +79 -0
  38. data/test/specs/cassettes/rackspace_stacks_all.yml +81 -0
  39. data/test/specs/cassettes/rackspace_stacks_before_create.yml +211 -0
  40. data/test/specs/cassettes/rackspace_stacks_direct_fetch.yml +38 -0
  41. data/test/specs/miasma_spec.rb +33 -0
  42. data/test/specs/models/compute_abstract.rb +118 -0
  43. data/test/specs/models/load_balancer_abstract.rb +88 -0
  44. data/test/specs/models/orchestration_abstract.rb +123 -0
  45. data/test/specs/models/storage_abstract.rb +120 -0
  46. data/test/specs/utils/animal_strings_spec.rb +15 -0
  47. data/test/specs/utils/memoization_spec.rb +83 -0
  48. data/test/specs/utils/smash_spec.rb +107 -0
  49. metadata +44 -2
@@ -0,0 +1,123 @@
1
+ MIASMA_ORCHESTRATION_ABSTRACT = ->{
2
+
3
+ # Required `let`s:
4
+ # * orchestration: orchestration API
5
+ # * build_args: stack build arguments [Smash]
6
+ # * cassette_prefix: cassette file prefix [String]
7
+
8
+ describe Miasma::Models::Orchestration do
9
+
10
+ it 'should provide #stacks collection' do
11
+ orchestration.stacks.must_be_kind_of Miasma::Models::Orchestration::Stacks
12
+ end
13
+
14
+ describe Miasma::Models::Orchestration::Stacks do
15
+
16
+ it 'should provide instance class used within collection' do
17
+ orchestration.stacks.model.must_equal Miasma::Models::Orchestration::Stack
18
+ end
19
+
20
+ it 'should build new instance for collection' do
21
+ instance = orchestration.stacks.build
22
+ instance.must_be_kind_of Miasma::Models::Orchestration::Stack
23
+ end
24
+
25
+ it 'should provide #all stacks' do
26
+ VCR.use_cassette("#{cassette_prefix}_stacks_all") do
27
+ orchestration.stacks.all.must_be_kind_of Array
28
+ end
29
+ end
30
+
31
+ end
32
+
33
+ describe Miasma::Models::Orchestration::Stacks do
34
+
35
+ before do
36
+ @stack = orchestration.stacks.build(build_args)
37
+ VCR.use_cassette("#{cassette_prefix}_stacks_before_create") do |obj|
38
+ @stack.save
39
+ until(@stack.state == :create_complete)
40
+ sleep(obj.recording? ? 60 : 0.01)
41
+ @stack.reload
42
+ end
43
+ @stack.template
44
+ orchestration.stacks.reload
45
+ end
46
+ end
47
+
48
+ after do
49
+ VCR.use_cassette("#{cassette_prefix}_stacks_after_destroy") do
50
+ @stack.destroy
51
+ end
52
+ end
53
+
54
+ let(:stack){ @stack }
55
+
56
+ describe 'collection' do
57
+
58
+ it 'should include stack' do
59
+ VCR.use_cassette("#{cassette_prefix}_stacks_direct_fetch") do
60
+ orchestration.stacks.all.detect{|s| s.id == stack.id}.wont_be_nil
61
+ orchestration.stacks.get(stack.id).wont_be_nil
62
+ end
63
+ end
64
+
65
+ end
66
+
67
+ describe 'instance methods' do
68
+
69
+ it 'should have a name' do
70
+ stack.name.must_equal build_args[:name]
71
+ end
72
+
73
+ it 'should be in :create_complete state' do
74
+ stack.state.must_equal :create_complete
75
+ end
76
+
77
+ it 'should have a status' do
78
+ stack.status.must_be_kind_of String
79
+ end
80
+
81
+ it 'should have a creation time' do
82
+ stack.created.must_be_kind_of Time
83
+ end
84
+
85
+ it 'should have parameters used for creation' do
86
+ stack.parameters.to_smash.must_equal build_args[:parameters].to_smash
87
+ end
88
+
89
+ it 'should include the templated used for creation' do
90
+ stack.template.to_smash.must_equal build_args[:template].to_smash
91
+ end
92
+
93
+ end
94
+
95
+ end
96
+
97
+ describe 'instance lifecycle' do
98
+ it 'should create new stack, reload details and destroy stack' do
99
+ VCR.use_cassette("#{cassette_prefix}_stack_create") do |obj|
100
+ stack = orchestration.stacks.build(build_args.merge(:name => 'miasma-test-stack-2'))
101
+ stack.save
102
+ stack.id.wont_be_nil
103
+ stack.state.must_equal :create_in_progress
104
+ orchestration.stacks.reload.get(stack.id).wont_be_nil
105
+ until(stack.state == :create_complete)
106
+ sleep(obj.recording? ? 60 : 0.01)
107
+ stack.reload
108
+ end
109
+ stack.state.must_equal :create_complete
110
+ stack.destroy
111
+ [:delete_in_progress, :delete_complete].must_include stack.state
112
+ until(stack.state == :delete_complete)
113
+ sleep(obj.recording? ? 60 : 0.01)
114
+ stack.reload
115
+ end
116
+ stack.state.must_equal :delete_complete
117
+ end
118
+ end
119
+
120
+ end
121
+
122
+ end
123
+ }
@@ -0,0 +1,120 @@
1
+ require 'open-uri'
2
+
3
+ MIASMA_STORAGE_ABSTRACT = ->{
4
+
5
+ # Required `let`s:
6
+ # * storage: storage API
7
+ # * cassette_prefix: cassette file prefix [String]
8
+
9
+ describe Miasma::Models::Storage do
10
+
11
+ it 'should provide #buckets collection' do
12
+ storage.buckets.must_be_kind_of Miasma::Models::Storage::Buckets
13
+ end
14
+
15
+ describe Miasma::Models::Storage::Buckets do
16
+
17
+ it 'should provide instance class used within collection' do
18
+ storage.buckets.model.must_equal Miasma::Models::Storage::Bucket
19
+ end
20
+
21
+ it 'should build new instance for collection' do
22
+ storage.buckets.build.must_be_kind_of Miasma::Models::Storage::Bucket
23
+ end
24
+
25
+ it 'should provide #all buckets' do
26
+ VCR.use_cassette("#{cassette_prefix}_buckets_all") do
27
+ storage.buckets.all.must_be_kind_of Array
28
+ end
29
+ end
30
+
31
+ end
32
+
33
+ describe Miasma::Models::Storage::Bucket do
34
+
35
+ it 'should act like a bucket' do
36
+ bucket = storage.buckets.build(:name => 'miasma-test-bucket-010')
37
+ VCR.use_cassette("#{cassette_prefix}_storage_bucket") do |obj|
38
+ bucket.save
39
+ bucket.reload
40
+
41
+ # should include the bucket
42
+ storage.buckets.reload.get('miasma-test-bucket-010').wont_be_nil
43
+ # should have a name
44
+ bucket.name.must_equal 'miasma-test-bucket-010'
45
+ # should have a #files collection
46
+ bucket.files.must_be_kind_of Miasma::Models::Storage::Files
47
+ #should provide #all files
48
+ bucket.files.all.must_be_kind_of Array
49
+ # should include reference to containing bucket
50
+ bucket.files.bucket.must_equal bucket
51
+ # should build new instance for collection
52
+ bucket.files.build.must_be_kind_of Miasma::Models::Storage::File
53
+
54
+ file_content = 'blahblahblah'
55
+ file = bucket.files.build
56
+ file.name = 'miasma-test-file'
57
+ file.body = file_content
58
+ file.save
59
+ file.reload
60
+
61
+ # should have a name
62
+ file.name.must_equal 'miasma-test-file'
63
+ # should have a size
64
+ file.size.must_equal file_content.size
65
+ # should have an updated timestamp
66
+ file.updated.must_be_kind_of Time
67
+ # should create a valid url
68
+ open(file.url).read.must_equal file_content
69
+ # should have a body
70
+ file.body.must_respond_to :readpartial
71
+ file.body.readpartial(Miasma::Models::Storage::READ_BODY_CHUNK_SIZE).must_equal file_content
72
+ file.destroy
73
+
74
+ big_file_content = '*' * Miasma::Models::Storage::MAX_BODY_SIZE_FOR_STRINGIFY
75
+ big_file = bucket.files.build
76
+ big_file.name = 'miasma-test-file-big'
77
+ big_file.body = big_file_content
78
+ big_file.save
79
+ big_file.reload
80
+
81
+ # should be the correct size
82
+ big_file.size.must_equal big_file.size
83
+ # should provide streaming body
84
+ big_file.body.must_respond_to :readpartial
85
+ content = big_file.body.readpartial(big_file.size)
86
+ content.must_equal big_file_content
87
+ big_file.destroy
88
+
89
+ require 'tempfile'
90
+ local_io_file = Tempfile.new('miasma-storage-test')
91
+ big_io_content = '*' * (Miasma::Models::Storage::MAX_BODY_SIZE_FOR_STRINGIFY * 2)
92
+ local_io_file.write big_io_content
93
+ local_io_file.flush
94
+ local_io_file.rewind
95
+ remote_file = bucket.files.build
96
+ remote_file.name = 'miasma-test-io-object-010'
97
+ remote_file.body = local_io_file
98
+ remote_file.save
99
+ remote_file.reload
100
+
101
+ # should be the correct size
102
+ remote_file.size.must_equal local_io_file.size
103
+ # should provide streaming body
104
+ remote_file.body.must_respond_to :readpartial
105
+ content = ''
106
+ while(chunk = remote_file.body.readpartial(1024))
107
+ content << chunk
108
+ end
109
+ content.must_equal big_io_content
110
+ remote_file.destroy
111
+ bucket.destroy
112
+ end
113
+
114
+ end
115
+
116
+
117
+ end
118
+
119
+ end
120
+ }
@@ -0,0 +1,15 @@
1
+ describe Miasma::Utils::AnimalStrings do
2
+
3
+ it 'should camel case strings' do
4
+ Miasma::Utils.camel('fubar_foobar_fuobar').must_equal 'FubarFoobarFuobar'
5
+ end
6
+
7
+ it 'should camel case symbols' do
8
+ Miasma::Utils.camel(:fubar_foobar_fuobar).must_equal 'FubarFoobarFuobar'
9
+ end
10
+
11
+ it 'should snake case strings' do
12
+ Miasma::Utils.snake('FubarFoobarFuobar').must_equal 'fubar_foobar_fuobar'
13
+ end
14
+
15
+ end
@@ -0,0 +1,83 @@
1
+ describe Miasma::Utils::Memoization do
2
+
3
+ before do
4
+ @memo = Object.new
5
+ @memo.extend Miasma::Utils::Memoization
6
+ end
7
+
8
+ after do
9
+ Thread.current[:miasma_memoization] = nil
10
+ end
11
+
12
+ let(:memo){ @memo }
13
+
14
+ it 'should #memoize the value returned by block' do
15
+ value = Kernel.rand
16
+ memo.memoize(:test) do
17
+ value
18
+ end.must_equal value
19
+ memo.memoize(:test){ Kernel.rand }.must_equal value
20
+ end
21
+
22
+ it 'should not return #memoize value from other instance' do
23
+ memo2 = Object.new
24
+ memo2.extend Miasma::Utils::Memoization
25
+ value = Kernel.rand
26
+ memo.memoize(:test) do
27
+ value
28
+ end.must_equal value
29
+ memo.memoize(:test){ Kernel.rand }.must_equal value
30
+ memo2.memoize(:test){ Kernel.rand }.wont_equal value
31
+ end
32
+
33
+ it 'should #unmemoize a memoized value' do
34
+ value = Kernel.rand
35
+ value2 = Kernel.rand
36
+ memo.memoize(:test) do
37
+ value
38
+ end.must_equal value
39
+ memo.unmemoize(:test)
40
+ memo.memoize(:test) do
41
+ value2
42
+ end.must_equal value2
43
+ end
44
+
45
+ it 'should allow direct #memoize not restricted to object' do
46
+ memo2 = Object.new
47
+ memo2.extend Miasma::Utils::Memoization
48
+ value = Kernel.rand
49
+ memo.memoize(:test, true) do
50
+ value
51
+ end.must_equal value
52
+ memo.memoize(:test, true){ Kernel.rand }.must_equal value
53
+ memo2.memoize(:test, true){ Kernal.rand }.must_equal value
54
+ end
55
+
56
+ it 'should clear all non-direct memoizations with #clear_memoizations!' do
57
+ memo2 = Object.new
58
+ memo2.extend Miasma::Utils::Memoization
59
+ value = Kernel.rand
60
+ memo.memoize(:test, true) do
61
+ value
62
+ end.must_equal value
63
+ memo.memoize(:test){ value }.must_equal value
64
+ memo2.memoize(:test){ value }.must_equal value
65
+
66
+ memo.memoize(:test, true){ Kernel.rand }.must_equal value
67
+ memo2.memoize(:test, true){ Kernel.rand }.must_equal value
68
+ memo.memoize(:test){ Kernel.rand }.must_equal value
69
+ memo2.memoize(:test){ Kernel.rand }.must_equal value
70
+
71
+ memo.clear_memoizations!
72
+ memo.memoize(:test){ Kernel.rand }.wont_equal value
73
+ memo2.memoize(:test){ Kernel.rand }.must_equal value
74
+
75
+ memo2.clear_memoizations!
76
+ memo.memoize(:test){ Kernel.rand }.wont_equal value
77
+ memo2.memoize(:test){ Kernel.rand }.wont_equal value
78
+
79
+ memo.memoize(:test, true){ Kernel.rand }.must_equal value
80
+ memo2.memoize(:test, true){ Kernel.rand }.must_equal value
81
+ end
82
+
83
+ end
@@ -0,0 +1,107 @@
1
+ describe Miasma::Utils::Smash do
2
+
3
+ it 'should provide top level constant' do
4
+ defined?(::Smash).wont_be_nil
5
+ end
6
+
7
+ it 'should provide #to_smash on Hash' do
8
+ Hash.instance_methods.must_include :to_smash
9
+ end
10
+
11
+ it 'should convert Hash to Smash' do
12
+ {:a => 1}.to_smash.must_equal Smash.new(:a => 1)
13
+ end
14
+
15
+ it 'should sort keys when converting' do
16
+ hash = {:z => 1, :d => 3, :m => 1}
17
+ smash = Smash.new(:d => 3, :m => 1, :z => 1)
18
+ hash.to_smash.must_equal smash
19
+ end
20
+
21
+ it 'should convert deep nested Hashes to Smashes' do
22
+ hash = {
23
+ :a => 1,
24
+ :b => [
25
+ {:c => 2},
26
+ {:d => 3}
27
+ ]
28
+ }
29
+ smash = Smash.new(
30
+ :a => 1,
31
+ :b => [
32
+ Smash.new(:c => 2),
33
+ Smash.new(:d => 3)
34
+ ]
35
+ )
36
+ hash.to_smash.must_equal smash
37
+ end
38
+
39
+ it 'should #get deeply nested value' do
40
+ smash = {
41
+ :a => {
42
+ :b => {
43
+ :c => {
44
+ :d => 1
45
+ }
46
+ }
47
+ }
48
+ }.to_smash
49
+ smash.get(:a, :b, :c, :d).must_equal 1
50
+ end
51
+
52
+ it 'should #get nil on missing deeply nested value' do
53
+ smash = {
54
+ :a => {
55
+ :b => {
56
+ :c => {
57
+ :d => 1
58
+ }
59
+ }
60
+ }
61
+ }.to_smash
62
+ smash.get(:a, :b, :c, :x).must_be_nil
63
+ end
64
+
65
+ it 'should #set deeply nested value' do
66
+ smash = Smash.new
67
+ smash.set(:a, :b, :c, 1)
68
+ smash.get(:a, :b, :c).must_equal 1
69
+ end
70
+
71
+ it 'should #fetch default value on missing' do
72
+ smash = {
73
+ :a => {
74
+ :b => {
75
+ :c => {
76
+ :d => 1
77
+ }
78
+ }
79
+ }
80
+ }.to_smash
81
+ smash.fetch(:a, :b, :c, :x, 1).must_equal 1
82
+ end
83
+
84
+ it 'should #fetch value when availble' do
85
+ smash = {
86
+ :a => {
87
+ :b => {
88
+ :c => {
89
+ :d => 1
90
+ }
91
+ }
92
+ }
93
+ }.to_smash
94
+ smash.fetch(:a, :b, :c, :d, 0).must_equal 1
95
+ end
96
+
97
+ it 'should generate a #checksum' do
98
+ Smash.new(:a => 1).checksum.must_be_kind_of String
99
+ end
100
+
101
+ it 'should generate equal #checksum' do
102
+ hash = {:z => 1, :d => 3}
103
+ smash = Smash.new(:d => 3, :z => 1)
104
+ hash.to_smash.checksum.must_equal smash.checksum
105
+ end
106
+
107
+ end