<commit_before>package gnosis

import (
	"encoding/json"
	"html/template"
	"io/ioutil"
	"log"
	"sync"
)

var staticConfig *Config
var configLock = new(sync.RWMutex)

//var templates = template.Must(template.ParseFiles("/var/wiki-backend/wiki.html"))
//template.New("allTemplates")
var allTemplates = template.New("allTemplates")
var templateLock = new(sync.RWMutex)

type GlobalSection struct {
	Port        string
	Hostname    string
	TemplateDir string
	Templates   []string
	Redirects   map[string]string
}

type ServerSection struct {
	Path        string   // filesystem path to serve out
	Prefix      string   // Web URL Prefix - alternatively the prefix for a search handler
	DefaultPage string   // Default page to serve if empty URI
	Template    string   // Template file to build the web URL from
	ServerType  string   // markdown, raw, or search to denote the type of Server handle
	TopicURL    string   // URI prefix to redirect to topic pages
	Restricted  []string // list of restricts - extensions for raw, topics for markdown
}

type IndexSection struct {
	WatchDir       []string // Location that we will be watching for updates
	WatchExtension string // file extensions that we will watch for within that dir
	IndexPath      string //location to store the index
	IndexType      string // type of index - likely "en"
	IndexName   string // name of the index
	Restricted []string // Tags to restrict indexing on
}

type RedirectSection struct {
	Requested string
	Target    string
	Code      int
}

type Config struct {
	Global    GlobalSection
	Redirects []RedirectSection
	Server    []ServerSection
	Indexes []IndexSection
}

var defaultConfig = []byte(`{
  "Global": {
    "Port": "8080",
    "Hostname": "localhost"
  },
  "Server": [
  	{}
      "Path": "/var/www/wiki/",
      "Prefix": "/",
      "DefaultPage": "index",
      "ServerType": "markdown",
      "Template": "wiki.html",
      "Restricted": [
        "internal",
        "handbook"
      ]
    }
  ]
}`)

func GetConfig() *Config {
	configLock.RLock()
	defer configLock.RUnlock()
	return staticConfig
}

func LoadConfig(configFile string) bool {

	if configFile == "" {
		log.Println("no configuration file specified, using ./config.json")
		// return an empty config file
		configFile = "config.json"
	}

	// have to read in the line into a byte[] array
	fileContents, err := ioutil.ReadFile(configFile)
	if err != nil {
		log.Printf("Problem loading config file: %s", err.Error())
	}

	// UnMarshal the config file that was read in
	temp := new(Config)

	err = json.Unmarshal(defaultConfig, temp)

	if err != nil {
		log.Println("problem parsing built in default configuration - this should not happen")
		return false
	}

	err = json.Unmarshal(fileContents, temp)
	//Make sure you were able to read it in
	if err != nil {
		log.Printf("parse config error: %s", err.Error())
		return false
	}

	configLock.Lock()
	staticConfig = temp
	configLock.Unlock()

	return true
}

func ParseTemplates(globalConfig GlobalSection) {
	var err error
	//newTemplate := template.New("newTemplate")
	newTemplate, err := template.ParseGlob(globalConfig.TemplateDir + "*")
	if err != nil {
		log.Println("Found an invalid template, abandoning updating templates")
		return
	}

	loadedTemplates := newTemplate.Templates()
	for _, individualTemplate := range loadedTemplates {
		log.Printf("Loaded template %s ", individualTemplate.Name())
	}

	/*
		for _, templateFile := range globalConfig.Templates {
			nextTemplate, err = newTemplate.ParseFiles(globalConfig.TemplateDir + templateFile)
			if nextTemplate != nil {
				newTemplate = nextTemplate
			} else {
				log.Println("Found an invalid template, abandoning updating templates")
			}
		}
	*/

	// log.Printf("loaded templates - %s", newTemplate.Name())

	if err == nil {
		templateLock.Lock()
		defer templateLock.Unlock()
		allTemplates = newTemplate
	}

}
<commit_msg>made some more changes, started changing the templates in the config and how they work<commit_after>package gnosis

import (
	"encoding/json"
	"html/template"
	"io/ioutil"
	"log"
	"sync"
)

var staticConfig *Config
var configLock = new(sync.RWMutex)

type Config struct {
	Global    GlobalSection
	Redirects []RedirectSection
	Server    []ServerSection
	Indexes []IndexSection
	Templates   map[string]string
}

//var templates = template.Must(template.ParseFiles("/var/wiki-backend/wiki.html"))
//template.New("allTemplates")
var allTemplates = template.New("allTemplates")
var templateLock = new(sync.RWMutex)

type GlobalSection struct {
	Port        string
	Hostname    string
	TemplateDir string
}

type RedirectSection struct {
	Requested string
	Target    string
	Code      int
}

type IndexSection struct {
	WatchDir       []string // Location that we will be watching for updates
	WatchExtension string // file extensions that we will watch for within that dir
	IndexPath      string //location to store the index
	IndexType      string // type of index - likely "en"
	IndexName   string // name of the index
	Restricted []string // Tags to restrict indexing on
}

type ServerSection struct {
	Path        string   // filesystem path to serve out
	Prefix      string   // Web URL Prefix - alternatively the prefix for a search handler
	DefaultPage string   // Default page to serve if empty URI
	Template    string   // Template file to build the web URL from
	ServerType  string   // markdown, raw, or search to denote the type of Server handle
	TopicURL    string   // URI prefix to redirect to topic pages
	Restricted  []string // list of restricts - extensions for raw, topics for markdown
}

func GetConfig() *Config {
	configLock.RLock()
	defer configLock.RUnlock()
	return staticConfig
}

func LoadConfig(configFile string) bool {

	if configFile == "" {
		log.Println("no configuration file specified, using ./config.json")
		// return an empty config file
		configFile = "config.json"
	}

	// have to read in the line into a byte[] array
	fileContents, err := ioutil.ReadFile(configFile)
	if err != nil {
		log.Printf("Problem loading config file: %s", err.Error())
	}

	// UnMarshal the config file that was read in
	temp := new(Config)

	err = json.Unmarshal(fileContents, temp)
	//Make sure you were able to read it in
	if err != nil {
		log.Printf("parse config error: %s", err.Error())
		return false
	}

	configLock.Lock()
	staticConfig = temp
	configLock.Unlock()

	return true
}

func ParseTemplates(globalConfig GlobalSection) {
	var err error
	//newTemplate := template.New("newTemplate")
	newTemplate, err := template.ParseGlob(globalConfig.TemplateDir + "*")
	if err != nil {
		log.Println("Found an invalid template, abandoning updating templates")
		return
	}

	loadedTemplates := newTemplate.Templates()
	for _, individualTemplate := range loadedTemplates {
		log.Printf("Loaded template %s ", individualTemplate.Name())
	}

	/*
		for _, templateFile := range globalConfig.Templates {
			nextTemplate, err = newTemplate.ParseFiles(globalConfig.TemplateDir + templateFile)
			if nextTemplate != nil {
				newTemplate = nextTemplate
			} else {
				log.Println("Found an invalid template, abandoning updating templates")
			}
		}
	*/

	// log.Printf("loaded templates - %s", newTemplate.Name())

	if err == nil {
		templateLock.Lock()
		defer templateLock.Unlock()
		allTemplates = newTemplate
	}

}
<|endoftext|>


<commit_before>package main

import (
	"encoding/base64"
	"encoding/json"

	"github.com/orktes/captainhub/Godeps/_workspace/src/github.com/google/go-github/github"
)

type captainConfigPlugin struct {
	Name   string                 `json:"name"`
	Config map[string]interface{} `json:"config"`
}

type captainConfig struct {
	Plugins []captainConfigPlugin `json:"plugins"`
}

func parseCaptainConf(content []byte, cfg *captainConfig) (err error) {
	return json.Unmarshal(content, cfg)
}

func getCaptainConfig(owner string, repo string) (cfg *captainConfig, err error) {
	cfg = &captainConfig{}

	client := getGithubClient()
	fileContent, _, resp, err := client.Repositories.GetContents(
		owner,
		repo, ".captain.conf", &github.RepositoryContentGetOptions{})

	if err != nil && resp.StatusCode == 404 {
		err = nil
		fileContent = nil
	} else if err != nil {
		return nil, err
	}

	if err == nil && fileContent != nil {
		str, _ := base64.StdEncoding.DecodeString(*fileContent.Content)
		err = parseCaptainConf(str, cfg)
	}

	return
}

func getCaptainPlugin(owner string, repo string, pluginName string) (data []byte, err error) {
	data, err = Asset(pluginName + ".js")

	if err == nil {
		return
	}

	client := getGithubClient()
	fileContent, _, _, err := client.Repositories.GetContents(
		owner,
		repo, "plugins/"+pluginName+".js", &github.RepositoryContentGetOptions{})

	if err != nil {
		return nil, err
	}

	if err == nil && fileContent != nil {
		data = []byte(*fileContent.Content)
	}

	return
}
<commit_msg>Error logs<commit_after>package main

import (
	"encoding/base64"
	"encoding/json"
	"fmt"

	"github.com/orktes/captainhub/Godeps/_workspace/src/github.com/google/go-github/github"
)

type captainConfigPlugin struct {
	Name   string                 `json:"name"`
	Config map[string]interface{} `json:"config"`
}

type captainConfig struct {
	Plugins []captainConfigPlugin `json:"plugins"`
}

func parseCaptainConf(content []byte, cfg *captainConfig) (err error) {
	return json.Unmarshal(content, cfg)
}

func getCaptainConfig(owner string, repo string) (cfg *captainConfig, err error) {
	cfg = &captainConfig{}

	client := getGithubClient()
	fileContent, _, resp, err := client.Repositories.GetContents(
		owner,
		repo, ".captain.conf", &github.RepositoryContentGetOptions{})

	if err != nil && resp.StatusCode == 404 {
		if err != nil {
			fmt.Printf("Could not load .captain.conf: %s %d\n", err.Error(), resp.StatusCode)
		} else {
			fmt.Printf("Could not load .captain.conf %d\n", resp.StatusCode)
		}
		err = nil
		fileContent = nil
	} else if err != nil {
		return nil, err
	}

	if err == nil && fileContent != nil {
		str, _ := base64.StdEncoding.DecodeString(*fileContent.Content)
		err = parseCaptainConf(str, cfg)
	}

	return
}

func getCaptainPlugin(owner string, repo string, pluginName string) (data []byte, err error) {
	data, err = Asset(pluginName + ".js")

	if err == nil {
		return
	}

	client := getGithubClient()
	fileContent, _, _, err := client.Repositories.GetContents(
		owner,
		repo, "plugins/"+pluginName+".js", &github.RepositoryContentGetOptions{})

	if err != nil {
		return nil, err
	}

	if err == nil && fileContent != nil {
		data = []byte(*fileContent.Content)
	}

	return
}
<|endoftext|>


<commit_before>package config

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"os/user"
	"path/filepath"
	"strconv"
	"strings"
)

type Settings struct {
	Token      string `json:"token"`
	ProjectId  string `json:"project_id"`
	Host       string `json:"host"`
	Protocol   string `json:"protocol"`
	Port       int    `json:"port"`
	ApiVersion string `json:"api_version"`
}

var (
	presets = map[string]Settings{
		"worker": Settings{Protocol: "https", Port: 443, ApiVersion: "1", Host: "worker-aws-us-east-1.iron.io"},
		"mq":     Settings{Protocol: "https", Port: 443, ApiVersion: "1", Host: "mq-aws-us-east-1.iron.io"},
		"cache":  Settings{Protocol: "https", Port: 443, ApiVersion: "1", Host: "cache-aws-us-east-1.iron.io"},
	}
)

// fullProduct is like "iron_worker" and "iron_mq", not "worker" or "mq", to
// keep some flexibility in future.
func Config(fullProduct string) (settings Settings) {
	pair := strings.SplitN(fullProduct, "_", 2)
	if len(pair) != 2 {
		panic("Invalid product name, has to use prefix.")
	}
	family, product := pair[0], pair[1]

	base, found := presets[product]

	if !found {
		base = Settings{
			Protocol:   "https",
			Port:       443,
			ApiVersion: "1",
			Host:       product + "-aws-us-east-1.iron.io",
		}
	}

	(&base).globalConfig(family, product)
	(&base).globalEnv(family, product)
	(&base).productEnv(family, product)
	(&base).localConfig(family, product)

	return base
}

func (s *Settings) globalConfig(family, product string) {
	if u, err := user.Current(); err == nil {
		path := filepath.Join(u.HomeDir, ".iron.json")
		s.UseConfigFile(family, product, path)
	}
}

// The environment variables the scheme looks for are all of the same formula:
// the camel-cased product name is switched to an underscore (“IronWorker”
// becomes “iron_worker”) and converted to be all capital letters. For the
// global environment variables, “IRON” is used by itself. The value being
// loaded is then joined by an underscore to the name, and again capitalised.
// For example, to retrieve the OAuth token, the client looks for “IRON_TOKEN”.
func (s *Settings) globalEnv(family, product string) {
	eFamily := strings.ToUpper(family) + "_"
	s.commonEnv(eFamily)
}

// In the case of product-specific variables (which override global variables),
// it would be “IRON_WORKER_TOKEN” (for IronWorker).
func (s *Settings) productEnv(family, product string) {
	eProduct := strings.ToUpper(family) + "_" + strings.ToUpper(product) + "_"
	s.commonEnv(eProduct)
}

func (s *Settings) localConfig(family, product string) {
	s.UseConfigFile(family, product, "iron.json")
}

func (s *Settings) commonEnv(prefix string) {
	if token := os.Getenv(prefix + "TOKEN"); token != "" {
		s.Token = token
	}
	if pid := os.Getenv(prefix + "PROJECT_ID"); pid != "" {
		s.ProjectId = pid
	}
	if host := os.Getenv(prefix + "HOST"); host != "" {
		s.Host = host
	}
	if prot := os.Getenv(prefix + "PROTOCOL"); prot != "" {
		s.Protocol = prot
	}
	if port := os.Getenv(prefix + "PORT"); port != "" {
		n, err := strconv.ParseInt(port, 10, 32)
		if err != nil {
			panic(err)
		}
		s.Port = int(n)
	}
	if vers := os.Getenv(prefix + "API_VERSION"); vers != "" {
		s.ApiVersion = vers
	}
}

func (s *Settings) UseConfigFile(family, product, path string) {
	content, err := ioutil.ReadFile(path)
	if err != nil {
		return
	}

	data := map[string]interface{}{}
	err = json.Unmarshal(content, &data)
	if err != nil {
		panic("Invalid JSON in " + path + ": " + err.Error())
	}

	s.commonConfigMap(data)

	ipData, found := data[family+"_"+product]
	if found {
		pData := ipData.(map[string]interface{})
		s.commonConfigMap(pData)
	}
}

func (s *Settings) commonConfigMap(data map[string]interface{}) {
	if token, found := data["token"]; found {
		s.Token = token.(string)
	}
	if projectId, found := data["project_id"]; found {
		s.ProjectId = projectId.(string)
	}
	if host, found := data["host"]; found {
		s.Host = host.(string)
	}
	if prot, found := data["protocol"]; found {
		s.Protocol = prot.(string)
	}
	if port, found := data["port"]; found {
		s.Port = int(port.(float64))
	}
	if vers, found := data["api_version"]; found {
		s.ApiVersion = vers.(string)
	}
}
<commit_msg>fix version of worker<commit_after>package config

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"os/user"
	"path/filepath"
	"strconv"
	"strings"
)

type Settings struct {
	Token      string `json:"token"`
	ProjectId  string `json:"project_id"`
	Host       string `json:"host"`
	Protocol   string `json:"protocol"`
	Port       int    `json:"port"`
	ApiVersion string `json:"api_version"`
}

var (
	presets = map[string]Settings{
		"worker": Settings{Protocol: "https", Port: 443, ApiVersion: "2", Host: "worker-aws-us-east-1.iron.io"},
		"mq":     Settings{Protocol: "https", Port: 443, ApiVersion: "1", Host: "mq-aws-us-east-1.iron.io"},
		"cache":  Settings{Protocol: "https", Port: 443, ApiVersion: "1", Host: "cache-aws-us-east-1.iron.io"},
	}
)

// fullProduct is like "iron_worker" and "iron_mq", not "worker" or "mq", to
// keep some flexibility in future.
func Config(fullProduct string) (settings Settings) {
	pair := strings.SplitN(fullProduct, "_", 2)
	if len(pair) != 2 {
		panic("Invalid product name, has to use prefix.")
	}
	family, product := pair[0], pair[1]

	base, found := presets[product]

	if !found {
		base = Settings{
			Protocol:   "https",
			Port:       443,
			ApiVersion: "1",
			Host:       product + "-aws-us-east-1.iron.io",
		}
	}

	(&base).globalConfig(family, product)
	(&base).globalEnv(family, product)
	(&base).productEnv(family, product)
	(&base).localConfig(family, product)

	return base
}

func (s *Settings) globalConfig(family, product string) {
	if u, err := user.Current(); err == nil {
		path := filepath.Join(u.HomeDir, ".iron.json")
		s.UseConfigFile(family, product, path)
	}
}

// The environment variables the scheme looks for are all of the same formula:
// the camel-cased product name is switched to an underscore (“IronWorker”
// becomes “iron_worker”) and converted to be all capital letters. For the
// global environment variables, “IRON” is used by itself. The value being
// loaded is then joined by an underscore to the name, and again capitalised.
// For example, to retrieve the OAuth token, the client looks for “IRON_TOKEN”.
func (s *Settings) globalEnv(family, product string) {
	eFamily := strings.ToUpper(family) + "_"
	s.commonEnv(eFamily)
}

// In the case of product-specific variables (which override global variables),
// it would be “IRON_WORKER_TOKEN” (for IronWorker).
func (s *Settings) productEnv(family, product string) {
	eProduct := strings.ToUpper(family) + "_" + strings.ToUpper(product) + "_"
	s.commonEnv(eProduct)
}

func (s *Settings) localConfig(family, product string) {
	s.UseConfigFile(family, product, "iron.json")
}

func (s *Settings) commonEnv(prefix string) {
	if token := os.Getenv(prefix + "TOKEN"); token != "" {
		s.Token = token
	}
	if pid := os.Getenv(prefix + "PROJECT_ID"); pid != "" {
		s.ProjectId = pid
	}
	if host := os.Getenv(prefix + "HOST"); host != "" {
		s.Host = host
	}
	if prot := os.Getenv(prefix + "PROTOCOL"); prot != "" {
		s.Protocol = prot
	}
	if port := os.Getenv(prefix + "PORT"); port != "" {
		n, err := strconv.ParseInt(port, 10, 32)
		if err != nil {
			panic(err)
		}
		s.Port = int(n)
	}
	if vers := os.Getenv(prefix + "API_VERSION"); vers != "" {
		s.ApiVersion = vers
	}
}

func (s *Settings) UseConfigFile(family, product, path string) {
	content, err := ioutil.ReadFile(path)
	if err != nil {
		return
	}

	data := map[string]interface{}{}
	err = json.Unmarshal(content, &data)
	if err != nil {
		panic("Invalid JSON in " + path + ": " + err.Error())
	}

	s.commonConfigMap(data)

	ipData, found := data[family+"_"+product]
	if found {
		pData := ipData.(map[string]interface{})
		s.commonConfigMap(pData)
	}
}

func (s *Settings) commonConfigMap(data map[string]interface{}) {
	if token, found := data["token"]; found {
		s.Token = token.(string)
	}
	if projectId, found := data["project_id"]; found {
		s.ProjectId = projectId.(string)
	}
	if host, found := data["host"]; found {
		s.Host = host.(string)
	}
	if prot, found := data["protocol"]; found {
		s.Protocol = prot.(string)
	}
	if port, found := data["port"]; found {
		s.Port = int(port.(float64))
	}
	if vers, found := data["api_version"]; found {
		s.ApiVersion = vers.(string)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"net"
	"os"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/BurntSushi/toml"
	"github.com/kelseyhightower/confd/backends"
	"github.com/kelseyhightower/confd/log"
	"github.com/kelseyhightower/confd/resource/template"
)

var (
	configFile        = ""
	defaultConfigFile = "/etc/confd/confd.toml"
	backend           string
	clientCaKeys      string
	clientCert        string
	clientKey         string
	confdir           string
	config            Config // holds the global confd config.
	debug             bool
	interval          int
	keepStageFile     bool
	nodes             Nodes
	noop              bool
	onetime           bool
	prefix            string
	printVersion      bool
	quiet             bool
	scheme            string
	srvDomain         string
	templateConfig    template.Config
	backendsConfig    backends.Config
	verbose           bool
	watch             bool
)

// A Config structure is used to configure confd.
type Config struct {
	Backend      string   `toml:"backend"`
	BackendNodes []string `toml:"nodes"`
	ClientCaKeys string   `toml:"client_cakeys"`
	ClientCert   string   `toml:"client_cert"`
	ClientKey    string   `toml:"client_key"`
	ConfDir      string   `toml:"confdir"`
	Debug        bool     `toml:"debug"`
	Interval     int      `toml:"interval"`
	Noop         bool     `toml:"noop"`
	Prefix       string   `toml:"prefix"`
	Quiet        bool     `toml:"quiet"`
	SRVDomain    string   `toml:"srv_domain"`
	Scheme       string   `toml:"scheme"`
	Verbose      bool     `toml:"verbose"`
	Watch        bool     `toml:"watch"`
}

func init() {
	flag.StringVar(&backend, "backend", "etcd", "backend to use")
	flag.StringVar(&clientCaKeys, "client-ca-keys", "", "client ca keys")
	flag.StringVar(&clientCert, "client-cert", "", "the client cert")
	flag.StringVar(&clientKey, "client-key", "", "the client key")
	flag.StringVar(&confdir, "confdir", "/etc/confd", "confd conf directory")
	flag.StringVar(&configFile, "config-file", "", "the confd config file")
	flag.BoolVar(&debug, "debug", false, "enable debug logging")
	flag.IntVar(&interval, "interval", 600, "backend polling interval")
	flag.BoolVar(&keepStageFile, "keep-stage-file", false, "keep staged files")
	flag.Var(&nodes, "node", "list of backend nodes")
	flag.BoolVar(&noop, "noop", false, "only show pending changes")
	flag.BoolVar(&onetime, "onetime", false, "run once and exit")
	flag.StringVar(&prefix, "prefix", "/", "key path prefix")
	flag.BoolVar(&printVersion, "version", false, "print version and exit")
	flag.BoolVar(&quiet, "quiet", false, "enable quiet logging")
	flag.StringVar(&scheme, "scheme", "http", "the backend URI scheme (http or https)")
	flag.StringVar(&srvDomain, "srv-domain", "", "the name of the resource record")
	flag.BoolVar(&verbose, "verbose", false, "enable verbose logging")
	flag.BoolVar(&watch, "watch", false, "enable watch support")
}

// initConfig initializes the confd configuration by first setting defaults,
// then overriding setting from the confd config file, and finally overriding
// settings from flags set on the command line.
// It returns an error if any.
func initConfig() error {
	if configFile == "" {
		if _, err := os.Stat(defaultConfigFile); !os.IsNotExist(err) {
			configFile = defaultConfigFile
		}
	}
	// Set defaults.
	config = Config{
		Backend:  "etcd",
		ConfDir:  "/etc/confd",
		Interval: 600,
		Prefix:   "/",
		Scheme:   "http",
	}
	// Update config from the TOML configuration file.
	if configFile == "" {
		log.Warning("Skipping confd config file.")
	} else {
		log.Debug("Loading " + configFile)
		configBytes, err := ioutil.ReadFile(configFile)
		if err != nil {
			return err
		}
		_, err = toml.Decode(string(configBytes), &config)
		if err != nil {
			return err
		}
	}
	// Update config from commandline flags.
	processFlags()

	// Configure logging.
	log.SetQuiet(config.Quiet)
	log.SetVerbose(config.Verbose)
	log.SetDebug(config.Debug)

	// Update BackendNodes from SRV records.
	if config.Backend != "env" && config.SRVDomain != "" {
		log.Info("SRV domain set to " + config.SRVDomain)
		srvNodes, err := getBackendNodesFromSRV(config.Backend, config.SRVDomain, config.Scheme)
		if err != nil {
			return errors.New("Cannot get nodes from SRV records " + err.Error())
		}
		config.BackendNodes = srvNodes
	}
	if len(config.BackendNodes) == 0 {
		switch config.Backend {
		case "consul":
			config.BackendNodes = []string{"127.0.0.1:8500"}
		case "etcd":
			peerstr := os.Getenv("ETCDCTL_PEERS")
			if len(peerstr) > 0 {
				config.BackendNodes = strings.Split(peerstr, ",")
			} else {
				config.BackendNodes = []string{"http://127.0.0.1:4001"}
			}
		case "redis":
			config.BackendNodes = []string{"127.0.0.1:6379"}
		}
	}
	// Initialize the storage client
	log.Notice("Backend set to " + config.Backend)

	if config.Watch {
		unsupportedBackends := map[string]bool{
			"zookeeper": true,
			"redis":     true,
		}

		if unsupportedBackends[config.Backend] {
			log.Notice("Watch is not supported for backend " + config.Backend + " exiting...")
			os.Exit(1)
		}
	}

	backendsConfig = backends.Config{
		Backend:      config.Backend,
		ClientCaKeys: config.ClientCaKeys,
		ClientCert:   config.ClientCert,
		ClientKey:    config.ClientKey,
		BackendNodes: config.BackendNodes,
		Scheme:       config.Scheme,
	}
	// Template configuration.
	templateConfig = template.Config{
		ConfDir:       config.ConfDir,
		ConfigDir:     filepath.Join(config.ConfDir, "conf.d"),
		KeepStageFile: keepStageFile,
		Noop:          config.Noop,
		Prefix:        config.Prefix,
		TemplateDir:   filepath.Join(config.ConfDir, "templates"),
	}
	return nil
}

func getBackendNodesFromSRV(backend, domain, scheme string) ([]string, error) {
	nodes := make([]string, 0)
	// Ignore the CNAME as we don't need it.
	_, addrs, err := net.LookupSRV(backend, "tcp", domain)
	if err != nil {
		return nodes, err
	}
	for _, srv := range addrs {
		host := strings.TrimRight(srv.Target, ".")
		port := strconv.FormatUint(uint64(srv.Port), 10)
		nodes = append(nodes, fmt.Sprintf("%s://%s", scheme, net.JoinHostPort(host, port)))
	}
	return nodes, nil
}

// processFlags iterates through each flag set on the command line and
// overrides corresponding configuration settings.
func processFlags() {
	flag.Visit(setConfigFromFlag)
}

func setConfigFromFlag(f *flag.Flag) {
	switch f.Name {
	case "backend":
		config.Backend = backend
	case "debug":
		config.Debug = debug
	case "client-cert":
		config.ClientCert = clientCert
	case "client-key":
		config.ClientKey = clientKey
	case "client-cakeys":
		config.ClientCaKeys = clientCaKeys
	case "confdir":
		config.ConfDir = confdir
	case "node":
		config.BackendNodes = nodes
	case "interval":
		config.Interval = interval
	case "noop":
		config.Noop = noop
	case "prefix":
		config.Prefix = prefix
	case "quiet":
		config.Quiet = quiet
	case "scheme":
		config.Scheme = scheme
	case "srv-domain":
		config.SRVDomain = srvDomain
	case "verbose":
		config.Verbose = verbose
	case "watch":
		config.Watch = watch
	}
}
<commit_msg>fix up --watch error output<commit_after>package main

import (
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"net"
	"os"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/BurntSushi/toml"
	"github.com/kelseyhightower/confd/backends"
	"github.com/kelseyhightower/confd/log"
	"github.com/kelseyhightower/confd/resource/template"
)

var (
	configFile        = ""
	defaultConfigFile = "/etc/confd/confd.toml"
	backend           string
	clientCaKeys      string
	clientCert        string
	clientKey         string
	confdir           string
	config            Config // holds the global confd config.
	debug             bool
	interval          int
	keepStageFile     bool
	nodes             Nodes
	noop              bool
	onetime           bool
	prefix            string
	printVersion      bool
	quiet             bool
	scheme            string
	srvDomain         string
	templateConfig    template.Config
	backendsConfig    backends.Config
	verbose           bool
	watch             bool
)

// A Config structure is used to configure confd.
type Config struct {
	Backend      string   `toml:"backend"`
	BackendNodes []string `toml:"nodes"`
	ClientCaKeys string   `toml:"client_cakeys"`
	ClientCert   string   `toml:"client_cert"`
	ClientKey    string   `toml:"client_key"`
	ConfDir      string   `toml:"confdir"`
	Debug        bool     `toml:"debug"`
	Interval     int      `toml:"interval"`
	Noop         bool     `toml:"noop"`
	Prefix       string   `toml:"prefix"`
	Quiet        bool     `toml:"quiet"`
	SRVDomain    string   `toml:"srv_domain"`
	Scheme       string   `toml:"scheme"`
	Verbose      bool     `toml:"verbose"`
	Watch        bool     `toml:"watch"`
}

func init() {
	flag.StringVar(&backend, "backend", "etcd", "backend to use")
	flag.StringVar(&clientCaKeys, "client-ca-keys", "", "client ca keys")
	flag.StringVar(&clientCert, "client-cert", "", "the client cert")
	flag.StringVar(&clientKey, "client-key", "", "the client key")
	flag.StringVar(&confdir, "confdir", "/etc/confd", "confd conf directory")
	flag.StringVar(&configFile, "config-file", "", "the confd config file")
	flag.BoolVar(&debug, "debug", false, "enable debug logging")
	flag.IntVar(&interval, "interval", 600, "backend polling interval")
	flag.BoolVar(&keepStageFile, "keep-stage-file", false, "keep staged files")
	flag.Var(&nodes, "node", "list of backend nodes")
	flag.BoolVar(&noop, "noop", false, "only show pending changes")
	flag.BoolVar(&onetime, "onetime", false, "run once and exit")
	flag.StringVar(&prefix, "prefix", "/", "key path prefix")
	flag.BoolVar(&printVersion, "version", false, "print version and exit")
	flag.BoolVar(&quiet, "quiet", false, "enable quiet logging")
	flag.StringVar(&scheme, "scheme", "http", "the backend URI scheme (http or https)")
	flag.StringVar(&srvDomain, "srv-domain", "", "the name of the resource record")
	flag.BoolVar(&verbose, "verbose", false, "enable verbose logging")
	flag.BoolVar(&watch, "watch", false, "enable watch support")
}

// initConfig initializes the confd configuration by first setting defaults,
// then overriding setting from the confd config file, and finally overriding
// settings from flags set on the command line.
// It returns an error if any.
func initConfig() error {
	if configFile == "" {
		if _, err := os.Stat(defaultConfigFile); !os.IsNotExist(err) {
			configFile = defaultConfigFile
		}
	}
	// Set defaults.
	config = Config{
		Backend:  "etcd",
		ConfDir:  "/etc/confd",
		Interval: 600,
		Prefix:   "/",
		Scheme:   "http",
	}
	// Update config from the TOML configuration file.
	if configFile == "" {
		log.Warning("Skipping confd config file.")
	} else {
		log.Debug("Loading " + configFile)
		configBytes, err := ioutil.ReadFile(configFile)
		if err != nil {
			return err
		}
		_, err = toml.Decode(string(configBytes), &config)
		if err != nil {
			return err
		}
	}
	// Update config from commandline flags.
	processFlags()

	// Configure logging.
	log.SetQuiet(config.Quiet)
	log.SetVerbose(config.Verbose)
	log.SetDebug(config.Debug)

	// Update BackendNodes from SRV records.
	if config.Backend != "env" && config.SRVDomain != "" {
		log.Info("SRV domain set to " + config.SRVDomain)
		srvNodes, err := getBackendNodesFromSRV(config.Backend, config.SRVDomain, config.Scheme)
		if err != nil {
			return errors.New("Cannot get nodes from SRV records " + err.Error())
		}
		config.BackendNodes = srvNodes
	}
	if len(config.BackendNodes) == 0 {
		switch config.Backend {
		case "consul":
			config.BackendNodes = []string{"127.0.0.1:8500"}
		case "etcd":
			peerstr := os.Getenv("ETCDCTL_PEERS")
			if len(peerstr) > 0 {
				config.BackendNodes = strings.Split(peerstr, ",")
			} else {
				config.BackendNodes = []string{"http://127.0.0.1:4001"}
			}
		case "redis":
			config.BackendNodes = []string{"127.0.0.1:6379"}
		}
	}
	// Initialize the storage client
	log.Notice("Backend set to " + config.Backend)

	if config.Watch {
		unsupportedBackends := map[string]bool{
			"zookeeper": true,
			"redis":     true,
		}

		if unsupportedBackends[config.Backend] {
			log.Notice(fmt.Sprintf("Watch is not supported for backend %s. Exiting...", config.Backend))
			os.Exit(1)
		}
	}

	backendsConfig = backends.Config{
		Backend:      config.Backend,
		ClientCaKeys: config.ClientCaKeys,
		ClientCert:   config.ClientCert,
		ClientKey:    config.ClientKey,
		BackendNodes: config.BackendNodes,
		Scheme:       config.Scheme,
	}
	// Template configuration.
	templateConfig = template.Config{
		ConfDir:       config.ConfDir,
		ConfigDir:     filepath.Join(config.ConfDir, "conf.d"),
		KeepStageFile: keepStageFile,
		Noop:          config.Noop,
		Prefix:        config.Prefix,
		TemplateDir:   filepath.Join(config.ConfDir, "templates"),
	}
	return nil
}

func getBackendNodesFromSRV(backend, domain, scheme string) ([]string, error) {
	nodes := make([]string, 0)
	// Ignore the CNAME as we don't need it.
	_, addrs, err := net.LookupSRV(backend, "tcp", domain)
	if err != nil {
		return nodes, err
	}
	for _, srv := range addrs {
		host := strings.TrimRight(srv.Target, ".")
		port := strconv.FormatUint(uint64(srv.Port), 10)
		nodes = append(nodes, fmt.Sprintf("%s://%s", scheme, net.JoinHostPort(host, port)))
	}
	return nodes, nil
}

// processFlags iterates through each flag set on the command line and
// overrides corresponding configuration settings.
func processFlags() {
	flag.Visit(setConfigFromFlag)
}

func setConfigFromFlag(f *flag.Flag) {
	switch f.Name {
	case "backend":
		config.Backend = backend
	case "debug":
		config.Debug = debug
	case "client-cert":
		config.ClientCert = clientCert
	case "client-key":
		config.ClientKey = clientKey
	case "client-cakeys":
		config.ClientCaKeys = clientCaKeys
	case "confdir":
		config.ConfDir = confdir
	case "node":
		config.BackendNodes = nodes
	case "interval":
		config.Interval = interval
	case "noop":
		config.Noop = noop
	case "prefix":
		config.Prefix = prefix
	case "quiet":
		config.Quiet = quiet
	case "scheme":
		config.Scheme = scheme
	case "srv-domain":
		config.SRVDomain = srvDomain
	case "verbose":
		config.Verbose = verbose
	case "watch":
		config.Watch = watch
	}
}
<|endoftext|>


<commit_before>package corbel

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

	"github.com/Sirupsen/logrus"
)

var (
	userAgent                string
	allowedEnvironments      []string
	allowedEndpoints         []string
	allowedJTWSigningMethods []string
)

// init defines constants that will be used later
func init() {
	userAgent = fmt.Sprintf("corbel-go/%s", Version)
	allowedEndpoints = []string{"iam", "oauth", "assets", "resources"}
	allowedJTWSigningMethods = []string{"HS256", "RSA"}
}

// Client is the struct that manages communication with the Corbel APIs.
type Client struct {
	// client is the HTTP client to communicate with the API.
	httpClient *http.Client

	// Endpoint is a structure that stores the uri for each resource
	Endpoints map[string]string

	// ClientName is the name that match the clientID
	// (Optional) The required information is the clientID
	ClientName string

	// ClientID is the application defined client on Corbel.
	ClientID string

	// ClientSecret is the application secret hash that match with clientID.
	ClientSecret string

	// ClientScopes are those scopes the client will ask for to the platform when building the client connection
	// ClientScopes is a string with the scopes delimited by spaces.
	ClientScopes string

	// ClientDomain is the SR domain where to make the operations using the provided credentials.
	// (Optional) Every clientID only maps to one SR domain.
	ClientDomain string

	// ClientJWTSigningMethod defines the signing method configured for the client.
	// Must match with the one configured on the platform since it will understand only that one.
	// Only allowed signing methods at the moment are: HS256 and RSA
	ClientJWTSigningMethod string

	// TokenExpirationTime define the amount of time in seconds that a token must be valid.
	// It must be lower than 3600 seconds, since is the imposed requisite from the platform.
	TokenExpirationTime uint64

	// UserAgent defines the UserAgent to send in the Headers for every request to the platform.
	UserAgent string

	// Token is the actual token to send as Authentication Bearer
	CurrentToken string

	// CurrentTokenExpiresAt is the unix time where the token will expire
	CurrentTokenExpiresAt int64

	// CurrentRefreshToken is the current refresh token received from the IAM service
	CurrentRefreshToken string

	// IAM endpoint struct
	IAM       *IAMService
	Resources *ResourcesService
	Assets    *AssetsService

	// Logger
	logger *logrus.Logger
}

// URLFor returns the formated url of the API using the actual url scheme
func (c *Client) URLFor(endpoint, uri string) string {
	return fmt.Sprintf("%s%s", c.Endpoints[endpoint], uri)
}

// Token returns the token to use as bearer. If the token has already expired
// it refresh it.
func (c *Client) Token() string {
	// if CurrentToken == "" then return it as is
	if c.CurrentToken == "" {
		return c.CurrentToken
	}
	// if we have CurrentToken check if already expired
	if c.CurrentTokenExpiresAt <= time.Now().Unix()*1000 {
		c.logger.Debug("refreshing token")
		if c.CurrentRefreshToken != "" {
			_ = c.IAM.RefreshToken()
		} else {
			_ = c.IAM.OauthToken()
		}
	}
	return c.CurrentToken
}

// DefaultClient return a client with most of its values set to the default ones
func DefaultClient(endpoints map[string]string, clientID, clientName, clientSecret, clientScopes, clientDomain string) (*Client, error) {
	return NewClient(nil, endpoints, clientID, clientName, clientSecret, clientScopes, clientDomain, "HS256", 3600, "info")
}

