class Arborist::Node::Service

A node type for Arborist trees that represent services running on hosts.

Constants

DEFAULT_PROTOCOL

The default transport layer protocol to use for services that don't specify one

Public Class Methods

new( identifier, host, attributes={}, &block ) click to toggle source

Create a new Service node.

Calls superclass method Arborist::Node::new
# File lib/arborist/node/service.rb, line 28
def initialize( identifier, host, attributes={}, &block )
        raise Arborist::NodeError, "no host given" unless host.is_a?( Arborist::Node::Host )
        qualified_identifier = "%s-%s" % [ host.identifier, identifier ]

        @host         = host
        @addresses    = nil
        @app_protocol = nil
        @protocol     = nil
        @port         = nil

        attributes[ :app_protocol ] ||= identifier
        attributes[ :protocol ] ||= DEFAULT_PROTOCOL

        super( qualified_identifier, host, attributes, &block )

        unless @port
                service_port = default_port_for( @app_protocol, @protocol ) or
                        raise ArgumentError, "can't determine the port for %s/%s" %
                                [ @app_protocol, @protocol ]
                @port = Integer( service_port )
        end
end

Public Instance Methods

==( other_host ) click to toggle source

Equality operator – returns true if other_node is equal to the receiver. Overridden to also compare addresses.

Calls superclass method Arborist::Node#==
# File lib/arborist/node/service.rb, line 185
def ==( other_host )
        return super &&
                other_host.addresses == self.addresses &&
                other_host.protocol == self.protocol &&
                other_host.app_protocol == self.app_protocol &&
                other_host.port == self.port
end
address( new_address ) click to toggle source

Set an IP address of the service. This must be one of the addresses of its containing host.

# File lib/arborist/node/service.rb, line 90
def address( new_address )
        self.log.debug "Adding address %p to %p" % [ new_address, self ]
        normalized_addresses = normalize_address( new_address )

        unless normalized_addresses.all? {|addr| @host.addresses.include?(addr) }
                raise Arborist::ConfigError, "%s is not one of %s's addresses" %
                        [ new_address, @host.identifier ]
        end

        @addresses ||= []
        @addresses += normalized_addresses
end
addresses() click to toggle source

Delegate the service's address to its host.

# File lib/arborist/node/service.rb, line 105
def addresses
        return @addresses || @host.addresses
end
app_protocol() click to toggle source

Get/set the application protocol the service uses

# File lib/arborist/node/service.rb, line 62
dsl_accessor :app_protocol
family() click to toggle source

Return the node family, so observers can know ancestry after serialization for custom node types that inherit from this class.

# File lib/arborist/node/service.rb, line 71
def family
        return :service
end
hostname() click to toggle source

Delegate the service's hostname to it's parent host.

# File lib/arborist/node/service.rb, line 111
def hostname
        return @host.hostname
end
match_criteria?( key, val ) click to toggle source

Returns true if the node matches the specified key and val criteria.

Calls superclass method Arborist::Node#match_criteria?
# File lib/arborist/node/service.rb, line 117
def match_criteria?( key, val )
        self.log.debug "Matching %p: %p against %p" % [ key, val, self ]
        array_val = Array( val )
        return case key
                when 'port'
                        vals = array_val.collect do |port|
                                port = default_port_for( port, @protocol ) unless port.is_a?( Integer )
                                port.to_i
                        end
                        vals.include?( self.port )
                when 'address'
                        search_addr = IPAddr.new( val )
                        self.addresses.any? {|a| search_addr.include?(a) }
                when 'protocol' then array_val.include?( self.protocol )
                when 'app', 'app_protocol' then array_val.include?( self.app_protocol )
                else
                        super
                end
end
modify( attributes ) click to toggle source

Set service attributes.

Calls superclass method Arborist::Node#modify
# File lib/arborist/node/service.rb, line 77
def modify( attributes )
        attributes = stringify_keys( attributes )

        super

        self.port( attributes['port'] )
        self.app_protocol( attributes['app_protocol'] )
        self.protocol( attributes['protocol'] )
end
node_description() click to toggle source

Return service-node-specific information for inspect.

# File lib/arborist/node/service.rb, line 152
def node_description
        return "{listening on %s port %d}" % [
                self.protocol,
                self.port,
        ]
end
operational_values() click to toggle source

Return a Hash of the operational values that are included with the node's monitor state.

Calls superclass method Arborist::Node#operational_values
# File lib/arborist/node/service.rb, line 140
def operational_values
        return super.merge(
                addresses: self.addresses.map( &:to_s ),
                hostname: self.hostname,
                port: self.port,
                protocol: self.protocol,
                app_protocol: self.app_protocol,
        )
end
parent( new_parent=nil ) click to toggle source

Overridden to disallow modification of a Service's parent, as it needs a reference to the Host node for delegation.

Calls superclass method Arborist::Node#parent
# File lib/arborist/node/service.rb, line 162
def parent( new_parent=nil )
        return super unless new_parent
        raise "Can't reparent a service; replace the node instead"
end
port() click to toggle source

Get/set the port the service binds to

# File lib/arborist/node/service.rb, line 58
dsl_accessor :port
protocol() click to toggle source

Get/set the network protocol the service uses

# File lib/arborist/node/service.rb, line 66
dsl_accessor :protocol
to_h( ** ) click to toggle source

Return a Hash of the host node's state.

Calls superclass method Arborist::Node#to_h
# File lib/arborist/node/service.rb, line 173
def to_h( ** )
        return super.merge(
                addresses: self.addresses.map(&:to_s),
                protocol: self.protocol,
                app_protocol: self.app_protocol,
                port: self.port
        )
end

Private Instance Methods

default_port_for( identifier, protocol ) click to toggle source

Try to default the appropriate port based on the node's identifier and protocol. Raises a SocketError if the service port can't be looked up.

# File lib/arborist/node/service.rb, line 201
def default_port_for( identifier, protocol )
        return Socket.getservbyname( identifier, protocol )
rescue SocketError
        return nil
end