<commit_before>package autonat

import (
	"context"
	"errors"
	"math/rand"
	"sync"
	"time"

	host "github.com/libp2p/go-libp2p-host"
	inet "github.com/libp2p/go-libp2p-net"
	peer "github.com/libp2p/go-libp2p-peer"
	ma "github.com/multiformats/go-multiaddr"
)

// NATStatus is the state of NAT as detected by the ambient service.
type NATStatus int

const (
	// NAT status is unknown; this means that the ambient service has not been
	// able to decide the presence of NAT in the most recent attempt to test
	// dial through known autonat peers.  initial state.
	NATStatusUnknown NATStatus = iota
	// NAT status is publicly dialable
	NATStatusPublic
	// NAT status is private network
	NATStatusPrivate
)

var (
	AutoNATBootDelay       = 15 * time.Second
	AutoNATRetryInterval   = 90 * time.Second
	AutoNATRefreshInterval = 15 * time.Minute
	AutoNATRequestTimeout  = 60 * time.Second
)

// AutoNAT is the interface for ambient NAT autodiscovery
type AutoNAT interface {
	// Status returns the current NAT status
	Status() NATStatus
	// PublicAddr returns the public dial address when NAT status is public and an
	// error otherwise
	PublicAddr() (ma.Multiaddr, error)
}

// AmbientAutoNAT is the implementation of ambient NAT autodiscovery
type AmbientAutoNAT struct {
	ctx  context.Context
	host host.Host

	mx         sync.Mutex
	peers      map[peer.ID]struct{}
	status     NATStatus
	addr       ma.Multiaddr
	confidence int
}

// NewAutoNAT creates a new ambient NAT autodiscovery instance attached to a host
func NewAutoNAT(ctx context.Context, h host.Host) AutoNAT {
	as := &AmbientAutoNAT{
		ctx:    ctx,
		host:   h,
		peers:  make(map[peer.ID]struct{}),
		status: NATStatusUnknown,
	}

	h.Network().Notify(as)
	go as.background()

	return as
}

func (as *AmbientAutoNAT) Status() NATStatus {
	return as.status
}

func (as *AmbientAutoNAT) PublicAddr() (ma.Multiaddr, error) {
	as.mx.Lock()
	defer as.mx.Unlock()

	if as.status != NATStatusPublic {
		return nil, errors.New("NAT Status is not public")
	}

	return as.addr, nil
}

func (as *AmbientAutoNAT) background() {
	// wait a bit for the node to come online and establish some connections
	// before starting autodetection
	select {
	case <-time.After(AutoNATBootDelay):
	case <-as.ctx.Done():
		return
	}

	for {
		as.autodetect()

		delay := AutoNATRefreshInterval
		if as.status == NATStatusUnknown {
			delay = AutoNATRetryInterval
		}

		select {
		case <-time.After(delay):
		case <-as.ctx.Done():
			return
		}
	}
}

func (as *AmbientAutoNAT) autodetect() {
	peers := as.getPeers()

	if len(peers) == 0 {
		log.Debugf("skipping NAT auto detection; no autonat peers")
		return
	}

	cli := NewAutoNATClient(as.host)
	failures := 0

	for _, p := range peers {
		ctx, cancel := context.WithTimeout(as.ctx, AutoNATRequestTimeout)
		a, err := cli.DialBack(ctx, p)
		cancel()

		switch {
		case err == nil:
			log.Debugf("NAT status is public; address through %s: %s", p.Pretty(), a.String())
			as.mx.Lock()
			as.addr = a
			as.status = NATStatusPublic
			as.confidence = 0
			as.mx.Unlock()
			return

		case IsDialError(err):
			log.Debugf("dial error through %s: %s", p.Pretty(), err.Error())
			failures++
			if failures >= 3 || as.confidence >= 3 { // 3 times is enemy action
				log.Debugf("NAT status is private")
				as.mx.Lock()
				as.status = NATStatusPrivate
				as.confidence = 3
				as.mx.Unlock()
				return
			}

		default:
			log.Debugf("Error dialing through %s: %s", p.Pretty(), err.Error())
		}
	}

	as.mx.Lock()
	if failures > 0 {
		as.status = NATStatusPrivate
		as.confidence++
		log.Debugf("NAT status is private")
	} else {
		as.status = NATStatusUnknown
		as.confidence = 0
		log.Debugf("NAT status is unknown")
	}
	as.mx.Unlock()
}

func (as *AmbientAutoNAT) getPeers() []peer.ID {
	as.mx.Lock()
	defer as.mx.Unlock()

	if len(as.peers) == 0 {
		return nil
	}

	var connected, others []peer.ID

	for p := range as.peers {
		if as.host.Network().Connectedness(p) == inet.Connected {
			connected = append(connected, p)
		} else {
			others = append(others, p)
		}
	}

	shufflePeers(connected)

	if len(connected) < 3 {
		shufflePeers(others)
		return append(connected, others...)
	} else {
		return connected
	}
}

func shufflePeers(peers []peer.ID) {
	for i := range peers {
		j := rand.Intn(i + 1)
		peers[i], peers[j] = peers[j], peers[i]
	}
}
<commit_msg>add docstring for confidence<commit_after>package autonat

import (
	"context"
	"errors"
	"math/rand"
	"sync"
	"time"

	host "github.com/libp2p/go-libp2p-host"
	inet "github.com/libp2p/go-libp2p-net"
	peer "github.com/libp2p/go-libp2p-peer"
	ma "github.com/multiformats/go-multiaddr"
)

// NATStatus is the state of NAT as detected by the ambient service.
type NATStatus int

const (
	// NAT status is unknown; this means that the ambient service has not been
	// able to decide the presence of NAT in the most recent attempt to test
	// dial through known autonat peers.  initial state.
	NATStatusUnknown NATStatus = iota
	// NAT status is publicly dialable
	NATStatusPublic
	// NAT status is private network
	NATStatusPrivate
)

var (
	AutoNATBootDelay       = 15 * time.Second
	AutoNATRetryInterval   = 90 * time.Second
	AutoNATRefreshInterval = 15 * time.Minute
	AutoNATRequestTimeout  = 60 * time.Second
)

// AutoNAT is the interface for ambient NAT autodiscovery
type AutoNAT interface {
	// Status returns the current NAT status
	Status() NATStatus
	// PublicAddr returns the public dial address when NAT status is public and an
	// error otherwise
	PublicAddr() (ma.Multiaddr, error)
}

// AmbientAutoNAT is the implementation of ambient NAT autodiscovery
type AmbientAutoNAT struct {
	ctx  context.Context
	host host.Host

	mx     sync.Mutex
	peers  map[peer.ID]struct{}
	status NATStatus
	addr   ma.Multiaddr
	// Reflects the confidence on of the NATStatus being private, as a single
	// dialback may fail for reasons unrelated to NAT.
	// If it is <3, then multiple autoNAT peers may be contacted for dialback
	// If only a single autoNAT peer is known, then the confidence increases
	// for each failure until it reaches 3.
	confidence int
}

// NewAutoNAT creates a new ambient NAT autodiscovery instance attached to a host
func NewAutoNAT(ctx context.Context, h host.Host) AutoNAT {
	as := &AmbientAutoNAT{
		ctx:    ctx,
		host:   h,
		peers:  make(map[peer.ID]struct{}),
		status: NATStatusUnknown,
	}

	h.Network().Notify(as)
	go as.background()

	return as
}

func (as *AmbientAutoNAT) Status() NATStatus {
	return as.status
}

func (as *AmbientAutoNAT) PublicAddr() (ma.Multiaddr, error) {
	as.mx.Lock()
	defer as.mx.Unlock()

	if as.status != NATStatusPublic {
		return nil, errors.New("NAT Status is not public")
	}

	return as.addr, nil
}

func (as *AmbientAutoNAT) background() {
	// wait a bit for the node to come online and establish some connections
	// before starting autodetection
	select {
	case <-time.After(AutoNATBootDelay):
	case <-as.ctx.Done():
		return
	}

	for {
		as.autodetect()

		delay := AutoNATRefreshInterval
		if as.status == NATStatusUnknown {
			delay = AutoNATRetryInterval
		}

		select {
		case <-time.After(delay):
		case <-as.ctx.Done():
			return
		}
	}
}

func (as *AmbientAutoNAT) autodetect() {
	peers := as.getPeers()

	if len(peers) == 0 {
		log.Debugf("skipping NAT auto detection; no autonat peers")
		return
	}

	cli := NewAutoNATClient(as.host)
	failures := 0

	for _, p := range peers {
		ctx, cancel := context.WithTimeout(as.ctx, AutoNATRequestTimeout)
		a, err := cli.DialBack(ctx, p)
		cancel()

		switch {
		case err == nil:
			log.Debugf("NAT status is public; address through %s: %s", p.Pretty(), a.String())
			as.mx.Lock()
			as.addr = a
			as.status = NATStatusPublic
			as.confidence = 0
			as.mx.Unlock()
			return

		case IsDialError(err):
			log.Debugf("dial error through %s: %s", p.Pretty(), err.Error())
			failures++
			if failures >= 3 || as.confidence >= 3 { // 3 times is enemy action
				log.Debugf("NAT status is private")
				as.mx.Lock()
				as.status = NATStatusPrivate
				as.confidence = 3
				as.mx.Unlock()
				return
			}

		default:
			log.Debugf("Error dialing through %s: %s", p.Pretty(), err.Error())
		}
	}

	as.mx.Lock()
	if failures > 0 {
		as.status = NATStatusPrivate
		as.confidence++
		log.Debugf("NAT status is private")
	} else {
		as.status = NATStatusUnknown
		as.confidence = 0
		log.Debugf("NAT status is unknown")
	}
	as.mx.Unlock()
}

func (as *AmbientAutoNAT) getPeers() []peer.ID {
	as.mx.Lock()
	defer as.mx.Unlock()

	if len(as.peers) == 0 {
		return nil
	}

	var connected, others []peer.ID

	for p := range as.peers {
		if as.host.Network().Connectedness(p) == inet.Connected {
			connected = append(connected, p)
		} else {
			others = append(others, p)
		}
	}

	shufflePeers(connected)

	if len(connected) < 3 {
		shufflePeers(others)
		return append(connected, others...)
	} else {
		return connected
	}
}

func shufflePeers(peers []peer.ID) {
	for i := range peers {
		j := rand.Intn(i + 1)
		peers[i], peers[j] = peers[j], peers[i]
	}
}
<|endoftext|>


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

package sacloud

import (
	"encoding/json"

	"github.com/sacloud/libsacloud/v2/sacloud/naked"
	"github.com/sacloud/libsacloud/v2/sacloud/search"
)

// UnmarshalJSON APIからの戻り値でレスポンスボディ直下にデータを持つことへの対応
func (a *authStatusReadResponseEnvelope) UnmarshalJSON(data []byte) error {
	type alias authStatusReadResponseEnvelope

	var tmp alias
	if err := json.Unmarshal(data, &tmp); err != nil {
		return err
	}

	var nakedAuthStatus naked.AuthStatus
	if err := json.Unmarshal(data, &nakedAuthStatus); err != nil {
		return err
	}
	tmp.AuthStatus = &nakedAuthStatus

	*a = authStatusReadResponseEnvelope(tmp)
	return nil
}

func (b *billDetailsCSVResponseEnvelope) UnmarshalJSON(data []byte) error {
	type alias billDetailsCSVResponseEnvelope

	var tmp alias
	if err := json.Unmarshal(data, &tmp); err != nil {
		return err
	}

	var nakedBillDetailCSV naked.BillDetailCSV
	if err := json.Unmarshal(data, &nakedBillDetailCSV); err != nil {
		return err
	}
	tmp.CSV = &nakedBillDetailCSV

	*b = billDetailsCSVResponseEnvelope(tmp)
	return nil
}

func (m *mobileGatewaySetSIMRoutesRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias struct {
		SIMRoutes []*naked.MobileGatewaySIMRoute `json:"sim_routes"`
	}
	tmp := &alias{
		SIMRoutes: m.SIMRoutes,
	}
	if len(tmp.SIMRoutes) == 0 {
		tmp.SIMRoutes = make([]*naked.MobileGatewaySIMRoute, 0)
	}
	return json.Marshal(tmp)
}

// UnmarshalJSON APIからの戻り値でレスポンスボディ直下にデータを持つことへの対応
func (s *serverGetVNCProxyResponseEnvelope) UnmarshalJSON(data []byte) error {
	type alias serverGetVNCProxyResponseEnvelope

	var tmp alias
	if err := json.Unmarshal(data, &tmp); err != nil {
		return err
	}

	var nakedVNCProxy naked.VNCProxyInfo
	if err := json.Unmarshal(data, &nakedVNCProxy); err != nil {
		return err
	}
	tmp.VNCProxyInfo = &nakedVNCProxy

	*s = serverGetVNCProxyResponseEnvelope(tmp)
	return nil
}

/*
 * 検索時に固定パラメータを設定するための実装
 */

func (s autoBackupFindRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias autoBackupFindRequestEnvelope
	tmp := alias(s)
	if tmp.Filter == nil {
		tmp.Filter = search.Filter{}
	}
	tmp.Filter[search.Key("Provider.Class")] = "autobackup"
	return json.Marshal(tmp)
}

func (s containerRegistryFindRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias containerRegistryFindRequestEnvelope
	tmp := alias(s)
	if tmp.Filter == nil {
		tmp.Filter = search.Filter{}
	}
	tmp.Filter[search.Key("Provider.Class")] = "containerregistry"
	return json.Marshal(tmp)
}

func (s eSMEFindRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias eSMEFindRequestEnvelope
	tmp := alias(s)
	if tmp.Filter == nil {
		tmp.Filter = search.Filter{}
	}
	tmp.Filter[search.Key("Provider.Class")] = "esme"
	return json.Marshal(tmp)
}

func (s dNSFindRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias dNSFindRequestEnvelope
	tmp := alias(s)
	if tmp.Filter == nil {
		tmp.Filter = search.Filter{}
	}
	tmp.Filter[search.Key("Provider.Class")] = "dns"
	return json.Marshal(tmp)
}

func (s simpleMonitorFindRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias simpleMonitorFindRequestEnvelope
	tmp := alias(s)
	if tmp.Filter == nil {
		tmp.Filter = search.Filter{}
	}
	tmp.Filter[search.Key("Provider.Class")] = "simplemon"
	return json.Marshal(tmp)
}

func (s gSLBFindRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias gSLBFindRequestEnvelope
	tmp := alias(s)
	if tmp.Filter == nil {
		tmp.Filter = search.Filter{}
	}
	tmp.Filter[search.Key("Provider.Class")] = "gslb"
	return json.Marshal(tmp)
}

func (s proxyLBFindRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias proxyLBFindRequestEnvelope
	tmp := alias(s)
	if tmp.Filter == nil {
		tmp.Filter = search.Filter{}
	}
	tmp.Filter[search.Key("Provider.Class")] = "proxylb"
	return json.Marshal(tmp)
}

func (s sIMFindRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias sIMFindRequestEnvelope
	tmp := alias(s)
	if tmp.Filter == nil {
		tmp.Filter = search.Filter{}
	}
	tmp.Filter[search.Key("Provider.Class")] = "sim"
	return json.Marshal(tmp)
}

func (s localRouterFindRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias localRouterFindRequestEnvelope
	tmp := alias(s)
	if tmp.Filter == nil {
		tmp.Filter = search.Filter{}
	}
	tmp.Filter[search.Key("Provider.Class")] = "localrouter"
	return json.Marshal(tmp)
}

func (s databaseFindRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias databaseFindRequestEnvelope
	tmp := alias(s)
	if tmp.Filter == nil {
		tmp.Filter = search.Filter{}
	}
	tmp.Filter[search.Key("Class")] = "database"
	return json.Marshal(tmp)
}

func (s loadBalancerFindRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias loadBalancerFindRequestEnvelope
	tmp := alias(s)
	if tmp.Filter == nil {
		tmp.Filter = search.Filter{}
	}
	tmp.Filter[search.Key("Class")] = "loadbalancer"
	return json.Marshal(tmp)
}

func (s vPCRouterFindRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias vPCRouterFindRequestEnvelope
	tmp := alias(s)
	if tmp.Filter == nil {
		tmp.Filter = search.Filter{}
	}
	tmp.Filter[search.Key("Class")] = "vpcrouter"
	return json.Marshal(tmp)
}

func (s nFSFindRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias nFSFindRequestEnvelope
	tmp := alias(s)
	if tmp.Filter == nil {
		tmp.Filter = search.Filter{}
	}
	tmp.Filter[search.Key("Class")] = "nfs"
	return json.Marshal(tmp)
}

func (s mobileGatewayFindRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias mobileGatewayFindRequestEnvelope
	tmp := alias(s)
	if tmp.Filter == nil {
		tmp.Filter = search.Filter{}
	}
	tmp.Filter[search.Key("Class")] = "mobilegateway"
	return json.Marshal(tmp)
}

/*
 * for Shared Archive
 */

func (s archiveShareRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias archiveShareRequestEnvelope
	tmp := alias(s)
	tmp.Shared = true
	return json.Marshal(tmp)
}

// UnmarshalJSON APIからの戻り値でレスポンスボディ直下にデータを持つことへの対応
func (s *archiveShareResponseEnvelope) UnmarshalJSON(data []byte) error {
	type alias archiveShareResponseEnvelope

	var tmp alias
	if err := json.Unmarshal(data, &tmp); err != nil {
		return err
	}

	var nakedData naked.ArchiveShareInfo
	if err := json.Unmarshal(data, &nakedData); err != nil {
		return err
	}
	tmp.ArchiveShareInfo = &nakedData

	*s = archiveShareResponseEnvelope(tmp)
	return nil
}
<commit_msg>Added search parameter for edb<commit_after>// Copyright 2016-2021 The Libsacloud Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package sacloud

import (
	"encoding/json"

	"github.com/sacloud/libsacloud/v2/sacloud/naked"
	"github.com/sacloud/libsacloud/v2/sacloud/search"
)

// UnmarshalJSON APIからの戻り値でレスポンスボディ直下にデータを持つことへの対応
func (a *authStatusReadResponseEnvelope) UnmarshalJSON(data []byte) error {
	type alias authStatusReadResponseEnvelope

	var tmp alias
	if err := json.Unmarshal(data, &tmp); err != nil {
		return err
	}

	var nakedAuthStatus naked.AuthStatus
	if err := json.Unmarshal(data, &nakedAuthStatus); err != nil {
		return err
	}
	tmp.AuthStatus = &nakedAuthStatus

	*a = authStatusReadResponseEnvelope(tmp)
	return nil
}

func (b *billDetailsCSVResponseEnvelope) UnmarshalJSON(data []byte) error {
	type alias billDetailsCSVResponseEnvelope

	var tmp alias
	if err := json.Unmarshal(data, &tmp); err != nil {
		return err
	}

	var nakedBillDetailCSV naked.BillDetailCSV
	if err := json.Unmarshal(data, &nakedBillDetailCSV); err != nil {
		return err
	}
	tmp.CSV = &nakedBillDetailCSV

	*b = billDetailsCSVResponseEnvelope(tmp)
	return nil
}

func (m *mobileGatewaySetSIMRoutesRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias struct {
		SIMRoutes []*naked.MobileGatewaySIMRoute `json:"sim_routes"`
	}
	tmp := &alias{
		SIMRoutes: m.SIMRoutes,
	}
	if len(tmp.SIMRoutes) == 0 {
		tmp.SIMRoutes = make([]*naked.MobileGatewaySIMRoute, 0)
	}
	return json.Marshal(tmp)
}

// UnmarshalJSON APIからの戻り値でレスポンスボディ直下にデータを持つことへの対応
func (s *serverGetVNCProxyResponseEnvelope) UnmarshalJSON(data []byte) error {
	type alias serverGetVNCProxyResponseEnvelope

	var tmp alias
	if err := json.Unmarshal(data, &tmp); err != nil {
		return err
	}

	var nakedVNCProxy naked.VNCProxyInfo
	if err := json.Unmarshal(data, &nakedVNCProxy); err != nil {
		return err
	}
	tmp.VNCProxyInfo = &nakedVNCProxy

	*s = serverGetVNCProxyResponseEnvelope(tmp)
	return nil
}

/*
 * 検索時に固定パラメータを設定するための実装
 */

func (s autoBackupFindRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias autoBackupFindRequestEnvelope
	tmp := alias(s)
	if tmp.Filter == nil {
		tmp.Filter = search.Filter{}
	}
	tmp.Filter[search.Key("Provider.Class")] = "autobackup"
	return json.Marshal(tmp)
}

func (s containerRegistryFindRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias containerRegistryFindRequestEnvelope
	tmp := alias(s)
	if tmp.Filter == nil {
		tmp.Filter = search.Filter{}
	}
	tmp.Filter[search.Key("Provider.Class")] = "containerregistry"
	return json.Marshal(tmp)
}

func (s eSMEFindRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias eSMEFindRequestEnvelope
	tmp := alias(s)
	if tmp.Filter == nil {
		tmp.Filter = search.Filter{}
	}
	tmp.Filter[search.Key("Provider.Class")] = "esme"
	return json.Marshal(tmp)
}

func (s dNSFindRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias dNSFindRequestEnvelope
	tmp := alias(s)
	if tmp.Filter == nil {
		tmp.Filter = search.Filter{}
	}
	tmp.Filter[search.Key("Provider.Class")] = "dns"
	return json.Marshal(tmp)
}

func (s simpleMonitorFindRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias simpleMonitorFindRequestEnvelope
	tmp := alias(s)
	if tmp.Filter == nil {
		tmp.Filter = search.Filter{}
	}
	tmp.Filter[search.Key("Provider.Class")] = "simplemon"
	return json.Marshal(tmp)
}

func (s gSLBFindRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias gSLBFindRequestEnvelope
	tmp := alias(s)
	if tmp.Filter == nil {
		tmp.Filter = search.Filter{}
	}
	tmp.Filter[search.Key("Provider.Class")] = "gslb"
	return json.Marshal(tmp)
}

func (s proxyLBFindRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias proxyLBFindRequestEnvelope
	tmp := alias(s)
	if tmp.Filter == nil {
		tmp.Filter = search.Filter{}
	}
	tmp.Filter[search.Key("Provider.Class")] = "proxylb"
	return json.Marshal(tmp)
}

func (s sIMFindRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias sIMFindRequestEnvelope
	tmp := alias(s)
	if tmp.Filter == nil {
		tmp.Filter = search.Filter{}
	}
	tmp.Filter[search.Key("Provider.Class")] = "sim"
	return json.Marshal(tmp)
}

func (s localRouterFindRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias localRouterFindRequestEnvelope
	tmp := alias(s)
	if tmp.Filter == nil {
		tmp.Filter = search.Filter{}
	}
	tmp.Filter[search.Key("Provider.Class")] = "localrouter"
	return json.Marshal(tmp)
}

func (s enhancedDBFindRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias enhancedDBFindRequestEnvelope
	tmp := alias(s)
	if tmp.Filter == nil {
		tmp.Filter = search.Filter{}
	}
	tmp.Filter[search.Key("Provider.Class")] = "enhanceddb"
	return json.Marshal(tmp)
}

func (s databaseFindRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias databaseFindRequestEnvelope
	tmp := alias(s)
	if tmp.Filter == nil {
		tmp.Filter = search.Filter{}
	}
	tmp.Filter[search.Key("Class")] = "database"
	return json.Marshal(tmp)
}

func (s loadBalancerFindRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias loadBalancerFindRequestEnvelope
	tmp := alias(s)
	if tmp.Filter == nil {
		tmp.Filter = search.Filter{}
	}
	tmp.Filter[search.Key("Class")] = "loadbalancer"
	return json.Marshal(tmp)
}

func (s vPCRouterFindRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias vPCRouterFindRequestEnvelope
	tmp := alias(s)
	if tmp.Filter == nil {
		tmp.Filter = search.Filter{}
	}
	tmp.Filter[search.Key("Class")] = "vpcrouter"
	return json.Marshal(tmp)
}

func (s nFSFindRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias nFSFindRequestEnvelope
	tmp := alias(s)
	if tmp.Filter == nil {
		tmp.Filter = search.Filter{}
	}
	tmp.Filter[search.Key("Class")] = "nfs"
	return json.Marshal(tmp)
}

func (s mobileGatewayFindRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias mobileGatewayFindRequestEnvelope
	tmp := alias(s)
	if tmp.Filter == nil {
		tmp.Filter = search.Filter{}
	}
	tmp.Filter[search.Key("Class")] = "mobilegateway"
	return json.Marshal(tmp)
}

/*
 * for Shared Archive
 */

func (s archiveShareRequestEnvelope) MarshalJSON() ([]byte, error) {
	type alias archiveShareRequestEnvelope
	tmp := alias(s)
	tmp.Shared = true
	return json.Marshal(tmp)
}

// UnmarshalJSON APIからの戻り値でレスポンスボディ直下にデータを持つことへの対応
func (s *archiveShareResponseEnvelope) UnmarshalJSON(data []byte) error {
	type alias archiveShareResponseEnvelope

	var tmp alias
	if err := json.Unmarshal(data, &tmp); err != nil {
		return err
	}

	var nakedData naked.ArchiveShareInfo
	if err := json.Unmarshal(data, &nakedData); err != nil {
		return err
	}
	tmp.ArchiveShareInfo = &nakedData

	*s = archiveShareResponseEnvelope(tmp)
	return nil
}
<|endoftext|>


<commit_before>package geojson

import (
	_"fmt"
	"github.com/dhconnelly/rtreego"
	"github.com/jeffail/gabs"
	"io/ioutil"
)

// See also
// https://github.com/dhconnelly/rtreego#storing-updating-and-deleting-objects

type WOFBounds struct {
     where *rtreego.Rect
     Id int
     Placetype string
}

func (b WOFBounds) Bounds() *rtreego.Rect {
     return b.where
}

/*
Something like this using "github.com/paulmach/go.geojson" seems
like it would be a good thing but I don't think I have the stamina
to figure out how to parse the properties separately right now...
(20151005/thisisaaronland)
/*

type WOFProperties struct {
     Raw    []byte
     Parsed *gabs.Container
}

type WOFFeature struct {
     ID          json.Number            `json:"id,omitempty"`
     Type        string                 `json:"type"`
     BoundingBox []float64              `json:"bbox,omitempty"`	// maybe make this a WOFBounds (rtree) like properties?
     Geometry    *gj.Geometry      `json:"geometry"`
     Properties  WOFProperties			`json:"properties"`
     // Properties  map[string]interface{} `json:"properties"`
     CRS         map[string]interface{} `json:"crs,omitempty"` // Coordinate Reference System Objects are not currently supported
}
*/

type WOFFeature struct {
	Raw    []byte
	Parsed *gabs.Container
}

func (wof WOFFeature) Body() *gabs.Container {
	return wof.Parsed
}

func (wof WOFFeature) Dumps() string {
	return wof.Parsed.String()
}

func (wof WOFFeature) Id() int {

	body := wof.Body()

	var flid float64
	flid = body.Path("properties.wof:id").Data().(float64)

	id := int(flid)
	return id
}

// Should return a full-on WOFPlacetype object thing-y
// (20151012/thisisaaronland)

func (wof WOFFeature) Placetype() string {

	body := wof.Body()

	var placetype string
	placetype = body.Path("properties.wof:placetype").Data().(string)

	return placetype
}

// See notes above in WOFFeature.BoundingBox - for now this will do...
// (20151012/thisisaaronland)

func (wof WOFFeature) Bounds() (*WOFBounds, error) {

	id := wof.Id()
	placetype = wof.Placetype()

	body := wof.Body()

	var swlon float64
	var swlat float64
	var nelon float64
	var nelat float64

	children, _ := body.S("bbox").Children()

	swlon = children[0].Data().(float64)
	swlat = children[1].Data().(float64)
	nelon = children[2].Data().(float64)
	nelat = children[3].Data().(float64)

	llat := nelat - swlat
	llon := nelon - swlon

	// fmt.Printf("%f - %f = %f\n", nelat, swlat, llat)
	// fmt.Printf("%f - %f = %f\n", nelon, swlon, llon)

	pt := rtreego.Point{swlon, swlat}
	rect, err := rtreego.NewRect(pt, []float64{llon, llat})

	if err != nil {
		return nil, err
	}

	return &WOFBounds{rect, id, placetype}, nil
}

func UnmarshalFile(path string) (*WOFFeature, error) {

	body, read_err := ioutil.ReadFile(path)

	if read_err != nil {
		return nil, read_err
	}

	return UnmarshalFeature(body)
}

func UnmarshalFeature(raw []byte) (*WOFFeature, error) {

	parsed, parse_err := gabs.ParseJSON(raw)

	if parse_err != nil {
		return nil, parse_err
	}

	rsp := WOFFeature{
		Raw:    raw,
		Parsed: parsed,
	}

	return &rsp, nil
}
<commit_msg>go is fussy<commit_after>package geojson

import (
	_"fmt"
	"github.com/dhconnelly/rtreego"
	"github.com/jeffail/gabs"
	"io/ioutil"
)

// See also
// https://github.com/dhconnelly/rtreego#storing-updating-and-deleting-objects

type WOFBounds struct {
     where *rtreego.Rect
     Id int
     Placetype string
}

func (b WOFBounds) Bounds() *rtreego.Rect {
     return b.where
}

/*
Something like this using "github.com/paulmach/go.geojson" seems
like it would be a good thing but I don't think I have the stamina
to figure out how to parse the properties separately right now...
(20151005/thisisaaronland)
/*

type WOFProperties struct {
     Raw    []byte
     Parsed *gabs.Container
}

type WOFFeature struct {
     ID          json.Number            `json:"id,omitempty"`
     Type        string                 `json:"type"`
     BoundingBox []float64              `json:"bbox,omitempty"`	// maybe make this a WOFBounds (rtree) like properties?
     Geometry    *gj.Geometry      `json:"geometry"`
     Properties  WOFProperties			`json:"properties"`
     // Properties  map[string]interface{} `json:"properties"`
     CRS         map[string]interface{} `json:"crs,omitempty"` // Coordinate Reference System Objects are not currently supported
}
*/

type WOFFeature struct {
	Raw    []byte
	Parsed *gabs.Container
}

func (wof WOFFeature) Body() *gabs.Container {
	return wof.Parsed
}

func (wof WOFFeature) Dumps() string {
	return wof.Parsed.String()
}

func (wof WOFFeature) Id() int {

	body := wof.Body()

	var flid float64
	flid = body.Path("properties.wof:id").Data().(float64)

	id := int(flid)
	return id
}

// Should return a full-on WOFPlacetype object thing-y
// (20151012/thisisaaronland)

func (wof WOFFeature) Placetype() string {

	body := wof.Body()

	var placetype string
	placetype = body.Path("properties.wof:placetype").Data().(string)

	return placetype
}

// See notes above in WOFFeature.BoundingBox - for now this will do...
// (20151012/thisisaaronland)

func (wof WOFFeature) Bounds() (*WOFBounds, error) {

	id := wof.Id()
	placetype := wof.Placetype()

	body := wof.Body()

	var swlon float64
	var swlat float64
	var nelon float64
	var nelat float64

	children, _ := body.S("bbox").Children()

	swlon = children[0].Data().(float64)
	swlat = children[1].Data().(float64)
	nelon = children[2].Data().(float64)
	nelat = children[3].Data().(float64)

	llat := nelat - swlat
	llon := nelon - swlon

	// fmt.Printf("%f - %f = %f\n", nelat, swlat, llat)
	// fmt.Printf("%f - %f = %f\n", nelon, swlon, llon)

	pt := rtreego.Point{swlon, swlat}
	rect, err := rtreego.NewRect(pt, []float64{llon, llat})

	if err != nil {
		return nil, err
	}

	return &WOFBounds{rect, id, placetype}, nil
}

func UnmarshalFile(path string) (*WOFFeature, error) {

	body, read_err := ioutil.ReadFile(path)

	if read_err != nil {
		return nil, read_err
	}

	return UnmarshalFeature(body)
}

func UnmarshalFeature(raw []byte) (*WOFFeature, error) {

	parsed, parse_err := gabs.ParseJSON(raw)

	if parse_err != nil {
		return nil, parse_err
	}

	rsp := WOFFeature{
		Raw:    raw,
		Parsed: parsed,
	}

	return &rsp, nil
}
<|endoftext|>


<commit_before>package vollocal_test

import (
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"code.cloudfoundry.org/clock/fakeclock"
	"code.cloudfoundry.org/lager/lagertest"

	"code.cloudfoundry.org/clock"
	"code.cloudfoundry.org/voldriver"
	"code.cloudfoundry.org/voldriver/voldriverfakes"
	"code.cloudfoundry.org/volman/vollocal"
	"code.cloudfoundry.org/volman/volmanfakes"
	"github.com/tedsuo/ifrit"
	"github.com/tedsuo/ifrit/ginkgomon"
)

