<commit_before>package config

import (
	"context"
	"fmt"

	"github.com/libp2p/go-libp2p-core/connmgr"
	"github.com/libp2p/go-libp2p-core/crypto"
	"github.com/libp2p/go-libp2p-core/host"
	"github.com/libp2p/go-libp2p-core/metrics"
	"github.com/libp2p/go-libp2p-core/network"
	"github.com/libp2p/go-libp2p-core/peer"
	"github.com/libp2p/go-libp2p-core/peerstore"
	"github.com/libp2p/go-libp2p-core/pnet"
	"github.com/libp2p/go-libp2p-core/routing"

	bhost "github.com/libp2p/go-libp2p/p2p/host/basic"
	relay "github.com/libp2p/go-libp2p/p2p/host/relay"
	routed "github.com/libp2p/go-libp2p/p2p/host/routed"

	circuit "github.com/libp2p/go-libp2p-circuit"
	discovery "github.com/libp2p/go-libp2p-discovery"
	swarm "github.com/libp2p/go-libp2p-swarm"
	tptu "github.com/libp2p/go-libp2p-transport-upgrader"

	logging "github.com/ipfs/go-log"
	filter "github.com/libp2p/go-maddr-filter"
	ma "github.com/multiformats/go-multiaddr"
)

var log = logging.Logger("p2p-config")

// AddrsFactory is a function that takes a set of multiaddrs we're listening on and
// returns the set of multiaddrs we should advertise to the network.
type AddrsFactory = bhost.AddrsFactory

// NATManagerC is a NATManager constructor.
type NATManagerC func(network.Network) bhost.NATManager

type RoutingC func(host.Host) (routing.PeerRouting, error)

// Config describes a set of settings for a libp2p node
//
// This is *not* a stable interface. Use the options defined in the root
// package.
type Config struct {
	// UserAgent is the identifier this node will send to other peers when
	// identifying itself, e.g. via the identify protocol.
	//
	// Set it via the UserAgent option function.
	UserAgent string

	PeerKey crypto.PrivKey

	Transports         []TptC
	Muxers             []MsMuxC
	SecurityTransports []MsSecC
	Insecure           bool
	Protector          pnet.Protector

	RelayCustom bool
	Relay       bool
	RelayOpts   []circuit.RelayOpt

	ListenAddrs  []ma.Multiaddr
	AddrsFactory bhost.AddrsFactory
	Filters      *filter.Filters

	ConnManager connmgr.ConnManager
	NATManager  NATManagerC
	Peerstore   peerstore.Peerstore
	Reporter    metrics.Reporter

	DisablePing bool

	Routing RoutingC

	EnableAutoRelay bool
	StaticRelays    []peer.AddrInfo
}

// NewNode constructs a new libp2p Host from the Config.
//
// This function consumes the config. Do not reuse it (really!).
func (cfg *Config) NewNode(ctx context.Context) (host.Host, error) {
	// Check this early. Prevents us from even *starting* without verifying this.
	if pnet.ForcePrivateNetwork && cfg.Protector == nil {
		log.Error("tried to create a libp2p node with no Private" +
			" Network Protector but usage of Private Networks" +
			" is forced by the enviroment")
		// Note: This is *also* checked the upgrader itself so it'll be
		// enforced even *if* you don't use the libp2p constructor.
		return nil, pnet.ErrNotInPrivateNetwork
	}

	if cfg.PeerKey == nil {
		return nil, fmt.Errorf("no peer key specified")
	}

	// Obtain Peer ID from public key
	pid, err := peer.IDFromPublicKey(cfg.PeerKey.GetPublic())
	if err != nil {
		return nil, err
	}

	if cfg.Peerstore == nil {
		return nil, fmt.Errorf("no peerstore specified")
	}

	if err := cfg.Peerstore.AddPrivKey(pid, cfg.PeerKey); err != nil {
		return nil, err
	}
	if err := cfg.Peerstore.AddPubKey(pid, cfg.PeerKey.GetPublic()); err != nil {
		return nil, err
	}

	// TODO: Make the swarm implementation configurable.
	swrm := swarm.NewSwarm(ctx, pid, cfg.Peerstore, cfg.Reporter)
	if cfg.Filters != nil {
		swrm.Filters = cfg.Filters
	}

	h, err := bhost.NewHost(ctx, swrm, &bhost.HostOpts{
		ConnManager:  cfg.ConnManager,
		AddrsFactory: cfg.AddrsFactory,
		NATManager:   cfg.NATManager,
		EnablePing:   !cfg.DisablePing,
		UserAgent:    cfg.UserAgent,
	})

	if err != nil {
		swrm.Close()
		return nil, err
	}

	if cfg.Relay {
		// If we've enabled the relay, we should filter out relay
		// addresses by default.
		//
		// TODO: We shouldn't be doing this here.
		oldFactory := h.AddrsFactory
		h.AddrsFactory = func(addrs []ma.Multiaddr) []ma.Multiaddr {
			return oldFactory(relay.Filter(addrs))
		}
	}

	upgrader := new(tptu.Upgrader)
	upgrader.Protector = cfg.Protector
	upgrader.Filters = swrm.Filters
	if cfg.Insecure {
		upgrader.Secure = makeInsecureTransport(pid, cfg.PeerKey)
	} else {
		upgrader.Secure, err = makeSecurityTransport(h, cfg.SecurityTransports)
		if err != nil {
			h.Close()
			return nil, err
		}
	}

	upgrader.Muxer, err = makeMuxer(h, cfg.Muxers)
	if err != nil {
		h.Close()
		return nil, err
	}

	tpts, err := makeTransports(h, upgrader, cfg.Transports)
	if err != nil {
		h.Close()
		return nil, err
	}
	for _, t := range tpts {
		err = swrm.AddTransport(t)
		if err != nil {
			h.Close()
			return nil, err
		}
	}

	if cfg.Relay {
		err := circuit.AddRelayTransport(swrm.Context(), h, upgrader, cfg.RelayOpts...)
		if err != nil {
			h.Close()
			return nil, err
		}
	}

	// TODO: This method succeeds if listening on one address succeeds. We
	// should probably fail if listening on *any* addr fails.
	if err := h.Network().Listen(cfg.ListenAddrs...); err != nil {
		h.Close()
		return nil, err
	}

	// Configure routing and autorelay
	var router routing.PeerRouting
	if cfg.Routing != nil {
		router, err = cfg.Routing(h)
		if err != nil {
			h.Close()
			return nil, err
		}
	}

	if cfg.EnableAutoRelay {
		if !cfg.Relay {
			h.Close()
			return nil, fmt.Errorf("cannot enable autorelay; relay is not enabled")
		}

		if router == nil {
			h.Close()
			return nil, fmt.Errorf("cannot enable autorelay; no routing for discovery")
		}

		crouter, ok := router.(routing.ContentRouting)
		if !ok {
			h.Close()
			return nil, fmt.Errorf("cannot enable autorelay; no suitable routing for discovery")
		}

		discovery := discovery.NewRoutingDiscovery(crouter)

		hop := false
		for _, opt := range cfg.RelayOpts {
			if opt == circuit.OptHop {
				hop = true
				break
			}
		}

		if hop {
			// advertise ourselves
			relay.Advertise(ctx, discovery)
		} else {
			_ = relay.NewAutoRelay(swrm.Context(), h, discovery, router, cfg.StaticRelays)
		}
	}

	// start the host background tasks
	h.Start()

	if router != nil {
		return routed.Wrap(h, router), nil
	}
	return h, nil
}

// Option is a libp2p config option that can be given to the libp2p constructor
// (`libp2p.New`).
type Option func(cfg *Config) error

// Apply applies the given options to the config, returning the first error
// encountered (if any).
func (cfg *Config) Apply(opts ...Option) error {
	for _, opt := range opts {
		if opt == nil {
			continue
		}
		if err := opt(cfg); err != nil {
			return err
		}
	}
	return nil
}
<commit_msg>fix: can enable autorelay without content routing as long as there are static relays configured<commit_after>package config

import (
	"context"
	"fmt"

	"github.com/libp2p/go-libp2p-core/connmgr"
	"github.com/libp2p/go-libp2p-core/crypto"
	"github.com/libp2p/go-libp2p-core/host"
	"github.com/libp2p/go-libp2p-core/metrics"
	"github.com/libp2p/go-libp2p-core/network"
	"github.com/libp2p/go-libp2p-core/peer"
	"github.com/libp2p/go-libp2p-core/peerstore"
	"github.com/libp2p/go-libp2p-core/pnet"
	"github.com/libp2p/go-libp2p-core/routing"

	bhost "github.com/libp2p/go-libp2p/p2p/host/basic"
	relay "github.com/libp2p/go-libp2p/p2p/host/relay"
	routed "github.com/libp2p/go-libp2p/p2p/host/routed"

	circuit "github.com/libp2p/go-libp2p-circuit"
	discovery "github.com/libp2p/go-libp2p-discovery"
	swarm "github.com/libp2p/go-libp2p-swarm"
	tptu "github.com/libp2p/go-libp2p-transport-upgrader"

	logging "github.com/ipfs/go-log"
	filter "github.com/libp2p/go-maddr-filter"
	ma "github.com/multiformats/go-multiaddr"
)

var log = logging.Logger("p2p-config")

// AddrsFactory is a function that takes a set of multiaddrs we're listening on and
// returns the set of multiaddrs we should advertise to the network.
type AddrsFactory = bhost.AddrsFactory

// NATManagerC is a NATManager constructor.
type NATManagerC func(network.Network) bhost.NATManager

type RoutingC func(host.Host) (routing.PeerRouting, error)

// Config describes a set of settings for a libp2p node
//
// This is *not* a stable interface. Use the options defined in the root
// package.
type Config struct {
	// UserAgent is the identifier this node will send to other peers when
	// identifying itself, e.g. via the identify protocol.
	//
	// Set it via the UserAgent option function.
	UserAgent string

	PeerKey crypto.PrivKey

	Transports         []TptC
	Muxers             []MsMuxC
	SecurityTransports []MsSecC
	Insecure           bool
	Protector          pnet.Protector

	RelayCustom bool
	Relay       bool
	RelayOpts   []circuit.RelayOpt

	ListenAddrs  []ma.Multiaddr
	AddrsFactory bhost.AddrsFactory
	Filters      *filter.Filters

	ConnManager connmgr.ConnManager
	NATManager  NATManagerC
	Peerstore   peerstore.Peerstore
	Reporter    metrics.Reporter

	DisablePing bool

	Routing RoutingC

	EnableAutoRelay bool
	StaticRelays    []peer.AddrInfo
}

// NewNode constructs a new libp2p Host from the Config.
//
// This function consumes the config. Do not reuse it (really!).
func (cfg *Config) NewNode(ctx context.Context) (host.Host, error) {
	// Check this early. Prevents us from even *starting* without verifying this.
	if pnet.ForcePrivateNetwork && cfg.Protector == nil {
		log.Error("tried to create a libp2p node with no Private" +
			" Network Protector but usage of Private Networks" +
			" is forced by the enviroment")
		// Note: This is *also* checked the upgrader itself so it'll be
		// enforced even *if* you don't use the libp2p constructor.
		return nil, pnet.ErrNotInPrivateNetwork
	}

	if cfg.PeerKey == nil {
		return nil, fmt.Errorf("no peer key specified")
	}

	// Obtain Peer ID from public key
	pid, err := peer.IDFromPublicKey(cfg.PeerKey.GetPublic())
	if err != nil {
		return nil, err
	}

	if cfg.Peerstore == nil {
		return nil, fmt.Errorf("no peerstore specified")
	}

	if err := cfg.Peerstore.AddPrivKey(pid, cfg.PeerKey); err != nil {
		return nil, err
	}
	if err := cfg.Peerstore.AddPubKey(pid, cfg.PeerKey.GetPublic()); err != nil {
		return nil, err
	}

	// TODO: Make the swarm implementation configurable.
	swrm := swarm.NewSwarm(ctx, pid, cfg.Peerstore, cfg.Reporter)
	if cfg.Filters != nil {
		swrm.Filters = cfg.Filters
	}

	h, err := bhost.NewHost(ctx, swrm, &bhost.HostOpts{
		ConnManager:  cfg.ConnManager,
		AddrsFactory: cfg.AddrsFactory,
		NATManager:   cfg.NATManager,
		EnablePing:   !cfg.DisablePing,
		UserAgent:    cfg.UserAgent,
	})

	if err != nil {
		swrm.Close()
		return nil, err
	}

	if cfg.Relay {
		// If we've enabled the relay, we should filter out relay
		// addresses by default.
		//
		// TODO: We shouldn't be doing this here.
		oldFactory := h.AddrsFactory
		h.AddrsFactory = func(addrs []ma.Multiaddr) []ma.Multiaddr {
			return oldFactory(relay.Filter(addrs))
		}
	}

	upgrader := new(tptu.Upgrader)
	upgrader.Protector = cfg.Protector
	upgrader.Filters = swrm.Filters
	if cfg.Insecure {
		upgrader.Secure = makeInsecureTransport(pid, cfg.PeerKey)
	} else {
		upgrader.Secure, err = makeSecurityTransport(h, cfg.SecurityTransports)
		if err != nil {
			h.Close()
			return nil, err
		}
	}

	upgrader.Muxer, err = makeMuxer(h, cfg.Muxers)
	if err != nil {
		h.Close()
		return nil, err
	}

	tpts, err := makeTransports(h, upgrader, cfg.Transports)
	if err != nil {
		h.Close()
		return nil, err
	}
	for _, t := range tpts {
		err = swrm.AddTransport(t)
		if err != nil {
			h.Close()
			return nil, err
		}
	}

	if cfg.Relay {
		err := circuit.AddRelayTransport(swrm.Context(), h, upgrader, cfg.RelayOpts...)
		if err != nil {
			h.Close()
			return nil, err
		}
	}

	// TODO: This method succeeds if listening on one address succeeds. We
	// should probably fail if listening on *any* addr fails.
	if err := h.Network().Listen(cfg.ListenAddrs...); err != nil {
		h.Close()
		return nil, err
	}

	// Configure routing and autorelay
	var router routing.PeerRouting
	if cfg.Routing != nil {
		router, err = cfg.Routing(h)
		if err != nil {
			h.Close()
			return nil, err
		}
	}

	if cfg.EnableAutoRelay {
		if !cfg.Relay {
			h.Close()
			return nil, fmt.Errorf("cannot enable autorelay; relay is not enabled")
		}

		hop := false
		for _, opt := range cfg.RelayOpts {
			if opt == circuit.OptHop {
				hop = true
				break
			}
		}

		if !hop && len(cfg.StaticRelays) > 0 {
			_ = relay.NewAutoRelay(swrm.Context(), h, nil, router, cfg.StaticRelays)
		} else {
			if router == nil {
				h.Close()
				return nil, fmt.Errorf("cannot enable autorelay; no routing for discovery")
			}

			crouter, ok := router.(routing.ContentRouting)
			if !ok {
				h.Close()
				return nil, fmt.Errorf("cannot enable autorelay; no suitable routing for discovery")
			}

			discovery := discovery.NewRoutingDiscovery(crouter)

			if hop {
				// advertise ourselves
				relay.Advertise(ctx, discovery)
			} else {
				_ = relay.NewAutoRelay(swrm.Context(), h, discovery, router, cfg.StaticRelays)
			}
		}
	}

	// start the host background tasks
	h.Start()

	if router != nil {
		return routed.Wrap(h, router), nil
	}
	return h, nil
}

