knife-spork 1.4.2 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZDQ0OGMxOWQxZjQ5OWQ4OTIxM2NjZjg0ZGFiZmIxYjEwYWRlZDYyZg==
4
+ ZjE4NDhiY2I4MTA3YjgyZWFmYWMxNDk0MTc0NmQzMDdiZjVmNDNlOA==
5
5
  data.tar.gz: !binary |-
6
- MDBiYmMzMjMxMjQxNzZhYmMwYzQ0MTVjNzczY2M5NTgxZWZhZTA1Nw==
6
+ NzFjYTlhOWIyMDhhYzVjZDI3Mjg2YWMwNmI1OGFhMzQyMWJmMTY3OQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ZDkwOWZmNjEyNzQ3YTgzOWJmOTJkNGU1NTFhYjMwNGMwMWE5ZjAwNjJhY2M4
10
- MGYyODgwMDdkMGY2ZTRjY2JiNDgyM2Y2NTlkNWFiYTlhMzMzNjM0YzExZjAy
11
- MWJjMzY3YmNmZjk1NDNiYjZlOTA5YmNkZmY0NDcwNDRkZjU3YTA=
9
+ NmRjNWRkNGQ4YWVkMDZkNjJkZmVkY2VlM2U1MjM3OWFkYTY0ZmNkNzdiMzcw
10
+ MDRjMzY4YjUyZTgyNDdkNmJjODdkZWM5NmU5YmQ2OTEzNGZiY2E3ZmQxYjE5
11
+ MjU5MTYxMmQ2MzAzMWIxOGQwMzEwNWQ4NTlmY2IyMGZmOTE5ZjA=
12
12
  data.tar.gz: !binary |-
