<commit_before>package worklist

import (
	"golang.org/x/tools/go/ssa"
)

// Transition represents a transition from a value context to another value context.
// The transition is caused by a node which is a call in the context causing the change to the tagetContext.
type Transition struct {
	*transition
}

type transition struct {
	context       *ValueContext
	targetContext *ValueContext
	node          ssa.Instruction
}

// Equal tests whether two transitions are equal
func (t1 *Transition) Equal(t2 *Transition) bool {
	equalContext := t1.context.Equal(t2.context)
	equalTargetContext := t1.targetContext.Equal(t2.targetContext)
	equalnode := t1.node == t1.node
	return equalContext && equalTargetContext && equalnode
}

// NewTransition returns a Transition.
// context is the valuecontext of the "start" node.
// callSite is the ssa.Function which "goes" to the other context.
// targetContext is the valuecontext which is the "goal" of the flow.
// NewTransition appends the new transition to the transitions slice.
func NewTransition(context *ValueContext, targetContext *ValueContext, node ssa.Instruction) {
	if context == nil || targetContext == nil || node == nil {
		return
	}
	// don't create a transition if we don't analyze the context because we know the abstract results.
	if context.Equal(targetContext) {
		return
	}
	t := &Transition{&transition{context: context, targetContext: targetContext, node: node}}
	// only add a new transition to the transition list
	for _, a := range transitions {
		if a.Equal(t) {
			return
		}
	}
	transitions = append(transitions, t)
}

// String returns a readable string of a transition.
func (t1 *Transition) String() string {
	return "Context: " + t1.context.String() + "  \n node: " + t1.node.String() + " | targetContext: " + t1.targetContext.String()
}

// Node returns the node of the transition
func (t1 *Transition) Node() ssa.Instruction {
	return t1.node
}

// Context returns the context of the caller
func (t1 *Transition) Context() *ValueContext {
	return t1.context
}

// TagerContext returns the context of the callee
func (t1 *Transition) TargetContext() *ValueContext {
	return t1.targetContext
}
<commit_msg>Fixes #2<commit_after>package worklist

import (
	"golang.org/x/tools/go/ssa"
)

// Transition represents a transition from a value context to another value context.
// The transition is caused by a node which is a call in the context causing the change to the tagetContext.
type Transition struct {
	*transition
}

type transition struct {
	context       *ValueContext
	targetContext *ValueContext
	node          ssa.Instruction
}

// Equal tests whether two transitions are equal
func (t1 *Transition) Equal(t2 *Transition) bool {
	equalContext := t1.context.Equal(t2.context)
	equalTargetContext := t1.targetContext.Equal(t2.targetContext)
	equalnode := t1.node == t2.node
	return equalContext && equalTargetContext && equalnode
}

// NewTransition returns a Transition.
// context is the valuecontext of the "start" node.
// callSite is the ssa.Function which "goes" to the other context.
// targetContext is the valuecontext which is the "goal" of the flow.
// NewTransition appends the new transition to the transitions slice.
func NewTransition(context *ValueContext, targetContext *ValueContext, node ssa.Instruction) {
	if context == nil || targetContext == nil || node == nil {
		return
	}
	// don't create a transition if we don't analyze the context because we know the abstract results.
	if context.Equal(targetContext) {
		return
	}
	t := &Transition{&transition{context: context, targetContext: targetContext, node: node}}
	// only add a new transition to the transition list
	for _, a := range transitions {
		if a.Equal(t) {
			return
		}
	}
	transitions = append(transitions, t)
}

// String returns a readable string of a transition.
func (t1 *Transition) String() string {
	return "Context: " + t1.context.String() + "  \n node: " + t1.node.String() + " | targetContext: " + t1.targetContext.String()
}

// Node returns the node of the transition
func (t1 *Transition) Node() ssa.Instruction {
	return t1.node
}

// Context returns the context of the caller
func (t1 *Transition) Context() *ValueContext {
	return t1.context
}

// TagerContext returns the context of the callee
func (t1 *Transition) TargetContext() *ValueContext {
	return t1.targetContext
}
<|endoftext|>


<commit_before>package checkmysql

import (
	"fmt"
	"os"
	"strings"

	"github.com/mackerelio/checkers"
	"github.com/ziutek/mymysql/mysql"
	// MySQL Driver
	_ "github.com/ziutek/mymysql/native"
)

type mysqlSetting struct {
	Host string `short:"H" long:"host" default:"localhost" description:"Hostname"`
	Port string `short:"p" long:"port" default:"3306" description:"Port"`
	User string `short:"u" long:"user" default:"root" description:"Username"`
	Pass string `short:"P" long:"password" default:"" description:"Password"`
}

var commands = map[string](func([]string) *checkers.Checker){
	"replication": checkReplication,
	"connection":  checkConnection,
	"uptime":      checkUptime,
	"readonly":    checkReadOnly,
}

func separateSub(argv []string) (string, []string) {
	if len(argv) == 0 || strings.HasPrefix(argv[0], "-") {
		return "", argv
	}
	return argv[0], argv[1:]
}

// Do the plugin
func Do() {
	subCmd, argv := separateSub(os.Args[1:])
	fn, ok := commands[subCmd]
	if !ok {
		fmt.Println(`Usage:
  check-mysql [subcommand] [OPTIONS]

SubCommands:`)
		for k := range commands {
			fmt.Printf("  %s\n", k)
		}
		os.Exit(1)
	}
	ckr := fn(argv)
	ckr.Name = fmt.Sprintf("MySQL %s", strings.ToUpper(string(subCmd[0]))+subCmd[1:])
	ckr.Exit()
}

func newMySQL(m mysqlSetting) mysql.Conn {
	target := fmt.Sprintf("%s:%s", m.Host, m.Port)
	return mysql.New("tcp", "", target, m.User, m.Pass, "")
}
<commit_msg>update check-mysql for setting password via environment variable<commit_after>package checkmysql

import (
	"fmt"
	"os"
	"strings"

	"github.com/mackerelio/checkers"
	"github.com/ziutek/mymysql/mysql"
	// MySQL Driver
	_ "github.com/ziutek/mymysql/native"
)

type mysqlSetting struct {
	Host string `short:"H" long:"host" default:"localhost" description:"Hostname"`
	Port string `short:"p" long:"port" default:"3306" description:"Port"`
	User string `short:"u" long:"user" default:"root" description:"Username"`
	Pass string `short:"P" long:"password" default:"" description:"Password" env:"MYSQL_PASSWORD"`
}

var commands = map[string](func([]string) *checkers.Checker){
	"replication": checkReplication,
	"connection":  checkConnection,
	"uptime":      checkUptime,
	"readonly":    checkReadOnly,
}

func separateSub(argv []string) (string, []string) {
	if len(argv) == 0 || strings.HasPrefix(argv[0], "-") {
		return "", argv
	}
	return argv[0], argv[1:]
}

// Do the plugin
func Do() {
	subCmd, argv := separateSub(os.Args[1:])
	fn, ok := commands[subCmd]
	if !ok {
		fmt.Println(`Usage:
  check-mysql [subcommand] [OPTIONS]

SubCommands:`)
		for k := range commands {
			fmt.Printf("  %s\n", k)
		}
		os.Exit(1)
	}
	ckr := fn(argv)
	ckr.Name = fmt.Sprintf("MySQL %s", strings.ToUpper(string(subCmd[0]))+subCmd[1:])
	ckr.Exit()
}

func newMySQL(m mysqlSetting) mysql.Conn {
	target := fmt.Sprintf("%s:%s", m.Host, m.Port)
	return mysql.New("tcp", "", target, m.User, m.Pass, "")
}
<|endoftext|>


<commit_before>/*
Copyright 2014 Google Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// outyet is a web server that announces whether or not a particular Go version
// has been tagged.
package main

import (
	"expvar"
	"flag"
	"fmt"
	"html/template"
	"log"
	"net/http"
	"sync"
	"time"
)

// Command-line flags.
var (
	httpAddr   = flag.String("http", ":8080", "Listen address")
	pollPeriod = flag.Duration("poll", 5*time.Second, "Poll period")
	version    = flag.String("version", "1.4", "Go version")
)

const baseChangeURL = "https://code.google.com/p/go/source/detail?r="

func main() {
	flag.Parse()
	changeURL := fmt.Sprintf("%sgo%s", baseChangeURL, *version)
	http.Handle("/", NewServer(*version, changeURL, *pollPeriod))
	log.Fatal(http.ListenAndServe(*httpAddr, nil))
}

// Exported variables for monitoring the server.
// These are exported via HTTP as a JSON object at /debug/vars.
var (
	hitCount       = expvar.NewInt("hitCount")
	pollCount      = expvar.NewInt("pollCount")
	pollError      = expvar.NewString("pollError")
	pollErrorCount = expvar.NewInt("pollErrorCount")
)

// Server implements the outyet server.
// It serves the user interface (it's an http.Handler)
// and polls the remote repository for changes.
type Server struct {
	version string
	url     string
	period  time.Duration

	mu  sync.RWMutex // protects the yes variable
	yes bool
}

// NewServer returns an initialized outyet server.
func NewServer(version, url string, period time.Duration) *Server {
	s := &Server{version: version, url: url, period: period}
	go s.poll()
	return s
}

// poll polls the change URL for the specified period until the tag exists.
// Then it sets the Server's yes field true and exits.
func (s *Server) poll() {
	for !isTagged(s.url) {
		pollSleep(s.period)
	}
	s.mu.Lock()
	s.yes = true
	s.mu.Unlock()
	pollDone()
}

// Hooks that may be overridden for integration tests.
var (
	pollSleep = time.Sleep
	pollDone  = func() {}
)

// isTagged makes an HTTP HEAD request to the given URL and reports whether it
// returned a 200 OK response.
func isTagged(url string) bool {
	pollCount.Add(1)
	r, err := http.Head(url)
	if err != nil {
		log.Print(err)
		pollError.Set(err.Error())
		pollErrorCount.Add(1)
		return false
	}
	return r.StatusCode == http.StatusOK
}

// ServeHTTP implements the HTTP user interface.
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	hitCount.Add(1)
	s.mu.RLock()
	data := struct {
		URL     string
		Version string
		Yes     bool
	}{
		s.url,
		s.version,
		s.yes,
	}
	s.mu.RUnlock()
	err := tmpl.Execute(w, data)
	if err != nil {
		log.Print(err)
	}
}

// tmpl is the HTML template that drives the user interface.
var tmpl = template.Must(template.New("tmpl").Parse(`
<!DOCTYPE html>

Is Go {{.Version}} out yet?

	{{if .Yes}}
		YES!
	{{else}}
		No. :-(
	{{end}}

`))
<commit_msg>example/outyet: Change baseurl to go.googlesource.com.<commit_after>/*
Copyright 2014 Google Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// outyet is a web server that announces whether or not a particular Go version
// has been tagged.
package main

import (
	"expvar"
	"flag"
	"fmt"
	"html/template"
	"log"
	"net/http"
	"sync"
	"time"
)

// Command-line flags.
var (
	httpAddr   = flag.String("http", ":8080", "Listen address")
	pollPeriod = flag.Duration("poll", 5*time.Second, "Poll period")
	version    = flag.String("version", "1.4", "Go version")
)

const baseChangeURL = "https://go.googlesource.com/go/+/"

func main() {
	flag.Parse()
	changeURL := fmt.Sprintf("%sgo%s", baseChangeURL, *version)
	http.Handle("/", NewServer(*version, changeURL, *pollPeriod))
	log.Fatal(http.ListenAndServe(*httpAddr, nil))
}

// Exported variables for monitoring the server.
// These are exported via HTTP as a JSON object at /debug/vars.
var (
	hitCount       = expvar.NewInt("hitCount")
	pollCount      = expvar.NewInt("pollCount")
	pollError      = expvar.NewString("pollError")
	pollErrorCount = expvar.NewInt("pollErrorCount")
)

// Server implements the outyet server.
// It serves the user interface (it's an http.Handler)
// and polls the remote repository for changes.
type Server struct {
	version string
	url     string
	period  time.Duration

	mu  sync.RWMutex // protects the yes variable
	yes bool
}

// NewServer returns an initialized outyet server.
func NewServer(version, url string, period time.Duration) *Server {
	s := &Server{version: version, url: url, period: period}
	go s.poll()
	return s
}

// poll polls the change URL for the specified period until the tag exists.
// Then it sets the Server's yes field true and exits.
func (s *Server) poll() {
	for !isTagged(s.url) {
		pollSleep(s.period)
	}
	s.mu.Lock()
	s.yes = true
	s.mu.Unlock()
	pollDone()
}

// Hooks that may be overridden for integration tests.
var (
	pollSleep = time.Sleep
	pollDone  = func() {}
)

// isTagged makes an HTTP HEAD request to the given URL and reports whether it
// returned a 200 OK response.
func isTagged(url string) bool {
	pollCount.Add(1)
	r, err := http.Head(url)
	if err != nil {
		log.Print(err)
		pollError.Set(err.Error())
		pollErrorCount.Add(1)
		return false
	}
	return r.StatusCode == http.StatusOK
}

// ServeHTTP implements the HTTP user interface.
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	hitCount.Add(1)
	s.mu.RLock()
	data := struct {
		URL     string
		Version string
		Yes     bool
	}{
		s.url,
		s.version,
		s.yes,
	}
	s.mu.RUnlock()
	err := tmpl.Execute(w, data)
	if err != nil {
		log.Print(err)
	}
}

// tmpl is the HTML template that drives the user interface.
var tmpl = template.Must(template.New("tmpl").Parse(`
<!DOCTYPE html>

Is Go {{.Version}} out yet?

	{{if .Yes}}
		YES!
	{{else}}
		No. :-(
	{{end}}

`))
<|endoftext|>


<commit_before>/*
  Copyright David Thorpe 2015-2016 All Rights Reserved
  Please see file LICENSE for information on distribution, etc
*/
package main

