<commit_before>package aerospike

import (
	"fmt"
	"time"
    "os"
    "strings"
    "os/exec"
	log "github.com/Sirupsen/logrus"
	"github.com/ehazlett/interlock"
	"github.com/ehazlett/interlock/plugins"
	"github.com/samalba/dockerclient"
)

type AerospikePlugin struct {
    pluginConfig    *PluginConfig
	interlockConfig *interlock.Config
	client          *dockerclient.DockerClient
}

func init() {
	plugins.Register(
		pluginInfo.Name,
		&plugins.RegisteredPlugin{
			New: NewPlugin,
			Info: func() *interlock.PluginInfo {
				return pluginInfo
			},
		})
}

func loadPluginConfig() (*PluginConfig, error) {
    cfg := &PluginConfig{
        ClusterName:    "aerospike",
		NetworkName:	"docker",
		MeshPort:		"3002",
    }
    clusterName  := os.Getenv("AEROSPIKE_CLUSTER_NAME")
    if clusterName != "" {
        cfg.ClusterName = clusterName
    }
    networkName := os.Getenv("AEROSPIKE_NETWORK_NAME")
    if networkName != "" {
        cfg.NetworkName = networkName
    }
    meshPort := os.Getenv("AEROSPIKE_MESH_PORT")
    if meshPort != "" {
        cfg.MeshPort = meshPort
    }
    return cfg, nil
}

func NewPlugin(interlockConfig *interlock.Config, client *dockerclient.DockerClient) (interlock.Plugin, error) {
	//return ExamplePlugin{interlockConfig: interlockConfig, client: client}, nil
    pluginConfig, err := loadPluginConfig()
    if err != nil {
        return nil, err
    }

    plugin := AerospikePlugin{
        pluginConfig:    pluginConfig,
        interlockConfig: interlockConfig,
        client:          client,
    }

    return plugin, nil
}

func (p AerospikePlugin) Info() *interlock.PluginInfo {
	return pluginInfo
}

func (p AerospikePlugin) HandleEvent(event *dockerclient.Event) error {

    switch event.Status {
    case "start":
        if err := p.clusterAerospike(event); err != nil{
            return err
        }
    }
    return nil
}

func (p AerospikePlugin) contains(containers []string, event *dockerclient.Event) bool {
	for _,a := range containers {
		if a == event.Id[:12]{
			return true
		}
	}
	return false
}
func (p AerospikePlugin) runDocker(command string, args ...string) (output []byte, err error){
	docker, err := exec.LookPath("docker")
    if err != nil {
        log.Errorf("error finding docker binary: %s",err)
        return nil,err
    }
    dockerArgs := []string{
    	"-H="+p.interlockConfig.SwarmUrl,
    	"--tlsverify=1",
    	"--tlscacert="+p.interlockConfig.TLSCaCert,
    	"--tlscert="+p.interlockConfig.TLSCert,
    	"--tlskey="+p.interlockConfig.TLSKey,
    	command,
    }
    dockerArgs =append(dockerArgs,args...)
    plugins.Log(pluginInfo.Name, log.DebugLevel, fmt.Sprintf("DOCKER ARGS  %+v",dockerArgs))
    return exec.Command(docker,dockerArgs...).Output()

}
func (p AerospikePlugin) runAsinfoTip(args ...string) bool{
	asinfo, err := exec.LookPath("asinfo")
    if err != nil{
    	log.Errorf("error finding asinfo binary: %s", err)
        return false
    }
    time.Sleep(time.Second*5)	//sleep 5s for ASD to be ready
    cmd := exec.Command(asinfo,args...)
    plugins.Log(pluginInfo.Name, log.DebugLevel,fmt.Sprintf("asinfo COMMANMD: %+v", cmd))
    if output,err := cmd.Output(); err != nil {
        log.Errorf("error running asinfo: %s",err)
        plugins.Log(pluginInfo.Name, log.DebugLevel,fmt.Sprintf("asinfo output: %+v", output))
        return false
    }
    plugins.Log(pluginInfo.Name, log.DebugLevel,fmt.Sprintf("Sending asinfo: %s %+v", asinfo, args))
    return true
}
func (p AerospikePlugin) clusterAerospike(event *dockerclient.Event) error {

    // scan all running containers
    plugins.Log(pluginInfo.Name, log.InfoLevel,fmt.Sprintf("status= %s",event.Status))

    filter := "label=com.aerospike.cluster="+p.pluginConfig.ClusterName
    args := []string{"-q","--filter",filter}
    filterOut, err := p.runDocker("ps",args...)

    if err != nil  {
        log.Errorf("error running docker: %s",err)
        return err
    }
    containers := strings.Split(string(filterOut),"\n")
    if ! p.contains(containers, event) {
    	plugins.Log(pluginInfo.Name, log.InfoLevel, fmt.Sprintf("CONTAINER not part of Aerospike Cluster"))
    	return nil
    }
    plugins.Log(pluginInfo.Name, log.DebugLevel, fmt.Sprintf("Containers= %s", containers))

	for _,cnt := range containers {
		plugins.Log(pluginInfo.Name, log.DebugLevel,fmt.Sprintf("ContainerID=%v EventID=%v",cnt, event.Id[:12]))

    	if cnt == event.Id[:12] || cnt == ""{
            continue
        }
    	cInfo,_ := p.client.InspectContainer(cnt) // missing network info

	    inspectArgs := []string{
	    	"-f",
	    	"{{.NetworkSettings.Networks."+p.pluginConfig.NetworkName+".IPAddress}}",
	    	event.Id,
	    }
	    cmdOut, err := p.runDocker("inspect",inspectArgs...)
	    if err != nil {
	        log.Errorf("error running docker: %s",err)
	        return err
	    }
	    plugins.Log(pluginInfo.Name, log.DebugLevel, fmt.Sprintf("DOCKER OUTPUT %+v",string(cmdOut)))

	    // strip trailing newline
	    ip := string(cmdOut)
	    ipLen := len(ip)-1
	    if ipLen > 0 {
	    	ip = ip[:ipLen]
	    }
	    if len(cInfo.Name) > 0{
		    infoArgs := []string{
		    	"-h",
		    	cInfo.Name[1:],    //strip leading / from cInfo.Name
		    	"-v",
		    	"tip:host="+ip[:ipLen]+";port="+p.pluginConfig.MeshPort,
		    }
			plugins.Log(pluginInfo.Name, log.InfoLevel, fmt.Sprintf("ARGS  %+v",infoArgs))
			p.runAsinfoTip(infoArgs...)
		}else{
			log.Errorf("Container name not found")
		}
    }
	return nil
}

func (p AerospikePlugin) Init() error {
	return nil
}
<commit_msg>Fixed duplicate event<commit_after>package aerospike

import (
	"fmt"
	"time"
    "os"
    "strings"
    "os/exec"
	log "github.com/Sirupsen/logrus"
	"github.com/ehazlett/interlock"
	"github.com/ehazlett/interlock/plugins"
	"github.com/samalba/dockerclient"
)

type AerospikePlugin struct {
    pluginConfig    *PluginConfig
	interlockConfig *interlock.Config
	client          *dockerclient.DockerClient
}

func init() {
	plugins.Register(
		pluginInfo.Name,
		&plugins.RegisteredPlugin{
			New: NewPlugin,
			Info: func() *interlock.PluginInfo {
				return pluginInfo
			},
		})
}

func loadPluginConfig() (*PluginConfig, error) {
    cfg := &PluginConfig{
        ClusterName:    "aerospike",
		NetworkName:	"docker",
		MeshPort:		"3002",
    }
    clusterName  := os.Getenv("AEROSPIKE_CLUSTER_NAME")
    if clusterName != "" {
        cfg.ClusterName = clusterName
    }
    networkName := os.Getenv("AEROSPIKE_NETWORK_NAME")
    if networkName != "" {
        cfg.NetworkName = networkName
    }
    meshPort := os.Getenv("AEROSPIKE_MESH_PORT")
    if meshPort != "" {
        cfg.MeshPort = meshPort
    }
    return cfg, nil
}

func NewPlugin(interlockConfig *interlock.Config, client *dockerclient.DockerClient) (interlock.Plugin, error) {
	//return ExamplePlugin{interlockConfig: interlockConfig, client: client}, nil
    pluginConfig, err := loadPluginConfig()
    if err != nil {
        return nil, err
    }

    plugin := AerospikePlugin{
        pluginConfig:    pluginConfig,
        interlockConfig: interlockConfig,
        client:          client,
    }

    return plugin, nil
}

func (p AerospikePlugin) Info() *interlock.PluginInfo {
	return pluginInfo
}

func (p AerospikePlugin) HandleEvent(event *dockerclient.Event) error {
    switch event.Status {
    case "start":
        if err := p.clusterAerospike(event.Id[:12]); err != nil{
            return err
        }
    }
    return nil
}

func (p AerospikePlugin) contains(containers []string, eventId string) bool {
	for _,a := range containers {
		if a == eventId{
			return true
		}
	}
	return false
}
func (p AerospikePlugin) runDocker(command string, args ...string) (output []byte, err error){
	docker, err := exec.LookPath("docker")
    if err != nil {
        log.Errorf("error finding docker binary: %s",err)
        return nil,err
    }
    dockerArgs := []string{
    	"-H="+p.interlockConfig.SwarmUrl,
    	"--tlsverify=1",
    	"--tlscacert="+p.interlockConfig.TLSCaCert,
    	"--tlscert="+p.interlockConfig.TLSCert,
    	"--tlskey="+p.interlockConfig.TLSKey,
    	command,
    }
    dockerArgs =append(dockerArgs,args...)
    plugins.Log(pluginInfo.Name, log.DebugLevel, fmt.Sprintf("DOCKER ARGS  %+v",dockerArgs))
    return exec.Command(docker,dockerArgs...).Output()

}
func (p AerospikePlugin) runAsinfoTip(args ...string) bool{
	asinfo, err := exec.LookPath("asinfo")
    if err != nil{
    	log.Errorf("error finding asinfo binary: %s", err)
        return false
    }
    time.Sleep(time.Second*5)	//sleep 5s for ASD to be ready
    cmd := exec.Command(asinfo,args...)
    plugins.Log(pluginInfo.Name, log.DebugLevel,fmt.Sprintf("asinfo COMMANMD: %+v", cmd))
    if output,err := cmd.Output(); err != nil {
        log.Errorf("error running asinfo: %s",err)
        plugins.Log(pluginInfo.Name, log.DebugLevel,fmt.Sprintf("asinfo output: %+v", output))
        return false
    }
    plugins.Log(pluginInfo.Name, log.DebugLevel,fmt.Sprintf("Sending asinfo: %s %+v", asinfo, args))
    return true
}
func (p AerospikePlugin) clusterAerospike(eventId string) error {

    // scan all running containers
    filter := "label=com.aerospike.cluster="+p.pluginConfig.ClusterName
    args := []string{"-q","--filter",filter}
    filterOut, err := p.runDocker("ps",args...)

    if err != nil  {
        log.Errorf("error running docker: %s",err)
        return err
    }
    containers := strings.Split(string(filterOut),"\n")
    if ! p.contains(containers, eventId) {
    	plugins.Log(pluginInfo.Name, log.InfoLevel, fmt.Sprintf("CONTAINER %s not part of Aerospike Cluster",eventId))
    	return nil
    }
    plugins.Log(pluginInfo.Name, log.DebugLevel, fmt.Sprintf("Containers= %s", containers))

	for _,cnt := range containers {
		plugins.Log(pluginInfo.Name, log.DebugLevel,fmt.Sprintf("ContainerID=%v EventID=%v",cnt, eventId))

    	if cnt == eventId || cnt == ""{
            continue
        }
    	cInfo,_ := p.client.InspectContainer(cnt) // missing network info

	    inspectArgs := []string{
	    	"-f",
	    	"{{.NetworkSettings.Networks."+p.pluginConfig.NetworkName+".IPAddress}}",
	    	eventId,
	    }
	    cmdOut, err := p.runDocker("inspect",inspectArgs...)
	    if err != nil {
	        log.Errorf("error running docker: %s",err)
	        return err
	    }
	    plugins.Log(pluginInfo.Name, log.DebugLevel, fmt.Sprintf("DOCKER OUTPUT %+v",string(cmdOut)))

	    // strip trailing newline
	    ip := string(cmdOut)
	    ipLen := len(ip)-1
	    if ipLen > 0 {
	    	ip = ip[:ipLen]
	    }
	    if len(cInfo.Name) > 0{
		    infoArgs := []string{
		    	"-h",
		    	cInfo.Name[1:],    //strip leading / from cInfo.Name
		    	"-v",
		    	"tip:host="+ip[:ipLen]+";port="+p.pluginConfig.MeshPort,
		    }
			plugins.Log(pluginInfo.Name, log.InfoLevel, fmt.Sprintf("ARGS  %+v",infoArgs))
			p.runAsinfoTip(infoArgs...)
		}else{
			log.Errorf("Container name not found")
		}
    }
	return nil
}

func (p AerospikePlugin) Init() error {
	return nil
}
<|endoftext|>


