<commit_before>package provision

import (
	"strings"
	"testing"

	docker "github.com/fsouza/go-dockerclient"
	fake "github.com/fsouza/go-dockerclient/testing"
)

func TestFnClientWrongClient(t *testing.T) {
	_, err := FnClient("http://localhost:a")
	if err == nil {
		t.Fatal("expected error but no errors found")
	}
}

func createFakeDockerAPI(t *testing.T) *fake.DockerServer {
	// Fake docker api
	server, err := fake.NewServer("127.0.0.1:0", nil, nil)
	if err != nil {
		t.Fatal(err)
	}
	return server
}

func createFakeImage(client *docker.Client) string {
	client.PullImage(docker.PullImageOptions{Repository: "gofn/python"}, docker.AuthConfiguration{})
	return "gofn/python"
}

func createFakeContainer(client *docker.Client, t *testing.T) *docker.Container {
	image := createFakeImage(client)
	container, err := client.CreateContainer(docker.CreateContainerOptions{
		Name: "gofn-123",
		Config: &docker.Config{
			Image:     image,
			StdinOnce: true,
			OpenStdin: true,
		},
	})
	if err != nil {
		t.Fatal(err)
	}
	return container
}

func runFakeContainer(client *docker.Client, containerID string, t *testing.T) {
	err := client.StartContainer(containerID, nil)
	if err != nil {
		t.Fatal(err)
	}
}

func NewTestClient(host string, t *testing.T) *docker.Client {
	client, err := docker.NewClient(host)
	if err != nil {
		t.Fatal(err)
	}
	return client
}

func TestFnRemoveContainerSuccessfully(t *testing.T) {

	server := createFakeDockerAPI(t)
	defer server.Stop()

	// Instantiate a client
	client := NewTestClient(server.URL(), t)

	// Create container before remove it
	container := createFakeContainer(client, t)

	// Remove a container
	if e := FnRemove(client, container.ID); e != nil {
		t.Errorf("Expected no errors but %q found", e)
	}
}

func TestFnRemoveContainerImageNotFound(t *testing.T) {

	server := createFakeDockerAPI(t)
	defer server.Stop()

	// Instantiate a client
	client := NewTestClient(server.URL(), t)

	// Remove a container
	if e := FnRemove(client, "wrong"); e == nil {
		t.Error("expected errors but no errors found")
	}
}

func TestFnContainerCreatedSuccessfully(t *testing.T) {

	server := createFakeDockerAPI(t)
	defer server.Stop()

	// Instantiate a client
	client := NewTestClient(server.URL(), t)
	image := createFakeImage(client)

	container, err := FnContainer(client, image, "")
	if err != nil {
		t.Errorf("Expected no errors but %q found", err)
	}
	// container name should starts with gofn
	if !strings.HasPrefix(container.Name, "gofn") {
		t.Errorf("container should starts with gofn but found %q", container.Name)
	}

}

func TestFnContainerInvalidImage(t *testing.T) {

	server := createFakeDockerAPI(t)
	defer server.Stop()

	// Instantiate a client
	client := NewTestClient(server.URL(), t)
	image := "wrong"

	_, err := FnContainer(client, image, "")
	if err == nil {
		t.Errorf("Expected errors but no errors found")
	}

}

func TestFnContainerCreatedWithVolume(t *testing.T) {

	server := createFakeDockerAPI(t)
	defer server.Stop()

	// Instantiate a client
	client := NewTestClient(server.URL(), t)
	image := createFakeImage(client)

	volume := "/tmp:/tmp"
	container, err := FnContainer(client, image, volume)
	if err != nil {
		t.Errorf("Expected no errors but %q found", err)
	}
	// container name should starts with gofn
	if !strings.HasPrefix(container.Name, "gofn") {
		t.Errorf("container should starts with gofn but found %q", container.Name)
	}
	// volume is binded with container
	if container.HostConfig.Binds[0] != volume {
		t.Errorf("expected volume %q bout found %q", volume, container.HostConfig.Binds[0])
	}
}

func TestFnBuildImageSuccessfully(t *testing.T) {
	server := createFakeDockerAPI(t)
	defer server.Stop()

	// Instantiate a client
	client := NewTestClient(server.URL(), t)
	name, _, err := FnImageBuild(client, &BuildOptions{"./testing_data", "", false, "test", "", nil})
	if err != nil {
		t.Errorf("FnImageBuild expected nil but found %q, %q", name, err)
	}

	imageName := "gofn/test"
	if name != imageName {
		t.Errorf("image name expected %q but found %q", imageName, name)
	}
}

func TestFnBuildImageRemoteSuccessfully(t *testing.T) {
	server := createFakeDockerAPI(t)
	defer server.Stop()

	// Instantiate a client
	client := NewTestClient(server.URL(), t)
	name, _, err := FnImageBuild(client, &BuildOptions{"./testing_data", "", false, "test", "https://github.com/gofn/dockerfile-python-exampl://github.com/gofn/dockerfile-python-example.git", nil})
	if err != nil {
		t.Errorf("FnImageBuild expected nil but found %q, %q", name, err)
	}

	imageName := "gofn/test"
	if name != imageName {
		t.Errorf("image name expected %q but found %q", imageName, name)
	}
}

func TestFnBuildImageDoNotUsePrefixImageName(t *testing.T) {
	server := createFakeDockerAPI(t)
	defer server.Stop()

	// Instantiate a client
	client := NewTestClient(server.URL(), t)
	imageName := "testDoNotUsePrefixImageName"
	name, _, err := FnImageBuild(client, &BuildOptions{"./wrong", "Dockerfile", true, imageName, "", nil})
	if name != imageName {
		t.Errorf("image name expected %q but found %q", imageName, name)
	}
}

func TestFnBuildImageDockerfileNotFound(t *testing.T) {
	server := createFakeDockerAPI(t)
	defer server.Stop()

	// Instantiate a client
	client := NewTestClient(server.URL(), t)
	_, _, err := FnImageBuild(client, &BuildOptions{"./wrong", "Dockerfile", false, "test", "", nil})
	if err == nil {
		t.Errorf("FnImageBuild expected error but returned nil")
	}
}

func TestFnFindImageSuccessfully(t *testing.T) {
	server := createFakeDockerAPI(t)
	defer server.Stop()

	// Instantiate a client
	client := NewTestClient(server.URL(), t)
	img := createFakeImage(client)

	_, err := FnFindImage(client, img)
	if err != nil {
		t.Errorf("no errors expected but found %q", err)
	}
}

func TestFnFindImageImageNotFound(t *testing.T) {
	server := createFakeDockerAPI(t)
	defer server.Stop()

	// Instantiate a client
	client := NewTestClient(server.URL(), t)

	_, err := FnFindImage(client, "wrong")
	if err != ErrImageNotFound {
		t.Errorf("unexpected error: %q", err)
	}
}

func TestFnFindImageServerError(t *testing.T) {
	client := NewTestClient("wrong", t)

	_, err := FnFindImage(client, "wrong")
	if err == nil || err == ErrImageNotFound {
		t.Errorf("Expected other errors but found ImageNotfound or null: %q", err)
	}
}

func TestFnFindContainerSuccessfully(t *testing.T) {
	server := createFakeDockerAPI(t)
	defer server.Stop()

	// Instantiate a client
	client := NewTestClient(server.URL(), t)

	// Create container before find it
	container := createFakeContainer(client, t)

	// Find a container by image
	if _, e := FnFindContainer(client, container.Image); e != nil {
		t.Errorf("Expected no errors but %q found", e)
	}
}

func TestFnFindContainerContainerNotFound(t *testing.T) {
	server := createFakeDockerAPI(t)
	defer server.Stop()

	// Instantiate a client
	client := NewTestClient(server.URL(), t)

	// Find a container by image
	if _, e := FnFindContainer(client, "python"); e != ErrContainerNotFound {
		t.Errorf("Expected %q but found %q", ErrContainerNotFound, e)
	}
}

func TestFnFindContainerServerError(t *testing.T) {
	client := NewTestClient("wrong", t)

	_, err := FnFindContainer(client, "wrong")
	if err == nil || err == ErrContainerNotFound {
		t.Errorf("Expected other errors but found COntainerNotfound or null: %q", err)
	}
}

func TestFnKilContainerSuccessfully(t *testing.T) {

	server := createFakeDockerAPI(t)
	defer server.Stop()
	// instantiate a client
	client := NewTestClient(server.URL(), t)

	// create container before kill it
	container := createFakeContainer(client, t)

	// make sure that container are runnig
	runFakeContainer(client, container.ID, t)

	// kill a container
	if e := FnKillContainer(client, container.ID); e != nil {
		t.Errorf("Expected no errors but %q found", e)
	}

}

func TestFnKilContainerNotRunning(t *testing.T) {

	server := createFakeDockerAPI(t)
	defer server.Stop()

	// Instantiate a client
	client := NewTestClient(server.URL(), t)

	// Create container before kill it
	container := createFakeContainer(client, t)

	// kill a container
	if e := FnKillContainer(client, container.ID); e == nil {
		t.Errorf("expecting errors, but nothing found")
	}
}

func TestFnKilContainerNotFound(t *testing.T) {

	server := createFakeDockerAPI(t)
	defer server.Stop()

	// Instantiate a client
	client := NewTestClient(server.URL(), t)

	// kill a container
	fakeID := "wrong123"
	if e := FnKillContainer(client, fakeID); e == nil {
		t.Errorf("expecting errors, but nothing found")
	}
}

func TestFnConfigVolumeAllEmpty(t *testing.T) {
	volume := FnConfigVolume(&VolumeOptions{})
	if volume != "" {
		t.Errorf("Expected \"\" but found %q", volume)
	}
}

func TestFnConfigVolumeDestinationOmitted(t *testing.T) {
	volume := FnConfigVolume(&VolumeOptions{Source: "/tmp"})
	if volume != "/tmp:/tmp" {
		t.Errorf("Expected \"/tmp:/tmp\" but found %q", volume)
	}
}

func TestFnConfigVolumeOnlyDestination(t *testing.T) {
	volume := FnConfigVolume(&VolumeOptions{Destination: "/tmp"})
	if volume != ":/tmp" {
		t.Errorf("Expected \":/tmp\" but found %q", volume)
	}
}

func TestFnConfigVolumeAllFields(t *testing.T) {
	volume := FnConfigVolume(&VolumeOptions{
		Source:      "/tmp",
		Destination: "/tmp",
	})
	if volume != "/tmp:/tmp" {
		t.Errorf("Expected \"/tmp:/tmp\" but found %q", volume)
	}
}
<commit_msg>fixed typo, check err var<commit_after>package provision

import (
	"strings"
	"testing"

	docker "github.com/fsouza/go-dockerclient"
	fake "github.com/fsouza/go-dockerclient/testing"
)

func TestFnClientWrongClient(t *testing.T) {
	_, err := FnClient("http://localhost:a")
	if err == nil {
		t.Fatal("expected error but no errors found")
	}
}

func createFakeDockerAPI(t *testing.T) *fake.DockerServer {
	// Fake docker api
	server, err := fake.NewServer("127.0.0.1:0", nil, nil)
	if err != nil {
		t.Fatal(err)
	}
	return server
}

func createFakeImage(client *docker.Client) string {
	client.PullImage(docker.PullImageOptions{Repository: "gofn/python"}, docker.AuthConfiguration{})
	return "gofn/python"
}

func createFakeContainer(client *docker.Client, t *testing.T) *docker.Container {
	image := createFakeImage(client)
	container, err := client.CreateContainer(docker.CreateContainerOptions{
		Name: "gofn-123",
		Config: &docker.Config{
			Image:     image,
			StdinOnce: true,
			OpenStdin: true,
		},
	})
	if err != nil {
		t.Fatal(err)
	}
	return container
}

func runFakeContainer(client *docker.Client, containerID string, t *testing.T) {
	err := client.StartContainer(containerID, nil)
	if err != nil {
		t.Fatal(err)
	}
}

func NewTestClient(host string, t *testing.T) *docker.Client {
	client, err := docker.NewClient(host)
	if err != nil {
		t.Fatal(err)
	}
	return client
}

func TestFnRemoveContainerSuccessfully(t *testing.T) {

	server := createFakeDockerAPI(t)
	defer server.Stop()

	// Instantiate a client
	client := NewTestClient(server.URL(), t)

	// Create container before remove it
	container := createFakeContainer(client, t)

	// Remove a container
	if e := FnRemove(client, container.ID); e != nil {
		t.Errorf("Expected no errors but %q found", e)
	}
}

func TestFnRemoveContainerImageNotFound(t *testing.T) {

	server := createFakeDockerAPI(t)
	defer server.Stop()

	// Instantiate a client
	client := NewTestClient(server.URL(), t)

	// Remove a container
	if e := FnRemove(client, "wrong"); e == nil {
		t.Error("expected errors but no errors found")
	}
}

func TestFnContainerCreatedSuccessfully(t *testing.T) {

	server := createFakeDockerAPI(t)
	defer server.Stop()

	// Instantiate a client
	client := NewTestClient(server.URL(), t)
	image := createFakeImage(client)

	container, err := FnContainer(client, image, "")
	if err != nil {
		t.Errorf("Expected no errors but %q found", err)
	}
	// container name should starts with gofn
	if !strings.HasPrefix(container.Name, "gofn") {
		t.Errorf("container should starts with gofn but found %q", container.Name)
	}

}

func TestFnContainerInvalidImage(t *testing.T) {

	server := createFakeDockerAPI(t)
	defer server.Stop()

	// Instantiate a client
	client := NewTestClient(server.URL(), t)
	image := "wrong"

	_, err := FnContainer(client, image, "")
	if err == nil {
		t.Errorf("Expected errors but no errors found")
	}

}

func TestFnContainerCreatedWithVolume(t *testing.T) {

	server := createFakeDockerAPI(t)
	defer server.Stop()

	// Instantiate a client
	client := NewTestClient(server.URL(), t)
	image := createFakeImage(client)

	volume := "/tmp:/tmp"
	container, err := FnContainer(client, image, volume)
	if err != nil {
		t.Errorf("Expected no errors but %q found", err)
	}
	// container name should starts with gofn
	if !strings.HasPrefix(container.Name, "gofn") {
		t.Errorf("container should starts with gofn but found %q", container.Name)
	}
	// volume is binded with container
	if container.HostConfig.Binds[0] != volume {
		t.Errorf("expected volume %q bout found %q", volume, container.HostConfig.Binds[0])
	}
}

func TestFnBuildImageSuccessfully(t *testing.T) {
	server := createFakeDockerAPI(t)
	defer server.Stop()

	// Instantiate a client
	client := NewTestClient(server.URL(), t)
	name, _, err := FnImageBuild(client, &BuildOptions{"./testing_data", "", false, "test", "", nil})
	if err != nil {
		t.Errorf("FnImageBuild expected nil but found %q, %q", name, err)
	}

	imageName := "gofn/test"
	if name != imageName {
		t.Errorf("image name expected %q but found %q", imageName, name)
	}
}

func TestFnBuildImageRemoteSuccessfully(t *testing.T) {
	server := createFakeDockerAPI(t)
	defer server.Stop()

	// Instantiate a client
	client := NewTestClient(server.URL(), t)
	name, _, err := FnImageBuild(client, &BuildOptions{"./testing_data", "", false, "test", "https://github.com/gofn/dockerfile-python-exampl://github.com/gofn/dockerfile-python-example.git", nil})
	if err != nil {
		t.Errorf("FnImageBuild expected nil but found %q, %q", name, err)
	}

	imageName := "gofn/test"
	if name != imageName {
		t.Errorf("image name expected %q but found %q", imageName, name)
	}
}

func TestFnBuildImageDoNotUsePrefixImageName(t *testing.T) {
	server := createFakeDockerAPI(t)
	defer server.Stop()

	// Instantiate a client
	client := NewTestClient(server.URL(), t)
	imageName := "testDoNotUsePrefixImageName"
	name, _, err := FnImageBuild(client, &BuildOptions{"./wrong", "Dockerfile", true, imageName, "", nil})
	if err != nil {
		t.Errorf("FnImageBuild expected nil but found %q, %q", name, err)
	}
	if name != imageName {
		t.Errorf("image name expected %q but found %q", imageName, name)
	}
}

func TestFnBuildImageDockerfileNotFound(t *testing.T) {
	server := createFakeDockerAPI(t)
	defer server.Stop()

	// Instantiate a client
	client := NewTestClient(server.URL(), t)
	_, _, err := FnImageBuild(client, &BuildOptions{"./wrong", "Dockerfile", false, "test", "", nil})
	if err == nil {
		t.Errorf("FnImageBuild expected error but returned nil")
	}
}

func TestFnFindImageSuccessfully(t *testing.T) {
	server := createFakeDockerAPI(t)
	defer server.Stop()

	// Instantiate a client
	client := NewTestClient(server.URL(), t)
	img := createFakeImage(client)

	_, err := FnFindImage(client, img)
	if err != nil {
		t.Errorf("no errors expected but found %q", err)
	}
}

func TestFnFindImageImageNotFound(t *testing.T) {
	server := createFakeDockerAPI(t)
	defer server.Stop()

	// Instantiate a client
	client := NewTestClient(server.URL(), t)

	_, err := FnFindImage(client, "wrong")
	if err != ErrImageNotFound {
		t.Errorf("unexpected error: %q", err)
	}
}

func TestFnFindImageServerError(t *testing.T) {
	client := NewTestClient("wrong", t)

	_, err := FnFindImage(client, "wrong")
	if err == nil || err == ErrImageNotFound {
		t.Errorf("Expected other errors but found ImageNotfound or null: %q", err)
	}
}

func TestFnFindContainerSuccessfully(t *testing.T) {
	server := createFakeDockerAPI(t)
	defer server.Stop()

	// Instantiate a client
	client := NewTestClient(server.URL(), t)

	// Create container before find it
	container := createFakeContainer(client, t)

	// Find a container by image
	if _, e := FnFindContainer(client, container.Image); e != nil {
		t.Errorf("Expected no errors but %q found", e)
	}
}

func TestFnFindContainerContainerNotFound(t *testing.T) {
	server := createFakeDockerAPI(t)
	defer server.Stop()

	// Instantiate a client
	client := NewTestClient(server.URL(), t)

	// Find a container by image
	if _, e := FnFindContainer(client, "python"); e != ErrContainerNotFound {
		t.Errorf("Expected %q but found %q", ErrContainerNotFound, e)
	}
}

func TestFnFindContainerServerError(t *testing.T) {
	client := NewTestClient("wrong", t)

	_, err := FnFindContainer(client, "wrong")
	if err == nil || err == ErrContainerNotFound {
		t.Errorf("Expected other errors but found COntainerNotfound or null: %q", err)
	}
}

func TestFnKilContainerSuccessfully(t *testing.T) {

	server := createFakeDockerAPI(t)
	defer server.Stop()
	// instantiate a client
	client := NewTestClient(server.URL(), t)

	// create container before kill it
	container := createFakeContainer(client, t)

	// make sure that container are runnig
	runFakeContainer(client, container.ID, t)

	// kill a container
	if e := FnKillContainer(client, container.ID); e != nil {
		t.Errorf("Expected no errors but %q found", e)
	}

}

func TestFnKilContainerNotRunning(t *testing.T) {

	server := createFakeDockerAPI(t)
	defer server.Stop()

	// Instantiate a client
	client := NewTestClient(server.URL(), t)

	// Create container before kill it
	container := createFakeContainer(client, t)

	// kill a container
	if e := FnKillContainer(client, container.ID); e == nil {
		t.Errorf("expecting errors, but nothing found")
	}
}

func TestFnKilContainerNotFound(t *testing.T) {

	server := createFakeDockerAPI(t)
	defer server.Stop()

	// Instantiate a client
	client := NewTestClient(server.URL(), t)

	// kill a container
	fakeID := "wrong123"
	if e := FnKillContainer(client, fakeID); e == nil {
		t.Errorf("expecting errors, but nothing found")
	}
}

func TestFnConfigVolumeAllEmpty(t *testing.T) {
	volume := FnConfigVolume(&VolumeOptions{})
	if volume != "" {
		t.Errorf("Expected \"\" but found %q", volume)
	}
}

func TestFnConfigVolumeDestinationOmitted(t *testing.T) {
	volume := FnConfigVolume(&VolumeOptions{Source: "/tmp"})
	if volume != "/tmp:/tmp" {
		t.Errorf("Expected \"/tmp:/tmp\" but found %q", volume)
	}
}

func TestFnConfigVolumeOnlyDestination(t *testing.T) {
	volume := FnConfigVolume(&VolumeOptions{Destination: "/tmp"})
	if volume != ":/tmp" {
		t.Errorf("Expected \":/tmp\" but found %q", volume)
	}
}

func TestFnConfigVolumeAllFields(t *testing.T) {
	volume := FnConfigVolume(&VolumeOptions{
		Source:      "/tmp",
		Destination: "/tmp",
	})
	if volume != "/tmp:/tmp" {
		t.Errorf("Expected \"/tmp:/tmp\" but found %q", volume)
	}
}
<|endoftext|>


<commit_before>// Copyright 2013 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package juju

import (
	"github.com/globocom/tsuru/heal"
	"os/exec"
)

func init() {
	heal.Register("bootstrap", &BootstrapHealer{})
}

// BootstrapHealer is an implementation for the Healer interface. For more
// details on how a healer work, check the documentation of the heal package.
type BootstrapHealer struct{}

// getBootstrapMachine returns the bootstrap machine.
func getBootstrapMachine() machine {
	p := JujuProvisioner{}
	output, _ := p.getOutput()
	// for juju bootstrap machine always is the machine 0.
	return output.Machines[0]
}

// NeedsHeal returns true if the AgentState of bootstrap machine is "not-started".
func (h *BootstrapHealer) NeedsHeal() bool {
	bootstrapMachine := getBootstrapMachine()
	return bootstrapMachine.AgentState == "not-started"
}

// Heal executes the action for heal the bootstrap agent.
func (h *BootstrapHealer) Heal() error {
	if h.NeedsHeal() {
		bootstrapMachine := getBootstrapMachine()
		args := []string{
			"-o",
			"StrictHostKeyChecking no",
			"-q",
			"-l",
			"ubuntu",
			bootstrapMachine.IpAddress,
			"sudo",
			"restart",
			"juju-machine-agent",
		}
		cmd := exec.Command("ssh", args...)
		return cmd.Run()
	}
	return nil
}
<commit_msg>added logs on bootstraphealer.<commit_after>// Copyright 2013 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package juju

import (
	"github.com/globocom/tsuru/heal"
	"github.com/globocom/tsuru/log"
	"os/exec"
	"strings"
)

func init() {
	heal.Register("bootstrap", &BootstrapHealer{})
}

// BootstrapHealer is an implementation for the Healer interface. For more
// details on how a healer work, check the documentation of the heal package.
type BootstrapHealer struct{}

// getBootstrapMachine returns the bootstrap machine.
func getBootstrapMachine() machine {
	p := JujuProvisioner{}
	output, _ := p.getOutput()
	// for juju bootstrap machine always is the machine 0.
	return output.Machines[0]
}

// NeedsHeal returns true if the AgentState of bootstrap machine is "not-started".
func (h *BootstrapHealer) NeedsHeal() bool {
	bootstrapMachine := getBootstrapMachine()
	return bootstrapMachine.AgentState == "not-started"
}

// Heal executes the action for heal the bootstrap agent.
func (h *BootstrapHealer) Heal() error {
	if h.NeedsHeal() {
		bootstrapMachine := getBootstrapMachine()
		args := []string{
			"-o",
			"StrictHostKeyChecking no",
			"-q",
			"-l",
			"ubuntu",
			bootstrapMachine.IpAddress,
			"sudo",
			"restart",
			"juju-machine-agent",
		}
		cmd := exec.Command("ssh", args...)
		log.Printf("Healing bootstrap juju-machine-agent")
		log.Printf(strings.Join(args, " "))
		return cmd.Run()
	}
	log.Printf("Bootstrap juju-machine-agent needs no cure, skipping...")
	return nil
}
<|endoftext|>


<commit_before>// This is the main package for the `tapasd` application.
package main

import (
	"encoding/xml"
	"flag"
	"io"
	"log"
	"net/http"
	"net/url"
	"os"
	"path"
	"regexp"
	"strings"
	"sync"
	"time"
)

const feedUrl = "https://rubytapas.dpdcart.com/feed"

type Enclosure struct {
	Url    string `xml:"url,attr"`
	Length int64  `xml:"length,attr"`
}

type Item struct {
	Title     string    `xml:"title"`
	Enclosure Enclosure `xml:"enclosure"`
}

func main() {
	defDataDir, _ := os.Getwd()
	user := flag.String("user", "[required]", "user for RubyTapas account (required)")
	pass := flag.String("pass", "[required]", "pass for RubyTapas account (required)")
	dataDir := flag.String("data", defDataDir, "data directory for downloads")
	concurrency := flag.Int("concurrency", 4, "data directory for downloads")
	daemon := flag.Bool("daemon", false, "daemon mode which checks feed periodically")
	interval := flag.Int("interval", 60*60*6, "number of seconds to sleep between reprocessing")
	flag.Parse()
	if *user == "[required]" || *pass == "[required]" {
		log.Fatal("-user and -pass flags are required")
	}

	for {
		items := make(chan Item)
		go generate(items, *user, *pass)
		process(items, *concurrency, *user, *pass, *dataDir)
		log.Println("Processing and downloading complete")
		if !*daemon {
			break
		}
		log.Printf("Sleeping for %d seconds\n", *interval)
		timer := time.NewTimer(time.Duration(*interval) * time.Second)
		<-timer.C
		log.Println("Waking to process and download")
	}
}

// generate creates the collection of episodes to be downloaded.
func generate(urls chan Item, user string, pass string) {
	defer close(urls)
	request, err := http.NewRequest("GET", feedUrl, nil)
	request.SetBasicAuth(user, pass)
	client := &http.Client{}
	response, err := client.Do(request)
	if err != nil {
		log.Fatal(err)
	}
	defer response.Body.Close()
	if response.StatusCode != 200 {
		log.Fatalf("URL %s returned status: %s\n", feedUrl, response.Status)
	}

	decoder := xml.NewDecoder(response.Body)
	for {
		token, _ := decoder.Token()
		if token == nil {
			break
		}

		switch startElement := token.(type) {
		case xml.StartElement:
			if startElement.Name.Local == "item" {
				var item Item
				decoder.DecodeElement(&item, &startElement)
				urls <- item
			}
		}
	}
}

// process works through the episode collection with a worker pool.
func process(items chan Item, concurrency int, user string, pass string, dataDir string) {
	var wg sync.WaitGroup
	for i := 1; i <= concurrency; i++ {
		wg.Add(1)
		worker := i
		go func() {
			defer wg.Done()
			for item := range items {
				download(worker, item, user, pass, dataDir)
			}
		}()
	}
	wg.Wait()
}

// download will download an episode movie file and verify its size.
func download(worker int, item Item, user string, pass string, dataDir string) {
	url, err := url.Parse(item.Enclosure.Url)
	if err != nil {
		log.Fatal(err)
	}
	fname := path.Join(dataDir, "rubytapas-"+slugify(item.Title)+path.Ext(url.Path))

	existing, err := os.Stat(fname)
	if !os.IsNotExist(err) {
		if existing.Size() != item.Enclosure.Length {
			log.Printf(
				"[%02d] Deleting and retrying %s, incorrect file size (expected: %d, actual: %d)",
				worker,
				fname,
				item.Enclosure.Length,
				existing.Size(),
			)
			os.Remove(fname)
		} else {
			log.Printf("[%02d] Skipping %s", worker, path.Base(fname))
			return
		}
	}

	log.Printf("[%02d] Downloading: %s to %s\n", worker, url.String(), fname)
	request, err := http.NewRequest("GET", url.String(), nil)
	request.SetBasicAuth(user, pass)
	client := &http.Client{}
	response, err := client.Do(request)
	if err != nil {
		log.Fatal(err)
	}
	defer response.Body.Close()
	if response.StatusCode != 200 {
		log.Printf("[%02d] URL %s returned status: %s\n", worker, url, response.Status)
		return
	}

	tempfile := path.Join(path.Dir(fname), "."+path.Base(fname))
	if _, err := os.Stat(tempfile); !os.IsNotExist(err) {
		os.Remove(tempfile)
	}
	temp, err := os.Create(tempfile)
	if err != nil {
		log.Fatal(err)
	}
	defer temp.Close()
	defer os.Remove(tempfile)

	written, err := io.Copy(temp, response.Body)
	if err != nil {
		log.Fatal(err)
	}
	if written != item.Enclosure.Length {
		log.Printf(
			"[%02d] Deleting %s, incorrect file size (expected: %d, actual: %d)",
			worker,
			fname,
			item.Enclosure.Length,
			written,
		)
		os.Remove(fname)
		return
	}
	err = os.Rename(tempfile, fname)
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("[%02d] Download complete: %s\n", worker, path.Base(fname))
}

// slugify takes a string and returns a sanitized string suitable for creating
// filenames and web site URL slugs.
func slugify(title string) string {
	invalidSlugPatterns := regexp.MustCompile(`[^a-z0-9 _-]`)
	whitespacePatterns := regexp.MustCompile(`\s+`)

	result := strings.ToLower(title)
	result = invalidSlugPatterns.ReplaceAllString(result, "")
	result = whitespacePatterns.ReplaceAllString(result, "-")
	return result
}
<commit_msg>Use *ln format of log calls.<commit_after>// This is the main package for the `tapasd` application.
package main

import (
	"encoding/xml"
	"flag"
	"io"
	"log"
	"net/http"
	"net/url"
	"os"
	"path"
	"regexp"
	"strings"
	"sync"
	"time"
)

const feedUrl = "https://rubytapas.dpdcart.com/feed"

type Enclosure struct {
	Url    string `xml:"url,attr"`
	Length int64  `xml:"length,attr"`
}

type Item struct {
	Title     string    `xml:"title"`
	Enclosure Enclosure `xml:"enclosure"`
}

func main() {
	defDataDir, _ := os.Getwd()
	user := flag.String("user", "[required]", "user for RubyTapas account (required)")
	pass := flag.String("pass", "[required]", "pass for RubyTapas account (required)")
	dataDir := flag.String("data", defDataDir, "data directory for downloads")
	concurrency := flag.Int("concurrency", 4, "data directory for downloads")
	daemon := flag.Bool("daemon", false, "daemon mode which checks feed periodically")
	interval := flag.Int("interval", 60*60*6, "number of seconds to sleep between reprocessing")
	flag.Parse()
	if *user == "[required]" || *pass == "[required]" {
		log.Fatalln("-user and -pass flags are required")
	}

	for {
		items := make(chan Item)
		go generate(items, *user, *pass)
		process(items, *concurrency, *user, *pass, *dataDir)
		log.Println("Processing and downloading complete")
		if !*daemon {
			break
		}
		log.Printf("Sleeping for %d seconds\n", *interval)
		timer := time.NewTimer(time.Duration(*interval) * time.Second)
		<-timer.C
		log.Println("Waking to process and download")
	}
}

// generate creates the collection of episodes to be downloaded.
func generate(urls chan Item, user string, pass string) {
	defer close(urls)
	request, err := http.NewRequest("GET", feedUrl, nil)
	request.SetBasicAuth(user, pass)
	client := &http.Client{}
	response, err := client.Do(request)
	if err != nil {
		log.Fatalln(err)
	}
	defer response.Body.Close()
	if response.StatusCode != 200 {
		log.Fatalln("URL", feedUrl, "returned status:", response.Status)
	}

	decoder := xml.NewDecoder(response.Body)
	for {
		token, _ := decoder.Token()
		if token == nil {
			break
		}

		switch startElement := token.(type) {
		case xml.StartElement:
			if startElement.Name.Local == "item" {
				var item Item
				decoder.DecodeElement(&item, &startElement)
				urls <- item
			}
		}
	}
}

// process works through the episode collection with a worker pool.
func process(items chan Item, concurrency int, user string, pass string, dataDir string) {
	var wg sync.WaitGroup
	for i := 1; i <= concurrency; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			for item := range items {
				download(item, user, pass, dataDir)
			}
		}()
	}
	wg.Wait()
}

// download will download an episode movie file and verify its size.
func download(item Item, user string, pass string, dataDir string) {
	url, err := url.Parse(item.Enclosure.Url)
	if err != nil {
		log.Fatalln(err)
	}
	fname := path.Join(
		dataDir,
		"rubytapas-"+slugify(item.Title)+path.Ext(url.Path),
	)

	existing, err := os.Stat(fname)
	if !os.IsNotExist(err) {
		if existing.Size() != item.Enclosure.Length {
			log.Println(
				"Deleting and retrying",
				fname,
				"(incorrect file size, expected:",
				item.Enclosure.Length,
				", actual:",
				existing.Size(),
				")",
			)
			os.Remove(fname)
		} else {
			log.Println("Skipping", path.Base(fname))
			return
		}
	}

	log.Println("Downloading", url.String(), "to", fname)
	request, err := http.NewRequest("GET", url.String(), nil)
	request.SetBasicAuth(user, pass)
	client := &http.Client{}
	response, err := client.Do(request)
	if err != nil {
		log.Fatalln(err)
	}
	defer response.Body.Close()
	if response.StatusCode != 200 {
		log.Println("URL", url, "returned status:", response.Status)
		return
	}

	tempfile := path.Join(path.Dir(fname), "."+path.Base(fname))
	if _, err := os.Stat(tempfile); !os.IsNotExist(err) {
		os.Remove(tempfile)
	}
	temp, err := os.Create(tempfile)
	if err != nil {
		log.Fatalln(err)
	}
	defer temp.Close()
	defer os.Remove(tempfile)

	written, err := io.Copy(temp, response.Body)
	if err != nil {
		log.Fatalln(err)
	}
	if written != item.Enclosure.Length {
		log.Println(
			"Deleting",
			fname,
			"(incorrect file size, expected:",
			item.Enclosure.Length,
			", actual:",
			written,
			")",
		)
		os.Remove(fname)
		return
	}
	err = os.Rename(tempfile, fname)
	if err != nil {
		log.Fatalln(err)
	}

	log.Printf("Download complete: %s\n", path.Base(fname))
}

// slugify takes a string and returns a sanitized string suitable for creating
// filenames and web site URL slugs.
func slugify(title string) string {
	invalidSlugPatterns := regexp.MustCompile(`[^a-z0-9 _-]`)
	whitespacePatterns := regexp.MustCompile(`\s+`)

	result := strings.ToLower(title)
	result = invalidSlugPatterns.ReplaceAllString(result, "")
	result = whitespacePatterns.ReplaceAllString(result, "-")
	return result
}
<|endoftext|>


<commit_before>// Copyright 2017 Jeff Foley. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package services

import (
	"strings"
	"sync"
	"time"

	"github.com/OWASP/Amass/config"
	eb "github.com/OWASP/Amass/eventbus"
	"github.com/OWASP/Amass/requests"
	"github.com/OWASP/Amass/resolvers"
	"github.com/OWASP/Amass/utils"
	"github.com/miekg/dns"
)

// BruteForceQueryTypes contains the DNS record types that service queries for.
var BruteForceQueryTypes = []string{
	"CNAME",
	"A",
	"AAAA",
}

// BruteForceService is the Service that handles all brute force name generation
// within the architecture.
type BruteForceService struct {
	BaseService

	metrics    *MetricsCollector
	totalLock  sync.RWMutex
	totalNames int
	curIdx     int

	filter *utils.StringFilter
}

// NewBruteForceService returns he object initialized, but not yet started.
func NewBruteForceService(c *config.Config, bus *eb.EventBus, pool *resolvers.ResolverPool) *BruteForceService {
	bfs := &BruteForceService{filter: utils.NewStringFilter()}

	bfs.BaseService = *NewBaseService(bfs, "Brute Forcing", c, bus, pool)
	return bfs
}

// OnStart implements the Service interface.
func (bfs *BruteForceService) OnStart() error {
	bfs.BaseService.OnStart()

	bfs.metrics = NewMetricsCollector(bfs)
	bfs.metrics.NamesRemainingCallback(bfs.namesRemaining)

	if bfs.Config().BruteForcing {
		if bfs.Config().Recursive {
			if bfs.Config().MinForRecursive == 0 {
				bfs.Bus().Subscribe(requests.NameResolvedTopic, bfs.SendDNSRequest)
			} else {
				bfs.Bus().Subscribe(requests.NewSubdomainTopic, bfs.NewSubdomain)
			}
		}
	}
	go bfs.processRequests()
	return nil
}

// OnLowNumberOfNames implements the Service interface.
func (bfs *BruteForceService) OnLowNumberOfNames() error {
	if !bfs.Config().BruteForcing {
		return nil
	}

	domains := bfs.Config().Domains()
	if len(domains) <= bfs.curIdx {
		return nil
	}

	domain := domains[bfs.curIdx]
	go bfs.performBruteForcing(domain, domain)
	bfs.curIdx++
	return nil
}

// OnStop implements the Service interface.
func (bfs *BruteForceService) OnStop() error {
	bfs.metrics.Stop()
	return nil
}

func (bfs *BruteForceService) processRequests() {
	for {
		select {
		case <-bfs.PauseChan():
			<-bfs.ResumeChan()
		case <-bfs.Quit():
			return
		case req := <-bfs.DNSRequestChan():
			if bfs.Config().Recursive && bfs.Config().MinForRecursive == 0 && bfs.goodRequest(req) {
				go bfs.performBruteForcing(req.Name, req.Domain)
			}
		case <-bfs.AddrRequestChan():
		case <-bfs.ASNRequestChan():
		case <-bfs.WhoisRequestChan():
		}
	}
}

func (bfs *BruteForceService) goodRequest(req *requests.DNSRequest) bool {
	if !bfs.Config().IsDomainInScope(req.Name) {
		return false
	}

	if len(req.Records) == 0 {
		return true
	}

	var ok bool
	for _, r := range req.Records {
		t := uint16(r.Type)

		if t == dns.TypeA || t == dns.TypeAAAA {
			ok = true
			break
		}
	}
	return ok
}

// NewSubdomain is called by the Name Service when proper subdomains are discovered.
func (bfs *BruteForceService) NewSubdomain(req *requests.DNSRequest, times int) {
	if times == bfs.Config().MinForRecursive {
		go bfs.performBruteForcing(req.Name, req.Domain)
	}
}

func (bfs *BruteForceService) performBruteForcing(subdomain, domain string) {
	subdomain = strings.ToLower(subdomain)
	domain = strings.ToLower(domain)
	req := &requests.DNSRequest{
		Name:   subdomain,
		Domain: domain,
	}
	if subdomain == "" || domain == "" || bfs.filter.Duplicate(subdomain) ||
		bfs.Pool().GetWildcardType(req) == resolvers.WildcardTypeDynamic {
		return
	}

	bfs.totalLock.Lock()
	bfs.totalNames += len(bfs.Config().Wordlist)
	bfs.totalLock.Unlock()

	var idx int
	t := time.NewTicker(time.Second)
	defer t.Stop()
	for {
		select {
		case <-bfs.Quit():
			return
		case <-t.C:
			bfs.SetActive()
		default:
			if idx >= len(bfs.Config().Wordlist) {
				return
			}
			bfs.Config().SemMaxDNSQueries.Acquire(1)
			word := strings.ToLower(bfs.Config().Wordlist[idx])
			go bfs.bruteForceResolution(word, subdomain, domain)
			idx++
		}
	}
}

func (bfs *BruteForceService) bruteForceResolution(word, sub, domain string) {
	defer bfs.SetActive()
	defer bfs.decTotalNames()
	defer bfs.Config().SemMaxDNSQueries.Release(1)

	if word == "" || sub == "" || domain == "" {
		return
	}

	name := word + "." + sub
	var answers []requests.DNSAnswer
	for _, t := range BruteForceQueryTypes {
		if a, err := bfs.Pool().Resolve(name, t, resolvers.PriorityLow); err == nil {
			answers = append(answers, a...)
			// Do not continue if a CNAME was discovered
			if t == "CNAME" {
				bfs.metrics.QueryTime(time.Now())
				break
			}
		}
		bfs.metrics.QueryTime(time.Now())
		bfs.SetActive()
	}
	if len(answers) == 0 {
		return
	}

	req := &requests.DNSRequest{
		Name:    name,
		Domain:  domain,
		Records: answers,
		Tag:     requests.BRUTE,
		Source:  bfs.String(),
	}

	if bfs.Pool().MatchesWildcard(req) {
		return
	}

	// Check if this passes the enumeration network contraints
	var records []requests.DNSAnswer
	for _, ans := range req.Records {
		if ans.Type == 1 || ans.Type == 28 {
			if !bfs.Config().IsAddressInScope(ans.Data) {
				continue
			}
		}
		records = append(records, ans)
	}
	if len(records) == 0 {
		return
	}
	req.Records = records

	bfs.Bus().Publish(requests.NameResolvedTopic, req)
}

// Stats implements the Service interface.
func (bfs *BruteForceService) Stats() *ServiceStats {
	return bfs.metrics.Stats()
}

func (bfs *BruteForceService) namesRemaining() int {
	bfs.totalLock.RLock()
	defer bfs.totalLock.RUnlock()

	return bfs.totalNames
}

func (bfs *BruteForceService) decTotalNames() {
	bfs.totalLock.Lock()
	defer bfs.totalLock.Unlock()

	bfs.totalNames--
}
<commit_msg>added logging for failed DNS queries<commit_after>// Copyright 2017 Jeff Foley. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package services

import (
	"strings"
	"sync"
	"time"

	"github.com/OWASP/Amass/config"
	eb "github.com/OWASP/Amass/eventbus"
	"github.com/OWASP/Amass/requests"
	"github.com/OWASP/Amass/resolvers"
	"github.com/OWASP/Amass/utils"
	"github.com/miekg/dns"
)

// BruteForceQueryTypes contains the DNS record types that service queries for.
var BruteForceQueryTypes = []string{
	"CNAME",
	"A",
	"AAAA",
}

// BruteForceService is the Service that handles all brute force name generation
// within the architecture.
type BruteForceService struct {
	BaseService

	metrics    *MetricsCollector
	totalLock  sync.RWMutex
	totalNames int
	curIdx     int

	filter *utils.StringFilter
}

// NewBruteForceService returns he object initialized, but not yet started.
func NewBruteForceService(c *config.Config, bus *eb.EventBus, pool *resolvers.ResolverPool) *BruteForceService {
	bfs := &BruteForceService{filter: utils.NewStringFilter()}

	bfs.BaseService = *NewBaseService(bfs, "Brute Forcing", c, bus, pool)
	return bfs
}

// OnStart implements the Service interface.
func (bfs *BruteForceService) OnStart() error {
	bfs.BaseService.OnStart()

	bfs.metrics = NewMetricsCollector(bfs)
	bfs.metrics.NamesRemainingCallback(bfs.namesRemaining)

	if bfs.Config().BruteForcing {
		if bfs.Config().Recursive {
			if bfs.Config().MinForRecursive == 0 {
				bfs.Bus().Subscribe(requests.NameResolvedTopic, bfs.SendDNSRequest)
			} else {
				bfs.Bus().Subscribe(requests.NewSubdomainTopic, bfs.NewSubdomain)
			}
		}
	}
	go bfs.processRequests()
	return nil
}

// OnLowNumberOfNames implements the Service interface.
func (bfs *BruteForceService) OnLowNumberOfNames() error {
	if !bfs.Config().BruteForcing {
		return nil
	}

	domains := bfs.Config().Domains()
	if len(domains) <= bfs.curIdx {
		return nil
	}

	domain := domains[bfs.curIdx]
	go bfs.performBruteForcing(domain, domain)
	bfs.curIdx++
	return nil
}

// OnStop implements the Service interface.
func (bfs *BruteForceService) OnStop() error {
	bfs.metrics.Stop()
	return nil
}

func (bfs *BruteForceService) processRequests() {
	for {
		select {
		case <-bfs.PauseChan():
			<-bfs.ResumeChan()
		case <-bfs.Quit():
			return
		case req := <-bfs.DNSRequestChan():
			if bfs.Config().Recursive && bfs.Config().MinForRecursive == 0 && bfs.goodRequest(req) {
				go bfs.performBruteForcing(req.Name, req.Domain)
			}
		case <-bfs.AddrRequestChan():
		case <-bfs.ASNRequestChan():
		case <-bfs.WhoisRequestChan():
		}
	}
}

func (bfs *BruteForceService) goodRequest(req *requests.DNSRequest) bool {
	if !bfs.Config().IsDomainInScope(req.Name) {
		return false
	}

	if len(req.Records) == 0 {
		return true
	}

	var ok bool
	for _, r := range req.Records {
		t := uint16(r.Type)

		if t == dns.TypeA || t == dns.TypeAAAA {
			ok = true
			break
		}
	}
	return ok
}

// NewSubdomain is called by the Name Service when proper subdomains are discovered.
func (bfs *BruteForceService) NewSubdomain(req *requests.DNSRequest, times int) {
	if times == bfs.Config().MinForRecursive {
		go bfs.performBruteForcing(req.Name, req.Domain)
	}
}

func (bfs *BruteForceService) performBruteForcing(subdomain, domain string) {
	subdomain = strings.ToLower(subdomain)
	domain = strings.ToLower(domain)
	req := &requests.DNSRequest{
		Name:   subdomain,
		Domain: domain,
	}
	if subdomain == "" || domain == "" || bfs.filter.Duplicate(subdomain) ||
		bfs.Pool().GetWildcardType(req) == resolvers.WildcardTypeDynamic {
		return
	}

	bfs.totalLock.Lock()
	bfs.totalNames += len(bfs.Config().Wordlist)
	bfs.totalLock.Unlock()

	var idx int
	t := time.NewTicker(time.Second)
	defer t.Stop()
	for {
		select {
		case <-bfs.Quit():
			return
		case <-t.C:
			bfs.SetActive()
		default:
			if idx >= len(bfs.Config().Wordlist) {
				return
			}
			bfs.Config().SemMaxDNSQueries.Acquire(1)
			word := strings.ToLower(bfs.Config().Wordlist[idx])
			go bfs.bruteForceResolution(word, subdomain, domain)
			idx++
		}
	}
}

func (bfs *BruteForceService) bruteForceResolution(word, sub, domain string) {
	defer bfs.SetActive()
	defer bfs.decTotalNames()
	defer bfs.Config().SemMaxDNSQueries.Release(1)

	if word == "" || sub == "" || domain == "" {
		return
	}

	name := word + "." + sub
	var answers []requests.DNSAnswer
	for _, t := range BruteForceQueryTypes {
		if a, err := bfs.Pool().Resolve(name, t, resolvers.PriorityLow); err == nil {
			answers = append(answers, a...)
			// Do not continue if a CNAME was discovered
			if t == "CNAME" {
				bfs.metrics.QueryTime(time.Now())
				break
			}
		} else {
			bfs.Config().Log.Printf("%s: %v", bfs.String(), err)
		}
		bfs.metrics.QueryTime(time.Now())
		bfs.SetActive()
	}
	if len(answers) == 0 {
		return
	}

	req := &requests.DNSRequest{
		Name:    name,
		Domain:  domain,
		Records: answers,
		Tag:     requests.BRUTE,
		Source:  bfs.String(),
	}

	if bfs.Pool().MatchesWildcard(req) {
		return
	}

	// Check if this passes the enumeration network contraints
	var records []requests.DNSAnswer
	for _, ans := range req.Records {
		if ans.Type == 1 || ans.Type == 28 {
			if !bfs.Config().IsAddressInScope(ans.Data) {
				continue
			}
		}
		records = append(records, ans)
	}
	if len(records) == 0 {
		return
	}
	req.Records = records

	bfs.Bus().Publish(requests.NameResolvedTopic, req)
}

// Stats implements the Service interface.
func (bfs *BruteForceService) Stats() *ServiceStats {
	return bfs.metrics.Stats()
}

func (bfs *BruteForceService) namesRemaining() int {
	bfs.totalLock.RLock()
	defer bfs.totalLock.RUnlock()

	return bfs.totalNames
}

func (bfs *BruteForceService) decTotalNames() {
	bfs.totalLock.Lock()
	defer bfs.totalLock.Unlock()

	bfs.totalNames--
}
<|endoftext|>


<commit_before>package glutton

import (
	"bufio"
	"crypto/sha256"
	"encoding/hex"
	"io"
	"math/rand"
	"net"
	"net/http"
	"os"
	"path/filepath"
	"regexp"
	"strings"
	"time"

	"github.com/kung-foo/freki"
)

// Mirai botnet  - https://github.com/CymmetriaResearch/MTPot/blob/master/mirai_conf.json
// Hajime botnet - https://security.rapiditynetworks.com/publications/2016-10-16/hajime.pdf
var miraiCom = map[string][]string{
	"ps":                          []string{"1 pts/21   00:00:00 init"},
	"cat /proc/mounts":            []string{"rootfs / rootfs rw 0 0\r\n/dev/root / ext2 rw,relatime,errors=continue 0 0\r\nproc /proc proc rw,relatime 0 0\r\nsysfs /sys sysfs rw,relatime 0 0\r\nudev /dev tmpfs rw,relatime 0 0\r\ndevpts /dev/pts devpts rw,relatime,mode=600,ptmxmode=000 0 0\r\n/dev/mtdblock1 /home/hik jffs2 rw,relatime 0 0\r\ntmpfs /run tmpfs rw,nosuid,noexec,relatime,size=3231524k,mode=755 0 0\r\n"},
	"(cat .s || cp /bin/echo .s)": []string{"cat: .s: No such file or directory"},
	"nc":   []string{"nc: command not found"},
	"wget": []string{"wget: missing URL"},
	"(dd bs=52 count=1 if=.s || cat .s)": []string{"\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00\x01\x00\x00\x00\xbc\x14\x01\x00\x34\x00\x00\x00"},
	"sh": []string{"$"},
	"echo -e \\x6b\\x61\\x6d\\x69/dev > /dev/.nippon":              []string{""},
	"cat /dev/.nippon":                                             []string{"kami/dev"},
	"rm /dev/.nippon":                                              []string{""},
	"echo -e \\x6b\\x61\\x6d\\x69/run > /run/.nippon":              []string{""},
	"cat /run/.nippon":                                             []string{"kami/run"},
	"rm /run/.nippon":                                              []string{""},
	"cat /bin/sh":                                                  []string{""},
	"/bin/busybox ps":                                              []string{"1 pts/21   00:00:00 init"},
	"/bin/busybox cat /proc/mounts":                                []string{"tmpfs /run tmpfs rw,nosuid,noexec,relatime,size=3231524k,mode=755 0 0"},
	"/bin/busybox echo -e \\x6b\\x61\\x6d\\x69/dev > /dev/.nippon": []string{""},
	"/bin/busybox cat /dev/.nippon":                                []string{"kami/dev"},
	"/bin/busybox rm /dev/.nippon":                                 []string{""},
	"/bin/busybox echo -e \\x6b\\x61\\x6d\\x69/run > /run/.nippon": []string{""},
	"/bin/busybox cat /run/.nippon":                                []string{"kami/run"},
	"/bin/busybox rm /run/.nippon":                                 []string{""},
	"/bin/busybox cat /bin/sh":                                     []string{""},
	"/bin/busybox cat /bin/echo":                                   []string{"/bin/busybox cat /bin/echo\r\n\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00\x01\x00\x00\x00\x6c\xb9\x00\x00\x34\x00\x00\x00"},
	"rm /dev/.human":                                               []string{"rm: can't remove '/.t': No such file or directory\r\nrm: can't remove '/.sh': No such file or directory\r\nrm: can't remove '/.human': No such file or directory\r\ncd /dev"},
}

func writeMsg(conn net.Conn, msg string, g *Glutton) error {
	_, err := conn.Write([]byte(msg))
	g.logger.Infof("[telnet  ] send: %q", msg)
	md := g.processor.Connections.GetByFlow(freki.NewConnKeyFromNetConn(conn))
	g.producer.LogHTTP(conn, md, msg, "write")
	return err
}

func readMsg(conn net.Conn, g *Glutton) (msg string, err error) {
	msg, err = bufio.NewReader(conn).ReadString('\n')
	if err != nil {
		return "", err
	}
	g.logger.Infof("[telnet  ] recv: %q", msg)
	md := g.processor.Connections.GetByFlow(freki.NewConnKeyFromNetConn(conn))
	g.producer.LogHTTP(conn, md, msg, "read")
	return msg, err
}

func getSample(cmd string, g *Glutton) error {
	parts := strings.Split(cmd, " ")
	if len(parts) < 2 {
		return nil
	}
	url := parts[1]
	timeout := time.Duration(5 * time.Second)
	client := http.Client{
		Timeout: timeout,
	}
	resp, err := client.Get(url)
	if err != nil {
		g.logger.Errorf("[telnet  ] getSample error: %v", err)
		return err
	}
	defer resp.Body.Close()
	p := new([]byte)
	resp.Body.Read(*p)
	sum := sha256.Sum256(*p)
	// Ignoring errors for if the folder already exists
	os.MkdirAll("samples", os.ModePerm)
	sha256Hash := hex.EncodeToString(sum[:])
	path := filepath.Join("samples", sha256Hash)
	out, err := os.Create(path)
	if err != nil {
		g.logger.Errorf("[telnet  ] getSample error: %v", err)
		return err
	}
	defer out.Close()
	_, err = io.Copy(out, resp.Body)
	if err != nil {
		g.logger.Errorf("[telnet  ] getSample error: %v", err)
		return err
	}
	g.logger.Infof("[telnet  ] getSample succcess: %s", path)
	return nil
}

// HandleTelnet handles telnet communication on a connection
func (g *Glutton) HandleTelnet(conn net.Conn) {
	defer conn.Close()

	// TODO (glaslos): Add device banner

	// telnet window size negotiation response
	writeMsg(conn, "\xff\xfd\x18\xff\xfd\x20\xff\xfd\x23\xff\xfd\x27", g)

	// User name prompt
	writeMsg(conn, "Username: ", g)
	_, err := readMsg(conn, g)
	if err != nil {
		g.logger.Errorf("[telnet  ] %v", err)
		return
	}
	writeMsg(conn, "Password: ", g)
	_, err = readMsg(conn, g)
	if err != nil {
		g.logger.Errorf("[telnet  ] %v", err)
		return
	}

	writeMsg(conn, "welcome\r\n> ", g)
	for {
		msg, err := readMsg(conn, g)
		if err != nil {
			g.logger.Errorf("[telnet  ] %v", err)
			return
		}
		for _, cmd := range strings.Split(msg, ";") {
			if strings.HasPrefix(strings.Trim(cmd, " "), "wget http") {
				go getSample(strings.Trim(cmd, " "), g)
			}
			if strings.TrimRight(cmd, "") == " rm /dev/.t" {
				continue
			}
			if strings.TrimRight(cmd, "\r\n") == " rm /dev/.sh" {
				continue
			}
			if strings.TrimRight(cmd, "\r\n") == "cd /dev/" {
				writeMsg(conn, "ECCHI: applet not found\r\n", g)
				writeMsg(conn, "\r\nBusyBox v1.16.1 (2014-03-04 16:00:18 CST) built-it shell (ash)\r\nEnter 'help' for a list of built-in commands.\r\n", g)
				continue
			}

			if resp := miraiCom[strings.TrimSpace(cmd)]; len(resp) > 0 {
				writeMsg(conn, resp[rand.Intn(len(resp))]+"\r\n", g)
			} else {
				// /bin/busybox YDKBI
				re := regexp.MustCompile(`\/bin\/busybox (?P<applet>[A-Z]+)`)
				match := re.FindStringSubmatch(cmd)
				if len(match) > 1 {
					writeMsg(conn, match[1]+": applet not found\r\n", g)
					writeMsg(conn, "BusyBox v1.16.1 (2014-03-04 16:00:18 CST) built-in shell (ash)\r\nEnter 'help' for a list of built-in commands.\r\n", g)
				}
			}
		}
		writeMsg(conn, "> ", g)
	}
}
<commit_msg>better error reporting and file handling in telnet<commit_after>package glutton

import (
	"bufio"
	"crypto/sha256"
	"encoding/hex"
	"math/rand"
	"net"
	"net/http"
	"os"
	"path/filepath"
	"regexp"
	"strings"
	"time"

	"github.com/kung-foo/freki"
)

// Mirai botnet  - https://github.com/CymmetriaResearch/MTPot/blob/master/mirai_conf.json
// Hajime botnet - https://security.rapiditynetworks.com/publications/2016-10-16/hajime.pdf
var miraiCom = map[string][]string{
	"ps":                          []string{"1 pts/21   00:00:00 init"},
	"cat /proc/mounts":            []string{"rootfs / rootfs rw 0 0\r\n/dev/root / ext2 rw,relatime,errors=continue 0 0\r\nproc /proc proc rw,relatime 0 0\r\nsysfs /sys sysfs rw,relatime 0 0\r\nudev /dev tmpfs rw,relatime 0 0\r\ndevpts /dev/pts devpts rw,relatime,mode=600,ptmxmode=000 0 0\r\n/dev/mtdblock1 /home/hik jffs2 rw,relatime 0 0\r\ntmpfs /run tmpfs rw,nosuid,noexec,relatime,size=3231524k,mode=755 0 0\r\n"},
	"(cat .s || cp /bin/echo .s)": []string{"cat: .s: No such file or directory"},
	"nc":   []string{"nc: command not found"},
	"wget": []string{"wget: missing URL"},
	"(dd bs=52 count=1 if=.s || cat .s)": []string{"\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00\x01\x00\x00\x00\xbc\x14\x01\x00\x34\x00\x00\x00"},
	"sh": []string{"$"},
	"echo -e \\x6b\\x61\\x6d\\x69/dev > /dev/.nippon":              []string{""},
	"cat /dev/.nippon":                                             []string{"kami/dev"},
	"rm /dev/.nippon":                                              []string{""},
	"echo -e \\x6b\\x61\\x6d\\x69/run > /run/.nippon":              []string{""},
	"cat /run/.nippon":                                             []string{"kami/run"},
	"rm /run/.nippon":                                              []string{""},
	"cat /bin/sh":                                                  []string{""},
	"/bin/busybox ps":                                              []string{"1 pts/21   00:00:00 init"},
	"/bin/busybox cat /proc/mounts":                                []string{"tmpfs /run tmpfs rw,nosuid,noexec,relatime,size=3231524k,mode=755 0 0"},
	"/bin/busybox echo -e \\x6b\\x61\\x6d\\x69/dev > /dev/.nippon": []string{""},
	"/bin/busybox cat /dev/.nippon":                                []string{"kami/dev"},
	"/bin/busybox rm /dev/.nippon":                                 []string{""},
	"/bin/busybox echo -e \\x6b\\x61\\x6d\\x69/run > /run/.nippon": []string{""},
	"/bin/busybox cat /run/.nippon":                                []string{"kami/run"},
	"/bin/busybox rm /run/.nippon":                                 []string{""},
	"/bin/busybox cat /bin/sh":                                     []string{""},
	"/bin/busybox cat /bin/echo":                                   []string{"/bin/busybox cat /bin/echo\r\n\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00\x01\x00\x00\x00\x6c\xb9\x00\x00\x34\x00\x00\x00"},
	"rm /dev/.human":                                               []string{"rm: can't remove '/.t': No such file or directory\r\nrm: can't remove '/.sh': No such file or directory\r\nrm: can't remove '/.human': No such file or directory\r\ncd /dev"},
}

func writeMsg(conn net.Conn, msg string, g *Glutton) error {
	_, err := conn.Write([]byte(msg))
	g.logger.Infof("[telnet  ] send: %q", msg)
	md := g.processor.Connections.GetByFlow(freki.NewConnKeyFromNetConn(conn))
	g.producer.LogHTTP(conn, md, msg, "write")
	return err
}

func readMsg(conn net.Conn, g *Glutton) (msg string, err error) {
	msg, err = bufio.NewReader(conn).ReadString('\n')
	if err != nil {
		return "", err
	}
	g.logger.Infof("[telnet  ] recv: %q", msg)
	md := g.processor.Connections.GetByFlow(freki.NewConnKeyFromNetConn(conn))
	g.producer.LogHTTP(conn, md, msg, "read")
	return msg, err
}

func getSample(cmd string, g *Glutton) error {
	parts := strings.Split(cmd, " ")
	if len(parts) < 2 {
		return nil
	}
	url := parts[1]
	timeout := time.Duration(5 * time.Second)
	client := http.Client{
		Timeout: timeout,
	}
	resp, err := client.Get(url)
	if err != nil {
		g.logger.Errorf("[telnet  ] getSample http error: %v", err)
		return err
	}
	defer resp.Body.Close()
	g.logger.Infof("[telnet  ] getSample body length: %s", resp.Header.Get("ContentLength"))
	p := new([]byte)
	resp.Body.Read(*p)
	sum := sha256.Sum256(*p)
	// Ignoring errors for if the folder already exists
	os.MkdirAll("samples", os.ModePerm)
	sha256Hash := hex.EncodeToString(sum[:])
	path := filepath.Join("samples", sha256Hash)
	out, err := os.Create(path)
	if err != nil {
		g.logger.Errorf("[telnet  ] getSample create error: %v", err)
		return err
	}
	defer out.Close()
	_, err = out.Write(*p)
	if err != nil {
		g.logger.Errorf("[telnet  ] getSample write error: %v", err)
		return err
	}
	g.logger.Infof("[telnet  ] getSample succcess: %s", path)
	return nil
}

// HandleTelnet handles telnet communication on a connection
func (g *Glutton) HandleTelnet(conn net.Conn) {
	defer conn.Close()

	// TODO (glaslos): Add device banner

	// telnet window size negotiation response
	writeMsg(conn, "\xff\xfd\x18\xff\xfd\x20\xff\xfd\x23\xff\xfd\x27", g)

	// User name prompt
	writeMsg(conn, "Username: ", g)
	_, err := readMsg(conn, g)
	if err != nil {
		g.logger.Errorf("[telnet  ] %v", err)
		return
	}
	writeMsg(conn, "Password: ", g)
	_, err = readMsg(conn, g)
	if err != nil {
		g.logger.Errorf("[telnet  ] %v", err)
		return
	}

	writeMsg(conn, "welcome\r\n> ", g)
	for {
		msg, err := readMsg(conn, g)
		if err != nil {
			g.logger.Errorf("[telnet  ] %v", err)
			return
		}
		for _, cmd := range strings.Split(msg, ";") {
			if strings.HasPrefix(strings.Trim(cmd, " "), "wget http") {
				go getSample(strings.Trim(cmd, " "), g)
			}
			if strings.TrimRight(cmd, "") == " rm /dev/.t" {
				continue
			}
			if strings.TrimRight(cmd, "\r\n") == " rm /dev/.sh" {
				continue
			}
			if strings.TrimRight(cmd, "\r\n") == "cd /dev/" {
				writeMsg(conn, "ECCHI: applet not found\r\n", g)
				writeMsg(conn, "\r\nBusyBox v1.16.1 (2014-03-04 16:00:18 CST) built-it shell (ash)\r\nEnter 'help' for a list of built-in commands.\r\n", g)
				continue
			}

			if resp := miraiCom[strings.TrimSpace(cmd)]; len(resp) > 0 {
				writeMsg(conn, resp[rand.Intn(len(resp))]+"\r\n", g)
			} else {
				// /bin/busybox YDKBI
				re := regexp.MustCompile(`\/bin\/busybox (?P<applet>[A-Z]+)`)
				match := re.FindStringSubmatch(cmd)
				if len(match) > 1 {
					writeMsg(conn, match[1]+": applet not found\r\n", g)
					writeMsg(conn, "BusyBox v1.16.1 (2014-03-04 16:00:18 CST) built-in shell (ash)\r\nEnter 'help' for a list of built-in commands.\r\n", g)
				}
			}
		}
		writeMsg(conn, "> ", g)
	}
}
<|endoftext|>


<commit_before>package httptoo

import (
	"compress/gzip"
	"io"
	"net/http"
	"strings"
)

type gzipResponseWriter struct {
	io.Writer
	http.ResponseWriter
	haveWritten bool
}

func (w *gzipResponseWriter) Write(b []byte) (int, error) {
	if w.haveWritten {
		goto write
	}
	w.haveWritten = true
	if w.Header().Get("Content-Type") != "" {
		goto write
	}
	if type_ := http.DetectContentType(b); type_ != "application/octet-stream" {
		w.Header().Set("Content-Type", type_)
	}
write:
	return w.Writer.Write(b)
}

// Gzips response body if the request says it'll allow it.
func GzipHandler(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") || w.Header().Get("Content-Encoding") != "" || w.Header().Get("Vary") != "" {
			h.ServeHTTP(w, r)
			return
		}
		w.Header().Set("Content-Encoding", "gzip")
		w.Header().Set("Vary", "Accept-Encoding")
		gz := gzip.NewWriter(w)
		defer gz.Close()
		h.ServeHTTP(&gzipResponseWriter{
			Writer:         gz,
			ResponseWriter: w,
		}, r)
	})
}
<commit_msg>httptoo: Ensure gzipResponseWriter implements http.ResponseWriter<commit_after>package httptoo

import (
	"compress/gzip"
	"io"
	"net/http"
	"strings"
)

type gzipResponseWriter struct {
	io.Writer
	http.ResponseWriter
	haveWritten bool
}

var _ http.ResponseWriter = &gzipResponseWriter{}

func (w *gzipResponseWriter) Write(b []byte) (int, error) {
	if w.haveWritten {
		goto write
	}
	w.haveWritten = true
	if w.Header().Get("Content-Type") != "" {
		goto write
	}
	if type_ := http.DetectContentType(b); type_ != "application/octet-stream" {
		w.Header().Set("Content-Type", type_)
	}
write:
	return w.Writer.Write(b)
}

// Gzips response body if the request says it'll allow it.
func GzipHandler(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") || w.Header().Get("Content-Encoding") != "" || w.Header().Get("Vary") != "" {
			h.ServeHTTP(w, r)
			return
		}
		w.Header().Set("Content-Encoding", "gzip")
		w.Header().Set("Vary", "Accept-Encoding")
		gz := gzip.NewWriter(w)
		defer gz.Close()
		h.ServeHTTP(&gzipResponseWriter{
			Writer:         gz,
			ResponseWriter: w,
		}, r)
	})
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"os"

	"github.com/webvariants/susi-dev/components"
	"github.com/webvariants/susi-dev/container"
	"github.com/webvariants/susi-dev/deploy"
	"github.com/webvariants/susi-dev/pki"
	"github.com/webvariants/susi-dev/setup"
	"github.com/webvariants/susi-dev/source"
)

var (
	addFlags         = flag.NewFlagSet("add", flag.ContinueOnError)
	connectTo        *string
	connectToAddress *string
	buildFlags       = flag.NewFlagSet("build", flag.ContinueOnError)
	targetOS         *string
	gpgPass          *string
)

func init() {
	connectTo = addFlags.String("connect-to", "", "connect to this instance")
	connectToAddress = addFlags.String("addr", "", "address of the instance to connect to")
	targetOS = buildFlags.String("os", "alpine", "for which OS")
	gpgPass = buildFlags.String("gpgpass", "", "password for signing key")
}

func create(name string) {
	pki.Init(name + "/pki")
	os.Mkdir(name+"/configs", 0755)
	os.Mkdir(name+"/assets", 0755)
	os.Mkdir(name+"/foreignKeys", 0755)
	os.Mkdir(name+"/containers", 0755)
}

func main() {
	if len(os.Args) == 1 {
		fmt.Printf("usage: %v <create|add|deploy|pki|container>\n", os.Args[0])
		os.Exit(1)
	}
	switch os.Args[1] {
	case "setup":
		{
			setup.InstallDependencies()
		}
	case "create":
		{
			nodeID := os.Args[2]
			create(nodeID)
		}
	case "add":
		{
			nodeID := os.Args[2]
			component := os.Args[3]
			addFlags.Parse(os.Args[4:])
			components.Add(nodeID, component, connectTo, connectToAddress)
		}
	case "deploy":
		{
			nodeID := os.Args[2]
			target := os.Args[3]
			deploy.Raw(nodeID, target)
		}
	case "pki":
		{
			subcommand := os.Args[2]
			switch subcommand {
			case "create":
				{
					pkiID := os.Args[3]
					pki.Init(pkiID)
				}
			case "add":
				{
					pkiID := os.Args[3]
					name := os.Args[4]
					pki.CreateCertificate(pkiID, name)
				}
			}
		}
	case "source":
		{
			subcommand := os.Args[2]
			switch subcommand {
			case "build":
				{
					buildFlags.Parse(os.Args[3:])
					source.Clone()
					switch *targetOS {
					case "alpine":
						{
							container.BuildAlpineBuilder(*gpgPass)
							container.RunAlpineBuilder()
						}
					case "debian-stable":
						{
							container.BuildDebianBuilder("stable", *gpgPass)
							container.RunDebianBuilder("stable")
						}
					case "debian-testing":
						{
							container.BuildDebianBuilder("testing", *gpgPass)
							container.RunDebianBuilder("testing")
						}
					default:
						{
							log.Fatal("no such target os")
						}
					}

				}
			case "checkout":
				{
					source.Checkout(os.Args[3])
				}
			case "clone":
				{
					source.Clone()
				}
			}
		}
	case "container":
		{
			subcommand := os.Args[2]
			switch subcommand {
			case "build":
				{
					nodeID := os.Args[3]
					buildFlags.Parse(os.Args[4:])
					source.Clone()
					switch *targetOS {
					case "alpine":
						{
							container.BuildAlpineBaseContainer()
							for _, component := range components.List(nodeID) {
								container.BuildAlpineContainer(nodeID, component, *gpgPass)
							}
						}
					default:
						{
							log.Fatal("no such target os")
						}
					}
				}
			case "run":
				{
					container.Run(os.Args[3])
				}
			}
		}
	case "list":
		{
			fmt.Println(components.List(os.Args[2]))
		}
	}
}
<commit_msg>added help text for command line tool;<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"os"

	"github.com/webvariants/susi-dev/components"
	"github.com/webvariants/susi-dev/container"
	"github.com/webvariants/susi-dev/deploy"
	"github.com/webvariants/susi-dev/pki"
	"github.com/webvariants/susi-dev/setup"
	"github.com/webvariants/susi-dev/source"
)

var (
	addFlags         = flag.NewFlagSet("add", flag.ContinueOnError)
	connectTo        *string
	connectToAddress *string
	buildFlags       = flag.NewFlagSet("build", flag.ContinueOnError)
	targetOS         *string
	gpgPass          *string
)

func help() {
	helpText := `usage: susi-dev
  setup -> install container tools
  create $node -> bootstrap a new node
    add $node $component -> setup a component on the given node
    deploy $node $target -> deploy a node to a target
  source
    clone -> clone the source of susi
    checkout $branch -> checkout a specific branch
    build --os $OS --gpgpass $pass -> build it for one of alpine, debian-stable or debian-testing
  container
    build $node --gpgpass $pass -> build containers for a node
    run $node -> runs the containers for a node
  pki
    create $folder -> create a new public key infrastructure
    add $folder $client -> create and sign a new client certificate
`
	fmt.Print(helpText)
}

func init() {
	connectTo = addFlags.String("connect-to", "", "connect to this instance")
	connectToAddress = addFlags.String("addr", "", "address of the instance to connect to")
	targetOS = buildFlags.String("os", "alpine", "for which OS")
	gpgPass = buildFlags.String("gpgpass", "", "password for signing key")
}

func create(name string) {
	pki.Init(name + "/pki")
	os.Mkdir(name+"/configs", 0755)
	os.Mkdir(name+"/assets", 0755)
	os.Mkdir(name+"/foreignKeys", 0755)
	os.Mkdir(name+"/containers", 0755)
}

func main() {
	if len(os.Args) == 1 {
		help()
		os.Exit(1)
	}
	switch os.Args[1] {
	case "setup":
		{
			setup.InstallDependencies()
		}
	case "create":
		{
			nodeID := os.Args[2]
			create(nodeID)
		}
	case "add":
		{
			nodeID := os.Args[2]
			component := os.Args[3]
			addFlags.Parse(os.Args[4:])
			components.Add(nodeID, component, connectTo, connectToAddress)
		}
	case "deploy":
		{
			nodeID := os.Args[2]
			target := os.Args[3]
			deploy.Raw(nodeID, target)
		}
	case "pki":
		{
			subcommand := os.Args[2]
			switch subcommand {
			case "create":
				{
					pkiID := os.Args[3]
					pki.Init(pkiID)
				}
			case "add":
				{
					pkiID := os.Args[3]
					name := os.Args[4]
					pki.CreateCertificate(pkiID, name)
				}
			}
		}
	case "source":
		{
			subcommand := os.Args[2]
			switch subcommand {
			case "build":
				{
					buildFlags.Parse(os.Args[3:])
					source.Clone()
					switch *targetOS {
					case "alpine":
						{
							container.BuildAlpineBuilder(*gpgPass)
							container.RunAlpineBuilder()
						}
					case "debian-stable":
						{
							container.BuildDebianBuilder("stable", *gpgPass)
							container.RunDebianBuilder("stable")
						}
					case "debian-testing":
						{
							container.BuildDebianBuilder("testing", *gpgPass)
							container.RunDebianBuilder("testing")
						}
					default:
						{
							log.Fatal("no such target os")
						}
					}

				}
			case "checkout":
				{
					source.Checkout(os.Args[3])
				}
			case "clone":
				{
					source.Clone()
				}
			}
		}
	case "container":
		{
			subcommand := os.Args[2]
			switch subcommand {
			case "build":
				{
					nodeID := os.Args[3]
					buildFlags.Parse(os.Args[4:])
					source.Clone()
					switch *targetOS {
					case "alpine":
						{
							container.BuildAlpineBaseContainer()
							for _, component := range components.List(nodeID) {
								container.BuildAlpineContainer(nodeID, component, *gpgPass)
							}
						}
					default:
						{
							log.Fatal("no such target os")
						}
					}
				}
			case "run":
				{
					container.Run(os.Args[3])
				}
			}
		}
	case "list":
		{
			fmt.Println(components.List(os.Args[2]))
		}
	case "--help":
		{
			help()
			os.Exit(0)
		}
	default:
		{
			help()
			os.Exit(1)
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 CNI authors
//
// 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.

package skel

import (
	"bytes"
	"errors"
	"strings"

	"github.com/containernetworking/cni/pkg/types"
	"github.com/containernetworking/cni/pkg/version"

	"github.com/containernetworking/cni/pkg/testutils"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/ginkgo/extensions/table"
	. "github.com/onsi/gomega"
)

type fakeCmd struct {
	CallCount int
	Returns   struct {
		Error error
	}
	Received struct {
		CmdArgs *CmdArgs
	}
}

func (c *fakeCmd) Func(args *CmdArgs) error {
	c.CallCount++
	c.Received.CmdArgs = args
	return c.Returns.Error
}

var _ = Describe("dispatching to the correct callback", func() {
	var (
		environment     map[string]string
		stdinData       string
		stdout, stderr  *bytes.Buffer
		cmdAdd, cmdDel  *fakeCmd
		dispatch        *dispatcher
		expectedCmdArgs *CmdArgs
		versionInfo     version.PluginInfo
	)

	BeforeEach(func() {
		environment = map[string]string{
			"CNI_COMMAND":     "ADD",
			"CNI_CONTAINERID": "some-container-id",
			"CNI_NETNS":       "/some/netns/path",
			"CNI_IFNAME":      "eth0",
			"CNI_ARGS":        "some;extra;args",
			"CNI_PATH":        "/some/cni/path",
		}

		stdinData = `{ "some": "config", "cniVersion": "9.8.7" }`
		stdout = &bytes.Buffer{}
		stderr = &bytes.Buffer{}
		versionInfo = version.PluginSupports("9.8.7")
		dispatch = &dispatcher{
			Getenv: func(key string) string { return environment[key] },
			Stdin:  strings.NewReader(stdinData),
			Stdout: stdout,
			Stderr: stderr,
		}
		cmdAdd = &fakeCmd{}
		cmdDel = &fakeCmd{}
		expectedCmdArgs = &CmdArgs{
			ContainerID: "some-container-id",
			Netns:       "/some/netns/path",
			IfName:      "eth0",
			Args:        "some;extra;args",
			Path:        "/some/cni/path",
			StdinData:   []byte(stdinData),
		}
	})

	var envVarChecker = func(envVar string, isRequired bool) {
		delete(environment, envVar)

		err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)
		if isRequired {
			Expect(err).To(Equal(&types.Error{
				Code: 100,
				Msg:  "required env variables missing",
			}))
			Expect(stderr.String()).To(ContainSubstring(envVar + " env variable missing\n"))
		} else {
			Expect(err).NotTo(HaveOccurred())
		}
	}

	Context("when the CNI_COMMAND is ADD", func() {
		It("extracts env vars and stdin data and calls cmdAdd", func() {
			err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)

			Expect(err).NotTo(HaveOccurred())
			Expect(cmdAdd.CallCount).To(Equal(1))
			Expect(cmdDel.CallCount).To(Equal(0))
			Expect(cmdAdd.Received.CmdArgs).To(Equal(expectedCmdArgs))
		})

		It("does not call cmdDel", func() {
			err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)

			Expect(err).NotTo(HaveOccurred())
			Expect(cmdDel.CallCount).To(Equal(0))
		})

		DescribeTable("required / optional env vars", envVarChecker,
			Entry("command", "CNI_COMMAND", true),
			Entry("container id", "CNI_CONTAINER_ID", false),
			Entry("net ns", "CNI_NETNS", true),
			Entry("if name", "CNI_IFNAME", true),
			Entry("args", "CNI_ARGS", false),
			Entry("path", "CNI_PATH", true),
		)

		Context("when multiple required env vars are missing", func() {
			BeforeEach(func() {
				delete(environment, "CNI_NETNS")
				delete(environment, "CNI_IFNAME")
				delete(environment, "CNI_PATH")
			})

			It("reports that all of them are missing, not just the first", func() {
				Expect(dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)).NotTo(Succeed())
				log := stderr.String()
				Expect(log).To(ContainSubstring("CNI_NETNS env variable missing\n"))
				Expect(log).To(ContainSubstring("CNI_IFNAME env variable missing\n"))
				Expect(log).To(ContainSubstring("CNI_PATH env variable missing\n"))

			})
		})

		Context("when the stdin data is missing the required cniVersion config", func() {
			BeforeEach(func() {
				dispatch.Stdin = strings.NewReader(`{ "some": "config" }`)
			})

			Context("when the plugin supports version 0.1.0", func() {
				BeforeEach(func() {
					versionInfo = version.PluginSupports("0.1.0")
					expectedCmdArgs.StdinData = []byte(`{ "some": "config" }`)
				})

				It("infers the config is 0.1.0 and calls the cmdAdd callback", func() {
					err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)
					Expect(err).NotTo(HaveOccurred())

					Expect(cmdAdd.CallCount).To(Equal(1))
					Expect(cmdAdd.Received.CmdArgs).To(Equal(expectedCmdArgs))
				})
			})

			Context("when the plugin does not support 0.1.0", func() {
				BeforeEach(func() {
					versionInfo = version.PluginSupports("4.3.2")
				})

				It("immediately returns a useful error", func() {
					err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)
					Expect(err.Code).To(Equal(types.ErrIncompatibleCNIVersion)) // see https://github.com/containernetworking/cni/blob/master/SPEC.md#well-known-error-codes
					Expect(err.Msg).To(Equal("incompatible CNI versions"))
					Expect(err.Details).To(Equal(`config is "0.1.0", plugin supports ["4.3.2"]`))
				})

				It("does not call either callback", func() {
					dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)
					Expect(cmdAdd.CallCount).To(Equal(0))
					Expect(cmdDel.CallCount).To(Equal(0))
				})
			})
		})
	})

	Context("when the CNI_COMMAND is DEL", func() {
		BeforeEach(func() {
			environment["CNI_COMMAND"] = "DEL"
		})

		It("calls cmdDel with the env vars and stdin data", func() {
			err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)

			Expect(err).NotTo(HaveOccurred())
			Expect(cmdDel.CallCount).To(Equal(1))
			Expect(cmdDel.Received.CmdArgs).To(Equal(expectedCmdArgs))
		})

		It("does not call cmdAdd", func() {
			err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)

			Expect(err).NotTo(HaveOccurred())
			Expect(cmdAdd.CallCount).To(Equal(0))
		})

		DescribeTable("required / optional env vars", envVarChecker,
			Entry("command", "CNI_COMMAND", true),
			Entry("container id", "CNI_CONTAINER_ID", false),
			Entry("net ns", "CNI_NETNS", false),
			Entry("if name", "CNI_IFNAME", true),
			Entry("args", "CNI_ARGS", false),
			Entry("path", "CNI_PATH", true),
		)
	})

	Context("when the CNI_COMMAND is VERSION", func() {
		BeforeEach(func() {
			environment["CNI_COMMAND"] = "VERSION"
		})

		It("prints the version to stdout", func() {
			err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)

			Expect(err).NotTo(HaveOccurred())
			Expect(stdout).To(MatchJSON(`{
				"cniVersion": "0.2.0",
				"supportedVersions": ["9.8.7"]
			}`))
		})

		It("does not call cmdAdd or cmdDel", func() {
			err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)

			Expect(err).NotTo(HaveOccurred())
			Expect(cmdAdd.CallCount).To(Equal(0))
			Expect(cmdDel.CallCount).To(Equal(0))
		})

		DescribeTable("VERSION does not need the usual env vars", envVarChecker,
			Entry("command", "CNI_COMMAND", true),
			Entry("container id", "CNI_CONTAINER_ID", false),
			Entry("net ns", "CNI_NETNS", false),
			Entry("if name", "CNI_IFNAME", false),
			Entry("args", "CNI_ARGS", false),
			Entry("path", "CNI_PATH", false),
		)

		Context("when the stdin is empty", func() {
			BeforeEach(func() {
				dispatch.Stdin = strings.NewReader("")
			})

			It("succeeds without error", func() {
				err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)

				Expect(err).NotTo(HaveOccurred())
				Expect(stdout).To(MatchJSON(`{
					"cniVersion": "0.2.0",
					"supportedVersions": ["9.8.7"]
			}`))
			})
		})
	})

	Context("when the CNI_COMMAND is unrecognized", func() {
		BeforeEach(func() {
			environment["CNI_COMMAND"] = "NOPE"
		})

		It("does not call any cmd callback", func() {
			dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)

			Expect(cmdAdd.CallCount).To(Equal(0))
			Expect(cmdDel.CallCount).To(Equal(0))
		})

		It("returns an error", func() {
			err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)

			Expect(err).To(Equal(&types.Error{
				Code: 100,
				Msg:  "unknown CNI_COMMAND: NOPE",
			}))
		})
	})

	Context("when stdin cannot be read", func() {
		BeforeEach(func() {
			dispatch.Stdin = &testutils.BadReader{}
		})

		It("does not call any cmd callback", func() {
			dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)

			Expect(cmdAdd.CallCount).To(Equal(0))
			Expect(cmdDel.CallCount).To(Equal(0))
		})

		It("wraps and returns the error", func() {
			err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)

			Expect(err).To(Equal(&types.Error{
				Code: 100,
				Msg:  "error reading from stdin: banana",
			}))
		})
	})

	Context("when the callback returns an error", func() {
		Context("when it is a typed Error", func() {
			BeforeEach(func() {
				cmdAdd.Returns.Error = &types.Error{
					Code: 1234,
					Msg:  "insufficient something",
				}
			})

			It("returns the error as-is", func() {
				err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)

				Expect(err).To(Equal(&types.Error{
					Code: 1234,
					Msg:  "insufficient something",
				}))
			})
		})

		Context("when it is an unknown error", func() {
			BeforeEach(func() {
				cmdAdd.Returns.Error = errors.New("potato")
			})

			It("wraps and returns the error", func() {
				err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)

				Expect(err).To(Equal(&types.Error{
					Code: 100,
					Msg:  "potato",
				}))
			})
		})
	})
})
<commit_msg>skel tests: correct name of CNI_CONTAINERID in tests of env vars<commit_after>// Copyright 2016 CNI authors
//
// 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.

package skel

import (
	"bytes"
	"errors"
	"strings"

	"github.com/containernetworking/cni/pkg/types"
	"github.com/containernetworking/cni/pkg/version"

	"github.com/containernetworking/cni/pkg/testutils"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/ginkgo/extensions/table"
	. "github.com/onsi/gomega"
)

type fakeCmd struct {
	CallCount int
	Returns   struct {
		Error error
	}
	Received struct {
		CmdArgs *CmdArgs
	}
}

func (c *fakeCmd) Func(args *CmdArgs) error {
	c.CallCount++
	c.Received.CmdArgs = args
	return c.Returns.Error
}

var _ = Describe("dispatching to the correct callback", func() {
	var (
		environment     map[string]string
		stdinData       string
		stdout, stderr  *bytes.Buffer
		cmdAdd, cmdDel  *fakeCmd
		dispatch        *dispatcher
		expectedCmdArgs *CmdArgs
		versionInfo     version.PluginInfo
	)

	BeforeEach(func() {
		environment = map[string]string{
			"CNI_COMMAND":     "ADD",
			"CNI_CONTAINERID": "some-container-id",
			"CNI_NETNS":       "/some/netns/path",
			"CNI_IFNAME":      "eth0",
			"CNI_ARGS":        "some;extra;args",
			"CNI_PATH":        "/some/cni/path",
		}

		stdinData = `{ "some": "config", "cniVersion": "9.8.7" }`
		stdout = &bytes.Buffer{}
		stderr = &bytes.Buffer{}
		versionInfo = version.PluginSupports("9.8.7")
		dispatch = &dispatcher{
			Getenv: func(key string) string { return environment[key] },
			Stdin:  strings.NewReader(stdinData),
			Stdout: stdout,
			Stderr: stderr,
		}
		cmdAdd = &fakeCmd{}
		cmdDel = &fakeCmd{}
		expectedCmdArgs = &CmdArgs{
			ContainerID: "some-container-id",
			Netns:       "/some/netns/path",
			IfName:      "eth0",
			Args:        "some;extra;args",
			Path:        "/some/cni/path",
			StdinData:   []byte(stdinData),
		}
	})

	var envVarChecker = func(envVar string, isRequired bool) {
		delete(environment, envVar)

		err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)
		if isRequired {
			Expect(err).To(Equal(&types.Error{
				Code: 100,
				Msg:  "required env variables missing",
			}))
			Expect(stderr.String()).To(ContainSubstring(envVar + " env variable missing\n"))
		} else {
			Expect(err).NotTo(HaveOccurred())
		}
	}

	Context("when the CNI_COMMAND is ADD", func() {
		It("extracts env vars and stdin data and calls cmdAdd", func() {
			err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)

			Expect(err).NotTo(HaveOccurred())
			Expect(cmdAdd.CallCount).To(Equal(1))
			Expect(cmdDel.CallCount).To(Equal(0))
			Expect(cmdAdd.Received.CmdArgs).To(Equal(expectedCmdArgs))
		})

		It("does not call cmdDel", func() {
			err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)

			Expect(err).NotTo(HaveOccurred())
			Expect(cmdDel.CallCount).To(Equal(0))
		})

		DescribeTable("required / optional env vars", envVarChecker,
			Entry("command", "CNI_COMMAND", true),
			Entry("container id", "CNI_CONTAINERID", false),
			Entry("net ns", "CNI_NETNS", true),
			Entry("if name", "CNI_IFNAME", true),
			Entry("args", "CNI_ARGS", false),
			Entry("path", "CNI_PATH", true),
		)

		Context("when multiple required env vars are missing", func() {
			BeforeEach(func() {
				delete(environment, "CNI_NETNS")
				delete(environment, "CNI_IFNAME")
				delete(environment, "CNI_PATH")
			})

			It("reports that all of them are missing, not just the first", func() {
				Expect(dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)).NotTo(Succeed())
				log := stderr.String()
				Expect(log).To(ContainSubstring("CNI_NETNS env variable missing\n"))
				Expect(log).To(ContainSubstring("CNI_IFNAME env variable missing\n"))
				Expect(log).To(ContainSubstring("CNI_PATH env variable missing\n"))

			})
		})

		Context("when the stdin data is missing the required cniVersion config", func() {
			BeforeEach(func() {
				dispatch.Stdin = strings.NewReader(`{ "some": "config" }`)
			})

			Context("when the plugin supports version 0.1.0", func() {
				BeforeEach(func() {
					versionInfo = version.PluginSupports("0.1.0")
					expectedCmdArgs.StdinData = []byte(`{ "some": "config" }`)
				})

				It("infers the config is 0.1.0 and calls the cmdAdd callback", func() {
					err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)
					Expect(err).NotTo(HaveOccurred())

					Expect(cmdAdd.CallCount).To(Equal(1))
					Expect(cmdAdd.Received.CmdArgs).To(Equal(expectedCmdArgs))
				})
			})

			Context("when the plugin does not support 0.1.0", func() {
				BeforeEach(func() {
					versionInfo = version.PluginSupports("4.3.2")
				})

				It("immediately returns a useful error", func() {
					err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)
					Expect(err.Code).To(Equal(types.ErrIncompatibleCNIVersion)) // see https://github.com/containernetworking/cni/blob/master/SPEC.md#well-known-error-codes
					Expect(err.Msg).To(Equal("incompatible CNI versions"))
					Expect(err.Details).To(Equal(`config is "0.1.0", plugin supports ["4.3.2"]`))
				})

				It("does not call either callback", func() {
					dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)
					Expect(cmdAdd.CallCount).To(Equal(0))
					Expect(cmdDel.CallCount).To(Equal(0))
				})
			})
		})
	})

	Context("when the CNI_COMMAND is DEL", func() {
		BeforeEach(func() {
			environment["CNI_COMMAND"] = "DEL"
		})

		It("calls cmdDel with the env vars and stdin data", func() {
			err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)

			Expect(err).NotTo(HaveOccurred())
			Expect(cmdDel.CallCount).To(Equal(1))
			Expect(cmdDel.Received.CmdArgs).To(Equal(expectedCmdArgs))
		})

		It("does not call cmdAdd", func() {
			err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)

			Expect(err).NotTo(HaveOccurred())
			Expect(cmdAdd.CallCount).To(Equal(0))
		})

		DescribeTable("required / optional env vars", envVarChecker,
			Entry("command", "CNI_COMMAND", true),
			Entry("container id", "CNI_CONTAINERID", false),
			Entry("net ns", "CNI_NETNS", false),
			Entry("if name", "CNI_IFNAME", true),
			Entry("args", "CNI_ARGS", false),
			Entry("path", "CNI_PATH", true),
		)
	})

	Context("when the CNI_COMMAND is VERSION", func() {
		BeforeEach(func() {
			environment["CNI_COMMAND"] = "VERSION"
		})

		It("prints the version to stdout", func() {
			err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)

			Expect(err).NotTo(HaveOccurred())
			Expect(stdout).To(MatchJSON(`{
				"cniVersion": "0.2.0",
				"supportedVersions": ["9.8.7"]
			}`))
		})

		It("does not call cmdAdd or cmdDel", func() {
			err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)

			Expect(err).NotTo(HaveOccurred())
			Expect(cmdAdd.CallCount).To(Equal(0))
			Expect(cmdDel.CallCount).To(Equal(0))
		})

		DescribeTable("VERSION does not need the usual env vars", envVarChecker,
			Entry("command", "CNI_COMMAND", true),
			Entry("container id", "CNI_CONTAINERID", false),
			Entry("net ns", "CNI_NETNS", false),
			Entry("if name", "CNI_IFNAME", false),
			Entry("args", "CNI_ARGS", false),
			Entry("path", "CNI_PATH", false),
		)

		Context("when the stdin is empty", func() {
			BeforeEach(func() {
				dispatch.Stdin = strings.NewReader("")
			})

			It("succeeds without error", func() {
				err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)

				Expect(err).NotTo(HaveOccurred())
				Expect(stdout).To(MatchJSON(`{
					"cniVersion": "0.2.0",
					"supportedVersions": ["9.8.7"]
			}`))
			})
		})
	})

	Context("when the CNI_COMMAND is unrecognized", func() {
		BeforeEach(func() {
			environment["CNI_COMMAND"] = "NOPE"
		})

		It("does not call any cmd callback", func() {
			dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)

			Expect(cmdAdd.CallCount).To(Equal(0))
			Expect(cmdDel.CallCount).To(Equal(0))
		})

		It("returns an error", func() {
			err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)

			Expect(err).To(Equal(&types.Error{
				Code: 100,
				Msg:  "unknown CNI_COMMAND: NOPE",
			}))
		})
	})

	Context("when stdin cannot be read", func() {
		BeforeEach(func() {
			dispatch.Stdin = &testutils.BadReader{}
		})

		It("does not call any cmd callback", func() {
			dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)

			Expect(cmdAdd.CallCount).To(Equal(0))
			Expect(cmdDel.CallCount).To(Equal(0))
		})

		It("wraps and returns the error", func() {
			err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)

			Expect(err).To(Equal(&types.Error{
				Code: 100,
				Msg:  "error reading from stdin: banana",
			}))
		})
	})

	Context("when the callback returns an error", func() {
		Context("when it is a typed Error", func() {
			BeforeEach(func() {
				cmdAdd.Returns.Error = &types.Error{
					Code: 1234,
					Msg:  "insufficient something",
				}
			})

			It("returns the error as-is", func() {
				err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)

				Expect(err).To(Equal(&types.Error{
					Code: 1234,
					Msg:  "insufficient something",
				}))
			})
		})

		Context("when it is an unknown error", func() {
			BeforeEach(func() {
				cmdAdd.Returns.Error = errors.New("potato")
			})

			It("wraps and returns the error", func() {
				err := dispatch.pluginMain(cmdAdd.Func, cmdDel.Func, versionInfo)

				Expect(err).To(Equal(&types.Error{
					Code: 100,
					Msg:  "potato",
				}))
			})
		})
	})
})
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	_ "github.com/go-sql-driver/mysql"
  "fmt"
  "log"
	"encoding/json"
	"os"
	"strconv"
)

type conditions struct {
  id int "json:id"
	cityname string "json:cityname"
	zipcode string "json:zipcode"
	tempk sql.NullFloat64
	descript string
	humidity sql.NullFloat64
	windspd sql.NullFloat64
	sunrise sql.NullFloat64
	sunset sql.NullFloat64
	ptime sql.NullFloat64
}

func main() {
  db, err := sql.Open("mysql", "root:byteme@tcp(127.0.0.1:3306)/weather")
  if err != nil {
    log.Fatal(err)
  }

  rows, err := db.Query("SELECT * FROM conditions")
  if err != nil {
    log.Fatal(err)
  }
  defer rows.Close()

  bks := make([]*conditions, 0)
  for rows.Next() {
    bk := new(conditions)
    err := rows.Scan(&bk.id, &bk.cityname, &bk.zipcode, &bk.tempk, &bk.descript, &bk.humidity, &bk.windspd, &bk.sunrise, &bk.sunset, &bk.ptime)
    if err != nil {
      log.Fatal(err)
    }
    bks = append(bks, bk)
	}
  if err = rows.Err(); err != nil {
    log.Fatal(err)
  }

  for _, bk := range bks {
		var city string = bk.cityname
		var zip string = bk.zipcode
		var temp float64
		// temp = fmt.Sprintf("%.2f", bk.tempk.Float64)
		temp = bk.tempk.Float64
		temp = temp - 273.15
		temp = temp * 1.8
		temp = temp + 32
		// fmt.Printf("%s, %s, %0.2f\n", city, zip, temp)4
		fmt.Printf("%s, %s, %0.1f \n", city, zip, temp)
		var stemp string = strconv.FormatFloat(float64(temp), 'f', 2, 32)
		enc := json.NewEncoder(os.Stdout)
    d := map[string]string{"cityname": city, "zipcode": zip, "tempature": stemp}
		// c := map[string]float64{"tempature": temp}
    enc.Encode(d)
	}
}
<commit_msg>updated json<commit_after>package main

import (
	"database/sql"
	_ "github.com/go-sql-driver/mysql"
  "log"
	"encoding/json"
	"os"
	"strconv"
)

type conditions struct {
  id int
	cityname string
	zipcode string
	tempk sql.NullFloat64
	descript string
	humidity sql.NullFloat64
	windspd sql.NullFloat64
	sunrise string
	sunset string
	ptime string
}

func main() {
	var zip string = os.Getenv("ZIP")
	var usrpwd string = os.Getenv("DB_USER_PWD")
  db, err := sql.Open("mysql", usrpwd + "@tcp(127.0.0.1:3306)/weather")
  if err != nil {
    log.Fatal(err)
  }

  rows, err := db.Query("SELECT * FROM conditions")
  if err != nil {
    log.Fatal(err)
  }
  defer rows.Close()

  bks := make([]*conditions, 0)
  for rows.Next() {
    bk := new(conditions)
    err := rows.Scan(&bk.id, &bk.cityname, &bk.zipcode, &bk.tempk, &bk.descript, &bk.humidity, &bk.windspd, &bk.sunrise, &bk.sunset, &bk.ptime)
    if err != nil {
      log.Fatal(err)
    }
    bks = append(bks, bk)
	}
  if err = rows.Err(); err != nil {
    log.Fatal(err)
  }

  for _, bk := range bks {
	  if zip == bk.zipcode {
		  var temp float64 = bk.tempk.Float64
      //convert temp from Kelvin to Fahrenheit
			// temp = ((temp - 273.15) * 1.8) + 32
	    // fmt.Printf("%s, %s, %0.1f \n", city, zip, temp)
		  var stemp string = strconv.FormatFloat(float64(temp), 'f', 2, 32)
      var hum float64 = bk.humidity.Float64
		  var shumidity string = strconv.FormatFloat(float64(hum), 'f', 1, 32)
      var ws float64 = bk.windspd.Float64
		  var swindspd string = strconv.FormatFloat(float64(ws), 'f', 1, 32)
		  enc := json.NewEncoder(os.Stdout)
      d := map[string]string{"data": "weather", "city": bk.cityname,
			                       "zipcode": bk.zipcode, "tempature": stemp,
			  										 "condition": bk.descript, "updated": bk.ptime,
			  									   "humidity": shumidity, "windspeed": swindspd,
			  									   "sunrise": bk.sunrise, "sunset": bk.sunset}
      enc.Encode(d)
		}
	}
}
<|endoftext|>


<commit_before>package cfg

// Config describes the config object..
type Config struct {
	TeamPlayerCount int      `yaml:"team_player_count"`
	TeamCount       int      `yaml:"teams"`
	Checks          []string `yaml:"checks"`
}
<commit_msg>TeamPlayerCount -> TeamSize<commit_after>package cfg

// Config describes the config object..
type Config struct {
	TeamSize  int      `yaml:"team_size"`
	TeamCount int      `yaml:"teams"`
	Checks    []string `yaml:"checks"`
}
<|endoftext|>


<commit_before>package dedup

import (
	"crypto/sha512"
	"hash"
	"io"
	"log"
	"sync"

	"github.com/amoghe/dedup/codec"
	"github.com/pkg/errors"
)

// Differ performs diff computation (and resuscitation)
type Differ struct {
	dedup     *Deduplicator
	seghasher hash.Hash
	segmenter Segmenter

	newSegmentNum uint64 // from where we can start issuing new segment IDs
}

type devnull struct{}

func (d devnull) Write(p []byte) (n int, err error) { return len(p), nil }
func (d devnull) Close() error                      { return nil }

// NewDiffer returns a Differ
func NewDiffer(winsz, mask uint64) *Differ {
	return &Differ{
		dedup:     NewDeduplicator(winsz, mask),
		segmenter: Segmenter{WindowSize: winsz, Mask: mask},
		seghasher: sha512.New(),
	}
}

// MakePatch writes a "patch" file to the specified WriteCloser
func (d *Differ) MakePatch(old, new io.ReadCloser, out io.WriteCloser) error {
	defer old.Close()
	defer new.Close()
	defer out.Close()

	// First parse old file and build up the segment state
	if err := d.dedup.Do(old, devnull{}); err != nil {
		return errors.Wrapf(err, "Failed to parse old file")
	}

	// Now parse the new file (with the state we've built)
	if err := d.dedup.Do(new, out); err != nil {
		return errors.Wrapf(err, "Failed to segment new file")
	}

	return nil
}

// ApplyPatch applies the patch file to the 'old' and writes the result to 'new'
func (d *Differ) ApplyPatch(old, patch io.ReadCloser, new io.WriteCloser) error {

	defer old.Close()
	defer patch.Close()
	defer new.Close()

	r, w := io.Pipe()
	redup := NewReduplicator()

	// First parse the 'old' file and build up segment state (in the redup)
	if err := d.dedup.Do(old, w); err != nil {
		return errors.Wrapf(err, "Failed to parse old file")
	}

	wg := sync.WaitGroup{}
	wg.Add(1)
	go func() {
		redup.Do(r, devnull{})
		wg.Done()
	}()

	wg.Wait()
	log.Println("finished parsing original file")

	// Next parse the 'patch' file and recreate 'new' using the messages
	cpatch := codec.NewGobReader(patch)

	handleDef := func(msg *codec.Message) {
		redup.tracker[msg.DefID] = msg.DefBytes
		// receipt of def is implicit ref, so output the bytes
		new.Write(msg.DefBytes)
	}
	handleRef := func(msg *codec.Message) {
		if b, ok := redup.tracker[msg.RefID]; ok {
			new.Write(b)
		} else {
			log.Panicln("Previously unseen Ref", msg.RefID)
		}
	}
	for {
		msg, err := cpatch.Read()
		if err == io.EOF {
			break
		} else if err != nil {
			return err
		}

		switch msg.Type {
		case codec.MessageDef:
			handleDef(&msg)
		case codec.MessageRef:
			handleRef(&msg)
		default:
			return errors.Errorf("Unexpected type in input stream: %d", msg.Type)
		}

	}
	return nil
}
<commit_msg>Fix ordering bug in diff.go (ApplyPatch)<commit_after>package dedup

import (
	"crypto/sha512"
	"hash"
	"io"
	"log"
	"sync"

	"github.com/amoghe/dedup/codec"
	"github.com/pkg/errors"
)

// Differ performs diff computation (and resuscitation)
type Differ struct {
	dedup     *Deduplicator
	seghasher hash.Hash
	segmenter Segmenter

	newSegmentNum uint64 // from where we can start issuing new segment IDs
}

type devnull struct{}

func (d devnull) Write(p []byte) (n int, err error) { return len(p), nil }
func (d devnull) Close() error                      { return nil }

// NewDiffer returns a Differ
func NewDiffer(winsz, mask uint64) *Differ {
	return &Differ{
		dedup:     NewDeduplicator(winsz, mask),
		segmenter: Segmenter{WindowSize: winsz, Mask: mask},
		seghasher: sha512.New(),
	}
}

// MakePatch writes a "patch" file to the specified WriteCloser
func (d *Differ) MakePatch(old, new io.ReadCloser, out io.WriteCloser) error {
	defer old.Close()
	defer new.Close()
	defer out.Close()

	// First parse old file and build up the segment state
	if err := d.dedup.Do(old, devnull{}); err != nil {
		return errors.Wrapf(err, "Failed to parse old file")
	}

	// Now parse the new file (with the state we've built)
	if err := d.dedup.Do(new, out); err != nil {
		return errors.Wrapf(err, "Failed to segment new file")
	}

	return nil
}

// ApplyPatch applies the patch file to the 'old' and writes the result to 'new'
func (d *Differ) ApplyPatch(old, patch io.Reader, new io.Writer) error {

	r, w := io.Pipe()
	redup := NewReduplicator()
	wg := sync.WaitGroup{}

	wg.Add(1)
	go func() {
		redup.Do(r, devnull{})
		wg.Done()
	}()

	// First parse the 'old' file and build up segment state (in the redup)
	if err := d.dedup.Do(old, w); err != nil {
		return errors.Wrapf(err, "Failed to parse old file")
	}
	w.Close() // close the dummy writer
	wg.Wait() // wait for dummy redup to be done

	// Next parse the 'patch' file and recreate 'new' using the messages
	cpatch := codec.NewGobReader(patch)

	handleDef := func(msg *codec.Message) {
		redup.tracker[msg.DefID] = msg.DefBytes
		// receipt of def is implicit ref, so output the bytes
		new.Write(msg.DefBytes)
	}
	handleRef := func(msg *codec.Message) {
		if b, ok := redup.tracker[msg.RefID]; ok {
			new.Write(b)
		} else {
			log.Panicln("Previously unseen Ref", msg.RefID)
		}
	}
	for {
		msg, err := cpatch.Read()
		if err == io.EOF {
			break
		} else if err != nil {
			return err
		}

		switch msg.Type {
		case codec.MessageDef:
			handleDef(&msg)
		case codec.MessageRef:
			handleRef(&msg)
		default:
			return errors.Errorf("Unexpected type in input stream: %d", msg.Type)
		}

	}
	return nil
}
<|endoftext|>