import (
	"errors"
	"flag"
	"fmt"
	"os"
	"os/user"
	"path/filepath"
	"strings"

	"github.com/djthorpe/ytapi/ytcommands"
	"github.com/djthorpe/ytapi/ytservice"
)

////////////////////////////////////////////////////////////////////////////////

type Operation struct {
	setup func(*ytservice.Params, *ytservice.Table) error
	do    func(*ytservice.Service, *ytservice.Params, *ytservice.Table) error
}

////////////////////////////////////////////////////////////////////////////////

var (
	operations = map[string]Operation{
		"Authenticate":    Operation{NoOp, Authenticate},
		"ListVideos":      Operation{NoOp, ytcommands.ListVideos},                                   // --channel=<id> --maxresults=<n>
		"ListPlaylists":   Operation{ytcommands.RegisterPlaylistFormat, ytcommands.ListPlaylists},   // --channel=<id> --maxresults=<n>
		"ListBroadcasts":  Operation{ytcommands.RegisterBroadcastFormat, ytcommands.ListBroadcasts}, // --channel=<id> --maxresults=<n>
		"DeleteBroadcast": Operation{NoOp, ytcommands.DeleteBroadcast},                              // --video=<id>
		"ListStreams":     Operation{ytcommands.RegisterStreamFormat, ytcommands.ListStreams},       // --channel=<id> --maxresults=<n>
		"DeleteStream":    Operation{NoOp, ytcommands.DeleteStream},                                 // --stream=<id>
		"Search":          Operation{ytcommands.RegisterSearchFormat, ytcommands.Search},            // --q=<string> --maxresults=<n>

		// Channels
		"ListChannels":                   Operation{ytcommands.RegisterChannelFormat, ytcommands.ListChannels}, // --channel=<id> --maxresults=<n>
		"ListLocalizedChannelMetadata":   Operation{ytcommands.RegisterLocalizedChannelMetadataFormat, ytcommands.ListLocalizedChannelMetadata},
		"UpdateChannelMetadata":          Operation{ytcommands.RegisterChannelFormat, ytcommands.UpdateChannelMetadata},          // -hl=<string> -title=<string> -description=<string>
		"UpdateLocalizedChannelMetadata": Operation{ytcommands.RegisterLocalizedChannelMetadataFormat, ytcommands.UpdateLocalizedChannelMetadata}, // -hl=<string> -title=<string> -description=<string>
	}
)

var (
	credentialsFolder      = flag.String("credentials", ".credentials", "Folder containing credentials")
	clientsecretFilename   = flag.String("clientsecret", "client_secret.json", "Client secret filename")
	serviceAccountFilename = flag.String("serviceaccount", "service_account.json", "Service account filename")
	defaultsFilename       = flag.String("defaults", "defaults.json", "Defaults filename")
	tokenFilename          = flag.String("authtoken", "oauth_token", "OAuth token filename")

	flagDebug           = flag.Bool("debug", false, "Show API requests and responses on stderr")
	flagChannel         = flag.String("channel", "", "Channel ID")
	flagContentOwner    = flag.String("contentowner", "", "Content Owner ID")
	flagVideo           = flag.String("video", "", "Video or Broadcast ID")
	flagStream          = flag.String("stream", "", "Stream Key")
	flagMaxResults      = flag.Int64("maxresults", 0, "Maximum results to return (or 0)")
	flagPart            = flag.String("part", "", "Comma-separated list of parts for response")
	flagOutput          = flag.String("output", "ascii", "Output type (csv, ascii)")
	flagBroadcastStatus = flag.String("broadcaststatus", "all", "Broadcast Status (all,upcoming,active,completed)")
	flagQuery           = flag.String("q", "", "Search Query")
	flagTitle           = flag.String("title", "", "Metadata Title")
	flagDescription     = flag.String("description", "", "Metadata Description")
	flagLanguage        = flag.String("hl", "", "Metadata Language")
)

const (
	credentialsPathMode = 0700
	credentialsFileMode = 0644
)

////////////////////////////////////////////////////////////////////////////////

func userDir() (userDir string) {
	currentUser, _ := user.Current()
	userDir = currentUser.HomeDir
	return
}

func NewParamsFromFile(filename string) (*ytservice.Params, error) {
	var params *ytservice.Params
	var err error

	// if a file exists, then read it
	if _, err := os.Stat(filename); os.IsNotExist(err) {
		params = ytservice.NewParams()
	} else {
		params, err = ytservice.NewParamsFromJSON(filename)
	}
	if err != nil {
		return nil, err
	}
	return params, nil
}

func CombineParamsWthContentOwnerFlag(params *ytservice.Params) (*ytservice.Params, error) {
	copy := params.Copy()

	// copy --contentowner
	if len(*flagContentOwner) > 0 {
		copy.ContentOwner = flagContentOwner
		if copy.IsValidContentOwner() == false {
			return nil, errors.New("Invalid -contentowner flag")
		}
	}

	return copy, nil
}

func CombineParamsWthFlags(params *ytservice.Params) (*ytservice.Params, error) {
	copy := params.Copy()

	// copy --contentowner
	if len(*flagContentOwner) > 0 {
		copy.ContentOwner = flagContentOwner
		if copy.IsValidContentOwner() == false {
			return nil, errors.New("Invalid -contentowner flag")
		}
	}

	// copy --channel
	if len(*flagChannel) > 0 {
		copy.Channel = flagChannel
		if copy.IsValidChannel() == false {
			return nil, errors.New("Invalid -channel flag")
		}
	}

	// copy --maxresults
	if *flagMaxResults < 0 {
		return nil, errors.New("Invalid -maxresults flag")
	}
	if *flagMaxResults > 0 {
		copy.MaxResults = *flagMaxResults
	}

	// copy --q
	if len(*flagQuery) > 0 {
		copy.Query = flagQuery
	}

	// copy -video
	if len(*flagVideo) > 0 {
		copy.Video = flagVideo
		if copy.IsValidVideo() == false {
			return nil, errors.New("Invalid -video flag")
		}
	}

	// copy -stream
	if len(*flagStream) > 0 {
		copy.Stream = flagStream
		if copy.IsValidStream() == false {
			return nil, errors.New("Invalid -stream flag")
		}
	}

	// copy -broadcaststatus
	if len(*flagBroadcastStatus) > 0 {
		copy.BroadcastStatus = flagBroadcastStatus
		if copy.IsValidBroadcastStatus() == false {
			return nil, errors.New("Invalid -broadcaststatus flag")
		}
	}

	// copy title & description
	if len(*flagTitle) > 0 {
		copy.Title = flagTitle
	}
	if len(*flagDescription) > 0 {
		copy.Description = flagDescription
	}

	// copy language
	if len(*flagLanguage) > 0 {
		copy.Language = flagLanguage
		if copy.IsValidLanguage() == false {
			return nil, errors.New("Invalid -hl flag")
		}
	}

	return copy, nil
}

func Authenticate(service *ytservice.Service, params *ytservice.Params, output *ytservice.Table) error {

	// output content owner and channel information
	output.AddColumn("contentowner")
	output.AddColumn("channel")
	row := output.NewRow()

	if params.IsEmptyContentOwner() == false {
		row.SetString("contentowner", *params.ContentOwner)
	}
	if params.IsEmptyChannel() == false {
		row.SetString("channel", *params.Channel)
	}

	// success
	return nil
}

func NoOp(params *ytservice.Params, table *ytservice.Table) error {
	// Do Nothing
	return nil
}

func AlterColumnsForParts(parts []string, table *ytservice.Table) error {
	for _, part := range parts {
		if strings.HasPrefix(part, "-") {
			if err := table.RemoveColumnsForPart(strings.TrimPrefix(part, "-")); err != nil {
				return err
			}
		} else if strings.HasPrefix(part, "+") {
			if err := table.AddColumnsForPart(strings.TrimPrefix(part, "+")); err != nil {
				return err
			}
		} else {
			return errors.New("part elements must be prefixed with + or -")
		}
	}
	// success
	return nil
}

////////////////////////////////////////////////////////////////////////////////

func main() {
	// enumerate operations
	operation_keys := make([]string, 0, len(operations))
	for key := range operations {
		operation_keys = append(operation_keys, key)
	}

	// Set usage function
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage of %s:\n", filepath.Base(os.Args[0]))
		fmt.Fprintf(os.Stderr, "\n\t%s <flags> <%v>\n\n", filepath.Base(os.Args[0]), strings.Join(operation_keys, "|"))
		fmt.Fprintf(os.Stderr, "Where <flags> are one or more of:\n\n")
		flag.PrintDefaults()
	}

	// Read flags, exit with no operation
	flag.Parse()
	if flag.NArg() == 0 {
		flag.Usage()
		os.Exit(1)
	}

	// Check operation
	opname := flag.Arg(0)
	_, ok := operations[opname]
	if !ok {
		fmt.Fprintf(os.Stderr, "Error: Invalid operation: %s\n", opname)
		os.Exit(1)
	}

	// Obtain path for credentials - create if not already made
	credentialsPath := filepath.Join(userDir(), *credentialsFolder)
	if credentialsPathInfo, err := os.Stat(credentialsPath); err != nil || !credentialsPathInfo.IsDir() {
		// if path is missing, try and create the folder
		if err := os.Mkdir(credentialsPath, credentialsPathMode); err != nil {
			fmt.Fprintf(os.Stderr, "Missing credentials folder: %v\n", credentialsPath)
			os.Exit(1)
		}
	}

	var api *ytservice.Service
	var err error

	// Create params object
	defaultsPath := filepath.Join(credentialsPath, *defaultsFilename)
	defaults, err := NewParamsFromFile(defaultsPath)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}

	// if operation is to authenticate, delete existing token
	tokenPath := filepath.Join(credentialsPath, *tokenFilename)
	if opname == "Authenticate" {
		// Delete OAuth token
		if _, err := os.Stat(tokenPath); os.IsNotExist(err) == false {
			err = os.Remove(tokenPath)
			if err != nil {
				fmt.Fprintf(os.Stderr, "Error: %v\n", err)
				os.Exit(1)
			}
		}
	}

	// Combine content owner flag
	defaults, err = CombineParamsWthContentOwnerFlag(defaults)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}

	// Authenticate
	serviceAccountPath := filepath.Join(credentialsPath, *serviceAccountFilename)
	clientSecretPath := filepath.Join(credentialsPath, *clientsecretFilename)
	if defaults.IsEmptyContentOwner() == false {
		api, err = ytservice.NewYouTubeServiceFromServiceAccountJSON(serviceAccountPath, defaults, *flagDebug)
	} else {
		api, err = ytservice.NewYouTubeServiceFromClientSecretsJSON(clientSecretPath, tokenPath, defaults, *flagDebug)
	}
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}

	// If this isn't a service account and no channel parameter is set, then
	// set the channel parameter
	if api.ServiceAccount == false && defaults.IsValidChannel() == false {
		call := api.API.Channels.List("id").Mine(true)
		response, err := call.MaxResults(1).Do()
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}
		if len(response.Items) > 0 {
			defaults.Channel = &response.Items[0].Id
		}
	}

	// Save Defaults
	defaults.Save(defaultsPath, credentialsFileMode)

	// Combine defaults with command-line flags to make parameters
	params, err := CombineParamsWthFlags(defaults)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}

	// Print out parameters
	if *flagDebug {
		fmt.Fprintf(os.Stderr, "parameters=%+v\n", params)
	}

	// Create a table object
	output := ytservice.NewTable()

	// Setup
	err = operations[opname].setup(params, output)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}

	// Add and remove parts
	if len(*flagPart) > 0 {
		err = AlterColumnsForParts(strings.Split(*flagPart, ","), output)
	}
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}

	// Execute
	err = operations[opname].do(api, params, output)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}

	if *flagOutput == "ascii" {
		err = output.ASCII(os.Stdout)
	} else if *flagOutput == "csv" {
		err = output.CSV(os.Stdout)
	} else {
		err = errors.New("Invalid --output flag")
	}
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}
}
<commit_msg>Updated playlist methods<commit_after>/*
  Copyright David Thorpe 2015-2016 All Rights Reserved
  Please see file LICENSE for information on distribution, etc
*/
package main