<commit_before>package tmpl

import (
	"bytes"
	"html/template"
	"strings"
	"time"

	"fmt"

	"strconv"

	"bitbucket.org/mundipagg/boletoapi/models"
)

var funcMap = template.FuncMap{
	"today":            today,
	"brdate":           brDate,
	"replace":          replace,
	"docType":          docType,
	"trim":             trim,
	"padLeft":          padLeft,
	"toString":         toString,
	"fmtDigitableLine": fmtDigitableLine,
	"fmtCNPJ":          fmtCNPJ,
	"fmtCPF":           fmtCPF,
	"attr": func(s string) template.HTMLAttr {
		return template.HTMLAttr(s)
	},
}

func toString(number int) string {
	return strconv.Itoa(number)
}

func padLeft(value, char string, total uint) string {
	s := "%" + char + strconv.Itoa(int(total)) + "s"
	return fmt.Sprintf(s, value)
}

func today() time.Time {
	return time.Now()
}

func brDate(d time.Time) string {
	return d.Format("02/01/2006")
}

func replace(str, old, new string) string {
	return strings.Replace(str, old, new, -1)
}

func docType(s models.DocumentType) int {
	if s.IsCpf() {
		return 1
	}
	return 2
}

func trim(s string) string {
	return strings.TrimSpace(s)
}
func fmtDigitableLine(s string) string {
	buf := bytes.Buffer{}
	for idx, c := range s {
		if idx == 5 || idx == 15 || idx == 26 {
			buf.WriteString(".")
		}
		if idx == 10 || idx == 21 || idx == 32 || idx == 33 {
			buf.WriteString(" ")
		}
		buf.WriteByte(byte(c))
	}
	return buf.String()
}

func fmtCNPJ(s string) string {
	buf := bytes.Buffer{}
	for idx, c := range s {
		if idx == 2 || idx == 5 {
			buf.WriteString(".")
		}
		if idx == 8 {
			buf.WriteString("/")
		}
		if idx == 12 {
			buf.WriteString("-")
		}
		buf.WriteRune(c)
	}
	return buf.String()
}

func fmtCPF(s string) string {
	buf := bytes.Buffer{}
	for idx, c := range s {
		if idx == 3 || idx == 6 {
			buf.WriteString(".")
		}
		if idx == 9 {
			buf.WriteString("-")
		}
		buf.WriteRune(c)
	}
	return buf.String()
}
<commit_msg>:art: remove funcao duplicada<commit_after>package tmpl

import (
	"bytes"
	"html/template"
	"strings"
	"time"

	"strconv"

	"bitbucket.org/mundipagg/boletoapi/models"
	"bitbucket.org/mundipagg/boletoapi/util"
)

var funcMap = template.FuncMap{
	"today":            today,
	"brdate":           brDate,
	"replace":          replace,
	"docType":          docType,
	"trim":             trim,
	"padLeft":          util.PadLeft,
	"toString":         toString,
	"fmtDigitableLine": fmtDigitableLine,
	"fmtCNPJ":          fmtCNPJ,
	"fmtCPF":           fmtCPF,
	"attr": func(s string) template.HTMLAttr {
		return template.HTMLAttr(s)
	},
}

func toString(number int) string {
	return strconv.Itoa(number)
}

func today() time.Time {
	return time.Now()
}

func brDate(d time.Time) string {
	return d.Format("02/01/2006")
}

func replace(str, old, new string) string {
	return strings.Replace(str, old, new, -1)
}

func docType(s models.DocumentType) int {
	if s.IsCpf() {
		return 1
	}
	return 2
}

func trim(s string) string {
	return strings.TrimSpace(s)
}
func fmtDigitableLine(s string) string {
	buf := bytes.Buffer{}
	for idx, c := range s {
		if idx == 5 || idx == 15 || idx == 26 {
			buf.WriteString(".")
		}
		if idx == 10 || idx == 21 || idx == 32 || idx == 33 {
			buf.WriteString(" ")
		}
		buf.WriteByte(byte(c))
	}
	return buf.String()
}

func fmtCNPJ(s string) string {
	buf := bytes.Buffer{}
	for idx, c := range s {
		if idx == 2 || idx == 5 {
			buf.WriteString(".")
		}
		if idx == 8 {
			buf.WriteString("/")
		}
		if idx == 12 {
			buf.WriteString("-")
		}
		buf.WriteRune(c)
	}
	return buf.String()
}

func fmtCPF(s string) string {
	buf := bytes.Buffer{}
	for idx, c := range s {
		if idx == 3 || idx == 6 {
			buf.WriteString(".")
		}
		if idx == 9 {
			buf.WriteString("-")
		}
		buf.WriteRune(c)
	}
	return buf.String()
}
<|endoftext|>


<commit_before>package application

import (
	"fmt"
	"github.com/getsentry/raven-go"
	"github.com/jmoiron/jsonq"
	"github.com/thoas/gostorages"
	"github.com/thoas/picfit/dummy"
	"github.com/thoas/picfit/engines"
	"github.com/thoas/picfit/util"
)

type Initializer func(jq *jsonq.JsonQuery, app *Application) error

var Initializers = []Initializer{
	KVStoreInitializer,
	StorageInitializer,
	ShardInitializer,
	BasicInitializer,
	SentryInitializer,
}

var KVStores = map[string]KVStoreParameter{
	"redis": RedisKVStoreParameter,
	"cache": CacheKVStoreParameter,
}

var Storages = map[string]StorageParameter{
	"http+s3": HTTPS3StorageParameter,
	"s3":      S3StorageParameter,
	"http+fs": HTTPFileSystemStorageParameter,
	"fs":      FileSystemStorageParameter,
}

var SentryInitializer Initializer = func(jq *jsonq.JsonQuery, app *Application) error {
	dsn, err := jq.String("sentry", "dsn")

	if err != nil {
		return nil
	}

	results, err := jq.Object("sentry", "tags")

	var tags map[string]string

	if err != nil {
		tags = map[string]string{}
	} else {
		tags = util.MapInterfaceToMapString(results)
	}

	client, err := raven.NewClient(dsn, tags)

	if err != nil {
		return err
	}

	app.Raven = client

	return nil
}

var BasicInitializer Initializer = func(jq *jsonq.JsonQuery, app *Application) error {
	var format string
	var quality int

	f, _ := jq.String("options", "format")

	if f != "" {
		format = f
	}

	q, err := jq.Int("options", "quality")

	if err != nil {
		quality = q
	} else {
		quality = DefaultQuality
	}

	app.SecretKey, _ = jq.String("secret_key")
	app.Engine = &engines.GoImageEngine{
		DefaultFormat:  DefaultFormat,
		Format:         format,
		DefaultQuality: quality,
	}

	enableUpload, err := jq.Bool("options", "enable_upload")

	if err == nil {
		app.EnableUpload = enableUpload
	}

	return nil
}

var ShardInitializer Initializer = func(jq *jsonq.JsonQuery, app *Application) error {
	width, err := jq.Int("shard", "width")

	if err != nil {
		width = DefaultShardWidth
	}

	depth, err := jq.Int("shard", "depth")

	if err != nil {
		depth = DefaultShardDepth
	}

	app.Shard = Shard{Width: width, Depth: depth}

	return nil
}

var KVStoreInitializer Initializer = func(jq *jsonq.JsonQuery, app *Application) error {
	_, err := jq.Object("kvstore")

	if err != nil {
		app.KVStore = &dummy.DummyKVStore{}

		return nil
	}

	key, err := jq.String("kvstore", "type")

	if err != nil {
		return err
	}

	parameter, ok := KVStores[key]

	if !ok {
		return fmt.Errorf("KVStore %s does not exist", key)
	}

	config, err := jq.Object("kvstore")

	if err != nil {
		return err
	}

	params := util.MapInterfaceToMapString(config)
	store, err := parameter(params)

	if err != nil {
		return err
	}

	app.Prefix = params["prefix"]
	app.KVStore = store

	return nil
}

func getStorageFromConfig(key string, jq *jsonq.JsonQuery) (gostorages.Storage, error) {
	storageType, err := jq.String("storage", key, "type")

	parameter, ok := Storages[storageType]

	if !ok {
		return nil, fmt.Errorf("Storage %s does not exist", key)
	}

	config, err := jq.Object("storage", key)

	if err != nil {
		return nil, err
	}

	storage, err := parameter(util.MapInterfaceToMapString(config))

	if err != nil {
		return nil, err
	}

	return storage, err
}

var StorageInitializer Initializer = func(jq *jsonq.JsonQuery, app *Application) error {
	_, err := jq.Object("storage")

	if err != nil {
		app.SourceStorage = &dummy.DummyStorage{}
		app.DestStorage = &dummy.DummyStorage{}

		return nil
	}

	sourceStorage, err := getStorageFromConfig("src", jq)

	if err != nil {
		return err
	}

	app.SourceStorage = sourceStorage

	destStorage, err := getStorageFromConfig("dst", jq)

	if err != nil {
		app.DestStorage = sourceStorage
	} else {
		app.DestStorage = destStorage
	}

	return nil
}
<commit_msg>Fix DefaultQuality parameter in config<commit_after>package application

import (
	"fmt"
	"github.com/getsentry/raven-go"
	"github.com/jmoiron/jsonq"
	"github.com/thoas/gostorages"
	"github.com/thoas/picfit/dummy"
	"github.com/thoas/picfit/engines"
	"github.com/thoas/picfit/util"
)

type Initializer func(jq *jsonq.JsonQuery, app *Application) error

var Initializers = []Initializer{
	KVStoreInitializer,
	StorageInitializer,
	ShardInitializer,
	BasicInitializer,
	SentryInitializer,
}

var KVStores = map[string]KVStoreParameter{
	"redis": RedisKVStoreParameter,
	"cache": CacheKVStoreParameter,
}

var Storages = map[string]StorageParameter{
	"http+s3": HTTPS3StorageParameter,
	"s3":      S3StorageParameter,
	"http+fs": HTTPFileSystemStorageParameter,
	"fs":      FileSystemStorageParameter,
}

var SentryInitializer Initializer = func(jq *jsonq.JsonQuery, app *Application) error {
	dsn, err := jq.String("sentry", "dsn")

	if err != nil {
		return nil
	}

	results, err := jq.Object("sentry", "tags")

	var tags map[string]string

	if err != nil {
		tags = map[string]string{}
	} else {
		tags = util.MapInterfaceToMapString(results)
	}

	client, err := raven.NewClient(dsn, tags)

	if err != nil {
		return err
	}

	app.Raven = client

	return nil
}

var BasicInitializer Initializer = func(jq *jsonq.JsonQuery, app *Application) error {
	var format string
	var quality int

	f, _ := jq.String("options", "format")

	if f != "" {
		format = f
	}

	q, err := jq.Int("options", "quality")

	if err != nil {
		quality = q
	}

	if quality == 0 {
		quality = DefaultQuality
	}

	app.SecretKey, _ = jq.String("secret_key")
	app.Engine = &engines.GoImageEngine{
		DefaultFormat:  DefaultFormat,
		Format:         format,
		DefaultQuality: quality,
	}

	enableUpload, err := jq.Bool("options", "enable_upload")

	if err == nil {
		app.EnableUpload = enableUpload
	}

	return nil
}

var ShardInitializer Initializer = func(jq *jsonq.JsonQuery, app *Application) error {
	width, err := jq.Int("shard", "width")

	if err != nil {
		width = DefaultShardWidth
	}

	depth, err := jq.Int("shard", "depth")

	if err != nil {
		depth = DefaultShardDepth
	}

	app.Shard = Shard{Width: width, Depth: depth}

	return nil
}

var KVStoreInitializer Initializer = func(jq *jsonq.JsonQuery, app *Application) error {
	_, err := jq.Object("kvstore")

	if err != nil {
		app.KVStore = &dummy.DummyKVStore{}

		return nil
	}

	key, err := jq.String("kvstore", "type")

	if err != nil {
		return err
	}

	parameter, ok := KVStores[key]

	if !ok {
		return fmt.Errorf("KVStore %s does not exist", key)
	}

	config, err := jq.Object("kvstore")

	if err != nil {
		return err
	}

	params := util.MapInterfaceToMapString(config)
	store, err := parameter(params)

	if err != nil {
		return err
	}

	app.Prefix = params["prefix"]
	app.KVStore = store

	return nil
}

func getStorageFromConfig(key string, jq *jsonq.JsonQuery) (gostorages.Storage, error) {
	storageType, err := jq.String("storage", key, "type")

	parameter, ok := Storages[storageType]

	if !ok {
		return nil, fmt.Errorf("Storage %s does not exist", key)
	}

	config, err := jq.Object("storage", key)

	if err != nil {
		return nil, err
	}

	storage, err := parameter(util.MapInterfaceToMapString(config))

	if err != nil {
		return nil, err
	}

	return storage, err
}

