cm 0.1.6 → 0.1.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: edae52b5afcceb98e314ad3cf88c6e85e92936b3
4
- data.tar.gz: 3b7f5440d1f088d7010ff5e9f9eee485ea3bdebc
3
+ metadata.gz: 056ec04a3593572a5b3d8ebf419d51d43a0682f6
4
+ data.tar.gz: f83af1f80f2ffa7ee0a66ebc16e92e66cddb7ec3
5
5
  SHA512:
6
- metadata.gz: 4f3107e50edb0d39d060650f64e136dd527723da8652c49ce0c6454f36bd220b649df1a7360462de6ea074608dd20d53f878c24f4bdfa20bb33a0813af202d4d
7
- data.tar.gz: 8af5ebdb2a390a1d1a9589a99dff19bf421c75b49aa2c28628abd5d3f988540e090d6f94008c688e061a9ee9d557deb623fc4be7f63d722277743b1ed7bd3631
6
+ metadata.gz: 01caec2831c096f83f8bde1d2823aaaaf126a651171c6ea8e28946d34b52aa1e41112726ca12aa1fd9cab7719e5e0c3536513926c438d397177768856bbdc3e7
7
+ data.tar.gz: 8fd25cc3a79ee4833335bb2c21b7fc8388bcb706d1a634b93726f438380aa419fc3aeb876da09ad7b112dddc2207773bb429d164094e969648d5b7eb5739829c
data/.gitignore CHANGED
@@ -11,6 +11,9 @@ pkg
11
11
  # Gem builds
12
12
  *.gem
13
13
 
14
+ # Vagrant
15
+ .vagrant
16
+
14
17
  # Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
15
18
  #
16
19
  # * Create a file at ~/.gitignore
data/.gitmodules CHANGED
@@ -1,3 +1,6 @@
1
1
  [submodule "bootstrap"]
2
2
  path = bootstrap
3
3
  url = https://github.com/adrianwebb/cm-bootstrap.git
4
+ [submodule "toolbox"]
5
+ path = toolbox
6
+ url = https://github.com/adrianwebb/gem-toolbox.git
data/Gemfile CHANGED
@@ -2,9 +2,11 @@ source "http://rubygems.org"
2
2
 
3
3
  gem "nucleon", "~> 0.2"
4
4
  gem "docker-api", "~> 1.24" # Compatible with Docker API version 1.16
5
+ gem "nokogiri", "= 1.5.11"
6
+ gem "fog-aws", "~> 0.8"
5
7
 
6
8
  group :development do
7
- gem "bundler", "~> 1.10"
9
+ gem "bundler", ">= 1.7"
8
10
  gem "jeweler", "~> 2.0"
9
11
  gem "rspec", "~> 3.4"
10
12
  gem "rdoc", "~> 4.2"
data/Gemfile.lock CHANGED
@@ -20,34 +20,48 @@ GEM
20
20
  timers (>= 4.1.1)
21
21
  celluloid-supervision (0.20.5)
22
22
  timers (>= 4.1.1)
23
- childprocess (0.5.8)
23
+ childprocess (0.5.9)
24
24
  ffi (~> 1.0, >= 1.0.11)
25
25
  deep_merge (1.0.1)
26
- descendants_tracker (0.0.4)
27
- thread_safe (~> 0.3, >= 0.3.1)
28
26
  diff-lcs (1.2.5)
29
27
  docker-api (1.24.1)
30
28
  excon (>= 0.38.0)
31
29
  json
32
30
  erubis (2.7.0)
33
31
  excon (0.45.4)
34
- faraday (0.9.2)
35
- multipart-post (>= 1.2, < 3)
32
+ faraday (0.8.11)
33
+ multipart-post (~> 1.2.0)
36
34
  ffi (1.9.10)
35
+ fog-aws (0.8.1)
36
+ fog-core (~> 1.27)
37
+ fog-json (~> 1.0)
38
+ fog-xml (~> 0.1)
39
+ ipaddress (~> 0.8)
40
+ fog-core (1.35.0)
41
+ builder
42
+ excon (~> 0.45)
43
+ formatador (~> 0.2)
44
+ fog-json (1.0.2)
45
+ fog-core (~> 1.0)
46
+ multi_json (~> 1.10)
47
+ fog-xml (0.1.2)
48
+ fog-core
49
+ nokogiri (~> 1.5, >= 1.5.11)
50
+ formatador (0.2.5)
37
51
  git (1.2.9.1)