import (
	"errors"
	"flag"
	"fmt"
	"os"
	"os/user"
	"path/filepath"
	"strings"

	"github.com/djthorpe/ytapi/ytcommands"
	"github.com/djthorpe/ytapi/ytservice"
)

////////////////////////////////////////////////////////////////////////////////

type Operation struct {
	setup func(*ytservice.Params, *ytservice.Table) error
	do    func(*ytservice.Service, *ytservice.Params, *ytservice.Table) error
}

////////////////////////////////////////////////////////////////////////////////

var (
	operations = map[string]Operation{
		"Authenticate":    Operation{NoOp, Authenticate},
		"ListVideos":      Operation{NoOp, ytcommands.ListVideos},                                   // --channel=<id> --maxresults=<n>
		"ListBroadcasts":  Operation{ytcommands.RegisterBroadcastFormat, ytcommands.ListBroadcasts}, // --channel=<id> --maxresults=<n>
		"DeleteBroadcast": Operation{NoOp, ytcommands.DeleteBroadcast},                              // --video=<id>
		"ListStreams":     Operation{ytcommands.RegisterStreamFormat, ytcommands.ListStreams},       // --channel=<id> --maxresults=<n>
		"DeleteStream":    Operation{NoOp, ytcommands.DeleteStream},                                 // --stream=<id>
		"Search":          Operation{ytcommands.RegisterSearchFormat, ytcommands.Search},            // --q=<string> --maxresults=<n>

		// Channels
		"ListChannels":                   Operation{ytcommands.RegisterChannelFormat, ytcommands.ListChannels}, // --channel=<id> --maxresults=<n>
		"ListLocalizedChannelMetadata":   Operation{ytcommands.RegisterLocalizedChannelMetadataFormat, ytcommands.ListLocalizedChannelMetadata},
		"UpdateChannelMetadata":          Operation{ytcommands.RegisterChannelFormat, ytcommands.UpdateChannelMetadata},          // -hl=<string> -title=<string> -description=<string>
		"UpdateLocalizedChannelMetadata": Operation{ytcommands.RegisterLocalizedChannelMetadataFormat, ytcommands.UpdateLocalizedChannelMetadata}, // -hl=<string> -title=<string> -description=<string>

		// Playlists
		"ListPlaylists":   Operation{ ytcommands.RegisterPlaylistFormat, ytcommands.ListPlaylists },           // -maxresults=<n>
		"ListLocalizedPlaylistMetadata":   Operation{ ytcommands.RegisterPlaylistFormat, ytcommands.ListPlaylists },                   // -playlist=<id>
		"CreatePlaylist":   Operation{ ytcommands.RegisterPlaylistFormat, ytcommands.ListPlaylists },         // -hl=<string> -title=<string> -description=<string> -privacystatus=(public|private|unlisted) -tags=
		"DeletePlaylist":   Operation{ ytcommands.RegisterPlaylistFormat, ytcommands.ListPlaylists },          // -playlist=<id>
		"UpdatePlaylistMetadata": Operation{ ytcommands.RegisterPlaylistFormat, ytcommands.ListPlaylists },   // -playlist=<id> -hl=<string> --title=<string> --description=<string> --privacystatus=(public|private|unlisted)
		"UpdateLocalizedPlaylistMetadata":   Operation{ ytcommands.RegisterPlaylistFormat, ytcommands.ListPlaylists },                 // --playlist=<id>  -hl=<string> --title=<string> --description=<string>

	}
)

var (
	credentialsFolder      = flag.String("credentials", ".credentials", "Folder containing credentials")
	clientsecretFilename   = flag.String("clientsecret", "client_secret.json", "Client secret filename")
	serviceAccountFilename = flag.String("serviceaccount", "service_account.json", "Service account filename")
	defaultsFilename       = flag.String("defaults", "defaults.json", "Defaults filename")
	tokenFilename          = flag.String("authtoken", "oauth_token", "OAuth token filename")

	flagDebug           = flag.Bool("debug", false, "Show API requests and responses on stderr")
	flagChannel         = flag.String("channel", "", "Channel ID")
	flagContentOwner    = flag.String("contentowner", "", "Content Owner ID")
	flagVideo           = flag.String("video", "", "Video or Broadcast ID")
	flagStream          = flag.String("stream", "", "Stream Key")
	flagMaxResults      = flag.Int64("maxresults", 0, "Maximum results to return (or 0)")
	flagPart            = flag.String("part", "", "Comma-separated list of parts for response")
	flagOutput          = flag.String("output", "ascii", "Output type (csv, ascii)")
	flagBroadcastStatus = flag.String("broadcaststatus", "all", "Broadcast Status (all,upcoming,active,completed)")
	flagQuery           = flag.String("q", "", "Search Query")
	flagTitle           = flag.String("title", "", "Metadata Title")
	flagDescription     = flag.String("description", "", "Metadata Description")
	flagLanguage        = flag.String("hl", "", "Metadata Language")
)

const (
	credentialsPathMode = 0700
	credentialsFileMode = 0644
)

////////////////////////////////////////////////////////////////////////////////

func userDir() (userDir string) {
	currentUser, _ := user.Current()
	userDir = currentUser.HomeDir
	return
}

func NewParamsFromFile(filename string) (*ytservice.Params, error) {
	var params *ytservice.Params
	var err error

	// if a file exists, then read it
	if _, err := os.Stat(filename); os.IsNotExist(err) {
		params = ytservice.NewParams()
	} else {
		params, err = ytservice.NewParamsFromJSON(filename)
	}
	if err != nil {
		return nil, err
	}
	return params, nil
}

func CombineParamsWthContentOwnerFlag(params *ytservice.Params) (*ytservice.Params, error) {
	copy := params.Copy()

	// copy --contentowner
	if len(*flagContentOwner) > 0 {
		copy.ContentOwner = flagContentOwner
		if copy.IsValidContentOwner() == false {
			return nil, errors.New("Invalid -contentowner flag")
		}
	}

	return copy, nil
}

func CombineParamsWthFlags(params *ytservice.Params) (*ytservice.Params, error) {
	copy := params.Copy()

	// copy --contentowner
	if len(*flagContentOwner) > 0 {
		copy.ContentOwner = flagContentOwner
		if copy.IsValidContentOwner() == false {
			return nil, errors.New("Invalid -contentowner flag")
		}
	}

	// copy --channel
	if len(*flagChannel) > 0 {
		copy.Channel = flagChannel
		if copy.IsValidChannel() == false {
			return nil, errors.New("Invalid -channel flag")
		}
	}

	// copy --maxresults
	if *flagMaxResults < 0 {
		return nil, errors.New("Invalid -maxresults flag")
	}
	if *flagMaxResults > 0 {
		copy.MaxResults = *flagMaxResults
	}

	// copy --q
	if len(*flagQuery) > 0 {
		copy.Query = flagQuery
	}

	// copy -video
	if len(*flagVideo) > 0 {
		copy.Video = flagVideo
		if copy.IsValidVideo() == false {
			return nil, errors.New("Invalid -video flag")
		}
	}

	// copy -stream
	if len(*flagStream) > 0 {
		copy.Stream = flagStream
		if copy.IsValidStream() == false {
			return nil, errors.New("Invalid -stream flag")
		}
	}

	// copy -broadcaststatus
	if len(*flagBroadcastStatus) > 0 {
		copy.BroadcastStatus = flagBroadcastStatus
		if copy.IsValidBroadcastStatus() == false {
			return nil, errors.New("Invalid -broadcaststatus flag")
		}
	}

	// copy title & description
	if len(*flagTitle) > 0 {
		copy.Title = flagTitle
	}
	if len(*flagDescription) > 0 {
		copy.Description = flagDescription
	}

	// copy language
	if len(*flagLanguage) > 0 {
		copy.Language = flagLanguage
		if copy.IsValidLanguage() == false {
			return nil, errors.New("Invalid -hl flag")
		}
	}

	return copy, nil
}

func Authenticate(service *ytservice.Service, params *ytservice.Params, output *ytservice.Table) error {

	// output content owner and channel information
	output.AddColumn("contentowner")
	output.AddColumn("channel")
	row := output.NewRow()

	if params.IsEmptyContentOwner() == false {
		row.SetString("contentowner", *params.ContentOwner)
	}
	if params.IsEmptyChannel() == false {
		row.SetString("channel", *params.Channel)
	}

	// success
	return nil
}

func NoOp(params *ytservice.Params, table *ytservice.Table) error {
	// Do Nothing
	return nil
}

func AlterColumnsForParts(parts []string, table *ytservice.Table) error {
	for _, part := range parts {
		if strings.HasPrefix(part, "-") {
			if err := table.RemoveColumnsForPart(strings.TrimPrefix(part, "-")); err != nil {
				return err
			}
		} else if strings.HasPrefix(part, "+") {
			if err := table.AddColumnsForPart(strings.TrimPrefix(part, "+")); err != nil {
				return err
			}
		} else {
			return errors.New("part elements must be prefixed with + or -")
		}
	}
	// success
	return nil
}

////////////////////////////////////////////////////////////////////////////////

func main() {
	// enumerate operations
	operation_keys := make([]string, 0, len(operations))
	for key := range operations {
		operation_keys = append(operation_keys, key)
	}

	// Set usage function
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage of %s:\n", filepath.Base(os.Args[0]))
		fmt.Fprintf(os.Stderr, "\n\t%s <flags> <%v>\n\n", filepath.Base(os.Args[0]), strings.Join(operation_keys, "|"))
		fmt.Fprintf(os.Stderr, "Where <flags> are one or more of:\n\n")
		flag.PrintDefaults()
	}

	// Read flags, exit with no operation
	flag.Parse()
	if flag.NArg() == 0 {
		flag.Usage()
		os.Exit(1)
	}

	// Check operation
	opname := flag.Arg(0)
	_, ok := operations[opname]
	if !ok {
		fmt.Fprintf(os.Stderr, "Error: Invalid operation: %s\n", opname)
		os.Exit(1)
	}

	// Obtain path for credentials - create if not already made
	credentialsPath := filepath.Join(userDir(), *credentialsFolder)
	if credentialsPathInfo, err := os.Stat(credentialsPath); err != nil || !credentialsPathInfo.IsDir() {
		// if path is missing, try and create the folder
		if err := os.Mkdir(credentialsPath, credentialsPathMode); err != nil {
			fmt.Fprintf(os.Stderr, "Missing credentials folder: %v\n", credentialsPath)
			os.Exit(1)
		}
	}

	var api *ytservice.Service
	var err error

	// Create params object
	defaultsPath := filepath.Join(credentialsPath, *defaultsFilename)
	defaults, err := NewParamsFromFile(defaultsPath)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}

	// if operation is to authenticate, delete existing token
	tokenPath := filepath.Join(credentialsPath, *tokenFilename)
	if opname == "Authenticate" {
		// Delete OAuth token
		if _, err := os.Stat(tokenPath); os.IsNotExist(err) == false {
			err = os.Remove(tokenPath)
			if err != nil {
				fmt.Fprintf(os.Stderr, "Error: %v\n", err)
				os.Exit(1)
			}
		}
	}

	// Combine content owner flag
	defaults, err = CombineParamsWthContentOwnerFlag(defaults)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}

	// Authenticate
	serviceAccountPath := filepath.Join(credentialsPath, *serviceAccountFilename)
	clientSecretPath := filepath.Join(credentialsPath, *clientsecretFilename)
	if defaults.IsEmptyContentOwner() == false {
		api, err = ytservice.NewYouTubeServiceFromServiceAccountJSON(serviceAccountPath, defaults, *flagDebug)
	} else {
		api, err = ytservice.NewYouTubeServiceFromClientSecretsJSON(clientSecretPath, tokenPath, defaults, *flagDebug)
	}
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}

	// If this isn't a service account and no channel parameter is set, then
	// set the channel parameter
	if api.ServiceAccount == false && defaults.IsValidChannel() == false {
		call := api.API.Channels.List("id").Mine(true)
		response, err := call.MaxResults(1).Do()
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
			os.Exit(1)
		}
		if len(response.Items) > 0 {
			defaults.Channel = &response.Items[0].Id
		}
	}

	// Save Defaults
	defaults.Save(defaultsPath, credentialsFileMode)

	// Combine defaults with command-line flags to make parameters
	params, err := CombineParamsWthFlags(defaults)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}

	// Print out parameters
	if *flagDebug {
		fmt.Fprintf(os.Stderr, "parameters=%+v\n", params)
	}

	// Create a table object
	output := ytservice.NewTable()

	// Setup
	err = operations[opname].setup(params, output)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}

	// Add and remove parts
	if len(*flagPart) > 0 {
		err = AlterColumnsForParts(strings.Split(*flagPart, ","), output)
	}
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}

	// Execute
	err = operations[opname].do(api, params, output)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}

	if *flagOutput == "ascii" {
		err = output.ASCII(os.Stdout)
	} else if *flagOutput == "csv" {
		err = output.CSV(os.Stdout)
	} else {
		err = errors.New("Invalid --output flag")
	}
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
		os.Exit(1)
	}
}
<|endoftext|>


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

