ironfan 4.12.3 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -6,6 +6,7 @@ gem 'excon', "~> 0.21.0" # v0.22 breaks EC2 calls
6
6
  gem 'formatador', "~> 0.2"
7
7
  gem 'gorillib', "~> 0.5.0"
8
8
  gem 'rbvmomi'
9
+ gem 'diff-lcs', "~> 1.2.5"
9
10
 
10
11
  # Everything in the world is being a stupid dick about JSON versions. Pin it
11
12
  # to the one that doesn't seem to angrify everyone.
data/Gemfile.lock CHANGED
@@ -33,7 +33,7 @@ GEM
33
33
  configliere (0.4.18)
34
34
  highline (>= 1.5.2)
35
35
  multi_json (>= 1.1)
36
- diff-lcs (1.2.4)
36
+ diff-lcs (1.2.5)
37
37
  erubis (2.7.0)
38
38
  excon (0.21.0)
39
39
  ffi (1.9.0)
@@ -132,14 +132,14 @@ GEM
132
132
  redcarpet (2.3.0)
133
133
  rest-client (1.6.7)
134
134
  mime-types (>= 1.16)
135
- rspec (2.13.0)
136
- rspec-core (~> 2.13.0)
137
- rspec-expectations (~> 2.13.0)
138
- rspec-mocks (~> 2.13.0)
139
- rspec-core (2.13.1)
140
- rspec-expectations (2.13.0)
135
+ rspec (2.14.1)
136
+ rspec-core (~> 2.14.0)
137
+ rspec-expectations (~> 2.14.0)
138
+ rspec-mocks (~> 2.14.0)
139
+ rspec-core (2.14.7)
140
+ rspec-expectations (2.14.4)
141
141
  diff-lcs (>= 1.1.3, < 2.0)
142
- rspec-mocks (2.13.1)
142
+ rspec-mocks (2.14.4)
143
143
  ruby-debug-base19 (0.11.25)
144
144
  columnize (>= 0.3.1)
145
145
  linecache19 (>= 0.5.11)
@@ -174,6 +174,7 @@ DEPENDENCIES
174
174
  bundler (~> 1.0)
175
175
  chef (~> 10.16)
176
176
  chef-zero
177
+ diff-lcs (~> 1.2.5)
177
178
  excon (~> 0.21.0)
178
179
  fog (~> 1.2)
179
180
  formatador (~> 0.2)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 4.12.3
1
+ 5.0.0
data/ironfan.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "ironfan"
8
- s.version = "4.12.3"
8
+ s.version = "5.0.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Infochimps"]
12
- s.date = "2013-10-10"
12
+ s.date = "2013-12-11"
13
13
  s.description = "Ironfan allows you to orchestrate not just systems but clusters of machines. It includes a powerful layer on top of knife and a collection of cloud cookbooks."
14
14
  s.email = "coders@infochimps.com"
