<commit_before>package router

import (
	"crypto/sha1"
	"errors"
	"fmt"
	"io"
	"log"
	"net/url"
	"os"
	"strconv"
	"strings"
	"sync"
	"time"
)

var Routes *RouteManager

func init() {
	Routes = &RouteManager{routes: make(map[string]*Route)}
	Jobs.Register(Routes, "routes")
}

type RouteManager struct {
	sync.Mutex
	persistor RouteStore
	routes    map[string]*Route
	routing   bool
}

func (rm *RouteManager) Load(persistor RouteStore) error {
	routes, err := persistor.GetAll()
	if err != nil {
		return err
	}
	for _, route := range routes {
		rm.Add(route)
	}
	rm.persistor = persistor
	return nil
}

func (rm *RouteManager) Get(id string) (*Route, error) {
	rm.Lock()
	defer rm.Unlock()
	route, ok := rm.routes[id]
	if !ok {
		return nil, os.ErrNotExist
	}
	return route, nil
}

func (rm *RouteManager) GetAll() ([]*Route, error) {
	rm.Lock()
	defer rm.Unlock()
	routes := make([]*Route, 0)
	for _, route := range rm.routes {
		routes = append(routes, route)
	}
	return routes, nil
}

func (rm *RouteManager) Remove(id string) bool {
	rm.Lock()
	defer rm.Unlock()
	route, ok := rm.routes[id]
	if ok && route.closer != nil {
		route.closer <- true
	}
	delete(rm.routes, id)
	if rm.persistor != nil {
		rm.persistor.Remove(id)
	}
	return ok
}

func (rm *RouteManager) AddFromUri(uri string) error {
	expandedRoute := os.ExpandEnv(uri)
	u, err := url.Parse(expandedRoute)
	if err != nil {
		return err
	}
	r := &Route{
		Address: u.Host,
		Adapter: u.Scheme,
	}
	if u.RawQuery != "" {
		params, err := url.ParseQuery(u.RawQuery)
		if err != nil {
			return err
		}
		for key, _ := range params {
			value := params.Get(key)
			switch key {
			case "filter.id":
				r.FilterID = value
			case "filter.name":
				r.FilterName = value
			case "filter.sources":
				r.FilterSources = strings.Split(value, ",")
			default:
				r.Options[key] = value
			}
		}
	}
	return rm.Add(r)
}

func (rm *RouteManager) Add(route *Route) error {
	rm.Lock()
	defer rm.Unlock()
	factory, found := AdapterFactories.Lookup(route.AdapterType())
	if !found {
		return errors.New("bad adapter: " + route.Adapter)
	}
	adapter, err := factory(route)
	if err != nil {
		return err
	}
	if route.ID == "" {
		h := sha1.New()
		io.WriteString(h, strconv.Itoa(int(time.Now().UnixNano())))
		route.ID = fmt.Sprintf("%x", h.Sum(nil))[:12]
	}
	route.closer = make(chan bool)
	route.adapter = adapter
	rm.routes[route.ID] = route
	if rm.persistor != nil {
		if err := rm.persistor.Add(route); err != nil {
			log.Println("persistor:", err)
		}
	}
	if rm.routing {
		go rm.route(route)
	}
	return nil
}

func (rm *RouteManager) route(route *Route) {
	logstream := make(chan *Message)
	defer route.Close()
	rm.Route(route, logstream)
	route.adapter.Stream(logstream)
}

func (rm *RouteManager) Route(route *Route, logstream chan *Message) {
	for _, router := range LogRouters.All() {
		go router.Route(route, logstream)
	}
}

func (rm *RouteManager) RoutingFrom(containerID string) bool {
	routing := false
	for _, router := range LogRouters.All() {
		routing = routing || router.RoutingFrom(containerID)
	}
	return routing
}

func (rm *RouteManager) Run() error {
	rm.Lock()
	for _, route := range rm.routes {
		go rm.route(route)
	}
	rm.routing = true
	rm.Unlock()
	select {}
}

func (rm *RouteManager) Name() string {
	return ""
}

func (rm *RouteManager) Setup() error {
	var uris string
	if os.Getenv("ROUTE_URIS") != "" {
		uris = os.Getenv("ROUTE_URIS")
	}
	if len(os.Args) > 1 {
		uris = os.Args[1]
	}
	if uris != "" {
		for _, uri := range strings.Split(uris, ",") {
			err := rm.AddFromUri(uri)
			if err != nil {
				return err
			}
		}
	}

	persistPath := getopt("ROUTESPATH", "/mnt/routes")
	if _, err := os.Stat(persistPath); err == nil {
		return rm.Load(RouteFileStore(persistPath))
	}
	return nil
}
<commit_msg>Simplify and add early exit to RoutingFrom<commit_after>package router

import (
	"crypto/sha1"
	"errors"
	"fmt"
	"io"
	"log"
	"net/url"
	"os"
	"strconv"
	"strings"
	"sync"
	"time"
)

var Routes *RouteManager

func init() {
	Routes = &RouteManager{routes: make(map[string]*Route)}
	Jobs.Register(Routes, "routes")
}

type RouteManager struct {
	sync.Mutex
	persistor RouteStore
	routes    map[string]*Route
	routing   bool
}

func (rm *RouteManager) Load(persistor RouteStore) error {
	routes, err := persistor.GetAll()
	if err != nil {
		return err
	}
	for _, route := range routes {
		rm.Add(route)
	}
	rm.persistor = persistor
	return nil
}

func (rm *RouteManager) Get(id string) (*Route, error) {
	rm.Lock()
	defer rm.Unlock()
	route, ok := rm.routes[id]
	if !ok {
		return nil, os.ErrNotExist
	}
	return route, nil
}

func (rm *RouteManager) GetAll() ([]*Route, error) {
	rm.Lock()
	defer rm.Unlock()
	routes := make([]*Route, 0)
	for _, route := range rm.routes {
		routes = append(routes, route)
	}
	return routes, nil
}

func (rm *RouteManager) Remove(id string) bool {
	rm.Lock()
	defer rm.Unlock()
	route, ok := rm.routes[id]
	if ok && route.closer != nil {
		route.closer <- true
	}
	delete(rm.routes, id)
	if rm.persistor != nil {
		rm.persistor.Remove(id)
	}
	return ok
}

func (rm *RouteManager) AddFromUri(uri string) error {
	expandedRoute := os.ExpandEnv(uri)
	u, err := url.Parse(expandedRoute)
	if err != nil {
		return err
	}
	r := &Route{
		Address: u.Host,
		Adapter: u.Scheme,
	}
	if u.RawQuery != "" {
		params, err := url.ParseQuery(u.RawQuery)
		if err != nil {
			return err
		}
		for key, _ := range params {
			value := params.Get(key)
			switch key {
			case "filter.id":
				r.FilterID = value
			case "filter.name":
				r.FilterName = value
			case "filter.sources":
				r.FilterSources = strings.Split(value, ",")
			default:
				r.Options[key] = value
			}
		}
	}
	return rm.Add(r)
}

func (rm *RouteManager) Add(route *Route) error {
	rm.Lock()
	defer rm.Unlock()
	factory, found := AdapterFactories.Lookup(route.AdapterType())
	if !found {
		return errors.New("bad adapter: " + route.Adapter)
	}
	adapter, err := factory(route)
	if err != nil {
		return err
	}
	if route.ID == "" {
		h := sha1.New()
		io.WriteString(h, strconv.Itoa(int(time.Now().UnixNano())))
		route.ID = fmt.Sprintf("%x", h.Sum(nil))[:12]
	}
	route.closer = make(chan bool)
	route.adapter = adapter
	rm.routes[route.ID] = route
	if rm.persistor != nil {
		if err := rm.persistor.Add(route); err != nil {
			log.Println("persistor:", err)
		}
	}
	if rm.routing {
		go rm.route(route)
	}
	return nil
}

func (rm *RouteManager) route(route *Route) {
	logstream := make(chan *Message)
	defer route.Close()
	rm.Route(route, logstream)
	route.adapter.Stream(logstream)
}

func (rm *RouteManager) Route(route *Route, logstream chan *Message) {
	for _, router := range LogRouters.All() {
		go router.Route(route, logstream)
	}
}

func (rm *RouteManager) RoutingFrom(containerID string) bool {
	for _, router := range LogRouters.All() {
		if router.RoutingFrom(containerID) {
			return true
		}
	}
	return false
}

func (rm *RouteManager) Run() error {
	rm.Lock()
	for _, route := range rm.routes {
		go rm.route(route)
	}
	rm.routing = true
	rm.Unlock()
	select {}
}

func (rm *RouteManager) Name() string {
	return ""
}

func (rm *RouteManager) Setup() error {
	var uris string
	if os.Getenv("ROUTE_URIS") != "" {
		uris = os.Getenv("ROUTE_URIS")
	}
	if len(os.Args) > 1 {
		uris = os.Args[1]
	}
	if uris != "" {
		for _, uri := range strings.Split(uris, ",") {
			err := rm.AddFromUri(uri)
			if err != nil {
				return err
			}
		}
	}

	persistPath := getopt("ROUTESPATH", "/mnt/routes")
	if _, err := os.Stat(persistPath); err == nil {
		return rm.Load(RouteFileStore(persistPath))
	}
	return nil
}
<|endoftext|>


<commit_before>/*
	Go Language Raspberry Pi Interface
	(c) Copyright David Thorpe 2016
	All Rights Reserved

	For Licensing and Usage information, please see LICENSE.md
*/
package egl

import (
	"fmt"
)

/* TYPES */
type Error struct {
	msg  string // description of error
	code int32  // error code
}

/* CONSTANTS */
const (
	SUCCESS             = 0x3000
	NOT_INITIALIZED     = 0x3001
	BAD_ACCESS          = 0x3002
	BAD_ALLOC           = 0x3003
	BAD_ATTRIBUTE       = 0x3004
	BAD_CONFIG          = 0x3005
	BAD_CONTEXT         = 0x3006
	BAD_CURRENT_SURFACE = 0x3007
	BAD_DISPLAY         = 0x3008
	BAD_MATCH           = 0x3009
	BAD_NATIVE_PIXMAP   = 0x300A
	BAD_NATIVE_WINDOW   = 0x300B
	BAD_PARAMETER       = 0x300C
	BAD_SURFACE         = 0x300D
	CONTEXT_LOST        = 0x300E
)

/* METHODS */
func (e *Error) Error() string {
	return e.msg
}

func toError(code int32) *Error {
	switch code {
	case SUCCESS:
		return &Error{"Success", code}
	case NOT_INITIALIZED:
		return &Error{"Not Initialized", code}
	case BAD_ACCESS:
		return &Error{"Bad Access", code}
	case BAD_ALLOC:
		return &Error{"Bad Memory Allocation", code}
	case BAD_ATTRIBUTE:
		return &Error{"Bad Attribute", code}
	case BAD_CONFIG:
		return &Error{"Bad Configuration", code}
	case BAD_CONTEXT:
		return &Error{"Bad Context", code}
	case BAD_CURRENT_SURFACE:
		return &Error{"Bad Current Surface", code}
	case BAD_DISPLAY:
		return &Error{"Bad Display", code}
	case BAD_MATCH:
		return &Error{"Bad Match", code}
	case BAD_NATIVE_PIXMAP:
		return &Error{"Bad Native Pixmap", code}
	case BAD_NATIVE_WINDOW:
		return &Error{"Bad Native Window", code}
	case BAD_PARAMETER:
		return &Error{"Bad Parameter", code}
	case BAD_SURFACE:
		return &Error{"Bad Surface", code}
	case CONTEXT_LOST:
		return &Error{"Context Lost", code}
	default:
		return &Error{fmt.Sprintf("Other Error 0x%04X", code), code}
	}
}
<commit_msg>Updated<commit_after>/*
	Go Language Raspberry Pi Interface
	(c) Copyright David Thorpe 2016
	All Rights Reserved

	For Licensing and Usage information, please see LICENSE.md
*/
package egl

import (
	"fmt"
)

/* TYPES */
type Error struct {
	msg  string // description of error
	code int32  // error code
}

/* CONSTANTS */
const (
	SUCCESS             = 0x3000
	NOT_INITIALIZED     = 0x3001
	BAD_ACCESS          = 0x3002
	BAD_ALLOC           = 0x3003
	BAD_ATTRIBUTE       = 0x3004
	BAD_CONFIG          = 0x3005
	BAD_CONTEXT         = 0x3006
	BAD_CURRENT_SURFACE = 0x3007
	BAD_DISPLAY         = 0x3008
	BAD_MATCH           = 0x3009
	BAD_NATIVE_PIXMAP   = 0x300A
	BAD_NATIVE_WINDOW   = 0x300B
	BAD_PARAMETER       = 0x300C
	BAD_SURFACE         = 0x300D
	CONTEXT_LOST        = 0x300E
)

/* METHODS */
func (e *Error) Error() string {
	return fmt.Sprintf("%s (egl/%04X)",e.msg,e.code)
}

func toError(code int32) *Error {
	switch code {
	case SUCCESS:
		return &Error{"Success", code}
	case NOT_INITIALIZED:
		return &Error{"Not Initialized", code}
	case BAD_ACCESS:
		return &Error{"Bad Access", code}
	case BAD_ALLOC:
		return &Error{"Bad Memory Allocation", code}
	case BAD_ATTRIBUTE:
		return &Error{"Bad Attribute", code}
	case BAD_CONFIG:
		return &Error{"Bad Configuration", code}
	case BAD_CONTEXT:
		return &Error{"Bad Context", code}
	case BAD_CURRENT_SURFACE:
		return &Error{"Bad Current Surface", code}
	case BAD_DISPLAY:
		return &Error{"Bad Display", code}
	case BAD_MATCH:
		return &Error{"Bad Match", code}
	case BAD_NATIVE_PIXMAP:
		return &Error{"Bad Native Pixmap", code}
	case BAD_NATIVE_WINDOW:
		return &Error{"Bad Native Window", code}
	case BAD_PARAMETER:
		return &Error{"Bad Parameter", code}
	case BAD_SURFACE:
		return &Error{"Bad Surface", code}
	case CONTEXT_LOST:
		return &Error{"Context Lost", code}
	default:
		return &Error{"General Error", code}
	}
}
<|endoftext|>


<commit_before>package rtm

import (
	"testing"

	"github.com/firba1/slack"

	"github.com/firba1/util/assert"
	"github.com/gorilla/websocket"
)

func TestUnescapeMessage(t *testing.T) {
	tests := []struct {
		in  string
		out string
	}{
		// HTML entity replacements
		{"Simon & Garfunkel", "Simon & Garfunkel"},
		{"Independence Day > Stargate", "Independence Day > Stargate"},
		{"):<", "):<"},
		// existing user
		{"<@U123A56BC>++", "@fart++"},
		// user with an alias
		{"<@U123A56BC|butt>++", "@butt++"},
		// unrecognized user
		{"<@UXYZ987WV>++", "<@UXYZ987WV>++"},
	}

	conn, err := Dialer{
		rtmStartFunc: func(token string) (*websocket.Conn, slack.RTMStartInfo, error) {
			rtmStartInfo := slack.RTMStartInfo{
				Users: []slack.User{
					slack.User{
						ID:   "U123A56BC",
						Name: "fart",
					},
				},
			}
			return nil, rtmStartInfo, nil
		},
	}.Dial("")
	assert.NilError(t, err)

	for _, test := range tests {
		assert.Equal(t, conn.UnescapeMessage(test.in), test.out)
	}
}

func TestParseEscapeType(t *testing.T) {
	tests := []struct {
		in  string
		out int
	}{
		{"@U123A56BC", userEscape},
		{"#C789D01EF", channelEscape},
		{"!everyone", commandEscape},
		{"http://www.facebook.com/prenis", linkEscape},
	}

	for _, test := range tests {
		assert.Equal(t, parseEscapeType(test.in), test.out)
	}
}
<commit_msg>Added test for UserInfo with updates.<commit_after>package rtm

import (
	"testing"

	"github.com/firba1/slack"

	"github.com/firba1/util/assert"
	"github.com/gorilla/websocket"
)

func TestUnescapeMessage(t *testing.T) {
	tests := []struct {
		in  string
		out string
	}{
		// HTML entity replacements
		{"Simon & Garfunkel", "Simon & Garfunkel"},
		{"Independence Day > Stargate", "Independence Day > Stargate"},
		{"):<", "):<"},
		// existing user
		{"<@U123A56BC>++", "@fart++"},
		// user with an alias
		{"<@U123A56BC|butt>++", "@butt++"},
		// unrecognized user
		{"<@UXYZ987WV>++", "<@UXYZ987WV>++"},
	}

	conn, err := Dialer{
		rtmStartFunc: func(token string) (*websocket.Conn, slack.RTMStartInfo, error) {
			rtmStartInfo := slack.RTMStartInfo{
				Users: []slack.User{
					slack.User{
						ID:   "U123A56BC",
						Name: "fart",
					},
				},
			}
			return nil, rtmStartInfo, nil
		},
	}.Dial("")
	assert.NilError(t, err)

	for _, test := range tests {
		assert.Equal(t, conn.UnescapeMessage(test.in), test.out)
	}
}

func TestUserInfoWithUpdates(t *testing.T) {
	conn, err := Dialer{
		rtmStartFunc: func(token string) (*websocket.Conn, slack.RTMStartInfo, error) {
			return nil, slack.RTMStartInfo{}, nil
		},
	}.Dial("")
	assert.NilError(t, err)

	assert.Equal(t, conn.UserInfo("U123"), slack.User{})

	user := slack.User{ID: "U123", Name: "butt fart"}
	conn.userChanges <- user

	assert.Equal(t, conn.UserInfo("U123"), user)
}

func TestParseEscapeType(t *testing.T) {
	tests := []struct {
		in  string
		out int
	}{
		{"@U123A56BC", userEscape},
		{"#C789D01EF", channelEscape},
		{"!everyone", commandEscape},
		{"http://www.facebook.com/prenis", linkEscape},
	}

	for _, test := range tests {
		assert.Equal(t, parseEscapeType(test.in), test.out)
	}
}
<|endoftext|>


<commit_before>package cmd_linkedapp

import (
	"flag"
	"github.com/watermint/toolbox/cmd"
	"github.com/watermint/toolbox/model/dbx_api"
	"github.com/watermint/toolbox/model/dbx_team"
	"github.com/watermint/toolbox/report"
)

type CmdMemberLinkedAppList struct {
	*cmd.SimpleCommandlet

	apiContext *dbx_api.Context
	report     report.Factory
}

func (CmdMemberLinkedAppList) Name() string {
	return "list"
}

func (CmdMemberLinkedAppList) Desc() string {
	return "List all applications linked to the team members' accounts"
}

func (CmdMemberLinkedAppList) Usage() string {
	return ""
}

func (c *CmdMemberLinkedAppList) FlagConfig(f *flag.FlagSet) {
	c.report.FlagConfig(f)
}

func (c *CmdMemberLinkedAppList) Exec(args []string) {
	apiFile, err := c.ExecContext.LoadOrAuthBusinessFile()
	if err != nil {
		return
	}

	c.report.Init(c.Log())
	defer c.report.Close()

	l := dbx_team.LinkedAppList{
		OnError: c.DefaultErrorHandler,
		OnEntry: func(app *dbx_team.LinkedApp) bool {
			c.report.Report(app)
			return true
		},
	}
	l.List(apiFile)
}
<commit_msg>list app enhancement<commit_after>package cmd_linkedapp

import (
	"flag"
	"github.com/tidwall/gjson"
	"github.com/watermint/toolbox/cmd"
	"github.com/watermint/toolbox/model/dbx_api"
	"github.com/watermint/toolbox/model/dbx_member"
	"github.com/watermint/toolbox/model/dbx_profile"
	"github.com/watermint/toolbox/model/dbx_team"
	"github.com/watermint/toolbox/report"
)

type CmdMemberLinkedAppList struct {
	*cmd.SimpleCommandlet

	apiContext         *dbx_api.Context
	OptWithMemberEmail bool
	report             report.Factory
}

func (CmdMemberLinkedAppList) Name() string {
	return "list"
}

func (CmdMemberLinkedAppList) Desc() string {
	return "List all applications linked to the team members' accounts"
}

func (CmdMemberLinkedAppList) Usage() string {
	return ""
}

func (z *CmdMemberLinkedAppList) FlagConfig(f *flag.FlagSet) {
	z.report.FlagConfig(f)

	descWithEmail := "Export report with team member email"
	f.BoolVar(&z.OptWithMemberEmail, "with-email", false, descWithEmail)
}

func (z *CmdMemberLinkedAppList) Exec(args []string) {
	apiFile, err := z.ExecContext.LoadOrAuthBusinessFile()
	if err != nil {
		return
	}

	z.report.Init(z.Log())
	defer z.report.Close()

	if z.OptWithMemberEmail {
		z.withMemberReport(apiFile)
	} else {
		z.plainReport(apiFile)
	}
}

func (z *CmdMemberLinkedAppList) plainReport(apiFile *dbx_api.Context) {
	l := dbx_team.LinkedAppList{
		OnError: z.DefaultErrorHandler,
		OnEntry: func(app *dbx_team.LinkedApp) bool {
			z.report.Report(app)
			return true
		},
	}
	l.List(apiFile)
}

func (z *CmdMemberLinkedAppList) withMemberReport(apiFile *dbx_api.Context) {
	z.Log().Info("Prepare for expand members")
	members := make(map[string]*dbx_profile.Member)
	lm := dbx_member.MembersList{
		OnError: z.DefaultErrorHandler,
		OnEntry: func(member *dbx_profile.Member) bool {
			members[member.Profile.TeamMemberId] = member
			return true
		},
	}
	if !lm.List(apiFile, false) {
		return
	}

	z.Log().Info("Listing App information")

	type App struct {
		TeamMemberId    string `json:"team_member_id"`
		TeamMemberEmail string `json:"team_member_email"`
		AppId           string `json:"app_id"`
		AppName         string `json:"app_name"`
		Publisher       string `json:"publisher"`
		PublisherUrl    string `json:"publisher_url"`
		IsAppFolder     bool   `json:"is_app_folder"`
		Linked          string `json:"linked"`
	}

	l := dbx_team.LinkedAppList{
		OnError: z.DefaultErrorHandler,
		OnEntry: func(app *dbx_team.LinkedApp) bool {
			email := ""
			if m, ok := members[app.TeamMemberId]; ok {
				email = m.Profile.Email
			}
			json := gjson.ParseBytes(app.LinkedApiApp)
			a := App{
				TeamMemberId:    app.TeamMemberId,
				TeamMemberEmail: email,
				AppId:           app.LinkedApiAppId,
				AppName:         json.Get("app_name").String(),
				Publisher:       json.Get("publisher").String(),
				PublisherUrl:    json.Get("publisher_url").String(),
				IsAppFolder:     json.Get("is_app_folder").Bool(),
				Linked:          json.Get("linked").String(),
			}
			z.report.Report(a)
			return true
		},
	}
	l.List(apiFile)
}
<|endoftext|>


<commit_before>/*
 * This file is part of the KubeVirt project
 *
 * 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.
 *
 * Copyright 2017, 2018 Red Hat, Inc.
 *
 */

package main

import (
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"syscall"
	"time"

	"github.com/libvirt/libvirt-go"
	"github.com/spf13/pflag"
	utilwait "k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/apimachinery/pkg/watch"

	"kubevirt.io/kubevirt/pkg/api/v1"
	cloudinit "kubevirt.io/kubevirt/pkg/cloud-init"
	ephemeraldisk "kubevirt.io/kubevirt/pkg/ephemeral-disk"
	"kubevirt.io/kubevirt/pkg/log"
	registrydisk "kubevirt.io/kubevirt/pkg/registry-disk"
	cmdclient "kubevirt.io/kubevirt/pkg/virt-handler/cmd-client"
	virtlauncher "kubevirt.io/kubevirt/pkg/virt-launcher"
	notifyclient "kubevirt.io/kubevirt/pkg/virt-launcher/notify-client"
	"kubevirt.io/kubevirt/pkg/virt-launcher/virtwrap"
	virtcli "kubevirt.io/kubevirt/pkg/virt-launcher/virtwrap/cli"
	cmdserver "kubevirt.io/kubevirt/pkg/virt-launcher/virtwrap/cmd-server"
	"kubevirt.io/kubevirt/pkg/virt-launcher/virtwrap/util"
	watchdog "kubevirt.io/kubevirt/pkg/watchdog"
)

const defaultStartTimeout = 3 * time.Minute
const defaultWatchdogInterval = 5 * time.Second

func markReady(readinessFile string) {
	f, err := os.OpenFile(readinessFile, os.O_RDONLY|os.O_CREATE, 0666)
	if err != nil {
		panic(err)
	}
	f.Close()
	log.Log.Info("Marked as ready")
}

func startCmdServer(socketPath string,
	domainManager virtwrap.DomainManager,
	stopChan chan struct{},
	options *cmdserver.ServerOptions) {

	err := os.RemoveAll(socketPath)
	if err != nil {
		log.Log.Reason(err).Error("Could not clean up virt-launcher cmd socket")
		panic(err)
	}

	err = os.MkdirAll(filepath.Dir(socketPath), 0755)
	if err != nil {
		log.Log.Reason(err).Error("Could not create directory for socket.")
		panic(err)
	}

	err = cmdserver.RunServer(socketPath, domainManager, stopChan, options)
	if err != nil {
		log.Log.Reason(err).Error("Failed to start virt-launcher cmd server")
		panic(err)
	}

	// ensure the cmdserver is responsive before continuing
	// PollImmediate breaks the poll loop when bool or err are returned OR if timeout occurs.
	//
	// Timing out causes an error to be returned
	err = utilwait.PollImmediate(1*time.Second, 15*time.Second, func() (bool, error) {
		client, err := cmdclient.GetClient(socketPath)
		if err != nil {
			return false, nil
		}

		err = client.Ping()
		if err != nil {
			return false, nil
		}
		return true, nil
	})

	if err != nil {
		panic(fmt.Errorf("failed to connect to cmd server: %v", err))
	}
}

func createLibvirtConnection() virtcli.Connection {
	libvirtUri := "qemu:///system"
	domainConn, err := virtcli.NewConnection(libvirtUri, "", "", 10*time.Second)
	if err != nil {
		panic(fmt.Sprintf("failed to connect to libvirtd: %v", err))
	}

	return domainConn
}

func startDomainEventMonitoring(virtShareDir string, domainConn virtcli.Connection, deleteNotificationSent chan watch.Event) {
	libvirt.EventRegisterDefaultImpl()

	go func() {
		for {
			if res := libvirt.EventRunDefaultImpl(); res != nil {
				log.Log.Reason(res).Error("Listening to libvirt events failed, retrying.")
				time.Sleep(time.Second)
			}
		}
	}()

	err := notifyclient.StartNotifier(virtShareDir, domainConn, deleteNotificationSent)
	if err != nil {
		panic(err)
	}

}

func startWatchdogTicker(watchdogFile string, watchdogInterval time.Duration, stopChan chan struct{}) {
	err := watchdog.WatchdogFileUpdate(watchdogFile)
	if err != nil {
		panic(err)
	}

	log.Log.Infof("Watchdog file created at %s", watchdogFile)

	go func() {

		ticker := time.NewTicker(watchdogInterval).C
		for {
			select {
			case <-stopChan:
				return
			case <-ticker:
				err := watchdog.WatchdogFileUpdate(watchdogFile)
				if err != nil {
					panic(err)
				}
			}
		}
	}()
}