var _ = Describe("Driver Syncer", func() {
	var (
		logger *lagertest.TestLogger

		scanInterval time.Duration

		fakeClock         *fakeclock.FakeClock
		fakeDriverFactory *volmanfakes.FakeDriverFactory

		registry vollocal.DriverRegistry
		syncer   vollocal.DriverSyncer
		process  ifrit.Process

		fakeDriver *voldriverfakes.FakeDriver

		driverName string
	)

	BeforeEach(func() {
		logger = lagertest.NewTestLogger("driver-syncer-test")

		fakeClock = fakeclock.NewFakeClock(time.Unix(123, 456))
		fakeDriverFactory = new(volmanfakes.FakeDriverFactory)

		scanInterval = 10 * time.Second

		registry = vollocal.NewDriverRegistry()
		syncer = vollocal.NewDriverSyncerWithDriverFactory(logger, registry, []string{defaultPluginsDirectory}, scanInterval, fakeClock, fakeDriverFactory)

		fakeDriver = new(voldriverfakes.FakeDriver)
		fakeDriver.ActivateReturns(voldriver.ActivateResponse{
			Implements: []string{"VolumeDriver"},
		})

		fakeDriverFactory.DriverReturns(fakeDriver, nil)

		driverName = "some-driver-name"
	})

	Describe("#Runner", func() {
		It("has a non-nil runner", func() {
			Expect(syncer.Runner()).NotTo(BeNil())
		})

		It("has a non-nil and empty driver registry", func() {
			Expect(registry).NotTo(BeNil())
			Expect(len(registry.Drivers())).To(Equal(0))
		})
	})

	Describe("#Run", func() {
		Context("when there are no drivers", func() {
			It("should have no drivers in registry map", func() {
				drivers := registry.Drivers()
				Expect(len(drivers)).To(Equal(0))
				Expect(fakeDriverFactory.DriverCallCount()).To(Equal(0))
			})
		})

		Context("when there are drivers", func() {
			var (
				fakeDriver *voldriverfakes.FakeDriver
				driverName string
				syncer     vollocal.DriverSyncer
			)

			BeforeEach(func() {
				driverName = "fakedriver"
				err := voldriver.WriteDriverSpec(logger, defaultPluginsDirectory, driverName, "spec", []byte("http://0.0.0.0:8080"))
				Expect(err).NotTo(HaveOccurred())

				syncer = vollocal.NewDriverSyncerWithDriverFactory(logger, registry, []string{defaultPluginsDirectory}, scanInterval, fakeClock, fakeDriverFactory)

				fakeDriver = new(voldriverfakes.FakeDriver)
				fakeDriver.ActivateReturns(voldriver.ActivateResponse{
					Implements: []string{"VolumeDriver"},
				})

				fakeDriverFactory.DriverReturns(fakeDriver, nil)

				process = ginkgomon.Invoke(syncer.Runner())
			})

			AfterEach(func() {
				ginkgomon.Kill(process)
			})

			It("should have fake driver in registry map", func() {
				drivers := registry.Drivers()
				Expect(len(drivers)).To(Equal(1))
				Expect(fakeDriverFactory.DriverCallCount()).To(Equal(1))
				Expect(fakeDriver.ActivateCallCount()).To(Equal(1))
			})

			Context("when drivers are added", func() {
				BeforeEach(func() {
					err := voldriver.WriteDriverSpec(logger, defaultPluginsDirectory, "anotherfakedriver", "spec", []byte("http://0.0.0.0:8080"))
					Expect(err).NotTo(HaveOccurred())
				})

				It("should find them!", func() {
					fakeClock.Increment(scanInterval * 2)
					Eventually(registry.Drivers).Should(HaveLen(2))
					Expect(fakeDriverFactory.DriverCallCount()).To(Equal(3))
					Expect(fakeDriver.ActivateCallCount()).To(Equal(3))
				})
			})
			Context("when drivers are not responding", func() {
				BeforeEach(func() {
					fakeDriver.ActivateReturns(voldriver.ActivateResponse{
						Err: "some err",
					})
				})

				It("should find no drivers", func() {
					fakeClock.Increment(scanInterval * 2)
					Eventually(registry.Drivers).Should(HaveLen(0))
				})
			})
		})

	})

	Describe("#Discover", func() {
		Context("when given driverspath with no drivers", func() {
			It("no drivers are found", func() {
				drivers, err := syncer.Discover(logger)
				Expect(err).ToNot(HaveOccurred())
				Expect(len(drivers)).To(Equal(0))
			})
		})

		Context("with a single driver", func() {
			BeforeEach(func() {
				err := voldriver.WriteDriverSpec(logger, defaultPluginsDirectory, driverName, "spec", []byte("http://0.0.0.0:8080"))
				Expect(err).NotTo(HaveOccurred())
			})

			It("should not find drivers that are unresponsive", func() {
				fakeDriver.ActivateReturns(voldriver.ActivateResponse{Err: "Error"})
				drivers, err := syncer.Discover(logger)
				Expect(err).ToNot(HaveOccurred())
				Expect(len(drivers)).To(Equal(0))
				Expect(fakeDriverFactory.DriverCallCount()).To(Equal(1))
			})

			It("should find drivers", func() {
				drivers, err := syncer.Discover(logger)
				Expect(err).ToNot(HaveOccurred())
				Expect(len(drivers)).To(Equal(1))
				Expect(fakeDriverFactory.DriverCallCount()).To(Equal(1))
			})
		})

		Context("when given a simple driverspath", func() {
			Context("with hetergeneous driver specifications", func() {
				BeforeEach(func() {
					err := voldriver.WriteDriverSpec(logger, defaultPluginsDirectory, driverName, "json", []byte("{\"Addr\":\"http://0.0.0.0:8080\"}"))
					Expect(err).NotTo(HaveOccurred())
					err = voldriver.WriteDriverSpec(logger, defaultPluginsDirectory, driverName, "spec", []byte("http://0.0.0.0:9090"))
					Expect(err).NotTo(HaveOccurred())
				})

				It("should preferentially select spec over json specification", func() {
					drivers, err := syncer.Discover(logger)
					Expect(err).ToNot(HaveOccurred())
					Expect(len(drivers)).To(Equal(1))
					_, _, _, specFileName, _ := fakeDriverFactory.DriverArgsForCall(0)
					Expect(specFileName).To(Equal(driverName + ".spec"))
				})
			})
		})

		Context("when given a compound driverspath", func() {
			BeforeEach(func() {
				syncer = vollocal.NewDriverSyncerWithDriverFactory(logger, registry, []string{defaultPluginsDirectory, secondPluginsDirectory}, scanInterval, fakeClock, fakeDriverFactory)
			})

			Context("with a single driver", func() {
				BeforeEach(func() {
					err := voldriver.WriteDriverSpec(logger, secondPluginsDirectory, driverName, "spec", []byte("http://0.0.0.0:8080"))
					Expect(err).NotTo(HaveOccurred())
				})

				It("should find drivers", func() {
					drivers, err := syncer.Discover(logger)
					Expect(err).ToNot(HaveOccurred())
					Expect(len(drivers)).To(Equal(1))
					Expect(fakeDriverFactory.DriverCallCount()).To(Equal(1))
				})

			})

			Context("with multiple drivers in multiple directories", func() {
				BeforeEach(func() {
					err := voldriver.WriteDriverSpec(logger, defaultPluginsDirectory, driverName, "json", []byte("{\"Addr\":\"http://0.0.0.0:8080\"}"))
					Expect(err).NotTo(HaveOccurred())
					err = voldriver.WriteDriverSpec(logger, secondPluginsDirectory, "some-other-driver-name", "json", []byte("{\"Addr\":\"http://0.0.0.0:9090\"}"))
					Expect(err).NotTo(HaveOccurred())
				})

				It("should find both drivers", func() {
					drivers, err := syncer.Discover(logger)
					Expect(err).ToNot(HaveOccurred())
					Expect(len(drivers)).To(Equal(2))
				})
			})

			Context("with the same driver but in multiple directories", func() {
				BeforeEach(func() {
					err := voldriver.WriteDriverSpec(logger, defaultPluginsDirectory, driverName, "json", []byte("{\"Addr\":\"http://0.0.0.0:8080\"}"))
					Expect(err).NotTo(HaveOccurred())
					err = voldriver.WriteDriverSpec(logger, secondPluginsDirectory, driverName, "spec", []byte("http://0.0.0.0:9090"))
					Expect(err).NotTo(HaveOccurred())
				})

				It("should preferentially select the driver in the first directory", func() {
					_, err := syncer.Discover(logger)
					Expect(err).ToNot(HaveOccurred())
					_, _, _, specFileName, _ := fakeDriverFactory.DriverArgsForCall(0)
					Expect(specFileName).To(Equal(driverName + ".json"))
				})
			})
		})

		Context("when given a driver spec not in canonical form", func() {
			var (
				fakeRemoteClientFactory *voldriverfakes.FakeRemoteClientFactory
				driverFactory           vollocal.DriverFactory
				fakeDriver              *voldriverfakes.FakeDriver
				driverSyncer            vollocal.DriverSyncer
			)

			JustBeforeEach(func() {
				fakeRemoteClientFactory = new(voldriverfakes.FakeRemoteClientFactory)
				driverFactory = vollocal.NewDriverFactoryWithRemoteClientFactory(fakeRemoteClientFactory)
				driverSyncer = vollocal.NewDriverSyncerWithDriverFactory(logger, nil, []string{defaultPluginsDirectory}, time.Second*60, clock.NewClock(), driverFactory)
			})

			TestCanonicalization := func(context, actual, it, expected string) {
				Context(context, func() {
					BeforeEach(func() {
						err := voldriver.WriteDriverSpec(logger, defaultPluginsDirectory, driverName, "spec", []byte(actual))
						Expect(err).NotTo(HaveOccurred())
					})

					JustBeforeEach(func() {
						fakeDriver = new(voldriverfakes.FakeDriver)
						fakeDriver.ActivateReturns(voldriver.ActivateResponse{
							Implements: []string{"VolumeDriver"},
						})

						fakeRemoteClientFactory.NewRemoteClientReturns(fakeDriver, nil)
					})

					It(it, func() {
						drivers, err := driverSyncer.Discover(logger)
						Expect(err).ToNot(HaveOccurred())
						Expect(len(drivers)).To(Equal(1))
						Expect(fakeRemoteClientFactory.NewRemoteClientCallCount()).To(Equal(1))
						Expect(fakeRemoteClientFactory.NewRemoteClientArgsForCall(0)).To(Equal(expected))
					})
				})
			}

			TestCanonicalization("with an ip (and no port)", "127.0.0.1", "should return a canonicalized address", "http://127.0.0.1")
			TestCanonicalization("with an ip and port", "127.0.0.1:8080", "should return a canonicalized address", "http://127.0.0.1:8080")
			TestCanonicalization("with a tcp protocol uri with port", "tcp://127.0.0.1:8080", "should return a canonicalized address", "http://127.0.0.1:8080")
			TestCanonicalization("with a tcp protocol uri without port", "tcp://127.0.0.1", "should return a canonicalized address", "http://127.0.0.1")
			TestCanonicalization("with a unix address including protocol", "unix:///other.sock", "should return a canonicalized address", "unix:///other.sock")
			TestCanonicalization("with a unix address missing its protocol", "/other.sock", "should return a canonicalized address", "/other.sock")

			Context("with an invalid url", func() {
				BeforeEach(func() {
					err := voldriver.WriteDriverSpec(logger, defaultPluginsDirectory, driverName, "spec", []byte("htt%p:\\\\"))
					Expect(err).NotTo(HaveOccurred())
				})

				It("doesn't make a driver", func() {
					_, err := driverSyncer.Discover(logger)
					Expect(err).NotTo(HaveOccurred())
					Expect(fakeRemoteClientFactory.NewRemoteClientCallCount()).To(Equal(0))
				})
			})
		})

		Context("when given a driver spec with a bad driver", func() {
			BeforeEach(func() {
				err := voldriver.WriteDriverSpec(logger, defaultPluginsDirectory, driverName, "spec", []byte("127.0.0.1:8080"))
				Expect(err).NotTo(HaveOccurred())
			})

			It("should return no drivers if the driver doesn't implement VolumeDriver", func() {
				fakeDriver.ActivateReturns(voldriver.ActivateResponse{
					Implements: []string{"something-else"},
				})

				drivers, err := syncer.Discover(logger)
				Expect(err).ToNot(HaveOccurred())
				Expect(len(drivers)).To(Equal(0))
			})

			It("should return no drivers if the driver doesn't respond", func() {
				fakeDriver.ActivateReturns(voldriver.ActivateResponse{
					Err: "some-error",
				})

				drivers, err := syncer.Discover(logger)
				Expect(err).ToNot(HaveOccurred())
				Expect(len(drivers)).To(Equal(0))
			})
		})
	})
})
<commit_msg>fix volman units to reflect new golang 1.8 behavior for url.Parse<commit_after>package vollocal_test

import (
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"code.cloudfoundry.org/clock/fakeclock"
	"code.cloudfoundry.org/lager/lagertest"

	"code.cloudfoundry.org/clock"
	"code.cloudfoundry.org/voldriver"
	"code.cloudfoundry.org/voldriver/voldriverfakes"
	"code.cloudfoundry.org/volman/vollocal"
	"code.cloudfoundry.org/volman/volmanfakes"
	"github.com/tedsuo/ifrit"
	"github.com/tedsuo/ifrit/ginkgomon"
)

