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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/lib/miasma/models/storage.rb +2 -2
- data/lib/miasma/types/api.rb +32 -25
- data/lib/miasma/version.rb +1 -1
- data/miasma.gemspec +1 -1
- data/test/spec.rb +20 -0
- data/test/specs/cassettes/aws_buckets_all.yml +45 -0
- data/test/specs/cassettes/aws_load_balancer_balancer_after_destroy.yml +85 -0
- data/test/specs/cassettes/aws_load_balancer_balancer_before_create.yml +271 -0
- data/test/specs/cassettes/aws_load_balancer_balancer_direct_fetch.yml +89 -0
- data/test/specs/cassettes/aws_load_balancer_balancers_all.yml +45 -0
- data/test/specs/cassettes/aws_server_after_destroy.yml +155 -0
- data/test/specs/cassettes/aws_server_before_create.yml +470 -0
- data/test/specs/cassettes/aws_servers_all.yml +44 -0
- data/test/specs/cassettes/aws_servers_create.yml +824 -0
- data/test/specs/cassettes/aws_stack_create.yml +603 -0
- data/test/specs/cassettes/aws_stacks_after_destroy.yml +148 -0
- data/test/specs/cassettes/aws_stacks_all.yml +99 -0
- data/test/specs/cassettes/aws_stacks_before_create.yml +300 -0
- data/test/specs/cassettes/aws_stacks_direct_fetch.yml +108 -0
- data/test/specs/cassettes/aws_storage_bucket.yml +429 -0
- data/test/specs/cassettes/open_stack_server_after_destroy.yml +83 -0
- data/test/specs/cassettes/open_stack_server_before_create.yml +138 -0
- data/test/specs/cassettes/open_stack_servers_all.yml +34 -0
- data/test/specs/cassettes/open_stack_servers_create.yml +296 -0
- data/test/specs/cassettes/open_stack_stack_create.yml +338 -0
- data/test/specs/cassettes/open_stack_stacks_after_destroy.yml +73 -0
- data/test/specs/cassettes/open_stack_stacks_all.yml +34 -0
- data/test/specs/cassettes/open_stack_stacks_before_create.yml +227 -0
- data/test/specs/cassettes/open_stack_stacks_direct_fetch.yml +39 -0
- data/test/specs/cassettes/rackspace_identity_seed.yml +38 -0
- data/test/specs/cassettes/rackspace_server_after_destroy.yml +88 -0
- data/test/specs/cassettes/rackspace_server_before_create.yml +143 -0
- data/test/specs/cassettes/rackspace_servers_create.yml +313 -0
- data/test/specs/cassettes/rackspace_stack_create.yml +289 -0
- data/test/specs/cassettes/rackspace_stacks_after_destroy.yml +79 -0
- data/test/specs/cassettes/rackspace_stacks_all.yml +81 -0
- data/test/specs/cassettes/rackspace_stacks_before_create.yml +211 -0
- data/test/specs/cassettes/rackspace_stacks_direct_fetch.yml +38 -0
- data/test/specs/miasma_spec.rb +33 -0
- data/test/specs/models/compute_abstract.rb +118 -0
- data/test/specs/models/load_balancer_abstract.rb +88 -0
- data/test/specs/models/orchestration_abstract.rb +123 -0
- data/test/specs/models/storage_abstract.rb +120 -0
- data/test/specs/utils/animal_strings_spec.rb +15 -0
- data/test/specs/utils/memoization_spec.rb +83 -0
- data/test/specs/utils/smash_spec.rb +107 -0
- 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
|