hostess

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 6, 2015 License: MIT Imports: 12 Imported by: 0

README

hostess

An idempotent command-line utility for managing your /etc/hosts file.

hostess add local.example.com 127.0.0.1
hostess add staging.example.com 10.0.2.16

Why? Because you edit /etc/hosts for development, testing, and debugging. Because sometimes DNS doesn't work in production. And because editing /etc/hosts by hand is a pain. Put hostess in your Makefile or deploy scripts and call it a day.

Using Hostess

Download and Install

Download a precompiled release from GitHub.

Usage
hostess add domain ip   # Add or replace a hosts entry for this domain pointing to this IP
hostess aff domain ip   # Add or replace a hosts entry in an off state
hostess del domain      # (alias rm) Remove a domain from your hosts file
hostess has domain      # exit code 0 if the domain is in your hostfile, 1 otherwise
hostess off domain      # Disable a domain (but don't remove it completely), exit 1 if entry is missing
hostess on domain       # Re-enable a domain that was disabled, exit 1 if entry is missing
hostess list            # (alias ls) List domains, target ips, and on/off status
hostess fix             # Rewrite your hosts file; use -n to dry run
hostess dump            # Dump your hostfile as json
hostess apply           # Add entries from a json file

Flags

-n   # Dry run. Show what will happen but don't do it; output to stdout
-4   # Limit operation to ipv4 entries
-6   # Limit operation to ipv6 entries

hostess will mangle your hosts file. Domains pointing at the same IP will be grouped together and disabled domains commented out.

127.0.0.1 localhost hostname2 hostname3
127.0.1.1 machine.name
# 10.10.20.30 some.host
IPv4 and IPv6

Your hosts file can contain overlapping entries where the same hostname points to both an IPv4 and IPv6 IP. In this case, hostess commands will apply to both entries. Typically you won't have this kind of overlap and the default behavior is OK. However, if you need to be more granular you can use -4 or -6 to limit operations to entries associated with that type of IP.

Developing Hostess

Configuration

By default, hostess will read / write to /etc/hosts. You can use the HOSTESS_PATH environment variable to provide an alternate path (for testing).

Building from Source

To build from source you'll need to have go 1.4+

Install with go get
go get github.com/cbednarski/hostess/cmd/hostess
Install from source
git clone https://github.com/cbednarski/hostess
cd hostess
make
make install

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrCantWriteHostFile = fmt.Errorf(
	"Unable to write to %s. Maybe you need to sudo?", GetHostsPath())

ErrCantWriteHostFile indicates that we are unable to write to the hosts file

View Source
var ErrInvalidVersionArg = errors.New("Version argument must be 4 or 6")

ErrInvalidVersionArg is raised when a function expects IPv 4 or 6 but is passed a value not 4 or 6.

Functions

func Add

func Add(c *cli.Context)

Add command parses <hostname> <ip> and adds or updates a hostname in the hosts file. If the aff command is used the hostname will be disabled or added in the off state.

func Apply

func Apply(c *cli.Context)

Apply command adds hostnames to the hosts file from JSON

func Del

func Del(c *cli.Context)

Del command removes any hostname(s) matching <domain> from the hosts file

func Dump

func Dump(c *cli.Context)

Dump command outputs hosts file contents as JSON

func Fix

func Fix(c *cli.Context)

Fix command removes duplicates and conflicts from the hosts file

func GetHostsPath

func GetHostsPath() string

GetHostsPath returns the location of the hostfile; either env HOSTESS_PATH or /etc/hosts if HOSTESS_PATH is not set.

func Has

func Has(c *cli.Context)

Has command indicates whether a hostname is present in the hosts file

func LooksLikeIPv4

func LooksLikeIPv4(ip string) bool

LooksLikeIPv4 returns true if the IP looks like it's IPv4. This does not validate whether the string is a valid IP address.

func LooksLikeIPv6