15
15
  s.extra_rdoc_files = [
@@ -44,6 +44,7 @@ Gem::Specification.new do |s|
44
44
  "lib/chef/knife/bootstrap/ubuntu10.04-ironfan.erb",
45
45
  "lib/chef/knife/bootstrap/ubuntu12.04-ironfan.erb",
46
46
  "lib/chef/knife/cluster_bootstrap.rb",
47
+ "lib/chef/knife/cluster_diff.rb",
47
48
  "lib/chef/knife/cluster_kick.rb",
48
49
  "lib/chef/knife/cluster_kill.rb",
49
50
  "lib/chef/knife/cluster_launch.rb",
@@ -55,8 +56,11 @@ Gem::Specification.new do |s|
55
56
  "lib/chef/knife/cluster_start.rb",
56
57
  "lib/chef/knife/cluster_stop.rb",
57
58
  "lib/chef/knife/cluster_sync.rb",
59
+ "lib/chef/knife/environment_from_realm.rb",
58
60
  "lib/chef/knife/ironfan_knife_common.rb",
59
61
  "lib/chef/knife/ironfan_script.rb",
62
+ "lib/gorillib/diff.rb",
63
+ "lib/gorillib/nil_check_delegate.rb",
60
64
  "lib/gorillib/resolution.rb",
61
65
  "lib/ironfan.rb",
62
66
  "lib/ironfan/broker.rb",
@@ -67,6 +71,7 @@ Gem::Specification.new do |s|
67
71
  "lib/ironfan/dsl.rb",
68
72
  "lib/ironfan/dsl/cloud.rb",
69
73
  "lib/ironfan/dsl/cluster.rb",
74
+ "lib/ironfan/dsl/component.rb",
70
75
  "lib/ironfan/dsl/compute.rb",
71
76
  "lib/ironfan/dsl/ec2.rb",
72
77
  "lib/ironfan/dsl/facet.rb",
@@ -78,6 +83,7 @@ Gem::Specification.new do |s|
78
83
  "lib/ironfan/dsl/volume.rb",
79
84
  "lib/ironfan/dsl/vsphere.rb",
80
85
  "lib/ironfan/headers.rb",
86
+ "lib/ironfan/plugin/base.rb",
81
87
  "lib/ironfan/provider.rb",
82
88
  "lib/ironfan/provider/chef.rb",
83
89
  "lib/ironfan/provider/chef/client.rb",
@@ -149,20 +155,26 @@ Gem::Specification.new do |s|
149
155
  "spec/integration/spec_helper.rb",
150
156
  "spec/integration/spec_helper/launch_cluster.rb",
151
157
  "spec/ironfan/cluster_spec.rb",
158
+ "spec/ironfan/diff_spec.rb",
159
+ "spec/ironfan/dsl_spec.rb",
152
160
  "spec/ironfan/ec2/cloud_provider_spec.rb",
153
161
  "spec/ironfan/ec2/elb_spec.rb",
154
162
  "spec/ironfan/ec2/security_group_spec.rb",
163
+ "spec/ironfan/manifest_spec.rb",
164
+ "spec/ironfan/plugin_spec.rb",
165
+ "spec/ironfan/realm_spec.rb",
155
166
  "spec/spec_helper.rb",
156
167
  "spec/spec_helper/dummy_chef.rb",
168
+ "spec/spec_helper/dummy_diff_drawer.rb",
157
169
  "spec/test_config.rb",
158
170
  "tasks/chef_config.rake"
159
171
  ]
160
172
  s.homepage = "http://infochimps.com/labs"
161
173
  s.licenses = ["apachev2"]
162
174
  s.require_paths = ["lib"]
163
- s.rubygems_version = "1.8.23"
175
+ s.rubygems_version = "1.8.25"
164
176
  s.summary = "Infochimps' lightweight cloud orchestration toolkit, built on top of Chef."
165
- s.test_files = ["spec/fixtures/gunbai.rb", "spec/fixtures/ec2/elb/snakeoil.key", "spec/fixtures/ec2/elb/snakeoil.crt", "spec/fixtures/gunbai_slice.json", "spec/fixtures/knife/knife.rb", "spec/test_config.rb", "spec/ironfan/ec2/cloud_provider_spec.rb", "spec/ironfan/ec2/elb_spec.rb", "spec/ironfan/ec2/security_group_spec.rb", "spec/ironfan/cluster_spec.rb", "spec/spec_helper.rb", "spec/spec_helper/dummy_chef.rb", "spec/chef/cluster_bootstrap_spec.rb", "spec/chef/cluster_launch_spec.rb", "spec/integration/spec/elb_build_spec.rb", "spec/integration/spec/simple_cluster_spec.rb", "spec/integration/spec_helper.rb", "spec/integration/minimal-chef-repo/chefignore", "spec/integration/minimal-chef-repo/roles/systemwide.rb", "spec/integration/minimal-chef-repo/environments/_default.json", "spec/integration/minimal-chef-repo/knife/credentials/knife-org.rb", "spec/integration/minimal-chef-repo/knife/knife.rb", "spec/integration/spec_helper/launch_cluster.rb"]
177
+ s.test_files = ["spec/chef/cluster_bootstrap_spec.rb", "spec/chef/cluster_launch_spec.rb", "spec/fixtures/ec2/elb/snakeoil.crt", "spec/fixtures/ec2/elb/snakeoil.key", "spec/fixtures/gunbai.rb", "spec/fixtures/gunbai_slice.json", "spec/fixtures/knife/knife.rb", "spec/integration/minimal-chef-repo/chefignore", "spec/integration/minimal-chef-repo/environments/_default.json", "spec/integration/minimal-chef-repo/knife/credentials/knife-org.rb", "spec/integration/minimal-chef-repo/knife/knife.rb", "spec/integration/minimal-chef-repo/roles/systemwide.rb", "spec/integration/spec/elb_build_spec.rb", "spec/integration/spec/simple_cluster_spec.rb", "spec/integration/spec_helper/launch_cluster.rb", "spec/integration/spec_helper.rb", "spec/ironfan/cluster_spec.rb", "spec/ironfan/diff_spec.rb", "spec/ironfan/dsl_spec.rb", "spec/ironfan/ec2/cloud_provider_spec.rb", "spec/ironfan/ec2/elb_spec.rb", "spec/ironfan/ec2/security_group_spec.rb", "spec/ironfan/manifest_spec.rb", "spec/ironfan/plugin_spec.rb", "spec/ironfan/realm_spec.rb", "spec/spec_helper/dummy_chef.rb", "spec/spec_helper/dummy_diff_drawer.rb", "spec/spec_helper.rb", "spec/test_config.rb"]
166
178
 
