Skip to content
This repository has been archived by the owner on Aug 25, 2021. It is now read-only.

Commit

Permalink
Added initial impl of etc_hosts recipe
Browse files Browse the repository at this point in the history
  • Loading branch information
kohder committed Jul 5, 2011
1 parent bcc58de commit a64d484
Show file tree
Hide file tree
Showing 9 changed files with 346 additions and 47 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/.bundle/
.idea
/bin
98 changes: 98 additions & 0 deletions libraries/etc_hosts.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#
# Cookbook Name:: hosts-awareness
# Library:: EtcHosts
#
# Copyright 2011, Rob Lewis <[email protected]>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

module HostsAwareness
class EtcHosts
attr_reader :etc_hosts_file
attr_writer :block_token
attr_accessor :use_private_addresses

def initialize(etc_hosts_file)
@etc_hosts_file = etc_hosts_file
@use_private_addresses = false
end

def block_token
@block_token || 'chef nodes'
end

def set_hosts(hosts)
write_out!(hosts)
end

def empty!
write_out!([])
end

protected

def host_entry(host)
if use_private_addresses
[host.private_ipv4, host.hostname, host.short_hostname, host.provider_public_hostname, host.provider_private_hostname]
else
[host.public_ipv4, host.hostname, host.short_hostname, host.provider_public_hostname, host.provider_private_hostname]
end
end

def format_host_entries(hosts)
host_entries = hosts.sort{|a,b| a.hostname <=> b.hostname}.collect{|host| host_entry(host)}
a = host_entries.transpose
a = a.map do |col|
w = col.map{|cell| cell.to_s.length}.max
col.map{|cell| cell.to_s.ljust(w)}
end
a.transpose.inject(''){|s, row| s << row.join(' ').rstrip + "\n"; s}
end

def write_out!(hosts)
host_entries_string = format_host_entries(hosts)
File.open(@etc_hosts_file, 'r+') do |f|
out, over, seen_tokens = '', false, false
f.each do |line|
if line =~ /^#{start_token}/
over = seen_tokens = true
out << line << host_entries_string
elsif line =~ /^#{end_token}/
over = false
end
out << line unless over
end
if !seen_tokens
out << surround_with_tokens(host_entries_string)
end

f.pos = 0
f.print out
f.truncate(f.pos)
end
end

def surround_with_tokens(str)
"\n#{start_token}\n" + str + "#{end_token}\n"
end

def start_token()
"## #{block_token} start"
end

def end_token()
"## #{block_token} end"
end
end
end
86 changes: 86 additions & 0 deletions libraries/host.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#
# Cookbook Name:: hosts-awareness
# Library:: Host
#
# Copyright 2011, Rob Lewis <[email protected]>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

module HostsAwareness
class Host
attr_reader :network
attr_accessor :hostname
attr_accessor :private_ipv4
attr_accessor :public_ipv4
attr_accessor :provider_private_hostname
attr_accessor :provider_public_hostname

def self.from_node(node, network=nil)
host = new(network)
host.hostname = node['fqdn'] || "#{node['hostname']}.#{node['domain']}"
if node['cloud'] && node['cloud']['local_ipv4']
host.private_ipv4 = node['cloud']['local_ipv4']
elsif node['ec2'] && node['ec2']['local_ipv4']
host.private_ipv4 = node['ec2']['local_ipv4']
else
host.private_ipv4 = node['ipaddress']
end

if node['cloud'] && node['cloud']['public_ipv4']
host.public_ipv4 = node['cloud']['public_ipv4']
elsif node['ec2'] && node['ec2']['public_ipv4']
host.public_ipv4 = node['ec2']['public_ipv4']
end

if node['cloud'] && node['cloud']['local_hostname']
host.provider_private_hostname = node['cloud']['local_hostname']
elsif node['ec2'] && node['ec2']['local_hostname']
host.provider_private_hostname = node['ec2']['local_hostname']
end

if node['cloud'] && node['cloud']['public_hostname']
host.provider_public_hostname = node['cloud']['public_hostname']
elsif node['ec2'] && node['ec2']['public_hostname']
host.provider_public_hostname = node['ec2']['public_hostname']
end
host
end

def initialize(network=nil)
@network = network
end

def short_hostname
@short_hostname ||= begin
if @network && @network.short_hostname_parts && @network.short_hostname_parts > 0
@hostname.split('.').shift(@network.short_hostname_parts).join('.')
else
@hostname.split('.').first
end
end
end

def domain_name
@domain_name ||= @hostname.partition('.').last
end

def ==(other)
other.equal?(self) || (other.instance_of?(self.class) && other.hostname == @hostname)
end

def eql?(other)
self == (other)
end
end
end
75 changes: 75 additions & 0 deletions libraries/network.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#
# Cookbook Name:: hosts-awareness
# Library:: Network
#
# Copyright 2011, Rob Lewis <[email protected]>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

require 'chef/mixin/language'
include Chef::Mixin::Language

module HostsAwareness
class Network
attr_reader :name
attr_accessor :provider
attr_accessor :node_search_query
attr_accessor :short_hostname_parts

