Class: RFacter::Node

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/rfacter/node.rb

Overview

Note:

This class should be refacter to provide an abstracted interface to different transport backends like Train, Vagrant, Chloride, etc.

Interface to a local or remote host

Since:

  • 0.1.0

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(uri, id: nil, config: RFacter::Config.config, **opts) ⇒ Node

Returns a new instance of Node

Parameters:

  • uri (URI)

    The URI of the node.

  • id (String, nil) (defaults to: nil)

    An optional string to use when identifying this node.

Since:

  • 0.1.0



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/rfacter/node.rb', line 48

def initialize(uri, id: nil, config: RFacter::Config.config, **opts)
  @config = config

  @uri = unless uri.is_a?(URI)
    URI.parse(uri.to_s)
  else
    uri
  end

  @hostname = @uri.hostname || @uri.path
  @scheme = if @uri.scheme.nil? && (@hostname == 'localhost')
    'local'
  elsif @uri.scheme.nil?
    'ssh'
  else
    @uri.scheme
  end

  case @scheme
  when 'ssh'
    @port = @uri.port || 22
    @user = @uri.user || 'root'
  when 'winrm'
    @user = @uri.user || 'Administrator'
  end

  @password = CGI.unescape(@uri.password) unless @uri.password.nil?
  @options = @uri.query.nil? ? Hash.new : CGI.parse(@uri.query)
  @options.update(opts)

  @id = unless id.nil?
          id
        else
          # Create a default from the URI, minus the password and options
          # components.
          id_string = "#{@scheme}://"
          id_string += "#{@user}@" unless @user.nil?
          id_string += @hostname
          id_string += ":#{@port}" unless @port.nil?
          id_string
        end

  @id.freeze

  # TODO: This should be abstracted.
  @transport = Train.create(@scheme,
    host: @hostname,
    user: @user,
    password: @password,
    port: @port,
    logger: logger, **@options)
end

Instance Attribute Details

#hostnameString (readonly)

Returns:

  • (String)

Since:

  • 0.1.0



27
28
29
# File 'lib/rfacter/node.rb', line 27

def hostname
  @hostname
end

#idString (readonly)

Returns:

  • (String)

Since:

  • 0.1.0



39
40
41
# File 'lib/rfacter/node.rb', line 39

def id
  @id
end

#optionsHash (readonly)

Returns:

  • (Hash)

Since:

  • 0.1.0



37
38
39
# File 'lib/rfacter/node.rb', line 37

def options
  @options
end

#passwordString? (readonly)

Returns:

  • (String, nil)

Since:

  • 0.1.0



35
36
37
# File 'lib/rfacter/node.rb', line 35

def password
  @password
end

#portInteger? (readonly)

Returns:

  • (Integer, nil)

Since:

  • 0.1.0



31
32
33
# File 'lib/rfacter/node.rb', line 31

def port
  @port
end

#schemeString (readonly)

Returns:

  • (String)

Since:

  • 0.1.0



29
30
31
# File 'lib/rfacter/node.rb', line 29

def scheme
  @scheme
end

#transportObject (readonly)

Since:

  • 0.1.0



41
42
43
# File 'lib/rfacter/node.rb', line 41

def transport
  @transport
end

#uriURI (readonly)

Returns:

  • (URI)

Since:

  • 0.1.0



24
25
26
# File 'lib/rfacter/node.rb', line 24

def uri
  @uri
end

#userString? (readonly)

Returns:

  • (String, nil)

Since:

  • 0.1.0



33
34
35
# File 'lib/rfacter/node.rb', line 33

def user
  @user
end

Instance Method Details

#connectionObject

FIXME: For some reason, Train’s connection re-use logic isn’t working, so a new connection is being negotiated for each command. File a bug.

TODO: Ensure connection use is thread-safe.

Since:

  • 0.1.0



105
106
107
# File 'lib/rfacter/node.rb', line 105

def connection
  @connection ||= @transport.connection
end

#execute(command) ⇒ Train::Extras::CommandResult

TODO:

Add support for setting user accounts and environment variables.

Execute a command on the node asynchronously

This method initiates the execution of a command line and returns an object representing the result.

Parameters:

  • command (String)

    The command string to execute.

Returns:

  • (Train::Extras::CommandResult)

    The result of the command including stdout, stderr and exit code.

Since:

  • 0.1.0



120
121
122
# File 'lib/rfacter/node.rb', line 120

def execute(command)
  connection.run_command(command)
end

#file(path) ⇒ Train::Extras::FileCommon

Interact with remote files in a read-only manner

This method returns an object that can povide read only access to the stats and content of a particular file path.

Parameters:

  • path (String)

    The file path to interact with.

Returns:

  • (Train::Extras::FileCommon)

    An object representing the remote file.

Since:

  • 0.1.0



156
157
158
# File 'lib/rfacter/node.rb', line 156

def file(path)
  connection.file(path)
end

#which(executable) ⇒ String?

TODO:

Add support for setting user accounts and environment variables.

Determine if an executable exists and return the path

Parameters:

  • executable (String)

    The executable to locate.

Returns:

  • (String)

    The path to the executable if it exists.

  • (nil)

    Returned when no matching executable can be located.

Since:

  • 0.1.0



133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/rfacter/node.rb', line 133

def which(executable)
  # TODO: Abstract away from the Train "os" implementation.
  result = if connection.os.windows?
    connection.run_command("(Get-Command -TotalCount 1 #{executable}).Path")
  else
    connection.run_command("command -v #{executable}")
  end

  if (result.exit_status != 0) || (result.stdout.chomp.empty?)
    nil
  else
    result.stdout.chomp
  end
end