pandler 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/.gitignore +23 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +47 -0
  5. data/Rakefile +10 -0
  6. data/Vagrantfile +33 -0
  7. data/bin/pandle +8 -0
  8. data/etc/yum/pandler.py +52 -0
  9. data/lib/pandler.rb +8 -0
  10. data/lib/pandler/chroot.rb +229 -0
  11. data/lib/pandler/cli.rb +40 -0
  12. data/lib/pandler/version.rb +3 -0
  13. data/lib/pandler/yumfile.rb +26 -0
  14. data/lib/pandler/yumrepo.rb +240 -0
  15. data/pandler.gemspec +24 -0
  16. data/spec/pandler/chroot_spec.rb +93 -0
  17. data/spec/pandler/cli_spec.rb +20 -0
  18. data/spec/pandler/yumfile_spec.rb +20 -0
  19. data/spec/pandler/yumrepo_spec.rb +152 -0
  20. data/spec/pandler_spec.rb +8 -0
  21. data/spec/resources/yumrepo/pandler-test-0.0.1-1.x86_64.rpm +0 -0
  22. data/spec/resources/yumrepo/pandler-test-a-0.0.1-1.x86_64.rpm +0 -0
  23. data/spec/resources/yumrepo/pandler-test-a-0.0.2-1.x86_64.rpm +0 -0
  24. data/spec/resources/yumrepo/pandler-test-dep-a-0.0.1-1.x86_64.rpm +0 -0
  25. data/spec/resources/yumrepo/pandler-test-dep-b-0.0.1-1.x86_64.rpm +0 -0
  26. data/spec/resources/yumrepo/pandler-test-dep-required-0.0.1-1.x86_64.rpm +0 -0
  27. data/spec/resources/yumrepo/pandler-test-dep-required-required-0.0.1-1.x86_64.rpm +0 -0
  28. data/spec/resources/yumrepo/repodata/09267893997a9b34726567132f642093ebd2a4b5e65096a6562efc3a29106723-other.xml.gz +0 -0
  29. data/spec/resources/yumrepo/repodata/596e9069dad80db19e7ba4c36b3df1e52583231b95bfa61186408c77520a213a-primary.xml.gz +0 -0
  30. data/spec/resources/yumrepo/repodata/7dd30f881bb1b1cbd723a5fa9d996b96805e25015b56140c99a444bf248c4260-other.sqlite.bz2 +0 -0
  31. data/spec/resources/yumrepo/repodata/8e6f832a8605163914b5aaf46e42daeaad10f9785d202c6c99c9d903354b3194-filelists.xml.gz +0 -0
  32. data/spec/resources/yumrepo/repodata/a810cd5676bb578a196231dae1f37179241630f6745a3d33691279ff61bfe175-primary.sqlite.bz2 +0 -0
  33. data/spec/resources/yumrepo/repodata/ad696c5b02dadaef085b16712ce0464ae0d4c102b3ccf1ce0f14e371a119463a-filelists.sqlite.bz2 +0 -0
  34. data/spec/resources/yumrepo/repodata/repomd.xml +55 -0
  35. data/spec/spec_helper.rb +82 -0
  36. data/vagrant_file.sh +30 -0
  37. metadata +156 -0
@@ -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,3 @@
1
+ module Pandler
2
+ VERSION = "0.0.1"
3
+ 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
@@ -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