dployr 0.0.1

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.
@@ -0,0 +1,99 @@
1
+ require 'dployr/utils'
2
+
3
+ module Dployr
4
+ module Config
5
+ class Instance
6
+
7
+ include Dployr::Utils
8
+
9
+ attr_reader :attributes, :providers, :authentication, :scripts, :parents
10
+ attr_accessor :name
11
+
12
+ def initialize
13
+ @name = 'unnamed'
14
+ @attributes = {}
15
+ @authentication = {}
16
+ @scripts = []
17
+ @providers = {}
18
+ @parents = []
19
+ yield self if block_given?
20
+ end
21
+
22
+ def configure(config)
23
+ if config.is_a? Hash
24
+ set_attributes get_by_key config, :attributes if has config, :attributes
25
+ set_providers get_by_key config, :providers if has config, :providers
26
+ set_auth get_by_key config, :authentication if has config, :authentication
27
+ set_scripts get_by_key config, :scripts if has config, :scripts
28
+ set_parents get_by_key config, :extends if has config, :extends
29
+ end
30
+ end
31
+
32
+ def get_values
33
+ deep_copy({
34
+ attributes: @attributes,
35
+ authentication: @authentication,
36
+ scripts: @scripts,
37
+ providers: @providers,
38
+ parents: @parents
39
+ })
40
+ end
41
+
42
+ def set_attribute(key, value)
43
+ @attributes[key] = value
44
+ end
45
+
46
+ def get_attribute(key)
47
+ @attributes[key]
48
+ end
49
+
50
+ def remove_attribute(key)
51
+ @attributes.remove key
52
+ end
53
+
54
+ def add_script(script)
55
+ @scripts << script if script.is_a? Hash
56
+ end
57
+
58
+ def add_auth(key, value)
59
+ @authentication[key] = value if key
60
+ end
61
+
62
+ def add_provider(name, provider)
63
+ @providers[name] = provider if provider.is_a? Hash
64
+ end
65
+
66
+ def get_provider(index)
67
+ @providers[index]
68
+ end
69
+
70
+ def remove_provider(provider)
71
+ @providers.delete provider
72
+ end
73
+
74
+ private
75
+
76
+ def set_auth(auth)
77
+ @authentication = auth if auth.is_a? Hash
78
+ end
79
+
80
+ def set_providers(providers)
81
+ @providers = providers if providers.is_a? Hash
82
+ end
83
+
84
+ def set_scripts(scripts)
85
+ @scripts = scripts if scripts.is_a? Array
86
+ end
87
+
88
+ def set_attributes(attrs)
89
+ @attributes = attrs if attrs.is_a? Hash
90
+ end
91
+
92
+ def set_parents(parents)
93
+ parents = [ parents ] if parents.is_a? String
94
+ @parents.concat parents if parents.is_a? Array
95
+ end
96
+
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,163 @@
1
+ require 'dployr/utils'
2
+
3
+ module Dployr
4
+ class Configuration
5
+
6
+ include Dployr::Utils
7
+
8
+ attr_reader :default, :instances
9
+
10
+ def initialize
11
+ @default = nil
12
+ @config = nil
13
+ @instances = []
14
+ @merged = false
15
+ yield self if block_given?
16
+ end
17
+
18
+ def exists?
19
+ (!@default.nil? or @instances.length >= 1)
20
+ end
21
+
22
+ def set_default(config)
23
+ @default = create_instance('default', config) if config.is_a? Hash
24
+ end
25
+
26
+ def add_instance(name, config)
27
+ @instances << create_instance(name, config) if config.is_a? Hash
28
+ @instances.last
29
+ end
30
+
31
+ def get_instance(name)
32
+ @instances.each { |i| return i if i.name.to_s == name.to_s }
33
+ nil
34
+ end
35
+
36
+ def get_config(name, attributes = {})
37
+ instance = get_instance name
38
+ raise ArgumentError.new "Instance '#{name.to_s}' do not exists" if instance.nil?
39
+ replace_variables merge_config(instance), replace_variables(attributes)
40
+ end
41
+
42
+ def get_config_all(attributes = {})
43
+ config = []
44
+ @instances.each do |i|
45
+ config << get_config(i.name, attributes)
46
+ end
47
+ puts config
48
+ config
49
+ end
50
+
51
+ def get_provider(name, provider, attributes = {})
52
+ config = get_config name, attributes
53
+ if config.is_a? Hash
54
+ config = config[get_real_key(config, :providers)]
55
+ if config.is_a? Hash
56
+ return config[get_real_key(config, provider)]
57
+ end
58
+ end
59
+ end
60
+
61
+ def get_region(name, provider, region, attributes = {})
62
+ provider = get_provider name, provider, attributes
63
+ if provider.is_a? Hash
64
+ regions = get_by_key provider, :regions
65
+ return get_by_key regions, region
66
+ end
67
+ end
68
+
69
+ def each(type = :providers)
70
+ config = get_config_all
71
+ config.each { |i| yield i if block_given? }
72
+ end
73
+
74
+ private
75
+
76
+ def create_instance(name = 'unnamed', config)
77
+ Dployr::Config::Instance.new do |i|
78
+ i.name = name
79
+ i.configure config
80
+ end if config.is_a? Hash
81
+ end
82
+
83
+ def replace_variables(config, attributes = {})
84
+ if config.is_a? Hash
85
+ attrs = get_all_attributes config
86
+ attrs.merge! attributes if attributes.is_a? Hash
87
+ traverse_map config do |str, key|
88
+ replace_env_vars template(str, attrs)
89
+ end
90
+ end
91
+ config
92
+ end
93
+
94
+ def get_all_attributes(config)
95
+ attrs = {}
96
+ config.each do |key, value|
97
+ if key.to_sym == :attributes
98
+ attrs.merge! value if value.is_a? Hash
99
+ elsif value.is_a? Hash
100
+ attrs.merge! get_all_attributes value
101
+ end
102
+ end if config.is_a? Hash
103
+ attrs
104
+ end
105
+
106
+ def merge_config(instance)
107
+ merge_providers merge_parents merge_defaults instance.get_values
108
+ end
109
+
110
+ def merge_defaults(config)
111
+ config = deep_merge @default.get_values, config if @default
112
+ config
113
+ end
114
+
115
+ def merge_providers(config)
116
+ key = get_real_key config, :providers
117
+ if config[key].is_a? Hash
118
+ config[key].each do |name, provider|
119
+ provider = replace_keywords 'provider', name, inherit_config(provider, config)
120
+ regions = get_by_key provider, get_real_key(provider, :regions)
121
+ regions.each do |name, region|
122
+ regions[name] = replace_keywords 'region', name, inherit_config(region, provider)
123
+ end if regions
124
+ end
125
+ end
126
+ config
127
+ end
128
+
129
+ def replace_keywords(keyword, value, hash)
130
+ traverse_map hash do |str|
131
+ str.gsub "${#{keyword.to_s}}", value.to_s
132
+ end if hash.is_a? Hash
133
+ end
134
+
135
+ def inherit_config(child, parent)
136
+ keys = [ :attributes, :scripts, :authentication ]
137
+ keys.each do |type|
138
+ current = deep_copy get_by_key(parent, type)
139
+ source = get_by_key child, type
140
+ if type == :scripts
141
+ current = [] unless current.is_a? Array
142
+ current.concat source if source.is_a? Array
143
+ current = current.compact.uniq
144
+ else
145
+ current = {} unless current.is_a? Hash
146
+ current = deep_merge current, source
147
+ end
148
+ child[type] = current if current.length
149
+ end
150
+ child
151
+ end
152
+
153
+ def merge_parents(child)
154
+ parents = get_by_key child, :parents
155
+ parents = [ parents ] if parents.is_a? String
156
+ parents.each do |parent|
157
+ parent = get_instance parent
158
+ child = deep_merge parent.get_values, child unless parent.nil?
159
+ end if parents.is_a? Array
160
+ child
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,72 @@
1
+ require 'dployr/configuration'
2
+ require 'dployr/config/file_utils'
3
+
4
+ module Dployr
5
+
6
+ module_function
7
+
8
+ def configure(attributes = {})
9
+ dployr = Init::instance
10
+ yield dployr if block_given?
11
+ end
12
+
13
+ def config
14
+ dployr = Init::instance
15
+ dployr.config if dployr
16
+ end
17
+
18
+ def load(file_path)
19
+ if Dployr::Config::FileUtils.yaml_file? file_path
20
+ Dployr::Config::FileUtils.read_yaml file_path
21
+ else
22
+ load file_path
23
+ end
24
+ end
25
+
26
+ class Init
27
+
28
+ include Dployr::Config::FileUtils
29
+
30
+ attr_reader :file_path, :config
31
+
32
+ @@instance = nil
33
+
34
+ def initialize(attributes = {})
35
+ @@instance = self
36
+ @attributes = attributes
37
+ @config = Dployr::Configuration.new
38
+ @file_path = discover
39
+ load_file @file_path
40
+ end
41
+
42
+ def self.instance
43
+ @@instance
44
+ end
45
+
46
+ private
47
+
48
+ def load_file(file_path)
49
+ if file_path.is_a? String
50
+ if yaml_file? file_path
51
+ load_yaml file_path
52
+ else
53
+ load file_path
54
+ end
55
+ end
56
+ end
57
+
58
+ def load_yaml(file_path)
59
+ config = read_yaml file_path
60
+ if config.is_a? Hash
61
+ config.each do |name, config|
62
+ if name == 'default'
63
+ @config.set_default config
64
+ else
65
+ @config.add_instance name, config
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ end
72
+ end
@@ -0,0 +1,11 @@
1
+ module Dployr
2
+ module Logger
3
+
4
+ module_function
5
+
6
+ def log(*msg)
7
+ msg.each { |msg| puts msg }
8
+ end
9
+
10
+ end
11
+ end
@@ -0,0 +1,127 @@
1
+ module Dployr
2
+ module Utils
3
+
4
+ MERGE_OPTIONS = { merge_hash_arrays: false, knockout_prefix: false }
5
+
6
+ module_function
7
+
8
+ def has(hash, key)
9
+ (hash.is_a? Hash and
10
+ (hash.key? key or hash.key? key.to_sym or hash.key? key.to_s))
11
+ end
12
+
13
+ def get_by_key(hash, key)
14
+ if hash.is_a? Hash
15
+ hash[key] or hash[key.to_sym] or hash[key.to_s]
16
+ end
17
+ end
18
+
19
+ def get_real_key(hash, key)
20
+ if hash.is_a? Hash
21
+ if hash.key? key
22
+ key
23
+ elsif hash.key? key.to_sym
24
+ key.to_sym
25
+ elsif hash.key? key.to_s
26
+ key.to_s
27
+ end
28
+ end
29
+ end
30
+
31
+ def merge(target, *origins)
32
+ origins.each { |h| target = target.merge h }
33
+ target
34
+ end
35
+
36
+ def deep_merge(target = {}, *origins)
37
+ origins.each do |h|
38
+ target.deep_merge! h, MERGE_OPTIONS if h.is_a? Hash
39
+ end
40
+ target
41
+ end
42
+
43
+ def deep_copy(o)
44
+ Marshal.load Marshal.dump o
45
+ end
46
+
47
+ def parse_matrix(str)
48
+ hash = {}
49
+ str.split(';').each do |val|
50
+ val = val.split '='
51
+ hash[val.first.strip] = val.last.strip
52
+ end if str.is_a? String
53
+ hash
54
+ end
55
+
56
+ def parse_flags(str)
57
+ hash = {}
58
+ str.gsub(/\s+/, ' ').strip.split(' ').each_slice(2) do |val|
59
+ key = val.first
60
+ if val.first.is_a? String
61
+ key = key.gsub(/^\-+/, '').strip
62
+ hash[key] = (val.last or '').strip
63
+ end
64
+ end if str.is_a? String
65
+ hash
66
+ end
67
+
68
+ def replace_vars(str)
69
+ str.gsub(/\%\{(\w+)\}/) { yield $1 }
70
+ end
71
+
72
+ def template(str, data)
73
+ raise ArgumentError.new 'Data must be a hash' unless data.is_a? Hash
74
+ replace_vars str do |match|
75
+ key = get_real_key data, match
76
+ if key
77
+ data[key]
78
+ else
79
+ raise ArgumentError.new "Missing template variable: #{match}"
80
+ end
81
+ end
82
+ end
83
+
84
+ def replace_env_vars(str)
85
+ str.gsub(/\$\{(\w+)\}/) do
86
+ if ENV.key? $1
87
+ ENV[$1]
88
+ else
89
+ ''
90
+ end
91
+ end
92
+ end
93
+
94
+ def replace_placeholders(str, data)
95
+ str % data if data.is_a? Hash or data.is_a? Array
96
+ end
97
+
98
+ def traverse_map(hash, &block)
99
+ traverse_mapper hash, nil, &block
100
+ end
101
+
102
+ def traverse_mapper(hash, key, &block)
103
+ case hash
104
+ when String
105
+ hash = yield hash, key
106
+ when Array
107
+ hash.map! { |item| traverse_mapper item, nil, &block }
108
+ when Hash
109
+ buf = {}
110
+ hash.each do |k, v|
111
+ if k.is_a? String
112
+ new_key = yield k, k
113
+ if new_key != k
114
+ hash.delete k
115
+ buf[new_key] = traverse_mapper v, new_key, &block
116
+ next
117
+ end
118
+ end
119
+ hash[k] = traverse_mapper v, k, &block
120
+ end
121
+ hash.merge! buf
122
+ end
123
+ hash
124
+ end
125
+
126
+ end
127
+ end
@@ -0,0 +1,3 @@
1
+ module Dployr
2
+ VERSION = '0.0.1'
3
+ end
data/lib/dployr.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'yaml'
2
+ require 'deep_merge'
3
+ require 'dployr/version'
4
+ require 'dployr/init'
5
+ require 'dployr/configuration'
6
+ require 'dployr/config/create'
7
+ require 'dployr/config/file_utils'
8
+ require 'dployr/config/instance'
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ describe Dployr::Config::FileUtils do
4
+
5
+ describe :read_yaml do
6
+ it "should expose the read method" do
7
+ Dployr::Config::FileUtils.respond_to?(:read_yaml).should be_true
8
+ end
9
+
10
+ it "should have a valid number of items" do
11
+ Dployr::Config::FileUtils.read_yaml(File.dirname(__FILE__) + '/fixtures/Dployrfile.yml').should have(2).item
12
+ end
13
+ end
14
+
15
+ describe :discover do
16
+ let(:pwd) { Dir.pwd }
17
+ let(:filename) { Dployr::Config::FileUtils::FILENAME }
18
+ let(:tmpdir) { File.join File.dirname(__FILE__), 'fixtures', '.tmp' }
19
+ let(:fixtures) { File.join File.dirname(__FILE__), 'fixtures' }
20
+
21
+ describe "current directory" do
22
+ context "when cannot discover" do
23
+ it { Dployr::Config::FileUtils.discover.should eql nil }
24
+ end
25
+
26
+ context "when discover" do
27
+ let(:expected) { File.join fixtures, filename }
28
+
29
+ before do
30
+ Dir.chdir fixtures
31
+ end
32
+
33
+ it { Dployr::Config::FileUtils.discover.should_not be_empty }
34
+
35
+ it { Dployr::Config::FileUtils.discover.should eql expected }
36
+
37
+ after do
38
+ Dir.chdir pwd
39
+ end
40
+ end
41
+ end
42
+
43
+ describe "higher directories" do
44
+ context "when discover" do
45
+ let(:expected) { File.join fixtures, filename }
46
+
47
+ before do
48
+ FileUtils.mkdir_p File.join tmpdir, 'sample'
49
+ Dir.chdir File.join tmpdir, 'sample'
50
+ end
51
+
52
+ after do
53
+ Dir.chdir pwd
54
+ FileUtils.rm_rf tmpdir
55
+ end
56
+
57
+ it { Dployr::Config::FileUtils.discover.should eql expected }
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+
3
+ describe Dployr::Config::Instance do
4
+ describe "Instance" do
5
+ describe "instance configuration" do
6
+ let(:instance) {
7
+ Dployr::Config::Instance.new
8
+ }
9
+
10
+ describe "setting attributes" do
11
+ context "when created" do
12
+ subject { instance.attributes }
13
+ it { should be_a Hash }
14
+ it { should have(0).items }
15
+ end
16
+
17
+ context "when add attributes" do
18
+ before do
19
+ instance.set_attribute :key, "value"
20
+ end
21
+
22
+ subject { instance.attributes }
23
+ it { should have_key(:key) }
24
+ end
25
+ end
26
+
27
+ describe "setting providers" do
28
+ context "when created" do
29
+ subject { instance.providers }
30
+ it { should be_a Hash }
31
+ it { should have(0).items }
32
+ end
33
+
34
+ describe "setting providers" do
35
+ let(:provider) do
36
+ {
37
+ attributes: {
38
+ instance_type: "m1.small"
39
+ },
40
+ scripts: [],
41
+ regions: {}
42
+ }
43
+ end
44
+
45
+ context "when add a provider" do
46
+ before do
47
+ instance.add_provider :aws, provider
48
+ end
49
+
50
+ subject { instance.get_provider :aws }
51
+ it { should be_a Hash }
52
+ it { should have_key(:attributes) }
53
+ it { should have_key(:scripts) }
54
+ it { should have_key(:regions) }
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end