knife-pkg 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|