func LooksLikeIPv6(ip string) bool

LooksLikeIPv6 returns true if the IP looks like it's IPv6. This does not validate whether the string is a valid IP address.

func Ls

func Ls(c *cli.Context)

Ls command shows a list of hostnames in the hosts file

func MakeSurrogateIP

func MakeSurrogateIP(IP net.IP) net.IP

MakeSurrogateIP takes an IP like 127.0.0.1 and munges it to 0.0.0.1 so we can sort it more easily. Note that we don't actually want to change the value, so we use value copies here (not pointers).

func MaybeError

func MaybeError(c *cli.Context, message string)

MaybeError will print an error message unless -s is passed and then exit

func MaybeErrorln

func MaybeErrorln(c *cli.Context, message string)

MaybeErrorln will print an error message unless -s is passed

func MaybePrintln

func MaybePrintln(c *cli.Context, message string)

MaybePrintln will print a message unless -q or -s is passed

func MaybeSaveHostFile

func MaybeSaveHostFile(c *cli.Context, hostfile *Hostfile)

MaybeSaveHostFile will output or write the Hostfile, or exit 1 and error.

func OnOff

func OnOff(c *cli.Context)

OnOff enables (uncomments) or disables (comments) the specified hostname in the hosts file. Exits code 1 if the hostname is missing.

func StrPadRight

func StrPadRight(s string, l int) string

StrPadRight adds spaces to the right of a string until it reaches l length. If the input string is already that long, do nothing.

func TrimWS

func TrimWS(s string) string

TrimWS (Trim Whitespace) removes space, newline, and tabs from a string using strings.Trim()

Types

type Hostfile

type Hostfile struct {
	Path  string
	Hosts Hostlist
	// contains filtered or unexported fields
}

Hostfile represents /etc/hosts (or a similar file, depending on OS), and includes a list of Hostnames. Hostfile includes

func AlwaysLoadHostFile

func AlwaysLoadHostFile(c *cli.Context) *Hostfile

AlwaysLoadHostFile will load, parse, and return a Hostfile. If we encouter errors they will be printed to the terminal, but we'll try to continue.

func LoadHostfile

func LoadHostfile() (hostfile *Hostfile, errs []error)

LoadHostfile creates a new Hostfile struct and tries to populate it from disk. Read and/or parse errors are returned as a slice.

func MaybeLoadHostFile

func MaybeLoadHostFile(c *cli.Context) *Hostfile

MaybeLoadHostFile will try to load, parse, and return a Hostfile. If we encounter errors we will terminate, unless -f is passed.

func NewHostfile

func NewHostfile() *Hostfile

NewHostfile creates a new Hostfile object from the specified file.

func (*Hostfile) Format

func (h *Hostfile) Format() []byte

