knife-pkg 0.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +20 -0
- data/.travis.yml +5 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +201 -0
- data/README.md +139 -0
- data/Rakefile +13 -0
- data/knife-pkg.gemspec +26 -0
- data/lib/chef/knife/pkg_base.rb +91 -0
- data/lib/chef/knife/pkg_install_updates.rb +107 -0
- data/lib/chef/knife/pkg_show_updates.rb +100 -0
- data/lib/knife-pkg/controllers/debian.rb +66 -0
- data/lib/knife-pkg/controllers/package_controller.rb +171 -0
- data/lib/knife-pkg/package.rb +42 -0
- data/lib/knife-pkg/shell_command.rb +61 -0
- data/lib/knife-pkg/shell_command_result.rb +43 -0
- data/lib/knife-pkg/user_decision.rb +44 -0
- data/lib/knife-pkg/version.rb +5 -0
- data/lib/knife-pkg.rb +28 -0
- data/spec/controllers/debian_spec.rb +45 -0
- data/spec/controllers/package_controller_spec.rb +28 -0
- data/spec/package_spec.rb +40 -0
- data/spec/spec_helper.rb +7 -0
- metadata +126 -0
@@ -0,0 +1,100 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2013, Holger Amann <holger@fehu.org>
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
|
17
|
+
class Chef
|
18
|
+
class Knife
|
19
|
+
class PkgShowUpdates < PkgBase
|
20
|
+
|
21
|
+
banner 'knife pkg show updates QUERY (options)'
|
22
|
+
|
23
|
+
deps do
|
24
|
+
require 'net/ssh'
|
25
|
+
require 'net/ssh/multi'
|
26
|
+
require 'chef/knife/ssh'
|
27
|
+
require 'knife-pkg'
|
28
|
+
end
|
29
|
+
|
30
|
+
option :attribute,
|
31
|
+
:short => "-a ATTR",
|
32
|
+
:long => "--attribute ATTR",
|
33
|
+
:description => "The attribute to use for opening the connection - default depends on the context",
|
34
|
+
:proc => Proc.new { |key| Chef::Config[:knife][:ssh_attribute] = key.strip }
|
35
|
+
|
36
|
+
option :ssh_user,
|
37
|
+
:short => "-x USERNAME",
|
38
|
+
:long => "--ssh-user USERNAME",
|
39
|
+
:description => "The ssh username"
|
40
|
+
|
41
|
+
option :ssh_password,
|
42
|
+
:short => "-P PASSWORD",
|
43
|
+
:long => "--ssh-password PASSWORD",
|
44
|
+
:description => "The ssh password"
|
45
|
+
|
46
|
+
option :ssh_port,
|
47
|
+
:short => "-p PORT",
|
48
|
+
:long => "--ssh-port PORT",
|
49
|
+
:description => "The ssh port",
|
50
|
+
:proc => Proc.new { |key| Chef::Config[:knife][:ssh_port] = key.strip }
|
51
|
+
|
52
|
+
option :ssh_gateway,
|
53
|
+
:short => "-G GATEWAY",
|
54
|
+
:long => "--ssh-gateway GATEWAY",
|
55
|
+
:description => "The ssh gateway",
|
56
|
+
:proc => Proc.new { |key| Chef::Config[:knife][:ssh_gateway] = key.strip }
|
57
|
+
|
58
|
+
option :forward_agent,
|
59
|
+
:short => "-A",
|
60
|
+
:long => "--forward-agent",
|
61
|
+
:description => "Enable SSH agent forwarding",
|
62
|
+
:boolean => true
|
63
|
+
|
64
|
+
option :identity_file,
|
65
|
+
:short => "-i IDENTITY_FILE",
|
66
|
+
:long => "--identity-file IDENTITY_FILE",
|
67
|
+
:description => "The SSH identity file used for authentication"
|
68
|
+
|
69
|
+
option :host_key_verify,
|
70
|
+
:long => "--[no-]host-key-verify",
|
71
|
+
:description => "Verify host key, enabled by default.",
|
72
|
+
:boolean => true,
|
73
|
+
:default => true
|
74
|
+
|
75
|
+
option :sudo_required,
|
76
|
+
:short => "-z",
|
77
|
+
:long => "--sudo-required",
|
78
|
+
:description => "Use sudo",
|
79
|
+
:boolean => true,
|
80
|
+
:default => false
|
81
|
+
|
82
|
+
option :pkg_verbose,
|
83
|
+
:short => "-l",
|
84
|
+
:long => "--pkg-verbose",
|
85
|
+
:description => "More verbose output for package related things",
|
86
|
+
:boolean => true,
|
87
|
+
:default => false
|
88
|
+
|
89
|
+
|
90
|
+
def run
|
91
|
+
super
|
92
|
+
end
|
93
|
+
|
94
|
+
def process(node, session)
|
95
|
+
ui.info("===> " + extract_nested_value(node, config[:attribute]))
|
96
|
+
::Knife::Pkg::PackageController.available_updates(node, session, pkg_options)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2013, Holger Amann <holger@fehu.org>
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
|
17
|
+
require 'knife-pkg'
|
18
|
+
|
19
|
+
module Knife
|
20
|
+
module Pkg
|
21
|
+
class DebianPackageController < PackageController
|
22
|
+
|
23
|
+
def initialize(node, session, opts = {})
|
24
|
+
super(node, session, opts)
|
25
|
+
end
|
26
|
+
|
27
|
+
def update_pkg_cache
|
28
|
+
ShellCommand.exec("#{sudo}apt-get update", @session)
|
29
|
+
end
|
30
|
+
|
31
|
+
def last_pkg_cache_update
|
32
|
+
result = ShellCommand.exec("stat -c %y /var/lib/apt/periodic/update-success-stamp", @session)
|
33
|
+
Time.parse(result.stdout.chomp)
|
34
|
+
end
|
35
|
+
|
36
|
+
def installed_version(package)
|
37
|
+
ShellCommand.exec("dpkg -p #{package.name} | grep -i Version: | awk '{print $2}'", @session).stdout.chomp
|
38
|
+
end
|
39
|
+
|
40
|
+
def available_updates
|
41
|
+
packages = Array.new
|
42
|
+
if !update_notifier_installed?
|
43
|
+
raise RuntimeError, "Gna!! No update-notifier(-common) installed!? Go ahead, install it and come back!"
|
44
|
+
else
|
45
|
+
result = ShellCommand.exec("#{sudo}/usr/lib/update-notifier/apt_check.py -p", @session)
|
46
|
+
result.stderr.split("\n").each do |item|
|
47
|
+
package = Package.new(item)
|
48
|
+
package.version = installed_version(package)
|
49
|
+
packages << package
|
50
|
+
end
|
51
|
+
end
|
52
|
+
packages
|
53
|
+
end
|
54
|
+
|
55
|
+
def update_package!(package)
|
56
|
+
cmd_string = "#{sudo} DEBIAN_FRONTEND=noninteractive apt-get install #{package.name} -y -o Dpkg::Options::='--force-confold'"
|
57
|
+
cmd_string += " -s" if @options[:dry_run]
|
58
|
+
ShellCommand.exec(cmd_string, @session)
|
59
|
+
end
|
60
|
+
|
61
|
+
def update_notifier_installed?
|
62
|
+
ShellCommand.exec("dpkg-query -W update-notifier-common 2>/dev/null || echo 'false'", @session).stdout.chomp != 'false'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2013, Holger Amann <holger@fehu.org>
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
|
17
|
+
require 'knife-pkg'
|
18
|
+
require 'chef/knife'
|
19
|
+
|
20
|
+
module Knife
|
21
|
+
module Pkg
|
22
|
+
class PackageController
|
23
|
+
|
24
|
+
attr_accessor :node
|
25
|
+
attr_accessor :session
|
26
|
+
attr_accessor :options
|
27
|
+
attr_accessor :ui
|
28
|
+
|
29
|
+
def initialize(node, session, opts = {})
|
30
|
+
@node = node
|
31
|
+
@session = session
|
32
|
+
@options = opts
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.ui
|
36
|
+
@ui ||= Chef::Knife::UI.new(STDOUT, STDERR, STDIN, {})
|
37
|
+
end
|
38
|
+
|
39
|
+
def sudo
|
40
|
+
@options[:sudo] ? 'sudo ' : ''
|
41
|
+
end
|
42
|
+
|
43
|
+
## ++ methods to implement
|
44
|
+
|
45
|
+
# update the package cache
|
46
|
+
# e.g apt-get update
|
47
|
+
def update_pkg_cache
|
48
|
+
raise NotImplementedError
|
49
|
+
end
|
50
|
+
|
51
|
+
# returns the `Time` of the last package cache update
|
52
|
+
def last_pkg_cache_update
|
53
|
+
raise NotImplementedError
|
54
|
+
end
|
55
|
+
|
56
|
+
# returns the version string of the installed package
|
57
|
+
def installed_version(package)
|
58
|
+
raise NotImplementedError
|
59
|
+
end
|
60
|
+
|
61
|
+
# returns an `Array` of all available updates
|
62
|
+
def available_updates
|
63
|
+
raise NotImplementedError
|
64
|
+
end
|
65
|
+
|
66
|
+
# updates a package
|
67
|
+
# should only execute a 'dry-run' if @options[:dry_run] is set
|
68
|
+
# returns a ShellCommandResult
|
69
|
+
def update_package!(package)
|
70
|
+
raise NotImplementedError
|
71
|
+
end
|
72
|
+
|
73
|
+
## ++ methods to implement
|
74
|
+
|
75
|
+
|
76
|
+
def update_package_verbose!(package)
|
77
|
+
result = update_package!(package)
|
78
|
+
if @options[:dry_run] || @options[:verbose]
|
79
|
+
ui.info(result.stdout)
|
80
|
+
ui.error(result.stderr)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def try_update_pkg_cache
|
85
|
+
if Time.now - last_pkg_cache_update > 86400 # 24 hours
|
86
|
+
@ui.info("Updating package cache...")
|
87
|
+
update_pkg_cache
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def update_dialog(packages)
|
92
|
+
return if packages.count == 0
|
93
|
+
|
94
|
+
ui.info("\tThe following updates are available:") if packages.count > 0
|
95
|
+
packages.each do |package|
|
96
|
+
ui.info(ui.color("\t" + package.to_s, :yellow))
|
97
|
+
end
|
98
|
+
|
99
|
+
if UserDecision.yes?("\tDo you want to update all packages? [y|n]: ")
|
100
|
+
ui.info("\tupdating...")
|
101
|
+
packages.each do |p|
|
102
|
+
update_package_verbose!(p)
|
103
|
+
end
|
104
|
+
ui.info("\tall packages updated!")
|
105
|
+
else
|
106
|
+
packages.each do |package|
|
107
|
+
if UserDecision.yes?("\tDo you want to update #{package}? [y|n]: ")
|
108
|
+
result = update_package_verbose!(package)
|
109
|
+
ui.info("\t#{package} updated!")
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.list_available_updates(updates)
|
116
|
+
updates.each do |update|
|
117
|
+
ui.info(ui.color("\t" + update.to_s, :yellow))
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def self.update!(node, session, packages, opts)
|
122
|
+
ctrl = self.init_controller(node, session, opts)
|
123
|
+
|
124
|
+
auto_updates = packages.map { |u| Package.new(u) }
|
125
|
+
updates_for_dialog = Array.new
|
126
|
+
|
127
|
+
ctrl.try_update_pkg_cache
|
128
|
+
available_updates = ctrl.available_updates
|
129
|
+
|
130
|
+
available_updates.each do |avail|
|
131
|
+
if auto_updates.select { |p| p.name == avail.name }.count == 0
|
132
|
+
updates_for_dialog << avail
|
133
|
+
else
|
134
|
+
ui.info("\tUpdating #{avail.to_s}")
|
135
|
+
ctrl.update_package_verbose!(avail)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
ctrl.update_dialog(updates_for_dialog)
|
140
|
+
end
|
141
|
+
|
142
|
+
def self.available_updates(node, session, opts = {})
|
143
|
+
ctrl = self.init_controller(node, session, opts)
|
144
|
+
ctrl.try_update_pkg_cache
|
145
|
+
updates = ctrl.available_updates
|
146
|
+
list_available_updates(updates)
|
147
|
+
end
|
148
|
+
|
149
|
+
def self.init_controller(node, session, opts)
|
150
|
+
begin
|
151
|
+
ctrl_name = self.controller_name(node.platform)
|
152
|
+
require File.join(File.dirname(__FILE__), ctrl_name)
|
153
|
+
rescue LoadError
|
154
|
+
raise NotImplementedError, "I'm sorry, but #{node.platform} is not supported!"
|
155
|
+
end
|
156
|
+
ctrl = Object.const_get('Knife').const_get('Pkg').const_get("#{ctrl_name.capitalize}PackageController").new(node, session, opts)
|
157
|
+
ctrl.ui = self.ui
|
158
|
+
ctrl
|
159
|
+
end
|
160
|
+
|
161
|
+
def self.controller_name(platform)
|
162
|
+
case platform
|
163
|
+
when 'debian', 'ubuntu'
|
164
|
+
'debian'
|
165
|
+
else
|
166
|
+
platform
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2013, Holger Amann <holger@fehu.org>
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
|
17
|
+
require 'knife-pkg'
|
18
|
+
|
19
|
+
module Knife
|
20
|
+
module Pkg
|
21
|
+
class Package
|
22
|
+
attr_accessor :name, :version
|
23
|
+
|
24
|
+
def initialize(name, version = '0.0')
|
25
|
+
@name = name.strip
|
26
|
+
@version = version
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_s
|
30
|
+
@name + (version_to_s == '' ? '' : " #{version_to_s}")
|
31
|
+
end
|
32
|
+
|
33
|
+
def version_to_s
|
34
|
+
if @version.to_s != '0.0'
|
35
|
+
"(#{@version})"
|
36
|
+
else
|
37
|
+
''
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2013, Holger Amann <holger@fehu.org>
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
|
17
|
+
module Knife
|
18
|
+
module Pkg
|
19
|
+
class ShellCommand
|
20
|
+
|
21
|
+
def self.exec(cmd, session)
|
22
|
+
|
23
|
+
stdout_data, stderr_data = "", ""
|
24
|
+
exit_code, exit_signal = nil, nil
|
25
|
+
session.open_channel do |channel|
|
26
|
+
channel.exec(cmd) do |_, success|
|
27
|
+
raise RuntimeError, "Command \"#{@cmd}\" could not be executed!" if !success
|
28
|
+
|
29
|
+
channel.on_data do |_, data|
|
30
|
+
stdout_data += data
|
31
|
+
end
|
32
|
+
|
33
|
+
channel.on_extended_data do |_,_,data|
|
34
|
+
stderr_data += data
|
35
|
+
end
|
36
|
+
|
37
|
+
channel.on_request("exit-status") do |_,data|
|
38
|
+
exit_code = data.read_long
|
39
|
+
end
|
40
|
+
|
41
|
+
channel.on_request("exit-signal") do |_, data|
|
42
|
+
exit_signal = data.read_long
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
session.loop
|
47
|
+
|
48
|
+
result = ShellCommandResult.new(cmd, stdout_data, stderr_data, exit_code.to_i)
|
49
|
+
|
50
|
+
raise_error!(result) unless result.succeeded?
|
51
|
+
|
52
|
+
return result
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.raise_error!(result)
|
56
|
+
raise RuntimeError, "Command failed! #{result.to_s}"
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2013, Holger Amann <holger@fehu.org>
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
|
17
|
+
module Knife
|
18
|
+
module Pkg
|
19
|
+
class ShellCommandResult
|
20
|
+
|
21
|
+
attr_accessor :cmd
|
22
|
+
attr_accessor :stdout
|
23
|
+
attr_accessor :stderr
|
24
|
+
attr_accessor :exit_code
|
25
|
+
|
26
|
+
def initialize(cmd, stdout, stderr, exit_code)
|
27
|
+
@cmd = cmd
|
28
|
+
@stdout = stdout
|
29
|
+
@stderr = stderr
|
30
|
+
@exit_code = exit_code
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_s
|
34
|
+
return "Command: \"#{@cmd}\", stdout: \"#{@stdout}\", stderr: \"#{@stderr}\", exit_code: \"#{@exit_code}\""
|
35
|
+
end
|
36
|
+
|
37
|
+
def succeeded?
|
38
|
+
return @exit_code.to_i == 0 ? true : false
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2013, Holger Amann <holger@fehu.org>
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
|
17
|
+
require 'chef/knife'
|
18
|
+
|
19
|
+
module Knife
|
20
|
+
module Pkg
|
21
|
+
class UserDecision
|
22
|
+
|
23
|
+
def self.ui
|
24
|
+
@ui ||= Chef::Knife::UI.new(STDOUT, STDERR, STDIN, {})
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.yes?(text)
|
28
|
+
decision = false
|
29
|
+
while true
|
30
|
+
response = ui.ask_question("#{text}", :default => false)
|
31
|
+
case response
|
32
|
+
when 'y'
|
33
|
+
decision = true
|
34
|
+
break
|
35
|
+
when 'n'
|
36
|
+
decision = false
|
37
|
+
break
|
38
|
+
end
|
39
|
+
end
|
40
|
+
decision
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/knife-pkg.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2013, Holger Amann <holger@fehu.org>
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
|
17
|
+
require 'knife-pkg/version'
|
18
|
+
require 'knife-pkg/package'
|
19
|
+
require 'knife-pkg/shell_command'
|
20
|
+
require 'knife-pkg/shell_command_result'
|
21
|
+
require 'knife-pkg/user_decision'
|
22
|
+
require 'knife-pkg/controllers/package_controller'
|
23
|
+
|
24
|
+
module Knife
|
25
|
+
module Pkg
|
26
|
+
# Your code goes here...
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'knife-pkg'
|
2
|
+
require 'knife-pkg/controllers/debian'
|
3
|
+
|
4
|
+
include Knife::Pkg
|
5
|
+
|
6
|
+
describe 'DebianPackageController' do
|
7
|
+
describe '#new' do
|
8
|
+
it 'should create an instance of DebianPkgCtrl' do
|
9
|
+
p = DebianPackageController.new('a', 'b', :h => 1)
|
10
|
+
expect(p).to be_an_instance_of(DebianPackageController)
|
11
|
+
expect(p.node).to eq('a')
|
12
|
+
expect(p.session).to eq('b')
|
13
|
+
expect(p.options).to eq(:h => 1)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "#last_pkg_cache_update" do
|
18
|
+
it 'should return a time object' do
|
19
|
+
t = Time.now
|
20
|
+
result = ShellCommandResult.new(nil,"2013-10-07 09:58:34.000000000 +0200\n",nil,nil)
|
21
|
+
ShellCommand.stub(:exec).and_return(result)
|
22
|
+
|
23
|
+
p = DebianPackageController.new(nil, nil)
|
24
|
+
expect(p.last_pkg_cache_update).to be_an_instance_of Time
|
25
|
+
expect(p.last_pkg_cache_update).to eq(Time.parse("2013-10-07 09:58:34.000000000 +0200"))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "#available_updates" do
|
30
|
+
it 'should raise an error if update-notifier is not installed' do
|
31
|
+
p = DebianPackageController.new(nil, nil)
|
32
|
+
p.stub(:update_notifier_installed?).and_return(false)
|
33
|
+
expect{p.available_updates}.to raise_error(/update-notifier/)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should return an array' do
|
37
|
+
result = ShellCommandResult.new(nil, nil, "1\n2\n3", nil)
|
38
|
+
ShellCommand.stub(:exec).and_return(result)
|
39
|
+
p = DebianPackageController.new(nil, nil)
|
40
|
+
p.stub(:update_notifier_installed?).and_return(true)
|
41
|
+
p.stub(:installed_version).and_return("1.0.0")
|
42
|
+
expect(p.available_updates).to be_an_instance_of Array
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'knife-pkg'
|
2
|
+
|
3
|
+
include Knife::Pkg
|
4
|
+
|
5
|
+
describe 'PackageController' do
|
6
|
+
describe '#new' do
|
7
|
+
end
|
8
|
+
|
9
|
+
describe '#sudo' do
|
10
|
+
it 'should return sudo prefix' do
|
11
|
+
p = PackageController.new(nil, nil, :sudo => true)
|
12
|
+
expect(p.sudo).to eq("sudo ")
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should return no sudo prefix' do
|
16
|
+
p = PackageController.new(nil, nil)
|
17
|
+
expect(p.sudo).to eq("")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '.init_controller' do
|
22
|
+
it 'should initialize the right package controller' do
|
23
|
+
FakeNode = Struct.new(:platform)
|
24
|
+
node = FakeNode.new("debian")
|
25
|
+
PackageController.init_controller(node, nil, nil)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'knife-pkg'
|
2
|
+
|
3
|
+
include Knife::Pkg
|
4
|
+
|
5
|
+
describe 'Package' do
|
6
|
+
describe '#new' do
|
7
|
+
it 'should create an instance of Package' do
|
8
|
+
p = Package.new('test')
|
9
|
+
expect(p).to be_an_instance_of Package
|
10
|
+
expect(p.version).to eq('0.0')
|
11
|
+
expect(p.name).to eq('test')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#version_to_s' do
|
16
|
+
it 'should return the version' do
|
17
|
+
p = Package.new('', '0.0.1')
|
18
|
+
expect(p.version_to_s).to eq('(0.0.1)')
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should return an empty string if version is not defined' do
|
22
|
+
p = Package.new('')
|
23
|
+
expect(p.version_to_s).to eq('')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#to_s' do
|
28
|
+
it 'should return package name with version' do
|
29
|
+
p = Package.new('test','0.0.1')
|
30
|
+
expect(p.to_s).to eq('test (0.0.1)')
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should return package without version' do
|
34
|
+
p = Package.new('test')
|
35
|
+
expect(p.to_s).to eq('test')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
end
|