167
179
  if s.respond_to? :specification_version then
168
180
  s.specification_version = 3
@@ -174,6 +186,7 @@ Gem::Specification.new do |s|
174
186
  s.add_runtime_dependency(%q<formatador>, ["~> 0.2"])
175
187
  s.add_runtime_dependency(%q<gorillib>, ["~> 0.5.0"])
176
188
  s.add_runtime_dependency(%q<rbvmomi>, [">= 0"])
189
+ s.add_runtime_dependency(%q<diff-lcs>, ["~> 1.2.5"])
177
190
  s.add_runtime_dependency(%q<json>, ["= 1.5.4"])
178
191
  s.add_development_dependency(%q<bundler>, ["~> 1.0"])
179
192
  s.add_development_dependency(%q<rake>, [">= 0"])
@@ -188,6 +201,7 @@ Gem::Specification.new do |s|
188
201
  s.add_dependency(%q<formatador>, ["~> 0.2"])
189
202
  s.add_dependency(%q<gorillib>, ["~> 0.5.0"])
190
203
  s.add_dependency(%q<rbvmomi>, [">= 0"])
204
+ s.add_dependency(%q<diff-lcs>, ["~> 1.2.5"])
191
205
  s.add_dependency(%q<json>, ["= 1.5.4"])
192
206
  s.add_dependency(%q<bundler>, ["~> 1.0"])
193
207
  s.add_dependency(%q<rake>, [">= 0"])
@@ -203,6 +217,7 @@ Gem::Specification.new do |s|
203
217
  s.add_dependency(%q<formatador>, ["~> 0.2"])
204
218
  s.add_dependency(%q<gorillib>, ["~> 0.5.0"])
205
219
  s.add_dependency(%q<rbvmomi>, [">= 0"])
220
+ s.add_dependency(%q<diff-lcs>, ["~> 1.2.5"])
206
221
  s.add_dependency(%q<json>, ["= 1.5.4"])
207
222
  s.add_dependency(%q<bundler>, ["~> 1.0"])
208
223
  s.add_dependency(%q<rake>, [">= 0"])