38
- github_api (0.13.0)
39
- addressable (~> 2.3)
40
- descendants_tracker (~> 0.0.4)
41
- faraday (~> 0.8, < 0.10)
42
- hashie (>= 3.4)
43
- multi_json (>= 1.7.5, < 2.0)
44
- nokogiri (~> 1.6.6)
52
+ github_api (0.10.1)
53
+ addressable
54
+ faraday (~> 0.8.1)
55
+ hashie (>= 1.2)
56
+ multi_json (~> 1.4)
57
+ nokogiri (~> 1.5.2)
45
58
  oauth2
46
59
  hashie (3.4.3)
47
60
  highline (1.7.8)
48
61
  hitimes (1.2.3)
49
62
  i18n (0.7.0)
50
- jeweler (2.0.1)
63
+ ipaddress (0.8.2)
64
+ jeweler (2.0.0)
51
65
  builder
52
66
  bundler (>= 1.0)
53
67
  git (>= 1.2.5)
@@ -59,14 +73,12 @@ GEM
59
73
  json (1.8.3)
60
74
  jwt (1.5.2)
61
75
  log4r (1.1.10)
62
- mini_portile2 (2.0.0)
63
76
  multi_json (1.11.2)
64
77
  multi_xml (0.5.5)
65
- multipart-post (2.0.0)
78
+ multipart-post (1.2.0)
66
79
  netrc (0.11.0)
67
- nokogiri (1.6.7)
68
- mini_portile2 (~> 2.0.0.rc2)
69
- nucleon (0.2.15)
80
+ nokogiri (1.5.11)
81
+ nucleon (0.2.16)
70
82
  celluloid (~> 0.17)
71
83
  childprocess (~> 0.5)
72
84
  deep_merge (~> 1.0)
@@ -89,7 +101,7 @@ GEM
89
101
  sawyer (~> 0.6.0, >= 0.5.3)
90
102
  rack (1.6.4)
91
103
  rake (10.4.2)
92
- rdoc (4.2.0)
104
+ rdoc (4.2.1)
93
105
  json (~> 1.4)
94
106
  rspec (3.4.0)
95
107
  rspec-core (~> 3.4.0)
@@ -109,7 +121,6 @@ GEM
109
121
  addressable (~> 2.3.5)
110
122
  faraday (~> 0.8, < 0.10)
111
123
  sshkey (1.8.0)
112
- thread_safe (0.3.5)
113
124
  timers (4.1.1)
114
125
  hitimes
115
126
 
@@ -117,12 +128,11 @@ PLATFORMS
117
128
  ruby
118
129
 
119
130
  DEPENDENCIES
120
- bundler (~> 1.10)
131
+ bundler (>= 1.7)
121
132
  docker-api (~> 1.24)
133
+ fog-aws (~> 0.8)
122
134
  jeweler (~> 2.0)
135
+ nokogiri (= 1.5.11)
123
136
  nucleon (~> 0.2)
124
137
  rdoc (~> 4.2)
125
138
  rspec (~> 3.4)
126
-
127
- BUNDLED WITH
128
- 1.10.6
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.6
1
+ 0.1.8
data/cm.gemspec CHANGED
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: cm 0.1.6 ruby lib
5
+ # stub: cm 0.1.8 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "cm"
9
- s.version = "0.1.6"
9
+ s.version = "0.1.8"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib"]
13
13
  s.authors = ["Adrian Webb"]
14
- s.date = "2015-12-27"
14
+ s.date = "2016-01-18"
15
15
  s.description = "\nPluggable cloud management framework that provides a simple foundation for\ndeploying and destroying enterprise ready cloud environments and components\nthat integrate; cloud provider components and services, cloud orchestration\nand configuration management tools, and continuous integration and delivery\npipelines.\n"
16
16
  s.email = "adrian.webb@gsa.gov"