package openstack

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

	"github.com/go-kit/kit/log"
	"github.com/gophercloud/gophercloud"
	"github.com/gophercloud/gophercloud/openstack"
	conntrack "github.com/mwitkow/go-conntrack"
	"github.com/pkg/errors"
	config_util "github.com/prometheus/common/config"
	"github.com/prometheus/common/model"

	"github.com/prometheus/prometheus/discovery/refresh"
	"github.com/prometheus/prometheus/discovery/targetgroup"
)

// DefaultSDConfig is the default OpenStack SD configuration.
var DefaultSDConfig = SDConfig{
	Port:            80,
	RefreshInterval: model.Duration(60 * time.Second),
	Availability:    "public",
}

// SDConfig is the configuration for OpenStack based service discovery.
type SDConfig struct {
	IdentityEndpoint            string                `yaml:"identity_endpoint"`
	Username                    string                `yaml:"username"`
	UserID                      string                `yaml:"userid"`
	Password                    config_util.Secret    `yaml:"password"`
	ProjectName                 string                `yaml:"project_name"`
	ProjectID                   string                `yaml:"project_id"`
	DomainName                  string                `yaml:"domain_name"`
	DomainID                    string                `yaml:"domain_id"`
	ApplicationCredentialName   string                `yaml:"application_credential_name"`
	ApplicationCredentialID     string                `yaml:"application_credential_id"`
	ApplicationCredentialSecret config_util.Secret    `yaml:"application_credential_secret"`
	Role                        Role                  `yaml:"role"`
	Region                      string                `yaml:"region"`
	RefreshInterval             model.Duration        `yaml:"refresh_interval,omitempty"`
	Port                        int                   `yaml:"port"`
	AllTenants                  bool                  `yaml:"all_tenants,omitempty"`
	TLSConfig                   config_util.TLSConfig `yaml:"tls_config,omitempty"`
	Availability                string                `yaml:"availability,omitempty"`
}

// Role is the role of the target in OpenStack.
type Role string

// The valid options for OpenStackRole.
const (
	// OpenStack document reference
	// https://docs.openstack.org/nova/pike/admin/arch.html#hypervisors
	OpenStackRoleHypervisor Role = "hypervisor"
	// OpenStack document reference
	// https://docs.openstack.org/horizon/pike/user/launch-instances.html
	OpenStackRoleInstance Role = "instance"
)

// UnmarshalYAML implements the yaml.Unmarshaler interface.
func (c *Role) UnmarshalYAML(unmarshal func(interface{}) error) error {
	if err := unmarshal((*string)(c)); err != nil {
		return err
	}
	switch *c {
	case OpenStackRoleHypervisor, OpenStackRoleInstance:
		return nil
	default:
		return errors.Errorf("unknown OpenStack SD role %q", *c)
	}
}

// UnmarshalYAML implements the yaml.Unmarshaler interface.
func (c *SDConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
	*c = DefaultSDConfig
	type plain SDConfig
	err := unmarshal((*plain)(c))
	if err != nil {
		return err
	}

	switch c.Availability {
	case "public", "internal", "admin":
	default:
		return fmt.Errorf("unknown availability %s, must be one of admin, internal or public", c.Availability)
	}

	if c.Role == "" {
		return errors.New("role missing (one of: instance, hypervisor)")
	}
	if c.Region == "" {
		return errors.New("openstack SD configuration requires a region")
	}

	return nil
}

type refresher interface {
	refresh(context.Context) ([]*targetgroup.Group, error)
}

// NewDiscovery returns a new OpenStack Discoverer which periodically refreshes its targets.
func NewDiscovery(conf *SDConfig, l log.Logger) (*refresh.Discovery, error) {
	r, err := newRefresher(conf, l)
	if err != nil {
		return nil, err
	}
	return refresh.NewDiscovery(
		l,
		"openstack",
		time.Duration(conf.RefreshInterval),
		r.refresh,
	), nil

}

func newRefresher(conf *SDConfig, l log.Logger) (refresher, error) {
	var opts gophercloud.AuthOptions
	if conf.IdentityEndpoint == "" {
		var err error
		opts, err = openstack.AuthOptionsFromEnv()
		if err != nil {
			return nil, err
		}
	} else {
		opts = gophercloud.AuthOptions{
			IdentityEndpoint:            conf.IdentityEndpoint,
			Username:                    conf.Username,
			UserID:                      conf.UserID,
			Password:                    string(conf.Password),
			TenantName:                  conf.ProjectName,
			TenantID:                    conf.ProjectID,
			DomainName:                  conf.DomainName,
			DomainID:                    conf.DomainID,
			ApplicationCredentialID:     conf.ApplicationCredentialID,
			ApplicationCredentialName:   conf.ApplicationCredentialName,
			ApplicationCredentialSecret: string(conf.ApplicationCredentialSecret),
		}
	}
	client, err := openstack.NewClient(opts.IdentityEndpoint)
	if err != nil {
		return nil, err
	}
	tls, err := config_util.NewTLSConfig(&conf.TLSConfig)
	if err != nil {
		return nil, err
	}
	client.HTTPClient = http.Client{
		Transport: &http.Transport{
			IdleConnTimeout: 5 * time.Duration(conf.RefreshInterval),
			TLSClientConfig: tls,
			DialContext: conntrack.NewDialContextFunc(
				conntrack.DialWithTracing(),
				conntrack.DialWithName("openstack_sd"),
			),
		},
		Timeout: 5 * time.Duration(conf.RefreshInterval),
	}
	availability := gophercloud.Availability(conf.Availability)
	switch conf.Role {
	case OpenStackRoleHypervisor:
		return newHypervisorDiscovery(client, &opts, conf.Port, conf.Region, availability, l), nil
	case OpenStackRoleInstance:
		return newInstanceDiscovery(client, &opts, conf.Port, conf.Region, conf.AllTenants, availability, l), nil
	}
	return nil, errors.New("unknown OpenStack discovery role")
}
<commit_msg>Openstack: Reduce timeouts (#7507)<commit_after>// Copyright 2017 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package openstack

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

	"github.com/go-kit/kit/log"
	"github.com/gophercloud/gophercloud"
	"github.com/gophercloud/gophercloud/openstack"
	conntrack "github.com/mwitkow/go-conntrack"
	"github.com/pkg/errors"
	config_util "github.com/prometheus/common/config"
	"github.com/prometheus/common/model"

	"github.com/prometheus/prometheus/discovery/refresh"
	"github.com/prometheus/prometheus/discovery/targetgroup"
)

// DefaultSDConfig is the default OpenStack SD configuration.
var DefaultSDConfig = SDConfig{
	Port:            80,
	RefreshInterval: model.Duration(60 * time.Second),
	Availability:    "public",
}

// SDConfig is the configuration for OpenStack based service discovery.
type SDConfig struct {
	IdentityEndpoint            string                `yaml:"identity_endpoint"`
	Username                    string                `yaml:"username"`
	UserID                      string                `yaml:"userid"`
	Password                    config_util.Secret    `yaml:"password"`
	ProjectName                 string                `yaml:"project_name"`
	ProjectID                   string                `yaml:"project_id"`
	DomainName                  string                `yaml:"domain_name"`
	DomainID                    string                `yaml:"domain_id"`
	ApplicationCredentialName   string                `yaml:"application_credential_name"`
	ApplicationCredentialID     string                `yaml:"application_credential_id"`
	ApplicationCredentialSecret config_util.Secret    `yaml:"application_credential_secret"`
	Role                        Role                  `yaml:"role"`
	Region                      string                `yaml:"region"`
	RefreshInterval             model.Duration        `yaml:"refresh_interval"`
	Port                        int                   `yaml:"port"`
	AllTenants                  bool                  `yaml:"all_tenants,omitempty"`
	TLSConfig                   config_util.TLSConfig `yaml:"tls_config,omitempty"`
	Availability                string                `yaml:"availability,omitempty"`
}

// Role is the role of the target in OpenStack.
type Role string

// The valid options for OpenStackRole.
const (
	// OpenStack document reference
	// https://docs.openstack.org/nova/pike/admin/arch.html#hypervisors
	OpenStackRoleHypervisor Role = "hypervisor"
	// OpenStack document reference
	// https://docs.openstack.org/horizon/pike/user/launch-instances.html
	OpenStackRoleInstance Role = "instance"
)

// UnmarshalYAML implements the yaml.Unmarshaler interface.
func (c *Role) UnmarshalYAML(unmarshal func(interface{}) error) error {
	if err := unmarshal((*string)(c)); err != nil {
		return err
	}
	switch *c {
	case OpenStackRoleHypervisor, OpenStackRoleInstance:
		return nil
	default:
		return errors.Errorf("unknown OpenStack SD role %q", *c)
	}
}

// UnmarshalYAML implements the yaml.Unmarshaler interface.
func (c *SDConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
	*c = DefaultSDConfig
	type plain SDConfig
	err := unmarshal((*plain)(c))
	if err != nil {
		return err
	}

	switch c.Availability {
	case "public", "internal", "admin":
	default:
		return fmt.Errorf("unknown availability %s, must be one of admin, internal or public", c.Availability)
	}

	if c.Role == "" {
		return errors.New("role missing (one of: instance, hypervisor)")
	}
	if c.Region == "" {
		return errors.New("openstack SD configuration requires a region")
	}

	return nil
}

type refresher interface {
	refresh(context.Context) ([]*targetgroup.Group, error)
}

// NewDiscovery returns a new OpenStack Discoverer which periodically refreshes its targets.
func NewDiscovery(conf *SDConfig, l log.Logger) (*refresh.Discovery, error) {
	r, err := newRefresher(conf, l)
	if err != nil {
		return nil, err
	}
	return refresh.NewDiscovery(
		l,
		"openstack",
		time.Duration(conf.RefreshInterval),
		r.refresh,
	), nil

}

