deltadsl 1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +92 -0
- data/lib/client.rb +17 -0
- data/lib/dsl.rb +21 -0
- data/lib/instance.rb +194 -0
- data/lib/instance_configuration.rb +13 -0
- data/lib/instance_definition.rb +45 -0
- data/lib/instance_profile.rb +37 -0
- data/lib/models.rb +20 -0
- data/lib/task.rb +142 -0
- data/tests/deltacloud_perf_test.rb +52 -0
- data/tests/dsl_test.rb +203 -0
- data/tests/test_test.rb +28 -0
- metadata +93 -0
data/README.md
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
Deltacloud API client DSL
|
2
|
+
-------------------------
|
3
|
+
|
4
|
+
Documentation
|
5
|
+
|
6
|
+
<a href="http://rdoc.info/github/mifo/deltadsl/master/frames">rdoc.info/github/mifo/deltadsl/master/frames</a>
|
7
|
+
|
8
|
+
Installation:
|
9
|
+
|
10
|
+
* No installation available yet ;-)
|
11
|
+
|
12
|
+
Prerequires:
|
13
|
+
|
14
|
+
* Deltacloud API server and client gems installed:
|
15
|
+
|
16
|
+
$ gem install deltacloud-core deltacloud-client
|
17
|
+
|
18
|
+
* Eventmachine (gem install eventmachine)
|
19
|
+
* Thin (gem install thin)
|
20
|
+
|
21
|
+
Examples
|
22
|
+
-------------------------
|
23
|
+
|
24
|
+
Simple scenario:
|
25
|
+
|
26
|
+
<script src="https://gist.github.com/1933563.js?file=dsl_sample.rb"></script>
|
27
|
+
|
28
|
+
@sample = Deltacloud::DSL::Task('launch some EC2 and RHEV-M instances') do
|
29
|
+
|
30
|
+
instances(:driver => :ec2, :username => '', :password => '') do
|
31
|
+
instance 'test-ec2-1' do
|
32
|
+
realm 'us-west-1'
|
33
|
+
image 'ami-12345'
|
34
|
+
profile 't1.micro'
|
35
|
+
end
|
36
|
+
|
37
|
+
instance 'test-ec2-2' do
|
38
|
+
realm 'us-west-1'
|
39
|
+
image 'ami-54321'
|
40
|
+
profile 't1.micro'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
instances(:driver => :rhevm, :username => '', :password => '', :provider => '') do
|
45
|
+
instance 'test-rhev-1' do
|
46
|
+
image '12345-12345-12345-12345'
|
47
|
+
profile 'SERVER' do |p|
|
48
|
+
p.memory = 512
|
49
|
+
p.cpu = 4
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
on(:instance_started) do |i|
|
55
|
+
# i.pool_for_ssh ??
|
56
|
+
end
|
57
|
+
|
58
|
+
on(:running) do
|
59
|
+
ec2_instance('test-ec2-1') do |i|
|
60
|
+
# do something with this instance
|
61
|
+
end
|
62
|
+
|
63
|
+
rhevm_instance('test-rhev-1') do |i|
|
64
|
+
# Do someting ;-)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Thing above is just an definition, so now let start it:
|
70
|
+
|
71
|
+
@sample.start!
|
72
|
+
|
73
|
+
# All instances will be started in parallel (using threads)
|
74
|
+
|
75
|
+
|
76
|
+
License
|
77
|
+
-----------------
|
78
|
+
|
79
|
+
Licensed to the Apache Software Foundation (ASF) under one or more
|
80
|
+
contributor license agreements. See the NOTICE file distributed with
|
81
|
+
this work for additional information regarding copyright ownership. The
|
82
|
+
ASF licenses this file to you under the Apache License, Version 2.0 (the
|
83
|
+
"License"); you may not use this file except in compliance with the
|
84
|
+
License. You may obtain a copy of the License at
|
85
|
+
|
86
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
87
|
+
|
88
|
+
Unless required by applicable law or agreed to in writing, software
|
89
|
+
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
90
|
+
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
91
|
+
License for the specific language governing permissions and limitations
|
92
|
+
under the License.
|
data/lib/client.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'deltacloud'
|
2
|
+
|
3
|
+
module Deltacloud
|
4
|
+
|
5
|
+
def self.Client(d)
|
6
|
+
config = {
|
7
|
+
:driver => d.configuration.driver || :mock,
|
8
|
+
:username => d.configuration.user || 'mockuser',
|
9
|
+
:password => d.configuration.password || 'mockpassword',
|
10
|
+
}
|
11
|
+
config.merge!({
|
12
|
+
:provider => d.configuration.provider
|
13
|
+
}) unless d.configuration.provider.nil?
|
14
|
+
DeltaCloud::API.new(nil, nil, d.configuration.url || 'http://localhost:3001/api').with_config(config)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
data/lib/dsl.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
module Deltacloud
|
2
|
+
module DSL
|
3
|
+
|
4
|
+
def self.Task(name, &block)
|
5
|
+
Task.new(name, &block)
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.Instance(name, &block)
|
9
|
+
Instance.new(name, &block) if block_given?
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.Configuration(params={})
|
13
|
+
InstanceConfiguration.new(params)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.Instances(configuration={}, &block)
|
17
|
+
InstanceDefinition.new(configuration, &block) if block_given?
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
data/lib/instance.rb
ADDED
@@ -0,0 +1,194 @@
|
|
1
|
+
module Deltacloud
|
2
|
+
module DSL
|
3
|
+
|
4
|
+
class Instance
|
5
|
+
|
6
|
+
include EM::Deferrable
|
7
|
+
|
8
|
+
attr_reader :name
|
9
|
+
attr_reader :parameters
|
10
|
+
|
11
|
+
def initialize(name, &block)
|
12
|
+
@name = name
|
13
|
+
@parameters = {
|
14
|
+
:state => :new
|
15
|
+
}
|
16
|
+
instance_eval(&block) if block_given?
|
17
|
+
warn "WARNING: Realm is not defined for instance '#{name}'. (Default driver realm will be used)." if params.realm_id.nil?
|
18
|
+
raise "Image is not defined for instance '#{@name}'" if params.image_id.nil?
|
19
|
+
raise "Profile is not defined for instance '#{@name}'" if params.profile.nil?
|
20
|
+
end
|
21
|
+
|
22
|
+
# Make call to Deltacloud to create this instance object
|
23
|
+
# Please note that this call will put the instance into
|
24
|
+
# PENDING state in most cases (except Mock).
|
25
|
+
#
|
26
|
+
# Use .wait_for_running! to pool Deltacloud until instance
|
27
|
+
# is not RUNNING
|
28
|
+
#
|
29
|
+
def create(definition)
|
30
|
+
@client = Deltacloud::Client(@definition = definition)
|
31
|
+
instance_opts = {
|
32
|
+
:name => self.name
|
33
|
+
}
|
34
|
+
instance_opts.merge!(profile.to_instance_params)
|
35
|
+
instance_opts.merge!({
|
36
|
+
:realm_id => instance_realm_id,
|
37
|
+
})
|
38
|
+
from_instance!(@client.create_instance(instance_image_id, instance_opts))
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
# Pool Deltacloud API for the state change of instance every 5 seconds.
|
43
|
+
# This will block program execution for time needed to transient from
|
44
|
+
#
|
45
|
+
|
46
|
+
%w(running stopped pending).each do |state|
|
47
|
+
define_method :"wait_for_#{state}!" do |*max_retries|
|
48
|
+
retries = 0
|
49
|
+
return if state_is?(state)
|
50
|
+
begin
|
51
|
+
update!
|
52
|
+
# Some Deltacloud drivers (like RHEV-M) put instance to STOPPED state
|
53
|
+
# instead of RUNNING. Is not an error, but backend cloud behavior.
|
54
|
+
# If instance transient to STOPPED, then we try to START it without
|
55
|
+
# incrementing retry counter.
|
56
|
+
if state == 'running' and is_stopped?
|
57
|
+
start!
|
58
|
+
raise 'NotRunning'
|
59
|
+
else
|
60
|
+
retries += 1
|
61
|
+
raise 'NotInState' if (!state_is?(state)) && sleep(5)
|
62
|
+
end
|
63
|
+
rescue => e
|
64
|
+
retry if (e.message == 'NotInState') && (retries <= max_retries.first)
|
65
|
+
raise "Failed to put instance '#{self.name}' in #{state} state."
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# This method will try to connect to Deltacloud API and refresh all attributes
|
71
|
+
#
|
72
|
+
def update!
|
73
|
+
raise 'Instance must be created first in order to call update' if @definition.nil?
|
74
|
+
from_instance!(@client.instance(params.instance_id))
|
75
|
+
end
|
76
|
+
|
77
|
+
# Instance actions:
|
78
|
+
#
|
79
|
+
# instance.start! will start stopped instance (if supported)
|
80
|
+
# instance.stop! will stop running instance (if supported)
|
81
|
+
# instance.destroy! will destroy instance and set state to ':destroyed'
|
82
|
+
#
|
83
|
+
%w(start stop destroy).each do |action|
|
84
|
+
define_method :"#{action}!" do
|
85
|
+
instance_action(action.intern)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Helper for instance actions
|
90
|
+
#
|
91
|
+
def instance_action(action)
|
92
|
+
must_have_definition!
|
93
|
+
@client.instance(params.instance_id).send(:"#{action}!")
|
94
|
+
instance = @client.instance(params.instance_id)
|
95
|
+
if instance.nil?
|
96
|
+
@parameters[:state] = :destroyed
|
97
|
+
@parameters.delete(:instance_id)
|
98
|
+
self
|
99
|
+
else
|
100
|
+
from_instance!(instance)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Convert attributes from DeltaCloud::Instance object to Instance
|
105
|
+
#
|
106
|
+
def from_instance!(instance)
|
107
|
+
attrs = {
|
108
|
+
:instance_id => instance.id,
|
109
|
+
:state => instance.state.downcase.intern,
|
110
|
+
:public_addresses => instance.public_addresses,
|
111
|
+
:private_addresses => instance.private_addresses
|
112
|
+
}
|
113
|
+
attrs.merge!(:owner_id => instance.owner_id)
|
114
|
+
@parameters.merge!(attrs)
|
115
|
+
self
|
116
|
+
end
|
117
|
+
|
118
|
+
# Assing InstanceProfile to the instance.
|
119
|
+
# If no profile name is provided, will return the active profile
|
120
|
+
#
|
121
|
+
# InstanceProfile DSL example:
|
122
|
+
#
|
123
|
+
# instance 'test-instance' do
|
124
|
+
# profile 'm1-small' do |p|
|
125
|
+
# p.memory = 500
|
126
|
+
# end
|
127
|
+
# end
|
128
|
+
#
|
129
|
+
def profile(name=nil, &block)
|
130
|
+
if name
|
131
|
+
@parameters[:profile] = Deltacloud::DSL::InstanceProfile(name, &block)
|
132
|
+
else
|
133
|
+
instance_profile
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
# Convert instance param hash to OpenStruct object for easy retrieval
|
138
|
+
#
|
139
|
+
def params
|
140
|
+
Deltacloud::DSL::Configuration(@parameters)
|
141
|
+
end
|
142
|
+
|
143
|
+
# Define various helper methods:
|
144
|
+
#
|
145
|
+
# instance_[attribute] -> retrieve instance attribute (instance_state,
|
146
|
+
# instance_public_addresses, etc...)
|
147
|
+
# is_[state]? -> true if instance is in given state
|
148
|
+
# is_not_[state]? -> same as above just negated
|
149
|
+
#
|
150
|
+
# Whatever else method is called on this object with some parameters,
|
151
|
+
# this method will automatically be transformed to instance variable.
|
152
|
+
#
|
153
|
+
def method_missing(name, *args)
|
154
|
+
if name.to_s =~ /^instance_([\w_]+)$/
|
155
|
+
@parameters[$1.intern]
|
156
|
+
elsif name.to_s =~ /^is_(\w+)\?$/
|
157
|
+
state_is?($1.intern)
|
158
|
+
elsif name.to_s =~ /^is_not_(\w+)\?$/
|
159
|
+
!state_is?($1.intern)
|
160
|
+
elsif !args.empty?
|
161
|
+
set_param(name.to_sym, args)
|
162
|
+
else
|
163
|
+
super
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
private
|
168
|
+
|
169
|
+
def state_is?(state)
|
170
|
+
instance_state == state.to_sym
|
171
|
+
end
|
172
|
+
|
173
|
+
def must_have_definition!
|
174
|
+
raise 'Instance must be created first in order to start it' if @definition.nil?
|
175
|
+
end
|
176
|
+
|
177
|
+
def convert_id_param(name)
|
178
|
+
case name
|
179
|
+
when :realm then :realm_id
|
180
|
+
when :image then :image_id
|
181
|
+
else name
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def set_param(key, val)
|
186
|
+
@parameters ||= {}
|
187
|
+
k = convert_id_param(key)
|
188
|
+
@parameters[k] = (val.size == 1) ? val[0] : val
|
189
|
+
end
|
190
|
+
|
191
|
+
end
|
192
|
+
|
193
|
+
end
|
194
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Deltacloud
|
2
|
+
module DSL
|
3
|
+
|
4
|
+
class InstanceDefinition
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
attr_reader :instances, :configuration
|
8
|
+
|
9
|
+
def initialize(configuration, &block)
|
10
|
+
@instances = []
|
11
|
+
@configuration = Deltacloud::DSL::Configuration(configuration)
|
12
|
+
define &block
|
13
|
+
end
|
14
|
+
|
15
|
+
def define(&block)
|
16
|
+
instance_eval(&block) if block_given?
|
17
|
+
end
|
18
|
+
|
19
|
+
# Add more instances to this instance definition
|
20
|
+
#
|
21
|
+
# @task.mock_instances.first << Deltacloud::DSL::Instance('instance-2') do
|
22
|
+
# realm 'us'
|
23
|
+
# image 'img1'
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
def <<(instance)
|
27
|
+
@instances << instance
|
28
|
+
end
|
29
|
+
|
30
|
+
# Syntax suggar for adding new instances to instance definition
|
31
|
+
#
|
32
|
+
def instance(name, &block)
|
33
|
+
self << Deltacloud::DSL::Instance(name, &block) if block_given?
|
34
|
+
end
|
35
|
+
|
36
|
+
# Make instance definition enumerative for instances
|
37
|
+
#
|
38
|
+
def each(&block)
|
39
|
+
@instances.each { |instance| block.call(instance) }
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
module Deltacloud
|
4
|
+
module DSL
|
5
|
+
|
6
|
+
def self.InstanceProfile(name, &block)
|
7
|
+
InstanceProfile.new(name, &block) if block_given?
|
8
|
+
end
|
9
|
+
|
10
|
+
class InstanceProfile < OpenStruct
|
11
|
+
|
12
|
+
def initialize(name, &block)
|
13
|
+
super(:name => name)
|
14
|
+
define &block
|
15
|
+
end
|
16
|
+
|
17
|
+
def define(&block)
|
18
|
+
yield self if block_given?
|
19
|
+
end
|
20
|
+
|
21
|
+
# Convert InstanceProfile to DeltaCloud create_instance method parameters.
|
22
|
+
# Some property names varies from the names used in DeltaCloud. This
|
23
|
+
# method will deal with them.
|
24
|
+
#
|
25
|
+
def to_instance_params
|
26
|
+
params = self.marshal_dump
|
27
|
+
params[:hardware_profile] = params.delete(:name)
|
28
|
+
params[:hwp_memory] = params.delete(:memory) unless params[:memory].nil?
|
29
|
+
params[:hwp_cpu] = params.delete(:cpu) unless params[:cpu].nil?
|
30
|
+
params[:hwp_storage] = params.delete(:storage) unless params[:storage].nil?
|
31
|
+
params
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
data/lib/models.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
# Workaround for Ruby 1.8 which does not have 'require_relative'
|
4
|
+
# method defined
|
5
|
+
#
|
6
|
+
unless Kernel.respond_to?(:require_relative)
|
7
|
+
module Kernel
|
8
|
+
def require_relative(path)
|
9
|
+
require File.join(File.dirname(caller[0]), path.to_str)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
require_relative 'client'
|
15
|
+
require_relative 'dsl'
|
16
|
+
require_relative 'task'
|
17
|
+
require_relative 'instance'
|
18
|
+
require_relative 'instance_configuration'
|
19
|
+
require_relative 'instance_definition'
|
20
|
+
require_relative 'instance_profile'
|
data/lib/task.rb
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'eventmachine'
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
module Deltacloud
|
5
|
+
module DSL
|
6
|
+
|
7
|
+
class Task
|
8
|
+
|
9
|
+
attr_reader :name, :state_machine, :log
|
10
|
+
|
11
|
+
def initialize(name, &block)
|
12
|
+
@name = name
|
13
|
+
@state_machine = {}
|
14
|
+
@log = Logger.new(STDERR)
|
15
|
+
define &block
|
16
|
+
end
|
17
|
+
|
18
|
+
def define(&block)
|
19
|
+
instance_eval(&block) if block_given?
|
20
|
+
end
|
21
|
+
|
22
|
+
# Configure group of instances that would be launched
|
23
|
+
# using specified configuration.
|
24
|
+
#
|
25
|
+
# Configuration:
|
26
|
+
#
|
27
|
+
# :driver - Deltacloud API driver to use (default: mock)
|
28
|
+
# :provider - API_PROVIDER (eg. URL to RHEV-M API)
|
29
|
+
# :username - API key (default: mockuser)
|
30
|
+
# :password - API secret (default: mockpassword)
|
31
|
+
# :url - Deltacloud API url (default: http://localhost:3001/api)
|
32
|
+
#
|
33
|
+
# The block should define single instances:
|
34
|
+
#
|
35
|
+
# instances(:driver => :ec2, :username => API_KEY, :password => API_SECRET) do
|
36
|
+
# instance 'instance-1' do
|
37
|
+
# # instance configuration here
|
38
|
+
# end
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
def instances(configuration={}, &block)
|
42
|
+
return find_instances_by_driver(configuration) if configuration.kind_of? Symbol
|
43
|
+
@instances ||= []
|
44
|
+
@instances << Deltacloud::DSL::Instances(configuration, &block) if block_given?
|
45
|
+
@instances
|
46
|
+
end
|
47
|
+
|
48
|
+
# Declare a set of methods dynamically:
|
49
|
+
#
|
50
|
+
# find_instances_by_[attribute] => returns InstanceDefinition objects that
|
51
|
+
# match the value of attribute provided in method name
|
52
|
+
#
|
53
|
+
# [driver]_instances => return InstanceDefinition objects that correspond
|
54
|
+
# to given driver
|
55
|
+
#
|
56
|
+
# [driver]_instance => return Instance object that match with name
|
57
|
+
# eg. mock_instance 'test-mock-1' will find this
|
58
|
+
# instance.
|
59
|
+
#
|
60
|
+
# instances_[state] => return Instance objects with corresponding state
|
61
|
+
#
|
62
|
+
def method_missing(name, *args)
|
63
|
+
if name.to_s =~ /^find_instances_by_([\w_]+)$/
|
64
|
+
@instances.select { |i| i.configuration.respond_to?($1.intern) && args.include?(i.configuration.send($1.intern)) }
|
65
|
+
elsif name.to_s =~ /^(\w+)_instances$/
|
66
|
+
find_instances_by_driver($1.intern)
|
67
|
+
elsif name.to_s =~ /^(\w+)_instance$/
|
68
|
+
inst = find_instances_by_driver($1.intern).map { |instances| instances.find { |i| args.include?(i.name) } }.flatten.compact.first
|
69
|
+
yield inst if block_given?
|
70
|
+
inst
|
71
|
+
elsif name.to_s =~ /^instances_(\w+)\?$/
|
72
|
+
@instances.any? { |d| d.map { |i| (i.update! rescue true) && i.instance_state == $1.intern }.include? true }
|
73
|
+
else
|
74
|
+
super
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Start executing given task.
|
79
|
+
#
|
80
|
+
# This method will try to start all instances defined for all drivers.
|
81
|
+
# Then it will wait for instances to become running.
|
82
|
+
#
|
83
|
+
# Various callback can be provided for different state:
|
84
|
+
#
|
85
|
+
# on(:running) callback is triggered when all instances are running
|
86
|
+
# on(:instance_started) callback is triggered for every instance when become running
|
87
|
+
#
|
88
|
+
def start!
|
89
|
+
task = self
|
90
|
+
EventMachine::run do
|
91
|
+
inst_arr = []
|
92
|
+
task.instances.each do |definition|
|
93
|
+
inst_arr += definition.instances
|
94
|
+
definition.instances.each do |instance|
|
95
|
+
Thread.new do
|
96
|
+
begin
|
97
|
+
instance.create(definition).wait_for_running!
|
98
|
+
perform(:instance_started, instance)
|
99
|
+
log.info "Instance #{instance.name}[#{definition.configuration.driver}] successfully started."
|
100
|
+
rescue => e
|
101
|
+
log.error "ERROR: #{e.message}"
|
102
|
+
ensure
|
103
|
+
inst_arr.delete(instance)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
until inst_arr.empty?; end
|
109
|
+
perform(:running)
|
110
|
+
EM.stop
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Handler for callback definition:
|
115
|
+
#
|
116
|
+
# on(:running) do
|
117
|
+
# end
|
118
|
+
#
|
119
|
+
# on(:instance_started) do |instance|
|
120
|
+
# end
|
121
|
+
#
|
122
|
+
def on(state, &block)
|
123
|
+
@state_machine[state] = block if block_given?
|
124
|
+
end
|
125
|
+
|
126
|
+
# Syntax sugar for @state_machine callbacks
|
127
|
+
#
|
128
|
+
def state(state)
|
129
|
+
@state_machine[state]
|
130
|
+
end
|
131
|
+
|
132
|
+
# Syntax sugar for performing callbacks
|
133
|
+
#
|
134
|
+
def perform(s, item=nil)
|
135
|
+
return unless @state_machine.keys.include?(s)
|
136
|
+
state(s).call(item)
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# 1.8 compatibility fix
|
2
|
+
unless Kernel.respond_to?(:require_relative)
|
3
|
+
module Kernel
|
4
|
+
def require_relative(path)
|
5
|
+
require File.join(File.dirname(caller[0]), path.to_str)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
require_relative '../lib/models'
|
11
|
+
require 'minitest/autorun'
|
12
|
+
require 'minitest/benchmark'
|
13
|
+
|
14
|
+
describe Deltacloud::DSL::Task do
|
15
|
+
|
16
|
+
def prepare_threaded_sample(prefix)
|
17
|
+
@threaded_sample = Deltacloud::DSL::Task('threaded pool') do
|
18
|
+
|
19
|
+
# Say we want to launch 80 instances in Mock
|
20
|
+
instances(:driver => :mock) do
|
21
|
+
1.upto(80) do |i|
|
22
|
+
instance "test-#{prefix}-#{i}" do
|
23
|
+
realm 'us'
|
24
|
+
image 'img1'
|
25
|
+
profile 'm1-large' do |p|
|
26
|
+
p.memory = 7680
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# After benchmarch destroy all instances
|
33
|
+
on(:ready) do
|
34
|
+
mock_instances.each do |d|
|
35
|
+
d.instances.each do |i|
|
36
|
+
i.stop!.wait_for_stopped!
|
37
|
+
i.destroy!
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
bench_performance_linear "threaded_pool" do |n|
|
46
|
+
10.times do
|
47
|
+
threaded_sample = prepare_threaded_sample(Time.now.to_i)
|
48
|
+
threaded_sample.start!
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
data/tests/dsl_test.rb
ADDED
@@ -0,0 +1,203 @@
|
|
1
|
+
# 1.8 compatibility fix
|
2
|
+
unless Kernel.respond_to?(:require_relative)
|
3
|
+
module Kernel
|
4
|
+
def require_relative(path)
|
5
|
+
require File.join(File.dirname(caller[0]), path.to_str)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
require_relative '../lib/models'
|
11
|
+
require 'minitest/autorun'
|
12
|
+
|
13
|
+
describe Deltacloud::DSL::Task do
|
14
|
+
before do
|
15
|
+
@sample = Deltacloud::DSL::Task('launch instance') do
|
16
|
+
instances(:driver => :mock) do
|
17
|
+
instance 'test-instance-1' do
|
18
|
+
realm 'us'
|
19
|
+
image 'img1'
|
20
|
+
profile('m1-large') do |p|
|
21
|
+
p.memory = 7680
|
22
|
+
end
|
23
|
+
end
|
24
|
+
instance 'test-instance-2' do
|
25
|
+
realm 'us'
|
26
|
+
image 'img1'
|
27
|
+
profile('m1-large') do |p|
|
28
|
+
p.memory = 10000
|
29
|
+
end
|
30
|
+
end
|
31
|
+
instance 'test-instance-3' do
|
32
|
+
realm 'eu'
|
33
|
+
image 'img1'
|
34
|
+
profile('m1-large') do |p|
|
35
|
+
p.memory = 10000
|
36
|
+
end
|
37
|
+
end
|
38
|
+
instance 'test-instance-4' do
|
39
|
+
realm 'us'
|
40
|
+
image 'img1'
|
41
|
+
profile('m1-large') do |p|
|
42
|
+
p.memory = 10000
|
43
|
+
end
|
44
|
+
end
|
45
|
+
instance 'test-instance-5' do
|
46
|
+
realm 'eu'
|
47
|
+
image 'img1'
|
48
|
+
profile('m1-large') do |p|
|
49
|
+
p.memory = 10000
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
on :instance_started do |i|
|
54
|
+
puts i.params.state
|
55
|
+
end
|
56
|
+
on :running do
|
57
|
+
mock_instance 'test-instance-1' do |i|
|
58
|
+
#puts "Getting IP address out of test-instance-1"
|
59
|
+
#puts i.params.public_addresses
|
60
|
+
end
|
61
|
+
mock_instance 'test-instance-2' do |i|
|
62
|
+
#puts "Destroying instance test-instance-2..."
|
63
|
+
i.stop!.wait_for_stopped!
|
64
|
+
i.destroy!
|
65
|
+
#puts i.params.state
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe Deltacloud::DSL::Task do
|
72
|
+
it 'should be constructed' do
|
73
|
+
@sample.must_be_instance_of Deltacloud::DSL::Task
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should have proper name' do
|
77
|
+
@sample.name.must_equal 'launch instance'
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'should have state machine' do
|
81
|
+
@sample.state_machine.must_be_instance_of Hash
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should find instance by driver' do
|
85
|
+
@sample.find_instances_by_driver(:mock).must_be_instance_of Array
|
86
|
+
@sample.find_instances_by_driver(:mock).size.must_equal 1
|
87
|
+
@sample.find_instances_by_driver(:mock).first.must_be_instance_of Deltacloud::DSL::InstanceDefinition
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should return all mock instances' do
|
91
|
+
@sample.mock_instances.must_be_instance_of Array
|
92
|
+
@sample.mock_instances.size.must_equal 1
|
93
|
+
@sample.mock_instances.first.must_be_instance_of Deltacloud::DSL::InstanceDefinition
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'should be able to find single instance by name' do
|
97
|
+
@sample.mock_instance('test-instance-1').must_be_instance_of Deltacloud::DSL::Instance
|
98
|
+
@sample.mock_instance('test-instance-1') do |i|
|
99
|
+
i.must_be_instance_of Deltacloud::DSL::Instance
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'should figure out if instances are new or running' do
|
104
|
+
@sample.instances_running?.must_equal false
|
105
|
+
@sample.instances_new?.must_equal true
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'should run' do
|
109
|
+
@sample.start!
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
describe Deltacloud::DSL::InstanceDefinition do
|
115
|
+
|
116
|
+
it 'should return all defined instances' do
|
117
|
+
@sample.instances.must_be_instance_of Array
|
118
|
+
@sample.instances.size.must_equal 1
|
119
|
+
@sample.instances.each do |i|
|
120
|
+
i.must_be_instance_of Deltacloud::DSL::InstanceDefinition
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'should have configuration set for every instances' do
|
125
|
+
@sample.instances.first.configuration.wont_be_nil
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'should have mock driver configuration' do
|
129
|
+
@sample.instances.first.configuration.driver.must_equal :mock
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'should find instances using driver' do
|
133
|
+
@sample.find_instances_by_driver(:mock).must_be_instance_of Array
|
134
|
+
@sample.find_instances_by_driver(:mock).size.must_equal 1
|
135
|
+
@sample.find_instances_by_driver(:mock).first.must_be_instance_of Deltacloud::DSL::InstanceDefinition
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
describe Deltacloud::DSL::Instance do
|
141
|
+
|
142
|
+
it 'should be all valid instances' do
|
143
|
+
@sample.mock_instances.first.each do |inst|
|
144
|
+
inst.must_be_instance_of Deltacloud::DSL::Instance
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'should find mock instance by name' do
|
149
|
+
@sample.mock_instance('test-instance-1') do |i|
|
150
|
+
i.wont_be_nil
|
151
|
+
i.must_be_instance_of Deltacloud::DSL::Instance
|
152
|
+
i.name.must_equal 'test-instance-1'
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'should all have have valid name' do
|
157
|
+
@sample.mock_instances.first.each do |inst|
|
158
|
+
inst.name.wont_be_nil
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'should have realm_id and image_id parameters defined' do
|
163
|
+
@sample.mock_instances.first.each do |inst|
|
164
|
+
['us', 'eu'].must_include inst.params.realm_id
|
165
|
+
inst.params.image_id.must_equal 'img1'
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'should have valid instance profile defined' do
|
170
|
+
@sample.mock_instances.first.each do |inst|
|
171
|
+
inst.instance_profile.must_be_instance_of Deltacloud::DSL::InstanceProfile
|
172
|
+
inst.instance_profile.name.wont_be_nil
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'should have memory specified in instance profile' do
|
177
|
+
@sample.mock_instances.first.each do |inst|
|
178
|
+
inst.instance_profile.memory.wont_be_nil
|
179
|
+
inst.instance_profile.memory.must_be_instance_of Fixnum
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
it 'should allow manipulation of instances' do
|
184
|
+
definition = @sample.mock_instances.first
|
185
|
+
instance = @sample.mock_instance('test-instance-3')
|
186
|
+
instance.create(definition).must_be_instance_of Deltacloud::DSL::Instance
|
187
|
+
instance.instance_owner_id.must_equal 'mockuser'
|
188
|
+
instance.params.state.must_equal :running
|
189
|
+
instance.is_running?.must_equal true
|
190
|
+
instance.is_not_running?.must_equal false
|
191
|
+
instance.is_stopped?.must_equal false
|
192
|
+
instance.stop!.must_be_instance_of Deltacloud::DSL::Instance
|
193
|
+
instance.params.state.must_equal :stopped
|
194
|
+
instance.is_running?.must_equal false
|
195
|
+
instance.is_stopped?.must_equal true
|
196
|
+
instance.destroy!.must_be_instance_of Deltacloud::DSL::Instance
|
197
|
+
instance.is_destroyed?.must_equal true
|
198
|
+
instance.params.instance_id.must_be_nil
|
199
|
+
end
|
200
|
+
|
201
|
+
end
|
202
|
+
|
203
|
+
end
|
data/tests/test_test.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
|
3
|
+
class Meme
|
4
|
+
def initialize
|
5
|
+
end
|
6
|
+
|
7
|
+
def i_can_has_cheezburger?
|
8
|
+
'OHAI!'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe Meme do
|
13
|
+
before do
|
14
|
+
@meme = Meme.new
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "when asked about cheeseburgers" do
|
18
|
+
it "must respond positively" do
|
19
|
+
@meme.i_can_has_cheezburger?.must_equal "OHAI!"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "when asked about blending possibilities" do
|
24
|
+
it "won't say no" do
|
25
|
+
@meme.will_it_blend?.wont_match /^no/i
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: deltadsl
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '1.0'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Michal Fojtik
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-02-28 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: deltacloud-client
|
16
|
+
requirement: &70175076503460 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.5.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70175076503460
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: eventmachine
|
27
|
+
requirement: &70175076501840 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70175076501840
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: minitest
|
38
|
+
requirement: &70175076500080 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70175076500080
|
47
|
+
description: Deltacloud API powered DSL for creating complex deployments
|
48
|
+
email: dev@deltacloud.apache.org
|
49
|
+
executables: []
|
50
|
+
extensions: []
|
51
|
+
extra_rdoc_files:
|
52
|
+
- README.md
|
53
|
+
files:
|
54
|
+
- README.md
|
55
|
+
- lib/client.rb
|
56
|
+
- lib/dsl.rb
|
57
|
+
- lib/instance.rb
|
58
|
+
- lib/instance_configuration.rb
|
59
|
+
- lib/instance_definition.rb
|
60
|
+
- lib/instance_profile.rb
|
61
|
+
- lib/models.rb
|
62
|
+
- lib/task.rb
|
63
|
+
- tests/deltacloud_perf_test.rb
|
64
|
+
- tests/dsl_test.rb
|
65
|
+
- tests/test_test.rb
|
66
|
+
homepage: http://www.deltacloud.org
|
67
|
+
licenses: []
|
68
|
+
post_install_message:
|
69
|
+
rdoc_options: []
|
70
|
+
require_paths:
|
71
|
+
- lib
|
72
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
|
+
none: false
|
80
|
+
requirements:
|
81
|
+
- - ! '>='
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
requirements: []
|
85
|
+
rubyforge_project:
|
86
|
+
rubygems_version: 1.8.15
|
87
|
+
signing_key:
|
88
|
+
specification_version: 3
|
89
|
+
summary: Deltacloud API DSL
|
90
|
+
test_files:
|
91
|
+
- tests/deltacloud_perf_test.rb
|
92
|
+
- tests/dsl_test.rb
|
93
|
+
- tests/test_test.rb
|