Format takes the current list of Hostnames in this Hostfile and turns it into a string suitable for use as an /etc/hosts file. Sorting uses the following logic: 1. List is sorted by IP address 2. Commented items are left in place 3. 127.* appears at the top of the list (so boot resolvers don't break) 4. When present, localhost will always appear first in the domain list

func (*Hostfile) GetData

func (h *Hostfile) GetData() []byte

GetData returns the internal snapshot of the hostfile we read when we loaded this hostfile from disk (if we ever did that). This is implemented for testing and you probably won't need to use it.

func (*Hostfile) Parse

func (h *Hostfile) Parse() []error

Parse reads

func (*Hostfile) Read

func (h *Hostfile) Read() error

Read the contents of the hostfile from disk

func (*Hostfile) Save

func (h *Hostfile) Save() error

Save writes the Hostfile to disk to /etc/hosts or to the location specified by the HOSTESS_PATH environment variable (if set).

type Hostlist

type Hostlist []*Hostname

Hostlist is a sortable set of Hostnames. When in a Hostlist, Hostnames must follow some rules:

  • Hostlist may contain IPv4 AND IPv6 ("IP version" or "IPv") Hostnames.
  • Names are only allowed to overlap if IP version is different.
  • Adding a Hostname for an existing name will replace the old one.

The Hostlist uses a deterministic Sort order designed to make a hostfile output look a particular way. Generally you don't need to worry about this as Sort will be called automatically before Format. However, the Hostlist may or may not be sorted at any particular time during runtime.

See the docs and implementation in Sort and Add for more details.

func NewHostlist

func NewHostlist() *Hostlist

NewHostlist initializes a new Hostlist

func ParseLine

func ParseLine(line string) Hostlist

ParseLine parses an individual line in a hostfile, which may contain one (un)commented ip and one or more hostnames. For example

127.0.0.1 localhost mysite1 mysite2

func (*Hostlist) Add

func (h *Hostlist) Add(hostnamev *Hostname) error

Add a new Hostname to this hostlist. Add uses some merging logic in the event it finds duplicated hostnames. In the case of a conflict (incompatible entries) the last write wins. In the case of duplicates, duplicates will be removed and the remaining entry will be enabled if any of the duplicates was enabled.

Both duplicate and conflicts return errors so you are aware of them, but you don't necessarily need to do anything about the error.

func (*Hostlist) Apply

func (h *Hostlist) Apply(jsonbytes []byte) error

Apply imports all entries from the JSON input to this Hostlist

func (*Hostlist) Contains

func (h *Hostlist) Contains(b *Hostname) bool

Contains returns true if this Hostlist has the specified Hostname

func (*Hostlist) ContainsDomain

func (h *Hostlist) ContainsDomain(domain string) bool

ContainsDomain returns true if a Hostname in this Hostlist matches domain

func (*Hostlist) ContainsIP

func (h *Hostlist) ContainsIP(IP net.IP) bool

ContainsIP returns true if a Hostname in this Hostlist matches IP

func (*Hostlist) Disable

func (h *Hostlist) Disable(domain string) bool

Disable will change any Hostnames matching domain to be disabled.

func (*Hostlist) DisableV

func (h *Hostlist) DisableV(domain string, version int) bool

DisableV will change any Hostnames matching domain and IP version to be disabled.

This function will panic if IP version is not 4 or 6.

func (*Hostlist) Dump

func (h *Hostlist) Dump() ([]byte, error)

Dump exports all entries in the Hostlist as JSON

func (*Hostlist) Enable

func (h *Hostlist) Enable(domain string) bool

Enable will change any Hostnames matching domain to be enabled.

func (*Hostlist) EnableV

func (h *Hostlist) EnableV(domain string, version int) bool

EnableV will change a Hostname matching domain and IP version to be enabled.

This function will panic if IP version is not 4 or 6.

func (*Hostlist) FilterByDomain

func (h *Hostlist) FilterByDomain(domain string) (hostnames []*Hostname)

FilterByDomain filters the list of hostnames by Domain.

func (*Hostlist) FilterByDomainV

func (h *Hostlist) FilterByDomainV(domain string, version int) (hostnames []*Hostname)

FilterByDomainV filters the list of hostnames by domain and IPv4 or IPv6. This should never contain more than one item, but returns a list for consistency with other filter functions.

This function will panic if IP version is not 4 or 6.

func (*Hostlist) FilterByIP

func (h *Hostlist) FilterByIP(IP net.IP) (hostnames []*Hostname)

FilterByIP filters the list of hostnames by IP address.

func (*Hostlist) Format

func (h *Hostlist) Format() []byte

Format takes the current list of Hostnames in this Hostfile and turns it into a string suitable for use as an /etc/hosts file. Sorting uses the following logic:

1. List is sorted by IP address 2. Commented items are sorted displayed 3. 127.* appears at the top of the list (so boot resolvers don't break) 4. When present, "localhost" will always appear first in the domain list

func (*Hostlist) GetUniqueIPs

func (h *Hostlist) GetUniqueIPs() []net.IP

GetUniqueIPs extracts an ordered list of unique IPs from the Hostlist. This calls Sort() internally.

func (*Hostlist) IndexOf

func (h *Hostlist) IndexOf(host *Hostname) int

IndexOf will indicate the index of a Hostname in Hostlist, or -1 if it is not found.

func (*Hostlist) IndexOfDomainV

func (h *Hostlist) IndexOfDomainV(domain string, version int) int

IndexOfDomainV will indicate the index of a Hostname in Hostlist that has the same domain and IP version, or -1 if it is not found.

This function will panic if IP version is not 4 or 6.

func (Hostlist) Len

func (h Hostlist) Len() int

Len returns the number of Hostnames in the list, part of sort.Interface

func (Hostlist) Less

func (h Hostlist) Less(A, B int) bool

Less determines the sort order of two Hostnames, part of sort.Interface

func (*Hostlist) Remove

func (h *Hostlist) Remove(index int) int

Remove will delete the Hostname at the specified index. If index is out of bounds (i.e. -1), Remove silently no-ops. Remove returns the number of items removed (0 or 1).

func (*Hostlist) RemoveDomain

func (h *Hostlist) RemoveDomain(domain string) int

RemoveDomain removes both IPv4 and IPv6 Hostname entries matching domain. Returns the number of entries removed.

func (*Hostlist) RemoveDomainV

func (h *Hostlist) RemoveDomainV(domain string, version int) int

RemoveDomainV removes a Hostname entry matching the domain and IP version.

func (*Hostlist) Sort

func (h *Hostlist) Sort()

Sort this list of Hostnames, according to Hostlist sorting rules:

  1. localhost comes before other domains
  2. IPv4 comes before IPv6
  3. IPs are sorted in numerical order
  4. domains are sorted in alphabetical

func (Hostlist) Swap

func (h Hostlist) Swap(i, j int)

Swap changes the position of two Hostnames, part of sort.Interface

type Hostname

type Hostname struct {
	Domain  string `json:"domain"`
	IP      net.IP `json:"ip"`
	Enabled bool   `json:"enabled"`
	IPv6    bool   `json:"-"`
}

Hostname represents a hosts file entry, including a Domain, IP, whether the Hostname is enabled (uncommented in the hosts file), and whether the IP is in the IPv6 format. You should always create these with NewHostname(). Note: when using Hostnames in the context of a Hostlist, you should not change the Hostname fields except through the Hostlist's aggregate methods. Doing so can cause unexpected behavior. Instead, use Hostlist's Add, Remove, Enable, and Disable methods.

func NewHostname

func NewHostname(domain, ip string, enabled bool) (hostname *Hostname)

NewHostname creates a new Hostname struct and automatically sets the IPv6 field based on the IP you pass in.

func (*Hostname) Equal

func (h *Hostname) Equal(n *Hostname) bool

Equal compares two Hostnames. Note that only the Domain and IP fields are compared because Enabled is transient state, and IPv6 should be set automatically based on IP.

func (*Hostname) EqualIP

func (h *Hostname) EqualIP(ip net.IP) bool

EqualIP compares an IP against this Hostname.

func (*Hostname) Format

func (h *Hostname) Format() string

Format outputs the Hostname as you'd see it in a hosts file, with a comment if it is disabled. E.g. # 127.0.0.1 blah.example.com

func (*Hostname) FormatEnabled

func (h *Hostname) FormatEnabled() string

FormatEnabled displays Hostname.Enabled as (On) or (Off)

func (*Hostname) FormatHuman

func (h *Hostname) FormatHuman() string

FormatHuman outputs the Hostname in a more human-readable format: blah.example.com -> 127.0.0.1 (Off)

func (*Hostname) IsValid

func (h *Hostname) IsValid() bool

IsValid does a spot-check on the domain and IP to make sure they aren't blank

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL