<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	"log"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/uber-common/cpustat/lib"
)

type pidList []int

func (pl *pidList) String() string {
	if pl == nil {
		return ""
	}
	ss := make([]string, len(*pl))
	for i, pid := range *pl {
		ss[i] = strconv.Itoa(pid)
	}
	return strings.Join(ss, ",")
}

func (pl *pidList) Set(s string) error {
	parts := strings.Split(s, ",")
	for _, part := range parts {
		pid, err := strconv.Atoi(part)
		if err != nil {
			return fmt.Errorf("invalid pid list component %q, expected an integer", part)
		}
		*pl = append(*pl, pid)
	}
	return nil
}

func main() {
	if err := run(); err != nil {
		log.Fatalln(err)
	}
}

func run() error {
	var (
		interval    = flag.Duration("i", 200*time.Millisecond, "duration between measurements")
		sampleCount = flag.Uint("n", 0, "Maximum number of samples to capture")
		pids        pidList
	)
	flag.Var(&pids, "p", "Comma separated PID list to profile")
	flag.Parse()

	if len(pids) == 0 {
		fmt.Fprintf(os.Stderr, "no pids provided")
		os.Exit(1)
	}

	procStats := cpustat.ProcStats{}
	procStatsReaderCount := len(pids)
	procStatsReaders := make([]*cpustat.ProcStatsSeekReader, procStatsReaderCount)

	samplesRemaining := int64(*sampleCount)
	if samplesRemaining == 0 {
		samplesRemaining = -1
	}

	for i, pid := range pids {
		procStatsReader := cpustat.ProcStatsSeekReader{
			PID: pid,
		}
		procStatsReaders[i] = &procStatsReader

		procStatsInitError := procStatsReader.Initialize()
		if procStatsInitError != nil {
			procStatsReaders[i] = nil
			procStatsReaderCount--
		}
	}

	var (
		bufw = bufio.NewWriterSize(os.Stdout, 4096) // output buffer
		tmp  [256]byte                              // scratch space for marshaling integers
	)

	for i, part := range []string{
		"pid",
		"time",
		"proc.utime",
		"proc.stime",
		"proc.cutime",
		"proc.cstime",
		"proc.numthreads",
		"proc.rss",
		"proc.guesttime",
		"proc.cguesttime",
	} {
		if i > 0 {
			_, _ = bufw.WriteRune(',')
		}
		_, _ = bufw.WriteString(part)
	}
	_, _ = bufw.WriteRune('\n')

	for procStatsReaderCount > 0 && samplesRemaining != 0 {
		startOfRead := time.Now()

		for i, procStatsReader := range procStatsReaders {
			if procStatsReader == nil {
				continue
			}

			procStatsError := procStatsReader.ReadStats(&procStats)
			if procStatsError != nil {
				procStatsReaders[i] = nil
				procStatsReaderCount--
				continue
			}

			_, _ = bufw.Write(strconv.AppendInt(tmp[:], int64(procStatsReader.PID), 10))
			_, _ = bufw.WriteRune(',')
			_, _ = bufw.Write(strconv.AppendInt(tmp[:], procStats.CaptureTime.UnixNano()/1e6, 10))
			_, _ = bufw.WriteRune(',')
			_, _ = bufw.Write(strconv.AppendUint(tmp[:], procStats.Utime, 10))
			_, _ = bufw.WriteRune(',')
			_, _ = bufw.Write(strconv.AppendUint(tmp[:], procStats.Stime, 10))
			_, _ = bufw.WriteRune(',')
			_, _ = bufw.Write(strconv.AppendUint(tmp[:], procStats.Cutime, 10))
			_, _ = bufw.WriteRune(',')
			_, _ = bufw.Write(strconv.AppendUint(tmp[:], procStats.Cstime, 10))
			_, _ = bufw.WriteRune(',')
			_, _ = bufw.Write(strconv.AppendUint(tmp[:], procStats.Numthreads, 10))
			_, _ = bufw.WriteRune(',')
			_, _ = bufw.Write(strconv.AppendUint(tmp[:], procStats.Rss, 10))
			_, _ = bufw.WriteRune(',')
			_, _ = bufw.Write(strconv.AppendUint(tmp[:], procStats.Guesttime, 10))
			_, _ = bufw.WriteRune(',')
			_, _ = bufw.Write(strconv.AppendUint(tmp[:], procStats.Cguesttime, 10))
			_, _ = bufw.WriteRune('\n')
		}
		if err := bufw.Flush(); err != nil {
			return err
		}

		if samplesRemaining > 0 {
			samplesRemaining--
		}

		if procStatsReaderCount > 0 && samplesRemaining != 0 {
			if adjustedSleep := *interval - time.Now().Sub(startOfRead); adjustedSleep > 0 {
				// TODO actually probably some minimum sleep tolerance
				time.Sleep(adjustedSleep)
			}
		}
	}

	return bufw.Flush()
}
<commit_msg>fixup! cpustat-raw: use a buffered writer, and stop printf-ing<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"log"
	"os"
	"strconv"
	"strings"
	"time"

	"github.com/uber-common/cpustat/lib"
)

type pidList []int

func (pl *pidList) String() string {
	if pl == nil {
		return ""
	}
	ss := make([]string, len(*pl))
	for i, pid := range *pl {
		ss[i] = strconv.Itoa(pid)
	}
	return strings.Join(ss, ",")
}

func (pl *pidList) Set(s string) error {
	parts := strings.Split(s, ",")
	for _, part := range parts {
		pid, err := strconv.Atoi(part)
		if err != nil {
			return fmt.Errorf("invalid pid list component %q, expected an integer", part)
		}
		*pl = append(*pl, pid)
	}
	return nil
}

func main() {
	if err := run(); err != nil {
		log.Fatalln(err)
	}
}

func run() error {
	var (
		interval    = flag.Duration("i", 200*time.Millisecond, "duration between measurements")
		sampleCount = flag.Uint("n", 0, "Maximum number of samples to capture")
		pids        pidList
	)
	flag.Var(&pids, "p", "Comma separated PID list to profile")
	flag.Parse()

	if len(pids) == 0 {
		fmt.Fprintf(os.Stderr, "no pids provided")
		os.Exit(1)
	}

	procStats := cpustat.ProcStats{}
	procStatsReaderCount := len(pids)
	procStatsReaders := make([]*cpustat.ProcStatsSeekReader, procStatsReaderCount)

	samplesRemaining := int64(*sampleCount)
	if samplesRemaining == 0 {
		samplesRemaining = -1
	}

	for i, pid := range pids {
		procStatsReader := cpustat.ProcStatsSeekReader{
			PID: pid,
		}
		procStatsReaders[i] = &procStatsReader

		procStatsInitError := procStatsReader.Initialize()
		if procStatsInitError != nil {
			procStatsReaders[i] = nil
			procStatsReaderCount--
		}
	}

	var (
		bufw = bufio.NewWriterSize(os.Stdout, 4096) // output buffer
		tmp  [256]byte                              // scratch space for marshaling integers
	)

	for i, part := range []string{
		"pid",
		"time",
		"proc.utime",
		"proc.stime",
		"proc.cutime",
		"proc.cstime",
		"proc.numthreads",
		"proc.rss",
		"proc.guesttime",
		"proc.cguesttime",
	} {
		if i > 0 {
			_, _ = bufw.WriteRune(',')
		}
		_, _ = bufw.WriteString(part)
	}
	_, _ = bufw.WriteRune('\n')

	for procStatsReaderCount > 0 && samplesRemaining != 0 {
		startOfRead := time.Now()

		for i, procStatsReader := range procStatsReaders {
			if procStatsReader == nil {
				continue
			}

			procStatsError := procStatsReader.ReadStats(&procStats)
			if procStatsError != nil {
				procStatsReaders[i] = nil
				procStatsReaderCount--
				continue
			}

			_, _ = bufw.Write(strconv.AppendInt(tmp[:0], int64(procStatsReader.PID), 10))
			_, _ = bufw.WriteRune(',')
			_, _ = bufw.Write(strconv.AppendInt(tmp[:0], procStats.CaptureTime.UnixNano()/1e6, 10))
			_, _ = bufw.WriteRune(',')
			_, _ = bufw.Write(strconv.AppendUint(tmp[:0], procStats.Utime, 10))
			_, _ = bufw.WriteRune(',')
			_, _ = bufw.Write(strconv.AppendUint(tmp[:0], procStats.Stime, 10))
			_, _ = bufw.WriteRune(',')
			_, _ = bufw.Write(strconv.AppendUint(tmp[:0], procStats.Cutime, 10))
			_, _ = bufw.WriteRune(',')
			_, _ = bufw.Write(strconv.AppendUint(tmp[:0], procStats.Cstime, 10))
			_, _ = bufw.WriteRune(',')
			_, _ = bufw.Write(strconv.AppendUint(tmp[:0], procStats.Numthreads, 10))
			_, _ = bufw.WriteRune(',')
			_, _ = bufw.Write(strconv.AppendUint(tmp[:0], procStats.Rss, 10))
			_, _ = bufw.WriteRune(',')
			_, _ = bufw.Write(strconv.AppendUint(tmp[:0], procStats.Guesttime, 10))
			_, _ = bufw.WriteRune(',')
			_, _ = bufw.Write(strconv.AppendUint(tmp[:0], procStats.Cguesttime, 10))
			_, _ = bufw.WriteRune('\n')
		}
		if err := bufw.Flush(); err != nil {
			return err
		}

		if samplesRemaining > 0 {
			samplesRemaining--
		}

		if procStatsReaderCount > 0 && samplesRemaining != 0 {
			if adjustedSleep := *interval - time.Now().Sub(startOfRead); adjustedSleep > 0 {
				// TODO actually probably some minimum sleep tolerance
				time.Sleep(adjustedSleep)
			}
		}
	}

	return bufw.Flush()
}
<|endoftext|>


<commit_before>package networkdb

import (
	"github.com/hashicorp/memberlist"
	"github.com/hashicorp/serf/serf"
)

type networkEventMessage struct {
	id   string
	node string
	msg  []byte
}

func (m *networkEventMessage) Invalidates(other memberlist.Broadcast) bool {
	otherm := other.(*networkEventMessage)
	return m.id == otherm.id && m.node == otherm.node
}

func (m *networkEventMessage) Message() []byte {
	return m.msg
}

func (m *networkEventMessage) Finished() {
}

func (nDB *NetworkDB) sendNetworkEvent(nid string, event NetworkEvent_Type, ltime serf.LamportTime) error {
	nEvent := NetworkEvent{
		Type:      event,
		LTime:     ltime,
		NodeName:  nDB.config.NodeName,
		NetworkID: nid,
	}

	raw, err := encodeMessage(MessageTypeNetworkEvent, &nEvent)
	if err != nil {
		return err
	}

	nDB.networkBroadcasts.QueueBroadcast(&networkEventMessage{
		msg:  raw,
		id:   nid,
		node: nDB.config.NodeName,
	})
	return nil
}

type tableEventMessage struct {
	id    string
	tname string
	key   string
	msg   []byte
	node  string
}

func (m *tableEventMessage) Invalidates(other memberlist.Broadcast) bool {
	otherm := other.(*tableEventMessage)
	return m.id == otherm.id && m.tname == otherm.tname && m.key == otherm.key
}

func (m *tableEventMessage) Message() []byte {
	return m.msg
}

func (m *tableEventMessage) Finished() {
}

func (nDB *NetworkDB) sendTableEvent(event TableEvent_Type, nid string, tname string, key string, entry *entry) error {
	tEvent := TableEvent{
		Type:      event,
		LTime:     entry.ltime,
		NodeName:  nDB.config.NodeName,
		NetworkID: nid,
		TableName: tname,
		Key:       key,
		Value:     entry.value,
	}

	raw, err := encodeMessage(MessageTypeTableEvent, &tEvent)
	if err != nil {
		return err
	}

	nDB.RLock()
	broadcastQ := nDB.networks[nDB.config.NodeName][nid].tableBroadcasts
	nDB.RUnlock()

	broadcastQ.QueueBroadcast(&tableEventMessage{
		msg:   raw,
		id:    nid,
		tname: tname,
		key:   key,
		node:  nDB.config.NodeName,
	})
	return nil
}
<commit_msg>Make sure broadcast queue is valid broadcasting<commit_after>package networkdb

import (
	"github.com/hashicorp/memberlist"
	"github.com/hashicorp/serf/serf"
)

type networkEventMessage struct {
	id   string
	node string
	msg  []byte
}