@@ -0,0 +1,95 @@
1
+ require 'gorillib/model/serialization'
2
+ require 'gorillib/nil_check_delegate'
3
+ require 'yaml'
4
+ require_relative '../../gorillib/diff'
5
+
6
+ #
7
+ # Author:: Philip (flip) Kromer (<flip@infochimps.com>)
8
+ # Copyright:: Copyright (c) 2011 Infochimps, Inc
9
+ # License:: Apache License, Version 2.0
10
+ #
11
+ # Licensed under the Apache License, Version 2.0 (the "License");
12
+ # you may not use this file except in compliance with the License.
13
+ # You may obtain a copy of the License at
14
+ #
15
+ # http://www.apache.org/licenses/LICENSE-2.0
16
+ #
17
+ # Unless required by applicable law or agreed to in writing, software
18
+ # distributed under the License is distributed on an "AS IS" BASIS,
19
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
+ # See the License for the specific language governing permissions and
21
+ # limitations under the License.
22
+ #
23
+
24
+ require File.expand_path('ironfan_knife_common', File.dirname(File.realdirpath(__FILE__)))
25
+ require 'yaml'
26
+
27
+ class Chef
28
+ class Knife
29
+ class ClusterDiff < Knife
30
+ include Ironfan::KnifeCommon
31
+ deps do
32
+ Ironfan::KnifeCommon.load_deps
33
+ end
34
+
35
+ banner "knife cluster diff CLUSTER[-FACET[-INDEXES]] (options) - differences between a cluster and its realization"
36
+
37
+ option :cache_file,
38
+ :long => "--cache_file FILE",
39
+ :description => "file to load chef information from, for testing purposes"
40
+
41
+ def _run
42
+ load_ironfan
43
+ die(banner) if @name_args.empty?
44
+ configure_dry_run
45
+
46
+ @test_chef_data =
47
+ if config.has_key? :cache_file
48
+ Hash[open(config.fetch(:cache_file)).readlines.map{|line| datum = MultiJson.load(line); [datum['name'], datum]}]
49
+ else
50
+ {}
51
+ end
52
+
53
+ # Load the cluster/facet/slice/whatever
54
+ target = get_slice(* @name_args)
55
+
56
+ exit(1) if self.class.mismatches?(target)
57
+ end
58
+
59
+ def self.mismatches?(target)
60
+ target.map do |computer|
61
+ local_manifest = computer.server.to_machine_manifest
62
+ remote_manifest = Ironfan::Dsl::MachineManifest.from_computer(computer)
63
+ display_diff(local_manifest, remote_manifest)
64
+ local_manifest != remote_manifest
65
+ end.to_a.any?
66
+ end
67
+
68
+ private
69
+
70
+ def self.node_name(manifest)
71
+ "#{manifest.cluster_name}-#{manifest.facet_name}-#{manifest.name}"
72
+ end
73
+
74
+ def self.display_diff(local_manifest, remote_manifest)
75
+ header("diffing manifests: local #{node_name(local_manifest)} <-> remote #{node_name(remote_manifest)}")
76
+ differ.display_diff(local_manifest.to_comparable, remote_manifest.to_comparable)
77
+ end
78
+
79
+ #---------------------------------------------------------------------------------------------
80
+
81
+ def self.differ
82
+ Gorillib::DiffFormatter.new(left: :local,
83
+ right: :remote,
84
+ stream: $stdout,
85
+ indentation: 4)
86
+ end
87
+
88
+ def self.header str
89
+ $stdout.puts(" #{'-' * 80}")
90
+ $stdout.puts(" #{str}")
91
+ $stdout.puts(" #{'-' * 80}")
92
+ end
93
+ end
94
+ end
95
+ end
@@ -55,7 +55,7 @@ class Chef
55
55
  :boolean => true,
56
56
  :default => false
57
57
 
58
- def run
58
+ def _run
59
59
  load_ironfan
60
60
  die(banner) if @name_args.empty?
61
61
  configure_dry_run
@@ -36,11 +36,13 @@ class Chef
36
36
  :default => false,
37
37
  :boolean => true
38
38
 
39
- def run
39
+ def _run
40
40
  load_ironfan
41
41
  configure_dry_run
42
+ Ironfan.load_cluster_files
42
43
 
43
- data = Ironfan.cluster_filenames.map do |name, path|
44
+ data = Ironfan.clusters.values.map do |cluster|
45
+ name, path = [cluster.name, cluster.source_file]
44
46
  as_table = { :cluster => name, :path => path }
45
47
  if config[:facets]
46
48
  facets = Ironfan.load_cluster(name).facets.to_a.map(&:name).join(', ')
@@ -35,7 +35,7 @@ class Chef
35
35
  :default => true,
36
36
  :boolean => true
37
37
 
38
- def run
38
+ def _run
39
39
  load_ironfan
40
40
  die(banner) if @name_args.empty?
41
41
  configure_dry_run
@@ -17,6 +17,7 @@
17
17
  #
18
18
 
19
19
  require File.expand_path('ironfan_knife_common', File.dirname(File.realdirpath(__FILE__)))
20
+ require 'yaml'
20
21
 
21
22
  class Chef
22
23
  class Knife
@@ -34,7 +35,7 @@ class Chef
34
35
  :default => true,
35
36
  :boolean => true
36
37
 
37
- def run
38
+ def _run
38
39
  with_verbosity(1){ config[:include_terminated] = true }
39
40
  load_ironfan
40
41
  die(banner) if @name_args.empty?
@@ -46,6 +47,7 @@ class Chef
46
47
  dump_command_config
47
48
  dump_chef_config
48
49
  #
50
+
49
51
  target.each do |computer|
50
52
  dump_computer(computer)
51
53
  end
@@ -60,6 +62,11 @@ class Chef
60
62
  header = "Computer #{computer.name} (#{computer.class})"
61
63
  with_verbosity 1 do
62
64
  Chef::Log.info(header)
