Class: CFA::Hosts

Inherits:
BaseModel
  • Object
show all
Includes:
Yast::Logger
Defined in:
src/lib/cfa/hosts.rb

Overview

class representings /etc/hosts file model. It provides helper to manipulate with file. It uses CFA framework and Augeas parser.

Constant Summary collapse

PATH =
"/etc/hosts".freeze

Instance Method Summary collapse

Constructor Details

#initialize(file_handler: nil) ⇒ Hosts

Returns a new instance of Hosts.



47
48
49
# File 'src/lib/cfa/hosts.rb', line 47

def initialize(file_handler: nil)
  super(AugeasParser.new("hosts.lns"), PATH, file_handler: file_handler)
end

Instance Method Details

#add_entry(ip, canonical, aliases = []) ⇒ void

This method returns an undefined value.

Adds new entry, even if it exists

Parameters:

  • ip (String)
  • canonical (String)
  • aliases (Array<String>) (defaults to: [])


147
148
149
150
151
152
153
154
155
156
157
# File 'src/lib/cfa/hosts.rb', line 147

def add_entry(ip, canonical, aliases = [])
  log.info "adding new entry for ip #{ip}"
  entry_line = AugeasTree.new
  entry_line["ipaddr"] = ip
  entry_line["canonical"] = canonical
  aliases_col = entry_line.collection("alias")
  aliases.each do |a|
    aliases_col.add(a)
  end
  data.add(data.unique_id, entry_line)
end

#delete_by_ip(ip) ⇒ void

This method returns an undefined value.

deletes all occurences of given ip in host table



99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'src/lib/cfa/hosts.rb', line 99

def delete_by_ip(ip)
  entries = data.select(ip_matcher(ip))
  if entries.empty?
    log.info "no entry to delete for ip #{ip}"
    return
  end

  log.info "delete host with ip '#{ip}' removes more then one entry" if entries.size > 1

  entries.each do |e|
    log.info "deleting record #{e.inspect}"
    data.delete(e[:key])
  end
end

#delete_hostname(hostname) ⇒ void

This method returns an undefined value.

Removes hostname from all entries in hosts table. If it is the only hostname for a given ip, the ip is removed If it is canonical name, then the first alias becomes the canonical hostname

Parameters:

  • hostname (String)


164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'src/lib/cfa/hosts.rb', line 164

def delete_hostname(hostname)
  entries = data.select(hostname_matcher(hostname))
  entries.each do |pair|
    entry = pair[:value]
    if entry["canonical"] == hostname
      aliases = aliases_for(entry)
      if aliases.empty?
        delete_by_ip(entry["ipaddr"])
      else
        entry["canonical"] = aliases.first
        entry.delete("alias")
        entry.delete("alias[]")
        aliases_col = entry.collection("alias")
        aliases[1..-1].each do |a|
          aliases_col.add(a)
        end
      end
    else
      reduced_aliases = aliases_for(entry)
      reduced_aliases.delete(hostname)
      entry.delete("alias")
      entry.delete("alias[]")
      aliases_col = entry.collection("alias")
      reduced_aliases.each do |a|
        aliases_col.add(a)
      end
    end
  end
end

#host(ip) ⇒ Array<String>

Returns single entry from hosts for given ip or empty array if not found

Returns:

  • (Array<String>)

See Also:



89
90
91
92
93
94
95
# File 'src/lib/cfa/hosts.rb', line 89

def host(ip)
  hosts = data.select(ip_matcher(ip))

  hosts.map do |host|
    single_host_entry(host[:value])
  end
end

#hostsHash{String => Array<String>}

The old format used by Yast::HostClass.

Returns:

  • (Hash{String => Array<String>})

    keys are IPs, values are lists of lines in /etc/hosts (not names!) with whitespace separated hostnames, where the first one is canonical and the rest are aliases

    For example, the file contents

    1.2.3.4 www.example.org www
    1.2.3.7 log.example.org log
    1.2.3.7 sql.example.org sql
    

    is returned as

    {
      "1.2.3.4" => "www.example.org www"
      "1.2.3.7" => [
        "log.example.org log",
        "sql.example.org sql"
      ]
    }
    


77
78
79
80
81
82
83
84
# File 'src/lib/cfa/hosts.rb', line 77

def hosts
  matcher = Matcher.new { |k, _v| k =~ /^\d*$/ }
  data.select(matcher).each_with_object({}) do |host, result|
    entry = host[:value]
    result[entry["ipaddr"]] ||= []
    result[entry["ipaddr"]] << single_host_entry(entry)
  end
end

#include_ip?(ip) ⇒ Boolean

returns true if hosts include entry with given IP

Returns:

  • (Boolean)


195
196
197
198
# File 'src/lib/cfa/hosts.rb', line 195

def include_ip?(ip)
  entries = data.select(ip_matcher(ip))
  !entries.empty?
end

#initialize_clone(source) ⇒ Object



51
52
53
54
# File 'src/lib/cfa/hosts.rb', line 51

def initialize_clone(source)
  # Cloning AugeasTree
  @data = source.data.clone
end

#set_entry(ip, canonical, aliases = []) ⇒ void

This method returns an undefined value.

Replaces or adds a new host entry. If more than one entry with the given ip exists then it replaces the last instance.

Parameters:

  • ip (String)
  • canonical (String)
  • aliases (Array<String>) (defaults to: [])


121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'src/lib/cfa/hosts.rb', line 121

def set_entry(ip, canonical, aliases = [])
  entries = data.select(ip_matcher(ip))
  if entries.empty?
    add_entry(ip, canonical, aliases)
    return
  end

  log.info "more then one entry with ip '#{ip}'. Replacing last one." if entries.size > 1

  entry = entries.last[:value]
  entry["ipaddr"] = ip
  entry["canonical"] = canonical
  # clear previous aliases
  entry.delete("alias")
  entry.delete("alias[]")
  aliases_col = entry.collection("alias")
  aliases.each do |a|
    aliases_col.add(a)
  end
end