var _ = Describe("Driver Syncer", func() {
	var (
		logger *lagertest.TestLogger

		scanInterval time.Duration

		fakeClock         *fakeclock.FakeClock
		fakeDriverFactory *volmanfakes.FakeDriverFactory

		registry vollocal.DriverRegistry
		syncer   vollocal.DriverSyncer
		process  ifrit.Process

		fakeDriver *voldriverfakes.FakeDriver

		driverName string
	)

	BeforeEach(func() {
		logger = lagertest.NewTestLogger("driver-syncer-test")

		fakeClock = fakeclock.NewFakeClock(time.Unix(123, 456))
		fakeDriverFactory = new(volmanfakes.FakeDriverFactory)

		scanInterval = 10 * time.Second

		registry = vollocal.NewDriverRegistry()
		syncer = vollocal.NewDriverSyncerWithDriverFactory(logger, registry, []string{defaultPluginsDirectory}, scanInterval, fakeClock, fakeDriverFactory)

		fakeDriver = new(voldriverfakes.FakeDriver)
		fakeDriver.ActivateReturns(voldriver.ActivateResponse{
			Implements: []string{"VolumeDriver"},
		})

		fakeDriverFactory.DriverReturns(fakeDriver, nil)

		driverName = "some-driver-name"
	})

	Describe("#Runner", func() {
		It("has a non-nil runner", func() {
			Expect(syncer.Runner()).NotTo(BeNil())
		})

		It("has a non-nil and empty driver registry", func() {
			Expect(registry).NotTo(BeNil())
			Expect(len(registry.Drivers())).To(Equal(0))
		})
	})

	Describe("#Run", func() {
		Context("when there are no drivers", func() {
			It("should have no drivers in registry map", func() {
				drivers := registry.Drivers()
				Expect(len(drivers)).To(Equal(0))
				Expect(fakeDriverFactory.DriverCallCount()).To(Equal(0))
			})
		})

		Context("when there are drivers", func() {
			var (
				fakeDriver *voldriverfakes.FakeDriver
				driverName string
				syncer     vollocal.DriverSyncer
			)

			BeforeEach(func() {
				driverName = "fakedriver"
				err := voldriver.WriteDriverSpec(logger, defaultPluginsDirectory, driverName, "spec", []byte("http://0.0.0.0:8080"))
				Expect(err).NotTo(HaveOccurred())

				syncer = vollocal.NewDriverSyncerWithDriverFactory(logger, registry, []string{defaultPluginsDirectory}, scanInterval, fakeClock, fakeDriverFactory)

				fakeDriver = new(voldriverfakes.FakeDriver)
				fakeDriver.ActivateReturns(voldriver.ActivateResponse{
					Implements: []string{"VolumeDriver"},
				})

				fakeDriverFactory.DriverReturns(fakeDriver, nil)

				process = ginkgomon.Invoke(syncer.Runner())
			})

			AfterEach(func() {
				ginkgomon.Kill(process)
			})

			It("should have fake driver in registry map", func() {
				drivers := registry.Drivers()
				Expect(len(drivers)).To(Equal(1))
				Expect(fakeDriverFactory.DriverCallCount()).To(Equal(1))
				Expect(fakeDriver.ActivateCallCount()).To(Equal(1))
			})

			Context("when drivers are added", func() {
				BeforeEach(func() {
					err := voldriver.WriteDriverSpec(logger, defaultPluginsDirectory, "anotherfakedriver", "spec", []byte("http://0.0.0.0:8080"))
					Expect(err).NotTo(HaveOccurred())
				})

				It("should find them!", func() {
					fakeClock.Increment(scanInterval * 2)
					Eventually(registry.Drivers).Should(HaveLen(2))
					Expect(fakeDriverFactory.DriverCallCount()).To(Equal(3))
					Expect(fakeDriver.ActivateCallCount()).To(Equal(3))
				})
			})
			Context("when drivers are not responding", func() {
				BeforeEach(func() {
					fakeDriver.ActivateReturns(voldriver.ActivateResponse{
						Err: "some err",
					})
				})

				It("should find no drivers", func() {
					fakeClock.Increment(scanInterval * 2)
					Eventually(registry.Drivers).Should(HaveLen(0))
				})
			})
		})

	})

	Describe("#Discover", func() {
		Context("when given driverspath with no drivers", func() {
			It("no drivers are found", func() {
				drivers, err := syncer.Discover(logger)
				Expect(err).ToNot(HaveOccurred())
				Expect(len(drivers)).To(Equal(0))
			})
		})

		Context("with a single driver", func() {
			BeforeEach(func() {
				err := voldriver.WriteDriverSpec(logger, defaultPluginsDirectory, driverName, "spec", []byte("http://0.0.0.0:8080"))
				Expect(err).NotTo(HaveOccurred())
			})

			It("should not find drivers that are unresponsive", func() {
				fakeDriver.ActivateReturns(voldriver.ActivateResponse{Err: "Error"})
				drivers, err := syncer.Discover(logger)
				Expect(err).ToNot(HaveOccurred())
				Expect(len(drivers)).To(Equal(0))
				Expect(fakeDriverFactory.DriverCallCount()).To(Equal(1))
			})

			It("should find drivers", func() {
				drivers, err := syncer.Discover(logger)
				Expect(err).ToNot(HaveOccurred())
				Expect(len(drivers)).To(Equal(1))
				Expect(fakeDriverFactory.DriverCallCount()).To(Equal(1))
			})
		})

		Context("when given a simple driverspath", func() {
			Context("with hetergeneous driver specifications", func() {
				BeforeEach(func() {
					err := voldriver.WriteDriverSpec(logger, defaultPluginsDirectory, driverName, "json", []byte("{\"Addr\":\"http://0.0.0.0:8080\"}"))
					Expect(err).NotTo(HaveOccurred())
					err = voldriver.WriteDriverSpec(logger, defaultPluginsDirectory, driverName, "spec", []byte("http://0.0.0.0:9090"))
					Expect(err).NotTo(HaveOccurred())
				})

				It("should preferentially select spec over json specification", func() {
					drivers, err := syncer.Discover(logger)
					Expect(err).ToNot(HaveOccurred())
					Expect(len(drivers)).To(Equal(1))
					_, _, _, specFileName, _ := fakeDriverFactory.DriverArgsForCall(0)
					Expect(specFileName).To(Equal(driverName + ".spec"))
				})
			})
		})

		Context("when given a compound driverspath", func() {
			BeforeEach(func() {
				syncer = vollocal.NewDriverSyncerWithDriverFactory(logger, registry, []string{defaultPluginsDirectory, secondPluginsDirectory}, scanInterval, fakeClock, fakeDriverFactory)
			})

			Context("with a single driver", func() {
				BeforeEach(func() {
					err := voldriver.WriteDriverSpec(logger, secondPluginsDirectory, driverName, "spec", []byte("http://0.0.0.0:8080"))
					Expect(err).NotTo(HaveOccurred())
				})

				It("should find drivers", func() {
					drivers, err := syncer.Discover(logger)
					Expect(err).ToNot(HaveOccurred())
					Expect(len(drivers)).To(Equal(1))
					Expect(fakeDriverFactory.DriverCallCount()).To(Equal(1))
				})

			})

			Context("with multiple drivers in multiple directories", func() {
				BeforeEach(func() {
					err := voldriver.WriteDriverSpec(logger, defaultPluginsDirectory, driverName, "json", []byte("{\"Addr\":\"http://0.0.0.0:8080\"}"))
					Expect(err).NotTo(HaveOccurred())
					err = voldriver.WriteDriverSpec(logger, secondPluginsDirectory, "some-other-driver-name", "json", []byte("{\"Addr\":\"http://0.0.0.0:9090\"}"))
					Expect(err).NotTo(HaveOccurred())
				})

				It("should find both drivers", func() {
					drivers, err := syncer.Discover(logger)
					Expect(err).ToNot(HaveOccurred())
					Expect(len(drivers)).To(Equal(2))
				})
			})

			Context("with the same driver but in multiple directories", func() {
				BeforeEach(func() {
					err := voldriver.WriteDriverSpec(logger, defaultPluginsDirectory, driverName, "json", []byte("{\"Addr\":\"http://0.0.0.0:8080\"}"))
					Expect(err).NotTo(HaveOccurred())
					err = voldriver.WriteDriverSpec(logger, secondPluginsDirectory, driverName, "spec", []byte("http://0.0.0.0:9090"))
					Expect(err).NotTo(HaveOccurred())
				})

				It("should preferentially select the driver in the first directory", func() {
					_, err := syncer.Discover(logger)
					Expect(err).ToNot(HaveOccurred())
					_, _, _, specFileName, _ := fakeDriverFactory.DriverArgsForCall(0)
					Expect(specFileName).To(Equal(driverName + ".json"))
				})
			})
		})

		Context("when given a driver spec not in canonical form", func() {
			var (
				fakeRemoteClientFactory *voldriverfakes.FakeRemoteClientFactory
				driverFactory           vollocal.DriverFactory
				fakeDriver              *voldriverfakes.FakeDriver
				driverSyncer            vollocal.DriverSyncer
			)

			JustBeforeEach(func() {
				fakeRemoteClientFactory = new(voldriverfakes.FakeRemoteClientFactory)
				driverFactory = vollocal.NewDriverFactoryWithRemoteClientFactory(fakeRemoteClientFactory)
				driverSyncer = vollocal.NewDriverSyncerWithDriverFactory(logger, nil, []string{defaultPluginsDirectory}, time.Second*60, clock.NewClock(), driverFactory)
			})

			TestCanonicalization := func(context, actual, it, expected string) {
				Context(context, func() {
					BeforeEach(func() {
						err := voldriver.WriteDriverSpec(logger, defaultPluginsDirectory, driverName, "spec", []byte(actual))
						Expect(err).NotTo(HaveOccurred())
					})

					JustBeforeEach(func() {
						fakeDriver = new(voldriverfakes.FakeDriver)
						fakeDriver.ActivateReturns(voldriver.ActivateResponse{
							Implements: []string{"VolumeDriver"},
						})

						fakeRemoteClientFactory.NewRemoteClientReturns(fakeDriver, nil)
					})

					It(it, func() {
						drivers, err := driverSyncer.Discover(logger)
						Expect(err).ToNot(HaveOccurred())
						Expect(len(drivers)).To(Equal(1))
						Expect(fakeRemoteClientFactory.NewRemoteClientCallCount()).To(Equal(1))
						Expect(fakeRemoteClientFactory.NewRemoteClientArgsForCall(0)).To(Equal(expected))
					})
				})
			}

			TestCanonicalization("with an ip (and no port)", "127.0.0.1", "should return a canonicalized address", "http://127.0.0.1")
			TestCanonicalization("with a tcp protocol uri with port", "tcp://127.0.0.1:8080", "should return a canonicalized address", "http://127.0.0.1:8080")
			TestCanonicalization("with a tcp protocol uri without port", "tcp://127.0.0.1", "should return a canonicalized address", "http://127.0.0.1")
			TestCanonicalization("with a unix address including protocol", "unix:///other.sock", "should return a canonicalized address", "unix:///other.sock")
			TestCanonicalization("with a unix address missing its protocol", "/other.sock", "should return a canonicalized address", "/other.sock")

			Context("with an invalid url", func() {
				BeforeEach(func() {
					err := voldriver.WriteDriverSpec(logger, defaultPluginsDirectory, driverName+"2", "spec", []byte("127.0.0.1:8080"))
					err = voldriver.WriteDriverSpec(logger, defaultPluginsDirectory, driverName, "spec", []byte("htt%p:\\\\"))
					Expect(err).NotTo(HaveOccurred())
				})

				It("doesn't make a driver", func() {
					_, err := driverSyncer.Discover(logger)
					Expect(err).NotTo(HaveOccurred())
					Expect(fakeRemoteClientFactory.NewRemoteClientCallCount()).To(Equal(0))
				})
			})
		})

		Context("when given a driver spec with a bad driver", func() {
			BeforeEach(func() {
				err := voldriver.WriteDriverSpec(logger, defaultPluginsDirectory, driverName, "spec", []byte("127.0.0.1:8080"))
				Expect(err).NotTo(HaveOccurred())
			})

			It("should return no drivers if the driver doesn't implement VolumeDriver", func() {
				fakeDriver.ActivateReturns(voldriver.ActivateResponse{
					Implements: []string{"something-else"},
				})

				drivers, err := syncer.Discover(logger)
				Expect(err).ToNot(HaveOccurred())
				Expect(len(drivers)).To(Equal(0))
			})

			It("should return no drivers if the driver doesn't respond", func() {
				fakeDriver.ActivateReturns(voldriver.ActivateResponse{
					Err: "some-error",
				})

				drivers, err := syncer.Discover(logger)
				Expect(err).ToNot(HaveOccurred())
				Expect(len(drivers)).To(Equal(0))
			})
		})
	})
})
<|endoftext|>


