knife-sharp 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -94,6 +94,38 @@ Available servers:
94
94
  dev (/home/jamiez/.chef/knife-dev.rb)
95
95
  </pre>
96
96
 
97
+ ## Rollback
98
+
99
+ Sometimes you need to be able to rollback a change quickly, because failure happens. So knife sharp now creates rollback points of environment constraints.
100
+
101
+ A picture says a thousand words :
102
+
103
+ <pre>
104
+ $ knife sharp rollback --list
105
+ Available rollback points :
106
+ * 1370414322 (Wed Jun 05 08:38:42 +0200 2013)
107
+ * 1370418655 (Wed Jun 05 09:50:55 +0200 2013)
108
+ * 1370419966 (Wed Jun 05 10:12:46 +0200 2013)
109
+ * 1370421569 (Wed Jun 05 10:39:29 +0200 2013)
110
+ $ knife sharp rollback --show 1370421569
111
+ Rollback point has the following informations :
112
+ environment : production
113
+ cookbooks versions :
114
+ * tests => = 0.0.2
115
+ * varnish => = 0.0.10
116
+ $ knife sharp rollback --to 1370421569
117
+ Rollback point has the following informations :
118
+ environment : production
119
+ cookbooks versions :
120
+ * varnish => = 0.0.10
121
+ * tests => = 0.0.2
122
+ Continue rollback ? Y/(N) [N] y
123
+ Setting varnish to version = 0.0.10
124
+ Setting tests to version = 0.0.2
125
+ </pre>
126
+
127
+ The activation of this rollback feature and its storage dir can be configured in your sharp-config.yml file.
128
+
97
129
  # Configuration
98
130
 
99
131
  Dependencies :
@@ -127,6 +159,17 @@ logging:
127
159
 
128
160
  It will log uploads, bumps and databags to the standard logger format.
129
161
 
162
+ # ZSH completion
163
+
164
+ want a completion on changing servers ?
165
+
166
+ <pre>
167
+ alias kss="knife sharp server"
168
+
169
+ function knife_servers { reply=($(ls .chef/knife-*.rb | sed -r 's/.*knife-([a-zA-Z0-9]+)\.rb/\1/' )); }
170
+ compctl -K knife_servers kss
171
+ </pre>
172
+
130
173
  # Credits
131
174
 
132
175
  The damn good knife spork plugin from the etsy folks : https://github.com/jonlives/knife-spork
@@ -139,5 +182,5 @@ License
139
182
 
140
183
  Authors
141
184
  ======
142
- Nicolas Szalay | https://github.com/rottenbytes
143
- Jonathan Amiez | https://github.com/josqu4red
185
+ * Nicolas Szalay | https://github.com/rottenbytes
186
+ * Jonathan Amiez | https://github.com/josqu4red
data/ext/sharp-config.yml CHANGED
@@ -14,3 +14,6 @@ notification:
14
14
  # key is the name of your server (in a knife sharp server sense)
15
15
  sandboxnico:
16
16
  ignore_cookbooks: [ "tests" ]
17
+ rollback:
18
+ enabled: true
19
+ destination: "/home/nico/.chef/sharp/rollbacks/"
@@ -8,7 +8,7 @@ module KnifeSharp
8
8
 
9
9
  [:cookbooks, :databags, :roles].each do |opt|
10
10
  option opt,
11
- :short => "-#{opt.to_s[0].upcase}",
11
+ :short => "-#{opt.to_s[0,1].upcase}",
12
12
  :long => "--#{opt}-only",
13
13
  :description => "sync #{opt} only",
14
14
  :default => false
@@ -187,8 +187,14 @@ module KnifeSharp
187
187
  unless @cookbooks.empty?
188
188
  env = Chef::Environment.load(@environment)
189
189
  cbs = Array.new
190
+ backup_data = Hash.new
191
+ backup_data["environment"] = @environment
192
+ backup_data["cookbook_versions"] = Hash.new
190
193
  @cookbooks.each do |cb_name|
191
194
  cb = @loader[cb_name]
195
+ if @cfg["rollback"]["enabled"] == true
196
+ backup_data["cookbook_versions"][cb_name] = env.cookbook_versions[cb_name]
197
+ end
192
198
  # Force "= a.b.c" in cookbook version, as chef11 will not accept "a.b.c"
193
199
  env.cookbook_versions[cb_name] = "= #{cb.version}"
194
200
  cbs << cb
@@ -204,6 +210,14 @@ module KnifeSharp
204
210
  log_action("bumping #{cb.name} to #{cb.version} for environment #{@environment}")
205
211
  end
206
212
  end