// NewClient returns a new Corbel API client.
// If a nil httpClient is provided, it will return a http.DefaultClient.
// If a empty environment is provided, it will use production as environment.
func NewClient(httpClient *http.Client, endpoints map[string]string, clientID, clientName, clientSecret, clientScopes, clientDomain, clientJWTSigningMethod string, tokenExpirationTime uint64, logLevel string) (*Client, error) {
	var thisClient *Client

	if httpClient == nil {
		httpClient = http.DefaultClient
	}

	if len(endpoints) == 0 {
		endpoints = map[string]string{"iam": "https://iam.bqws.io", "resources": "https://resources.bqws.io"}
	}

	// allowedJTWSigningMethods?
	if stringInSlice(allowedJTWSigningMethods, clientJWTSigningMethod) == false {
		return nil, errInvalidJWTSigningMethod
	}

	// incorrect Token Expiration Time?
	if tokenExpirationTime > 3600 || tokenExpirationTime == 0 {
		return nil, errInvalidTokenExpirationTime
	}

	// required parameters?
	if clientID == "" || clientSecret == "" {
		return nil, errMissingClientParams
	}

	thisClient = &Client{
		httpClient:             httpClient,
		Endpoints:              endpoints,
		ClientName:             clientName,
		ClientID:               clientID,
		ClientSecret:           clientSecret,
		ClientDomain:           clientDomain,
		ClientScopes:           clientScopes,
		ClientJWTSigningMethod: clientJWTSigningMethod,
		TokenExpirationTime:    tokenExpirationTime * 1000,
		UserAgent:              userAgent,
	}

	thisClient.IAM = &IAMService{client: thisClient}
	thisClient.Resources = &ResourcesService{client: thisClient}
	thisClient.Assets = &AssetsService{client: thisClient}

	level, err := logrus.ParseLevel(logLevel)
	if err != nil {
		return nil, errInvalidLogLevel
	}
	thisClient.logger = logrus.New()
	thisClient.logger.Level = level

	return thisClient, nil
}
<commit_msg>Added a public LogLevel property. Thus, we can share the log level between corbel clients.<commit_after>package corbel

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

	"github.com/Sirupsen/logrus"
)

var (
	userAgent                string
	allowedEnvironments      []string
	allowedEndpoints         []string
	allowedJTWSigningMethods []string
)

// init defines constants that will be used later
func init() {
	userAgent = fmt.Sprintf("corbel-go/%s", Version)
	allowedEndpoints = []string{"iam", "oauth", "assets", "resources"}
	allowedJTWSigningMethods = []string{"HS256", "RSA"}
}

// Client is the struct that manages communication with the Corbel APIs.
type Client struct {
	// client is the HTTP client to communicate with the API.
	httpClient *http.Client

	// Endpoint is a structure that stores the uri for each resource
	Endpoints map[string]string

	// ClientName is the name that match the clientID
	// (Optional) The required information is the clientID
	ClientName string

	// ClientID is the application defined client on Corbel.
	ClientID string

	// ClientSecret is the application secret hash that match with clientID.
	ClientSecret string

	// ClientScopes are those scopes the client will ask for to the platform when building the client connection
	// ClientScopes is a string with the scopes delimited by spaces.
	ClientScopes string

	// ClientDomain is the SR domain where to make the operations using the provided credentials.
	// (Optional) Every clientID only maps to one SR domain.
	ClientDomain string

	// ClientJWTSigningMethod defines the signing method configured for the client.
	// Must match with the one configured on the platform since it will understand only that one.
	// Only allowed signing methods at the moment are: HS256 and RSA
	ClientJWTSigningMethod string

	// TokenExpirationTime define the amount of time in seconds that a token must be valid.
	// It must be lower than 3600 seconds, since is the imposed requisite from the platform.
	TokenExpirationTime uint64

	// UserAgent defines the UserAgent to send in the Headers for every request to the platform.
	UserAgent string

	// Token is the actual token to send as Authentication Bearer
	CurrentToken string

	// CurrentTokenExpiresAt is the unix time where the token will expire
	CurrentTokenExpiresAt int64

	// CurrentRefreshToken is the current refresh token received from the IAM service
	CurrentRefreshToken string

	// IAM endpoint struct
	IAM       *IAMService
	Resources *ResourcesService
	Assets    *AssetsService

	// Logger
	logger *logrus.Logger

	// LogLevel for the logger.
	LogLevel string
}

// URLFor returns the formated url of the API using the actual url scheme
func (c *Client) URLFor(endpoint, uri string) string {
	return fmt.Sprintf("%s%s", c.Endpoints[endpoint], uri)
}

// Token returns the token to use as bearer. If the token has already expired
// it refresh it.
func (c *Client) Token() string {
	// if CurrentToken == "" then return it as is
	if c.CurrentToken == "" {
		return c.CurrentToken
	}
	// if we have CurrentToken check if already expired
	if c.CurrentTokenExpiresAt <= time.Now().Unix()*1000 {
		c.logger.Debug("refreshing token")
		if c.CurrentRefreshToken != "" {
			_ = c.IAM.RefreshToken()
		} else {
			_ = c.IAM.OauthToken()
		}
	}
	return c.CurrentToken
}

// DefaultClient return a client with most of its values set to the default ones
func DefaultClient(endpoints map[string]string, clientID, clientName, clientSecret, clientScopes, clientDomain string) (*Client, error) {
	return NewClient(nil, endpoints, clientID, clientName, clientSecret, clientScopes, clientDomain, "HS256", 3600, "info")
}

// NewClient returns a new Corbel API client.
// If a nil httpClient is provided, it will return a http.DefaultClient.
// If a empty environment is provided, it will use production as environment.
func NewClient(httpClient *http.Client, endpoints map[string]string, clientID, clientName, clientSecret, clientScopes, clientDomain, clientJWTSigningMethod string, tokenExpirationTime uint64, logLevel string) (*Client, error) {
	var thisClient *Client

	if httpClient == nil {
		httpClient = http.DefaultClient
	}

	if len(endpoints) == 0 {
		endpoints = map[string]string{"iam": "https://iam.bqws.io", "resources": "https://resources.bqws.io"}
	}

	// allowedJTWSigningMethods?
	if stringInSlice(allowedJTWSigningMethods, clientJWTSigningMethod) == false {
		return nil, errInvalidJWTSigningMethod
	}

	// incorrect Token Expiration Time?
	if tokenExpirationTime > 3600 || tokenExpirationTime == 0 {
		return nil, errInvalidTokenExpirationTime
	}

	// required parameters?
	if clientID == "" || clientSecret == "" {
		return nil, errMissingClientParams
	}

	thisClient = &Client{
		httpClient:             httpClient,
		Endpoints:              endpoints,
		ClientName:             clientName,
		ClientID:               clientID,
		ClientSecret:           clientSecret,
		ClientDomain:           clientDomain,
		ClientScopes:           clientScopes,
		ClientJWTSigningMethod: clientJWTSigningMethod,
		TokenExpirationTime:    tokenExpirationTime * 1000,
		UserAgent:              userAgent,
	}

	thisClient.IAM = &IAMService{client: thisClient}
	thisClient.Resources = &ResourcesService{client: thisClient}
	thisClient.Assets = &AssetsService{client: thisClient}

	level, err := logrus.ParseLevel(logLevel)
	if err != nil {
		return nil, errInvalidLogLevel
	}
	thisClient.logger = logrus.New()
	thisClient.logger.Level = level
	thisClient.LogLevel = logLevel

	return thisClient, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"strings"

	log "github.com/Sirupsen/logrus"
	"github.com/docker/docker/pkg/namesgenerator"
	humanize "github.com/dustin/go-humanize"
)

var cmdCreate = &Command{
	Exec:        runCreate,
	UsageLine:   "create [OPTIONS] IMAGE",
	Description: "Create a new server but do not start it",
	Help:        "Create a new server but do not start it.",
	Examples: `
    $ scw create docker
    $ scw create 10GB
    $ scw create --bootscript=3.2.34 --env="boot=live rescue_image=http://j.mp/scaleway-ubuntu-trusty-tarball" 50GB
    $ scw inspect $(scw create 1GB --bootscript=rescue --volume=50GB)
    $ scw create $(scw tag my-snapshot my-image)
`,
}

func init() {
	cmdCreate.Flag.StringVar(&createName, []string{"-name"}, "", "Assign a name")
	cmdCreate.Flag.StringVar(&createBootscript, []string{"-bootscript"}, "", "Assign a bootscript")
	cmdCreate.Flag.BoolVar(&forceBootscript, []string{"-force-bootscript"}, false, "Do not attempt to resolve bootscript by name")
	cmdCreate.Flag.StringVar(&createEnv, []string{"e", "-env"}, "", "Provide metadata tags passed to initrd (i.e., boot=resue INITRD_DEBUG=1)")
	cmdCreate.Flag.StringVar(&createVolume, []string{"v", "-volume"}, "", "Attach additional volume (i.e., 50G)")
	cmdCreate.Flag.BoolVar(&createHelp, []string{"h", "-help"}, false, "Print usage")
}

// Flags
var createName string       // --name flag
var createBootscript string // --bootscript flag
var forceBootscript bool    // --force-bootscript flag
var createEnv string        // -e, --env flag
var createVolume string     // -v, --volume flag
var createHelp bool         // -h, --help flag

// CreateVolumeFromHumanSize create a new volume using the API from a human-readable size
func CreateVolumeFromHumanSize(cmd *Command, size string) (*string, error) {
	bytes, err := humanize.ParseBytes(size)
	if err != nil {
		return nil, err
	}

	var newVolume ScalewayVolumeDefinition
	newVolume.Name = size
	newVolume.Size = bytes
	newVolume.Type = "l_ssd"

	volumeID, err := cmd.API.PostVolume(newVolume)
	if err != nil {
		return nil, err
	}

	return &volumeID, nil
}

func createServer(cmd *Command, imageName string, name string, bootscript string, env string, additionalVolumes string) (string, error) {
	if name == "" {
		name = strings.Replace(namesgenerator.GetRandomName(0), "_", "-", -1)
	}

	var server ScalewayServerDefinition
	server.Volumes = make(map[string]string)

	server.Tags = []string{}
	if env != "" {
		server.Tags = strings.Split(env, " ")
	}
	if additionalVolumes != "" {
		volumes := strings.Split(additionalVolumes, " ")
		for i := range volumes {
			volumeID, err := CreateVolumeFromHumanSize(cmd, volumes[i])
			if err != nil {
				return "", err
			}

			volumeIDx := fmt.Sprintf("%d", i+1)
			server.Volumes[volumeIDx] = *volumeID
		}
	}
	server.Name = name
	if bootscript != "" {
		if !forceBootscript {
			bootscript = cmd.GetBootscript(bootscript)
		}
		server.Bootscript = &bootscript
	}

	_, err := humanize.ParseBytes(imageName)
	if err == nil {
		// Create a new root volume
		volumeID, err := CreateVolumeFromHumanSize(cmd, imageName)
		if err != nil {
			return "", err
		}
		server.Volumes["0"] = *volumeID
	} else {
		// Use an existing image
		// FIXME: handle snapshots
		image := cmd.GetImage(imageName)
		server.Image = &image
	}

	serverID, err := cmd.API.PostServer(server)
	if err != nil {
		return "", nil
	}

	return serverID, nil

}

func runCreate(cmd *Command, args []string) {
	if createHelp {
		cmd.PrintUsage()
	}
	if len(args) != 1 {
		cmd.PrintShortUsage()
	}

	serverID, err := createServer(cmd, args[0], createName, createBootscript, createEnv, createVolume)

	if err != nil {
		log.Fatalf("Failed to create server: %v", err)
	}

	fmt.Println(serverID)
}
<commit_msg>Revert "Added ability to force a bootscript in 'scw create'. Fix #53"<commit_after>package main

import (
	"fmt"
	"strings"

	log "github.com/Sirupsen/logrus"
	"github.com/docker/docker/pkg/namesgenerator"
	humanize "github.com/dustin/go-humanize"
)

var cmdCreate = &Command{
	Exec:        runCreate,
	UsageLine:   "create [OPTIONS] IMAGE",
	Description: "Create a new server but do not start it",
	Help:        "Create a new server but do not start it.",
	Examples: `
    $ scw create docker
    $ scw create 10GB
    $ scw create --bootscript=3.2.34 --env="boot=live rescue_image=http://j.mp/scaleway-ubuntu-trusty-tarball" 50GB
    $ scw inspect $(scw create 1GB --bootscript=rescue --volume=50GB)
    $ scw create $(scw tag my-snapshot my-image)
`,
}

func init() {
	cmdCreate.Flag.StringVar(&createName, []string{"-name"}, "", "Assign a name")
	cmdCreate.Flag.StringVar(&createBootscript, []string{"-bootscript"}, "", "Assign a bootscript")
	cmdCreate.Flag.StringVar(&createEnv, []string{"e", "-env"}, "", "Provide metadata tags passed to initrd (i.e., boot=resue INITRD_DEBUG=1)")
	cmdCreate.Flag.StringVar(&createVolume, []string{"v", "-volume"}, "", "Attach additional volume (i.e., 50G)")
	cmdCreate.Flag.BoolVar(&createHelp, []string{"h", "-help"}, false, "Print usage")
}