var StorageInitializer Initializer = func(jq *jsonq.JsonQuery, app *Application) error {
	_, err := jq.Object("storage")

	if err != nil {
		app.SourceStorage = &dummy.DummyStorage{}
		app.DestStorage = &dummy.DummyStorage{}

		return nil
	}

	sourceStorage, err := getStorageFromConfig("src", jq)

	if err != nil {
		return err
	}

	app.SourceStorage = sourceStorage

	destStorage, err := getStorageFromConfig("dst", jq)

	if err != nil {
		app.DestStorage = sourceStorage
	} else {
		app.DestStorage = destStorage
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"log"
	"net/http"
	"os/exec"
	"strconv"
	"strings"
	"time"
)

func DownloadHandler(w http.ResponseWriter, r *http.Request, db *sql.DB) {

	whitelist := []string{"image/gif", "image/png", "image/jpeg", "image/bmp", "application/pdf", "text/plain"}
	/* Security checks */
	request_id_t := strings.TrimSpace(r.FormValue("id"))
	if len(request_id_t) == 0 {
		http.Redirect(w, r, CONF_DOMAIN, 303)
		return
	}

	request_commands := strings.Split(request_id_t, "/")
	request_id := strings.Split(request_commands[0], ".")[0]
	if len(request_id) == 0 {
		http.Redirect(w, r, CONF_DOMAIN, 303)
		return
	}

	/*dbstmt, err := db.Prepare("SELECT name, size, diskid, uploaded FROM files WHERE fileid = '?'")
	if err != nil {
		panic(err)
	}
	defer dbstmt.Close()

	dbrow := db.QueryRow(request_id)
    */
    dbrow := db.QueryRow("SELECT name, size, diskid, uploaded FROM files WHERE fileid = ?", request_id)
	var filename string
	var filesize int64
	var diskid string
	var uploaded int64

	err := dbrow.Scan(&filename, &filesize, &diskid, &uploaded)
	if err != nil {
		http.Redirect(w, r, CONF_DOMAIN, 303)
		return
	}

    log.Printf("Database values: %s, %d, %s, %d\n", filename, filesize, diskid, uploaded)

	out, err := exec.Command("file", "-biL", UPLOAD_DIR+request_id+"/"+filename).Output()

	// Tells IE not to try to guess the content type
	w.Header().Set("X-Content-Type-Options", "nosniff")

	// Tells the browser to expect a file
	w.Header().Set("Content-Description", "File Transfer")

	// Enables some XSS protection in IE
	w.Header().Set("X-XSS-Protection", "1; mode=block")

	if StringInArray(strings.Split(string(out), ";")[0], whitelist) && err == nil {
		w.Header().Set("Content-Disposition", "inline; filename=\""+string(filename)+"\"")
	} else {
		w.Header().Set("Content-Disposition", "attachment; filename=\""+string(filename)+"\"")
	}

	// watfile links currently don't expire, so tell the browser
	w.Header().Set("Expires", "Sun, 17 Jan 2038 19:14:07 GMT")
	w.Header().Set("Cache-Control", "max-age=31536000, must-revalidate")

	w.Header().Set("Last-Modified", time.Unix(uploaded, 0).Format("Mon, 2 Jan 2006 15:04:05 MST"))
	w.Header().Set("Content-Length", strconv.FormatInt(filesize, 10))
	if CONF_USE_XACCEL {
		w.Header().Set("X-Accel-Redirect", "/protected/"+diskid)
		w.Header().Set("Content-Transfer-Encoding", "binary")
	} else {
		http.ServeFile(w, r, UPLOAD_DIR+request_id+"/"+diskid)
	}
	log.Printf("[LOG] File %s dowloaded\n", request_id)
	return
}
<commit_msg>Fixed whitelisted file types not displaying in browser<commit_after>package main

import (
	"database/sql"
	"log"
	"net/http"
	"os/exec"
	"strconv"
	"strings"
	"time"
)

func DownloadHandler(w http.ResponseWriter, r *http.Request, db *sql.DB) {

	whitelist := []string{"image/gif", "image/png", "image/jpeg", "image/bmp", "application/pdf", "text/plain"}
	/* Security checks */
	request_id_t := strings.TrimSpace(r.FormValue("id"))
	if len(request_id_t) == 0 {
		http.Redirect(w, r, CONF_DOMAIN, 303)
		return
	}

	request_commands := strings.Split(request_id_t, "/")
	request_id := strings.Split(request_commands[0], ".")[0]
	if len(request_id) == 0 {
		http.Redirect(w, r, CONF_DOMAIN, 303)
		return
	}

	/*dbstmt, err := db.Prepare("SELECT name, size, diskid, uploaded FROM files WHERE fileid = '?'")
	if err != nil {
		panic(err)
	}
	defer dbstmt.Close()

	dbrow := db.QueryRow(request_id)
    */
    dbrow := db.QueryRow("SELECT name, size, diskid, uploaded FROM files WHERE fileid = ?", request_id)
	var filename string
	var filesize int64
	var diskid string
	var uploaded int64

	err := dbrow.Scan(&filename, &filesize, &diskid, &uploaded)
	if err != nil {
		http.Redirect(w, r, CONF_DOMAIN, 303)
		return
	}

	out, err := exec.Command("file", "-biL", UPLOAD_DIR+diskid).Output()

	// Tells IE not to try to guess the content type
	w.Header().Set("X-Content-Type-Options", "nosniff")

	// Tells the browser to expect a file
	w.Header().Set("Content-Description", "File Transfer")

	// Enables some XSS protection in IE
	w.Header().Set("X-XSS-Protection", "1; mode=block")

	if StringInArray(strings.Split(string(out), ";")[0], whitelist) && err == nil {
		w.Header().Set("Content-Disposition", "inline; filename=\""+string(filename)+"\"")
	} else {
		w.Header().Set("Content-Disposition", "attachment; filename=\""+string(filename)+"\"")
	}

	// watfile links currently don't expire, so tell the browser
	w.Header().Set("Expires", "Sun, 17 Jan 2038 19:14:07 GMT")
	w.Header().Set("Cache-Control", "max-age=31536000, must-revalidate")

	w.Header().Set("Last-Modified", time.Unix(uploaded, 0).Format("Mon, 2 Jan 2006 15:04:05 MST"))
	w.Header().Set("Content-Length", strconv.FormatInt(filesize, 10))
	if CONF_USE_XACCEL {
		w.Header().Set("X-Accel-Redirect", "/protected/"+diskid)
		w.Header().Set("Content-Transfer-Encoding", "binary")
	} else {
		http.ServeFile(w, r, UPLOAD_DIR+request_id+"/"+diskid)
	}
	log.Printf("[LOG] File %s dowloaded\n", request_id)
	return
}
<|endoftext|>


<commit_before>package draw2dimg

import (
	"code.google.com/p/freetype-go/freetype/raster"
	"code.google.com/p/freetype-go/freetype/truetype"
	"github.com/llgcode/draw2d"
	"github.com/llgcode/draw2d/draw2dbase"
	"image"
	"image/draw"
)

type Drawer struct {
	matrix           draw2d.Matrix
	img              draw.Image
	painter          Painter
	fillRasterizer   *raster.Rasterizer
	strokeRasterizer *raster.Rasterizer
	glyphBuf         *truetype.GlyphBuf
}

func NewDrawer(img *image.RGBA) *Drawer {
	width, height := img.Bounds().Dx(), img.Bounds().Dy()
	return &Drawer{
		draw2d.NewIdentityMatrix(),
		img,
		raster.NewRGBAPainter(img),
		raster.NewRasterizer(width, height),
		raster.NewRasterizer(width, height),
		truetype.NewGlyphBuf(),
	}
}

func (d *Drawer) Matrix() *draw2d.Matrix {
	return d.Matrix()
}

func (d *Drawer) Fill(path *draw2d.Path, style draw2d.FillStyle) {
	switch fillStyle := style.(type) {
	case draw2d.SolidFillStyle:
		d.fillRasterizer.UseNonZeroWinding = useNonZeroWinding(fillStyle.FillRule)
		d.painter.SetColor(fillStyle.Color)
	default:
		panic("FillStyle not supported")
	}

	flattener := draw2dbase.Transformer{d.matrix, draw2dbase.FtLineBuilder{d.fillRasterizer}}

	draw2dbase.Flatten(path, flattener, d.matrix.GetScale())

	d.fillRasterizer.Rasterize(d.painter)
	d.fillRasterizer.Clear()
}

func (d *Drawer) Stroke(path *draw2d.Path, style draw2d.StrokeStyle) {
	d.strokeRasterizer.UseNonZeroWinding = true

	stroker := draw2dbase.NewLineStroker(style.LineCap, style.LineJoin, draw2dbase.Transformer{d.matrix, draw2dbase.FtLineBuilder{d.strokeRasterizer}})
	stroker.HalfLineWidth = style.Width / 2

	var liner draw2dbase.Flattener
	if style.Dash != nil && len(style.Dash) > 0 {
		liner = draw2dbase.NewDashConverter(style.Dash, style.DashOffset, stroker)
	} else {
		liner = stroker
	}

	draw2dbase.Flatten(path, liner, d.matrix.GetScale())

	d.painter.SetColor(style.Color)
	d.strokeRasterizer.Rasterize(d.painter)
	d.strokeRasterizer.Clear()
}

func (d *Drawer) Text(text string, x, y float64, style draw2d.TextStyle) {

}

func (d *Drawer) Image(image image.Image, x, y float64, scaling draw2d.ImageScaling) {
}
<commit_msg>Fix bug<commit_after>package draw2dimg

import (
	"code.google.com/p/freetype-go/freetype/raster"
	"code.google.com/p/freetype-go/freetype/truetype"
	"github.com/llgcode/draw2d"
	"github.com/llgcode/draw2d/draw2dbase"
	"image"
	"image/draw"
)

type Drawer struct {
	matrix           draw2d.Matrix
	img              draw.Image
	painter          Painter
	fillRasterizer   *raster.Rasterizer
	strokeRasterizer *raster.Rasterizer
	glyphBuf         *truetype.GlyphBuf
}

func NewDrawer(img *image.RGBA) *Drawer {
	width, height := img.Bounds().Dx(), img.Bounds().Dy()
	return &Drawer{
		draw2d.NewIdentityMatrix(),
		img,
		raster.NewRGBAPainter(img),
		raster.NewRasterizer(width, height),
		raster.NewRasterizer(width, height),
		truetype.NewGlyphBuf(),
	}
}

func (d *Drawer) Matrix() *draw2d.Matrix {
	return &d.matrix
}

func (d *Drawer) Fill(path *draw2d.Path, style draw2d.FillStyle) {
	switch fillStyle := style.(type) {
	case draw2d.SolidFillStyle:
		d.fillRasterizer.UseNonZeroWinding = useNonZeroWinding(fillStyle.FillRule)
		d.painter.SetColor(fillStyle.Color)
	default:
		panic("FillStyle not supported")
	}

	flattener := draw2dbase.Transformer{d.matrix, draw2dbase.FtLineBuilder{d.fillRasterizer}}

	draw2dbase.Flatten(path, flattener, d.matrix.GetScale())

	d.fillRasterizer.Rasterize(d.painter)
	d.fillRasterizer.Clear()
}

func (d *Drawer) Stroke(path *draw2d.Path, style draw2d.StrokeStyle) {
	d.strokeRasterizer.UseNonZeroWinding = true

	stroker := draw2dbase.NewLineStroker(style.LineCap, style.LineJoin, draw2dbase.Transformer{d.matrix, draw2dbase.FtLineBuilder{d.strokeRasterizer}})
	stroker.HalfLineWidth = style.Width / 2

	var liner draw2dbase.Flattener
	if style.Dash != nil && len(style.Dash) > 0 {
		liner = draw2dbase.NewDashConverter(style.Dash, style.DashOffset, stroker)
	} else {
		liner = stroker
	}

	draw2dbase.Flatten(path, liner, d.matrix.GetScale())

	d.painter.SetColor(style.Color)
	d.strokeRasterizer.Rasterize(d.painter)
	d.strokeRasterizer.Clear()
}

func (d *Drawer) Text(text string, x, y float64, style draw2d.TextStyle) {

}

func (d *Drawer) Image(image image.Image, x, y float64, scaling draw2d.ImageScaling) {
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////
// Porgram: EasyGen
// Purpose: Universal code/text generator that is easy to use
// Authors: Tong Sun (c) 2015, All rights reserved
////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
// Program start

package main

import (
	"bytes"
	"flag"
	"fmt"
	ht "html/template"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	tt "text/template"

	"gopkg.in/yaml.v2"
)

////////////////////////////////////////////////////////////////////////////
// Constant and data type/structure definitions

const progname = "EasyGen" // os.Args[0]

// The Options structure holds the values for/from commandline
type Options struct {
	HTML bool
}

// common type for a *(text|html).Template value
type template interface {
	Execute(wr io.Writer, data interface{}) error
	ExecuteTemplate(wr io.Writer, name string, data interface{}) error
	Name() string
}

////////////////////////////////////////////////////////////////////////////
// Global variables definitions

var opts Options

////////////////////////////////////////////////////////////////////////////
// Commandline definitions

func init() {
	flag.BoolVar(&opts.HTML, "html", false, "Use html template instead of text")
}

func usage() {
	fmt.Fprintf(os.Stderr, "\nUsage:\n %s [flags] TemplateFileName\n\nFlags:\n\n",
		progname)
	flag.PrintDefaults()
	fmt.Fprintf(os.Stderr, "\nTemplateFileName: The name for the template and yaml file\n\tOnly the name part, without extension. Can include the path as well.\n")
	os.Exit(0)
}

////////////////////////////////////////////////////////////////////////////
// Main

func main() {
	flag.Usage = usage
	flag.Parse()

	// One mandatory non-flag arguments
	if len(flag.Args()) < 1 {
		usage()
	}
	fileName := flag.Args()[0]

	fmt.Print(Generate(opts.HTML, fileName))
}

////////////////////////////////////////////////////////////////////////////
// Function definitions

// Generate will produce output from the template according to driving data
func Generate(HTML bool, fileName string) string {
	source, err := ioutil.ReadFile(fileName + ".yaml")
	checkError(err)

	m := make(map[interface{}]interface{})

	err = yaml.Unmarshal(source, &m)
	checkError(err)

	t, err := parseFiles(HTML, fileName+".tmpl")
	checkError(err)

	buf := new(bytes.Buffer)
	err = t.Execute(buf, m)
	checkError(err)

	return buf.String()
}

// parseFiles, intialization. By Matt Harden @gmail.com
func parseFiles(HTML bool, filenames ...string) (template, error) {
	tname := filepath.Base(filenames[0])

	if HTML {
		// use html template
		t, err := ht.ParseFiles(filenames...)
		return t, err
	} else {
		// use text template
		funcMap := tt.FuncMap{
			"minus1": minus1,
			"join":   join,
		}
		t, err := tt.New(tname).Funcs(funcMap).ParseFiles(filenames...)
		return t, err
	}
}

// Exit if error occurs
func checkError(err error) {
	if err != nil {
		fmt.Printf("[%s] Fatal error - %v", progname, err.Error())
		os.Exit(1)
	}
}

//==========================================================================
// template custom functions

// Get input less 1
func minus1(n int) int { return n - 1 }

// Custom template function to join string array
func join(s []string) string { return strings.Join(s, ", ") }
<commit_msg>- [!] fix lint issue: if block ends with a return statement, so drop this else and outdent its block, http://golang.org/s/style#indent_error_flow<commit_after>////////////////////////////////////////////////////////////////////////////
// Porgram: EasyGen
// Purpose: Universal code/text generator that is easy to use
// Authors: Tong Sun (c) 2015, All rights reserved
////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
// Program start

package main

import (
	"bytes"
	"flag"
	"fmt"
	ht "html/template"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	tt "text/template"

	"gopkg.in/yaml.v2"
)

////////////////////////////////////////////////////////////////////////////
// Constant and data type/structure definitions

const progname = "EasyGen" // os.Args[0]

// The Options structure holds the values for/from commandline
type Options struct {
	HTML bool
}

// common type for a *(text|html).Template value
type template interface {
	Execute(wr io.Writer, data interface{}) error
	ExecuteTemplate(wr io.Writer, name string, data interface{}) error
	Name() string
}

////////////////////////////////////////////////////////////////////////////
// Global variables definitions

var opts Options

////////////////////////////////////////////////////////////////////////////
// Commandline definitions

func init() {
	flag.BoolVar(&opts.HTML, "html", false, "Use html template instead of text")
}

func usage() {
	fmt.Fprintf(os.Stderr, "\nUsage:\n %s [flags] TemplateFileName\n\nFlags:\n\n",
		progname)
	flag.PrintDefaults()
	fmt.Fprintf(os.Stderr, "\nTemplateFileName: The name for the template and yaml file\n\tOnly the name part, without extension. Can include the path as well.\n")
	os.Exit(0)
}

////////////////////////////////////////////////////////////////////////////
// Main

func main() {
	flag.Usage = usage
	flag.Parse()

	// One mandatory non-flag arguments
	if len(flag.Args()) < 1 {
		usage()
	}
	fileName := flag.Args()[0]

	fmt.Print(Generate(opts.HTML, fileName))
}

////////////////////////////////////////////////////////////////////////////
// Function definitions

// Generate will produce output from the template according to driving data
func Generate(HTML bool, fileName string) string {
	source, err := ioutil.ReadFile(fileName + ".yaml")
	checkError(err)

	m := make(map[interface{}]interface{})

	err = yaml.Unmarshal(source, &m)
	checkError(err)

	t, err := parseFiles(HTML, fileName+".tmpl")
	checkError(err)

	buf := new(bytes.Buffer)
	err = t.Execute(buf, m)
	checkError(err)

	return buf.String()
}

// parseFiles, intialization. By Matt Harden @gmail.com
func parseFiles(HTML bool, filenames ...string) (template, error) {
	tname := filepath.Base(filenames[0])

	if HTML {
		// use html template
		t, err := ht.ParseFiles(filenames...)
		return t, err
	}

	// use text template
	funcMap := tt.FuncMap{
		"minus1": minus1,
		"join":   join,
	}
	t, err := tt.New(tname).Funcs(funcMap).ParseFiles(filenames...)
	return t, err
}

// Exit if error occurs
func checkError(err error) {
	if err != nil {
		fmt.Printf("[%s] Fatal error - %v", progname, err.Error())
		os.Exit(1)
	}
}

//==========================================================================
// template custom functions

// Get input less 1
func minus1(n int) int { return n - 1 }

// Custom template function to join string array
func join(s []string) string { return strings.Join(s, ", ") }
<|endoftext|>


<commit_before><commit_msg>rename -chatty to more conventional -v. add -match flag to select tests.<commit_after><|endoftext|>


<commit_before>package main

import (
	"github.com/drone/drone/model"
	"github.com/urfave/cli"
)

var secretCreateCmd = cli.Command{
	Name:   "add",
	Usage:  "adds a secret",
	Action: secretCreate,
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:  "repository",
			Usage: "repository name (e.g. octocat/hello-world)",
		},
		cli.StringFlag{
			Name:  "name",
			Usage: "secret name",
		},
		cli.StringFlag{
			Name:  "value",
			Usage: "secret value",
		},
		cli.StringSliceFlag{
			Name:  "event",
			Usage: "secret limited to these events",
		},
		cli.StringSliceFlag{
			Name:  "image",
			Usage: "secret limited to these images",
		},
	},
}

func secretCreate(c *cli.Context) error {
	reponame := c.String("repository")
	if reponame == "" {
		reponame = c.Args().First()
	}
	owner, name, err := parseRepo(reponame)
	if err != nil {
		return err
	}
	client, err := newClient(c)
	if err != nil {
		return err
	}
	secret := &model.Secret{
		Name:   c.String("name"),
		Value:  c.String("value"),
		Images: c.StringSlice("image"),
		Events: c.StringSlice("events"),
	}
	if len(secret.Events) == 0 {
		secret.Events = defaultSecretEvents
	}
	_, err = client.SecretCreate(owner, name, secret)
	return err
}

var defaultSecretEvents = []string{
	model.EventPush,
	model.EventTag,
	model.EventDeploy,
}
<commit_msg>fix event flag for secret add<commit_after>package main

import (
	"github.com/drone/drone/model"
	"github.com/urfave/cli"
)

var secretCreateCmd = cli.Command{
	Name:   "add",
	Usage:  "adds a secret",
	Action: secretCreate,
	Flags: []cli.Flag{
		cli.StringFlag{
			Name:  "repository",
			Usage: "repository name (e.g. octocat/hello-world)",
		},
		cli.StringFlag{
			Name:  "name",
			Usage: "secret name",
		},
		cli.StringFlag{
			Name:  "value",
			Usage: "secret value",
		},
		cli.StringSliceFlag{
			Name:  "event",
			Usage: "secret limited to these events",
		},
		cli.StringSliceFlag{
			Name:  "image",
			Usage: "secret limited to these images",
		},
	},
}

func secretCreate(c *cli.Context) error {
	reponame := c.String("repository")
	if reponame == "" {
		reponame = c.Args().First()
	}
	owner, name, err := parseRepo(reponame)
	if err != nil {
		return err
	}
	client, err := newClient(c)
	if err != nil {
		return err
	}
	secret := &model.Secret{
		Name:   c.String("name"),
		Value:  c.String("value"),
		Images: c.StringSlice("image"),
		Events: c.StringSlice("event"),
	}
	if len(secret.Events) == 0 {
		secret.Events = defaultSecretEvents
	}
	_, err = client.SecretCreate(owner, name, secret)
	return err
}

var defaultSecretEvents = []string{
	model.EventPush,
	model.EventTag,
	model.EventDeploy,
}
<|endoftext|>


<commit_before>package gosmpp

import (
	"sync/atomic"

	"github.com/linxGnu/gosmpp/pdu"
)

type transceivable struct {
	settings Settings

	conn *Connection
	in   *receivable
	out  *transmittable

	aliveState int32
}

func newTransceivable(conn *Connection, settings Settings) *transceivable {
	t := &transceivable{
		settings: settings,
		conn:     conn,
	}

	t.out = newTransmittable(conn, Settings{
		WriteTimeout: settings.WriteTimeout,

		EnquireLink: settings.EnquireLink,

		OnSubmitError: settings.OnSubmitError,

		OnClosed: func(state State) {
			switch state {
			case ExplicitClosing:
				return

			case ConnectionIssue:
				// also close input
				_ = t.in.close(ExplicitClosing)

				if t.settings.OnClosed != nil {
					t.settings.OnClosed(ConnectionIssue)
				}
			}
		},
	})

	t.in = newReceivable(conn, Settings{
		ReadTimeout: settings.ReadTimeout,

		OnPDU: settings.OnPDU,

		OnReceivingError: settings.OnReceivingError,

		OnClosed: func(state State) {
			switch state {
			case ExplicitClosing:
				return

			case InvalidStreaming, UnbindClosing:
				// also close output
				_ = t.out.close(ExplicitClosing)

				if t.settings.OnClosed != nil {
					t.settings.OnClosed(state)
				}
			}
		},

		response: func(p pdu.PDU) {
			if t.out.Submit(p) != nil { // only happened when transceiver is closed
				_, _ = t.out.write(p)
			}
		},
	})

	t.out.start()
	t.in.start()

	return t
}

// SystemID returns tagged SystemID which is attached with bind_resp from SMSC.
func (t *transceivable) SystemID() string {
	return t.conn.systemID
}

// Close transceiver and stop underlying daemons.
func (t *transceivable) Close() (err error) {
	if atomic.CompareAndSwapInt32(&t.aliveState, Alive, Closed) {
		// closing input and output
		_ = t.out.close(StoppingProcessOnly)
		_ = t.in.close(StoppingProcessOnly)

		// close underlying conn
		err = t.conn.Close()

		// notify transceiver closed
		if t.settings.OnClosed != nil {
			t.settings.OnClosed(ExplicitClosing)
		}
	}
	return
}

// Submit a PDU.
func (t *transceivable) Submit(p pdu.PDU) error {
	return t.out.Submit(p)
}
<commit_msg>Fix transceiver resubmit<commit_after>package gosmpp

import (
	"sync/atomic"

	"github.com/linxGnu/gosmpp/pdu"
)

type transceivable struct {
	settings Settings

	conn *Connection
	in   *receivable
	out  *transmittable

	aliveState int32
}

func newTransceivable(conn *Connection, settings Settings) *transceivable {
	t := &transceivable{
		settings: settings,
		conn:     conn,
	}

	t.out = newTransmittable(conn, Settings{
		WriteTimeout: settings.WriteTimeout,

		EnquireLink: settings.EnquireLink,

		OnSubmitError: settings.OnSubmitError,

		OnClosed: func(state State) {
			switch state {
			case ExplicitClosing:
				return

			case ConnectionIssue:
				// also close input
				_ = t.in.close(ExplicitClosing)

				if t.settings.OnClosed != nil {
					t.settings.OnClosed(ConnectionIssue)
				}
			}
		},
	})

	t.in = newReceivable(conn, Settings{
		ReadTimeout: settings.ReadTimeout,

		OnPDU: settings.OnPDU,

		OnReceivingError: settings.OnReceivingError,

		OnClosed: func(state State) {
			switch state {
			case ExplicitClosing:
				return

			case InvalidStreaming, UnbindClosing:
				// also close output
				_ = t.out.close(ExplicitClosing)

				if t.settings.OnClosed != nil {
					t.settings.OnClosed(state)
				}
			}
		},

		response: func(p pdu.PDU) {
			t.Submit(p)
		},
	})

	t.out.start()
	t.in.start()

	return t
}

// SystemID returns tagged SystemID which is attached with bind_resp from SMSC.
func (t *transceivable) SystemID() string {
	return t.conn.systemID
}

// Close transceiver and stop underlying daemons.
func (t *transceivable) Close() (err error) {
	if atomic.CompareAndSwapInt32(&t.aliveState, Alive, Closed) {
		// closing input and output
		_ = t.out.close(StoppingProcessOnly)
		_ = t.in.close(StoppingProcessOnly)

		// close underlying conn
		err = t.conn.Close()

		// notify transceiver closed
		if t.settings.OnClosed != nil {
			t.settings.OnClosed(ExplicitClosing)
		}
	}
	return
}

