ironfan 4.12.3 → 5.0.0

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.
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?