65
+
66
+ # Terminated instances don't have servers.
67
+ unless computer.server.nil?
68
+ Chef::Log.info(computer.server.canonical_machine_manifest_hash.to_yaml)
69
+ end
63
70
  end
64
71
  with_verbosity 2 do
65
72
  dump(header, computer.to_wire)
@@ -85,10 +92,6 @@ class Chef
85
92
  Chef::Log.info( MultiJson.dump(hsh, pretty: true ) )
86
93
  end
87
94
 
88
- def with_verbosity(num)
89
- yield if config[:verbosity] >= num
90
- end
91
-
92
95
  end
93
96
  end
94
97
  end
@@ -114,7 +114,7 @@ class Chef
114
114
  exec "cssh "+session.servers_for.map{|server| server.user ? "#{server.user}@#{server.host}" : server.host}.join(" ")
115
115
  end
116
116
 
117
- def run
117
+ def _run
118
118
  load_ironfan
119
119
  die(banner) if @name_args.empty?
120
120
  extend Chef::Mixin::Command
@@ -0,0 +1,60 @@
1
+ #
2
+ # Author:: Philip (flip) Kromer (<flip@infochimps.com>)
3
+ # Copyright:: Copyright (c) 2011 Infochimps, Inc
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ require File.expand_path('ironfan_knife_common', File.dirname(File.realdirpath(__FILE__)))
20
+ require 'yaml'
21
+
22
+ class Chef
23
+ class Knife
24
+ class EnvironmentFromRealm < Knife
25
+ include Ironfan::KnifeCommon
26
+ deps do
27
+ Ironfan::KnifeCommon.load_deps
28
+ end
29
+
30
+ banner "knife environment from realm realm (options) - syncs a realm's environment"
31
+
32
+ option :dry_run,
33
+ :long => "--dry-run",
34
+ :description => "Don't really run, just use mock calls",
35
+ :boolean => true,
36
+ :default => false
37
+
38
+ def _run
39
+ load_ironfan
40
+ die(banner) unless @name_args.size == 1
41
+ configure_dry_run
42
+
43
+ # Load the cluster/facet/slice/whatever
44
+ target = Ironfan.load_realm(* @name_args)
45
+
46
+ env = Chef::Environment.new.tap do |env|
47
+ env.name target.environment
48
+ env.description "Ironfan-created environment for #{target.name} realm"
49
+ Chef::Log.info "pinning cookbooks in #{target.name} realm"
50
+ target.cookbook_reqs.each do |cookbook, version|
51
+ Chef::Log.info " pinning cookbook #{cookbook} #{version}"
52
+ env.cookbook cookbook, version
53
+ end
54
+ end
55
+
56
+ env.save unless config[:dry_run]
57
+ end
58
+ end
59
+ end
60
+ end
@@ -22,6 +22,25 @@ module Ironfan
22
22
  self.broker = Ironfan.broker
23
23
  end
24
24
 
25
+ def run()
26
+ gemfile_v = gemfile(@name_args.first.to_s.split(/[_-]/).first)
27
+
28
+ if ENV['BUNDLE_GEMFILE'] == gemfile_v
29
+ _run
30
+ elsif not File.exist?(gemfile_v)
31
+ ui.info("no realm-specific Gemfile found. using default Gemfile.")
32
+ _run
33
+ else
34
+ cmd = "bundle exec knife #{ARGV.join(' ')}"
35
+ ui.info("re-running `#{cmd}` with BUNDLE_GEMFILE=#{gemfile_v}")
36
+ return Bundler.clean_exec({'BUNDLE_GEMFILE' => gemfile_v}, cmd)
37
+ end
38
+ end
39
+
40
+ def gemfile(realm_or_cluster_name)
41
+ "Gemfile.#{realm_or_cluster_name}"
42
+ end
43
+
25
44
  #
26
45
  # A slice of a cluster:
27
46
  #
@@ -249,5 +268,8 @@ module Ironfan
249
268
  Chef::Config[:environment] = environments.first
250
269
  end
251
270
 
271
+ def with_verbosity(num)
272
+ yield if config[:verbosity] >= num
273
+ end
252
274
  end
253
275
  end
@@ -36,7 +36,7 @@ module Ironfan
36
36
  :description => "Skip confirmation prompts on risky actions.",
37
37
  :boolean => true
38
38
 
39
- def run
39
+ def _run
40
40
  load_ironfan
41
41
 
42
42
  die(banner) if @name_args.empty?