213
+
214
+ if @cfg["rollback"]["enabled"] == true
215
+ identifier = Time.now.to_i
216
+ Dir.mkdir(@cfg["rollback"]["destination"]) unless File.exists?(@cfg["rollback"]["destination"])
217
+ fp = open(File.join(@cfg["rollback"]["destination"], "#{identifier}.json"), "w")
218
+ fp.write(JSON.pretty_generate(backup_data))
219
+ fp.close()
220
+ end
207
221
  end
208
222
  end
209
223
 
@@ -0,0 +1,144 @@
1
+ module KnifeSharp
2
+ class SharpRollback < Chef::Knife
3
+
4
+ banner "knife sharp rollback [--list] [--to <identifier>] [--show <identifier>]"
5
+
6
+ option :list,
7
+ :short => '-l',
8
+ :long => '--list',
9
+ :description => "lists rollback points",
10
+ :default => false
11
+
12
+ option :to,
13
+ :short => "-t",
14
+ :long => "--to",
15
+ :description => "the rollback point identifier",
16
+ :default => nil
17
+
18
+ option :show,
19
+ :short => "-s",
20
+ :long => "--show",
21
+ :description => "show what the rollback point contains",
22
+ :default => false
23
+
24
+ deps do
25
+ require 'chef/cookbook/metadata'
26
+ require 'chef/cookbook_loader'
27
+ require 'chef/cookbook_uploader'
28
+ end
29
+
30
+ def run()
31
+ setup()
32
+
33
+ if config[:list]
34
+ list_rollback_points()
35
+ exit 0
36
+ end
37
+
38
+ if config[:show]
39
+ identifier = name_args
40
+ show_rollback_point(identifier)
41
+ exit 0
42
+ end
43
+
44
+ if config[:to]
45
+ identifier = name_args
46
+ rollback_to(identifier)
47
+ exit 0
48
+ end
49
+ end
50
+
51
+ def setup()
52
+ actions = 0
53
+ [:to, :list, :show].each do |action|
54
+ if config[action]
55
+ actions+=1
56
+ end
57
+ end
58
+
59
+ if actions > 1
60
+ ui.error("please specify only one action")
61
+ exit 1
62
+ end
63
+
64
+
65
+ # Sharp config
66
+ cfg_files = [ "/etc/sharp-config.yml", "~/.chef/sharp-config.yml" ]
67
+ loaded = false
68
+ cfg_files.each do |cfg_file|
69
+ begin
70
+ @cfg = YAML::load_file(File.expand_path(cfg_file))
71
+ loaded = true
72
+ rescue Exception => e
73
+ ui.error "Error on loading config : #{e.inspect}" if config[:verbosity] > 0
74
+ end
75
+ end
76
+ unless loaded == true
77
+ ui.error "config could not be loaded ! Tried the following files : #{cfg_files.join(", ")}"
78
+ exit 1
79
+ end
80
+
81
+ # Knife config
82
+ if Chef::Knife.chef_config_dir && File.exists?(File.join(Chef::Knife.chef_config_dir, "knife.rb"))
83
+ Chef::Config.from_file(File.join(Chef::Knife.chef_config_dir, "knife.rb"))
84
+ else
85
+ ui.error "Cannot find knife.rb config file"
86
+ exit 1
87
+ end
88
+
89
+ chefcfg = Chef::Config
90
+ @cb_path = chefcfg.cookbook_path.is_a?(Array) ? chefcfg.cookbook_path.first : chefcfg.cookbook_path
91
+ @loader = Chef::CookbookLoader.new(@cb_path)
92
+ end
93
+
94
+ def list_rollback_points()
95
+ ui.msg("Available rollback points :")
96
+ Dir.glob(File.join(@cfg["rollback"]["destination"], "*.json")).each do |f|
97
+ ts = File.basename(f, ".json")
98
+ ui.msg(" * #{ts} (#{Time.at(ts.to_i).to_s})")
99
+ end
100
+ exit 0
101
+ end
102
+
103
+ def rollback_to(identifier)
104
+ show_rollback_point(identifier)
105
+ answer = ui.ask_question("Continue rollback ? Y/(N) ", :default => "N").upcase
106
+ if answer != "Y"
107
+ ui.msg("Aborting !")
108
+ exit 0
109
+ end
110
+
111
+ begin
112
+ fp = File.open(File.join(@cfg["rollback"]["destination"],"#{identifier}.json"),"r")
113
+ infos = JSON.load(fp)
114
+ rescue
115
+ ui.error("could not load rollback point #{identifier}")
116
+ exit 1
117
+ end
118
+
119
+ env = Chef::Environment.load(infos["environment"])
120
+ infos["cookbook_versions"].each do |cb, version|
121
+ env.cookbook_versions[cb] = version
122
+ ui.msg("Setting #{cb} to version #{version}")
123
+ end
124
+ env.save
125
+ end
126
+
127
+ def show_rollback_point(identifier)
128
+ begin
129
+ fp = File.open(File.join(@cfg["rollback"]["destination"],"#{identifier}.json"),"r")
130
+ rescue
131
+ ui.error("could not load rollback point #{identifier}")
132
+ exit 1
133
+ end
134
+ infos = JSON.load(fp)
135
+ ui.msg("Rollback point has the following informations :")
136
+ ui.msg(" environment : #{infos["environment"]}")
137
+ ui.msg(" cookbooks versions :")
138
+ infos["cookbook_versions"].each do |cb, version|
139
+ ui.msg(" * #{cb} => #{version}")
140
+ end
141
+ end
142
+
143
+ end
144
+ end
data/lib/knife-sharp.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module KnifeSharp
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
metadata CHANGED
@@ -1,57 +1,66 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: knife-sharp
3
- version: !ruby/object:Gem::Version
4
- version: 0.2.0
3
+ version: !ruby/object:Gem::Version
4
+ hash: 19
5
5
  prerelease:
