<commit_before>package docker

import (
    "fmt"
    "github.com/fsouza/go-dockerclient"
    "log"
    "net"
    "path"
)

type DockerConfig struct {
    Endpoint string
}

type Docker struct {
    config DockerConfig
    client *docker.Client

    // convenience info from docker
    Version string

    // XXX: not supported on docker 1.3.3
    Name string
}

type Container struct {
    // local unique ID for continer
    ID          string

    // optional human-readble name for container, or ID
    Name        string

    // Current running state
    Running     bool

    // internal IPv4 address assigned to container
    IPv4        net.IP

    // internal hostname for container, or short ID
    Hostname    string

    // basename of image used to run container
    Image       string

    // exposed, published ports
    Ports       []Port

    // XXX: configured image, run labels?
    Labels      map[string]string
}

type Port struct {
    Proto       string
    Port        string

    // exposed
    HostIP      string
    HostPort    string
}

type ContainerEvent struct {
    ID          string
    Status      string

    // Interpretation of running state after this event
    Running     bool

    // Current state of container; may be inconsistent or missing
    State       *Container
}

func (self DockerConfig) Open() (*Docker, error) {
    d := &Docker{config: self}

    if err := d.open(); err != nil {
        return nil, err
    } else {
        return d, err
    }
}

func (self *Docker) open() error {
    if dockerClient, err := docker.NewClient(self.config.Endpoint); err != nil {
        return err
    } else {
        self.client = dockerClient
    }

    // Version
    if env, err := self.client.Version(); err != nil {
        return err
    } else {
        self.Version = env.Get("Version")
    }

    // Info
    if env, err := self.client.Info(); err != nil {
        return err
    } else {
        self.Name = env.Get("Name")
    }

    return nil
}

func (self *Docker) String() string {
    return fmt.Sprintf("Docker<%v>", self.config)
}

/*
 * Return the state of the given container, based on the given event.
 *
 *  event       - /event status, or "" when listing
 */
func (self *Docker) inspectContainer(id string) (*Container, error) {
    dockerContainer, err := self.client.InspectContainer(id)
    if err != nil {
        log.Printf("%v.inspectContainer(%v): %v\n", self, id, err)
        return nil, err
    }

    state := Container{
        ID:         id,
        Name:       path.Base(dockerContainer.Name),
        Running:    dockerContainer.State.Running,
        IPv4:       net.ParseIP(dockerContainer.NetworkSettings.IPAddress),
        Hostname:   dockerContainer.Config.Hostname,
        Image:      path.Base(dockerContainer.Config.Image),
        Labels:     dockerContainer.Config.Labels,
    }

    for dockerPort, portBindings := range dockerContainer.NetworkSettings.Ports {
        port := Port{
            Port:   dockerPort.Port(),
            Proto:  dockerPort.Proto(),
        }

        for _, portBinding := range portBindings {
            // XXX: choose one
            port.HostIP = portBinding.HostIP
            port.HostPort = portBinding.HostPort
        }

        state.Ports = append(state.Ports, port)
    }

    return &state, nil
}

/*
 * Full list of (running) containers.
 *
 * TODO: somehow synchronize this with Subscribe() events to ensure consistency during listings?
 */
func (self *Docker) List() (out []*Container, err error) {
    containers, err := self.client.ListContainers(docker.ListContainersOptions{All: true})
    if err != nil {
        log.Printf("%v.ListContainers: %v\n", self, err)
        return nil, err
    }

    for _, listContainer := range containers {
        if containerState, err := self.inspectContainer(listContainer.ID); err != nil {
            break
        } else {
            out = append(out, containerState)
        }
    }

    return out, nil
}

// Handle a container event
func (self *Docker) containerEvent(dockerEvent *docker.APIEvents) (event ContainerEvent, err error) {
    event.ID = dockerEvent.ID
    event.Status = dockerEvent.Status

    if containerState, err := self.inspectContainer(dockerEvent.ID); err != nil {
        // skip lookup for cases where we don't have the container state anymore
        // this is normal for "destroy", but other events could also race
        event.State = nil

        // XXX: Running is indeterminite, but we can assume it is not?

    } else {
        event.Running = containerState.Running
        event.State = containerState
    }

    if dockerEvent.Status == "die" {
        // XXX: docker seems to be inconsistent about the inspected container State.Running=true/false immediately after a die?
        event.Running = false
    }

    return
}

/*
 * Subscribe to container events.
 */
func (self *Docker) Subscribe() (chan ContainerEvent, error) {
    listener := make(chan *docker.APIEvents)
    out := make(chan ContainerEvent)

    if err := self.client.AddEventListener(listener); err != nil {
        log.Printf("%v.Subscribe: AddEventListener\n", self, err)
        return nil, err
    }

    go func() {
        defer close(out)

        for dockerEvent := range listener {
            switch dockerEvent.Status {
            case "EOF":
                // XXX: how is this different to close()'ing the chan?
                log.Printf("%v.Subscribe: EOF\n", self)
                break

            // container events
            case "attach", "commit", "copy", "create", "destroy", "die", "exec_create", "exec_start", "export", "kill", "oom", "pause", "rename", "resize", "restart", "start", "stop", "top", "unpause":
                if containerEvent, err := self.containerEvent(dockerEvent); err != nil {
                    log.Printf("%v.Subscribe %v:%v: containerEvent: %v\n", self, dockerEvent.Status, dockerEvent.ID, err)

                } else {
                    // log.Printf("%v.Subscribe %v:%v: %#v\n", self, dockerEvent.Status, dockerEvent.ID, containerEvent)

                    out <- containerEvent
                }

            // image events
            case "delete", "import", "pull", "push", "tag", "untag":
                log.Printf("%v.Subscribe %v:%v: image event: ignore\n", self, dockerEvent.Status, dockerEvent.ID)

            default:
                log.Printf("%v.Subscribe %v:%v: unknown event: ignore\n", self, dockerEvent.Status, dockerEvent.ID)
            }
        }
    }()

    return out, nil
}
<commit_msg>docker: Port is uint16<commit_after>package docker

import (
    "fmt"
    "github.com/fsouza/go-dockerclient"
    "log"
    "net"
    "path"
    "strconv"
)

type DockerConfig struct {
    Endpoint string
}

type Docker struct {
    config DockerConfig
    client *docker.Client

    // convenience info from docker
    Version string

    // XXX: not supported on docker 1.3.3
    Name string
}

type Container struct {
    // local unique ID for continer
    ID          string

    // optional human-readble name for container, or ID
    Name        string

    // Current running state
    Running     bool

    // internal IPv4 address assigned to container
    IPv4        net.IP

    // internal hostname for container, or short ID
    Hostname    string

    // basename of image used to run container
    Image       string

    // exposed, published ports
    Ports       []Port

    // XXX: configured image, run labels?
    Labels      map[string]string
}

type Port struct {
    Proto       string
    Port        uint16

    // exposed
    HostIP      string
    HostPort    uint16
}

type ContainerEvent struct {
    ID          string
    Status      string

    // Interpretation of running state after this event
    Running     bool

    // Current state of container; may be inconsistent or missing
    State       *Container
}

func (self DockerConfig) Open() (*Docker, error) {
    d := &Docker{config: self}

    if err := d.open(); err != nil {
        return nil, err
    } else {
        return d, err
    }
}

func (self *Docker) open() error {
    if dockerClient, err := docker.NewClient(self.config.Endpoint); err != nil {
        return err
    } else {
        self.client = dockerClient
    }

    // Version
    if env, err := self.client.Version(); err != nil {
        return err
    } else {
        self.Version = env.Get("Version")
    }

    // Info
    if env, err := self.client.Info(); err != nil {
        return err
    } else {
        self.Name = env.Get("Name")
    }

    return nil
}

func (self *Docker) String() string {
    return fmt.Sprintf("Docker<%v>", self.config)
}

func parsePort(portString string) (uint16, error) {
    if portValue, err := strconv.Atoi(portString); err != nil {
        return 0, fmt.Errorf("port invalid: %v", portString)
    } else if portValue <= 0 || portValue >= (1 << 16) {
        return 0, fmt.Errorf("port out of range: %v", portString)
    } else {
        return uint16(portValue), nil
    }
}

/*
 * Return the state of the given container, based on the given event.
 *
 *  event       - /event status, or "" when listing
 */
func (self *Docker) inspectContainer(id string) (*Container, error) {
    dockerContainer, err := self.client.InspectContainer(id)
    if err != nil {
        log.Printf("%v.inspectContainer(%v): %v\n", self, id, err)
        return nil, err
    }

    state := Container{
        ID:         id,
        Name:       path.Base(dockerContainer.Name),
        Running:    dockerContainer.State.Running,
        IPv4:       net.ParseIP(dockerContainer.NetworkSettings.IPAddress),
        Hostname:   dockerContainer.Config.Hostname,
        Image:      path.Base(dockerContainer.Config.Image),
        Labels:     dockerContainer.Config.Labels,
    }

    for dockerPort, portBindings := range dockerContainer.NetworkSettings.Ports {
        port := Port{
            Proto:  dockerPort.Proto(),
        }

        if portValue, err := parsePort(dockerPort.Port()); err != nil {
            return nil, err
        } else {
            port.Port = portValue
        }

        for _, portBinding := range portBindings {
            // XXX: choose one
            port.HostIP = portBinding.HostIP

            if hostPort, err := parsePort(portBinding.HostPort); err != nil {
                return nil, err
            } else {
                port.HostPort = hostPort
            }
        }

        state.Ports = append(state.Ports, port)
    }

    return &state, nil
}

/*
 * Full list of (running) containers.
 *
 * TODO: somehow synchronize this with Subscribe() events to ensure consistency during listings?
 */
func (self *Docker) List() (out []*Container, err error) {
    containers, err := self.client.ListContainers(docker.ListContainersOptions{All: true})
    if err != nil {
        log.Printf("%v.ListContainers: %v\n", self, err)
        return nil, err
    }

    for _, listContainer := range containers {
        if containerState, err := self.inspectContainer(listContainer.ID); err != nil {
            break
        } else {
            out = append(out, containerState)
        }
    }

    return out, nil
}

// Handle a container event
func (self *Docker) containerEvent(dockerEvent *docker.APIEvents) (event ContainerEvent, err error) {
    event.ID = dockerEvent.ID
    event.Status = dockerEvent.Status

    if containerState, err := self.inspectContainer(dockerEvent.ID); err != nil {
        // skip lookup for cases where we don't have the container state anymore
        // this is normal for "destroy", but other events could also race
        event.State = nil

        // XXX: Running is indeterminite, but we can assume it is not?

    } else {
        event.Running = containerState.Running
        event.State = containerState
    }

    if dockerEvent.Status == "die" {
        // XXX: docker seems to be inconsistent about the inspected container State.Running=true/false immediately after a die?
        event.Running = false
    }

    return
}

