From fe3b39d7130154126620437b1dfa9af79062170a Mon Sep 17 00:00:00 2001 From: Brandon Dunne Date: Mon, 12 Aug 2013 23:39:39 -0400 Subject: [PATCH 1/6] Create LinuxAdmin::RegistrationSystem --- lib/linux_admin.rb | 18 ++--------- lib/linux_admin/registration_system.rb | 45 ++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 16 deletions(-) create mode 100644 lib/linux_admin/registration_system.rb diff --git a/lib/linux_admin.rb b/lib/linux_admin.rb index 2586d6a..07fb097 100644 --- a/lib/linux_admin.rb +++ b/lib/linux_admin.rb @@ -1,11 +1,11 @@ require 'more_core_extensions/all' require 'active_support/core_ext' +require 'linux_admin/registration_system' + require 'linux_admin/common' require 'linux_admin/exceptions' -require 'linux_admin/rhn' require 'linux_admin/rpm' -require 'linux_admin/subscription_manager' require 'linux_admin/version' require 'linux_admin/yum' @@ -22,18 +22,4 @@ class LinuxAdmin extend Common include Common - - def self.registered? - !!self.registration_type - end - - def self.registration_type - if SubscriptionManager.registered? - SubscriptionManager - elsif Rhn.registered? - Rhn - else - nil - end - end end diff --git a/lib/linux_admin/registration_system.rb b/lib/linux_admin/registration_system.rb new file mode 100644 index 0000000..01f76d6 --- /dev/null +++ b/lib/linux_admin/registration_system.rb @@ -0,0 +1,45 @@ +class LinuxAdmin + class RegistrationSystem < LinuxAdmin + def self.registration_type(reload = false) + return @registration_type if @registration_type && !reload + @registration_type = registration_type_uncached + end + + def self.method_missing(meth, *args, &block) + if white_list_methods.include?(meth) + r = self.registration_type.new + raise NotImplementedError, "#{meth} not implemented for #{self.name}" unless r.respond_to?(meth) + r.send(meth, *args, &block) + else + super + end + end + + def registered? + false + end + + private + + def self.registration_type_uncached + if SubscriptionManager.new.registered? + SubscriptionManager + elsif Rhn.new.registered? + Rhn + else + self + end + end + private_class_method :registration_type_uncached + + def self.white_list_methods + @white_list_methods ||= begin + all_methods = RegistrationSystem.instance_methods(false) + Rhn.instance_methods(false) + SubscriptionManager.instance_methods(false) + all_methods.uniq + end + end + private_class_method :white_list_methods + end +end + +Dir.glob(File.join(File.dirname(__FILE__), "registration_system", "*.rb")).each { |f| require f } \ No newline at end of file From d3c4ed68897f06d75909601773a41663a41f79f2 Mon Sep 17 00:00:00 2001 From: Brandon Dunne Date: Mon, 12 Aug 2013 23:40:08 -0400 Subject: [PATCH 2/6] Modify Inheritence --- lib/linux_admin/rhn.rb | 2 +- lib/linux_admin/subscription_manager.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/linux_admin/rhn.rb b/lib/linux_admin/rhn.rb index c686706..13c4a73 100644 --- a/lib/linux_admin/rhn.rb +++ b/lib/linux_admin/rhn.rb @@ -1,7 +1,7 @@ require 'nokogiri' class LinuxAdmin - class Rhn < LinuxAdmin + class Rhn < RegistrationSystem def self.systemid_file "/etc/sysconfig/rhn/systemid" end diff --git a/lib/linux_admin/subscription_manager.rb b/lib/linux_admin/subscription_manager.rb index 70f3f7d..784de27 100644 --- a/lib/linux_admin/subscription_manager.rb +++ b/lib/linux_admin/subscription_manager.rb @@ -1,7 +1,7 @@ require 'date' class LinuxAdmin - class SubscriptionManager < LinuxAdmin + class SubscriptionManager < RegistrationSystem def self.registered? run("subscription-manager identity", :return_exitstatus => true) == 0 end From aa3db5496274026be25357d99bcb42a9a4a8592a Mon Sep 17 00:00:00 2001 From: Brandon Dunne Date: Tue, 13 Aug 2013 23:00:35 -0400 Subject: [PATCH 3/6] Fix tests related to registration_system commands --- spec/linux_admin_spec.rb | 38 -------------------- spec/registration_system_spec.rb | 60 ++++++++++++++++++++++++++++++++ spec/spec_helper.rb | 8 +++++ 3 files changed, 68 insertions(+), 38 deletions(-) create mode 100644 spec/registration_system_spec.rb diff --git a/spec/linux_admin_spec.rb b/spec/linux_admin_spec.rb index 64b20cc..b1fcce8 100644 --- a/spec/linux_admin_spec.rb +++ b/spec/linux_admin_spec.rb @@ -1,42 +1,4 @@ require 'spec_helper' describe LinuxAdmin do - context ".registered?" do - it "when registered Subscription Manager" do - stub_registered_to_system(:sm) - expect(described_class.registered?).to be_true - end - - it "when registered RHN" do - stub_registered_to_system(:rhn) - expect(described_class.registered?).to be_true - end - - it "when unregistered" do - stub_registered_to_system(nil) - expect(described_class.registered?).to be_false - end - end - - context ".registration_type" do - it "when registered Subscription Manager" do - stub_registered_to_system(:sm) - expect(described_class.registration_type).to eq(LinuxAdmin::SubscriptionManager) - end - - it "when registered RHN" do - stub_registered_to_system(:rhn) - expect(described_class.registration_type).to eq(LinuxAdmin::Rhn) - end - - it "when unregistered" do - stub_registered_to_system(nil) - expect(described_class.registration_type).to be_nil - end - end - - def stub_registered_to_system(system) - described_class::SubscriptionManager.stub(:registered? => (system == :sm)) - described_class::Rhn.stub(:registered? => (system == :rhn)) - end end \ No newline at end of file diff --git a/spec/registration_system_spec.rb b/spec/registration_system_spec.rb new file mode 100644 index 0000000..52900e3 --- /dev/null +++ b/spec/registration_system_spec.rb @@ -0,0 +1,60 @@ +require 'spec_helper' + +describe LinuxAdmin::RegistrationSystem do + context ".registration_type" do + it "when registered Subscription Manager" do + stub_registered_to_system(:sm) + expect(described_class.registration_type).to eq(LinuxAdmin::SubscriptionManager) + end + + it "when registered RHN" do + stub_registered_to_system(:rhn) + expect(described_class.registration_type).to eq(LinuxAdmin::Rhn) + end + + it "when unregistered" do + stub_registered_to_system(nil) + expect(described_class.registration_type).to eq(described_class) + end + + it "should memoize results" do + described_class.should_receive(:registration_type_uncached).once.and_call_original + described_class.registration_type + described_class.registration_type + end + + it "with reload should refresh results" do + described_class.should_receive(:registration_type_uncached).twice.and_call_original + described_class.registration_type + described_class.registration_type(true) + end + end + + it "#registered? when unregistered" do + stub_registered_to_system(nil) + expect(described_class.registered?).to be_false + end + + context ".method_missing" do + before do + stub_registered_to_system(:rhn) + end + + it "exists on the subclass" do + expect(LinuxAdmin::RegistrationSystem.registered?).to be_true + end + + it "does not exist on the subclass" do + expect { LinuxAdmin::RegistrationSystem.organizations }.to raise_error(NotImplementedError) + end + + it "is an unknown method" do + expect { LinuxAdmin::RegistrationSystem.method_does_not_exist }.to be_true + end + end + + def stub_registered_to_system(system) + LinuxAdmin::SubscriptionManager.any_instance.stub(:registered? => (system == :sm)) + LinuxAdmin::Rhn.any_instance.stub(:registered? => data_file_path("rhn/systemid")) if system == :rhn + end +end \ No newline at end of file diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 4eea6b9..544a52d 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -22,6 +22,10 @@ config.before do Kernel.stub(:spawn).and_raise("Spawning is not permitted in specs. Please change your spec to use expectations/stubs.") end + + config.after do + clear_caches + end end def data_file_path(to) @@ -32,6 +36,10 @@ def sample_output(to) File.read(data_file_path(to)) end +def clear_caches + LinuxAdmin::RegistrationSystem.instance_variable_set(:@registration_type, nil) +end + class LinuxAdmin module Distros # simply alias test distro to redhat distro for time being From 7288583e4b1e6d04c1cb3be535efe7ff535f7446 Mon Sep 17 00:00:00 2001 From: Brandon Dunne Date: Wed, 14 Aug 2013 10:11:49 -0400 Subject: [PATCH 4/6] Change Rhn class methods to instance methods --- lib/linux_admin/rhn.rb | 16 +++++++++------- spec/rhn_spec.rb | 38 +++++++++++++++++--------------------- 2 files changed, 26 insertions(+), 28 deletions(-) diff --git a/lib/linux_admin/rhn.rb b/lib/linux_admin/rhn.rb index 13c4a73..04511df 100644 --- a/lib/linux_admin/rhn.rb +++ b/lib/linux_admin/rhn.rb @@ -2,11 +2,7 @@ class LinuxAdmin class Rhn < RegistrationSystem - def self.systemid_file - "/etc/sysconfig/rhn/systemid" - end - - def self.registered? + def registered? id = "" if File.exists?(systemid_file) xml = Nokogiri.XML(File.read(systemid_file)) @@ -15,7 +11,7 @@ def self.registered? id.length > 0 end - def self.register(options) + def register(options) cmd = "rhnreg_ks" params = {} @@ -36,7 +32,7 @@ def self.register(options) run(cmd, :params => params) end - def self.subscribe(options) + def subscribe(options) raise ArgumentError, "pools, username and password are required" if options[:pools].blank? || options[:username].blank? || options[:password].blank? cmd = "rhn-channel -a" @@ -49,5 +45,11 @@ def self.subscribe(options) run(cmd, :params => params) end + + private + + def systemid_file + "/etc/sysconfig/rhn/systemid" + end end end \ No newline at end of file diff --git a/spec/rhn_spec.rb b/spec/rhn_spec.rb index e813b4d..bc692a0 100644 --- a/spec/rhn_spec.rb +++ b/spec/rhn_spec.rb @@ -1,35 +1,31 @@ require 'spec_helper' describe LinuxAdmin::Rhn do - it ".systemid_file" do - expect(described_class.systemid_file).to be_kind_of(String) - end - - context ".registered?" do + context "#registered?" do it "with registered system_id" do - described_class.stub(:systemid_file => data_file_path("rhn/systemid")) - expect(described_class).to be_registered + described_class.any_instance.stub(:systemid_file => data_file_path("rhn/systemid")) + expect(described_class.new).to be_registered end it "with unregistered system_id" do - described_class.stub(:systemid_file => data_file_path("rhn/systemid.missing_system_id")) - expect(described_class).to_not be_registered + described_class.any_instance.stub(:systemid_file => data_file_path("rhn/systemid.missing_system_id")) + expect(described_class.new).to_not be_registered end it "with missing systemid file" do - described_class.stub(:systemid_file => data_file_path("rhn/systemid.missing_file")) - expect(described_class).to_not be_registered + described_class.any_instance.stub(:systemid_file => data_file_path("rhn/systemid.missing_file")) + expect(described_class.new).to_not be_registered end end - context ".register" do + context "#register" do it "no username or activation key" do - expect { described_class.register({}) }.to raise_error(ArgumentError) + expect { described_class.new.register({}) }.to raise_error(ArgumentError) end it "with username and password" do - described_class.should_receive(:run).once.with("rhnreg_ks", {:params=>{"--username="=>"SomeUser", "--password="=>"SomePass", "--proxy="=>"1.2.3.4", "--proxyUser="=>"ProxyUser", "--proxyPassword="=>"ProxyPass", "--serverUrl="=>"192.168.1.1"}}).and_return(0) - described_class.register( + described_class.any_instance.should_receive(:run).once.with("rhnreg_ks", {:params=>{"--username="=>"SomeUser", "--password="=>"SomePass", "--proxy="=>"1.2.3.4", "--proxyUser="=>"ProxyUser", "--proxyPassword="=>"ProxyPass", "--serverUrl="=>"192.168.1.1"}}).and_return(0) + described_class.new.register( :username => "SomeUser", :password => "SomePass", :proxy_address => "1.2.3.4", @@ -40,8 +36,8 @@ end it "with activation key" do - described_class.should_receive(:run).once.with("rhnreg_ks", {:params=>{"--activationkey="=>"123abc", "--proxy="=>"1.2.3.4", "--proxyUser="=>"ProxyUser", "--proxyPassword="=>"ProxyPass", "--serverUrl="=>"192.168.1.1"}}).and_return(0) - described_class.register( + described_class.any_instance.should_receive(:run).once.with("rhnreg_ks", {:params=>{"--activationkey="=>"123abc", "--proxy="=>"1.2.3.4", "--proxyUser="=>"ProxyUser", "--proxyPassword="=>"ProxyPass", "--serverUrl="=>"192.168.1.1"}}).and_return(0) + described_class.new.register( :activationkey => "123abc", :proxy_address => "1.2.3.4", :proxy_username => "ProxyUser", @@ -51,14 +47,14 @@ end end - context ".subscribe" do + context "#subscribe" do it "without arguments" do - expect { described_class.subscribe({}) }.to raise_error(ArgumentError) + expect { described_class.new.subscribe({}) }.to raise_error(ArgumentError) end it "with pools" do - described_class.should_receive(:run).once.with("rhn-channel -a", {:params=>[["--user=", "SomeUser"], ["--password=", "SomePass"], ["--channel=", 123], ["--channel=", 456]]}) - described_class.subscribe({ + described_class.any_instance.should_receive(:run).once.with("rhn-channel -a", {:params=>[["--user=", "SomeUser"], ["--password=", "SomePass"], ["--channel=", 123], ["--channel=", 456]]}) + described_class.new.subscribe({ :username => "SomeUser", :password => "SomePass", :pools => [123, 456] From f645e060e60cadf47a4620ac8c603f06995e7b11 Mon Sep 17 00:00:00 2001 From: Brandon Dunne Date: Wed, 14 Aug 2013 10:15:56 -0400 Subject: [PATCH 5/6] Change SubscriptionManager class methods to instance methods --- lib/linux_admin/subscription_manager.rb | 25 +++++++++------ spec/subscription_manager_spec.rb | 42 ++++++++++++------------- 2 files changed, 36 insertions(+), 31 deletions(-) diff --git a/lib/linux_admin/subscription_manager.rb b/lib/linux_admin/subscription_manager.rb index 784de27..cde67e3 100644 --- a/lib/linux_admin/subscription_manager.rb +++ b/lib/linux_admin/subscription_manager.rb @@ -2,15 +2,20 @@ class LinuxAdmin class SubscriptionManager < RegistrationSystem - def self.registered? + + def validate_credentials(options) + !!organizations(options) + end + + def registered? run("subscription-manager identity", :return_exitstatus => true) == 0 end - def self.refresh + def refresh run("subscription-manager refresh") end - def self.organizations(options) + def organizations(options) raise ArgumentError, "username and password are required" unless options[:username] && options[:password] cmd = "subscription-manager orgs" @@ -22,7 +27,7 @@ def self.organizations(options) parse_output(output).index_by {|i| i[:name]} end - def self.register(options) + def register(options) raise ArgumentError, "username and password are required" unless options[:username] && options[:password] cmd = "subscription-manager register" @@ -34,7 +39,7 @@ def self.register(options) run(cmd, :params => params) end - def self.subscribe(options) + def subscribe(options) cmd = "subscription-manager attach" pools = options[:pools].collect {|pool| ["--pool", pool]} params = proxy_params(options).to_a + pools @@ -42,7 +47,7 @@ def self.subscribe(options) run(cmd, :params => params) end - def self.available_subscriptions + def available_subscriptions cmd = "subscription-manager list --all --available" output = run(cmd, :return_output => true) parse_output(output).index_by {|i| i[:pool_id]} @@ -50,13 +55,13 @@ def self.available_subscriptions private - def self.parse_output(output) + def parse_output(output) # Strip the 3 line header off the top content = output.split("\n")[3..-1].join("\n") parse_content(content) end - def self.parse_content(content) + def parse_content(content) # Break into content groupings by "\n\n" then process each grouping content.split("\n\n").each_with_object([]) do |group, group_array| group = group.split("\n").each_with_object({}) do |line, hash| @@ -68,12 +73,12 @@ def self.parse_content(content) end end - def self.format_values(content_group) + def format_values(content_group) content_group[:ends] = Date.strptime(content_group[:ends], "%m/%d/%Y") if content_group[:ends] content_group end - def self.proxy_params(options) + def proxy_params(options) config = {} config["--proxy="] = options[:proxy_address] if options[:proxy_address] config["--proxyuser="] = options[:proxy_username] if options[:proxy_username] diff --git a/spec/subscription_manager_spec.rb b/spec/subscription_manager_spec.rb index d16b73d..4e009aa 100644 --- a/spec/subscription_manager_spec.rb +++ b/spec/subscription_manager_spec.rb @@ -1,31 +1,31 @@ require 'spec_helper' describe LinuxAdmin::SubscriptionManager do - context ".registered?" do + context "#registered?" do it "system with subscription-manager commands" do - described_class.should_receive(:run).once.with("subscription-manager identity", {:return_exitstatus=>true}).and_return(0) - expect(described_class.registered?).to be_true + described_class.any_instance.should_receive(:run).once.with("subscription-manager identity", {:return_exitstatus=>true}).and_return(0) + expect(described_class.new.registered?).to be_true end it "system without subscription-manager commands" do - described_class.should_receive(:run).once.with("subscription-manager identity", {:return_exitstatus=>true}).and_return(255) - expect(described_class.registered?).to be_false + described_class.any_instance.should_receive(:run).once.with("subscription-manager identity", {:return_exitstatus=>true}).and_return(255) + expect(described_class.new.registered?).to be_false end end - it ".refresh" do - described_class.should_receive(:run).once.with("subscription-manager refresh").and_return(0) - described_class.refresh + it "#refresh" do + described_class.any_instance.should_receive(:run).once.with("subscription-manager refresh").and_return(0) + described_class.new.refresh end - context ".register" do + context "#register" do it "no username" do - expect { described_class.register }.to raise_error(ArgumentError) + expect { described_class.new.register }.to raise_error(ArgumentError) end it "with username and password" do - described_class.should_receive(:run).once.with("subscription-manager register", {:params=>{"--username="=>"SomeUser", "--password="=>"SomePass", "--org="=>"IT", "--proxy="=>"1.2.3.4", "--proxyuser="=>"ProxyUser", "--proxypassword="=>"ProxyPass", "--serverurl="=>"192.168.1.1"}}).and_return(0) - described_class.register( + described_class.any_instance.should_receive(:run).once.with("subscription-manager register", {:params=>{"--username="=>"SomeUser", "--password="=>"SomePass", "--org="=>"IT", "--proxy="=>"1.2.3.4", "--proxyuser="=>"ProxyUser", "--proxypassword="=>"ProxyPass", "--serverurl="=>"192.168.1.1"}}).and_return(0) + described_class.new.register( :username => "SomeUser", :password => "SomePass", :org => "IT", @@ -37,14 +37,14 @@ end end - it ".subscribe" do - described_class.should_receive(:run).once.with("subscription-manager attach", {:params=>[["--pool", 123], ["--pool", 456]]}) - described_class.subscribe({:pools => [123, 456]}) + it "#subscribe" do + described_class.any_instance.should_receive(:run).once.with("subscription-manager attach", {:params=>[["--pool", 123], ["--pool", 456]]}) + described_class.new.subscribe({:pools => [123, 456]}) end - it ".available_subscriptions" do - described_class.should_receive(:run).once.with("subscription-manager list --all --available", :return_output => true).and_return(sample_output("subscription_manager/output_list_all_available")) - expect(described_class.available_subscriptions).to eq({ + it "#available_subscriptions" do + described_class.any_instance.should_receive(:run).once.with("subscription-manager list --all --available", :return_output => true).and_return(sample_output("subscription_manager/output_list_all_available")) + expect(described_class.new.available_subscriptions).to eq({ "82c042fca983889b10178893f29b06e3" => { :subscription_name => "Example Subscription", :sku => "SER0123", @@ -92,8 +92,8 @@ }) end - it ".organizations" do - described_class.should_receive(:run).once.with("subscription-manager orgs", {:params=>{"--username="=>"SomeUser", "--password="=>"SomePass", "--proxy="=>"1.2.3.4", "--proxyuser="=>"ProxyUser", "--proxypassword="=>"ProxyPass", "--serverurl="=>"192.168.1.1"}, :return_output => true}).and_return(sample_output("subscription_manager/output_orgs")) - expect(described_class.organizations({:username=>"SomeUser", :password=>"SomePass", :proxy_address=>"1.2.3.4", :proxy_username=>"ProxyUser", :proxy_password=>"ProxyPass", :server_url=>"192.168.1.1"})).to eq({"SomeOrg"=>{:name=>"SomeOrg", :key=>"1234567"}}) + it "#organizations" do + described_class.any_instance.should_receive(:run).once.with("subscription-manager orgs", {:params=>{"--username="=>"SomeUser", "--password="=>"SomePass", "--proxy="=>"1.2.3.4", "--proxyuser="=>"ProxyUser", "--proxypassword="=>"ProxyPass", "--serverurl="=>"192.168.1.1"}, :return_output => true}).and_return(sample_output("subscription_manager/output_orgs")) + expect(described_class.new.organizations({:username=>"SomeUser", :password=>"SomePass", :proxy_address=>"1.2.3.4", :proxy_username=>"ProxyUser", :proxy_password=>"ProxyPass", :server_url=>"192.168.1.1"})).to eq({"SomeOrg"=>{:name=>"SomeOrg", :key=>"1234567"}}) end end From 1d9d4cd1f9f69f0cd46800c5b74cb429029b0f6d Mon Sep 17 00:00:00 2001 From: Brandon Dunne Date: Wed, 14 Aug 2013 15:19:31 -0400 Subject: [PATCH 6/6] Move subclasses into a folder --- lib/linux_admin/{ => registration_system}/rhn.rb | 0 lib/linux_admin/{ => registration_system}/subscription_manager.rb | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename lib/linux_admin/{ => registration_system}/rhn.rb (100%) rename lib/linux_admin/{ => registration_system}/subscription_manager.rb (100%) diff --git a/lib/linux_admin/rhn.rb b/lib/linux_admin/registration_system/rhn.rb similarity index 100% rename from lib/linux_admin/rhn.rb rename to lib/linux_admin/registration_system/rhn.rb diff --git a/lib/linux_admin/subscription_manager.rb b/lib/linux_admin/registration_system/subscription_manager.rb similarity index 100% rename from lib/linux_admin/subscription_manager.rb rename to lib/linux_admin/registration_system/subscription_manager.rb