// Submit a PDU.
func (t *transceivable) Submit(p pdu.PDU) error {
	return t.out.Submit(p)
}
<|endoftext|>


<commit_before>//  Copyright 2016 The goscope Authors
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.

package triggers

import (
	"github.com/zagrodzki/goscope/scope"
)

// RisingEdge represents the trigger edge type, rising or falling
type RisingEdge bool

// RisingEdge values for readability.
const (
	Rising  RisingEdge = true
	Falling RisingEdge = false
)

// Trigger represents a filter running on the data channel, waiting for
// a triggering event and then allowing a set of samples equal to the
// configured timebase.
type Trigger struct {
	source  scope.ChanID
	slope   RisingEdge
	lvl     scope.Voltage
	rec     scope.DataRecorder
	tbCount int
}

// New returns an initialized Trigger.
func New(rec scope.DataRecorder) *Trigger {
	return &Trigger{
		rec: rec,
	}
}

// TimeBase returns the trigger timebase, which is the same as the underlying recorder timebase.
func (t *Trigger) TimeBase() scope.Duration {
	return t.rec.TimeBase()
}

// Reset initializes the recording.
func (t *Trigger) Reset(i scope.Duration, ch <-chan []scope.ChannelData) {
	out := make(chan []scope.ChannelData, 20)
	t.tbCount = int(t.rec.TimeBase() / i)
	t.rec.Reset(i, out)
	go t.run(ch, out)
}

// Error passes the error down to the underlying recorder.
func (t *Trigger) Error(err error) {
	t.rec.Error(err)
}

// Source sets the source for the trigger. If received data doesn't contain
// samples for specified source, the trigger allows all samples without filtering.
func (t *Trigger) Source(id scope.ChanID) {
	t.source = id
}

// Edge configures the type of edge (rising/falling) that is the triggering condition.
func (t *Trigger) Edge(e RisingEdge) {
	t.slope = e
}

// Level configures the level that the edge has to cross for the triggering condition.
func (t *Trigger) Level(l scope.Voltage) {
	t.lvl = l
}

func (t *Trigger) run(in <-chan []scope.ChannelData, out chan<- []scope.ChannelData) {
	var left int
	var last scope.Voltage
	var source int
	var trg, scanned, found, initialized bool
	for d := range in {
		if !scanned {
			scanned = true
			for i := range d {
				if d[i].ID == t.source {
					source = i
					found = true
					break
				}
			}
		}
		if !found {
			out <- d
			continue
		}
		num := len(d[source].Samples)
		if !initialized && num > 0 {
			initialized = true
			last = d[source].Samples[0]
		}
		for num > 0 {
			// look for trigger
			if !trg {
				for i, v := range d[source].Samples {
					if (last < t.lvl) != (v < t.lvl) && RisingEdge(v >= t.lvl) == t.slope {
						trg = true
						left = t.tbCount
						for ch := range d {
							d[ch].Samples = d[ch].Samples[i:]
						}
						break
					}
					last = v
					num--
				}
			}
			// flush samples
			if trg {
				if left >= num {
					left -= num
					num = 0
					out <- d
				} else {
					// we need to send only a small chunk
					chunk := make([]scope.ChannelData, len(d))
					for ch := range d {
						chunk[ch].ID = d[ch].ID
						chunk[ch].Samples = d[ch].Samples[:left]
					}
					last = d[source].Samples[left-1]
					left = 0
					num -= left
					out <- chunk
				}
				if left == 0 {
					trg = false
				}
			}
		}
	}
	close(out)
}
<commit_msg>Fix a bug where trigger would loop indefinitely because number of samples didn't decrease correctly. Fix a bug where trigger would activate without an edge (because of sloppy comparison condition).<commit_after>//  Copyright 2016 The goscope Authors
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.

package triggers

import (
	"github.com/zagrodzki/goscope/scope"
)

// RisingEdge represents the trigger edge type, rising or falling
type RisingEdge bool

// RisingEdge values for readability.
const (
	Rising  RisingEdge = true
	Falling RisingEdge = false
)

// Trigger represents a filter running on the data channel, waiting for
// a triggering event and then allowing a set of samples equal to the
// configured timebase.
type Trigger struct {
	source  scope.ChanID
	slope   RisingEdge
	lvl     scope.Voltage
	rec     scope.DataRecorder
	tbCount int
}

// New returns an initialized Trigger.
func New(rec scope.DataRecorder) *Trigger {
	return &Trigger{
		rec: rec,
	}
}

// TimeBase returns the trigger timebase, which is the same as the underlying recorder timebase.
func (t *Trigger) TimeBase() scope.Duration {
	return t.rec.TimeBase()
}

// Reset initializes the recording.
func (t *Trigger) Reset(i scope.Duration, ch <-chan []scope.ChannelData) {
	out := make(chan []scope.ChannelData, 20)
	t.tbCount = int(t.rec.TimeBase() / i)
	t.rec.Reset(i, out)
	go t.run(ch, out)
}

// Error passes the error down to the underlying recorder.
func (t *Trigger) Error(err error) {
	t.rec.Error(err)
}

// Source sets the source for the trigger. If received data doesn't contain
// samples for specified source, the trigger allows all samples without filtering.
func (t *Trigger) Source(id scope.ChanID) {
	t.source = id
}

// Edge configures the type of edge (rising/falling) that is the triggering condition.
func (t *Trigger) Edge(e RisingEdge) {
	t.slope = e
}

// Level configures the level that the edge has to cross for the triggering condition.
func (t *Trigger) Level(l scope.Voltage) {
	t.lvl = l
}

func (t *Trigger) run(in <-chan []scope.ChannelData, out chan<- []scope.ChannelData) {
	var left int
	var last scope.Voltage
	var source int
	var trg, scanned, found, initialized bool
	for d := range in {
		if !scanned {
			scanned = true
			for i := range d {
				if d[i].ID == t.source {
					source = i
					found = true
					break
				}
			}
		}
		if !found {
			out <- d
			continue
		}
		num := len(d[source].Samples)
		if !initialized && num > 0 {
			initialized = true
			last = d[source].Samples[0]
		}
		for num > 0 {
			// look for trigger
			if !trg {
				for i, v := range d[source].Samples {
					switch t.slope {
					case Rising:
						trg = last < t.lvl && v > t.lvl
					case Falling:
						trg = last > t.lvl && v < t.lvl
					}
					if trg {
						left = t.tbCount
						for ch := range d {
							d[ch].Samples = d[ch].Samples[i:]
						}
						break
					}
					last = v
					num--
				}
			}
			// flush samples
			if trg {
				if left >= num {
					left -= num
					num = 0
					out <- d
				} else {
					// we need to send only a small chunk
					chunk := make([]scope.ChannelData, len(d))
					for ch := range d {
						chunk[ch].ID = d[ch].ID
						chunk[ch].Samples = d[ch].Samples[:left]
					}
					last = d[source].Samples[left-1]
					num -= left
					left = 0
					out <- chunk
				}
				if left == 0 {
					trg = false
				}
			}
		}
	}
	close(out)
}
<|endoftext|>


<commit_before>package generate

import (
	"../grid"
	"../words"
	"fmt"
)

// TODO: figure out how to process in parallel.

func Generate(words *words.Words, grid *grid.Grid) {
	// grid generation is performed in three steps
	// 1. place a random word in a random position
	// 2. resolve any partial words until there are none left.
	//    print the grid if it's a better grid or backtrack.
	// 3. place words that intersect existing words
	//    repeat step 2 or step 1.
	//
	// Note: step 2 should prune the search space. It does however
	//       trigger the exploration of duplicate states.
	phaseOne(words, grid, 0)
}

// Checks that all the partial words can be solved.
// Returns a map of partial -> how many permutations are valid.
func phaseTwoValidateDown(words *words.Words, g *grid.Grid) (map[grid.Partial]int, bool) {
	r := make(map[grid.Partial]int)

	// For each partial word, count how many words we can still place
	for _, partial := range g.PartialDown() {
		count := 0
		ngrams := words.GetNgrams(partial.Partial)
		for _, ngram := range ngrams {
			if words.IsUsed(ngram.Word) {
				continue
			}
			// try to place ngram.word at partial.x, partial.y - ngram.offset
			sb, eb, ok := g.Place(partial.X, partial.Y - ngram.Offset, grid.DOWN, ngram.Word)
			if ok {
				count++
				g.Unplace(partial.X, partial.Y - ngram.Offset, grid.DOWN, ngram.Word, sb, eb)
			}
		}
		r[partial] = count
    if count == 0 {
      return r, false
    }
	}
	return r, true
}

func phaseTwoValidateRight(words *words.Words, g *grid.Grid) (map[grid.Partial]int, bool) {
	r := make(map[grid.Partial]int)

	// For each partial word, count how many words we can still place
	for _, partial := range g.PartialRight() {
		count := 0
		ngrams := words.GetNgrams(partial.Partial)
		for _, ngram := range ngrams {
			if words.IsUsed(ngram.Word) {
				continue
			}
			// try to place ngram.word at partial.x - ngram.offset, partial.y
			sb, eb, ok := g.Place(partial.X - ngram.Offset, partial.Y, grid.RIGHT, ngram.Word)
			if ok {
				count++
				g.Unplace(partial.X - ngram.Offset, partial.Y, grid.RIGHT, ngram.Word, sb, eb)
			}
		}
		r[partial] = count
    if count == 0 {
      return r, false
    }
	}
	return r, true
}

func phaseTwo(words *words.Words, g *grid.Grid, score int) bool {
	// Find all the vertical partial words
	partials := g.PartialDown()
	if len(partials) > 0 {
		//fmt.Printf("PartialDown: %s\n", partials)
		return false
	}

	// And the horizontal ones
	t := g.PartialRight()
	if len(t) > 0 {
		//fmt.Printf("PartialRight: %s\n", t)
		return false
	}

	// grid is in good state!
	fmt.Printf("score: %d\n", score)
	fmt.Println(g)

	return phaseOne(words, g, score)
}

func phaseOne(words *words.Words, g *grid.Grid, score int) bool {
	for _, word := range words.GetWords() {
		if words.IsUsed(word) {
			continue
		}
		//fmt.Printf("trying to place: %s\n", word)
		for i := 0; i <= g.Size; i++ {
			for j := 0; j <= g.Size-len(word); j++ {
				a, z, ok := g.Place(i, j, grid.DOWN, word)
				if ok {
					//fmt.Printf("placed '%s' at DOWN %d, %d\n", word, i, j)
					words.MarkUsed(word)
					// recurse
					if phaseTwo(words, g, score+1) {
						return true
					}
					g.Unplace(i, j, grid.DOWN, word, a, z)
					//fmt.Printf("unplaced '%s' at DOWN %d, %d\n", word, i, j)
					words.MarkUnused(word)
				}
			}
		}
		for i := 0; i <= g.Size-len(word); i++ {
			for j := 0; j <= g.Size; j++ {
				a, z, ok := g.Place(i, j, grid.RIGHT, word)
				if ok {
					//fmt.Printf("placed '%s' at RIGHT %d, %d\n", word, i, j)
					words.MarkUsed(word)
					// recurse
					if phaseTwo(words, g, score+1) {
						return true
					}
					g.Unplace(i, j, grid.RIGHT, word, a, z)
					//fmt.Printf("unplaced '%s' at RIGHT %d, %d\n", word, i, j)
					words.MarkUnused(word)
				}
			}
		}
	}
	return false
}
<commit_msg>phaseTwo<commit_after>package generate

import (
	"../grid"
	. "../utils"
	"../words"
	"fmt"
)

// TODO: figure out how to process in parallel.

func Generate(words *words.Words, grid *grid.Grid) {
	// grid generation is performed in three steps
	// 1. place a random word in a random position
	// 2. resolve any partial words until there are none left.
	//    print the grid if it's a better grid or backtrack.
	// 3. place words that intersect existing words
	//    repeat step 2 or step 1.
	//
	// Note: step 2 should prune the search space. It does however
	//       trigger the exploration of duplicate states.
	phaseOne(words, grid, 0)
}

// Checks that all the partial words can be solved.
// Returns a map of partial -> how many permutations are valid.
func phaseTwoValidateDown(w *words.Words, g *grid.Grid) (map[grid.Partial][]words.Ngram, bool) {
	r := make(map[grid.Partial][]words.Ngram)

	// For each partial word, count how many words we can still place
	for _, partial := range g.PartialDown() {
		r[partial] = []words.Ngram{}
		ngrams := w.GetNgrams(partial.Partial)
		for _, ngram := range ngrams {
			if w.IsUsed(ngram.Word) {
				continue
			}
			// try to place ngram.word at partial.x, partial.y - ngram.offset
			sb, eb, ok := g.Place(partial.X, partial.Y-ngram.Offset, grid.DOWN, ngram.Word)
			if ok {
				r[partial] = append(r[partial], ngram)
				g.Unplace(partial.X, partial.Y-ngram.Offset, grid.DOWN, ngram.Word, sb, eb)
			}
		}
		if len(r[partial]) == 0 {
			return r, false
		}
	}
	return r, true
}