/*
 * Subscribe to container events.
 */
func (self *Docker) Subscribe() (chan ContainerEvent, error) {
    listener := make(chan *docker.APIEvents)
    out := make(chan ContainerEvent)

    if err := self.client.AddEventListener(listener); err != nil {
        log.Printf("%v.Subscribe: AddEventListener\n", self, err)
        return nil, err
    }

    go func() {
        defer close(out)

        for dockerEvent := range listener {
            switch dockerEvent.Status {
            case "EOF":
                // XXX: how is this different to close()'ing the chan?
                log.Printf("%v.Subscribe: EOF\n", self)
                break

            // container events
            case "attach", "commit", "copy", "create", "destroy", "die", "exec_create", "exec_start", "export", "kill", "oom", "pause", "rename", "resize", "restart", "start", "stop", "top", "unpause":
                if containerEvent, err := self.containerEvent(dockerEvent); err != nil {
                    log.Printf("%v.Subscribe %v:%v: containerEvent: %v\n", self, dockerEvent.Status, dockerEvent.ID, err)

                } else {
                    // log.Printf("%v.Subscribe %v:%v: %#v\n", self, dockerEvent.Status, dockerEvent.ID, containerEvent)

                    out <- containerEvent
                }

            // image events
            case "delete", "import", "pull", "push", "tag", "untag":
                log.Printf("%v.Subscribe %v:%v: image event: ignore\n", self, dockerEvent.Status, dockerEvent.ID)

            default:
                log.Printf("%v.Subscribe %v:%v: unknown event: ignore\n", self, dockerEvent.Status, dockerEvent.ID)
            }
        }
    }()

    return out, nil
}
<|endoftext|>


<commit_before>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

// Package docker exposes an API to convert Jujuisms to dockerisms.
package docker

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"os/exec"
	"strings"

	"github.com/juju/deputy"
	"gopkg.in/juju/charm.v5"
)

var execCommand = exec.Command

// Launch runs a new docker container with the given process data.
func Launch(p charm.Process) (ProcDetails, error) {
	args, err := launchArgs(p)
	if err != nil {
		return ProcDetails{}, err
	}
	d := deputy.Deputy{
		Errors: deputy.FromStderr,
	}
	cmd := execCommand("docker", args...)
	out := &bytes.Buffer{}
	cmd.Stdout = out
	if err := d.Run(cmd); err != nil {
		return ProcDetails{}, err
	}
	id := string(bytes.TrimSpace(out.Bytes()))
	status, err := inspect(id)
	if err != nil {
		return ProcDetails{}, fmt.Errorf("can't get status for container %q: %s", id, err)
	}
	name := status.Name
	if strings.HasPrefix(name, "/") {
		name = name[1:]
	}
	return ProcDetails{
		ID: name,
		Status: ProcStatus{
			State: status.brief(),
		},
	}, nil
}

// Status returns the ProcStatus for the docker container with the given id.
func Status(id string) (ProcStatus, error) {
	status, err := inspect(id)
	if err != nil {
		return ProcStatus{}, err
	}
	return ProcStatus{
		State: status.brief(),
	}, nil
}

// Destroy stops and removes the docker container with the given id.
func Destroy(id string) error {
	d := deputy.Deputy{
		Errors: deputy.FromStderr,
	}
	cmd := execCommand("docker", "stop", id)
	if err := d.Run(cmd); err != nil {
		return fmt.Errorf("error while stopping container %q: %s", err)
	}

	cmd = execCommand("docker", "rm", id)
	if err := d.Run(cmd); err != nil {
		return fmt.Errorf("error while removing container %q: %s", err)
	}
	return nil
}

// launchArgs converts the Process struct into arguments for the docker run
// command.
func launchArgs(p charm.Process) ([]string, error) {
	if err := p.Validate(); err != nil {
		return nil, fmt.Errorf("invalid proc-info: %s", err)
	}

	args := []string{"run", "--detach", "--name", p.Name}
	for k, v := range p.EnvVars {
		args = append(args, "-e", k+"="+v)
	}

	for _, p := range p.Ports {
		// TODO(natefinch): update this when we use portranges
		args = append(args, "-p", fmt.Sprintf("%d:%d/%s", p.External, p.Internal, "tcp"))
	}

	for _, v := range p.Volumes {
		args = append(args, "-v", fmt.Sprintf("%s:%s:%s", v.ExternalMount, v.InternalMount, v.Mode))
	}

	// Image and Command must come after all options.
	args = append(args, p.Image)
	if p.Command != "" {
		// TODO(natefinch): update this when we make command a list of strings
		args = append(args, strings.Fields(p.Command)...)
	}
	return args, nil
}

// status is the struct that contains the schema returned by docker's inspect command
type status struct {
	State state
	Name  string
}

type state struct {
	Running    bool
	Paused     bool
	Restarting bool
	OOMKilled  bool
	Dead       bool
	Pid        int
	ExitCode   int
	Error      string
}

// brief returns a short summary for the status.
func (s *status) brief() string {
	switch {
	case s.State.Running:
		return "Running"
	case s.State.OOMKilled:
		return "OOMKilled"
	case s.State.Dead:
		return "Dead"
	case s.State.Restarting:
		return "Restarting"
	case s.State.Paused:
		return "Paused"
	}
	return "Unknown"
}

// inspect calls docker inspect and returns the unmarshaled json response.
func inspect(id string) (status, error) {
	cmd := execCommand("docker", "inspect", id)
	out := &bytes.Buffer{}
	cmd.Stdout = out
	d := deputy.Deputy{
		Errors: deputy.FromStderr,
	}
	if err := d.Run(cmd); err != nil {
		return status{}, err
	}
	return statusFromInspect(id, out.Bytes())
}

func statusFromInspect(id string, b []byte) (status, error) {
	var st []status
	if err := json.Unmarshal(b, &st); err != nil {
		return status{}, fmt.Errorf("can't decode response from docker inspect %s: %s", id, err)
	}
	if len(st) == 0 {
		return status{}, errors.New("no status returned from docker inspect " + id)
	}
	if len(st) > 1 {
		return status{}, errors.New("multiple status values returned from docker inspect " + id)
	}
	return st[0], nil

}

// These two structs are copied from juju/process/plugin

// ProcDetails represents information about a process launched by a plugin.
type ProcDetails struct {
	// ID is a unique string identifying the process to the plugin.
	ID string `json:"id"`
	// Status is the status of the process after launch.
	Status ProcStatus `json:"status"`
}

// ProcStatus represents the data returned from the Status call.
type ProcStatus struct {
	// State represents the human-readable string returned by the plugin for
	// the process.
	State string `json:"state"`
}
<commit_msg>Use strings.TrimPrefix.<commit_after>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

// Package docker exposes an API to convert Jujuisms to dockerisms.
package docker

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"os/exec"
	"strings"

	"github.com/juju/deputy"
	"gopkg.in/juju/charm.v5"
)

var execCommand = exec.Command

// Launch runs a new docker container with the given process data.
func Launch(p charm.Process) (ProcDetails, error) {
	args, err := launchArgs(p)
	if err != nil {
		return ProcDetails{}, err
	}
	d := deputy.Deputy{
		Errors: deputy.FromStderr,
	}
	cmd := execCommand("docker", args...)
	out := &bytes.Buffer{}
	cmd.Stdout = out
	if err := d.Run(cmd); err != nil {
		return ProcDetails{}, err
	}
	id := string(bytes.TrimSpace(out.Bytes()))
	status, err := inspect(id)
	if err != nil {
		return ProcDetails{}, fmt.Errorf("can't get status for container %q: %s", id, err)
	}
	return ProcDetails{
		ID: strings.TrimPrefix(status.Name, "/"),
		Status: ProcStatus{
			State: status.brief(),
		},
	}, nil
}

// Status returns the ProcStatus for the docker container with the given id.
func Status(id string) (ProcStatus, error) {
	status, err := inspect(id)
	if err != nil {
		return ProcStatus{}, err
	}
	return ProcStatus{
		State: status.brief(),
	}, nil
}

// Destroy stops and removes the docker container with the given id.
func Destroy(id string) error {
	d := deputy.Deputy{
		Errors: deputy.FromStderr,
	}
	cmd := execCommand("docker", "stop", id)
	if err := d.Run(cmd); err != nil {
		return fmt.Errorf("error while stopping container %q: %s", err)
	}

	cmd = execCommand("docker", "rm", id)
	if err := d.Run(cmd); err != nil {
		return fmt.Errorf("error while removing container %q: %s", err)
	}
	return nil
}

// launchArgs converts the Process struct into arguments for the docker run
// command.
func launchArgs(p charm.Process) ([]string, error) {
	if err := p.Validate(); err != nil {
		return nil, fmt.Errorf("invalid proc-info: %s", err)
	}

	args := []string{"run", "--detach", "--name", p.Name}
	for k, v := range p.EnvVars {
		args = append(args, "-e", k+"="+v)
	}

	for _, p := range p.Ports {
		// TODO(natefinch): update this when we use portranges
		args = append(args, "-p", fmt.Sprintf("%d:%d/%s", p.External, p.Internal, "tcp"))
	}

	for _, v := range p.Volumes {
		args = append(args, "-v", fmt.Sprintf("%s:%s:%s", v.ExternalMount, v.InternalMount, v.Mode))
	}

	// Image and Command must come after all options.
	args = append(args, p.Image)
	if p.Command != "" {
		// TODO(natefinch): update this when we make command a list of strings
		args = append(args, strings.Fields(p.Command)...)
	}
	return args, nil
}

// status is the struct that contains the schema returned by docker's inspect command
type status struct {
	State state
	Name  string
}

type state struct {
	Running    bool
	Paused     bool
	Restarting bool
	OOMKilled  bool
	Dead       bool
	Pid        int
	ExitCode   int
	Error      string
}

// brief returns a short summary for the status.
func (s *status) brief() string {
	switch {
	case s.State.Running:
		return "Running"
	case s.State.OOMKilled:
		return "OOMKilled"
	case s.State.Dead:
		return "Dead"
	case s.State.Restarting:
		return "Restarting"
	case s.State.Paused:
		return "Paused"
	}
	return "Unknown"
}