func newRefresher(conf *SDConfig, l log.Logger) (refresher, error) {
	var opts gophercloud.AuthOptions
	if conf.IdentityEndpoint == "" {
		var err error
		opts, err = openstack.AuthOptionsFromEnv()
		if err != nil {
			return nil, err
		}
	} else {
		opts = gophercloud.AuthOptions{
			IdentityEndpoint:            conf.IdentityEndpoint,
			Username:                    conf.Username,
			UserID:                      conf.UserID,
			Password:                    string(conf.Password),
			TenantName:                  conf.ProjectName,
			TenantID:                    conf.ProjectID,
			DomainName:                  conf.DomainName,
			DomainID:                    conf.DomainID,
			ApplicationCredentialID:     conf.ApplicationCredentialID,
			ApplicationCredentialName:   conf.ApplicationCredentialName,
			ApplicationCredentialSecret: string(conf.ApplicationCredentialSecret),
		}
	}
	client, err := openstack.NewClient(opts.IdentityEndpoint)
	if err != nil {
		return nil, err
	}
	tls, err := config_util.NewTLSConfig(&conf.TLSConfig)
	if err != nil {
		return nil, err
	}
	client.HTTPClient = http.Client{
		Transport: &http.Transport{
			IdleConnTimeout: 2 * time.Duration(conf.RefreshInterval),
			TLSClientConfig: tls,
			DialContext: conntrack.NewDialContextFunc(
				conntrack.DialWithTracing(),
				conntrack.DialWithName("openstack_sd"),
			),
		},
		Timeout: time.Duration(conf.RefreshInterval),
	}
	availability := gophercloud.Availability(conf.Availability)
	switch conf.Role {
	case OpenStackRoleHypervisor:
		return newHypervisorDiscovery(client, &opts, conf.Port, conf.Region, availability, l), nil
	case OpenStackRoleInstance:
		return newInstanceDiscovery(client, &opts, conf.Port, conf.Region, conf.AllTenants, availability, l), nil
	}
	return nil, errors.New("unknown OpenStack discovery role")
}
<|endoftext|>


<commit_before><commit_msg>twitch: update to new endpoint<commit_after><|endoftext|>


<commit_before>package controller

import (
	"flag"
	"html/template"
	"log"
	"net/http"
	"sync"
)

// If flag is set, templates are reloaded on every refresh
var noCache = flag.Bool("nocache", false, "Determines whether template caching should occur.")

// Global template engine
var tpl *BlogTemplate

// Custom template wrapper
type BlogTemplate struct {
	*template.Template
	files []string
	mu *sync.Mutex
}

func (t *BlogTemplate) ExecuteTemplate(w http.ResponseWriter, name string, data interface{}) error {
	if *noCache {
		log.Printf("[%s] Recompiling templates.", name)
		t.mu.Lock()
		defer t.mu.Unlock()
		t.Template = template.Must(template.ParseFiles(t.files...))
	}

	return t.Template.ExecuteTemplate(w, name, data)
}

func init() {
	tpl = &BlogTemplate{
		files: []string{
			"views/login.html",
			"views/404.html",
			"views/manage.html",
			"views/editPost.html",
			"views/header.html",
			"views/footer.html",
			"views/home.html",
			"views/post.html",
		},
	}

	tpl.Template = template.Must(template.ParseFiles(tpl.files...))
}
<commit_msg>Gofmt<commit_after>package controller

import (
	"flag"
	"html/template"
	"log"
	"net/http"
	"sync"
)

// If flag is set, templates are reloaded on every refresh
var noCache = flag.Bool("nocache", false, "Determines whether template caching should occur.")

// Global template engine
var tpl *BlogTemplate

// Custom template wrapper
type BlogTemplate struct {
	*template.Template
	files []string
	mu    *sync.Mutex
}

func (t *BlogTemplate) ExecuteTemplate(w http.ResponseWriter, name string, data interface{}) error {
	if *noCache {
		log.Printf("[%s] Recompiling templates.", name)
		t.mu.Lock()
		defer t.mu.Unlock()
		t.Template = template.Must(template.ParseFiles(t.files...))
	}

	return t.Template.ExecuteTemplate(w, name, data)
}

func init() {
	tpl = &BlogTemplate{
		files: []string{
			"views/login.html",
			"views/404.html",
			"views/manage.html",
			"views/editPost.html",
			"views/header.html",
			"views/footer.html",
			"views/home.html",
			"views/post.html",
		},
	}

	tpl.Template = template.Must(template.ParseFiles(tpl.files...))
}
<|endoftext|>


<commit_before>package controllers

import (
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"

	e "github.com/techjanitor/pram-get/errors"
	"github.com/techjanitor/pram-get/models"
)

// TagsController handles tags pages
func TagsController(c *gin.Context) {

	// Get parameters from validate middleware
	params := c.MustGet("params").([]uint)

	// get search query if its there
	search := c.Query("search")

	// Initialize model struct
	m := &models.TagsModel{
		Ib:   params[0],
		Term: search,
	}

	// Get the model which outputs JSON
	err := m.Get()
	if err == e.ErrNotFound {
		c.Set("controllerError", err)
		c.JSON(e.ErrorMessage(e.ErrNotFound))
		c.Error(err)
		return
	}
	if err != nil {
		c.Set("controllerError", err)
		c.JSON(e.ErrorMessage(e.ErrInternalError))
		c.Error(err)
		return
	}

	// Marshal the structs into JSON
	output, err := json.Marshal(m.Result)
	if err != nil {
		c.Set("controllerError", err)
		c.JSON(e.ErrorMessage(e.ErrInternalError))
		c.Error(err)
		return
	}

	// Hand off data to cache middleware
	c.Set("data", output)

	c.Writer.Header().Set("Content-Type", "application/json")
	c.Writer.Write(output)

	return

}
<commit_msg>add cache busting to cache middleware<commit_after>package controllers

import (
	"encoding/json"
	"github.com/gin-gonic/gin"

	e "github.com/techjanitor/pram-get/errors"
	"github.com/techjanitor/pram-get/models"
)

// TagsController handles tags pages
func TagsController(c *gin.Context) {

	// Get parameters from validate middleware
	params := c.MustGet("params").([]uint)

	// get search query if its there
	search := c.Query("search")

	// Initialize model struct
	m := &models.TagsModel{
		Ib:   params[0],
		Term: search,
	}

	// Get the model which outputs JSON
	err := m.Get()
	if err == e.ErrNotFound {
		c.Set("controllerError", err)
		c.JSON(e.ErrorMessage(e.ErrNotFound))
		c.Error(err)
		return
	}
	if err != nil {
		c.Set("controllerError", err)
		c.JSON(e.ErrorMessage(e.ErrInternalError))
		c.Error(err)
		return
	}

	// Marshal the structs into JSON
	output, err := json.Marshal(m.Result)
	if err != nil {
		c.Set("controllerError", err)
		c.JSON(e.ErrorMessage(e.ErrInternalError))
		c.Error(err)
		return
	}

	// Hand off data to cache middleware
	c.Set("data", output)

	c.Writer.Header().Set("Content-Type", "application/json")
	c.Writer.Write(output)

	return

}
<|endoftext|>


<commit_before>// +build windows

package openvr

import "C"

// convertCBool2Int is a bandaid over the way the bool types end up working out
// with go re: openvr_capi.h. On windows, openvr_capi.h will setup a typedef
// mapping bool to char; on any other platform stdbool.h is used which will boil
// down to using C._Bool in go.
//
// In order to cope with the different types, this function was made to return
// an integer version of the bool value. It is conditionally compiled based on
// platform so it shouldn't create a duplication error.
func convertCBool2Int(b C.bool) int {
	if b == C.bool(0) {
		return 0
	}

	return 1
}
<commit_msg>one more fix to get bool2int working on windows<commit_after>// +build windows

package openvr

/*
#include <stdio.h>
#include <stdlib.h>
#include "openvr_capi.h"
*/
import "C"

// convertCBool2Int is a bandaid over the way the bool types end up working out
// with go re: openvr_capi.h. On windows, openvr_capi.h will setup a typedef
// mapping bool to char; on any other platform stdbool.h is used which will boil
// down to using C._Bool in go.
//
// In order to cope with the different types, this function was made to return
// an integer version of the bool value. It is conditionally compiled based on
// platform so it shouldn't create a duplication error.
func convertCBool2Int(b C.bool) int {
	if b == C.bool(0) {
		return 0
	}

	return 1
}
<|endoftext|>


<commit_before>package params

type cluster struct {
	NetworkID   int      `json:"networkID"`
	StaticNodes []string `json:"staticnodes"`
	BootNodes   []string `json:"bootnodes"`
}

var ropstenCluster = cluster{
	NetworkID: 3,
	BootNodes: []string{
		"enode://436cc6f674928fdc9a9f7990f2944002b685d1c37f025c1be425185b5b1f0900feaf1ccc2a6130268f9901be4a7d252f37302c8335a2c1a62736e9232691cc3a@174.138.105.243:30404", // boot-01.do-ams3.eth.beta
		"enode://5395aab7833f1ecb671b59bf0521cf20224fe8162fc3d2675de4ee4d5636a75ec32d13268fc184df8d1ddfa803943906882da62a4df42d4fccf6d17808156a87@206.189.243.57:30404",  // boot-02.do-ams3.eth.beta
		"enode://7427dfe38bd4cf7c58bb96417806fab25782ec3e6046a8053370022cbaa281536e8d64ecd1b02e1f8f72768e295d06258ba43d88304db068e6f2417ae8bcb9a6@104.154.88.123:30404",  // boot-01.gc-us-central1-a.eth.beta
		"enode://ebefab39b69bbbe64d8cd86be765b3be356d8c4b24660f65d493143a0c44f38c85a257300178f7845592a1b0332811542e9a58281c835babdd7535babb64efc1@35.202.99.224:30404",   // boot-02.gc-us-central1-a.eth.beta
	},
	StaticNodes: []string{
		"enode://a6a2a9b3a7cbb0a15da74301537ebba549c990e3325ae78e1272a19a3ace150d03c184b8ac86cc33f1f2f63691e467d49308f02d613277754c4dccd6773b95e8@206.189.108.68:30304",
		"enode://207e53d9bf66be7441e3daba36f53bfbda0b6099dba9a865afc6260a2d253fb8a56a72a48598a4f7ba271792c2e4a8e1a43aaef7f34857f520c8c820f63b44c8@35.224.15.65:30304",
	},
}

var rinkebyCluster = cluster{
	NetworkID: 4,
	BootNodes: []string{
		"enode://1b843c7697f6fc42a1f606fb3cfaac54e025f06789dc20ad9278be3388967cf21e3a1b1e4be51faecd66c2c3adef12e942b4fcdeb8727657abe60636efb6224f@206.189.6.46:30404",
		"enode://b29100c8468e3e6604817174a15e4d71627458b0dcdbeea169ab2eb4ab2bbc6f24adbb175826726cec69db8fdba6c0dd60b3da598e530ede562180d300728659@206.189.6.48:30404",
	},
	StaticNodes: []string{
		"enode://ff1d6ac1c1d79fe060137d217ad26e372b6dea3d53690677e231000334f6e71c0b720000b6f79edb1e1100c172c1df85a3f05867e4f0716e7ff7fbc47327898b@51.15.75.244:30303",
		"enode://6a1e9b88da1cb5e55e9174c21d3808800671c342416e90edd181341b5c2192a9a6189a770a69ae7cf24dd97cb1322f9b56d8093549a2bf944b3baaa6ccaa9ba9@51.15.68.93:30303",
		"enode://ba41aa829287a0a9076d9bffed97c8ce2e491b99873288c9e886f16fd575306ac6c656db4fbf814f5a9021aec004ffa9c0ae8650f92fd10c12eeb7c364593eb3@51.15.69.147:30303",
		"enode://28ecf5272b560ca951f4cd7f1eb8bd62da5853b026b46db432c4b01797f5b0114819a090a72acd7f32685365ecd8e00450074fa0673039aefe10f3fb666e0f3f@51.15.76.249:30303",
	},
}

var mainnetCluster = cluster{
	NetworkID: 1,
	BootNodes: []string{
		"enode://436cc6f674928fdc9a9f7990f2944002b685d1c37f025c1be425185b5b1f0900feaf1ccc2a6130268f9901be4a7d252f37302c8335a2c1a62736e9232691cc3a@174.138.105.243:30404", // boot-01.do-ams3.eth.beta
		"enode://5395aab7833f1ecb671b59bf0521cf20224fe8162fc3d2675de4ee4d5636a75ec32d13268fc184df8d1ddfa803943906882da62a4df42d4fccf6d17808156a87@206.189.243.57:30404",  // boot-02.do-ams3.eth.beta
		"enode://7427dfe38bd4cf7c58bb96417806fab25782ec3e6046a8053370022cbaa281536e8d64ecd1b02e1f8f72768e295d06258ba43d88304db068e6f2417ae8bcb9a6@104.154.88.123:30404",  // boot-01.gc-us-central1-a.eth.beta
		"enode://ebefab39b69bbbe64d8cd86be765b3be356d8c4b24660f65d493143a0c44f38c85a257300178f7845592a1b0332811542e9a58281c835babdd7535babb64efc1@35.202.99.224:30404",   // boot-02.gc-us-central1-a.eth.beta
	},
	StaticNodes: []string{
		"enode://a6a2a9b3a7cbb0a15da74301537ebba549c990e3325ae78e1272a19a3ace150d03c184b8ac86cc33f1f2f63691e467d49308f02d613277754c4dccd6773b95e8@206.189.108.68:30304",
		"enode://207e53d9bf66be7441e3daba36f53bfbda0b6099dba9a865afc6260a2d253fb8a56a72a48598a4f7ba271792c2e4a8e1a43aaef7f34857f520c8c820f63b44c8@35.224.15.65:30304",
	},
}