// Option is a libp2p config option that can be given to the libp2p constructor
// (`libp2p.New`).
type Option func(cfg *Config) error

// Apply applies the given options to the config, returning the first error
// encountered (if any).
func (cfg *Config) Apply(opts ...Option) error {
	for _, opt := range opts {
		if opt == nil {
			continue
		}
		if err := opt(cfg); err != nil {
			return err
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package config

import (
	"flag"
	"fmt"
	"github.com/BurntSushi/toml"
	"os"
	"path/filepath"
)

func init() {
	flag.Var(&nodes, "n", "list of etcd nodes")
	flag.StringVar(&confdir, "c", "/etc/confd", "confd config directory")
	flag.StringVar(&confFile, "C", "/etc/confd/confd.toml", "confd config file")
	flag.IntVar(&interval, "i", 600, "etcd polling interval")
	flag.StringVar(&prefix, "p", "/", "etcd key path prefix")
	flag.BoolVar(&onetime, "onetime", false, "run once and exit")
}

var (
	config   Config
	confFile = "/etc/confd/confd.toml"
	nodes    Nodes
	confdir  string
	interval int
	prefix   string
	onetime  bool
)

type Nodes []string

func (n *Nodes) String() string {
	return fmt.Sprintf("%d", *n)
}

func (n *Nodes) Set(node string) error {
	*n = append(*n, node)
	return nil
}

type Config struct {
	Confd confd
}

type confd struct {
	ConfDir   string
	Interval  int
	Prefix    string
	EtcdNodes []string `toml:"etcd_nodes"`
}

func ConfigDir() string {
	return filepath.Join(config.Confd.ConfDir, "conf.d")
}

func EtcdNodes() []string {
	return config.Confd.EtcdNodes
}

func Interval() int {
	return config.Confd.Interval
}

func Onetime() bool {
	return onetime
}

func Prefix() string {
	return config.Confd.Prefix
}

func TemplateDir() string {
	return filepath.Join(config.Confd.ConfDir, "templates")
}

func SetConfFile(path string) {
	confFile = path
}

func setDefaults() {
	config = Config{
		Confd: confd{
			ConfDir:   "/etc/confd/conf.d",
			Interval:  600,
			Prefix:    "/",
			EtcdNodes: []string{"http://127.0.0.1:4001"},
		},
	}
}

func loadConfFile() error {
	if IsFileExist(confFile) {
		_, err := toml.DecodeFile(confFile, &config)
		if err != nil {
			return err
		}
	}
	return nil
}

func override(f *flag.Flag) {
	switch f.Name {
	case "c":
		config.Confd.ConfDir = confdir
	case "i":
		config.Confd.Interval = interval
	case "n":
		config.Confd.EtcdNodes = nodes
	case "p":
		config.Confd.Prefix = prefix
	}
}

func overrideConfig() {
	flag.Visit(override)
}

func InitConfig() error {
	setDefaults()
	if err := loadConfFile(); err != nil {
		return err
	}
	overrideConfig()
	return nil
}

func IsFileExist(fpath string) bool {
	if _, err := os.Stat(fpath); os.IsNotExist(err) {
		return false
	}
	return true
}
<commit_msg>Add comments to the confd/config package and remove unused SetConfFile()<commit_after>// Copyright (c) 2013 Kelsey Hightower. All rights reserved.
// Use of this source code is governed by the Apache License, Version 2.0
// that can be found in the LICENSE file.

/*
Package config provides global configuration settings for confd.
*/
package config

import (
	"flag"
	"fmt"
	"github.com/BurntSushi/toml"
	"os"
	"path/filepath"
)

func init() {
	flag.Var(&nodes, "n", "list of etcd nodes")
	flag.StringVar(&confdir, "c", "/etc/confd", "confd config directory")
	flag.StringVar(&confFile, "C", "/etc/confd/confd.toml", "confd config file")
	flag.IntVar(&interval, "i", 600, "etcd polling interval")
	flag.StringVar(&prefix, "p", "/", "etcd key path prefix")
	flag.BoolVar(&onetime, "onetime", false, "run once and exit")
}

var (
	config   Config
	confFile = "/etc/confd/confd.toml" // default confd configuration file
	nodes    Nodes
	confdir  string
	interval int
	prefix   string
	onetime  bool
)

// Nodes is a custom flag Var representing a list of etcd nodes. We use a custom
// Var to allow us to define more than one etcd node from the command line, and
// collect the results in a single value.
type Nodes []string

func (n *Nodes) String() string {
	return fmt.Sprintf("%d", *n)
}

// Set appends the node to the etcd node list.
func (n *Nodes) Set(node string) error {
	*n = append(*n, node)
	return nil
}

// Config represents the confd configuration settings.
type Config struct {
	Confd confd
}

// confd represents the parsed configuration settings.
type confd struct {
	ConfDir   string
	Interval  int
	Prefix    string
	EtcdNodes []string `toml:"etcd_nodes"`
}

// ConfigDir returns the path to the confd config dir.
func ConfigDir() string {
	return filepath.Join(config.Confd.ConfDir, "conf.d")
}

// EtcdNodes returns a list of etcd node url strings.
// For example: ["http://203.0.113.30:4001"]
func EtcdNodes() []string {
	return config.Confd.EtcdNodes
}

// Interval returns the number of seconds to wait between configuration runs.
func Interval() int {
	return config.Confd.Interval
}

// Onetime returns true if the -onetime flag was set on the command line.
func Onetime() bool {
	return onetime
}

// Prefix returns the etcd key prefix to use when querying etcd.
func Prefix() string {
	return config.Confd.Prefix
}

// TemplateDir returns the path to the directory of config file templates.
func TemplateDir() string {
	return filepath.Join(config.Confd.ConfDir, "templates")
}

func setDefaults() {
	config = Config{
		Confd: confd{
			ConfDir:   "/etc/confd/conf.d",
			Interval:  600,
			Prefix:    "/",
			EtcdNodes: []string{"http://127.0.0.1:4001"},
		},
	}
}

func loadConfFile() error {
	if IsFileExist(confFile) {
		_, err := toml.DecodeFile(confFile, &config)
		if err != nil {
			return err
		}
	}
	return nil
}

func override(f *flag.Flag) {
	switch f.Name {
	case "c":
		config.Confd.ConfDir = confdir
	case "i":
		config.Confd.Interval = interval
	case "n":
		config.Confd.EtcdNodes = nodes
	case "p":
		config.Confd.Prefix = prefix
	}
}

func overrideConfig() {
	flag.Visit(override)
}

func InitConfig() error {
	setDefaults()
	if err := loadConfFile(); err != nil {
		return err
	}
	overrideConfig()
	return nil
}

func IsFileExist(fpath string) bool {
	if _, err := os.Stat(fpath); os.IsNotExist(err) {
		return false
	}
	return true
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 Pagoda Box Inc.
//
// This Source Code Form is subject to the terms of the Mozilla Public License,
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
// obtain one at http://mozilla.org/MPL/2.0/.

//
package config

import (
	"errors"
	"io/ioutil"
	"net"
	"net/http"
	"strings"

	"github.com/jcelliott/lumber"

	"github.com/nanobox-io/nanobox-logtap"
	"github.com/nanopack/mist/core"
)

//
var (
	app         string
	LogtapHost  string
	Ports       map[string]string
	IP          string
	MountFolder string
	DockerMount string

	Log        lumber.Logger
	Logtap     *logtap.Logtap
	Mist       *mist.Mist
	LogHandler http.HandlerFunc
)

//
func init() {
	MountFolder = "/vagrant/"
	DockerMount = "/mnt/"
	// create an error object
	var err error
	levelEnv := os.Getenv("NANOBOX_LOGLEVEL")
	if levelEnv == "" {
		levelEnv = "INFO"
	}
	Log = lumber.NewConsoleLogger(lumber.LvlInt(levelEnv))

	//
	Ports = map[string]string{
		"api":    ":1757",
		"logtap": ":514",
		"mist":   ":1445",
		"router": "60000",
	}

	IP, err = externalIP()
	if err != nil {
		Log.Error("error: %s\n", err.Error())
	}

	LogtapHost = IP

	Mist = mist.New()
	Logtap = logtap.New(Log)
}

//
func externalIP() (string, error) {
	ifaces, err := net.Interfaces()
	if err != nil {
		return "", err
	}
	for _, iface := range ifaces {
		if iface.Flags&net.FlagUp == 0 {
			continue // interface down
		}
		if iface.Flags&net.FlagLoopback != 0 {
			continue // loopback interface
		}
		addrs, err := iface.Addrs()
		if err != nil {
			return "", err
		}
		for _, addr := range addrs {
			var ip net.IP
			switch v := addr.(type) {
			case *net.IPNet:
				ip = v.IP
			case *net.IPAddr:
				ip = v.IP
			}
			if ip == nil || ip.IsLoopback() {
				continue
			}
			ip = ip.To4()
			if ip == nil {
				continue // not an ipv4 address
			}
			if strings.HasPrefix(ip.String(), "10") {
				continue
			}
			return ip.String(), nil
		}
	}
	return "", errors.New("are you connected to the network?")
}

//
func App() string {
	if app != "" {
		return app
	}
	Log.Error("appfolder: ", MountFolder+"code/")

	files, err := ioutil.ReadDir(MountFolder + "code/")
	if err != nil {
		Log.Error(err.Error())
		return ""
	}

	if len(files) < 1 || !files[0].IsDir() {
		Log.Error("There is no code in your " + MountFolder + "code/ folder")
		return ""
	}
	app = files[0].Name()
	return app
}
<commit_msg>include missing dependencies<commit_after>// Copyright (c) 2014 Pagoda Box Inc.
//
// This Source Code Form is subject to the terms of the Mozilla Public License,
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
// obtain one at http://mozilla.org/MPL/2.0/.

//
package config

import (
	"errors"
	"io/ioutil"
	"net"
	"net/http"
	"strings"
	"os"

	"github.com/jcelliott/lumber"

	"github.com/nanobox-io/nanobox-logtap"
	"github.com/nanopack/mist/core"
)

//
var (
	app         string
	LogtapHost  string
	Ports       map[string]string
	IP          string
	MountFolder string
	DockerMount string

	Log        lumber.Logger
	Logtap     *logtap.Logtap
	Mist       *mist.Mist
	LogHandler http.HandlerFunc
)

//
func init() {
	MountFolder = "/vagrant/"
	DockerMount = "/mnt/"
	// create an error object
	var err error
	levelEnv := os.Getenv("NANOBOX_LOGLEVEL")
	if levelEnv == "" {
		levelEnv = "INFO"
	}
	Log = lumber.NewConsoleLogger(lumber.LvlInt(levelEnv))

	//
	Ports = map[string]string{
		"api":    ":1757",
		"logtap": ":514",
		"mist":   ":1445",
		"router": "60000",
	}

	IP, err = externalIP()
	if err != nil {
		Log.Error("error: %s\n", err.Error())
	}

	LogtapHost = IP

	Mist = mist.New()
	Logtap = logtap.New(Log)
}

//
func externalIP() (string, error) {
	ifaces, err := net.Interfaces()
	if err != nil {
		return "", err
	}
	for _, iface := range ifaces {
		if iface.Flags&net.FlagUp == 0 {
			continue // interface down
		}
		if iface.Flags&net.FlagLoopback != 0 {
			continue // loopback interface
		}
		addrs, err := iface.Addrs()
		if err != nil {
			return "", err
		}
		for _, addr := range addrs {
			var ip net.IP
			switch v := addr.(type) {
			case *net.IPNet:
				ip = v.IP
			case *net.IPAddr:
				ip = v.IP
			}
			if ip == nil || ip.IsLoopback() {
				continue
			}
			ip = ip.To4()
			if ip == nil {
				continue // not an ipv4 address
			}
			if strings.HasPrefix(ip.String(), "10") {
				continue
			}
			return ip.String(), nil
		}
	}
	return "", errors.New("are you connected to the network?")
}

//
func App() string {
	if app != "" {
		return app
	}
	Log.Error("appfolder: ", MountFolder+"code/")

	files, err := ioutil.ReadDir(MountFolder + "code/")
	if err != nil {
		Log.Error(err.Error())
		return ""
	}

	if len(files) < 1 || !files[0].IsDir() {
		Log.Error("There is no code in your " + MountFolder + "code/ folder")
		return ""
	}
	app = files[0].Name()
	return app
}
<|endoftext|>


<commit_before>package config

import (
	"github.com/mediocregopher/flagconfig"
	"log"
	"strings"
)

var (
	TCPAddr     string
	UDPAddr     string
	ForwardAddr string
	APIAddr     string
	BackupFile  string
	MasterAddr  string
)

const forwardSuffix = ":53"

func init() {
	fc := flagconfig.New("gobdns")

	fc.StrParam("tcp-addr", "TCP address to listen on. Set to empty to not listen on tcp", ":53")
	fc.StrParam("udp-addr", "UDP address to listen on. Set to empty to not listen on udp", ":53")
	fc.StrParam("forward-addr", "Address to forward requests to when no matches are found", "")
	fc.StrParam("api-addr", "Address for the REST API to listen on. Leave blank to disable it", "")
	fc.StrParam("backup-file", "File to read data from during startup and to write data to during runtime. Leave blank to disable persistance", "./gobdns.db")
	fc.StrParam("master-addr", "ip:port of master instance to periodically pull snapshots from. Leave blank to disable", "")

	if err := fc.Parse(); err != nil {
		log.Fatal(err)
	}

	TCPAddr = fc.GetStr("tcp-addr")
	UDPAddr = fc.GetStr("udp-addr")
	ForwardAddr = fc.GetStr("forward-addr")
	APIAddr = fc.GetStr("api-addr")
	BackupFile = fc.GetStr("backup-file")
	MasterAddr = fc.GetStr("master-addr")

	if ForwardAddr != "" && !strings.HasSuffix(ForwardAddr, forwardSuffix) {
		ForwardAddr += forwardSuffix
	}
}
<commit_msg>make rest api come on by default<commit_after>package config

import (
	"github.com/mediocregopher/flagconfig"
	"log"
	"strings"
)

var (
	TCPAddr     string
	UDPAddr     string
	ForwardAddr string
	APIAddr     string
	BackupFile  string
	MasterAddr  string
)

const forwardSuffix = ":53"

func init() {
	fc := flagconfig.New("gobdns")

	fc.StrParam("tcp-addr", "TCP address to listen on. Set to empty to not listen on tcp", ":53")
	fc.StrParam("udp-addr", "UDP address to listen on. Set to empty to not listen on udp", ":53")
	fc.StrParam("forward-addr", "Address to forward requests to when no matches are found", "")
	fc.StrParam("api-addr", "Address for the REST API to listen on. Set to empty to disable it", ":8080")
	fc.StrParam("backup-file", "File to read data from during startup and to write data to during runtime. Leave blank to disable persistance", "./gobdns.db")
	fc.StrParam("master-addr", "ip:port of master instance to periodically pull snapshots from. Leave blank to disable", "")

	if err := fc.Parse(); err != nil {
		log.Fatal(err)
	}

	TCPAddr = fc.GetStr("tcp-addr")
	UDPAddr = fc.GetStr("udp-addr")
	ForwardAddr = fc.GetStr("forward-addr")
	APIAddr = fc.GetStr("api-addr")
	BackupFile = fc.GetStr("backup-file")
	MasterAddr = fc.GetStr("master-addr")

	if ForwardAddr != "" && !strings.HasSuffix(ForwardAddr, forwardSuffix) {
		ForwardAddr += forwardSuffix
	}
}
<|endoftext|>


<commit_before>package config

import (
	"errors"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"

	"github.com/goreleaser/releaser/config/git"
	yaml "gopkg.in/yaml.v1"
)

var filePatterns = []string{"LICENCE*", "LICENSE*", "README*", "CHANGELOG*"}

// Homebrew contains the brew section
type Homebrew struct {
	Repo    string
	Token   string `yaml:"-"`
	Caveats string
}

// BuildConfig contains the build configuration section
type BuildConfig struct {
	Oses   []string
	Arches []string
	Main   string
}

// GitInfo includes tags and diffs used in some point
type GitInfo struct {
	CurrentTag  string
	PreviousTag string
	Diff        string
}

// ProjectConfig includes all project configuration
type ProjectConfig struct {
	Repo         string
	BinaryName   string `yaml:"binary_name"`
	Files        []string
	Brew         Homebrew
	Token        string `yaml:"-"`
	Build        BuildConfig
	Git          GitInfo `yaml:"-"`
	NameTemplate string `yaml:"name_template"`
}

// Load config file
func Load(file string) (config ProjectConfig, err error) {
	data, err := ioutil.ReadFile(file)
	if err != nil {
		return config, err
	}
	if err := yaml.Unmarshal(data, &config); err != nil {
		return config, err
	}
	config.fillBasicData()
	if err := config.fillFiles(); err != nil {
		return config, err
	}
	if err := config.fillGitData(); err != nil {
		return config, err
	}
	return config, config.validate()
}

func (config *ProjectConfig) validate() (err error) {
	if config.BinaryName == "" {
		return errors.New("missing binary_name")
	}
	if config.Repo == "" {
		return errors.New("missing repo")
	}
	return
}

func (config *ProjectConfig) fillFiles() (err error) {
	if len(config.Files) != 0 {
		return
	}
	config.Files = []string{}
	for _, pattern := range filePatterns {
		matches, err := globPath(pattern)
		if err != nil {
			return err
		}

		config.Files = append(config.Files, matches...)
	}
	return
}

func (config *ProjectConfig) fillBasicData() {
	if config.Token == "" {
		config.Token = os.Getenv("GITHUB_TOKEN")
	}
	if config.Brew.Repo != "" {
		config.Brew.Token = config.Token
	}
	if config.Build.Main == "" {
		config.Build.Main = "main.go"
	}
	if len(config.Build.Oses) == 0 {
		config.Build.Oses = []string{"linux", "darwin"}
	}
	if len(config.Build.Arches) == 0 {
		config.Build.Arches = []string{"amd64", "386"}
	}
	if config.NameTemplate == "" {
		config.NameTemplate = "{{.BinaryName}}_{{.Os}}_{{.Arch}}"
	}
}

func (config *ProjectConfig) fillGitData() (err error) {
	tag, err := git.CurrentTag()
	if err != nil {
		return
	}
	previous, err := git.PreviousTag(tag)
	if err != nil {
		return
	}
	log, err := git.Log(previous, tag)
	if err != nil {
		return
	}

	config.Git.CurrentTag = tag
	config.Git.PreviousTag = previous
	config.Git.Diff = log
	return
}

func globPath(p string) (m []string, err error) {
	var cwd string
	var dirs []string

	if cwd, err = os.Getwd(); err != nil {
		return
	}

	fp := path.Join(cwd, p)

	if dirs, err = filepath.Glob(fp); err != nil {
		return
	}

	// Normalise to avoid nested dirs in tarball
	for _, dir := range dirs {
		_, f := filepath.Split(dir)
		m = append(m, f)
	}

	return
}
<commit_msg>go fmt<commit_after>package config

import (
	"errors"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"

	"github.com/goreleaser/releaser/config/git"
	yaml "gopkg.in/yaml.v1"
)

var filePatterns = []string{"LICENCE*", "LICENSE*", "README*", "CHANGELOG*"}

// Homebrew contains the brew section
type Homebrew struct {
	Repo    string
	Token   string `yaml:"-"`
	Caveats string
}

// BuildConfig contains the build configuration section
type BuildConfig struct {
	Oses   []string
	Arches []string
	Main   string
}

// GitInfo includes tags and diffs used in some point
type GitInfo struct {
	CurrentTag  string
	PreviousTag string
	Diff        string
}

// ProjectConfig includes all project configuration
type ProjectConfig struct {
	Repo         string
	BinaryName   string `yaml:"binary_name"`
	Files        []string
	Brew         Homebrew
	Token        string `yaml:"-"`
	Build        BuildConfig
	Git          GitInfo `yaml:"-"`
	NameTemplate string  `yaml:"name_template"`
}

// Load config file
func Load(file string) (config ProjectConfig, err error) {
	data, err := ioutil.ReadFile(file)
	if err != nil {
		return config, err
	}
	if err := yaml.Unmarshal(data, &config); err != nil {
		return config, err
	}
	config.fillBasicData()
	if err := config.fillFiles(); err != nil {
		return config, err
	}
	if err := config.fillGitData(); err != nil {
		return config, err
	}
	return config, config.validate()
}

func (config *ProjectConfig) validate() (err error) {
	if config.BinaryName == "" {
		return errors.New("missing binary_name")
	}
	if config.Repo == "" {
		return errors.New("missing repo")
	}
	return
}

func (config *ProjectConfig) fillFiles() (err error) {
	if len(config.Files) != 0 {
		return
	}
	config.Files = []string{}
	for _, pattern := range filePatterns {
		matches, err := globPath(pattern)
		if err != nil {
			return err
		}

		config.Files = append(config.Files, matches...)
	}
	return
}

func (config *ProjectConfig) fillBasicData() {
	if config.Token == "" {
		config.Token = os.Getenv("GITHUB_TOKEN")
	}
	if config.Brew.Repo != "" {
		config.Brew.Token = config.Token
	}
	if config.Build.Main == "" {
		config.Build.Main = "main.go"
	}
	if len(config.Build.Oses) == 0 {
		config.Build.Oses = []string{"linux", "darwin"}
	}
	if len(config.Build.Arches) == 0 {
		config.Build.Arches = []string{"amd64", "386"}
	}
	if config.NameTemplate == "" {
		config.NameTemplate = "{{.BinaryName}}_{{.Os}}_{{.Arch}}"
	}
}

func (config *ProjectConfig) fillGitData() (err error) {
	tag, err := git.CurrentTag()
	if err != nil {
		return
	}
	previous, err := git.PreviousTag(tag)
	if err != nil {
		return
	}
	log, err := git.Log(previous, tag)
	if err != nil {
		return
	}

	config.Git.CurrentTag = tag
	config.Git.PreviousTag = previous
	config.Git.Diff = log
	return
}

func globPath(p string) (m []string, err error) {
	var cwd string
	var dirs []string

	if cwd, err = os.Getwd(); err != nil {
		return
	}

	fp := path.Join(cwd, p)

	if dirs, err = filepath.Glob(fp); err != nil {
		return
	}

	// Normalise to avoid nested dirs in tarball
	for _, dir := range dirs {
		_, f := filepath.Split(dir)
		m = append(m, f)
	}

	return
}
<|endoftext|>


<commit_before>package config

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"log"
	"time"

	"github.com/eliothedeman/statsdaemon/backend"
)

const (
	DEFAULT_SERVICE_ADDRESS    = ":8125"
	DEFAULT_FLUSH_INTERVAL     = time.Second * 10
	DEFAULT_DEBUG              = false
	DEFUALT_PERSIST_COUNT_KEYS = 60
	DEFUALT_PREFIX             = ""
)

var (
	WRONG_CONFIG_TYPE = errors.New("wrong config type")
)

type Config struct {
	ServiceAddress      string                     `json:"service_address"`
	FlushInterval       time.Duration              `json:"-"`
	FlushIntervalString string                     `json:"flush_interval"`
	Debug               bool                       `json:"debug"`
	PersistCountKeys    int64                      `json:"persist_count_keys"`
	Prefix              string                     `json:"prefix"`
	Backends            map[string]json.RawMessage `json:"backends"`
}

// apply the config to all of the loaded backends, and return all of the configured backends
func (c *Config) InitBackends() ([]backend.Backend, error) {
	loaded := make([]backend.Backend, 0, len(c.Backends))
	for k, raw := range c.Backends {
		v, inMap := backend.Backends[k]
		if inMap {
			conf := v.ConfigStruct()
			err := json.Unmarshal(raw, conf)
			if err != nil {
				return loaded, err
			}
			err = v.Init(conf)
			if err != nil {
				return loaded, err
			}
			log.Printf("Loaded config for %s\n", k)
			loaded = append(loaded, v)
		} else {
			log.Println("No backend found for ", k)
		}
	}
	return loaded, nil
}

// Given a file name, load the config that resides at that path
func LoadConfigFromFile(name string) (*Config, error) {
	c := &Config{
		ServiceAddress:   DEFAULT_SERVICE_ADDRESS,
		FlushInterval:    DEFAULT_FLUSH_INTERVAL,
		Debug:            DEFAULT_DEBUG,
		PersistCountKeys: DEFUALT_PERSIST_COUNT_KEYS,
		Prefix:           DEFUALT_PREFIX,
		Backends:         make(map[string]json.RawMessage),
	}

	buff, err := ioutil.ReadFile(name)
	if err != nil {
		return c, err
	}

	err = json.Unmarshal(buff, c)
	if err != nil {
		log.Fatal(err)
	}

	c.FlushInterval, err = time.ParseDuration(c.FlushIntervalString)
	if c.Debug {
		log.SetFlags(log.Llongfile)
	}
	return c, err
}
<commit_msg>don't try to parse an interval if the string is not given<commit_after>package config

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"log"
	"time"

	"github.com/eliothedeman/statsdaemon/backend"
)

const (
	DEFAULT_SERVICE_ADDRESS    = ":8125"
	DEFAULT_FLUSH_INTERVAL     = time.Second * 10
	DEFAULT_DEBUG              = false
	DEFUALT_PERSIST_COUNT_KEYS = 60
	DEFUALT_PREFIX             = ""
)

var (
	WRONG_CONFIG_TYPE = errors.New("wrong config type")
)

type Config struct {
	ServiceAddress      string                     `json:"service_address"`
	FlushInterval       time.Duration              `json:"-"`
	FlushIntervalString string                     `json:"flush_interval"`
	Debug               bool                       `json:"debug"`
	PersistCountKeys    int64                      `json:"persist_count_keys"`
	Prefix              string                     `json:"prefix"`
	Backends            map[string]json.RawMessage `json:"backends"`
}

// apply the config to all of the loaded backends, and return all of the configured backends
func (c *Config) InitBackends() ([]backend.Backend, error) {
	loaded := make([]backend.Backend, 0, len(c.Backends))
	for k, raw := range c.Backends {
		v, inMap := backend.Backends[k]
		if inMap {
			conf := v.ConfigStruct()
			err := json.Unmarshal(raw, conf)
			if err != nil {
				return loaded, err
			}
			err = v.Init(conf)
			if err != nil {
				return loaded, err
			}
			log.Printf("Loaded config for %s\n", k)
			loaded = append(loaded, v)
		} else {
			log.Println("No backend found for ", k)
		}
	}
	return loaded, nil
}

// Given a file name, load the config that resides at that path
func LoadConfigFromFile(name string) (*Config, error) {
	c := &Config{
		ServiceAddress:   DEFAULT_SERVICE_ADDRESS,
		FlushInterval:    DEFAULT_FLUSH_INTERVAL,
		Debug:            DEFAULT_DEBUG,
		PersistCountKeys: DEFUALT_PERSIST_COUNT_KEYS,
		Prefix:           DEFUALT_PREFIX,
		Backends:         make(map[string]json.RawMessage),
	}

	buff, err := ioutil.ReadFile(name)
	if err != nil {
		return c, err
	}

	err = json.Unmarshal(buff, c)
	if err != nil {
		log.Fatal(err)
	}

	if c.FlushIntervalString != "" {
		c.FlushInterval, err = time.ParseDuration(c.FlushIntervalString)
	}
	if c.Debug {
		log.SetFlags(log.Llongfile)
	}
	return c, err
}
<|endoftext|>


<commit_before>package config

import (
	"html/template"
	"os"

	"github.com/jinzhu/configor"
	"github.com/microcosm-cc/bluemonday"
	"github.com/qor/auth/providers/github"
	"github.com/qor/auth/providers/google"
	"github.com/qor/mailer"
	"github.com/qor/mailer/logger"
	"github.com/qor/redirect_back"
	"github.com/qor/render"
	"github.com/qor/session/manager"
)

type SMTPConfig struct {
	Host     string
	Port     string
	User     string
	Password string
}

var Config = struct {
	Port uint `default:"7000" env:"PORT"`
	DB   struct {
		Name     string `env:"DBName" default:"qor_example"`
		Adapter  string `env:"DBAdapter" default:"mysql"`
		Host     string `env:"DBHost" default:"localhost"`
		Port     string `env:"DBPort" default:"3306"`
		User     string `env:"DBUser"`
		Password string `env:"DBPassword"`
	}
	SMTP   SMTPConfig
	Github github.Config
	Google google.Config
}{}

var (
	Root         = os.Getenv("GOPATH") + "/src/github.com/qor/qor-example"
	View         *render.Render
	Mailer       *mailer.Mailer
	RedirectBack = redirect_back.New(&redirect_back.Config{
		SessionManager:  manager.SessionManager,
		IgnoredPrefixes: []string{"/auth"},
	})
)

func init() {
	if err := configor.Load(&Config, "config/database.yml", "config/smtp.yml", "config/application.yml"); err != nil {
		panic(err)
	}

	View = render.New()

	htmlSanitizer := bluemonday.UGCPolicy()
	View.RegisterFuncMap("raw", func(str string) template.HTML {
		return template.HTML(htmlSanitizer.Sanitize(str))
	})

	// dialer := gomail.NewDialer(Config.SMTP.Host, Config.SMTP.Port, Config.SMTP.User, Config.SMTP.Password)
	// sender, err := dialer.Dial()

	// Mailer = mailer.New(&mailer.Config{
	// 	Sender: gomailer.New(&gomailer.Config{Sender: sender}),
	// })
	Mailer = mailer.New(&mailer.Config{
		Sender: logger.New(&logger.Config{}),
	})
}
<commit_msg>Update Render API<commit_after>package config

import (
	"html/template"
	"os"

	"github.com/jinzhu/configor"
	"github.com/microcosm-cc/bluemonday"
	"github.com/qor/auth/providers/github"
	"github.com/qor/auth/providers/google"
	"github.com/qor/mailer"
	"github.com/qor/mailer/logger"
	"github.com/qor/redirect_back"
	"github.com/qor/render"
	"github.com/qor/session/manager"
)

type SMTPConfig struct {
	Host     string
	Port     string
	User     string
	Password string
}

var Config = struct {
	Port uint `default:"7000" env:"PORT"`
	DB   struct {
		Name     string `env:"DBName" default:"qor_example"`
		Adapter  string `env:"DBAdapter" default:"mysql"`
		Host     string `env:"DBHost" default:"localhost"`
		Port     string `env:"DBPort" default:"3306"`
		User     string `env:"DBUser"`
		Password string `env:"DBPassword"`
	}
	SMTP   SMTPConfig
	Github github.Config
	Google google.Config
}{}

var (
	Root         = os.Getenv("GOPATH") + "/src/github.com/qor/qor-example"
	View         *render.Render
	Mailer       *mailer.Mailer
	RedirectBack = redirect_back.New(&redirect_back.Config{
		SessionManager:  manager.SessionManager,
		IgnoredPrefixes: []string{"/auth"},
	})
)

func init() {
	if err := configor.Load(&Config, "config/database.yml", "config/smtp.yml", "config/application.yml"); err != nil {
		panic(err)
	}

	View = render.New(nil)

	htmlSanitizer := bluemonday.UGCPolicy()
	View.RegisterFuncMap("raw", func(str string) template.HTML {
		return template.HTML(htmlSanitizer.Sanitize(str))
	})

	// dialer := gomail.NewDialer(Config.SMTP.Host, Config.SMTP.Port, Config.SMTP.User, Config.SMTP.Password)
	// sender, err := dialer.Dial()

	// Mailer = mailer.New(&mailer.Config{
	// 	Sender: gomailer.New(&gomailer.Config{Sender: sender}),
	// })
	Mailer = mailer.New(&mailer.Config{
		Sender: logger.New(&logger.Config{}),
	})
}
<|endoftext|>


<commit_before>package rest

import (
	"fmt"
	"io"
	"net/http"
	"net/mail"
	"time"

	"github.com/jhillyerd/inbucket/httpd"
	"github.com/jhillyerd/inbucket/log"
	"github.com/jhillyerd/inbucket/smtpd"
)

// JSONMessageHeaderV1 contains the basic header data for a message
type JSONMessageHeaderV1 struct {
	Mailbox string    `json:"mailbox"`
	ID      string    `json:"id"`
	From    string    `json:"from"`
	To      []string  `json:"to"`
	Subject string    `json:"subject"`
	Date    time.Time `json:"date"`
	Size    int64     `json:"size"`
}

// JSONMessageV1 contains the same data as the header plus a JSONMessageBody
type JSONMessageV1 struct {
	Mailbox string             `json:"mailbox"`
	ID      string             `json:"id"`
	From    string             `json:"from"`
	To      []string           `json:"to"`
	Subject string             `json:"subject"`
	Date    time.Time          `json:"date"`
	Size    int64              `json:"size"`
	Body    *JSONMessageBodyV1 `json:"body"`
	Header  mail.Header        `json:"header"`
}

// JSONMessageBodyV1 contains the Text and HTML versions of the message body
type JSONMessageBodyV1 struct {
	Text string `json:"text"`
	HTML string `json:"html"`
}

// MailboxListV1 renders a list of messages in a mailbox
func MailboxListV1(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
	// Don't have to validate these aren't empty, Gorilla returns 404
	name, err := smtpd.ParseMailboxName(ctx.Vars["name"])
	if err != nil {
		return err
	}
	mb, err := ctx.DataStore.MailboxFor(name)
	if err != nil {
		// This doesn't indicate not found, likely an IO error
		return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
	}
	messages, err := mb.GetMessages()
	if err != nil {
		// This doesn't indicate empty, likely an IO error
		return fmt.Errorf("Failed to get messages for %v: %v", name, err)
	}
	log.Tracef("Got %v messsages", len(messages))

	jmessages := make([]*JSONMessageHeaderV1, len(messages))
	for i, msg := range messages {
		jmessages[i] = &JSONMessageHeaderV1{
			Mailbox: name,
			ID:      msg.ID(),
			From:    msg.From(),
			To:      msg.To(),
			Subject: msg.Subject(),
			Date:    msg.Date(),
			Size:    msg.Size(),
		}
	}
	return httpd.RenderJSON(w, jmessages)
}

// MailboxShowV1 renders a particular message from a mailbox
func MailboxShowV1(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
	// Don't have to validate these aren't empty, Gorilla returns 404
	id := ctx.Vars["id"]
	name, err := smtpd.ParseMailboxName(ctx.Vars["name"])
	if err != nil {
		return err
	}
	mb, err := ctx.DataStore.MailboxFor(name)
	if err != nil {
		// This doesn't indicate not found, likely an IO error
		return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
	}
	msg, err := mb.GetMessage(id)
	if err == smtpd.ErrNotExist {
		http.NotFound(w, req)
		return nil
	}
	if err != nil {
		// This doesn't indicate empty, likely an IO error
		return fmt.Errorf("GetMessage(%q) failed: %v", id, err)
	}
	header, err := msg.ReadHeader()
	if err != nil {
		return fmt.Errorf("ReadHeader(%q) failed: %v", id, err)
	}
	mime, err := msg.ReadBody()
	if err != nil {
		return fmt.Errorf("ReadBody(%q) failed: %v", id, err)
	}

	return httpd.RenderJSON(w,
		&JSONMessageV1{
			Mailbox: name,
			ID:      msg.ID(),
			From:    msg.From(),
			To:      msg.To(),
			Subject: msg.Subject(),
			Date:    msg.Date(),
			Size:    msg.Size(),
			Header:  header.Header,
			Body: &JSONMessageBodyV1{
				Text: mime.Text,
				HTML: mime.HTML,
			},
		})
}

// MailboxPurgeV1 deletes all messages from a mailbox
func MailboxPurgeV1(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
	// Don't have to validate these aren't empty, Gorilla returns 404
	name, err := smtpd.ParseMailboxName(ctx.Vars["name"])
	if err != nil {
		return err
	}
	mb, err := ctx.DataStore.MailboxFor(name)
	if err != nil {
		// This doesn't indicate not found, likely an IO error
		return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
	}
	// Delete all messages
	err = mb.Purge()
	if err != nil {
		return fmt.Errorf("Mailbox(%q) purge failed: %v", name, err)
	}
	log.Tracef("HTTP purged mailbox for %q", name)

	return httpd.RenderJSON(w, "OK")
}

// MailboxSourceV1 displays the raw source of a message, including headers. Renders text/plain
func MailboxSourceV1(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
	// Don't have to validate these aren't empty, Gorilla returns 404
	id := ctx.Vars["id"]
	name, err := smtpd.ParseMailboxName(ctx.Vars["name"])
	if err != nil {
		return err
	}
	mb, err := ctx.DataStore.MailboxFor(name)
	if err != nil {
		// This doesn't indicate not found, likely an IO error
		return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
	}
	message, err := mb.GetMessage(id)
	if err == smtpd.ErrNotExist {
		http.NotFound(w, req)
		return nil
	}
	if err != nil {
		// This doesn't indicate missing, likely an IO error
		return fmt.Errorf("GetMessage(%q) failed: %v", id, err)
	}
	raw, err := message.ReadRaw()
	if err != nil {
		return fmt.Errorf("ReadRaw(%q) failed: %v", id, err)
	}

	w.Header().Set("Content-Type", "text/plain")
	if _, err := io.WriteString(w, *raw); err != nil {
		return err
	}
	return nil
}

// MailboxDeleteV1 removes a particular message from a mailbox.  Renders JSON or plain/text OK
func MailboxDeleteV1(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
	// Don't have to validate these aren't empty, Gorilla returns 404
	id := ctx.Vars["id"]
	name, err := smtpd.ParseMailboxName(ctx.Vars["name"])
	if err != nil {
		return err
	}
	mb, err := ctx.DataStore.MailboxFor(name)
	if err != nil {
		// This doesn't indicate not found, likely an IO error
		return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
	}
	message, err := mb.GetMessage(id)
	if err == smtpd.ErrNotExist {
		http.NotFound(w, req)
		return nil
	}
	if err != nil {
		// This doesn't indicate missing, likely an IO error
		return fmt.Errorf("GetMessage(%q) failed: %v", id, err)
	}
	err = message.Delete()
	if err != nil {
		return fmt.Errorf("Delete(%q) failed: %v", id, err)
	}

	return httpd.RenderJSON(w, "OK")
}
<commit_msg>Added data about message attachments to REST API (#46)<commit_after>package rest

import (
	"fmt"
	"io"
	"net/http"
	"net/mail"
	"time"

	"github.com/jhillyerd/inbucket/httpd"
	"github.com/jhillyerd/inbucket/log"
	"github.com/jhillyerd/inbucket/smtpd"
	"strconv"
	"crypto/md5"
	"encoding/hex"
	"io/ioutil"
)

// JSONMessageHeaderV1 contains the basic header data for a message
type JSONMessageHeaderV1 struct {
	Mailbox string    `json:"mailbox"`
	ID      string    `json:"id"`
	From    string    `json:"from"`
	To      []string  `json:"to"`
	Subject string    `json:"subject"`
	Date    time.Time `json:"date"`
	Size    int64     `json:"size"`
}

// JSONMessageV1 contains the same data as the header plus a JSONMessageBody
type JSONMessageV1 struct {
	Mailbox string             `json:"mailbox"`
	ID      string             `json:"id"`
	From    string             `json:"from"`
	To      []string           `json:"to"`
	Subject string             `json:"subject"`
	Date    time.Time          `json:"date"`
	Size    int64              `json:"size"`
	Body    *JSONMessageBodyV1 `json:"body"`
	Header  mail.Header        `json:"header"`
	Attachments []*JSONMessageAttachmentV1 `json:"attachments"`
}

type JSONMessageAttachmentV1 struct {
	FileName     string                `json:"filename"`
	ContentType  string        `json:"content-type"`
	DownloadLink string        `json:"download-link"`
	ViewLink     string        `json:"view-link"`
	MD5	     string	   `json:"md5"`
}

// JSONMessageBodyV1 contains the Text and HTML versions of the message body
type JSONMessageBodyV1 struct {
	Text string `json:"text"`
	HTML string `json:"html"`
}

// MailboxListV1 renders a list of messages in a mailbox
func MailboxListV1(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
	// Don't have to validate these aren't empty, Gorilla returns 404
	name, err := smtpd.ParseMailboxName(ctx.Vars["name"])
	if err != nil {
		return err
	}
	mb, err := ctx.DataStore.MailboxFor(name)
	if err != nil {
		// This doesn't indicate not found, likely an IO error
		return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
	}
	messages, err := mb.GetMessages()
	if err != nil {
		// This doesn't indicate empty, likely an IO error
		return fmt.Errorf("Failed to get messages for %v: %v", name, err)
	}
	log.Tracef("Got %v messsages", len(messages))

	jmessages := make([]*JSONMessageHeaderV1, len(messages))
	for i, msg := range messages {
		jmessages[i] = &JSONMessageHeaderV1{
			Mailbox: name,
			ID:      msg.ID(),
			From:    msg.From(),
			To:      msg.To(),
			Subject: msg.Subject(),
			Date:    msg.Date(),
			Size:    msg.Size(),
		}
	}
	return httpd.RenderJSON(w, jmessages)
}

// MailboxShowV1 renders a particular message from a mailbox
func MailboxShowV1(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
	// Don't have to validate these aren't empty, Gorilla returns 404
	id := ctx.Vars["id"]
	name, err := smtpd.ParseMailboxName(ctx.Vars["name"])
	if err != nil {
		return err
	}
	mb, err := ctx.DataStore.MailboxFor(name)
	if err != nil {
		// This doesn't indicate not found, likely an IO error
		return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
	}
	msg, err := mb.GetMessage(id)
	if err == smtpd.ErrNotExist {
		http.NotFound(w, req)
		return nil
	}
	if err != nil {
		// This doesn't indicate empty, likely an IO error
		return fmt.Errorf("GetMessage(%q) failed: %v", id, err)
	}
	header, err := msg.ReadHeader()
	if err != nil {
		return fmt.Errorf("ReadHeader(%q) failed: %v", id, err)
	}
	mime, err := msg.ReadBody()
	if err != nil {
		return fmt.Errorf("ReadBody(%q) failed: %v", id, err)
	}

	attachments := make([]*JSONMessageAttachmentV1, len(mime.Attachments))
	for i, att := range mime.Attachments {
		var content []byte
		content, err = ioutil.ReadAll(att)
		var checksum = md5.Sum(content)
		attachments[i] = &JSONMessageAttachmentV1{
			ContentType: att.ContentType,
			FileName: att.FileName,
			DownloadLink:  "http://" + req.Host + "/mailbox/dattach/" + name + "/" + id + "/" + strconv.Itoa(i) + "/" + att.FileName,
			ViewLink: "http://" + req.Host + "/mailbox/vattach/" + name + "/" + id + "/" + strconv.Itoa(i) + "/" + att.FileName,
			MD5: hex.EncodeToString(checksum[:]),
		}
	}

	return httpd.RenderJSON(w,
		&JSONMessageV1{
			Mailbox: name,
			ID:      msg.ID(),
			From:    msg.From(),
			To:      msg.To(),
			Subject: msg.Subject(),
			Date:    msg.Date(),
			Size:    msg.Size(),
			Header:  header.Header,
			Body: &JSONMessageBodyV1{
				Text: mime.Text,
				HTML: mime.HTML,
			},
			Attachments: attachments,
		})
}

// MailboxPurgeV1 deletes all messages from a mailbox
func MailboxPurgeV1(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
	// Don't have to validate these aren't empty, Gorilla returns 404
	name, err := smtpd.ParseMailboxName(ctx.Vars["name"])
	if err != nil {
		return err
	}
	mb, err := ctx.DataStore.MailboxFor(name)
	if err != nil {
		// This doesn't indicate not found, likely an IO error
		return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
	}
	// Delete all messages
	err = mb.Purge()
	if err != nil {
		return fmt.Errorf("Mailbox(%q) purge failed: %v", name, err)
	}
	log.Tracef("HTTP purged mailbox for %q", name)

	return httpd.RenderJSON(w, "OK")
}

// MailboxSourceV1 displays the raw source of a message, including headers. Renders text/plain
func MailboxSourceV1(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
	// Don't have to validate these aren't empty, Gorilla returns 404
	id := ctx.Vars["id"]
	name, err := smtpd.ParseMailboxName(ctx.Vars["name"])
	if err != nil {
		return err
	}
	mb, err := ctx.DataStore.MailboxFor(name)
	if err != nil {
		// This doesn't indicate not found, likely an IO error
		return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
	}
	message, err := mb.GetMessage(id)
	if err == smtpd.ErrNotExist {
		http.NotFound(w, req)
		return nil
	}
	if err != nil {
		// This doesn't indicate missing, likely an IO error
		return fmt.Errorf("GetMessage(%q) failed: %v", id, err)
	}
	raw, err := message.ReadRaw()
	if err != nil {
		return fmt.Errorf("ReadRaw(%q) failed: %v", id, err)
	}

	w.Header().Set("Content-Type", "text/plain")
	if _, err := io.WriteString(w, *raw); err != nil {
		return err
	}
	return nil
}

// MailboxDeleteV1 removes a particular message from a mailbox.  Renders JSON or plain/text OK
func MailboxDeleteV1(w http.ResponseWriter, req *http.Request, ctx *httpd.Context) (err error) {
	// Don't have to validate these aren't empty, Gorilla returns 404
	id := ctx.Vars["id"]
	name, err := smtpd.ParseMailboxName(ctx.Vars["name"])
	if err != nil {
		return err
	}
	mb, err := ctx.DataStore.MailboxFor(name)
	if err != nil {
		// This doesn't indicate not found, likely an IO error
		return fmt.Errorf("Failed to get mailbox for %q: %v", name, err)
	}
	message, err := mb.GetMessage(id)
	if err == smtpd.ErrNotExist {
		http.NotFound(w, req)
		return nil
	}
	if err != nil {
		// This doesn't indicate missing, likely an IO error
		return fmt.Errorf("GetMessage(%q) failed: %v", id, err)
	}
	err = message.Delete()
	if err != nil {
		return fmt.Errorf("Delete(%q) failed: %v", id, err)
	}

	return httpd.RenderJSON(w, "OK")
}
<|endoftext|>


<commit_before>// Code generated by protoc-gen-go.
// source: system_message.proto
// DO NOT EDIT!

/*
Package operation is a generated protocol buffer package.

It is generated from these files:
	system_message.proto

It has these top-level messages:
	VolumeInformationMessage
	JoinMessage
*/
package operation

import proto "code.google.com/p/goprotobuf/proto"
import math "math"

// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = math.Inf

type VolumeInformationMessage struct {
	Id               *uint32 `protobuf:"varint,1,req,name=id" json:"id,omitempty"`
	Size             *uint64 `protobuf:"varint,2,req,name=size" json:"size,omitempty"`
	Collection       *string `protobuf:"bytes,3,opt,name=collection" json:"collection,omitempty"`
	FileCount        *uint64 `protobuf:"varint,4,req,name=file_count" json:"file_count,omitempty"`
	DeleteCount      *uint64 `protobuf:"varint,5,req,name=delete_count" json:"delete_count,omitempty"`
	DeletedByteCount *uint64 `protobuf:"varint,6,req,name=deleted_byte_count" json:"deleted_byte_count,omitempty"`
	ReadOnly         *bool   `protobuf:"varint,7,opt,name=read_only" json:"read_only,omitempty"`
	ReplicaPlacement *uint32 `protobuf:"varint,8,req,name=replica_placement" json:"replica_placement,omitempty"`
	Version          *uint32 `protobuf:"varint,9,opt,name=version,def=2" json:"version,omitempty"`
	Ttl              *uint32 `protobuf:"varint,10,opt,name=ttl" json:"ttl,omitempty"`
	XXX_unrecognized []byte  `json:"-"`
}

func (m *VolumeInformationMessage) Reset()         { *m = VolumeInformationMessage{} }
func (m *VolumeInformationMessage) String() string { return proto.CompactTextString(m) }
func (*VolumeInformationMessage) ProtoMessage()    {}

const Default_VolumeInformationMessage_Version uint32 = 2

func (m *VolumeInformationMessage) GetId() uint32 {
	if m != nil && m.Id != nil {
		return *m.Id
	}
	return 0
}

func (m *VolumeInformationMessage) GetSize() uint64 {
	if m != nil && m.Size != nil {
		return *m.Size
	}
	return 0
}

func (m *VolumeInformationMessage) GetCollection() string {
	if m != nil && m.Collection != nil {
		return *m.Collection
	}
	return ""
}

func (m *VolumeInformationMessage) GetFileCount() uint64 {
	if m != nil && m.FileCount != nil {
		return *m.FileCount
	}
	return 0
}

func (m *VolumeInformationMessage) GetDeleteCount() uint64 {
	if m != nil && m.DeleteCount != nil {
		return *m.DeleteCount
	}
	return 0
}

func (m *VolumeInformationMessage) GetDeletedByteCount() uint64 {
	if m != nil && m.DeletedByteCount != nil {
		return *m.DeletedByteCount
	}
	return 0
}

func (m *VolumeInformationMessage) GetReadOnly() bool {
	if m != nil && m.ReadOnly != nil {
		return *m.ReadOnly
	}
	return false
}

func (m *VolumeInformationMessage) GetReplicaPlacement() uint32 {
	if m != nil && m.ReplicaPlacement != nil {
		return *m.ReplicaPlacement
	}
	return 0
}

func (m *VolumeInformationMessage) GetVersion() uint32 {
	if m != nil && m.Version != nil {
		return *m.Version
	}
	return Default_VolumeInformationMessage_Version
}

func (m *VolumeInformationMessage) GetTtl() uint32 {
	if m != nil && m.Ttl != nil {
		return *m.Ttl
	}
	return 0
}

type JoinMessage struct {
	IsInit           *bool                       `protobuf:"varint,1,opt,name=is_init" json:"is_init,omitempty"`
	Ip               *string                     `protobuf:"bytes,2,req,name=ip" json:"ip,omitempty"`
	Port             *uint32                     `protobuf:"varint,3,req,name=port" json:"port,omitempty"`
	PublicUrl        *string                     `protobuf:"bytes,4,opt,name=public_url" json:"public_url,omitempty"`
	MaxVolumeCount   *uint32                     `protobuf:"varint,5,req,name=max_volume_count" json:"max_volume_count,omitempty"`
	MaxFileKey       *uint64                     `protobuf:"varint,6,req,name=max_file_key" json:"max_file_key,omitempty"`
	DataCenter       *string                     `protobuf:"bytes,7,opt,name=data_center" json:"data_center,omitempty"`
	Rack             *string                     `protobuf:"bytes,8,opt,name=rack" json:"rack,omitempty"`
	Volumes          []*VolumeInformationMessage `protobuf:"bytes,9,rep,name=volumes" json:"volumes,omitempty"`
	AdminPort        *uint32                     `protobuf:"varint,10,opt,name=admin_port" json:"admin_port,omitempty"`
	XXX_unrecognized []byte                      `json:"-"`
}

func (m *JoinMessage) Reset()         { *m = JoinMessage{} }
func (m *JoinMessage) String() string { return proto.CompactTextString(m) }
func (*JoinMessage) ProtoMessage()    {}

func (m *JoinMessage) GetIsInit() bool {
	if m != nil && m.IsInit != nil {
		return *m.IsInit
	}
	return false
}

func (m *JoinMessage) GetIp() string {
	if m != nil && m.Ip != nil {
		return *m.Ip
	}
	return ""
}

func (m *JoinMessage) GetPort() uint32 {
	if m != nil && m.Port != nil {
		return *m.Port
	}
	return 0
}

func (m *JoinMessage) GetPublicUrl() string {
	if m != nil && m.PublicUrl != nil {
		return *m.PublicUrl
	}
	return ""
}

func (m *JoinMessage) GetMaxVolumeCount() uint32 {
	if m != nil && m.MaxVolumeCount != nil {
		return *m.MaxVolumeCount
	}
	return 0
}

func (m *JoinMessage) GetMaxFileKey() uint64 {
	if m != nil && m.MaxFileKey != nil {
		return *m.MaxFileKey
	}
	return 0
}

func (m *JoinMessage) GetDataCenter() string {
	if m != nil && m.DataCenter != nil {
		return *m.DataCenter
	}
	return ""
}

func (m *JoinMessage) GetRack() string {
	if m != nil && m.Rack != nil {
		return *m.Rack
	}
	return ""
}

func (m *JoinMessage) GetVolumes() []*VolumeInformationMessage {
	if m != nil {
		return m.Volumes
	}
	return nil
}

func (m *JoinMessage) GetAdminPort() uint32 {
	if m != nil && m.AdminPort != nil {
		return *m.AdminPort
	}
	return 0
}

func init() {
}
<commit_msg>use proto "github.com/golang/protobuf/proto"<commit_after>// Code generated by protoc-gen-go.
// source: system_message.proto
// DO NOT EDIT!

/*
Package operation is a generated protocol buffer package.

It is generated from these files:
	system_message.proto

It has these top-level messages:
	VolumeInformationMessage
	JoinMessage
*/
package operation

import proto "github.com/golang/protobuf/proto"
import math "math"

// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = math.Inf

type VolumeInformationMessage struct {
	Id               *uint32 `protobuf:"varint,1,req,name=id" json:"id,omitempty"`
	Size             *uint64 `protobuf:"varint,2,req,name=size" json:"size,omitempty"`
	Collection       *string `protobuf:"bytes,3,opt,name=collection" json:"collection,omitempty"`
	FileCount        *uint64 `protobuf:"varint,4,req,name=file_count" json:"file_count,omitempty"`
	DeleteCount      *uint64 `protobuf:"varint,5,req,name=delete_count" json:"delete_count,omitempty"`
	DeletedByteCount *uint64 `protobuf:"varint,6,req,name=deleted_byte_count" json:"deleted_byte_count,omitempty"`
	ReadOnly         *bool   `protobuf:"varint,7,opt,name=read_only" json:"read_only,omitempty"`
	ReplicaPlacement *uint32 `protobuf:"varint,8,req,name=replica_placement" json:"replica_placement,omitempty"`
	Version          *uint32 `protobuf:"varint,9,opt,name=version,def=2" json:"version,omitempty"`
	Ttl              *uint32 `protobuf:"varint,10,opt,name=ttl" json:"ttl,omitempty"`
	XXX_unrecognized []byte  `json:"-"`
}

func (m *VolumeInformationMessage) Reset()         { *m = VolumeInformationMessage{} }
func (m *VolumeInformationMessage) String() string { return proto.CompactTextString(m) }
func (*VolumeInformationMessage) ProtoMessage()    {}

const Default_VolumeInformationMessage_Version uint32 = 2

func (m *VolumeInformationMessage) GetId() uint32 {
	if m != nil && m.Id != nil {
		return *m.Id
	}
	return 0
}

func (m *VolumeInformationMessage) GetSize() uint64 {
	if m != nil && m.Size != nil {
		return *m.Size
	}
	return 0
}

func (m *VolumeInformationMessage) GetCollection() string {
	if m != nil && m.Collection != nil {
		return *m.Collection
	}
	return ""
}

func (m *VolumeInformationMessage) GetFileCount() uint64 {
	if m != nil && m.FileCount != nil {
		return *m.FileCount
	}
	return 0
}

func (m *VolumeInformationMessage) GetDeleteCount() uint64 {
	if m != nil && m.DeleteCount != nil {
		return *m.DeleteCount
	}
	return 0
}

func (m *VolumeInformationMessage) GetDeletedByteCount() uint64 {
	if m != nil && m.DeletedByteCount != nil {
		return *m.DeletedByteCount
	}
	return 0
}

func (m *VolumeInformationMessage) GetReadOnly() bool {
	if m != nil && m.ReadOnly != nil {
		return *m.ReadOnly
	}
	return false
}

func (m *VolumeInformationMessage) GetReplicaPlacement() uint32 {
	if m != nil && m.ReplicaPlacement != nil {
		return *m.ReplicaPlacement
	}
	return 0
}

func (m *VolumeInformationMessage) GetVersion() uint32 {
	if m != nil && m.Version != nil {
		return *m.Version
	}
	return Default_VolumeInformationMessage_Version
}

func (m *VolumeInformationMessage) GetTtl() uint32 {
	if m != nil && m.Ttl != nil {
		return *m.Ttl
	}
	return 0
}

type JoinMessage struct {
	IsInit           *bool                       `protobuf:"varint,1,opt,name=is_init" json:"is_init,omitempty"`
	Ip               *string                     `protobuf:"bytes,2,req,name=ip" json:"ip,omitempty"`
	Port             *uint32                     `protobuf:"varint,3,req,name=port" json:"port,omitempty"`
	PublicUrl        *string                     `protobuf:"bytes,4,opt,name=public_url" json:"public_url,omitempty"`
	MaxVolumeCount   *uint32                     `protobuf:"varint,5,req,name=max_volume_count" json:"max_volume_count,omitempty"`
	MaxFileKey       *uint64                     `protobuf:"varint,6,req,name=max_file_key" json:"max_file_key,omitempty"`
	DataCenter       *string                     `protobuf:"bytes,7,opt,name=data_center" json:"data_center,omitempty"`
	Rack             *string                     `protobuf:"bytes,8,opt,name=rack" json:"rack,omitempty"`
	Volumes          []*VolumeInformationMessage `protobuf:"bytes,9,rep,name=volumes" json:"volumes,omitempty"`
	AdminPort        *uint32                     `protobuf:"varint,10,opt,name=admin_port" json:"admin_port,omitempty"`
	XXX_unrecognized []byte                      `json:"-"`
}

func (m *JoinMessage) Reset()         { *m = JoinMessage{} }
func (m *JoinMessage) String() string { return proto.CompactTextString(m) }
func (*JoinMessage) ProtoMessage()    {}

func (m *JoinMessage) GetIsInit() bool {
	if m != nil && m.IsInit != nil {
		return *m.IsInit
	}
	return false
}

func (m *JoinMessage) GetIp() string {
	if m != nil && m.Ip != nil {
		return *m.Ip
	}
	return ""
}

func (m *JoinMessage) GetPort() uint32 {
	if m != nil && m.Port != nil {
		return *m.Port
	}
	return 0
}

func (m *JoinMessage) GetPublicUrl() string {
	if m != nil && m.PublicUrl != nil {
		return *m.PublicUrl
	}
	return ""
}

func (m *JoinMessage) GetMaxVolumeCount() uint32 {
	if m != nil && m.MaxVolumeCount != nil {
		return *m.MaxVolumeCount
	}
	return 0
}

func (m *JoinMessage) GetMaxFileKey() uint64 {
	if m != nil && m.MaxFileKey != nil {
		return *m.MaxFileKey
	}
	return 0
}

func (m *JoinMessage) GetDataCenter() string {
	if m != nil && m.DataCenter != nil {
		return *m.DataCenter
	}
	return ""
}

func (m *JoinMessage) GetRack() string {
	if m != nil && m.Rack != nil {
		return *m.Rack
	}
	return ""
}

func (m *JoinMessage) GetVolumes() []*VolumeInformationMessage {
	if m != nil {
		return m.Volumes
	}
	return nil
}

func (m *JoinMessage) GetAdminPort() uint32 {
	if m != nil && m.AdminPort != nil {
		return *m.AdminPort
	}
	return 0
}

func init() {
}
<|endoftext|>


<commit_before>package polecalc

// Error returned when the self-consistent equation cannot be solved
type SelfConsistentError struct {
	ResponsibleEnv Environment
	Reason         string
}

func (e *SelfConsistentError) String() string {
	return e.Reason
}

// One-parameter scalar self-consistent equation
type SelfConsistentEquation interface {
	// return the absolute error associated with this equation under the given Environment
	AbsError(env Environment) float64
	// set the appropriate variable in env to value
	SetEnvironment(value float64, env *Environment)
}

// Return an Environment which solves eq to the given tolerance
func Solve(eq SelfConsistentEquation, env Environment, tolerance float64) (Environment, *SelfConsistentError) {
	error := func(value float64) float64 {
		eq.SetEnvironment(value, &env)
		return eq.AbsError(env)
	}
	// -- find solution --
	error(0)        // dummy
	solution := 0.0 // dummy
	eq.SetEnvironment(solution, &env)
	return env, nil
}

// A group of self-consistent equations which may be coupled and must all be
// solved for the group to be considered solved.
type SelfConsistentSystem struct {
	Equations  []SelfConsistentEquation
	Tolerances []float64
}

// Solve the self-consistent system, returning the resulting Environment
func (system *SelfConsistentSystem) Solve(env Environment) (Environment, *SelfConsistentError) {
	i := 0
	for !system.IsSolved(env) {
		// this should never be true: if it is, failed to iterate
		if i >= len(system.Equations) {
			panic("self-consistent system overran bounds")
		}
		// set env to the value that solves the equation
		newEnv, err := Solve(system.Equations[i], env, system.Tolerances[i])
		if err != nil {
			return env, err
		}
		env = newEnv
		// check if we need to iterate
		if !system.solvedUpTo(env, i) {
			// previous equations have been disturbed; restart
			i = 0
		} else {
			// ok to continue to next equation
			i++
		}
	}
	return env, nil
}

// Check if the first (maxIndex + 1) equations are solved
func (system *SelfConsistentSystem) solvedUpTo(env Environment, maxIndex int) bool {
	for i, eq := range system.Equations {
		if i > maxIndex {
			break
		}
		if eq.AbsError(env) > system.Tolerances[i] {
			return false
		}
	}
	return true
}

// Are all the self-consistent equations solved?
func (system *SelfConsistentSystem) IsSolved(env Environment) bool {
	if len(system.Equations) == 0 {
		return true
	}
	return system.solvedUpTo(env, len(system.Equations)-1)
}
<commit_msg>selconsistent functionality is in. testing needed.<commit_after>package polecalc

import "os"

// One-parameter scalar self-consistent equation
type SelfConsistentEquation interface {
	// return the absolute error associated with this equation under the given Environment
	AbsError(env Environment) float64
	// set the appropriate variable in env to value
	SetEnvironment(value float64, env *Environment)
	// range of possible values for SetEnvironment
	Range(env Environment) (float64, float64, os.Error)
}

// Return an Environment which solves eq to the given tolerance
func Solve(eq SelfConsistentEquation, env Environment, tolerance float64) (Environment, os.Error) {
	eqError := func(value float64) float64 {
		eq.SetEnvironment(value, &env)
		return eq.AbsError(env)
	}
	// if eq only has one root, left and right must bracket it
	// --- todo: need to verify this ---
	left, right, err := eq.Range(env)
	if err != nil {
		return env, err
	}
	solution, err := BisectionFullPrecision(eqError, left, right)
	if err != nil {
		return env, err
	}
	eq.SetEnvironment(solution, &env)
	return env, nil
}

// A group of self-consistent equations which may be coupled and must all be
// solved for the group to be considered solved.
type SelfConsistentSystem struct {
	Equations  []SelfConsistentEquation
	Tolerances []float64
}

// Solve the self-consistent system, returning the resulting Environment
func (system *SelfConsistentSystem) Solve(env Environment) (Environment, os.Error) {
	i := 0
	for !system.IsSolved(env) {
		// this should never be true: if it is, failed to iterate
		if i >= len(system.Equations) {
			panic("self-consistent system overran bounds")
		}
		// set env to the value that solves the equation
		newEnv, err := Solve(system.Equations[i], env, system.Tolerances[i])
		if err != nil {
			return env, err
		}
		env = newEnv
		// check if we need to iterate
		if !system.solvedUpTo(env, i) {
			// previous equations have been disturbed; restart
			i = 0
		} else {
			// ok to continue to next equation
			i++
		}
	}
	return env, nil
}

// Check if the first (maxIndex + 1) equations are solved
func (system *SelfConsistentSystem) solvedUpTo(env Environment, maxIndex int) bool {
	for i, eq := range system.Equations {
		if i > maxIndex {
			break
		}
		if eq.AbsError(env) > system.Tolerances[i] {
			return false
		}
	}
	return true
}

// Are all the self-consistent equations solved?
func (system *SelfConsistentSystem) IsSolved(env Environment) bool {
	if len(system.Equations) == 0 {
		return true
	}
	return system.solvedUpTo(env, len(system.Equations)-1)
}
<|endoftext|>


<commit_before>package ringbuffer

import (
	"fmt"
	"sync"
	"sync/atomic"
	"time"
)

type RingBuffer struct {
	readIndex  int64      //读序号
	writeIndex int64      //写序号
	buf        []*[]byte  //环形buffer指针数组
	bufSize    int64      //初始化环形buffer指针数组大小
	mask       int64      //初始化环形buffer指针数组大小
	pcond      *sync.Cond //生产者
	ccond      *sync.Cond //消费者
	done       int64      //is done? 1=done; 0=doing
}

func powerOfTwo64(n int64) bool {
	return n != 0 && (n&(n-1)) == 0
}

/**
初始化ringbuffer
参数bufferSize：初始化环形buffer指针数组大小
*/
func NewRingBuffer(size int64) (*RingBuffer, error) {
	if !powerOfTwo64(size) {
		return nil, fmt.Errorf("This size is not able to used")
	}
	buffer := RingBuffer{
		readIndex:  int64(0),
		writeIndex: int64(0),
		buf:        make([]*[]byte, size),
		bufSize:    size,
		mask:       size - int64(1),
		pcond:      sync.NewCond(new(sync.Mutex)),
		ccond:      sync.NewCond(new(sync.Mutex)),
		done:       int64(0),
	}
	for i := int64(0); i < size; i++ {
		buffer.buf[i] = nil
	}
	return &buffer, nil
}

/**
获取当前读序号
*/
func (this *RingBuffer) GetCurrentReadIndex() int64 {
	return atomic.LoadInt64(&this.readIndex)
}

/**
获取当前写序号
*/
func (this *RingBuffer) GetCurrentWriteIndex() int64 {
	return atomic.LoadInt64(&this.writeIndex)
}

/**
读取ringbuffer指定的buffer指针，返回该指针并清空ringbuffer该位置存在的指针内容，以及将读序号加1
*/
func (this *RingBuffer) ReadBuffer() (p *[]byte, ok bool) {
	this.ccond.L.Lock()
	defer func() {
		this.pcond.Broadcast()
		this.ccond.L.Unlock()
	}()
	ok = false
	p = nil
	readIndex := this.GetCurrentReadIndex()
	writeIndex := this.GetCurrentWriteIndex()
	for {
		if this.isDone() {
			return nil, false
		}
		writeIndex = this.GetCurrentWriteIndex()
		if readIndex >= writeIndex {
			//fmt.Println("read wait")
			this.pcond.Broadcast()
			this.ccond.Wait()
		} else {
			break
		}
	}
	index := readIndex & this.mask //替代求模
	p = this.buf[index]
	this.buf[index] = nil
	atomic.AddInt64(&this.readIndex, int64(1))
	if p != nil {
		ok = true
	}
	return p, ok
}

/**
写入ringbuffer指针，以及将写序号加1
*/
func (this *RingBuffer) WriteBuffer(in *[]byte) (ok bool) {
	this.pcond.L.Lock()
	defer func() {
		this.ccond.Broadcast()
		this.pcond.L.Unlock()
	}()
	ok = false
	readIndex := this.GetCurrentReadIndex()
	writeIndex := this.GetCurrentWriteIndex()
	for {
		if this.isDone() {
			return false
		}
		readIndex = this.GetCurrentReadIndex()
		if writeIndex >= readIndex && writeIndex-readIndex >= this.bufSize {
			//fmt.Println("write wait")
			time.Sleep(1 * time.Millisecond)
			this.ccond.Broadcast()
			this.pcond.Wait()
			//time.Sleep(1 * time.Millisecond)
		} else {
			break
		}

	}
	index := writeIndex & this.mask //替代求模
	this.buf[index] = in
	atomic.AddInt64(&this.writeIndex, int64(1))
	ok = true
	return ok
}

func (this *RingBuffer) Close() error {
	atomic.StoreInt64(&this.done, 1)

	this.pcond.L.Lock()
	this.ccond.Broadcast()
	this.pcond.L.Unlock()

	this.ccond.L.Lock()
	this.pcond.Broadcast()
	this.ccond.L.Unlock()

	return nil
}

func (this *RingBuffer) isDone() bool {
	if atomic.LoadInt64(&this.done) == 1 {
		return true
	}

	return false
}
<commit_msg>修改ringbuffer锁<commit_after>package ringbuffer

import (
	"fmt"
	"sync"
	"sync/atomic"
)

type RingBuffer struct {
	readIndex  int64      //读序号
	writeIndex int64      //写序号
	buf        []*[]byte  //环形buffer指针数组
	bufSize    int64      //初始化环形buffer指针数组大小
	mask       int64      //初始化环形buffer指针数组大小
	pcond      *sync.Cond //生产者
	ccond      *sync.Cond //消费者
	done       int64      //is done? 1=done; 0=doing
}

func powerOfTwo64(n int64) bool {
	return n != 0 && (n&(n-1)) == 0
}

/**
初始化ringbuffer
参数bufferSize：初始化环形buffer指针数组大小
*/
func NewRingBuffer(size int64) (*RingBuffer, error) {
	if !powerOfTwo64(size) {
		return nil, fmt.Errorf("This size is not able to used")
	}
	buffer := RingBuffer{
		readIndex:  int64(0),
		writeIndex: int64(0),
		buf:        make([]*[]byte, size),
		bufSize:    size,
		mask:       size - int64(1),
		pcond:      sync.NewCond(new(sync.Mutex)),
		ccond:      sync.NewCond(new(sync.Mutex)),
		done:       int64(0),
	}
	for i := int64(0); i < size; i++ {
		buffer.buf[i] = nil
	}
	return &buffer, nil
}

/**
获取当前读序号
*/
func (this *RingBuffer) GetCurrentReadIndex() int64 {
	return atomic.LoadInt64(&this.readIndex)
}

/**
获取当前写序号
*/
func (this *RingBuffer) GetCurrentWriteIndex() int64 {
	return atomic.LoadInt64(&this.writeIndex)
}

/**
读取ringbuffer指定的buffer指针，返回该指针并清空ringbuffer该位置存在的指针内容，以及将读序号加1
*/
func (this *RingBuffer) ReadBuffer() (p *[]byte, ok bool) {
	this.ccond.L.Lock()
	defer func() {
		this.pcond.Broadcast()
		this.ccond.L.Unlock()
	}()
	ok = false
	p = nil
	readIndex := this.GetCurrentReadIndex()
	writeIndex := this.GetCurrentWriteIndex()
	for {
		if this.isDone() {
			return nil, false
		}
		writeIndex = this.GetCurrentWriteIndex()
		if readIndex >= writeIndex {
			//fmt.Println("read wait")
			this.pcond.Broadcast()
			this.ccond.Wait()
		} else {
			break
		}
	}
	index := readIndex & this.mask //替代求模
	p = this.buf[index]
	this.buf[index] = nil
	atomic.AddInt64(&this.readIndex, int64(1))
	if p != nil {
		ok = true
	}
	return p, ok
}

/**
写入ringbuffer指针，以及将写序号加1
*/
func (this *RingBuffer) WriteBuffer(in *[]byte) (ok bool) {
	this.pcond.L.Lock()
	defer func() {
		this.ccond.Broadcast()
		this.pcond.L.Unlock()
	}()
	ok = false
	readIndex := this.GetCurrentReadIndex()
	writeIndex := this.GetCurrentWriteIndex()
	for {
		if this.isDone() {
			return false
		}
		readIndex = this.GetCurrentReadIndex()
		if writeIndex >= readIndex && writeIndex-readIndex >= this.bufSize {
			//fmt.Println("write wait")
			this.ccond.Broadcast()
			this.pcond.Wait()
			//time.Sleep(1 * time.Millisecond)
		} else {
			break
		}

	}
	index := writeIndex & this.mask //替代求模
	this.buf[index] = in
	atomic.AddInt64(&this.writeIndex, int64(1))
	ok = true
	return ok
}

func (this *RingBuffer) Close() error {
	atomic.StoreInt64(&this.done, 1)

	this.pcond.L.Lock()
	this.ccond.Broadcast()
	this.pcond.L.Unlock()

	this.ccond.L.Lock()
	this.pcond.Broadcast()
	this.ccond.L.Unlock()

	return nil
}

func (this *RingBuffer) isDone() bool {
	if atomic.LoadInt64(&this.done) == 1 {
		return true
	}

	return false
}
<|endoftext|>


<commit_before>package txmanager

import (
	"database/sql"
	"errors"
)

type Dbm interface {
	// Exec executes a query without returning any rows.
	// See sql.DB and sql.Tx for more information.
	Exec(query string, args ...interface{}) (sql.Result, error)

	// Prepare creates a prepared statement for later queries or executions.
	// See sql.DB and sql.Tx for more information.
	Prepare(query string) (*sql.Stmt, error)

	// Query executes a query that returns rows, typically a SELECT.
	// See sql.DB and sql.Tx for more information.
	Query(query string, args ...interface{}) (*sql.Rows, error)

	// QueryRow executes a query that is expected to return at most one row.
	// See sql.DB and sql.Tx for more information.
	QueryRow(query string, args ...interface{}) *sql.Row

	// TxBegin starts a transaction.
	// If the Dbm is a transaction, TxBegin does't do BEGIN at here.
	// It just pushed transaction stack and do nothing.
	TxBegin() (Dbm, error)

	// TxCommit commits the transaction.
	// If the Dbm is in a nested transaction, TxCommit doesn't do COMMIT at here.
	// It just poped transaction stack and do nothing.
	TxCommit() error

	// TxRollback aborts the transaction.
	// TxRollback always does ROLLBACK at here.
	TxRollback() error

	// TxFinish aborts the transaction if it is not commited.
	TxFinish() error
}

type dbm struct {
	*sql.DB
}

type tx struct {
	*sql.Tx
	parent     *tx
	root       *tx
	childCount int
	done       bool
}

func NewDbm(db *sql.DB) Dbm {
	return &dbm{db}
}

func (d *dbm) TxBegin() (Dbm, error) {
	t, err := d.Begin()
	if err != nil {
		return nil, err
	}

	child := &tx{Tx: t}
	child.root = child
	return child, nil
}

func (d *dbm) TxCommit() error {
	return sql.ErrTxDone
}

func (d *dbm) TxRollback() error {
	return sql.ErrTxDone
}

func (d *dbm) TxFinish() error {
	return nil
}

func (t *tx) TxBegin() (Dbm, error) {
	t.childCount++
	child := &tx{
		Tx:     t.Tx,
		parent: t,
		root:   t.root,
	}
	return child, nil
}

func (t *tx) TxCommit() error {
	if t.done || t.root.done {
		return sql.ErrTxDone
	}

	if t.childCount != 0 {
		t.TxRollback()
		return errors.New("txmanager: child transactions are not done")
	}

	t.done = true
	if t.parent == nil {
		err := t.Commit()
		if err != nil {
			return t.Rollback()
		}
	} else {
		t.parent.childCount--
	}
	return nil
}

func (t *tx) TxRollback() error {
	if t.done || t.root.done {
		return sql.ErrTxDone
	}
	t.done = true
	t.root.done = true
	return t.Rollback()
}

func (t *tx) TxFinish() error {
	if t.done || t.root.done {
		return nil
	}
	return t.TxRollback()
}

// Do executes the function in a transaction.
func Do(d Dbm, f func(t Dbm) error) error {
	t, err := d.TxBegin()
	if err != nil {
		return err
	}
	defer t.TxFinish()
	err = f(t)
	if err != nil {
		return err
	}
	return t.TxCommit()
}
<commit_msg>パッケージの説明追加<commit_after>// The txnmanager is a nested transation manager for database/sql.

package txmanager

import (
	"database/sql"
	"errors"
)

var ErrChildrenNotDone = errors.New("txmanager: children transactions are not done")

type Dbm interface {
	// Exec executes a query without returning any rows.
	// See sql.DB and sql.Tx for more information.
	Exec(query string, args ...interface{}) (sql.Result, error)

	// Prepare creates a prepared statement for later queries or executions.
	// See sql.DB and sql.Tx for more information.
	Prepare(query string) (*sql.Stmt, error)

	// Query executes a query that returns rows, typically a SELECT.
	// See sql.DB and sql.Tx for more information.
	Query(query string, args ...interface{}) (*sql.Rows, error)

	// QueryRow executes a query that is expected to return at most one row.
	// See sql.DB and sql.Tx for more information.
	QueryRow(query string, args ...interface{}) *sql.Row

	// TxBegin starts a transaction.
	// If the Dbm is a transaction, TxBegin does't do BEGIN at here.
	// It just pushed transaction stack and do nothing.
	TxBegin() (Dbm, error)

	// TxCommit commits the transaction.
	// If the Dbm is in a nested transaction, TxCommit doesn't do COMMIT at here.
	// It just poped transaction stack and do nothing.
	TxCommit() error

	// TxRollback aborts the transaction.
	// TxRollback always does ROLLBACK at here.
	TxRollback() error

	// TxFinish aborts the transaction if it is not commited.
	TxFinish() error
}

type dbm struct {
	*sql.DB
}

type tx struct {
	*sql.Tx
	parent     *tx
	root       *tx
	childCount int
	done       bool
}

func NewDbm(db *sql.DB) Dbm {
	return &dbm{db}
}

func (d *dbm) TxBegin() (Dbm, error) {
	t, err := d.Begin()
	if err != nil {
		return nil, err
	}

	child := &tx{Tx: t}
	child.root = child
	return child, nil
}

func (d *dbm) TxCommit() error {
	return sql.ErrTxDone
}

func (d *dbm) TxRollback() error {
	return sql.ErrTxDone
}

func (d *dbm) TxFinish() error {
	return nil
}

func (t *tx) TxBegin() (Dbm, error) {
	t.childCount++
	child := &tx{
		Tx:     t.Tx,
		parent: t,
		root:   t.root,
	}
	return child, nil
}

func (t *tx) TxCommit() error {
	if t.done || t.root.done {
		return sql.ErrTxDone
	}

	if t.childCount != 0 {
		t.TxRollback()
		return ErrChildrenNotDone
	}

	t.done = true
	if t.parent == nil {
		err := t.Commit()
		if err != nil {
			return t.Rollback()
		}
	} else {
		t.parent.childCount--
	}
	return nil
}

func (t *tx) TxRollback() error {
	if t.done || t.root.done {
		return sql.ErrTxDone
	}
	t.done = true
	t.root.done = true
	return t.Rollback()
}

func (t *tx) TxFinish() error {
	if t.done || t.root.done {
		return nil
	}
	return t.TxRollback()
}

// Do executes the function in a transaction.
func Do(d Dbm, f func(t Dbm) error) error {
	t, err := d.TxBegin()
	if err != nil {
		return err
	}
	defer t.TxFinish()
	err = f(t)
	if err != nil {
		return err
	}
	return t.TxCommit()
}
<|endoftext|>


<commit_before>package u9

import (
	"github.com/gopherjs/gopherjs/js"
	"honnef.co/go/js/dom"
)

// AddTabSupport is a helper that modifies a <textarea>, so that pressing tab key will insert tabs.
func AddTabSupport(textArea *dom.HTMLTextAreaElement) {
	textArea.AddEventListener("keydown", false, func(event dom.Event) {
		switch ke := event.(*dom.KeyboardEvent); {
		case ke.KeyCode == 9 && !ke.CtrlKey && !ke.AltKey && !ke.MetaKey && !ke.ShiftKey: // Tab.
			value, start, end := textArea.Value, textArea.SelectionStart, textArea.SelectionEnd

			textArea.Value = value[:start] + "\t" + value[end:]

			textArea.SelectionStart, textArea.SelectionEnd = start+1, start+1

			event.PreventDefault()

			// Trigger "input" event listeners.
			inputEvent := js.Global.Get("CustomEvent").New("input")
			textArea.Underlying().Call("dispatchEvent", inputEvent)
		}
	})
}
<commit_msg>u9: Use a more readable constant.<commit_after>package u9

import (
	"github.com/gopherjs/gopherjs/js"
	"honnef.co/go/js/dom"
)

// AddTabSupport is a helper that modifies a <textarea>, so that pressing tab key will insert tabs.
func AddTabSupport(textArea *dom.HTMLTextAreaElement) {
	textArea.AddEventListener("keydown", false, func(event dom.Event) {
		switch ke := event.(*dom.KeyboardEvent); {
		case ke.KeyCode == '\t' && !ke.CtrlKey && !ke.AltKey && !ke.MetaKey && !ke.ShiftKey: // Tab.
			value, start, end := textArea.Value, textArea.SelectionStart, textArea.SelectionEnd

			textArea.Value = value[:start] + "\t" + value[end:]

			textArea.SelectionStart, textArea.SelectionEnd = start+1, start+1

			event.PreventDefault()

			// Trigger "input" event listeners.
			inputEvent := js.Global.Get("CustomEvent").New("input")
			textArea.Underlying().Call("dispatchEvent", inputEvent)
		}
	})
}
<|endoftext|>


<commit_before>/*
Copyright 2017 Google Inc.

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

    https://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 v1alpha1

import (
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
)

// +genclient
// +genclient:noStatus
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

type CompositeController struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata"`

	Spec   CompositeControllerSpec   `json:"spec"`
	Status CompositeControllerStatus `json:"status,omitempty"`
}

type CompositeControllerSpec struct {
	ParentResource ResourceRule   `json:"parentResource"`
	ChildResources []ResourceRule `json:"childResources,omitempty"`

	ClientConfig ClientConfig             `json:"clientConfig,omitempty"`
	Hooks        CompositeControllerHooks `json:"hooks,omitempty"`

	GenerateSelector bool `json:"generateSelector,omitempty"`
}

type ResourceRule struct {
	APIVersion string `json:"apiVersion"`
	Resource   string `json:"resource"`
}

type ClientConfig struct {
	Service ServiceReference `json:"service,omitempty"`
}

type ServiceReference struct {
	Name      string `json:"name"`
	Namespace string `json:"namespace"`
}

type CompositeControllerHooks struct {
	Sync CompositeControllerSyncHook `json:"sync,omitempty"`
}

type CompositeControllerSyncHook struct {
	Path string `json:"path"`
}

type CompositeControllerStatus struct {
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

type CompositeControllerList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata"`
	Items           []CompositeController `json:"items"`
}

// +genclient
// +genclient:noStatus
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

type ControllerRevision struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata"`

	Revision    int64                        `json:"revision"`
	ParentPatch runtime.RawExtension         `json:"parentPatch"`
	Children    []ControllerRevisionChildren `json:"children,omitempty"`
}

type ControllerRevisionChildren struct {
	APIGroup string   `json:"apiGroup"`
	Kind     string   `json:"kind"`
	Names    []string `json:"names"`
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

type ControllerRevisionList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata"`
	Items           []ControllerRevision `json:"items"`
}

// +genclient
// +genclient:noStatus
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

type InitializerController struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata"`
	Spec              InitializerControllerSpec   `json:"spec"`
	Status            InitializerControllerStatus `json:"status,omitempty"`
}

type InitializerControllerSpec struct {
	InitializerName        string                     `json:"initializerName"`
	UninitializedResources []ResourceRule             `json:"uninitializedResources,omitempty"`
	ClientConfig           ClientConfig               `json:"clientConfig,omitempty"`
	Hooks                  InitializerControllerHooks `json:"hooks,omitempty"`
}

type InitializerControllerHooks struct {
	Init InitializerControllerInitHook `json:"init,omitempty"`
}

type InitializerControllerInitHook struct {
	Path string `json:"path"`
}

type InitializerControllerStatus struct {
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

type InitializerControllerList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata"`
	Items           []InitializerController `json:"items"`
}
<commit_msg>rolling update: Add CompositeController configuration types.<commit_after>/*
Copyright 2017 Google Inc.

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

    https://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 v1alpha1

import (
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
)

// +genclient
// +genclient:noStatus
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

type CompositeController struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata"`

	Spec   CompositeControllerSpec   `json:"spec"`
	Status CompositeControllerStatus `json:"status,omitempty"`
}

type CompositeControllerSpec struct {
	ParentResource ParentResourceRule  `json:"parentResource"`
	ChildResources []ChildResourceRule `json:"childResources,omitempty"`

	ClientConfig ClientConfig             `json:"clientConfig,omitempty"`
	Hooks        CompositeControllerHooks `json:"hooks,omitempty"`

	GenerateSelector bool `json:"generateSelector,omitempty"`
}

type ResourceRule struct {
	APIVersion string `json:"apiVersion"`
	Resource   string `json:"resource"`
}

type ParentResourceRule struct {
	ResourceRule    `json:",inline"`
	RevisionHistory *CompositeControllerRevisionHistory `json:"revisionHistory,omitempty"`
}

type CompositeControllerRevisionHistory struct {
	FieldPaths []string `json:"fieldPaths,omitempty"`
}

type ChildUpdateMethod string

const (
	ChildUpdateOnDelete ChildUpdateMethod = "OnDelete"
	ChildUpdateRecreate ChildUpdateMethod = "Recreate"
	ChildUpdateInPlace  ChildUpdateMethod = "InPlace"
)

type ChildResourceRule struct {
	ResourceRule   `json:",inline"`
	UpdateStrategy *ChildUpdateStrategy `json:"updateStrategy,omitempty"`
}

type ChildUpdateStrategy struct {
	Method       ChildUpdateMethod       `json:"method,omitempty"`
	StatusChecks ChildUpdateStatusChecks `json:"statusChecks,omitempty"`
}

type ChildUpdateStatusChecks struct {
	Conditions []StatusConditionCheck `json:"conditions,omitempty"`
}

type StatusConditionCheck struct {
	Type   string  `json:"type"`
	Status *string `json:"status,omitempty"`
	Reason *string `json:"reason,omitempty"`
}

type ClientConfig struct {
	Service ServiceReference `json:"service,omitempty"`
}

type ServiceReference struct {
	Name      string `json:"name"`
	Namespace string `json:"namespace"`
}

type CompositeControllerHooks struct {
	Sync *CompositeControllerSyncHook `json:"sync,omitempty"`

	PreUpdateChild  *CompositeControllerPreUpdateChildHook  `json:"preUpdateChild,omitempty"`
	PostUpdateChild *CompositeControllerPostUpdateChildHook `json:"postUpdateChild,omitempty"`
}

type CompositeControllerSyncHook struct {
	Path string `json:"path"`
}

type CompositeControllerPreUpdateChildHook struct {
	Path string `json:"path"`
}

type CompositeControllerPostUpdateChildHook struct {
	Path string `json:"path"`
}

type CompositeControllerStatus struct {
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

type CompositeControllerList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata"`
	Items           []CompositeController `json:"items"`
}

// +genclient
// +genclient:noStatus
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

type ControllerRevision struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata"`

	ParentPatch runtime.RawExtension         `json:"parentPatch"`
	Children    []ControllerRevisionChildren `json:"children,omitempty"`
}

type ControllerRevisionChildren struct {
	APIGroup string   `json:"apiGroup"`
	Kind     string   `json:"kind"`
	Names    []string `json:"names"`
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

type ControllerRevisionList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata"`
	Items           []ControllerRevision `json:"items"`
}

// +genclient
// +genclient:noStatus
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

type InitializerController struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata"`
	Spec              InitializerControllerSpec   `json:"spec"`
	Status            InitializerControllerStatus `json:"status,omitempty"`
}

type InitializerControllerSpec struct {
	InitializerName        string                     `json:"initializerName"`
	UninitializedResources []ResourceRule             `json:"uninitializedResources,omitempty"`
	ClientConfig           ClientConfig               `json:"clientConfig,omitempty"`
	Hooks                  InitializerControllerHooks `json:"hooks,omitempty"`
}

type InitializerControllerHooks struct {
	Init InitializerControllerInitHook `json:"init,omitempty"`
}

type InitializerControllerInitHook struct {
	Path string `json:"path"`
}

type InitializerControllerStatus struct {
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

type InitializerControllerList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata"`
	Items           []InitializerController `json:"items"`
}
<|endoftext|>


<commit_before>package restic

import (
	"io"

	"github.com/leeola/errors"
	"github.com/leeola/fixity"
	"github.com/restic/chunker"
)

type Roller struct {
	buf     []byte
	chunker *chunker.Chunker
}

func New(r io.Reader, min, max int64) (*Roller, error) {
	if r == nil {
		return nil, errors.New("missing Reader")
	}

	return &Roller{
		// does this size matter?
		buf:     make([]byte, 8*1024*1024),
		chunker: chunker.NewWithBoundaries(r, chunker.Pol(0x3DA3358B4DC173), uint(min), uint(max)),
	}, nil
}

func (c *Roller) Roll() (fixity.Chunk, error) {
	// TODO(leeola): Add a peek method to break out of the loop if the end of the
	// roller is near. This way we don't create small tailing chunks if possible.

	chunk, err := c.chunker.Next(c.buf)
	// eof is okay to pass on immediately
	if err != nil {
		return fixity.Chunk{}, err
	}

	return fixity.Chunk{
		ChunkBytes: chunk.Data,
		Size:       int64(chunk.Length),
	}, nil
}
<commit_msg>feat: use forked chunker with custom average bits value<commit_after>package restic

import (
	"io"

	"github.com/leeola/chunker"
	"github.com/leeola/errors"
	"github.com/leeola/fixity"
)

// averageBits of 14 is resulting in roughly chunks of 12KiB by default.
//
// This size should be low enough to allow small writes to be split up,
// even at the cost of write performance (within reason).
const averageBits = 14

type Roller struct {
	buf     []byte
	chunker *chunker.Chunker
}

func New(r io.Reader, min, max int64) (*Roller, error) {
	if r == nil {
		return nil, errors.New("missing Reader")
	}

	return &Roller{
		// does this size matter?
		buf: make([]byte, 8*1024*1024),
		chunker: chunker.NewWithConfig(r, chunker.Pol(0x3DA3358B4DC173),
			chunker.ChunkerConfig{
				MinSize:     uint(min),
				MaxSize:     uint(max),
				AverageBits: averageBits,
			}),
	}, nil
}

func (c *Roller) Roll() (fixity.Chunk, error) {
	// TODO(leeola): Add a peek method to break out of the loop if the end of the
	// roller is near. This way we don't create small tailing chunks if possible.

	chunk, err := c.chunker.Next(c.buf)
	// eof is okay to pass on immediately
	if err != nil {
		return fixity.Chunk{}, err
	}

	return fixity.Chunk{
		ChunkBytes: chunk.Data,
		Size:       int64(chunk.Length),
	}, nil
}
<|endoftext|>


<commit_before>package main
import "github.com/donomii/throfflib"

import (

	"os"
	"fmt"
	_ "net/http/pprof"
	//"log"
	//"net/http"

)

func main () {
	go func() {
			//log.Println(http.ListenAndServe("localhost:6060", nil))
	}()
	t := throfflib.MakeEngine()
	t = throfflib.LoadGraphics(t)
	t = throfflib.LoadAudio(t)
	strs := os.Args[1:]
	//t = t.RunFile("bootstrapgo.lib")
	t = t.RunString(throfflib.BootStrapString(), "Internal Bootstrap")
	if len(strs) == 0 {
		t = t.RunString("PRINTLN [ Welcome to the THROFF command shell v0.1.  Type HELP for help. ]", "repl")
		throfflib.Repl(t)
	} else {

		fmt.Printf("")
		tokens := throfflib.StringsToTokens(strs)
		t.LoadTokens(tokens)
		t=t.Run()
		t.RunString("PRINTLN", "replprint")
	}
}
<commit_msg>Removed portaudio library<commit_after>package main
import "github.com/donomii/throfflib"

import (

	"os"
	"fmt"
	_ "net/http/pprof"
	//"log"
	//"net/http"

)

func main () {
	go func() {
			//log.Println(http.ListenAndServe("localhost:6060", nil))
	}()
	t := throfflib.MakeEngine()
	t = throfflib.LoadGraphics(t)
	//t = throfflib.LoadAudio(t)
	strs := os.Args[1:]
	//t = t.RunFile("bootstrapgo.lib")
	t = t.RunString(throfflib.BootStrapString(), "Internal Bootstrap")
	if len(strs) == 0 {
		t = t.RunString("PRINTLN [ Welcome to the THROFF command shell v0.1.  Type HELP for help. ]", "repl")
		throfflib.Repl(t)
	} else {

		fmt.Printf("")
		tokens := throfflib.StringsToTokens(strs)
		t.LoadTokens(tokens)
		t=t.Run()
		t.RunString("PRINTLN", "replprint")
	}
}
<|endoftext|>