def self.from_data_bag(network_name)
network = HostsAwareness::Network.new(network_name)
all_network_names = data_bag('networks')
if all_network_names.include?(network_name)
network_data_bag_item = data_bag_item('networks', network_name)
network.provider = network_data_bag_item['provider']
network.node_search_query = network_data_bag_item['node_search_query']
network.short_hostname_parts = network_data_bag_item['short_hostname_parts'].to_i
else
Chef::Log.error("No data bag entry for network \"#{network_name}\"")
end
network
end

def initialize(network_name)
@name = network_name
end

def hosts
@hosts ||= begin
hosts = nodes.collect{|n| HostsAwareness::Host.from_node(n, self)}
hosts.uniq
end
end

def nodes
@nodes ||= @node_search_query.nil? ? [] : search(:node, @node_search_query)
end

def member?(node_or_host)
if node_or_host.is_a?(HostsAwareness::Host)
hosts.any?{|host| host == node_or_host}
else
nodes.any?{|node| node.name == node_or_host.name}
end
end

def ==(other)
other.equal?(self) || (other.instance_of?(self.class) && other.name == @name)
end

def eql?(other)
self == (other)
end
end
end
92 changes: 47 additions & 45 deletions libraries/ssh_known_hosts.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,61 +17,63 @@
# limitations under the License.
#

class SshKnownHosts
attr_reader :known_hosts_file
attr_accessor :start_token
attr_accessor :end_token
module HostsAwareness
class SshKnownHosts
attr_reader :known_hosts_file
attr_accessor :start_token
attr_accessor :end_token

def initialize(known_hosts_file, start_token=nil, end_token=nil)
@known_hosts_file = known_hosts_file
@start_token = start_token || '# chef nodes start'
@end_token = end_token || '# chef nodes end'
end
def initialize(known_hosts_file, start_token=nil, end_token=nil)
@known_hosts_file = known_hosts_file
@start_token = start_token || '# chef nodes start'
@end_token = end_token || '# chef nodes end'
end

def set_hosts(hosts)
write_out!(hosts)
end
def set_hosts(hosts)
write_out!(hosts)
end

def empty!
write_out!([])
end
def empty!
write_out!([])
end

protected
protected

def write_out!(hosts)
new_ghosts = hosts.inject('') do |s, host|
fqdn = host['fqdn']
unless fqdn.nil?
rsa_public_ssh_key = host['keys']['ssh']['host_rsa_public']
s += "#{fqdn},#{host['ipaddress']} ssh-rsa #{rsa_public_ssh_key}\n" unless rsa_public_ssh_key.nil?
dsa_public_ssh_key = host['keys']['ssh']['host_rsa_public']
s += "#{fqdn},#{host['ipaddress']} ssh-dsa #{dsa_public_ssh_key}\n" unless dsa_public_ssh_key.nil?
def write_out!(hosts)
new_ghosts = hosts.inject('') do |s, host|
fqdn = host['fqdn']
unless fqdn.nil?
rsa_public_ssh_key = host['keys']['ssh']['host_rsa_public']
s += "#{fqdn},#{host['ipaddress']} ssh-rsa #{rsa_public_ssh_key}\n" unless rsa_public_ssh_key.nil?
dsa_public_ssh_key = host['keys']['ssh']['host_rsa_public']
s += "#{fqdn},#{host['ipaddress']} ssh-dsa #{dsa_public_ssh_key}\n" unless dsa_public_ssh_key.nil?
end
s
end
s
end

File.open(@known_hosts_file, 'r+') do |f|
out, over, seen_tokens = '', false, false
f.each do |line|
if line =~ /^#{@start_token}/o
over = seen_tokens = true
out << line << new_ghosts
elsif line =~ /^#{@end_token}/o
over = false
File.open(@known_hosts_file, 'r+') do |f|
out, over, seen_tokens = '', false, false
f.each do |line|
if line =~ /^#{@start_token}/o
over = seen_tokens = true
out << line << new_ghosts
elsif line =~ /^#{@end_token}/o
over = false
end
out << line unless over
end
if !seen_tokens
out << surround_with_tokens(new_ghosts)
end
out << line unless over
end
if !seen_tokens
out << surround_with_tokens(new_ghosts)
end

f.pos = 0
f.print out
f.truncate(f.pos)
f.pos = 0
f.print out
f.truncate(f.pos)
end
end
end

def surround_with_tokens(str)
"\n#{@start_token}\n" + str + "#{@end_token}\n"
def surround_with_tokens(str)
"\n#{@start_token}\n" + str + "#{@end_token}\n"
end
end
end
3 changes: 2 additions & 1 deletion metadata.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
license 'Apache 2.0'
description 'Installs/Configures hosts-awareness'
long_description IO.read(File.join(File.dirname(__FILE__), 'README.rdoc'))
version '0.0.1'
version '0.0.3'

recipe 'hosts-awareness', 'Includes all recipes'
recipe 'hosts-awareness::etc_hosts', 'Updates /etc/hosts with node entries.'
recipe 'hosts-awareness::ssh_known_hosts', 'Updates ssh/known_hosts with node entries.'

attribute 'hosts-awareness/ssh_known_hosts/file_owner',
Expand Down
1 change: 1 addition & 0 deletions recipes/default.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@
# limitations under the License.
#

include_recipe 'hosts-awareness::etc_hosts'
include_recipe 'hosts-awareness::ssh_known_hosts'
Loading

0 comments on commit a64d484

Please sign in to comment.