func phaseTwoValidateRight(w *words.Words, g *grid.Grid) (map[grid.Partial][]words.Ngram, bool) {
	r := make(map[grid.Partial][]words.Ngram)

	// For each partial word, count how many words we can still place
	for _, partial := range g.PartialRight() {
		r[partial] = []words.Ngram{}
		ngrams := w.GetNgrams(partial.Partial)
		for _, ngram := range ngrams {
			if w.IsUsed(ngram.Word) {
				continue
			}
			// try to place ngram.word at partial.x - ngram.offset, partial.y
			sb, eb, ok := g.Place(partial.X-ngram.Offset, partial.Y, grid.RIGHT, ngram.Word)
			if ok {
				r[partial] = append(r[partial], ngram)
				g.Unplace(partial.X-ngram.Offset, partial.Y, grid.RIGHT, ngram.Word, sb, eb)
			}
		}
		if len(r[partial]) == 0 {
			return r, false
		}
	}
	return r, true
}

func phaseTwo(w *words.Words, g *grid.Grid, score int) bool {
	partialDown, valid := phaseTwoValidateDown(w, g)
	if !valid {
		return false
	}
	partialRight, valid := phaseTwoValidateRight(w, g)
	if !valid {
		return false
	}

	// Resolve the first partial with a count of 1.
	for partial, ngrams := range partialDown {
		if len(ngrams) == 1 {
			sb, eb, ok := g.Place(partial.X, partial.Y-ngrams[0].Offset, grid.DOWN, ngrams[0].Word)
			PanicIfFalse(ok, "partialDown contains invalid data")
			w.MarkUsed(ngrams[0].Word)
			valid := phaseTwo(w, g, score)
			g.Unplace(partial.X, partial.Y-ngrams[0].Offset, grid.DOWN, ngrams[0].Word, sb, eb)
			w.MarkUnused(ngrams[0].Word)
			return valid
		}
	}
	for partial, ngrams := range partialRight {
		if len(ngrams) == 1 {
			sb, eb, ok := g.Place(partial.X-ngrams[0].Offset, partial.Y, grid.RIGHT, ngrams[0].Word)
			PanicIfFalse(ok, "partialRight contains invalid data")
			w.MarkUsed(ngrams[0].Word)
			valid := phaseTwo(w, g, score)
			g.Unplace(partial.X-ngrams[0].Offset, partial.Y, grid.RIGHT, ngrams[0].Word, sb, eb)
			w.MarkUnused(ngrams[0].Word)
			return valid
		}
	}

	// Iterate over first partial
	for partial, ngrams := range partialDown {
		valid := false
		for _, ngram := range ngrams {
			sb, eb, ok := g.Place(partial.X, partial.Y-ngram.Offset, grid.DOWN, ngram.Word)
			PanicIfFalse(ok, "partialDown contains invalid data")
			w.MarkUsed(ngram.Word)
			valid = valid || phaseTwo(w, g, score)
			g.Unplace(partial.X, partial.Y-ngram.Offset, grid.DOWN, ngram.Word, sb, eb)
			w.MarkUnused(ngram.Word)
		}
		return valid
	}
	for partial, ngrams := range partialRight {
		valid := false
		for _, ngram := range ngrams {
			sb, eb, ok := g.Place(partial.X-ngram.Offset, partial.Y, grid.RIGHT, ngram.Word)
			PanicIfFalse(ok, "partialRight contains invalid data")
			w.MarkUsed(ngram.Word)
			valid = valid || phaseTwo(w, g, score)
			g.Unplace(partial.X-ngram.Offset, partial.Y, grid.RIGHT, ngram.Word, sb, eb)
			w.MarkUnused(ngram.Word)
		}
		return valid
	}

	// We don't have any partials, grid is in good state!
	fmt.Printf("score: %d\n", score)
	fmt.Println(g)

	return phaseOne(w, g, score)
}

func phaseOne(words *words.Words, g *grid.Grid, score int) bool {
	for _, word := range words.GetWords() {
		if words.IsUsed(word) {
			continue
		}
		//fmt.Printf("trying to place: %s\n", word)
		for i := 0; i <= g.Size; i++ {
			for j := 0; j <= g.Size-len(word); j++ {
				a, z, ok := g.Place(i, j, grid.DOWN, word)
				if ok {
					//fmt.Printf("placed '%s' at DOWN %d, %d\n", word, i, j)
					words.MarkUsed(word)
					// recurse
					if phaseTwo(words, g, score+1) {
						return true
					}
					g.Unplace(i, j, grid.DOWN, word, a, z)
					//fmt.Printf("unplaced '%s' at DOWN %d, %d\n", word, i, j)
					words.MarkUnused(word)
				}
			}
		}
		for i := 0; i <= g.Size-len(word); i++ {
			for j := 0; j <= g.Size; j++ {
				a, z, ok := g.Place(i, j, grid.RIGHT, word)
				if ok {
					//fmt.Printf("placed '%s' at RIGHT %d, %d\n", word, i, j)
					words.MarkUsed(word)
					// recurse
					if phaseTwo(words, g, score+1) {
						return true
					}
					g.Unplace(i, j, grid.RIGHT, word, a, z)
					//fmt.Printf("unplaced '%s' at RIGHT %d, %d\n", word, i, j)
					words.MarkUnused(word)
				}
			}
		}
	}
	return false
}
<|endoftext|>


<commit_before>// Package generate will parse and create files from template pairs.
// A template pair is a set of template files:
//   * default.json - json file
//   * default.gen - any type of text file
//
// Both files are template files and are parsed using the Go text/template
// package. The 'jay generate' tool loops through the first level of key pairs
// for empty strings. For every empty string, an argument is required to be
// passed (whether empty or not) to the 'jay generate' command.
//
// Let's look at generate/model/default.json:
// {
//   "config.type": "single",
//   "config.output": "model/{{.package}}/{{.package}}.go",
//   "package": "",
//   "table": ""
// }
//
// Let's break down this command into pieces:
// jay generate model/default package:automobile table:car
//
// Argument: 'model/default'
// Specifies generate/model/default.json and generate/model/default.gen are the
// template pair.
//
// Argument: 'package:automobile'
// The key, 'package', from default.json will be filled with the value:
// 'automobile'
//
// Argument: 'table:car'
// The key, 'table', from default.json will be filled with the value: 'car'
//
// The .json file is actually parsed up to 100 times (LoopLimit of 100 can be
// changed at the package level) to ensure all variables like '{{.package}}' are
// set to the correct value.
//
// In the first iteration of parsing, the 'package' key is set to 'car'.
// In the second iteration of parsing, the '{{.package}}' variables
// are set to 'car' also since the 'package' key becomes a variable.
//
// All first level keys (info, package, table) become variables after the first
// iteration of parsing so they can be used without the file. If a variable is
// misspelled and is never filled, a helpful error will be displayed.
//
// The 'output' key under 'info' is required. It should be the relative output
// file path to the project root for the generated file.
//
// The folder structure of the templates (model, controller, etc) has no effect
// on the generation, it's purely to aid with organization of the template pairs.
//
// You must store the path to the env.json file in the environment
// variable: JAYCONFIG. The file is at project root that is prepended to all
// relative file paths.
//
// Examples:
//   jay generate model/default package:car table:car
//   Generate a new model from variables in model/default.json and applies
//   those variables to model/default.gen.
//   jay generate controller/default package:car url:car model:car view:car
//   Generate a new controller from variables in controller/default.json
//   and applies those variables to controller/default.gen.
//
// Flags:
//   Argument 1 - model/default or controller/default
//   Relative path without an extension to the template pair. Any combination
//   of folders and files can be used.
//   Argument 2,3,etc - package:car
//   Key pair to set in the .json file. Required for every empty key in the
//   .json file.
package generate

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"text/template"

	"github.com/blue-jay/jay/lib/common"
)

var (
	// LoopLimit specified the max number of iterations of replacing variables
	// with values to prevent an infinite loop.
	LoopLimit = 100
)

// Run starts the template generation logic
func Run(args []string, rootFolder string) error {
	// Ensure the template pair files exist
	jsonFilePath := filepath.Join(rootFolder, "generate", args[0]+".json")
	if !common.Exists(jsonFilePath) {
		return fmt.Errorf("File doesn't exist: %v", jsonFilePath)
	}

	argMap := argsToMap(args)

	// Get the json file as a map - not parsed
	mapFile, err := jsonFileToMap(jsonFilePath)
	if err != nil {
		return err
	}

	// Generate variable map
	variableMap := generateVariableMap(mapFile, argMap)

	// Check for config type
	configType, ok := variableMap["config.type"]
	if !ok {
		return errors.New("Key, 'config.type', is missing from the .json file")
	}

	// Handle based on config.type
	switch configType {
	case "single":
		// Template File
		genFilePath := filepath.Join(rootFolder, "generate", args[0]+".gen")

		// Generate the template
		generateSingle(rootFolder, genFilePath, variableMap)

		return nil
	case "collection":
		generateCollection(rootFolder, variableMap)
		return nil
	default:
		return fmt.Errorf("Value of '%v' for key 'config.type' is not supported", configType)
	}

	return nil
}

func generateCollection(folderPath string, variableMap map[string]interface{}) {
	// Check for required key
	collectionRaw, ok := variableMap["config.collection"]
	if !ok {
		log.Fatal("Key, 'config.collection', is missing from the .json file")
	}

	collection, ok := collectionRaw.([]interface{})
	if !ok {
		log.Fatal("Key, 'config.collection', is not in the correct format")
	}

	// Loop through the collections
	for i, v := range collection {
		vMap, ok := v.(map[string]interface{})
		if !ok {
			log.Fatal("Values for key, 'config.collection', are not in the correct format")
		}

		for name, varArray := range vMap {
			argMap, ok := varArray.(map[string]interface{})
			if !ok {
				log.Fatalf("Item at index '%v' for key, 'config.collection', is not in the correct format", i)
			}

			// Template File
			genFilePath := filepath.Join(folderPath, "generate", name+".gen")
			jsonFilePath := filepath.Join(folderPath, "generate", name+".json")

			// Get the json file as a map - not parsed
			mapFile, err := jsonFileToMap(jsonFilePath)
			if err != nil {
				log.Fatal(err)
			}

			// Generate variable map
			variableMap := generateVariableMap(mapFile, argMap)

			// Check for config type
			configType, ok := variableMap["config.type"]
			if !ok {
				log.Fatal("Key, 'config.type', is missing from the .json file")
			}

			// Handle based on config.type
			switch configType {
			case "single":
				generateSingle(folderPath, genFilePath, variableMap)
			case "collection":
				generateCollection(folderPath, variableMap)
			default:
				log.Fatalf("Value of '%v' for key 'config.type' is not supported", configType)
			}
		}
	}
}

func generateSingle(folderPath string, genFilePath string, variableMap map[string]interface{}) {
	// Check for required key
	if _, ok := variableMap["config.output"]; !ok {
		log.Fatal("Key, 'config.output', is missing from the .json file")
	}

	// Output file
	outputRelativeFile := fmt.Sprintf("%v", variableMap["config.output"])
	outputFile := filepath.Join(folderPath, outputRelativeFile)

	// Check if the file exists
	if common.Exists(outputFile) {
		log.Fatalf("Cannot generate because file already exists: %v", outputFile)
	}

	// Check if the folder exists
	dir := filepath.Dir(outputFile)
	if !common.Exists(dir) {
		err := os.MkdirAll(dir, os.ModePerm)
		if err != nil {
			log.Fatalln(err)
		}
	}

	// If config.parse = false
	if val, ok := variableMap["config.parse"]; ok {
		if b, _ := strconv.ParseBool(fmt.Sprintf("%v", val)); !b {
			// Don't parse template, just copy to new file
			err := toFile(genFilePath, outputFile)
			if err != nil {
				log.Fatal(err)
			}
			fmt.Println("Code generated:", outputFile)
			return
		}
	}

	// Parse template and write to file
	err := fromMapToFile(genFilePath, variableMap, outputFile)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("Code generated:", outputFile)
}

func cloneMap(originalMap map[string]interface{}) map[string]interface{} {
	copyMap := make(map[string]interface{})

	for k, v := range originalMap {
		copyMap[k] = v
	}

	return copyMap
}

// jsonFileToMap converts json file to an interface map.
func jsonFileToMap(file string) (map[string]interface{}, error) {
	// Read the config file
	b, err := ioutil.ReadFile(file)
	if err != nil {
		return nil, err
	}

	// Convert json to interface
	var d map[string]interface{}
	err = json.Unmarshal(b, &d)
	if err != nil {
		return nil, err
	}

	return d, nil
}

// fromMapToFile will output a file by parsing a template and applying
// variables from an interface map.
func fromMapToFile(templateFile string, d map[string]interface{}, outputFile string) error {
	// Parse the template
	t, err := template.ParseFiles(templateFile)
	if err != nil {
		return err
	}

	// Create the output file
	f, err := os.Create(outputFile)
	if err != nil {
		return err
	}
	defer f.Close()

	// Fills template with variables and writes to file
	err = t.Execute(f, d)
	if err != nil {
		return err
	}

	return nil
}

