knife-spork-berks 1.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/.gitignore +19 -0
  2. data/.ruby-gemset +1 -0
  3. data/.ruby-version +1 -0
  4. data/CHANGELOG.md +284 -0
  5. data/Gemfile +3 -0
  6. data/LICENSE +35 -0
  7. data/README.md +406 -0
  8. data/Rakefile +2 -0
  9. data/knife-spork-berks.gemspec +22 -0
  10. data/lib/chef/knife/spork-bump.rb +86 -0
  11. data/lib/chef/knife/spork-check.rb +149 -0
  12. data/lib/chef/knife/spork-databag-create.rb +53 -0
  13. data/lib/chef/knife/spork-databag-delete.rb +51 -0
  14. data/lib/chef/knife/spork-databag-edit.rb +54 -0
  15. data/lib/chef/knife/spork-databag-fromfile.rb +82 -0
  16. data/lib/chef/knife/spork-environment-create.rb +43 -0
  17. data/lib/chef/knife/spork-environment-delete.rb +36 -0
  18. data/lib/chef/knife/spork-environment-edit.rb +37 -0
  19. data/lib/chef/knife/spork-environment-fromfile.rb +42 -0
  20. data/lib/chef/knife/spork-info.rb +30 -0
  21. data/lib/chef/knife/spork-node-create.rb +38 -0
  22. data/lib/chef/knife/spork-node-delete.rb +38 -0
  23. data/lib/chef/knife/spork-node-edit.rb +45 -0
  24. data/lib/chef/knife/spork-node-fromfile.rb +43 -0
  25. data/lib/chef/knife/spork-node-runlistadd.rb +48 -0
  26. data/lib/chef/knife/spork-node-runlistremove.rb +42 -0
  27. data/lib/chef/knife/spork-node-runlistset.rb +42 -0
  28. data/lib/chef/knife/spork-omni.rb +107 -0
  29. data/lib/chef/knife/spork-promote.rb +166 -0
  30. data/lib/chef/knife/spork-role-create.rb +43 -0
  31. data/lib/chef/knife/spork-role-delete.rb +36 -0
  32. data/lib/chef/knife/spork-role-edit.rb +37 -0
  33. data/lib/chef/knife/spork-role-fromfile.rb +42 -0
  34. data/lib/chef/knife/spork-upload.rb +129 -0
  35. data/lib/knife-spork.rb +3 -0
  36. data/lib/knife-spork/plugins.rb +25 -0
  37. data/lib/knife-spork/plugins/campfire.rb +211 -0
  38. data/lib/knife-spork/plugins/eventinator.rb +317 -0
  39. data/lib/knife-spork/plugins/foodcritic.rb +46 -0
  40. data/lib/knife-spork/plugins/git.rb +197 -0
  41. data/lib/knife-spork/plugins/graphite.rb +25 -0
  42. data/lib/knife-spork/plugins/grove.rb +161 -0
  43. data/lib/knife-spork/plugins/hipchat.rb +131 -0
  44. data/lib/knife-spork/plugins/irccat.rb +298 -0
  45. data/lib/knife-spork/plugins/jabber.rb +129 -0
  46. data/lib/knife-spork/plugins/plugin.rb +105 -0
  47. data/lib/knife-spork/plugins/statusnet.rb +118 -0
  48. data/lib/knife-spork/runner.rb +277 -0
  49. data/plugins/Campfire.md +43 -0
  50. data/plugins/Eventinator.md +30 -0
  51. data/plugins/Foodcritic.md +53 -0
  52. data/plugins/Git.md +46 -0
  53. data/plugins/Graphite.md +30 -0
  54. data/plugins/Grove.md +31 -0
  55. data/plugins/HipChat.md +50 -0
  56. data/plugins/Irccat.md +50 -0
  57. data/plugins/Jabber.md +61 -0
  58. data/plugins/README.md +70 -0
  59. data/plugins/StatusNet.md +41 -0
  60. data/plugins/Template.md +34 -0
  61. metadata +170 -0
