Skip to content

Commit

Permalink
Feat/pkg refactor (#48)
Browse files Browse the repository at this point in the history
big module refactor, with 95 new tests! 🎉

* [x] Add a decent amount code coverage of all files in `pkg` directory.
* [x] Refactor `pkg` code to expose a better API to use as module.
* [x] Change semantics to have profiles as arguments instead of flag. #37
* [x] Allow to manage multiple profiles at once. Ex: `hostctl disable profile1 profile2... `
* [x] Add mutex to save file to avoid concurrency issues.

Fixes #37
Fixes #39
Closes #47
Related to #45
  • Loading branch information
guumaster committed Apr 13, 2020
1 parent 47c8bd0 commit cae3517
Show file tree
Hide file tree
Showing 76 changed files with 3,189 additions and 1,352 deletions.
29 changes: 28 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
strategy:
matrix:
go-version: [1.14.x]
platform: [macos-latest, windows-latest, ubuntu-latest]
platform: [macos-latest] # , windows-latest // TODO: Review Tests on windows
runs-on: ${{ matrix.platform }}
steps:
- name: Install Go
Expand All @@ -25,3 +25,30 @@ jobs:

- name: Test
run: go test ./...

coverage:
strategy:
matrix:
go-version: [1.14.x]
platform: [ubuntu-latest]
runs-on: ${{ matrix.platform }}
steps:
- name: Install Go
uses: actions/setup-go@v1
with:
go-version: ${{ matrix.go-version }}

- name: Checkout code
uses: actions/checkout@v2
- run: git fetch --prune --unshallow

- name: Test
run: |
go test ./... -cover -coverprofile=coverage.out
go tool cover -func=coverage.out
- name: Analyze with SonarCloud
uses: sonarsource/sonarcloud-github-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ hostctl
hostctl.exe
.etchosts
docs/public
coverage.out
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
[![Go Report Card][report-badge]][report-link]
[![License][license-badge]][license-link]
[![All Contributors][all-contributors-badge]][all-contributors-link]

[![Coverage][coverage-badge]][coverage-link]

# hostctl

Expand Down Expand Up @@ -113,6 +113,9 @@ This project follows the [all-contributors](https://github.com/all-contributors/
[license-badge]: https://img.shields.io/github/license/guumaster/hostctl
[license-link]: https://github.com/guumaster/hostctl/blob/master/LICENSE

[coverage-badge]: https://sonarcloud.io/api/project_badges/measure?project=guumaster_hostctl&metric=coverage
[coverage-link]: https://sonarcloud.io/dashboard?id=guumaster_hostctl

<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
[all-contributors-badge]: https://img.shields.io/badge/contributors-7-blue.svg
<!-- ALL-CONTRIBUTORS-BADGE:END -->
Expand Down
63 changes: 0 additions & 63 deletions cmd/add.go

This file was deleted.

49 changes: 25 additions & 24 deletions cmd/add_domains.go
Original file line number Diff line number Diff line change
@@ -1,49 +1,50 @@
package cmd

import (
"fmt"
"strings"

"github.com/spf13/cobra"

"github.com/guumaster/hostctl/pkg/host"
)

// addDomainsCmd represents the fromFile command
var addDomainsCmd = &cobra.Command{
Use: "domains",
Short: "Add content in your hosts file.",
Use: "domains [domains] [flag]",
Aliases: []string{"domain"},
Short: "Add content in your hosts file.",
Long: `
Set content in your hosts file.
If the profile already exists it will be added to it.`,
PreRunE: func(cmd *cobra.Command, args []string) error {
profile, _ := cmd.Flags().GetString("profile")

if profile == "" {
return host.MissingProfileError
}

if profile == "default" {
return host.DefaultProfileError
}
return nil
},
Args: commonCheckProfileOnly,
RunE: func(cmd *cobra.Command, args []string) error {
src, _ := cmd.Flags().GetString("host-file")
ip, _ := cmd.Flags().GetString("ip")
profile, _ := cmd.Flags().GetString("profile")
quiet, _ := cmd.Flags().GetBool("quiet")
name := args[0]
routes := args[1:]

h, err := host.NewFile(src)
if err != nil {
return err
}

err := host.AddFromArgs(&host.AddFromArgsOptions{
Domains: args,
IP: ip,
Dst: src,
Profile: profile,
Reset: false,
})
err = h.AddRoutes(name, ip, routes)
if err != nil {
return err
}

return host.Enable(src, profile)
err = h.Flush()
if err != nil {
return err
}
if !quiet {
fmt.Fprintf(cmd.OutOrStdout(), "Domains '%s' added.\n\n", strings.Join(args[1:], ", "))
}
return nil
},
PostRunE: func(cmd *cobra.Command, args []string) error {
return postActionCmd(cmd, args, removeDomainsCmd)
return postActionCmd(cmd, args, removeDomainsCmd, true)
},
}
69 changes: 69 additions & 0 deletions cmd/add_domains_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package cmd

import (
"bytes"
"io/ioutil"
"os"
"testing"

"github.com/stretchr/testify/assert"
)

func Test_AddDomains(t *testing.T) {
cmd := rootCmd

t.Run("Add domains", func(t *testing.T) {
tmp := makeTempHostsFile(t, "addDomainCmd")
defer os.Remove(tmp.Name())
b := bytes.NewBufferString("")

cmd.SetOut(b)
cmd.SetArgs([]string{"add", "domains", "profile1", "arg.domain.loc", "--host-file", tmp.Name()})

err := cmd.Execute()
assert.NoError(t, err)

out, err := ioutil.ReadAll(b)
assert.NoError(t, err)

actual := "\n" + string(out)
expected := `
+----------+--------+-----------+----------------+
| PROFILE | STATUS | IP | DOMAIN |
+----------+--------+-----------+----------------+
| profile1 | on | 127.0.0.1 | first.loc |
| profile1 | on | 127.0.0.1 | second.loc |
| profile1 | on | 127.0.0.1 | arg.domain.loc |
+----------+--------+-----------+----------------+
`
assert.Contains(t, actual, expected)
})

t.Run("Add domains with IP", func(t *testing.T) {
tmp := makeTempHostsFile(t, "addDomainCmd")
defer os.Remove(tmp.Name())
b := bytes.NewBufferString("")

cmd.SetOut(b)
cmd.SetArgs([]string{"add", "domains", "profile1", "--ip", "5.5.5.5", "arg2.domain.loc", "--host-file", tmp.Name()})

err := cmd.Execute()
assert.NoError(t, err)

out, err := ioutil.ReadAll(b)
assert.NoError(t, err)

actual := "\n" + string(out)
expected := `
+----------+--------+-----------+-----------------+
| PROFILE | STATUS | IP | DOMAIN |
+----------+--------+-----------+-----------------+
| profile1 | on | 127.0.0.1 | first.loc |
| profile1 | on | 127.0.0.1 | second.loc |
| profile1 | on | 5.5.5.5 | arg2.domain.loc |
+----------+--------+-----------+-----------------+
`
assert.Contains(t, actual, expected)
})

}
103 changes: 103 additions & 0 deletions cmd/add_replace.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package cmd

import (
"io"
"os"

"github.com/spf13/cobra"

"github.com/guumaster/hostctl/pkg/host"
)

// addCmd represents the fromFile command
var addCmd = &cobra.Command{
Use: "add-to [profile] [flags]",
Aliases: []string{"add"},
Short: "Add content to a profile in your hosts file.",
Long: `
Reads from a file and set content to a profile in your hosts file.
If the profile already exists it will be added to it.`,
Args: commonCheckArgs,
RunE: makeAddReplace("add"),
PostRunE: func(cmd *cobra.Command, args []string) error {
return postActionCmd(cmd, args, removeCmd, true)
},
}

// replaceCmd represents the setFromFile command
var replaceCmd = &cobra.Command{
Use: "replace [profile] [domains] [flags]",
Aliases: []string{"set"},
Short: "Replace content to a profile in your hosts file.",
Long: `
Reads from a file and set content to a profile in your hosts file.
If the profile already exists it will be overwritten.
`,
Args: commonCheckArgs,
RunE: makeAddReplace("replace"),
PostRunE: postRunListOnly,
}

func init() {

addCmd.Flags().StringP("from", "f", "", "file to read")
addCmd.PersistentFlags().DurationP("wait", "w", -1, "Enables a profile for a specific amount of time")
rootCmd.AddCommand(addCmd)

replaceCmd.Flags().StringP("from", "f", "", "file to read")
rootCmd.AddCommand(replaceCmd)

addDomainsCmd.Flags().String("ip", "127.0.0.1", "domains ip")
addCmd.AddCommand(addDomainsCmd)

}

func makeAddReplace(action string) func(cmd *cobra.Command, profiles []string) error {
actionFn := func(h *host.File, p *host.Profile) error {
return h.AddProfile(*p)
}
if action == "replace" {
actionFn = func(h *host.File, p *host.Profile) error {
return h.ReplaceProfile(*p)
}
}

return func(cmd *cobra.Command, profiles []string) error {
src, _ := cmd.Flags().GetString("host-file")
from, _ := cmd.Flags().GetString("from")

in := cmd.InOrStdin()

var r io.Reader
var err error
if isPiped() || in != os.Stdin {
r = in
} else {
r, err = os.Open(from)
if err != nil {
return err
}
}

p, err := host.NewProfileFromReader(r)
if err != nil {
return err
}

h, err := host.NewFile(src)
if err != nil {
return err
}

p.Name = profiles[0]
p.Status = host.Enabled

err = actionFn(h, p)
if err != nil {
return err
}

return h.Flush()
}

}
Loading

0 comments on commit cae3517

Please sign in to comment.