var defaultClusters = []cluster{ropstenCluster, rinkebyCluster, mainnetCluster}
<commit_msg>fix enode IPs for DigitalOcean static whisper nodes (#1095)<commit_after>package params

type cluster struct {
	NetworkID   int      `json:"networkID"`
	StaticNodes []string `json:"staticnodes"`
	BootNodes   []string `json:"bootnodes"`
}

var ropstenCluster = cluster{
	NetworkID: 3,
	BootNodes: []string{
		"enode://436cc6f674928fdc9a9f7990f2944002b685d1c37f025c1be425185b5b1f0900feaf1ccc2a6130268f9901be4a7d252f37302c8335a2c1a62736e9232691cc3a@174.138.105.243:30404", // boot-01.do-ams3.eth.beta
		"enode://5395aab7833f1ecb671b59bf0521cf20224fe8162fc3d2675de4ee4d5636a75ec32d13268fc184df8d1ddfa803943906882da62a4df42d4fccf6d17808156a87@206.189.243.57:30404",  // boot-02.do-ams3.eth.beta
		"enode://7427dfe38bd4cf7c58bb96417806fab25782ec3e6046a8053370022cbaa281536e8d64ecd1b02e1f8f72768e295d06258ba43d88304db068e6f2417ae8bcb9a6@104.154.88.123:30404",  // boot-01.gc-us-central1-a.eth.beta
		"enode://ebefab39b69bbbe64d8cd86be765b3be356d8c4b24660f65d493143a0c44f38c85a257300178f7845592a1b0332811542e9a58281c835babdd7535babb64efc1@35.202.99.224:30404",   // boot-02.gc-us-central1-a.eth.beta
	},
	StaticNodes: []string{
		"enode://a6a2a9b3a7cbb0a15da74301537ebba549c990e3325ae78e1272a19a3ace150d03c184b8ac86cc33f1f2f63691e467d49308f02d613277754c4dccd6773b95e8@206.189.243.176:30304", // node-01.do-ams3.eth.beta
		"enode://207e53d9bf66be7441e3daba36f53bfbda0b6099dba9a865afc6260a2d253fb8a56a72a48598a4f7ba271792c2e4a8e1a43aaef7f34857f520c8c820f63b44c8@35.224.15.65:30304",    // node-01.gc-us-central1-a.eth.beta
	},
}

var rinkebyCluster = cluster{
	NetworkID: 4,
	BootNodes: []string{
		"enode://1b843c7697f6fc42a1f606fb3cfaac54e025f06789dc20ad9278be3388967cf21e3a1b1e4be51faecd66c2c3adef12e942b4fcdeb8727657abe60636efb6224f@206.189.6.46:30404",
		"enode://b29100c8468e3e6604817174a15e4d71627458b0dcdbeea169ab2eb4ab2bbc6f24adbb175826726cec69db8fdba6c0dd60b3da598e530ede562180d300728659@206.189.6.48:30404",
	},
	StaticNodes: []string{
		"enode://ff1d6ac1c1d79fe060137d217ad26e372b6dea3d53690677e231000334f6e71c0b720000b6f79edb1e1100c172c1df85a3f05867e4f0716e7ff7fbc47327898b@51.15.75.244:30303",
		"enode://6a1e9b88da1cb5e55e9174c21d3808800671c342416e90edd181341b5c2192a9a6189a770a69ae7cf24dd97cb1322f9b56d8093549a2bf944b3baaa6ccaa9ba9@51.15.68.93:30303",
		"enode://ba41aa829287a0a9076d9bffed97c8ce2e491b99873288c9e886f16fd575306ac6c656db4fbf814f5a9021aec004ffa9c0ae8650f92fd10c12eeb7c364593eb3@51.15.69.147:30303",
		"enode://28ecf5272b560ca951f4cd7f1eb8bd62da5853b026b46db432c4b01797f5b0114819a090a72acd7f32685365ecd8e00450074fa0673039aefe10f3fb666e0f3f@51.15.76.249:30303",
	},
}

var mainnetCluster = cluster{
	NetworkID: 1,
	BootNodes: []string{
		"enode://436cc6f674928fdc9a9f7990f2944002b685d1c37f025c1be425185b5b1f0900feaf1ccc2a6130268f9901be4a7d252f37302c8335a2c1a62736e9232691cc3a@174.138.105.243:30404", // boot-01.do-ams3.eth.beta
		"enode://5395aab7833f1ecb671b59bf0521cf20224fe8162fc3d2675de4ee4d5636a75ec32d13268fc184df8d1ddfa803943906882da62a4df42d4fccf6d17808156a87@206.189.243.57:30404",  // boot-02.do-ams3.eth.beta
		"enode://7427dfe38bd4cf7c58bb96417806fab25782ec3e6046a8053370022cbaa281536e8d64ecd1b02e1f8f72768e295d06258ba43d88304db068e6f2417ae8bcb9a6@104.154.88.123:30404",  // boot-01.gc-us-central1-a.eth.beta
		"enode://ebefab39b69bbbe64d8cd86be765b3be356d8c4b24660f65d493143a0c44f38c85a257300178f7845592a1b0332811542e9a58281c835babdd7535babb64efc1@35.202.99.224:30404",   // boot-02.gc-us-central1-a.eth.beta
	},
	StaticNodes: []string{
		"enode://a6a2a9b3a7cbb0a15da74301537ebba549c990e3325ae78e1272a19a3ace150d03c184b8ac86cc33f1f2f63691e467d49308f02d613277754c4dccd6773b95e8@206.189.243.176:30304", // node-01.do-ams3.eth.beta
		"enode://207e53d9bf66be7441e3daba36f53bfbda0b6099dba9a865afc6260a2d253fb8a56a72a48598a4f7ba271792c2e4a8e1a43aaef7f34857f520c8c820f63b44c8@35.224.15.65:30304",    // node-01.gc-us-central1-a.eth.beta
	},
}

var defaultClusters = []cluster{ropstenCluster, rinkebyCluster, mainnetCluster}
<|endoftext|>


<commit_before>package core

import (
	"bytes"
	"encoding/hex"
	"errors"
	crypto "gx/ipfs/QmPGxZ1DP2w45WcogpW1h43BvseXbfke9N91qotpoQcUeS/go-libp2p-crypto"

	"time"

	"github.com/OpenBazaar/openbazaar-go/pb"
	"github.com/OpenBazaar/spvwallet"
	"github.com/btcsuite/btcd/txscript"
	"github.com/btcsuite/btcutil"
	hd "github.com/btcsuite/btcutil/hdkeychain"
	"github.com/golang/protobuf/proto"
	"github.com/golang/protobuf/ptypes"
)

func (n *OpenBazaarNode) FulfillOrder(fulfillment *pb.OrderFulfillment, contract *pb.RicardianContract, records []*spvwallet.TransactionRecord) error {
	if fulfillment.Slug == "" && len(contract.VendorListings) == 1 {
		fulfillment.Slug = contract.VendorListings[0].Slug
	}
	rc := new(pb.RicardianContract)
	if contract.BuyerOrder.Payment.Method == pb.Order_Payment_MODERATED {
		payout := new(pb.OrderFulfillment_Payout)
		payout.PayoutAddress = n.Wallet.CurrentAddress(spvwallet.EXTERNAL).EncodeAddress()
		payout.PayoutFeePerByte = n.Wallet.GetFeePerByte(spvwallet.NORMAL)
		var ins []spvwallet.TransactionInput
		var outValue int64
		for _, r := range records {
			if !r.Spent && r.Value > 0 {
				outpointHash, err := hex.DecodeString(r.Txid)
				if err != nil {
					return err
				}
				outValue += r.Value
				in := spvwallet.TransactionInput{OutpointIndex: r.Index, OutpointHash: outpointHash}
				ins = append(ins, in)
			}
		}

		refundAddress, err := btcutil.DecodeAddress(contract.BuyerOrder.RefundAddress, n.Wallet.Params())
		if err != nil {
			return err
		}
		var output spvwallet.TransactionOutput

		outputScript, err := txscript.PayToAddrScript(refundAddress)
		if err != nil {
			return err
		}
		output.ScriptPubKey = outputScript
		output.Value = outValue

		chaincode, err := hex.DecodeString(contract.BuyerOrder.Payment.Chaincode)
		if err != nil {
			return err
		}
		parentFP := []byte{0x00, 0x00, 0x00, 0x00}
		mPrivKey := n.Wallet.MasterPrivateKey()
		if err != nil {
			return err
		}
		mECKey, err := mPrivKey.ECPrivKey()
		if err != nil {
			return err
		}
		hdKey := hd.NewExtendedKey(
			n.Wallet.Params().HDPrivateKeyID[:],
			mECKey.Serialize(),
			chaincode,
			parentFP,
			0,
			0,
			true)

		vendorKey, err := hdKey.Child(0)
		if err != nil {
			return err
		}
		redeemScript, err := hex.DecodeString(contract.BuyerOrder.Payment.RedeemScript)

		signatures, err := n.Wallet.CreateMultisigSignature(ins, []spvwallet.TransactionOutput{output}, vendorKey, redeemScript, payout.PayoutFeePerByte)
		if err != nil {
			return err
		}
		var sigs []*pb.BitcoinSignature
		for _, s := range signatures {
			pbSig := &pb.BitcoinSignature{Signature: s.Signature, InputIndex: s.InputIndex}
			sigs = append(sigs, pbSig)
		}
		payout.Sigs = sigs
		fulfillment.Payout = payout
	}
	var keyIndex int
	for i, listing := range contract.VendorListings {
		if listing.Slug == fulfillment.Slug {
			keyIndex = i
			break
		}
	}

	ts, err := ptypes.TimestampProto(time.Now())
	if err != nil {
		return err
	}
	fulfillment.Timestamp = ts

	rs := new(pb.RatingSignature)
	metadata := new(pb.RatingSignature_TransactionMetadata)
	metadata.RatingKey = contract.BuyerOrder.RatingKeys[keyIndex]
	metadata.ListingSlug = fulfillment.Slug
	ser, err := proto.Marshal(metadata)
	if err != nil {
		return err
	}
	signature, err := n.IpfsNode.PrivateKey.Sign(ser)
	if err != nil {
		return err
	}
	rs.Metadata = metadata
	rs.Signature = signature

	fulfillment.RatingSignature = rs

	fulfils := []*pb.OrderFulfillment{}

	rc.VendorOrderFulfillment = append(fulfils, fulfillment)
	rc, err = n.SignOrderFulfillment(rc)
	if err != nil {
		return err
	}
	buyerkey, err := crypto.UnmarshalPublicKey(contract.BuyerOrder.BuyerID.Pubkeys.Guid)
	if err != nil {
		return err
	}
	err = n.SendOrderFulfillment(contract.BuyerOrder.BuyerID.Guid, &buyerkey, rc)
	if err != nil {
		return err
	}
	contract.VendorOrderFulfillment = append(contract.VendorOrderFulfillment, fulfillment)
	for _, sig := range rc.Signatures {
		if sig.Section == pb.Signature_ORDER_FULFILLMENT {
			contract.Signatures = append(contract.Signatures, sig)
		}
	}
	n.Datastore.Sales().Put(contract.VendorOrderConfirmation.OrderID, *contract, pb.OrderState_FULFILLED, false)
	return nil
}

func (n *OpenBazaarNode) SignOrderFulfillment(contract *pb.RicardianContract) (*pb.RicardianContract, error) {
	serializedOrderFulfil, err := proto.Marshal(contract.VendorOrderFulfillment[0])
	if err != nil {
		return contract, err
	}
	s := new(pb.Signature)
	s.Section = pb.Signature_ORDER_FULFILLMENT
	if err != nil {
		return contract, err
	}
	guidSig, err := n.IpfsNode.PrivateKey.Sign(serializedOrderFulfil)
	if err != nil {
		return contract, err
	}
	s.SignatureBytes = guidSig
	contract.Signatures = append(contract.Signatures, s)
	return contract, nil
}

func (n *OpenBazaarNode) ValidateOrderFulfillment(fulfillment *pb.OrderFulfillment, contract *pb.RicardianContract) error {
	if err := verifySignaturesOnOrderFulfilment(contract); err != nil {
		return err
	}

	slugExists := func(a string, list []string) bool {
		for _, b := range list {
			if b == a {
				return true
			}
		}
		return false
	}
	keyExists := func(a []byte, list [][]byte) bool {
		for _, b := range list {
			if bytes.Equal(b, a) {
				return true
			}
		}
		return false
	}

	var listingSlugs []string
	for _, listing := range contract.VendorListings {
		listingSlugs = append(listingSlugs, listing.Slug)
	}
	if !slugExists(fulfillment.Slug, listingSlugs) {
		return errors.New("Slug in rating signature does not exist in order")
	}
	if !keyExists(fulfillment.RatingSignature.Metadata.RatingKey, contract.BuyerOrder.RatingKeys) {
		return errors.New("Rating key in vendor's rating signature is invalid")
	}

	pubkey, err := crypto.UnmarshalPublicKey(contract.VendorListings[0].VendorID.Pubkeys.Guid)
	if err != nil {
		return err
	}

	ser, err := proto.Marshal(fulfillment.RatingSignature.Metadata)
	if err != nil {
		return err
	}
	valid, err := pubkey.Verify(ser, fulfillment.RatingSignature.Signature)
	if err != nil || !valid {
		return errors.New("Failed to verify signature on rating keys")
	}

	if contract.BuyerOrder.Payment.Method == pb.Order_Payment_MODERATED {
		if fulfillment.Payout == nil {
			return errors.New("Payout object for multisig is nil")
		}
		_, err := btcutil.DecodeAddress(fulfillment.Payout.PayoutAddress, n.Wallet.Params())
		if err != nil {
			return errors.New("Invalid payout address")
		}
	}
	if n.IsFulfilled(contract) {
		var listingSlugs []string
		for _, listing := range contract.VendorListings {
			listingSlugs = append(listingSlugs, listing.Slug)
		}
		var ratingSlugs []string
		for _, fulfil := range contract.VendorOrderFulfillment {
			ratingSlugs = append(ratingSlugs, fulfil.RatingSignature.Metadata.ListingSlug)
		}
		for _, ls := range listingSlugs {
			if !slugExists(ls, ratingSlugs) {
				return errors.New("Vendor failed to send rating signatures covering all purchased listings")
			}
		}
		var vendorSignedKeys [][]byte
		for _, fulfil := range contract.VendorOrderFulfillment {
			vendorSignedKeys = append(vendorSignedKeys, fulfil.RatingSignature.Metadata.RatingKey)
		}
		for _, bk := range contract.BuyerOrder.RatingKeys {
			if !keyExists(bk, vendorSignedKeys) {
				return errors.New("Vendor failed to send rating signatures covering all ratingKeys")
			}
		}
	}
	return nil
}

func verifySignaturesOnOrderFulfilment(contract *pb.RicardianContract) error {
	for _, fulfil := range contract.VendorOrderFulfillment {
		if err := verifyMessageSignature(
			fulfil,
			contract.VendorListings[0].VendorID.Pubkeys.Guid,
			contract.Signatures,
			pb.Signature_ORDER_FULFILLMENT,
			contract.VendorListings[0].VendorID.Guid,
		); err != nil {
			switch err.(type) {
			case noSigError:
				return errors.New("Contract does not contain a signature for the order fulfilment")
			case invalidSigError:
				return errors.New("Vendor's guid signature on contact failed to verify")
			case matchKeyError:
				return errors.New("Public key in order does not match reported vendor ID")
			default:
				return err
			}
		}
	}
	return nil
}

func (n *OpenBazaarNode) IsFulfilled(contract *pb.RicardianContract) bool {
	if len(contract.VendorOrderFulfillment) < len(contract.VendorListings) {
		return false
	}
	return true
}
<commit_msg>Check slug on multiple item order<commit_after>package core

import (
	"bytes"
	"encoding/hex"
	"errors"
	crypto "gx/ipfs/QmPGxZ1DP2w45WcogpW1h43BvseXbfke9N91qotpoQcUeS/go-libp2p-crypto"

	"time"

	"github.com/OpenBazaar/openbazaar-go/pb"
	"github.com/OpenBazaar/spvwallet"
	"github.com/btcsuite/btcd/txscript"
	"github.com/btcsuite/btcutil"
	hd "github.com/btcsuite/btcutil/hdkeychain"
	"github.com/golang/protobuf/proto"
	"github.com/golang/protobuf/ptypes"
)

func (n *OpenBazaarNode) FulfillOrder(fulfillment *pb.OrderFulfillment, contract *pb.RicardianContract, records []*spvwallet.TransactionRecord) error {
	if fulfillment.Slug == "" && len(contract.VendorListings) == 1 {
		fulfillment.Slug = contract.VendorListings[0].Slug
	} else if fulfillment.Slug == "" && len(contract.VendorListings) > 1 {
		return errors.New("Slug must be specified when an order contains multiple items")
	}
	rc := new(pb.RicardianContract)
	if contract.BuyerOrder.Payment.Method == pb.Order_Payment_MODERATED {
		payout := new(pb.OrderFulfillment_Payout)
		payout.PayoutAddress = n.Wallet.CurrentAddress(spvwallet.EXTERNAL).EncodeAddress()
		payout.PayoutFeePerByte = n.Wallet.GetFeePerByte(spvwallet.NORMAL)
		var ins []spvwallet.TransactionInput
		var outValue int64
		for _, r := range records {
			if !r.Spent && r.Value > 0 {
				outpointHash, err := hex.DecodeString(r.Txid)
				if err != nil {
					return err
				}
				outValue += r.Value
				in := spvwallet.TransactionInput{OutpointIndex: r.Index, OutpointHash: outpointHash}
				ins = append(ins, in)
			}
		}

		refundAddress, err := btcutil.DecodeAddress(contract.BuyerOrder.RefundAddress, n.Wallet.Params())
		if err != nil {
			return err
		}
		var output spvwallet.TransactionOutput

		outputScript, err := txscript.PayToAddrScript(refundAddress)
		if err != nil {
			return err
		}
		output.ScriptPubKey = outputScript
		output.Value = outValue

		chaincode, err := hex.DecodeString(contract.BuyerOrder.Payment.Chaincode)
		if err != nil {
			return err
		}
		parentFP := []byte{0x00, 0x00, 0x00, 0x00}
		mPrivKey := n.Wallet.MasterPrivateKey()
		if err != nil {
			return err
		}
		mECKey, err := mPrivKey.ECPrivKey()
		if err != nil {
			return err
		}
		hdKey := hd.NewExtendedKey(
			n.Wallet.Params().HDPrivateKeyID[:],
			mECKey.Serialize(),
			chaincode,
			parentFP,
			0,
			0,
			true)

		vendorKey, err := hdKey.Child(0)
		if err != nil {
			return err
		}
		redeemScript, err := hex.DecodeString(contract.BuyerOrder.Payment.RedeemScript)

		signatures, err := n.Wallet.CreateMultisigSignature(ins, []spvwallet.TransactionOutput{output}, vendorKey, redeemScript, payout.PayoutFeePerByte)
		if err != nil {
			return err
		}
		var sigs []*pb.BitcoinSignature
		for _, s := range signatures {
			pbSig := &pb.BitcoinSignature{Signature: s.Signature, InputIndex: s.InputIndex}
			sigs = append(sigs, pbSig)
		}
		payout.Sigs = sigs
		fulfillment.Payout = payout
	}
	var keyIndex int
	for i, listing := range contract.VendorListings {
		if listing.Slug == fulfillment.Slug {
			keyIndex = i
			break
		}
	}

	ts, err := ptypes.TimestampProto(time.Now())
	if err != nil {
		return err
	}
	fulfillment.Timestamp = ts

	rs := new(pb.RatingSignature)
	metadata := new(pb.RatingSignature_TransactionMetadata)
	metadata.RatingKey = contract.BuyerOrder.RatingKeys[keyIndex]
	metadata.ListingSlug = fulfillment.Slug
	ser, err := proto.Marshal(metadata)
	if err != nil {
		return err
	}
	signature, err := n.IpfsNode.PrivateKey.Sign(ser)
	if err != nil {
		return err
	}
	rs.Metadata = metadata
	rs.Signature = signature

	fulfillment.RatingSignature = rs

	fulfils := []*pb.OrderFulfillment{}

	rc.VendorOrderFulfillment = append(fulfils, fulfillment)
	rc, err = n.SignOrderFulfillment(rc)
	if err != nil {
		return err
	}
	buyerkey, err := crypto.UnmarshalPublicKey(contract.BuyerOrder.BuyerID.Pubkeys.Guid)
	if err != nil {
		return err
	}
	err = n.SendOrderFulfillment(contract.BuyerOrder.BuyerID.Guid, &buyerkey, rc)
	if err != nil {
		return err
	}
	contract.VendorOrderFulfillment = append(contract.VendorOrderFulfillment, fulfillment)
	for _, sig := range rc.Signatures {
		if sig.Section == pb.Signature_ORDER_FULFILLMENT {
			contract.Signatures = append(contract.Signatures, sig)
		}
	}
	n.Datastore.Sales().Put(contract.VendorOrderConfirmation.OrderID, *contract, pb.OrderState_FULFILLED, false)
	return nil
}

func (n *OpenBazaarNode) SignOrderFulfillment(contract *pb.RicardianContract) (*pb.RicardianContract, error) {
	serializedOrderFulfil, err := proto.Marshal(contract.VendorOrderFulfillment[0])
	if err != nil {
		return contract, err
	}
	s := new(pb.Signature)
	s.Section = pb.Signature_ORDER_FULFILLMENT
	if err != nil {
		return contract, err
	}
	guidSig, err := n.IpfsNode.PrivateKey.Sign(serializedOrderFulfil)
	if err != nil {
		return contract, err
	}
	s.SignatureBytes = guidSig
	contract.Signatures = append(contract.Signatures, s)
	return contract, nil
}

func (n *OpenBazaarNode) ValidateOrderFulfillment(fulfillment *pb.OrderFulfillment, contract *pb.RicardianContract) error {
	if err := verifySignaturesOnOrderFulfilment(contract); err != nil {
		return err
	}

	slugExists := func(a string, list []string) bool {
		for _, b := range list {
			if b == a {
				return true
			}
		}
		return false
	}
	keyExists := func(a []byte, list [][]byte) bool {
		for _, b := range list {
			if bytes.Equal(b, a) {
				return true
			}
		}
		return false
	}

	var listingSlugs []string
	for _, listing := range contract.VendorListings {
		listingSlugs = append(listingSlugs, listing.Slug)
	}
	if !slugExists(fulfillment.Slug, listingSlugs) {
		return errors.New("Slug in rating signature does not exist in order")
	}
	if !keyExists(fulfillment.RatingSignature.Metadata.RatingKey, contract.BuyerOrder.RatingKeys) {
		return errors.New("Rating key in vendor's rating signature is invalid")
	}

	pubkey, err := crypto.UnmarshalPublicKey(contract.VendorListings[0].VendorID.Pubkeys.Guid)
	if err != nil {
		return err
	}

	ser, err := proto.Marshal(fulfillment.RatingSignature.Metadata)
	if err != nil {
		return err
	}
	valid, err := pubkey.Verify(ser, fulfillment.RatingSignature.Signature)
	if err != nil || !valid {
		return errors.New("Failed to verify signature on rating keys")
	}

	if contract.BuyerOrder.Payment.Method == pb.Order_Payment_MODERATED {
		if fulfillment.Payout == nil {
			return errors.New("Payout object for multisig is nil")
		}
		_, err := btcutil.DecodeAddress(fulfillment.Payout.PayoutAddress, n.Wallet.Params())
		if err != nil {
			return errors.New("Invalid payout address")
		}
	}
	if n.IsFulfilled(contract) {
		var listingSlugs []string
		for _, listing := range contract.VendorListings {
			listingSlugs = append(listingSlugs, listing.Slug)
		}
		var ratingSlugs []string
		for _, fulfil := range contract.VendorOrderFulfillment {
			ratingSlugs = append(ratingSlugs, fulfil.RatingSignature.Metadata.ListingSlug)
		}
		for _, ls := range listingSlugs {
			if !slugExists(ls, ratingSlugs) {
				return errors.New("Vendor failed to send rating signatures covering all purchased listings")
			}
		}
		var vendorSignedKeys [][]byte
		for _, fulfil := range contract.VendorOrderFulfillment {
			vendorSignedKeys = append(vendorSignedKeys, fulfil.RatingSignature.Metadata.RatingKey)
		}
		for _, bk := range contract.BuyerOrder.RatingKeys {
			if !keyExists(bk, vendorSignedKeys) {
				return errors.New("Vendor failed to send rating signatures covering all ratingKeys")
			}
		}
	}
	return nil
}

func verifySignaturesOnOrderFulfilment(contract *pb.RicardianContract) error {
	for _, fulfil := range contract.VendorOrderFulfillment {
		if err := verifyMessageSignature(
			fulfil,
			contract.VendorListings[0].VendorID.Pubkeys.Guid,
			contract.Signatures,
			pb.Signature_ORDER_FULFILLMENT,
			contract.VendorListings[0].VendorID.Guid,
		); err != nil {
			switch err.(type) {
			case noSigError:
				return errors.New("Contract does not contain a signature for the order fulfilment")
			case invalidSigError:
				return errors.New("Vendor's guid signature on contact failed to verify")
			case matchKeyError:
				return errors.New("Public key in order does not match reported vendor ID")
			default:
				return err
			}
		}
	}
	return nil
}

func (n *OpenBazaarNode) IsFulfilled(contract *pb.RicardianContract) bool {
	if len(contract.VendorOrderFulfillment) < len(contract.VendorListings) {
		return false
	}
	return true
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"flag"
	"fmt"
	"go/ast"
	"go/format"
	"go/parser"
	"go/token"
	"io/ioutil"
	"log"
	"os"
	"strings"
	"text/template"
)

var (
	importName = "__log"
	importPath = `"github.com/jbardin/gotrace/log"`

	importStmt = `
import __log "github.com/jbardin/gotrace/log"
`

	setup = `
var _ = __log.Setup("stderr", "%s ")
`

	tmpl = `
__traceID := __log.Next()
__log.L.Printf("[%d] {{.fname}}({{.formatters}}) \n", __traceID, {{.args}})
{{ if .return }}defer func() {
	__log.L.Printf("[%d] {{.fname}} returned\n", __traceID)
}(){{ end }}
`
)

var (
	funcTemplate *template.Template
	showReturn   bool
	exportedOnly bool
	prefix       string
	showPackage  bool
	writeFiles   bool
)

// return n '%v's for formatting
func formatters(n int) string {
	f := []string{}
	for i := 0; i < n; i++ {
		f = append(f, "%v")
	}
	return strings.Join(f, ", ")
}

// convert function parameters to a list of names
func paramNames(params *ast.FieldList) []string {
	var p []string
	for _, f := range params.List {
		for _, n := range f.Names {
			p = append(p, n.Name)
		}
	}
	return p
}

func debugCall(fName string, args ...string) []byte {
	vals := make(map[string]string)
	if len(args) > 0 {
		vals["formatters"] = formatters(len(args))
		vals["args"] = strings.Join(args, ", ")
	} else {
		vals["formatters"] = ""
		vals["args"] = ""
	}

	vals["fname"] = fName

	if showReturn {
		vals["return"] = "true"
	}

	var b bytes.Buffer
	err := funcTemplate.Execute(&b, vals)
	if err != nil {
		log.Fatal(err)
	}
	return b.Bytes()
}

type edit struct {
	pos int
	val []byte
}

type editList struct {
	edits       []edit
	packageName string
}

func (e *editList) Add(pos int, val []byte) {
	e.edits = append(e.edits, edit{pos: pos, val: val})
}

func (e *editList) inspect(node ast.Node) bool {
	if node == nil {
		return false
	}

	var funcType *ast.FuncType
	var body *ast.BlockStmt
	var funcName string

	switch n := node.(type) {
	case *ast.FuncDecl:
		body = n.Body
		if body == nil {
			return true
		}
		funcType = n.Type
		funcName = n.Name.Name

	case *ast.FuncLit:
		body = n.Body
		funcType = n.Type
		funcName = "func"

	default:
		return true
	}

	if exportedOnly && !ast.IsExported(funcName) {
		return true
	}

	if showPackage {
		funcName = e.packageName + "." + funcName
	}

	e.Add(int(body.Lbrace), debugCall(funcName, paramNames(funcType.Params)...))

	return true
}

func annotate(file string) {
	fset := token.NewFileSet()
	f, err := parser.ParseFile(fset, file, nil, parser.ParseComments)
	if err != nil {
		panic(err)
	}

	for _, imp := range f.Imports {
		if imp.Name != nil && imp.Name.Name == importName {
			log.Printf(`"%s" already imported. skipping %s`, importName, file)
			return
		}
		if imp.Path.Value == importPath {
			log.Printf(`"%s", already imported. skipping %s`, importPath, file)
			return
		}
	}

	edits := editList{packageName: f.Name.Name}

	// insert our import directly after the package line
	edits.Add(int(f.Name.End()), []byte(importStmt))

	ast.Inspect(f, edits.inspect)

	var buf bytes.Buffer
	if err := format.Node(&buf, fset, f); err != nil {
		panic(err)
	}

	data := buf.Bytes()

	var pos int
	var out []byte
	for _, e := range edits.edits {
		out = append(out, data[pos:e.pos]...)
		out = append(out, []byte(e.val)...)
		pos = e.pos
	}
	out = append(out, data[pos:]...)

	// it's easier to append the setup code at the end
	out = append(out, []byte(setup)...)

	src, err := format.Source(out)
	if err != nil {
		panic(err)
	}

	if !writeFiles {
		fmt.Println(string(src))
		return
	}

	err = ioutil.WriteFile(file, src, 0)
	if err != nil {
		log.Fatal(err)
	}
}

func init() {
	funcTemplate = template.Must(template.New("debug").Parse(tmpl))
}

func main() {
	flag.BoolVar(&showReturn, "returns", false, "show function return")
	flag.BoolVar(&exportedOnly, "exported", false, "only annotate exported functions")
	flag.StringVar(&prefix, "prefix", "\t", "log prefix")
	flag.BoolVar(&showPackage, "package", false, "show package name prefix on function calls")
	flag.BoolVar(&writeFiles, "w", false, "re-write files in place")
	flag.Parse()

	if flag.NArg() < 1 {
		flag.PrintDefaults()
		os.Exit(1)
	}

	setup = fmt.Sprintf(setup, prefix)

	for _, file := range flag.Args() {
		annotate(file)
	}
}
<commit_msg>get rid of panics<commit_after>package main

import (
	"bytes"
	"flag"
	"fmt"
	"go/ast"
	"go/format"
	"go/parser"
	"go/token"
	"io/ioutil"
	"log"
	"os"
	"strings"
	"text/template"
)

var (
	importName = "__log"
	importPath = `"github.com/jbardin/gotrace/log"`

	importStmt = `
import __log "github.com/jbardin/gotrace/log"
`

	setup = `
var _ = __log.Setup("stderr", "%s ")
`

	tmpl = `
__traceID := __log.Next()
__log.L.Printf("[%d] {{.fname}}({{.formatters}}) \n", __traceID, {{.args}})
{{ if .return }}defer func() {
	__log.L.Printf("[%d] {{.fname}} returned\n", __traceID)
}(){{ end }}
`
)

var (
	funcTemplate *template.Template
	showReturn   bool
	exportedOnly bool
	prefix       string
	showPackage  bool
	writeFiles   bool
)

// return n '%v's for formatting
func formatters(n int) string {
	f := []string{}
	for i := 0; i < n; i++ {
		f = append(f, "%v")
	}
	return strings.Join(f, ", ")
}

// convert function parameters to a list of names
func paramNames(params *ast.FieldList) []string {
	var p []string
	for _, f := range params.List {
		for _, n := range f.Names {
			p = append(p, n.Name)
		}
	}
	return p
}

func debugCall(fName string, args ...string) []byte {
	vals := make(map[string]string)
	if len(args) > 0 {
		vals["formatters"] = formatters(len(args))
		vals["args"] = strings.Join(args, ", ")
	} else {
		vals["formatters"] = ""
		vals["args"] = ""
	}

	vals["fname"] = fName

	if showReturn {
		vals["return"] = "true"
	}

	var b bytes.Buffer
	err := funcTemplate.Execute(&b, vals)
	if err != nil {
		log.Fatal(err)
	}
	return b.Bytes()
}

type edit struct {
	pos int
	val []byte
}

type editList struct {
	edits       []edit
	packageName string
}

func (e *editList) Add(pos int, val []byte) {
	e.edits = append(e.edits, edit{pos: pos, val: val})
}

func (e *editList) inspect(node ast.Node) bool {
	if node == nil {
		return false
	}

	var funcType *ast.FuncType
	var body *ast.BlockStmt
	var funcName string

	switch n := node.(type) {
	case *ast.FuncDecl:
		body = n.Body
		if body == nil {
			return true
		}
		funcType = n.Type
		funcName = n.Name.Name

	case *ast.FuncLit:
		body = n.Body
		funcType = n.Type
		funcName = "func"

	default:
		return true
	}

	if exportedOnly && !ast.IsExported(funcName) {
		return true
	}

	if showPackage {
		funcName = e.packageName + "." + funcName
	}

	e.Add(int(body.Lbrace), debugCall(funcName, paramNames(funcType.Params)...))

	return true
}

func annotate(file string) {
	fset := token.NewFileSet()
	f, err := parser.ParseFile(fset, file, nil, parser.ParseComments)
	if err != nil {
		log.Fatal(err)
	}

	for _, imp := range f.Imports {
		if imp.Name != nil && imp.Name.Name == importName {
			log.Printf(`"%s" already imported. skipping %s`, importName, file)
			return
		}
		if imp.Path.Value == importPath {
			log.Printf(`"%s", already imported. skipping %s`, importPath, file)
			return
		}
	}

	edits := editList{packageName: f.Name.Name}

	// insert our import directly after the package line
	edits.Add(int(f.Name.End()), []byte(importStmt))

	ast.Inspect(f, edits.inspect)

	var buf bytes.Buffer
	if err := format.Node(&buf, fset, f); err != nil {
		log.Fatal(err)
	}

	data := buf.Bytes()

	var pos int
	var out []byte
	for _, e := range edits.edits {
		out = append(out, data[pos:e.pos]...)
		out = append(out, []byte(e.val)...)
		pos = e.pos
	}
	out = append(out, data[pos:]...)

	// it's easier to append the setup code at the end
	out = append(out, []byte(setup)...)

	src, err := format.Source(out)
	if err != nil {
		log.Fatal(err)
	}

	if !writeFiles {
		fmt.Println(string(src))
		return
	}

	err = ioutil.WriteFile(file, src, 0)
	if err != nil {
		log.Fatal(err)
	}
}

func init() {
	funcTemplate = template.Must(template.New("debug").Parse(tmpl))
}

func main() {
	flag.BoolVar(&showReturn, "returns", false, "show function return")
	flag.BoolVar(&exportedOnly, "exported", false, "only annotate exported functions")
	flag.StringVar(&prefix, "prefix", "\t", "log prefix")
	flag.BoolVar(&showPackage, "package", false, "show package name prefix on function calls")
	flag.BoolVar(&writeFiles, "w", false, "re-write files in place")
	flag.Parse()

	if flag.NArg() < 1 {
		flag.PrintDefaults()
		os.Exit(1)
	}

	setup = fmt.Sprintf(setup, prefix)

	for _, file := range flag.Args() {
		annotate(file)
	}
}
<|endoftext|>


<commit_before>package coremain

// Various CoreDNS constants.
const (
	CoreVersion = "1.6.6"
	coreName    = "CoreDNS"
	serverType  = "dns"
)
<commit_msg>Bump version to 1.6.7 (#3594)<commit_after>package coremain

// Various CoreDNS constants.
const (
	CoreVersion = "1.6.7"
	coreName    = "CoreDNS"
	serverType  = "dns"
)
<|endoftext|>