17
17
  s.executables = ["cm"]
@@ -35,9 +35,8 @@ Gem::Specification.new do |s|
35
35
  "lib/CM/plan/default.rb",
36
36
  "lib/CM/resource/AWS.rb",
37
37
  "lib/CM/resource/BOSH.rb",
38
- "lib/CM/resource/MicroBOSH.rb",
39
38
  "lib/CM/resource/concourse.rb",
40
- "lib/CM/resource/keypair.rb",
39
+ "lib/CM/resource/plan.rb",
41
40
  "lib/CM/resource/variables.rb",
42
41
  "lib/CM/sequence/default.rb",
43
42
  "lib/cm.rb",
@@ -62,13 +61,16 @@ Gem::Specification.new do |s|
62
61
  "lib/nucleon/action/plan/destroy.rb",
63
62
  "lib/nucleon/action/resource/run.rb",
64
63
  "locales/en.yml",
65
- "spec/spec_helper.rb"
64
+ "spec/spec_helper.rb",
65
+ "toolbox/LICENSE.txt",
66
+ "toolbox/README.txt",
67
+ "toolbox/lib/shell/LICENSE.txt"
66
68
  ]
67
69
  s.homepage = "http://github.com/adrianwebb/cm"
68
70
  s.licenses = ["Apache License, Version 2.0"]
69
71
  s.rdoc_options = ["--title", "CM (Cloud Manager)", "--main", "README.rdoc", "--line-numbers"]
70
72
  s.required_ruby_version = Gem::Requirement.new(">= 1.9.1")
71
- s.rubygems_version = "2.4.5"
73
+ s.rubygems_version = "2.4.8"
72
74
  s.summary = "Pluggable cloud management framework that provides a simple foundation for deploying and destroying enterprise ready cloud environments and components"
73
75
 
74
76
  if s.respond_to? :specification_version then
@@ -77,14 +79,18 @@ Gem::Specification.new do |s|
77
79
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
78
80
  s.add_runtime_dependency(%q<nucleon>, ["~> 0.2"])
79
81
  s.add_runtime_dependency(%q<docker-api>, ["~> 1.24"])
80
- s.add_development_dependency(%q<bundler>, ["~> 1.10"])
82
+ s.add_runtime_dependency(%q<nokogiri>, ["= 1.5.11"])
83
+ s.add_runtime_dependency(%q<fog-aws>, ["~> 0.8"])
84
+ s.add_development_dependency(%q<bundler>, [">= 1.7"])
81
85
  s.add_development_dependency(%q<jeweler>, ["~> 2.0"])
82
86
  s.add_development_dependency(%q<rspec>, ["~> 3.4"])
83
87
  s.add_development_dependency(%q<rdoc>, ["~> 4.2"])
84
88
  else
85
89
  s.add_dependency(%q<nucleon>, ["~> 0.2"])
86
90
  s.add_dependency(%q<docker-api>, ["~> 1.24"])
87
- s.add_dependency(%q<bundler>, ["~> 1.10"])
91
+ s.add_dependency(%q<nokogiri>, ["= 1.5.11"])
92
+ s.add_dependency(%q<fog-aws>, ["~> 0.8"])
93
+ s.add_dependency(%q<bundler>, [">= 1.7"])
88
94
  s.add_dependency(%q<jeweler>, ["~> 2.0"])
89
95
  s.add_dependency(%q<rspec>, ["~> 3.4"])
90
96
  s.add_dependency(%q<rdoc>, ["~> 4.2"])
@@ -92,7 +98,9 @@ Gem::Specification.new do |s|
92
98
  else
93
99
  s.add_dependency(%q<nucleon>, ["~> 0.2"])
94
100
  s.add_dependency(%q<docker-api>, ["~> 1.24"])
95
- s.add_dependency(%q<bundler>, ["~> 1.10"])
101
+ s.add_dependency(%q<nokogiri>, ["= 1.5.11"])
102
+ s.add_dependency(%q<fog-aws>, ["~> 0.8"])
103
+ s.add_dependency(%q<bundler>, [">= 1.7"])
96
104
  s.add_dependency(%q<jeweler>, ["~> 2.0"])
97
105
  s.add_dependency(%q<rspec>, ["~> 3.4"])
98
106
  s.add_dependency(%q<rdoc>, ["~> 4.2"])
@@ -25,12 +25,32 @@ class Celluloid < Nucleon.plugin_class(:CM, :batch)
25
25
 
26
26
  def execute_parallel(operation)
27
27
  values = []
28
+ timeouts = []
29
+
28
30
  resources.each do |resource|
29
31
  values << ::Celluloid::Future.new(resource) do
30
- resource.execute(operation)
32
+ success = true
33
+ begin
34
+ timeouts << ( resource.respond_to?(:timeout) ? resource.timeout : nil )
35
+
36
+ resource.execute(operation)
37
+ success = resource.status == code.success
38
+
39
+ rescue => error
40
+ logger.error("Resource #{resource.id} #{operation} experienced an error:")
41
+ logger.error(error.inspect)
42
+ logger.error(error.message)
43
+ logger.error(Nucleon::Util::Data.to_yaml(error.backtrace))
44
+
45
+ error('resource_execution', { :id => resource.id, :operation => operation, :message => error.message })
46
+ success = false
47
+ end
48
+ success
31
49
  end
32
50
  end
33
- values = values.map { |future| future.value }
51
+ values = values.each_with_index.map do |future, index|
52
+ future.value(timeouts[index])
53
+ end
34
54
  !values.include?(false)
35
55
  end
36
56
  end
@@ -8,6 +8,9 @@ class AWS < Nucleon.plugin_class(:CM, :docker_resource)
8
8
 
9
9
  def normalize(reload)
10
10
  super
11
+
12
+ codes :aws_request_failed
13
+
11
14
  yield if block_given?
12
15
  end
13
16
 
@@ -21,26 +24,199 @@ class AWS < Nucleon.plugin_class(:CM, :docker_resource)
21
24
  #-----------------------------------------------------------------------------
22
25
  # Property accessors / modifiers
23
26
 
27
+ def template
28
+ settings[:template].to_sym
29
+ end
30
+
31
+ #---
32
+
33
+ def manifest_config
34
+ @manifest_config ||= plan.manifest_config
35
+ end
36
+
37
+ #---
38
+
39
+ def compute
40
+ @compute ||= init_compute
41
+ end
42
+
43
+ #---
44
+
45
+ def key_file(name)
46
+ File.join(plan.key_directory, "#{name}.pem")
47
+ end
48
+
24
49
  #-----------------------------------------------------------------------------
25
50
  # Operations
26
51
 
27
- def operation_deploy
28
- super do
29
- success = true
52
+ def create_resource
53
+ super do |data|
54
+ if template == :keypair
55
+ create_keypair(parameters[:Name], data)
56
+ else
57
+ #info('create_stack', { :id => id, :name => template, :prefix => false })
58
+ #create_stack(template, parameters, data)
59
+ end
30
60
  end
31
61
  end
32
62
 
33
- #---
63
+ def retrieve_resource
64
+ resource = nil
65
+ if template == :keypair
66
+ resource = fetch_keypair(parameters[:Name])
67
+ else
68
+ #resource = fetch_stack(template)
69
+ #dbg(resource, 'retrieval results')
70
+ end
71
+ resource
72
+ end
73
+
74
+ def update_resource
75
+ super do |data|
76
+ if template == :keypair
77
+ update_keypair(parameters[:Name], data)
78
+ else
79
+ #info('update_stack', { :id => id, :name => template, :prefix => false })
80
+ #update_stack(template, parameters, data)
81
+ end
82
+ end
83
+ end
84
+
85
+ def delete_resource
86
+ super do |data|
87
+ if template == :keypair
88
+ delete_keypair(parameters[:Name], data)
89
+ else
90
+ #info('delete_stack', { :id => id, :name => template, :prefix => false })
91
+ #delete_stack(template, data)
92
+ end
93
+ end
94
+ end
95
+
96
+ #-----------------------------------------------------------------------------
97
+ # Keypair related functionality
98
+
99
+ def fetch_keypair(name, reset = false)
100
+ if reset || !@keypair
101
+ begin
102
+ aws_keypair = nil
103
+
104
+ result = compute.describe_key_pairs({ 'key-name' => [name] })
105
+ aws_keypair = result.body['keySet'].first['keyFingerprint'] if result.body['keySet'].length == 1
106
+
107
+ if aws_keypair
108
+ @keypair = {
109
+ :name => name.to_sym,
110
+ :fingerprint => aws_keypair,
111
+ :file => key_file(name)
112
+ }
113
+ end
114
+ rescue => error
115
+ # Placeholder for logging in the future
116
+ raise error
117
+ end
118
+ end
119
+ @keypair
120
+ end
34
121
 
