Class: Xlogin::Factory

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
lib/xlogin/factory.rb

Instance Method Summary collapse

Constructor Details

#initializeFactory

Returns a new instance of Factory.



13
14
15
16
17
18
# File 'lib/xlogin/factory.rb', line 13

def initialize
  @inventory = Hash.new
  @templates = Hash.new
  @tunnels   = Hash.new
  @mutex     = Mutex.new
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *args, **opts, &block) ⇒ Object



118
119
120
121
122
123
124
125
# File 'lib/xlogin/factory.rb', line 118

def method_missing(method_name, *args, **opts, &block)
  super unless args.size == 2 && Addressable::URI::URIREGEX =~ args[1]

  name = args[0]
  uri  = args[1]
  type = method_name.to_s.downcase
  set_hostinfo(name.to_s, type: type, uri: uri, **opts)
end

Instance Method Details

#build(type:, **opts, &block) ⇒ Object

Raises:



96
97
98
99
100
101
102
103
# File 'lib/xlogin/factory.rb', line 96

def build(type:, **opts, &block)
  template = get_template(type)
  raise Xlogin::Error.new("Template not found: '#{type}'") unless template

  session = template.build(uri(opts), **opts)
  return session unless block
  begin block.call(session) ensure session.close end
end

#build_from_hostname(args, **opts, &block) ⇒ Object

Raises:



111
112
113
114
115
116
# File 'lib/xlogin/factory.rb', line 111

def build_from_hostname(args, **opts, &block)
  hostinfo = get_hostinfo(args)
  raise Xlogin::Error.new("Host not found: '#{args}'") unless hostinfo

  build(**hostinfo.merge(**opts), &block)
end

#build_pool(args, **opts, &block) ⇒ Object



105
106
107
108
109
# File 'lib/xlogin/factory.rb', line 105

def build_pool(args, **opts, &block)
  pool = Xlogin::SessionPool.new(args, **opts)
  return pool unless block
  begin block.call(pool) ensure pool.close end
end

#close_tunnel(name, port) ⇒ Object



86
87
88
89
90
91
92
93
94
# File 'lib/xlogin/factory.rb', line 86

def close_tunnel(name, port)
  @mutex.synchronize do
    if tunnel = @tunnels[name]
      tunnel.ports.delete(port)
      tunnel.gateway.close(port)
      tunnel.gateway.shutdown! if tunnel.ports.empty?
    end
  end
end

#get_hostinfo(name) ⇒ Object



24
25
26
# File 'lib/xlogin/factory.rb', line 24

def get_hostinfo(name)
  @inventory[name]
end

#get_template(name) ⇒ Object



50
51
52
# File 'lib/xlogin/factory.rb', line 50

def get_template(name)
  @templates[name.to_s.downcase]
end

#list_hostinfo(*patterns) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/xlogin/factory.rb', line 28

def list_hostinfo(*patterns)
  patterns = patterns.compact.flat_map{ |e| e.split(/\s+/) }
  return @inventory.values if patterns.empty?

  values1 = patterns.map do |pattern|
    values2 = pattern.split(',').map do |entry|
      key, val = entry.to_s.split(':')
      key, val = 'name', key if val.nil?
      @inventory.values.select{ |e| File.fnmatch(val, e[key.to_sym], File::FNM_EXTGLOB) }
    end
    values2.reduce(&:&) || []
  end
  values1.reduce(&:|) || []
end

#list_templatesObject



54
55
56
# File 'lib/xlogin/factory.rb', line 54

def list_templates
  @templates.keys
end

#open_tunnel(name, host, port) ⇒ Object



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
# File 'lib/xlogin/factory.rb', line 58

def open_tunnel(name, host, port)
  @mutex.synchronize do
    tunnel = @tunnels[name]
    unless tunnel && tunnel.gateway.active?
      uri = Addressable::URI.parse(name)
      case uri.scheme
      when 'ssh'
        username, password = *uri.userinfo.split(':')
        gateway = Net::SSH::Gateway.new(
          uri.host,
          username,
          password: password,
          port: uri.port || 22
        )

         @tunnels[name] = Struct.new('Tunnel', :gateway, :ports).new(gateway, [])
      end
    end

    if tunnel = @tunnels[name]
      port = tunnel.gateway.open(host, port)
      host = '127.0.0.1'
      tunnel.ports << port
    end
    return host, port
  end
end

#set_hostinfo(name, **opts) ⇒ Object



20
21
22
# File 'lib/xlogin/factory.rb', line 20

def set_hostinfo(name, **opts)
  @inventory[name] = (get_hostinfo(name) || {name: name}).merge(opts)
end

#set_template(name, text = nil, &block) ⇒ Object



43
44
45
46
47
48
# File 'lib/xlogin/factory.rb', line 43

def set_template(name, text = nil, &block)
  template = get_template(name) || Xlogin::Template.new(name)
  template.instance_eval(text)   if text
  template.instance_eval(&block) if block
  @templates[name.to_s.downcase] = template
end