Giter Club home page Giter Club logo

hostsfile's Introduction

Go package for working with a system's hostsfile

codecov Go Reference

Reads the content of a file in the hosts format into go structs for easy manipulation in go programs. When all changes are complete you can Flush the hosts file back to disk to save your changes. Supports an indexing system on both ips and hosts for quick management of large hosts files.

Simple Usage

Simple usage reading in your system's hosts file and adding an entry for the ip 192.168.1.1 and the host my-hostname

package main

import (
	"log"
	
	"github.com/goodhosts/hostsfile"
)

func main() {
    hosts, err := hostsfile.NewHosts()
    if err != nil {
        log.Fatal(err.Error())
    }
    if err := hosts.Add("192.168.1.1", "my-hostname"); err != nil {
        log.Fatal(err.Error())
    }
    if err := hosts.Flush(); err != nil {
        log.Fatal(err.Error())
    }
}

Other Usage

Read in a hosts file from a custom location which is not the system default, this is useful for tests or systems with non-standard hosts file locations.

hosts, err := hostsfile.NewCustomHosts("./my-custom-hostsfile")

Use Add to put an ip and host combination in the hosts file

err := hosts.Add("192.168.1.1", "my-hostname")

Add is variadic and can take multiple hosts to add for the same ip

err := hosts.Add("192.168.1.1", "my-hostname", "another-hostname")

Use Remove to drop an ip and host combination from the hosts file

err := hosts.Remove("192.168.1.1", "my-hostname")

Remove is variadic and can take multiple hosts to remove from the same ip

err := hosts.Remove("192.168.1.1", "my-hostname", "another-hostname")

Flush the hosts file changes back to disk

err := hosts.Flush()

hostsfile's People

Contributors

cfergeau avatar guillaumerose avatar kaespi avatar luthermonson avatar toasterson avatar tomjn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

hostsfile's Issues

Duplicate lines in hostsfile after `Flush()`

commit 946b651 introduced a regression, Flush() duplicates some hostfiles lines as shown by this test case:

commit 88dad12e0131601416e2f488856f33c3d3ea80f3
Author: Christophe Fergeau <[email protected]>
Date:   Tue Jan 4 11:42:25 2022 +0100

    test: Add TestHosts_Flush() test case
    
    This tests Hosts.Flush(), which currently seems to be duplicating
    some hosts file entries.
    
    This is a regression which was introduced in commit 946b651a0.

diff --git a/hosts_test.go b/hosts_test.go
index 043f262..8d4482b 100644
--- a/hosts_test.go
+++ b/hosts_test.go
@@ -241,7 +241,7 @@ func BenchmarkHosts_Flush500k(b *testing.B) {
 	benchmarkHosts_Flush(50, b)
 }
 