// toFile will output a file by without parsing.
func toFile(templateFile string, outputFile string) error {

	data, err := ioutil.ReadFile(templateFile)
	if err != nil {
		return err
	}

	err = ioutil.WriteFile(outputFile, data, os.ModePerm)
	if err != nil {
		return err
	}

	return nil
}

func argsToMap(args []string) map[string]interface{} {
	// Fill a new map with variables
	argMap := make(map[string]interface{})
	for _, a := range args[1:] {
		arr := strings.Split(a, ":")

		if len(arr) < 2 {
			log.Fatalf("Arg is in wrong format: %v", a)
		}

		argMap[arr[0]] = strings.Join(arr[1:], ":")
	}

	return argMap
}

// generateVariableMap returns the relative file output path and the map of
// variables.
func generateVariableMap(mapFile map[string]interface{}, argMap map[string]interface{}) map[string]interface{} {
	m := cloneMap(mapFile)

	// Loop through the map to find empty variables
	for s, v := range m {
		switch t := v.(type) {
		case string:
			if len(t) == 0 {
				if val, ok := argMap[s]; ok {
					m[s] = val
				} else {
					log.Fatalf("Variable missing: %v", s)
				}
			} else { // Else delete any values that are not empty
				delete(m, s)
			}
		default:
			delete(m, s)
		}
	}

	// Look through the map of the file and update it with the variables
	for s := range mapFile {
		if passedVal, ok := m[s]; ok {
			mapFile[s] = passedVal
		}
	}

	// Look through the map of the variables and overwrite it with any left over arguments
	// This allows you to overwrite config.output
	for s, v := range argMap {
		if _, ok := m[s]; !ok {
			mapFile[s] = v
		}
	}

	// Counter to prevent infinite loops
	counter := 0

	for true {
		// Convert the mapFile to bytes
		mapFileBytes, err := json.Marshal(mapFile)
		if err != nil {
			log.Fatal(err)
		}

		// Create the buffer
		buf := new(bytes.Buffer)

		// Parse the template
		t, err := template.New("").Parse(string(mapFileBytes))
		if err != nil {
			log.Fatal(err)
		}

		// Fills template with variables
		err = t.Execute(buf, m)
		if err != nil {
			log.Fatal(err)
		}

		parsedTemplate := buf.Bytes()

		// Convert the json text back to a map
		err = json.Unmarshal(parsedTemplate, &m)
		if err != nil {
			log.Fatal(err)
		}

		// If the parsed template is completely filled, then stop the run, else
		// keep running
		if !strings.Contains(string(parsedTemplate), "<no value>") {
			break
		}

		var invalidKeys []string

		// Loop through the map to find empty variables
		for s, v := range m {
			switch t := v.(type) {
			case string:
				if strings.Contains(t, "<no value>") {
					invalidKeys = append(invalidKeys, s)
					delete(m, s)
				}
			default:
				// This if statement outputs a helpful error if in a nested
				// map
				if strings.Contains(fmt.Sprintf("%v", v), "<no value>") {
					invalidKeys = append(invalidKeys, fmt.Sprintf("%v %v", s, v))
				}
				delete(m, s)
			}
		}

		counter++

		if counter > LoopLimit {
			log.Fatalf("Check these keys for variable mistakes: %v", invalidKeys)
			break
		}
	}

	return m
}
<commit_msg>Fix vet issue<commit_after>// Package generate will parse and create files from template pairs.
// A template pair is a set of template files:
//   * default.json - json file
//   * default.gen - any type of text file
//
// Both files are template files and are parsed using the Go text/template
// package. The 'jay generate' tool loops through the first level of key pairs
// for empty strings. For every empty string, an argument is required to be
// passed (whether empty or not) to the 'jay generate' command.
//
// Let's look at generate/model/default.json:
// {
//   "config.type": "single",
//   "config.output": "model/{{.package}}/{{.package}}.go",
//   "package": "",
//   "table": ""
// }
//
// Let's break down this command into pieces:
// jay generate model/default package:automobile table:car
//
// Argument: 'model/default'
// Specifies generate/model/default.json and generate/model/default.gen are the
// template pair.
//
// Argument: 'package:automobile'
// The key, 'package', from default.json will be filled with the value:
// 'automobile'
//
// Argument: 'table:car'
// The key, 'table', from default.json will be filled with the value: 'car'
//
// The .json file is actually parsed up to 100 times (LoopLimit of 100 can be
// changed at the package level) to ensure all variables like '{{.package}}' are
// set to the correct value.
//
// In the first iteration of parsing, the 'package' key is set to 'car'.
// In the second iteration of parsing, the '{{.package}}' variables
// are set to 'car' also since the 'package' key becomes a variable.
//
// All first level keys (info, package, table) become variables after the first
// iteration of parsing so they can be used without the file. If a variable is
// misspelled and is never filled, a helpful error will be displayed.
//
// The 'output' key under 'info' is required. It should be the relative output
// file path to the project root for the generated file.
//
// The folder structure of the templates (model, controller, etc) has no effect
// on the generation, it's purely to aid with organization of the template pairs.
//
// You must store the path to the env.json file in the environment
// variable: JAYCONFIG. The file is at project root that is prepended to all
// relative file paths.
//
// Examples:
//   jay generate model/default package:car table:car
//   Generate a new model from variables in model/default.json and applies
//   those variables to model/default.gen.
//   jay generate controller/default package:car url:car model:car view:car
//   Generate a new controller from variables in controller/default.json
//   and applies those variables to controller/default.gen.
//
// Flags:
//   Argument 1 - model/default or controller/default
//   Relative path without an extension to the template pair. Any combination
//   of folders and files can be used.
//   Argument 2,3,etc - package:car
//   Key pair to set in the .json file. Required for every empty key in the
//   .json file.
package generate

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"text/template"

	"github.com/blue-jay/jay/lib/common"
)

var (
	// LoopLimit specified the max number of iterations of replacing variables
	// with values to prevent an infinite loop.
	LoopLimit = 100
)

// Run starts the template generation logic
func Run(args []string, rootFolder string) error {
	// Ensure the template pair files exist
	jsonFilePath := filepath.Join(rootFolder, "generate", args[0]+".json")
	if !common.Exists(jsonFilePath) {
		return fmt.Errorf("File doesn't exist: %v", jsonFilePath)
	}

	argMap := argsToMap(args)

	// Get the json file as a map - not parsed
	mapFile, err := jsonFileToMap(jsonFilePath)
	if err != nil {
		return err
	}

	// Generate variable map
	variableMap := generateVariableMap(mapFile, argMap)

	// Check for config type
	configType, ok := variableMap["config.type"]
	if !ok {
		return errors.New("Key, 'config.type', is missing from the .json file")
	}

	// Handle based on config.type
	switch configType {
	case "single":
		// Template File
		genFilePath := filepath.Join(rootFolder, "generate", args[0]+".gen")

		// Generate the template
		generateSingle(rootFolder, genFilePath, variableMap)
	case "collection":
		generateCollection(rootFolder, variableMap)
	default:
		return fmt.Errorf("Value of '%v' for key 'config.type' is not supported", configType)
	}

	return nil
}

func generateCollection(folderPath string, variableMap map[string]interface{}) {
	// Check for required key
	collectionRaw, ok := variableMap["config.collection"]
	if !ok {
		log.Fatal("Key, 'config.collection', is missing from the .json file")
	}

	collection, ok := collectionRaw.([]interface{})
	if !ok {
		log.Fatal("Key, 'config.collection', is not in the correct format")
	}

	// Loop through the collections
	for i, v := range collection {
		vMap, ok := v.(map[string]interface{})
		if !ok {
			log.Fatal("Values for key, 'config.collection', are not in the correct format")
		}

		for name, varArray := range vMap {
			argMap, ok := varArray.(map[string]interface{})
			if !ok {
				log.Fatalf("Item at index '%v' for key, 'config.collection', is not in the correct format", i)
			}

			// Template File
			genFilePath := filepath.Join(folderPath, "generate", name+".gen")
			jsonFilePath := filepath.Join(folderPath, "generate", name+".json")

			// Get the json file as a map - not parsed
			mapFile, err := jsonFileToMap(jsonFilePath)
			if err != nil {
				log.Fatal(err)
			}

			// Generate variable map
			variableMap := generateVariableMap(mapFile, argMap)

			// Check for config type
			configType, ok := variableMap["config.type"]
			if !ok {
				log.Fatal("Key, 'config.type', is missing from the .json file")
			}

			// Handle based on config.type
			switch configType {
			case "single":
				generateSingle(folderPath, genFilePath, variableMap)
			case "collection":
				generateCollection(folderPath, variableMap)
			default:
				log.Fatalf("Value of '%v' for key 'config.type' is not supported", configType)
			}
		}
	}
}

func generateSingle(folderPath string, genFilePath string, variableMap map[string]interface{}) {
	// Check for required key
	if _, ok := variableMap["config.output"]; !ok {
		log.Fatal("Key, 'config.output', is missing from the .json file")
	}

	// Output file
	outputRelativeFile := fmt.Sprintf("%v", variableMap["config.output"])
	outputFile := filepath.Join(folderPath, outputRelativeFile)

	// Check if the file exists
	if common.Exists(outputFile) {
		log.Fatalf("Cannot generate because file already exists: %v", outputFile)
	}

	// Check if the folder exists
	dir := filepath.Dir(outputFile)
	if !common.Exists(dir) {
		err := os.MkdirAll(dir, os.ModePerm)
		if err != nil {
			log.Fatalln(err)
		}
	}

	// If config.parse = false
	if val, ok := variableMap["config.parse"]; ok {
		if b, _ := strconv.ParseBool(fmt.Sprintf("%v", val)); !b {
			// Don't parse template, just copy to new file
			err := toFile(genFilePath, outputFile)
			if err != nil {
				log.Fatal(err)
			}
			fmt.Println("Code generated:", outputFile)
			return
		}
	}

	// Parse template and write to file
	err := fromMapToFile(genFilePath, variableMap, outputFile)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("Code generated:", outputFile)
}

func cloneMap(originalMap map[string]interface{}) map[string]interface{} {
	copyMap := make(map[string]interface{})

	for k, v := range originalMap {
		copyMap[k] = v
	}

	return copyMap
}

// jsonFileToMap converts json file to an interface map.
func jsonFileToMap(file string) (map[string]interface{}, error) {
	// Read the config file
	b, err := ioutil.ReadFile(file)
	if err != nil {
		return nil, err
	}

	// Convert json to interface
	var d map[string]interface{}
	err = json.Unmarshal(b, &d)
	if err != nil {
		return nil, err
	}

	return d, nil
}

// fromMapToFile will output a file by parsing a template and applying
// variables from an interface map.
func fromMapToFile(templateFile string, d map[string]interface{}, outputFile string) error {
	// Parse the template
	t, err := template.ParseFiles(templateFile)
	if err != nil {
		return err
	}

	// Create the output file
	f, err := os.Create(outputFile)
	if err != nil {
		return err
	}
	defer f.Close()

	// Fills template with variables and writes to file
	err = t.Execute(f, d)
	if err != nil {
		return err
	}

	return nil
}

// toFile will output a file by without parsing.
func toFile(templateFile string, outputFile string) error {

	data, err := ioutil.ReadFile(templateFile)
	if err != nil {
		return err
	}

	err = ioutil.WriteFile(outputFile, data, os.ModePerm)
	if err != nil {
		return err
	}

	return nil
}

func argsToMap(args []string) map[string]interface{} {
	// Fill a new map with variables
	argMap := make(map[string]interface{})
	for _, a := range args[1:] {
		arr := strings.Split(a, ":")

		if len(arr) < 2 {
			log.Fatalf("Arg is in wrong format: %v", a)
		}

		argMap[arr[0]] = strings.Join(arr[1:], ":")
	}

	return argMap
}