func initializeDirs(virtShareDir string,
	ephemeralDiskDir string,
	namespace string,
	name string) {

	err := virtlauncher.InitializeSharedDirectories(virtShareDir)
	if err != nil {
		panic(err)
	}

	err = virtlauncher.InitializePrivateDirectories(filepath.Join("/var/run/kubevirt-private", namespace, name))
	if err != nil {
		panic(err)
	}

	err = cloudinit.SetLocalDirectory(ephemeralDiskDir + "/cloud-init-data")
	if err != nil {
		panic(err)
	}

	err = registrydisk.SetLocalDirectory(ephemeralDiskDir + "/registry-disk-data")
	if err != nil {
		panic(err)
	}

	err = ephemeraldisk.SetLocalDirectory(ephemeralDiskDir + "/disk-data")
	if err != nil {
		panic(err)
	}

	err = virtlauncher.InitializeDisksDirectories(filepath.Join("/var/run/kubevirt-private", "vm-disks"))
	if err != nil {
		panic(err)
	}
}

func waitForFinalNotify(deleteNotificationSent chan watch.Event,
	domainManager virtwrap.DomainManager,
	vm *v1.VirtualMachine) {
	// There are many conditions that can cause the qemu pid to exit that
	// don't involve the VM's domain from being deleted from libvirt.
	//
	// KillVM is idempotent. Making a call to KillVM here ensures that the deletion
	// occurs regardless if the VM crashed unexpectedly or if virt-handler requested
	// a graceful shutdown.
	domainManager.KillVM(vm)

	log.Log.Info("Waiting on final notifications to be sent to virt-handler.")

	// We don't want to block here forever. If the delete does not occur, that could mean
	// something is wrong with libvirt. In this situation, wirt-handler will detect that
	// the domain went away eventually, however the exit status will be unknown.
	timeout := time.After(30 * time.Second)
	select {
	case <-deleteNotificationSent:
		log.Log.Info("Final Delete notification sent")
	case <-timeout:
		log.Log.Info("Timed out waiting for final delete notification.")
	}
}

func main() {
	qemuTimeout := flag.Duration("qemu-timeout", defaultStartTimeout, "Amount of time to wait for qemu")
	virtShareDir := flag.String("kubevirt-share-dir", "/var/run/kubevirt", "Shared directory between virt-handler and virt-launcher")
	ephemeralDiskDir := flag.String("ephemeral-disk-dir", "/var/run/libvirt/kubevirt-ephemeral-disk", "Base directory for ephemeral disk data")
	name := flag.String("name", "", "Name of the VM")
	namespace := flag.String("namespace", "", "Namespace of the VM")
	watchdogInterval := flag.Duration("watchdog-update-interval", defaultWatchdogInterval, "Interval at which watchdog file should be updated")
	readinessFile := flag.String("readiness-file", "/tmp/health", "Pod looks for this file to determine when virt-launcher is initialized")
	gracePeriodSeconds := flag.Int("grace-period-seconds", 30, "Grace period to observe before sending SIGTERM to vm process")
	allowEmulation := flag.Bool("allow-emulation", false, "Allow fallback to emulation if /dev/kvm is not present")

	pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
	pflag.Parse()

	log.InitializeLogging("virt-launcher")

	vm := v1.NewVMReferenceFromNameWithNS(*namespace, *name)

	// Initialize local and shared directories
	initializeDirs(*virtShareDir, *ephemeralDiskDir, *namespace, *name)

	// Start libvirtd, virtlogd, and establish libvirt connection
	stopChan := make(chan struct{})
	defer close(stopChan)

	util.StartLibvirt(stopChan)
	util.StartVirtlog(stopChan)

	domainConn := createLibvirtConnection()
	defer domainConn.Close()

	domainManager, err := virtwrap.NewLibvirtDomainManager(domainConn)
	if err != nil {
		panic(err)
	}

	// Start the virt-launcher command service.
	// Clients can use this service to tell virt-launcher
	// to start/stop virtual machines
	options := cmdserver.NewServerOptions(*allowEmulation)
	socketPath := cmdclient.SocketFromNamespaceName(*virtShareDir, *namespace, *name)
	startCmdServer(socketPath, domainManager, stopChan, options)

	watchdogFile := watchdog.WatchdogFileFromNamespaceName(*virtShareDir,
		*namespace,
		*name)
	startWatchdogTicker(watchdogFile, *watchdogInterval, stopChan)

	gracefulShutdownTriggerFile := virtlauncher.GracefulShutdownTriggerFromNamespaceName(*virtShareDir,
		*namespace,
		*name)
	err = virtlauncher.GracefulShutdownTriggerClear(gracefulShutdownTriggerFile)
	if err != nil {
		log.Log.Reason(err).Errorf("Error clearing shutdown trigger file %s.", gracefulShutdownTriggerFile)
		panic(err)
	}

	shutdownCallback := func(pid int) {
		err := domainManager.KillVM(vm)
		if err != nil {
			log.Log.Reason(err).Errorf("Unable to stop qemu with libvirt, falling back to SIGTERM")
			syscall.Kill(pid, syscall.SIGTERM)
		}
	}
	mon := virtlauncher.NewProcessMonitor("qemu",
		gracefulShutdownTriggerFile,
		*gracePeriodSeconds,
		shutdownCallback)

	deleteNotificationSent := make(chan watch.Event, 10)
	// Send domain notifications to virt-handler
	startDomainEventMonitoring(*virtShareDir, domainConn, deleteNotificationSent)

	// Marking Ready allows the container's readiness check to pass.
	// This informs virt-controller that virt-launcher is ready to handle
	// managing virtual machines.
	markReady(*readinessFile)

	// This is a wait loop that monitors the qemu pid. When the pid
	// exits, the wait loop breaks.
	mon.RunForever(*qemuTimeout)

	// Now that the pid has exited, we wait for the final delete notification to be
	// sent back to virt-handler. This delete notification contains the reason the
	// domain exited.
	waitForFinalNotify(deleteNotificationSent, domainManager, vm)

	log.Log.Info("Exiting...")
}
<commit_msg>Change name of monitored process to qemu-system<commit_after>/*
 * This file is part of the KubeVirt project
 *
 * 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.
 *
 * Copyright 2017, 2018 Red Hat, Inc.
 *
 */

package main

import (
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"syscall"
	"time"

	"github.com/libvirt/libvirt-go"
	"github.com/spf13/pflag"
	utilwait "k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/apimachinery/pkg/watch"

	"kubevirt.io/kubevirt/pkg/api/v1"
	cloudinit "kubevirt.io/kubevirt/pkg/cloud-init"
	ephemeraldisk "kubevirt.io/kubevirt/pkg/ephemeral-disk"
	"kubevirt.io/kubevirt/pkg/log"
	registrydisk "kubevirt.io/kubevirt/pkg/registry-disk"
	cmdclient "kubevirt.io/kubevirt/pkg/virt-handler/cmd-client"
	virtlauncher "kubevirt.io/kubevirt/pkg/virt-launcher"
	notifyclient "kubevirt.io/kubevirt/pkg/virt-launcher/notify-client"
	"kubevirt.io/kubevirt/pkg/virt-launcher/virtwrap"
	virtcli "kubevirt.io/kubevirt/pkg/virt-launcher/virtwrap/cli"
	cmdserver "kubevirt.io/kubevirt/pkg/virt-launcher/virtwrap/cmd-server"
	"kubevirt.io/kubevirt/pkg/virt-launcher/virtwrap/util"
	watchdog "kubevirt.io/kubevirt/pkg/watchdog"
)

const defaultStartTimeout = 3 * time.Minute
const defaultWatchdogInterval = 5 * time.Second

func markReady(readinessFile string) {
	f, err := os.OpenFile(readinessFile, os.O_RDONLY|os.O_CREATE, 0666)
	if err != nil {
		panic(err)
	}
	f.Close()
	log.Log.Info("Marked as ready")
}

func startCmdServer(socketPath string,
	domainManager virtwrap.DomainManager,
	stopChan chan struct{},
	options *cmdserver.ServerOptions) {

	err := os.RemoveAll(socketPath)
	if err != nil {
		log.Log.Reason(err).Error("Could not clean up virt-launcher cmd socket")
		panic(err)
	}

	err = os.MkdirAll(filepath.Dir(socketPath), 0755)
	if err != nil {
		log.Log.Reason(err).Error("Could not create directory for socket.")
		panic(err)
	}

	err = cmdserver.RunServer(socketPath, domainManager, stopChan, options)
	if err != nil {
		log.Log.Reason(err).Error("Failed to start virt-launcher cmd server")
		panic(err)
	}

	// ensure the cmdserver is responsive before continuing
	// PollImmediate breaks the poll loop when bool or err are returned OR if timeout occurs.
	//
	// Timing out causes an error to be returned
	err = utilwait.PollImmediate(1*time.Second, 15*time.Second, func() (bool, error) {
		client, err := cmdclient.GetClient(socketPath)
		if err != nil {
			return false, nil
		}

		err = client.Ping()
		if err != nil {
			return false, nil
		}
		return true, nil
	})

	if err != nil {
		panic(fmt.Errorf("failed to connect to cmd server: %v", err))
	}
}

func createLibvirtConnection() virtcli.Connection {
	libvirtUri := "qemu:///system"
	domainConn, err := virtcli.NewConnection(libvirtUri, "", "", 10*time.Second)
	if err != nil {
		panic(fmt.Sprintf("failed to connect to libvirtd: %v", err))
	}

	return domainConn
}

func startDomainEventMonitoring(virtShareDir string, domainConn virtcli.Connection, deleteNotificationSent chan watch.Event) {
	libvirt.EventRegisterDefaultImpl()

	go func() {
		for {
			if res := libvirt.EventRunDefaultImpl(); res != nil {
				log.Log.Reason(res).Error("Listening to libvirt events failed, retrying.")
				time.Sleep(time.Second)
			}
		}
	}()

	err := notifyclient.StartNotifier(virtShareDir, domainConn, deleteNotificationSent)
	if err != nil {
		panic(err)
	}

}

func startWatchdogTicker(watchdogFile string, watchdogInterval time.Duration, stopChan chan struct{}) {
	err := watchdog.WatchdogFileUpdate(watchdogFile)
	if err != nil {
		panic(err)
	}

	log.Log.Infof("Watchdog file created at %s", watchdogFile)

	go func() {

		ticker := time.NewTicker(watchdogInterval).C
		for {
			select {
			case <-stopChan:
				return
			case <-ticker:
				err := watchdog.WatchdogFileUpdate(watchdogFile)
				if err != nil {
					panic(err)
				}
			}
		}
	}()
}

func initializeDirs(virtShareDir string,
	ephemeralDiskDir string,
	namespace string,
	name string) {

	err := virtlauncher.InitializeSharedDirectories(virtShareDir)
	if err != nil {
		panic(err)
	}

	err = virtlauncher.InitializePrivateDirectories(filepath.Join("/var/run/kubevirt-private", namespace, name))
	if err != nil {
		panic(err)
	}

	err = cloudinit.SetLocalDirectory(ephemeralDiskDir + "/cloud-init-data")
	if err != nil {
		panic(err)
	}

	err = registrydisk.SetLocalDirectory(ephemeralDiskDir + "/registry-disk-data")
	if err != nil {
		panic(err)
	}

	err = ephemeraldisk.SetLocalDirectory(ephemeralDiskDir + "/disk-data")
	if err != nil {
		panic(err)
	}

	err = virtlauncher.InitializeDisksDirectories(filepath.Join("/var/run/kubevirt-private", "vm-disks"))
	if err != nil {
		panic(err)
	}
}

func waitForFinalNotify(deleteNotificationSent chan watch.Event,
	domainManager virtwrap.DomainManager,
	vm *v1.VirtualMachine) {
	// There are many conditions that can cause the qemu pid to exit that
	// don't involve the VM's domain from being deleted from libvirt.
	//
	// KillVM is idempotent. Making a call to KillVM here ensures that the deletion
	// occurs regardless if the VM crashed unexpectedly or if virt-handler requested
	// a graceful shutdown.
	domainManager.KillVM(vm)

	log.Log.Info("Waiting on final notifications to be sent to virt-handler.")

	// We don't want to block here forever. If the delete does not occur, that could mean
	// something is wrong with libvirt. In this situation, wirt-handler will detect that
	// the domain went away eventually, however the exit status will be unknown.
	timeout := time.After(30 * time.Second)
	select {
	case <-deleteNotificationSent:
		log.Log.Info("Final Delete notification sent")
	case <-timeout:
		log.Log.Info("Timed out waiting for final delete notification.")
	}
}

func main() {
	qemuTimeout := flag.Duration("qemu-timeout", defaultStartTimeout, "Amount of time to wait for qemu")
	virtShareDir := flag.String("kubevirt-share-dir", "/var/run/kubevirt", "Shared directory between virt-handler and virt-launcher")
	ephemeralDiskDir := flag.String("ephemeral-disk-dir", "/var/run/libvirt/kubevirt-ephemeral-disk", "Base directory for ephemeral disk data")
	name := flag.String("name", "", "Name of the VM")
	namespace := flag.String("namespace", "", "Namespace of the VM")
	watchdogInterval := flag.Duration("watchdog-update-interval", defaultWatchdogInterval, "Interval at which watchdog file should be updated")
	readinessFile := flag.String("readiness-file", "/tmp/health", "Pod looks for this file to determine when virt-launcher is initialized")
	gracePeriodSeconds := flag.Int("grace-period-seconds", 30, "Grace period to observe before sending SIGTERM to vm process")
	allowEmulation := flag.Bool("allow-emulation", false, "Allow fallback to emulation if /dev/kvm is not present")

	pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
	pflag.Parse()

	log.InitializeLogging("virt-launcher")

	vm := v1.NewVMReferenceFromNameWithNS(*namespace, *name)

	// Initialize local and shared directories
	initializeDirs(*virtShareDir, *ephemeralDiskDir, *namespace, *name)

	// Start libvirtd, virtlogd, and establish libvirt connection
	stopChan := make(chan struct{})
	defer close(stopChan)

	util.StartLibvirt(stopChan)
	util.StartVirtlog(stopChan)

	domainConn := createLibvirtConnection()
	defer domainConn.Close()

	domainManager, err := virtwrap.NewLibvirtDomainManager(domainConn)
	if err != nil {
		panic(err)
	}

	// Start the virt-launcher command service.
	// Clients can use this service to tell virt-launcher
	// to start/stop virtual machines
	options := cmdserver.NewServerOptions(*allowEmulation)
	socketPath := cmdclient.SocketFromNamespaceName(*virtShareDir, *namespace, *name)
	startCmdServer(socketPath, domainManager, stopChan, options)

	watchdogFile := watchdog.WatchdogFileFromNamespaceName(*virtShareDir,
		*namespace,
		*name)
	startWatchdogTicker(watchdogFile, *watchdogInterval, stopChan)

	gracefulShutdownTriggerFile := virtlauncher.GracefulShutdownTriggerFromNamespaceName(*virtShareDir,
		*namespace,
		*name)
	err = virtlauncher.GracefulShutdownTriggerClear(gracefulShutdownTriggerFile)
	if err != nil {
		log.Log.Reason(err).Errorf("Error clearing shutdown trigger file %s.", gracefulShutdownTriggerFile)
		panic(err)
	}

	shutdownCallback := func(pid int) {
		err := domainManager.KillVM(vm)
		if err != nil {
			log.Log.Reason(err).Errorf("Unable to stop qemu with libvirt, falling back to SIGTERM")
			syscall.Kill(pid, syscall.SIGTERM)
		}
	}
	mon := virtlauncher.NewProcessMonitor("qemu-system",
		gracefulShutdownTriggerFile,
		*gracePeriodSeconds,
		shutdownCallback)

	deleteNotificationSent := make(chan watch.Event, 10)
	// Send domain notifications to virt-handler
	startDomainEventMonitoring(*virtShareDir, domainConn, deleteNotificationSent)

	// Marking Ready allows the container's readiness check to pass.
	// This informs virt-controller that virt-launcher is ready to handle
	// managing virtual machines.
	markReady(*readinessFile)

	// This is a wait loop that monitors the qemu pid. When the pid
	// exits, the wait loop breaks.
	mon.RunForever(*qemuTimeout)

	// Now that the pid has exited, we wait for the final delete notification to be
	// sent back to virt-handler. This delete notification contains the reason the
	// domain exited.
	waitForFinalNotify(deleteNotificationSent, domainManager, vm)

	log.Log.Info("Exiting...")
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"crypto/tls"
	"flag"
	"net"
	"net/http"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"

	"github.com/coreos/go-semver/semver"
	"github.com/fnproject/fn/fnlb/lb"
	"github.com/sirupsen/logrus"
)

const VERSION = "0.0.62"

func main() {
	// XXX (reed): normalize
	fnodes := flag.String("nodes", "", "comma separated list of functions nodes")
	minAPIVersion := flag.String("min-api-version", "0.0.29", "minimal node API to accept")

	var conf lb.Config
	flag.StringVar(&conf.DBurl, "db", "sqlite3://:memory:", "backend to store nodes, default to in memory")
	flag.StringVar(&conf.Listen, "listen", ":8081", "port to run on")
	flag.IntVar(&conf.HealthcheckInterval, "hc-interval", 3, "how often to check f(x) nodes, in seconds")
	flag.StringVar(&conf.HealthcheckEndpoint, "hc-path", "/version", "endpoint to determine node health")
	flag.IntVar(&conf.HealthcheckUnhealthy, "hc-unhealthy", 2, "threshold of failed checks to declare node unhealthy")
	flag.IntVar(&conf.HealthcheckTimeout, "hc-timeout", 5, "timeout of healthcheck endpoint, in seconds")
	flag.StringVar(&conf.ZipkinURL, "zipkin", "", "zipkin endpoint to send traces")
	flag.Parse()

	conf.MinAPIVersion = semver.New(*minAPIVersion)

	if len(*fnodes) > 0 {
		// starting w/o nodes is fine too
		conf.Nodes = strings.Split(*fnodes, ",")
	}

	conf.Transport = &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		Dial: (&net.Dialer{
			Timeout:   10 * time.Second,
			KeepAlive: 120 * time.Second,
		}).Dial,
		MaxIdleConnsPerHost: 512,
		TLSHandshakeTimeout: 10 * time.Second,
		TLSClientConfig: &tls.Config{
			ClientSessionCache: tls.NewLRUClientSessionCache(4096),
		},
	}

	g, err := lb.NewAllGrouper(conf)
	if err != nil {
		logrus.WithError(err).Fatal("error setting up grouper")
	}

	r := lb.NewConsistentRouter(conf)
	k := func(r *http.Request) (string, error) {
		return r.URL.Path, nil
	}

	h := lb.NewProxy(k, g, r, conf)
	h = g.Wrap(h) // add/del/list endpoints
	h = r.Wrap(h) // stats / dash endpoint

	err = serve(conf.Listen, h)
	if err != nil {
		logrus.WithError(err).Fatal("server error")
	}
}

func serve(addr string, handler http.Handler) error {
	server := &http.Server{Addr: addr, Handler: handler}

	ch := make(chan os.Signal, 1)
	signal.Notify(ch, syscall.SIGQUIT, syscall.SIGINT)
	go func() {
		for sig := range ch {
			logrus.WithFields(logrus.Fields{"signal": sig}).Info("received signal")
			server.Shutdown(context.Background()) // safe shutdown
			return
		}
	}()
	return server.ListenAndServe()
}
<commit_msg>fnlb: 0.0.63 release [skip ci]<commit_after>package main

import (
	"context"
	"crypto/tls"
	"flag"
	"net"
	"net/http"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"

	"github.com/coreos/go-semver/semver"
	"github.com/fnproject/fn/fnlb/lb"
	"github.com/sirupsen/logrus"
)

const VERSION = "0.0.63"

func main() {
	// XXX (reed): normalize
	fnodes := flag.String("nodes", "", "comma separated list of functions nodes")
	minAPIVersion := flag.String("min-api-version", "0.0.30", "minimal node API to accept")

	var conf lb.Config
	flag.StringVar(&conf.DBurl, "db", "sqlite3://:memory:", "backend to store nodes, default to in memory")
	flag.StringVar(&conf.Listen, "listen", ":8081", "port to run on")
	flag.IntVar(&conf.HealthcheckInterval, "hc-interval", 3, "how often to check f(x) nodes, in seconds")
	flag.StringVar(&conf.HealthcheckEndpoint, "hc-path", "/version", "endpoint to determine node health")
	flag.IntVar(&conf.HealthcheckUnhealthy, "hc-unhealthy", 2, "threshold of failed checks to declare node unhealthy")
	flag.IntVar(&conf.HealthcheckTimeout, "hc-timeout", 5, "timeout of healthcheck endpoint, in seconds")
	flag.StringVar(&conf.ZipkinURL, "zipkin", "", "zipkin endpoint to send traces")
	flag.Parse()

	conf.MinAPIVersion = semver.New(*minAPIVersion)

	if len(*fnodes) > 0 {
		// starting w/o nodes is fine too
		conf.Nodes = strings.Split(*fnodes, ",")
	}

	conf.Transport = &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		Dial: (&net.Dialer{
			Timeout:   10 * time.Second,
			KeepAlive: 120 * time.Second,
		}).Dial,
		MaxIdleConnsPerHost: 512,
		TLSHandshakeTimeout: 10 * time.Second,
		TLSClientConfig: &tls.Config{
			ClientSessionCache: tls.NewLRUClientSessionCache(4096),
		},
	}

	g, err := lb.NewAllGrouper(conf)
	if err != nil {
		logrus.WithError(err).Fatal("error setting up grouper")
	}

	r := lb.NewConsistentRouter(conf)
	k := func(r *http.Request) (string, error) {
		return r.URL.Path, nil
	}

	h := lb.NewProxy(k, g, r, conf)
	h = g.Wrap(h) // add/del/list endpoints
	h = r.Wrap(h) // stats / dash endpoint

	err = serve(conf.Listen, h)
	if err != nil {
		logrus.WithError(err).Fatal("server error")
	}
}

func serve(addr string, handler http.Handler) error {
	server := &http.Server{Addr: addr, Handler: handler}

	ch := make(chan os.Signal, 1)
	signal.Notify(ch, syscall.SIGQUIT, syscall.SIGINT)
	go func() {
		for sig := range ch {
			logrus.WithFields(logrus.Fields{"signal": sig}).Info("received signal")
			server.Shutdown(context.Background()) // safe shutdown
			return
		}
	}()
	return server.ListenAndServe()
}
<|endoftext|>


<commit_before>package iglo

import (
	"bitbucket.org/pkg/inflect"
	"html/template"
	"io"
	"strings"
)

func labelize(method string) string {
	switch method {
	case "GET":
		return "primary"
	case "POST":
		return "success"
	case "PUT":
		return "info"
	case "PATCH":
		return "warning"
	case "DELETE":
		return "danger"
	}

	return "default"
}

func HTML(w io.Writer, api *API) error {
	// template functions
	funcMap := template.FuncMap{
		"dasherize": inflect.Dasherize,
		"trim":      strings.Trim,
		"labelize":  labelize,
	}

	tmpl, err := template.New("html").Funcs(funcMap).Parse(Tmpl)
	if err != nil {
		return err
	}

	err = tmpl.Execute(w, api)
	if err != nil {
		return err
	}

	return nil
}

var Tmpl = `
{{define "Headers"}}

	{{range $index, $element := .}}

			{{$index}}
			{{.Value}}

	{{end}}

{{end}}

{{define "Examples"}}
{{end}}

{{define "Parameters"}}
{{end}}

{{define "Resources"}}
	{{range .Resources}}
		{{$UriTemplate := .UriTemplate}}

{{.Name}}

{{trim .Description "\n"}}

		{{range .Actions}}

				{{.Method}}
				{{$UriTemplate}}

				{{.Description}}

		{{end}}
	{{end}}
{{end}}

{{define "ResourceGroups"}}
	{{range .}}

{{.Name}}

		{{template "Resources" .}}
	{{end}}
{{end}}

{{define "NavResourceGroups"}}

	{{range .}}

		{{.Name}}

			{{range .Resources}}

{{.Name}}

			{{end}}

	{{end}}

{{end}}

<!DOCTYPE html>

		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>{{.Name}}</title>
		<meta name="description" content="{{.Description}}">
		<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">

					{{template "NavResourceGroups" .ResourceGroups}}

					{{template "ResourceGroups" .ResourceGroups}}

`
<commit_msg>enhance layout<commit_after>package iglo

import (
	"bitbucket.org/pkg/inflect"
	"html/template"
	"io"
	"strings"
)

func labelize(method string) string {
	switch method {
	case "GET":
		return "primary"
	case "POST":
		return "success"
	case "PUT":
		return "info"
	case "PATCH":
		return "warning"
	case "DELETE":
		return "danger"
	}

	return "default"
}

func HTML(w io.Writer, api *API) error {
	// template functions
	funcMap := template.FuncMap{
		"dasherize": inflect.Dasherize,
		"trim":      strings.Trim,
		"labelize":  labelize,
	}

	tmpl, err := template.New("html").Funcs(funcMap).Parse(Tmpl)
	if err != nil {
		return err
	}

	err = tmpl.Execute(w, api)
	if err != nil {
		return err
	}

	return nil
}

var Tmpl = `
{{define "Headers"}}

Headers

	{{range $index, $element := .}}

			{{$index}}
			{{.Value}}

	{{end}}

{{end}}

{{define "Responses"}}
	{{range .}}
		{{if .Body}}

{{.Body}}

		{{end}}
		{{if .Headers}}

				{{template "Headers" .Headers}}

		{{end}}
	{{end}}
{{end}}

{{define "Examples"}}
	{{range .}}
		{{template "Responses" .Responses}}
	{{end}}
{{end}}

{{define "Parameters"}}

Parameters

	{{range $index, $element := .}}

			{{$index}}
			{{.Type}}
			{{.Description}}

	{{end}}

{{end}}

{{define "Resources"}}
	{{range .Resources}}
		{{$UriTemplate := .UriTemplate}}
		{{$Parameters := .Parameters}}

{{.Name}}

{{trim .Description "\n"}}

		{{range .Actions}}

				{{.Method}}
				{{$UriTemplate}}

				{{.Description}}

				{{if .Examples}}{{template "Examples" .Examples}}{{end}}
				{{if $Parameters}}

{{template "Parameters" $Parameters}}

				{{end}}

		{{end}}
	{{end}}
{{end}}

{{define "ResourceGroups"}}
	{{range .}}

{{.Name}}

		{{template "Resources" .}}
	{{end}}
{{end}}

{{define "NavResourceGroups"}}

	{{range .}}

		{{.Name}}

			{{range .Resources}}

{{.Name}}

			{{end}}

	{{end}}

{{end}}

<!DOCTYPE html>

		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>{{.Name}}</title>
		<meta name="description" content="{{.Description}}">
		<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">

					{{template "NavResourceGroups" .ResourceGroups}}

					{{template "ResourceGroups" .ResourceGroups}}

`
<|endoftext|>


<commit_before>package smaz

import (
	"bufio"
	"bytes"
	"os"
	"testing"
)

var antirezTestStrings = []string{"",
	"This is a small string",
	"foobar",
	"the end",
	"not-a-g00d-Exampl333",
	"Smaz is a simple compression library",
	"Nothing is more difficult, and therefore more precious, than to be able to decide",
	"this is an example of what works very well with smaz",
	"1000 numbers 2000 will 10 20 30 compress very little",
	"and now a few italian sentences:",
	"Nel mezzo del cammin di nostra vita, mi ritrovai in una selva oscura",
	"Mi illumino di immenso",
	"L'autore di questa libreria vive in Sicilia",
	"try it against urls",
	"http://google.com",
	"http://programming.reddit.com",
	"http://github.com/antirez/smaz/tree/master",
	"/media/hdb1/music/Alben/The Bla",
}

func TestCorrectness(t *testing.T) {
	// Set up our slice of test strings.
	inputs := make([][]byte, 0)
	for _, s := range antirezTestStrings {
		inputs = append(inputs, []byte(s))
	}
	// An array with every possible byte value in it.
	allBytes := make([]byte, 256)
	for i := 0; i < 256; i++ {
		allBytes[i] = byte(i)
	}
	inputs = append(inputs, allBytes)
	// A long array of all 0s (the longest continuous string that can be represented is 256; any longer than
	// this and the compressor will need to split it into chunks)
	allZeroes := make([]byte, 300)
	for i := 0; i < 300; i++ {
		allZeroes[i] = byte(0)
	}
	inputs = append(inputs, allZeroes)

	for _, input := range inputs {
		compressed := Compress(input)
		decompressed, err := Decompress(compressed)
		if err != nil {
			t.Fatal(err)
		}
		if !bytes.Equal(input, decompressed) {
			t.Fatal("want %q after decompression; got %q\n", input, decompressed)
		}

		if len(input) > 1 && len(input) < 50 {
			compressionLevel := 100 - ((100.0 * len(compressed)) / len(input))
			if compressionLevel < 0 {
				t.Logf("%q enlarged by %d%%\n", input, -compressionLevel)
			} else {
				t.Logf("%q compressed by %d%%\n", input, compressionLevel)
			}
		}
	}
}

func loadTestData(t testing.TB) ([][]byte, int64) {
	f, err := os.Open("./testdata/pg5200.txt")
	if err != nil {
		t.Fatal(err)
	}

	var lines [][]byte
	var n int64
	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		input := []byte(scanner.Text()) // Note that .Bytes() would require us to manually copy
		lines = append(lines, input)
		n += int64(len(input))
	}
	return lines, n
}

func BenchmarkCompression(b *testing.B) {
	b.StopTimer()
	inputs, n := loadTestData(b)
	b.SetBytes(n)
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		for _, input := range inputs {
			Compress(input)
		}
	}
}

func BenchmarkDecompression(b *testing.B) {
	b.StopTimer()
	inputs, _ := loadTestData(b)
	compressedStrings := make([][]byte, len(inputs))
	var n int64
	for i, input := range inputs {
		compressed := Compress(input)
		compressedStrings[i] = compressed
		n += int64(len(compressed))
	}
	b.SetBytes(n)
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		for _, compressed := range compressedStrings {
			Decompress(compressed)
		}
	}
}
<commit_msg>Use t.Fatalf<commit_after>package smaz

import (
	"bufio"
	"bytes"
	"os"
	"testing"
)

var antirezTestStrings = []string{"",
	"This is a small string",
	"foobar",
	"the end",
	"not-a-g00d-Exampl333",
	"Smaz is a simple compression library",
	"Nothing is more difficult, and therefore more precious, than to be able to decide",
	"this is an example of what works very well with smaz",
	"1000 numbers 2000 will 10 20 30 compress very little",
	"and now a few italian sentences:",
	"Nel mezzo del cammin di nostra vita, mi ritrovai in una selva oscura",
	"Mi illumino di immenso",
	"L'autore di questa libreria vive in Sicilia",
	"try it against urls",
	"http://google.com",
	"http://programming.reddit.com",
	"http://github.com/antirez/smaz/tree/master",
	"/media/hdb1/music/Alben/The Bla",
}

func TestCorrectness(t *testing.T) {
	// Set up our slice of test strings.
	inputs := make([][]byte, 0)
	for _, s := range antirezTestStrings {
		inputs = append(inputs, []byte(s))
	}
	// An array with every possible byte value in it.
	allBytes := make([]byte, 256)
	for i := 0; i < 256; i++ {
		allBytes[i] = byte(i)
	}
	inputs = append(inputs, allBytes)
	// A long array of all 0s (the longest continuous string that can be represented is 256; any longer than
	// this and the compressor will need to split it into chunks)
	allZeroes := make([]byte, 300)
	for i := 0; i < 300; i++ {
		allZeroes[i] = byte(0)
	}
	inputs = append(inputs, allZeroes)

	for _, input := range inputs {
		compressed := Compress(input)
		decompressed, err := Decompress(compressed)
		if err != nil {
			t.Fatal(err)
		}
		if !bytes.Equal(input, decompressed) {
			t.Fatalf("want %q after decompression; got %q\n", input, decompressed)
		}

		if len(input) > 1 && len(input) < 50 {
			compressionLevel := 100 - ((100.0 * len(compressed)) / len(input))
			if compressionLevel < 0 {
				t.Logf("%q enlarged by %d%%\n", input, -compressionLevel)
			} else {
				t.Logf("%q compressed by %d%%\n", input, compressionLevel)
			}
		}
	}
}

func loadTestData(t testing.TB) ([][]byte, int64) {
	f, err := os.Open("./testdata/pg5200.txt")
	if err != nil {
		t.Fatal(err)
	}

	var lines [][]byte
	var n int64
	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		input := []byte(scanner.Text()) // Note that .Bytes() would require us to manually copy
		lines = append(lines, input)
		n += int64(len(input))
	}
	return lines, n
}

func BenchmarkCompression(b *testing.B) {
	b.StopTimer()
	inputs, n := loadTestData(b)
	b.SetBytes(n)
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		for _, input := range inputs {
			Compress(input)
		}
	}
}

func BenchmarkDecompression(b *testing.B) {
	b.StopTimer()
	inputs, _ := loadTestData(b)
	compressedStrings := make([][]byte, len(inputs))
	var n int64
	for i, input := range inputs {
		compressed := Compress(input)
		compressedStrings[i] = compressed
		n += int64(len(compressed))
	}
	b.SetBytes(n)
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		for _, compressed := range compressedStrings {
			Decompress(compressed)
		}
	}
}
<|endoftext|>


<commit_before>package stow

import (
	"encoding/gob"
	"os"
	"testing"

	"github.com/boltdb/bolt"
)

type MyType struct {
	FirstName string `json:"first"`
	LastName  string `json:"last"`
}

func init() {
	gob.Register(MyType{})
}

func testStore(t *testing.T, store *Store) {
	store.Put([]byte("hello"), &MyType{"Derek", "Kered"})

	var found bool
	err := store.ForEach(func(name MyType) {
		found = true
		if name.FirstName != "Derek" || name.LastName != "Kered" {
			t.Errorf("mismatching name %s", name)
		}
	})

	if !found {
		t.Errorf("ForEach failed!")
	}

	if err != nil {
		t.Error(err.Error())
	}

	var name MyType
	store.Pull([]byte("hello"), &name)

	if name.FirstName != "Derek" || name.LastName != "Kered" {
		t.Errorf("Unexpected name: %v", name)
	}
}

func TestJSON(t *testing.T) {
	db, err := bolt.Open("my1.db", 0600, nil)
	if err != nil {
		t.Error(err.Error())
	}
	defer os.Remove("my1.db")
	defer db.Close()

	testStore(t, NewJSONStore(db, []byte("json")))
}

func TestXML(t *testing.T) {
	db, err := bolt.Open("my2.db", 0600, nil)
	if err != nil {
		t.Error(err.Error())
	}
	defer os.Remove("my2.db")
	defer db.Close()

	testStore(t, NewXMLStore(db, []byte("xml")))
}

func TestGob(t *testing.T) {
	db, err := bolt.Open("my3.db", 0600, nil)
	if err != nil {
		t.Error(err.Error())
	}
	defer os.Remove("my3.db")
	defer db.Close()

	testStore(t, NewStore(db, []byte("gob")))
}
<commit_msg>extending test cases<commit_after>package stow

import (
	"encoding/gob"
	"os"
	"testing"

	"github.com/boltdb/bolt"
)

type MyType struct {
	FirstName string `json:"first"`
	LastName  string `json:"last"`
}

func init() {
	gob.Register(MyType{})
}

func testStore(t *testing.T, store *Store) {
	store.Put([]byte("hello"), &MyType{"Derek", "Kered"})

	var found bool
	err := store.ForEach(func(name MyType) {
		found = true
		if name.FirstName != "Derek" || name.LastName != "Kered" {
			t.Errorf("mismatching name %s", name)
		}
	})

	if !found {
		t.Errorf("ForEach failed!")
	}

	if err != nil {
		t.Error(err.Error())
	}

	var name MyType
	store.Get([]byte("hello"), &name)

	if name.FirstName != "Derek" || name.LastName != "Kered" {
		t.Errorf("Unexpected name: %v", name)
	}

	var name2 MyType
	store.Pull([]byte("hello"), &name2)

	if name2.FirstName != "Derek" || name2.LastName != "Kered" {
		t.Errorf("Unexpected name2: %v", name2)
	}

	var name3 MyType
	err = store.Pull([]byte("hello"), &name3)
	if err != ErrNotFound {
		t.Errorf("pull failed to remove the name!")
	}
}

func TestJSON(t *testing.T) {
	db, err := bolt.Open("my1.db", 0600, nil)
	if err != nil {
		t.Error(err.Error())
	}
	defer os.Remove("my1.db")
	defer db.Close()

	testStore(t, NewJSONStore(db, []byte("json")))
}

func TestXML(t *testing.T) {
	db, err := bolt.Open("my2.db", 0600, nil)
	if err != nil {
		t.Error(err.Error())
	}
	defer os.Remove("my2.db")
	defer db.Close()

	testStore(t, NewXMLStore(db, []byte("xml")))
}

func TestGob(t *testing.T) {
	db, err := bolt.Open("my3.db", 0600, nil)
	if err != nil {
		t.Error(err.Error())
	}
	defer os.Remove("my3.db")
	defer db.Close()

	testStore(t, NewStore(db, []byte("gob")))
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"math/rand"
	"os"

	"github.com/cryptix/goSSEClient"
)

type PshdlApiStreamingEvent interface {
	GetSubject() string
	GetFiles() []PshdlApiRecord
}

func (wp *PshdlWorkspace) OpenEventStream(done chan bool) error {
	// todo we need a unique client id!
	url := fmt.Sprintf("http://%s/api/v0.1/streaming/workspace/%s/%d/sse", ApiHost, wp.Id, rand.Intn(128))

	sseEvent, err := goSSEClient.OpenSSEUrl(url)
	if err != nil {
		done <- false
		return err
	}

	wp.Events = make(chan PshdlApiStreamingEvent)

	go func() {
		for ev := range sseEvent {
			var peek struct {
				Subject string
				MsgType string
			}

			err := json.Unmarshal(ev.Data, &peek)
			if err != nil {
				fmt.Fprintf(os.Stderr, "Error during Peek Unmarshal:%s\n", err)
				done <- false
			}

			var apiEvent PshdlApiStreamingEvent

			switch peek.Subject {

			case "P:COMPILER:VHDL":
				apiEvent = new(PshdlApiCompilerVhdlEvent)

			case "P:COMPILER:C":
				apiEvent = new(PShdlApiCompilerCEvent)

			case "P:WORKSPACE:ADDED":
				apiEvent = new(PshdlApiWorskpaceUpdatedEvent)

			case "P:WORKSPACE:UPDATED":
				apiEvent = new(PshdlApiWorskpaceUpdatedEvent)

			case "P:WORKSPACE:DELETED":
				apiEvent = new(PshdlApiWorskpaceDeletedEvent)

			default:
				fmt.Fprintf(os.Stderr, "Error unhandeld event type!:%v\n", peek)
				done <- false
			}

			err = json.Unmarshal(ev.Data, &apiEvent)
			if err != nil {
				fmt.Fprintf(os.Stderr, "Error during Event Unmarshal:%s\n", err)
				done <- false
			} else {
				wp.Events <- apiEvent
			}

		}
		fmt.Fprintln(os.Stderr, "SSEvent chan was closed.")
		done <- true
	}()

	return nil
}
<commit_msg>Properly requesting clientID for streaming<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"os"
	"strconv"

	"github.com/cryptix/goSSEClient"
)

type PshdlApiStreamingEvent interface {
	GetSubject() string
	GetFiles() []PshdlApiRecord
}