35
- def operation_destroy
36
- super do
37
- success = true
122
+ def create_keypair(name, data, suppress_info = false)
123
+ begin
124
+ info('create_keypair', { :id => id, :name => parameters[:Name] }) unless suppress_info
125
+
126
+ private_key_file = key_file(name)
127
+ result = compute.create_key_pair(name)
128
+
129
+ Nucleon::Util::Disk.write(private_key_file, result.body['keyMaterial'])
130
+ FileUtils.chmod(0600, private_key_file)
131
+
132
+ aws_keypair = fetch_keypair(name, true)
133
+ data[:Fingerprint] = aws_keypair[:fingerprint]
134
+ data[:Content] = result.body['keyMaterial']
135
+ data[:File] = aws_keypair[:file]
136
+
137
+ rescue => error
138
+ myself.status = code.aws_request_failed
139
+ raise error
140
+ end
141
+ end
142
+
143
+ def update_keypair(name, data)
144
+ begin
145
+ info('check_keypair', { :id => id, :name => parameters[:Name] })
146
+
147
+ aws_keypair = fetch_keypair(name)
148
+ private_key_file = aws_keypair[:file]
149
+ update = false
150
+
151
+ if File.exist?(private_key_file)
152
+ local_keypair = `openssl pkcs8 -in #{private_key_file} -inform PEM -outform DER -topk8 -nocrypt | openssl sha1 -c`.strip.sub(/^[^\s]+\s+/, '')
153
+
154
+ if aws_keypair[:fingerprint] != local_keypair
155
+ File.delete(private_key_file)
156
+ update = true
157
+ end
158
+ else
159
+ update = true
160
+ end
161
+
162
+ if update
163
+ info('update_keypair', { :id => id, :name => parameters[:Name] })
164
+
165
+ compute.delete_key_pair(name)
166
+ create_keypair(name, data, true)
167
+ end
168
+ rescue => error
169
+ myself.status = code.aws_request_failed
170
+ raise error
171
+ end
172
+ end
173
+
174
+ def delete_keypair(name, data)
175
+ begin
176
+ info('delete_keypair', { :id => id, :name => parameters[:Name] })
177
+
178
+ if aws_keypair = fetch_keypair(name)
179
+ result = compute.delete_key_pair(name)
180
+ File.delete(aws_keypair[:file]) if File.exist?(aws_keypair[:file])
181
+ end
182
+ rescue => error
183
+ myself.status = code.aws_request_failed
184
+ raise error
38
185
  end
39
186
  end
40
187
 
188
+ #-----------------------------------------------------------------------------
189
+ # Stack related functionality
190
+
191
+ def fetch_stack(name, data)
192
+
193
+ end
194
+
195
+ def create_stack(name, parameters = {}, data)
196
+
197
+ end
198
+
199
+ def update_stack(name, parameters = {}, data)
200
+
201
+ end
202
+
203
+ def delete_stack(name, data)
204
+
205
+ end
206
+
41
207
  #-----------------------------------------------------------------------------
42
208
  # Utilities
43
209
 
210
+ def init_compute
211
+ require 'fog/aws'
212
+
213
+ Fog::Compute.new({
214
+ :provider => 'AWS',
215
+ :region => manifest_config[:aws][:Region],
216
+ :aws_access_key_id => manifest_config[:aws][:AccessKey],
217
+ :aws_secret_access_key => manifest_config[:aws][:SecretAccessKey]
218
+ })
219
+ end
44
220
  end
45
221
  end
46
222
  end