rhn_satellite 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/.rspec +1 -0
  2. data/Gemfile +14 -0
  3. data/Gemfile.lock +30 -0
  4. data/LICENSE.txt +20 -0
  5. data/README.rdoc +94 -0
  6. data/Rakefile +49 -0
  7. data/VERSION +1 -0
  8. data/lib/rhn_satellite.rb +25 -0
  9. data/lib/rhn_satellite/activation_key.rb +5 -0
  10. data/lib/rhn_satellite/api.rb +36 -0
  11. data/lib/rhn_satellite/channel.rb +5 -0
  12. data/lib/rhn_satellite/channel_access.rb +20 -0
  13. data/lib/rhn_satellite/channel_software.rb +20 -0
  14. data/lib/rhn_satellite/common/collection.rb +15 -0
  15. data/lib/rhn_satellite/common/debug.rb +35 -0
  16. data/lib/rhn_satellite/common/misc.rb +24 -0
  17. data/lib/rhn_satellite/connection/base.rb +25 -0
  18. data/lib/rhn_satellite/connection/handler.rb +116 -0
  19. data/lib/rhn_satellite/package.rb +15 -0
  20. data/lib/rhn_satellite/system.rb +83 -0
  21. data/lib/rhn_satellite/systemgroup.rb +34 -0
  22. data/rhn_satellite.gemspec +87 -0
  23. data/spec/spec.opts +6 -0
  24. data/spec/spec_helper.rb +12 -0
  25. data/spec/unit/rhn_satellite/activation_key_spec.rb +58 -0
  26. data/spec/unit/rhn_satellite/api_spec.rb +94 -0
  27. data/spec/unit/rhn_satellite/channel_access_spec.rb +61 -0
  28. data/spec/unit/rhn_satellite/channel_software_spec.rb +65 -0
  29. data/spec/unit/rhn_satellite/channel_spec.rb +58 -0
  30. data/spec/unit/rhn_satellite/common/debug_spec.rb +42 -0
  31. data/spec/unit/rhn_satellite/common/misc_spec.rb +33 -0
  32. data/spec/unit/rhn_satellite/connection/base_spec.rb +44 -0
  33. data/spec/unit/rhn_satellite/connection/handler_spec.rb +229 -0
  34. data/spec/unit/rhn_satellite/package_spec.rb +52 -0
  35. data/spec/unit/rhn_satellite/system_spec.rb +320 -0
  36. data/spec/unit/rhn_satellite/systemgroup_spec.rb +127 -0
  37. metadata +180 -0