// inspect calls docker inspect and returns the unmarshaled json response.
func inspect(id string) (status, error) {
	cmd := execCommand("docker", "inspect", id)
	out := &bytes.Buffer{}
	cmd.Stdout = out
	d := deputy.Deputy{
		Errors: deputy.FromStderr,
	}
	if err := d.Run(cmd); err != nil {
		return status{}, err
	}
	return statusFromInspect(id, out.Bytes())
}

func statusFromInspect(id string, b []byte) (status, error) {
	var st []status
	if err := json.Unmarshal(b, &st); err != nil {
		return status{}, fmt.Errorf("can't decode response from docker inspect %s: %s", id, err)
	}
	if len(st) == 0 {
		return status{}, errors.New("no status returned from docker inspect " + id)
	}
	if len(st) > 1 {
		return status{}, errors.New("multiple status values returned from docker inspect " + id)
	}
	return st[0], nil

}

// These two structs are copied from juju/process/plugin

// ProcDetails represents information about a process launched by a plugin.
type ProcDetails struct {
	// ID is a unique string identifying the process to the plugin.
	ID string `json:"id"`
	// Status is the status of the process after launch.
	Status ProcStatus `json:"status"`
}

// ProcStatus represents the data returned from the Status call.
type ProcStatus struct {
	// State represents the human-readable string returned by the plugin for
	// the process.
	State string `json:"state"`
}
<|endoftext|>


<commit_before>package main

import (
	c3to10 "eaciit/wfdemo-git/processapp/threeextractor/convert3secto10min/lib"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"sync"

	"github.com/eaciit/database/base"
	"github.com/eaciit/orm"
	"github.com/fsnotify/fsnotify"
	// "github.com/metakeule/fmtdate"
	//dc "eaciit/wfdemo-git/processapp/threeextractor/dataconversion"
	"archive/tar"
	"archive/zip"
	"bytes"
	. "eaciit/wfdemo-git/processapp/watcher/controllers"
	"time"

	tk "github.com/eaciit/toolkit"
)

const (
	NOK = "NOK"
	OK  = "OK"
	// TIME_FORMAT_STR = "DDMMYYhhmmss"
)

type Command struct {
	Action  string
	Command string
	Success string
	Fail    string
}
type Configuration struct {
	Draft    string
	Process  string
	Fail     string
	Success  string
	Errors   string
	Archive  string
	Commands []Command
}

var (
	conn    base.IConnection
	ctx     *orm.DataContext
	conf    Configuration
	mux     = &sync.Mutex{}
	pathSep = string(os.PathSeparator)
)

func main() {

	fmt.Println(".." + pathSep + "conf" + pathSep + "receiver-config.json")

	file, _ := os.Open(".." + pathSep + "conf" + pathSep + "receiver-config.json")
	decoder := json.NewDecoder(file)
	err := decoder.Decode(&conf)

	if err != nil {
		panic(err)
	}

	// now, _ := time.Parse("2006-1-2 15:4:05", "2016-10-22 23:57:30")
	// tenMinInfo := GenTenMinuteInfo(now)

	// log.Printf("%#v \n", tenMinInfo)

	runtime.GOMAXPROCS(runtime.NumCPU())
	log.Println("Starting the app..\n")

	log.Println()
	log.Printf("Draft: %v\n", conf.Draft)
	log.Printf("Process: %v\n", conf.Process)
	log.Printf("Fail: %v\n", conf.Fail)
	log.Printf("Success: %v\n", conf.Success)
	log.Printf("Errors: %v\n", conf.Errors)
	log.Println()

	/*db, _ := PrepareConnection()
	base := new(BaseController)
	base.Ctx = orm.New(db)
	defer base.Ctx.Close()

	log.Println("xxx")

	new(GenTenFromThreeSecond).Generate(base, "sample.csv")*/

	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		log.Fatal(err)
	}
	defer watcher.Close()

	done := make(chan bool)
	go func() {
		for {
			select {
			case event := <-watcher.Events:
				// log.Println("event:", event)
				if event.Op&fsnotify.Create == fsnotify.Create {
					go processFile(event.Name, conf.Commands)
				}
			case err := <-watcher.Errors:
				log.Println("error:", err)
			}
		}
	}()

	// watch draft
	err = watcher.Add(conf.Draft)
	if err != nil {
		log.Fatal(err)
	}

	// watch process
	err = watcher.Add(conf.Process)
	if err != nil {
		log.Fatal(err)
	}

	/*// watch fail
	err = watcher.Add("/Users/frezadev/Documents/watch/fail")
	if err != nil {
		log.Fatal(err)
	}

	// watch success
	err = watcher.Add("/Users/frezadev/Documents/watch/success")
	if err != nil {
		log.Fatal(err)
	}*/
	<-done
}

func processFile(filePath string, com []Command) {
	// dt := time.Now()
	// dtStr := fmtdate.Format(TIME_FORMAT_STR, dt)
	fmt.Println(" >>> Process : ", filePath)
	for true {
		byteOut, err := runCMD("lsof " + filePath)
		if err != nil {
			log.Print("Gagal")
		}
		if len(byteOut) == 0 {
			break
		} else {
			fmt.Println(string(byteOut))
			time.Sleep(200 * time.Millisecond)
		}

	}
	file := strings.Split(filePath, pathSep)
	fileName := file[len(file)-1]

	if strings.Contains(fileName, ".csv") {
		time.Sleep(100 * time.Millisecond)
		log.Printf("Proccess file: %v \n", filePath)
		var action Command

		if strings.Contains(filePath, conf.Draft) {
			action = com[0]
		} else if strings.Contains(filePath, conf.Process) {
			action = com[1]
		}

		// log.Printf("action: %v \n", action)

		next := action.Action
	done:

		for {
			log.Printf("\n\nnext: %v \n", next)

			if next == "DONE" {
				break done
			} else {
				for _, act := range com {
					//fmt.Println("PPPP")
					if act.Action == next {
						next = run(act, fileName)

						break
					}
				}
			}
		}

		log.Printf("DONE for file: %v\n", filePath)
	} else if strings.Contains(fileName, ".tar") {
		time.Sleep(100 * time.Millisecond)
		untar(filePath, conf.Draft)
		_, _ = runCMD(fmt.Sprintf("mv %v %v", filePath, conf.Archive))
	} else if strings.Contains(fileName, ".zip") {
		time.Sleep(100 * time.Millisecond)
		e := unzip(filePath, conf.Draft)
		if e != nil {
			log.Printf(filepath, e.Error())
			_, _ = runCMD(fmt.Sprintf("mv %v %v", filePath, conf.Errors))
		} else {
			fmt.Println("Unzip Done")
			_, _ = runCMD(fmt.Sprintf("mv %v %v", filePath, conf.Archive))
		}
	}
}

func untar(tarball, target string) error {
	reader, err := os.Open(tarball)
	if err != nil {
		return err
	}
	defer reader.Close()
	tarReader := tar.NewReader(reader)

	for {
		header, err := tarReader.Next()

		if err == io.EOF {
			break
		} else if err != nil {
			log.Printf("ERR: %#v \n", err.Error())
			return err
		}

		path := filepath.Join(target, header.Name)
		info := header.FileInfo()
		// log.Printf("path: %#v \n", path)
		// log.Printf("info: %#v \n", info)
		if strings.Contains(info.Name(), ".csv") {
			if info.IsDir() {
				if err = os.MkdirAll(path, info.Mode()); err != nil {
					return err
				}
				continue
			}

			file, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, info.Mode())
			if err != nil {
				return err
			}
			defer file.Close()
			_, err = io.Copy(file, tarReader)
			if err != nil {
				return err
			}
		}
	}

	return nil
}

func unzip(archive, target string) error {
	fmt.Println("Unzip", archive, target)
	reader, err := zip.OpenReader(archive)
	if err != nil {
		return err
	}

	if err := os.MkdirAll(target, 0755); err != nil {
		return err
	}

	for _, file := range reader.File {
		if strings.Contains(file.Name, ".csv") {

			path := filepath.Join(target, file.Name)
			fileReader, err := file.Open()

			if err != nil {
				log.Printf("ERR: %#v \n", err.Error())
				return err
			}
			defer fileReader.Close()

			targetFile, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode())
			if err != nil {
				return err
			}
			defer targetFile.Close()

			if _, err := io.Copy(targetFile, fileReader); err != nil {
				return err
			}
		}
	}

	reader.Close()
	return nil
}

func runCMD(cmdStr string) (out []byte, err error) {
	if pathSep == "\\" {
		cmdStr = strings.Replace(cmdStr, "\\", "/", -1)

	}

	if !strings.Contains(cmdStr, "lsof") {
		fmt.Println("sh", "-c", cmdStr)
	}

	var errBuff bytes.Buffer
	cmd := exec.Command("sh", "-c", cmdStr)
	cmd.Stderr = &errBuff
	//cmd.Run()
	//cmd.Path = os.Getenv("Path")
	//fmt.Println(cmd.Path)
	out, err = cmd.Output()
	if err != nil {
		fmt.Println(errBuff.String())
	}
	return
}

func run(action Command, file string) (next string) {
	cmdStr := ""
	runCommand := true
	log.Printf("run: %v | %v \n", action, file)
	// mux.Lock()

	if action.Action == "COPY_TO_PROCESS" {
		cmdStr = fmt.Sprintf(action.Command, conf.Draft+pathSep+file, conf.Process+pathSep+file)
	} else if action.Action == "COPY_TO_SUCCESS" {
		runCommand = doProcess(conf.Process + pathSep + file)

		cmdStr = fmt.Sprintf(action.Command, conf.Process+pathSep+file, conf.Success+pathSep+file)
	} else if action.Action == "COPY_TO_FAIL" {
		cmdStr = fmt.Sprintf(action.Command, conf.Process+pathSep+file, conf.Fail+pathSep+file)
	}
	//log.Printf("cmdstr: %v \n", cmdStr)
	// mux.Unlock()

	if runCommand {
		out, err := runCMD(cmdStr)

		if out != nil {
			log.Printf("%v \n", out)
		}

		if err != nil {
			log.Printf("result: %v %s\n%s", err.Error(), cmdStr, string(out))
			next = action.Success
		} else {
			next = action.Success
		}
	} else {
		log.Println("DONE")
		next = action.Fail
	}

	// log.Printf("next: %v \n", next)

	return
}

