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 +8 -8
- data/.travis.yml +1 -1
- data/CHANGELOG.md +25 -1
- data/README.md +17 -1
- data/Rakefile +2 -2
- data/knife-spork.gemspec +1 -1
- data/lib/chef/knife/spork-bump.rb +17 -18
- data/lib/chef/knife/spork-check.rb +21 -22
- data/lib/chef/knife/spork-databag-create.rb +2 -1
- data/lib/chef/knife/spork-environment-create.rb +17 -0
- data/lib/chef/knife/spork-omni.rb +9 -10
- data/lib/chef/knife/spork-promote.rb +9 -16
- data/lib/chef/knife/spork-role-fromfile.rb +19 -0
- data/lib/chef/knife/spork-upload.rb +6 -7
- data/lib/knife-spork/plugins/hipchat.rb +55 -21
- data/lib/knife-spork/plugins/influxdb.rb +28 -0
- data/lib/knife-spork/plugins/slack.rb +1 -1
- data/lib/knife-spork/runner.rb +17 -2
- data/plugins/HipChat.md +7 -0
- data/plugins/Influxdb.md +25 -0
- data/plugins/Slack.md +2 -6
- data/spec/unit/fixtures/cookbooks/example/metadata.rb +2 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ZjE4NDhiY2I4MTA3YjgyZWFmYWMxNDk0MTc0NmQzMDdiZjVmNDNlOA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NzFjYTlhOWIyMDhhYzVjZDI3Mjg2YWMwNmI1OGFhMzQyMWJmMTY3OQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NmRjNWRkNGQ4YWVkMDZkNjJkZmVkY2VlM2U1MjM3OWFkYTY0ZmNkNzdiMzcw
|
10
|
+
MDRjMzY4YjUyZTgyNDdkNmJjODdkZWM5NmU5YmQ2OTEzNGZiY2E3ZmQxYjE5
|
11
|
+
MjU5MTYxMmQ2MzAzMWIxOGQwMzEwNWQ4NTlmY2IyMGZmOTE5ZjA=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
OTIzMWU3YTViODZmZjUzZWI4ZGQzM2QyYzAyMmZlYzc1YzY2ODU2OTJkNzJj
|
14
|
+
OTU4MWE2NWRhZTRiNDc5NGJlN2FjMGU2MWE1MzljY2RhNWZkODQ0Y2Q5ZjM5
|
15
|
+
ZTZlMzM5Y2I0ZGEyMGVkMmRmNTU5NDcyZDE0ODIwNTRhZmEwMjg=
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -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
|
-
|
25
|
-
|
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
|
data/knife-spork.gemspec
CHANGED
@@ -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.
|
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
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
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
|
-
|
19
|
-
|
18
|
+
:long => "--fail",
|
19
|
+
:description => "If the check fails exit with non-zero exit code"
|
20
20
|
|
21
21
|
option :cookbook_path,
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
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 =
|
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
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
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
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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.
|
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.'
|
data/lib/knife-spork/runner.rb
CHANGED
@@ -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
|
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
|
data/plugins/HipChat.md
CHANGED
@@ -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
|
+
|
data/plugins/Influxdb.md
ADDED
@@ -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
|
+
```
|
data/plugins/Slack.md
CHANGED
@@ -20,14 +20,14 @@ Configuration
|
|
20
20
|
```yaml
|
21
21
|
plugins:
|
22
22
|
slack:
|
23
|
-
|
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
|
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
|
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
|
+
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:
|
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:
|