13
- MTg4MGRlN2Q5YzgxNWJmZjFkODZjNDZkNTcxZDI5MDIyMTQzOTEyMDY3NGIy
14
- MTI1NDRjMmE2OTI3NTU2OWVkY2I4NmQ3MjY0YzA1MjlmNDVkOGFkMGQyMDli
15
- YmY5ZTlkYjE4YmRiMDYwM2RlNmI1NjZkNTFmYjVjMjZlM2Y4Nzc=
13
+ OTIzMWU3YTViODZmZjUzZWI4ZGQzM2QyYzAyMmZlYzc1YzY2ODU2OTJkNzJj
14
+ OTU4MWE2NWRhZTRiNDc5NGJlN2FjMGU2MWE1MzljY2RhNWZkODQ0Y2Q5ZjM5
15
+ ZTZlMzM5Y2I0ZGEyMGVkMmRmNTU5NDcyZDE0ODIwNTRhZmEwMjg=
@@ -1,3 +1,3 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.9.3
3
+ - 2.1.1
@@ -1,3 +1,27 @@
1
+ ## 1.5.0(26th January, 2015)
2
+
3
+ Features:
4
+
5
+ - InfluxDB Plugin added (Thanks to @vic3lord https://github.com/jonlives/knife-spork/pull/167)
6
+ - Add gist & diff behavior to the Hipchat plugin (Thanks to @danieleva https://github.com/jonlives/knife-spork/pull/153)
7
+ - Optional config flag to enforce that role files share the same name as the role they contain (Thanks to @nishansubedi https://github.com/jonlives/knife-spork/pull/152)
8
+ - Add optional --cookbook-path flag to Spork Promote (Thanks to @bcandrea https://github.com/jonlives/knife-spork/pull/169)
9
+ - Add --cookbook-path option to spork promote command (Thanks to @bcandrea https://github.com/jonlives/knife-spork/pull/169)
10
+ - Add verification check to environment create commadn when environment already exists (https://github.com/jonlives/knife-spork/issues/171)
11
+ - Add save_environment_locally_on_create option to have environment create command save a local copy of the environment file (https://github.com/jonlives/knife-spork/issues/172)
12
+ - Lazily load Berkshelf to improve overall knife performance (Thanks to @lamont-granquist https://github.com/jonlives/knife-spork/pull/158)
13
+
14
+ Bugfixes:
15
+
16
+ - Add cookbook name metadata field to test cookbook (Thanks to @jdmundrawala https://github.com/jonlives/knife-spork/pull/162)
17
+ - Add missing require statements to fix specs running against Chef 12 (Thanks to @jdmunrawala https://github.com/jonlives/knife-spork/pull/163)
18
+ - Fix issues with the slack plugin (Thanks to @therobot https://github.com/jonlives/knife-spork/pull/160)
19
+ - Fix issue with knife spork omni and skip_berkshelf option when Berkshelf not installed (Thanks to @ctrlok https://github.com/jonlives/knife-spork/pull/168)
20
+ - Fix yajl error on missing environment files (Thanks to @oker1 https://github.com/jonlives/knife-spork/pull/165)
21
+ - Fix for changed constant name from Yaj to FFI_Yajl in Chef 12 (Thanks to @jeunito https://github.com/jonlives/knife-spork/pull/154)
22
+ - Fix Spork DataBag Create to handle specifying a data bag item name too (https://github.com/jonlives/knife-spork/issues/156)
23
+
24
+
1
25
  ## 1.4.2(3rd November, 2014)
2
26
 
3
27
  Features:
@@ -14,7 +38,7 @@ Bugfixes:
14
38
  - Fix custom plugin loading on Window (Thanks to @carpnick https://github.com/jonlives/knife-spork/pull/150)
15
39
  - Fix config loading in CookbookUploader under Chef 12 (Thanks to @jordane https://github.com/jonlives/knife-spork/pull/149)
16
40
  - Do not attempt to load Berksfile if not present (Thanks to @redondos https://github.com/jonlives/knife-spork/pull/142)
17
-
41
+
18
42
  ## 1.4.1 (21st August, 2014)
19
43
 
20
44
  Bugfixes:
data/README.md CHANGED
@@ -50,10 +50,12 @@ environment_groups:
50
50
  version_change_threshold: 2
51
51
  preserve_constraint_operators: true
52
52
  environment_path: "/home/me/environments"
53
+ save_environment_locally_on_create: false
53
54
  role_path: "/home/me/roles"
54
55
  custom_plugin_path: "/home/me/spork-plugins"
55
56
  always_promote_remote: true
56
57
  skip_berkshelf: false
58
+ role_match_file_name: true
57
59
  json_options:
58
60
  indent: " "
59
61
  plugins:
@@ -90,6 +92,13 @@ plugins:
90
92
  graphite:
91
93
  server: graphite.mydomain.com
92
94
  port: 2003
95
+ influxdb:
96
+ database: deployments
97
+ username: deploy
98
+ password: deploy
99
+ series: deployments
100
+ host: influx.example.com
101
+ port: 8086
93
102
  eventinator:
94
103
  url: http://eventinator.mydomain.com/events/oneshot
95
104
  slack:
@@ -129,11 +138,18 @@ The `skip_berkshelf` directive is a temporary flag added in [#138](https://githu
129
138
  The `json_options` directive allows you to tell spork to pass options to [pretty_generate](http://www.ruby-doc.org/stdlib-1.9.3/libdoc/json/rdoc/JSON.html#method-i-pretty_generate) to control the format of the resulting json
130
139
 
131
140
  #### Environment Path
132
- The `environment_path` allows you to specify the path to where you store your chef environment json files. If this parameter is not specified, spork will default to using the first element of your cookbook_path, replacing the word "cookbooks" with "environments"
141
+ The `environment_path` directive allows you to specify the path to where you store your chef environment json files. If this parameter is not specified, spork will default to using the first element of your cookbook_path, replacing the word "cookbooks" with "environments"
142
+
143
+ #### Save Environment on Create
144
+ The `save_environment_on_create` directive allows you to have the ```knife spork environment create``` command save a copy of the new environment to your Chef repository. This will default to saving environment files in the location specified by the ```environment_path``` directive. If this parameter is not specified, spork will default to using the first element of your cookbook_path, replacing the word "cookbooks" with "environments"
145
+
133
146
 
134
147
  #### Role Path
135
148
  The `role_path` allows you to specify the path to where you store your chef role json files. If this parameter is not specified, spork will default to using the first element of your cookbook_path, replacing the word "cookbooks" with "roles"
136
149
 
150
+ #### Role Match File Name
151
+ The `role_match_file_name` flag allows you to check whether the file name that is used to upload a role matches the role name as well. If the parameter is specified, or flag `--match-filename` is set, spork will not let you upload a role from a file unless the name matches the rolename.
152
+
137
153
  #### Custom Plugin Path
138
154
  The `custom_plugin_path` allows you to specify an additional directory from which to load knife-spork plugins. If this parameter is not specified or the path set does not exist, only the default plugins shipped with knife-spork will be loaded (if enabled in config)
139
155
 
data/Rakefile CHANGED
@@ -21,8 +21,8 @@ task :preseed_test_environment do
21
21
  @server = ChefZero::Server.new(port: 4000)
22
22
  @server.start_background
23
23
  puts "Uploading test data"
24
- `knife cookbook upload example -c spec/unit/fixtures/knife.rb`
25
- `knife environment from file spec/unit/fixtures/environments/example.json -c spec/unit/fixtures/knife.rb`
24
+ system("knife cookbook upload example -c spec/unit/fixtures/knife.rb")
25
+ system("knife environment from file spec/unit/fixtures/environments/example.json -c spec/unit/fixtures/knife.rb")
26
26
  end
27
27
 
28
28
  task :cleanup_test_environment do
@@ -2,7 +2,7 @@ $:.push File.expand_path('../lib', __FILE__)
2
2
 
3
3
  Gem::Specification.new do |gem|
4
4
  gem.name = 'knife-spork'
5
- gem.version = '1.4.2'
5
+ gem.version = '1.5.0'
6
6
  gem.authors = ["Jon Cowie"]
7
7
  gem.email = 'jonlives@gmail.com'
8
8
  gem.homepage = 'https://github.com/jonlives/knife-spork'
@@ -10,24 +10,23 @@ module KnifeSpork
10
10
  TYPE_INDEX = { :major => 0, :minor => 1, :patch => 2, :manual => 3 }.freeze
11
11
 
12
12
  option :cookbook_path,
13
- :short => '-o PATH:PATH',
14
- :long => '--cookbook-path PATH:PATH',
15
- :description => 'A colon-separated path to look for cookbooks in',
16
- :proc => lambda { |o| o.split(':') }
17
-
18
- if defined?(::Berkshelf)
19
- option :berksfile,
20
- :short => '-b',
21
- :long => 'berksfile',
22
- :description => 'Path to a Berksfile to operate off of',
23
- :default => File.join(Dir.pwd, ::Berkshelf::DEFAULT_FILENAME)
24
-
25
- option :skip_dependencies,
26
- :short => '-s',
27
- :long => '--skip-dependencies',
28
- :description => 'Berksfile skips resolving source cookbook dependencies',
29
- :default => true
30
- end
13
+ :short => '-o PATH:PATH',
14
+ :long => '--cookbook-path PATH:PATH',
15
+ :description => 'A colon-separated path to look for cookbooks in',
16
+ :proc => lambda { |o| o.split(':') }
17
+
18
+ option :berksfile,
19
+ :short => '-b',
20
+ :long => 'berksfile',
21
+ :description => 'Path to a Berksfile to operate off of',
22
+ :default => nil,
23
+ :proc => lambda { |o| o || File.join(Dir.pwd, ::Berkshelf::DEFAULT_FILENAME) }
24
+
25
+ option :skip_dependencies,
26
+ :short => '-s',
27
+ :long => '--skip-dependencies',
28
+ :description => 'Berksfile skips resolving source cookbook dependencies',
29
+ :default => true
31
30
 
32
31
  banner 'knife spork bump COOKBOOK [major|minor|patch|manual]'
33
32
 
@@ -15,28 +15,27 @@ module KnifeSpork
15
15
  :description => 'Show all uploaded versions of the cookbook'
16
16
 
17
17
  option :fail,
18
- :long => "--fail",
19
- :description => "If the check fails exit with non-zero exit code"
18
+ :long => "--fail",
19
+ :description => "If the check fails exit with non-zero exit code"
20
20
 
21
21
  option :cookbook_path,
22
- :short => '-o PATH:PATH',
23
- :long => '--cookbook-path PATH:PATH',
24
- :description => 'A colon-separated path to look for cookbooks in',
25
- :proc => lambda { |o| o.split(':') }
26
-
27
- if defined?(::Berkshelf)
28
- option :berksfile,
29
- :short => '-b',
30
- :long => 'berksfile',
31
- :description => 'Path to a Berksfile to operate off of',
32
- :default => File.join(Dir.pwd, ::Berkshelf::DEFAULT_FILENAME)
33
-
34
- option :skip_dependencies,
35
- :short => '-s',
36
- :long => '--skip-dependencies',
37
- :description => 'Berksfile skips resolving source cookbook dependencies',
38
- :default => true
39
- end
22
+ :short => '-o PATH:PATH',
23
+ :long => '--cookbook-path PATH:PATH',
24
+ :description => 'A colon-separated path to look for cookbooks in',
25
+ :proc => lambda { |o| o.split(':') }
26
+
27
+ option :berksfile,
28
+ :short => '-b',
29
+ :long => 'berksfile',
30
+ :description => 'Path to a Berksfile to operate off of',
31
+ :default => nil,
32
+ :proc => lambda { |o| o || File.join(Dir.pwd, ::Berkshelf::DEFAULT_FILENAME) }
33
+
34
+ option :skip_dependencies,
35
+ :short => '-s',
36
+ :long => '--skip-dependencies',
37
+ :description => 'Berksfile skips resolving source cookbook dependencies',
38
+ :default => true
40
39
 
41
40
  def run
42
41
  self.class.send(:include, KnifeSpork::Runner)
@@ -54,7 +53,7 @@ module KnifeSpork
54
53
 
55
54
  #First load so plugins etc know what to work with
56
55
  initial_load
57
-
56
+
58
57
  run_plugins(:before_check)
59
58
 
60
59
  #Reload cookbook in case a VCS plugin found updates
@@ -152,7 +151,7 @@ module KnifeSpork
152
151
  rest.get_rest(api_endpoint).to_hash['frozen?']
153
152
  end
154
153
  end
155
-
154
+
156
155
  def fail_and_exit(message, options={})
157
156
  ui.fatal message
158
157
  show_usage if options[:show_usage]
@@ -31,11 +31,12 @@ module KnifeSpork
31
31
  end
32
32
 
33
33
  @object_name = @name_args.first
34
+ @object_secondary_name = @name_args.last
34
35
 
35
36
  run_plugins(:before_databagcreate)
36
37
  pre_databag = {}
37
38
  databag_create
38
- post_databag = load_databag(@object_name)
39
+ post_databag = load_databag_item(@object_name, @object_secondary_name)
39
40
  @object_difference = json_diff(pre_databag,post_databag).to_s
40
41
  run_plugins(:after_databagcreate)
41
42
  end
@@ -27,9 +27,26 @@ module KnifeSpork
27
27
  @object_name = @name_args.first
28
28
 
29
29
  run_plugins(:before_environmentcreate)
30
+
31
+ # Check if environment already exists
32
+ begin
33
+ check_environment = load_environment(@object_name)
34
+ if check_environment
35
+ ui.confirm("It looks like the environment #{@object_name} already exists. Are you sure you want to overwrite it")
36
+ end
37
+ rescue Net::HTTPServerException
38
+ end
39
+
40
+
30
41
  pre_environment = {}
31
42
  environment_create
32
43
  post_environment = load_environment(@object_name)
44
+
45
+ if spork_config[:save_environment_locally_on_create]
46
+ ui.msg "Saving environment changes to #{@object_name}.json"
47
+ save_environment_changes(@object_name, pretty_print_json(post_environment))
48
+ end
49
+
33
50
  @object_difference = json_diff(pre_environment,post_environment).to_s
34
51
  run_plugins(:after_environmentcreate)
35
52
  end
@@ -1,13 +1,13 @@
1
1
  require 'chef/knife'
2
- begin
3
- require 'berkshelf'
4
- rescue LoadError; end
5
2
 
6
3
  module KnifeSpork
7
4
  class SporkOmni < Chef::Knife
8
5
 
9
6
  deps do
10
7
  require 'knife-spork/runner'
8
+ begin
9
+ require 'berkshelf'
10
+ rescue LoadError; end
11
11
  end
12
12
 
13
13
  banner 'knife spork omni COOKBOOK (options)'
@@ -40,13 +40,12 @@ module KnifeSpork
40
40
  :description => 'Make omni finish with promote --remote instead of a local promote',
41
41
  :default => nil
42
42
 
43
- if defined?(::Berkshelf)
44
- option :berksfile,
45
- :short => '-b',
46
- :long => '--berksfile BERKSFILE',
47
- :description => 'Path to a Berksfile to operate from',
48
- :default => File.join(Dir.pwd, ::Berkshelf::DEFAULT_FILENAME)
49
- end
43
+ option :berksfile,
44
+ :short => '-b',
45
+ :long => '--berksfile BERKSFILE',
46
+ :description => 'Path to a Berksfile to operate from',
47
+ :default => nil,
48
+ :proc => lambda { |o| o || File.join(Dir.pwd, ::Berkshelf::DEFAULT_FILENAME) }
50
49
 
51
50
  def run
52
51
  self.class.send(:include, KnifeSpork::Runner)
@@ -1,7 +1,4 @@
1
1
  require 'chef/knife'
2
- begin
3
- require 'berkshelf'
4
- rescue LoadError; end
5
2
 
6
3
  module KnifeSpork
7
4
  class SporkPromote < Chef::Knife
@@ -9,6 +6,9 @@ module KnifeSpork
9
6
  deps do
10
7
  require 'chef/exceptions'
11
8
  require 'knife-spork/runner'
9
+ begin
10
+ require 'berkshelf'
11
+ rescue LoadError; end
12
12
  end
13
13
 
14
14
  banner 'knife spork promote ENVIRONMENT COOKBOOK (options)'
@@ -24,6 +24,12 @@ module KnifeSpork
24
24
  :description => 'Save the environment to the chef server in addition to the local JSON file',
25
25
  :default => nil
26
26
 
27
+ option :cookbook_path,
28
+ :short => '-o PATH:PATH',
29
+ :long => '--cookbook-path PATH:PATH',
30
+ :description => 'A colon-separated path to look for cookbooks in',
31
+ :proc => lambda { |o| o.split(':') }
32
+
27
33
  if defined?(::Berkshelf)
28
34
  option :berksfile,
29
35
  :short => '-b',
@@ -151,19 +157,6 @@ module KnifeSpork
151
157
  local_environment.save
152
158
  end
153
159
 
154
- def save_environment_changes(environment, json)
155
- if spork_config[:environment_path]
156
- environments_path = spork_config[:environment_path]
157
- else
158
- split_cb_path = cookbook_path.split("/")
159
- environments_path = (split_cb_path[0..-2] << split_cb_path[-1].gsub("cookbooks","environments")).join("/")
160
- end
161
-
162
- environment_path = File.expand_path( File.join(environments_path, "#{environment}.json") )
163
-
164
- File.open(environment_path, 'w'){ |f| f.puts(json) }
165
- end
166
-
167
160
  def promote(environment, cookbook_names)
168
161
  cookbook_names = [cookbook_names].flatten
169
162
 
@@ -11,6 +11,13 @@ module KnifeSpork
11
11
 
12
12
  banner 'knife spork role from file FILENAME (options)'
13
13
 
14
+ option :match_filename,
15
+ :long => '--match-filename',
16
+ :short => '-f',
17
+ :description => 'Ensure that the filename matches the name specified in the role (true|false).',
18
+ :boolean => true,
19
+ :default => false
20
+
14
21
  def run
15
22
  self.class.send(:include, KnifeSpork::Runner)
16
23
  self.config = Chef::Config.merge!(config)
@@ -40,6 +47,18 @@ module KnifeSpork
40
47
  def role_from_file
41
48
  rff = Chef::Knife::RoleFromFile.new
42
49
  rff.name_args = @name_args
50
+ if (config[:match_filename] || spork_config[:role_match_file_name])
51
+ ## Check if file names match role names
52
+ @name_args.each do |arg|
53
+ file_name = arg.split("/").last
54
+ role = rff.loader.load_from("roles", file_name)
55
+ file_name = file_name.gsub(".json","").gsub(".rb", "")
56
+ if file_name != role.name
57
+ ui.error("Role name in file #{role.name} does not match file name #{file_name}")
58
+ exit 1
59
+ end
60
+ end
61
+ end
43
62
  rff.run
44
63
  end
45
64
  end
@@ -32,13 +32,12 @@ module KnifeSpork
32
32
  :long => '--include-dependencies',
33
33
  :description => 'Also upload cookbook dependencies'
34
34
 
35
- if defined?(::Berkshelf)
36
- option :berksfile,
37
- :short => '-b',
38
- :long => 'berksfile',
39
- :description => 'Path to a Berksfile to operate off of',
40
- :default => File.join(Dir.pwd, ::Berkshelf::DEFAULT_FILENAME)
41
- end
35
+ option :berksfile,
36
+ :short => '-b',
37
+ :long => 'berksfile',
38
+ :description => 'Path to a Berksfile to operate off of',
39
+ :default => nil,
40
+ :proc => lambda { |o| o || File.join(Dir.pwd, ::Berkshelf::DEFAULT_FILENAME) }
42
41
 
43
42
  def run
44
43
  self.class.send(:include, KnifeSpork::Runner)
@@ -12,87 +12,109 @@ module KnifeSpork
12
12
  end
13
13
 
14
14
  def after_promote_remote
15
- hipchat "#{organization}#{current_user} promoted the following cookbooks:\n#{cookbooks.collect{ |c| " #{c.name}@#{c.version}" }.join("\n")} to #{environments.collect{ |e| "#{e.name}" }.join(", ")}"
15
+ diff = environment_diffs[environment.name]
16
+ env_gist = env_gist(environment, diff) if config.gist
17
+ hipchat "#{organization}#{current_user} promoted the following cookbooks:\n#{cookbooks.collect{ |c| " #{c.name}@#{c.version}" }.join("\n")} to #{environments.collect{ |e| "#{e.name}" }.join(", ")} #{env_gist}"
16
18
  end
17
19
 
18
20
  def after_environmentfromfile
19
- hipchat "#{organization}#{current_user} uploaded environment #{object_name}"
21
+ environment_gist = object_gist("environment", object_name, object_difference) if config.gist and !object_difference.empty?
22
+ hipchat "#{organization}#{current_user} uploaded environment #{object_name} #{environment_gist}"
20
23
  end
21
24
 
22
25
  def after_environmentedit
23
- hipchat "#{organization}#{current_user} edited environment #{object_name}"
26
+ environment_gist = object_gist("environment", object_name, object_difference) if config.gist and !object_difference.empty?
27
+ hipchat "#{organization}#{current_user} edited environment #{object_name} #{environment_gist}"
24
28
  end
25
29
 
26
30
  def after_environmentcreate
27
- hipchat "#{organization}#{current_user} created environment #{object_name}"
31
+ environment_gist = object_gist("environment", object_name, object_difference) if config.gist and !object_difference.empty?
32
+ hipchat "#{organization}#{current_user} created environment #{object_name} #{environment_gist}"
28
33
  end
29
34
 
30
35
  def after_environmentdelete
31
- hipchat "#{organization}#{current_user} deleted environment #{object_name}"
36
+ environment_gist = object_gist("environment", object_name, object_difference) if config.gist and !object_difference.empty?
37
+ hipchat "#{organization}#{current_user} deleted environment #{object_name} #{environment_gist}"
32
38
  end
33
39
 
34
40
  def after_rolefromfile
35
- hipchat "#{organization}#{current_user} uploaded role #{object_name}"
41
+ role_gist = object_gist("role", object_name, object_difference) if config.gist and !object_difference.empty?
42
+ hipchat "#{organization}#{current_user} uploaded role #{object_name} #{role_gist}"
36
43
  end
37
44
 
38
45
  def after_roleedit
39
- hipchat "#{organization}#{current_user} edited role #{object_name}"
46
+ role_gist = object_gist("role", object_name, object_difference) if config.gist and !object_difference.empty?
47
+ hipchat "#{organization}#{current_user} edited role #{object_name} #{role_gist}"
40
48
  end
41
49
 
42
50
  def after_rolecreate
43
- hipchat "#{organization}#{current_user} created role #{object_name}"
51
+ role_gist = object_gist("role", object_name, object_difference) if config.gist and !object_difference.empty?
52
+ hipchat "#{organization}#{current_user} created role #{object_name} #{role_gist}"
44
53
  end
45
54
 
46
55
  def after_roledelete
47
- hipchat "#{organization}#{current_user} deleted role #{object_name}"
56
+ role_gist = object_gist("role", object_name, object_difference) if config.gist and !object_difference.empty?
57
+ hipchat "#{organization}#{current_user} deleted role #{object_name} #{role_gist}"
48
58
  end
49
59
 
50
60
  def after_databagedit
51
- hipchat "#{organization}#{current_user} edited data bag item #{object_name}:#{object_secondary_name}"
61
+ databag_gist = object_gist("databag item", "#{object_name}:#{object_secondary_name}", object_difference) if config.gist and !object_difference.empty?
62
+ hipchat "#{organization}#{current_user} edited data bag item #{object_name}:#{object_secondary_name} #{databag_gist}"
52
63
  end
53
64
 
54
65
  def after_databagcreate
55
- hipchat "#{organization}#{current_user} created data bag #{object_name}"
66
+ databag_gist = object_gist("databag item", "#{object_name}:#{object_secondary_name}", object_difference) if config.gist and !object_difference.empty?
67
+ hipchat "#{organization}#{current_user} created data bag #{object_name} #{databag_gist}"
56
68
  end
57
69
 
58
70
  def after_databagdelete
59
- hipchat "#{organization}#{current_user} deleted data bag item #{object_name}"
71
+ databag_gist = object_gist("databag item", "#{object_name}:#{object_secondary_name}", object_difference) if config.gist and !object_difference.empty?
72
+ hipchat "#{organization}#{current_user} deleted data bag item #{object_name} #{databag_gist}"
60
73
  end
61
74
 
62
75
  def after_databagitemdelete
63
- hipchat "#{organization}#{current_user} deleted data bag item #{object_name}:#{object_secondary_name}"
76
+ databag_gist = object_gist("databag item", "#{object_name}:#{object_secondary_name}", object_difference) if config.gist and !object_difference.empty?
77
+ hipchat "#{organization}#{current_user} deleted data bag item #{object_name}:#{object_secondary_name} #{databag_gist}"
64
78
  end
65
79
 
66
80
  def after_databagfromfile
67
- hipchat "#{organization}#{current_user} uploaded data bag item #{object_name}:#{object_secondary_name}"
81
+ databag_gist = object_gist("databag item", "#{object_name}:#{object_secondary_name}", object_difference) if config.gist and !object_difference.empty?
82
+ hipchat "#{organization}#{current_user} uploaded data bag item #{object_name}:#{object_secondary_name} #{databag_gist}"
68
83
  end
69
84
 
70
85
  def after_nodeedit
71
- hipchat "#{organization}#{current_user} edited node #{object_name}"
86
+ node_gist = object_gist("node", "#{object_name}", object_difference) if config.gist and !object_difference.empty?
87
+ hipchat "#{organization}#{current_user} edited node #{object_name} #{node_gist}"
72
88
  end
73
89
 
74
90
  def after_nodedelete
75
- hipchat "#{organization}#{current_user} deleted node #{object_name}"
91
+ node_gist = object_gist("node", "#{object_name}", object_difference) if config.gist and !object_difference.empty?
92
+ hipchat "#{organization}#{current_user} deleted node #{object_name} #{node_gist}"
76
93
  end
77
94
 
78
95
  def after_nodecreate
79
- hipchat "#{organization}#{current_user} created node #{object_name}"
96
+ node_gist = object_gist("node", "#{object_name}", object_difference) if config.gist and !object_difference.empty?
97
+ hipchat "#{organization}#{current_user} created node #{object_name} #{node_gist}"
80
98
  end
81
99
 
82
100
  def after_nodefromfile
83
- hipchat "#{organization}#{current_user} uploaded node #{object_name}"
101
+ node_gist = object_gist("node", "#{object_name}", object_difference) if config.gist and !object_difference.empty?
102
+ hipchat "#{organization}#{current_user} uploaded node #{object_name} #{node_gist}"
84
103
  end
85
104
 
86
105
  def after_noderunlistadd
87
- hipchat "#{organization}#{current_user} added run_list items to #{object_name}: #{object_secondary_name}"
106
+ node_gist = object_gist("node", "#{object_name}", object_difference) if config.gist and !object_difference.empty?
107
+ hipchat "#{organization}#{current_user} added run_list items to #{object_name}: #{object_secondary_name} #{node_gist}"
88
108
  end
89
109
 
90
110
  def after_noderunlistremove
91
- hipchat "#{organization}#{current_user} removed run_list items from #{object_name}: #{object_secondary_name}"
111
+ node_gist = object_gist("node", "#{object_name}", object_difference) if config.gist and !object_difference.empty?
112
+ hipchat "#{organization}#{current_user} removed run_list items from #{object_name}: #{object_secondary_name} #{node_gist}"
92
113
  end
93
114
 
94
115
  def after_noderunlistset
95
- hipchat "#{organization}#{current_user} set the run_list for #{object_name} to #{object_secondary_name}"
116
+ node_gist = object_gist("node", "#{object_name}", object_difference) if config.gist and !object_difference.empty?
117
+ hipchat "#{organization}#{current_user} set the run_list for #{object_name} to #{object_secondary_name} #{node_gist}"
96
118
  end
97
119
 
98
120
 
@@ -111,6 +133,18 @@ module KnifeSpork
111
133
  end
112
134
  end
113
135
 
136
+ def env_gist(environment, diff)
137
+ msg = "Environment #{environment} uploaded at #{Time.now.getutc} by #{current_user}\n\nConstraints updated on server in this version:\n\n#{diff.collect { |k, v| "#{k}: #{v}\n" }.join}"
138
+ link = %x[ echo "#{msg}" | #{config.gist}]
139
+ return "<a href=\"#{link}\">Diff</a>" if !link.nil? || !link.empty?
140
+ end
141
+
142
+ def object_gist(object_type, object_name, object_diff)
143
+ msg = "#{object_type.capitalize} #{object_name} changed at #{Time.now.getutc} by #{current_user}\n\nDiff is as follows:\n\n#{object_diff}"
144
+ link = %x[ echo "#{msg}" | #{config.gist}]
145
+ return "<a href=\"#{link}\">Diff</a>" if !link.nil? || !link.empty?
146
+ end
147
+
114
148
  def rooms
115
149
  [ config.room || config.rooms ].flatten
116
150
  end
@@ -0,0 +1,28 @@
1
+ require 'knife-spork/plugins/plugin'
2
+
3
+ module KnifeSpork
4
+ module Plugins
5
+ class Influxdb < Plugin
6
+ name :influxdb
7
+ hooks :after_upload
8
+
9
+ def perform
10
+ safe_require 'influxdb'
11
+ conn = InfluxDB::Client.new(config.database, host: config.host, port: config.port, username: config.username, password: config.password, use_ssl: config.ssl)
12
+ environments.each do |environment|
13
+ begin
14
+ data = {
15
+ user: current_user,
16
+ cookbook: cookbook.name,
17
+ version: cookbook.version
18
+ }
19
+ conn.write_point(config.series, data)
20
+ rescue Exception => e
21
+ ui.error 'Could not write data to influxdb'
22
+ ui.error e.to_s
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -100,7 +100,7 @@ module KnifeSpork
100
100
  def slack(message)
101
101
  safe_require 'slack-notifier'
102
102
  begin
103
- notifier = ::Slack::Notifier.new( config.teamname, config.api_token, channel: channel, username: username, icon_url: config.icon_url)
103
+ notifier = ::Slack::Notifier.new( config.webhook_url, channel: channel, username: username, icon_url: config.icon_url)
104
104
  notifier.ping message
105
105
  rescue Exception => e
106
106
  ui.error 'Something went wrong sending to Slack.'
@@ -3,6 +3,8 @@ require 'diffy'
3
3
  require 'json'
4
4
 
5
5
  require 'chef/cookbook_loader'
6
+ require 'chef/environment'
7
+ require 'chef/data_bag_item'
6
8
  require 'chef/knife/core/object_loader'
7
9
  require 'knife-spork/plugins'
8
10
 
@@ -106,6 +108,19 @@ module KnifeSpork
106
108
  JSON.pretty_generate(json, options.to_hash)
107
109
  end
108
110
 
111
+ def save_environment_changes(environment, json)
112
+ if spork_config[:environment_path]
113
+ environments_path = spork_config[:environment_path]
114
+ else
115
+ split_cb_path = cookbook_path.split("/")
116
+ environments_path = (split_cb_path[0..-2] << split_cb_path[-1].gsub("cookbooks","environments")).join("/")
117
+ end
118
+
119
+ environment_path = File.expand_path( File.join(environments_path, "#{environment}.json") )
120
+
121
+ File.open(environment_path, 'w'){ |f| f.puts(json) }
122
+ end
123
+
109
124
  def valid_version?(version)
110
125
  version_keys = version.split('.')
111
126
  return false unless version_keys.size == 3 && version_keys.any?{ |k| begin Float(k); rescue false; else true; end }
@@ -231,7 +246,7 @@ module KnifeSpork
231
246
  def load_environment_from_file(environment_name)
232
247
  begin
233
248
  environment_loader.object_from_file("#{environment_path}/#{environment_name}.json")
234
- rescue Yajl::ParseError => e
249
+ rescue FFI_Yajl::ParseError => e
235
250
  raise "#{environment_name} environment file has syntactically incorrect json.\n #{e.to_s}"
236
251
  end
237
252
  end
@@ -300,7 +315,7 @@ module KnifeSpork
300
315
  # to be bypassed until #85 has been completed and Berkshelf 3 support added
301
316
  if spork_config.skip_berkshelf
302
317
  ui.warn "Unloading Berkshelf as skip_berkshelf option found in config"
303
- Object.send(:remove_const, :Berkshelf)
318
+ Object.send(:remove_const, :Berkshelf) if defined?(::Berkshelf)
304
319
  end
305
320
  end
306
321
  end
@@ -28,6 +28,7 @@ plugins:
28
28
  - Web Operations
29
29
  notify: true
30
30
  color: yellow
31
+ gist: /usr/bin/gist
31
32
  ```
32
33
 
33
34
  #### server_url
@@ -60,3 +61,9 @@ The color of the message.
60
61
 
61
62
  - Type: `String`
62
63
  - Acceptable Values: `[yellow, red, green, purple, random]`
64
+
65
+ #### gist
66
+ Optional path to gist binary installed by https://rubygems.org/gems/gist
67
+
68
+ - Type: `String`
69
+
@@ -0,0 +1,25 @@
1
+ Influxdb
2
+ ========
3
+
4
+ Annouce influxdb about your chef deployments
5
+
6
+ Gem Requirements
7
+ ----------------
8
+ `gem influxdb`
9
+
10
+ Hooks
11
+ -----
12
+ - `after_upload`
13
+
14
+ Configuration
15
+ -------------
16
+ ```yaml
17
+ plugins:
18
+ influxdb:
19
+ database: deployments
20
+ username: deploy
21
+ password: deploy
22
+ series: deployments
23
+ host: influx.example.com
24
+ port: 8086
25
+ ```
@@ -20,14 +20,14 @@ Configuration
20
20
  ```yaml
21
21
  plugins:
22
22
  slack:
23
- api_token: ABC123
23
+ webhook_url: https://hooks.slack.com/services/AABBCC
24
24
  channel: "#operations"
25
25
  teamname: myteam
26
26
  username: knife
27
27
  ```
28
28
 
29
29
  #### api_token
30
- Your Slack API token.
30
+ Your Slack Webhook URL.
31
31
 
32
32
  - Type: `String`
33
33
 
@@ -36,10 +36,6 @@ The channel to post to.
36
36
 
37
37
  - Type: `String`
38
38
 
39
- #### teamname
40
- The teamname of the slack account. ex. https://TEAMNAME.slack.com
41
-
42
- - Type: `String`
43
39
 
44
40
  #### username
45
41
  The username to post as.
@@ -1,7 +1,8 @@
1
+ name "example"
1
2
  maintainer "Jon Cowie"
2
3
  maintainer_email "jonlives@gmail.com"
3
4
  license "All rights reserved"
4
5
  description "Test cookbook for knife-spork"
5
- long_description "Test cookbook for knife-spork"
6
+ long_description "Test cookbook for knife-spork"
6
7
  version "0.0.1"
7
8
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: knife-spork
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.2
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jon Cowie
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-03 00:00:00.000000000 Z
11
+ date: 2015-01-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -162,6 +162,7 @@ files:
162
162
  - lib/knife-spork/plugins/graphite.rb
163
163
  - lib/knife-spork/plugins/grove.rb
164
164
  - lib/knife-spork/plugins/hipchat.rb
165
+ - lib/knife-spork/plugins/influxdb.rb
165
166
  - lib/knife-spork/plugins/irccat.rb
166
167
  - lib/knife-spork/plugins/jabber.rb
167
168
  - lib/knife-spork/plugins/plugin.rb
@@ -176,6 +177,7 @@ files:
176
177
  - plugins/Graphite.md
177
178
  - plugins/Grove.md
178
179
  - plugins/HipChat.md
180
+ - plugins/Influxdb.md
179
181
  - plugins/Irccat.md
180
182
  - plugins/Jabber.md
181
183
  - plugins/README.md
@@ -230,3 +232,4 @@ test_files:
230
232
  - spec/unit/spork_info_spec.rb
231
233
  - spec/unit/spork_promote_spec.rb
232
234
  - spec/unit/spork_upload_spec.rb
235
+ has_rdoc: