Class: RightScale::AgentIdentity

Inherits:
Object
  • Object
show all
Includes:
ProtocolVersionMixin
Defined in:
lib/right_agent/agent_identity.rb

Overview

Agent identity management

Constant Summary collapse

SEPARATOR_EPOCH =

Cutover time at which agents began using new separator

Time.at(1256702400)
ID_SEPARATOR =

Separator used to differentiate between identity components when serialized

'-'
ID_SEPARATOR_OLD =

Separator used to differentiate between identity components prior to release 3.4

'*'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ProtocolVersionMixin

#can_always_handle_hash_payload?, #can_handle_http?, #can_handle_msgpack_result?, #can_handle_multicast_result?, #can_handle_non_delivery_result?, #can_handle_non_nanite_ids?, #can_handle_request_retries?, #can_put_version_in_packet?, #can_route_to_response_queue?, #can_use_router_query_tags?

Constructor Details

#initialize(prefix, agent_type, base_id, token = nil, separator = nil) ⇒ AgentIdentity

Generate new id

Parameters

prefix(String)

Prefix used to scope identity

agent_type(String)

Agent type (e.g. ‘core’, ‘instance’)

base_id(Integer)

Unique integer value

token(String)

Unique identity token, will be generated randomly if not provided

separator(String)

Character used to separate identity components, defaults to ID_SEPARATOR

Raise

ArgumentError

Invalid argument

Raises:

  • (ArgumentError)


53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/right_agent/agent_identity.rb', line 53

def initialize(prefix, agent_type, base_id, token = nil, separator = nil)
  err = "Prefix cannot contain '#{ID_SEPARATOR}'" if prefix && prefix.include?(ID_SEPARATOR)
  err = "Prefix cannot contain '#{ID_SEPARATOR_OLD}'" if prefix && prefix.include?(ID_SEPARATOR_OLD)
  err = "Agent type cannot contain '#{ID_SEPARATOR}'" if agent_type.include?(ID_SEPARATOR)
  err = "Agent type cannot contain '#{ID_SEPARATOR_OLD}'" if agent_type.include?(ID_SEPARATOR_OLD)
  err = "Agent type cannot be nil" if agent_type.nil?
  err = "Agent type cannot be empty" if agent_type.size == 0
  err = "Base ID must be a positive integer" unless base_id.kind_of?(Integer) && base_id >= 0
  err = "Token cannot contain '#{ID_SEPARATOR}'" if token && token.include?(ID_SEPARATOR)
  err = "Token cannot contain '#{ID_SEPARATOR_OLD}'" if token && token.include?(ID_SEPARATOR_OLD)
  raise ArgumentError, err if err

  @separator  = separator || ID_SEPARATOR
  @prefix     = prefix
  @agent_type = agent_type
  @token      = token || self.class.generate
  @base_id    = base_id
end

Instance Attribute Details

#agent_typeObject (readonly)

Identity components



40
41
42
# File 'lib/right_agent/agent_identity.rb', line 40

def agent_type
  @agent_type
end

#base_idObject (readonly)

Identity components



40
41
42
# File 'lib/right_agent/agent_identity.rb', line 40

def base_id
  @base_id
end

#prefixObject (readonly)

Identity components



40
41
42
# File 'lib/right_agent/agent_identity.rb', line 40

def prefix
  @prefix
end

#tokenObject (readonly)

Identity components



40
41
42
# File 'lib/right_agent/agent_identity.rb', line 40

def token
  @token
end

Class Method Details

.compatible_serialized(serialized_id, version = nil) ⇒ Object

Convert serialized agent identity to format valid for given protocol version Ignore identity that is not in serialized AgentIdentity format

Parameters

serialized_id(String)

Serialized agent identity to be converted

version(Integer)

Target protocol version

Return

serialized_id(String)

Compatible serialized agent identity



121
122
123
124
125
126
127
128
# File 'lib/right_agent/agent_identity.rb', line 121

def self.compatible_serialized(serialized_id, version = nil)
  if version.nil? || ProtocolVersionMixin.can_handle_non_nanite_ids?(version)
    serialized_id = serialized_id[7..-1] if serialized_id =~ /^nanite-|^mapper-|^router-/
  else
    serialized_id = "nanite-#{serialized_id}" if self.valid_parts?(serialized_id)
  end
  serialized_id
end

.generateObject

Generate unique identity

Return

id(String)

Random 128-bit hexadecimal string



76
77
78
79
80
# File 'lib/right_agent/agent_identity.rb', line 76

def self.generate
  bytes = Platform.rng.pseudorandom_bytes(16)
  #Transform into hex string
  id = bytes.unpack('H*')[0]
end

.instance_agent?(serialized_id) ⇒ Boolean

Check whether identity corresponds to an instance agent

Parameters

serialized_id(String)

Valid serialized agent identity (use ‘valid?’ to check first)

Return

(Boolean)

true if id corresponds to an instance agent, otherwise false

Returns:

  • (Boolean)


145
146
147
# File 'lib/right_agent/agent_identity.rb', line 145

def self.instance_agent?(serialized_id)
  parts(serialized_id)[1] == 'instance'
end

.parse(serialized_id) ⇒ Object

Instantiate by parsing given token

Parameters

serialized_id(String)

Valid serialized agent identity (use ‘valid?’ to check first)

Return

(AgentIdentity)

Corresponding agent identity

Raise

(ArgumentError)

Serialized agent identity is invalid

Raises:

  • (ArgumentError)


103
104
105
106
107
108
109
110
# File 'lib/right_agent/agent_identity.rb', line 103

def self.parse(serialized_id)
  prefix, agent_type, token, bid, separator = parts(self.compatible_serialized(serialized_id))
  raise ArgumentError, "Invalid agent identity: #{serialized_id.inspect}" unless prefix && agent_type && token && bid
  base_id = bid.to_i
  raise ArgumentError, "Invalid agent identity base ID: #{bid ? bid : bid.inspect}" unless base_id.to_s == bid

  AgentIdentity.new(prefix, agent_type, base_id, token, separator)
end

.valid?(serialized_id) ⇒ Boolean

Check validity of given serialized identity

Parameters

serialized_id(String)

Serialized identity to be tested

Return

(Boolean)

true if serialized identity is a valid, otherwise false

Returns:

  • (Boolean)


89
90
91
# File 'lib/right_agent/agent_identity.rb', line 89

def self.valid?(serialized_id)
  valid_parts?(self.compatible_serialized(serialized_id)) if serialized_id
end

Instance Method Details

#==(other) ⇒ Object

Comparison operator

Parameters

other(AgentIdentity)

Other agent identity

Return

(Boolean)

true if other is identical to self, otherwise false



164
165
166
167
168
169
170
# File 'lib/right_agent/agent_identity.rb', line 164

def ==(other)
  other.kind_of?(::RightScale::AgentIdentity) &&
  prefix     == other.prefix     &&
  agent_type == other.agent_type &&
  token      == other.token      &&
  base_id    == other.base_id
end

#instance_agent?Boolean

Check whether identity corresponds to an instance agent

Return

(Boolean)

true if id corresponds to an instance agent, otherwise false

Returns:

  • (Boolean)


134
135
136
# File 'lib/right_agent/agent_identity.rb', line 134

def instance_agent?
  agent_type == 'instance'
end

#to_sObject

String representation of identity

Return

(String)

Serialized identity



153
154
155
# File 'lib/right_agent/agent_identity.rb', line 153

def to_s
  "#{@prefix}#{@separator}#{@agent_type}#{@separator}#{@token}#{@separator}#{@base_id}"
end