6
+ segments:
7
+ - 0
8
+ - 3
9
+ - 0
10
+ version: 0.3.0
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - Nicolas Szalay
9
14
  - Jonathan Amiez
10
15
  autorequire:
11
16
  bindir: bin
12
17
  cert_chain: []
13
- date: 2013-04-23 00:00:00.000000000 Z
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
18
+
19
+ date: 2013-06-05 00:00:00 Z
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
16
22
  name: chef
17
- requirement: !ruby/object:Gem::Requirement
18
- none: false
19
- requirements:
20
- - - ! '>='
21
- - !ruby/object:Gem::Version
22
- version: 10.14.0
23
- type: :runtime
24
23
  prerelease: false
25
- version_requirements: !ruby/object:Gem::Requirement
24
+ requirement: &id001 !ruby/object:Gem::Requirement
26
25
  none: false
27
- requirements:
28
- - - ! '>='
29
- - !ruby/object:Gem::Version
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 119
30
+ segments:
31
+ - 10
32
+ - 14
33
+ - 0
30
34
  version: 10.14.0
31
- - !ruby/object:Gem::Dependency
32
- name: grit
33
- requirement: !ruby/object:Gem::Requirement
34
- none: false
35
- requirements:
36
- - - ~>
37
- - !ruby/object:Gem::Version
38
- version: 2.5.0
39
35
  type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: grit
40
39
  prerelease: false
41
- version_requirements: !ruby/object:Gem::Requirement
40
+ requirement: &id002 !ruby/object:Gem::Requirement
42
41
  none: false
43
- requirements:
42
+ requirements:
44
43
  - - ~>
45
- - !ruby/object:Gem::Version
44
+ - !ruby/object:Gem::Version
45
+ hash: 27
46
+ segments:
47
+ - 2
48
+ - 5
49
+ - 0
46
50
  version: 2.5.0
51
+ type: :runtime
52
+ version_requirements: *id002
47
53
  description: Sharpen your knife
48
- email:
54
+ email:
49
55
  - nico@rottenbytes.info
50
56
  - jonathan.amiez@gmail.com
51
57
  executables: []
58
+
52
59
  extensions: []
60
+
53
61
  extra_rdoc_files: []
54
- files:
62
+
63
+ files:
55
64
  - README.md
56
65
  - ext/sharp-config.yml
57
66
  - lib/knife-sharp.rb
@@ -59,28 +68,39 @@ files:
59
68
  - lib/chef/knife/sharp-backup.rb
60
69
  - lib/chef/knife/sharp-history.rb
61
70
  - lib/chef/knife/sharp-server.rb
71
+ - lib/chef/knife/sharp-rollback.rb
62
72
  homepage: https://github.com/Fotolia/knife-sharp
63
73
  licenses: []
74
+
64
75
  post_install_message:
65
76
  rdoc_options: []
66
- require_paths:
77
+
78
+ require_paths:
67
79
  - lib
68
- required_ruby_version: !ruby/object:Gem::Requirement
80
+ required_ruby_version: !ruby/object:Gem::Requirement
69
81
  none: false
70
- requirements:
71
- - - ! '>='
72
- - !ruby/object:Gem::Version
73
- version: '0'
74
- required_rubygems_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ hash: 3
86
+ segments:
87
+ - 0
88
+ version: "0"
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
90
  none: false
76
- requirements:
77
- - - ! '>='
78
- - !ruby/object:Gem::Version
79
- version: '0'
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ hash: 3
95
+ segments:
96
+ - 0
97
+ version: "0"
80
98
  requirements: []
99
+
81
100
  rubyforge_project:
82
- rubygems_version: 1.8.25
101
+ rubygems_version: 1.8.24
83
102
  signing_key:
84
103
  specification_version: 3
85
104
  summary: Knife sharp plugin
86
105
  test_files: []
106
+