func doProcess(file string) (success bool) {
	log.Printf("doProcess: %v \n", file)
	db, e := PrepareConnection()
	if e != nil {
		log.Printf("ERROR on Process: %v\n", e.Error())
		success = false
	} else {
		//start := time.Now()
		base := new(BaseController)
		base.Ctx = orm.New(db)
		defer base.Ctx.Close()

		anFile := strings.Split(file, pathSep)
		fileName := anFile[len(anFile)-1]

		muxDo := &sync.Mutex{}

		muxDo.Lock()
		errorLine := new(ConvScadaTreeSecs).Generate(base, file)
		WriteWatcherErrors(errorLine, fileName, conf.Errors)
		log.Println("ConvScadaTreeSecs: DONE")
		muxDo.Unlock()
		log.Println("Begin Converting ", file)
		err := c3to10.Generate(tk.M{}.Set("selector", "file").Set("file", fileName))
		if err != nil {
			tk.Println(err)
		} else {
			tk.Println(">> DONE <<")
		}

		// errorLine = tk.M{}
		// errorLine = new(GenTenFromThreeSecond).Generate(base, fileName)
		// WriteWatcherErrors(errorLine, fileName+"-ten", conf.Errors)
		// log.Println("GenTenFromThreeSecond: DONE")

		/*
			muxDo.Lock()
			errorLine = tk.M{}
			conv := dc.NewDataConversion(base.Ctx)
			errorLine = conv.Generate(fileName)
			// errorLine = new(GenTenFromThreeSecond).Generate(base, fileName)
			WriteWatcherErrors(errorLine, fileName+"-ten", conf.Errors)
			log.Printf("GenTenFromThreeSecond: %v DONE | in %v seconds \n", file, time.Now().Sub(start).Seconds())
			success = true
			muxDo.Unlock()*/
	}

	return
}
<commit_msg>bug fix<commit_after>package main

import (
	c3to10 "eaciit/wfdemo-git/processapp/threeextractor/convert3secto10min/lib"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"sync"

	"github.com/eaciit/database/base"
	"github.com/eaciit/orm"
	"github.com/fsnotify/fsnotify"
	// "github.com/metakeule/fmtdate"
	//dc "eaciit/wfdemo-git/processapp/threeextractor/dataconversion"
	"archive/tar"
	"archive/zip"
	"bytes"
	. "eaciit/wfdemo-git/processapp/watcher/controllers"
	"time"

	tk "github.com/eaciit/toolkit"
)

const (
	NOK = "NOK"
	OK  = "OK"
	// TIME_FORMAT_STR = "DDMMYYhhmmss"
)

type Command struct {
	Action  string
	Command string
	Success string
	Fail    string
}
type Configuration struct {
	Draft    string
	Process  string
	Fail     string
	Success  string
	Errors   string
	Archive  string
	Commands []Command
}

var (
	conn    base.IConnection
	ctx     *orm.DataContext
	conf    Configuration
	mux     = &sync.Mutex{}
	pathSep = string(os.PathSeparator)
)

func main() {

	fmt.Println(".." + pathSep + "conf" + pathSep + "receiver-config.json")

	file, _ := os.Open(".." + pathSep + "conf" + pathSep + "receiver-config.json")
	decoder := json.NewDecoder(file)
	err := decoder.Decode(&conf)

	if err != nil {
		panic(err)
	}

	// now, _ := time.Parse("2006-1-2 15:4:05", "2016-10-22 23:57:30")
	// tenMinInfo := GenTenMinuteInfo(now)

	// log.Printf("%#v \n", tenMinInfo)

	runtime.GOMAXPROCS(runtime.NumCPU())
	log.Println("Starting the app..\n")

	log.Println()
	log.Printf("Draft: %v\n", conf.Draft)
	log.Printf("Process: %v\n", conf.Process)
	log.Printf("Fail: %v\n", conf.Fail)
	log.Printf("Success: %v\n", conf.Success)
	log.Printf("Errors: %v\n", conf.Errors)
	log.Println()

	/*db, _ := PrepareConnection()
	base := new(BaseController)
	base.Ctx = orm.New(db)
	defer base.Ctx.Close()

	log.Println("xxx")

	new(GenTenFromThreeSecond).Generate(base, "sample.csv")*/

	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		log.Fatal(err)
	}
	defer watcher.Close()

	done := make(chan bool)
	go func() {
		for {
			select {
			case event := <-watcher.Events:
				// log.Println("event:", event)
				if event.Op&fsnotify.Create == fsnotify.Create {
					go processFile(event.Name, conf.Commands)
				}
			case err := <-watcher.Errors:
				log.Println("error:", err)
			}
		}
	}()

	// watch draft
	err = watcher.Add(conf.Draft)
	if err != nil {
		log.Fatal(err)
	}

	// watch process
	err = watcher.Add(conf.Process)
	if err != nil {
		log.Fatal(err)
	}

	/*// watch fail
	err = watcher.Add("/Users/frezadev/Documents/watch/fail")
	if err != nil {
		log.Fatal(err)
	}

	// watch success
	err = watcher.Add("/Users/frezadev/Documents/watch/success")
	if err != nil {
		log.Fatal(err)
	}*/
	<-done
}

func processFile(filePath string, com []Command) {
	// dt := time.Now()
	// dtStr := fmtdate.Format(TIME_FORMAT_STR, dt)
	fmt.Println(" >>> Process : ", filePath)
	for true {
		byteOut, err := runCMD("lsof " + filePath)
		if err != nil {
			log.Print("Gagal")
		}
		if len(byteOut) == 0 {
			break
		} else {
			fmt.Println(string(byteOut))
			time.Sleep(200 * time.Millisecond)
		}

	}
	file := strings.Split(filePath, pathSep)
	fileName := file[len(file)-1]

	if strings.Contains(fileName, ".csv") {
		time.Sleep(100 * time.Millisecond)
		log.Printf("Proccess file: %v \n", filePath)
		var action Command

		if strings.Contains(filePath, conf.Draft) {
			action = com[0]
		} else if strings.Contains(filePath, conf.Process) {
			action = com[1]
		}

		// log.Printf("action: %v \n", action)

		next := action.Action
	done:

		for {
			log.Printf("\n\nnext: %v \n", next)

			if next == "DONE" {
				break done
			} else {
				for _, act := range com {
					//fmt.Println("PPPP")
					if act.Action == next {
						next = run(act, fileName)

						break
					}
				}
			}
		}

		log.Printf("DONE for file: %v\n", filePath)
	} else if strings.Contains(fileName, ".tar") {
		time.Sleep(100 * time.Millisecond)
		untar(filePath, conf.Draft)
		_, _ = runCMD(fmt.Sprintf("mv %v %v", filePath, conf.Archive))
	} else if strings.Contains(fileName, ".zip") {
		time.Sleep(100 * time.Millisecond)
		e := unzip(filePath, conf.Draft)
		if e != nil {
			log.Printf("%s - %s", filepath, e.Error())
			_, _ = runCMD(fmt.Sprintf("mv %v %v", filePath, conf.Errors))
		} else {
			fmt.Println("Unzip Done")
			_, _ = runCMD(fmt.Sprintf("mv %v %v", filePath, conf.Archive))
		}
	}
}

func untar(tarball, target string) error {
	reader, err := os.Open(tarball)
	if err != nil {
		return err
	}
	defer reader.Close()
	tarReader := tar.NewReader(reader)

	for {
		header, err := tarReader.Next()

		if err == io.EOF {
			break
		} else if err != nil {
			log.Printf("ERR: %#v \n", err.Error())
			return err
		}

		path := filepath.Join(target, header.Name)
		info := header.FileInfo()
		// log.Printf("path: %#v \n", path)
		// log.Printf("info: %#v \n", info)
		if strings.Contains(info.Name(), ".csv") {
			if info.IsDir() {
				if err = os.MkdirAll(path, info.Mode()); err != nil {
					return err
				}
				continue
			}

			file, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, info.Mode())
			if err != nil {
				return err
			}
			defer file.Close()
			_, err = io.Copy(file, tarReader)
			if err != nil {
				return err
			}
		}
	}

	return nil
}

func unzip(archive, target string) error {
	fmt.Println("Unzip", archive, target)
	reader, err := zip.OpenReader(archive)
	if err != nil {
		return err
	}

	if err := os.MkdirAll(target, 0755); err != nil {
		return err
	}

	for _, file := range reader.File {
		if strings.Contains(file.Name, ".csv") {

			path := filepath.Join(target, file.Name)
			fileReader, err := file.Open()

			if err != nil {
				log.Printf("ERR: %#v \n", err.Error())
				return err
			}
			defer fileReader.Close()

			targetFile, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode())
			if err != nil {
				return err
			}
			defer targetFile.Close()

			if _, err := io.Copy(targetFile, fileReader); err != nil {
				return err
			}
		}
	}

	reader.Close()
	return nil
}

func runCMD(cmdStr string) (out []byte, err error) {
	if pathSep == "\\" {
		cmdStr = strings.Replace(cmdStr, "\\", "/", -1)

	}

	if !strings.Contains(cmdStr, "lsof") {
		fmt.Println("sh", "-c", cmdStr)
	}

	var errBuff bytes.Buffer
	cmd := exec.Command("sh", "-c", cmdStr)
	cmd.Stderr = &errBuff
	//cmd.Run()
	//cmd.Path = os.Getenv("Path")
	//fmt.Println(cmd.Path)
	out, err = cmd.Output()
	if err != nil {
		fmt.Println(errBuff.String())
	}
	return
}

func run(action Command, file string) (next string) {
	cmdStr := ""
	runCommand := true
	log.Printf("run: %v | %v \n", action, file)
	// mux.Lock()

	if action.Action == "COPY_TO_PROCESS" {
		cmdStr = fmt.Sprintf(action.Command, conf.Draft+pathSep+file, conf.Process+pathSep+file)
	} else if action.Action == "COPY_TO_SUCCESS" {
		runCommand = doProcess(conf.Process + pathSep + file)

		cmdStr = fmt.Sprintf(action.Command, conf.Process+pathSep+file, conf.Success+pathSep+file)
	} else if action.Action == "COPY_TO_FAIL" {
		cmdStr = fmt.Sprintf(action.Command, conf.Process+pathSep+file, conf.Fail+pathSep+file)
	}
	//log.Printf("cmdstr: %v \n", cmdStr)
	// mux.Unlock()

	if runCommand {
		out, err := runCMD(cmdStr)

		if out != nil {
			log.Printf("%v \n", out)
		}

		if err != nil {
			log.Printf("result: %v %s\n%s", err.Error(), cmdStr, string(out))
			next = action.Success
		} else {
			next = action.Success
		}
	} else {
		log.Println("DONE")
		next = action.Fail
	}

	// log.Printf("next: %v \n", next)

	return
}

func doProcess(file string) (success bool) {
	log.Printf("doProcess: %v \n", file)
	db, e := PrepareConnection()
	if e != nil {
		log.Printf("ERROR on Process: %v\n", e.Error())
		success = false
	} else {
		//start := time.Now()
		base := new(BaseController)
		base.Ctx = orm.New(db)
		defer base.Ctx.Close()

		anFile := strings.Split(file, pathSep)
		fileName := anFile[len(anFile)-1]

		muxDo := &sync.Mutex{}

		muxDo.Lock()
		errorLine := new(ConvScadaTreeSecs).Generate(base, file)
		WriteWatcherErrors(errorLine, fileName, conf.Errors)
		log.Println("ConvScadaTreeSecs: DONE")
		muxDo.Unlock()
		log.Println("Begin Converting ", file)
		err := c3to10.Generate(tk.M{}.Set("selector", "file").Set("file", fileName))
		if err != nil {
			tk.Println(err)
		} else {
			tk.Println(">> DONE <<")
		}

		// errorLine = tk.M{}
		// errorLine = new(GenTenFromThreeSecond).Generate(base, fileName)
		// WriteWatcherErrors(errorLine, fileName+"-ten", conf.Errors)
		// log.Println("GenTenFromThreeSecond: DONE")

		/*
			muxDo.Lock()
			errorLine = tk.M{}
			conv := dc.NewDataConversion(base.Ctx)
			errorLine = conv.Generate(fileName)
			// errorLine = new(GenTenFromThreeSecond).Generate(base, fileName)
			WriteWatcherErrors(errorLine, fileName+"-ten", conf.Errors)
			log.Printf("GenTenFromThreeSecond: %v DONE | in %v seconds \n", file, time.Now().Sub(start).Seconds())
			success = true
			muxDo.Unlock()*/
	}

	return
}
<|endoftext|>


<commit_before>// Copyright 2014 Manu Martinez-Almeida.  All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.

package render

import "net/http"

type Render interface {
	Render(http.ResponseWriter) error
	WriteContentType(w http.ResponseWriter)
}

var (
	_ Render     = JSON{}
	_ Render     = IJSON{}
	_ Render     = FFJSON{}
	_ Render     = IndentedJSON{}
	_ Render     = SecureJSON{}
	_ Render     = XML{}
	_ Render     = String{}
	_ Render     = Redirect{}
	_ Render     = Data{}
	_ Render     = HTML{}
	_ HTMLRender = HTMLDebug{}
	_ HTMLRender = HTMLProduction{}
	_ Render     = YAML{}
	_ Render     = MsgPack{}
	_ Render     = MsgPack{}
)

func writeContentType(w http.ResponseWriter, value []string) {
	header := w.Header()
	if val := header["Content-Type"]; len(val) == 0 {
		header["Content-Type"] = value
	}
}
<commit_msg>remove repeated static check<commit_after>// Copyright 2014 Manu Martinez-Almeida.  All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.

package render

import "net/http"

type Render interface {
	Render(http.ResponseWriter) error
	WriteContentType(w http.ResponseWriter)
}

var (
	_ Render     = JSON{}
	_ Render     = IJSON{}
	_ Render     = FFJSON{}
	_ Render     = IndentedJSON{}
	_ Render     = SecureJSON{}
	_ Render     = XML{}
	_ Render     = String{}
	_ Render     = Redirect{}
	_ Render     = Data{}
	_ Render     = HTML{}
	_ HTMLRender = HTMLDebug{}
	_ HTMLRender = HTMLProduction{}
	_ Render     = YAML{}
	_ Render     = MsgPack{}
)

func writeContentType(w http.ResponseWriter, value []string) {
	header := w.Header()
	if val := header["Content-Type"]; len(val) == 0 {
		header["Content-Type"] = value
	}
}
<|endoftext|>


<commit_before>package websockets

import (
	"time"

	"github.com/gorilla/websocket"
)

const (
	// Time allowed to write a message to the peer.
	writeWait = 10 * time.Second
	// Time allowed to read the next pong message from the peer.
	pongWait = 60 * time.Second
	// Send pings to peer with this period. Must be less than pongWait.
	pingPeriod = (pongWait * 9) / 10
	// Maximum message size allowed from peer.
	maxMessageSize = 256
)

type connection struct {
	hub  *Hub
	ws   *websocket.Conn
	send chan interface{}
}

func (c *connection) readLoop() {
	defer func() {
		c.hub.unregisterChan <- c
		c.ws.Close()
	}()
	c.ws.SetReadLimit(256)
	c.ws.SetReadDeadline(time.Now().Add(pongWait))
	c.ws.SetPongHandler(func(string) error { c.ws.SetReadDeadline(time.Now().Add(pongWait)); return nil })
	for {
		if _, _, err := c.ws.NextReader(); err != nil {
			return
		}
	}
}

func (c *connection) writeLoop() {
	ticker := time.NewTicker(pingPeriod)
	defer func() {
		ticker.Stop()
		c.ws.Close()
	}()
	for {
		select {
		case message, ok := <-c.send:
			if !ok {
				c.writeControl(websocket.CloseMessage)
				return
			}
			if err := c.writeJSON(message); err != nil {
				return
			}
		case <-ticker.C:
			if err := c.writeControl(websocket.PingMessage); err != nil {
				return
			}
		}
	}
}

func (c *connection) writeJSON(message interface{}) error {
	c.ws.SetWriteDeadline(time.Now().Add(writeWait))
	return c.ws.WriteJSON(message)
}

func (c *connection) writeControl(messageType int) error {
	c.ws.SetWriteDeadline(time.Now().Add(writeWait))
	return c.ws.WriteMessage(messageType, []byte{})
}
<commit_msg>Set websocket read limit to 1 byte<commit_after>package websockets

import (
	"time"

	"github.com/gorilla/websocket"
)

const (
	// Time allowed to write a message to the peer.
	writeWait = 10 * time.Second
	// Time allowed to read the next pong message from the peer.
	pongWait = 60 * time.Second
	// Send pings to peer with this period. Must be less than pongWait.
	pingPeriod = (pongWait * 9) / 10
	// Maximum message size allowed from peer. Set to minimum allowed value as we don't expect the client to send non-control messages.
	maxMessageSize = 1
)

type connection struct {
	hub  *Hub
	ws   *websocket.Conn
	send chan interface{}
}

func (c *connection) readLoop() {
	defer func() {
		c.hub.unregisterChan <- c
		c.ws.Close()
	}()
	c.ws.SetReadLimit(maxMessageSize)
	c.ws.SetReadDeadline(time.Now().Add(pongWait))
	c.ws.SetPongHandler(func(string) error { c.ws.SetReadDeadline(time.Now().Add(pongWait)); return nil })
	for {
		if _, _, err := c.ws.NextReader(); err != nil {
			return
		}
	}
}

func (c *connection) writeLoop() {
	ticker := time.NewTicker(pingPeriod)
	defer func() {
		ticker.Stop()
		c.ws.Close()
	}()
	for {
		select {
		case message, ok := <-c.send:
			if !ok {
				c.writeControl(websocket.CloseMessage)
				return
			}
			if err := c.writeJSON(message); err != nil {
				return
			}
		case <-ticker.C:
			if err := c.writeControl(websocket.PingMessage); err != nil {
				return
			}
		}
	}
}

func (c *connection) writeJSON(message interface{}) error {
	c.ws.SetWriteDeadline(time.Now().Add(writeWait))
	return c.ws.WriteJSON(message)
}

func (c *connection) writeControl(messageType int) error {
	c.ws.SetWriteDeadline(time.Now().Add(writeWait))
	return c.ws.WriteMessage(messageType, []byte{})
}
<|endoftext|>


<commit_before>package command

import (
	"io/ioutil"
	"path/filepath"
)

func init() {
	cmdScaffold.Run = runScaffold // break init cycle
}

var cmdScaffold = &Command{
	UsageLine: "scaffold -config=[filer|notification|replication|security|master]",
	Short:     "generate basic configuration files",
	Long: `Generate filer.toml with all possible configurations for you to customize.

  `,
}

var (
	outputPath = cmdScaffold.Flag.String("output", "", "if not empty, save the configuration file to this directory")
	config     = cmdScaffold.Flag.String("config", "filer", "[filer|notification|replication|security|master] the configuration file to generate")
)

func runScaffold(cmd *Command, args []string) bool {

	content := ""
	switch *config {
	case "filer":
		content = FILER_TOML_EXAMPLE
	case "notification":
		content = NOTIFICATION_TOML_EXAMPLE
	case "replication":
		content = REPLICATION_TOML_EXAMPLE
	case "security":
		content = SECURITY_TOML_EXAMPLE
	case "master":
		content = MASTER_TOML_EXAMPLE
	}
	if content == "" {
		println("need a valid -config option")
		return false
	}

	if *outputPath != "" {
		ioutil.WriteFile(filepath.Join(*outputPath, *config+".toml"), []byte(content), 0644)
	} else {
		println(content)
	}
	return true
}

const (
	FILER_TOML_EXAMPLE = `
# A sample TOML config file for SeaweedFS filer store
# Used with "weed filer" or "weed server -filer"
# Put this file to one of the location, with descending priority
#    ./filer.toml
#    $HOME/.seaweedfs/filer.toml
#    /etc/seaweedfs/filer.toml

[leveldb2]
# local on disk, mostly for simple single-machine setup, fairly scalable
# faster than previous leveldb, recommended.
enabled = true
dir = "."					# directory to store level db files

####################################################
# multiple filers on shared storage, fairly scalable
####################################################

[mysql]  # or tidb
# CREATE TABLE IF NOT EXISTS filemeta (
#   dirhash     BIGINT         COMMENT 'first 64 bits of MD5 hash value of directory field',
#   name        VARCHAR(1000)  COMMENT 'directory or file name',
#   directory   TEXT           COMMENT 'full path to parent directory',
#   meta        LONGBLOB,
#   PRIMARY KEY (dirhash, name)
# ) DEFAULT CHARSET=utf8;

enabled = false
hostname = "localhost"
port = 3306
username = "root"
password = ""
database = ""              # create or use an existing database
connection_max_idle = 2
connection_max_open = 100
interpolateParams = false

[postgres] # or cockroachdb
# CREATE TABLE IF NOT EXISTS filemeta (
#   dirhash     BIGINT,
#   name        VARCHAR(65535),
#   directory   VARCHAR(65535),
#   meta        bytea,
#   PRIMARY KEY (dirhash, name)
# );
enabled = false
hostname = "localhost"
port = 5432
username = "postgres"
password = ""
database = ""              # create or use an existing database
sslmode = "disable"
connection_max_idle = 100
connection_max_open = 100

[cassandra]
# CREATE TABLE filemeta (
#    directory varchar,
#    name varchar,
#    meta blob,
#    PRIMARY KEY (directory, name)
# ) WITH CLUSTERING ORDER BY (name ASC);
enabled = false
keyspace="seaweedfs"
hosts=[
	"localhost:9042",
]

[redis]
enabled = false
address  = "localhost:6379"
password = ""
database = 0

[redis_cluster]
enabled = false
addresses = [
    "localhost:30001",
    "localhost:30002",
    "localhost:30003",
    "localhost:30004",
    "localhost:30005",
    "localhost:30006",
]
password = ""

[etcd]
enabled = false
servers = "localhost:2379"
timeout = "3s"

[tikv]
enabled = false
pdAddress = "192.168.199.113:2379"

`

	NOTIFICATION_TOML_EXAMPLE = `
# A sample TOML config file for SeaweedFS filer store
# Used by both "weed filer" or "weed server -filer" and "weed filer.replicate"
# Put this file to one of the location, with descending priority
#    ./notification.toml
#    $HOME/.seaweedfs/notification.toml
#    /etc/seaweedfs/notification.toml

####################################################
# notification
# send and receive filer updates for each file to an external message queue
####################################################
[notification.log]
# this is only for debugging perpose and does not work with "weed filer.replicate"
enabled = false

[notification.kafka]
enabled = false
hosts = [
  "localhost:9092"
]
topic = "seaweedfs_filer"
offsetFile = "./last.offset"
offsetSaveIntervalSeconds = 10

[notification.aws_sqs]
# experimental, let me know if it works
enabled = false
aws_access_key_id     = ""        # if empty, loads from the shared credentials file (~/.aws/credentials).
aws_secret_access_key = ""        # if empty, loads from the shared credentials file (~/.aws/credentials).
region = "us-east-2"
sqs_queue_name = "my_filer_queue" # an existing queue name

[notification.google_pub_sub]
# read credentials doc at https://cloud.google.com/docs/authentication/getting-started
enabled = false
google_application_credentials = "/path/to/x.json" # path to json credential file
project_id = ""                       # an existing project id
topic = "seaweedfs_filer_topic"       # a topic, auto created if does not exists

[notification.gocdk_pub_sub]
# The Go Cloud Development Kit (https://gocloud.dev).
# PubSub API (https://godoc.org/gocloud.dev/pubsub).
# Supports AWS SNS/SQS, Azure Service Bus, Google PubSub, NATS and RabbitMQ.
enabled = false
# This URL will Dial the RabbitMQ server at the URL in the environment
# variable RABBIT_SERVER_URL and open the exchange "myexchange".
# The exchange must have already been created by some other means, like
# the RabbitMQ management plugin.
topic_url = "rabbit://myexchange"
sub_url = "rabbit://myqueue"
`

	REPLICATION_TOML_EXAMPLE = `
# A sample TOML config file for replicating SeaweedFS filer
# Used with "weed filer.replicate"
# Put this file to one of the location, with descending priority
#    ./replication.toml
#    $HOME/.seaweedfs/replication.toml
#    /etc/seaweedfs/replication.toml

[source.filer]
enabled = true
grpcAddress = "localhost:18888"
# all files under this directory tree are replicated.
# this is not a directory on your hard drive, but on your filer.
# i.e., all files with this "prefix" are sent to notification message queue.
directory = "/buckets"

[sink.filer]
enabled = false
grpcAddress = "localhost:18888"
# all replicated files are under this directory tree
# this is not a directory on your hard drive, but on your filer.
# i.e., all received files will be "prefixed" to this directory.
directory = "/backup"
replication = ""
collection = ""
ttlSec = 0

[sink.s3]
# read credentials doc at https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/sessions.html
# default loads credentials from the shared credentials file (~/.aws/credentials).
enabled = false
aws_access_key_id     = ""     # if empty, loads from the shared credentials file (~/.aws/credentials).
aws_secret_access_key = ""     # if empty, loads from the shared credentials file (~/.aws/credentials).
region = "us-east-2"
bucket = "your_bucket_name"    # an existing bucket
directory = "/"                # destination directory

[sink.google_cloud_storage]
# read credentials doc at https://cloud.google.com/docs/authentication/getting-started
enabled = false
google_application_credentials = "/path/to/x.json" # path to json credential file
bucket = "your_bucket_seaweedfs"    # an existing bucket
directory = "/"                     # destination directory

[sink.azure]
# experimental, let me know if it works
enabled = false
account_name = ""
account_key  = ""
container = "mycontainer"      # an existing container
directory = "/"                # destination directory

[sink.backblaze]
enabled = false
b2_account_id = ""
b2_master_application_key  = ""
bucket = "mybucket"            # an existing bucket
directory = "/"                # destination directory

`

	SECURITY_TOML_EXAMPLE = `
# Put this file to one of the location, with descending priority
#    ./security.toml
#    $HOME/.seaweedfs/security.toml
#    /etc/seaweedfs/security.toml
# this file is read by master, volume server, and filer

# the jwt signing key is read by master and volume server.
# a jwt defaults to expire after 10 seconds.
[jwt.signing]
key = ""
expires_after_seconds = 10           # seconds

# jwt for read is only supported with master+volume setup. Filer does not support this mode.
[jwt.signing.read]
key = ""
expires_after_seconds = 10           # seconds

# all grpc tls authentications are mutual
# the values for the following ca, cert, and key are paths to the PERM files.
# the host name is not checked, so the PERM files can be shared.
[grpc]
ca = ""

[grpc.volume]
cert = ""
key  = ""

[grpc.master]
cert = ""
key  = ""

[grpc.filer]
cert = ""
key  = ""

# use this for any place needs a grpc client
# i.e., "weed backup|benchmark|filer.copy|filer.replicate|mount|s3|upload"
[grpc.client]
cert = ""
key  = ""

# volume server https options
# Note: work in progress!
#     this does not work with other clients, e.g., "weed filer|mount" etc, yet.
[https.client]
enabled = true
[https.volume]
cert = ""
key  = ""

`

	MASTER_TOML_EXAMPLE = `
# Put this file to one of the location, with descending priority
#    ./master.toml
#    $HOME/.seaweedfs/master.toml
#    /etc/seaweedfs/master.toml
# this file is read by master

[master.maintenance]
# periodically run these scripts are the same as running them from 'weed shell'
scripts = """
  ec.encode -fullPercent=95 -quietFor=1h
  ec.rebuild -force
  ec.balance -force
  volume.balance -force
"""
sleep_minutes = 17          # sleep minutes between each script execution

[master.filer]
default_filer_url = "http://localhost:8888/"

[master.sequencer]
type = "memory"     # Choose [memory|etcd] type for storing the file id sequence
# when sequencer.type = etcd, set listen client urls of etcd cluster that store file id sequence
# example : http://127.0.0.1:2379,http://127.0.0.1:2389
sequencer_etcd_urls = "http://127.0.0.1:2379"

[storage.backend]
	[storage.backend.s3.default]
	enabled = false
	aws_access_key_id     = ""     # if empty, loads from the shared credentials file (~/.aws/credentials).
	aws_secret_access_key = ""     # if empty, loads from the shared credentials file (~/.aws/credentials).
	region = "us-east-2"
	bucket = "your_bucket_name"    # an existing bucket

`
)
<commit_msg>Add readOnly and routeByLatency options to scaffold.go<commit_after>package command

import (
	"io/ioutil"
	"path/filepath"
)

func init() {
	cmdScaffold.Run = runScaffold // break init cycle
}

var cmdScaffold = &Command{
	UsageLine: "scaffold -config=[filer|notification|replication|security|master]",
	Short:     "generate basic configuration files",
	Long: `Generate filer.toml with all possible configurations for you to customize.

  `,
}

var (
	outputPath = cmdScaffold.Flag.String("output", "", "if not empty, save the configuration file to this directory")
	config     = cmdScaffold.Flag.String("config", "filer", "[filer|notification|replication|security|master] the configuration file to generate")
)

func runScaffold(cmd *Command, args []string) bool {

	content := ""
	switch *config {
	case "filer":
		content = FILER_TOML_EXAMPLE
	case "notification":
		content = NOTIFICATION_TOML_EXAMPLE
	case "replication":
		content = REPLICATION_TOML_EXAMPLE
	case "security":
		content = SECURITY_TOML_EXAMPLE
	case "master":
		content = MASTER_TOML_EXAMPLE
	}
	if content == "" {
		println("need a valid -config option")
		return false
	}

	if *outputPath != "" {
		ioutil.WriteFile(filepath.Join(*outputPath, *config+".toml"), []byte(content), 0644)
	} else {
		println(content)
	}
	return true
}

const (
	FILER_TOML_EXAMPLE = `
# A sample TOML config file for SeaweedFS filer store
# Used with "weed filer" or "weed server -filer"
# Put this file to one of the location, with descending priority
#    ./filer.toml
#    $HOME/.seaweedfs/filer.toml
#    /etc/seaweedfs/filer.toml

[leveldb2]
# local on disk, mostly for simple single-machine setup, fairly scalable
# faster than previous leveldb, recommended.
enabled = true
dir = "."					# directory to store level db files

####################################################
# multiple filers on shared storage, fairly scalable
####################################################

[mysql]  # or tidb
# CREATE TABLE IF NOT EXISTS filemeta (
#   dirhash     BIGINT         COMMENT 'first 64 bits of MD5 hash value of directory field',
#   name        VARCHAR(1000)  COMMENT 'directory or file name',
#   directory   TEXT           COMMENT 'full path to parent directory',
#   meta        LONGBLOB,
#   PRIMARY KEY (dirhash, name)
# ) DEFAULT CHARSET=utf8;

enabled = false
hostname = "localhost"
port = 3306
username = "root"
password = ""
database = ""              # create or use an existing database
connection_max_idle = 2
connection_max_open = 100
interpolateParams = false

[postgres] # or cockroachdb
# CREATE TABLE IF NOT EXISTS filemeta (
#   dirhash     BIGINT,
#   name        VARCHAR(65535),
#   directory   VARCHAR(65535),
#   meta        bytea,
#   PRIMARY KEY (dirhash, name)
# );
enabled = false
hostname = "localhost"
port = 5432
username = "postgres"
password = ""
database = ""              # create or use an existing database
sslmode = "disable"
connection_max_idle = 100
connection_max_open = 100

[cassandra]
# CREATE TABLE filemeta (
#    directory varchar,
#    name varchar,
#    meta blob,
#    PRIMARY KEY (directory, name)
# ) WITH CLUSTERING ORDER BY (name ASC);
enabled = false
keyspace="seaweedfs"
hosts=[
	"localhost:9042",
]

[redis]
enabled = false
address  = "localhost:6379"
password = ""
database = 0

[redis_cluster]
enabled = false
addresses = [
    "localhost:30001",
    "localhost:30002",
    "localhost:30003",
    "localhost:30004",
    "localhost:30005",
    "localhost:30006",
]
password = ""
readOnly = true
routeByLatency = true

[etcd]
enabled = false
servers = "localhost:2379"
timeout = "3s"

[tikv]
enabled = false
pdAddress = "192.168.199.113:2379"

`

	NOTIFICATION_TOML_EXAMPLE = `
# A sample TOML config file for SeaweedFS filer store
# Used by both "weed filer" or "weed server -filer" and "weed filer.replicate"
# Put this file to one of the location, with descending priority
#    ./notification.toml
#    $HOME/.seaweedfs/notification.toml
#    /etc/seaweedfs/notification.toml

####################################################
# notification
# send and receive filer updates for each file to an external message queue
####################################################
[notification.log]
# this is only for debugging perpose and does not work with "weed filer.replicate"
enabled = false

[notification.kafka]
enabled = false
hosts = [
  "localhost:9092"
]
topic = "seaweedfs_filer"
offsetFile = "./last.offset"
offsetSaveIntervalSeconds = 10

[notification.aws_sqs]
# experimental, let me know if it works
enabled = false
aws_access_key_id     = ""        # if empty, loads from the shared credentials file (~/.aws/credentials).
aws_secret_access_key = ""        # if empty, loads from the shared credentials file (~/.aws/credentials).
region = "us-east-2"
sqs_queue_name = "my_filer_queue" # an existing queue name

[notification.google_pub_sub]
# read credentials doc at https://cloud.google.com/docs/authentication/getting-started
enabled = false
google_application_credentials = "/path/to/x.json" # path to json credential file
project_id = ""                       # an existing project id
topic = "seaweedfs_filer_topic"       # a topic, auto created if does not exists

[notification.gocdk_pub_sub]
# The Go Cloud Development Kit (https://gocloud.dev).
# PubSub API (https://godoc.org/gocloud.dev/pubsub).
# Supports AWS SNS/SQS, Azure Service Bus, Google PubSub, NATS and RabbitMQ.
enabled = false
# This URL will Dial the RabbitMQ server at the URL in the environment
# variable RABBIT_SERVER_URL and open the exchange "myexchange".
# The exchange must have already been created by some other means, like
# the RabbitMQ management plugin.
topic_url = "rabbit://myexchange"
sub_url = "rabbit://myqueue"
`

	REPLICATION_TOML_EXAMPLE = `
# A sample TOML config file for replicating SeaweedFS filer
# Used with "weed filer.replicate"
# Put this file to one of the location, with descending priority
#    ./replication.toml
#    $HOME/.seaweedfs/replication.toml
#    /etc/seaweedfs/replication.toml

[source.filer]
enabled = true
grpcAddress = "localhost:18888"
# all files under this directory tree are replicated.
# this is not a directory on your hard drive, but on your filer.
# i.e., all files with this "prefix" are sent to notification message queue.
directory = "/buckets"

[sink.filer]
enabled = false
grpcAddress = "localhost:18888"
# all replicated files are under this directory tree
# this is not a directory on your hard drive, but on your filer.
# i.e., all received files will be "prefixed" to this directory.
directory = "/backup"
replication = ""
collection = ""
ttlSec = 0

[sink.s3]
# read credentials doc at https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/sessions.html
# default loads credentials from the shared credentials file (~/.aws/credentials).
enabled = false
aws_access_key_id     = ""     # if empty, loads from the shared credentials file (~/.aws/credentials).
aws_secret_access_key = ""     # if empty, loads from the shared credentials file (~/.aws/credentials).
region = "us-east-2"
bucket = "your_bucket_name"    # an existing bucket
directory = "/"                # destination directory

[sink.google_cloud_storage]
# read credentials doc at https://cloud.google.com/docs/authentication/getting-started
enabled = false
google_application_credentials = "/path/to/x.json" # path to json credential file
bucket = "your_bucket_seaweedfs"    # an existing bucket
directory = "/"                     # destination directory

[sink.azure]
# experimental, let me know if it works
enabled = false
account_name = ""
account_key  = ""
container = "mycontainer"      # an existing container
directory = "/"                # destination directory

[sink.backblaze]
enabled = false
b2_account_id = ""
b2_master_application_key  = ""
bucket = "mybucket"            # an existing bucket
directory = "/"                # destination directory

`

	SECURITY_TOML_EXAMPLE = `
# Put this file to one of the location, with descending priority
#    ./security.toml
#    $HOME/.seaweedfs/security.toml
#    /etc/seaweedfs/security.toml
# this file is read by master, volume server, and filer

# the jwt signing key is read by master and volume server.
# a jwt defaults to expire after 10 seconds.
[jwt.signing]
key = ""
expires_after_seconds = 10           # seconds

# jwt for read is only supported with master+volume setup. Filer does not support this mode.
[jwt.signing.read]
key = ""
expires_after_seconds = 10           # seconds

# all grpc tls authentications are mutual
# the values for the following ca, cert, and key are paths to the PERM files.
# the host name is not checked, so the PERM files can be shared.
[grpc]
ca = ""

[grpc.volume]
cert = ""
key  = ""

[grpc.master]
cert = ""
key  = ""

[grpc.filer]
cert = ""
key  = ""

# use this for any place needs a grpc client
# i.e., "weed backup|benchmark|filer.copy|filer.replicate|mount|s3|upload"
[grpc.client]
cert = ""
key  = ""

# volume server https options
# Note: work in progress!
#     this does not work with other clients, e.g., "weed filer|mount" etc, yet.
[https.client]
enabled = true
[https.volume]
cert = ""
key  = ""

`

	MASTER_TOML_EXAMPLE = `
# Put this file to one of the location, with descending priority
#    ./master.toml
#    $HOME/.seaweedfs/master.toml
#    /etc/seaweedfs/master.toml
# this file is read by master

[master.maintenance]
# periodically run these scripts are the same as running them from 'weed shell'
scripts = """
  ec.encode -fullPercent=95 -quietFor=1h
  ec.rebuild -force
  ec.balance -force
  volume.balance -force
"""
sleep_minutes = 17          # sleep minutes between each script execution

[master.filer]
default_filer_url = "http://localhost:8888/"

[master.sequencer]
type = "memory"     # Choose [memory|etcd] type for storing the file id sequence
# when sequencer.type = etcd, set listen client urls of etcd cluster that store file id sequence
# example : http://127.0.0.1:2379,http://127.0.0.1:2389
sequencer_etcd_urls = "http://127.0.0.1:2379"

[storage.backend]
	[storage.backend.s3.default]
	enabled = false
	aws_access_key_id     = ""     # if empty, loads from the shared credentials file (~/.aws/credentials).
	aws_secret_access_key = ""     # if empty, loads from the shared credentials file (~/.aws/credentials).
	region = "us-east-2"
	bucket = "your_bucket_name"    # an existing bucket

`
)
<|endoftext|>


<commit_before>package filer

func hasWritePermission(dir *Entry, entry *Entry) bool {

	if dir == nil {
		return false
	}

	if dir.Uid == entry.Uid && dir.Mode&0200 > 0 {
		return true
	}

	if dir.Gid == entry.Gid && dir.Mode&0020 > 0 {
		return true
	}

	if dir.Mode&0002 > 0 {
		return true
	}

	return false
}
<commit_msg>remove dead code<commit_after><|endoftext|>


<commit_before>// errchk $G $D/$F.go

// Copyright 2009 The Go 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 main

import (
	OS "os"  // should require semicolon here; this is no different from other decls
	IO "io"
)

func main() {
}
<commit_msg>Add ERROR comment for errmsg to look for.<commit_after>// errchk $G $D/$F.go

// Copyright 2009 The Go 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 main

import (
	OS "os"  // should require semicolon here; this is no different from other decls
	IO "io"  // ERROR "missing"
)

func main() {
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"github.com/pzurek/vendengo/vend"
	"io/ioutil"
	"log"
	"net/http"
	"os"
)

// to run:
// go run vend.go <store name> <username> <password>
func main() {
	args := os.Args
	storeName := args[1]
	username := args[2]
	password := args[3]

	baseUrl := fmt.Sprintf("https://%s.vendhq.com/api/", storeName)

	client := &http.Client{}
	req, err := http.NewRequest("GET", baseUrl+"config", nil)
	req.SetBasicAuth(username, password)
	res, err := client.Do(req)
	defer res.Body.Close()

	if err != nil {
		log.Fatal("Error: %s", err)
	}

	if res.StatusCode != http.StatusOK {
		log.Fatal("Response status: ", res.Status)
	}

	body, err := ioutil.ReadAll(res.Body)

	if err != nil {
		log.Fatal("Error: %s", err)
	}

	cr := new(vend.ConfigResponse)
	c := new(vend.Config)

	if err != nil {
		log.Fatal(err)
	}

	err = json.Unmarshal(body, &cr)

	if err != nil {
		log.Fatal(err)
	}

	c = cr.Config

	fmt.Printf("Retailer name: %+v\n", *c.RetailerName)
	fmt.Printf("Retailer id: %+v\n", *c.RetailerId)
	fmt.Printf("Account state: %+v\n", *c.AccountState)
	fmt.Printf("User name: %+v\n", *c.UserName)
	fmt.Printf("Currency name:  %+v\n", *c.Currency)
}
<commit_msg>First draft of the ProductService<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"

	"github.com/pzurek/go-vend/vend"
)

