<commit_before>// Copyright 2016 Mesosphere, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     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 main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"reflect"
	"strings"
	"time"

	log "github.com/Sirupsen/logrus"
	yaml "gopkg.in/yaml.v2"

	"github.com/dcos/dcos-go/dcos"
	"github.com/dcos/dcos-go/dcos/nodeutil"
	"github.com/dcos/dcos-go/jwt/transport"
	"github.com/dcos/dcos-metrics/collector"
	"github.com/dcos/dcos-metrics/producers"
	httpProducer "github.com/dcos/dcos-metrics/producers/http"
	//kafkaProducer "github.com/dcos/dcos-metrics/producers/kafka"
	//statsdProducer "github.com/dcos/dcos-metrics/producers/statsd"
	"github.com/dcos/dcos-metrics/util"
)

var (
	VERSION  = "unset"
	REVISION = "unset"
)

// Config defines the top-level configuration options for the dcos-metrics-collector project.
// It is (currently) broken up into two main sections: collectors and producers.
type Config struct {
	// Config from the service config file
	Collector     CollectorConfig `yaml:"collector"`
	Producers     ProducersConfig `yaml:"producers"`
	IAMConfigPath string          `yaml:"iam_config_path"`
	VersionFlag   bool

	// Generated by dcos.NodeInfo{}
	MesosID   string
	IPAddress string
	ClusterID string

	// Flag configuration
	DCOSRole   string
	ConfigPath string
	LogLevel   string
}

// CollectorConfig contains configuration options relevant to the "collector"
// portion of this project. That is, the code responsible for querying Mesos,
// et. al to gather metrics and send them to a "producer".
type CollectorConfig struct {
	HTTPProfiler  bool   `yaml:"http_profiler"`
	IPCommand     string `yaml:"ip_command"`
	PollingPeriod int    `yaml:"polling_period"`

	MasterConfig collector.MasterConfig `yaml:"master_config,omitempty"`
	AgentConfig  collector.AgentConfig  `yaml:"agent_config,omitempty"`
}

// ProducersConfig contains references to other structs that provide individual producer configs.
// The configuration for all producers is then located in their corresponding packages.
//
// For example: Config.Producers.KafkaProducerConfig references kafkaProducer.Config. This struct
// contains an optional Kafka configuration. This configuration is available in the source file
// 'producers/kafka/kafka.go'. It is then the responsibility of the individual producers to
// validate the configuration the user has provided and panic if necessary.
type ProducersConfig struct {
	HTTPProducerConfig httpProducer.Config `yaml:"http,omitempty"`
	//KafkaProducerConfig  kafkaProducer.Config  `yaml:"kafka,omitempty"`
	//StatsdProducerConfig statsdProducer.Config `yaml:"statsd,omitempty"`
}

func main() {
	// Get configuration
	cfg, err := getNewConfig(os.Args[1:])
	if err != nil {
		log.Fatal(err)
		os.Exit(1)
	}
	if cfg.VersionFlag {
		fmt.Printf("DC/OS Metrics Service\nVersion: %s\nRevsision: %s\n\r", VERSION, REVISION)
		os.Exit(0)
	}

	// Set logging level
	lvl, err := log.ParseLevel(cfg.LogLevel)
	if err != nil {
		log.Fatal(err)
		os.Exit(1)
	}
	log.SetLevel(lvl)

	// HTTP profiling
	if cfg.Collector.HTTPProfiler {
		log.Info("HTTP profiling enabled")
		go util.RunHTTPProfAccess()
	}

	var producerChans []chan<- producers.MetricsMessage

	// HTTP producer
	if producerIsConfigured("http", cfg) {
		log.Info("HTTP producer enabled")
		c := httpProducer.Config{
			Port:        cfg.Producers.HTTPProducerConfig.Port,
			DCOSRole:    cfg.DCOSRole,
			CacheExpiry: time.Duration(cfg.Collector.PollingPeriod) * time.Second * 2,
		}
		hp, httpProducerChan := httpProducer.New(c)
		producerChans = append(producerChans, httpProducerChan)
		go hp.Run()
	}

	// Host-level Metrics Collector
	nodeCollectorChan := make(chan producers.MetricsMessage)
	frameworkCollectorChan := make(chan *collector.AvroDatum)

	log.Info("Agent polling enabled")

	host, err := collector.NewDCOSHost(
		cfg.DCOSRole,
		cfg.IPAddress,
		cfg.MesosID,
		cfg.ClusterID,
		cfg.Collector.AgentConfig.Port,
		time.Duration(cfg.Collector.PollingPeriod)*time.Second, nodeCollectorChan)

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

	go host.RunPoller()

	go collector.RunFrameworkTCPListener(frameworkCollectorChan)

	// Broadcast (many-to-many) messages from the collector to the various producers.
	for {
		select {
		case frameworkMessage := <-frameworkCollectorChan:
			pmm, err := frameworkMessage.Transform(cfg.MesosID, cfg.ClusterID, cfg.IPAddress)
			if err != nil {
				log.Error(err)
			}
			for _, producer := range producerChans {
				producer <- pmm
			}
		case agentMessage := <-nodeCollectorChan:
			for _, producer := range producerChans {
				producer <- agentMessage
			}
		}
	}
}

func (c *Config) setFlags(fs *flag.FlagSet) {
	fs.StringVar(&c.ConfigPath, "config", c.ConfigPath, "The path to the config file.")
	fs.StringVar(&c.LogLevel, "loglevel", c.LogLevel, "Logging level (default: info). Must be one of: debug, info, warn, error, fatal, panic.")
	fs.StringVar(&c.DCOSRole, "role", c.DCOSRole, "The DC/OS role this instance runs on.")
	fs.BoolVar(&c.VersionFlag, "version", c.VersionFlag, "Print version and revsion then exit")
}

func (c *Config) loadConfig() error {
	fileByte, err := ioutil.ReadFile(c.ConfigPath)
	if err != nil {
		return err
	}

	if err = yaml.Unmarshal(fileByte, &c); err != nil {
		return err
	}

	return nil
}

func (c *Config) getNodeInfo() error {
	// Create a DC/OS transport
	client := &http.Client{}
	// If IAM config path is set, use it to generate a new
	// round tripper for JWT stuff
	if len(c.IAMConfigPath) != 0 {
		rt, err := transport.NewRoundTripper(
			client.Transport,
			transport.OptionReadIAMConfig(c.IAMConfigPath))
		if err != nil {
			log.Fatal(err)
		}
		client.Transport = rt
	}

	// Get NodeInfo
	nodeInfo, err := nodeutil.NewNodeInfo(client)
	if err != nil {
		return err
	}

	ip, err := nodeInfo.DetectIP()
	if err != nil {
		return err
	}
	c.IPAddress = ip.String()

	id, err := nodeInfo.MesosID(nil)
	if err != nil {
		c.MesosID = ""
	} else {
		c.MesosID = id
	}

	if c.DCOSRole == dcos.RoleMaster {
		cid, err := nodeInfo.ClusterID()
		if err != nil {
			return err
		}
		c.ClusterID = cid
	}
	return nil
}

// newConfig establishes our default, base configuration.
func newConfig() Config {
	return Config{
		Collector: CollectorConfig{
			HTTPProfiler:  true,
			IPCommand:     "/opt/mesosphere/bin/detect_ip",
			PollingPeriod: 15,
			MasterConfig: collector.MasterConfig{
				Port: 5050,
			},
			AgentConfig: collector.AgentConfig{
				Port: 5051,
			},
		},
		Producers: ProducersConfig{
			HTTPProducerConfig: httpProducer.Config{
				Port: 8000,
			},
		},
		ConfigPath: "dcos-metrics-config.yaml",
		LogLevel:   "info",
	}
}

// getNewConfig loads the configuration and sets precedence of configuration values.
// For example: command line flags override values provided in the config file.
func getNewConfig(args []string) (Config, error) {
	c := newConfig()
	thisFlagSet := flag.NewFlagSet("", flag.ExitOnError)
	c.setFlags(thisFlagSet)
	// Override default config with CLI flags if any
	if err := thisFlagSet.Parse(args); err != nil {
		fmt.Println("Errors encountered parsing flags.")
		return c, err
	}

	if err := c.loadConfig(); err != nil {
		return c, err
	}

	// Note: .getNodeInfo() is last so we are sure we have all the
	// configuration we need from flags and config file to make
	// this run correctly.
	if err := c.getNodeInfo(); err != nil {
		return c, err
	}

	return c, nil
}

// producerIsConfigured analyzes the ProducersConfig struct and determines if
// configuration exists for a given producer by name (i.e., is the "http"
// producer configured?). If a configuration exists, this function will return
// true, as a configured producer is an enabled one.
func producerIsConfigured(name string, cfg Config) bool {
	s := reflect.ValueOf(cfg.Producers)
	cfgType := s.Type()
	for i := 0; i < s.NumField(); i++ {
		if strings.Split(cfgType.Field(i).Tag.Get("yaml"), ",")[0] == name {
			return true
		}
	}
	return false
}
<commit_msg>Add comments to exported VERSION & REVISION<commit_after>// Copyright 2016 Mesosphere, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     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 main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"reflect"
	"strings"
	"time"

	log "github.com/Sirupsen/logrus"
	yaml "gopkg.in/yaml.v2"

	"github.com/dcos/dcos-go/dcos"
	"github.com/dcos/dcos-go/dcos/nodeutil"
	"github.com/dcos/dcos-go/jwt/transport"
	"github.com/dcos/dcos-metrics/collector"
	"github.com/dcos/dcos-metrics/producers"
	httpProducer "github.com/dcos/dcos-metrics/producers/http"
	//kafkaProducer "github.com/dcos/dcos-metrics/producers/kafka"
	//statsdProducer "github.com/dcos/dcos-metrics/producers/statsd"
	"github.com/dcos/dcos-metrics/util"
)

var (
	// VERSION set by $(git describe --always)
	// Set by scripts/build.sh, executed by `make build`
	VERSION = "unset"
	// REVISION set by $(git rev-parse --shore HEAD)
	// Set by scripts/build.sh, executed by `make build`
	REVISION = "unset"
)

// Config defines the top-level configuration options for the dcos-metrics-collector project.
// It is (currently) broken up into two main sections: collectors and producers.
type Config struct {
	// Config from the service config file
	Collector     CollectorConfig `yaml:"collector"`
	Producers     ProducersConfig `yaml:"producers"`
	IAMConfigPath string          `yaml:"iam_config_path"`
	VersionFlag   bool

	// Generated by dcos.NodeInfo{}
	MesosID   string
	IPAddress string
	ClusterID string

	// Flag configuration
	DCOSRole   string
	ConfigPath string
	LogLevel   string
}

// CollectorConfig contains configuration options relevant to the "collector"
// portion of this project. That is, the code responsible for querying Mesos,
// et. al to gather metrics and send them to a "producer".
type CollectorConfig struct {
	HTTPProfiler  bool   `yaml:"http_profiler"`
	IPCommand     string `yaml:"ip_command"`
	PollingPeriod int    `yaml:"polling_period"`

	MasterConfig collector.MasterConfig `yaml:"master_config,omitempty"`
	AgentConfig  collector.AgentConfig  `yaml:"agent_config,omitempty"`
}

// ProducersConfig contains references to other structs that provide individual producer configs.
// The configuration for all producers is then located in their corresponding packages.
//
// For example: Config.Producers.KafkaProducerConfig references kafkaProducer.Config. This struct
// contains an optional Kafka configuration. This configuration is available in the source file
// 'producers/kafka/kafka.go'. It is then the responsibility of the individual producers to
// validate the configuration the user has provided and panic if necessary.
type ProducersConfig struct {
	HTTPProducerConfig httpProducer.Config `yaml:"http,omitempty"`
	//KafkaProducerConfig  kafkaProducer.Config  `yaml:"kafka,omitempty"`
	//StatsdProducerConfig statsdProducer.Config `yaml:"statsd,omitempty"`
}

func main() {
	// Get configuration
	cfg, err := getNewConfig(os.Args[1:])
	if err != nil {
		log.Fatal(err)
		os.Exit(1)
	}
	if cfg.VersionFlag {
		fmt.Printf("DC/OS Metrics Service\nVersion: %s\nRevsision: %s\n\r", VERSION, REVISION)
		os.Exit(0)
	}

	// Set logging level
	lvl, err := log.ParseLevel(cfg.LogLevel)
	if err != nil {
		log.Fatal(err)
		os.Exit(1)
	}
	log.SetLevel(lvl)

	// HTTP profiling
	if cfg.Collector.HTTPProfiler {
		log.Info("HTTP profiling enabled")
		go util.RunHTTPProfAccess()
	}

	var producerChans []chan<- producers.MetricsMessage

	// HTTP producer
	if producerIsConfigured("http", cfg) {
		log.Info("HTTP producer enabled")
		c := httpProducer.Config{
			Port:        cfg.Producers.HTTPProducerConfig.Port,
			DCOSRole:    cfg.DCOSRole,
			CacheExpiry: time.Duration(cfg.Collector.PollingPeriod) * time.Second * 2,
		}
		hp, httpProducerChan := httpProducer.New(c)
		producerChans = append(producerChans, httpProducerChan)
		go hp.Run()
	}

	// Host-level Metrics Collector
	nodeCollectorChan := make(chan producers.MetricsMessage)
	frameworkCollectorChan := make(chan *collector.AvroDatum)

	log.Info("Agent polling enabled")

	host, err := collector.NewDCOSHost(
		cfg.DCOSRole,
		cfg.IPAddress,
		cfg.MesosID,
		cfg.ClusterID,
		cfg.Collector.AgentConfig.Port,
		time.Duration(cfg.Collector.PollingPeriod)*time.Second, nodeCollectorChan)

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

	go host.RunPoller()

	go collector.RunFrameworkTCPListener(frameworkCollectorChan)

	// Broadcast (many-to-many) messages from the collector to the various producers.
	for {
		select {
		case frameworkMessage := <-frameworkCollectorChan:
			pmm, err := frameworkMessage.Transform(cfg.MesosID, cfg.ClusterID, cfg.IPAddress)
			if err != nil {
				log.Error(err)
			}
			for _, producer := range producerChans {
				producer <- pmm
			}
		case agentMessage := <-nodeCollectorChan:
			for _, producer := range producerChans {
				producer <- agentMessage
			}
		}
	}
}

func (c *Config) setFlags(fs *flag.FlagSet) {
	fs.StringVar(&c.ConfigPath, "config", c.ConfigPath, "The path to the config file.")
	fs.StringVar(&c.LogLevel, "loglevel", c.LogLevel, "Logging level (default: info). Must be one of: debug, info, warn, error, fatal, panic.")
	fs.StringVar(&c.DCOSRole, "role", c.DCOSRole, "The DC/OS role this instance runs on.")
	fs.BoolVar(&c.VersionFlag, "version", c.VersionFlag, "Print version and revsion then exit")
}

func (c *Config) loadConfig() error {
	fileByte, err := ioutil.ReadFile(c.ConfigPath)
	if err != nil {
		return err
	}

	if err = yaml.Unmarshal(fileByte, &c); err != nil {
		return err
	}

	return nil
}

func (c *Config) getNodeInfo() error {
	// Create a DC/OS transport
	client := &http.Client{}
	// If IAM config path is set, use it to generate a new
	// round tripper for JWT stuff
	if len(c.IAMConfigPath) != 0 {
		rt, err := transport.NewRoundTripper(
			client.Transport,
			transport.OptionReadIAMConfig(c.IAMConfigPath))
		if err != nil {
			log.Fatal(err)
		}
		client.Transport = rt
	}

	// Get NodeInfo
	nodeInfo, err := nodeutil.NewNodeInfo(client)
	if err != nil {
		return err
	}

	ip, err := nodeInfo.DetectIP()
	if err != nil {
		return err
	}
	c.IPAddress = ip.String()

	id, err := nodeInfo.MesosID(nil)
	if err != nil {
		c.MesosID = ""
	} else {
		c.MesosID = id
	}

	if c.DCOSRole == dcos.RoleMaster {
		cid, err := nodeInfo.ClusterID()
		if err != nil {
			return err
		}
		c.ClusterID = cid
	}
	return nil
}

// newConfig establishes our default, base configuration.
func newConfig() Config {
	return Config{
		Collector: CollectorConfig{
			HTTPProfiler:  true,
			IPCommand:     "/opt/mesosphere/bin/detect_ip",
			PollingPeriod: 15,
			MasterConfig: collector.MasterConfig{
				Port: 5050,
			},
			AgentConfig: collector.AgentConfig{
				Port: 5051,
			},
		},
		Producers: ProducersConfig{
			HTTPProducerConfig: httpProducer.Config{
				Port: 8000,
			},
		},
		ConfigPath: "dcos-metrics-config.yaml",
		LogLevel:   "info",
	}
}

// getNewConfig loads the configuration and sets precedence of configuration values.
// For example: command line flags override values provided in the config file.
func getNewConfig(args []string) (Config, error) {
	c := newConfig()
	thisFlagSet := flag.NewFlagSet("", flag.ExitOnError)
	c.setFlags(thisFlagSet)
	// Override default config with CLI flags if any
	if err := thisFlagSet.Parse(args); err != nil {
		fmt.Println("Errors encountered parsing flags.")
		return c, err
	}

	if err := c.loadConfig(); err != nil {
		return c, err
	}

	// Note: .getNodeInfo() is last so we are sure we have all the
	// configuration we need from flags and config file to make
	// this run correctly.
	if err := c.getNodeInfo(); err != nil {
		return c, err
	}

	return c, nil
}

// producerIsConfigured analyzes the ProducersConfig struct and determines if
// configuration exists for a given producer by name (i.e., is the "http"
// producer configured?). If a configuration exists, this function will return
// true, as a configured producer is an enabled one.
func producerIsConfigured(name string, cfg Config) bool {
	s := reflect.ValueOf(cfg.Producers)
	cfgType := s.Type()
	for i := 0; i < s.NumField(); i++ {
		if strings.Split(cfgType.Field(i).Tag.Get("yaml"), ",")[0] == name {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>package haigo

import (
	"bytes"
	"encoding/json"
	"fmt"
	"text/template"

	"gopkg.in/mgo.v2"
	"gopkg.in/yaml.v2"
)

type param struct {
	Name string
	Type string
}

type Query struct {
	Name        string  `yaml:"name"`
	Description string  `yaml:"description,omitempty"`
	QueryString string  `yaml:"query"`
	params      []param // TODO
}

type Params map[string]interface{}

// Returns configured mgo Query.
func (h *Query) Query(col *mgo.Collection, params Params) (*mgo.Query, error) {

	q, err := h.Map(params)
	if err != nil {
		return nil, err
	}

	return col.Find(q), nil
}

// Accepts a params map and returns a map for use with the mgo `find()`
// function.
func (h *Query) Map(params Params) (map[string]interface{}, error) {

	// Create the template
	t, err := template.New("haigo").Parse(h.QueryString)
	if err != nil {
		return nil, err
	}

	// Buffer to capture string
	buf := new(bytes.Buffer)

	// Execute template
	err = t.Execute(buf, sanitizeParams(params))
	if err != nil {
		return nil, err
	}

	// Unmarshal JSON into Map
	var m map[string]interface{}
	err = json.Unmarshal(buf.Bytes(), &m)
	if err != nil {
		return nil, err
	}

	return m, nil
}

// YAML formatted file with MongoDB Queries.
//
//  ---
//    - name: basic-select
//      description: Basic MongoDB Select
//      query: '{"type": {{.type}} }'
//
//    - name: conditional
//      description: Conditional Query
//      query: '{
//         "type": "food",
//         "$or": [ { "qty": { "$gt": {{.qty}} } }, { "name": {{.name}} } ]
//      }'
type File struct {
	Queries map[string]*Query
}

func (m *File) unmarshalYAML(data []byte) error {

	var hqs []Query

	err := yaml.Unmarshal(data, &hqs)
	if err != nil {
		return err
	}

	qm := make(map[string]*Query)

	for i := range hqs {
		qm[hqs[i].Name] = &hqs[i]
	}

	m.Queries = qm

	return nil
}

// sanitizeParams - Adds single quotes if param is a string (as needed by Mongo).
func sanitizeParams(params Params) Params {
	for k, v := range params {
		switch v.(type) {
		case string:
			params[k] = fmt.Sprintf("\"%s\"", v)
		}

	}
	return params
}

// Reads in Mongo Query File for use with Haigo.
func LoadQueryFile(file string) (*File, error) {
	return parseMongoFile(file)
}
<commit_msg>support mgo Pipe (aggregation)<commit_after>package haigo

import (
	"bytes"
	"encoding/json"
	"fmt"
	"text/template"

	"gopkg.in/mgo.v2"
	"gopkg.in/yaml.v2"
)

type param struct {
	Name string
	Type string
}

type Query struct {
	Name        string  `yaml:"name"`
	Description string  `yaml:"description,omitempty"`
	QueryString string  `yaml:"query"`
	params      []param // TODO
}

type Params map[string]interface{}

// Returns configured mgo Pipe.
func (h *Query) Pipe(col *mgo.Collection, params Params) (*mgo.Pipe, error) {

	q, err := h.Map(params)
	if err != nil {
		return nil, err
	}

	return col.Pipe(q), nil
}

// Returns configured mgo Query.
func (h *Query) Query(col *mgo.Collection, params Params) (*mgo.Query, error) {

	q, err := h.Map(params)
	if err != nil {
		return nil, err
	}

	return col.Find(q), nil
}

// Accepts a params map and returns a map for use with the mgo `find()`
// function.
func (h *Query) Map(params Params) (map[string]interface{}, error) {

	// Create the template
	t, err := template.New("haigo").Parse(h.QueryString)
	if err != nil {
		return nil, err
	}

	// Buffer to capture string
	buf := new(bytes.Buffer)

	// Execute template
	err = t.Execute(buf, sanitizeParams(params))
	if err != nil {
		return nil, err
	}

	// Unmarshal JSON into Map
	var m map[string]interface{}
	err = json.Unmarshal(buf.Bytes(), &m)
	if err != nil {
		return nil, err
	}

	return m, nil
}

// YAML formatted file with MongoDB Queries.
//
//  ---
//    - name: basic-select
//      description: Basic MongoDB Select
//      query: '{"type": {{.type}} }'
//
//    - name: conditional
//      description: Conditional Query
//      query: '{
//         "type": "food",
//         "$or": [ { "qty": { "$gt": {{.qty}} } }, { "name": {{.name}} } ]
//      }'
type File struct {
	Queries map[string]*Query
}

func (m *File) unmarshalYAML(data []byte) error {

	var hqs []Query

	err := yaml.Unmarshal(data, &hqs)
	if err != nil {
		return err
	}

	qm := make(map[string]*Query)

	for i := range hqs {
		qm[hqs[i].Name] = &hqs[i]
	}

	m.Queries = qm

	return nil
}

// sanitizeParams - Adds single quotes if param is a string (as needed by Mongo).
func sanitizeParams(params Params) Params {
	for k, v := range params {
		switch v.(type) {
		case string:
			params[k] = fmt.Sprintf("\"%s\"", v)
		}

	}
	return params
}

// Reads in Mongo Query File for use with Haigo.
func LoadQueryFile(file string) (*File, error) {
	return parseMongoFile(file)
}
<|endoftext|>


<commit_before><commit_msg>Remove unnecessary else block in AddBeer func<commit_after><|endoftext|>


<commit_before>package hello

import (
    "fmt"
    "net/http"
    "html/template"
)

func init() {
    http.HandleFunc("/", handler)
    http.HandleFunc("/html-template", handlerHtmlTemplate)
}

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "Hello, world!")
}

type Model struct {
	Titolo1, Titolo2 string
}
func handlerHtmlTemplate(w http.ResponseWriter, r *http.Request) {
    tmpl, err := template.ParseFiles("templates/basic.html")

    err = tmpl.Execute(w, Model{"Titolo 1", "Titolo 2"})

    if err != nil {
      http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

<commit_msg>demo su template base html con commenti<commit_after>package hello

import (
    "fmt"
    "net/http"
    "html/template"
    "math/rand"
	  "strconv"
)

func init() {
    http.HandleFunc("/", handler)
    http.HandleFunc("/html-template", handlerHtmlTemplate)
}

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "Hello, world!")
}

type BasicModel struct {
	Titolo1, Titolo2 string
}
func handlerHtmlTemplate(w http.ResponseWriter, r *http.Request) {

    // recupero il template
    tmpl, err := template.ParseFiles("templates/basic.html")
    if err != nil {
      // se avvengono errori nel recupero del template mi fermo
      http.Error(w, err.Error(), http.StatusInternalServerError)
      return
    }

    // creo la struttura dati composta da un titolo fisso ed un valore casuale
    valoreCasuale := rand.Intn(3000);
    data := BasicModel{"Sotto un valore casuale da 0 a 3000", strconv.Itoa(valoreCasuale)}

    // unisco struttura dati e template html
    err = tmpl.Execute(w, data)
    if err != nil {
      // se avvengono errori nella creazione della pagina dinamica mi fermo
      http.Error(w, err.Error(), http.StatusInternalServerError)
      return
    }
}<|endoftext|>


<commit_before>package ot

type OpType int

const (
	OpRetain OpType = iota
	OpInsert
	OpDelete
)

type Op interface {
	Type() OpType
	Span() int
}

type RetainOp int

func (p RetainOp) Type() OpType {
	return OpRetain
}

func (p RetainOp) Span() int {
	return int(p)
}

func (p RetainOp) ComposeRetain(q RetainOp) (Op, Op, Op) {
	switch {
	case p > q:
		return q, p - q, Noop

	default:
		return p, Noop, q - p
	}
}

func (p RetainOp) ComposeDelete(q DeleteOp) (Op, Op, Op) {
	switch {
	case int(p) < int(q):
		return DeleteOp(p), Noop, q - DeleteOp(p)

	default:
		return q, p - RetainOp(q), Noop
	}
}

func (p RetainOp) TransformRetain(q RetainOp) (Op, Op, Op, Op) {
	switch {
	case p > q:
		return q, q, p - q, Noop

	default:
		return p, p, Noop, q - p
	}
}

func (p RetainOp) TransformDelete(q DeleteOp) (Op, Op, Op, Op) {
	switch {
	case int(p) > int(q):
		return Noop, q, p - RetainOp(q), Noop

	default:
		return Noop, p, Noop, RetainOp(q) - p
	}
}

var Noop = RetainOp(0)

type InsertOp string

func (p InsertOp) Type() OpType {
	return OpInsert
}

func (p InsertOp) Span() int {
	return len(p)
}

func (p InsertOp) ComposeRetain(q RetainOp) (Op, Op, Op) {
	switch {
	case len(p) > int(q):
		return p[:int(q)], p[int(q):], Noop

	default:
		return p, Noop, q - RetainOp(len(p))
	}
}

func (p InsertOp) ComposeDelete(q DeleteOp) (Op, Op, Op) {
	switch {
	case len(p) > int(q):
		return Noop, p[int(q):], Noop

	case len(p) < int(q):
		return Noop, Noop, q - DeleteOp(len(p))

	default:
		return Noop, Noop, Noop
	}
}

type DeleteOp int

func (p DeleteOp) Type() OpType {
	return OpDelete
}

func (p DeleteOp) Span() int {
	return int(p)
}

func (p DeleteOp) TransformRetain(q RetainOp) (Op, Op, Op, Op) {
	switch {
	case int(p) > int(q):
		return q, Noop, p - DeleteOp(q), Noop

	default:
		return DeleteOp(p), Noop, Noop, q - RetainOp(p)
	}
}

func (p DeleteOp) TransformDelete(q DeleteOp) (Op, Op, Op, Op) {
	switch {
	case p > q:
		return Noop, Noop, p - q, Noop

	default:
		return Noop, Noop, Noop, q - p
	}
}

type RetainComposer interface {
	ComposeRetain(q RetainOp) (Op, Op, Op)
}

type DeleteComposer interface {
	ComposeDelete(q DeleteOp) (Op, Op, Op)
}

type RetainTransformer interface {
	TransformRetain(q RetainOp) (Op, Op, Op, Op)
}

type DeleteTransformer interface {
	TransformDelete(q DeleteOp) (Op, Op, Op, Op)
}
<commit_msg>Fix delete-retain transform bug<commit_after>package ot

type OpType int

const (
	OpRetain OpType = iota
	OpInsert
	OpDelete
)

type Op interface {
	Type() OpType
	Span() int
}

type RetainOp int

func (p RetainOp) Type() OpType {
	return OpRetain
}

func (p RetainOp) Span() int {
	return int(p)
}

func (p RetainOp) ComposeRetain(q RetainOp) (Op, Op, Op) {
	switch {
	case p > q:
		return q, p - q, Noop

	default:
		return p, Noop, q - p
	}
}

func (p RetainOp) ComposeDelete(q DeleteOp) (Op, Op, Op) {
	switch {
	case int(p) < int(q):
		return DeleteOp(p), Noop, q - DeleteOp(p)

	default:
		return q, p - RetainOp(q), Noop
	}
}

func (p RetainOp) TransformRetain(q RetainOp) (Op, Op, Op, Op) {
	switch {
	case p > q:
		return q, q, p - q, Noop

	default:
		return p, p, Noop, q - p
	}
}

func (p RetainOp) TransformDelete(q DeleteOp) (Op, Op, Op, Op) {
	switch {
	case int(p) > int(q):
		return Noop, q, p - RetainOp(q), Noop

	default:
		return Noop, p, Noop, RetainOp(q) - p
	}
}

var Noop = RetainOp(0)

type InsertOp string

func (p InsertOp) Type() OpType {
	return OpInsert
}

func (p InsertOp) Span() int {
	return len(p)
}

func (p InsertOp) ComposeRetain(q RetainOp) (Op, Op, Op) {
	switch {
	case len(p) > int(q):
		return p[:int(q)], p[int(q):], Noop

	default:
		return p, Noop, q - RetainOp(len(p))
	}
}

func (p InsertOp) ComposeDelete(q DeleteOp) (Op, Op, Op) {
	switch {
	case len(p) > int(q):
		return Noop, p[int(q):], Noop

	case len(p) < int(q):
		return Noop, Noop, q - DeleteOp(len(p))

	default:
		return Noop, Noop, Noop
	}
}

type DeleteOp int

func (p DeleteOp) Type() OpType {
	return OpDelete
}

func (p DeleteOp) Span() int {
	return int(p)
}

func (p DeleteOp) TransformRetain(q RetainOp) (Op, Op, Op, Op) {
	switch {
	case int(p) > int(q):
		return DeleteOp(q), Noop, p - DeleteOp(q), Noop

	default:
		return p, Noop, Noop, q - RetainOp(p)
	}
}

func (p DeleteOp) TransformDelete(q DeleteOp) (Op, Op, Op, Op) {
	switch {
	case p > q:
		return Noop, Noop, p - q, Noop

	default:
		return Noop, Noop, Noop, q - p
	}
}

type RetainComposer interface {
	ComposeRetain(q RetainOp) (Op, Op, Op)
}

type DeleteComposer interface {
	ComposeDelete(q DeleteOp) (Op, Op, Op)
}

type RetainTransformer interface {
	TransformRetain(q RetainOp) (Op, Op, Op, Op)
}

type DeleteTransformer interface {
	TransformDelete(q DeleteOp) (Op, Op, Op, Op)
}
<|endoftext|>


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

// +build ignore

package tcp

// +godefs map struct_in_addr [4]byte /* in_addr */
// +godefs map struct_in6_addr [16]byte /* in6_addr */
// +godefs map struct_pf_addr [16]byte /* pf_addr */

/*
#include <sys/ioctl.h>
#include <sys/socket.h>

#include <net/if.h>
#include <net/pfvar.h>

#include <netinet/tcp.h>

#include <netpfil/pf/pf.h>
*/
import "C"

const (
	sysFIONREAD  = C.FIONREAD
	sysFIONWRITE = C.FIONWRITE
	sysFIONSPACE = C.FIONSPACE

	sysAF_INET  = C.AF_INET
	sysAF_INET6 = C.AF_INET6

	sysPF_INOUT = C.PF_INOUT
	sysPF_IN    = C.PF_IN
	sysPF_OUT   = C.PF_OUT
	sysPF_FWD   = C.PF_FWD

	sysDIOCNATLOOK = C.DIOCNATLOOK
)

type sockaddrStorage C.struct_sockaddr_storage

type sockaddr C.struct_sockaddr

type sockaddrInet C.struct_sockaddr_in

type sockaddrInet6 C.struct_sockaddr_in6

type pfiocNatlook C.struct_pfioc_natlook

const (
	sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
	sizeofSockaddr        = C.sizeof_struct_sockaddr
	sizeofSockaddrInet    = C.sizeof_struct_sockaddr_in
	sizeofSockaddrInet6   = C.sizeof_struct_sockaddr_in6
	sizeofPfiocNatlook    = C.sizeof_struct_pfioc_natlook
)
<commit_msg>tcp: tweak bootstrap file for FreeBSD<commit_after>// Copyright 2014 Mikio Hara. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build ignore

package tcp

// +godefs map struct_in_addr [4]byte /* in_addr */
// +godefs map struct_in6_addr [16]byte /* in6_addr */
// +godefs map struct_pf_addr [16]byte /* pf_addr */

/*
#include <sys/ioctl.h>
#include <sys/socket.h>

#include <net/if.h>
#include <net/pfvar.h>

#include <netinet/in.h>

#include <netpfil/pf/pf.h>
*/
import "C"

const (
	sysFIONREAD  = C.FIONREAD
	sysFIONWRITE = C.FIONWRITE
	sysFIONSPACE = C.FIONSPACE

	sysAF_INET  = C.AF_INET
	sysAF_INET6 = C.AF_INET6

	sysPF_INOUT = C.PF_INOUT
	sysPF_IN    = C.PF_IN
	sysPF_OUT   = C.PF_OUT
	sysPF_FWD   = C.PF_FWD

	sysDIOCNATLOOK = C.DIOCNATLOOK
)

type sockaddrStorage C.struct_sockaddr_storage

type sockaddr C.struct_sockaddr

type sockaddrInet C.struct_sockaddr_in

type sockaddrInet6 C.struct_sockaddr_in6

type pfiocNatlook C.struct_pfioc_natlook

const (
	sizeofSockaddrStorage = C.sizeof_struct_sockaddr_storage
	sizeofSockaddr        = C.sizeof_struct_sockaddr
	sizeofSockaddrInet    = C.sizeof_struct_sockaddr_in
	sizeofSockaddrInet6   = C.sizeof_struct_sockaddr_in6
	sizeofPfiocNatlook    = C.sizeof_struct_pfioc_natlook
)
<|endoftext|>


<commit_before>package id3v2

import (
	"errors"
	"io"
	"os"

	"github.com/bogem/id3v2/util"
)

const frameHeaderSize = 10

type frameHeader struct {
	ID        string
	FrameSize int64
}

func parseTag(file *os.File) (*Tag, error) {
	if file == nil {
		err := errors.New("Invalid file: file is nil")
		return nil, err
	}
	header, err := parseHeader(file)
	if err != nil {
		err = errors.New("Trying to parse tag header: " + err.Error())
		return nil, err
	}
	if header == nil {
		return newTag(file, 0), nil
	}
	if header.Version < 3 {
		err = errors.New("Unsupported version of ID3 tag")
		return nil, err
	}

	t := newTag(file, tagHeaderSize+header.FramesSize)
	err = t.findAllFrames()

	return t, err
}

func newTag(file *os.File, originalSize int64) *Tag {
	return &Tag{
		framesCoords: make(map[string][]frameCoordinates),
		frames:       make(map[string]Framer),
		sequences:    make(map[string]sequencer),
		ids:          V24IDs,

		file:         file,
		originalSize: originalSize,
	}
}

func (t *Tag) findAllFrames() error {
	pos := int64(tagHeaderSize) // initial position of read - beginning of first frame
	tagSize := t.originalSize
	f := t.file

	for pos < tagSize {
		if _, err := f.Seek(pos, os.SEEK_SET); err != nil {
			return err
		}

		header, err := parseFrameHeader(f)
		if err != nil {
			return err
		}
		pos += frameHeaderSize

		fc := frameCoordinates{
			Len: header.FrameSize,
			Pos: pos,
		}
		fcs := t.framesCoords[header.ID]
		fcs = append(fcs, fc)
		t.framesCoords[header.ID] = fcs

		pos += header.FrameSize
	}

	return nil
}

func parseFrameHeader(rd io.Reader) (*frameHeader, error) {
	byteHeader := make([]byte, frameHeaderSize)
	n, err := rd.Read(byteHeader)
	if err != nil {
		return nil, err
	}
	if n < frameHeaderSize {
		err = errors.New("Size of frame header is less than expected")
	}

	header := &frameHeader{
		ID:        string(byteHeader[:4]),
		FrameSize: util.ParseSize(byteHeader[4:8]),
	}

	return header, nil

}

func (t *Tag) parseAllFramesCoords() {
	for id := range t.framesCoords {
		t.parseFramesCoordsWithID(id)
	}
}

func (t *Tag) parseFramesCoordsWithID(id string) {
	fcs, exists := t.framesCoords[id]
	if !exists {
		return
	}

	parseFunc := t.findParseFunc(id)
	if parseFunc != nil {
		for _, fc := range fcs {
			fr := readFrame(parseFunc, t.file, fc)
			t.AddFrame(id, fr)
		}
	}
	// Delete frames with id from t.framesCoords,
	// because they are just being parsed
	delete(t.framesCoords, id)
}

func (t Tag) findParseFunc(id string) func(io.Reader) (Framer, error) {
	if id[0] == 'T' {
		return ParseTextFrame
	}

	switch id {
	case t.ids["Attached picture"]:
		return ParsePictureFrame
	case t.ids["Comments"]:
		return ParseCommentFrame
	case t.ids["Unsynchronised lyrics/text transcription"]:
		return ParseUnsynchronisedLyricsFrame
	}
	return nil
}

func readFrame(parseFunc func(io.Reader) (Framer, error), rs io.ReadSeeker, fc frameCoordinates) Framer {
	rs.Seek(fc.Pos, os.SEEK_SET)
	rd := &io.LimitedReader{R: rs, N: fc.Len}
	fr, err := parseFunc(rd)
	if err != nil {
		panic(err)
	}
	return fr
}
<commit_msg>Fix memory compsution if parseFrameHeader func<commit_after>package id3v2

import (
	"errors"
	"io"
	"os"

	"github.com/bogem/id3v2/bytesbufferpool"
	"github.com/bogem/id3v2/util"
)

const frameHeaderSize = 10

type frameHeader struct {
	ID        string
	FrameSize int64
}

func parseTag(file *os.File) (*Tag, error) {
	if file == nil {
		err := errors.New("Invalid file: file is nil")
		return nil, err
	}
	header, err := parseHeader(file)
	if err != nil {
		err = errors.New("Trying to parse tag header: " + err.Error())
		return nil, err
	}
	if header == nil {
		return newTag(file, 0), nil
	}
	if header.Version < 3 {
		err = errors.New("Unsupported version of ID3 tag")
		return nil, err
	}

	t := newTag(file, tagHeaderSize+header.FramesSize)
	err = t.findAllFrames()

	return t, err
}

func newTag(file *os.File, originalSize int64) *Tag {
	return &Tag{
		framesCoords: make(map[string][]frameCoordinates),
		frames:       make(map[string]Framer),
		sequences:    make(map[string]sequencer),
		ids:          V24IDs,

		file:         file,
		originalSize: originalSize,
	}
}

func (t *Tag) findAllFrames() error {
	pos := int64(tagHeaderSize) // initial position of read - beginning of first frame
	tagSize := t.originalSize
	f := t.file

	for pos < tagSize {
		if _, err := f.Seek(pos, os.SEEK_SET); err != nil {
			return err
		}

		header, err := parseFrameHeader(f)
		if err != nil {
			return err
		}
		pos += frameHeaderSize

		fc := frameCoordinates{
			Len: header.FrameSize,
			Pos: pos,
		}
		fcs := t.framesCoords[header.ID]
		fcs = append(fcs, fc)
		t.framesCoords[header.ID] = fcs

		pos += header.FrameSize
	}

	return nil
}

func parseFrameHeader(rd io.Reader) (*frameHeader, error) {
	fhBuf := bytesbufferpool.Get()
	defer bytesbufferpool.Put(fhBuf)

	limitedRd := &io.LimitedReader{R: rd, N: frameHeaderSize}

	n, err := fhBuf.ReadFrom(limitedRd)
	if err != nil {
		return nil, err
	}
	if n < frameHeaderSize {
		err = errors.New("Size of frame header is less than expected")
	}

	byteHeader := fhBuf.Bytes()

	header := &frameHeader{
		ID:        string(byteHeader[:4]),
		FrameSize: util.ParseSize(byteHeader[4:8]),
	}

	return header, nil

}

func (t *Tag) parseAllFramesCoords() {
	for id := range t.framesCoords {
		t.parseFramesCoordsWithID(id)
	}
}

func (t *Tag) parseFramesCoordsWithID(id string) {
	fcs, exists := t.framesCoords[id]
	if !exists {
		return
	}

	parseFunc := t.findParseFunc(id)
	if parseFunc != nil {
		for _, fc := range fcs {
			fr := readFrame(parseFunc, t.file, fc)
			t.AddFrame(id, fr)
		}
	}
	// Delete frames with id from t.framesCoords,
	// because they are just being parsed
	delete(t.framesCoords, id)
}

func (t Tag) findParseFunc(id string) func(io.Reader) (Framer, error) {
	if id[0] == 'T' {
		return ParseTextFrame
	}

	switch id {
	case t.ids["Attached picture"]:
		return ParsePictureFrame
	case t.ids["Comments"]:
		return ParseCommentFrame
	case t.ids["Unsynchronised lyrics/text transcription"]:
		return ParseUnsynchronisedLyricsFrame
	}
	return nil
}

func readFrame(parseFunc func(io.Reader) (Framer, error), rs io.ReadSeeker, fc frameCoordinates) Framer {
	rs.Seek(fc.Pos, os.SEEK_SET)
	rd := &io.LimitedReader{R: rs, N: fc.Len}
	fr, err := parseFunc(rd)
	if err != nil {
		panic(err)
	}
	return fr
}
<|endoftext|>


<commit_before>package scipipe

import (
	"errors"
	"fmt"
	"os"
	"os/exec"
	str "strings"
)

// ================== SciTask ==================

type SciTask struct {
	Name          string
	Command       string
	CustomExecute func(*SciTask)
	InTargets     map[string]*FileTarget
	OutTargets    map[string]*FileTarget
	Params        map[string]string
	Done          chan int
}

func NewSciTask(name string, cmdPat string, inTargets map[string]*FileTarget, outPathFuncs map[string]func(*SciTask) string, outPortsDoStream map[string]bool, params map[string]string, prepend string) *SciTask {
	t := &SciTask{
		Name:       name,
		InTargets:  inTargets,
		OutTargets: make(map[string]*FileTarget),
		Params:     params,
		Command:    "",
		Done:       make(chan int),
	}
	// Create out targets
	Debug.Printf("Task:%s: Creating outTargets now ... [%s]", name, cmdPat)
	outTargets := make(map[string]*FileTarget)
	for oname, ofun := range outPathFuncs {
		opath := ofun(t)
		otgt := NewFileTarget(opath)
		if outPortsDoStream[oname] {
			otgt.doStream = true
		}
		Debug.Printf("Task:%s: Creating outTarget with path %s ... [%s]", name, cmdPat)
		outTargets[oname] = otgt
	}
	t.OutTargets = outTargets
	t.Command = formatCommand(cmdPat, inTargets, outTargets, params, prepend)
	Debug.Printf("Task:%s: Created formatted command: %s [%s]", name, t.Command, cmdPat)
	return t
}

// --------------- SciTask API methods ----------------

func (t *SciTask) GetInPath(inPort string) string {
	return t.InTargets[inPort].GetPath()
}

func (t *SciTask) Execute() {
	defer close(t.Done)
	if !t.anyOutputExists() && !t.fifosInOutTargetsMissing() {
		Debug.Printf("Task:%-12s Executing task. [%s]\n", t.Name, t.Command)
		if t.CustomExecute != nil {
			t.CustomExecute(t)
		} else {
			t.executeCommand(t.Command)
		}
		Debug.Printf("Task:%-12s Atomizing targets. [%s]\n", t.Name, t.Command)
		t.atomizeTargets()
	}
	Debug.Printf("Task:%s: Starting to send Done in t.Execute() ...) [%s]\n", t.Name, t.Command)
	t.Done <- 1
	Debug.Printf("Task:%s: Done sending Done, in t.Execute() [%s]\n", t.Name, t.Command)
}

// --------------- SciTask Helper methods ----------------

// Check if any output file target, or temporary file targets, exist
func (t *SciTask) anyOutputExists() (anyFileExists bool) {
	anyFileExists = false
	for _, tgt := range t.OutTargets {
		opath := tgt.GetPath()
		otmpPath := tgt.GetTempPath()
		if !tgt.doStream {
			if _, err := os.Stat(opath); err == nil {
				Audit.Printf("Task:%-12s Output file already exists: %s, so skipping... [%s]\n", t.Name, opath, t.Command)
				anyFileExists = true
			}
			if _, err := os.Stat(otmpPath); err == nil {
				Warning.Printf("Task:%-12s Temporary Output file already exists: %s. Check your workflow for correctness! [%s]\n", t.Name, otmpPath, t.Command)
				anyFileExists = true
			}
		}
	}
	return
}

// Check if any FIFO files for this tasks exist, for out-ports specified to support streaming
func (t *SciTask) anyFifosExist() (anyFifosExist bool) {
	anyFifosExist = false
	for _, tgt := range t.OutTargets {
		ofifoPath := tgt.GetFifoPath()
		if tgt.doStream {
			if _, err := os.Stat(ofifoPath); err == nil {
				Warning.Printf("Task:%-12s Output FIFO already exists: %s. Check your workflow for correctness! [%s]\n", t.Name, ofifoPath, t.Command)
				anyFifosExist = true
			}
		}
	}
	return
}

// Make sure that FIFOs that are supposed to exist, really exists
func (t *SciTask) fifosInOutTargetsMissing() (fifosInOutTargetsMissing bool) {
	fifosInOutTargetsMissing = false
	for _, tgt := range t.OutTargets {
		if tgt.doStream {
			ofifoPath := tgt.GetFifoPath()
			if _, err := os.Stat(ofifoPath); err != nil {
				Warning.Printf("Task:%-12s FIFO Output file missing, for streaming output: %s. Check your workflow for correctness! [%s]\n", t.Name, t.Command, ofifoPath)
				fifosInOutTargetsMissing = true
			}
		}
	}
	return
}

func (t *SciTask) executeCommand(cmd string) {
	Audit.Printf("Task:%-12s Executing command: %s\n", t.Name, cmd)
	_, err := exec.Command("bash", "-c", cmd).Output()
	Check(err)
}

// Create FIFO files for all out-ports that are specified to support streaming
func (t *SciTask) createFifos() {
	Debug.Printf("Task:%s: Now creating fifos for task [%s]\n", t.Name, t.Command)
	for _, otgt := range t.OutTargets {
		if otgt.doStream {
			otgt.CreateFifo()
		}
	}
}

// Rename temporary output files to their proper file names
func (t *SciTask) atomizeTargets() {
	for _, tgt := range t.OutTargets {
		if !tgt.doStream {
			Debug.Printf("Atomizing file: %s -> %s", tgt.GetTempPath(), tgt.GetPath())
			tgt.Atomize()
			Debug.Printf("Done atomizing file: %s -> %s", tgt.GetTempPath(), tgt.GetPath())
		} else {
			Debug.Printf("Target is streaming, so not atomizing: %s", tgt.GetPath())
		}
	}
}

// Clean up any remaining FIFOs
// TODO: this is actually not really used anymore ...
func (t *SciTask) cleanUpFifos() {
	for _, tgt := range t.OutTargets {
		if tgt.doStream {
			Debug.Printf("Task:%s: Cleaning up FIFO for output target: %s [%s]\n", t.Name, tgt.GetFifoPath(), t.Command)
			tgt.RemoveFifo()
		} else {
			Debug.Printf("Task:%s: output target is not FIFO, so not removing any FIFO: %s [%s]\n", t.Name, tgt.GetPath(), t.Command)
		}
	}
}

// ================== Helper functions==================

func formatCommand(cmd string, inTargets map[string]*FileTarget, outTargets map[string]*FileTarget, params map[string]string, prepend string) string {

	// Debug.Println("Formatting command with the following data:")
	// Debug.Println("prepend:", prepend)
	// Debug.Println("cmd:", cmd)
	// Debug.Println("inTargets:", inTargets)
	// Debug.Println("outTargets:", outTargets)
	// Debug.Println("params:", params)

	r := getShellCommandPlaceHolderRegex()
	ms := r.FindAllStringSubmatch(cmd, -1)
	for _, m := range ms {
		placeHolderStr := m[0]
		typ := m[1]
		name := m[2]
		var filePath string
		if typ == "o" || typ == "os" {
			// Out-ports
			if outTargets[name] == nil {
				msg := fmt.Sprint("Missing outpath for outport '", name, "' for command '", cmd, "'")
				Check(errors.New(msg))
			} else {
				if typ == "o" {
					filePath = outTargets[name].GetTempPath() // Means important to Atomize afterwards!
				} else if typ == "os" {
					filePath = outTargets[name].GetFifoPath()
				}
			}
		} else if typ == "i" {
			// In-ports
			if inTargets[name] == nil {
				msg := fmt.Sprint("Missing intarget for inport '", name, "' for command '", cmd, "'")
				Check(errors.New(msg))
			} else if inTargets[name].GetPath() == "" {
				msg := fmt.Sprint("Missing inpath for inport '", name, "' for command '", cmd, "'")
				Check(errors.New(msg))
			} else {
				if inTargets[name].doStream {
					filePath = inTargets[name].GetFifoPath()
				} else {
					filePath = inTargets[name].GetPath()
				}
			}
		} else if typ == "p" {
			if params[name] == "" {
				msg := fmt.Sprint("Missing param value param '", name, "' for command '", cmd, "'")
				Check(errors.New(msg))
			} else {
				filePath = params[name]
			}
		}
		if filePath == "" {
			msg := fmt.Sprint("Replace failed for port ", name, " for command '", cmd, "'")
			Check(errors.New(msg))
		}
		cmd = str.Replace(cmd, placeHolderStr, filePath, -1)
	}
	// Add prepend string to the command
	if prepend != "" {
		cmd = fmt.Sprintf("%s %s", prepend, cmd)
	}
	return cmd
}
<commit_msg>Give sensible output when commands fail<commit_after>package scipipe

import (
	"errors"
	"fmt"
	"os"
	"os/exec"
	str "strings"
)

// ================== SciTask ==================

type SciTask struct {
	Name          string
	Command       string
	CustomExecute func(*SciTask)
	InTargets     map[string]*FileTarget
	OutTargets    map[string]*FileTarget
	Params        map[string]string
	Done          chan int
}

func NewSciTask(name string, cmdPat string, inTargets map[string]*FileTarget, outPathFuncs map[string]func(*SciTask) string, outPortsDoStream map[string]bool, params map[string]string, prepend string) *SciTask {
	t := &SciTask{
		Name:       name,
		InTargets:  inTargets,
		OutTargets: make(map[string]*FileTarget),
		Params:     params,
		Command:    "",
		Done:       make(chan int),
	}
	// Create out targets
	Debug.Printf("Task:%s: Creating outTargets now ... [%s]", name, cmdPat)
	outTargets := make(map[string]*FileTarget)
	for oname, ofun := range outPathFuncs {
		opath := ofun(t)
		otgt := NewFileTarget(opath)
		if outPortsDoStream[oname] {
			otgt.doStream = true
		}
		Debug.Printf("Task:%s: Creating outTarget with path %s ... [%s]", name, cmdPat)
		outTargets[oname] = otgt
	}
	t.OutTargets = outTargets
	t.Command = formatCommand(cmdPat, inTargets, outTargets, params, prepend)
	Debug.Printf("Task:%s: Created formatted command: %s [%s]", name, t.Command, cmdPat)
	return t
}

// --------------- SciTask API methods ----------------

func (t *SciTask) GetInPath(inPort string) string {
	return t.InTargets[inPort].GetPath()
}

func (t *SciTask) Execute() {
	defer close(t.Done)
	if !t.anyOutputExists() && !t.fifosInOutTargetsMissing() {
		Debug.Printf("Task:%-12s Executing task. [%s]\n", t.Name, t.Command)
		if t.CustomExecute != nil {
			t.CustomExecute(t)
		} else {
			t.executeCommand(t.Command)
		}
		Debug.Printf("Task:%-12s Atomizing targets. [%s]\n", t.Name, t.Command)
		t.atomizeTargets()
	}
	Debug.Printf("Task:%s: Starting to send Done in t.Execute() ...) [%s]\n", t.Name, t.Command)
	t.Done <- 1
	Debug.Printf("Task:%s: Done sending Done, in t.Execute() [%s]\n", t.Name, t.Command)
}

// --------------- SciTask Helper methods ----------------

// Check if any output file target, or temporary file targets, exist
func (t *SciTask) anyOutputExists() (anyFileExists bool) {
	anyFileExists = false
	for _, tgt := range t.OutTargets {
		opath := tgt.GetPath()
		otmpPath := tgt.GetTempPath()
		if !tgt.doStream {
			if _, err := os.Stat(opath); err == nil {
				Audit.Printf("Task:%-12s Output file already exists: %s, so skipping... [%s]\n", t.Name, opath, t.Command)
				anyFileExists = true
			}
			if _, err := os.Stat(otmpPath); err == nil {
				Warning.Printf("Task:%-12s Temporary Output file already exists: %s. Check your workflow for correctness! [%s]\n", t.Name, otmpPath, t.Command)
				anyFileExists = true
			}
		}
	}
	return
}

// Check if any FIFO files for this tasks exist, for out-ports specified to support streaming
func (t *SciTask) anyFifosExist() (anyFifosExist bool) {
	anyFifosExist = false
	for _, tgt := range t.OutTargets {
		ofifoPath := tgt.GetFifoPath()
		if tgt.doStream {
			if _, err := os.Stat(ofifoPath); err == nil {
				Warning.Printf("Task:%-12s Output FIFO already exists: %s. Check your workflow for correctness! [%s]\n", t.Name, ofifoPath, t.Command)
				anyFifosExist = true
			}
		}
	}
	return
}

// Make sure that FIFOs that are supposed to exist, really exists
func (t *SciTask) fifosInOutTargetsMissing() (fifosInOutTargetsMissing bool) {
	fifosInOutTargetsMissing = false
	for _, tgt := range t.OutTargets {
		if tgt.doStream {
			ofifoPath := tgt.GetFifoPath()
			if _, err := os.Stat(ofifoPath); err != nil {
				Warning.Printf("Task:%-12s FIFO Output file missing, for streaming output: %s. Check your workflow for correctness! [%s]\n", t.Name, t.Command, ofifoPath)
				fifosInOutTargetsMissing = true
			}
		}
	}
	return
}

func (t *SciTask) executeCommand(cmd string) {
	Audit.Printf("Task:%-12s Executing command: %s\n", t.Name, cmd)
	out, err := exec.Command("bash", "-c", cmd).CombinedOutput()
	if err != nil {
		Error.Println("Command failed, with output:\n", string(out))
		os.Exit(126)
	}
}

// Create FIFO files for all out-ports that are specified to support streaming
func (t *SciTask) createFifos() {
	Debug.Printf("Task:%s: Now creating fifos for task [%s]\n", t.Name, t.Command)
	for _, otgt := range t.OutTargets {
		if otgt.doStream {
			otgt.CreateFifo()
		}
	}
}

// Rename temporary output files to their proper file names
func (t *SciTask) atomizeTargets() {
	for _, tgt := range t.OutTargets {
		if !tgt.doStream {
			Debug.Printf("Atomizing file: %s -> %s", tgt.GetTempPath(), tgt.GetPath())
			tgt.Atomize()
			Debug.Printf("Done atomizing file: %s -> %s", tgt.GetTempPath(), tgt.GetPath())
		} else {
			Debug.Printf("Target is streaming, so not atomizing: %s", tgt.GetPath())
		}
	}
}

// Clean up any remaining FIFOs
// TODO: this is actually not really used anymore ...
func (t *SciTask) cleanUpFifos() {
	for _, tgt := range t.OutTargets {
		if tgt.doStream {
			Debug.Printf("Task:%s: Cleaning up FIFO for output target: %s [%s]\n", t.Name, tgt.GetFifoPath(), t.Command)
			tgt.RemoveFifo()
		} else {
			Debug.Printf("Task:%s: output target is not FIFO, so not removing any FIFO: %s [%s]\n", t.Name, tgt.GetPath(), t.Command)
		}
	}
}

// ================== Helper functions==================

func formatCommand(cmd string, inTargets map[string]*FileTarget, outTargets map[string]*FileTarget, params map[string]string, prepend string) string {

	// Debug.Println("Formatting command with the following data:")
	// Debug.Println("prepend:", prepend)
	// Debug.Println("cmd:", cmd)
	// Debug.Println("inTargets:", inTargets)
	// Debug.Println("outTargets:", outTargets)
	// Debug.Println("params:", params)

	r := getShellCommandPlaceHolderRegex()
	ms := r.FindAllStringSubmatch(cmd, -1)
	for _, m := range ms {
		placeHolderStr := m[0]
		typ := m[1]
		name := m[2]
		var filePath string
		if typ == "o" || typ == "os" {
			// Out-ports
			if outTargets[name] == nil {
				msg := fmt.Sprint("Missing outpath for outport '", name, "' for command '", cmd, "'")
				Check(errors.New(msg))
			} else {
				if typ == "o" {
					filePath = outTargets[name].GetTempPath() // Means important to Atomize afterwards!
				} else if typ == "os" {
					filePath = outTargets[name].GetFifoPath()
				}
			}
		} else if typ == "i" {
			// In-ports
			if inTargets[name] == nil {
				msg := fmt.Sprint("Missing intarget for inport '", name, "' for command '", cmd, "'")
				Check(errors.New(msg))
			} else if inTargets[name].GetPath() == "" {
				msg := fmt.Sprint("Missing inpath for inport '", name, "' for command '", cmd, "'")
				Check(errors.New(msg))
			} else {
				if inTargets[name].doStream {
					filePath = inTargets[name].GetFifoPath()
				} else {
					filePath = inTargets[name].GetPath()
				}
			}
		} else if typ == "p" {
			if params[name] == "" {
				msg := fmt.Sprint("Missing param value param '", name, "' for command '", cmd, "'")
				Check(errors.New(msg))
			} else {
				filePath = params[name]
			}
		}
		if filePath == "" {
			msg := fmt.Sprint("Replace failed for port ", name, " for command '", cmd, "'")
			Check(errors.New(msg))
		}
		cmd = str.Replace(cmd, placeHolderStr, filePath, -1)
	}
	// Add prepend string to the command
	if prepend != "" {
		cmd = fmt.Sprintf("%s %s", prepend, cmd)
	}
	return cmd
}
<|endoftext|>


<commit_before>/*
 *    Copyright (C) 2014-2017 Christian Muehlhaeuser
 *
 *    This program is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU Affero General Public License as published
 *    by the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *    Authors:
 *      Christian Muehlhaeuser <muesli@gmail.com>
 */

package main

import (
	_ "github.com/muesli/beehive/bees/alertoverbee"
	_ "github.com/muesli/beehive/bees/anelpowerctrlbee"
	_ "github.com/muesli/beehive/bees/cricketbee"
	_ "github.com/muesli/beehive/bees/cronbee"
	_ "github.com/muesli/beehive/bees/devrantbee"
	_ "github.com/muesli/beehive/bees/efabee"
	_ "github.com/muesli/beehive/bees/emailbee"
	_ "github.com/muesli/beehive/bees/execbee"
	_ "github.com/muesli/beehive/bees/facebookbee"
	_ "github.com/muesli/beehive/bees/fsnotifybee"
	_ "github.com/muesli/beehive/bees/githubbee"
	_ "github.com/muesli/beehive/bees/gitterbee"
	_ "github.com/muesli/beehive/bees/htmlextractbee"
	_ "github.com/muesli/beehive/bees/httpbee"
	_ "github.com/muesli/beehive/bees/huebee"
	_ "github.com/muesli/beehive/bees/ircbee"
	_ "github.com/muesli/beehive/bees/jabberbee"
	_ "github.com/muesli/beehive/bees/jenkinsbee"
	_ "github.com/muesli/beehive/bees/mumblebee"
	_ "github.com/muesli/beehive/bees/nagiosbee"
	_ "github.com/muesli/beehive/bees/pastebinbee"
	_ "github.com/muesli/beehive/bees/pushoverbee"
	_ "github.com/muesli/beehive/bees/rssbee"
	_ "github.com/muesli/beehive/bees/s3bee"
	_ "github.com/muesli/beehive/bees/serialbee"
	_ "github.com/muesli/beehive/bees/simplepushbee"
	_ "github.com/muesli/beehive/bees/slackbee"
	_ "github.com/muesli/beehive/bees/spaceapibee"
	_ "github.com/muesli/beehive/bees/telegrambee"
	_ "github.com/muesli/beehive/bees/timebee"
	_ "github.com/muesli/beehive/bees/transmissionbee"
	_ "github.com/muesli/beehive/bees/tumblrbee"
	_ "github.com/muesli/beehive/bees/twiliobee"
	_ "github.com/muesli/beehive/bees/twitterbee"
	_ "github.com/muesli/beehive/bees/webbee"
)
<commit_msg>Added tinderbee to the available hives<commit_after>/*
 *    Copyright (C) 2014-2017 Christian Muehlhaeuser
 *
 *    This program is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU Affero General Public License as published
 *    by the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *    Authors:
 *      Christian Muehlhaeuser <muesli@gmail.com>
 */

package main

import (
	_ "github.com/muesli/beehive/bees/alertoverbee"
	_ "github.com/muesli/beehive/bees/anelpowerctrlbee"
	_ "github.com/muesli/beehive/bees/cricketbee"
	_ "github.com/muesli/beehive/bees/cronbee"
	_ "github.com/muesli/beehive/bees/devrantbee"
	_ "github.com/muesli/beehive/bees/efabee"
	_ "github.com/muesli/beehive/bees/emailbee"
	_ "github.com/muesli/beehive/bees/execbee"
	_ "github.com/muesli/beehive/bees/facebookbee"
	_ "github.com/muesli/beehive/bees/fsnotifybee"
	_ "github.com/muesli/beehive/bees/githubbee"
	_ "github.com/muesli/beehive/bees/gitterbee"
	_ "github.com/muesli/beehive/bees/htmlextractbee"
	_ "github.com/muesli/beehive/bees/httpbee"
	_ "github.com/muesli/beehive/bees/huebee"
	_ "github.com/muesli/beehive/bees/ircbee"
	_ "github.com/muesli/beehive/bees/jabberbee"
	_ "github.com/muesli/beehive/bees/jenkinsbee"
	_ "github.com/muesli/beehive/bees/mumblebee"
	_ "github.com/muesli/beehive/bees/nagiosbee"
	_ "github.com/muesli/beehive/bees/pastebinbee"
	_ "github.com/muesli/beehive/bees/pushoverbee"
	_ "github.com/muesli/beehive/bees/rssbee"
	_ "github.com/muesli/beehive/bees/s3bee"
	_ "github.com/muesli/beehive/bees/serialbee"
	_ "github.com/muesli/beehive/bees/simplepushbee"
	_ "github.com/muesli/beehive/bees/slackbee"
	_ "github.com/muesli/beehive/bees/spaceapibee"
	_ "github.com/muesli/beehive/bees/telegrambee"
	_ "github.com/muesli/beehive/bees/timebee"
	_ "github.com/muesli/beehive/bees/tinderbee"
	_ "github.com/muesli/beehive/bees/transmissionbee"
	_ "github.com/muesli/beehive/bees/tumblrbee"
	_ "github.com/muesli/beehive/bees/twiliobee"
	_ "github.com/muesli/beehive/bees/twitterbee"
	_ "github.com/muesli/beehive/bees/webbee"
)
<|endoftext|>


<commit_before>/*
Copyright 2019 The Knative 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 v1beta1

import (
	"context"
	"fmt"
	"testing"

	"github.com/knative/pkg/test/logging"
	"github.com/knative/serving/pkg/apis/serving/v1beta1"
	"github.com/pkg/errors"
	corev1 "k8s.io/api/core/v1"
	// 	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/types"
	"k8s.io/apimachinery/pkg/util/wait"

	// 	"github.com/knative/pkg/ptr"
	ptest "github.com/knative/pkg/test"
	rtesting "github.com/knative/serving/pkg/testing/v1beta1"
	"github.com/knative/serving/test"
)

// CreateConfiguration create a configuration resource in namespace with the name names.Config
// that uses the image specified by names.Image.
func CreateConfiguration(t *testing.T, clients *test.Clients, names test.ResourceNames, fopt ...rtesting.ConfigOption) (*v1beta1.Configuration, error) {
	config := Configuration(names, fopt...)
	LogResourceObject(t, ResourceObjects{Config: config})
	return clients.ServingBetaClient.Configs.Create(config)
}

// PatchConfig patches the existing configuration passed in with the applied mutations.
// Returns the latest configuration object
func PatchConfig(t *testing.T, clients *test.Clients, svc *v1beta1.Configuration, fopt ...rtesting.ConfigOption) (*v1beta1.Configuration, error) {
	newSvc := svc.DeepCopy()
	for _, opt := range fopt {
		opt(newSvc)
	}
	LogResourceObject(t, ResourceObjects{Config: newSvc})
	patchBytes, err := createPatch(svc, newSvc)
	if err != nil {
		return nil, err
	}
	return clients.ServingBetaClient.Configs.Patch(svc.ObjectMeta.Name, types.JSONPatchType, patchBytes, "")
}

// WaitForConfigLatestRevision takes a revision in through names and compares it to the current state of LatestCreatedRevisionName in Configuration.
// Once an update is detected in the LatestCreatedRevisionName, the function waits for the created revision to be set in LatestReadyRevisionName
// before returning the name of the revision.
func WaitForConfigLatestRevision(clients *test.Clients, names test.ResourceNames) (string, error) {
	var revisionName string
	err := WaitForConfigurationState(clients.ServingBetaClient, names.Config, func(c *v1beta1.Configuration) (bool, error) {
		if c.Status.LatestCreatedRevisionName != names.Revision {
			revisionName = c.Status.LatestCreatedRevisionName
			return true, nil
		}
		return false, nil
	}, "ConfigurationUpdatedWithRevision")
	if err != nil {
		return "", err
	}
	err = WaitForConfigurationState(clients.ServingBetaClient, names.Config, func(c *v1beta1.Configuration) (bool, error) {
		return (c.Status.LatestReadyRevisionName == revisionName), nil
	}, "ConfigurationReadyWithRevision")

	return revisionName, err
}

// ConfigurationSpec returns the spec of a configuration to be used throughout different
// CRD helpers.
func ConfigurationSpec(imagePath string) *v1beta1.ConfigurationSpec {
	return &v1beta1.ConfigurationSpec{
		Template: v1beta1.RevisionTemplateSpec{
			Spec: v1beta1.RevisionSpec{
				PodSpec: corev1.PodSpec{
					Containers: []corev1.Container{{
						Image: imagePath,
					}},
				},
			},
		},
	}
}

// Configuration returns a Configuration object in namespace with the name names.Config
// that uses the image specified by names.Image
func Configuration(names test.ResourceNames, fopt ...rtesting.ConfigOption) *v1beta1.Configuration {
	config := &v1beta1.Configuration{
		ObjectMeta: metav1.ObjectMeta{
			Name: names.Config,
		},
		Spec: *ConfigurationSpec(ptest.ImagePath(names.Image)),
	}

	for _, opt := range fopt {
		opt(config)
	}

	return config
}

// WaitForConfigurationState polls the status of the Configuration called name
// from client every interval until inState returns `true` indicating it
// is done, returns an error or timeout. desc will be used to name the metric
// that is emitted to track how long it took for name to get into the state checked by inState.
func WaitForConfigurationState(client *test.ServingBetaClients, name string, inState func(c *v1beta1.Configuration) (bool, error), desc string) error {
	span := logging.GetEmitableSpan(context.Background(), fmt.Sprintf("WaitForConfigurationState/%s/%s", name, desc))
	defer span.End()

	var lastState *v1beta1.Configuration
	waitErr := wait.PollImmediate(interval, timeout, func() (bool, error) {
		var err error
		lastState, err = client.Configs.Get(name, metav1.GetOptions{})
		if err != nil {
			return true, err
		}
		return inState(lastState)
	})

	if waitErr != nil {
		return errors.Wrapf(waitErr, "configuration %q is not in desired state, got: %+v", name, lastState)
	}
	return nil
}

// CheckConfigurationState verifies the status of the Configuration called name from client
// is in a particular state by calling `inState` and expecting `true`.
// This is the non-polling variety of WaitForConfigurationState
func CheckConfigurationState(client *test.ServingBetaClients, name string, inState func(r *v1beta1.Configuration) (bool, error)) error {
	c, err := client.Configs.Get(name, metav1.GetOptions{})
	if err != nil {
		return err
	}
	if done, err := inState(c); err != nil {
		return err
	} else if !done {
		return fmt.Errorf("configuration %q is not in desired state, got: %+v", name, c)
	}
	return nil
}

// // ConfigurationHasCreatedRevision returns whether the Configuration has created a Revision.
// func ConfigurationHasCreatedRevision(c *v1beta1.Configuration) (bool, error) {
// 	return c.Status.LatestCreatedRevisionName != "", nil
// }

// // IsConfigRevisionCreationFailed will check the status conditions of the
// // configuration and return true if the configuration's revision failed to
// // create.
// func IsConfigRevisionCreationFailed(c *v1beta1.Configuration) (bool, error) {
// 	if cond := c.Status.GetCondition(v1beta1.ConfigurationConditionReady); cond != nil {
// 		return cond.Status == corev1.ConditionFalse && cond.Reason == "RevisionFailed", nil
// 	}
// 	return false, nil
// }
<commit_msg>golang format tools (#4375)<commit_after>/*
Copyright 2019 The Knative 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 v1beta1

import (
	"context"
	"fmt"
	"testing"

	"github.com/knative/pkg/test/logging"
	"github.com/knative/serving/pkg/apis/serving/v1beta1"
	"github.com/pkg/errors"
	corev1 "k8s.io/api/core/v1"

	// 	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/types"
	"k8s.io/apimachinery/pkg/util/wait"

	// 	"github.com/knative/pkg/ptr"
	ptest "github.com/knative/pkg/test"
	rtesting "github.com/knative/serving/pkg/testing/v1beta1"
	"github.com/knative/serving/test"
)

// CreateConfiguration create a configuration resource in namespace with the name names.Config
// that uses the image specified by names.Image.
func CreateConfiguration(t *testing.T, clients *test.Clients, names test.ResourceNames, fopt ...rtesting.ConfigOption) (*v1beta1.Configuration, error) {
	config := Configuration(names, fopt...)
	LogResourceObject(t, ResourceObjects{Config: config})
	return clients.ServingBetaClient.Configs.Create(config)
}

// PatchConfig patches the existing configuration passed in with the applied mutations.
// Returns the latest configuration object
func PatchConfig(t *testing.T, clients *test.Clients, svc *v1beta1.Configuration, fopt ...rtesting.ConfigOption) (*v1beta1.Configuration, error) {
	newSvc := svc.DeepCopy()
	for _, opt := range fopt {
		opt(newSvc)
	}
	LogResourceObject(t, ResourceObjects{Config: newSvc})
	patchBytes, err := createPatch(svc, newSvc)
	if err != nil {
		return nil, err
	}
	return clients.ServingBetaClient.Configs.Patch(svc.ObjectMeta.Name, types.JSONPatchType, patchBytes, "")
}

// WaitForConfigLatestRevision takes a revision in through names and compares it to the current state of LatestCreatedRevisionName in Configuration.
// Once an update is detected in the LatestCreatedRevisionName, the function waits for the created revision to be set in LatestReadyRevisionName
// before returning the name of the revision.
func WaitForConfigLatestRevision(clients *test.Clients, names test.ResourceNames) (string, error) {
	var revisionName string
	err := WaitForConfigurationState(clients.ServingBetaClient, names.Config, func(c *v1beta1.Configuration) (bool, error) {
		if c.Status.LatestCreatedRevisionName != names.Revision {
			revisionName = c.Status.LatestCreatedRevisionName
			return true, nil
		}
		return false, nil
	}, "ConfigurationUpdatedWithRevision")
	if err != nil {
		return "", err
	}
	err = WaitForConfigurationState(clients.ServingBetaClient, names.Config, func(c *v1beta1.Configuration) (bool, error) {
		return (c.Status.LatestReadyRevisionName == revisionName), nil
	}, "ConfigurationReadyWithRevision")

	return revisionName, err
}

// ConfigurationSpec returns the spec of a configuration to be used throughout different
// CRD helpers.
func ConfigurationSpec(imagePath string) *v1beta1.ConfigurationSpec {
	return &v1beta1.ConfigurationSpec{
		Template: v1beta1.RevisionTemplateSpec{
			Spec: v1beta1.RevisionSpec{
				PodSpec: corev1.PodSpec{
					Containers: []corev1.Container{{
						Image: imagePath,
					}},
				},
			},
		},
	}
}

// Configuration returns a Configuration object in namespace with the name names.Config
// that uses the image specified by names.Image
func Configuration(names test.ResourceNames, fopt ...rtesting.ConfigOption) *v1beta1.Configuration {
	config := &v1beta1.Configuration{
		ObjectMeta: metav1.ObjectMeta{
			Name: names.Config,
		},
		Spec: *ConfigurationSpec(ptest.ImagePath(names.Image)),
	}

	for _, opt := range fopt {
		opt(config)
	}

	return config
}

// WaitForConfigurationState polls the status of the Configuration called name
// from client every interval until inState returns `true` indicating it
// is done, returns an error or timeout. desc will be used to name the metric
// that is emitted to track how long it took for name to get into the state checked by inState.
func WaitForConfigurationState(client *test.ServingBetaClients, name string, inState func(c *v1beta1.Configuration) (bool, error), desc string) error {
	span := logging.GetEmitableSpan(context.Background(), fmt.Sprintf("WaitForConfigurationState/%s/%s", name, desc))
	defer span.End()

	var lastState *v1beta1.Configuration
	waitErr := wait.PollImmediate(interval, timeout, func() (bool, error) {
		var err error
		lastState, err = client.Configs.Get(name, metav1.GetOptions{})
		if err != nil {
			return true, err
		}
		return inState(lastState)
	})

	if waitErr != nil {
		return errors.Wrapf(waitErr, "configuration %q is not in desired state, got: %+v", name, lastState)
	}
	return nil
}

// CheckConfigurationState verifies the status of the Configuration called name from client
// is in a particular state by calling `inState` and expecting `true`.
// This is the non-polling variety of WaitForConfigurationState
func CheckConfigurationState(client *test.ServingBetaClients, name string, inState func(r *v1beta1.Configuration) (bool, error)) error {
	c, err := client.Configs.Get(name, metav1.GetOptions{})
	if err != nil {
		return err
	}
	if done, err := inState(c); err != nil {
		return err
	} else if !done {
		return fmt.Errorf("configuration %q is not in desired state, got: %+v", name, c)
	}
	return nil
}

// // ConfigurationHasCreatedRevision returns whether the Configuration has created a Revision.
// func ConfigurationHasCreatedRevision(c *v1beta1.Configuration) (bool, error) {
// 	return c.Status.LatestCreatedRevisionName != "", nil
// }

// // IsConfigRevisionCreationFailed will check the status conditions of the
// // configuration and return true if the configuration's revision failed to
// // create.
// func IsConfigRevisionCreationFailed(c *v1beta1.Configuration) (bool, error) {
// 	if cond := c.Status.GetCondition(v1beta1.ConfigurationConditionReady); cond != nil {
// 		return cond.Status == corev1.ConditionFalse && cond.Reason == "RevisionFailed", nil
// 	}
// 	return false, nil
// }
<|endoftext|>


<commit_before>// Copyright 2014, Hǎiliàng Wáng. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package cwrap

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"os/exec"
	"reflect"
	"regexp"
	"strconv"
	"strings"
	"unsafe"
)

var (
	MachineSize = int(unsafe.Sizeof(uintptr(0)))
)

func p(v ...interface{}) {
	fmt.Println(v...)
}

func checkError(err error) {
	if err != nil {
		panic(err)
	}
}

func gofmt(file string) error {
	p("go fmt:")
	defer p("")
	return newCmd("go", "fmt", file).exec()
}

func fp(w io.Writer, v ...interface{}) {
	fmt.Fprint(w, v...)
	fmt.Fprintln(w)
}

func fpn(w io.Writer, v ...interface{}) {
	fmt.Fprint(w, v...)
}

func trimPrefix(s, prefix string) string {
	return strings.TrimPrefix(s, prefix)
}

func join(a []string, sep string) string {
	return strings.Join(a, sep)
}

func joins(a ...string) string {
	return strings.Join(a, "")
}

func sprint(v ...interface{}) string {
	return fmt.Sprint(v...)
}

func snakeToCamel(s string) string {
	ss := strings.Split(s, "_")
	for i := range ss {
		s := ss[i]
		if strings.ToUpper(s) == s {
			s = strings.ToLower(s)
		}
		ss[i] = strings.Title(s)
	}
	return join(ss, "")
}

func upperName(s string, re *regexp.Regexp) string {
	if re != nil {
		m := re.FindStringSubmatch(s)
		if len(m) > 1 && m[1] != "" {
			s = m[1]
		}
	}
	if len(s) > 3 {
		s = trimSuffix(s, "_t")
	}
	return snakeToCamel(s)
}

func hasPrefix(s, prefix string) bool {
	return strings.HasPrefix(s, prefix)
}

func snakeToLowerCamel(s string) string {
	if len(s) <= 1 {
		return s
	}
	s = snakeToCamel(s)
	return strings.ToLower(s[:1]) + s[1:]
}

func spaceToSnake(s string) string {
	return strings.Replace(s, " ", "_", -1)
}

func typeSizeAssert(ctype, gotype string) string {
	return fmt.Sprintf(
		`	if s1, s2 := unsafe.Sizeof(%[1]s), unsafe.Sizeof(%[2]s); s1 != s2 {
			panic(fmt.Errorf("Size of %[1]s is %%d, expected %%d as Go's %[2]s.", s1, s2))
		}
	`, ctype, gotype)
}

type SSet struct {
	m map[string]struct{}
}

func NewSSet() SSet {
	return SSet{make(map[string]struct{})}
}

func (m *SSet) Len() int {
	return len(m.m)
}

func (m *SSet) IsNil() bool {
	return m.m == nil
}

func (m *SSet) Add(ss ...string) {
	for _, s := range ss {
		m.m[s] = struct{}{}
	}
}

func (m *SSet) Del(s string) {
	delete(m.m, s)
}

func (m *SSet) Has(s string) bool {
	if m.m == nil {
		return false
	}
	_, has := m.m[s]
	return has
}

func contains(s, substr string) bool {
	return strings.Contains(s, substr)
}

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

func trimPreSuffix(s, fix string) string {
	return strings.TrimSuffix(strings.TrimPrefix(s, fix), fix)
}

func trimSuffix(s, suffix string) string {
	return strings.TrimSuffix(s, suffix)
}

func remove(s, substr string) string {
	return strings.Replace(s, substr, "", -1)
}

func atoi(s string) int {
	if s == "" {
		return 0
	}
	i, err := strconv.Atoi(s)
	if err != nil {
		panic(err)
	}
	return i
}

func fileExists(file string) bool {
	f, err := os.Open(file)
	if err != nil {
		return false
	}
	f.Close()
	return true
}

type cmd struct {
	*exec.Cmd
}

func newCmd(name string, arg ...string) cmd {
	return cmd{exec.Command(name, arg...)}
}

func (c cmd) read(visit func(r io.Reader) error) error {
	stdout, err := c.StdoutPipe()
	if err != nil {
		return err
	}
	defer stdout.Close()
	stderr, err := c.StderrPipe()
	if err != nil {
		return err
	}
	defer stderr.Close()
	if err := c.Start(); err != nil {
		return err
	}
	go io.Copy(os.Stderr, stderr)
	if err := visit(stdout); err != nil {
		return err
	}
	if err := c.Wait(); err != nil {
		return err
	}
	return nil
}

func (c cmd) exec() error {
	stdout, err := c.StdoutPipe()
	if err != nil {
		return err
	}
	defer stdout.Close()
	stderr, err := c.StderrPipe()
	if err != nil {
		return err
	}
	defer stderr.Close()
	if err := c.Start(); err != nil {
		return err
	}
	go io.Copy(os.Stderr, stderr)
	go io.Copy(os.Stdout, stdout)
	if err := c.Wait(); err != nil {
		return err
	}
	return nil

}

func writeToString(write func(w io.Writer)) string {
	var buf bytes.Buffer
	write(&buf)
	return buf.String()
}

func pt(v interface{}) {
	p(reflect.TypeOf(v))
}

func hex(i int, length int) string {
	if i < 0 {
		return strconv.FormatInt(int64(i), 10)
	}
	s := strings.ToUpper(strconv.FormatInt(int64(i), 16))
	if len(s)+2 < length {
		s = strings.Repeat("0", length-len(s)-2) + s
	}
	return "0x" + s
}
<commit_msg>better type name.<commit_after>// Copyright 2014, Hǎiliàng Wáng. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package cwrap

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"os/exec"
	"reflect"
	"regexp"
	"strconv"
	"strings"
	"unsafe"
)

var (
	MachineSize = int(unsafe.Sizeof(uintptr(0)))
)

func p(v ...interface{}) {
	fmt.Println(v...)
}

func checkError(err error) {
	if err != nil {
		panic(err)
	}
}

func gofmt(file string) error {
	p("go fmt:")
	defer p("")
	return newCmd("go", "fmt", file).exec()
}

func fp(w io.Writer, v ...interface{}) {
	fmt.Fprint(w, v...)
	fmt.Fprintln(w)
}

func fpn(w io.Writer, v ...interface{}) {
	fmt.Fprint(w, v...)
}

func trimPrefix(s, prefix string) string {
	return strings.TrimPrefix(s, prefix)
}

func join(a []string, sep string) string {
	return strings.Join(a, sep)
}

func joins(a ...string) string {
	return strings.Join(a, "")
}

func sprint(v ...interface{}) string {
	return fmt.Sprint(v...)
}

func snakeToCamel(s string) string {
	ss := strings.Split(s, "_")
	for i := range ss {
		s := ss[i]
		if strings.ToUpper(s) == s {
			s = strings.ToLower(s)
		}
		ss[i] = strings.Title(s)
	}
	return join(ss, "")
}

func upperName(s string, re *regexp.Regexp) string {
	if re != nil {
		m := re.FindStringSubmatch(s)
		if len(m) > 1 && len(m[1]) > 2 {
			s = m[1]
		}
	}
	if len(s) > 3 {
		s = trimSuffix(s, "_t")
	}
	return snakeToCamel(s)
}

func hasPrefix(s, prefix string) bool {
	return strings.HasPrefix(s, prefix)
}

func snakeToLowerCamel(s string) string {
	if len(s) <= 1 {
		return s
	}
	s = snakeToCamel(s)
	return strings.ToLower(s[:1]) + s[1:]
}

func spaceToSnake(s string) string {
	return strings.Replace(s, " ", "_", -1)
}

func typeSizeAssert(ctype, gotype string) string {
	return fmt.Sprintf(
		`	if s1, s2 := unsafe.Sizeof(%[1]s), unsafe.Sizeof(%[2]s); s1 != s2 {
			panic(fmt.Errorf("Size of %[1]s is %%d, expected %%d as Go's %[2]s.", s1, s2))
		}
	`, ctype, gotype)
}

type SSet struct {
	m map[string]struct{}
}

func NewSSet() SSet {
	return SSet{make(map[string]struct{})}
}

func (m *SSet) Len() int {
	return len(m.m)
}

func (m *SSet) IsNil() bool {
	return m.m == nil
}

func (m *SSet) Add(ss ...string) {
	for _, s := range ss {
		m.m[s] = struct{}{}
	}
}

func (m *SSet) Del(s string) {
	delete(m.m, s)
}

func (m *SSet) Has(s string) bool {
	if m.m == nil {
		return false
	}
	_, has := m.m[s]
	return has
}

func contains(s, substr string) bool {
	return strings.Contains(s, substr)
}

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

func trimPreSuffix(s, fix string) string {
	return strings.TrimSuffix(strings.TrimPrefix(s, fix), fix)
}

func trimSuffix(s, suffix string) string {
	return strings.TrimSuffix(s, suffix)
}

func remove(s, substr string) string {
	return strings.Replace(s, substr, "", -1)
}

func atoi(s string) int {
	if s == "" {
		return 0
	}
	i, err := strconv.Atoi(s)
	if err != nil {
		panic(err)
	}
	return i
}

func fileExists(file string) bool {
	f, err := os.Open(file)
	if err != nil {
		return false
	}
	f.Close()
	return true
}

type cmd struct {
	*exec.Cmd
}

func newCmd(name string, arg ...string) cmd {
	return cmd{exec.Command(name, arg...)}
}

func (c cmd) read(visit func(r io.Reader) error) error {
	stdout, err := c.StdoutPipe()
	if err != nil {
		return err
	}
	defer stdout.Close()
	stderr, err := c.StderrPipe()
	if err != nil {
		return err
	}
	defer stderr.Close()
	if err := c.Start(); err != nil {
		return err
	}
	go io.Copy(os.Stderr, stderr)
	if err := visit(stdout); err != nil {
		return err
	}
	if err := c.Wait(); err != nil {
		return err
	}
	return nil
}

func (c cmd) exec() error {
	stdout, err := c.StdoutPipe()
	if err != nil {
		return err
	}
	defer stdout.Close()
	stderr, err := c.StderrPipe()
	if err != nil {
		return err
	}
	defer stderr.Close()
	if err := c.Start(); err != nil {
		return err
	}
	go io.Copy(os.Stderr, stderr)
	go io.Copy(os.Stdout, stdout)
	if err := c.Wait(); err != nil {
		return err
	}
	return nil

}

func writeToString(write func(w io.Writer)) string {
	var buf bytes.Buffer
	write(&buf)
	return buf.String()
}

func pt(v interface{}) {
	p(reflect.TypeOf(v))
}

func hex(i int, length int) string {
	if i < 0 {
		return strconv.FormatInt(int64(i), 10)
	}
	s := strings.ToUpper(strconv.FormatInt(int64(i), 16))
	if len(s)+2 < length {
		s = strings.Repeat("0", length-len(s)-2) + s
	}
	return "0x" + s
}
<|endoftext|>


<commit_before>// Collection of small, useful utility functions
package util

import (
	"bufio"
	"flag"
	"io"
	"math/rand"
	"net"
	"os"
	"strings"
	"time"
)

// TimeoutDialer creates a Dialer that can timeout after a connection timeout
// or a read timeout
func TimeoutDialer(connTimeout, rwTimeout time.Duration) func(netw, addr string) (c net.Conn, err error) {
	return func(netw, addr string) (net.Conn, error) {
		conn, err := net.DialTimeout(netw, addr, connTimeout)

		if err != nil {
			return nil, err
		}

		conn.SetDeadline(time.Now().Add(rwTimeout))

		return conn, nil
	}
}

// ExitWhenOrphaned checks if the current process becomes orphaned and
// immediately kills the script. This prevents multiple instances of the
// script running indefinitely when it's being launched by some external
// process (e.g. Splunk).
func ExitWhenOrphaned() {
	tick1s := time.NewTicker(time.Second * 1).C

	// Check for orphaned process
	go func() {
		for {
			select {
			case <-tick1s:
				if os.Getppid() == 1 {
					panic("Orphaned process! Exiting!")
				}
			}
		}
	}()
}

// Collect args from files or stdin
func GetArgs() (args []string) {
	var inputs []io.Reader

	// Check for files first and use stdin if no files are specified
	files := flag.Args()

	if len(files) > 0 {
		for _, file := range files {
			input, err := os.Open(file)

			if err != nil {
				//logging.Warn(err.Error())
				continue
			}

			inputs = append(inputs, input)
		}
	} else {
		inputs = append(inputs, os.Stdin)
	}

	// Scan all inputs for arguments
	for _, input := range inputs {
		scanner := bufio.NewScanner(input)

		for scanner.Scan() {
			line := scanner.Text()
			// Skip empty lines and comments
			arg := strings.TrimSpace(line)

			if arg == "" || strings.HasPrefix(arg, "#") {
				continue
			}

			args = append(args, arg)
			//logging.Trace("Adding arg: %s", arg)
		}

		if err := scanner.Err(); err != nil {
			//logging.Error("Unable to add line: %s", err)
		}
	}

	return args
}

// Return a random duration between two (positive) durations
func RandomDuration(min, max time.Duration) time.Duration {
	rand.Seed(time.Now().UnixNano())
	nmin := int(min.Seconds())
	nmax := int(max.Seconds())
	n := rand.Intn(nmax-nmin) + nmax

	return time.Second * time.Duration(n)
}
<commit_msg>Refactor to use time.Tick instead of NewTicker<commit_after>// Collection of small, useful utility functions
package util

import (
	"bufio"
	"flag"
	"io"
	"math/rand"
	"net"
	"os"
	"strings"
	"time"
)

// TimeoutDialer creates a Dialer that can timeout after a connection timeout
// or a read timeout
func TimeoutDialer(connTimeout, rwTimeout time.Duration) func(netw, addr string) (c net.Conn, err error) {
	return func(netw, addr string) (net.Conn, error) {
		conn, err := net.DialTimeout(netw, addr, connTimeout)

		if err != nil {
			return nil, err
		}

		conn.SetDeadline(time.Now().Add(rwTimeout))

		return conn, nil
	}
}

// ExitWhenOrphaned checks if the current process becomes orphaned and
// immediately kills the script. This prevents multiple instances of the
// script running indefinitely when it's being launched by some external
// process (e.g. Splunk).
func ExitWhenOrphaned() {
	ticker := time.Tick(1 * time.Second)

	go func() {
		for _ := range ticker {
			// The parent pid of an orphaned process is PID 1
			if os.Getppid() == 1 {
				panic("Orphaned process. Exiting!")
			}
		}
	}()
}

// Collect args from files or stdin
func GetArgs() (args []string) {
	var inputs []io.Reader

	// Check for files first and use stdin if no files are specified
	files := flag.Args()

	if len(files) > 0 {
		for _, file := range files {
			input, err := os.Open(file)

			if err != nil {
				//logging.Warn(err.Error())
				continue
			}

			inputs = append(inputs, input)
		}
	} else {
		inputs = append(inputs, os.Stdin)
	}

	// Scan all inputs for arguments
	for _, input := range inputs {
		scanner := bufio.NewScanner(input)

		for scanner.Scan() {
			line := scanner.Text()
			// Skip empty lines and comments
			arg := strings.TrimSpace(line)

			if arg == "" || strings.HasPrefix(arg, "#") {
				continue
			}

			args = append(args, arg)
			//logging.Trace("Adding arg: %s", arg)
		}

		if err := scanner.Err(); err != nil {
			//logging.Error("Unable to add line: %s", err)
		}
	}

	return args
}

// Return a random duration between two (positive) durations
func RandomDuration(min, max time.Duration) time.Duration {
	rand.Seed(time.Now().UnixNano())
	nmin := int(min.Seconds())
	nmax := int(max.Seconds())
	n := rand.Intn(nmax-nmin) + nmax

	return time.Second * time.Duration(n)
}
<|endoftext|>


<commit_before>package main

import "encoding/json"
import "io/ioutil"
import "math/rand"
import "time"
import "os"

func main() {
	configBytes, err := ioutil.ReadFile(os.Args[1])
	if err != nil {
		panic(err)
	}
	var config map[string]interface{}
	err = json.Unmarshal(configBytes, &config)
	if err != nil {
		panic(err)
	}
	sceneConfig := config["scene"].(map[string]interface{})
	scene := MakeScene(sceneConfig)
	rendererConfig := config["renderer"].(map[string]interface{})
	renderer := MakeRenderer(rendererConfig)
	seed := time.Now().UTC().UnixNano()
	rng := rand.New(rand.NewSource(seed))
	renderer.Render(rng, &scene)
}
<commit_msg>Process any number of config files on the command line<commit_after>package main

import "encoding/json"
import "fmt"
import "io/ioutil"
import "math/rand"
import "time"
import "os"

func main() {
	seed := time.Now().UTC().UnixNano()
	rng := rand.New(rand.NewSource(seed))

	nArgs := len(os.Args)
	for i := 1; i < nArgs; i++ {
		inputPath := os.Args[i]
		fmt.Printf(
			"Processing %s (%d/%d)...\n",
			inputPath, i, nArgs-1)
		configBytes, err := ioutil.ReadFile(inputPath)
		if err != nil {
			panic(err)
		}
		var config map[string]interface{}
		err = json.Unmarshal(configBytes, &config)
		if err != nil {
			panic(err)
		}
		sceneConfig := config["scene"].(map[string]interface{})
		scene := MakeScene(sceneConfig)
		rendererConfig := config["renderer"].(map[string]interface{})
		renderer := MakeRenderer(rendererConfig)
		renderer.Render(rng, &scene)
	}
}
<|endoftext|>


<commit_before>package main

// This is a direct port of https://gist.github.com/benjojo/0124c7875113831a4274

import (
	"fmt"
	"strconv"
	"strings"
)

// PacketType can be:
// * Status Report
// * GPGGA
type APRSPacket struct {
	Callsign      string // Done!
	PacketType    string
	Latitude      string
	Longitude     string
	Altitude      string
	GPSTime       string
	RawData       string
	Symbol        string
	Heading       string
	PHG           string
	Speed         string
	Destination   string // Done!
	Status        string
	WindDirection string
	WindSpeed     string
	WindGust      string
	WeatherTemp   string
	RainHour      string
	RainDay       string
	RainMidnight  string
	Humidity      string
	Pressure      string
	Luminosity    string
	Snowfall      string
	Raincounter   string
}

func ParseAPRSPacket(input string) (p APRSPacket, e error) {
	if input == "" {
		e = fmt.Errorf("Could not parse the packet because the packet line is blank")
		return p, e
	}

	if !strings.Contains(input, ">") {
		e = fmt.Errorf("This libary does not support this kind of packet.")
		return p, e
	}
	p = APRSPacket{}
	CommaParts := strings.Split(input, ",")
	RouteString := CommaParts[0]
	RouteParts := strings.Split(RouteString, ">")
	if len(RouteParts) != 2 {
		e = fmt.Errorf("There was not one > in the route part of the packet, dunno how to decode this")
		return p, e
	}
	p.Callsign = RouteParts[0]
	p.Destination = RouteParts[1]

	LocationOfStatusMarker := strings.Index(input, ":>")
	LocationOfNormalMarker := strings.Index(input, ">")

	if LocationOfStatusMarker > LocationOfNormalMarker {
		p.PacketType = "Status Report"
		RawArray := []byte(input[LocationOfStatusMarker+2 : (LocationOfStatusMarker+2)+(len(input)-LocationOfStatusMarker-2)])
		if len(RawArray) > 6 && strings.ToLower(string(RawArray[6])) == "z" {
			p.GPSTime = input[LocationOfStatusMarker+2 : LocationOfStatusMarker+8]
			p.Status = input[LocationOfStatusMarker+2 : (LocationOfStatusMarker+2)+len(input)-LocationOfStatusMarker-9]
		} else {
			p.Status = input[LocationOfStatusMarker+2 : (LocationOfStatusMarker+2)+len(input)-LocationOfStatusMarker-2]
		}
	}

	// Test if the packet is a GPGGA packet
	if strings.Contains(input, ":$GPGGA,") {
		p.PacketType = "GPGGA"
		GPGGALocation := strings.Index(input, ":$GPGGA,")
		RawData := input[GPGGALocation : GPGGALocation+(len(input)-GPGGALocation)]
		SplitData := strings.Split(RawData, ",")
		if len(SplitData) < 9 {
			e = fmt.Errorf("There was not enough data inside the GPGGA packet to decode it")
			return p, e
		}
		p.GPSTime = SplitData[1]

		// Lat
		DegLatitude := SplitData[2]
		DegLatMin, e := strconv.ParseFloat(DegLatitude[2:2+len(DegLatitude)-2], 64)
		if e != nil {
			e = fmt.Errorf("Could not decode the DegLatMin part of the GPGGA packet")
			return p, e
		}
		DegLatMin = DegLatMin / 60
		StrDegLatMin := fmt.Sprintf("%f", DegLatMin)
		p.Latitude = fmt.Sprintf("%s%s", DegLatitude[:2], StrDegLatMin[1:len(StrDegLatMin)-1])

		if Split[3] == "S" {
			p.Latitude = fmt.Sprintf("-%s", p.Latitude)
		}

		// Long
		DegLongitude := SplitData[4]
		DegLonMin, e := strconv.ParseFloat(DegLongitude[3:3+len(DegLongitude)-3], 64)
		if e != nil {
			e = fmt.Errorf("Could not decode the DegLonMin part of the GPGGA packet")
			return p, e
		}
		DegLonMin = DegLonMin / 60
		StrDegLonMin := fmt.Sprintf("%f", DegLonMin)
		p.Longitude = fmt.Sprintf("%s%s", DegLongitude[:3], StrDegLonMin[1:len(StrDegLonMin)-1])

		if Split[3] == "W" {
			p.Longitude = fmt.Sprintf("-%s", p.Longitude)
		}

	}

	return p, e
}
<commit_msg>Finished off the GPGGA packet decoding.<commit_after>package main

// This is a direct port of https://gist.github.com/benjojo/0124c7875113831a4274

import (
	"fmt"
	"strconv"
	"strings"
)

// PacketType can be:
// * Status Report
// * GPGGA
type APRSPacket struct {
	Callsign      string // Done!
	PacketType    string
	Latitude      string
	Longitude     string
	Altitude      string
	GPSTime       string
	RawData       string
	Symbol        string
	Heading       string
	PHG           string
	Speed         string
	Destination   string // Done!
	Status        string
	WindDirection string
	WindSpeed     string
	WindGust      string
	WeatherTemp   string
	RainHour      string
	RainDay       string
	RainMidnight  string
	Humidity      string
	Pressure      string
	Luminosity    string
	Snowfall      string
	Raincounter   string
}

func ParseAPRSPacket(input string) (p APRSPacket, e error) {
	if input == "" {
		e = fmt.Errorf("Could not parse the packet because the packet line is blank")
		return p, e
	}

	if !strings.Contains(input, ">") {
		e = fmt.Errorf("This libary does not support this kind of packet.")
		return p, e
	}
	p = APRSPacket{}
	CommaParts := strings.Split(input, ",")
	RouteString := CommaParts[0]
	RouteParts := strings.Split(RouteString, ">")
	if len(RouteParts) != 2 {
		e = fmt.Errorf("There was not one > in the route part of the packet, dunno how to decode this")
		return p, e
	}
	p.Callsign = RouteParts[0]
	p.Destination = RouteParts[1]

	LocationOfStatusMarker := strings.Index(input, ":>")
	LocationOfNormalMarker := strings.Index(input, ">")

	if LocationOfStatusMarker > LocationOfNormalMarker {
		p.PacketType = "Status Report"
		RawArray := []byte(input[LocationOfStatusMarker+2 : (LocationOfStatusMarker+2)+(len(input)-LocationOfStatusMarker-2)])
		if len(RawArray) > 6 && strings.ToLower(string(RawArray[6])) == "z" {
			p.GPSTime = input[LocationOfStatusMarker+2 : LocationOfStatusMarker+8]
			p.Status = input[LocationOfStatusMarker+2 : (LocationOfStatusMarker+2)+len(input)-LocationOfStatusMarker-9]
		} else {
			p.Status = input[LocationOfStatusMarker+2 : (LocationOfStatusMarker+2)+len(input)-LocationOfStatusMarker-2]
		}
	}

	// Test if the packet is a GPGGA packet
	if strings.Contains(input, ":$GPGGA,") {
		p.PacketType = "GPGGA"
		GPGGALocation := strings.Index(input, ":$GPGGA,")
		RawData := input[GPGGALocation : GPGGALocation+(len(input)-GPGGALocation)]
		SplitData := strings.Split(RawData, ",")
		if len(SplitData) < 9 {
			e = fmt.Errorf("There was not enough data inside the GPGGA packet to decode it")
			return p, e
		}
		p.GPSTime = SplitData[1]

		// Lat
		DegLatitude := SplitData[2]
		DegLatMin, e := strconv.ParseFloat(DegLatitude[2:2+len(DegLatitude)-2], 64)
		if e != nil {
			e = fmt.Errorf("Could not decode the DegLatMin part of the GPGGA packet")
			return p, e
		}
		DegLatMin = DegLatMin / 60
		StrDegLatMin := fmt.Sprintf("%f", DegLatMin)
		p.Latitude = fmt.Sprintf("%s%s", DegLatitude[:2], StrDegLatMin[1:len(StrDegLatMin)-1])

		if Split[3] == "S" {
			p.Latitude = fmt.Sprintf("-%s", p.Latitude)
		}

		// Long
		DegLongitude := SplitData[4]
		DegLonMin, e := strconv.ParseFloat(DegLongitude[3:3+len(DegLongitude)-3], 64)
		if e != nil {
			e = fmt.Errorf("Could not decode the DegLonMin part of the GPGGA packet")
			return p, e
		}
		DegLonMin = DegLonMin / 60
		StrDegLonMin := fmt.Sprintf("%f", DegLonMin)
		p.Longitude = fmt.Sprintf("%s%s", DegLongitude[:3], StrDegLonMin[1:len(StrDegLonMin)-1])

		if Split[3] == "W" {
			p.Longitude = fmt.Sprintf("-%s", p.Longitude)
		}

		f, e := strconv.ParseFloat(SplitData[9], 64)
		if e != nil {
			e = fmt.Errorf("Could not decode the Altitude part of the GPGGA packet")
			return p, e
		}
		p.Altitude = fmt.Sprintf("%f", f)
	}

	return p, e
}
<|endoftext|>


<commit_before>package macross

import (
	"github.com/insionng/macross/libraries/com"
	"strconv"
	"time"
)

type (
	Args struct {
		s string
	}
)

func (a *Args) MustInt() int {
	return com.StrTo(a.s).MustInt()
}

func (a *Args) MustInt64() int64 {
	return com.StrTo(a.s).MustInt64()
}

func (a *Args) MustUint8() uint8 {
	return com.StrTo(a.s).MustUint8()
}

func (a *Args) MustUint() uint {
	return uint(com.StrTo(a.s).MustInt64())
}

func (a *Args) Float32() (f float64, e error) {
	f, e = strconv.ParseFloat(a.s, 32)
	return
}

func (a *Args) MustFloat32() (f float64) {
	f, _ = strconv.ParseFloat(a.s, 32)
	return
}

func (a *Args) Float64() (f float64, e error) {
	f, e = strconv.ParseFloat(a.s, 64)
	return
}

func (a *Args) MustFloat64() (f float64) {
	f, _ = strconv.ParseFloat(a.s, 64)
	return
}

func (a *Args) Int() (int, error) {
	return com.StrTo(a.s).Int()
}

func (a *Args) Int64() (int64, error) {
	return com.StrTo(a.s).Int64()
}

func (a *Args) String() string {
	return com.StrTo(a.s).String()
}

func (a *Args) Bytes() []byte {
	return []byte(com.StrTo(a.s).String())
}

func (a *Args) Time() time.Time {
	tme, _ := time.Parse("2006-01-02 03:04:05 PM", com.StrTo(a.s).String())
	return tme
}

func (a *Args) Exist() bool {
	return com.StrTo(a.s).Exist()
}

func (a *Args) ToStr(args ...int) (s string) {
	return com.ToStr(a.s, args...)
}

func (a *Args) ToSnakeCase(str ...string) string {
	var s string
	if len(str) > 0 {
		s = str[0]
	} else {
		if len(a.s) != 0 {
			s = a.s
		}
	}
	return com.ToSnakeCase(s)
}

// Param returns the named parameter value that is found in the URL path matching the current route.
// If the named parameter cannot be found, an empty string will be returned.
func (c *Context) Param(name string) *Args {
	var a = new(Args)
	for i, n := range c.pnames {
		if n == name {
			a.s = c.pvalues[i]
		}
	}
	return a
}

func (c *Context) Form(key ...string) *Args {
	var a = new(Args)
	var k string
	if len(key) > 0 {
		k = key[0]
		a.s = c.FormValue(k)
	}
	return a
}

//Args 先从URL获取参数，如若没有则再尝试从from获取参数
func (c *Context) Args(key ...string) *Args {
	var a = new(Args)
	var k string
	if len(key) > 0 {
		k = key[0]
		for i, n := range c.pnames {
			if n == k {
				a.s = c.pvalues[i]
			}
		}
		if len(a.s) == 0 {
			a.s = c.FormValue(k)
		}
	}
	return a
}

func (c *Context) Parameter(i int) (value string) {
	l := len(c.pnames)
	if i < l {
		value = c.pvalues[i]
	}
	return
}

// QueryParam implements `Context#QueryParam` function.
func (c *Context) QueryParam(name string) string {
	return string(c.QueryArgs().Peek(name))
}

// QueryParams implements `Context#QueryParams` function.
func (c *Context) QueryParams() (params map[string][]string) {
	params = make(map[string][]string)
	c.URI().QueryArgs().VisitAll(func(k, v []byte) {
		_, ok := params[string(k)]
		if !ok {
			params[string(k)] = make([]string, 0)
		}
		params[string(k)] = append(params[string(k)], string(v))
	})
	return
}

func (c *Context) QueryString() string {
	return string(c.URI().QueryString())
}
<commit_msg>fix float32 for args<commit_after>package macross

import (
	"github.com/insionng/macross/libraries/com"
	"strconv"
	"time"
)

type (
	Args struct {
		s string
	}
)

func (a *Args) MustInt() int {
	return com.StrTo(a.s).MustInt()
}

func (a *Args) MustInt64() int64 {
	return com.StrTo(a.s).MustInt64()
}

func (a *Args) MustUint8() uint8 {
	return com.StrTo(a.s).MustUint8()
}

func (a *Args) MustUint() uint {
	return uint(com.StrTo(a.s).MustInt64())
}

func (a *Args) Float32() (f float32, e error) {
	var _f float64
	_f, e = strconv.ParseFloat(a.s, 32)
	f = float32(_f)
	return
}

func (a *Args) MustFloat32() (f float32) {
	_f, _ := strconv.ParseFloat(a.s, 32)
	f = float32(_f)
	return
}

func (a *Args) Float64() (f float64, e error) {
	f, e = strconv.ParseFloat(a.s, 64)
	return
}

func (a *Args) MustFloat64() (f float64) {
	f, _ = strconv.ParseFloat(a.s, 64)
	return
}

func (a *Args) Int() (int, error) {
	return com.StrTo(a.s).Int()
}

func (a *Args) Int64() (int64, error) {
	return com.StrTo(a.s).Int64()
}

func (a *Args) String() string {
	return com.StrTo(a.s).String()
}

func (a *Args) Bytes() []byte {
	return []byte(com.StrTo(a.s).String())
}

func (a *Args) Time() time.Time {
	tme, _ := time.Parse("2006-01-02 03:04:05 PM", com.StrTo(a.s).String())
	return tme
}

func (a *Args) Exist() bool {
	return com.StrTo(a.s).Exist()
}

func (a *Args) ToStr(args ...int) (s string) {
	return com.ToStr(a.s, args...)
}

func (a *Args) ToSnakeCase(str ...string) string {
	var s string
	if len(str) > 0 {
		s = str[0]
	} else {
		if len(a.s) != 0 {
			s = a.s
		}
	}
	return com.ToSnakeCase(s)
}

// Param returns the named parameter value that is found in the URL path matching the current route.
// If the named parameter cannot be found, an empty string will be returned.
func (c *Context) Param(name string) *Args {
	var a = new(Args)
	for i, n := range c.pnames {
		if n == name {
			a.s = c.pvalues[i]
		}
	}
	return a
}

func (c *Context) Form(key ...string) *Args {
	var a = new(Args)
	var k string
	if len(key) > 0 {
		k = key[0]
		a.s = c.FormValue(k)
	}
	return a
}

//Args 先从URL获取参数，如若没有则再尝试从from获取参数
func (c *Context) Args(key ...string) *Args {
	var a = new(Args)
	var k string
	if len(key) > 0 {
		k = key[0]
		for i, n := range c.pnames {
			if n == k {
				a.s = c.pvalues[i]
			}
		}
		if len(a.s) == 0 {
			a.s = c.FormValue(k)
		}
	}
	return a
}

func (c *Context) Parameter(i int) (value string) {
	l := len(c.pnames)
	if i < l {
		value = c.pvalues[i]
	}
	return
}

// QueryParam implements `Context#QueryParam` function.
func (c *Context) QueryParam(name string) string {
	return string(c.QueryArgs().Peek(name))
}

// QueryParams implements `Context#QueryParams` function.
func (c *Context) QueryParams() (params map[string][]string) {
	params = make(map[string][]string)
	c.URI().QueryArgs().VisitAll(func(k, v []byte) {
		_, ok := params[string(k)]
		if !ok {
			params[string(k)] = make([]string, 0)
		}
		params[string(k)] = append(params[string(k)], string(v))
	})
	return
}

func (c *Context) QueryString() string {
	return string(c.URI().QueryString())
}
<|endoftext|>