Skip to content

Commit

Permalink
Merge tag '0.0.5' into support-windows
Browse files Browse the repository at this point in the history
  • Loading branch information
3846masa committed Sep 7, 2017
2 parents 03d00bf + e7d0792 commit de458d9
Show file tree
Hide file tree
Showing 12 changed files with 171 additions and 3 deletions.
11 changes: 11 additions & 0 deletions .codeclimate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
engines:
gofmt:
enabled: true
golint:
enabled: true

ratings:
paths:
- "**.go"

exclude_paths:
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Change log

## 0.1.0 - 2017-03-04
### Added
* Ask permission before installing a package that needs to listen on ports, access environment variables, or access files/directories on the host.
* A `-f` flag to `whalebrew install` to force install a package over an existing file.

## 0.0.4 - 2017-02-07
### Added
* `whalebrew edit` command for editing packages
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@ There are some labels you can use to configure how Whalebrew installs your image

LABEL io.whalebrew.config.ports '["8100:8100"]'

* `io.whalebrew.config.networks`: A list of networks to connect on the container.

LABEL io.whalebrew.config.networks '["host"]'

### Whalebrew images

We maintain a set of packages which are known to follow these requirements under the `whalebrew` organization on [GitHub](https://github.com/whalebrew) and [Docker Hub](https://hub.docker.com/u/whalebrew/). If you want to add a package to this, open a pull request against [whalebrew-packages](https://github.com/whalebrew/whalebrew-packages).
Expand Down
1 change: 0 additions & 1 deletion cmd/edit.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ var editCommand = &cobra.Command{
Use: "edit PACKAGENAME",
Short: "Edit a package file",
Long: "Edit a package file using your default editor ($EDITOR).",
DisableFlagParsing: true,
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return cmd.Help()
Expand Down
17 changes: 16 additions & 1 deletion cmd/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"os"
"os/exec"

"github.com/Songmu/prompter"
"github.com/bfirsh/whalebrew/client"
"github.com/bfirsh/whalebrew/packages"
dockerClient "github.com/docker/docker/client"
Expand All @@ -14,9 +15,11 @@ import (
)

var customPackageName string
var forceInstall bool

func init() {
installCommand.Flags().StringVarP(&customPackageName, "name", "n", "", "Name to give installed package. Defaults to image name.")
installCommand.Flags().BoolVarP(&forceInstall, "force", "f", false, "Replace existing package if already exists. Defaults to false.")

RootCmd.AddCommand(installCommand)
}
Expand Down Expand Up @@ -65,8 +68,20 @@ var installCommand = &cobra.Command{
if customPackageName != "" {
pkg.Name = customPackageName
}

preinstallMessage := pkg.PreinstallMessage()
if preinstallMessage != "" {
fmt.Println(preinstallMessage)
if !prompter.YN("Is this okay?", true) {
return fmt.Errorf("not installing package")
}
}
pm := packages.NewPackageManager(viper.GetString("install_path"))
err = pm.Install(pkg)
if forceInstall {
err = pm.ForceInstall(pkg)
} else {
err = pm.Install(pkg)
}
if err != nil {
return err
}
Expand Down
5 changes: 5 additions & 0 deletions cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ var runCommand = &cobra.Command{
dockerArgs = append(dockerArgs, pkg.Image)
dockerArgs = append(dockerArgs, args[1:]...)

for _, network := range pkg.Networks {
dockerArgs = append(dockerArgs, "--net")
dockerArgs = append(dockerArgs, network)
}

if runtime.GOOS == "windows" {
dockerCmd := exec.Command(dockerPath, dockerArgs[1:]...)
dockerCmd.Env = os.Environ()
Expand Down
13 changes: 13 additions & 0 deletions packages/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,19 @@ func (pm *PackageManager) Install(pkg *Package) error {
return ioutil.WriteFile(packagePath, d, 0755)
}

// ForceInstall installs a package
func (pm *PackageManager) ForceInstall(pkg *Package) error {
d, err := yaml.Marshal(&pkg)
if err != nil {
return err
}

packagePath := path.Join(pm.InstallPath, pkg.Name)

d = append([]byte("#!/usr/bin/env whalebrew\n"), d...)
return ioutil.WriteFile(packagePath, d, 0755)
}

// List lists installed packages
func (pm *PackageManager) List() (map[string]*Package, error) {
packages := make(map[string]*Package)
Expand Down
41 changes: 41 additions & 0 deletions packages/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,48 @@ func TestPackageManagerInstall(t *testing.T) {
err = pm.Install(pkg)
assert.NotNil(t, err)
assert.Contains(t, err.Error(), "already exists")
}

func TestPackageManagerForceInstall(t *testing.T) {
installPath, err := ioutil.TempDir("", "whalebrewtest")
assert.Nil(t, err)
pm := NewPackageManager(installPath)

pkg, err := NewPackageFromImage("whalebrew/whalesay", types.ImageInspect{})
assert.Nil(t, err)
err = pm.ForceInstall(pkg)
assert.Nil(t, err)
packagePath := path.Join(installPath, "whalesay")
contents, err := ioutil.ReadFile(packagePath)
assert.Nil(t, err)
assert.Equal(t, strings.TrimSpace(string(contents)), "#!/usr/bin/env whalebrew\nimage: whalebrew/whalesay")
fi, err := os.Stat(packagePath)
assert.Nil(t, err)
assert.Equal(t, int(fi.Mode()), 0755)

// custom install path
pkg, err = NewPackageFromImage("whalebrew/whalesay", types.ImageInspect{})
assert.Nil(t, err)
pkg.Name = "whalesay2"
err = pm.ForceInstall(pkg)
assert.Nil(t, err)
packagePath = path.Join(installPath, "whalesay2")
contents, err = ioutil.ReadFile(packagePath)
assert.Nil(t, err)
assert.Equal(t, strings.TrimSpace(string(contents)), "#!/usr/bin/env whalebrew\nimage: whalebrew/whalesay")

// file already exists
err = ioutil.WriteFile(path.Join(installPath, "alreadyexists"), []byte("not a whalebrew package"), 0755)
assert.Nil(t, err)
pkg, err = NewPackageFromImage("whalebrew/whalesay", types.ImageInspect{})
assert.Nil(t, err)
pkg.Name = "alreadyexists"
err = pm.ForceInstall(pkg)
assert.Nil(t, err)
packagePath = path.Join(installPath, "alreadyexists")
contents, err = ioutil.ReadFile(packagePath)
assert.Nil(t, err)
assert.Equal(t, strings.TrimSpace(string(contents)), "#!/usr/bin/env whalebrew\nimage: whalebrew/whalesay")
}

func TestPackageManagerList(t *testing.T) {
Expand Down
44 changes: 44 additions & 0 deletions packages/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package packages

import (
"context"
"fmt"
"io/ioutil"
"strings"

Expand All @@ -17,6 +18,7 @@ type Package struct {
Image string `yaml:"image"`
Volumes []string `yaml:"volumes,omitempty"`
Ports []string `yaml:"ports,omitempty"`
Networks []string `yaml:"networks,omitempty"`
}

// NewPackageFromImage creates a package from a given image name,
Expand Down Expand Up @@ -58,6 +60,12 @@ func NewPackageFromImage(image string, imageInspect types.ImageInspect) (*Packag
return pkg, err
}
}

if networks, ok := labels["io.whalebrew.config.networks"]; ok {
if err := yaml.Unmarshal([]byte(networks), &pkg.Networks); err != nil {
return pkg, err
}
}
}

return pkg, nil
Expand Down Expand Up @@ -85,3 +93,39 @@ func (pkg *Package) ImageInspect() (*types.ImageInspect, error) {
img, _, err := cli.ImageInspectWithRaw(context.Background(), pkg.Image)
return &img, err
}

// PreinstallMessage returns the preinstall message for the package
func (pkg *Package) PreinstallMessage() string {
if len(pkg.Environment) == 0 && len(pkg.Volumes) == 0 && len(pkg.Ports) == 0 {
return ""
}

out := []string{"This package needs additional access to your system. It wants to:", ""}
for _, env := range pkg.Environment {
out = append(out, fmt.Sprintf("* Read the environment variable %s", env))
}

if len(pkg.Ports) > 0 {
for _, port := range pkg.Ports {
// no support for interfaces (e.g. 127.0.0.1:80:80)
portNumber := strings.Split(port, ":")[0]
proto := "TCP"
if strings.HasSuffix(port, "udp") {
proto = "UDP"
}
out = append(out, fmt.Sprintf("* Listen on %s port %s", proto, portNumber))
}
}

for _, vol := range pkg.Volumes {
if len(strings.Split(vol, ":")) > 1 {
text := "* Read and write to the file or directory %q"
if strings.HasSuffix(vol, "ro") {
text = "* Read the file or directory %q"
}
out = append(out, fmt.Sprintf(text, strings.Split(vol, ":")[0]))
}
}

return strings.Join(out, "\n") + "\n"
}
28 changes: 28 additions & 0 deletions packages/package_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ func TestNewPackageFromImage(t *testing.T) {
"io.whalebrew.config.environment": "[\"SOME_CONFIG_OPTION\"]",
"io.whalebrew.config.volumes": "[\"/somesource:/somedest\"]",
"io.whalebrew.config.ports": "[\"8100:8100\"]",
"io.whalebrew.config.networks": "[\"host\"]",
},
},
})
Expand All @@ -32,5 +33,32 @@ func TestNewPackageFromImage(t *testing.T) {
assert.Equal(t, pkg.Environment, []string{"SOME_CONFIG_OPTION"})
assert.Equal(t, pkg.Volumes, []string{"/somesource:/somedest"})
assert.Equal(t, pkg.Ports, []string{"8100:8100"})
assert.Equal(t, pkg.Networks, []string{"host"})

}

func TestPreinstallMessage(t *testing.T) {
pkg := &Package{}
assert.Equal(t, pkg.PreinstallMessage(), "")

pkg = &Package{
Environment: []string{"AWS_ACCESS_KEY"},
Ports: []string{
"80:80",
"81:81:udp",
},
Volumes: []string{
"/etc/passwd:/passwdtosteal",
"/etc/readonly:/readonly:ro",
},
}
assert.Equal(t, pkg.PreinstallMessage(),
"This package needs additional access to your system. It wants to:\n"+
"\n"+
"* Read the environment variable AWS_ACCESS_KEY\n"+
"* Listen on TCP port 80\n"+
"* Listen on UDP port 81\n"+
"* Read and write to the file or directory \"/etc/passwd\"\n"+
"* Read the file or directory \"/etc/readonly\"\n",
)
}
3 changes: 3 additions & 0 deletions script/build
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#!/bin/bash

set -e

mkdir -p build
cd build
gox -osarch="linux/amd64" -osarch="darwin/amd64" ../
Expand Down
2 changes: 1 addition & 1 deletion version/version.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package version

// Version is the current Whalebrew version
const Version = "0.0.4"
const Version = "0.0.5"

0 comments on commit de458d9

Please sign in to comment.