vagrant-box-updater 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +30 -24
- data/lib/vagrant-box-updater/action/add_box.rb +8 -17
- data/lib/vagrant-box-updater/action/up_box.rb +66 -54
- data/lib/vagrant-box-updater/plugin.rb +9 -3
- data/lib/vagrant-box-updater/util/common.rb +76 -0
- data/lib/vagrant-box-updater/version.rb +1 -1
- data/out.txt +40 -0
- data/vagrant-box-updater.gemspec +2 -2
- metadata +6 -4
data/README.md
CHANGED
@@ -1,46 +1,52 @@
|
|
1
1
|
# vagrant-box-updater
|
2
2
|
|
3
|
-
|
3
|
+
Vagrant 1.1+ plugin to detect changes to a remote box's creation date,
|
4
|
+
and perform an interactive update if desired.
|
4
5
|
|
5
|
-
|
6
|
+
By default Vagrant just store box images locally and never checks if
|
7
|
+
there are updates for that image. Users may therefore end up working
|
8
|
+
with outdated boxes.
|
6
9
|
|
7
|
-
|
10
|
+
This plugin hooks into `vagrant box add` and `vagrant up`, saving
|
11
|
+
details about each box sources creation date, and optioning performing
|
12
|
+
an update when a change is detected.
|
8
13
|
|
14
|
+
## Installation
|
9
15
|
|
10
|
-
|
16
|
+
vagrant plugin install vagrant-box-updater
|
11
17
|
|
12
|
-
|
18
|
+
## Usage
|
13
19
|
|
14
|
-
|
15
|
-
|
16
|
-
|
20
|
+
After plugin installed it's recommended to re-add box images so that the
|
21
|
+
plugin can collect necessary information about the box.
|
17
22
|
|
18
|
-
|
23
|
+
vagrant box add --force <source_uri>
|
19
24
|
|
20
|
-
|
25
|
+
To disable the plugin for a project:
|
21
26
|
|
22
|
-
|
27
|
+
```ruby
|
28
|
+
Vagrant.configure("2") do |config|
|
29
|
+
config.vm.box = "precise64"
|
30
|
+
config.vm.box_url = "http://files.vagrantup.com/precise64.box"
|
23
31
|
|
24
|
-
|
32
|
+
config.box_updater.disable = true
|
25
33
|
|
26
|
-
|
34
|
+
// ...
|
27
35
|
|
28
|
-
|
29
|
-
|
30
|
-
3. install plugin to vagrant environment "sudo vagrant plugin install pkg/vagrant-box-updater-0.0.1.gem"
|
36
|
+
end
|
37
|
+
```
|
31
38
|
|
32
|
-
##
|
33
|
-
|
34
|
-
After plugin installed it's recommended to re-add box images (vagrant box add -f ) so plugin can collect necessary information about box (such as source url and creation timestamp).
|
39
|
+
## Install from source (Advanced)
|
35
40
|
|
36
|
-
|
41
|
+
1. Clone project
|
42
|
+
2. Create a gem file: `rake build`
|
43
|
+
3. Install local gem: `vagrant plugin install pkg/vagrant-box-updater-0.0.1.gem`
|
37
44
|
|
38
|
-
config.box_updater.disable = true
|
39
45
|
|
40
46
|
## Contributing
|
41
47
|
|
42
48
|
1. Fork it
|
43
|
-
2. Create your feature branch
|
44
|
-
3. Commit your changes
|
45
|
-
4. Push to the branch
|
49
|
+
2. Create your feature branch: `git checkout -b my-new-feature`
|
50
|
+
3. Commit your changes: `git commit -am 'Add some feature'`
|
51
|
+
4. Push to the branch: `git push origin my-new-feature`
|
46
52
|
5. Create new Pull Request
|
@@ -1,4 +1,7 @@
|
|
1
1
|
require 'yaml'
|
2
|
+
require 'net/http'
|
3
|
+
require 'uri'
|
4
|
+
require 'vagrant-box-updater/util/common'
|
2
5
|
|
3
6
|
module VagrantPlugins
|
4
7
|
module BoxUpdater
|
@@ -12,32 +15,20 @@ module VagrantPlugins
|
|
12
15
|
def call(env)
|
13
16
|
box_url = env[:box_url]
|
14
17
|
box_name = env[:box_name]
|
15
|
-
|
16
18
|
begin
|
17
|
-
|
19
|
+
modification_attribute = Util::Common.get_modification_attribute(box_url)
|
18
20
|
rescue
|
19
21
|
env[:ui].error("Unable access: #{box_url}")
|
20
22
|
env[:ui].error("Can not collect image status, please check box url and repeat action")
|
21
23
|
@app.call(env)
|
22
24
|
return 0
|
23
25
|
end
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
stat_file = env[:home_path].join(box_name + ".stat")
|
28
|
-
File.open(stat_file, 'w+') {|f| f.write(@box_attributes.to_yaml) }
|
26
|
+
@box_attributes = {"url" => box_url}.merge(modification_attribute)
|
27
|
+
path_box_stat_file = Util::Common.get_path_box_stat_file(env, box_name)
|
28
|
+
Util::Common.save_box_stats(path_box_stat_file, @box_attributes)
|
29
29
|
@app.call(env)
|
30
30
|
end
|
31
|
-
|
32
|
-
def get_remote_modification_date?(url)
|
33
|
-
require 'open-uri'
|
34
|
-
require 'net/http'
|
35
|
-
url = URI.parse(url)
|
36
|
-
Net::HTTP.start(url.host, url.port) do |http|
|
37
|
-
response = http.head(url.request_uri)
|
38
|
-
return response['Last-Modified']
|
39
|
-
end
|
40
|
-
end
|
31
|
+
|
41
32
|
|
42
33
|
end
|
43
34
|
end
|
@@ -1,4 +1,7 @@
|
|
1
1
|
require 'yaml'
|
2
|
+
require 'net/http'
|
3
|
+
require 'uri'
|
4
|
+
require 'vagrant-box-updater/util/common'
|
2
5
|
|
3
6
|
module VagrantPlugins
|
4
7
|
module BoxUpdater
|
@@ -13,6 +16,7 @@ module VagrantPlugins
|
|
13
16
|
require 'time'
|
14
17
|
box_name = env[:machine].config.vm.box
|
15
18
|
box_url = env[:machine].config.vm.box_url
|
19
|
+
path_box_stat_file = Util::Common.get_path_box_stat_file(env, box_name)
|
16
20
|
|
17
21
|
disable_plugin_flag = env[:machine].config.box_updater.disable
|
18
22
|
if disable_plugin_flag == true
|
@@ -20,26 +24,38 @@ module VagrantPlugins
|
|
20
24
|
@app.call(env)
|
21
25
|
return 0
|
22
26
|
end
|
23
|
-
|
27
|
+
|
24
28
|
stat_file = env[:home_path].join(box_name + ".stat")
|
25
29
|
|
26
30
|
# Create empty stat file if missing
|
27
31
|
if !File.file?(stat_file)
|
28
32
|
env[:ui].info("Local stat file not found: #{stat_file}")
|
29
33
|
@box_attributes = {"modification_date" => nil, "url" => box_url}
|
30
|
-
|
31
|
-
File.open(stat_file, 'w+') {|f| f.write(@box_attributes.to_yaml) }
|
34
|
+
Util::Common.save_box_stats(path_box_stat_file, @box_attributes)
|
32
35
|
end
|
33
36
|
|
34
37
|
box_stats = YAML.load_file(stat_file)
|
35
38
|
|
36
|
-
present_modification_date = box_stats["modification_date"]
|
37
39
|
box_url = box_stats["url"]
|
38
40
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
41
|
+
current_modification_date = box_stats["Last-Modified"]
|
42
|
+
# "Etag" attribute is not in use - but we may use it in future
|
43
|
+
# What we trying to achieve : some public resources such as github.com does not provide "Last-Modified"
|
44
|
+
# but "Etag" id, so optionally we may need number of generic methods to decide if object modified
|
45
|
+
current_modification_etag = box_stats["Etag"]
|
46
|
+
|
47
|
+
if current_modification_date == nil and current_modification_etag != nil
|
48
|
+
env[:ui].warn("Not enough data to decide whether image need to be updated")
|
49
|
+
env[:ui].warn("Remote server does not provide \"Last-Modified\" field in the header but \"Etag\" which is not supported at the moment")
|
50
|
+
env[:ui].warn("This is known issue for some websites (like github.com)")
|
51
|
+
env[:ui].warn("If you want to have this functionality added, please, fire feature request on oficial plugin page on github")
|
52
|
+
@app.call(env)
|
53
|
+
return 0
|
54
|
+
end
|
55
|
+
|
56
|
+
if current_modification_date == nil
|
57
|
+
env[:ui].warn("Not enough data to decide whether image need to be updated")
|
58
|
+
env[:ui].warn("Please, add box again \"vagrant box add -f\" so it'll update image data")
|
43
59
|
@app.call(env)
|
44
60
|
return 0
|
45
61
|
end
|
@@ -47,53 +63,59 @@ module VagrantPlugins
|
|
47
63
|
if box_url == nil
|
48
64
|
env[:ui].warn("Local box url is not set")
|
49
65
|
env[:ui].warn("Unable to check remote box")
|
50
|
-
env[:ui].warn("Please, add box again \"vagrant box add\" so it'll update image data")
|
66
|
+
env[:ui].warn("Please, add box again \"vagrant box add -f\" so it'll update image data")
|
51
67
|
@app.call(env)
|
52
68
|
return 0
|
53
69
|
end
|
54
70
|
|
55
71
|
begin
|
56
|
-
|
57
|
-
|
72
|
+
env[:ui].info("Verify remote image data: #{box_url}")
|
73
|
+
remote_modification_attribute = Util::Common.get_modification_attribute(box_url)
|
58
74
|
rescue
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
end
|
64
|
-
|
65
|
-
if remote_modification_date == nil
|
66
|
-
env[:ui].warn("Can not retrieve 'Last-Modified' attribute for: #{box_url}")
|
67
|
-
env[:ui].warn("Skip remote box check")
|
68
|
-
@app.call(env)
|
69
|
-
return 0
|
75
|
+
env[:ui].warn("Unable access: #{box_url}")
|
76
|
+
env[:ui].warn("Skip remote box check")
|
77
|
+
@app.call(env)
|
78
|
+
return 0
|
70
79
|
end
|
71
80
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
env[:ui].info("Remote box timestamp #{remote_modification_timestamp}")
|
76
|
-
env[:ui].info("Local box timestamp #{present_modification_timestamp}")
|
77
|
-
|
78
|
-
if present_modification_timestamp < remote_modification_timestamp
|
79
|
-
env[:ui].warn("Updated image detected!!!!")
|
80
|
-
if ask_confirm(env,"Would you like to update the box? (Y/N)")
|
81
|
-
env[:ui].info("Going to update and replace box \"#{box_name}\" now!")
|
82
|
-
provider = nil
|
83
|
-
env[:action_runner].run(Vagrant::Action.action_box_add, {
|
84
|
-
:box_name => box_name,
|
85
|
-
:box_provider => provider,
|
86
|
-
:box_url => box_url,
|
87
|
-
:box_force => true,
|
88
|
-
:box_download_insecure => true,
|
89
|
-
})
|
90
|
-
else
|
91
|
-
env[:ui].warn("Update disabled")
|
81
|
+
if remote_modification_attribute['Last-Modified'] == nil
|
82
|
+
env[:ui].warn("Can not retrieve any useful data for: #{box_url}")
|
83
|
+
env[:ui].warn("Skip remote box check")
|
92
84
|
@app.call(env)
|
93
|
-
|
85
|
+
return 0
|
86
|
+
end
|
87
|
+
remote_modification_timestamp = remote_modification_attribute['Last-Modified'].is_a?(Time) ? remote_modification_attribute['Last-Modified'] : Time.parse(remote_modification_attribute['Last-Modified'])
|
88
|
+
current_modification_timestamp = current_modification_date.is_a?(Time) ? current_modification_date : Time.parse(current_modification_date)
|
89
|
+
|
90
|
+
#env[:ui].info("Remote box timestamp #{remote_modification_timestamp}")
|
91
|
+
#env[:ui].info("Local box timestamp #{current_modification_timestamp}")
|
92
|
+
|
93
|
+
if current_modification_timestamp.to_i < remote_modification_timestamp.to_i
|
94
|
+
box_stats = Util::Common.read_box_stats(path_box_stat_file, box_name)
|
95
|
+
if box_stats['ignored_image_attribute'] and box_stats['ignored_image_attribute'].to_i == remote_modification_timestamp.to_i
|
96
|
+
env[:ui].warn("Modified image detected, this update set to be ignored until next change")
|
97
|
+
else
|
98
|
+
env[:ui].warn("Modified image detected : #{box_stats['url']} #{remote_modification_attribute}")
|
99
|
+
if ask_confirm(env,"Would you like to update the box? \nIf negative - we keep ignoring this update, and notify only when another update detected. \nType (Y/N)")
|
100
|
+
env[:ui].info("Going to update and replace box \"#{box_name}\" now!")
|
101
|
+
provider = nil
|
102
|
+
env[:action_runner].run(Vagrant::Action.action_box_add, {
|
103
|
+
:box_name => box_name,
|
104
|
+
:box_provider => provider,
|
105
|
+
:box_url => box_url,
|
106
|
+
:box_force => true,
|
107
|
+
:box_download_insecure => true,
|
108
|
+
})
|
109
|
+
else
|
110
|
+
env[:ui].warn("This update will be ignored")
|
111
|
+
Util::Common.add_box_stats(path_box_stat_file, {'ignored_image_attribute' => remote_modification_timestamp})
|
112
|
+
@app.call(env)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
else
|
116
|
+
env[:ui].info("Box is uptodate")
|
94
117
|
end
|
95
118
|
|
96
|
-
env[:ui].info("Box is uptodate")
|
97
119
|
@app.call(env)
|
98
120
|
end
|
99
121
|
|
@@ -111,16 +133,6 @@ module VagrantPlugins
|
|
111
133
|
return result
|
112
134
|
end
|
113
135
|
|
114
|
-
def get_remote_modification_date?(url)
|
115
|
-
require 'open-uri'
|
116
|
-
require 'net/http'
|
117
|
-
url = URI.parse(url)
|
118
|
-
Net::HTTP.start(url.host, url.port) do |http|
|
119
|
-
response = http.head(url.request_uri)
|
120
|
-
return response['Last-Modified']
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
136
|
end
|
125
137
|
end
|
126
138
|
end
|
@@ -9,9 +9,15 @@ module VagrantPlugins
|
|
9
9
|
Config
|
10
10
|
end
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
# action_hook 'do-before-boot' do |hook|
|
13
|
+
# require_relative 'action/up_box'
|
14
|
+
# #hook.after ::Vagrant::Action::Builtin::ConfigValidate, VagrantPlugins::BoxUpdater::Action::UpBox
|
15
|
+
# hook.before Vagrant::Action::Builtin::Provision, VagrantPlugins::BoxUpdater::Action::UpBox
|
16
|
+
# end
|
17
|
+
|
18
|
+
action_hook(:do_before_boot, :machine_action_up) do |hook|
|
19
|
+
require_relative 'action/up_box'
|
20
|
+
hook.prepend(VagrantPlugins::BoxUpdater::Action::UpBox)
|
15
21
|
end
|
16
22
|
|
17
23
|
action_hook 'on_update' do |hook|
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module BoxUpdater
|
3
|
+
module Util
|
4
|
+
class Common
|
5
|
+
|
6
|
+
def self.get_path_box_stat_file(env, box_name)
|
7
|
+
YAML::ENGINE.yamler='syck'
|
8
|
+
stat_file = env[:home_path].join(box_name + ".stat")
|
9
|
+
return stat_file
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.save_box_stats(stat_file, box_attributes)
|
13
|
+
YAML::ENGINE.yamler='syck'
|
14
|
+
File.open(stat_file, 'w+') {|f| f.write(box_attributes.to_yaml) }
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.add_box_stats(stat_file, box_attributes)
|
18
|
+
YAML::ENGINE.yamler='syck'
|
19
|
+
content = YAML.load_file(stat_file)
|
20
|
+
content = content.merge(box_attributes)
|
21
|
+
#env[:ui].info("Save to: #{stat_file}")
|
22
|
+
File.open(stat_file, 'w+') {|f| f.write(content.to_yaml) }
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.read_box_stats(stat_file, box_name)
|
26
|
+
YAML::ENGINE.yamler='syck'
|
27
|
+
content = YAML.load_file(stat_file)
|
28
|
+
return content
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.get_modification_attribute(box_path)
|
32
|
+
if !box_path.start_with? "http"
|
33
|
+
ref_modification_attribute = method(:get_local_file_modification_date?)
|
34
|
+
else
|
35
|
+
ref_modification_attribute = method(:get_url_modification_attribute?)
|
36
|
+
end
|
37
|
+
modification_attribute = ref_modification_attribute.call(box_path)
|
38
|
+
return modification_attribute
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.get_url_modification_attribute?(url)
|
42
|
+
response = fetch_url(url)
|
43
|
+
return { 'Last-Modified' => response['Last-Modified'] } if response['Last-Modified']
|
44
|
+
return { 'Etag' => response['ETag'].delete("\"") } if response['Etag']
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.fetch_url(uri_str, limit = 10)
|
48
|
+
# You should choose better exception.
|
49
|
+
raise ArgumentError, 'HTTP redirect too deep' if limit == 0
|
50
|
+
|
51
|
+
uri = URI.parse(uri_str)
|
52
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
53
|
+
http.use_ssl = (uri.port == 443)
|
54
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
55
|
+
|
56
|
+
#request = Net::HTTP::Get.new(uri.request_uri, { 'User-Agent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.63 Safari/537.31' })
|
57
|
+
#response = Net::HTTP.start(uri.host, uri.port) { |http| http.request(request) }
|
58
|
+
#response = http.request(request)
|
59
|
+
response = http.head(uri.request_uri)
|
60
|
+
case response
|
61
|
+
when Net::HTTPSuccess then response
|
62
|
+
when Net::HTTPRedirection then fetch_url(response['location'], limit - 1)
|
63
|
+
else
|
64
|
+
response.error!
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.get_local_file_modification_date?(url)
|
69
|
+
mtime = File.mtime(url)
|
70
|
+
return { 'Last-Modified' => mtime }
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
data/out.txt
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
HTTP/1.1 302 Found
|
2
|
+
Server: GitHub.com
|
3
|
+
Date: Fri, 07 Jun 2013 21:33:10 GMT
|
4
|
+
Content-Type: text/html; charset=utf-8
|
5
|
+
Connection: keep-alive
|
6
|
+
Status: 302 Found
|
7
|
+
Cache-Control: no-cache
|
8
|
+
X-RateLimit-Limit: 100
|
9
|
+
X-RateLimit-Remaining: 100
|
10
|
+
X-Frame-Options: deny
|
11
|
+
Access-Control-Allow-Origin: https://render.github.com
|
12
|
+
Location: https://raw.github.com/cloudbau/vagrant-openstack-plugin/master/dummy.box
|
13
|
+
X-Runtime: 20
|
14
|
+
Content-Length: 139
|
15
|
+
Vary: Accept-Encoding
|
16
|
+
|
17
|
+
HTTP/1.1 200 OK
|
18
|
+
Date: Fri, 07 Jun 2013 21:33:10 GMT
|
19
|
+
Server: GitHub.com
|
20
|
+
Content-Type: text/plain
|
21
|
+
Status: 200 OK
|
22
|
+
X-RateLimit-Limit: 100
|
23
|
+
X-RateLimit-Remaining: 100
|
24
|
+
X-Frame-Options: deny
|
25
|
+
Access-Control-Allow-Origin: https://render.github.com
|
26
|
+
X-Content-Type-Options: nosniff
|
27
|
+
Content-Disposition: attachment; filename=dummy.box
|
28
|
+
Content-Transfer-Encoding: binary
|
29
|
+
X-Runtime: 13
|
30
|
+
ETag: "bc98c4c9dbf7e8c513544a2615758fec"
|
31
|
+
Content-Length: 685
|
32
|
+
Accept-Ranges: bytes
|
33
|
+
Via: 1.1 varnish
|
34
|
+
Age: 0
|
35
|
+
X-Served-By: cache-a39-AMS
|
36
|
+
X-Cache: MISS
|
37
|
+
X-Cache-Hits: 0
|
38
|
+
Vary: Accept-Encoding
|
39
|
+
Cache-Control: private
|
40
|
+
|
data/vagrant-box-updater.gemspec
CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |gem|
|
|
9
9
|
gem.authors = ["Ruslan Lutsenko"]
|
10
10
|
gem.email = ["ruslan.lutcenko@gmail.com"]
|
11
11
|
gem.description = "vagrant plugin which save details about added box image (image creation timestamp image source path), during start of virtual machine checks the source url of a box image for updates (use 'Last-Modified' header to detect changes), notify user and perform interactive download of the box image if update detected"
|
12
|
-
gem.summary = "
|
13
|
-
gem.homepage = ""
|
12
|
+
gem.summary = "Vagrant plugin to detect and notify on update of remote box images"
|
13
|
+
gem.homepage = "https://github.com/spil-ruslan/vagrant-box-updater"
|
14
14
|
|
15
15
|
#gem.files = `git ls-files`.split($/)
|
16
16
|
#gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vagrant-box-updater
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-06-18 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: vagrant plugin which save details about added box image (image creation
|
15
15
|
timestamp image source path), during start of virtual machine checks the source
|
@@ -23,7 +23,9 @@ extra_rdoc_files: []
|
|
23
23
|
files:
|
24
24
|
- Gemfile
|
25
25
|
- vagrant-box-updater.gemspec
|
26
|
+
- out.txt
|
26
27
|
- lib/vagrant-box-updater/version.rb
|
28
|
+
- lib/vagrant-box-updater/util/common.rb
|
27
29
|
- lib/vagrant-box-updater/action/up_box.rb
|
28
30
|
- lib/vagrant-box-updater/action/add_box.rb
|
29
31
|
- lib/vagrant-box-updater/config.rb
|
@@ -34,7 +36,7 @@ files:
|
|
34
36
|
- LICENSE.txt
|
35
37
|
- README.md
|
36
38
|
- .gitignore
|
37
|
-
homepage:
|
39
|
+
homepage: https://github.com/spil-ruslan/vagrant-box-updater
|
38
40
|
licenses: []
|
39
41
|
post_install_message:
|
40
42
|
rdoc_options: []
|
@@ -57,5 +59,5 @@ rubyforge_project:
|
|
57
59
|
rubygems_version: 1.8.23
|
58
60
|
signing_key:
|
59
61
|
specification_version: 3
|
60
|
-
summary:
|
62
|
+
summary: Vagrant plugin to detect and notify on update of remote box images
|
61
63
|
test_files: []
|