func (m *networkEventMessage) Invalidates(other memberlist.Broadcast) bool {
	otherm := other.(*networkEventMessage)
	return m.id == otherm.id && m.node == otherm.node
}

func (m *networkEventMessage) Message() []byte {
	return m.msg
}

func (m *networkEventMessage) Finished() {
}

func (nDB *NetworkDB) sendNetworkEvent(nid string, event NetworkEvent_Type, ltime serf.LamportTime) error {
	nEvent := NetworkEvent{
		Type:      event,
		LTime:     ltime,
		NodeName:  nDB.config.NodeName,
		NetworkID: nid,
	}

	raw, err := encodeMessage(MessageTypeNetworkEvent, &nEvent)
	if err != nil {
		return err
	}

	nDB.networkBroadcasts.QueueBroadcast(&networkEventMessage{
		msg:  raw,
		id:   nid,
		node: nDB.config.NodeName,
	})
	return nil
}

type tableEventMessage struct {
	id    string
	tname string
	key   string
	msg   []byte
	node  string
}

func (m *tableEventMessage) Invalidates(other memberlist.Broadcast) bool {
	otherm := other.(*tableEventMessage)
	return m.id == otherm.id && m.tname == otherm.tname && m.key == otherm.key
}

func (m *tableEventMessage) Message() []byte {
	return m.msg
}

func (m *tableEventMessage) Finished() {
}

func (nDB *NetworkDB) sendTableEvent(event TableEvent_Type, nid string, tname string, key string, entry *entry) error {
	tEvent := TableEvent{
		Type:      event,
		LTime:     entry.ltime,
		NodeName:  nDB.config.NodeName,
		NetworkID: nid,
		TableName: tname,
		Key:       key,
		Value:     entry.value,
	}

	raw, err := encodeMessage(MessageTypeTableEvent, &tEvent)
	if err != nil {
		return err
	}

	var broadcastQ *memberlist.TransmitLimitedQueue
	nDB.RLock()
	thisNodeNetworks, ok := nDB.networks[nDB.config.NodeName]
	if ok {
		// The network may have been removed
		network, networkOk := thisNodeNetworks[nid]
		if !networkOk {
			nDB.RUnlock()
			return nil
		}

		broadcastQ = network.tableBroadcasts
	}
	nDB.RUnlock()

	// The network may have been removed
	if broadcastQ == nil {
		return nil
	}

	broadcastQ.QueueBroadcast(&tableEventMessage{
		msg:   raw,
		id:    nid,
		tname: tname,
		key:   key,
		node:  nDB.config.NodeName,
	})
	return nil
}
<|endoftext|>