func (wp *PshdlWorkspace) OpenEventStream(done chan bool) error {
	// todo we need a unique client id!
	clientIdUrl := fmt.Sprintf("http://%s/api/v0.1/streaming/workspace/%s/clientID", ApiHost, wp.Id)
	// fmt.Printf("Debug: clientIdUrl:%s\n", clientIdUrl)

	resp, err := http.Get(clientIdUrl)
	if err != nil {
		done <- false
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		done <- false
		return fmt.Errorf("Error: ClientId response code: %d", resp.StatusCode)
	}

	buf := make([]byte, resp.ContentLength)
	_, err = resp.Body.Read(buf)
	if err != nil {
		done <- false
		return fmt.Errorf("Error: ClientId response could not be read: %s", err)
	}

	clientId, err := strconv.Atoi(string(buf))
	if err != nil {
		done <- false
		return fmt.Errorf("Error: ClientId response could not be parsed to int: %s", err)
	}

	url := fmt.Sprintf("http://%s/api/v0.1/streaming/workspace/%s/%d/sse", ApiHost, wp.Id, clientId)
	// fmt.Printf("Debug: streamingUrl:%s\n", url)

	sseEvent, err := goSSEClient.OpenSSEUrl(url)
	if err != nil {
		done <- false
		return err
	}

	wp.Events = make(chan PshdlApiStreamingEvent)

	go func() {
		for ev := range sseEvent {
			var peek struct {
				Subject string
				MsgType string
			}

			err := json.Unmarshal(ev.Data, &peek)
			if err != nil {
				fmt.Fprintf(os.Stderr, "Error during Peek Unmarshal:%s\n", err)
				done <- false
			}

			var apiEvent PshdlApiStreamingEvent

			switch peek.Subject {

			case "P:COMPILER:VHDL":
				apiEvent = new(PshdlApiCompilerVhdlEvent)

			case "P:COMPILER:C":
				apiEvent = new(PShdlApiCompilerCEvent)

			case "P:WORKSPACE:ADDED":
				apiEvent = new(PshdlApiWorskpaceUpdatedEvent)

			case "P:WORKSPACE:UPDATED":
				apiEvent = new(PshdlApiWorskpaceUpdatedEvent)

			case "P:WORKSPACE:DELETED":
				apiEvent = new(PshdlApiWorskpaceDeletedEvent)

			default:
				fmt.Fprintf(os.Stderr, "Error unhandeld event type!:%v\n", peek)
				done <- false
			}

			err = json.Unmarshal(ev.Data, &apiEvent)
			if err != nil {
				fmt.Fprintf(os.Stderr, "Error during Event Unmarshal:%s\n", err)
				done <- false
			} else {
				wp.Events <- apiEvent
			}

		}
		fmt.Fprintln(os.Stderr, "SSEvent chan was closed.")
		done <- true
	}()

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"reflect"
	"testing"
)

func TestSupportedPlatforms(t *testing.T) {
	var ps []Platform

	ps = SupportedPlatforms("go1.0")
	if !reflect.DeepEqual(ps, Platforms_1_0) {
		t.Fatalf("bad: %#v", ps)
	}

	ps = SupportedPlatforms("go1.1")
	if !reflect.DeepEqual(ps, Platforms_1_1) {
		t.Fatalf("bad: %#v", ps)
	}

	ps = SupportedPlatforms("go1.3")
	if !reflect.DeepEqual(ps, Platforms_1_3) {
		t.Fatalf("bad: %#v", ps)
	}

	ps = SupportedPlatforms("go1.4")
	if !reflect.DeepEqual(ps, Platforms_1_4) {
		t.Fatalf("bad: %#v", ps)
	}

	// Unknown
	ps = SupportedPlatforms("foo")
	if !reflect.DeepEqual(ps, Platforms_1_5) {
		t.Fatalf("bad: %#v", ps)
	}
}
<commit_msg>Add test for go 1.2<commit_after>package main

import (
	"reflect"
	"testing"
)

func TestSupportedPlatforms(t *testing.T) {
	var ps []Platform

	ps = SupportedPlatforms("go1.0")
	if !reflect.DeepEqual(ps, Platforms_1_0) {
		t.Fatalf("bad: %#v", ps)
	}

	ps = SupportedPlatforms("go1.1")
	if !reflect.DeepEqual(ps, Platforms_1_1) {
		t.Fatalf("bad: %#v", ps)
	}

	ps = SupportedPlatforms("go1.2")
	if !reflect.DeepEqual(ps, Platforms_1_1) {
		t.Fatalf("bad: %#v", ps)
	}

	ps = SupportedPlatforms("go1.3")
	if !reflect.DeepEqual(ps, Platforms_1_3) {
		t.Fatalf("bad: %#v", ps)
	}

	ps = SupportedPlatforms("go1.4")
	if !reflect.DeepEqual(ps, Platforms_1_4) {
		t.Fatalf("bad: %#v", ps)
	}

	// Unknown
	ps = SupportedPlatforms("foo")
	if !reflect.DeepEqual(ps, Platforms_1_5) {
		t.Fatalf("bad: %#v", ps)
	}
}
<|endoftext|>


<commit_before>package lazycache
// A generic cache that favors returning stale data
// than blocking a caller

import (
  "sync"
  "time"
)

type Fetcher func(id string) (interface{}, error)

type Item struct {
  object interface{}
  expires time.Time
}

type LazyCache struct {
  fetcher Fetcher
  ttl time.Duration
  lock sync.RWMutex
  items map[string]*Item
}

func New(fetcher Fetcher, ttl time.Duration, size int) *LazyCache {
  return &LazyCache{
    ttl: ttl,
    fetcher: fetcher,
    items: make(map[string]*Item, size),
  }
}

func (cache *LazyCache) Get(id string) (interface{}, bool) {
  cache.lock.RLock()
  item, exists := cache.items[id]
  cache.lock.RUnlock()
  if exists == false {
    return cache.Fetch(id, item)
  }
  if time.Now().After(item.expires) {
    if item.object == nil {
      return cache.Fetch(id, item)
    } else {
      go cache.Fetch(id, item)
    }
  }
  return item.object, true
}

func (cache *LazyCache) Set(id string, object interface{}) {
  cache.lock.Lock()
  defer cache.lock.Unlock()
  cache.items[id] = &Item{expires: time.Now().Add(cache.ttl), object: object}
}

func (cache *LazyCache) Fetch(id string, current *Item) (interface{}, bool) {
  object, err := cache.fetcher(id)
  if err != nil { return nil, false }

  if current == nil {
    cache.Set(id, object)
    return object, true
  }

  cache.lock.Lock()
  defer cache.lock.Unlock()
  if object == nil {
    delete(cache.items, id)
  } else {
    current.expires = time.Now().Add(cache.ttl)
    current.object = object
  }
  return object, object != nil
}
<commit_msg>handle a nil initial fetch<commit_after>package lazycache
// A generic cache that favors returning stale data
// than blocking a caller

import (
  "sync"
  "time"
)

type Fetcher func(id string) (interface{}, error)

type Item struct {
  object interface{}
  expires time.Time
}

type LazyCache struct {
  fetcher Fetcher
  ttl time.Duration
  lock sync.RWMutex
  items map[string]*Item
}

func New(fetcher Fetcher, ttl time.Duration, size int) *LazyCache {
  return &LazyCache{
    ttl: ttl,
    fetcher: fetcher,
    items: make(map[string]*Item, size),
  }
}

func (cache *LazyCache) Get(id string) (interface{}, bool) {
  cache.lock.RLock()
  item, exists := cache.items[id]
  cache.lock.RUnlock()
  if exists == false {
    return cache.Fetch(id, item)
  }
  if time.Now().After(item.expires) {
    if item.object == nil {
      return cache.Fetch(id, item)
    } else {
      go cache.Fetch(id, item)
    }
  }
  return item.object, true
}

func (cache *LazyCache) Set(id string, object interface{}) {
  cache.lock.Lock()
  defer cache.lock.Unlock()
  cache.items[id] = &Item{expires: time.Now().Add(cache.ttl), object: object}
}

func (cache *LazyCache) Fetch(id string, current *Item) (interface{}, bool) {
  object, err := cache.fetcher(id)
  if err != nil { return nil, false }

  if current == nil {
    if object == nil { return nil, false }
    cache.Set(id, object)
    return object, true
  }

  cache.lock.Lock()
  defer cache.lock.Unlock()
  if object == nil {
    delete(cache.items, id)
  } else {
    current.expires = time.Now().Add(cache.ttl)
    current.object = object
  }
  return object, object != nil
}
<|endoftext|>


<commit_before>package main

import (
  "fmt"
  "net/http"
)
import "github.com/amarburg/go-lazyfs"

var OOIRawDataRootURL = "https://rawdata.oceanobservatories.org/"

var fs *lazyfs.HttpFSSource = nil

func index(w http.ResponseWriter, req *http.Request) {
  fmt.Fprintf(w, "rawdata.oceanobservatories.org/\n")
}

func rawData( w http.ResponseWriter, req *http.Request ) {
  listing,err := fs.ReadHttpDir( req.URL.Path )

  if err == nil {
    for _,child := range listing.Children {
      fmt.Fprintf(w, "%s
\n", child, child )
    }

    fmt.Fprintf(w, "\n")
  } else {
    fmt.Fprintf( w, "Error: %s\n", err.Error() )
  }

  }

  func main() {

    var err error
    fs, err = lazyfs.OpenHttpFSSource( OOIRawDataRootURL )

    if err != nil {
      panic( fmt.Sprintf("Error opening HTTP FS Source: %s", err.Error() ) )
    }

    fmt.Printf("Starting http handler at http://localhost:5000/")

    http.HandleFunc("/", rawData)
    //http.HandleFunc("/", index)
    http.ListenAndServe("127.0.0.1:5000", nil)
  }
<commit_msg>Very cursory JSON output.<commit_after>package main

import (
  "fmt"
  "net/http"
  "regexp"
  "encoding/json"
)
import "github.com/amarburg/go-lazyfs"

var OOIRawDataRootURL = "https://rawdata.oceanobservatories.org/"

var fs *lazyfs.HttpFSSource = nil
var trailingSlash = regexp.MustCompile(`/$`)

func index(w http.ResponseWriter, req *http.Request) {
  fmt.Fprintf(w, "rawdata.oceanobservatories.org/\n")
}

func rawData( w http.ResponseWriter, req *http.Request ) {
  listing,err := fs.ReadHttpDir( req.URL.Path )

  if err == nil {
      for _,child := range listing.Children {
        if( trailingSlash.MatchString( child ) ) {
        fmt.Fprintf(w, "%s
\n", child, child )
      } else {
        fmt.Fprintf(w, "%s\n", child )
      }
    }

    fmt.Fprintf(w, "\n")
  } else {
    fmt.Fprintf( w, "Error: %s\n", err.Error() )
  }

}

func rawDataJson( w http.ResponseWriter, req *http.Request ) {
  listing,err := fs.ReadHttpDir( req.URL.Path )

  if err == nil {

    type DirListing struct {
      Directories []string
      Files []string
    }

    output := DirListing{}

    for _,child := range listing.Children {
      if( trailingSlash.MatchString( child ) ) {
        output.Directories = append(output.Directories, child )
      } else {
        output.Files = append(output.Files, child )
      }
    }

    b, err := json.MarshalIndent(output,"","  ")
    if err != nil {
      fmt.Fprintln(w, "JSON error:", err)
    }

    w.Write(b)

  } else {
    fmt.Fprintf( w, "Error: %s\n", err.Error() )
  }

}

func main() {

  var err error
  fs, err = lazyfs.OpenHttpFSSource( OOIRawDataRootURL )

  if err != nil {
    panic( fmt.Sprintf("Error opening HTTP FS Source: %s", err.Error() ) )
  }

  fmt.Printf("Starting http handler at http://localhost:5000/\n")

  http.HandleFunc("/", rawDataJson)
  //http.HandleFunc("/", index)
  http.ListenAndServe("127.0.0.1:5000", nil)
}
<|endoftext|>


<commit_before>package lbot

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/json"
	// "errors"
	"io/ioutil"
	"net/http"
	// "strings"
	"time"
)

// The LINE BOT
type Bot struct {
	// Configuration of this BOT
	config *Config
}

// mid, message? ID
type mid string

type eventString string

type Location struct {
	Title   string `json:"title"`
	Address string `json:"Address"`
}

// When a user sends a message, the following data is sent to your server from the LINE platform.
type Message struct {

	// Identifier of the message.
	Id string `json:"id,omitempty"`
	// A numeric value indicating the type of message sent.
	ContentType int `json:"contentType,omitempty"`
	// MID of the user who sent the message.
	From string `json:"from,omitempty"`
	// Time and date request created. Displayed as the amount of time passed since 0:00:00 on January 1, 1970. The unit is given in milliseconds.
	CreatedTime       int `json:"createdTime,omitempty"`
	parsedCreatedTime *time.Time

	// Array of user who will receive the message.
	To []mid `json:"to,omitempty"`
	// Type of user who will receive the message. (1: To user )
	ToType int `json:"toType,omitempty"`
	// Detailed information about the message
	// ContentMetadata

	// Posted text to be delivered. Note: users can send a message which has max 10,000 characters.
	Text string `json:"text,omitempty"`

	// Location data. This property is defined if the text message sent contains location data.
	Location *Location `json:"location,omitempty"`
}

// The LINE platform sends operation requests to your BOT API server when users perform actions such as adding your official account as friend.
type Operation struct {

	// Revision number of operation
	Revision int `json:"revision,omitempty"`
	// Type of operation
	OpType int `json:"opType,omitempty"`
	// Array of MIDs
	Params []*string `json:"params,omitempty"`
}

type Content struct {
	Message
	Operation
}

type Result struct {
	// Fixed value "u2ddf2eb3c959e561f6c9fa2ea732e7eb8"
	From string `json:from`
	// Fixed value "1341301815"
	FromChannel json.Number `json:"fromChannel"`
	// MID value granted by the BOT API server’s Channel
	To []mid `json:"to"`
	// Channel ID of the BOT API server
	ToChannel json.Number `json:"toChannel"`
	// Identifier used to show the type of data
	EventType eventString `json:eventType`
	// ID string to identify each event
	Id string `json:"id"`
	// Actual data relayed by the message
	Content Content `json:"content"`
}

type Request struct {

	// Array of target user. Max count: 150.
	To []mid `json:"to"`
	// 1383378250 Fixed value
	ToChannel int `json:"toChannel"`
	// "138311608800106203" Fixed value.
	EventType eventString `json:"eventType"`
	// Object that contains the message (varies according to message type).
	Content Content `json:"content"`
}

// Return object for Callback Request
type CallbackRequest struct {
	vaild  bool
	Result []Result `json:"result"`
}

type UserProfileResponse struct {
	// contacts
	Contacts []ProfileInfo `json:"contacts"`
	Count    int           `json:"count"`
	Total    int           `json:"total"`
	Start    int           `json:"start"`
	Display  int           `json:"display"`
}

type ProfileInfo struct {
	DisplayName   string `json:"displayName"`
	MID           mid    `json:"mid"`
	pictureUrl    string `json:"pictureUrl"`
	statusMessage string `json:"statusMessage"`
}

func ParseRequest(r *http.Request) (*CallbackRequest, error) {
	result := CallbackRequest{}
	data, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return nil, err
	}
	err = json.Unmarshal(data, &result)
	if err != nil {
		return nil, err
	}
	return &result, nil
}