-// benchmarks flushing a hostsfile and confirms the hashmap lookup for ips/hosts is thread save via mutex + locking
+// benchmarks flushing a hostsfile and confirms the hashmap lookup for ips/hosts is thread-safe via mutex + locking
 func benchmarkHosts_Flush(c int, b *testing.B) {
 	_, err := os.Create("hostsfile")
 	assert.Nil(b, err)
@@ -263,3 +263,17 @@ func benchmarkHosts_Flush(c int, b *testing.B) {
 	assert.Nil(b, hosts.Flush())
 	assert.Nil(b, os.Remove("hostsfile"))
 }
+
+func TestHosts_Flush(t *testing.T) {
+	_, err := os.Create("hostsfile")
+	assert.Nil(t, err)
+	hosts, err := NewCustomHosts("hostsfile")
+	assert.Nil(t, err)
+	defer assert.Nil(t, os.Remove("hostsfile"))
+	assert.Nil(t, hosts.Add("127.0.0.2", "host1"))
+	assert.Equal(t, 1, len(hosts.Lines))
+	assert.Equal(t, "127.0.0.2 host1", hosts.Lines[0].Raw)
+	assert.Nil(t, hosts.Flush())
+	assert.Equal(t, 1, len(hosts.Lines))
+	assert.Equal(t, "127.0.0.2 host1", hosts.Lines[0].Raw)
+}

Limiting hosts per line works for first line, but after that each item goes on its own line

This isn't a huge deal, but probably not what's intended.

Using the artifacts in ddev/ddev#4805 and running the manual test there,

for item in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do 
  sudo ddev hostname a$item.ddev.site 127.0.0.1
done

You'll see the results are that the first hosts line goes to 8, but after that they are all on separate lines.

127.0.0.1 localhost junk.ddev.site a1.ddev.site a2.ddev.site a3.ddev.site a4.ddev.site a5.ddev.site a6.ddev.site
127.0.0.1 a15.ddev.site
127.0.0.1 a14.ddev.site
127.0.0.1 a13.ddev.site
127.0.0.1 a12.ddev.site
127.0.0.1 a11.ddev.site
127.0.0.1 a10.ddev.site
127.0.0.1 a9.ddev.site
127.0.0.1 a8.ddev.site
127.0.0.1 a7.ddev.site

Code from https://github.com/rfay/ddev/blob/b71df9536b015854d9ee3cc7829861ef34e0e909/pkg/ddevapp/hostname_mgt.go#L135-L146 is

	hosts, err := goodhosts.NewCustomHosts(osHostsFilePath)

	if err != nil {
		return err
	}
	err = hosts.Add(ip, name)
	if err != nil {
		return err
	}
	hosts.HostsPerLine(8)
	err = hosts.Flush()
	return err

License?

Can you add a license please?
Thanks!

Comments are not published on Flush

Hi with the new update , Comments are not published
func (l *HostsLine) ToRaw() string {
var comment string
if l.Comment != "" {
comment = fmt.Sprintf(" %s%s", commentChar, l.Comment)
}

return fmt.Sprintf("%s %s%s", l.IP, strings.Join(l.Hosts, " "), comment)

}`

can be changed to

`func (l *HostsLine) ToRaw() string {
if l.IsComment() {
return l
}
var comment string
if l.Comment != "" {
comment = fmt.Sprintf(" %s%s", commentChar, l.Comment)
}

return fmt.Sprintf("%s %s%s", l.IP, strings.Join(l.Hosts, " "), comment)

}`

Bug: Adding a host can add duplicates with differing IPs

This situation is not handled:

when adding hostname with IP
  if ( h.HasHostname( 'example.com' ) AND ! h.Has( ip,'example.com ) ) {
    remove hostname with old IP

If I add a hostname example.com with 1.1.1.1, then try to add the same hostname with 2.2.2.2 the result is that I now have 2 entries for example.com for both IPs. I expected a single entry for 2.2.2.2.

When adding a host, old entries should be removed.

This has recently caught us out over at VVV with the vagrant plugin usage when a VirtualBox restriction forced us to change the IP we use. Users who upgraded without halting their VMs kept the hosts file entry, and when they reprovisioned a second entry was added with the new IP. As a result requests to our domains were sent to the old IP, and destroying/halting the VM only triggered the new entry to be removed, the old entry being preserved and persisting the issue.

Regression - panic when calling Clear and then Add

Version: 0.1.1

When calling Hosts.Clear() to remove lines from the hosts file and then regenerating the file with Hosts.Add cause a panic on this line:
hostsCopy := h.Lines[position[0]].Hosts because position[0] use the new lookup.

When calling Hosts.Clear, it should also clear the lookup information.

This was working on version 0.0.8.

Calling HostsPerLine() before Add() results in a panic with plain vanilla macOS hosts file

If you call HostsPerLine() before Add(), (with a plain-vanilla macOS starter hosts file) you get a panic, like this:

panic: runtime error: index out of range [6] with length 4

goroutine 1 [running]:
github.com/goodhosts/hostsfile.(*Hosts).Add(0x140003264d0, {0x16eff7b14, 0x9}, {0x14000460fe0?, 0x1, 0x1})
	/Users/rfay/workspace/ddev/vendor/github.com/goodhosts/hostsfile/hosts.go:167 +0x3ec
github.com/ddev/ddev/pkg/ddevapp.AddHostEntry({0x16eff7b06, 0xd}, {0x16eff7b14, 0x9})
	/Users/rfay/workspace/ddev/pkg/ddevapp/hostname_mgt.go:140 +0xd4
github.com/ddev/ddev/cmd/ddev/cmd.glob..func30(0x1019e66c0?, {0x14000066600?, 0x2, 0x2})
	/Users/rfay/workspace/ddev/cmd/ddev/cmd/hostname.go:74 +0x20c
github.com/spf13/cobra.(*Command).execute(0x1019e66c0, {0x140000665a0, 0x2, 0x2})
	/Users/rfay/workspace/ddev/vendor/github.com/spf13/cobra/command.go:860 +0x4ac
github.com/spf13/cobra.(*Command).ExecuteC(0x1019e98c0)
	/Users/rfay/workspace/ddev/vendor/github.com/spf13/cobra/command.go:974 +0x354
github.com/spf13/cobra.(*Command).Execute(...)
	/Users/rfay/workspace/ddev/vendor/github.com/spf13/cobra/command.go:902
github.com/ddev/ddev/cmd/ddev/cmd.Execute()
	/Users/rfay/workspace/ddev/cmd/ddev/cmd/root.go:143 +0x40
main.main()
	/Users/rfay/workspace/ddev/cmd/ddev/main.go:20 +0xac

This is demonstrated in a test repo: https://github.com/rfay/goodhostsbug/tree/broken

It's fixed by changing HostsPerLine() to later, see https://github.com/rfay/goodhostsbug

Add/Remove/Contains functions for HostsLine

Currently the hosts functions manipulate lines directly, but instead they should be encapsulated with add/remove/contains functions. This should make things easier to read as well as simplifying testing.

Panic: goodhosts does not check slice length during removal

Mind you, these entries were found in the wild with bone stock Proxmox installs. This was while using the remove command.

goodhosts/cli Command

hosts r ff00::0

Version[s] reproduced with

(Using goodhosts/cli in all cases)

  • Vendored copy that comes with goodhosts/cli
  • Latest release
  • Main branch

Excerpt of problematic IPv6 entries:

(ignore first line, it's only for context)

[::1 ip6-localhost ip6-loopback]
fe00::0 
ff00::0 
ff02::1 
ff02::2 
ff02::3 

Stack Trace:

removing ip ff00::0
panic: runtime error: slice bounds out of range [5:3]

goroutine 1 [running]:
github.com/goodhosts/hostsfile.(*Hosts).removeByPosition(...)
	/home/kayos/go/pkg/mod/github.com/goodhosts/[email protected]/hosts.go:390
github.com/goodhosts/hostsfile.(*Hosts).RemoveByIp(0xc0002f0770, {0x7fff5401b761?, 0x660254?})
	/home/kayos/go/pkg/mod/github.com/goodhosts/[email protected]/hosts.go:282 +0x1ff
github.com/goodhosts/cli/cmd.processSingleArg(0xc00029fae8?, {0x7fff5401b761, 0x7})
	/home/kayos/Workshop/goodhosts/cli/cmd/remove.go:97 +0xa9
github.com/goodhosts/cli/cmd.remove(0xc0002ee500)
	/home/kayos/Workshop/goodhosts/cli/cmd/remove.go:45 +0x145
github.com/urfave/cli/v2.(*Command).Run(0xc0001aab40, 0xc0002ee340)
	/home/kayos/go/pkg/mod/github.com/urfave/cli/[email protected]/command.go:163 +0x5bb
github.com/urfave/cli/v2.(*App).RunContext(0xc0001a4d00, {0x6c90d8?, 0xc0000140b0}, {0xc000010180, 0x3, 0x3})
	/home/kayos/go/pkg/mod/github.com/urfave/cli/[email protected]/app.go:313 +0xb48
github.com/urfave/cli/v2.(*App).Run(...)
	/home/kayos/go/pkg/mod/github.com/urfave/cli/[email protected]/app.go:224
main.main()
	/home/kayos/Workshop/goodhosts/cli/main.go:59 +0x414

Other Thoughts

I started trying to trace this out but I'm not sure exactly where to fix this yet. I'll try to take a look when I have more time.

HostsPerLine is destructive

The HostsPerLine function is destructive, and does a number of unexpected things:

  • it de-dupes which is the responsibility of a different function
  • it's stripping out comments

I believe this is related to goodhosts/vagrant#51

Please keep commit history and versioning!

I think it's fine to move this to an org, but a couple of good options:

  1. Just change the ownership of the project, and all issues and PRs will go with it.
  2. At least keep the commit and version history (by pushing up the git repo)

With either of these (#1 is far better) we can all tell what actually happened and what effect this has on our projects and dependence on this one.

Q: Why is the position of a host on the line used?

I'm debugging an issue that's sourced to code introduced in this commit:

57158c4

However, looking at it, I see that a host is being removed based on its position in a list, which does not make sense to me.

Would it not make more sense to generate the list fresh or remove by value? This seems very fragile. Would it not make more sense to de-duplicate any entries then remove by value?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.