right_agent 1.0.1 → 2.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +10 -8
- data/Rakefile +31 -5
- data/lib/right_agent.rb +6 -1
- data/lib/right_agent/actor.rb +4 -20
- data/lib/right_agent/actors/agent_manager.rb +1 -1
- data/lib/right_agent/agent.rb +357 -144
- data/lib/right_agent/agent_config.rb +7 -6
- data/lib/right_agent/agent_identity.rb +13 -11
- data/lib/right_agent/agent_tag_manager.rb +60 -64
- data/{spec/results_mock.rb → lib/right_agent/clients.rb} +10 -24
- data/lib/right_agent/clients/api_client.rb +383 -0
- data/lib/right_agent/clients/auth_client.rb +247 -0
- data/lib/right_agent/clients/balanced_http_client.rb +369 -0
- data/lib/right_agent/clients/base_retry_client.rb +495 -0
- data/lib/right_agent/clients/right_http_client.rb +279 -0
- data/lib/right_agent/clients/router_client.rb +493 -0
- data/lib/right_agent/command/command_io.rb +4 -4
- data/lib/right_agent/command/command_parser.rb +2 -2
- data/lib/right_agent/command/command_runner.rb +1 -1
- data/lib/right_agent/connectivity_checker.rb +179 -0
- data/lib/right_agent/core_payload_types/secure_document_location.rb +2 -2
- data/lib/right_agent/dispatcher.rb +12 -10
- data/lib/right_agent/enrollment_result.rb +16 -12
- data/lib/right_agent/exceptions.rb +34 -20
- data/lib/right_agent/history.rb +10 -5
- data/lib/right_agent/log.rb +5 -5
- data/lib/right_agent/minimal.rb +1 -0
- data/lib/right_agent/multiplexer.rb +1 -1
- data/lib/right_agent/offline_handler.rb +270 -0
- data/lib/right_agent/packets.rb +7 -7
- data/lib/right_agent/payload_formatter.rb +1 -1
- data/lib/right_agent/pending_requests.rb +128 -0
- data/lib/right_agent/platform.rb +1 -1
- data/lib/right_agent/protocol_version_mixin.rb +69 -0
- data/lib/right_agent/{idempotent_request.rb → retryable_request.rb} +7 -7
- data/lib/right_agent/scripts/agent_controller.rb +28 -26
- data/lib/right_agent/scripts/agent_deployer.rb +37 -22
- data/lib/right_agent/scripts/common_parser.rb +10 -3
- data/lib/right_agent/secure_identity.rb +1 -1
- data/lib/right_agent/sender.rb +299 -785
- data/lib/right_agent/serialize/secure_serializer.rb +3 -1
- data/lib/right_agent/serialize/secure_serializer_initializer.rb +2 -2
- data/lib/right_agent/serialize/serializable.rb +8 -3
- data/right_agent.gemspec +49 -18
- data/spec/agent_config_spec.rb +7 -7
- data/spec/agent_identity_spec.rb +7 -4
- data/spec/agent_spec.rb +43 -7
- data/spec/agent_tag_manager_spec.rb +72 -83
- data/spec/clients/api_client_spec.rb +423 -0
- data/spec/clients/auth_client_spec.rb +272 -0
- data/spec/clients/balanced_http_client_spec.rb +576 -0
- data/spec/clients/base_retry_client_spec.rb +635 -0
- data/spec/clients/router_client_spec.rb +594 -0
- data/spec/clients/spec_helper.rb +111 -0
- data/spec/command/command_io_spec.rb +1 -1
- data/spec/command/command_parser_spec.rb +1 -1
- data/spec/connectivity_checker_spec.rb +83 -0
- data/spec/dispatcher_spec.rb +3 -2
- data/spec/enrollment_result_spec.rb +2 -2
- data/spec/history_spec.rb +51 -39
- data/spec/offline_handler_spec.rb +340 -0
- data/spec/pending_requests_spec.rb +136 -0
- data/spec/{idempotent_request_spec.rb → retryable_request_spec.rb} +73 -73
- data/spec/sender_spec.rb +835 -1052
- data/spec/serialize/secure_serializer_spec.rb +3 -2
- data/spec/spec_helper.rb +54 -1
- metadata +71 -12
@@ -26,6 +26,8 @@ module RightScale
|
|
26
26
|
# X.509 certificate signing
|
27
27
|
class SecureSerializer
|
28
28
|
|
29
|
+
include ProtocolVersionMixin
|
30
|
+
|
29
31
|
class MissingPrivateKey < Exception; end
|
30
32
|
class MissingCertificate < Exception; end
|
31
33
|
class InvalidSignature < Exception; end
|
@@ -90,7 +92,7 @@ module RightScale
|
|
90
92
|
# Exception:: If certificate identity, certificate store, certificate, or private key missing
|
91
93
|
def dump(obj, encrypt = nil)
|
92
94
|
must_encrypt = encrypt || @encrypt
|
93
|
-
serialize_format = if obj.respond_to?(:send_version) && obj.send_version
|
95
|
+
serialize_format = if obj.respond_to?(:send_version) && can_handle_msgpack_result?(obj.send_version)
|
94
96
|
@serializer.format
|
95
97
|
else
|
96
98
|
:json
|
@@ -36,8 +36,8 @@ module RightScale
|
|
36
36
|
def self.init(agent_type, agent_id)
|
37
37
|
cert = Certificate.load(AgentConfig.certs_file("#{agent_type}.cert"))
|
38
38
|
key = RsaKeyPair.load(AgentConfig.certs_file("#{agent_type}.key"))
|
39
|
-
|
40
|
-
store = StaticCertificateStore.new(cert, key,
|
39
|
+
router_cert = Certificate.load(AgentConfig.certs_file("router.cert"))
|
40
|
+
store = StaticCertificateStore.new(cert, key, router_cert, router_cert)
|
41
41
|
SecureSerializer.init(Serializer.new, agent_id, store)
|
42
42
|
true
|
43
43
|
end
|
@@ -128,6 +128,7 @@ module RightScale
|
|
128
128
|
|
129
129
|
# Symbolize keys of hash, use when retrieving hashes that use symbols
|
130
130
|
# for keys as JSON and MessagePack serialization will produce strings instead
|
131
|
+
# Simply return any object that is not a hash as is
|
131
132
|
#
|
132
133
|
# === Parameters
|
133
134
|
# hash(Hash):: Hash whose keys are to be symbolized
|
@@ -135,9 +136,13 @@ module RightScale
|
|
135
136
|
# === Return
|
136
137
|
# (Hash):: Hash with same values but symbol keys
|
137
138
|
def self.symbolize_keys(hash)
|
138
|
-
hash.
|
139
|
-
|
140
|
-
|
139
|
+
if hash.is_a?(Hash)
|
140
|
+
hash.inject({}) do |h, (key, value)|
|
141
|
+
h[(key.to_sym rescue key) || key] = value
|
142
|
+
h
|
143
|
+
end
|
144
|
+
else
|
145
|
+
hash
|
141
146
|
end
|
142
147
|
end
|
143
148
|
|
data/right_agent.gemspec
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# -*-ruby-*-
|
2
|
-
# Copyright: Copyright (c) 2011 RightScale, Inc.
|
2
|
+
# Copyright: Copyright (c) 2011-2013 RightScale, Inc.
|
3
3
|
#
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining
|
5
5
|
# a copy of this software and associated documentation files (the
|
@@ -21,11 +21,12 @@
|
|
21
21
|
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
22
|
|
23
23
|
require 'rubygems'
|
24
|
+
require 'rbconfig'
|
24
25
|
|
25
26
|
Gem::Specification.new do |spec|
|
26
27
|
spec.name = 'right_agent'
|
27
|
-
spec.version = '
|
28
|
-
spec.date = '
|
28
|
+
spec.version = '2.0.7'
|
29
|
+
spec.date = '2014-02-28'
|
29
30
|
spec.authors = ['Lee Kirchhoff', 'Raphael Simon', 'Tony Spataro', 'Scott Messier']
|
30
31
|
spec.email = 'lee@rightscale.com'
|
31
32
|
spec.homepage = 'https://github.com/rightscale/right_agent'
|
@@ -39,29 +40,59 @@ Gem::Specification.new do |spec|
|
|
39
40
|
|
40
41
|
spec.add_dependency('right_support', ['>= 2.4.1', '< 3.0'])
|
41
42
|
spec.add_dependency('right_amqp', '~> 0.7')
|
43
|
+
spec.add_dependency('rest-client', '1.7.0.alpha')
|
44
|
+
spec.add_dependency('faye-websocket', '0.7.0')
|
42
45
|
spec.add_dependency('eventmachine', ['>= 0.12.10', '< 2.0'])
|
43
46
|
spec.add_dependency('net-ssh', '~> 2.0')
|
44
47
|
|
45
|
-
#
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
48
|
+
# TEAL HACK: rake gem may override current RUBY_PLATFORM to allow building
|
49
|
+
# gems for all supported platforms from any platform. rubygems 1.8.x makes it
|
50
|
+
# necessary to produce platform-specific gems with context-sensitive gemspecs
|
51
|
+
# in order to retain Windows (or Linux)-specific gem requirements. this works
|
52
|
+
# from any platform because there is no native code to pre-compile and package
|
53
|
+
# with this gem.
|
54
|
+
gem_platform = defined?(::RightScale::MultiPlatformGemTask.gem_platform_override) ?
|
55
|
+
::RightScale::MultiPlatformGemTask.gem_platform_override :
|
56
|
+
nil
|
57
|
+
gem_platform ||= ::RbConfig::CONFIG['host_os']
|
58
|
+
case gem_platform
|
59
|
+
when /mswin/i
|
60
|
+
spec.add_dependency('win32-api', ['>= 1.4.5', '< 1.4.7'])
|
61
|
+
spec.add_dependency('win32-dir', '~> 0.3.5')
|
62
|
+
spec.add_dependency('win32-process', '~> 0.6.1')
|
63
|
+
spec.add_dependency('msgpack', ['>= 0.4.4', '< 0.5'])
|
64
|
+
spec.add_dependency('json', '1.4.6')
|
65
|
+
spec.platform = 'x86-mswin32-60'
|
66
|
+
when /mingw/i
|
67
|
+
spec.add_dependency('ffi')
|
68
|
+
spec.add_dependency('win32-dir', '>= 0.3.5')
|
69
|
+
spec.add_dependency('win32-process', '>= 0.6.1')
|
70
|
+
spec.add_dependency('msgpack', ['>= 0.4.4', '< 0.6'])
|
71
|
+
spec.add_dependency('json', '~> 1.4')
|
72
|
+
spec.platform = 'x86-mingw32'
|
73
|
+
when /win32|dos|cygwin|windows/i
|
52
74
|
raise ::NotImplementedError, 'Unsupported Ruby-on-Windows variant'
|
75
|
+
else
|
76
|
+
# ffi is not currently needed by Linux but it does no harm to have it and it
|
77
|
+
# allows bundler to generate a consistent Gemfile.lock when it is declared
|
78
|
+
# for both mingw and Linux.
|
79
|
+
spec.add_dependency('ffi')
|
80
|
+
spec.add_dependency('msgpack', ['>= 0.4.4', '< 0.6'])
|
81
|
+
spec.add_dependency('json', '~> 1.4')
|
53
82
|
end
|
54
|
-
spec.add_dependency('msgpack', ['>= 0.4.4', '< 0.6'])
|
55
|
-
spec.add_dependency('json', '~> 1.4')
|
56
83
|
|
57
84
|
spec.description = <<-EOF
|
58
85
|
RightAgent provides a foundation for running an agent on a server to interface
|
59
|
-
in a secure fashion with other agents in the RightScale system
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
86
|
+
in a secure fashion with other agents in the RightScale system using RightNet,
|
87
|
+
which operates in either HTTP or AMQP mode. When using HTTP, RightAgent
|
88
|
+
makes requests to RightApi servers and receives requests using long-polling or
|
89
|
+
WebSockets via the RightNet router. To respond to requests it posts to the
|
90
|
+
HTTP router. When using AMQP, RightAgent uses RabbitMQ as the message bus and
|
91
|
+
the RightNet router as the routing node to make requests; to receives requests
|
92
|
+
routed to it by the RightNet router, it establishes a queue on startup. The
|
93
|
+
packets are structured to invoke services in the agent represented by actors
|
94
|
+
and methods. The RightAgent may respond to these requests with a result packet
|
95
|
+
that the router then routes to the originator.
|
65
96
|
EOF
|
66
97
|
|
67
98
|
candidates = Dir.glob("{lib,spec}/**/*") +
|
data/spec/agent_config_spec.rb
CHANGED
@@ -43,10 +43,10 @@ describe RightScale::AgentConfig do
|
|
43
43
|
@actors = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'right_agent', 'actors'))
|
44
44
|
FileUtils.mkdir_p(@certs1 = File.join(@root_dir1, 'certs'))
|
45
45
|
FileUtils.mkdir_p(@certs2 = File.join(@root_dir2, 'certs'))
|
46
|
-
FileUtils.touch([@
|
47
|
-
FileUtils.touch([@
|
46
|
+
FileUtils.touch([@router_cert1 = File.join(@certs1, 'router.cert')])
|
47
|
+
FileUtils.touch([@router_cert2 = File.join(@certs2, 'router.cert')])
|
48
48
|
FileUtils.touch([@agent_cert2 = File.join(@certs2, 'agent.cert')])
|
49
|
-
FileUtils.touch([@
|
49
|
+
FileUtils.touch([@router_key2 = File.join(@certs2, 'router.key')])
|
50
50
|
FileUtils.mkdir_p(@lib1 = File.join(@root_dir1, 'lib'))
|
51
51
|
FileUtils.mkdir_p(@scripts3 = File.join(@root_dir3, 'scripts'))
|
52
52
|
FileUtils.mkdir_p(@cfg_dir = File.join(@test_dir, 'cfg'))
|
@@ -150,15 +150,15 @@ describe RightScale::AgentConfig do
|
|
150
150
|
|
151
151
|
it 'should return first certs file path found' do
|
152
152
|
@agent_config.root_dir = [@root_dir1, @root_dir2, @root_dir3]
|
153
|
-
@agent_config.certs_file('
|
154
|
-
@agent_config.certs_file('
|
153
|
+
@agent_config.certs_file('router.cert').should == @router_cert1
|
154
|
+
@agent_config.certs_file('router.key').should == @router_key2
|
155
155
|
@agent_config.certs_file('agent.key').should be_nil
|
156
156
|
end
|
157
157
|
|
158
158
|
it 'should return all certs file paths found without any duplicates and by root directory order' do
|
159
159
|
@agent_config.root_dir = [@root_dir1, @root_dir2, @root_dir3]
|
160
|
-
@agent_config.certs_files('*.cert').should == [@
|
161
|
-
@agent_config.certs_files('*.key').should == [@
|
160
|
+
@agent_config.certs_files('*.cert').should == [@router_cert1, @agent_cert2]
|
161
|
+
@agent_config.certs_files('*.key').should == [@router_key2]
|
162
162
|
@agent_config.certs_files('*.abc').should == []
|
163
163
|
end
|
164
164
|
|
data/spec/agent_identity_spec.rb
CHANGED
@@ -56,20 +56,23 @@ describe RightScale::AgentIdentity do
|
|
56
56
|
RightScale::AgentIdentity.valid?(id.to_s).should be_true
|
57
57
|
end
|
58
58
|
|
59
|
-
it "should treat serialized id with nanite or
|
59
|
+
it "should treat serialized id with nanite, mapper, or router prefix as valid" do
|
60
60
|
RightScale::AgentIdentity.valid?("nanite-prefix-agent_type-token-1").should be_true
|
61
61
|
RightScale::AgentIdentity.valid?("mapper-prefix-agent_type-token-1").should be_true
|
62
|
+
RightScale::AgentIdentity.valid?("router-prefix-agent_type-token-1").should be_true
|
62
63
|
end
|
63
64
|
|
64
|
-
it "should parse serialized id with nanite or
|
65
|
+
it "should parse serialized id with nanite, mapper, or router prefix but discard this prefix" do
|
65
66
|
RightScale::AgentIdentity.parse("nanite-prefix-agent_type-token-1").to_s.should == "prefix-agent_type-token-1"
|
66
67
|
RightScale::AgentIdentity.parse("mapper-prefix-agent_type-token-1").to_s.should == "prefix-agent_type-token-1"
|
68
|
+
RightScale::AgentIdentity.parse("router-prefix-agent_type-token-1").to_s.should == "prefix-agent_type-token-1"
|
67
69
|
end
|
68
70
|
|
69
71
|
it 'should prefix with nanite to make backward compatible' do
|
70
72
|
id = RightScale::AgentIdentity.new('prefix', 'agent_type', 1, 'token')
|
71
|
-
RightScale::AgentIdentity.compatible_serialized(id.to_s,
|
72
|
-
RightScale::AgentIdentity.compatible_serialized(id.to_s,
|
73
|
+
RightScale::AgentIdentity.compatible_serialized(id.to_s, version_can_handle_non_nanite_ids).should == "prefix-agent_type-token-1"
|
74
|
+
RightScale::AgentIdentity.compatible_serialized(id.to_s, version_cannot_handle_non_nanite_ids).should == "nanite-prefix-agent_type-token-1"
|
75
|
+
RightScale::AgentIdentity.compatible_serialized(id.to_s).should == "prefix-agent_type-token-1"
|
73
76
|
end
|
74
77
|
|
75
78
|
end
|
data/spec/agent_spec.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#
|
2
|
-
# Copyright (c) 2009-
|
2
|
+
# Copyright (c) 2009-2013 RightScale Inc
|
3
3
|
#
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining
|
5
5
|
# a copy of this software and associated documentation files (the
|
@@ -309,7 +309,7 @@ describe RightScale::Agent do
|
|
309
309
|
@agent.instance_variable_get(:@remaining_queue_setup).should == {@identity => @broker_ids.last(1)}
|
310
310
|
@sender.should_receive(:send_push).with("/registrar/connect", {:agent_identity => @identity, :host => "123",
|
311
311
|
:port => 2, :id => 1, :priority => 1}).once
|
312
|
-
@agent.
|
312
|
+
@agent.send(:check_status)
|
313
313
|
end
|
314
314
|
end
|
315
315
|
|
@@ -539,6 +539,38 @@ describe RightScale::Agent do
|
|
539
539
|
end
|
540
540
|
end
|
541
541
|
|
542
|
+
it "should sleep before an abnormal termination that is following a crash" do
|
543
|
+
run_in_em do
|
544
|
+
@agent = RightScale::Agent.new(:user => "me", :identity => @identity)
|
545
|
+
@broker.should_receive(:nil?).and_return(true)
|
546
|
+
@log.should_receive(:error).with(/Terminating because just because/, Exception, :trace).once
|
547
|
+
@log.should_receive(:info).with(/Delaying termination for 10 sec/).once.ordered
|
548
|
+
@log.should_receive(:info).with(/Terminating immediately/).once.ordered
|
549
|
+
now = Time.now
|
550
|
+
flexmock(Time).should_receive(:now).and_return(now)
|
551
|
+
flexmock(@agent.instance_variable_get(:@history)).should_receive(:analyze_service).
|
552
|
+
and_return({:last_crashed => true, :last_crash_time => now.to_i - 5}).once
|
553
|
+
flexmock(@agent).should_receive(:sleep).with(10).once
|
554
|
+
@agent.terminate("just because", Exception.new("error"))
|
555
|
+
end
|
556
|
+
end
|
557
|
+
|
558
|
+
it "should limit the sleep time before an abnormal termination" do
|
559
|
+
run_in_em do
|
560
|
+
@agent = RightScale::Agent.new(:user => "me", :identity => @identity)
|
561
|
+
@broker.should_receive(:nil?).and_return(true)
|
562
|
+
@log.should_receive(:error).with(/Terminating because just because/, Exception, :trace).once
|
563
|
+
@log.should_receive(:info).with(/Delaying termination for 60 min 0 sec/).once.ordered
|
564
|
+
@log.should_receive(:info).with(/Terminating immediately/).once.ordered
|
565
|
+
now = Time.now
|
566
|
+
flexmock(Time).should_receive(:now).and_return(now)
|
567
|
+
flexmock(@agent.instance_variable_get(:@history)).should_receive(:analyze_service).
|
568
|
+
and_return({:last_crashed => true, :last_crash_time => now.to_i - 1801}).once
|
569
|
+
flexmock(@agent).should_receive(:sleep).with(3600).once
|
570
|
+
@agent.terminate("just because", Exception.new("error"))
|
571
|
+
end
|
572
|
+
end
|
573
|
+
|
542
574
|
it "should close unusable broker connections at start of termination" do
|
543
575
|
@broker.should_receive(:unusable).and_return(["rs-broker-123-1"]).once
|
544
576
|
@broker.should_receive(:close_one).with("rs-broker-123-1", false).once
|
@@ -611,11 +643,13 @@ describe RightScale::Agent do
|
|
611
643
|
@broker.should_receive(:close).and_yield.once
|
612
644
|
flexmock(EM::Timer).should_receive(:new).with(20, Proc).and_return(@timer).and_yield.once
|
613
645
|
run_in_em do
|
646
|
+
called = 0
|
647
|
+
callback = lambda { called += 1}
|
614
648
|
@agent = RightScale::Agent.new(:user => "me", :identity => @identity)
|
649
|
+
@agent.instance_variable_set(:@terminate_callback, callback)
|
615
650
|
flexmock(@agent).should_receive(:load_actors).and_return(true)
|
616
651
|
@agent.run
|
617
|
-
|
618
|
-
@agent.terminate { called += 1 }
|
652
|
+
@agent.terminate
|
619
653
|
called.should == 1
|
620
654
|
end
|
621
655
|
end
|
@@ -647,13 +681,15 @@ describe RightScale::Agent do
|
|
647
681
|
@timer.should_receive(:cancel).once
|
648
682
|
@periodic_timer.should_receive(:cancel).once
|
649
683
|
run_in_em do
|
684
|
+
called = 0
|
685
|
+
callback = lambda { called += 1}
|
650
686
|
@agent = RightScale::Agent.new(:user => "me", :identity => @identity)
|
687
|
+
@agent.instance_variable_set(:@terminate_callback, callback)
|
651
688
|
flexmock(@agent).should_receive(:load_actors).and_return(true)
|
652
689
|
@agent.run
|
653
|
-
|
654
|
-
@agent.terminate { called += 1 }
|
690
|
+
@agent.terminate
|
655
691
|
called.should == 0
|
656
|
-
@agent.terminate
|
692
|
+
@agent.terminate
|
657
693
|
called.should == 1
|
658
694
|
end
|
659
695
|
end
|
@@ -29,18 +29,18 @@ describe RightScale::AgentTagManager do
|
|
29
29
|
before(:each) do
|
30
30
|
@log = flexmock(RightScale::Log)
|
31
31
|
@log.should_receive(:error).by_default.and_return { |m| raise RightScale::Log.format(*m) }
|
32
|
-
@identity = "rs-agent-
|
33
|
-
@
|
34
|
-
@
|
35
|
-
@
|
36
|
-
@
|
32
|
+
@identity = "rs-agent-1-1"
|
33
|
+
@agent_href = "/api/clouds/1/instances/1"
|
34
|
+
@agent_href2 = "/api/clouds/2/instances/2"
|
35
|
+
@agent = flexmock("agent", :self_href => @agent_href, :identity => @identity)
|
36
|
+
@hrefs = [@agent_href, @agent_href2]
|
37
37
|
@manager = RightScale::AgentTagManager.instance
|
38
38
|
@manager.agent = @agent
|
39
39
|
@request = flexmock("request", :run => true)
|
40
40
|
@request.should_receive(:callback).and_yield("result").by_default
|
41
41
|
@request.should_receive(:errback).by_default
|
42
42
|
@request.should_receive(:raw_response).and_return("raw response").by_default
|
43
|
-
@
|
43
|
+
@retryable_request = flexmock(RightScale::RetryableRequest)
|
44
44
|
@tag = "some:tag=value"
|
45
45
|
@tag1 = "other:tag=value"
|
46
46
|
@tags = [@tag, @tag1]
|
@@ -50,13 +50,12 @@ describe RightScale::AgentTagManager do
|
|
50
50
|
context :tags do
|
51
51
|
|
52
52
|
before(:each) do
|
53
|
-
@
|
54
|
-
|
55
|
-
{}).and_return(@request).once.by_default
|
53
|
+
@retryable_request.should_receive(:new).with("/router/query_tags",
|
54
|
+
{:agent_identity => @identity, :hrefs => [@agent_href]}, {}).and_return(@request).once.by_default
|
56
55
|
end
|
57
56
|
|
58
57
|
it "retrieves current agent tags" do
|
59
|
-
@request.should_receive(:callback).and_yield({@
|
58
|
+
@request.should_receive(:callback).and_yield({@agent_href => {"tags" => [@tag]}}).once
|
60
59
|
@manager.tags { |r| @result = r }
|
61
60
|
@result.should == [@tag]
|
62
61
|
end
|
@@ -81,10 +80,9 @@ describe RightScale::AgentTagManager do
|
|
81
80
|
end
|
82
81
|
|
83
82
|
it "forwards timeout option" do
|
84
|
-
@
|
85
|
-
|
86
|
-
|
87
|
-
@request.should_receive(:callback).and_yield({@identity => {"tags" => [@tag]}}).once
|
83
|
+
@retryable_request.should_receive(:new).with("/router/query_tags",
|
84
|
+
{:agent_identity => @identity, :hrefs => [@agent_href]}, {:timeout => 9}).and_return(@request).once
|
85
|
+
@request.should_receive(:callback).and_yield({@agent_href => {"tags" => [@tag]}}).once
|
88
86
|
@manager.tags(:timeout => 9) { |r| @result = r }
|
89
87
|
@result.should == [@tag]
|
90
88
|
end
|
@@ -101,27 +99,24 @@ describe RightScale::AgentTagManager do
|
|
101
99
|
context :query_tags do
|
102
100
|
|
103
101
|
it "queries for agents having individual tag" do
|
104
|
-
@
|
105
|
-
|
106
|
-
|
107
|
-
@request.should_receive(:callback).and_yield({@identity => {"tags" => [@tag]}, @agent_id1 => {"tags" => [@tag]}}).once
|
102
|
+
@retryable_request.should_receive(:new).with("/router/query_tags",
|
103
|
+
{:agent_identity => @identity, :tags => [@tag]}, {}).and_return(@request).once
|
104
|
+
@request.should_receive(:callback).and_yield({@identity => {"tags" => [@tag]}, @agent_href => {"tags" => [@tag]}}).once
|
108
105
|
@manager.query_tags(@tag) { |r| @result = r }
|
109
|
-
@result.should == {@identity => {"tags" => [@tag]}, @
|
106
|
+
@result.should == {@identity => {"tags" => [@tag]}, @agent_href => {"tags" => [@tag]}}
|
110
107
|
end
|
111
108
|
|
112
109
|
it "queries for agents having multiple tags" do
|
113
|
-
@
|
114
|
-
|
115
|
-
|
116
|
-
@request.should_receive(:callback).and_yield({@agent_id1 => {"tags" => @tags}}).once
|
110
|
+
@retryable_request.should_receive(:new).with("/router/query_tags",
|
111
|
+
{:agent_identity => @identity, :tags => @tags}, {}).and_return(@request).once
|
112
|
+
@request.should_receive(:callback).and_yield({@agent_href => {"tags" => @tags}}).once
|
117
113
|
@manager.query_tags(@tags) { |r| @result = r }
|
118
|
-
@result.should == {@
|
114
|
+
@result.should == {@agent_href => {"tags" => @tags}}
|
119
115
|
end
|
120
116
|
|
121
117
|
it "forwards options" do
|
122
|
-
@
|
123
|
-
|
124
|
-
{:timeout => 9}).and_return(@request).once
|
118
|
+
@retryable_request.should_receive(:new).with("/router/query_tags",
|
119
|
+
{:agent_identity => @identity, :tags => @tags}, {:timeout => 9}).and_return(@request).once
|
125
120
|
@request.should_receive(:callback).and_yield({@identity => {"tags" => [@tag]}}).once
|
126
121
|
@request.should_receive(:raw_response).and_return("raw response").once
|
127
122
|
@manager.query_tags(@tags, :raw => true, :timeout => 9) { |r| @result = r }
|
@@ -129,9 +124,8 @@ describe RightScale::AgentTagManager do
|
|
129
124
|
end
|
130
125
|
|
131
126
|
it "yields error result and logs error" do
|
132
|
-
@
|
133
|
-
|
134
|
-
{}).and_return(@request).once
|
127
|
+
@retryable_request.should_receive(:new).with("/router/query_tags",
|
128
|
+
{:agent_identity => @identity, :tags => [@tag]}, {}).and_return(@request).once
|
135
129
|
@log.should_receive(:error).with(/Failed to query tags/).once
|
136
130
|
@request.should_receive(:errback).and_yield("error").once
|
137
131
|
@request.should_receive(:callback).once
|
@@ -147,45 +141,40 @@ describe RightScale::AgentTagManager do
|
|
147
141
|
end
|
148
142
|
|
149
143
|
it "always yields raw response" do
|
150
|
-
@
|
151
|
-
|
152
|
-
|
153
|
-
@request.should_receive(:callback).and_yield({@identity => {"tags" => [@tag]}, @agent_id1 => {"tags" => [@tag]}}).once
|
144
|
+
@retryable_request.should_receive(:new).with("/router/query_tags",
|
145
|
+
{:agent_identity => @identity, :tags => [@tag]}, {}).and_return(@request).once
|
146
|
+
@request.should_receive(:callback).and_yield({@identity => {"tags" => [@tag]}, @agent_href => {"tags" => [@tag]}}).once
|
154
147
|
@manager.query_tags_raw(@tag) { |r| @result = r }
|
155
148
|
@result.should == "raw response"
|
156
149
|
end
|
157
150
|
|
158
151
|
it "queries for agents having individual tag and always yields raw response" do
|
159
|
-
@
|
160
|
-
|
161
|
-
|
162
|
-
@request.should_receive(:callback).and_yield({@identity => {"tags" => [@tag]}, @agent_id1 => {"tags" => [@tag]}}).once
|
152
|
+
@retryable_request.should_receive(:new).with("/router/query_tags",
|
153
|
+
{:agent_identity => @identity, :tags => [@tag]}, {}).and_return(@request).once
|
154
|
+
@request.should_receive(:callback).and_yield({@identity => {"tags" => [@tag]}, @agent_href => {"tags" => [@tag]}}).once
|
163
155
|
@manager.query_tags_raw(@tag) { |r| @result = r }
|
164
156
|
@result.should == "raw response"
|
165
157
|
end
|
166
158
|
|
167
159
|
it "queries for agents having multiple tags always yields raw response" do
|
168
|
-
@
|
169
|
-
|
170
|
-
|
171
|
-
@request.should_receive(:callback).and_yield({@agent_id1 => {"tags" => @tags}}).once
|
160
|
+
@retryable_request.should_receive(:new).with("/router/query_tags",
|
161
|
+
{:agent_identity => @identity, :tags => @tags}, {}).and_return(@request).once
|
162
|
+
@request.should_receive(:callback).and_yield({@agent_href => {"tags" => @tags}}).once
|
172
163
|
@manager.query_tags_raw(@tags) { |r| @result = r }
|
173
164
|
@result.should == "raw response"
|
174
165
|
end
|
175
166
|
|
176
167
|
it "queries for selected agents" do
|
177
|
-
@
|
178
|
-
|
179
|
-
|
180
|
-
@
|
181
|
-
@manager.query_tags_raw(@tags, @agent_ids) { |r| @result = r }
|
168
|
+
@retryable_request.should_receive(:new).with("/router/query_tags",
|
169
|
+
{:agent_identity => @identity, :hrefs => @hrefs, :tags => @tags}, {}).and_return(@request).once
|
170
|
+
@request.should_receive(:callback).and_yield({@agent_href => {"tags" => @tags}}).once
|
171
|
+
@manager.query_tags_raw(@tags, @hrefs) { |r| @result = r }
|
182
172
|
@result.should == "raw response"
|
183
173
|
end
|
184
174
|
|
185
175
|
it "forwards timeout option" do
|
186
|
-
@
|
187
|
-
|
188
|
-
{:timeout => 9}).and_return(@request).once
|
176
|
+
@retryable_request.should_receive(:new).with("/router/query_tags",
|
177
|
+
{:agent_identity => @identity, :tags => @tags}, {:timeout => 9}).and_return(@request).once
|
189
178
|
@request.should_receive(:callback).and_yield({@identity => {"tags" => [@tag]}}).once
|
190
179
|
@manager.query_tags_raw(@tags, nil, :timeout => 9) { |r| @result = r }
|
191
180
|
@result.should == "raw response"
|
@@ -201,20 +190,17 @@ describe RightScale::AgentTagManager do
|
|
201
190
|
end
|
202
191
|
|
203
192
|
it "adds individual tag to agent" do
|
204
|
-
@
|
205
|
-
{:new_tags => [@tag], :obsolete_tags => []}).and_return(@request).once
|
193
|
+
@retryable_request.should_receive(:new).with("/router/add_tags", {:tags => [@tag]}).and_return(@request).once
|
206
194
|
@manager.add_tags(@tag).should be_true
|
207
195
|
end
|
208
196
|
|
209
197
|
it "adds multiple tags to agent" do
|
210
|
-
@
|
211
|
-
{:new_tags => @tags, :obsolete_tags => []}).and_return(@request).once
|
198
|
+
@retryable_request.should_receive(:new).with("/router/add_tags", {:tags => @tags}).and_return(@request).once
|
212
199
|
@manager.add_tags(@tags).should be_true
|
213
200
|
end
|
214
201
|
|
215
202
|
it "optionally yields raw response" do
|
216
|
-
@
|
217
|
-
{:new_tags => @tags, :obsolete_tags => []}).and_return(@request).once
|
203
|
+
@retryable_request.should_receive(:new).with("/router/add_tags", {:tags => @tags}).and_return(@request).once
|
218
204
|
@request.should_receive(:callback).and_yield("result").once
|
219
205
|
@manager.add_tags(@tags) { |r| @result = r }
|
220
206
|
@result.should == "raw response"
|
@@ -223,8 +209,7 @@ describe RightScale::AgentTagManager do
|
|
223
209
|
it "updates local tags" do
|
224
210
|
@agent.should_receive(:tags).and_return([@tag1]).once
|
225
211
|
@agent.should_receive(:tags=).should_receive([@tag]).once
|
226
|
-
@
|
227
|
-
{:new_tags => [@tag], :obsolete_tags => []}).and_return(@request).once
|
212
|
+
@retryable_request.should_receive(:new).with("/router/add_tags", {:tags => [@tag]}).and_return(@request).once
|
228
213
|
@manager.add_tags(@tag).should be_true
|
229
214
|
end
|
230
215
|
end
|
@@ -238,20 +223,17 @@ describe RightScale::AgentTagManager do
|
|
238
223
|
end
|
239
224
|
|
240
225
|
it "removes individual tag to agent" do
|
241
|
-
@
|
242
|
-
{:new_tags => [], :obsolete_tags => [@tag]}).and_return(@request).once
|
226
|
+
@retryable_request.should_receive(:new).with("/router/delete_tags", {:tags => [@tag]}).and_return(@request).once
|
243
227
|
@manager.remove_tags(@tag).should be_true
|
244
228
|
end
|
245
229
|
|
246
230
|
it "removes multiple tags to agent" do
|
247
|
-
@
|
248
|
-
{:new_tags => [], :obsolete_tags => @tags}).and_return(@request).once
|
231
|
+
@retryable_request.should_receive(:new).with("/router/delete_tags", {:tags => @tags}).and_return(@request).once
|
249
232
|
@manager.remove_tags(@tags).should be_true
|
250
233
|
end
|
251
234
|
|
252
235
|
it "optionally yields raw response" do
|
253
|
-
@
|
254
|
-
{:new_tags => [], :obsolete_tags => @tags}).and_return(@request).once
|
236
|
+
@retryable_request.should_receive(:new).with("/router/delete_tags", {:tags => @tags}).and_return(@request).once
|
255
237
|
@request.should_receive(:callback).and_yield("result").once
|
256
238
|
@manager.remove_tags(@tags) { |r| @result = r }
|
257
239
|
@result.should == "raw response"
|
@@ -260,13 +242,12 @@ describe RightScale::AgentTagManager do
|
|
260
242
|
it "updates local tags" do
|
261
243
|
@agent.should_receive(:tags).and_return([]).once
|
262
244
|
@agent.should_receive(:tags=).should_receive([@tag]).once
|
263
|
-
@
|
264
|
-
{:new_tags => [], :obsolete_tags => [@tag]}).and_return(@request).once
|
245
|
+
@retryable_request.should_receive(:new).with("/router/delete_tags", {:tags => [@tag]}).and_return(@request).once
|
265
246
|
@manager.remove_tags(@tag).should be_true
|
266
247
|
end
|
267
248
|
end
|
268
249
|
|
269
|
-
context :
|
250
|
+
context :do_update do
|
270
251
|
|
271
252
|
before(:each) do
|
272
253
|
@agent.should_receive(:tags).and_return([]).once.by_default
|
@@ -275,42 +256,51 @@ describe RightScale::AgentTagManager do
|
|
275
256
|
it "checks that agent has been set" do
|
276
257
|
@manager.agent = nil
|
277
258
|
@agent.should_receive(:tags).never
|
278
|
-
lambda { @manager.
|
259
|
+
lambda { @manager.send(:do_update, [@tag], []) }.should \
|
260
|
+
raise_error(ArgumentError, "Must set agent= before using tag manager")
|
261
|
+
end
|
262
|
+
|
263
|
+
it "does not allow both add and removal of tags in same request" do
|
264
|
+
@agent.should_receive(:tags).never
|
265
|
+
lambda { @manager.send(:do_update, [@tag], [@tag1]) }.should \
|
266
|
+
raise_error(ArgumentError, "Cannot add and remove tags in same update")
|
267
|
+
end
|
268
|
+
|
269
|
+
it "adds tags for agent" do
|
270
|
+
@retryable_request.should_receive(:new).with("/router/add_tags", {:tags => [@tag]}).and_return(@request).once
|
271
|
+
@agent.should_receive(:tags=).never
|
272
|
+
@manager.send(:do_update, [@tag], []).should be_true
|
279
273
|
end
|
280
274
|
|
281
|
-
it "
|
282
|
-
@
|
283
|
-
{:new_tags => [@tag], :obsolete_tags => [@tag1]}).and_return(@request).once
|
275
|
+
it "removes tags for agent" do
|
276
|
+
@retryable_request.should_receive(:new).with("/router/delete_tags", {:tags => [@tag1]}).and_return(@request).once
|
284
277
|
@agent.should_receive(:tags=).never
|
285
|
-
@manager.
|
278
|
+
@manager.send(:do_update, [], [@tag1]).should be_true
|
286
279
|
end
|
287
280
|
|
288
281
|
it "yields raw response if block given" do
|
289
|
-
@
|
290
|
-
{:new_tags => [@tag], :obsolete_tags => [@tag1]}).and_return(@request).once
|
282
|
+
@retryable_request.should_receive(:new).with("/router/add_tags", {:tags => [@tag]}).and_return(@request).once
|
291
283
|
@request.should_receive(:raw_response).and_return("raw response").once
|
292
284
|
@agent.should_receive(:tags=).once
|
293
|
-
@manager.
|
285
|
+
@manager.send(:do_update, [@tag], []) { |r| @result = r }
|
294
286
|
@result.should == "raw response"
|
295
287
|
end
|
296
288
|
|
297
289
|
it "updates local tags if block given and successful" do
|
298
|
-
@
|
299
|
-
{:new_tags => [@tag], :obsolete_tags => [@tag1]}).and_return(@request).once
|
290
|
+
@retryable_request.should_receive(:new).with("/router/add_tags", {:tags => [@tag]}).and_return(@request).once
|
300
291
|
@request.should_receive(:raw_response).and_return("raw response").once
|
301
292
|
@agent.should_receive(:tags=).with([@tag]).once
|
302
|
-
@manager.
|
293
|
+
@manager.send(:do_update, [@tag], []) { |r| @result = r }
|
303
294
|
@result.should == "raw response"
|
304
295
|
end
|
305
296
|
|
306
297
|
it "yields error result and does not update local tags" do
|
307
|
-
@
|
308
|
-
{:new_tags => [@tag], :obsolete_tags => [@tag1]}).and_return(@request).once
|
298
|
+
@retryable_request.should_receive(:new).with("/router/add_tags", {:tags => [@tag]}).and_return(@request).once
|
309
299
|
@request.should_receive(:raw_response).and_return("error").once
|
310
300
|
@request.should_receive(:errback).and_yield("error").once
|
311
301
|
@request.should_receive(:callback).once
|
312
302
|
@agent.should_receive(:tags=).never
|
313
|
-
@manager.
|
303
|
+
@manager.send(:do_update, [@tag], []) { |r| @result = r }
|
314
304
|
@result.should == "error"
|
315
305
|
end
|
316
306
|
end
|
@@ -321,8 +311,7 @@ describe RightScale::AgentTagManager do
|
|
321
311
|
@request.should_receive(:raw_response).and_return("raw response").once
|
322
312
|
@agent.should_receive(:tags).and_return(@tags).twice
|
323
313
|
@agent.should_receive(:tags=).with([]).once
|
324
|
-
@
|
325
|
-
{:new_tags => [], :obsolete_tags => @tags}).and_return(@request).once
|
314
|
+
@retryable_request.should_receive(:new).with("/router/delete_tags", {:tags => @tags}).and_return(@request).once
|
326
315
|
@manager.clear { |r| @result = r }
|
327
316
|
@result.should == "raw response"
|
328
317
|
end
|