func ParseProfileResponse(r *http.Response) (*UserProfileResponse, error) {
	result := UserProfileResponse{}
	data, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return nil, err
	}
	err = json.Unmarshal(data, &result)
	if err != nil {
		return nil, err
	}
	return &result, nil

}

// checkSignature reports whether messageMAC is a valid HMAC tag for message.
func CheckSignature(message, messageMAC, key []byte) bool {
	mac := hmac.New(sha256.New, key)
	mac.Write(message)
	expectedMAC := mac.Sum(nil)
	return hmac.Equal(messageMAC, expectedMAC)
}

// Set default fixed value for request
func (r *Request) SetDefaults() {
	r.ToChannel = DefaultToChannel
	r.EventType = EventSendMessage
}

func (r *Request) AddTargetUser(m mid) error {
	if len(r.To) >= 150 {
		return ErrUserExceed
	}
	r.To = append(r.To, m)
	return nil
}

func (r *Request) SetText(text string) error {
	r.Content.ToType = ToTypeUser
	r.Content.ContentType = TextMessage
	r.Content.Text = text
	return nil
}
<commit_msg>modify From mid<commit_after>package lbot

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/json"
	// "errors"
	"io/ioutil"
	"net/http"
	// "strings"
	"time"
)

// The LINE BOT
type Bot struct {
	// Configuration of this BOT
	config *Config
}

// mid, message? ID
type mid string

type eventString string

type Location struct {
	Title   string `json:"title"`
	Address string `json:"Address"`
}

// When a user sends a message, the following data is sent to your server from the LINE platform.
type Message struct {

	// Identifier of the message.
	Id string `json:"id,omitempty"`
	// A numeric value indicating the type of message sent.
	ContentType int `json:"contentType,omitempty"`
	// MID of the user who sent the message.
	From string `json:"from,omitempty"`
	// Time and date request created. Displayed as the amount of time passed since 0:00:00 on January 1, 1970. The unit is given in milliseconds.
	CreatedTime       int `json:"createdTime,omitempty"`
	parsedCreatedTime *time.Time

	// Array of user who will receive the message.
	To []mid `json:"to,omitempty"`
	// Type of user who will receive the message. (1: To user )
	ToType int `json:"toType,omitempty"`
	// Detailed information about the message
	// ContentMetadata

	// Posted text to be delivered. Note: users can send a message which has max 10,000 characters.
	Text string `json:"text,omitempty"`

	// Location data. This property is defined if the text message sent contains location data.
	Location *Location `json:"location,omitempty"`
}

// The LINE platform sends operation requests to your BOT API server when users perform actions such as adding your official account as friend.
type Operation struct {

	// Revision number of operation
	Revision int `json:"revision,omitempty"`
	// Type of operation
	OpType int `json:"opType,omitempty"`
	// Array of MIDs
	Params []*string `json:"params,omitempty"`
}

type Content struct {
	Message
	Operation
}

type Result struct {
	// Fixed value "u2ddf2eb3c959e561f6c9fa2ea732e7eb8"
	From mid `json:from`
	// Fixed value "1341301815"
	FromChannel json.Number `json:"fromChannel"`
	// MID value granted by the BOT API server’s Channel
	To []mid `json:"to"`
	// Channel ID of the BOT API server
	ToChannel json.Number `json:"toChannel"`
	// Identifier used to show the type of data
	EventType eventString `json:eventType`
	// ID string to identify each event
	Id string `json:"id"`
	// Actual data relayed by the message
	Content Content `json:"content"`
}

type Request struct {

	// Array of target user. Max count: 150.
	To []mid `json:"to"`
	// 1383378250 Fixed value
	ToChannel int `json:"toChannel"`
	// "138311608800106203" Fixed value.
	EventType eventString `json:"eventType"`
	// Object that contains the message (varies according to message type).
	Content Content `json:"content"`
}

// Return object for Callback Request
type CallbackRequest struct {
	vaild  bool
	Result []Result `json:"result"`
}

type UserProfileResponse struct {
	// contacts
	Contacts []ProfileInfo `json:"contacts"`
	Count    int           `json:"count"`
	Total    int           `json:"total"`
	Start    int           `json:"start"`
	Display  int           `json:"display"`
}

type ProfileInfo struct {
	DisplayName   string `json:"displayName"`
	MID           mid    `json:"mid"`
	pictureUrl    string `json:"pictureUrl"`
	statusMessage string `json:"statusMessage"`
}

func ParseRequest(r *http.Request) (*CallbackRequest, error) {
	result := CallbackRequest{}
	data, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return nil, err
	}
	err = json.Unmarshal(data, &result)
	if err != nil {
		return nil, err
	}
	return &result, nil
}

func ParseProfileResponse(r *http.Response) (*UserProfileResponse, error) {
	result := UserProfileResponse{}
	data, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return nil, err
	}
	err = json.Unmarshal(data, &result)
	if err != nil {
		return nil, err
	}
	return &result, nil

}

// checkSignature reports whether messageMAC is a valid HMAC tag for message.
func CheckSignature(message, messageMAC, key []byte) bool {
	mac := hmac.New(sha256.New, key)
	mac.Write(message)
	expectedMAC := mac.Sum(nil)
	return hmac.Equal(messageMAC, expectedMAC)
}

// Set default fixed value for request
func (r *Request) SetDefaults() {
	r.ToChannel = DefaultToChannel
	r.EventType = EventSendMessage
}

func (r *Request) AddTargetUser(m mid) error {
	if len(r.To) >= 150 {
		return ErrUserExceed
	}
	r.To = append(r.To, m)
	return nil
}

func (r *Request) SetText(text string) error {
	r.Content.ToType = ToTypeUser
	r.Content.ContentType = TextMessage
	r.Content.Text = text
	return nil
}
<|endoftext|>


<commit_before>// Package lzma2 provides readers and writers for the LZMA2 format. The
// format adds the capabilities flushing, parallel compression and
// uncompressed segments to the LZMA algorithm.
package lzma2

import "io"

type segmentReader struct {
}

type segmentParameters struct {
	DictSize int64
}

func newSegmentReader(lzma io.Reader, p segmentParameters) (r *segmentReader, err error) {
	panic("TODO")
}

func (r *segmentReader) Read(p []byte) (n int, err error) {
	panic("TODO")
}

func (r *segmentReader) EOS() bool {
	panic("TODO")
}
<commit_msg>lzma2: renamed segmentParameters into Parameters<commit_after>// Package lzma2 provides readers and writers for the LZMA2 format. The
// format adds the capabilities flushing, parallel compression and
// uncompressed segments to the LZMA algorithm.
package lzma2

import "io"

type segmentReader struct {
}

type Parameters struct {
	DictSize int64
}

func newSegmentReader(lzma io.Reader, p Parameters) (r *segmentReader, err error) {
	panic("TODO")
}

func (r *segmentReader) Read(p []byte) (n int, err error) {
	panic("TODO")
}

func (r *segmentReader) EOS() bool {
	panic("TODO")
}
<|endoftext|>


<commit_before>package spec

import (
	"strings"

	"github.com/casualjim/go-swagger/util"
)

// type operationRef struct {
// 	operation *Operation
// 	parameter *Parameter
// }

// specAnalyzer takes a swagger spec object and turns it into a registry
// with a bunch of utility methods to act on the information in the spec
type specAnalyzer struct {
	spec        *Swagger
	consumes    map[string]struct{}
	produces    map[string]struct{}
	authSchemes map[string]struct{}
	operations  map[string]map[string]*Operation
}

func (s *specAnalyzer) initialize() {
	for _, c := range s.spec.Consumes {
		s.consumes[c] = struct{}{}
	}
	for _, c := range s.spec.Produces {
		s.produces[c] = struct{}{}
	}
	for _, ss := range s.spec.Security {
		for k := range ss {
			s.authSchemes[k] = struct{}{}
		}
	}
	for path, pathItem := range s.AllPaths() {
		s.analyzeOperations(path, &pathItem)
	}
}

func (s *specAnalyzer) analyzeOperations(path string, op *PathItem) {
	s.analyzeOperation("GET", path, op.Get)
	s.analyzeOperation("PUT", path, op.Put)
	s.analyzeOperation("POST", path, op.Post)
	s.analyzeOperation("PATCH", path, op.Patch)
	s.analyzeOperation("DELETE", path, op.Delete)
	s.analyzeOperation("HEAD", path, op.Head)
	s.analyzeOperation("OPTIONS", path, op.Options)
}

func (s *specAnalyzer) analyzeOperation(method, path string, op *Operation) {
	if op != nil {
		for _, c := range op.Consumes {
			s.consumes[c] = struct{}{}
		}
		for _, c := range op.Produces {
			s.produces[c] = struct{}{}
		}
		for _, ss := range op.Security {
			for k := range ss {
				s.authSchemes[k] = struct{}{}
			}
		}
		if _, ok := s.operations[method]; !ok {
			s.operations[method] = make(map[string]*Operation)
		}
		s.operations[method][path] = op
	}
}

// SecurityRequirement is a representation of a security requirement for an operation
type SecurityRequirement struct {
	Name   string
	Scopes []string
}

// SecurityRequirementsFor gets the security requirements for the operation
func (s *specAnalyzer) securityRequirementsFor(operation *Operation) []SecurityRequirement {
	if s.spec.Security == nil && operation.Security == nil {
		return nil
	}

	schemes := s.spec.Security
	if operation.Security != nil {
		schemes = operation.Security
	}

	unique := make(map[string]SecurityRequirement)
	for _, scheme := range schemes {
		for k, v := range scheme {
			if _, ok := unique[k]; !ok {
				unique[k] = SecurityRequirement{Name: k, Scopes: v}
			}
		}
	}

	var result []SecurityRequirement
	for _, v := range unique {
		result = append(result, v)
	}
	return result
}

// SecurityDefinitionsFor gets the matching security definitions for a set of requirements
func (s *specAnalyzer) SecurityDefinitionsFor(operation *Operation) map[string]SecurityScheme {
	requirements := s.securityRequirementsFor(operation)
	if len(requirements) == 0 {
		return nil
	}
	result := make(map[string]SecurityScheme)
	for _, v := range requirements {
		if definition, ok := s.spec.SecurityDefinitions[v.Name]; ok {
			if definition != nil {
				result[v.Name] = *definition
			}
		}
	}
	return result
}

// ConsumesFor gets the mediatypes for the operation
func (s *specAnalyzer) ConsumesFor(operation *Operation) []string {
	cons := make(map[string]struct{})
	for k := range s.consumes {
		cons[k] = struct{}{}
	}
	for _, c := range operation.Consumes {
		cons[c] = struct{}{}
	}
	return s.structMapKeys(cons)
}

// ProducesFor gets the mediatypes for the operation
func (s *specAnalyzer) ProducesFor(operation *Operation) []string {
	prod := make(map[string]struct{})
	for k := range s.produces {
		prod[k] = struct{}{}
	}
	for _, c := range operation.Produces {
		prod[c] = struct{}{}
	}
	return s.structMapKeys(prod)
}

func fieldNameFromParam(param *Parameter) string {
	if nm, ok := param.Extensions.GetString("go-name"); ok {
		return nm
	}
	return util.ToGoName(param.Name)
}

func (s *specAnalyzer) paramsAsMap(parameters []Parameter, res map[string]Parameter) {
	for _, param := range parameters {
		res[fieldNameFromParam(&param)] = param
	}
}

func (s *specAnalyzer) ParamsFor(method, path string) map[string]Parameter {
	res := make(map[string]Parameter)
	for _, param := range s.spec.Parameters {
		res[fieldNameFromParam(&param)] = param
	}
	if pi, ok := s.spec.Paths.Paths[path]; ok {
		s.paramsAsMap(pi.Parameters, res)
		s.paramsAsMap(s.operations[strings.ToUpper(method)][path].Parameters, res)
	}
	return res
}

func (s *specAnalyzer) OperationFor(method, path string) (*Operation, bool) {
	if mp, ok := s.operations[strings.ToUpper(method)]; ok {
		op, fn := mp[path]
		return op, fn
	}
	return nil, false
}

func (s *specAnalyzer) Operations() map[string]map[string]*Operation {
	return s.operations
}

func (s *specAnalyzer) structMapKeys(mp map[string]struct{}) []string {
	var result []string
	for k := range mp {
		result = append(result, k)
	}
	return result
}

// AllPaths returns all the paths in the swagger spec
func (s *specAnalyzer) AllPaths() map[string]PathItem {
	return s.spec.Paths.Paths
}

func (s *specAnalyzer) OperationIDs() []string {
	var result []string
	for _, v := range s.operations {
		for _, vv := range v {
			result = append(result, vv.ID)
		}
	}
	return result
}

func (s *specAnalyzer) RequiredConsumes() []string {
	return s.structMapKeys(s.consumes)
}

func (s *specAnalyzer) RequiredProduces() []string {
	return s.structMapKeys(s.produces)
}

func (s *specAnalyzer) RequiredSchemes() []string {
	return s.structMapKeys(s.authSchemes)
}
<commit_msg>generate operations and parameters for the server<commit_after>package spec

import (
	"strings"

	"github.com/casualjim/go-swagger/util"
)

