From 541b1852ff8cf097c9fa4d6e4fec8a76d09adcfa Mon Sep 17 00:00:00 2001 From: Mo Morsi Date: Thu, 7 Nov 2013 14:39:54 -0500 Subject: [PATCH] Add mechanism to lookup specific package information Native package system lookup method for rpm and deb package systems are provided as well as an abstract mechanism so the user doesn't have to know distro details. --- lib/linux_admin.rb | 2 ++ lib/linux_admin/deb.rb | 39 +++++++++++++++++++++++++++ lib/linux_admin/package.rb | 18 +++++++++++++ lib/linux_admin/rpm.rb | 23 +++++++++++++++- spec/deb_spec.rb | 54 ++++++++++++++++++++++++++++++++++++++ spec/package_spec.rb | 17 ++++++++++++ spec/rpm_spec.rb | 48 ++++++++++++++++++++++++++++++++- 7 files changed, 199 insertions(+), 2 deletions(-) create mode 100644 lib/linux_admin/deb.rb create mode 100644 lib/linux_admin/package.rb create mode 100644 spec/deb_spec.rb create mode 100644 spec/package_spec.rb diff --git a/lib/linux_admin.rb b/lib/linux_admin.rb index 9e4ad47..be668d4 100644 --- a/lib/linux_admin.rb +++ b/lib/linux_admin.rb @@ -6,7 +6,9 @@ require 'linux_admin/common' require 'linux_admin/exceptions' require 'linux_admin/command_result' +require 'linux_admin/package' require 'linux_admin/rpm' +require 'linux_admin/deb' require 'linux_admin/version' require 'linux_admin/yum' diff --git a/lib/linux_admin/deb.rb b/lib/linux_admin/deb.rb new file mode 100644 index 0000000..8bf7639 --- /dev/null +++ b/lib/linux_admin/deb.rb @@ -0,0 +1,39 @@ +# LinuxAdmin Deb Representation +# +# Copyright (C) 2013 Red Hat Inc. +# Licensed under the MIT License + +class LinuxAdmin + class Deb < Package + APT_CACHE_CMD = '/usr/bin/apt-cache' + + def self.from_line(apt_cache_line, in_description=false) + tag,value = apt_cache_line.split(':') + tag = tag.strip.downcase + [tag, value] + end + + def self.from_string(apt_cache_string) + in_description = false + apt_cache_string.split("\n").each.with_object({}) do |line,deb| + tag,value = self.from_line(line) + if tag == 'description-en' + in_description = true + elsif tag == 'homepage' + in_description = false + end + + if in_description && tag != 'description-en' + deb['description-en'] << line + else + deb[tag] = value.strip + end + end + end + + def self.info(pkg) + self.from_string(run!(APT_CACHE_CMD, :params => ["show", pkg]).output) + end + + end +end diff --git a/lib/linux_admin/package.rb b/lib/linux_admin/package.rb new file mode 100644 index 0000000..2b202e5 --- /dev/null +++ b/lib/linux_admin/package.rb @@ -0,0 +1,18 @@ +# LinuxAdmin Abstract Package Representation +# +# Copyright (C) 2013 Red Hat Inc. +# Licensed under the MIT License + +class LinuxAdmin + class Package < LinuxAdmin + def self.info(pkg) + if Distro.local == Distros.redhat + return Rpm.info(pkg) + elsif Distro.local == Distros.ubuntu + return Deb.info(pkg) + end + + nil + end + end +end diff --git a/lib/linux_admin/rpm.rb b/lib/linux_admin/rpm.rb index 9cf1511..51a7fea 100644 --- a/lib/linux_admin/rpm.rb +++ b/lib/linux_admin/rpm.rb @@ -1,5 +1,7 @@ class LinuxAdmin - class Rpm < LinuxAdmin + class Rpm < Package + RPM_CMD = '/usr/bin/rpm' + def self.list_installed out = run!("rpm -qa --qf \"%{NAME} %{VERSION}-%{RELEASE}\n\"").output out.split("\n").each_with_object({}) do |line, pkg_hash| @@ -8,6 +10,25 @@ def self.list_installed end end + def self.info(pkg) + params = { "-qi" => pkg} + in_description = false + out = run!(RPM_CMD, :params => params).output + out.split("\n").each.with_object({}) do |line, rpm| + tag,value = line.split(':') + tag = tag.strip + if tag == 'Description' + in_description = true + elsif in_description + rpm['description'] ||= "" + rpm['description'] << line + " " + else + tag = tag.downcase.gsub(/\s/, '_') + rpm[tag] = value.strip + end + end + end + def self.upgrade(pkg) cmd = "rpm -U" params = { nil => pkg } diff --git a/spec/deb_spec.rb b/spec/deb_spec.rb new file mode 100644 index 0000000..af41ff0 --- /dev/null +++ b/spec/deb_spec.rb @@ -0,0 +1,54 @@ +require 'spec_helper' + +describe LinuxAdmin::Deb do + describe "#info" do + it "returns package metadata" do + # as output w/ apt-cache show ruby on ubuntu 13.04 + data = < +Original-Maintainer: akira yamada +Architecture: all +Source: ruby-defaults +Version: 4.9 +Replaces: irb, rdoc +Provides: irb, rdoc +Depends: ruby1.9.1 (>= 1.9.3.194-1) +Suggests: ri, ruby-dev +Conflicts: irb, rdoc +Filename: pool/main/r/ruby-defaults/ruby_4.9_all.deb +Size: 4896 +MD5sum: b1991f2e0eafb04f5930ed242cfe1476 +SHA1: a7c55fbb83dd8382631ea771b5555d989351f840 +SHA256: 84d042e0273bd2f0082dd9e7dda0246267791fd09607041a35485bfff92f38d9 +Description-en: Interpreter of object-oriented scripting language Ruby (default version) + Ruby is the interpreted scripting language for quick and easy + object-oriented programming. It has many features to process text + files and to do system management tasks (as in perl). It is simple, + straight-forward, and extensible. + . + This package is a dependency package, which depends on Debian's default Ruby + version (currently v1.9.3). +Homepage: http://www.ruby-lang.org/ +Description-md5: da2991b37e3991230d79ba70f9c01682 +Bugs: https://bugs.launchpad.net/ubuntu/+filebug +Origin: Ubuntu +Supported: 9m +Task: kubuntu-desktop, kubuntu-full, kubuntu-active, kubuntu-active-desktop, kubuntu-active-full, kubuntu-active, edubuntu-desktop-gnome, ubuntustudio-font-meta +EOS + described_class.should_receive(:run). + with(described_class::APT_CACHE_CMD, :params => ["show", "ruby"]). + and_return(CommandResult.new(data, "", 0)) + metadata = described_class.info("ruby") + metadata['package'].should == 'ruby' + metadata['priority'].should == 'optional' + metadata['section'].should == 'interpreters' + metadata['architecture'].should == 'all' + metadata['version'].should == '4.9' + metadata['origin'].should == 'Ubuntu' + end + end +end diff --git a/spec/package_spec.rb b/spec/package_spec.rb new file mode 100644 index 0000000..0aaf0fd --- /dev/null +++ b/spec/package_spec.rb @@ -0,0 +1,17 @@ +require 'spec_helper' + +describe LinuxAdmin::Package do + describe "#info" do + it "dispatches to redhat lookup mechanism" do + LinuxAdmin::Distro.should_receive(:local).and_return(LinuxAdmin::Distros.redhat) + LinuxAdmin::Rpm.should_receive(:info).with('ruby') + described_class.info 'ruby' + end + + it "dispatches to ubuntu lookup mechanism" do + LinuxAdmin::Distro.should_receive(:local).twice.and_return(LinuxAdmin::Distros.ubuntu) + LinuxAdmin::Deb.should_receive(:info).with('ruby') + described_class.info 'ruby' + end + end +end diff --git a/spec/rpm_spec.rb b/spec/rpm_spec.rb index 85906fb..39fb6d9 100644 --- a/spec/rpm_spec.rb +++ b/spec/rpm_spec.rb @@ -27,8 +27,54 @@ }) end + describe "#info" do + it "returns package metadata" do + # as output w/ rpm -qi ruby on F19 + data = < {"-qi" => "ruby"}). + and_return(CommandResult.new(data, "", 0)) + metadata = described_class.info("ruby") + metadata['name'].should == 'ruby' + metadata['version'].should == '2.0.0.247' + metadata['release'].should == '15.fc19' + metadata['architecture'].should == 'x86_64' + metadata['group'].should == 'Development/Languages' + metadata['size'].should == '64473' + metadata['license'].should == '(Ruby or BSD) and Public Domain' + metadata['source_rpm'].should == 'ruby-2.0.0.247-15.fc19.src.rpm' + metadata['build_host'].should == 'buildvm-16.phx2.fedoraproject.org' + metadata['packager'].should == 'Fedora Project' + metadata['vendor'].should == 'Fedora Project' + metadata['summary'].should == 'An interpreter of object-oriented scripting language' + end + end + it ".upgrade" do described_class.should_receive(:run).with("rpm -U", {:params=>{nil=>"abc"}}).and_return(CommandResult.new("", "", 0)) expect(described_class.upgrade("abc")).to be_true end -end \ No newline at end of file +end