// Flags
var createName string       // --name flag
var createBootscript string // --bootscript flag
var createEnv string        // -e, --env flag
var createVolume string     // -v, --volume flag
var createHelp bool         // -h, --help flag

// CreateVolumeFromHumanSize create a new volume using the API from a human-readable size
func CreateVolumeFromHumanSize(cmd *Command, size string) (*string, error) {
	bytes, err := humanize.ParseBytes(size)
	if err != nil {
		return nil, err
	}

	var newVolume ScalewayVolumeDefinition
	newVolume.Name = size
	newVolume.Size = bytes
	newVolume.Type = "l_ssd"

	volumeID, err := cmd.API.PostVolume(newVolume)
	if err != nil {
		return nil, err
	}

	return &volumeID, nil
}

func createServer(cmd *Command, imageName string, name string, bootscript string, env string, additionalVolumes string) (string, error) {
	if name == "" {
		name = strings.Replace(namesgenerator.GetRandomName(0), "_", "-", -1)
	}

	var server ScalewayServerDefinition
	server.Volumes = make(map[string]string)

	server.Tags = []string{}
	if env != "" {
		server.Tags = strings.Split(env, " ")
	}
	if additionalVolumes != "" {
		volumes := strings.Split(additionalVolumes, " ")
		for i := range volumes {
			volumeID, err := CreateVolumeFromHumanSize(cmd, volumes[i])
			if err != nil {
				return "", err
			}

			volumeIDx := fmt.Sprintf("%d", i+1)
			server.Volumes[volumeIDx] = *volumeID
		}
	}
	server.Name = name
	if bootscript != "" {
		bootscript := cmd.GetBootscript(bootscript)
		server.Bootscript = &bootscript
	}

	_, err := humanize.ParseBytes(imageName)
	if err == nil {
		// Create a new root volume
		volumeID, err := CreateVolumeFromHumanSize(cmd, imageName)
		if err != nil {
			return "", err
		}
		server.Volumes["0"] = *volumeID
	} else {
		// Use an existing image
		// FIXME: handle snapshots
		image := cmd.GetImage(imageName)
		server.Image = &image
	}

	serverID, err := cmd.API.PostServer(server)
	if err != nil {
		return "", nil
	}

	return serverID, nil

}

func runCreate(cmd *Command, args []string) {
	if createHelp {
		cmd.PrintUsage()
	}
	if len(args) != 1 {
		cmd.PrintShortUsage()
	}

	serverID, err := createServer(cmd, args[0], createName, createBootscript, createEnv, createVolume)

	if err != nil {
		log.Fatalf("Failed to create server: %v", err)
	}

	fmt.Println(serverID)
}
<|endoftext|>


<commit_before>package revel

import (
	"bytes"
	"code.google.com/p/go.net/websocket"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"regexp"
	"strings"
)

type TestSuite struct {
	Client       *http.Client
	Response     *http.Response
	ResponseBody []byte
	Session      Session
}

var TestSuites []interface{} // Array of structs that embed TestSuite

// NewTestSuite returns an initialized TestSuite ready for use. It is invoked
// by the test harness to initialize the embedded field in application tests.
func NewTestSuite() TestSuite {
	jar, _ := cookiejar.New(nil)
	return TestSuite{
		Client:  &http.Client{Jar: jar},
		Session: make(Session),
	}
}

// Return the address and port of the server, e.g. "127.0.0.1:8557"
func (t *TestSuite) Host() string {
	if Server.Addr[0] == ':' {
		return "127.0.0.1" + Server.Addr
	}
	return Server.Addr
}

// Return the base http URL of the server, e.g. "http://127.0.0.1:8557"
func (t *TestSuite) BaseUrl() string {
	return "http://" + t.Host()
}

// Return the base websocket URL of the server, e.g. "ws://127.0.0.1:8557"
func (t *TestSuite) WebSocketUrl() string {
	return "ws://" + t.Host()
}

// Issue a GET request to the given path and store the result in Request and
// RequestBody.
func (t *TestSuite) Get(path string) {
	req, err := http.NewRequest("GET", t.BaseUrl()+path, nil)
	if err != nil {
		panic(err)
	}
	t.MakeRequestSession(req)
}

// Issue a POST request to the given path, sending the given Content-Type and
// data, and store the result in Request and RequestBody.  "data" may be nil.
func (t *TestSuite) Post(path string, contentType string, reader io.Reader) {
	req, err := http.NewRequest("POST", t.BaseUrl()+path, reader)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Content-Type", contentType)
	t.MakeRequestSession(req)
}