<commit_before>// +build gotask

package main

import (
	"github.com/jingweno/gotask/tasking"
	"os"
	"runtime"
)

// NAME
//    cross-compile-all - cross-compiles gh for all supported platforms.
//
// DESCRIPTION
//    Cross-compiles gh for all supported platforms. Build artifacts will be in target/VERSION.
//    This only works on darwin with Vagrant setup.
func TaskCrossCompileAll(t *tasking.T) {
	t.Log("Removing build target...")
	err := os.RemoveAll("target")
	if err != nil {
		t.Errorf("Can't remove build target: %s\n", err)
		return
	}

	// for current
	t.Logf("Compiling for %s...\n", runtime.GOOS)
	TaskCrossCompile(t)
	if t.Failed() {
		return
	}

	// for linux
	t.Log("Compiling for linux...")
	t.Log("Downloading gh...")
	err = t.Exec("vagrant ssh -c 'rm -rf ~/gocode && go get github.com/jingweno/gh'")
	if err != nil {
		t.Errorf("Can't download gh on linux: %s\n", err)
		return
	}

	t.Log("Cross-compiling gh...")
	err = t.Exec("vagrant ssh -c 'cd ~/gocode/src/github.com/jingweno/gh && ./script/bootstrap && GOPATH=`godep path`:$GOPATH gotask cross-compile'")
	if err != nil {
		t.Errorf("Can't cross-compile gh on linux: %s\n", err)
		return
	}

	t.Log("Moving build artifacts...")
	err = t.Exec("vagrant ssh -c 'cp -R ~/gocode/src/github.com/jingweno/gh/target/* ~/target/'")
	if err != nil {
		t.Errorf("Can't cross-compile gh on linux: %s\n", err)
		return
	}
}

// NAME
//    cross-compile - cross-compiles gh for current platform.
//
// DESCRIPTION
//    Cross-compiles gh for current platform. Build artifacts will be in target/VERSION
func TaskCrossCompile(t *tasking.T) {
	t.Log("Updating goxc...")
	err := t.Exec("go get -u github.com/laher/goxc")
	if err != nil {
		t.Errorf("Can't update goxc: %s\n", err)
		return
	}

	t.Logf("Cross-compiling gh for %s...\n", runtime.GOOS)
	err = t.Exec("goxc", "-wd=.", "-os="+runtime.GOOS, "-c="+runtime.GOOS)
	if err != nil {
		t.Errorf("Can't cross-compile gh: %s\n", err)
		return
	}
}
<commit_msg>Download goxc instead of update<commit_after>// +build gotask

package main

import (
	"github.com/jingweno/gotask/tasking"
	"os"
	"runtime"
)

// NAME
//    cross-compile-all - cross-compiles gh for all supported platforms.
//
// DESCRIPTION
//    Cross-compiles gh for all supported platforms. Build artifacts will be in target/VERSION.
//    This only works on darwin with Vagrant setup.
func TaskCrossCompileAll(t *tasking.T) {
	t.Log("Removing build target...")
	err := os.RemoveAll("target")
	if err != nil {
		t.Errorf("Can't remove build target: %s\n", err)
		return
	}

	// for current
	t.Logf("Compiling for %s...\n", runtime.GOOS)
	TaskCrossCompile(t)
	if t.Failed() {
		return
	}

	// for linux
	t.Log("Compiling for linux...")
	t.Log("Downloading gh...")
	err = t.Exec("vagrant ssh -c 'rm -rf ~/gocode && go get github.com/jingweno/gh'")
	if err != nil {
		t.Errorf("Can't download gh on linux: %s\n", err)
		return
	}

	t.Log("Cross-compiling gh...")
	err = t.Exec("vagrant ssh -c 'cd ~/gocode/src/github.com/jingweno/gh && ./script/bootstrap && GOPATH=`godep path`:$GOPATH gotask cross-compile'")
	if err != nil {
		t.Errorf("Can't cross-compile gh on linux: %s\n", err)
		return
	}

	t.Log("Moving build artifacts...")
	err = t.Exec("vagrant ssh -c 'cp -R ~/gocode/src/github.com/jingweno/gh/target/* ~/target/'")
	if err != nil {
		t.Errorf("Can't cross-compile gh on linux: %s\n", err)
		return
	}
}

// NAME
//    cross-compile - cross-compiles gh for current platform.
//
// DESCRIPTION
//    Cross-compiles gh for current platform. Build artifacts will be in target/VERSION
func TaskCrossCompile(t *tasking.T) {
	t.Log("Updating goxc...")
	err := t.Exec("go get github.com/laher/goxc")
	if err != nil {
		t.Errorf("Can't update goxc: %s\n", err)
		return
	}

	t.Logf("Cross-compiling gh for %s...\n", runtime.GOOS)
	err = t.Exec("goxc", "-wd=.", "-os="+runtime.GOOS, "-c="+runtime.GOOS)
	if err != nil {
		t.Errorf("Can't cross-compile gh: %s\n", err)
		return
	}
}
<|endoftext|>


<commit_before>package git

import (
	"io"
	"net"
	"net/url"
)

type GitURL struct {
	Host     string
	Port     string
	RepoPath string
}

//covert git url string to a gitURL Stuct
func NewGitURL(addr string) *GitURL {
	gurl, err := url.Parse(addr)
	if err != nil {
		panic(err)
	}
	host, port, err := net.SplitHostPort(gurl.Host)
	if err != nil {
		port = "9418"
		host = gurl.Host
	}
	return &GitURL{
		Host:     host,
		Port:     port,
		RepoPath: gurl.Path,
	}
}

func getSupportCapabilities() []string {
	return []string{
		"multi_ack_detailed",
		"side-band-64k",
		"thin-pack",
		"ofs-delta",
		"agent=git/1.8.2",
	}
}

//parse variable-length integers
func ParseVarLen(r io.Reader) (len int64, err error) {
	b, err := ReadOneByte(r)
	if err != nil {
		return
	}
	var shift uint = 7
	len |= int64(b) & '\x7f'
	for IsMsbSet(b) {
		b, err = ReadOneByte(r)
		if err != nil {
			return
		}
		len |= (int64(b) & '\x7f') << shift
		shift += 7
	}
	return
}

//read only one byte from the Reader
func ReadOneByte(r io.Reader) (b byte, err error) {
	buf := make([]byte, 1)
	n, err := r.Read(buf)
	if err != nil {
		return
	}
	if n == 1 {
		b = buf[0]
	}
	return
}
<commit_msg>simple the capabilities<commit_after>package git

import (
	"io"
	"net"
	"net/url"
)

type GitURL struct {
	Host     string
	Port     string
	RepoPath string
}

//covert git url string to a gitURL Stuct
func NewGitURL(addr string) *GitURL {
	gurl, err := url.Parse(addr)
	if err != nil {
		panic(err)
	}
	host, port, err := net.SplitHostPort(gurl.Host)
	if err != nil {
		port = "9418"
		host = gurl.Host
	}
	return &GitURL{
		Host:     host,
		Port:     port,
		RepoPath: gurl.Path,
	}
}

func getSupportCapabilities() []string {
	return []string{
		"multi_ack_detailed",
		"side-band-64k",
		//"thin-pack",
		//"ofs-delta",
		"agent=git/2.3.2",
	}
}

//parse variable-length integers
func ParseVarLen(r io.Reader) (len int64, err error) {
	b, err := ReadOneByte(r)
	if err != nil {
		return
	}
	var shift uint = 7
	len |= int64(b) & '\x7f'
	for IsMsbSet(b) {
		b, err = ReadOneByte(r)
		if err != nil {
			return
		}
		len |= (int64(b) & '\x7f') << shift
		shift += 7
	}
	return
}

//read only one byte from the Reader
func ReadOneByte(r io.Reader) (b byte, err error) {
	buf := make([]byte, 1)
	n, err := r.Read(buf)
	if err != nil {
		return
	}
	if n == 1 {
		b = buf[0]
	}
	return
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"github.com/grafana/grafana/pkg/build/config"
	"github.com/grafana/grafana/pkg/build/droneutil"
	"github.com/urfave/cli/v2"
)

func GenerateVersions(c *cli.Context) error {
	var metadata config.Metadata
	version := ""
	if c.NArg() == 1 {
		version = strings.TrimPrefix(c.Args().Get(0), "v")
	} else {
		buildID, ok := os.LookupEnv("DRONE_BUILD_NUMBER")
		if !ok {
			return fmt.Errorf("unable to get DRONE_BUILD_NUMBER environmental variable")
		}
		var err error
		version, err = config.GetGrafanaVersion(buildID, ".")
		if err != nil {
			return err
		}
	}
	event, err := droneutil.GetDroneEventFromEnv()
	if err != nil {
		return err
	}

	var releaseMode config.ReleaseMode
	switch event {
	case string(config.PullRequestMode):
		releaseMode = config.ReleaseMode{Mode: config.PullRequestMode}
	case config.Push:
		mode, err := config.CheckDroneTargetBranch()
		if err != nil {
			return err
		}
		releaseMode = config.ReleaseMode{Mode: mode}
	case config.Custom:
		mode, err := config.CheckDroneTargetBranch()
		if err != nil {
			return err
		}
		// if there is a custom event targeting the main branch, that's an enterprise downstream build
		if mode == config.MainBranch {
			releaseMode = config.ReleaseMode{Mode: config.CustomMode}
		} else {
			releaseMode = config.ReleaseMode{Mode: mode}
		}
	case config.Tag, config.Promote:
		mode, err := config.CheckSemverSuffix()
		if err != nil {
			return err
		}
		releaseMode = mode
	}

	currentCommit, err := config.GetDroneCommit()
	if err != nil {
		return err
	}
	metadata = config.Metadata{
		GrafanaVersion: version,
		ReleaseMode:    releaseMode,
		GrabplVersion:  c.App.Version,
		CurrentCommit:  currentCommit,
	}

	fmt.Printf("building Grafana version: %s, release mode: %+v", metadata.GrafanaVersion, metadata.ReleaseMode)

	jsonMetadata, err := json.Marshal(&metadata)
	if err != nil {
		return fmt.Errorf("error marshalling metadata, %w", err)
	}

	const distDir = "dist"
	if err := os.RemoveAll(distDir); err != nil {
		return err
	}
	if err := os.Mkdir(distDir, 0750); err != nil {
		return err
	}

	// nolint:gosec
	if err := os.WriteFile(filepath.Join(distDir, "version.json"), jsonMetadata, 0664); err != nil {
		return err
	}

	return nil
}
<commit_msg>Check if dist dir exists (#54590)<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"github.com/grafana/grafana/pkg/build/config"
	"github.com/grafana/grafana/pkg/build/droneutil"
	"github.com/urfave/cli/v2"
)