// to run:
// go run vend.go <store name> <username> <password>
func main() {
	args := os.Args
	storeName := args[1]
	username := args[2]
	password := args[3]

	baseUrl := fmt.Sprintf("https://%s.vendhq.com/api/", storeName)

	client := &http.Client{}
	req, err := http.NewRequest("GET", baseUrl+"config", nil)
	req.SetBasicAuth(username, password)
	res, err := client.Do(req)
	defer res.Body.Close()

	if err != nil {
		log.Fatal("Error: %s", err)
	}

	if res.StatusCode != http.StatusOK {
		log.Fatal("Response status: ", res.Status)
	}

	body, err := ioutil.ReadAll(res.Body)

	if err != nil {
		log.Fatal("Error: %s", err)
	}

	cr := new(vend.ConfigResponse)
	c := new(vend.Config)

	if err != nil {
		log.Fatal(err)
	}

	err = json.Unmarshal(body, &cr)

	if err != nil {
		log.Fatal(err)
	}

	c = cr.Config

	fmt.Printf("Retailer name: %+v\n", *c.RetailerName)
	fmt.Printf("Retailer id: %+v\n", *c.RetailerId)
	fmt.Printf("Account state: %+v\n", *c.AccountState)
	fmt.Printf("User name: %+v\n", *c.UserName)
	fmt.Printf("Currency name:  %+v\n", *c.Currency)
}
<|endoftext|>


<commit_before>/*
Copyright 2014 Google Inc. All rights reserved.

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 examples_test

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"testing"

	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
	_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
	"github.com/golang/glog"
)

func validateObject(obj interface{}) (errors []error) {
	switch t := obj.(type) {
	case *api.ReplicationController:
		errors = api.ValidateManifest(&t.DesiredState.PodTemplate.DesiredState.Manifest)
	case *api.ReplicationControllerList:
		for i := range t.Items {
			errors = append(errors, validateObject(&t.Items[i])...)
		}
	case *api.Service:
		errors = api.ValidateService(t)
	case *api.ServiceList:
		for i := range t.Items {
			errors = append(errors, validateObject(&t.Items[i])...)
		}
	case *api.Pod:
		errors = api.ValidateManifest(&t.DesiredState.Manifest)
	case *api.PodList:
		for i := range t.Items {
			errors = append(errors, validateObject(&t.Items[i])...)
		}
	default:
		return []error{fmt.Errorf("no validation defined for %#v", obj)}
	}
	return errors
}

func walkJSONFiles(inDir string, fn func(name, path string, data []byte)) error {
	err := filepath.Walk(inDir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if info.IsDir() && path != inDir {
			return filepath.SkipDir
		}
		name := filepath.Base(path)
		ext := filepath.Ext(name)
		if ext != "" {
			name = name[:len(name)-len(ext)]
		}
		if ext != ".json" {
			return nil
		}
		glog.Infof("Testing %s", path)
		data, err := ioutil.ReadFile(path)
		if err != nil {
			return err
		}
		fn(name, path, data)
		return nil
	})
	return err
}

func TestApiExamples(t *testing.T) {
	expected := map[string]interface{}{
		"controller":       &api.ReplicationController{},
		"controller-list":  &api.ReplicationControllerList{},
		"pod":              &api.Pod{},
		"pod-list":         &api.PodList{},
		"service":          &api.Service{},
		"external-service": &api.Service{},
		"service-list":     &api.ServiceList{},
	}

	tested := 0
	err := walkJSONFiles("../api/examples", func(name, path string, data []byte) {
		expectedType, found := expected[name]
		if !found {
			t.Errorf("%s does not have a test case defined", path)
			return
		}
		tested += 1
		if err := api.DecodeInto(data, expectedType); err != nil {
			t.Errorf("%s did not decode correctly: %v\n%s", path, err, string(data))
			return
		}
		if errors := validateObject(expectedType); len(errors) > 0 {
			t.Errorf("%s did not validate correctly: %v", path, errors)
		}
	})
	if err != nil {
		t.Errorf("Expected no error, Got %v", err)
	}
	if tested != len(expected) {
		t.Errorf("Expected %d examples, Got %d", len(expected), tested)
	}
}

func TestExamples(t *testing.T) {
	expected := map[string]interface{}{
		"frontend-controller":    &api.ReplicationController{},
		"redis-slave-controller": &api.ReplicationController{},
		"redis-master":           &api.Pod{},
		"frontend-service":       &api.Service{},
		"redis-master-service":   &api.Service{},
		"redis-slave-service":    &api.Service{},
	}

	tested := 0
	err := walkJSONFiles("../examples/guestbook", func(name, path string, data []byte) {
		expectedType, found := expected[name]
		if !found {
			t.Errorf("%s does not have a test case defined", path)
			return
		}
		tested += 1
		if err := api.DecodeInto(data, expectedType); err != nil {
			t.Errorf("%s did not decode correctly: %v\n%s", path, err, string(data))
			return
		}
		if errors := validateObject(expectedType); len(errors) > 0 {
			t.Errorf("%s did not validate correctly: %v", path, errors)
		}
	})
	if err != nil {
		t.Errorf("Expected no error, Got %v", err)
	}
	if tested != len(expected) {
		t.Errorf("Expected %d examples, Got %d", len(expected), tested)
	}
}

var jsonRegexp = regexp.MustCompile("(?ms)^```\\w*\\n(\\{.+?\\})\\w*\\n^```")

func TestReadme(t *testing.T) {
	path := "../README.md"
	data, err := ioutil.ReadFile(path)
	if err != nil {
		t.Fatalf("Unable to read file: %v", err)
	}

	match := jsonRegexp.FindStringSubmatch(string(data))
	if match == nil {
		return
	}
	for _, json := range match[1:] {
		expectedType := &api.Pod{}
		if err := api.DecodeInto([]byte(json), expectedType); err != nil {
			t.Errorf("%s did not decode correctly: %v\n%s", path, err, string(data))
			return
		}
		if errors := validateObject(expectedType); len(errors) > 0 {
			t.Errorf("%s did not validate correctly: %v", path, errors)
		}
		encoded, err := api.Encode(expectedType)
		if err != nil {
			t.Errorf("Could not encode object: %v", err)
			continue
		}
		t.Logf("Found pod %s\n%s", json, encoded)
	}
}
<commit_msg>Propagate rename; tests pass again.<commit_after>/*
Copyright 2014 Google Inc. All rights reserved.

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 examples_test

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"testing"

	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
	_ "github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/apitools"
	"github.com/golang/glog"
)

func validateObject(obj interface{}) (errors []error) {
	switch t := obj.(type) {
	case *api.ReplicationController:
		errors = validation.ValidateManifest(&t.DesiredState.PodTemplate.DesiredState.Manifest)
	case *api.ReplicationControllerList:
		for i := range t.Items {
			errors = append(errors, validateObject(&t.Items[i])...)
		}
	case *api.Service:
		errors = validation.ValidateService(t)
	case *api.ServiceList:
		for i := range t.Items {
			errors = append(errors, validateObject(&t.Items[i])...)
		}
	case *api.Pod:
		errors = validation.ValidateManifest(&t.DesiredState.Manifest)
	case *api.PodList:
		for i := range t.Items {
			errors = append(errors, validateObject(&t.Items[i])...)
		}
	default:
		return []error{fmt.Errorf("no validation defined for %#v", obj)}
	}
	return errors
}

func walkJSONFiles(inDir string, fn func(name, path string, data []byte)) error {
	err := filepath.Walk(inDir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if info.IsDir() && path != inDir {
			return filepath.SkipDir
		}
		name := filepath.Base(path)
		ext := filepath.Ext(name)
		if ext != "" {
			name = name[:len(name)-len(ext)]
		}
		if ext != ".json" {
			return nil
		}
		glog.Infof("Testing %s", path)
		data, err := ioutil.ReadFile(path)
		if err != nil {
			return err
		}
		fn(name, path, data)
		return nil
	})
	return err
}

func TestApiExamples(t *testing.T) {
	expected := map[string]interface{}{
		"controller":       &api.ReplicationController{},
		"controller-list":  &api.ReplicationControllerList{},
		"pod":              &api.Pod{},
		"pod-list":         &api.PodList{},
		"service":          &api.Service{},
		"external-service": &api.Service{},
		"service-list":     &api.ServiceList{},
	}

	tested := 0
	err := walkJSONFiles("../api/examples", func(name, path string, data []byte) {
		expectedType, found := expected[name]
		if !found {
			t.Errorf("%s does not have a test case defined", path)
			return
		}
		tested += 1
		if err := apitools.DecodeInto(data, expectedType); err != nil {
			t.Errorf("%s did not decode correctly: %v\n%s", path, err, string(data))
			return
		}
		if errors := validateObject(expectedType); len(errors) > 0 {
			t.Errorf("%s did not validate correctly: %v", path, errors)
		}
	})
	if err != nil {
		t.Errorf("Expected no error, Got %v", err)
	}
	if tested != len(expected) {
		t.Errorf("Expected %d examples, Got %d", len(expected), tested)
	}
}

func TestExamples(t *testing.T) {
	expected := map[string]interface{}{
		"frontend-controller":    &api.ReplicationController{},
		"redis-slave-controller": &api.ReplicationController{},
		"redis-master":           &api.Pod{},
		"frontend-service":       &api.Service{},
		"redis-master-service":   &api.Service{},
		"redis-slave-service":    &api.Service{},
	}

	tested := 0
	err := walkJSONFiles("../examples/guestbook", func(name, path string, data []byte) {
		expectedType, found := expected[name]
		if !found {
			t.Errorf("%s does not have a test case defined", path)
			return
		}
		tested += 1
		if err := apitools.DecodeInto(data, expectedType); err != nil {
			t.Errorf("%s did not decode correctly: %v\n%s", path, err, string(data))
			return
		}
		if errors := validateObject(expectedType); len(errors) > 0 {
			t.Errorf("%s did not validate correctly: %v", path, errors)
		}
	})
	if err != nil {
		t.Errorf("Expected no error, Got %v", err)
	}
	if tested != len(expected) {
		t.Errorf("Expected %d examples, Got %d", len(expected), tested)
	}
}

var jsonRegexp = regexp.MustCompile("(?ms)^```\\w*\\n(\\{.+?\\})\\w*\\n^```")

func TestReadme(t *testing.T) {
	path := "../README.md"
	data, err := ioutil.ReadFile(path)
	if err != nil {
		t.Fatalf("Unable to read file: %v", err)
	}

	match := jsonRegexp.FindStringSubmatch(string(data))
	if match == nil {
		return
	}
	for _, json := range match[1:] {
		expectedType := &api.Pod{}
		if err := apitools.DecodeInto([]byte(json), expectedType); err != nil {
			t.Errorf("%s did not decode correctly: %v\n%s", path, err, string(data))
			return
		}
		if errors := validateObject(expectedType); len(errors) > 0 {
			t.Errorf("%s did not validate correctly: %v", path, errors)
		}
		encoded, err := apitools.Encode(expectedType)
		if err != nil {
			t.Errorf("Could not encode object: %v", err)
			continue
		}
		t.Logf("Found pod %s\n%s", json, encoded)
	}
}
<|endoftext|>