pandler 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +23 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +47 -0
- data/Rakefile +10 -0
- data/Vagrantfile +33 -0
- data/bin/pandle +8 -0
- data/etc/yum/pandler.py +52 -0
- data/lib/pandler.rb +8 -0
- data/lib/pandler/chroot.rb +229 -0
- data/lib/pandler/cli.rb +40 -0
- data/lib/pandler/version.rb +3 -0
- data/lib/pandler/yumfile.rb +26 -0
- data/lib/pandler/yumrepo.rb +240 -0
- data/pandler.gemspec +24 -0
- data/spec/pandler/chroot_spec.rb +93 -0
- data/spec/pandler/cli_spec.rb +20 -0
- data/spec/pandler/yumfile_spec.rb +20 -0
- data/spec/pandler/yumrepo_spec.rb +152 -0
- data/spec/pandler_spec.rb +8 -0
- data/spec/resources/yumrepo/pandler-test-0.0.1-1.x86_64.rpm +0 -0
- data/spec/resources/yumrepo/pandler-test-a-0.0.1-1.x86_64.rpm +0 -0
- data/spec/resources/yumrepo/pandler-test-a-0.0.2-1.x86_64.rpm +0 -0
- data/spec/resources/yumrepo/pandler-test-dep-a-0.0.1-1.x86_64.rpm +0 -0
- data/spec/resources/yumrepo/pandler-test-dep-b-0.0.1-1.x86_64.rpm +0 -0
- data/spec/resources/yumrepo/pandler-test-dep-required-0.0.1-1.x86_64.rpm +0 -0
- data/spec/resources/yumrepo/pandler-test-dep-required-required-0.0.1-1.x86_64.rpm +0 -0
- data/spec/resources/yumrepo/repodata/09267893997a9b34726567132f642093ebd2a4b5e65096a6562efc3a29106723-other.xml.gz +0 -0
- data/spec/resources/yumrepo/repodata/596e9069dad80db19e7ba4c36b3df1e52583231b95bfa61186408c77520a213a-primary.xml.gz +0 -0
- data/spec/resources/yumrepo/repodata/7dd30f881bb1b1cbd723a5fa9d996b96805e25015b56140c99a444bf248c4260-other.sqlite.bz2 +0 -0
- data/spec/resources/yumrepo/repodata/8e6f832a8605163914b5aaf46e42daeaad10f9785d202c6c99c9d903354b3194-filelists.xml.gz +0 -0
- data/spec/resources/yumrepo/repodata/a810cd5676bb578a196231dae1f37179241630f6745a3d33691279ff61bfe175-primary.sqlite.bz2 +0 -0
- data/spec/resources/yumrepo/repodata/ad696c5b02dadaef085b16712ce0464ae0d4c102b3ccf1ce0f14e371a119463a-filelists.sqlite.bz2 +0 -0
- data/spec/resources/yumrepo/repodata/repomd.xml +55 -0
- data/spec/spec_helper.rb +82 -0
- data/vagrant_file.sh +30 -0
- metadata +156 -0
data/lib/pandler/cli.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require "pandler"
|
2
|
+
require "thor"
|
3
|
+
|
4
|
+
class Pandler::CLI < Thor
|
5
|
+
class_option :yumfile, :type => :string, :aliases => "-f", :desc => "Default: Yumfile"
|
6
|
+
|
7
|
+
def initialize(args=[], options={}, config={})
|
8
|
+
super
|
9
|
+
@chroot = Pandler::Chroot.new
|
10
|
+
@yumrepo = Pandler::Yumrepo.new
|
11
|
+
end
|
12
|
+
|
13
|
+
desc "version", "Display pandler version"
|
14
|
+
map ["-v", "--version"] => :version
|
15
|
+
def version
|
16
|
+
puts Pandler::VERSION
|
17
|
+
end
|
18
|
+
|
19
|
+
desc "install", "Install"
|
20
|
+
def install
|
21
|
+
@chroot.init
|
22
|
+
@yumrepo.createrepo
|
23
|
+
@chroot.install(*@yumrepo.install_pkgs)
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "list", "List"
|
27
|
+
def list
|
28
|
+
puts @chroot.list
|
29
|
+
end
|
30
|
+
|
31
|
+
desc "clean", "Clean"
|
32
|
+
def clean
|
33
|
+
@chroot.clean
|
34
|
+
end
|
35
|
+
|
36
|
+
desc "exec", "Execute"
|
37
|
+
def exec(*cmd)
|
38
|
+
@chroot.execute(*cmd)
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class Pandler::Yumfile
|
2
|
+
attr_reader :repos, :rpms
|
3
|
+
|
4
|
+
def initialize(filename)
|
5
|
+
@repos = {}
|
6
|
+
@rpms = []
|
7
|
+
load_file(filename) if File.exists? filename
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def load_file(filename)
|
13
|
+
contents = File.read(filename)
|
14
|
+
instance_eval(contents, filename, 1)
|
15
|
+
@rpms.sort!
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
def repo(name, url)
|
20
|
+
@repos[name] = url
|
21
|
+
end
|
22
|
+
|
23
|
+
def rpm(name)
|
24
|
+
@rpms.push(name)
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,240 @@
|
|
1
|
+
require "erb"
|
2
|
+
require "open3"
|
3
|
+
require "yaml"
|
4
|
+
|
5
|
+
class Hash
|
6
|
+
def to_yaml( opts = {} )
|
7
|
+
YAML::quick_emit( object_id, opts ) do |out|
|
8
|
+
out.map( taguri, to_yaml_style ) do |map|
|
9
|
+
sort.each do |k, v|
|
10
|
+
map.add( k, v )
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class Pandler::Yumrepo
|
18
|
+
attr_reader :base_dir, :repo_dir, :yumfile_path, :lockfile_path
|
19
|
+
def initialize(args = {})
|
20
|
+
@base_dir = args[:base_dir] || File.expand_path("pandler")
|
21
|
+
@repo_dir = args[:repo_dir] || File.join(base_dir, "yumrepo")
|
22
|
+
@yumfile_path = args[:yumfile_path] || File.expand_path("Yumfile")
|
23
|
+
@lockfile_path = args[:lockfile_path] || yumfile_path + ".lock"
|
24
|
+
|
25
|
+
@cache_dir = File.join(base_dir, "yumcache")
|
26
|
+
@yum_log = File.join(@cache_dir, "/var/lib/yum/pandler.log")
|
27
|
+
FileUtils.mkdir_p base_dir
|
28
|
+
FileUtils.mkdir_p repo_dir
|
29
|
+
FileUtils.mkdir_p @cache_dir
|
30
|
+
|
31
|
+
@yumfile = Pandler::Yumfile.new(yumfile_path)
|
32
|
+
@lockfile = read_lockfile
|
33
|
+
end
|
34
|
+
|
35
|
+
def createrepo
|
36
|
+
setup_dirs
|
37
|
+
setup_files
|
38
|
+
yum_download
|
39
|
+
write_lockfile
|
40
|
+
symlink_pkgs
|
41
|
+
run_cmd("createrepo", "-v", repo_dir)
|
42
|
+
end
|
43
|
+
|
44
|
+
def install_pkgs
|
45
|
+
specs.sort_by { |package, spec| spec["name"] }.map { |package, spec| package }
|
46
|
+
end
|
47
|
+
|
48
|
+
def specs
|
49
|
+
@specs
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def run_cmd(*cmd)
|
55
|
+
ret = Kernel.system(*cmd)
|
56
|
+
raise "command failed(ret: #{ret}) '#{cmd.join(" ")}'" unless ret
|
57
|
+
end
|
58
|
+
|
59
|
+
def repos
|
60
|
+
@yumfile.repos
|
61
|
+
end
|
62
|
+
|
63
|
+
def rpms
|
64
|
+
@yumfile.rpms
|
65
|
+
end
|
66
|
+
|
67
|
+
def read_lockfile
|
68
|
+
File.exists?(lockfile_path) ? YAML.load_file(lockfile_path) : nil
|
69
|
+
end
|
70
|
+
|
71
|
+
def write_lockfile
|
72
|
+
open(@lockfile_path, "w") do |f|
|
73
|
+
YAML.dump({
|
74
|
+
"repos" => repos,
|
75
|
+
"rpms" => rpms,
|
76
|
+
"specs" => specs,
|
77
|
+
}, f)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def yum_download
|
82
|
+
run_cmd(*yum("install", *download_pkgs))
|
83
|
+
update_specs
|
84
|
+
end
|
85
|
+
|
86
|
+
def download_pkgs
|
87
|
+
pkgs = []
|
88
|
+
if @lockfile.nil?
|
89
|
+
pkgs = rpms
|
90
|
+
else
|
91
|
+
pkgs = @lockfile["specs"].keys
|
92
|
+
new_pkgs = rpms - @lockfile["rpms"]
|
93
|
+
removed_pkgs = @lockfile["rpms"] - rpms
|
94
|
+
|
95
|
+
if new_pkgs.size > 0
|
96
|
+
pkgs += new_pkgs
|
97
|
+
end
|
98
|
+
|
99
|
+
if removed_pkgs.size > 0
|
100
|
+
removed_pkgs.each do |rm|
|
101
|
+
rm_package = ""
|
102
|
+
@lockfile["specs"].each { |package, spec| rm_package = package if spec["name"] == rm }
|
103
|
+
rpms_package = []
|
104
|
+
rpms.each { |name| @lockfile["specs"].each { |package, spec| rpms_package.push package if spec["name"] == name } }
|
105
|
+
@lockfile["specs"].each do |package, spec|
|
106
|
+
if spec["comesfrom"].include? rm_package
|
107
|
+
if spec["comesfrom"].select { |pkg| rpms_package.include?(pkg) or pkg == rm_package } == [rm_package]
|
108
|
+
pkgs.delete(package)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
pkgs
|
116
|
+
end
|
117
|
+
|
118
|
+
def update_specs
|
119
|
+
@specs = read_yum_log
|
120
|
+
solve_comesfrom
|
121
|
+
end
|
122
|
+
|
123
|
+
def read_yum_log
|
124
|
+
results = {}
|
125
|
+
File.open(@yum_log).each_line do |log|
|
126
|
+
data = Hash[log.chomp.split("\t").map{|f| f.split(":", 2)}]
|
127
|
+
if results.has_key? data["package"]
|
128
|
+
results[data["package"]]["relatedto"].push data["relatedto"]
|
129
|
+
else
|
130
|
+
package = data.delete("package")
|
131
|
+
data["relatedto"] = [data["relatedto"]] if data.has_key?("relatedto")
|
132
|
+
results[package] = data
|
133
|
+
end
|
134
|
+
end
|
135
|
+
results
|
136
|
+
end
|
137
|
+
|
138
|
+
def solve_comesfrom
|
139
|
+
@specs.each do |package, spec|
|
140
|
+
checked_pkg = {}
|
141
|
+
@specs[package]["comesfrom"] = comesfrom(package, checked_pkg)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def comesfrom(pkgs, checked_pkg)
|
146
|
+
rpm_list = []
|
147
|
+
pkgs.each do |pkg|
|
148
|
+
next if checked_pkg[pkg]
|
149
|
+
|
150
|
+
checked_pkg[pkg] = true
|
151
|
+
spec = @specs[pkg]
|
152
|
+
|
153
|
+
rpm_list.push pkg if rpms.include?(@specs[pkg]["name"])
|
154
|
+
if spec.has_key? "relatedto"
|
155
|
+
spec["relatedto"].each do |related|
|
156
|
+
rpm_list.push related if rpms.include?(@specs[related]["name"])
|
157
|
+
end
|
158
|
+
rpm_list += comesfrom(spec["relatedto"], checked_pkg)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
rpm_list.uniq
|
162
|
+
end
|
163
|
+
|
164
|
+
def yum(*args)
|
165
|
+
cmd = ["yum", "--disableplugin=*", "--enableplugin=pandler"]
|
166
|
+
cmd += ["--installroot", @cache_dir, *args]
|
167
|
+
cmd
|
168
|
+
end
|
169
|
+
|
170
|
+
def symlink_pkgs
|
171
|
+
Dir.chdir(repo_dir) do
|
172
|
+
pkgs = Dir.glob("../yumcache/var/cache/yum/**/packages/*.rpm")
|
173
|
+
FileUtils.mkdir_p repo_dir
|
174
|
+
FileUtils.ln_s(pkgs, ".", { :force => true })
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def setup_dirs
|
179
|
+
dirs = [
|
180
|
+
'/var/lib/rpm',
|
181
|
+
'/var/lib/yum',
|
182
|
+
'/var/log',
|
183
|
+
'/var/lock/rpm',
|
184
|
+
'/var/cache/yum',
|
185
|
+
'/tmp',
|
186
|
+
'/var/tmp',
|
187
|
+
'/etc/yum.repos.d',
|
188
|
+
'/etc/yum',
|
189
|
+
'/etc/yum/plugin',
|
190
|
+
'/etc/yum/pluginconf.d',
|
191
|
+
]
|
192
|
+
dirs.each do |dir|
|
193
|
+
FileUtils.mkdir_p(File.join(@cache_dir, dir))
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def setup_files
|
198
|
+
open(File.join(@cache_dir, "/etc/yum/yum.conf"), "w") { |f| f.write yum_conf }
|
199
|
+
open(File.join(@cache_dir, "/etc/yum/pluginconf.d/pandler.conf"), "w") { |f| f.write plugin_conf }
|
200
|
+
FileUtils.cp(yum_plugin_path, File.join(@cache_dir, "/etc/yum/plugin"))
|
201
|
+
end
|
202
|
+
|
203
|
+
def yum_plugin_path
|
204
|
+
File.expand_path("../../../etc/yum/pandler.py", __FILE__)
|
205
|
+
end
|
206
|
+
|
207
|
+
def yum_conf
|
208
|
+
content = ERB.new <<-EOF
|
209
|
+
[main]
|
210
|
+
cachedir=/var/cache/yum
|
211
|
+
debuglevel=1
|
212
|
+
reposdir=/dev/null
|
213
|
+
logfile=/var/log/yum.log
|
214
|
+
retries=20
|
215
|
+
obsoletes=1
|
216
|
+
gpgcheck=0
|
217
|
+
assumeyes=1
|
218
|
+
syslog_ident=pandler
|
219
|
+
syslog_device=
|
220
|
+
plugins=1
|
221
|
+
pluginpath=<%= @cache_dir %>/etc/yum/plugin
|
222
|
+
pluginconfpath=<%= @cache_dir %>/etc/yum/pluginconf.d
|
223
|
+
<% repos.each { |repo, url| %>
|
224
|
+
[<%= repo %>]
|
225
|
+
name=<%= repo %>
|
226
|
+
enabled=1
|
227
|
+
baseurl=<%= url %>
|
228
|
+
<% } %>
|
229
|
+
EOF
|
230
|
+
content.result(binding)
|
231
|
+
end
|
232
|
+
|
233
|
+
def plugin_conf
|
234
|
+
content = <<-EOF
|
235
|
+
[main]
|
236
|
+
enabled=1
|
237
|
+
EOF
|
238
|
+
content
|
239
|
+
end
|
240
|
+
end
|
data/pandler.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'pandler/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "pandler"
|
8
|
+
gem.version = Pandler::VERSION
|
9
|
+
gem.authors = ["Ryosuke IWANAGA"]
|
10
|
+
gem.email = ["riywo.jp@gmail.com"]
|
11
|
+
gem.description = %q{Manage your packages with chroot}
|
12
|
+
gem.summary = %q{Yumfile}
|
13
|
+
gem.homepage = "https://github.com/riywo/pandler"
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_dependency 'thor', '>= 0.13.6'
|
21
|
+
|
22
|
+
gem.add_development_dependency 'rake', '>= 0.9.2.2'
|
23
|
+
gem.add_development_dependency 'rspec'
|
24
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require "pathname"
|
2
|
+
|
3
|
+
describe Pandler::Chroot do
|
4
|
+
include TempDirHelper
|
5
|
+
before :all do
|
6
|
+
# @base_dir = File.expand_path("../../../.spec_cache", __FILE__)
|
7
|
+
yumrepo = "file://" + File.expand_path("../../resources/yumrepo", __FILE__)
|
8
|
+
@chroot = Pandler::Chroot.new(:yumrepo => yumrepo)
|
9
|
+
end
|
10
|
+
|
11
|
+
subject { @chroot }
|
12
|
+
its(:root_dir) { should eq "#{@chroot.base_dir}/root" }
|
13
|
+
|
14
|
+
describe "chroot file path" do
|
15
|
+
subject { @chroot.real_path("/") }
|
16
|
+
it { should eq @chroot.root_dir + "/" }
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "init" do
|
20
|
+
before(:all) { @chroot.init }
|
21
|
+
it "should create directories" do
|
22
|
+
[
|
23
|
+
'/var/lib/rpm',
|
24
|
+
'/var/lib/yum',
|
25
|
+
'/var/lib/dbus',
|
26
|
+
'/var/log',
|
27
|
+
'/var/lock/rpm',
|
28
|
+
'/var/cache/yum',
|
29
|
+
'/etc/rpm',
|
30
|
+
'/tmp',
|
31
|
+
'/tmp/ccache',
|
32
|
+
'/var/tmp',
|
33
|
+
'/etc/yum.repos.d',
|
34
|
+
'/etc/yum',
|
35
|
+
'/proc',
|
36
|
+
'/sys',
|
37
|
+
].each do |path|
|
38
|
+
Pathname(@chroot.real_path(path)).should exist
|
39
|
+
end
|
40
|
+
end
|
41
|
+
it "should create files" do
|
42
|
+
[
|
43
|
+
'/etc/mtab',
|
44
|
+
'/etc/fstab',
|
45
|
+
'/var/log/yum.log',
|
46
|
+
'/etc/yum/yum.conf',
|
47
|
+
'/etc/yum.conf',
|
48
|
+
'/etc/resolv.conf',
|
49
|
+
'/etc/hosts',
|
50
|
+
].each do |path|
|
51
|
+
Pathname(@chroot.real_path(path)).should exist
|
52
|
+
end
|
53
|
+
end
|
54
|
+
it "should create devs" do
|
55
|
+
[
|
56
|
+
'/dev/null',
|
57
|
+
'/dev/full',
|
58
|
+
'/dev/zero',
|
59
|
+
'/dev/random',
|
60
|
+
'/dev/urandom',
|
61
|
+
'/dev/tty',
|
62
|
+
'/dev/console',
|
63
|
+
'/dev/stdin',
|
64
|
+
'/dev/stdout',
|
65
|
+
'/dev/stderr',
|
66
|
+
'/dev/fd',
|
67
|
+
# '/dev/ptmx',
|
68
|
+
].each do |path|
|
69
|
+
Pathname(@chroot.real_path(path)).should exist
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "install first time" do
|
75
|
+
before(:all) { @chroot.install("pandler-test-0.0.1-1.x86_64", "pandler-test-a-0.0.1-1.x86_64") }
|
76
|
+
it "should execute /pandler-test" do
|
77
|
+
Kernel.system("chroot", @chroot.root_dir, "/pandler-test").should be_true
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "exec /pandler-test" do
|
82
|
+
subject { capture_stdout { @chroot.execute("/pandler-test") } }
|
83
|
+
it { should eq "pandler test\n" }
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "install second time" do
|
87
|
+
before(:all) { @chroot.install("pandler-test-0.0.1-1.x86_64") }
|
88
|
+
subject { @chroot.installed_pkgs }
|
89
|
+
it { should eq ["pandler-test-0.0.1-1.x86_64"] }
|
90
|
+
end
|
91
|
+
|
92
|
+
after(:all) { @chroot.clean }
|
93
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
describe Pandler::CLI do
|
2
|
+
include TempDirHelper
|
3
|
+
include PandleHelper
|
4
|
+
describe "version" do
|
5
|
+
it "displays gem version" do
|
6
|
+
pandle("version").chomp.should == Pandler::VERSION
|
7
|
+
end
|
8
|
+
|
9
|
+
it "displays gem version on shortcut command" do
|
10
|
+
pandle("-v").chomp.should == Pandler::VERSION
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
=begin
|
15
|
+
describe "exec echo 'test'" do
|
16
|
+
subject { pandle("exec echo 'test'") }
|
17
|
+
it { should eq "test\n" }
|
18
|
+
end
|
19
|
+
=end
|
20
|
+
end
|