func GenerateVersions(c *cli.Context) error {
	var metadata config.Metadata
	version := ""
	if c.NArg() == 1 {
		version = strings.TrimPrefix(c.Args().Get(0), "v")
	} else {
		buildID, ok := os.LookupEnv("DRONE_BUILD_NUMBER")
		if !ok {
			return fmt.Errorf("unable to get DRONE_BUILD_NUMBER environmental variable")
		}
		var err error
		version, err = config.GetGrafanaVersion(buildID, ".")
		if err != nil {
			return err
		}
	}
	event, err := droneutil.GetDroneEventFromEnv()
	if err != nil {
		return err
	}

	var releaseMode config.ReleaseMode
	switch event {
	case string(config.PullRequestMode):
		releaseMode = config.ReleaseMode{Mode: config.PullRequestMode}
	case config.Push:
		mode, err := config.CheckDroneTargetBranch()
		if err != nil {
			return err
		}
		releaseMode = config.ReleaseMode{Mode: mode}
	case config.Custom:
		mode, err := config.CheckDroneTargetBranch()
		if err != nil {
			return err
		}
		// if there is a custom event targeting the main branch, that's an enterprise downstream build
		if mode == config.MainBranch {
			releaseMode = config.ReleaseMode{Mode: config.CustomMode}
		} else {
			releaseMode = config.ReleaseMode{Mode: mode}
		}
	case config.Tag, config.Promote:
		mode, err := config.CheckSemverSuffix()
		if err != nil {
			return err
		}
		releaseMode = mode
	}

	currentCommit, err := config.GetDroneCommit()
	if err != nil {
		return err
	}
	metadata = config.Metadata{
		GrafanaVersion: version,
		ReleaseMode:    releaseMode,
		GrabplVersion:  c.App.Version,
		CurrentCommit:  currentCommit,
	}

	fmt.Printf("building Grafana version: %s, release mode: %+v", metadata.GrafanaVersion, metadata.ReleaseMode)

	jsonMetadata, err := json.Marshal(&metadata)
	if err != nil {
		return fmt.Errorf("error marshalling metadata, %w", err)
	}

	const distDir = "dist"
	if _, err := os.Stat(distDir); os.IsNotExist(err) {
		if err := os.RemoveAll(distDir); err != nil {
			return err
		}
		if err := os.Mkdir(distDir, 0750); err != nil {
			return err
		}

		// nolint:gosec
		if err := os.WriteFile(filepath.Join(distDir, "version.json"), jsonMetadata, 0664); err != nil {
			return err
		}
	}

	return nil
}
<|endoftext|>


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

// Handlers for namespace updates.  Keeps an index of namespace
// annotations

package controller

import (
	"reflect"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/watch"
	"k8s.io/client-go/kubernetes"
	v1 "k8s.io/client-go/pkg/api/v1"
	"k8s.io/client-go/tools/cache"
	"k8s.io/kubernetes/pkg/controller"

	"github.com/noironetworks/aci-containers/pkg/apicapi"
)

func (cont *AciController) initNamespaceInformerFromClient(
	kubeClient kubernetes.Interface) {

	cont.initNamespaceInformerBase(
		&cache.ListWatch{
			ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
				return kubeClient.CoreV1().Namespaces().List(options)
			},
			WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
				return kubeClient.CoreV1().Namespaces().Watch(options)
			},
		})
}

func (cont *AciController) initNamespaceInformerBase(listWatch *cache.ListWatch) {
	cont.namespaceInformer = cache.NewSharedIndexInformer(
		listWatch,
		&v1.Namespace{},
		controller.NoResyncPeriodFunc(),
		cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc},
	)
	cont.namespaceInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
		AddFunc: func(obj interface{}) {
			cont.namespaceAdded(obj)
		},
		UpdateFunc: func(oldobj interface{}, newobj interface{}) {
			cont.namespaceChanged(oldobj, newobj)
		},
		DeleteFunc: func(obj interface{}) {
			cont.namespaceDeleted(obj)
		},
	})

}

func (cont *AciController) updatePodsForNamespace(ns string) {
	cache.ListAllByNamespace(cont.podInformer.GetIndexer(), ns, labels.Everything(),
		func(podobj interface{}) {
			cont.queuePodUpdate(podobj.(*v1.Pod))
		})
}

func (cont *AciController) writeApicNs(ns *v1.Namespace) {
	aobj := apicapi.NewVmmInjectedNs("Kubernetes",
		cont.config.AciVmmDomain, cont.config.AciVmmController,
		ns.Name)
	cont.apicConn.WriteApicContainer(cont.aciNameForKey("ns", ns.Name),
		apicapi.ApicSlice{aobj})
}

func (cont *AciController) namespaceAdded(obj interface{}) {
	ns := obj.(*v1.Namespace)
	cont.writeApicNs(ns)
	cont.depPods.UpdateNamespace(ns)
	cont.updatePodsForNamespace(ns.ObjectMeta.Name)
}

func (cont *AciController) namespaceChanged(oldobj interface{},
	newobj interface{}) {

	oldns := oldobj.(*v1.Namespace)
	newns := newobj.(*v1.Namespace)

	cont.writeApicNs(newns)

	if !reflect.DeepEqual(oldns.ObjectMeta.Labels, newns.ObjectMeta.Labels) {
		cont.depPods.UpdateNamespace(newns)
		cont.netPolPods.UpdateNamespace(newns)
		cont.netPolIngressPods.UpdateNamespace(newns)
	}
	if !reflect.DeepEqual(oldns.ObjectMeta.Annotations,
		newns.ObjectMeta.Annotations) {
		cont.updatePodsForNamespace(newns.ObjectMeta.Name)
	}
}

func (cont *AciController) namespaceDeleted(obj interface{}) {
	ns := obj.(*v1.Namespace)
	cont.apicConn.ClearApicObjects(cont.aciNameForKey("ns", ns.Name))
	cont.depPods.DeleteNamespace(ns)
	cont.netPolPods.DeleteNamespace(ns)
	cont.netPolIngressPods.DeleteNamespace(ns)
	cont.updatePodsForNamespace(ns.ObjectMeta.Name)
}
<commit_msg>Add namespace to netpol indices on create.<commit_after>// Copyright 2016 Cisco Systems, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Handlers for namespace updates.  Keeps an index of namespace
// annotations

package controller

import (
	"reflect"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/watch"
	"k8s.io/client-go/kubernetes"
	v1 "k8s.io/client-go/pkg/api/v1"
	"k8s.io/client-go/tools/cache"
	"k8s.io/kubernetes/pkg/controller"

	"github.com/noironetworks/aci-containers/pkg/apicapi"
)

func (cont *AciController) initNamespaceInformerFromClient(
	kubeClient kubernetes.Interface) {

	cont.initNamespaceInformerBase(
		&cache.ListWatch{
			ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
				return kubeClient.CoreV1().Namespaces().List(options)
			},
			WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
				return kubeClient.CoreV1().Namespaces().Watch(options)
			},
		})
}

func (cont *AciController) initNamespaceInformerBase(listWatch *cache.ListWatch) {
	cont.namespaceInformer = cache.NewSharedIndexInformer(
		listWatch,
		&v1.Namespace{},
		controller.NoResyncPeriodFunc(),
		cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc},
	)
	cont.namespaceInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
		AddFunc: func(obj interface{}) {
			cont.namespaceAdded(obj)
		},
		UpdateFunc: func(oldobj interface{}, newobj interface{}) {
			cont.namespaceChanged(oldobj, newobj)
		},
		DeleteFunc: func(obj interface{}) {
			cont.namespaceDeleted(obj)
		},
	})

}

func (cont *AciController) updatePodsForNamespace(ns string) {
	cache.ListAllByNamespace(cont.podInformer.GetIndexer(), ns, labels.Everything(),
		func(podobj interface{}) {
			cont.queuePodUpdate(podobj.(*v1.Pod))
		})
}

func (cont *AciController) writeApicNs(ns *v1.Namespace) {
	aobj := apicapi.NewVmmInjectedNs("Kubernetes",
		cont.config.AciVmmDomain, cont.config.AciVmmController,
		ns.Name)
	cont.apicConn.WriteApicContainer(cont.aciNameForKey("ns", ns.Name),
		apicapi.ApicSlice{aobj})
}

func (cont *AciController) namespaceAdded(obj interface{}) {
	ns := obj.(*v1.Namespace)
	cont.writeApicNs(ns)
	cont.depPods.UpdateNamespace(ns)
	cont.netPolPods.UpdateNamespace(ns)
	cont.netPolIngressPods.UpdateNamespace(ns)
	cont.updatePodsForNamespace(ns.ObjectMeta.Name)
}

func (cont *AciController) namespaceChanged(oldobj interface{},
	newobj interface{}) {

	oldns := oldobj.(*v1.Namespace)
	newns := newobj.(*v1.Namespace)

	cont.writeApicNs(newns)

	if !reflect.DeepEqual(oldns.ObjectMeta.Labels, newns.ObjectMeta.Labels) {
		cont.depPods.UpdateNamespace(newns)
		cont.netPolPods.UpdateNamespace(newns)
		cont.netPolIngressPods.UpdateNamespace(newns)
	}
	if !reflect.DeepEqual(oldns.ObjectMeta.Annotations,
		newns.ObjectMeta.Annotations) {
		cont.updatePodsForNamespace(newns.ObjectMeta.Name)
	}
}

func (cont *AciController) namespaceDeleted(obj interface{}) {
	ns := obj.(*v1.Namespace)
	cont.apicConn.ClearApicObjects(cont.aciNameForKey("ns", ns.Name))
	cont.depPods.DeleteNamespace(ns)
	cont.netPolPods.DeleteNamespace(ns)
	cont.netPolIngressPods.DeleteNamespace(ns)
	cont.updatePodsForNamespace(ns.ObjectMeta.Name)
}
<|endoftext|>


<commit_before>// Copyright 2017-2018 the u-root 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 kmodule interfaces with Linux kernel modules.
//
// kmodule allows loading and unloading kernel modules with dependencies, as
// well as locating them through probing.
package kmodule

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"strings"

	"golang.org/x/sys/unix"
)

// Flags to finit_module(2) / FileInit.
const (
	// Ignore symbol version hashes.
	MODULE_INIT_IGNORE_MODVERSIONS = 0x1

	// Ignore kernel version magic.
	MODULE_INIT_IGNORE_VERMAGIC = 0x2
)

// Init loads the kernel module given by image with the given options.
func Init(image []byte, opts string) error {
	return unix.InitModule(image, opts)
}

// FileInit loads the kernel module contained by `f` with the given opts and
// flags.
//
// FileInit falls back to Init when the finit_module(2) syscall is not available.
func FileInit(f *os.File, opts string, flags uintptr) error {
	err := unix.FinitModule(int(f.Fd()), opts, int(flags))
	if err == unix.ENOSYS {
		if flags != 0 {
			return err
		}

		// Fall back to regular init_module(2).
		img, err := ioutil.ReadAll(f)
		if err != nil {
			return err
		}
		return Init(img, opts)
	}

	return err
}

// Delete removes a kernel module.
func Delete(name string, flags uintptr) error {
	return unix.DeleteModule(name, int(flags))
}

type modState uint8

const (
	unloaded modState = iota
	loading
	loaded
	builtin
)

type dependency struct {
	state modState
	deps  []string
}

type depMap map[string]*dependency

// ProbeOpts contains optional parameters to Probe.
//
// An empty ProbeOpts{} should lead to the default behavior.
type ProbeOpts struct {
	DryRunCB       func(string)
	RootDir        string
	KVer           string
	IgnoreProcMods bool
}

// Probe loads the given kernel module and its dependencies.
// It is calls ProbeOptions with the default ProbeOpts.
func Probe(name string, modParams string) error {
	return ProbeOptions(name, modParams, ProbeOpts{})
}