<commit_before>/*
Copyright 2014 Google Inc. All rights reserved.

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

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

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

package apiserver

import (
	"net/http"
	gpath "path"
	"time"

	"github.com/GoogleCloudPlatform/kubernetes/pkg/admission"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"

	"github.com/emicklei/go-restful"
	"github.com/golang/glog"
)

// ContextFunc returns a Context given a request - a context must be returned
type ContextFunc func(req *restful.Request) api.Context

// ScopeNamer handles accessing names from requests and objects
type ScopeNamer interface {
	// Namespace returns the appropriate namespace value from the request (may be empty) or an
	// error.
	Namespace(req *restful.Request) (namespace string, err error)
	// Name returns the name from the request, and an optional namespace value if this is a namespace
	// scoped call. An error is returned if the name is not available.
	Name(req *restful.Request) (namespace, name string, err error)
	// ObjectName returns the namespace and name from an object if they exist, or an error if the object
	// does not support names.
	ObjectName(obj runtime.Object) (namespace, name string, err error)
	// SetSelfLink sets the provided URL onto the object. The method should return nil if the object
	// does not support selfLinks.
	SetSelfLink(obj runtime.Object, url string) error
	// GenerateLink creates a path and query for a given runtime object that represents the canonical path.
	GenerateLink(req *restful.Request, obj runtime.Object) (path, query string, err error)
}

// GetResource returns a function that handles retrieving a single resource from a RESTStorage object.
func GetResource(r RESTGetter, ctxFn ContextFunc, namer ScopeNamer, codec runtime.Codec) restful.RouteFunction {
	return func(req *restful.Request, res *restful.Response) {
		w := res.ResponseWriter
		namespace, name, err := namer.Name(req)
		if err != nil {
			notFound(w, req.Request)
			return
		}
		ctx := ctxFn(req)
		ctx = api.WithNamespace(ctx, namespace)

		result, err := r.Get(ctx, name)
		if err != nil {
			errorJSON(err, codec, w)
			return
		}
		if err := setSelfLink(result, req, namer); err != nil {
			errorJSON(err, codec, w)
			return
		}
		writeJSON(http.StatusOK, codec, result, w)
	}
}

// ListResource returns a function that handles retrieving a list of resources from a RESTStorage object.
func ListResource(r RESTLister, ctxFn ContextFunc, namer ScopeNamer, codec runtime.Codec) restful.RouteFunction {
	return func(req *restful.Request, res *restful.Response) {
		w := res.ResponseWriter

		namespace, err := namer.Namespace(req)
		if err != nil {
			notFound(w, req.Request)
			return
		}
		ctx := ctxFn(req)
		ctx = api.WithNamespace(ctx, namespace)

		label, err := labels.ParseSelector(req.Request.URL.Query().Get("labels"))
		if err != nil {
			errorJSON(err, codec, w)
			return
		}
		field, err := labels.ParseSelector(req.Request.URL.Query().Get("fields"))
		if err != nil {
			errorJSON(err, codec, w)
			return
		}

		result, err := r.List(ctx, label, field)
		if err != nil {
			errorJSON(err, codec, w)
			return
		}
		if err := setSelfLink(result, req, namer); err != nil {
			errorJSON(err, codec, w)
			return
		}
		writeJSON(http.StatusOK, codec, result, w)
	}
}

// CreateResource returns a function that will handle a resource creation.
func CreateResource(r RESTCreater, ctxFn ContextFunc, namer ScopeNamer, codec runtime.Codec, resource string, admit admission.Interface) restful.RouteFunction {
	return func(req *restful.Request, res *restful.Response) {
		w := res.ResponseWriter

		// TODO: we either want to remove timeout or document it (if we document, move timeout out of this function and declare it in api_installer)
		timeout := parseTimeout(req.Request.URL.Query().Get("timeout"))

		namespace, err := namer.Namespace(req)
		if err != nil {
			notFound(w, req.Request)
			return
		}
		ctx := ctxFn(req)
		ctx = api.WithNamespace(ctx, namespace)

		body, err := readBody(req.Request)
		if err != nil {
			errorJSON(err, codec, w)
			return
		}

		obj := r.New()
		if err := codec.DecodeInto(body, obj); err != nil {
			errorJSON(err, codec, w)
			return
		}

		err = admit.Admit(admission.NewAttributesRecord(obj, namespace, resource, "CREATE"))
		if err != nil {
			errorJSON(err, codec, w)
			return
		}

		result, err := finishRequest(timeout, func() (runtime.Object, error) {
			out, err := r.Create(ctx, obj)
			if status, ok := out.(*api.Status); ok && err == nil && status.Code == 0 {
				status.Code = http.StatusCreated
			}
			return out, err
		})
		if err != nil {
			errorJSON(err, codec, w)
			return
		}

		if err := setSelfLink(result, req, namer); err != nil {
			errorJSON(err, codec, w)
			return
		}

		writeJSON(http.StatusCreated, codec, result, w)
	}
}

// UpdateResource returns a function that will handle a resource update
func UpdateResource(r RESTUpdater, ctxFn ContextFunc, namer ScopeNamer, codec runtime.Codec, resource string, admit admission.Interface) restful.RouteFunction {
	return func(req *restful.Request, res *restful.Response) {
		w := res.ResponseWriter

		// TODO: we either want to remove timeout or document it (if we document, move timeout out of this function and declare it in api_installer)
		timeout := parseTimeout(req.Request.URL.Query().Get("timeout"))

		namespace, name, err := namer.Name(req)
		if err != nil {
			notFound(w, req.Request)
			return
		}
		ctx := ctxFn(req)
		ctx = api.WithNamespace(ctx, namespace)

		body, err := readBody(req.Request)
		if err != nil {
			errorJSON(err, codec, w)
			return
		}

		obj := r.New()
		if err := codec.DecodeInto(body, obj); err != nil {
			errorJSON(err, codec, w)
			return
		}

		// check the provided name against the request
		if objNamespace, objName, err := namer.ObjectName(obj); err == nil {
			if objName != name {
				errorJSON(errors.NewBadRequest("the name of the object does not match the name on the URL"), codec, w)
				return
			}
			if len(namespace) > 0 {
				if len(objNamespace) > 0 && objNamespace != namespace {
					errorJSON(errors.NewBadRequest("the namespace of the object does not match the namespace on the request"), codec, w)
					return
				}
			}
		}

		err = admit.Admit(admission.NewAttributesRecord(obj, namespace, resource, "UPDATE"))
		if err != nil {
			errorJSON(err, codec, w)
			return
		}

		wasCreated := false
		result, err := finishRequest(timeout, func() (runtime.Object, error) {
			obj, created, err := r.Update(ctx, obj)
			wasCreated = created
			return obj, err
		})
		if err != nil {
			errorJSON(err, codec, w)
			return
		}

		if err := setSelfLink(result, req, namer); err != nil {
			errorJSON(err, codec, w)
			return
		}

		status := http.StatusOK
		if wasCreated {
			status = http.StatusCreated
		}
		writeJSON(status, codec, result, w)
	}
}

// DeleteResource returns a function that will handle a resource deletion
func DeleteResource(r RESTDeleter, ctxFn ContextFunc, namer ScopeNamer, codec runtime.Codec, resource, kind string, admit admission.Interface) restful.RouteFunction {
	return func(req *restful.Request, res *restful.Response) {
		w := res.ResponseWriter

		// TODO: we either want to remove timeout or document it (if we document, move timeout out of this function and declare it in api_installer)
		timeout := parseTimeout(req.Request.URL.Query().Get("timeout"))

		namespace, name, err := namer.Name(req)
		if err != nil {
			notFound(w, req.Request)
			return
		}
		ctx := ctxFn(req)
		if len(namespace) > 0 {
			ctx = api.WithNamespace(ctx, namespace)
		}

		err = admit.Admit(admission.NewAttributesRecord(nil, namespace, resource, "DELETE"))
		if err != nil {
			errorJSON(err, codec, w)
			return
		}

		result, err := finishRequest(timeout, func() (runtime.Object, error) {
			return r.Delete(ctx, name)
		})
		if err != nil {
			errorJSON(err, codec, w)
			return
		}

		// if the RESTDeleter returns a nil object, fill out a status. Callers may return a valid
		// object with the response.
		if result == nil {
			result = &api.Status{
				Status: api.StatusSuccess,
				Code:   http.StatusOK,
				Details: &api.StatusDetails{
					ID:   name,
					Kind: kind,
				},
			}
		} else {
			// when a non-status response is returned, set the self link
			if _, ok := result.(*api.Status); !ok {
				if err := setSelfLink(result, req, namer); err != nil {
					errorJSON(err, codec, w)
					return
				}
			}
		}
		writeJSON(http.StatusOK, codec, result, w)
	}
}

// resultFunc is a function that returns a rest result and can be run in a goroutine
type resultFunc func() (runtime.Object, error)

// finishRequest makes a given resultFunc asynchronous and handles errors returned by the response.
// Any api.Status object returned is considered an "error", which interrupts the normal response flow.
func finishRequest(timeout time.Duration, fn resultFunc) (result runtime.Object, err error) {
	ch := make(chan runtime.Object)
	errCh := make(chan error)
	go func() {
		if result, err := fn(); err != nil {
			errCh <- err
		} else {
			ch <- result
		}
	}()

	select {
	case result = <-ch:
		if status, ok := result.(*api.Status); ok {
			return nil, errors.FromObject(status)
		}
		return result, nil
	case err = <-errCh:
		return nil, err
	case <-time.After(timeout):
		return nil, errors.NewTimeoutError("request did not complete within allowed duration")
	}
}

// setSelfLink sets the self link of an object (or the child items in a list) to the base URL of the request
// plus the path and query generated by the provided linkFunc
func setSelfLink(obj runtime.Object, req *restful.Request, namer ScopeNamer) error {
	if runtime.IsListType(obj) {
		// Set self-link of objects in the list.
		items, err := runtime.ExtractList(obj)
		if err != nil {
			return err
		}
		for i := range items {
			if err := setSelfLink(items[i], req, namer); err != nil {
				return err
			}
		}
		return runtime.SetList(obj, items)
	}

	path, query, err := namer.GenerateLink(req, obj)
	if err == errEmptyName {
		return nil
	}
	if err != nil {
		glog.Errorf("error generating link: %v", err)
		return nil
	}

	newURL := *req.Request.URL
	// use only canonical paths
	newURL.Path = gpath.Clean(path)
	newURL.RawQuery = query
	newURL.Fragment = ""

	return namer.SetSelfLink(obj, newURL.String())
}
<commit_msg>UPSTREAM: move setSelfLink logging to v(5)<commit_after>/*
Copyright 2014 Google Inc. All rights reserved.

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

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

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

package apiserver

import (
	"net/http"
	gpath "path"
	"time"

	"github.com/GoogleCloudPlatform/kubernetes/pkg/admission"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
	"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"

	"github.com/emicklei/go-restful"
	"github.com/golang/glog"
)

// ContextFunc returns a Context given a request - a context must be returned
type ContextFunc func(req *restful.Request) api.Context

// ScopeNamer handles accessing names from requests and objects
type ScopeNamer interface {
	// Namespace returns the appropriate namespace value from the request (may be empty) or an
	// error.
	Namespace(req *restful.Request) (namespace string, err error)
	// Name returns the name from the request, and an optional namespace value if this is a namespace
	// scoped call. An error is returned if the name is not available.
	Name(req *restful.Request) (namespace, name string, err error)
	// ObjectName returns the namespace and name from an object if they exist, or an error if the object
	// does not support names.
	ObjectName(obj runtime.Object) (namespace, name string, err error)
	// SetSelfLink sets the provided URL onto the object. The method should return nil if the object
	// does not support selfLinks.
	SetSelfLink(obj runtime.Object, url string) error
	// GenerateLink creates a path and query for a given runtime object that represents the canonical path.
	GenerateLink(req *restful.Request, obj runtime.Object) (path, query string, err error)
}

// GetResource returns a function that handles retrieving a single resource from a RESTStorage object.
func GetResource(r RESTGetter, ctxFn ContextFunc, namer ScopeNamer, codec runtime.Codec) restful.RouteFunction {
	return func(req *restful.Request, res *restful.Response) {
		w := res.ResponseWriter
		namespace, name, err := namer.Name(req)
		if err != nil {
			notFound(w, req.Request)
			return
		}
		ctx := ctxFn(req)
		ctx = api.WithNamespace(ctx, namespace)

		result, err := r.Get(ctx, name)
		if err != nil {
			errorJSON(err, codec, w)
			return
		}
		if err := setSelfLink(result, req, namer); err != nil {
			errorJSON(err, codec, w)
			return
		}
		writeJSON(http.StatusOK, codec, result, w)
	}
}

// ListResource returns a function that handles retrieving a list of resources from a RESTStorage object.
func ListResource(r RESTLister, ctxFn ContextFunc, namer ScopeNamer, codec runtime.Codec) restful.RouteFunction {
	return func(req *restful.Request, res *restful.Response) {
		w := res.ResponseWriter

		namespace, err := namer.Namespace(req)
		if err != nil {
			notFound(w, req.Request)
			return
		}
		ctx := ctxFn(req)
		ctx = api.WithNamespace(ctx, namespace)

		label, err := labels.ParseSelector(req.Request.URL.Query().Get("labels"))
		if err != nil {
			errorJSON(err, codec, w)
			return
		}
		field, err := labels.ParseSelector(req.Request.URL.Query().Get("fields"))
		if err != nil {
			errorJSON(err, codec, w)
			return
		}

		result, err := r.List(ctx, label, field)
		if err != nil {
			errorJSON(err, codec, w)
			return
		}
		if err := setSelfLink(result, req, namer); err != nil {
			errorJSON(err, codec, w)
			return
		}
		writeJSON(http.StatusOK, codec, result, w)
	}
}

// CreateResource returns a function that will handle a resource creation.
func CreateResource(r RESTCreater, ctxFn ContextFunc, namer ScopeNamer, codec runtime.Codec, resource string, admit admission.Interface) restful.RouteFunction {
	return func(req *restful.Request, res *restful.Response) {
		w := res.ResponseWriter

		// TODO: we either want to remove timeout or document it (if we document, move timeout out of this function and declare it in api_installer)
		timeout := parseTimeout(req.Request.URL.Query().Get("timeout"))

		namespace, err := namer.Namespace(req)
		if err != nil {
			notFound(w, req.Request)
			return
		}
		ctx := ctxFn(req)
		ctx = api.WithNamespace(ctx, namespace)

		body, err := readBody(req.Request)
		if err != nil {
			errorJSON(err, codec, w)
			return
		}

		obj := r.New()
		if err := codec.DecodeInto(body, obj); err != nil {
			errorJSON(err, codec, w)
			return
		}

		err = admit.Admit(admission.NewAttributesRecord(obj, namespace, resource, "CREATE"))
		if err != nil {
			errorJSON(err, codec, w)
			return
		}

		result, err := finishRequest(timeout, func() (runtime.Object, error) {
			out, err := r.Create(ctx, obj)
			if status, ok := out.(*api.Status); ok && err == nil && status.Code == 0 {
				status.Code = http.StatusCreated
			}
			return out, err
		})
		if err != nil {
			errorJSON(err, codec, w)
			return
		}

		if err := setSelfLink(result, req, namer); err != nil {
			errorJSON(err, codec, w)
			return
		}

		writeJSON(http.StatusCreated, codec, result, w)
	}
}

// UpdateResource returns a function that will handle a resource update
func UpdateResource(r RESTUpdater, ctxFn ContextFunc, namer ScopeNamer, codec runtime.Codec, resource string, admit admission.Interface) restful.RouteFunction {
	return func(req *restful.Request, res *restful.Response) {
		w := res.ResponseWriter

		// TODO: we either want to remove timeout or document it (if we document, move timeout out of this function and declare it in api_installer)
		timeout := parseTimeout(req.Request.URL.Query().Get("timeout"))

		namespace, name, err := namer.Name(req)
		if err != nil {
			notFound(w, req.Request)
			return
		}
		ctx := ctxFn(req)
		ctx = api.WithNamespace(ctx, namespace)

		body, err := readBody(req.Request)
		if err != nil {
			errorJSON(err, codec, w)
			return
		}

		obj := r.New()
		if err := codec.DecodeInto(body, obj); err != nil {
			errorJSON(err, codec, w)
			return
		}

		// check the provided name against the request
		if objNamespace, objName, err := namer.ObjectName(obj); err == nil {
			if objName != name {
				errorJSON(errors.NewBadRequest("the name of the object does not match the name on the URL"), codec, w)
				return
			}
			if len(namespace) > 0 {
				if len(objNamespace) > 0 && objNamespace != namespace {
					errorJSON(errors.NewBadRequest("the namespace of the object does not match the namespace on the request"), codec, w)
					return
				}
			}
		}

		err = admit.Admit(admission.NewAttributesRecord(obj, namespace, resource, "UPDATE"))
		if err != nil {
			errorJSON(err, codec, w)
			return
		}

		wasCreated := false
		result, err := finishRequest(timeout, func() (runtime.Object, error) {
			obj, created, err := r.Update(ctx, obj)
			wasCreated = created
			return obj, err
		})
		if err != nil {
			errorJSON(err, codec, w)
			return
		}

		if err := setSelfLink(result, req, namer); err != nil {
			errorJSON(err, codec, w)
			return
		}

		status := http.StatusOK
		if wasCreated {
			status = http.StatusCreated
		}
		writeJSON(status, codec, result, w)
	}
}

// DeleteResource returns a function that will handle a resource deletion
func DeleteResource(r RESTDeleter, ctxFn ContextFunc, namer ScopeNamer, codec runtime.Codec, resource, kind string, admit admission.Interface) restful.RouteFunction {
	return func(req *restful.Request, res *restful.Response) {
		w := res.ResponseWriter

		// TODO: we either want to remove timeout or document it (if we document, move timeout out of this function and declare it in api_installer)
		timeout := parseTimeout(req.Request.URL.Query().Get("timeout"))

		namespace, name, err := namer.Name(req)
		if err != nil {
			notFound(w, req.Request)
			return
		}
		ctx := ctxFn(req)
		if len(namespace) > 0 {
			ctx = api.WithNamespace(ctx, namespace)
		}

		err = admit.Admit(admission.NewAttributesRecord(nil, namespace, resource, "DELETE"))
		if err != nil {
			errorJSON(err, codec, w)
			return
		}

		result, err := finishRequest(timeout, func() (runtime.Object, error) {
			return r.Delete(ctx, name)
		})
		if err != nil {
			errorJSON(err, codec, w)
			return
		}

		// if the RESTDeleter returns a nil object, fill out a status. Callers may return a valid
		// object with the response.
		if result == nil {
			result = &api.Status{
				Status: api.StatusSuccess,
				Code:   http.StatusOK,
				Details: &api.StatusDetails{
					ID:   name,
					Kind: kind,
				},
			}
		} else {
			// when a non-status response is returned, set the self link
			if _, ok := result.(*api.Status); !ok {
				if err := setSelfLink(result, req, namer); err != nil {
					errorJSON(err, codec, w)
					return
				}
			}
		}
		writeJSON(http.StatusOK, codec, result, w)
	}
}

// resultFunc is a function that returns a rest result and can be run in a goroutine
type resultFunc func() (runtime.Object, error)

// finishRequest makes a given resultFunc asynchronous and handles errors returned by the response.
// Any api.Status object returned is considered an "error", which interrupts the normal response flow.
func finishRequest(timeout time.Duration, fn resultFunc) (result runtime.Object, err error) {
	ch := make(chan runtime.Object)
	errCh := make(chan error)
	go func() {
		if result, err := fn(); err != nil {
			errCh <- err
		} else {
			ch <- result
		}
	}()

	select {
	case result = <-ch:
		if status, ok := result.(*api.Status); ok {
			return nil, errors.FromObject(status)
		}
		return result, nil
	case err = <-errCh:
		return nil, err
	case <-time.After(timeout):
		return nil, errors.NewTimeoutError("request did not complete within allowed duration")
	}
}

// setSelfLink sets the self link of an object (or the child items in a list) to the base URL of the request
// plus the path and query generated by the provided linkFunc
func setSelfLink(obj runtime.Object, req *restful.Request, namer ScopeNamer) error {
	if runtime.IsListType(obj) {
		// Set self-link of objects in the list.
		items, err := runtime.ExtractList(obj)
		if err != nil {
			return err
		}
		for i := range items {
			if err := setSelfLink(items[i], req, namer); err != nil {
				return err
			}
		}
		return runtime.SetList(obj, items)
	}

	path, query, err := namer.GenerateLink(req, obj)
	if err == errEmptyName {
		return nil
	}
	if err != nil {
		glog.V(5).Infof("error generating link: %v", err)
		return nil
	}

	newURL := *req.Request.URL
	// use only canonical paths
	newURL.Path = gpath.Clean(path)
	newURL.RawQuery = query
	newURL.Fragment = ""

	return namer.SetSelfLink(obj, newURL.String())
}
<|endoftext|>


<commit_before>package citrixadc

import (
	"github.com/chiradeep/go-nitro/config/network"

	"github.com/chiradeep/go-nitro/netscaler"
	"github.com/hashicorp/terraform/helper/schema"

	"fmt"
	"log"
	"net/url"
)

func resourceCitrixAdcRoute() *schema.Resource {
	return &schema.Resource{
		SchemaVersion: 1,
		Create:        createRouteFunc,
		Read:          readRouteFunc,
		Update:        updateRouteFunc,
		Delete:        deleteRouteFunc,
		Schema: map[string]*schema.Schema{
			"network": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"netmask": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"gateway": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"advertise": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
			"cost": &schema.Schema{
				Type:     schema.TypeInt,
				Optional: true,
				Computed: true,
			},
			"cost1": &schema.Schema{
				Type:     schema.TypeInt,
				Optional: true,
				Computed: true,
			},
			"detail": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Computed: true,
			},
			"distance": &schema.Schema{
				Type:     schema.TypeInt,
				Optional: true,
				Computed: true,
			},
			"monitor": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
			"msr": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
			"ownergroup": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
			"routetype": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
			"td": &schema.Schema{
				Type:     schema.TypeInt,
				Optional: true,
				Computed: true,
			},
			"vlan": &schema.Schema{
				Type:     schema.TypeInt,
				Optional: true,
				Computed: true,
			},
			"weight": &schema.Schema{
				Type:     schema.TypeInt,
				Optional: true,
				Computed: true,
			},
		},
	}
}

func createRouteFunc(d *schema.ResourceData, meta interface{}) error {
	log.Printf("[DEBUG]  citrixadc-provider: In createRouteFunc")
	client := meta.(*NetScalerNitroClient).client
	// setting ID as `network__netmask__gateway` for better logging
	routeName := d.Get("network").(string) + "__" + d.Get("netmask").(string) + "__" + d.Get("gateway").(string)

	route := network.Route{
		Advertise:  d.Get("advertise").(string),
		Cost:       d.Get("cost").(int),
		Cost1:      d.Get("cost1").(int),
		Detail:     d.Get("detail").(bool),
		Distance:   d.Get("distance").(int),
		Gateway:    d.Get("gateway").(string),
		Monitor:    d.Get("monitor").(string),
		Msr:        d.Get("msr").(string),
		Netmask:    d.Get("netmask").(string),
		Network:    d.Get("network").(string),
		Ownergroup: d.Get("ownergroup").(string),
		Routetype:  d.Get("routetype").(string),
		Td:         d.Get("td").(int),
		Vlan:       d.Get("vlan").(int),
		Weight:     d.Get("weight").(int),
	}

	_, err := client.AddResource(netscaler.Route.Type(), route.Network, &route)
	if err != nil {
		return err
	}

	d.SetId(routeName)

	err = readRouteFunc(d, meta)
	if err != nil {
		log.Printf("[ERROR] netscaler-provider: ?? we just created this route but we can't read it ?? %s", routeName)
		return nil
	}
	return nil
}

func readRouteFunc(d *schema.ResourceData, meta interface{}) error {
	log.Printf("[DEBUG] citrixadc-provider:  In readRouteFunc")
	client := meta.(*NetScalerNitroClient).client
	routeName := d.Id()
	log.Printf("[DEBUG] citrixadc-provider: Reading route state %s", routeName)
	argsMap := make(map[string]string)
	argsMap["network"] = url.QueryEscape(d.Get("network").(string))
	argsMap["netmask"] = url.QueryEscape(d.Get("netmask").(string))
	argsMap["gateway"] = url.QueryEscape(d.Get("gateway").(string))
	findParams := netscaler.FindParams{
		ResourceType: netscaler.Route.Type(),
		ArgsMap:      argsMap,
	}
	dataArray, err := client.FindResourceArrayWithParams(findParams)
	if err != nil {
		log.Printf("[WARN] citrixadc-provider: Clearing route state %s", routeName)
		d.SetId("")
		return nil
	}
	if len(dataArray) == 0 {
		log.Printf("[WARN] citrixadc-provider: route does not exist. Clearing state.")
		d.SetId("")
		return nil
	}

	if len(dataArray) > 1 {
		return fmt.Errorf("multiple entries found for route")
	}

	data := dataArray[0]

	d.Set("advertise", data["advertise"])
	d.Set("cost", data["cost"])
	d.Set("cost1", data["cost1"])
	d.Set("detail", data["detail"])
	d.Set("distance", data["distance"])
	d.Set("gateway", data["gateway"])
	d.Set("monitor", data["monitor"])
	d.Set("msr", data["msr"])
	d.Set("netmask", data["netmask"])
	d.Set("network", data["network"])
	d.Set("ownergroup", data["ownergroup"])
	d.Set("routetype", data["routetype"])
	d.Set("td", data["td"])
	d.Set("vlan", data["vlan"])
	d.Set("weight", data["weight"])

	return nil

}

func updateRouteFunc(d *schema.ResourceData, meta interface{}) error {
	log.Printf("[DEBUG]  citrixadc-provider: In updateRouteFunc")
	client := meta.(*NetScalerNitroClient).client
	routeName := d.Id()

	route := network.Route{}
	hasChange := false
	if d.HasChange("advertise") {
		log.Printf("[DEBUG]  citrixadc-provider: Advertise has changed for route %s, starting update", routeName)
		route.Advertise = d.Get("advertise").(string)
		hasChange = true
	}
	if d.HasChange("cost") {
		log.Printf("[DEBUG]  citrixadc-provider: Cost has changed for route %s, starting update", routeName)
		route.Cost = d.Get("cost").(int)
		hasChange = true
	}
	if d.HasChange("cost1") {
		log.Printf("[DEBUG]  citrixadc-provider: Cost1 has changed for route %s, starting update", routeName)
		route.Cost1 = d.Get("cost1").(int)
		hasChange = true
	}
	if d.HasChange("detail") {
		log.Printf("[DEBUG]  citrixadc-provider: Detail has changed for route %s, starting update", routeName)
		route.Detail = d.Get("detail").(bool)
		hasChange = true
	}
	if d.HasChange("distance") {
		log.Printf("[DEBUG]  citrixadc-provider: Distance has changed for route %s, starting update", routeName)
		route.Distance = d.Get("distance").(int)
		hasChange = true
	}
	if d.HasChange("gateway") {
		log.Printf("[DEBUG]  citrixadc-provider: Gateway has changed for route %s, starting update", routeName)
		route.Gateway = d.Get("gateway").(string)
		hasChange = true
	}
	if d.HasChange("monitor") {
		log.Printf("[DEBUG]  citrixadc-provider: Monitor has changed for route %s, starting update", routeName)
		route.Monitor = d.Get("monitor").(string)
		hasChange = true
	}
	if d.HasChange("msr") {
		log.Printf("[DEBUG]  citrixadc-provider: Msr has changed for route %s, starting update", routeName)
		route.Msr = d.Get("msr").(string)
		hasChange = true
	}
	if d.HasChange("netmask") {
		log.Printf("[DEBUG]  citrixadc-provider: Netmask has changed for route %s, starting update", routeName)
		route.Netmask = d.Get("netmask").(string)
		hasChange = true
	}
	if d.HasChange("network") {
		log.Printf("[DEBUG]  citrixadc-provider: Network has changed for route %s, starting update", routeName)
		route.Network = d.Get("network").(string)
		hasChange = true
	}
	if d.HasChange("ownergroup") {
		log.Printf("[DEBUG]  citrixadc-provider: Ownergroup has changed for route %s, starting update", routeName)
		route.Ownergroup = d.Get("ownergroup").(string)
		hasChange = true
	}
	if d.HasChange("routetype") {
		log.Printf("[DEBUG]  citrixadc-provider: Routetype has changed for route %s, starting update", routeName)
		route.Routetype = d.Get("routetype").(string)
		hasChange = true
	}
	if d.HasChange("td") {
		log.Printf("[DEBUG]  citrixadc-provider: Td has changed for route %s, starting update", routeName)
		route.Td = d.Get("td").(int)
		hasChange = true
	}
	if d.HasChange("vlan") {
		log.Printf("[DEBUG]  citrixadc-provider: Vlan has changed for route %s, starting update", routeName)
		route.Vlan = d.Get("vlan").(int)
		hasChange = true
	}
	if d.HasChange("weight") {
		log.Printf("[DEBUG]  citrixadc-provider: Weight has changed for route %s, starting update", routeName)
		route.Weight = d.Get("weight").(int)
		hasChange = true
	}

	if hasChange {
		// network, netmask, gateway attributes are mandatory in UPDATE data
		route.Network = d.Get("network").(string)
		route.Netmask = d.Get("netmask").(string)
		route.Gateway = d.Get("gateway").(string)
		err := client.UpdateUnnamedResource(netscaler.Route.Type(), &route)
		if err != nil {
			return fmt.Errorf("Error updating route %s", routeName)
		}
	}
	return readRouteFunc(d, meta)
}

func deleteRouteFunc(d *schema.ResourceData, meta interface{}) error {
	log.Printf("[DEBUG]  citrixadc-provider: In deleteRouteFunc")
	client := meta.(*NetScalerNitroClient).client

	argsMap := make(map[string]string)
	argsMap["network"] = url.QueryEscape(d.Get("network").(string))
	argsMap["netmask"] = url.QueryEscape(d.Get("netmask").(string))
	argsMap["gateway"] = url.QueryEscape(d.Get("gateway").(string))

	err := client.DeleteResourceWithArgsMap(netscaler.Route.Type(), d.Get("network").(string), argsMap)
	if err != nil {
		return err
	}

	d.SetId("")

	return nil
}
<commit_msg>Implement import operation for resource route<commit_after>package citrixadc

import (
	"github.com/chiradeep/go-nitro/config/network"

	"github.com/chiradeep/go-nitro/netscaler"
	"github.com/hashicorp/terraform/helper/schema"

	"fmt"
	"log"
	"net/url"
)

func resourceCitrixAdcRoute() *schema.Resource {
	return &schema.Resource{
		SchemaVersion: 1,
		Create:        createRouteFunc,
		Read:          readRouteFunc,
		Update:        updateRouteFunc,
		Delete:        deleteRouteFunc,
		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},
		Schema: map[string]*schema.Schema{
			"network": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"netmask": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"gateway": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},
			"advertise": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
			"cost": &schema.Schema{
				Type:     schema.TypeInt,
				Optional: true,
				Computed: true,
			},
			"cost1": &schema.Schema{
				Type:     schema.TypeInt,
				Optional: true,
				Computed: true,
			},
			"detail": &schema.Schema{
				Type:     schema.TypeBool,
				Optional: true,
				Computed: true,
			},
			"distance": &schema.Schema{
				Type:     schema.TypeInt,
				Optional: true,
				Computed: true,
			},
			"monitor": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
			"msr": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
			"ownergroup": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
			"routetype": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},
			"td": &schema.Schema{
				Type:     schema.TypeInt,
				Optional: true,
				Computed: true,
			},
			"vlan": &schema.Schema{
				Type:     schema.TypeInt,
				Optional: true,
				Computed: true,
			},
			"weight": &schema.Schema{
				Type:     schema.TypeInt,
				Optional: true,
				Computed: true,
			},
		},
	}
}

func createRouteFunc(d *schema.ResourceData, meta interface{}) error {
	log.Printf("[DEBUG]  citrixadc-provider: In createRouteFunc")
	client := meta.(*NetScalerNitroClient).client
	// setting ID as `network__netmask__gateway` for better logging
	routeName := d.Get("network").(string) + "__" + d.Get("netmask").(string) + "__" + d.Get("gateway").(string)

	route := network.Route{
		Advertise:  d.Get("advertise").(string),
		Cost:       d.Get("cost").(int),
		Cost1:      d.Get("cost1").(int),
		Detail:     d.Get("detail").(bool),
		Distance:   d.Get("distance").(int),
		Gateway:    d.Get("gateway").(string),
		Monitor:    d.Get("monitor").(string),
		Msr:        d.Get("msr").(string),
		Netmask:    d.Get("netmask").(string),
		Network:    d.Get("network").(string),
		Ownergroup: d.Get("ownergroup").(string),
		Routetype:  d.Get("routetype").(string),
		Td:         d.Get("td").(int),
		Vlan:       d.Get("vlan").(int),
		Weight:     d.Get("weight").(int),
	}

	_, err := client.AddResource(netscaler.Route.Type(), route.Network, &route)
	if err != nil {
		return err
	}

	d.SetId(routeName)

	err = readRouteFunc(d, meta)
	if err != nil {
		log.Printf("[ERROR] netscaler-provider: ?? we just created this route but we can't read it ?? %s", routeName)
		return nil
	}
	return nil
}

func readRouteFunc(d *schema.ResourceData, meta interface{}) error {
	log.Printf("[DEBUG] citrixadc-provider:  In readRouteFunc")
	client := meta.(*NetScalerNitroClient).client
	routeName := d.Id()
	log.Printf("[DEBUG] citrixadc-provider: Reading route state %s", routeName)
	argsMap := make(map[string]string)
	argsMap["network"] = url.QueryEscape(d.Get("network").(string))
	argsMap["netmask"] = url.QueryEscape(d.Get("netmask").(string))
	argsMap["gateway"] = url.QueryEscape(d.Get("gateway").(string))
	findParams := netscaler.FindParams{
		ResourceType: netscaler.Route.Type(),
		ArgsMap:      argsMap,
	}
	dataArray, err := client.FindResourceArrayWithParams(findParams)
	if err != nil {
		log.Printf("[WARN] citrixadc-provider: Clearing route state %s", routeName)
		d.SetId("")
		return nil
	}
	if len(dataArray) == 0 {
		log.Printf("[WARN] citrixadc-provider: route does not exist. Clearing state.")
		d.SetId("")
		return nil
	}

	if len(dataArray) > 1 {
		return fmt.Errorf("multiple entries found for route")
	}

	data := dataArray[0]

	d.Set("advertise", data["advertise"])
	d.Set("cost", data["cost"])
	d.Set("cost1", data["cost1"])
	d.Set("detail", data["detail"])
	d.Set("distance", data["distance"])
	d.Set("gateway", data["gateway"])
	d.Set("monitor", data["monitor"])
	d.Set("msr", data["msr"])
	d.Set("netmask", data["netmask"])
	d.Set("network", data["network"])
	d.Set("ownergroup", data["ownergroup"])
	d.Set("routetype", data["routetype"])
	d.Set("td", data["td"])
	d.Set("vlan", data["vlan"])
	d.Set("weight", data["weight"])

	return nil

}

func updateRouteFunc(d *schema.ResourceData, meta interface{}) error {
	log.Printf("[DEBUG]  citrixadc-provider: In updateRouteFunc")
	client := meta.(*NetScalerNitroClient).client
	routeName := d.Id()

	route := network.Route{}
	hasChange := false
	if d.HasChange("advertise") {
		log.Printf("[DEBUG]  citrixadc-provider: Advertise has changed for route %s, starting update", routeName)
		route.Advertise = d.Get("advertise").(string)
		hasChange = true
	}
	if d.HasChange("cost") {
		log.Printf("[DEBUG]  citrixadc-provider: Cost has changed for route %s, starting update", routeName)
		route.Cost = d.Get("cost").(int)
		hasChange = true
	}
	if d.HasChange("cost1") {
		log.Printf("[DEBUG]  citrixadc-provider: Cost1 has changed for route %s, starting update", routeName)
		route.Cost1 = d.Get("cost1").(int)
		hasChange = true
	}
	if d.HasChange("detail") {
		log.Printf("[DEBUG]  citrixadc-provider: Detail has changed for route %s, starting update", routeName)
		route.Detail = d.Get("detail").(bool)
		hasChange = true
	}
	if d.HasChange("distance") {
		log.Printf("[DEBUG]  citrixadc-provider: Distance has changed for route %s, starting update", routeName)
		route.Distance = d.Get("distance").(int)
		hasChange = true
	}
	if d.HasChange("gateway") {
		log.Printf("[DEBUG]  citrixadc-provider: Gateway has changed for route %s, starting update", routeName)
		route.Gateway = d.Get("gateway").(string)
		hasChange = true
	}
	if d.HasChange("monitor") {
		log.Printf("[DEBUG]  citrixadc-provider: Monitor has changed for route %s, starting update", routeName)
		route.Monitor = d.Get("monitor").(string)
		hasChange = true
	}
	if d.HasChange("msr") {
		log.Printf("[DEBUG]  citrixadc-provider: Msr has changed for route %s, starting update", routeName)
		route.Msr = d.Get("msr").(string)
		hasChange = true
	}
	if d.HasChange("netmask") {
		log.Printf("[DEBUG]  citrixadc-provider: Netmask has changed for route %s, starting update", routeName)
		route.Netmask = d.Get("netmask").(string)
		hasChange = true
	}
	if d.HasChange("network") {
		log.Printf("[DEBUG]  citrixadc-provider: Network has changed for route %s, starting update", routeName)
		route.Network = d.Get("network").(string)
		hasChange = true
	}
	if d.HasChange("ownergroup") {
		log.Printf("[DEBUG]  citrixadc-provider: Ownergroup has changed for route %s, starting update", routeName)
		route.Ownergroup = d.Get("ownergroup").(string)
		hasChange = true
	}
	if d.HasChange("routetype") {
		log.Printf("[DEBUG]  citrixadc-provider: Routetype has changed for route %s, starting update", routeName)
		route.Routetype = d.Get("routetype").(string)
		hasChange = true
	}
	if d.HasChange("td") {
		log.Printf("[DEBUG]  citrixadc-provider: Td has changed for route %s, starting update", routeName)
		route.Td = d.Get("td").(int)
		hasChange = true
	}
	if d.HasChange("vlan") {
		log.Printf("[DEBUG]  citrixadc-provider: Vlan has changed for route %s, starting update", routeName)
		route.Vlan = d.Get("vlan").(int)
		hasChange = true
	}
	if d.HasChange("weight") {
		log.Printf("[DEBUG]  citrixadc-provider: Weight has changed for route %s, starting update", routeName)
		route.Weight = d.Get("weight").(int)
		hasChange = true
	}

	if hasChange {
		// network, netmask, gateway attributes are mandatory in UPDATE data
		route.Network = d.Get("network").(string)
		route.Netmask = d.Get("netmask").(string)
		route.Gateway = d.Get("gateway").(string)
		err := client.UpdateUnnamedResource(netscaler.Route.Type(), &route)
		if err != nil {
			return fmt.Errorf("Error updating route %s", routeName)
		}
	}
	return readRouteFunc(d, meta)
}

func deleteRouteFunc(d *schema.ResourceData, meta interface{}) error {
	log.Printf("[DEBUG]  citrixadc-provider: In deleteRouteFunc")
	client := meta.(*NetScalerNitroClient).client

	argsMap := make(map[string]string)
	argsMap["network"] = url.QueryEscape(d.Get("network").(string))
	argsMap["netmask"] = url.QueryEscape(d.Get("netmask").(string))
	argsMap["gateway"] = url.QueryEscape(d.Get("gateway").(string))

	err := client.DeleteResourceWithArgsMap(netscaler.Route.Type(), d.Get("network").(string), argsMap)
	if err != nil {
		return err
	}

	d.SetId("")

	return nil
}
<|endoftext|>


<commit_before>package tradeoffer

import (
	"errors"
	"fmt"
	"regexp"
	"strconv"
)

type EscrowDuration struct {
	DaysMyEscrow    uint32
	DaysTheirEscrow uint32
}

func parseEscrowDuration(data []byte) (*EscrowDuration, error) {
	// TODO: why we are using case insensitive matching?
	myRegex := regexp.MustCompile("(?i)g_daysMyEscrow[\\s=]+(\\d+);")
	theirRegex := regexp.MustCompile("(?i)g_daysTheirEscrow[\\s=]+(\\d+);")

	myM := myRegex.FindSubmatch(data)
	theirM := theirRegex.FindSubmatch(data)

	if myM == nil || theirM == nil {
		return nil, errors.New("regexp does not match")
	}

	myEscrow, err := strconv.ParseUint(string(myM[1]), 10, 32)
	if err != nil {
		return nil, fmt.Errorf("failed to parse my duration into uint: %v", err)
	}
	theirEscrow, err := strconv.ParseUint(string(theirM[1]), 10, 32)
	if err != nil {
		return nil, fmt.Errorf("failed to parse their duration into uint: %v", err)
	}

	return &EscrowDuration{
		DaysMyEscrow:    uint32(myEscrow),
		DaysTheirEscrow: uint32(theirEscrow),
	}, nil
}
<commit_msg>Add non-friends err to parseEscrowDuration<commit_after>package tradeoffer

import (
	"errors"
	"fmt"
	"regexp"
	"strconv"
)

type EscrowDuration struct {
	DaysMyEscrow    uint32
	DaysTheirEscrow uint32
}

func parseEscrowDuration(data []byte) (*EscrowDuration, error) {
	// TODO: why we are using case insensitive matching?
	myRegex := regexp.MustCompile("(?i)g_daysMyEscrow[\\s=]+(\\d+);")
	theirRegex := regexp.MustCompile("(?i)g_daysTheirEscrow[\\s=]+(\\d+);")

	myM := myRegex.FindSubmatch(data)
	theirM := theirRegex.FindSubmatch(data)

	if myM == nil || theirM == nil {
		// check if access token is valid
		notFriendsRegex := regexp.MustCompile(">You are not friends with this user<")
		notFriendsM := notFriendsRegex.FindSubmatch(data)
		if notFriendsM == nil {
			return nil, errors.New("regexp does not match")
		} else {
			return nil, errors.New("you are not friends with this user")
		}
	}

	myEscrow, err := strconv.ParseUint(string(myM[1]), 10, 32)
	if err != nil {
		return nil, fmt.Errorf("failed to parse my duration into uint: %v", err)
	}
	theirEscrow, err := strconv.ParseUint(string(theirM[1]), 10, 32)
	if err != nil {
		return nil, fmt.Errorf("failed to parse their duration into uint: %v", err)
	}

	return &EscrowDuration{
		DaysMyEscrow:    uint32(myEscrow),
		DaysTheirEscrow: uint32(theirEscrow),
	}, nil
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"path/filepath"

	"github.com/hpcloud/tail"
)

func IsClosed(ch <-chan Message) bool {
	select {
	case <-ch:
		return true
	default:
	}

	return false
}

func logSubscribe(client *Client, data interface{}) {
	go func() {
		logfile := filepath.Join(config.FactorioDir, "factorio-server-console.log")
		t, err := tail.TailFile(logfile, tail.Config{Follow: true})
		if err != nil {
			log.Printf("Error subscribing to tail log %s", err)
			return
		}

		for line := range t.Lines {
			if !IsClosed(client.send) {
				client.send <- Message{"log update", line.Text}
			} else {
				log.Printf("Channel was closed")
				return
			}
		}
	}()
}

func commandSend(client *Client, data interface{}) {
	if FactorioServ.Running {
		go func() {
			log.Printf("Received command: %v", data)

			reqId, err := FactorioServ.Rcon.Write(data.(string))
			if err != nil {
				log.Printf("Error sending rcon command: %s", err)
				return
			}

			log.Printf("Command send to Factorio: %s, with rcon request id: %v", data, reqId)

			if !IsClosed(client.send) {
				client.send <- Message{"receive command", data}
			} else {
				log.Printf("Channel was closed")
				return
			}
		}()
	}
}
<commit_msg>switch from notify to poll<commit_after>package main

import (
	"log"
	"path/filepath"

	"github.com/hpcloud/tail"
)

func IsClosed(ch <-chan Message) bool {
	select {
	case <-ch:
		return true
	default:
	}

	return false
}

func logSubscribe(client *Client, data interface{}) {
	go func() {
		logfile := filepath.Join(config.FactorioDir, "factorio-server-console.log")
		t, err := tail.TailFile(logfile, tail.Config{Follow: true, Poll: true})
		if err != nil {
			log.Printf("Error subscribing to tail log %s", err)
			return
		}

		for line := range t.Lines {
			if !IsClosed(client.send) {
				client.send <- Message{"log update", line.Text}
			} else {
				log.Printf("Channel was closed")
				return
			}
		}
	}()
}

func commandSend(client *Client, data interface{}) {
	if FactorioServ.Running {
		go func() {
			log.Printf("Received command: %v", data)

			reqId, err := FactorioServ.Rcon.Write(data.(string))
			if err != nil {
				log.Printf("Error sending rcon command: %s", err)
				return
			}

			log.Printf("Command send to Factorio: %s, with rcon request id: %v", data, reqId)

			if !IsClosed(client.send) {
				client.send <- Message{"receive command", data}
			} else {
				log.Printf("Channel was closed")
				return
			}
		}()
	}
}
<|endoftext|>


<commit_before>package echo

import (
	"encoding/json"
	"net/http"

	"github.com/labstack/echo"
	"github.com/open-gtd/server/sse"
)

func NewSseRegisterer(g *echo.Group) sse.Registerer {
	return &sseRegisterer{
		group:   g,
		channel: make(chan interface{}),
		exit:    make(chan bool),
	}
}

type sseRegisterer struct {
	group   *echo.Group
	channel chan interface{}
	exit    chan bool
}

func (sr sseRegisterer) CreatePushDataFunc(prefix sse.Prefix, closeNotify sse.ClientClosedNotificationFunc) sse.PushDataToSseFunc {
	sr.group.GET("/"+string(prefix), func(c echo.Context) error {
		c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
		c.Response().WriteHeader(http.StatusOK)

		notify := c.Response().CloseNotify()

		go func() {
			<-notify
			sr.exit <- true
			closeNotify()
		}()

		for {
			select {
			case <-sr.exit:
				closeNotify()
				return nil
			case v := <-sr.channel:
				if err := json.NewEncoder(c.Response()).Encode(v); err != nil {
					closeNotify()
					return err
				}
				c.Response().Flush()
			}
		}
	})

	return func(topic sse.Topic, v interface{}) {
		sr.channel <- sse.Envelope{Topic: topic, Data: v}
	}
}
<commit_msg>sseRegisterer abstracted from echo framework<commit_after>package echo

import (
	"encoding/json"
	"net/http"

	"github.com/labstack/echo"
	"github.com/open-gtd/server/sse"
)

type Router interface {
	Add(method, path string, handler echo.HandlerFunc, middleware ...echo.MiddlewareFunc) *echo.Route
}

func NewSseRegisterer(r Router) sse.Registerer {
	return &sseRegisterer{
		router:  r,
		channel: make(chan interface{}),
		exit:    make(chan bool),
	}
}

type sseRegisterer struct {
	router  Router
	channel chan interface{}
	exit    chan bool
}

func (sr sseRegisterer) CreatePushDataFunc(prefix sse.Prefix, closeNotify sse.ClientClosedNotificationFunc) sse.PushDataToSseFunc {
	sr.router.Add(echo.GET, "/"+string(prefix), func(c echo.Context) error {
		c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
		c.Response().WriteHeader(http.StatusOK)

		notify := c.Response().CloseNotify()

		go func() {
			<-notify
			sr.exit <- true
			closeNotify()
		}()

		for {
			select {
			case <-sr.exit:
				closeNotify()
				return nil
			case v := <-sr.channel:
				if err := json.NewEncoder(c.Response()).Encode(v); err != nil {
					closeNotify()
					return err
				}
				c.Response().Flush()
			}
		}
	})

	return func(topic sse.Topic, v interface{}) {
		sr.channel <- sse.Envelope{Topic: topic, Data: v}
	}
}
<|endoftext|>


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

package ssh

// Key exchange tests.

import (
	"crypto/rand"
	"reflect"
	"testing"
)

func TestKexes(t *testing.T) {
	type kexResultErr struct {
		result *kexResult
		err    error
	}

	for name, kex := range kexAlgoMap {
		a, b := memPipe()

		s := make(chan kexResultErr, 1)
		c := make(chan kexResultErr, 1)
		var magics handshakeMagics
		go func() {
			r, e := kex.Client(a, rand.Reader, &magics)
			c <- kexResultErr{r, e}
		}()
		go func() {
			r, e := kex.Server(b, rand.Reader, &magics, testSigners["ecdsa"])
			s <- kexResultErr{r, e}
		}()

		clientRes := <-c
		serverRes := <-s
		if clientRes.err != nil {
			t.Errorf("client: %v", clientRes.err)
		}
		if serverRes.err != nil {
			t.Errorf("server: %v", serverRes.err)
		}
		if !reflect.DeepEqual(clientRes.result, serverRes.result) {
			t.Errorf("kex %q: mismatch %#v, %#v", name, clientRes.result, serverRes.result)
		}
	}
}
<commit_msg>x/crypto/ssh: close memPipe after running kex test.<commit_after>// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package ssh

// Key exchange tests.

import (
	"crypto/rand"
	"reflect"
	"testing"
)

func TestKexes(t *testing.T) {
	type kexResultErr struct {
		result *kexResult
		err    error
	}

	for name, kex := range kexAlgoMap {
		a, b := memPipe()

		s := make(chan kexResultErr, 1)
		c := make(chan kexResultErr, 1)
		var magics handshakeMagics
		go func() {
			r, e := kex.Client(a, rand.Reader, &magics)
			a.Close()
			c <- kexResultErr{r, e}
		}()
		go func() {
			r, e := kex.Server(b, rand.Reader, &magics, testSigners["ecdsa"])
			b.Close()
			s <- kexResultErr{r, e}
		}()

		clientRes := <-c
		serverRes := <-s
		if clientRes.err != nil {
			t.Errorf("client: %v", clientRes.err)
		}
		if serverRes.err != nil {
			t.Errorf("server: %v", serverRes.err)
		}
		if !reflect.DeepEqual(clientRes.result, serverRes.result) {
			t.Errorf("kex %q: mismatch %#v, %#v", name, clientRes.result, serverRes.result)
		}
	}
}
<|endoftext|>


<commit_before>// Copyright ©2016 The gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package stat

import (
	"errors"
	"math"

	"gonum.org/v1/gonum/floats"
	"gonum.org/v1/gonum/matrix"
	"gonum.org/v1/gonum/matrix/mat64"
)

// PC is a type for computing and extracting the principal components of a
// matrix. The results of the principal components analysis are only valid
// if the call to PrincipalComponents was successful.
type PC struct {
	n, d    int
	weights []float64
	svd     *mat64.SVD
	ok      bool
}

// PrincipalComponents performs a weighted principal components analysis on the
// matrix of the input data which is represented as an n×d matrix a where each
// row is an observation and each column is a variable.
//
// PrincipalComponents centers the variables but does not scale the variance.
//
// The weights slice is used to weight the observations. If weights is nil, each
// weight is considered to have a value of one, otherwise the length of weights
// must match the number of observations or PrincipalComponents will panic.
//
// PrincipalComponents returns whether the analysis was successful.
func (c *PC) PrincipalComponents(a mat64.Matrix, weights []float64) (ok bool) {
	c.n, c.d = a.Dims()
	if weights != nil && len(weights) != c.n {
		panic("stat: len(weights) != observations")
	}

	c.svd, c.ok = svdFactorizeCentered(c.svd, a, weights)
	if c.ok {
		c.weights = append(c.weights[:0], weights...)
	}
	return c.ok
}

// Vectors returns the component direction vectors of a principal components
// analysis. The vectors are returned in the columns of a d×min(n, d) matrix.
// If dst is not nil it must either be zero-sized or be a d×min(n, d) matrix.
// dst will  be used as the destination for the direction vector data. If dst
// is nil, a new mat64.Dense is allocated for the destination.
func (c *PC) Vectors(dst *mat64.Dense) *mat64.Dense {
	if !c.ok {
		panic("stat: use of unsuccessful principal components analysis")
	}

	if dst == nil {
		dst = &mat64.Dense{}
	} else if d, n := dst.Dims(); (n != 0 || d != 0) && (d != c.d || n != min(c.n, c.d)) {
		panic(matrix.ErrShape)
	}
	dst.VFromSVD(c.svd)
	return dst
}

// Vars returns the column variances of the principal component scores,
// b * vecs, where b is a matrix with centered columns. Variances are returned
// in descending order.
// If dst is not nil it is used to store the variances and returned.
// Vars will panic if the receiver has not successfully performed a principal
// components analysis or dst is not nil and the length of dst is not min(n, d).
func (c *PC) Vars(dst []float64) []float64 {
	if !c.ok {
		panic("stat: use of unsuccessful principal components analysis")
	}
	if dst != nil && len(dst) != min(c.n, c.d) {
		panic("stat: length of slice does not match analysis")
	}

	dst = c.svd.Values(dst)
	var f float64
	if c.weights == nil {
		f = 1 / float64(c.n-1)
	} else {
		f = 1 / (floats.Sum(c.weights) - 1)
	}
	for i, v := range dst {
		dst[i] = f * v * v
	}
	return dst
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

// CC is a type for computing the canonical correlations of a pair of matrices.
// The results of the canonical correlation analysis are only valid
// if the call to CanonicalCorrelations was successful.
type CC struct {
	// n is the number of observations used to
	// construct the canonical correlations.
	n int

	// xd and yd are used for size checks.
	xd, yd int

	x, y, c *mat64.SVD
	ok      bool
}

// CanonicalCorrelations returns a CC which can provide the results of canonical
// correlation analysis of the input data x and y, columns of which should be
// interpretable as two sets of measurements on the same observations (rows).
// These observations are optionally weighted by weights.
//
// Canonical correlation analysis finds associations between two sets of
// variables on the same observations by finding linear combinations of the two
// sphered datasets that maximize the correlation between them.
//
// Some notation: let Xc and Yc denote the centered input data matrices x
// and y (column means subtracted from each column), let Sx and Sy denote the
// sample covariance matrices within x and y respectively, and let Sxy denote
// the covariance matrix between x and y. The sphered data can then be expressed
// as Xc * Sx^{-1/2} and Yc * Sy^{-1/2} respectively, and the correlation matrix
// between the sphered data is called the canonical correlation matrix,
// Sx^{-1/2} * Sxy * Sy^{-1/2}. In cases where S^{-1/2} is ambiguous for some
// covariance matrix S, S^{-1/2} is taken to be E * D^{-1/2} * E^T where S can
// be eigendecomposed as S = E * D * E^T.
//
// The canonical correlations are the correlations between the corresponding
// pairs of canonical variables and can be obtained with c.Corrs(). Canonical
// variables can be obtained by projecting the sphered data into the left and
// right eigenvectors of the canonical correlation matrix, and these
// eigenvectors can be obtained with c.Left(m, true) and c.Right(m, true)
// respectively. The canonical variables can also be obtained directly from the
// centered raw data by using the back-transformed eigenvectors which can be
// obtained with c.Left(m, false) and c.Right(m, false) respectively.
//
// The first pair of left and right eigenvectors of the canonical correlation
// matrix can be interpreted as directions into which the respective sphered
// data can be projected such that the correlation between the two projections
// is maximized. The second pair and onwards solve the same optimization but
// under the constraint that they are uncorrelated (orthogonal in sphered space)
// to previous projections.
//
// CanonicalCorrelations will panic if the inputs x and y do not have the same
// number of rows.
//
// The slice weights is used to weight the observations. If weights is nil, each
// weight is considered to have a value of one, otherwise the length of weights
// must match the number of observations (rows of both x and y) or
// CanonicalCorrelations will panic.
//
// More details can be found at
// https://en.wikipedia.org/wiki/Canonical_correlation
// or in Chapter 3 of
// Koch, Inge. Analysis of multivariate and high-dimensional data.
// Vol. 32. Cambridge University Press, 2013. ISBN: 9780521887939
func (c *CC) CanonicalCorrelations(x, y mat64.Matrix, weights []float64) error {
	var yn int
	c.n, c.xd = x.Dims()
	yn, c.yd = y.Dims()
	if c.n != yn {
		panic("stat: unequal number of observations")
	}
	if weights != nil && len(weights) != c.n {
		panic("stat: len(weights) != observations")
	}

	// Center and factorize x and y.
	c.x, c.ok = svdFactorizeCentered(c.x, x, weights)
	if !c.ok {
		return errors.New("stat: failed to factorize x")
	}
	c.y, c.ok = svdFactorizeCentered(c.y, y, weights)
	if !c.ok {
		return errors.New("stat: failed to factorize y")
	}
	var xu, xv, yu, yv mat64.Dense
	xu.UFromSVD(c.x)
	xv.VFromSVD(c.x)
	yu.UFromSVD(c.y)
	yv.VFromSVD(c.y)

	// Calculate and factorise the canonical correlation matrix.
	var ccor mat64.Dense
	ccor.Product(&xv, xu.T(), &yu, yv.T())
	if c.c == nil {
		c.c = &mat64.SVD{}
	}
	c.ok = c.c.Factorize(&ccor, matrix.SVDThin)
	if !c.ok {
		return errors.New("stat: failed to factorize ccor")
	}
	return nil
}

// Corrs returns the canonical correlations, using dst if it is not nil.
// If dst is not nil and len(dst) does not match the number of columns in
// the y input matrix, Corrs will panic.
func (c *CC) Corrs(dst []float64) []float64 {
	if !c.ok {
		panic("stat: canonical correlations missing or invalid")
	}

	if dst != nil && len(dst) != c.yd {
		panic("stat: length of destination does not match input dimension")
	}
	return c.c.Values(dst)
}

// Left returns the left eigenvectors of the canonical correlation matrix if
// spheredSpace is true. If spheredSpace is false it returns these eigenvectors
// back-transformed to the original data space.
// If dst is not nil it must either be zero-sized or be an xd×yd matrix where xd
// and yd are the number of variables in the input x and y matrices. dst will
// be used as the destination for the vector data. If dst is nil, a new
// mat64.Dense is allocated for the destination.
func (c *CC) Left(dst *mat64.Dense, spheredSpace bool) *mat64.Dense {
	if !c.ok || c.n < 2 {
		panic("stat: canonical correlations missing or invalid")
	}

	if dst == nil {
		dst = &mat64.Dense{}
	} else if d, n := dst.Dims(); (n != 0 || d != 0) && (n != c.yd || d != c.xd) {
		panic(matrix.ErrShape)
	}
	dst.UFromSVD(c.c)
	if spheredSpace {
		return dst
	}

	var xv mat64.Dense
	xs := c.x.Values(nil)
	xv.VFromSVD(c.x)

	scaleColsReciSqrt(&xv, xs)

	dst.Product(&xv, xv.T(), dst)
	dst.Scale(math.Sqrt(float64(c.n-1)), dst)
	return dst
}

// Right returns the right eigenvectors of the canonical correlation matrix if
// spheredSpace is true. If spheredSpace is false it returns these eigenvectors
// back-transformed to the original data space.
// If dst is not nil it must either be zero-sized or be an yd×yd matrix where yd
// is the number of variables in the input y matrix. dst will
// be used as the destination for the vector data. If dst is nil, a new
// mat64.Dense is allocated for the destination.
func (c *CC) Right(dst *mat64.Dense, spheredSpace bool) *mat64.Dense {
	if !c.ok || c.n < 2 {
		panic("stat: canonical correlations missing or invalid")
	}

	if dst == nil {
		dst = &mat64.Dense{}
	} else if d, n := dst.Dims(); (n != 0 || d != 0) && (n != c.yd || d != c.yd) {
		panic(matrix.ErrShape)
	}
	dst.VFromSVD(c.c)
	if spheredSpace {
		return dst
	}

	var yv mat64.Dense
	ys := c.y.Values(nil)
	yv.VFromSVD(c.y)

	scaleColsReciSqrt(&yv, ys)

	dst.Product(&yv, yv.T(), dst)
	dst.Scale(math.Sqrt(float64(c.n-1)), dst)
	return dst
}

func svdFactorizeCentered(work *mat64.SVD, m mat64.Matrix, weights []float64) (svd *mat64.SVD, ok bool) {
	n, d := m.Dims()
	centered := mat64.NewDense(n, d, nil)
	col := make([]float64, n)
	for j := 0; j < d; j++ {
		mat64.Col(col, j, m)
		floats.AddConst(-Mean(col, weights), col)
		centered.SetCol(j, col)
	}
	for i, w := range weights {
		floats.Scale(math.Sqrt(w), centered.RawRowView(i))
	}
	if work == nil {
		work = &mat64.SVD{}
	}
	ok = work.Factorize(centered, matrix.SVDThin)
	return work, ok
}

// scaleColsReciSqrt scales the columns of cols
// by the reciprocal square-root of vals.
func scaleColsReciSqrt(cols *mat64.Dense, vals []float64) {
	if cols == nil {
		panic("stat: input nil")
	}
	n, d := cols.Dims()
	if len(vals) != d {
		panic("stat: input length mismatch")
	}
	col := make([]float64, n)
	for j := 0; j < d; j++ {
		mat64.Col(col, j, cols)
		floats.Scale(math.Sqrt(1/vals[j]), col)
		cols.SetCol(j, col)
	}
}
<commit_msg>stat: use the updated decomposition extraction API<commit_after>// Copyright ©2016 The gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package stat

import (
	"errors"
	"math"

	"gonum.org/v1/gonum/floats"
	"gonum.org/v1/gonum/matrix"
	"gonum.org/v1/gonum/matrix/mat64"
)

// PC is a type for computing and extracting the principal components of a
// matrix. The results of the principal components analysis are only valid
// if the call to PrincipalComponents was successful.
type PC struct {
	n, d    int
	weights []float64
	svd     *mat64.SVD
	ok      bool
}

// PrincipalComponents performs a weighted principal components analysis on the
// matrix of the input data which is represented as an n×d matrix a where each
// row is an observation and each column is a variable.
//
// PrincipalComponents centers the variables but does not scale the variance.
//
// The weights slice is used to weight the observations. If weights is nil, each
// weight is considered to have a value of one, otherwise the length of weights
// must match the number of observations or PrincipalComponents will panic.
//
// PrincipalComponents returns whether the analysis was successful.
func (c *PC) PrincipalComponents(a mat64.Matrix, weights []float64) (ok bool) {
	c.n, c.d = a.Dims()
	if weights != nil && len(weights) != c.n {
		panic("stat: len(weights) != observations")
	}

	c.svd, c.ok = svdFactorizeCentered(c.svd, a, weights)
	if c.ok {
		c.weights = append(c.weights[:0], weights...)
	}
	return c.ok
}

// Vectors returns the component direction vectors of a principal components
// analysis. The vectors are returned in the columns of a d×min(n, d) matrix.
// If dst is not nil it must either be zero-sized or be a d×min(n, d) matrix.
// dst will  be used as the destination for the direction vector data. If dst
// is nil, a new mat64.Dense is allocated for the destination.
func (c *PC) Vectors(dst *mat64.Dense) *mat64.Dense {
	if !c.ok {
		panic("stat: use of unsuccessful principal components analysis")
	}

	if dst != nil {
		if d, n := dst.Dims(); (n != 0 || d != 0) && (d != c.d || n != min(c.n, c.d)) {
			panic(matrix.ErrShape)
		}
	}
	return c.svd.VTo(dst)
}

// Vars returns the column variances of the principal component scores,
// b * vecs, where b is a matrix with centered columns. Variances are returned
// in descending order.
// If dst is not nil it is used to store the variances and returned.
// Vars will panic if the receiver has not successfully performed a principal
// components analysis or dst is not nil and the length of dst is not min(n, d).
func (c *PC) Vars(dst []float64) []float64 {
	if !c.ok {
		panic("stat: use of unsuccessful principal components analysis")
	}
	if dst != nil && len(dst) != min(c.n, c.d) {
		panic("stat: length of slice does not match analysis")
	}

	dst = c.svd.Values(dst)
	var f float64
	if c.weights == nil {
		f = 1 / float64(c.n-1)
	} else {
		f = 1 / (floats.Sum(c.weights) - 1)
	}
	for i, v := range dst {
		dst[i] = f * v * v
	}
	return dst
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

// CC is a type for computing the canonical correlations of a pair of matrices.
// The results of the canonical correlation analysis are only valid
// if the call to CanonicalCorrelations was successful.
type CC struct {
	// n is the number of observations used to
	// construct the canonical correlations.
	n int

	// xd and yd are used for size checks.
	xd, yd int

	x, y, c *mat64.SVD
	ok      bool
}

// CanonicalCorrelations returns a CC which can provide the results of canonical
// correlation analysis of the input data x and y, columns of which should be
// interpretable as two sets of measurements on the same observations (rows).
// These observations are optionally weighted by weights.
//
// Canonical correlation analysis finds associations between two sets of
// variables on the same observations by finding linear combinations of the two
// sphered datasets that maximize the correlation between them.
//
// Some notation: let Xc and Yc denote the centered input data matrices x
// and y (column means subtracted from each column), let Sx and Sy denote the
// sample covariance matrices within x and y respectively, and let Sxy denote
// the covariance matrix between x and y. The sphered data can then be expressed
// as Xc * Sx^{-1/2} and Yc * Sy^{-1/2} respectively, and the correlation matrix
// between the sphered data is called the canonical correlation matrix,
// Sx^{-1/2} * Sxy * Sy^{-1/2}. In cases where S^{-1/2} is ambiguous for some
// covariance matrix S, S^{-1/2} is taken to be E * D^{-1/2} * E^T where S can
// be eigendecomposed as S = E * D * E^T.
//
// The canonical correlations are the correlations between the corresponding
// pairs of canonical variables and can be obtained with c.Corrs(). Canonical
// variables can be obtained by projecting the sphered data into the left and
// right eigenvectors of the canonical correlation matrix, and these
// eigenvectors can be obtained with c.Left(m, true) and c.Right(m, true)
// respectively. The canonical variables can also be obtained directly from the
// centered raw data by using the back-transformed eigenvectors which can be
// obtained with c.Left(m, false) and c.Right(m, false) respectively.
//
// The first pair of left and right eigenvectors of the canonical correlation
// matrix can be interpreted as directions into which the respective sphered
// data can be projected such that the correlation between the two projections
// is maximized. The second pair and onwards solve the same optimization but
// under the constraint that they are uncorrelated (orthogonal in sphered space)
// to previous projections.
//
// CanonicalCorrelations will panic if the inputs x and y do not have the same
// number of rows.
//
// The slice weights is used to weight the observations. If weights is nil, each
// weight is considered to have a value of one, otherwise the length of weights
// must match the number of observations (rows of both x and y) or
// CanonicalCorrelations will panic.
//
// More details can be found at
// https://en.wikipedia.org/wiki/Canonical_correlation
// or in Chapter 3 of
// Koch, Inge. Analysis of multivariate and high-dimensional data.
// Vol. 32. Cambridge University Press, 2013. ISBN: 9780521887939
func (c *CC) CanonicalCorrelations(x, y mat64.Matrix, weights []float64) error {
	var yn int
	c.n, c.xd = x.Dims()
	yn, c.yd = y.Dims()
	if c.n != yn {
		panic("stat: unequal number of observations")
	}
	if weights != nil && len(weights) != c.n {
		panic("stat: len(weights) != observations")
	}

	// Center and factorize x and y.
	c.x, c.ok = svdFactorizeCentered(c.x, x, weights)
	if !c.ok {
		return errors.New("stat: failed to factorize x")
	}
	c.y, c.ok = svdFactorizeCentered(c.y, y, weights)
	if !c.ok {
		return errors.New("stat: failed to factorize y")
	}
	xu := c.x.UTo(nil)
	xv := c.x.VTo(nil)
	yu := c.y.UTo(nil)
	yv := c.y.VTo(nil)

	// Calculate and factorise the canonical correlation matrix.
	var ccor mat64.Dense
	ccor.Product(xv, xu.T(), yu, yv.T())
	if c.c == nil {
		c.c = &mat64.SVD{}
	}
	c.ok = c.c.Factorize(&ccor, matrix.SVDThin)
	if !c.ok {
		return errors.New("stat: failed to factorize ccor")
	}
	return nil
}

// Corrs returns the canonical correlations, using dst if it is not nil.
// If dst is not nil and len(dst) does not match the number of columns in
// the y input matrix, Corrs will panic.
func (c *CC) Corrs(dst []float64) []float64 {
	if !c.ok {
		panic("stat: canonical correlations missing or invalid")
	}

	if dst != nil && len(dst) != c.yd {
		panic("stat: length of destination does not match input dimension")
	}
	return c.c.Values(dst)
}

// Left returns the left eigenvectors of the canonical correlation matrix if
// spheredSpace is true. If spheredSpace is false it returns these eigenvectors
// back-transformed to the original data space.
// If dst is not nil it must either be zero-sized or be an xd×yd matrix where xd
// and yd are the number of variables in the input x and y matrices. dst will
// be used as the destination for the vector data. If dst is nil, a new
// mat64.Dense is allocated for the destination.
func (c *CC) Left(dst *mat64.Dense, spheredSpace bool) *mat64.Dense {
	if !c.ok || c.n < 2 {
		panic("stat: canonical correlations missing or invalid")
	}

	if dst != nil {
		if d, n := dst.Dims(); (n != 0 || d != 0) && (n != c.yd || d != c.xd) {
			panic(matrix.ErrShape)
		}
	}
	dst = c.c.UTo(dst)
	if spheredSpace {
		return dst
	}

	xs := c.x.Values(nil)
	xv := c.x.VTo(nil)

	scaleColsReciSqrt(xv, xs)

	dst.Product(xv, xv.T(), dst)
	dst.Scale(math.Sqrt(float64(c.n-1)), dst)
	return dst
}

// Right returns the right eigenvectors of the canonical correlation matrix if
// spheredSpace is true. If spheredSpace is false it returns these eigenvectors
// back-transformed to the original data space.
// If dst is not nil it must either be zero-sized or be an yd×yd matrix where yd
// is the number of variables in the input y matrix. dst will
// be used as the destination for the vector data. If dst is nil, a new
// mat64.Dense is allocated for the destination.
func (c *CC) Right(dst *mat64.Dense, spheredSpace bool) *mat64.Dense {
	if !c.ok || c.n < 2 {
		panic("stat: canonical correlations missing or invalid")
	}

	if dst != nil {
		if d, n := dst.Dims(); (n != 0 || d != 0) && (n != c.yd || d != c.yd) {
			panic(matrix.ErrShape)
		}
	}
	dst = c.c.VTo(dst)
	if spheredSpace {
		return dst
	}

	ys := c.y.Values(nil)
	yv := c.y.VTo(nil)

	scaleColsReciSqrt(yv, ys)

	dst.Product(yv, yv.T(), dst)
	dst.Scale(math.Sqrt(float64(c.n-1)), dst)
	return dst
}

func svdFactorizeCentered(work *mat64.SVD, m mat64.Matrix, weights []float64) (svd *mat64.SVD, ok bool) {
	n, d := m.Dims()
	centered := mat64.NewDense(n, d, nil)
	col := make([]float64, n)
	for j := 0; j < d; j++ {
		mat64.Col(col, j, m)
		floats.AddConst(-Mean(col, weights), col)
		centered.SetCol(j, col)
	}
	for i, w := range weights {
		floats.Scale(math.Sqrt(w), centered.RawRowView(i))
	}
	if work == nil {
		work = &mat64.SVD{}
	}
	ok = work.Factorize(centered, matrix.SVDThin)
	return work, ok
}

// scaleColsReciSqrt scales the columns of cols
// by the reciprocal square-root of vals.
func scaleColsReciSqrt(cols *mat64.Dense, vals []float64) {
	if cols == nil {
		panic("stat: input nil")
	}
	n, d := cols.Dims()
	if len(vals) != d {
		panic("stat: input length mismatch")
	}
	col := make([]float64, n)
	for j := 0; j < d; j++ {
		mat64.Col(col, j, cols)
		floats.Scale(math.Sqrt(1/vals[j]), col)
		cols.SetCol(j, col)
	}
}
<|endoftext|>


<commit_before>package raft

import (
  "fmt"
  "time"
  "log"
)

var INIT string = "init"

var STATE *State = &State{
  Status: INIT,
  C: make(chan string, 1),
}

type State struct {
  Status string
  C chan string
}

func (s *State) Switch(state string) error {
  if state == STATE.Status {
    return nil
  }

  if STATE.Status == INIT && state != FOLLOWER {
    return fmt.Errorf("State must be follower when STATE == INIT")
  }

  switch state {
    case FOLLOWER, CANDIDATE, LEADER:
      s.C <- state
    default:
      return fmt.Errorf("Only supported operations: FOLLOWER, CANDIDATE or LEADER.")
  }

  switch state {
    case FOLLOWER:
      <- time.Tick(100 * time.Millisecond)
    case CANDIDATE:
      <- time.Tick(300 * time.Millisecond)
    case LEADER:
      <- time.Tick(500 * time.Millisecond)
  }

  s.Status = <- s.C

  return nil
}

type StateMachine struct {
  Init []func()
}

func (s *StateMachine) Initialize() error {
  return nil
}

func NewStateMachine() {
}
<commit_msg>Removed log for debug purposes<commit_after>package raft

import (
  "fmt"
  "time"
)

var INIT string = "init"

var STATE *State = &State{
  Status: INIT,
  C: make(chan string, 1),
}

type State struct {
  Status string
  C chan string
}

func (s *State) Switch(state string) error {
  if state == STATE.Status {
    return nil
  }

  if STATE.Status == INIT && state != FOLLOWER {
    return fmt.Errorf("State must be follower when STATE == INIT")
  }

  switch state {
    case FOLLOWER, CANDIDATE, LEADER:
      s.C <- state
    default:
      return fmt.Errorf("Only supported operations: FOLLOWER, CANDIDATE or LEADER.")
  }

  switch state {
    case FOLLOWER:
      <- time.Tick(100 * time.Millisecond)
    case CANDIDATE:
      <- time.Tick(300 * time.Millisecond)
    case LEADER:
      <- time.Tick(500 * time.Millisecond)
  }

  s.Status = <- s.C

  return nil
}

type StateMachine struct {
  Init []func()
}

func (s *StateMachine) Initialize() error {
  return nil
}

func NewStateMachine() {
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"reflect"
	"testing"

	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/hashicorp/terraform/terraform"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/route53"
)

func TestAccAWSRoute53DelegationSet_basic(t *testing.T) {
	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckRoute53ZoneDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccRoute53DelegationSetConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckRoute53DelegationSetExists("aws_route53_delegation_set.test"),
				),
			},
		},
	})
}

func TestAccAWSRoute53DelegationSet_withZones(t *testing.T) {
	var zone route53.GetHostedZoneOutput

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckRoute53ZoneDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccRoute53DelegationSetWithZonesConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckRoute53DelegationSetExists("aws_route53_delegation_set.main"),
					testAccCheckRoute53ZoneExists("aws_route53_zone.primary", &zone),
					testAccCheckRoute53ZoneExists("aws_route53_zone.secondary", &zone),
					testAccCheckRoute53NameServersMatch("aws_route53_delegation_set.main", "aws_route53_zone.primary"),
					testAccCheckRoute53NameServersMatch("aws_route53_delegation_set.main", "aws_route53_zone.secondary"),
				),
			},
		},
	})
}

func testAccCheckRoute53DelegationSetDestroy(s *terraform.State, provider *schema.Provider) error {
	conn := provider.Meta().(*AWSClient).r53conn
	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_route53_delegation_set" {
			continue
		}

		_, err := conn.GetReusableDelegationSet(&route53.GetReusableDelegationSetInput{Id: aws.String(rs.Primary.ID)})
		if err == nil {
			return fmt.Errorf("Delegation set still exists")
		}
	}
	return nil
}

func testAccCheckRoute53DelegationSetExists(n string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		conn := testAccProvider.Meta().(*AWSClient).r53conn
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No delegation set ID is set")
		}

		out, err := conn.GetReusableDelegationSet(&route53.GetReusableDelegationSetInput{
			Id: aws.String(rs.Primary.ID),
		})

		if err != nil {
			return fmt.Errorf("Delegation set does not exist: %#v", rs.Primary.ID)
		}

		setID := cleanDelegationSetId(*out.DelegationSet.Id)
		if setID != rs.Primary.ID {
			return fmt.Errorf("Delegation set ID does not match:\nExpected: %#v\nReturned: %#v", rs.Primary.ID, setID)
		}

		return nil
	}
}

func testAccCheckRoute53NameServersMatch(delegationSetName, zoneName string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		conn := testAccProvider.Meta().(*AWSClient).r53conn

		delegationSetLocal, ok := s.RootModule().Resources[delegationSetName]
		if !ok {
			return fmt.Errorf("Not found: %s", delegationSetName)
		}
		delegationSet, err := conn.GetReusableDelegationSet(&route53.GetReusableDelegationSetInput{
			Id: aws.String(delegationSetLocal.Primary.ID),
		})
		if err != nil {
			return fmt.Errorf("Delegation set does not exist: %#v", delegationSetLocal.Primary.ID)
		}

		hostedZoneLocal, ok := s.RootModule().Resources[zoneName]
		if !ok {
			return fmt.Errorf("Not found: %s", zoneName)
		}
		hostedZone, err := conn.GetHostedZone(&route53.GetHostedZoneInput{
			Id: aws.String(hostedZoneLocal.Primary.ID),
		})
		if err != nil {
			return fmt.Errorf("Delegation set does not exist: %#v", hostedZoneLocal.Primary.ID)
		}

		if !reflect.DeepEqual(delegationSet.DelegationSet.NameServers, hostedZone.DelegationSet.NameServers) {
			return fmt.Errorf("Name servers do not match:\nDelegation Set: %#v\nHosted Zone:%#v",
				delegationSet.DelegationSet.NameServers, hostedZone.DelegationSet.NameServers)
		}

		return nil
	}
}

const testAccRoute53DelegationSetConfig = `
resource "aws_route53_delegation_set" "test" {
	reference_name = "test"
}
`

const testAccRoute53DelegationSetWithZonesConfig = `
resource "aws_route53_delegation_set" "main" {
    reference_name = "main"
}

resource "aws_route53_zone" "primary" {
    name = "hashicorp.com"
    delegation_set_id = "${aws_route53_delegation_set.main.id}"
}

resource "aws_route53_zone" "secondary" {
    name = "terraform.io"
    delegation_set_id = "${aws_route53_delegation_set.main.id}"
}
`
<commit_msg>provider/aws: fix name on id-only check<commit_after>package aws

import (
	"fmt"
	"reflect"
	"testing"

	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
	"github.com/hashicorp/terraform/terraform"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/route53"
)

func TestAccAWSRoute53DelegationSet_basic(t *testing.T) {
	resource.Test(t, resource.TestCase{
		PreCheck:        func() { testAccPreCheck(t) },
		IDRefreshName:   "aws_route53_delegation_set.test",
		IDRefreshIgnore: []string{"reference_name"},
		Providers:       testAccProviders,
		CheckDestroy:    testAccCheckRoute53ZoneDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccRoute53DelegationSetConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckRoute53DelegationSetExists("aws_route53_delegation_set.test"),
				),
			},
		},
	})
}

func TestAccAWSRoute53DelegationSet_withZones(t *testing.T) {
	var zone route53.GetHostedZoneOutput

	resource.Test(t, resource.TestCase{
		PreCheck:        func() { testAccPreCheck(t) },
		IDRefreshName:   "aws_route53_delegation_set.main",
		IDRefreshIgnore: []string{"reference_name"},
		Providers:       testAccProviders,
		CheckDestroy:    testAccCheckRoute53ZoneDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccRoute53DelegationSetWithZonesConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckRoute53DelegationSetExists("aws_route53_delegation_set.main"),
					testAccCheckRoute53ZoneExists("aws_route53_zone.primary", &zone),
					testAccCheckRoute53ZoneExists("aws_route53_zone.secondary", &zone),
					testAccCheckRoute53NameServersMatch("aws_route53_delegation_set.main", "aws_route53_zone.primary"),
					testAccCheckRoute53NameServersMatch("aws_route53_delegation_set.main", "aws_route53_zone.secondary"),
				),
			},
		},
	})
}

func testAccCheckRoute53DelegationSetDestroy(s *terraform.State, provider *schema.Provider) error {
	conn := provider.Meta().(*AWSClient).r53conn
	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_route53_delegation_set" {
			continue
		}

		_, err := conn.GetReusableDelegationSet(&route53.GetReusableDelegationSetInput{Id: aws.String(rs.Primary.ID)})
		if err == nil {
			return fmt.Errorf("Delegation set still exists")
		}
	}
	return nil
}

func testAccCheckRoute53DelegationSetExists(n string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		conn := testAccProvider.Meta().(*AWSClient).r53conn
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No delegation set ID is set")
		}

		out, err := conn.GetReusableDelegationSet(&route53.GetReusableDelegationSetInput{
			Id: aws.String(rs.Primary.ID),
		})

		if err != nil {
			return fmt.Errorf("Delegation set does not exist: %#v", rs.Primary.ID)
		}

		setID := cleanDelegationSetId(*out.DelegationSet.Id)
		if setID != rs.Primary.ID {
			return fmt.Errorf("Delegation set ID does not match:\nExpected: %#v\nReturned: %#v", rs.Primary.ID, setID)
		}

		return nil
	}
}

func testAccCheckRoute53NameServersMatch(delegationSetName, zoneName string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		conn := testAccProvider.Meta().(*AWSClient).r53conn

		delegationSetLocal, ok := s.RootModule().Resources[delegationSetName]
		if !ok {
			return fmt.Errorf("Not found: %s", delegationSetName)
		}
		delegationSet, err := conn.GetReusableDelegationSet(&route53.GetReusableDelegationSetInput{
			Id: aws.String(delegationSetLocal.Primary.ID),
		})
		if err != nil {
			return fmt.Errorf("Delegation set does not exist: %#v", delegationSetLocal.Primary.ID)
		}

		hostedZoneLocal, ok := s.RootModule().Resources[zoneName]
		if !ok {
			return fmt.Errorf("Not found: %s", zoneName)
		}
		hostedZone, err := conn.GetHostedZone(&route53.GetHostedZoneInput{
			Id: aws.String(hostedZoneLocal.Primary.ID),
		})
		if err != nil {
			return fmt.Errorf("Delegation set does not exist: %#v", hostedZoneLocal.Primary.ID)
		}

		if !reflect.DeepEqual(delegationSet.DelegationSet.NameServers, hostedZone.DelegationSet.NameServers) {
			return fmt.Errorf("Name servers do not match:\nDelegation Set: %#v\nHosted Zone:%#v",
				delegationSet.DelegationSet.NameServers, hostedZone.DelegationSet.NameServers)
		}

		return nil
	}
}

const testAccRoute53DelegationSetConfig = `
resource "aws_route53_delegation_set" "test" {
	reference_name = "test"
}
`

const testAccRoute53DelegationSetWithZonesConfig = `
resource "aws_route53_delegation_set" "main" {
    reference_name = "main"
}

resource "aws_route53_zone" "primary" {
    name = "hashicorp.com"
    delegation_set_id = "${aws_route53_delegation_set.main.id}"
}

resource "aws_route53_zone" "secondary" {
    name = "terraform.io"
    delegation_set_id = "${aws_route53_delegation_set.main.id}"
}
`
<|endoftext|>