// type operationRef struct {
// 	operation *Operation
// 	parameter *Parameter
// }

// specAnalyzer takes a swagger spec object and turns it into a registry
// with a bunch of utility methods to act on the information in the spec
type specAnalyzer struct {
	spec        *Swagger
	consumes    map[string]struct{}
	produces    map[string]struct{}
	authSchemes map[string]struct{}
	operations  map[string]map[string]*Operation
}

func (s *specAnalyzer) initialize() {
	for _, c := range s.spec.Consumes {
		s.consumes[c] = struct{}{}
	}
	for _, c := range s.spec.Produces {
		s.produces[c] = struct{}{}
	}
	for _, ss := range s.spec.Security {
		for k := range ss {
			s.authSchemes[k] = struct{}{}
		}
	}
	for path, pathItem := range s.AllPaths() {
		s.analyzeOperations(path, &pathItem)
	}
}

func (s *specAnalyzer) analyzeOperations(path string, op *PathItem) {
	s.analyzeOperation("GET", path, op.Get)
	s.analyzeOperation("PUT", path, op.Put)
	s.analyzeOperation("POST", path, op.Post)
	s.analyzeOperation("PATCH", path, op.Patch)
	s.analyzeOperation("DELETE", path, op.Delete)
	s.analyzeOperation("HEAD", path, op.Head)
	s.analyzeOperation("OPTIONS", path, op.Options)
}

func (s *specAnalyzer) analyzeOperation(method, path string, op *Operation) {
	if op != nil {
		for _, c := range op.Consumes {
			s.consumes[c] = struct{}{}
		}
		for _, c := range op.Produces {
			s.produces[c] = struct{}{}
		}
		for _, ss := range op.Security {
			for k := range ss {
				s.authSchemes[k] = struct{}{}
			}
		}
		if _, ok := s.operations[method]; !ok {
			s.operations[method] = make(map[string]*Operation)
		}
		s.operations[method][path] = op
	}
}

// SecurityRequirement is a representation of a security requirement for an operation
type SecurityRequirement struct {
	Name   string
	Scopes []string
}

// SecurityRequirementsFor gets the security requirements for the operation
func (s *specAnalyzer) securityRequirementsFor(operation *Operation) []SecurityRequirement {
	if s.spec.Security == nil && operation.Security == nil {
		return nil
	}

	schemes := s.spec.Security
	if operation.Security != nil {
		schemes = operation.Security
	}

	unique := make(map[string]SecurityRequirement)
	for _, scheme := range schemes {
		for k, v := range scheme {
			if _, ok := unique[k]; !ok {
				unique[k] = SecurityRequirement{Name: k, Scopes: v}
			}
		}
	}

	var result []SecurityRequirement
	for _, v := range unique {
		result = append(result, v)
	}
	return result
}

// SecurityDefinitionsFor gets the matching security definitions for a set of requirements
func (s *specAnalyzer) SecurityDefinitionsFor(operation *Operation) map[string]SecurityScheme {
	requirements := s.securityRequirementsFor(operation)
	if len(requirements) == 0 {
		return nil
	}
	result := make(map[string]SecurityScheme)
	for _, v := range requirements {
		if definition, ok := s.spec.SecurityDefinitions[v.Name]; ok {
			if definition != nil {
				result[v.Name] = *definition
			}
		}
	}
	return result
}

// ConsumesFor gets the mediatypes for the operation
func (s *specAnalyzer) ConsumesFor(operation *Operation) []string {
	cons := make(map[string]struct{})
	for k := range s.consumes {
		cons[k] = struct{}{}
	}
	for _, c := range operation.Consumes {
		cons[c] = struct{}{}
	}
	return s.structMapKeys(cons)
}

// ProducesFor gets the mediatypes for the operation
func (s *specAnalyzer) ProducesFor(operation *Operation) []string {
	prod := make(map[string]struct{})
	for k := range s.produces {
		prod[k] = struct{}{}
	}
	for _, c := range operation.Produces {
		prod[c] = struct{}{}
	}
	return s.structMapKeys(prod)
}

func fieldNameFromParam(param *Parameter) string {
	if nm, ok := param.Extensions.GetString("go-name"); ok {
		return nm
	}
	return util.ToGoName(param.Name)
}

func (s *specAnalyzer) paramsAsMap(parameters []Parameter, res map[string]Parameter) {
	for _, param := range parameters {
		res[fieldNameFromParam(&param)] = param
	}
}

func (s *specAnalyzer) ParamsFor(method, path string) map[string]Parameter {
	res := make(map[string]Parameter)
	for _, param := range s.spec.Parameters {
		res[fieldNameFromParam(&param)] = param
	}
	if pi, ok := s.spec.Paths.Paths[path]; ok {
		s.paramsAsMap(pi.Parameters, res)
		s.paramsAsMap(s.operations[strings.ToUpper(method)][path].Parameters, res)
	}
	return res
}

func (s *specAnalyzer) OperationForName(operationID string) (*Operation, bool) {
	for _, v := range s.operations {
		for _, vv := range v {
			if operationID == vv.ID {
				return vv, true
			}
		}
	}
	return nil, false
}

func (s *specAnalyzer) OperationFor(method, path string) (*Operation, bool) {
	if mp, ok := s.operations[strings.ToUpper(method)]; ok {
		op, fn := mp[path]
		return op, fn
	}
	return nil, false
}

func (s *specAnalyzer) Operations() map[string]map[string]*Operation {
	return s.operations
}

func (s *specAnalyzer) structMapKeys(mp map[string]struct{}) []string {
	var result []string
	for k := range mp {
		result = append(result, k)
	}
	return result
}

// AllPaths returns all the paths in the swagger spec
func (s *specAnalyzer) AllPaths() map[string]PathItem {
	return s.spec.Paths.Paths
}

func (s *specAnalyzer) OperationIDs() []string {
	var result []string
	for _, v := range s.operations {
		for _, vv := range v {
			result = append(result, vv.ID)
		}
	}
	return result
}

func (s *specAnalyzer) RequiredConsumes() []string {
	return s.structMapKeys(s.consumes)
}

func (s *specAnalyzer) RequiredProduces() []string {
	return s.structMapKeys(s.produces)
}

func (s *specAnalyzer) RequiredSchemes() []string {
	return s.structMapKeys(s.authSchemes)
}
<|endoftext|>


<commit_before>package annot

import (
	"fmt"
	"reflect"
	"testing"
)

func testScanComment(t *testing.T, src string, expect []Comment, expect_err bool) {
	res, err := ScanComment(src)
	fmt.Printf("%q:\n\texpect=%+v\n\tresult=%+v\n\texpect_err=%v\n\terr=%v\n",
		src, expect, res, expect_err, err)

	if (err != nil && !expect_err) || (err == nil && expect_err) {
		t.Errorf("%q: expect_err=%v, err=%v\n", src, expect_err, err)
		return
	}
	if !reflect.DeepEqual(res, expect) {
		t.Errorf("%q: scan failed\n", src)
		return
	}

}

func TestSharp(t *testing.T) {
	fmt.Println("TestSharp")
	testScanComment(t, "# abc ", []Comment{
		Comment{
			Offset:  0,
			Length:  6,
			Content: "abc",
		},
	}, false)
	testScanComment(t, "# abc \nx", []Comment{
		Comment{
			Offset:  0,
			Length:  7,
			Content: "abc",
		},
	}, false)
}

func TestDash(t *testing.T) {
	fmt.Println("TestDash")
	testScanComment(t, "-- abc ", []Comment{
		Comment{
			Offset:  0,
			Length:  7,
			Content: "abc",
		},
	}, false)
	testScanComment(t, "-- abc \nx", []Comment{
		Comment{
			Offset:  0,
			Length:  8,
			Content: "abc",
		},
	}, false)
	testScanComment(t, "-", []Comment{}, false)
	testScanComment(t, "1-1", []Comment{}, false)
}

func TestBlock(t *testing.T) {
	fmt.Println("TestBlock")
	testScanComment(t, "/* abc */", []Comment{
		Comment{
			Offset:  0,
			Length:  9,
			Content: "abc",
		},
	}, false)
	testScanComment(t, "/*", nil, true)
	testScanComment(t, "/*/", nil, true)
	testScanComment(t, "/* abc", nil, true)
	testScanComment(t, "/* abc *", nil, true)
	testScanComment(t, "/* abc * */", []Comment{
		Comment{
			Offset:  0,
			Length:  11,
			Content: "abc *",
		},
	}, false)
	testScanComment(t, "/* \n\n\n */", []Comment{
		Comment{
			Offset:  0,
			Length:  9,
			Content: "",
		},
	}, false)
}

func TestMix(t *testing.T) {
	fmt.Println("TestMix")
	testScanComment(t, "/* abc *//* def */", []Comment{
		Comment{
			Offset:  0,
			Length:  9,
			Content: "abc",
		},
		Comment{
			Offset:  9,
			Length:  9,
			Content: "def",
		},
	}, false)
	testScanComment(t, "# /* abc */", []Comment{
		Comment{
			Offset:  0,
			Length:  11,
			Content: "/* abc */",
		},
	}, false)
	testScanComment(t, "# \n/* abc */", []Comment{
		Comment{
			Offset:  0,
			Length:  3,
			Content: "",
		},
		Comment{
			Offset:  3,
			Length:  9,
			Content: "abc",
		},
	}, false)
	testScanComment(t, "/* abc # def \n */", []Comment{
		Comment{
			Offset:  0,
			Length:  17,
			Content: "abc # def",
		},
	}, false)
}

func TestStringLiteral(t *testing.T) {
	fmt.Println("TestStringLiteral")
	testScanComment(t, "hello '/* alsjfdjas */'/*  */", []Comment{
		Comment{
			Offset:  23,
			Length:  6,
			Content: "",
		},
	}, false)
	testScanComment(t, "'", nil, true)
	testScanComment(t, "'\\''", []Comment{}, false)
	testScanComment(t, "'\\''# ...", []Comment{
		Comment{
			Offset:  4,
			Length:  5,
			Content: "...",
		},
	}, false)
}
<commit_msg>Change error display in comment_test<commit_after>package annot

import (
	"fmt"
	"reflect"
	"testing"
)

func testScanComment(t *testing.T, src string, expect []Comment, expect_err bool) {
	res, err := ScanComment(src)
	fmt.Printf("%q:\n\texpect=%+v\n\tresult=%+v\n\texpect_err=%v\n\terr=%v\n",
		src, expect, res, expect_err, err)

	if (err != nil && !expect_err) || (err == nil && expect_err) {
		t.Errorf("%q: err != expect_err\n", src)
		return
	}
	if !reflect.DeepEqual(res, expect) {
		t.Errorf("%q: result != expect\n", src)
		return
	}

}

func TestSharp(t *testing.T) {
	fmt.Println("TestSharp")
	testScanComment(t, "# abc ", []Comment{
		Comment{
			Offset:  0,
			Length:  6,
			Content: "abc",
		},
	}, false)
	testScanComment(t, "# abc \nx", []Comment{
		Comment{
			Offset:  0,
			Length:  7,
			Content: "abc",
		},
	}, false)
}

func TestDash(t *testing.T) {
	fmt.Println("TestDash")
	testScanComment(t, "-- abc ", []Comment{
		Comment{
			Offset:  0,
			Length:  7,
			Content: "abc",
		},
	}, false)
	testScanComment(t, "-- abc \nx", []Comment{
		Comment{
			Offset:  0,
			Length:  8,
			Content: "abc",
		},
	}, false)
	testScanComment(t, "-", []Comment{}, false)
	testScanComment(t, "1-1", []Comment{}, false)
}

func TestBlock(t *testing.T) {
	fmt.Println("TestBlock")
	testScanComment(t, "/* abc */", []Comment{
		Comment{
			Offset:  0,
			Length:  9,
			Content: "abc",
		},
	}, false)
	testScanComment(t, "/*", nil, true)
	testScanComment(t, "/*/", nil, true)
	testScanComment(t, "/* abc", nil, true)
	testScanComment(t, "/* abc *", nil, true)
	testScanComment(t, "/* abc * */", []Comment{
		Comment{
			Offset:  0,
			Length:  11,
			Content: "abc *",
		},
	}, false)
	testScanComment(t, "/* \n\n\n */", []Comment{
		Comment{
			Offset:  0,
			Length:  9,
			Content: "",
		},
	}, false)
}

func TestMix(t *testing.T) {
	fmt.Println("TestMix")
	testScanComment(t, "/* abc *//* def */", []Comment{
		Comment{
			Offset:  0,
			Length:  9,
			Content: "abc",
		},
		Comment{
			Offset:  9,
			Length:  9,
			Content: "def",
		},
	}, false)
	testScanComment(t, "# /* abc */", []Comment{
		Comment{
			Offset:  0,
			Length:  11,
			Content: "/* abc */",
		},
	}, false)
	testScanComment(t, "# \n/* abc */", []Comment{
		Comment{
			Offset:  0,
			Length:  3,
			Content: "",
		},
		Comment{
			Offset:  3,
			Length:  9,
			Content: "abc",
		},
	}, false)
	testScanComment(t, "/* abc # def \n */", []Comment{
		Comment{
			Offset:  0,
			Length:  17,
			Content: "abc # def",
		},
	}, false)
}

func TestStringLiteral(t *testing.T) {
	fmt.Println("TestStringLiteral")
	testScanComment(t, "hello '/* alsjfdjas */'/*  */", []Comment{
		Comment{
			Offset:  23,
			Length:  6,
			Content: "",
		},
	}, false)
	testScanComment(t, "'", nil, true)
	testScanComment(t, "'\\''", []Comment{}, false)
	testScanComment(t, "'\\''# ...", []Comment{
		Comment{
			Offset:  4,
			Length:  5,
			Content: "...",
		},
	}, false)
}
<|endoftext|>