// ProbeOptions loads the given kernel module and its dependencies.
// This functions takes ProbeOpts.
func ProbeOptions(name, modParams string, opts ProbeOpts) error {
	deps, err := genDeps(opts)
	if err != nil {
		return fmt.Errorf("could not generate dependency map %v", err)
	}

	modPath, err := findModPath(name, deps)
	if err != nil {
		return fmt.Errorf("could not find module path %q: %v", name, err)
	}

	dep := deps[modPath]

	if dep.state == builtin || dep.state == loaded {
		return nil
	}

	dep.state = loading
	for _, d := range dep.deps {
		if err := loadDeps(d, deps, opts); err != nil {
			return err
		}
	}
	if err := loadModule(modPath, modParams, opts); err != nil {
		return err
	}

	return nil
}

func checkBuiltin(moduleDir string, deps depMap) error {
	f, err := os.Open(filepath.Join(moduleDir, "modules.builtin"))
	if os.IsNotExist(err) {
		return nil
	} else if err != nil {
		return fmt.Errorf("could not open builtin file: %v", err)
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		txt := scanner.Text()
		modPath := filepath.Join(moduleDir, strings.TrimSpace(txt))
		if deps[modPath] == nil {
			deps[modPath] = new(dependency)
		}
		deps[modPath].state = builtin
	}

	return scanner.Err()
}

func genDeps(opts ProbeOpts) (depMap, error) {
	deps := make(depMap)
	rel := opts.KVer

	if rel == "" {
		var u unix.Utsname
		if err := unix.Uname(&u); err != nil {
			return nil, fmt.Errorf("could not get release (uname -r): %v", err)
		}
		rel = string(u.Release[:bytes.IndexByte(u.Release[:], 0)])
	}

	var moduleDir string
	for _, n := range []string{"/lib/modules", "/usr/lib/modules"} {
		moduleDir = filepath.Join(opts.RootDir, n, strings.TrimSpace(rel))
		if _, err := os.Stat(moduleDir); err == nil {
			break
		}
	}

	f, err := os.Open(filepath.Join(moduleDir, "modules.dep"))
	if err != nil {
		return nil, fmt.Errorf("could not open dependency file: %v", err)
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		txt := scanner.Text()
		nameDeps := strings.Split(txt, ":")
		modPath, modDeps := nameDeps[0], nameDeps[1]
		modPath = filepath.Join(moduleDir, strings.TrimSpace(modPath))

		var dependency dependency
		if len(modDeps) > 0 {
			for _, dep := range strings.Split(strings.TrimSpace(modDeps), " ") {
				dependency.deps = append(dependency.deps, filepath.Join(moduleDir, dep))
			}
		}
		deps[modPath] = &dependency
	}

	if err := scanner.Err(); err != nil {
		return nil, err
	}

	if err = checkBuiltin(moduleDir, deps); err != nil {
		return nil, err
	}

	if !opts.IgnoreProcMods {
		fm, err := os.Open("/proc/modules")
		if err == nil {
			defer fm.Close()
			genLoadedMods(fm, deps)
		}
	}

	return deps, nil
}

func findModPath(name string, m depMap) (string, error) {
	for mp := range m {
		if path.Base(mp) == name+".ko" {
			return mp, nil
		}
	}

	return "", fmt.Errorf("Could not find path for module %q", name)
}

func loadDeps(path string, m depMap, opts ProbeOpts) error {
	dependency, ok := m[path]
	if !ok {
		return fmt.Errorf("could not find dependency %q", path)
	}

	if dependency.state == loading {
		return fmt.Errorf("circular dependency! %q already LOADING", path)
	} else if (dependency.state == loaded) || (dependency.state == builtin) {
		return nil
	}

	m[path].state = loading

	for _, dep := range dependency.deps {
		if err := loadDeps(dep, m, opts); err != nil {
			return err
		}
	}

	// done with dependencies, load module
	if err := loadModule(path, "", opts); err != nil {
		return err
	}
	m[path].state = loaded

	return nil
}

func loadModule(path, modParams string, opts ProbeOpts) error {
	if opts.DryRunCB != nil {
		opts.DryRunCB(path)
		return nil
	}

	f, err := os.Open(path)
	if err != nil {
		return err
	}
	defer f.Close()

	if err := FileInit(f, modParams, 0); err != nil && err != unix.EEXIST {
		return err
	}

	return nil
}

func genLoadedMods(r io.Reader, deps depMap) error {
	scanner := bufio.NewScanner(r)
	for scanner.Scan() {
		arr := strings.Split(scanner.Text(), " ")
		name := strings.Replace(arr[0], "_", "-", -1)
		modPath, err := findModPath(name, deps)
		if err != nil {
			return fmt.Errorf("could not find module path %q: %v", name, err)
		}
		if deps[modPath] == nil {
			deps[modPath] = new(dependency)
		}
		deps[modPath].state = loaded
	}
	return scanner.Err()
}
<commit_msg>kmodule: lower-case error string<commit_after>// Copyright 2017-2018 the u-root 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 kmodule interfaces with Linux kernel modules.
//
// kmodule allows loading and unloading kernel modules with dependencies, as
// well as locating them through probing.
package kmodule

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"strings"

	"golang.org/x/sys/unix"
)

// Flags to finit_module(2) / FileInit.
const (
	// Ignore symbol version hashes.
	MODULE_INIT_IGNORE_MODVERSIONS = 0x1

	// Ignore kernel version magic.
	MODULE_INIT_IGNORE_VERMAGIC = 0x2
)

// Init loads the kernel module given by image with the given options.
func Init(image []byte, opts string) error {
	return unix.InitModule(image, opts)
}

// FileInit loads the kernel module contained by `f` with the given opts and
// flags.
//
// FileInit falls back to Init when the finit_module(2) syscall is not available.
func FileInit(f *os.File, opts string, flags uintptr) error {
	err := unix.FinitModule(int(f.Fd()), opts, int(flags))
	if err == unix.ENOSYS {
		if flags != 0 {
			return err
		}

		// Fall back to regular init_module(2).
		img, err := ioutil.ReadAll(f)
		if err != nil {
			return err
		}
		return Init(img, opts)
	}

	return err
}

// Delete removes a kernel module.
func Delete(name string, flags uintptr) error {
	return unix.DeleteModule(name, int(flags))
}

type modState uint8

const (
	unloaded modState = iota
	loading
	loaded
	builtin
)

type dependency struct {
	state modState
	deps  []string
}

type depMap map[string]*dependency

// ProbeOpts contains optional parameters to Probe.
//
// An empty ProbeOpts{} should lead to the default behavior.
type ProbeOpts struct {
	DryRunCB       func(string)
	RootDir        string
	KVer           string
	IgnoreProcMods bool
}

// Probe loads the given kernel module and its dependencies.
// It is calls ProbeOptions with the default ProbeOpts.
func Probe(name string, modParams string) error {
	return ProbeOptions(name, modParams, ProbeOpts{})
}

// ProbeOptions loads the given kernel module and its dependencies.
// This functions takes ProbeOpts.
func ProbeOptions(name, modParams string, opts ProbeOpts) error {
	deps, err := genDeps(opts)
	if err != nil {
		return fmt.Errorf("could not generate dependency map %v", err)
	}

	modPath, err := findModPath(name, deps)
	if err != nil {
		return fmt.Errorf("could not find module path %q: %v", name, err)
	}

	dep := deps[modPath]

	if dep.state == builtin || dep.state == loaded {
		return nil
	}

	dep.state = loading
	for _, d := range dep.deps {
		if err := loadDeps(d, deps, opts); err != nil {
			return err
		}
	}
	if err := loadModule(modPath, modParams, opts); err != nil {
		return err
	}

	return nil
}

func checkBuiltin(moduleDir string, deps depMap) error {
	f, err := os.Open(filepath.Join(moduleDir, "modules.builtin"))
	if os.IsNotExist(err) {
		return nil
	} else if err != nil {
		return fmt.Errorf("could not open builtin file: %v", err)
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		txt := scanner.Text()
		modPath := filepath.Join(moduleDir, strings.TrimSpace(txt))
		if deps[modPath] == nil {
			deps[modPath] = new(dependency)
		}
		deps[modPath].state = builtin
	}

	return scanner.Err()
}

func genDeps(opts ProbeOpts) (depMap, error) {
	deps := make(depMap)
	rel := opts.KVer

	if rel == "" {
		var u unix.Utsname
		if err := unix.Uname(&u); err != nil {
			return nil, fmt.Errorf("could not get release (uname -r): %v", err)
		}
		rel = string(u.Release[:bytes.IndexByte(u.Release[:], 0)])
	}

	var moduleDir string
	for _, n := range []string{"/lib/modules", "/usr/lib/modules"} {
		moduleDir = filepath.Join(opts.RootDir, n, strings.TrimSpace(rel))
		if _, err := os.Stat(moduleDir); err == nil {
			break
		}
	}

	f, err := os.Open(filepath.Join(moduleDir, "modules.dep"))
	if err != nil {
		return nil, fmt.Errorf("could not open dependency file: %v", err)
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		txt := scanner.Text()
		nameDeps := strings.Split(txt, ":")
		modPath, modDeps := nameDeps[0], nameDeps[1]
		modPath = filepath.Join(moduleDir, strings.TrimSpace(modPath))

		var dependency dependency
		if len(modDeps) > 0 {
			for _, dep := range strings.Split(strings.TrimSpace(modDeps), " ") {
				dependency.deps = append(dependency.deps, filepath.Join(moduleDir, dep))
			}
		}
		deps[modPath] = &dependency
	}

	if err := scanner.Err(); err != nil {
		return nil, err
	}

	if err = checkBuiltin(moduleDir, deps); err != nil {
		return nil, err
	}

	if !opts.IgnoreProcMods {
		fm, err := os.Open("/proc/modules")
		if err == nil {
			defer fm.Close()
			genLoadedMods(fm, deps)
		}
	}

	return deps, nil
}

func findModPath(name string, m depMap) (string, error) {
	for mp := range m {
		if path.Base(mp) == name+".ko" {
			return mp, nil
		}
	}

	return "", fmt.Errorf("could not find path for module %q", name)
}

func loadDeps(path string, m depMap, opts ProbeOpts) error {
	dependency, ok := m[path]
	if !ok {
		return fmt.Errorf("could not find dependency %q", path)
	}

	if dependency.state == loading {
		return fmt.Errorf("circular dependency! %q already LOADING", path)
	} else if (dependency.state == loaded) || (dependency.state == builtin) {
		return nil
	}

	m[path].state = loading

	for _, dep := range dependency.deps {
		if err := loadDeps(dep, m, opts); err != nil {
			return err
		}
	}

	// done with dependencies, load module
	if err := loadModule(path, "", opts); err != nil {
		return err
	}
	m[path].state = loaded

	return nil
}

func loadModule(path, modParams string, opts ProbeOpts) error {
	if opts.DryRunCB != nil {
		opts.DryRunCB(path)
		return nil
	}

	f, err := os.Open(path)
	if err != nil {
		return err
	}
	defer f.Close()

	if err := FileInit(f, modParams, 0); err != nil && err != unix.EEXIST {
		return err
	}

	return nil
}

func genLoadedMods(r io.Reader, deps depMap) error {
	scanner := bufio.NewScanner(r)
	for scanner.Scan() {
		arr := strings.Split(scanner.Text(), " ")
		name := strings.Replace(arr[0], "_", "-", -1)
		modPath, err := findModPath(name, deps)
		if err != nil {
			return fmt.Errorf("could not find module path %q: %v", name, err)
		}
		if deps[modPath] == nil {
			deps[modPath] = new(dependency)
		}
		deps[modPath].state = loaded
	}
	return scanner.Err()
}
<|endoftext|>