ironfan 4.12.3 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,78 @@
1
+ require 'spec_helper'
2
+ require 'gorillib/diff'
3
+ require_relative '../spec_helper/dummy_diff_drawer.rb'
4
+
5
+ describe Gorillib::DiffFormatter do
6
+ it 'writes the indices of displayed elements for both sides' do
7
+ TestDrawer.diffing_objs([1], [1,2]) do |drawer|
8
+ drawer.should_receive(:display_indices).with(1,1)
9
+ end
10
+ end
11
+ it 'adds objects correctly on the right' do
12
+ TestDrawer.diffing_objs([1], [1,2]) do |drawer|
13
+ drawer.should_receive(:display_add).with(nil, 2)
14
+ end
15
+ end
16
+ it 'labels objects correctly on the right' do
17
+ TestDrawer.diffing_objs([1], [1,2]) do |drawer|
18
+ # meaning it displayed the name of the right object
19
+ drawer.should_receive(:b_right)
20
+ end
21
+ end
22
+ it 'adds objects correctly on the left' do
23
+ TestDrawer.diffing_objs([1,2], [1]) do |drawer|
24
+ drawer.should_receive(:display_add).with(2, nil)
25
+ end
26
+ TestDrawer.diffing_objs([1,2], [1]) do |drawer|
27
+ # meaning it displayed the name of the left object
28
+ drawer.should_receive(:b_left)
29
+ end
30
+ end
31
+ it 'lists keys only on the left correctly' do
32
+ TestDrawer.diffing_objs({a: 1, b: 2}, {a: 1}) do |drawer|
33
+ drawer.should_receive(:only_left_key).with(:b)
34
+ end
35
+ end
36
+ it 'lists keys only on the right correctly' do
37
+ TestDrawer.diffing_objs({a: 1}, {a: 1, b: 2}) do |drawer|
38
+ drawer.should_receive(:only_right_key).with(:b)
39
+ end
40
+ end
41
+ it 'explains when elements differ' do
42
+ TestDrawer.diffing_objs(1, 2) do |drawer|
43
+ drawer.should_receive(:display_noteql_atoms).with(1,2)
44
+ end
45
+ end
46
+ it 'explains when elements are of different classes' do
47
+ TestDrawer.diffing_objs([], {}) do |drawer|
48
+ drawer.should_receive(:display_hetero).with([],{})
49
+ end
50
+ end
51
+ it 'initializes itself every time it diffs a new pair of objects object' do
52
+ diff_formatter = TestDrawer.diff_formatter
53
+
54
+ diff_formatter.should_receive :setup
55
+ diff_formatter.display_diff(nil, nil)
56
+ diff_formatter.should_receive :setup
57
+ diff_formatter.display_diff(nil, nil)
58
+ end
59
+
60
+ it 'correctly diffs complex objects' do
61
+
62
+ # These aren't incredibly descriptive, but they are nice for
63
+ # bug-hunting.
64
+
65
+ TestDrawer.transform_ltor(1,2)
66
+ TestDrawer.transform_ltor([1], [1,2])
67
+ TestDrawer.transform_ltor({a: 1}, {a: 1, b: 2})
68
+ TestDrawer.transform_ltor([1,2], [1])
69
+ TestDrawer.transform_ltor({a: 1, b: 2}, {a: 1})
70
+ TestDrawer.transform_ltor({a: 1, b: 2}, {a: 1, c: 3})
71
+ TestDrawer.transform_ltor({a: [1]}, {a: [1,2]})
72
+ TestDrawer.transform_ltor({a: [1,2]}, {a: [1]})
73
+ TestDrawer.transform_ltor({a: [1]}, {a: [1,2]})
74
+ TestDrawer.transform_ltor({a: [1]}, {a: [1,2]})
75
+ TestDrawer.transform_ltor({a: [1], b: 3, c: {a: 1}, d: []}, {a: [1,2], c: [7,8], d: {a: 2}})
76
+ TestDrawer.transform_ltor([], [[1,2]])
77
+ end
78
+ end
@@ -0,0 +1,115 @@
1
+ require 'spec_helper'
2
+ require 'ironfan'
3
+
4
+ describe Ironfan::Dsl do
5
+ context 'when joining requirement pairs' do
6
+ subject{ Ironfan::Dsl.new }
7
+
8
+ def test_join(cn1, cn2)
9
+ name = 'foo'
10
+ subject.join_req(Ironfan::Plugin::CookbookRequirement.new(name: name, constraint: cn1),
11
+ Ironfan::Plugin::CookbookRequirement.new(name: name, constraint: cn2)).constraint
12
+ end
13
+
14
+ it 'joins =,= requirements when valid' do
15
+ test_join('= 1.0.0', '= 1.0.0').should == '= 1.0.0'
16
+ end
17
+ it 'raises when =,= requirements not valid' do
18
+ expect{ test_join('= 1.0.0', '= 2.0.0') }.to raise_error
19
+ end
20
+ it 'chooses the more restrictive constraint for >= , >= requirements' do
21
+ test_join('>= 1.0.0', '>= 2.0.0').should == '>= 2.0.0'
22
+ test_join('>= 2.0.0', '>= 1.0.0').should == '>= 2.0.0'
23
+ end
24
+ it 'chooses the more restrictive constraint for ~> , ~> requirements' do
25
+ test_join('~> 1.0', '~> 1.2').should == '~> 1.2'
26
+ test_join('~> 1.2', '~> 1.0').should == '~> 1.2'
27
+ end
28
+ it 'raises when ~> , ~> requirements not valid' do
29
+ expect{ test_join('~> 1.0', '~> 1.0.0') }.to raise_error
30
+ expect{ test_join('~> 1.0', '~> 2.0') }.to raise_error
31
+ expect{ test_join('~> 2.0', '~> 1.0') }.to raise_error
32
+ end
33
+ it 'joins =, >= requirements when valid' do
34
+ test_join('= 1.1.0', '>= 1.1.0').should == '= 1.1.0'
35
+ test_join('>= 1.1.0', '= 1.1.0').should == '= 1.1.0'
36
+ end
37
+ it 'raises when =, >= requirements not valid' do
38
+ expect{ test_join('= 1.0.0', '>= 1.1.0') }.to raise_error
39
+ expect{ test_join('>= 1.1.0', '= 1.0.0') }.to raise_error
40
+ end
41
+ it 'joins =, ~> requirements when valid' do
42
+ test_join('= 1.1.0', '~> 1.0').should == '= 1.1.0'
43
+ test_join('~> 1.0', '= 1.1.0').should == '= 1.1.0'
44
+ end
45
+ it 'raises when =, ~> requirements not valid' do
46
+ expect{ test_join('= 2.0.0', '~> 1.0') }.to raise_error
47
+ expect{ test_join('~> 1.0', '= 2.0.0') }.to raise_error
48
+ end
49
+ it 'joins >=, ~> requirements when valid' do
50
+ test_join('>= 1.1.0', '~> 1.1.2').should == '~> 1.1.2'
51
+ test_join('~> 1.1.2', '>= 1.1.0').should == '~> 1.1.2'
52
+ end
53
+ it 'raises when >=, ~> requirements not valid' do
54
+ expect{ test_join('>= 1.1.3', '~> 1.1.2') }.to raise_error
55
+ expect{ test_join('~> 1.1.2', '>= 1.1.3') }.to raise_error
56
+ end
57
+ end
58
+
59
+ context 'when aggregating requirements' do
60
+ before(:each) do
61
+ Ironfan::Dsl.class_eval{ @@testing = true }
62
+
63
+ Ironfan::Dsl::Component.template(%w[foo]) do
64
+ cookbook_req 'a', '>= 1.2.3'
65
+ def project(*_) end
66
+ end
67
+ Ironfan::Dsl::Component.template(%w[bar]) do
68
+ cookbook_req 'a', '>= 1.2.5'
69
+ def project(*_) end
70
+ end
71
+ Ironfan::Dsl::Component.template(%w[baz]) do
72
+ cookbook_req 'a', '>= 1.2.7'
73
+ def project(*_) end
74
+ end
75
+ Ironfan.realm(:test) do
76
+ cluster(:just_foo) do
77
+ foo
78
+ end
79
+ cluster(:foo_bar) do
80
+ foo; bar
81
+ end
82
+ cluster(:nest_foo_bar) do
83
+ foo
84
+ facet(:bar) do
85
+ bar
86
+ end
87
+ end
88
+ cluster(:baz) do
89
+ baz
90
+ end
91
+ end
92
+ end
93
+
94
+ after(:each) do
95
+ [:Foo, :Bar, :Baz].each{|x| Ironfan::Dsl::Component.send(:remove_const, x)}
96
+ end
97
+
98
+ it 'correctly merges version requirements in simple cases' do
99
+ Ironfan.realm(:test).tap do |realm|
100
+ realm.cluster(:just_foo).cookbook_reqs['a'].should == '>= 1.2.3'
101
+ realm.cluster( :foo_bar).cookbook_reqs['a'].should == '>= 1.2.5'
102
+ end
103
+ end
104
+
105
+ it 'correctly handles nested versions requirements' do
106
+ Ironfan.realm(:test).tap do |realm|
107
+ realm.cluster(:nest_foo_bar).tap do |cluster|
108
+ cluster .cookbook_reqs['a'].should == '>= 1.2.5'
109
+ cluster.facet(:bar).cookbook_reqs['a'].should == '>= 1.2.5'
110
+ end
111
+ realm.cookbook_reqs['a'].should == '>= 1.2.7'
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+ require 'ironfan'
3
+
4
+ describe Ironfan::Dsl::MachineManifest do
5
+ context 'it disregards whether values are strings or symbols' do
6
+ before(:each) do
7
+ Ironfan::Dsl::Component.template(%w[baz bif]) do
8
+ collection :bams, Symbol
9
+ magic :pow, Whatever
10
+ end
11
+ end
12
+
13
+ def comparable_manifest(hsh)
14
+ Ironfan::Dsl::MachineManifest.receive(components: [Ironfan::Dsl::Component::BazBif.new(hsh)]).to_comparable
15
+ end
16
+
17
+ it 'when those values are contained in an array of within its serialization' do
18
+ comparable_manifest(bam: [:a, :b, :c]).should == comparable_manifest(bam: %w[a b c])
19
+ comparable_manifest(pow: [:a, :b, :c]).should == comparable_manifest(pow: %w[a b c])
20
+ end
21
+ it 'when those values are contained in hash within its serialization' do
22
+ comparable_manifest(pow: {a: 'a'}).should == comparable_manifest(pow: {'a' => :a})
23
+ end
24
+ it 'correctly stores the chef environment' do
25
+ node = Chef::Node.json_create('chef_environment' => 'buzi', 'recipes' => [])
26
+ Ironfan::Dsl::MachineManifest.from_remote(nil, nil, nil, node, nil, nil, nil, nil, nil).environment.to_s.should == 'buzi'
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,138 @@
1
+ require_relative '../spec_helper.rb'
2
+
3
+ describe MyPlugin do
4
+ subject { MyPlugin }
5
+
6
+ it 'should respond to template' do
7
+ subject.should(respond_to(:template))
8
+ end
9
+
10
+ context 'when templatizing plugins' do
11
+ after(:each) do
12
+ uncreate_plugin(subject, Foo)
13
+ end
14
+ before(:each) do
15
+ subject.template(%w[baz bif])
16
+ end
17
+
18
+ it 'should create them as classes within itself' do
19
+ subject.constants.should(include(:BazBif))
20
+ end
21
+ it 'should create them as subclasses of itself' do
22
+ subject.const_get(:BazBif).should(be < subject)
23
+ end
24
+ it 'should allow customizing the classes' do
25
+ uncreate_plugin(subject, Foo)
26
+ subject.template(%w[baz bif]){ def bam() end }
27
+ subject.const_get(:BazBif).new.should(respond_to(:bam))
28
+ end
29
+ it 'should register methods on the specified class' do
30
+ Foo.new.should(respond_to(:baz_bif))
31
+ end
32
+ it 'should wire those methods to the plugin_hook method of itself' do
33
+ foo = Foo.new
34
+ subject.should_receive(:plugin_hook).with(foo, {}, :baz, :baz_bif)
35
+ foo.baz_bif
36
+ end
37
+ it 'should allow the user to create a custom class that will also be registered' do
38
+ Foo.registry[:baz_bif].should(be(subject.const_get(:BazBif)))
39
+ end
40
+ end
41
+ end
42
+
43
+ describe Ironfan::Dsl::Component do
44
+ before(:each) do
45
+ Ironfan::Dsl::Component.template(%w[baz bif]) do
46
+ include Ironfan::Dsl::Component::Announcement
47
+
48
+ magic :bam, Symbol, node_attr: 'a.b.c', default: nil
49
+
50
+ def project(compute)
51
+ compute.role(:called_from_project, compute) unless bam
52
+ end
53
+ end
54
+ end
55
+
56
+ after(:each) do
57
+ uncreate_plugin(Ironfan::Dsl::Component, Ironfan::Dsl::Compute)
58
+ end
59
+
60
+ it 'should have its project method called by the plugin_hook' do
61
+ Ironfan.cluster(:foo) do
62
+ should_receive(:role).with(:called_from_project, self)
63
+ baz_bif
64
+ end
65
+ end
66
+
67
+ it 'should merge its node attribute to create a node' do
68
+ node = Chef::Node.new
69
+ node.set['a'] = {'b' => {'c' => :baz}}
70
+ Ironfan.cluster(:foo) do
71
+ baz_bif{ bam(:baz) }.to_node.to_hash.should == node.to_hash
72
+ end
73
+ end
74
+ it 'should be instantiable from a node object' do
75
+ node = Chef::Node.new
76
+ node.set['a'] = {'b' => {'c' => :baz}}
77
+ Ironfan::Dsl::Compute.registry[:baz_bif].from_node(node).bam.should == :baz
78
+ end
79
+
80
+ it 'should remember all of its node attributes' do
81
+ Ironfan.cluster(:foo) do
82
+ component = baz_bif{ bam(:baz) }
83
+ component.to_node.to_hash.should ==
84
+ Ironfan::Dsl::Compute.registry[:baz_bif].from_node(component.to_node).to_node.to_hash
85
+ end
86
+ end
87
+
88
+ context 'when announcing' do
89
+ before (:each) do
90
+ def make_plugin(name, server_b)
91
+ Ironfan::Dsl::Component.template([name, server_b ? 'server' : 'client']) do
92
+ include Ironfan::Dsl::Component::Announcement if server_b
93
+ include Ironfan::Dsl::Component::Discovery if not server_b
94
+
95
+ if server_b
96
+ def project(compute)
97
+ end
98
+ else
99
+ def project(compute)
100
+ set_discovery compute, [announce_name]
101
+ end
102
+ end
103
+ end
104
+ end
105
+
106
+ def make_plugin_pair(name) make_plugin(name, true); make_plugin(name, false); end
107
+
108
+ make_plugin_pair(:bam); make_plugin_pair(:pow)
109
+ end
110
+
111
+ it 'automatically discovers announcements within realms' do
112
+ Ironfan.realm(:wap) do
113
+ cluster(:foo){ bam_client; pow_server }
114
+ cluster(:bar){ bam_server; pow_client }
115
+
116
+ cluster(:foo).cluster_role.override_attributes[:discovers].should == {bam: :wap_bar}
117
+ cluster(:bar).cluster_role.override_attributes[:discovers].should == {pow: :wap_foo}
118
+ end
119
+ end
120
+
121
+ it 'automatically configures security groups during discovery' do
122
+ Ironfan.realm(:wap) do
123
+ cloud(:ec2)
124
+
125
+ cluster(:foo){ bam_client; pow_server }
126
+ cluster(:bar){ bam_server; pow_client }
127
+ end.resolve!
128
+
129
+ rspec = self
130
+
131
+ foo_group = Ironfan.realm(:wap).cluster(:foo).cloud(:ec2).security_group('wap_foo')
132
+ bar_group = Ironfan.realm(:wap).cluster(:bar).cloud(:ec2).security_group('wap_bar')
133
+
134
+ foo_group.group_authorized.should include('wap_bar')
135
+ bar_group.group_authorized.should include('wap_foo')
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,137 @@
1
+ require 'spec_helper'
2
+
3
+ require 'ironfan'
4
+
5
+ describe Ironfan::Dsl::Realm do
6
+ before(:each) do
7
+ (Chef::Config[:ec2_image_info] ||= {}).merge!({
8
+ %w[us-east-1 64-bit ebs ironfan-precise ] =>
9
+ { :image_id => 'ami-29fe7640', :ssh_user => 'bam', :bootstrap_distro => "ubuntu12.04-ironfan", },
10
+ })
11
+
12
+ Ironfan.realm(:foo) do
13
+ environment :bif
14
+
15
+ cloud(:ec2) do
16
+ flavor 'm1.xlarge'
17
+ image_name 'ironfan-precise'
18
+ end
19
+
20
+ cluster(:bar) do
21
+ cluster_role.override_attributes(a: 1)
22
+ facet(:baz) do
23
+ instances 1
24
+ role :blah
25
+ facet_role.override_attributes(b: 1)
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ def manifest
32
+ Ironfan.cluster(:foo_bar).facets[:baz].server(0).to_machine_manifest
33
+ end
34
+
35
+ it 'should choose its own name as its default environment' do
36
+ Ironfan.realm(:bar).environment.to_s.should == 'bar'
37
+ end
38
+
39
+ it 'should choose the widest possible cookbook contraints to satisfy all plugins' do
40
+ Ironfan::Dsl::Component.template(%w[bam pow]) do
41
+ cookbook_req 'bif', '>= 1.0.0'
42
+ def project(_) end
43
+ end
44
+
45
+ Ironfan::Dsl::Component.template(%w[jam wam]) do
46
+ cookbook_req 'bif', '>= 2.0.0'
47
+ def project(_) end
48
+ end
49
+
50
+ Ironfan.realm(:qux) do
51
+ cluster(:cuz) do
52
+ facet(:lix) do
53
+ bam_pow
54
+ jam_wam
55
+ end
56
+ end
57
+ end.cookbook_reqs['bif'].should == '>= 2.0.0'
58
+ end
59
+
60
+ it 'should complain when no cookbook constraints can satisfy all plugins' do
61
+ Ironfan::Dsl::Component.template(%w[bam pow]) do
62
+ cookbook_req 'bif', '~> 1.0.0'
63
+ def project(_) end
64
+ end
65
+
66
+ Ironfan::Dsl::Component.template(%w[jam wam]) do
67
+ cookbook_req 'bif', '>= 2.0.0'
68
+ def project(_) end
69
+ end
70
+
71
+ Ironfan.realm(:qux) do
72
+ cluster(:cuz) do
73
+ facet(:lix) do
74
+ bam_pow
75
+ jam_wam
76
+ end
77
+ end
78
+ end
79
+
80
+ expect{ Ironfan.realm(:qux).cookbook_reqs }.to raise_error
81
+ end
82
+
83
+ it 'should create clusters that can be referenced later' do
84
+ x = self
85
+ Ironfan.realm :xx do
86
+ cluster(:bar).should(x.be(cluster(:bar)))
87
+ end
88
+ end
89
+
90
+ it 'should create clusters that can be edited later' do
91
+ Ironfan.realm :xy do
92
+ cluster(:baz)
93
+ cluster(:baz){ facet :bif }
94
+ end
95
+
96
+ Ironfan.cluster(:xy_baz).facets.to_a.should_not(be_empty)
97
+ Ironfan.cluster(:xy_baz).servers.to_a.first.should_not(be_nil)
98
+ end
99
+
100
+ it 'should create clusters with names prefixed by its own' do
101
+ Ironfan.cluster(:foo_bar).should_not(be_nil)
102
+ end
103
+
104
+ it 'should create clusters with machines' do
105
+ Ironfan.cluster(:foo_bar).facets[:baz].server(0).should_not(be_nil)
106
+ end
107
+
108
+ it 'should create clusters with attributes correctly applied' do
109
+ manifest.cluster_override_attributes.should == {a: 1}
110
+ manifest.facet_override_attributes.should == {b: 1}
111
+ manifest.run_list.should == %w[role[blah] role[foo_bar-cluster] role[foo_bar-baz-facet]]
112
+ end
113
+
114
+ it 'should create clusters with the correct ssh user' do
115
+ manifest.flavor.should == 'm1.xlarge'
116
+ manifest.ssh_user.should == 'bam'
117
+ end
118
+
119
+ it 'should save cloud properties to be shared among all clusters within the realm' do
120
+ # We need to resolve before the cloud settings come through
121
+ Ironfan.realm(:foo).clusters[:foo_bar].resolve.facets[:baz].servers.to_a.first.to_machine_manifest.flavor.should == 'm1.xlarge'
122
+
123
+ # Ironfan.cluster will do the resolution for us.
124
+ manifest.flavor.should == 'm1.xlarge'
125
+ end
126
+
127
+ it 'should save an environment to be shared among all clusters within the realm' do
128
+ # We need to resolve before the cloud settings come through
129
+ Ironfan.realm(:foo).clusters[:foo_bar].resolve.facets[:baz].environment.should == :bif
130
+
131
+ # The server manifest should contain the environment.
132
+ manifest.environment.should == :bif
133
+
134
+ # Ironfan.cluster will do the resolution for us.
135
+ Ironfan.cluster(:foo_bar).facets[:baz].environment.should == :bif
136
+ end
137
+ end
@@ -0,0 +1,94 @@
1
+ require 'gorillib/diff'
2
+ require 'stringio'
3
+
4
+ module TransformLeftToRight
5
+ attr_reader :left
6
+
7
+ DELETE_ME = Object.new
8
+
9
+ def display_key_header(key)
10
+ @left_lineage << [@left, key]
11
+ @left = @left[key]
12
+
13
+ @right_lineage << @right
14
+ @right = @right[key]
15
+ end
16
+
17
+ def only_left_key(_)
18
+ @left = DELETE_ME
19
+ end
20
+
21
+ def only_right_key(key)
22
+ @left = @right
23
+ end
24
+
25
+ def display_add(this, other)
26
+ if this.nil?
27
+ @left.insert(@ix, other)
28
+ @ix += 1
29
+ else
30
+ @left.delete_at(@ix)
31
+ end
32
+ end
33
+
34
+ def display_hetero(this, other)
35
+ @ix += 1
36
+ @left = @right
37
+ end
38
+
39
+ def display_noteql_items(*args)
40
+ @in_array = true
41
+ super(*args)
42
+ @in_array = false
43
+ end
44
+
45
+ def display_noteql_atoms(this, other)
46
+ @ix += 1
47
+ @left = @right
48
+ end
49
+
50
+ def decrease_indentation
51
+ tmp = @left
52
+ @left,key = @left_lineage.pop
53
+
54
+ if tmp.equal?(DELETE_ME)
55
+ @left.delete(key)
56
+ else
57
+ @left[key] = tmp
58
+ end
59
+
60
+ @right = @right_lineage.pop
61
+ end
62
+
63
+ def increase_indentation() end
64
+ def indent() end
65
+
66
+ def display_indices(ixl, ixr)
67
+ @ix = ixr
68
+ end
69
+ end
70
+
71
+ class TestDrawer
72
+ include Gorillib::DiffDrawerMethods
73
+ include TransformLeftToRight
74
+
75
+ def initialize this = nil, other = nil
76
+ @left_lineage = [@left = this]
77
+ @right_lineage = [@right = other]
78
+ @ix = 0
79
+ end
80
+
81
+ def self.diffing_objs this, other
82
+ diff_formatter.display_diff(this, other)
83
+ end
84
+
85
+ def self.diff_formatter(drawer = nil)
86
+ Gorillib::DiffFormatter.new(stream: StringIO.new, drawer: drawer)
87
+ end
88
+
89
+ def self.transform_ltor this, other
90
+ drawer = new(this, other)
91
+ Gorillib::DiffFormatter.new(drawer: drawer).display_diff(this, other)
92
+ drawer.left.should == other
93
+ end
94
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  $:.unshift File.expand_path('../../lib', __FILE__)
2
2
  require 'chef'
3
3
  require 'chef/knife'
4
+ require 'ironfan'
4
5
  require 'fog'
5
6
  Fog.mock!
6
7
  Fog::Mock.delay = 0
@@ -36,3 +37,17 @@ end
36
37
  require 'chef_zero/server'
37
38
  server = ChefZero::Server.new(port: 4000)
38
39
  server.start_background
40
+
41
+ def uncreate_plugin(plugin_class, target_class)
42
+ target_class.registry.clear
43
+ plugin_class.instance_eval{ remove_const :BazBif }
44
+ end
45
+
46
+ class Foo
47
+ end
48
+
49
+ class MyPlugin
50
+ include Ironfan::Plugin::Base; register_with Foo
51
+
52
+ def self.plugin_hook(*_) end
53
+ end