// Issue a POST request to the given path as a form post of the given key and
// values, and store the result in Request and RequestBody.
func (t *TestSuite) PostForm(path string, data url.Values) {
	t.Post(path, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
}

// Issue any request and read the response. If successful, the caller may
// examine the Response and ResponseBody properties. Session data will be
// added to the request cookies for you.
func (t *TestSuite) MakeRequestSession(req *http.Request) {
	req.AddCookie(t.Session.cookie())
	t.MakeRequest(req)
}

// Issue any request and read the response. If successful, the caller may
// examine the Response and ResponseBody properties. You will need to
// manage session / cookie data manually
func (t *TestSuite) MakeRequest(req *http.Request) {
	var err error
	if t.Response, err = t.Client.Do(req); err != nil {
		panic(err)
	}
	if t.ResponseBody, err = ioutil.ReadAll(t.Response.Body); err != nil {
		panic(err)
	}

	// Look for a session cookie in the response and parse it.
	sessionCookieName := t.Session.cookie().Name
	for _, cookie := range t.Client.Jar.Cookies(req.URL) {
		if cookie.Name == sessionCookieName {
			t.Session = getSessionFromCookie(cookie)
			break
		}
	}
}

// Create a websocket connection to the given path and return the connection
func (t *TestSuite) WebSocket(path string) *websocket.Conn {
	origin := t.BaseUrl() + "/"
	url := t.WebSocketUrl() + path
	ws, err := websocket.Dial(url, "", origin)
	if err != nil {
		panic(err)
	}
	return ws
}

func (t *TestSuite) AssertOk() {
	t.AssertStatus(http.StatusOK)
}

func (t *TestSuite) AssertNotFound() {
	t.AssertStatus(http.StatusNotFound)
}

func (t *TestSuite) AssertStatus(status int) {
	if t.Response.StatusCode != status {
		panic(fmt.Errorf("Status: (expected) %d != %d (actual)", status, t.Response.StatusCode))
	}
}

func (t *TestSuite) AssertContentType(contentType string) {
	t.AssertHeader("Content-Type", contentType)
}

func (t *TestSuite) AssertHeader(name, value string) {
	actual := t.Response.Header.Get(name)
	if actual != value {
		panic(fmt.Errorf("Header %s: (expected) %s != %s (actual)", name, value, actual))
	}
}

func (t *TestSuite) AssertEqual(expected, actual interface{}) {
	if !Equal(expected, actual) {
		panic(fmt.Errorf("(expected) %v != %v (actual)", expected, actual))
	}
}

func (t *TestSuite) Assert(exp bool) {
	t.Assertf(exp, "Assertion failed")
}

func (t *TestSuite) Assertf(exp bool, formatStr string, args ...interface{}) {
	if !exp {
		panic(fmt.Errorf(formatStr, args))
	}
}

// Assert that the response contains the given string.
func (t *TestSuite) AssertContains(s string) {
	if !bytes.Contains(t.ResponseBody, []byte(s)) {
		panic(fmt.Errorf("Assertion failed. Expected response to contain %s", s))
	}
}

// Assert that the response matches the given regular expression.BUG
func (t *TestSuite) AssertContainsRegex(regex string) {
	r := regexp.MustCompile(regex)

	if !r.Match(t.ResponseBody) {
		panic(fmt.Errorf("Assertion failed. Expected response to match regexp %s", regex))
	}
}
<commit_msg>Fix Variable Argument Error in Assertf<commit_after>package revel

import (
	"bytes"
	"code.google.com/p/go.net/websocket"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"regexp"
	"strings"
)

type TestSuite struct {
	Client       *http.Client
	Response     *http.Response
	ResponseBody []byte
	Session      Session
}

var TestSuites []interface{} // Array of structs that embed TestSuite

// NewTestSuite returns an initialized TestSuite ready for use. It is invoked
// by the test harness to initialize the embedded field in application tests.
func NewTestSuite() TestSuite {
	jar, _ := cookiejar.New(nil)
	return TestSuite{
		Client:  &http.Client{Jar: jar},
		Session: make(Session),
	}
}

// Return the address and port of the server, e.g. "127.0.0.1:8557"
func (t *TestSuite) Host() string {
	if Server.Addr[0] == ':' {
		return "127.0.0.1" + Server.Addr
	}
	return Server.Addr
}

// Return the base http URL of the server, e.g. "http://127.0.0.1:8557"
func (t *TestSuite) BaseUrl() string {
	return "http://" + t.Host()
}

// Return the base websocket URL of the server, e.g. "ws://127.0.0.1:8557"
func (t *TestSuite) WebSocketUrl() string {
	return "ws://" + t.Host()
}

// Issue a GET request to the given path and store the result in Request and
// RequestBody.
func (t *TestSuite) Get(path string) {
	req, err := http.NewRequest("GET", t.BaseUrl()+path, nil)
	if err != nil {
		panic(err)
	}
	t.MakeRequestSession(req)
}

// Issue a POST request to the given path, sending the given Content-Type and
// data, and store the result in Request and RequestBody.  "data" may be nil.
func (t *TestSuite) Post(path string, contentType string, reader io.Reader) {
	req, err := http.NewRequest("POST", t.BaseUrl()+path, reader)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Content-Type", contentType)
	t.MakeRequestSession(req)
}

// Issue a POST request to the given path as a form post of the given key and
// values, and store the result in Request and RequestBody.
func (t *TestSuite) PostForm(path string, data url.Values) {
	t.Post(path, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
}

// Issue any request and read the response. If successful, the caller may
// examine the Response and ResponseBody properties. Session data will be
// added to the request cookies for you.
func (t *TestSuite) MakeRequestSession(req *http.Request) {
	req.AddCookie(t.Session.cookie())
	t.MakeRequest(req)
}

// Issue any request and read the response. If successful, the caller may
// examine the Response and ResponseBody properties. You will need to
// manage session / cookie data manually
func (t *TestSuite) MakeRequest(req *http.Request) {
	var err error
	if t.Response, err = t.Client.Do(req); err != nil {
		panic(err)
	}
	if t.ResponseBody, err = ioutil.ReadAll(t.Response.Body); err != nil {
		panic(err)
	}

	// Look for a session cookie in the response and parse it.
	sessionCookieName := t.Session.cookie().Name
	for _, cookie := range t.Client.Jar.Cookies(req.URL) {
		if cookie.Name == sessionCookieName {
			t.Session = getSessionFromCookie(cookie)
			break
		}
	}
}

// Create a websocket connection to the given path and return the connection
func (t *TestSuite) WebSocket(path string) *websocket.Conn {
	origin := t.BaseUrl() + "/"
	url := t.WebSocketUrl() + path
	ws, err := websocket.Dial(url, "", origin)
	if err != nil {
		panic(err)
	}
	return ws
}

func (t *TestSuite) AssertOk() {
	t.AssertStatus(http.StatusOK)
}

func (t *TestSuite) AssertNotFound() {
	t.AssertStatus(http.StatusNotFound)
}

func (t *TestSuite) AssertStatus(status int) {
	if t.Response.StatusCode != status {
		panic(fmt.Errorf("Status: (expected) %d != %d (actual)", status, t.Response.StatusCode))
	}
}

func (t *TestSuite) AssertContentType(contentType string) {
	t.AssertHeader("Content-Type", contentType)
}

func (t *TestSuite) AssertHeader(name, value string) {
	actual := t.Response.Header.Get(name)
	if actual != value {
		panic(fmt.Errorf("Header %s: (expected) %s != %s (actual)", name, value, actual))
	}
}

func (t *TestSuite) AssertEqual(expected, actual interface{}) {
	if !Equal(expected, actual) {
		panic(fmt.Errorf("(expected) %v != %v (actual)", expected, actual))
	}
}

func (t *TestSuite) Assert(exp bool) {
	t.Assertf(exp, "Assertion failed")
}

func (t *TestSuite) Assertf(exp bool, formatStr string, args ...interface{}) {
	if !exp {
		panic(fmt.Errorf(formatStr, args...))
	}
}

// Assert that the response contains the given string.
func (t *TestSuite) AssertContains(s string) {
	if !bytes.Contains(t.ResponseBody, []byte(s)) {
		panic(fmt.Errorf("Assertion failed. Expected response to contain %s", s))
	}
}

// Assert that the response matches the given regular expression.BUG
func (t *TestSuite) AssertContainsRegex(regex string) {
	r := regexp.MustCompile(regex)

	if !r.Match(t.ResponseBody) {
		panic(fmt.Errorf("Assertion failed. Expected response to match regexp %s", regex))
	}
}
<|endoftext|>


<commit_before>package quic

const QUIC_VERSION = uint32('Q'<<24 | '0'<<16 | '2'<<8 | '5') // temporally

type PublicFlagType byte

const (
	CONTAIN_QUIC_VERSION        PublicFlagType = 0x01
	PUBLIC_RESET                               = 0x02
	CONNECTION_ID_LENGTH_MASK                  = 0x0c
	CONNECTION_ID_LENGTH_8                     = 0x0c
	CONNECTION_ID_LENGTH_4                     = 0x08
	CONNECTION_ID_LENGTH_1                     = 0x04
	OMIT_CONNECTION_ID                         = 0x00
	SEQUENCE_NUMBER_LENGTH_MASK                = 0x30
	SEQUENCE_NUMBER_LENGTH_6                   = 0x30
	SEQUENCE_NUMBER_LENGTH_4                   = 0x20
	SEQUENCE_NUMBER_LENGTH_2                   = 0x10
	SEQUENCE_NUMBER_LENGTH_1                   = 0x00
	RESERVED                                   = 0xc0
)

type PrivateFlagType byte

const (
	FLAG_ENTROPY   PrivateFlagType = 0x01
	FLAG_FEC_GROUP                 = 0x02
	FLAG_FEC                       = 0x04
)

// Packet Header
/*
+--------+--------+--------+--------+--------+---    ---+
| Public |    Connection ID (0, 8, 32, or 64)    ...    | ->
|Flags(8)|      (variable length)                       |
+--------+--------+--------+--------+--------+---    ---+
    9       10       11        12
+--------+--------+--------+--------+
|      Quic Version (32)            | ->
|         (optional)                |
+--------+--------+--------+--------+
    13      14       15        16        17       18       19       20
+--------+--------+--------+--------+--------+--------+--------+--------+
|         Sequence Number (8, 16, 32, or 48)          |Private | FEC (8)|
|                         (variable length)           |Flags(8)|  (opt) |
+--------+--------+--------+--------+--------+--------+--------+--------+
*/

type PacketHeader struct {
	PublicFlags    PublicFlagType
	ConnectionID   uint64
	Version        uint32
	SequenceNumber uint64
	PrivateFlags   PrivateFlagType
	FEC            byte
}

func NewPacketHeader(connectionID uint64, version uint32, sequenceNumber uint64, privateFlags PrivateFlagType, fec byte) *PacketHeader {
	// TODO: flags should be passed from New...Packet()
	var publicFlags PublicFlagType = 0x00
	switch {
	case connectionID <= 0:
		publicFlags |= OMIT_CONNECTION_ID
	case connectionID <= 0xff:
		publicFlags |= CONNECTION_ID_LENGTH_1
	case connectionID <= 0xffffffff:
		publicFlags |= CONNECTION_ID_LENGTH_4
	case connectionID <= 0xffffffffffffffff:
		// This indicate public reset packet
		publicFlags |= CONNECTION_ID_LENGTH_8
	}

	if publicFlags&PUBLIC_RESET != PUBLIC_RESET {
		switch {
		case sequenceNumber <= 0xff:
			publicFlags |= SEQUENCE_NUMBER_LENGTH_1
		case sequenceNumber <= 0xffff:
			publicFlags |= SEQUENCE_NUMBER_LENGTH_2
		case sequenceNumber <= 0xffffffff:
			publicFlags |= SEQUENCE_NUMBER_LENGTH_4
		case sequenceNumber <= 0xffffffffffff:
			publicFlags |= SEQUENCE_NUMBER_LENGTH_6
		}

		// version negotiation packet is still considering?
		// private flags == FLAG_FEC indicate FEC packet
		// others indicate frame packet
	}

	ph := &PacketHeader{
		PublicFlags:    publicFlags,
		ConnectionID:   connectionID,
		Version:        version,
		SequenceNumber: sequenceNumber,
		PrivateFlags:   privateFlags,
		FEC:            fec,
	}
	return ph
}

func (ph *PacketHeader) Parse(data []byte) (err error) {
	index := 0
	ph.PublicFlags = PublicFlagType(data[index])

	switch ph.PublicFlags & CONNECTION_ID_LENGTH_MASK {
	case CONNECTION_ID_LENGTH_8:
		ph.ConnectionID = uint64(data[1]<<56 | data[2]<<48 | data[3]<<40 | data[4]<<32 | data[5]<<24 | data[6]<<16 | data[7]<<8 | data[8])
		index = 9
	case CONNECTION_ID_LENGTH_4:
		ph.ConnectionID = uint64(data[1]<<24 | data[2]<<16 | data[3]<<8 | data[4])
		index = 5
	case CONNECTION_ID_LENGTH_1:
		ph.ConnectionID = uint64(data[1])
		index = 2
	case OMIT_CONNECTION_ID:
		ph.ConnectionID = 0 // omitted
		index = 1
	}
	if ph.PublicFlags&PUBLIC_RESET != PUBLIC_RESET {
		if ph.PublicFlags&CONTAIN_QUIC_VERSION == CONTAIN_QUIC_VERSION {
			ph.Version = uint32(data[index]<<24 | data[index+1]<<16 | data[index+2]<<8 | data[index+3])
			index += 4
		}

		// TODO: parse sequence number
		switch ph.PublicFlags & SEQUENCE_NUMBER_LENGTH_MASK {
		case SEQUENCE_NUMBER_LENGTH_6:
			ph.SequenceNumber = uint64(data[index]<<40 | data[index+1]<<32 | data[index+2]<<24 | data[index+3]<<16 | data[index+4]<<8 | data[index+5])
			index += 6
		case SEQUENCE_NUMBER_LENGTH_4:
			ph.SequenceNumber = uint64(data[index]<<24 | data[index+1]<<16 | data[index+2]<<8 | data[index+3])
			index += 4
		case SEQUENCE_NUMBER_LENGTH_2:
			ph.SequenceNumber = uint64(data[index]<<8 | data[index+1])
			index += 2
		case SEQUENCE_NUMBER_LENGTH_1:
			ph.SequenceNumber = uint64(data[index])
			index += 1
		}

		ph.PrivateFlags = PrivateFlagType(data[index])
		if ph.PrivateFlags&FLAG_ENTROPY == FLAG_ENTROPY {
			// TODO: ?
		}
		if ph.PrivateFlags&FLAG_FEC_GROUP == FLAG_FEC_GROUP {
			ph.FEC = data[index]
		}
		if ph.PrivateFlags&FLAG_FEC == FLAG_FEC {
			//TODO: FEC packet
		}
	}
	return
}

func (ph *PacketHeader) GetWire() (wire []byte, err error) {
	// confirm variable length
	connectionIDLen := 0
	switch ph.PublicFlags & CONNECTION_ID_LENGTH_MASK {
	case CONNECTION_ID_LENGTH_8:
		connectionIDLen = 8
	case CONNECTION_ID_LENGTH_4:
		connectionIDLen = 4
	case CONNECTION_ID_LENGTH_1:
		connectionIDLen = 1
	case OMIT_CONNECTION_ID:
		//pass
	}

	versionLen := 0
	if ph.PublicFlags&0x01 > 0 {
		versionLen = 4
	}

	sequenceNumberLen := 1
	switch ph.PublicFlags & SEQUENCE_NUMBER_LENGTH_MASK {
	case SEQUENCE_NUMBER_LENGTH_6:
		sequenceNumberLen = 6
	case SEQUENCE_NUMBER_LENGTH_4:
		sequenceNumberLen = 4
	case SEQUENCE_NUMBER_LENGTH_2:
		sequenceNumberLen = 2
	case SEQUENCE_NUMBER_LENGTH_1:
		//pass
	}

	// deal with FEC part
	fecLen := 0
	if ph.PrivateFlags&FLAG_ENTROPY == FLAG_ENTROPY {
		// TODO: ?
	}
	if ph.PrivateFlags&FLAG_FEC_GROUP == FLAG_FEC_GROUP {
		fecLen = 1
	}
	if ph.PrivateFlags&FLAG_FEC == FLAG_FEC {
		//TODO: FEC packet
	}

	// pack to wire
	wire = make([]byte, 1+connectionIDLen+versionLen+sequenceNumberLen+1+fecLen)
	wire[0] = byte(ph.PublicFlags)
	index := 1
	for i := 0; i < connectionIDLen; i++ {
		wire[index+i] = byte(ph.ConnectionID >> byte(8*(connectionIDLen-i-1)))
	}
	index += connectionIDLen

	for i := 0; i < versionLen; i++ {
		wire[index+i] = byte(ph.Version >> byte(8*(versionLen-i-1)))
	}
	index += versionLen

	for i := 0; i < sequenceNumberLen; i++ {
		wire[index+i] = byte(ph.SequenceNumber >> byte(8*(sequenceNumberLen-i-1)))
	}
	index += sequenceNumberLen

	wire[index] = byte(ph.PrivateFlags)

	if fecLen > 0 {
		wire[index+1] = ph.FEC
	}

	return
}

func (ph *PacketHeader) String() (str string) {
	str = "Packet Header" // temporally
	return
}

type VersionNegotiationPacket struct {
	*PacketHeader
	Version uint32 //?
}

func NewVersionNegotiationPacket(version uint32) *VersionNegotiationPacket {
	//flag := CONTAIN_QUIC_VERSION
	// ph := NewPacketHeader(flag,)
	ph := &PacketHeader{} //temporally
	packet := &VersionNegotiationPacket{
		PacketHeader: ph,
		Version:      version,
	}
	return packet
}

func (packet *VersionNegotiationPacket) Parse(data []byte) (length int, err error) {
	// TODO: there are no detail on specification stil
	return
}

func (packet *VersionNegotiationPacket) GetWire() (wire []byte, err error) {
	// TODO: there are no detail on specification stil
	return
}

/*
   +--------+---...---+--------+---...---+
   | Type   | Payload | Type   | Payload |
   +--------+---...---+--------+---...---+
*/
type FramePacket struct {
	*PacketHeader
	Frames []Frame
}

func NewFramePacket() *FramePacket {
	ph := &PacketHeader{} //temporally
	packet := &FramePacket{
		PacketHeader: ph,
		Frames:       []Frame{},
	}
	return packet
}

func (packet *FramePacket) Parse(data []byte) (idx int, err error) {
	var frame Frame
	for idx < len(data) {
		switch FrameType(data[idx]) {
		case PaddingFrameType:
			frame = &PaddingFrame{}
		case RstStreamFrameType:
			frame = &RstStreamFrame{}
		case ConnectionCloseFrameType:
			frame = &ConnectionCloseFrame{}
		case GoAwayFrameType:
			frame = &GoAwayFrame{}
		case WindowUpdateFrameType:
			frame = &WindowUpdateFrame{}
		case BlockedFrameType:
			frame = &BlockedFrame{}
		case StopWaitingFrameType:
			frame = &StopWaitingFrame{}
		case PingFrameType:
			frame = &PingFrame{}
		default:
			if data[idx]&StreamFrameType == StreamFrameType {
				frame = &StreamFrame{}
			} else if data[idx]&AckFrameType == AckFrameType {
				frame = &AckFrame{}
			} else if data[idx]&CongestionFeedbackFrameType == CongestionFeedbackFrameType {
				//frame = &CongestionFeedbackFrame{}
			}
		}
		nxt, _ := frame.Parse(data[idx:])
		idx += nxt
		packet.Frames = append(packet.Frames, frame)
	}
	return
}

func (packet *FramePacket) GetWire() (wire []byte, err error) {
	for _, frame := range packet.Frames {
		wireTmp, _ := frame.GetWire()
		wire = append(wire, wireTmp...)
	}
	return
}

func (packet *FramePacket) String() (str string) {
	str = packet.PacketHeader.String()
	str += "Frame Packet\n"
	for _, frame := range packet.Frames {
		str += frame.String() + "\n"
	}
	return
}

/*
   +-----...----+
   | Redundancy |
   +-----...----+
*/
type FECPacket struct {
	*PacketHeader
	Redundancy []byte
}

func NewFECPacket() *FECPacket {
	ph := &PacketHeader{} // temporally
	packet := &FECPacket{
		PacketHeader: ph,
		Redundancy:   []byte{}, //temporally
	}
	return packet
}

func (packet *FECPacket) Parse(data []byte) (length int, err error) {
	packet.Redundancy = data // TODO: clearify here
	return
}

func (packet *FECPacket) GetWire() (wire []byte, err error) {
	return packet.Redundancy, err // TODO: clearify here
}

/*
        0        1        2        3        4         8
   +--------+--------+--------+--------+--------+--   --+
   | Public |    Connection ID (64)                ...  | ->
   |Flags(8)|                                           |
   +--------+--------+--------+--------+--------+--   --+
        9       10       11        12       13      14
   +--------+--------+--------+--------+--------+--------+---
   |      Quic Tag (32)                |  Tag value map      ... ->
   |         (PRST)                    |  (variable length)
   +--------+--------+--------+--------+--------+--------+---
*/
type PublicResetPacket struct {
	*PacketHeader
	Tag         QuicTag
	TagValueMap uint64 // ?
}

func NewPublicResetPacket(tag QuicTag, tagValue uint64) *PublicResetPacket {
	//ph := NewPacketHeader(over 64 bit connectionID, 0?, PrivateFlags(0)?, 0?)
	//flag := PUBLIC_RESET | CONNECTION_ID_LENGTH_8
	//ph = NewPacketHeader(flag, )
	ph := &PacketHeader{} //temporally
	packet := &PublicResetPacket{
		PacketHeader: ph,
		Tag:          tag,
		TagValueMap:  tagValue,
	}
	return packet
}

func (packet *PublicResetPacket) Parse(data []byte) (err error) {
	packet.Tag = QuicTag(data[0]<<24 | data[1]<<16 | data[2]<<8 | data[3])
	for i := 0; i < 8; i++ {
		packet.TagValueMap |= uint64(data[4+i] << byte(8*(7-i)))
	}
	return
}

func (packet *PublicResetPacket) GetWire() (wire []byte, err error) {
	// wire of Public Flags and Connection ID are extract from PacketHeader
	wire = make([]byte, 12)
	for i := 0; i < 4; i++ {
		wire[i] = byte(packet.Tag >> byte(8*(3-i)))
	}
	for i := 0; i < 8; i++ {
		wire[4+i] = byte(packet.TagValueMap >> byte(8*(7-i)))
	}
	return
}
<commit_msg>call NewPacketHeader from each packet type<commit_after>package quic

const QUIC_VERSION = uint32('Q'<<24 | '0'<<16 | '2'<<8 | '5') // temporally

type PublicFlagType byte

const (
	CONTAIN_QUIC_VERSION        PublicFlagType = 0x01
	PUBLIC_RESET                               = 0x02
	CONNECTION_ID_LENGTH_MASK                  = 0x0c
	CONNECTION_ID_LENGTH_8                     = 0x0c
	CONNECTION_ID_LENGTH_4                     = 0x08
	CONNECTION_ID_LENGTH_1                     = 0x04
	OMIT_CONNECTION_ID                         = 0x00
	SEQUENCE_NUMBER_LENGTH_MASK                = 0x30
	SEQUENCE_NUMBER_LENGTH_6                   = 0x30
	SEQUENCE_NUMBER_LENGTH_4                   = 0x20
	SEQUENCE_NUMBER_LENGTH_2                   = 0x10
	SEQUENCE_NUMBER_LENGTH_1                   = 0x00
	RESERVED                                   = 0xc0
)

type PrivateFlagType byte

const (
	FLAG_ENTROPY   PrivateFlagType = 0x01
	FLAG_FEC_GROUP                 = 0x02
	FLAG_FEC                       = 0x04
)

// Packet Header
/*
+--------+--------+--------+--------+--------+---    ---+
| Public |    Connection ID (0, 8, 32, or 64)    ...    | ->
|Flags(8)|      (variable length)                       |
+--------+--------+--------+--------+--------+---    ---+
    9       10       11        12
+--------+--------+--------+--------+
|      Quic Version (32)            | ->
|         (optional)                |
+--------+--------+--------+--------+
    13      14       15        16        17       18       19       20
+--------+--------+--------+--------+--------+--------+--------+--------+
|         Sequence Number (8, 16, 32, or 48)          |Private | FEC (8)|
|                         (variable length)           |Flags(8)|  (opt) |
+--------+--------+--------+--------+--------+--------+--------+--------+
*/

type PacketHeader struct {
	PublicFlags    PublicFlagType
	ConnectionID   uint64
	Version        uint32
	SequenceNumber uint64
	PrivateFlags   PrivateFlagType
	FEC            byte
}

func NewPacketHeader(publicFlags PublicFlagType, connectionID uint64, version uint32, sequenceNumber uint64, privateFlags PrivateFlagType, fec byte) *PacketHeader {

	switch {
	case connectionID <= 0:
		publicFlags |= OMIT_CONNECTION_ID
	case connectionID <= 0xff:
		publicFlags |= CONNECTION_ID_LENGTH_1
	case connectionID <= 0xffffffff:
		publicFlags |= CONNECTION_ID_LENGTH_4
	case connectionID <= 0xffffffffffffffff:
		// This indicate public reset packet
		publicFlags |= CONNECTION_ID_LENGTH_8
	}

	if publicFlags&PUBLIC_RESET != PUBLIC_RESET {
		switch {
		case sequenceNumber <= 0xff:
			publicFlags |= SEQUENCE_NUMBER_LENGTH_1
		case sequenceNumber <= 0xffff:
			publicFlags |= SEQUENCE_NUMBER_LENGTH_2
		case sequenceNumber <= 0xffffffff:
			publicFlags |= SEQUENCE_NUMBER_LENGTH_4
		case sequenceNumber <= 0xffffffffffff:
			publicFlags |= SEQUENCE_NUMBER_LENGTH_6
		}

		// version negotiation packet is still considering?
		// private flags == FLAG_FEC indicate FEC packet
		// others indicate frame packet
	}

	ph := &PacketHeader{
		PublicFlags:    publicFlags,
		ConnectionID:   connectionID,
		Version:        version,
		SequenceNumber: sequenceNumber,
		PrivateFlags:   privateFlags,
		FEC:            fec,
	}
	return ph
}

func (ph *PacketHeader) Parse(data []byte) (err error) {
	index := 0
	ph.PublicFlags = PublicFlagType(data[index])

	switch ph.PublicFlags & CONNECTION_ID_LENGTH_MASK {
	case CONNECTION_ID_LENGTH_8:
		ph.ConnectionID = uint64(data[1]<<56 | data[2]<<48 | data[3]<<40 | data[4]<<32 | data[5]<<24 | data[6]<<16 | data[7]<<8 | data[8])
		index = 9
	case CONNECTION_ID_LENGTH_4:
		ph.ConnectionID = uint64(data[1]<<24 | data[2]<<16 | data[3]<<8 | data[4])
		index = 5
	case CONNECTION_ID_LENGTH_1:
		ph.ConnectionID = uint64(data[1])
		index = 2
	case OMIT_CONNECTION_ID:
		ph.ConnectionID = 0 // omitted
		index = 1
	}
	if ph.PublicFlags&PUBLIC_RESET != PUBLIC_RESET {
		if ph.PublicFlags&CONTAIN_QUIC_VERSION == CONTAIN_QUIC_VERSION {
			ph.Version = uint32(data[index]<<24 | data[index+1]<<16 | data[index+2]<<8 | data[index+3])
			index += 4
		}

		// TODO: parse sequence number
		switch ph.PublicFlags & SEQUENCE_NUMBER_LENGTH_MASK {
		case SEQUENCE_NUMBER_LENGTH_6:
			ph.SequenceNumber = uint64(data[index]<<40 | data[index+1]<<32 | data[index+2]<<24 | data[index+3]<<16 | data[index+4]<<8 | data[index+5])
			index += 6
		case SEQUENCE_NUMBER_LENGTH_4:
			ph.SequenceNumber = uint64(data[index]<<24 | data[index+1]<<16 | data[index+2]<<8 | data[index+3])
			index += 4
		case SEQUENCE_NUMBER_LENGTH_2:
			ph.SequenceNumber = uint64(data[index]<<8 | data[index+1])
			index += 2
		case SEQUENCE_NUMBER_LENGTH_1:
			ph.SequenceNumber = uint64(data[index])
			index += 1
		}

		ph.PrivateFlags = PrivateFlagType(data[index])
		if ph.PrivateFlags&FLAG_ENTROPY == FLAG_ENTROPY {
			// TODO: ?
		}
		if ph.PrivateFlags&FLAG_FEC_GROUP == FLAG_FEC_GROUP {
			ph.FEC = data[index]
		}
		if ph.PrivateFlags&FLAG_FEC == FLAG_FEC {
			//TODO: FEC packet
		}
	}
	return
}

func (ph *PacketHeader) GetWire() (wire []byte, err error) {
	// confirm variable length
	connectionIDLen := 0
	switch ph.PublicFlags & CONNECTION_ID_LENGTH_MASK {
	case CONNECTION_ID_LENGTH_8:
		connectionIDLen = 8
	case CONNECTION_ID_LENGTH_4:
		connectionIDLen = 4
	case CONNECTION_ID_LENGTH_1:
		connectionIDLen = 1
	case OMIT_CONNECTION_ID:
		//pass
	}

	versionLen := 0
	if ph.PublicFlags&0x01 > 0 {
		versionLen = 4
	}

	sequenceNumberLen := 1
	switch ph.PublicFlags & SEQUENCE_NUMBER_LENGTH_MASK {
	case SEQUENCE_NUMBER_LENGTH_6:
		sequenceNumberLen = 6
	case SEQUENCE_NUMBER_LENGTH_4:
		sequenceNumberLen = 4
	case SEQUENCE_NUMBER_LENGTH_2:
		sequenceNumberLen = 2
	case SEQUENCE_NUMBER_LENGTH_1:
		//pass
	}

	// deal with FEC part
	fecLen := 0
	if ph.PrivateFlags&FLAG_ENTROPY == FLAG_ENTROPY {
		// TODO: ?
	}
	if ph.PrivateFlags&FLAG_FEC_GROUP == FLAG_FEC_GROUP {
		fecLen = 1
	}
	if ph.PrivateFlags&FLAG_FEC == FLAG_FEC {
		//TODO: FEC packet
	}

	// pack to wire
	wire = make([]byte, 1+connectionIDLen+versionLen+sequenceNumberLen+1+fecLen)
	wire[0] = byte(ph.PublicFlags)
	index := 1
	for i := 0; i < connectionIDLen; i++ {
		wire[index+i] = byte(ph.ConnectionID >> byte(8*(connectionIDLen-i-1)))
	}
	index += connectionIDLen

	for i := 0; i < versionLen; i++ {
		wire[index+i] = byte(ph.Version >> byte(8*(versionLen-i-1)))
	}
	index += versionLen

	for i := 0; i < sequenceNumberLen; i++ {
		wire[index+i] = byte(ph.SequenceNumber >> byte(8*(sequenceNumberLen-i-1)))
	}
	index += sequenceNumberLen

	wire[index] = byte(ph.PrivateFlags)

	if fecLen > 0 {
		wire[index+1] = ph.FEC
	}

	return
}

func (ph *PacketHeader) String() (str string) {
	str = "Packet Header" // temporally
	return
}

type VersionNegotiationPacket struct {
	*PacketHeader
	Version uint32 //?
}

func NewVersionNegotiationPacket(connectionID, sequenceNumber uint64, version uint32) *VersionNegotiationPacket {
	var flag PublicFlagType = CONTAIN_QUIC_VERSION
	ph := NewPacketHeader(flag, connectionID, version, sequenceNumber, 0, 0)
	packet := &VersionNegotiationPacket{
		PacketHeader: ph,
		Version:      version,
	}
	return packet
}

func (packet *VersionNegotiationPacket) Parse(data []byte) (length int, err error) {
	// TODO: there are no detail on specification stil
	return
}

func (packet *VersionNegotiationPacket) GetWire() (wire []byte, err error) {
	// TODO: there are no detail on specification stil
	return
}

/*
   +--------+---...---+--------+---...---+
   | Type   | Payload | Type   | Payload |
   +--------+---...---+--------+---...---+
*/
type FramePacket struct {
	*PacketHeader
	Frames []Frame
}

func NewFramePacket(connectionID, sequenceNumber uint64) *FramePacket {
	ph := NewPacketHeader(0, connectionID, 0, sequenceNumber, 0, 0)
	packet := &FramePacket{
		PacketHeader: ph,
		Frames:       []Frame{},
	}
	return packet
}

func (packet *FramePacket) Parse(data []byte) (idx int, err error) {
	var frame Frame
	for idx < len(data) {
		switch FrameType(data[idx]) {
		case PaddingFrameType:
			frame = &PaddingFrame{}
		case RstStreamFrameType:
			frame = &RstStreamFrame{}
		case ConnectionCloseFrameType:
			frame = &ConnectionCloseFrame{}
		case GoAwayFrameType:
			frame = &GoAwayFrame{}
		case WindowUpdateFrameType:
			frame = &WindowUpdateFrame{}
		case BlockedFrameType:
			frame = &BlockedFrame{}
		case StopWaitingFrameType:
			frame = &StopWaitingFrame{}
		case PingFrameType:
			frame = &PingFrame{}
		default:
			if data[idx]&StreamFrameType == StreamFrameType {
				frame = &StreamFrame{}
			} else if data[idx]&AckFrameType == AckFrameType {
				frame = &AckFrame{}
			} else if data[idx]&CongestionFeedbackFrameType == CongestionFeedbackFrameType {
				//frame = &CongestionFeedbackFrame{}
			}
		}
		nxt, _ := frame.Parse(data[idx:])
		idx += nxt
		packet.Frames = append(packet.Frames, frame)
	}
	return
}

func (packet *FramePacket) GetWire() (wire []byte, err error) {
	for _, frame := range packet.Frames {
		wireTmp, _ := frame.GetWire()
		wire = append(wire, wireTmp...)
	}
	return
}

func (packet *FramePacket) String() (str string) {
	str = packet.PacketHeader.String()
	str += "Frame Packet\n"
	for _, frame := range packet.Frames {
		str += frame.String() + "\n"
	}
	return
}

/*
   +-----...----+
   | Redundancy |
   +-----...----+
*/
type FECPacket struct {
	*PacketHeader
	Redundancy []byte
}

func NewFECPacket(connectionID uint64, sequenceNumber uint64, fec byte) *FECPacket {
	// TODO: is fec correct?
	var flag PrivateFlagType = FLAG_FEC
	ph := NewPacketHeader(0, connectionID, 0, sequenceNumber, flag, fec)
	packet := &FECPacket{
		PacketHeader: ph,
		Redundancy:   []byte{}, //temporally
	}
	return packet
}

func (packet *FECPacket) Parse(data []byte) (length int, err error) {
	packet.Redundancy = data // TODO: clearify here
	return
}

func (packet *FECPacket) GetWire() (wire []byte, err error) {
	return packet.Redundancy, err // TODO: clearify here
}

/*
        0        1        2        3        4         8
   +--------+--------+--------+--------+--------+--   --+
   | Public |    Connection ID (64)                ...  | ->
   |Flags(8)|                                           |
   +--------+--------+--------+--------+--------+--   --+
        9       10       11        12       13      14
   +--------+--------+--------+--------+--------+--------+---
   |      Quic Tag (32)                |  Tag value map      ... ->
   |         (PRST)                    |  (variable length)
   +--------+--------+--------+--------+--------+--------+---
*/
type PublicResetPacket struct {
	*PacketHeader
	Tag         QuicTag
	TagValueMap uint64 // ?
}

func NewPublicResetPacket(connectionID uint64, tag QuicTag, tagValue uint64) *PublicResetPacket {
	var flag PublicFlagType = PUBLIC_RESET | CONNECTION_ID_LENGTH_8
	ph := NewPacketHeader(flag, connectionID, 0, 0, 0, 0)
	packet := &PublicResetPacket{
		PacketHeader: ph,
		Tag:          tag,
		TagValueMap:  tagValue,
	}
	return packet
}

func (packet *PublicResetPacket) Parse(data []byte) (err error) {
	packet.Tag = QuicTag(data[0]<<24 | data[1]<<16 | data[2]<<8 | data[3])
	for i := 0; i < 8; i++ {
		packet.TagValueMap |= uint64(data[4+i] << byte(8*(7-i)))
	}
	return
}

func (packet *PublicResetPacket) GetWire() (wire []byte, err error) {
	// wire of Public Flags and Connection ID are extract from PacketHeader
	wire = make([]byte, 12)
	for i := 0; i < 4; i++ {
		wire[i] = byte(packet.Tag >> byte(8*(3-i)))
	}
	for i := 0; i < 8; i++ {
		wire[4+i] = byte(packet.TagValueMap >> byte(8*(7-i)))
	}
	return
}
<|endoftext|>


<commit_before>package revel

import (
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
)

type TestSuite struct {
	Client       *http.Client
	Response     *http.Response
	ResponseBody []byte
}

var TestSuites []interface{} // Array of structs that embed TestSuite

// NewTestSuite returns an initialized TestSuite ready for use. It is invoked
// by the test harness to initialize the embedded field in application tests.
func NewTestSuite() TestSuite {
	return TestSuite{Client: &http.Client{}}
}

// Return the base URL of the server, e.g. "http://127.0.0.1:8557"
func (t *TestSuite) BaseUrl() string {
	if Server.Addr[0] == ':' {
		return "http://127.0.0.1" + Server.Addr
	}
	return "http://" + Server.Addr
}

// Issue a GET request to the given path and store the result in Request and
// RequestBody.
func (t *TestSuite) Get(path string) {
	req, err := http.NewRequest("GET", t.BaseUrl()+path, nil)
	if err != nil {
		panic(err)
	}
	t.MakeRequest(req)
}

// Issue a POST request to the given path, sending the given Content-Type and
// data, and store the result in Request and RequestBody.  "data" may be nil.
func (t *TestSuite) Post(path string, contentType string, reader io.Reader) {
	req, err := http.NewRequest("POST", t.BaseUrl()+path, reader)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Content-Type", contentType)
	t.MakeRequest(req)
}

// Issue a POST request to the given path as a form post of the given key and
// values, and store the result in Request and RequestBody.
func (t *TestSuite) PostForm(path string, data url.Values) {
	t.Post(path, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
}

// Issue any request and read the response. If successful, the caller may
// examine the Response and ResponseBody properties.
func (t *TestSuite) MakeRequest(req *http.Request) {
	var err error
	if t.Response, err = t.Client.Do(req); err != nil {
		panic(err)
	}
	if t.ResponseBody, err = ioutil.ReadAll(t.Response.Body); err != nil {
		panic(err)
	}
}

func (t *TestSuite) AssertOk() {
	t.AssertStatus(http.StatusOK)
}

func (t *TestSuite) AssertNotFound() {
	t.AssertStatus(http.StatusNotFound)
}

func (t *TestSuite) AssertStatus(status int) {
	if t.Response.StatusCode != status {
		panic(fmt.Errorf("Status: (expected) %d != %d (actual)", status, t.Response.StatusCode))
	}
}

func (t *TestSuite) AssertContentType(contentType string) {
	t.AssertHeader("Content-Type", contentType)
}

func (t *TestSuite) AssertHeader(name, value string) {
	actual := t.Response.Header.Get(name)
	if actual != value {
		panic(fmt.Errorf("Header %s: (expected) %s != %s (actual)", name, value, actual))
	}
}

func (t *TestSuite) AssertEqual(expected, actual interface{}) {
	if !Equal(expected, actual) {
		panic(fmt.Errorf("(expected) %v != %v (actual)", expected, actual))
	}
}

func (t *TestSuite) Assert(exp bool) {
	t.Assertf(exp, "Assertion failed")
}

func (t *TestSuite) Assertf(exp bool, formatStr string, args ...interface{}) {
	if !exp {
		panic(fmt.Errorf(formatStr, args))
	}
}
<commit_msg>adding a test method to create a websocket connection<commit_after>package revel

import (
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	"code.google.com/p/go.net/websocket"
)

type TestSuite struct {
	Client       *http.Client
	Response     *http.Response
	ResponseBody []byte
}

var TestSuites []interface{} // Array of structs that embed TestSuite

// NewTestSuite returns an initialized TestSuite ready for use. It is invoked
// by the test harness to initialize the embedded field in application tests.
func NewTestSuite() TestSuite {
	return TestSuite{Client: &http.Client{}}
}

// Return the address and port of the server, e.g. "127.0.0.1:8557"
func (t *TestSuite) AddrAndPort() string {
	if Server.Addr[0] == ':' {
		return "127.0.0.1" + Server.Addr
	}
	return Server.Addr
}

// Return the base http URL of the server, e.g. "http://127.0.0.1:8557"
func (t *TestSuite) BaseUrl() string {
	return "http://" + t.AddrAndPort()
}

// Return the base websocket URL of the server, e.g. "ws://127.0.0.1:8557"
func (t *TestSuite) WebSocketUrl() string {
	return "ws://" + t.AddrAndPort()
}
// Issue a GET request to the given path and store the result in Request and
// RequestBody.
func (t *TestSuite) Get(path string) {
	req, err := http.NewRequest("GET", t.BaseUrl()+path, nil)
	if err != nil {
		panic(err)
	}
	t.MakeRequest(req)
}

// Issue a POST request to the given path, sending the given Content-Type and
// data, and store the result in Request and RequestBody.  "data" may be nil.
func (t *TestSuite) Post(path string, contentType string, reader io.Reader) {
	req, err := http.NewRequest("POST", t.BaseUrl()+path, reader)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Content-Type", contentType)
	t.MakeRequest(req)
}

// Issue a POST request to the given path as a form post of the given key and
// values, and store the result in Request and RequestBody.
func (t *TestSuite) PostForm(path string, data url.Values) {
	t.Post(path, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
}

// Issue any request and read the response. If successful, the caller may
// examine the Response and ResponseBody properties.
func (t *TestSuite) MakeRequest(req *http.Request) {
	var err error
	if t.Response, err = t.Client.Do(req); err != nil {
		panic(err)
	}
	if t.ResponseBody, err = ioutil.ReadAll(t.Response.Body); err != nil {
		panic(err)
	}
}

// Create a websocket connection to the given path and return the connection
func (t *TestSuite) WebSocket(path string) *websocket.Conn{
	origin := t.BaseUrl() + "/"
	url := t.WebSocketUrl() + path
	ws, err := websocket.Dial(url, "", origin)
	if err != nil {
		panic(err)
	}
	return ws
}

func (t *TestSuite) AssertOk() {
	t.AssertStatus(http.StatusOK)
}

func (t *TestSuite) AssertNotFound() {
	t.AssertStatus(http.StatusNotFound)
}

func (t *TestSuite) AssertStatus(status int) {
	if t.Response.StatusCode != status {
		panic(fmt.Errorf("Status: (expected) %d != %d (actual)", status, t.Response.StatusCode))
	}
}

func (t *TestSuite) AssertContentType(contentType string) {
	t.AssertHeader("Content-Type", contentType)
}

func (t *TestSuite) AssertHeader(name, value string) {
	actual := t.Response.Header.Get(name)
	if actual != value {
		panic(fmt.Errorf("Header %s: (expected) %s != %s (actual)", name, value, actual))
	}
}

func (t *TestSuite) AssertEqual(expected, actual interface{}) {
	if !Equal(expected, actual) {
		panic(fmt.Errorf("(expected) %v != %v (actual)", expected, actual))
	}
}

func (t *TestSuite) Assert(exp bool) {
	t.Assertf(exp, "Assertion failed")
}

func (t *TestSuite) Assertf(exp bool, formatStr string, args ...interface{}) {
	if !exp {
		panic(fmt.Errorf(formatStr, args))
	}
}
<|endoftext|>


<commit_before>package golax

import (
	"encoding/json"
	"log"
)

/**
 * Core interceptors free to use
 */

/**
 * `InterceptorError`
 * Print a JSON with the last error if exists
 */
var InterceptorError = &Interceptor{
	Documentation: Doc{
		Name: "Error",
		Description: `
Print JSON error in this form:

´´´json
{
	"status_code": 404,
	"error_code": 21,
	"description_code": "User '231223' not found."
}
´´´
		`,
	},
	After: func(c *Context) {
		if nil != c.LastError {
			json.NewEncoder(c.Response).Encode(c.LastError)
		}
	},
}

/**
 * `InterceptorLog`
 * Log request and response
 */
var InterceptorLog = &Interceptor{
	Documentation: Doc{
		Name: "Log",
		Description: `
Log all HTTP requests to stdout in this form:

´´´
2016/02/20 11:09:17 GET	/favicon.ico	404	59B
2016/02/20 11:09:34 GET	/service/v1/	405	68B
2016/02/20 11:09:46 GET	/service/v1/doc	405	68B
´´´
		`,
	},
	After: func(c *Context) {
		log.Printf(
			"%s\t%s\t%d\t%dB",
			c.Request.Method,
			c.Request.URL.RequestURI(),
			c.Response.StatusCode,
			c.Response.Length,
		)
	},
}
<commit_msg>Add interceptor NoCache<commit_after>package golax

import (
	"encoding/json"
	"log"

	"github.com/fulldump/golax"
)

/**
 * Core interceptors free to use
 */

/**
 * `InterceptorError`
 * Print a JSON with the last error if exists
 */
var InterceptorError = &Interceptor{
	Documentation: Doc{
		Name: "Error",
		Description: `
Print JSON error in this form:

´´´json
{
	"status_code": 404,
	"error_code": 21,
	"description_code": "User '231223' not found."
}
´´´
		`,
	},
	After: func(c *Context) {
		if nil != c.LastError {
			json.NewEncoder(c.Response).Encode(c.LastError)
		}
	},
}

/**
 * `InterceptorLog`
 * Log request and response
 */
var InterceptorLog = &Interceptor{
	Documentation: Doc{
		Name: "Log",
		Description: `
Log all HTTP requests to stdout in this form:

´´´
2016/02/20 11:09:17 GET	/favicon.ico	404	59B
2016/02/20 11:09:34 GET	/service/v1/	405	68B
2016/02/20 11:09:46 GET	/service/v1/doc	405	68B
´´´
		`,
	},
	After: func(c *Context) {
		log.Printf(
			"%s\t%s\t%d\t%dB",
			c.Request.Method,
			c.Request.URL.RequestURI(),
			c.Response.StatusCode,
			c.Response.Length,
		)
	},
}

/**
 * `InterceptorNoCache`
 * Send headers to disable browser caching
 */
var InterceptorNoCache = &golax.Interceptor{
	Documentation: golax.Doc{
		Name: "InterceptorNoCache",
		Description: `
			Avoid caching via http headers
		`,
	},
	Before: func(c *golax.Context) {
		add := c.Response.Header().Add

		add("Cache-Control", "no-store, no-cache, must-revalidate, post-check=0, pre-check=0")
		add("Pragma", "no-cache")
		add("Expires", "0")
	},
}
<|endoftext|>