@@ -0,0 +1,42 @@
1
+ require 'chef/knife'
2
+ require 'knife-spork/runner'
3
+
4
+ module KnifeSpork
5
+ class SporkNodeRunListSet < Chef::Knife
6
+ include KnifeSpork::Runner
7
+
8
+ banner 'knife spork node run_list set NODE ENTRIES (options)'
9
+
10
+
11
+ def run
12
+ self.config = Chef::Config.merge!(config)
13
+
14
+ if @name_args.size < 2
15
+ ui.error "You must supply both a node name and a run list."
16
+ show_usage
17
+ exit 1
18
+ end
19
+
20
+ @object_name = @name_args.first
21
+
22
+ @object_secondary_name = @name_args[1..-1].map do |entry|
23
+ entry.split(',').map { |e| e.strip }
24
+ end.flatten.to_s
25
+
26
+ run_plugins(:before_noderunlistset)
27
+ pre_node = load_node(@object_name)
28
+ node_runlistset
29
+ post_node = load_node(@object_name)
30
+ @object_difference = json_diff(pre_node,post_node).to_s
31
+ run_plugins(:after_noderunlistset)
32
+ end
33
+
34
+ private
35
+ def node_runlistset
36
+ nrla = Chef::Knife::NodeRunListSet.new
37
+ nrla.name_args = @name_args
38
+ nrla.config[:editor] = config[:editor]
39
+ nrla.run
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,107 @@
1
+ require 'chef/knife'
2
+ require 'knife-spork/runner'
3
+
4
+ begin
5
+ require 'berkshelf'
6
+ rescue LoadError; end
7
+
8
+ module KnifeSpork
9
+ class SporkOmni < Chef::Knife
10
+ include KnifeSpork::Runner
11
+
12
+ banner 'knife spork omni COOKBOOK (options)'
13
+
14
+ option :cookbook_path,
15
+ :short => '-o PATH:PATH',
16
+ :long => '--cookbook-path PATH:PATH',
17
+ :description => 'A colon-separated path to look for cookbooks in',
18
+ :proc => lambda { |o| o.split(':') }
19
+
20
+ option :depends,
21
+ :short => '-D',
22
+ :long => '--include-dependencies',
23
+ :description => 'Also upload cookbook dependencies during the upload step'
24
+
25
+ option :bump_level,
26
+ :short => '-l',
27
+ :long => '--bump-level [major|minor|patch]',
28
+ :description => 'Version level to bump the cookbook (defaults to patch)',
29
+ :default => nil
30
+
31
+ option :omni_environment,
32
+ :short => '-e',
33
+ :long => '--environment ENVIRONMENT',
34
+ :description => 'Environment to promote the cookbook to',
35
+ :default => nil
36
+
37
+ option :remote,
38
+ :long => '--remote',
39
+ :description => 'Make omni finish with promote --remote instead of a local promote',
40
+ :default => nil
41
+
42
+ if defined?(::Berkshelf)
43
+ option :berksfile,
44
+ :short => '-b',
45
+ :long => '--berksfile BERKSFILE',
46
+ :description => 'Path to a Berksfile to operate from',
47
+ :default => File.join(Dir.pwd, ::Berkshelf::DEFAULT_FILENAME)
48
+ end
49
+
50
+ def run
51
+ self.config = Chef::Config.merge!(config)
52
+
53
+ if name_args.empty?
54
+ ui.fatal 'You must specify a cookbook name!'
55
+ show_usage
56
+ exit(1)
57
+ end
58
+
59
+ cookbook = name_args.first
60
+
61
+ run_plugins(:before_omni)
62
+ omni(cookbook)
63
+ run_plugins(:after_omni)
64
+ end
65
+
66
+ private
67
+
68
+ def bump(cookbook)
69
+ ui.msg "OMNI: Bumping #{cookbook}"
70
+ bump = SporkBump.new
71
+ bump.name_args = [cookbook,config[:bump_level]]
72
+ bump.run
73
+ end
74
+
75
+ def upload(cookbook)
76
+ ui.msg "OMNI: Uploading #{cookbook}"
77
+ upload = SporkUpload.new
78
+ upload.name_args = [cookbook]
79
+ upload.config[:cookbook_path] = config[:cookbook_path]
80
+ upload.config[:depends] = config[:depends]
81
+ upload.run
82
+ end
83
+
84
+ def promote(cookbook)
85
+ ui.msg "OMNI: Promoting #{cookbook}"
86
+ promote = SporkPromote.new
87
+ if config[:omni_environment]
88
+ promote.name_args = [config[:omni_environment],cookbook]
89
+ else
90
+ promote.name_args = [cookbook]
91
+ end
92
+ promote.config[:remote] = config[:remote]
93
+ if defined?(::Berkshelf)
94
+ promote.config[:berksfile] = config[:berksfile]
95
+ end
96
+ promote.run
97
+ end
98
+
99
+ def omni(cookbook)
100
+ bump(cookbook)
101
+ ui.msg ""
102
+ upload(cookbook)
103
+ ui.msg ""
104
+ promote(cookbook)
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,166 @@
1
+ require 'chef/knife'
2
+ require 'chef/exceptions'
3
+ require 'knife-spork/runner'
4
+
5
+ begin
6
+ require 'berkshelf'
7
+ rescue LoadError; end
8
+
9
+ module KnifeSpork
10
+ class SporkPromote < Chef::Knife
11
+ include KnifeSpork::Runner
12
+
13
+ banner 'knife spork promote ENVIRONMENT COOKBOOK (options)'
14
+
15
+ option :version,
16
+ :short => '-v',
17
+ :long => '--version VERSION',
18
+ :description => 'Set the environment\'s version constraint to the specified version',
19
+ :default => nil
20
+
21
+ option :remote,
22
+ :long => '--remote',
23
+ :description => 'Save the environment to the chef server in addition to the local JSON file',
24
+ :default => nil
25
+
26
+ if defined?(::Berkshelf)
27
+ option :berksfile,
28
+ :short => '-b',
29
+ :long => '--berksfile BERKSFILE',
30
+ :description => 'Path to a Berksfile to operate off of',
31
+ :default => File.join(Dir.pwd, ::Berkshelf::DEFAULT_FILENAME)
32
+ end
33
+
34
+ def run
35
+ self.config = Chef::Config.merge!(config)
36
+
37
+ if @name_args.empty?
38
+ show_usage
39
+ ui.error("You must specify the cookbook and environment to promote to")
40
+ exit 1
41
+ end
42
+
43
+ #First load so plugins etc know what to work with
44
+ @environments, @cookbook = load_environments_and_cookbook
45
+
46
+ run_plugins(:before_promote)
47
+
48
+ #Reload cookbook and env in case a VCS plugin found updates
49
+ @environments, @cookbook = load_environments_and_cookbook
50
+
51
+ check_cookbook_uploaded(@cookbook)
52
+
53
+ @environments.each do |e|
54
+ environment = load_environment_from_file(e)
55
+
56
+
57
+ promote(environment, @cookbook)
58
+
59
+ ui.msg "Saving changes to #{e}.json"
60
+
61
+ new_environment_json = pretty_print_json(environment.to_hash)
62
+ save_environment_changes(e, new_environment_json)
63
+
64
+ if config[:remote] || spork_config.always_promote_remote
65
+ ui.msg "Uploading #{environment.name}.json to Chef Server"
66
+ save_environment_changes_remote(e)
67
+ ui.info "Promotion complete at #{Time.now}!"
68
+ else
69
+ ui.info "Promotion complete. Don't forget to upload your changed #{environment.name}.json to Chef Server"
70
+ end
71
+ end
72
+ run_plugins(:after_promote_local)
73
+ if config[:remote] || spork_config.always_promote_remote
74
+ run_plugins(:after_promote_remote)
75
+ end
76
+ end
77
+
78
+ def update_version_constraints(environment, cookbook, new_version)
79
+ validate_version!(new_version)
80
+ environment.cookbook_versions[cookbook] = "= #{new_version}"
81
+ end
82
+
83
+ def save_environment_changes_remote(environment)
84
+ local_environment = load_environment_from_file(environment)
85
+ remote_environment = load_remote_environment(environment)
86
+ @environment_diffs ||= Hash.new
87
+ @environment_diffs["#{environment}"] = environment_diff(local_environment, remote_environment)
88
+
89
+ version_change_threshold = spork_config.version_change_threshold || 2
90
+ env_constraints_diff = constraints_diff(@environment_diffs["#{environment}"]).select{|k,v| v > version_change_threshold}
91
+
92
+ if env_constraints_diff.size !=0 then
93
+ ui.warn 'You\'re about to promote a significant version number change to 1 or more cookbooks:'
94
+ ui.warn @environment_diffs["#{environment}"].select{|k,v|env_constraints_diff.has_key?(k)}.collect{|k,v| "\t#{k}: #{v}"}.join("\n")
95
+
96
+ begin
97
+ ui.confirm('Are you sure you want to continue?')
98
+ rescue SystemExit => e
99
+ if e.status == 3
100
+ ui.confirm("Would you like to reset your local #{environment}.json to match the remote server?")
101
+ tmp = Chef::Environment.load(environment)
102
+ save_environment_changes(environment, pretty_print_json(tmp))
103
+ ui.info "#{environment}.json was reset"
104
+ end
105
+
106
+ raise
107
+ end
108
+ end
109
+
110
+ if @environment_diffs["#{environment}"].size > 1
111
+ ui.msg ""
112
+ ui.warn "You're about to promote changes to several cookbooks at once:"
113
+ ui.warn @environment_diffs["#{environment}"].collect{|k,v| "\t#{k}: #{v}"}.join("\n")
114
+
115
+ begin
116
+ ui.confirm('Are you sure you want to continue?')
117
+ rescue SystemExit => e
118
+ if e.status == 3
119
+ ui.confirm("Would you like to reset your local #{environment}.json to match the remote server?")
120
+ tmp = Chef::Environment.load(environment)
121
+ save_environment_changes(environment, pretty_print_json(tmp))
122
+ ui.info "#{environment}.json was reset"
123
+ end
124
+
125
+ raise
126
+ end
127
+ end
128
+
129
+ local_environment.save
130
+ end
131
+
132
+ def save_environment_changes(environment, json)
133
+ environments_path = spork_config[:environment_path] || cookbook_path.gsub('cookbooks', 'environments')
134
+ environment_path = File.expand_path( File.join(environments_path, "#{environment}.json") )
135
+
136
+ File.open(environment_path, 'w'){ |f| f.puts(json) }
137
+ end
138
+
139
+ def promote(environment, cookbook_names)
140
+ cookbook_names = [cookbook_names].flatten
141
+
142
+ cookbook_names.each do |cookbook_name|
143
+ validate_version!(config[:version])
144
+ version = config[:version] || load_cookbook(cookbook_name).version
145
+
146
+ ui.msg "Adding version constraint #{cookbook_name} = #{version}"
147
+ update_version_constraints(environment, cookbook_name, version)
148
+ end
149
+ end
150
+
151
+ def check_cookbook_uploaded(cookbook_name)
152
+ validate_version!(config[:version])
153
+ version = config[:version] || load_cookbook(cookbook_name).version
154
+
155
+ environment = config[:environment]
156
+ api_endpoint = environment ? "environments/#{environment}/cookbooks/#{cookbook_name}/#{version}" : "cookbooks/#{cookbook_name}/#{version}"
157
+
158
+ begin
159
+ cookbooks = rest.get_rest(api_endpoint)
160
+ rescue Net::HTTPServerException => e
161
+ ui.error "#{cookbook_name}@#{version} does not exist on Chef Server! Upload the cookbook first by running:\n\n\tknife spork upload #{cookbook_name}\n\n"
162
+ exit(1)
163
+ end
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,43 @@
1
+ require 'chef/knife'
2
+ require 'knife-spork/runner'
3
+
4
+ module KnifeSpork
5
+ class SporkRoleCreate < Chef::Knife
6
+ include KnifeSpork::Runner
7
+
8
+ banner 'knife spork role create ROLE (options)'
9
+
10
+ option :description,
11
+ :short => "-d DESC",
12
+ :long => "--description DESC",
13
+ :description => "The role description"
14
+
15
+ def run
16
+ self.config = Chef::Config.merge!(config)
17
+
18
+ if @name_args.empty?
19
+ show_usage
20
+ ui.error("You must specify a role name")
21
+ exit 1
22
+ end
23
+
24
+ @object_name = @name_args.first
25
+
26
+ run_plugins(:before_rolecreate)
27
+ pre_role = {}
28
+ role_create
29
+ post_role = load_role(@object_name)
30
+ @object_difference = json_diff(pre_role,post_role).to_s
31
+ run_plugins(:after_rolecreate)
32
+ end
33
+
34
+ private
35
+ def role_create
36
+ rc = Chef::Knife::RoleCreate.new
37
+ rc.name_args = @name_args
38
+ rc.config[:editor] = config[:editor]
39
+ rc.config[:description] = config[:description]
40
+ rc.run
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,36 @@
1
+ require 'chef/knife'
2
+ require 'knife-spork/runner'
3
+
4
+ module KnifeSpork
5
+ class SporkRoleDelete < Chef::Knife
6
+ include KnifeSpork::Runner
7
+
8
+ banner 'knife spork role delete ROLENAME (options)'
9
+
10
+ def run
11
+ self.config = Chef::Config.merge!(config)
12
+
13
+ if @name_args.empty?
14
+ show_usage
15
+ ui.error("You must specify a role name")
16
+ exit 1
17
+ end
18
+
19
+ @object_name = @name_args.first
20
+
21
+ run_plugins(:before_roledelete)
22
+ pre_role = load_role(@object_name)
23
+ role_delete
24
+ post_role = {}
25
+ @object_difference = json_diff(pre_role,post_role).to_s
26
+ run_plugins(:after_roledelete)
27
+ end
28
+
29
+ private
30
+ def role_delete
31
+ rd = Chef::Knife::RoleDelete.new
32
+ rd.name_args = @name_args
33
+ rd.run
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,37 @@
1
+ require 'chef/knife'
2
+ require 'knife-spork/runner'
3
+
4
+ module KnifeSpork
5
+ class SporkRoleEdit < Chef::Knife
6
+ include KnifeSpork::Runner
7
+
8
+ banner 'knife spork role edit ROLENAME (options)'
9
+
10
+ def run
11
+ self.config = Chef::Config.merge!(config)
12
+
13
+ if @name_args.empty?
14
+ show_usage
15
+ ui.error("You must specify a role name")
16
+ exit 1
17
+ end
18
+
19
+ @object_name = @name_args.first
20
+
21
+ run_plugins(:before_roleedit)
22
+ pre_role = load_role(@object_name)
23
+ role_edit
24
+ post_role = load_role(@object_name)
25
+ @object_difference = json_diff(pre_role,post_role).to_s
26
+ run_plugins(:after_roleedit)
27
+ end
28
+
29
+ private
30
+ def role_edit
31
+ re = Chef::Knife::RoleEdit.new
32
+ re.name_args = @name_args
33
+ re.config[:editor] = config[:editor]
34
+ re.run
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,42 @@
1
+ require 'chef/knife'
2
+ require 'knife-spork/runner'
3
+ require 'json'
4
+
5
+ module KnifeSpork
6
+ class SporkRoleFromFile < Chef::Knife
7
+ include KnifeSpork::Runner
8
+
9
+ deps do
10
+ require 'chef/knife/role_from_file'
11
+ end
12
+
13
+ banner 'knife spork role from file FILENAME (options)'
14
+
15
+ def run
16
+ self.config = Chef::Config.merge!(config)
17
+
18
+ if @name_args.empty?
19
+ show_usage
20
+ ui.error("You must specify a role name")
21
+ exit 1
22
+ end
23
+
24
+ @name_args.each do |arg|
25
+ @object_name = arg.split("/").last
26
+ run_plugins(:before_rolefromfile)
27
+ pre_role = load_role(@object_name.gsub(".json","").gsub(".rb",""))
28
+ role_from_file
29
+ post_role = load_role(@object_name.gsub(".json","").gsub(".rb",""))
30
+ @object_difference = json_diff(pre_role,post_role).to_s
31
+ run_plugins(:after_rolefromfile)
32
+ end
33
+ end
34
+
35
+ private
36
+ def role_from_file
37
+ rff = Chef::Knife::RoleFromFile.new
38
+ rff.name_args = @name_args
39
+ rff.run
40
+ end
41
+ end
42
+ end