@@ -0,0 +1,116 @@
1
+ module RhnSatellite
2
+ module Connection
3
+ class Handler
4
+
5
+ include RhnSatellite::Common::Debug
6
+
7
+ class << self
8
+ attr_accessor :default_hostname,:default_username, :default_password, :default_timeout
9
+
10
+ def instance_for(identifier,hostname=nil,username=nil,password=nil,timeout=nil,https=true)
11
+ instances[identifier] ||= Handler.new(
12
+ hostname||default_hostname,
13
+ username||default_username,
14
+ password||default_password,
15
+ timeout||default_timeout,
16
+ https
17
+ )
18
+ end
19
+
20
+ def reset_instance(identifier)
21
+ instances.delete(identifier)
22
+ end
23
+
24
+ def reset_all
25
+ @instances = {}
26
+ end
27
+
28
+ private
29
+ def instances
30
+ @instances ||= {}
31
+ end
32
+ end
33
+
34
+ def initialize(hostname,username=nil,password=nil,timeout=30,https=true)
35
+ @hostname = hostname
36
+ @username = username
37
+ @password = password
38
+ @timeout = timeout
39
+ @https = https
40
+ end
41
+
42
+ def login(duration=nil)
43
+ @auth_token ||= make_call('auth.login', *[@username, @password, duration].compact)
44
+ end
45
+
46
+ def logout
47
+ make_call('auth.logout',@auth_token) if @auth_token
48
+ true
49
+ ensure
50
+ @auth_token = nil
51
+ end
52
+
53
+
54
+ # Makes a remote call.
55
+ def make_call(*args)
56
+ raise "No connection established on #{@hostname}." unless connected?
57
+
58
+ debug("Remote call: #{args.first} (#{args[1..-1].inspect})")
59
+ result = connection.call(*args)
60
+ debug("Result: #{result}\n")
61
+ result
62
+ end
63
+
64
+ def in_transaction(do_login=false,&blk)
65
+ begin
66
+ begin_transaction
67
+ token = do_login ? login : nil
68
+ result = yield(token)
69
+ logout if do_login
70
+ ensure
71
+ end_transaction
72
+ end
73
+ result
74
+ end
75
+
76
+ def connected?
77
+ !connection.nil?
78
+ end
79
+
80
+ def connect
81
+ debug("Connecting to #{url}")
82
+ @connection = XMLRPC::Client.new2(url,nil,@timeout)
83
+ end
84
+
85
+ def disconnect
86
+ @connection = nil
87
+ end
88
+
89
+ def default_call(cmd,*args)
90
+ in_transaction(true) {|token| make_call(cmd,token,*args) }
91
+ end
92
+
93
+ private
94
+ def begin_transaction
95
+ connect
96
+ end
97
+ # Ends a transaction and disconnects.
98
+ def end_transaction
99
+ @connection = @auth_token = @version = nil
100
+ end
101
+
102
+ def connection
103
+ @connection
104
+ end
105
+
106
+ def url
107
+ @url ||= "#{@https ? 'https' : 'http'}://#{@hostname}#{api_path}"
108
+ end
109
+
110
+ def api_path
111
+ "/rpc/api"
112
+ end
113
+
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,15 @@
1
+ module RhnSatellite
2
+ class Package < RhnSatellite::Connection::Base
3
+ class << self
4
+ def details(package_id)
5
+ base.default_call('package.getDetails',package_id.to_i)
6
+ end
7
+
8
+ def exists?(package_id)
9
+ !details(package_id).nil?
10
+ rescue XMLRPC::FaultException
11
+ false
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,83 @@
1
+ module RhnSatellite
2
+ class System < RhnSatellite::Connection::Base
3
+ collection 'system.listUserSystems'
4
+ class << self
5
+
6
+ def active_systems
7
+ base.default_call('system.listActiveSystems').to_a
8
+ end
9
+
10
+ def details(system_id)
11
+ base.default_call('system.getDetails',system_id.to_i)
12
+ end
13
+
14
+ def online?(server_name)
15
+ !(system = get(server_name)).nil? && \
16
+ !(sysdetails = details(system['id'])).nil? && \
17
+ (sysdetails['osa_status'] == 'online')
18
+ end
19
+
20
+ def active?(server_name)
21
+ active_systems.any?{|system| system["name"] =~ /#{server_name}$/ }
22
+ end
23
+
24
+ def relevant_erratas(system_id)
25
+ base.default_call('system.getRelevantErrata',system_id).to_a
26
+ end
27
+
28
+ def latest_available_packages(system_ids)
29
+ base.default_call('system.listLatestAvailablePackages',system_ids).to_a
30
+ end
31
+
32
+ def latest_installable_packages(system_id)
33
+ base.default_call('system.listLatestInstallablePackages',system_id).to_a
34
+ end
35
+
36
+ def latest_upgradable_packages(system_id)
37
+ base.default_call('system.listLatestUpgradablePackages',system_id).to_a
38
+ end
39
+
40
+ def uptodate?(system_id)
41
+ latest_upgradable_packages(system_id).empty? && relevant_erratas(system_id).empty?
42
+ end
43
+
44
+ def subscribed_base_channel(system_id)
45
+ base.default_call('system.getSubscribedBaseChannel',system_id.to_i)
46
+ end
47
+ def set_base_channel(system_id,channel_label)
48
+ base.default_call('system.setBaseChannel',system_id.to_i,channel_label)
49
+ end
50
+ def subscribable_base_channels(system_id)
51
+ base.default_call('system.listSubscribableBaseChannels',system_id.to_i)
52
+ end
53
+
54
+ def subscribed_child_channels(system_id)
55
+ base.default_call('system.listSubscribedChildChannels',system_id.to_i)
56
+ end
57
+ def set_child_channels(system_id,child_channel_labels)
58
+ base.default_call('system.setChildChannels',system_id.to_i,child_channel_labels)
59
+ end
60
+ def subscribable_child_channels(system_id)
61
+ base.default_call('system.listSubscribableChildChannels',system_id.to_i)
62
+ end
63
+
64
+ def schedule_apply_errata(system_ids,errata_ids,earliest_occurence=nil)
65
+ base.default_call(
66
+ 'system.scheduleApplyErrata',
67
+ *([
68
+ [*system_ids].collect{|i| i.to_i },
69
+ [*errata_ids].collect{|i| i.to_i },
70
+ RhnSatellite::Common::Misc.gen_date_time(earliest_occurence)
71
+ ].compact))
72
+ end
73
+
74
+ def schedule_reboot(system_id,earliest_occurence='now')
75
+ base.default_call('system.scheduleReboot',system_id.to_i,RhnSatellite::Common::Misc.gen_date_time(earliest_occurence))
76
+ end
77
+
78
+ def schedule_package_install(system_id,package_ids,earliest_occurence='now')
79
+ base.default_call('system.schedulePackageInstall',system_id.to_i,package_ids,RhnSatellite::Common::Misc.gen_date_time(earliest_occurence))
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,34 @@
1
+ module RhnSatellite
2
+ class Systemgroup < RhnSatellite::Connection::Base
3
+ collection 'systemgroup.listAllGroups'
4
+
5
+ class << self
6
+ def delete(group_name)
7
+ base.default_call('systemgroup.delete',group_name)
8
+ end
9
+
10
+ def create(group_name, description)
11
+ base.default_call('systemgroup.create',group_name,description)
12
+ end
13
+
14
+ def systems(group_name)
15
+ base.default_call('systemgroup.listSystems',group_name)
16
+ end
17
+
18
+ # if group is not valid an XMLRPC::FaultException is raised
19
+ def systems_safe(group_name)
20
+ systems(group_name)
21
+ rescue XMLRPC::FaultException
22
+ []
23
+ end
24
+
25
+ def remove_systems(group_name,system_ids)
26
+ base.default_call('systemgroup.addOrRemoveSystems',group_name,system_ids,false)
27
+ end
28
+
29
+ def add_systems(group_name,system_ids)
30
+ base.default_call('systemgroup.addOrRemoveSystems',group_name,system_ids,true)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,87 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{rhn_satellite}
8
+ s.version = "0.0.4"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["duritong"]
12
+ s.date = %q{2012-01-05}
13
+ s.description = %q{It provides an easy way to interact with a RedHat Satellite API.}
14
+ s.email = %q{peter.meier@immerda.ch}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".rspec",
21
+ "Gemfile",
22
+ "Gemfile.lock",
23
+ "LICENSE.txt",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "lib/rhn_satellite.rb",
28
+ "lib/rhn_satellite/activation_key.rb",
29
+ "lib/rhn_satellite/api.rb",
30
+ "lib/rhn_satellite/channel.rb",
31
+ "lib/rhn_satellite/channel_access.rb",
32
+ "lib/rhn_satellite/channel_software.rb",
33
+ "lib/rhn_satellite/common/collection.rb",
34
+ "lib/rhn_satellite/common/debug.rb",
35
+ "lib/rhn_satellite/common/misc.rb",
36
+ "lib/rhn_satellite/connection/base.rb",
37
+ "lib/rhn_satellite/connection/handler.rb",
38
+ "lib/rhn_satellite/package.rb",
39
+ "lib/rhn_satellite/system.rb",
40
+ "lib/rhn_satellite/systemgroup.rb",
41
+ "rhn_satellite.gemspec",
42
+ "spec/spec.opts",
43
+ "spec/spec_helper.rb",
44
+ "spec/unit/rhn_satellite/activation_key_spec.rb",
45
+ "spec/unit/rhn_satellite/api_spec.rb",
46
+ "spec/unit/rhn_satellite/channel_access_spec.rb",
47
+ "spec/unit/rhn_satellite/channel_software_spec.rb",
48
+ "spec/unit/rhn_satellite/channel_spec.rb",
49
+ "spec/unit/rhn_satellite/common/debug_spec.rb",
50
+ "spec/unit/rhn_satellite/common/misc_spec.rb",
51
+ "spec/unit/rhn_satellite/connection/base_spec.rb",
52
+ "spec/unit/rhn_satellite/connection/handler_spec.rb",
53
+ "spec/unit/rhn_satellite/package_spec.rb",
54
+ "spec/unit/rhn_satellite/system_spec.rb",
55
+ "spec/unit/rhn_satellite/systemgroup_spec.rb"
56
+ ]
57
+ s.homepage = %q{http://github.com/duritong/ruby-rhn_satellite}
58
+ s.licenses = ["MIT"]
59
+ s.require_paths = ["lib"]
60
+ s.rubygems_version = %q{1.6.2}
61
+ s.summary = %q{RhnSatellite is a ruby api to the RedHat Satellite}
62
+
63
+ if s.respond_to? :specification_version then
64
+ s.specification_version = 3
65
+
66
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
67
+ s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
68
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
69
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
70
+ s.add_development_dependency(%q<rcov>, [">= 0"])
71
+ s.add_development_dependency(%q<mocha>, ["~> 0.9.10"])
72
+ else
73
+ s.add_dependency(%q<rspec>, ["~> 2.3.0"])
74
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
75
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
76
+ s.add_dependency(%q<rcov>, [">= 0"])
77
+ s.add_dependency(%q<mocha>, ["~> 0.9.10"])
78
+ end
79
+ else
80
+ s.add_dependency(%q<rspec>, ["~> 2.3.0"])
81
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
82
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
83
+ s.add_dependency(%q<rcov>, [">= 0"])
84
+ s.add_dependency(%q<mocha>, ["~> 0.9.10"])
85
+ end
86
+ end
87
+
data/spec/spec.opts ADDED
@@ -0,0 +1,6 @@
1
+ --format
2
+ s
3
+ --colour
4
+ --loadby
5
+ mtime
6
+ --backtrace
@@ -0,0 +1,12 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rspec'
4
+ require 'rhn_satellite'
5
+
6
+ # Requires supporting files with custom matchers and macros, etc,
7
+ # # in ./support/ and its subdirectories.
8
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
9
+
10
+ RSpec.configure do |config|
11
+ config.mock_with :mocha
12
+ end
@@ -0,0 +1,58 @@
1
+ #! /usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../../spec_helper'
3
+
4
+ describe RhnSatellite::ActivationKey do
5
+ before(:each) { RhnSatellite::ActivationKey.reset }
6
+
7
+ describe ".all" do
8
+ before(:each) do
9
+ conn = Object.new
10
+ conn.stubs(:call)
11
+
12
+ XMLRPC::Client.stubs(:new2).returns(conn)
13
+
14
+ RhnSatellite::ActivationKey.username = 'user'
15
+ RhnSatellite::ActivationKey.password = 'pwd'
16
+ RhnSatellite::Connection::Handler.any_instance.expects(:make_call).with("auth.login",'user','pwd').returns("token")
17
+ RhnSatellite::Connection::Handler.any_instance.expects(:make_call).with("auth.logout",'token')
18
+ end
19
+ it "logins and returns a bunch of activation keys" do
20
+ RhnSatellite::Connection::Handler.any_instance.expects(:make_call).with("activationkey.listActivationKeys","token").returns(["123","234"])
21
+
22
+ RhnSatellite::ActivationKey.all.should eql(["123","234"])
23
+ end
24
+
25
+ it "returns an empty array on an empty answer" do
26
+ RhnSatellite::Connection::Handler.any_instance.expects(:make_call).with("activationkey.listActivationKeys","token").returns(nil)
27
+
28
+ RhnSatellite::ActivationKey.all.should eql([])
29
+ end
30
+
31
+ it "iterates the items over the block" do
32
+ RhnSatellite::Connection::Handler.any_instance.expects(:make_call).with("activationkey.listActivationKeys","token").returns(["123","234"])
33
+ RhnSatellite::ActivationKey.all{|i| ["123","234"].include?(i).should be_true }.should eql(["123","234"])
34
+ end
35
+ describe ".get" do
36
+ context "with keys" do
37
+ before :each do
38
+ RhnSatellite::Connection::Handler.any_instance.expects(:make_call).with('activationkey.listActivationKeys',"token").returns([{'name' => "123"},{'name' => "234"}])
39
+ end
40
+ it "finds a key in all keys" do
41
+ RhnSatellite::ActivationKey.get('123').should eql({'name' => '123'})
42
+ end
43
+
44
+ it "returns nil on an non-existant key" do
45
+ RhnSatellite::ActivationKey.get('12333').should eql(nil)
46
+ end
47
+ end
48
+ context "without any keys" do
49
+ before :each do
50
+ RhnSatellite::Connection::Handler.any_instance.expects(:make_call).with('activationkey.listActivationKeys',"token").returns([])
51
+ end
52
+ it "returns nil" do
53
+ RhnSatellite::ActivationKey.get('12333').should eql(nil)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,94 @@
1
+ #! /usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../../spec_helper'
3
+
4
+ describe RhnSatellite::Api do
5
+ before(:each) { RhnSatellite::Api.reset }
6
+
7
+ {:api_version => "getVersion", :satellite_version => "systemVersion" }.each do |m,cmd|
8
+ describe ".#{m.to_s}" do
9
+ it "gets the version and disconnects by default" do
10
+ conn = Object.new
11
+ conn.stubs(:call)
12
+
13
+ XMLRPC::Client.expects(:new2).returns(conn)
14
+ RhnSatellite::Connection::Handler.any_instance.expects(:make_call).with("api.#{cmd}").returns("2.0")
15
+
16
+ RhnSatellite::Api.send(m).should eql("2.0")
17
+ RhnSatellite::Api.send(:base).connected?.should eql(false)
18
+ end
19
+
20
+ it "caches the version" do
21
+ conn = Object.new
22
+ conn.stubs(:call)
23
+
24
+ XMLRPC::Client.expects(:new2).returns(conn)
25
+ RhnSatellite::Connection::Handler.any_instance.expects(:make_call).with("api.#{cmd}").once.returns("2.0")
26
+
27
+ RhnSatellite::Api.send(m).should eql("2.0")
28
+ RhnSatellite::Api.send(m).should eql("2.0")
29
+ RhnSatellite::Api.send(:base).connected?.should eql(false)
30
+ end
31
+
32
+ it "does not disconnect if told so" do
33
+ conn = Object.new
34
+ conn.stubs(:call)
35
+
36
+ XMLRPC::Client.expects(:new2).returns(conn)
37
+ RhnSatellite::Connection::Handler.any_instance.expects(:make_call).with("api.#{cmd}").returns("2.0")
38
+
39
+ RhnSatellite::Connection::Handler.any_instance.expects(:disconnect).never
40
+
41
+ RhnSatellite::Api.send(m,false).should eql("2.0")
42
+ RhnSatellite::Api.send(:base).connected?.should eql(true)
43
+ end
44
+ end
45
+ end
46
+ describe ".reset" do
47
+ it "resets the versions" do
48
+ conn = Object.new
49
+ conn.stubs(:call)
50
+
51
+ XMLRPC::Client.stubs(:new2).returns(conn)
52
+ RhnSatellite::Connection::Handler.any_instance.expects(:make_call).with("api.getVersion").returns("2.0")
53
+ RhnSatellite::Connection::Handler.any_instance.expects(:make_call).with("api.systemVersion").returns("2.0")
54
+
55
+ RhnSatellite::Api.api_version.should eql("2.0")
56
+ RhnSatellite::Api.satellite_version.should eql("2.0")
57
+
58
+ RhnSatellite::Api.reset
59
+
60
+ RhnSatellite::Api.instance_variable_get("@api_version").should be_nil
61
+ RhnSatellite::Api.instance_variable_get("@satellite_version").should be_nil
62
+ end
63
+ end
64
+
65
+ describe ".test_connection" do
66
+ it "runs a test login and logout" do
67
+ conn = Object.new
68
+ conn.stubs(:call)
69
+
70
+ XMLRPC::Client.stubs(:new2).returns(conn)
71
+
72
+ RhnSatellite::Api.username = 'user'
73
+ RhnSatellite::Api.password = 'pwd'
74
+ RhnSatellite::Connection::Handler.any_instance.expects(:make_call).with("auth.login",'user','pwd').returns("token")
75
+ RhnSatellite::Connection::Handler.any_instance.expects(:make_call).with("auth.logout",'token')
76
+
77
+ RhnSatellite::Api.test_connection.should eql(true)
78
+ end
79
+
80
+ it "runs a test login and logout with a dediacted user and pwd" do
81
+ conn = Object.new
82
+ conn.stubs(:call)
83
+
84
+ XMLRPC::Client.stubs(:new2).returns(conn)
85
+
86
+ RhnSatellite::Api.username = 'user'
87
+ RhnSatellite::Api.password = 'pwd'
88
+ RhnSatellite::Connection::Handler.any_instance.expects(:make_call).with("auth.login",'user2','pwd2').returns("token")
89
+ RhnSatellite::Connection::Handler.any_instance.expects(:make_call).with("auth.logout",'token')
90
+
91
+ RhnSatellite::Api.test_connection('user2','pwd2').should eql(true)
92
+ end
93
+ end
94
+ end