// generateVariableMap returns the relative file output path and the map of
// variables.
func generateVariableMap(mapFile map[string]interface{}, argMap map[string]interface{}) map[string]interface{} {
	m := cloneMap(mapFile)

	// Loop through the map to find empty variables
	for s, v := range m {
		switch t := v.(type) {
		case string:
			if len(t) == 0 {
				if val, ok := argMap[s]; ok {
					m[s] = val
				} else {
					log.Fatalf("Variable missing: %v", s)
				}
			} else { // Else delete any values that are not empty
				delete(m, s)
			}
		default:
			delete(m, s)
		}
	}

	// Look through the map of the file and update it with the variables
	for s := range mapFile {
		if passedVal, ok := m[s]; ok {
			mapFile[s] = passedVal
		}
	}

	// Look through the map of the variables and overwrite it with any left over arguments
	// This allows you to overwrite config.output
	for s, v := range argMap {
		if _, ok := m[s]; !ok {
			mapFile[s] = v
		}
	}

	// Counter to prevent infinite loops
	counter := 0

	for true {
		// Convert the mapFile to bytes
		mapFileBytes, err := json.Marshal(mapFile)
		if err != nil {
			log.Fatal(err)
		}

		// Create the buffer
		buf := new(bytes.Buffer)

		// Parse the template
		t, err := template.New("").Parse(string(mapFileBytes))
		if err != nil {
			log.Fatal(err)
		}

		// Fills template with variables
		err = t.Execute(buf, m)
		if err != nil {
			log.Fatal(err)
		}

		parsedTemplate := buf.Bytes()

		// Convert the json text back to a map
		err = json.Unmarshal(parsedTemplate, &m)
		if err != nil {
			log.Fatal(err)
		}

		// If the parsed template is completely filled, then stop the run, else
		// keep running
		if !strings.Contains(string(parsedTemplate), "<no value>") {
			break
		}

		var invalidKeys []string

		// Loop through the map to find empty variables
		for s, v := range m {
			switch t := v.(type) {
			case string:
				if strings.Contains(t, "<no value>") {
					invalidKeys = append(invalidKeys, s)
					delete(m, s)
				}
			default:
				// This if statement outputs a helpful error if in a nested
				// map
				if strings.Contains(fmt.Sprintf("%v", v), "<no value>") {
					invalidKeys = append(invalidKeys, fmt.Sprintf("%v %v", s, v))
				}
				delete(m, s)
			}
		}

		counter++

		if counter > LoopLimit {
			log.Fatalf("Check these keys for variable mistakes: %v", invalidKeys)
			break
		}
	}

	return m
}
<|endoftext|>


<commit_before>package tutum

import "encoding/json"

type SListResponse struct {
	Objects []Service `json: "objects"`
}

type Service struct {
	Autodestroy            string       `json:"autodestroy"`
	Autoreplace            string       `json:"autoreplace"`
	Autoredeploy           bool         `json:"autoredeploy"`
	Autorestart            string       `json:"autorestart"`
	Containers             []string     `json:"containers"`
	Container_ports        []SCPInfo    `json:"container_ports"`
	Container_size         string       `json:"container_size"`
	Current_num_containers int          `json:"current_num_containers"`
	Deployed_datetime      string       `json:"deployed_datetime"`
	Destroyed_datetime     string       `json:"destroyed_datetime"`
	Entrypoint             string       `json:"entrypoint"`
	Exit_code              int          `json:"exit_code"`
	Exit_code_message      string       `json:"exit_code_message"`
	Image_name             string       `json:"image_name"`
	Image_tag              string       `json:"image_tag"`
	Linked_to_service      []LinkToInfo `json:"linked_to_service"`
	Name                   string       `json:"name"`
	Public_dns             string       `json:"public_dns"`
	Resource_uri           string       `json:"resource_uri"`
	Run_command            string       `json:"run_command"`
	Started_datetime       string       `json:"started_datetime"`
	State                  string       `json:"state"`
	Stack                  string       `json:"stack"`
	Stopped_datetime       string       `json:"stopped_datetime"`
	Target_num_containers  int          `json:"target_num_containers"`
	Unique_name            string       `json:"unique_name"`
	Uuid                   string       `json:"uuid"`
}

type SCPInfo struct {
	Container  string `json:"container"`
	Inner_port int    `json:"inner_port"`
	Outer_port int    `json:"outer_port"`
	Protocol   string `json:"protocol"`
}

type LinkToInfo struct {
	From_service string `json:"from_service"`
	Name         string `json:"name"`
	To_service   string `json:"to_service"`
}

type BasicService struct {
	Image                 string `json:"image"`
	Name                  string `json:"name"`
	Target_num_containers int    `json:"target_num_containers"`
}

func ListServices() ([]Service, error) {
	url := "service/"
	request := "GET"
	body := []byte(`{}`)
	var response SListResponse

	data, err := TutumCall(url, request, body)
	if err != nil {
		return nil, err
	}
	err = json.Unmarshal(data, &response)
	if err != nil {
		return nil, err
	}
	return response.Objects, nil

}

func GetService(uuid string) (Service, error) {

	url := "service/" + uuid + "/"
	request := "GET"
	body := []byte(`{}`)
	var response Service

	data, err := TutumCall(url, request, body)
	if err != nil {
		panic(err)
	}

	err = json.Unmarshal(data, &response)
	if err != nil {
		panic(err)
	}

	return response, nil

}

func CreateService(newService BasicService) (Service, error) {

	/*url := "service/"
	request := "POST"*/
	//TUTUM CALL WITH BYTE BODY REQUEST
	var response Service

	return response, nil

}

func GetServiceLogs(uuid string) (string, error) {

	url := "service/" + uuid + "/logs/"
	request := "GET"
	body := []byte(`{}`)

	data, err := TutumCall(url, request, body)
	if err != nil {
		return "", err
	}

	s := string(data)

	return s, nil

}

func StartService(uuid string) (Service, error) {

	url := "service/" + uuid + "/start/"
	request := "POST"
	body := []byte(`{}`)
	var response Service

	data, err := TutumCall(url, request, body)
	if err != nil {
		panic(err)
	}

	err = json.Unmarshal(data, &response)
	if err != nil {
		panic(err)
	}

	return response, nil
}

func StopService(uuid string) (Service, error) {

	url := "service/" + uuid + "/stop/"
	request := "POST"
	body := []byte(`{}`)
	var response Service

	data, err := TutumCall(url, request, body)
	if err != nil {
		panic(err)
	}

	err = json.Unmarshal(data, &response)
	if err != nil {
		panic(err)
	}

	return response, nil
}

func RedeployService(uuid string) (Service, error) {

	url := "service/" + uuid + "/redeploy/"
	request := "POST"
	body := []byte(`{}`)
	var response Service

	data, err := TutumCall(url, request, body)
	if err != nil {
		panic(err)
	}

	err = json.Unmarshal(data, &response)
	if err != nil {
		panic(err)
	}

	return response, nil

}

func TerminateService(uuid string) (Service, error) {
	url := "service/" + uuid + "/"
	request := "DELETE"
	body := []byte(`{}`)
	var response Service

	data, err := TutumCall(url, request, body)
	if err != nil {
		panic(err)
	}

	err = json.Unmarshal(data, &response)
	if err != nil {
		panic(err)
	}

	return response, nil

}
<commit_msg>Add createService method<commit_after>package tutum

import "encoding/json"

type SListResponse struct {
	Objects []Service `json: "objects"`
}

type Service struct {
	Autodestroy            string       `json:"autodestroy"`
	Autoreplace            string       `json:"autoreplace"`
	Autoredeploy           bool         `json:"autoredeploy"`
	Autorestart            string       `json:"autorestart"`
	Containers             []string     `json:"containers"`
	Container_ports        []SCPInfo    `json:"container_ports"`
	Container_size         string       `json:"container_size"`
	Current_num_containers int          `json:"current_num_containers"`
	Deployed_datetime      string       `json:"deployed_datetime"`
	Destroyed_datetime     string       `json:"destroyed_datetime"`
	Entrypoint             string       `json:"entrypoint"`
	Exit_code              int          `json:"exit_code"`
	Exit_code_message      string       `json:"exit_code_message"`
	Image_name             string       `json:"image_name"`
	Image_tag              string       `json:"image_tag"`
	Linked_to_service      []LinkToInfo `json:"linked_to_service"`
	Name                   string       `json:"name"`
	Public_dns             string       `json:"public_dns"`
	Resource_uri           string       `json:"resource_uri"`
	Run_command            string       `json:"run_command"`
	Started_datetime       string       `json:"started_datetime"`
	State                  string       `json:"state"`
	Stack                  string       `json:"stack"`
	Stopped_datetime       string       `json:"stopped_datetime"`
	Target_num_containers  int          `json:"target_num_containers"`
	Unique_name            string       `json:"unique_name"`
	Uuid                   string       `json:"uuid"`
}

type SCPInfo struct {
	Container  string `json:"container"`
	Inner_port int    `json:"inner_port"`
	Outer_port int    `json:"outer_port"`
	Protocol   string `json:"protocol"`
}

type LinkToInfo struct {
	From_service string `json:"from_service"`
	Name         string `json:"name"`
	To_service   string `json:"to_service"`
}

type BasicService struct {
	Image                 string `json:"image"`
	Name                  string `json:"name"`
	Target_num_containers int    `json:"target_num_containers"`
}

func ListServices() ([]Service, error) {
	url := "service/"
	request := "GET"
	body := []byte(`{}`)
	var response SListResponse

	data, err := TutumCall(url, request, body)
	if err != nil {
		return nil, err
	}
	err = json.Unmarshal(data, &response)
	if err != nil {
		return nil, err
	}
	return response.Objects, nil

}

func GetService(uuid string) (Service, error) {

	url := "service/" + uuid + "/"
	request := "GET"
	body := []byte(`{}`)
	var response Service

	data, err := TutumCall(url, request, body)
	if err != nil {
		panic(err)
	}

	err = json.Unmarshal(data, &response)
	if err != nil {
		panic(err)
	}

	return response, nil

}

func CreateService(newService []byte) (Service, error) {

	url := "service/"
	request := "POST"

	var response Service

	data, err := TutumCall(url, request, newService)
	if err != nil {
		panic(err)
	}

	err = json.Unmarshal(data, &response)
	if err != nil {
		panic(err)
	}

	return response, nil

}

func GetServiceLogs(uuid string) (string, error) {

	url := "service/" + uuid + "/logs/"
	request := "GET"
	body := []byte(`{}`)

	data, err := TutumCall(url, request, body)
	if err != nil {
		return "", err
	}

	s := string(data)

	return s, nil

}

func StartService(uuid string) (Service, error) {

	url := "service/" + uuid + "/start/"
	request := "POST"
	body := []byte(`{}`)
	var response Service

	data, err := TutumCall(url, request, body)
	if err != nil {
		panic(err)
	}

	err = json.Unmarshal(data, &response)
	if err != nil {
		panic(err)
	}

	return response, nil
}

func StopService(uuid string) (Service, error) {

	url := "service/" + uuid + "/stop/"
	request := "POST"
	body := []byte(`{}`)
	var response Service

	data, err := TutumCall(url, request, body)
	if err != nil {
		panic(err)
	}

	err = json.Unmarshal(data, &response)
	if err != nil {
		panic(err)
	}

	return response, nil
}

func RedeployService(uuid string) (Service, error) {

	url := "service/" + uuid + "/redeploy/"
	request := "POST"
	body := []byte(`{}`)
	var response Service

	data, err := TutumCall(url, request, body)
	if err != nil {
		panic(err)
	}

	err = json.Unmarshal(data, &response)
	if err != nil {
		panic(err)
	}

	return response, nil

}

func TerminateService(uuid string) (Service, error) {
	url := "service/" + uuid + "/"
	request := "DELETE"
	body := []byte(`{}`)
	var response Service

	data, err := TutumCall(url, request, body)
	if err != nil {
		panic(err)
	}

	err = json.Unmarshal(data, &response)
	if err != nil {
		panic(err)
	}

	return response, nil

}
<|endoftext|>


<commit_before>// Copyright © 2016 Jip J. Dekker <jip@dekker.li>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package compiler

import "github.com/jjdekker/ponder/settings"

var (
	lilypondCmd  = "lilypond"
	lilypondArgs []string
)

//
func prepareLilypondArgs(opts *settings.Settings) {
	// Adds all includes to the lilypond arguments
	for dir := range opts.LilypondIncludes {
		lilypondArgs = append(lilypondArgs, "--include=\""+dir+"\"")
	}
	lilypondArgs = append(lilypondArgs, "--loglevel=ERROR")
	lilypondArgs = append(lilypondArgs, "--pdf")
	// TODO: Make this an absolute path.
	lilypondArgs = append(lilypondArgs, "--output=\""+opts.OutputDir+"\"")
}

// Lilypond runs the lilypond compiler
func Lilypond(path string) error {
	return nil
}
<commit_msg>Adds function to call the lilypond compiler<commit_after>// Copyright © 2016 Jip J. Dekker <jip@dekker.li>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package compiler

import (
	"os/exec"

	"github.com/jjdekker/ponder/settings"
)

var (
	lilypondCmd  = "lilypond"
	lilypondArgs []string
)

// PrepareLilypond sets all arguments and options for the Lilypond
// compilation function using the given settings
func PrepareLilypond(opts *settings.Settings) {
	// Adds all includes to the lilypond arguments
	for dir := range opts.LilypondIncludes {
		lilypondArgs = append(lilypondArgs, "--include=\""+dir+"\"")
	}
	lilypondArgs = append(lilypondArgs, "--loglevel=ERROR")
	lilypondArgs = append(lilypondArgs, "--pdf")
	// TODO: Make this an absolute path.
	lilypondArgs = append(lilypondArgs, "--output=\""+opts.OutputDir+"\"")
}

// Lilypond runs the lilypond compiler on the given path
// using the arguments prepared by the PrepareLilypond function
func Lilypond(path string) (string, error) {
	cmd := exec.Command(lilypondCmd, append(lilypondArgs, path)...)
	return cmd.CombinedOutput()
}
<|endoftext|>