<commit_before>// Copyright Istio 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 options

import (
	"fmt"
	"path/filepath"
	"strings"

	meshconfig "istio.io/api/mesh/v1alpha1"
	"istio.io/istio/pilot/pkg/features"
	securityModel "istio.io/istio/pilot/pkg/security/model"
	"istio.io/istio/pkg/config/constants"
	"istio.io/istio/pkg/jwt"
	"istio.io/istio/pkg/security"
	"istio.io/istio/security/pkg/credentialfetcher"
	"istio.io/istio/security/pkg/nodeagent/plugin/providers/google/stsclient"
	"istio.io/istio/security/pkg/stsservice/tokenmanager"
	"istio.io/pkg/log"
)

func NewSecurityOptions(proxyConfig *meshconfig.ProxyConfig, stsPort int, tokenManagerPlugin string) (*security.Options, error) {
	o := &security.Options{
		CAEndpoint:                     caEndpointEnv,
		CAProviderName:                 caProviderEnv,
		PilotCertProvider:              features.PilotCertProvider,
		OutputKeyCertToDir:             outputKeyCertToDir,
		ProvCert:                       provCert,
		WorkloadUDSPath:                filepath.Join(proxyConfig.ConfigPath, "SDS"),
		ClusterID:                      clusterIDVar.Get(),
		FileMountedCerts:               fileMountedCertsEnv,
		WorkloadNamespace:              PodNamespaceVar.Get(),
		ServiceAccount:                 serviceAccountVar.Get(),
		XdsAuthProvider:                xdsAuthProvider.Get(),
		TrustDomain:                    trustDomainEnv,
		Pkcs8Keys:                      pkcs8KeysEnv,
		ECCSigAlg:                      eccSigAlgEnv,
		SecretTTL:                      secretTTLEnv,
		SecretRotationGracePeriodRatio: secretRotationGracePeriodRatioEnv,
		STSPort:                        stsPort,
	}

	o, err := SetupSecurityOptions(proxyConfig, o, jwtPolicy.Get(),
		credFetcherTypeEnv, credIdentityProvider)
	if err != nil {
		return o, err
	}

	var tokenManager security.TokenManager
	if stsPort > 0 || xdsAuthProvider.Get() != "" {
		// tokenManager is gcp token manager when using the default token manager plugin.
		tokenManager = tokenmanager.CreateTokenManager(tokenManagerPlugin,
			tokenmanager.Config{CredFetcher: o.CredFetcher, TrustDomain: o.TrustDomain})
	}
	o.TokenManager = tokenManager

	return o, err
}

func SetupSecurityOptions(proxyConfig *meshconfig.ProxyConfig, secOpt *security.Options, jwtPolicy,
	credFetcherTypeEnv, credIdentityProvider string) (*security.Options, error) {
	var jwtPath string
	if jwtPolicy == jwt.PolicyThirdParty {
		log.Info("JWT policy is third-party-jwt")
		jwtPath = constants.TrustworthyJWTPath
	} else if jwtPolicy == jwt.PolicyFirstParty {
		log.Info("JWT policy is first-party-jwt")
		jwtPath = securityModel.K8sSAJwtFileName
	} else {
		log.Info("Using existing certs")
	}

	o := secOpt
	o.JWTPath = jwtPath

	// If not set explicitly, default to the discovery address.
	if o.CAEndpoint == "" {
		o.CAEndpoint = proxyConfig.DiscoveryAddress
	}

	// TODO (liminw): CredFetcher is a general interface. In 1.7, we limit the use on GCE only because
	// GCE is the only supported plugin at the moment.
	if credFetcherTypeEnv == security.GCE {
		o.CredIdentityProvider = credIdentityProvider
		credFetcher, err := credentialfetcher.NewCredFetcher(credFetcherTypeEnv, o.TrustDomain, jwtPath, o.CredIdentityProvider)
		if err != nil {
			return nil, fmt.Errorf("failed to create credential fetcher: %v", err)
		}
		log.Infof("using credential fetcher of %s type in %s trust domain", credFetcherTypeEnv, o.TrustDomain)
		o.CredFetcher = credFetcher
	}
	// Default the CA provider where possible
	if strings.Contains(o.CAEndpoint, "googleapis.com") {
		o.CAProviderName = security.GoogleCAProvider
	}
	// TODO extract this logic out to a plugin
	if o.CAProviderName == security.GoogleCAProvider {
		o.TokenExchanger = stsclient.NewSecureTokenServiceExchanger(o.CredFetcher, o.TrustDomain)
	}

	if o.ProvCert != "" && o.FileMountedCerts {
		return nil, fmt.Errorf("invalid options: PROV_CERT and FILE_MOUNTED_CERTS are mutually exclusive")
	}
	return o, nil
}
<commit_msg>Using switch-case instead of multiple if-else (#33823)<commit_after>// Copyright Istio 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 options

import (
	"fmt"
	"path/filepath"
	"strings"

	meshconfig "istio.io/api/mesh/v1alpha1"
	"istio.io/istio/pilot/pkg/features"
	securityModel "istio.io/istio/pilot/pkg/security/model"
	"istio.io/istio/pkg/config/constants"
	"istio.io/istio/pkg/jwt"
	"istio.io/istio/pkg/security"
	"istio.io/istio/security/pkg/credentialfetcher"
	"istio.io/istio/security/pkg/nodeagent/plugin/providers/google/stsclient"
	"istio.io/istio/security/pkg/stsservice/tokenmanager"
	"istio.io/pkg/log"
)

func NewSecurityOptions(proxyConfig *meshconfig.ProxyConfig, stsPort int, tokenManagerPlugin string) (*security.Options, error) {
	o := &security.Options{
		CAEndpoint:                     caEndpointEnv,
		CAProviderName:                 caProviderEnv,
		PilotCertProvider:              features.PilotCertProvider,
		OutputKeyCertToDir:             outputKeyCertToDir,
		ProvCert:                       provCert,
		WorkloadUDSPath:                filepath.Join(proxyConfig.ConfigPath, "SDS"),
		ClusterID:                      clusterIDVar.Get(),
		FileMountedCerts:               fileMountedCertsEnv,
		WorkloadNamespace:              PodNamespaceVar.Get(),
		ServiceAccount:                 serviceAccountVar.Get(),
		XdsAuthProvider:                xdsAuthProvider.Get(),
		TrustDomain:                    trustDomainEnv,
		Pkcs8Keys:                      pkcs8KeysEnv,
		ECCSigAlg:                      eccSigAlgEnv,
		SecretTTL:                      secretTTLEnv,
		SecretRotationGracePeriodRatio: secretRotationGracePeriodRatioEnv,
		STSPort:                        stsPort,
	}

	o, err := SetupSecurityOptions(proxyConfig, o, jwtPolicy.Get(),
		credFetcherTypeEnv, credIdentityProvider)
	if err != nil {
		return o, err
	}

	var tokenManager security.TokenManager
	if stsPort > 0 || xdsAuthProvider.Get() != "" {
		// tokenManager is gcp token manager when using the default token manager plugin.
		tokenManager = tokenmanager.CreateTokenManager(tokenManagerPlugin,
			tokenmanager.Config{CredFetcher: o.CredFetcher, TrustDomain: o.TrustDomain})
	}
	o.TokenManager = tokenManager

	return o, err
}

func SetupSecurityOptions(proxyConfig *meshconfig.ProxyConfig, secOpt *security.Options, jwtPolicy,
	credFetcherTypeEnv, credIdentityProvider string) (*security.Options, error) {
	var jwtPath string
	switch jwtPolicy {
	case jwt.PolicyThirdParty:
		log.Info("JWT policy is third-party-jwt")
		jwtPath = constants.TrustworthyJWTPath
	case jwt.PolicyFirstParty:
		log.Info("JWT policy is first-party-jwt")
		jwtPath = securityModel.K8sSAJwtFileName
	default:
		log.Info("Using existing certs")
	}

	o := secOpt
	o.JWTPath = jwtPath

	// If not set explicitly, default to the discovery address.
	if o.CAEndpoint == "" {
		o.CAEndpoint = proxyConfig.DiscoveryAddress
	}

	// TODO (liminw): CredFetcher is a general interface. In 1.7, we limit the use on GCE only because
	// GCE is the only supported plugin at the moment.
	if credFetcherTypeEnv == security.GCE {
		o.CredIdentityProvider = credIdentityProvider
		credFetcher, err := credentialfetcher.NewCredFetcher(credFetcherTypeEnv, o.TrustDomain, jwtPath, o.CredIdentityProvider)
		if err != nil {
			return nil, fmt.Errorf("failed to create credential fetcher: %v", err)
		}
		log.Infof("using credential fetcher of %s type in %s trust domain", credFetcherTypeEnv, o.TrustDomain)
		o.CredFetcher = credFetcher
	}
	// Default the CA provider where possible
	if strings.Contains(o.CAEndpoint, "googleapis.com") {
		o.CAProviderName = security.GoogleCAProvider
	}
	// TODO extract this logic out to a plugin
	if o.CAProviderName == security.GoogleCAProvider {
		o.TokenExchanger = stsclient.NewSecureTokenServiceExchanger(o.CredFetcher, o.TrustDomain)
	}

	if o.ProvCert != "" && o.FileMountedCerts {
		return nil, fmt.Errorf("invalid options: PROV_CERT and FILE_MOUNTED_CERTS are mutually exclusive")
	}
	return o, nil
}
<|endoftext|>


<commit_before>package authn

import (
	"strings"
	"sync"

	"github.com/pkg/errors"
	"github.com/rancher/norman/httperror"
	"github.com/rancher/norman/store/transform"
	"github.com/rancher/norman/types"
	"github.com/rancher/types/apis/management.cattle.io/v3"
	"github.com/rancher/types/client/management/v3"
	"github.com/rancher/types/config"
	"golang.org/x/crypto/bcrypt"
	"k8s.io/client-go/tools/cache"
)

const userByUsernameIndex = "auth.management.cattle.io/user-by-username"

type userStore struct {
	types.Store
	mu          sync.Mutex
	userIndexer cache.Indexer
}

func SetUserStore(schema *types.Schema, mgmt *config.ScaledContext) {
	userInformer := mgmt.Management.Users("").Controller().Informer()
	userIndexers := map[string]cache.IndexFunc{
		userByUsernameIndex: userByUsername,
	}
	userInformer.AddIndexers(userIndexers)

	store := &userStore{
		Store:       schema.Store,
		mu:          sync.Mutex{},
		userIndexer: userInformer.GetIndexer(),
	}

	t := &transform.Store{
		Store: store,
		Transformer: func(apiContext *types.APIContext, data map[string]interface{}, opt *types.QueryOptions) (map[string]interface{}, error) {
			// filter system users out of the api
			if princIds, ok := data[client.UserFieldPrincipalIDs].([]interface{}); ok {
				for _, p := range princIds {
					pid, _ := p.(string)
					if strings.HasPrefix(pid, "system://") {
						if opt != nil && opt.Options["ByID"] == "true" {
							return nil, httperror.NewAPIError(httperror.NotFound, "resource not found")
						}
						return nil, nil
					}
				}
			}

			// set "me" field on user
			userID := apiContext.Request.Header.Get("Impersonate-User")
			if userID != "" {
				id, ok := data[types.ResourceFieldID].(string)
				if ok {
					if id == userID {
						data["me"] = "true"
					}
				}
			}

			return data, nil
		},
	}

	schema.Store = t
}

func userByUsername(obj interface{}) ([]string, error) {
	u, ok := obj.(*v3.User)
	if !ok {
		return []string{}, nil
	}

	return []string{u.Username}, nil
}

func hashPassword(data map[string]interface{}) error {
	pass, ok := data[client.UserFieldPassword].(string)
	if !ok {
		return errors.New("password not a string")
	}
	hashed, err := hashPasswordString(pass)
	if err != nil {
		return err
	}
	data[client.UserFieldPassword] = string(hashed)

	return nil
}

func hashPasswordString(password string) (string, error) {
	hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	if err != nil {
		return "", errors.Wrap(err, "problem encrypting password")
	}
	return string(hash), nil
}

func (s *userStore) Create(apiContext *types.APIContext, schema *types.Schema, data map[string]interface{}) (map[string]interface{}, error) {
	if err := hashPassword(data); err != nil {
		return nil, err
	}

	created, err := s.create(apiContext, schema, data)
	if err != nil {
		return nil, err
	}

	if id, ok := created[types.ResourceFieldID].(string); ok {
		var principalIDs []interface{}
		if pids, ok := created[client.UserFieldPrincipalIDs].([]interface{}); ok {
			principalIDs = pids
		}
		created[client.UserFieldPrincipalIDs] = append(principalIDs, "local://"+id)
		return s.Update(apiContext, schema, created, id)
	}

	return created, err
}

func (s *userStore) create(apiContext *types.APIContext, schema *types.Schema, data map[string]interface{}) (map[string]interface{}, error) {
	username, ok := data[client.UserFieldUsername].(string)
	if !ok {
		return nil, errors.New("invalid username")
	}

	s.mu.Lock()
	defer s.mu.Unlock()

	users, err := s.userIndexer.ByIndex(userByUsernameIndex, username)
	if err != nil {
		return nil, err
	}
	if len(users) > 0 {
		return nil, httperror.NewFieldAPIError(httperror.NotUnique, "username", "Username is already in use.")
	}

	return s.Store.Create(apiContext, schema, data)
}
<commit_msg>Don't return password hash on user create<commit_after>package authn

import (
	"strings"
	"sync"

	"github.com/pkg/errors"
	"github.com/rancher/norman/httperror"
	"github.com/rancher/norman/store/transform"
	"github.com/rancher/norman/types"
	"github.com/rancher/types/apis/management.cattle.io/v3"
	"github.com/rancher/types/client/management/v3"
	"github.com/rancher/types/config"
	"golang.org/x/crypto/bcrypt"
	"k8s.io/client-go/tools/cache"
)

const userByUsernameIndex = "auth.management.cattle.io/user-by-username"

type userStore struct {
	types.Store
	mu          sync.Mutex
	userIndexer cache.Indexer
}

func SetUserStore(schema *types.Schema, mgmt *config.ScaledContext) {
	userInformer := mgmt.Management.Users("").Controller().Informer()
	userIndexers := map[string]cache.IndexFunc{
		userByUsernameIndex: userByUsername,
	}
	userInformer.AddIndexers(userIndexers)

	store := &userStore{
		Store:       schema.Store,
		mu:          sync.Mutex{},
		userIndexer: userInformer.GetIndexer(),
	}

	t := &transform.Store{
		Store: store,
		Transformer: func(apiContext *types.APIContext, data map[string]interface{}, opt *types.QueryOptions) (map[string]interface{}, error) {
			// filter system users out of the api
			if princIds, ok := data[client.UserFieldPrincipalIDs].([]interface{}); ok {
				for _, p := range princIds {
					pid, _ := p.(string)
					if strings.HasPrefix(pid, "system://") {
						if opt != nil && opt.Options["ByID"] == "true" {
							return nil, httperror.NewAPIError(httperror.NotFound, "resource not found")
						}
						return nil, nil
					}
				}
			}

			// set "me" field on user
			userID := apiContext.Request.Header.Get("Impersonate-User")
			if userID != "" {
				id, ok := data[types.ResourceFieldID].(string)
				if ok {
					if id == userID {
						data["me"] = "true"
					}
				}
			}

			return data, nil
		},
	}

	schema.Store = t
}

func userByUsername(obj interface{}) ([]string, error) {
	u, ok := obj.(*v3.User)
	if !ok {
		return []string{}, nil
	}

	return []string{u.Username}, nil
}

func hashPassword(data map[string]interface{}) error {
	pass, ok := data[client.UserFieldPassword].(string)
	if !ok {
		return errors.New("password not a string")
	}
	hashed, err := hashPasswordString(pass)
	if err != nil {
		return err
	}
	data[client.UserFieldPassword] = string(hashed)

	return nil
}

func hashPasswordString(password string) (string, error) {
	hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	if err != nil {
		return "", errors.Wrap(err, "problem encrypting password")
	}
	return string(hash), nil
}

func (s *userStore) Create(apiContext *types.APIContext, schema *types.Schema, data map[string]interface{}) (map[string]interface{}, error) {
	if err := hashPassword(data); err != nil {
		return nil, err
	}

	created, err := s.create(apiContext, schema, data)
	if err != nil {
		return nil, err
	}

	if id, ok := created[types.ResourceFieldID].(string); ok {
		var principalIDs []interface{}
		if pids, ok := created[client.UserFieldPrincipalIDs].([]interface{}); ok {
			principalIDs = pids
		}
		created[client.UserFieldPrincipalIDs] = append(principalIDs, "local://"+id)
		created, err = s.Update(apiContext, schema, created, id)
		if err != nil {
			return created, err
		}
	}

	delete(created, client.UserFieldPassword)

	return created, err
}

func (s *userStore) create(apiContext *types.APIContext, schema *types.Schema, data map[string]interface{}) (map[string]interface{}, error) {
	username, ok := data[client.UserFieldUsername].(string)
	if !ok {
		return nil, errors.New("invalid username")
	}

	s.mu.Lock()
	defer s.mu.Unlock()

	users, err := s.userIndexer.ByIndex(userByUsernameIndex, username)
	if err != nil {
		return nil, err
	}
	if len(users) > 0 {
		return nil, httperror.NewFieldAPIError(httperror.NotUnique, "username", "Username is already in use.")
	}

	return s.Store.Create(apiContext, schema, data)
}
<|endoftext|>


<commit_before>package utils

import (
	"os"
	"path"
	"path/filepath"

	"github.com/grafana/grafana/pkg/cmd/grafana-cli/logger"
	"golang.org/x/xerrors"
)

func GetGrafanaPluginDir(currentOS string) string {
	if rootPath, ok := tryGetRootForDevEnvironment(); ok {
		return filepath.Join(rootPath, "data/plugins")
	}

	return returnOsDefault(currentOS)
}

// getGrafanaRoot tries to get root of directory when developing grafana ie repo root. It is not perfect it just
// checks what is the binary path and tries to guess based on that but if it is not running in dev env you get a bogus
// path back.
func getGrafanaRoot() (string, error) {
	ex, err := os.Executable()
	if err != nil {
		return "", xerrors.New("Failed to get executable path")
	}
	exPath := filepath.Dir(ex)
	_, last := path.Split(exPath)
	if last == "bin" {
		// In dev env the executable for current platform is created in 'bin/' dir
		return filepath.Join(exPath, ".."), nil
	}

	// But at the same time there are per platform directories that contain the binaries and can also be used.
	return filepath.Join(exPath, "../.."), nil
}

// tryGetRootForDevEnvironment returns root path if we are in dev environment. It checks if conf/defaults.ini exists
// which should only exist in dev. Second param is false if we are not in dev or if it wasn't possible to determine it.
func tryGetRootForDevEnvironment() (string, bool) {
	rootPath, err := getGrafanaRoot()
	if err != nil {
		logger.Error("Could not get executable path. Assuming non dev environment.", err)
		return "", false
	}

	defaultsPath := filepath.Join(rootPath, "conf/defaults.ini")

	_, err = os.Stat(defaultsPath)
	if err != nil {
		return "", false
	}
	return rootPath, true
}

func returnOsDefault(currentOs string) string {
	switch currentOs {
	case "windows":
		return "../data/plugins"
	case "darwin":
		return "/usr/local/var/lib/grafana/plugins"
	case "freebsd":
		return "/var/db/grafana/plugins"
	case "openbsd":
		return "/var/grafana/plugins"
	default: //"linux"
		return "/var/lib/grafana/plugins"
	}
}
<commit_msg>cli: fix for recognizing when in dev mode. (#18334)<commit_after>package utils

import (
	"os"
	"path"
	"path/filepath"

	"github.com/grafana/grafana/pkg/cmd/grafana-cli/logger"
	"golang.org/x/xerrors"
)

func GetGrafanaPluginDir(currentOS string) string {
	if rootPath, ok := tryGetRootForDevEnvironment(); ok {
		return filepath.Join(rootPath, "data/plugins")
	}

	return returnOsDefault(currentOS)
}

// getGrafanaRoot tries to get root of directory when developing grafana ie repo root. It is not perfect it just
// checks what is the binary path and tries to guess based on that but if it is not running in dev env you get a bogus
// path back.
func getGrafanaRoot() (string, error) {
	ex, err := os.Executable()
	if err != nil {
		return "", xerrors.New("Failed to get executable path")
	}
	exPath := filepath.Dir(ex)
	_, last := path.Split(exPath)
	if last == "bin" {
		// In dev env the executable for current platform is created in 'bin/' dir
		return filepath.Join(exPath, ".."), nil
	}

	// But at the same time there are per platform directories that contain the binaries and can also be used.
	return filepath.Join(exPath, "../.."), nil
}

// tryGetRootForDevEnvironment returns root path if we are in dev environment. It checks if conf/defaults.ini exists
// which should only exist in dev. Second param is false if we are not in dev or if it wasn't possible to determine it.
func tryGetRootForDevEnvironment() (string, bool) {
	rootPath, err := getGrafanaRoot()
	if err != nil {
		logger.Error("Could not get executable path. Assuming non dev environment.", err)
		return "", false
	}

	devenvPath := filepath.Join(rootPath, "devenv")

	_, err = os.Stat(devenvPath)
	if err != nil {
		return "", false
	}

	return rootPath, true
}

func returnOsDefault(currentOs string) string {
	switch currentOs {
	case "windows":
		return "../data/plugins"
	case "darwin":
		return "/usr/local/var/lib/grafana/plugins"
	case "freebsd":
		return "/var/db/grafana/plugins"
	case "openbsd":
		return "/var/grafana/plugins"
	default: //"linux"
		return "/var/lib/grafana/plugins"
	}
}
<|endoftext|>


<commit_before>package infraconfigurators

import (
	"net"
	"strconv"

	"github.com/vishvananda/netlink"

	v1 "kubevirt.io/client-go/api/v1"
	"kubevirt.io/client-go/log"
	"kubevirt.io/kubevirt/pkg/network/cache"
	netdriver "kubevirt.io/kubevirt/pkg/network/driver"
	"kubevirt.io/kubevirt/pkg/virt-launcher/virtwrap/api"
)

type MacvtapPodNetworkConfigurator struct {
	podInterfaceName string
	podNicLink       netlink.Link
	vmiSpecIface     *v1.Interface
	vmMac            *net.HardwareAddr
	launcherPID      int
	handler          netdriver.NetworkHandler
}

func NewMacvtapPodNetworkConfigurator(podIfaceName string, vmiSpecIface *v1.Interface, handler netdriver.NetworkHandler) *MacvtapPodNetworkConfigurator {
	return &MacvtapPodNetworkConfigurator{
		podInterfaceName: podIfaceName,
		vmiSpecIface:     vmiSpecIface,
		handler:          handler,
	}
}

func (b *MacvtapPodNetworkConfigurator) discoverPodNetworkInterface(podIfaceName string) error {
	link, err := b.handler.LinkByName(b.podInterfaceName)
	if err != nil {
		log.Log.Reason(err).Errorf("failed to get a link for interface: %s", podIfaceName)
		return err
	}
	b.podNicLink = link

	return nil
}

func (b *MacvtapPodNetworkConfigurator) preparePodNetworkInterface() error {
	return nil
}

func (b *MacvtapPodNetworkConfigurator) generateDomainIfaceSpec() api.Interface {
	return api.Interface{
		MAC: &api.MAC{MAC: b.vmMac},
		MTU: &api.MTU{Size: strconv.Itoa(b.podNicLink.Attrs().MTU)},
		Target: &api.InterfaceTarget{
			Device:  b.podNicLink.Attrs().Name,
			Managed: "no",
		},
	}
}
func (b *MacvtapPodNetworkConfigurator) DiscoverPodNetworkInterface(podIfaceName string) error {
	link, err := b.handler.LinkByName(b.podInterfaceName)
	if err != nil {
		log.Log.Reason(err).Errorf("failed to get a link for interface: %s", podIfaceName)
		return err
	}
	b.podNicLink = link

	b.vmMac, err = retrieveMacAddressFromVMISpecIface(b.vmiSpecIface)
	if err != nil {
		return err
	}
	if b.vmMac == nil {
		b.vmMac = &b.podNicLink.Attrs().HardwareAddr
	}

	return nil
}

func (b *MacvtapPodNetworkConfigurator) PreparePodNetworkInterface() error {
	return nil
}

func (b *MacvtapPodNetworkConfigurator) GenerateDomainIfaceSpec() api.Interface {
	return api.Interface{
		MAC: &api.MAC{MAC: b.vmMac.String()},
		MTU: &api.MTU{Size: strconv.Itoa(b.podNicLink.Attrs().MTU)},
		Target: &api.InterfaceTarget{
			Device:  b.podNicLink.Attrs().Name,
			Managed: "no",
		},
	}
}

func (b *MacvtapPodNetworkConfigurator) GenerateDHCPConfig() *cache.DHCPConfig {
	return nil
}
<commit_msg>MacvtapPodNetworkConfigurator: remove unused methods<commit_after>package infraconfigurators

import (
	"net"
	"strconv"

	"github.com/vishvananda/netlink"

	v1 "kubevirt.io/client-go/api/v1"
	"kubevirt.io/client-go/log"
	"kubevirt.io/kubevirt/pkg/network/cache"
	netdriver "kubevirt.io/kubevirt/pkg/network/driver"
	"kubevirt.io/kubevirt/pkg/virt-launcher/virtwrap/api"
)

type MacvtapPodNetworkConfigurator struct {
	podInterfaceName string
	podNicLink       netlink.Link
	vmiSpecIface     *v1.Interface
	vmMac            *net.HardwareAddr
	launcherPID      int
	handler          netdriver.NetworkHandler
}

func NewMacvtapPodNetworkConfigurator(podIfaceName string, vmiSpecIface *v1.Interface, handler netdriver.NetworkHandler) *MacvtapPodNetworkConfigurator {
	return &MacvtapPodNetworkConfigurator{
		podInterfaceName: podIfaceName,
		vmiSpecIface:     vmiSpecIface,
		handler:          handler,
	}
}

func (b *MacvtapPodNetworkConfigurator) DiscoverPodNetworkInterface(podIfaceName string) error {
	link, err := b.handler.LinkByName(b.podInterfaceName)
	if err != nil {
		log.Log.Reason(err).Errorf("failed to get a link for interface: %s", podIfaceName)
		return err
	}
	b.podNicLink = link

	b.vmMac, err = retrieveMacAddressFromVMISpecIface(b.vmiSpecIface)
	if err != nil {
		return err
	}
	if b.vmMac == nil {
		b.vmMac = &b.podNicLink.Attrs().HardwareAddr
	}

	return nil
}

func (b *MacvtapPodNetworkConfigurator) PreparePodNetworkInterface() error {
	return nil
}

func (b *MacvtapPodNetworkConfigurator) GenerateDomainIfaceSpec() api.Interface {
	return api.Interface{
		MAC: &api.MAC{MAC: b.vmMac.String()},
		MTU: &api.MTU{Size: strconv.Itoa(b.podNicLink.Attrs().MTU)},
		Target: &api.InterfaceTarget{
			Device:  b.podNicLink.Attrs().Name,
			Managed: "no",
		},
	}
}

func (b *MacvtapPodNetworkConfigurator) GenerateDHCPConfig() *cache.DHCPConfig {
	return nil
}
<|endoftext|>


<commit_before>package network

import (
	"errors"
	"fmt"

	"github.com/spf13/cobra"

	kerrors "k8s.io/apimachinery/pkg/util/errors"
	"k8s.io/cli-runtime/pkg/genericclioptions"
	kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
	"k8s.io/kubernetes/pkg/kubectl/util/templates"

	"github.com/openshift/library-go/pkg/network/networkapihelpers"
	"github.com/openshift/origin/pkg/network"
)

const JoinProjectsNetworkCommandName = "join-projects"

var (
	joinProjectsNetworkLong = templates.LongDesc(`
		Join project network

		Allows projects to join existing project network when using the %[1]s network plugin.`)

	joinProjectsNetworkExample = templates.Examples(`
		# Allow project p2 to use project p1 network
		%[1]s --to=<p1> <p2>

		# Allow all projects with label name=top-secret to use project p1 network
		%[1]s --to=<p1> --selector='name=top-secret'`)
)

type JoinOptions struct {
	Options *ProjectOptions

	joinProjectName string
}

func NewJoinOptions(streams genericclioptions.IOStreams) *JoinOptions {
	return &JoinOptions{
		Options: NewProjectOptions(streams),
	}
}

func NewCmdJoinProjectsNetwork(commandName, fullName string, f kcmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
	o := NewJoinOptions(streams)
	cmd := &cobra.Command{
		Use:     commandName,
		Short:   "Join project network",
		Long:    fmt.Sprintf(joinProjectsNetworkLong, network.MultiTenantPluginName),
		Example: fmt.Sprintf(joinProjectsNetworkExample, fullName),
		Run: func(c *cobra.Command, args []string) {
			kcmdutil.CheckErr(o.Complete(f, c, args))
			kcmdutil.CheckErr(o.Validate())
			kcmdutil.CheckErr(o.Run())
		},
	}
	// Supported operations
	cmd.Flags().StringVar(&o.joinProjectName, "to", o.joinProjectName, "Join network of the given project name")

	// Common optional params
	cmd.Flags().StringVar(&o.Options.Selector, "selector", o.Options.Selector, "Label selector to filter projects. Either pass one/more projects as arguments or use this project selector")

	return cmd
}

func (o *JoinOptions) Complete(f kcmdutil.Factory, c *cobra.Command, args []string) error {
	if err := o.Options.Complete(f, c, args); err != nil {
		return err
	}
	o.Options.CheckSelector = c.Flag("selector").Changed
	return nil
}

func (o *JoinOptions) Validate() error {
	errList := []error{}
	if err := o.Options.Validate(); err != nil {
		errList = append(errList, err)
	}
	if len(o.joinProjectName) == 0 {
		errList = append(errList, errors.New("must provide --to=<project_name>"))
	}
	return kerrors.NewAggregate(errList)
}

func (o *JoinOptions) Run() error {
	projects, err := o.Options.GetProjects()
	if err != nil {
		return err
	}

	errList := []error{}
	for _, project := range projects {
		if project.Name != o.joinProjectName {
			if err = o.Options.UpdatePodNetwork(project.Name, networkapihelpers.JoinPodNetwork, o.joinProjectName); err != nil {
				errList = append(errList, fmt.Errorf("project %q failed to join %q, error: %v", project.Name, o.joinProjectName, err))
			}
		}
	}
	return kerrors.NewAggregate(errList)
}
<commit_msg>BZ 1592217 Correct error message when joining two projects<commit_after>package network

import (
	"errors"
	"fmt"

	"github.com/spf13/cobra"

	kerrors "k8s.io/apimachinery/pkg/util/errors"
	"k8s.io/cli-runtime/pkg/genericclioptions"
	kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
	"k8s.io/kubernetes/pkg/kubectl/util/templates"

	"github.com/openshift/library-go/pkg/network/networkapihelpers"
	"github.com/openshift/origin/pkg/network"
)

const JoinProjectsNetworkCommandName = "join-projects"

var (
	joinProjectsNetworkLong = templates.LongDesc(`
		Join project network

		Allows projects to join existing project network when using the %[1]s network plugin.`)

	joinProjectsNetworkExample = templates.Examples(`
		# Allow project p2 to use project p1 network
		%[1]s --to=<p1> <p2>

		# Allow all projects with label name=top-secret to use project p1 network
		%[1]s --to=<p1> --selector='name=top-secret'`)
)

type JoinOptions struct {
	Options     *ProjectOptions
	JoinProject *ProjectOptions

	joinProjectName string
}

func NewJoinOptions(streams genericclioptions.IOStreams) *JoinOptions {
	return &JoinOptions{
		Options:     NewProjectOptions(streams),
		JoinProject: NewProjectOptions(streams),
	}
}

func NewCmdJoinProjectsNetwork(commandName, fullName string, f kcmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
	o := NewJoinOptions(streams)
	cmd := &cobra.Command{
		Use:     commandName,
		Short:   "Join project network",
		Long:    fmt.Sprintf(joinProjectsNetworkLong, network.MultiTenantPluginName),
		Example: fmt.Sprintf(joinProjectsNetworkExample, fullName),
		Run: func(c *cobra.Command, args []string) {
			kcmdutil.CheckErr(o.Complete(f, c, args))
			kcmdutil.CheckErr(o.Validate())
			kcmdutil.CheckErr(o.Run())
		},
	}
	// Supported operations
	cmd.Flags().StringVar(&o.joinProjectName, "to", o.joinProjectName, "Join network of the given project name")

	// Common optional params
	cmd.Flags().StringVar(&o.Options.Selector, "selector", o.Options.Selector, "Label selector to filter projects. Either pass one/more projects as arguments or use this project selector")

	return cmd
}

func (o *JoinOptions) Complete(f kcmdutil.Factory, c *cobra.Command, args []string) error {
	if err := o.Options.Complete(f, c, args); err != nil {
		return err
	}
	if err := o.JoinProject.Complete(f, c, []string{o.joinProjectName}); err != nil {
		return err
	}
	o.Options.CheckSelector = c.Flag("selector").Changed
	return nil
}

func (o *JoinOptions) Validate() error {
	errList := []error{}
	if err := o.Options.Validate(); err != nil {
		errList = append(errList, err)
	}
	if len(o.joinProjectName) == 0 {
		errList = append(errList, errors.New("must provide --to=<project_name>"))
	}
	return kerrors.NewAggregate(errList)
}

func (o *JoinOptions) Run() error {
	projects, err := o.Options.GetProjects()
	if err != nil {
		return err
	}
	_, err = o.JoinProject.GetProjects()
	if err != nil {
		return err
	}

	errList := []error{}
	for _, project := range projects {
		if project.Name != o.joinProjectName {
			if err = o.Options.UpdatePodNetwork(project.Name, networkapihelpers.JoinPodNetwork, o.joinProjectName); err != nil {
				errList = append(errList, fmt.Errorf("project %q failed to join %q, error: %v", project.Name, o.joinProjectName, err))
			}
		}
	}
	return kerrors.NewAggregate(errList)
}
<|endoftext|>


<commit_before>/*
   Nging is a toolbox for webmasters
   Copyright (C) 2018-present  Wenhui Shen <swh@admpub.com>

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as published
   by the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Affero General Public License for more details.

   You should have received a copy of the GNU Affero General Public License
   along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

package common

import (
	"encoding/gob"
	"errors"
	"strings"

	"github.com/webx-top/echo"
	"github.com/webx-top/echo/code"
)

func init() {
	gob.Register(&Success{})
}

var (
	// - JSON

	//ErrUserNotLoggedIn 用户未登录
	ErrUserNotLoggedIn = echo.NewError(`User not logged in`, code.Unauthenticated)
	//ErrUserNotFound 用户不存在
	ErrUserNotFound = echo.NewError(`User does not exist`, code.UserNotFound)
	//ErrUserNoPerm 用户无权限
	ErrUserNoPerm = echo.NewError(`User has no permission`, code.NonPrivileged)
	//ErrUserDisabled 用户已被禁用
	ErrUserDisabled = echo.NewError(`User has been disabled`, code.UserDisabled)
	//ErrBalanceNoEnough 余额不足
	ErrBalanceNoEnough = echo.NewError(`Balance is not enough`, code.BalanceNoEnough)
	//ErrCaptcha 验证码错误
	ErrCaptcha = echo.NewError(`Captcha is incorrect`, code.CaptchaError)
	//ErrCaptchaIdMissing 缺少captchaId
	ErrCaptchaIdMissing = echo.NewError(`Missing captchaId`, code.CaptchaIdMissing).SetZone(`captchaId`)
	//ErrInvalidAppID App ID 无效
	ErrInvalidAppID = echo.NewError(`Invalid app id`, code.InvalidAppID)
	//ErrInvalidSign 无效签名
	ErrInvalidSign = echo.NewError(`Invalid sign`, code.InvalidSignature)
	//ErrInvalidToken 令牌无效
	ErrInvalidToken = echo.NewError(`Invalid token`, code.InvalidToken)

	// - Operation

	//ErrRepeatOperation 重复操作
	ErrRepeatOperation = echo.NewError(`Repeat operation`, code.RepeatOperation)
	//ErrUnsupported 不支持
	ErrUnsupported = echo.NewError(`Unsupported`, code.Unsupported)
	//ErrOperationTimeout 操作超时
	ErrOperationTimeout = echo.NewError(`Operation timeout`, code.OperationTimeout)
	//ErrOperationFail 操作失败
	ErrOperationFail = echo.NewError(`Operation fail`, code.Failure)

	// - HTTP

	//ErrResponseFormatError 响应格式错误
	ErrResponseFormatError = echo.NewError(`Response format error`, code.AbnormalResponse)
	//ErrRequestTimeout 提交超时
	ErrRequestTimeout = echo.NewError(`Request timeout`, code.RequestTimeout)
	//ErrRequestFail 提交失败
	ErrRequestFail = echo.NewError(`Request fail`, code.RequestFailure)

	// - Watcher

	// ErrIgnoreConfigChange 忽略配置文件更改
	ErrIgnoreConfigChange = errors.New(`Ignore configuration file changes`)

	// - Checker

	// ErrNext 需要继续向下检查
	ErrNext = errors.New("Next")
)

// DefaultNopMessage 默认空消息
var DefaultNopMessage Messager = &NopMessage{}

// Errors 多个错误信息
type Errors []error

func (e Errors) Error() string {
	s := make([]string, len(e))
	for k, v := range e {
		s[k] = v.Error()
	}
	return strings.Join(s, "\n")
}

func (e Errors) String() string {
	return e.Error()
}

// NopMessage 空消息
type NopMessage struct {
}

// Error 错误信息
func (n *NopMessage) Error() string {
	return ``
}

// Success 成功信息
func (n *NopMessage) Success() string {
	return ``
}

// String 信息字符串
func (n *NopMessage) String() string {
	return ``
}

// Messager 信息接口
type Messager interface {
	Successor
	error
}

// IsMessage 判断err是否为Message
func IsMessage(err interface{}) bool {
	_, y := err.(Messager)
	return y
}

// Message 获取err中的信息接口
func Message(err interface{}) Messager {
	if v, y := err.(Messager); y {
		return v
	}
	return DefaultNopMessage
}

// NewOk 创建成功信息
func NewOk(v string) Successor {
	return &Success{
		Value: v,
	}
}

// Success 成功信息
type Success struct {
	Value string
}

// Success 成功信息
func (s *Success) Success() string {
	return s.Value
}

func (s *Success) String() string {
	return s.Value
}

// Successor 成功信息接口
type Successor interface {
	Success() string
}

// IsError 是否是错误信息
func IsError(err interface{}) bool {
	_, y := err.(error)
	return y
}

// IsOk 是否是成功信息
func IsOk(err interface{}) bool {
	_, y := err.(Successor)
	return y
}

// OkString 获取成功信息
func OkString(err interface{}) string {
	if v, y := err.(Successor); y {
		return v.Success()
	}
	return ``
}
<commit_msg>update<commit_after>/*
   Nging is a toolbox for webmasters
   Copyright (C) 2018-present  Wenhui Shen <swh@admpub.com>

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as published
   by the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Affero General Public License for more details.

   You should have received a copy of the GNU Affero General Public License
   along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

package common

import (
	"encoding/gob"
	"errors"
	"strings"

	"github.com/webx-top/echo"
	"github.com/webx-top/echo/code"
)

func init() {
	gob.Register(&Success{})
}

var (
	// - JSON

	//ErrUserNotLoggedIn 用户未登录
	ErrUserNotLoggedIn = echo.NewError(`User not logged in`, code.Unauthenticated)
	//ErrUserNotFound 用户不存在
	ErrUserNotFound = echo.NewError(`User does not exist`, code.UserNotFound)
	//ErrUserNoPerm 用户无权限
	ErrUserNoPerm = echo.NewError(`User has no permission`, code.NonPrivileged)
	//ErrUserDisabled 用户已被禁用
	ErrUserDisabled = echo.NewError(`User has been disabled`, code.UserDisabled)
	//ErrBalanceNoEnough 余额不足
	ErrBalanceNoEnough = echo.NewError(`Balance is not enough`, code.BalanceNoEnough)
	//ErrCaptcha 验证码错误
	ErrCaptcha = echo.NewError(`Captcha is incorrect`, code.CaptchaError)
	//ErrCaptchaIdMissing 缺少captchaId
	ErrCaptchaIdMissing = echo.NewError(`Missing captchaId`, code.CaptchaIdMissing).SetZone(`captchaId`)
	//ErrInvalidAppID App ID 无效
	ErrInvalidAppID = echo.NewError(`Invalid app id`, code.InvalidAppID)
	//ErrInvalidSign 无效签名
	ErrInvalidSign = echo.NewError(`Invalid sign`, code.InvalidSignature)
	//ErrInvalidToken 令牌无效
	ErrInvalidToken = echo.NewError(`Invalid token`, code.InvalidToken)

	// - Operation

	//ErrRepeatOperation 重复操作
	ErrRepeatOperation = echo.NewError(`Repeat operation`, code.RepeatOperation)
	//ErrUnsupported 不支持
	ErrUnsupported = echo.NewError(`Unsupported`, code.Unsupported)
	//ErrOperationTimeout 操作超时
	ErrOperationTimeout = echo.NewError(`Operation timeout`, code.OperationTimeout)
	//ErrOperationFail 操作失败
	ErrOperationFail = echo.NewError(`Operation fail`, code.Failure)

	// - HTTP

	//ErrResponseFormatError 响应格式错误
	ErrResponseFormatError = echo.NewError(`Response format error`, code.AbnormalResponse)
	//ErrRequestTimeout 提交超时
	ErrRequestTimeout = echo.NewError(`Request timeout`, code.RequestTimeout)
	//ErrRequestFail 提交失败
	ErrRequestFail = echo.NewError(`Request fail`, code.RequestFailure)

	// - Watcher

	// ErrIgnoreConfigChange 忽略配置文件更改
	ErrIgnoreConfigChange = errors.New(`Ignore configuration file changes`)

	// - Checker

	// ErrNext 需要继续向下检查
	ErrNext           = errors.New("Next")
	ErrConcurrentLock = errors.New("Concurrent lock has been triggered")
)

// DefaultNopMessage 默认空消息
var DefaultNopMessage Messager = &NopMessage{}

// Errors 多个错误信息
type Errors []error

func (e Errors) Error() string {
	s := make([]string, len(e))
	for k, v := range e {
		s[k] = v.Error()
	}
	return strings.Join(s, "\n")
}

func (e Errors) String() string {
	return e.Error()
}

// NopMessage 空消息
type NopMessage struct {
}

// Error 错误信息
func (n *NopMessage) Error() string {
	return ``
}

// Success 成功信息
func (n *NopMessage) Success() string {
	return ``
}

// String 信息字符串
func (n *NopMessage) String() string {
	return ``
}

// Messager 信息接口
type Messager interface {
	Successor
	error
}

// IsMessage 判断err是否为Message
func IsMessage(err interface{}) bool {
	_, y := err.(Messager)
	return y
}

// Message 获取err中的信息接口
func Message(err interface{}) Messager {
	if v, y := err.(Messager); y {
		return v
	}
	return DefaultNopMessage
}

// NewOk 创建成功信息
func NewOk(v string) Successor {
	return &Success{
		Value: v,
	}
}

// Success 成功信息
type Success struct {
	Value string
}

// Success 成功信息
func (s *Success) Success() string {
	return s.Value
}

func (s *Success) String() string {
	return s.Value
}

// Successor 成功信息接口
type Successor interface {
	Success() string
}

// IsError 是否是错误信息
func IsError(err interface{}) bool {
	_, y := err.(error)
	return y
}

// IsOk 是否是成功信息
func IsOk(err interface{}) bool {
	_, y := err.(Successor)
	return y
}

// OkString 获取成功信息
func OkString(err interface{}) string {
	if v, y := err.(Successor); y {
		return v.Success()
	}
	return ``
}
<|endoftext|>


<commit_before>package compress

import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"strings"
)

const (
	Unknown    Format = iota // unknown format
	GZip                     // Gzip compression format
	BZip2                    // Bzip2 compression
	LZ4                      // LZ4 compression
	Tar                      // Tar format; normally used
	Tar1                     // Tar1 magicnum format; normalizes to Tar
	Tar2                     // Tar1 magicnum format; normalizes to Tar
	Zip                      // Zip archive
	ZipEmpty                 // Empty Zip Archive
	ZipSpanned               // Spanned Zip Archive
)

// Magic numbers for compression and archive formats
var (
	magicnumGZip       = []byte{0x1f, 0x8b}
	magicnumBZip2      = []byte{0x42, 0x5a, 0x68}
	magicnumLZ4        = []byte{0x18, 0x4d, 0x22, 0x04}
	magicnumTar1       = []byte{0x75, 0x73, 0x74, 0x61, 0x72, 0x00, 0x30, 0x30} // offset: 257
	magicnumTar2       = []byte{0x75, 0x73, 0x74, 0x61, 0x72, 0x00, 0x20, 0x00} // offset: 257
	magicnumZip        = []byte{0x50, 0x4b, 0x03, 0x04}
	magicnumZipEmpty   = []byte{0x50, 0x4b, 0x05, 0x06}
	magicnumZipSpanned = []byte{0x50, 0x4b, 0x07, 0x08}
	//magicnumLZW        = []byte{0x1F, 0x9d}
)

var (
	ErrUnknown = errors.New("unknown compression format")
	ErrEmpty   = errors.New("no data to read")
)

type Format int

const formatName = "UnknownGZipBZip2LZ4TarTar1Tar2ZipEmpty ZipSpanned Zip"

var formatIndex = [...]uint8{0, 7, 11, 16, 19, 22, 26, 30, 33, 42, 53}

func (i Format) String() string {
	if i < 0 || i >= Format(len(formatIndex)-1) {
		return fmt.Sprintf("Format(%d)", i)
	}
	return formatName[formatIndex[i]:formatIndex[i+1]]
}

// Ext returns the extension for the format. Formats may have more than one
// accepted extension; alternate extensiona are not supported.
func (f Format) Ext() string {
	switch f {
	case GZip:
		return ".gz"
	case BZip2:
		return ".bz2"
	case LZ4:
		return ".lz4"
	case Tar, Tar1, Tar2:
		return ".tar"
	case Zip, ZipEmpty, ZipSpanned:
		return ".zip"
		//case LZW:
		//	return ".Z"
	}
	return "unknown"
}

// ParseFormat takes a string and returns the format or unknown. Any compressed
// tar extensions are returned as the compression format and not tar.
//
// If the passed string starts with a '.', it is removed.
// All strings are lowercased
func ParseFormat(s string) Format {
	if len(s) == 0 {
		return Unknown
	}
	if s[0] == '.' {
		s = s[1:]
	}
	s = strings.ToLower(s)
	switch s {
	case "gzip", "tar.gz", "tgz":
		return GZip
	case "tar":
		return Tar
	case "bz2", "tbz", "tb2", "tbz2", "tar.bz2":
		return BZip2
	case "lz4", "tar.lz4", "tz4":
		return LZ4
	case "zip":
		return Zip
	}
	return Unknown
}

// GetFormat tries to match up the data in the Reader to a supported
// magic number, if a match isn't found, UnsupportedFmt is returned
//
// For zips, this will also match on files with empty zip or spanned zip magic
// numbers.  If you need to distinguich between the various zip formats, use
// something else.
func GetFormat(r io.ReaderAt) (Format, error) {
	// see if the reader contains anything
	b := make([]byte, 1)
	if _, err := r.ReadAt(b, 0); err == io.EOF {
		return Unknown, ErrEmpty
	}
	ok, err := IsLZ4(r)
	if err != nil {
		return Unknown, err
	}
	if ok {
		return LZ4, nil
	}
	ok, err = IsGZip(r)
	if err != nil {
		return Unknown, err
	}
	if ok {
		return GZip, nil
	}
	ok, err = IsZip(r)
	if err != nil {
		return Unknown, err
	}
	if ok {
		return Zip, nil
	}
	ok, err = IsTar(r)
	if err != nil {
		return Unknown, err
	}
	if ok {
		return Tar, nil
	}
	ok, err = IsBZip2(r)
	if err != nil {
		return Unknown, err
	}
	if ok {
		return BZip2, nil
	}
	//ok, err = IsLZW(r)
	//if err != nil {
	//	return Unknown, err
	//}
	//if ok {
	//	return LZW, nil
	//}
	return Unknown, ErrUnknown
}

// IsBZip2 checks to see if the received reader's contents are in bzip2 format
// by checking the magic numbers.
func IsBZip2(r io.ReaderAt) (bool, error) {
	h := make([]byte, 3)
	// Read the first 3 bytes
	_, err := r.ReadAt(h, 0)
	if err != nil {
		return false, err
	}
	var hb [3]byte
	// check for bzip2
	hbuf := bytes.NewReader(h)
	err = binary.Read(hbuf, binary.LittleEndian, &hb)
	if err != nil {
		return false, fmt.Errorf("error while checking if input matched bzip2's magic number: %s", err)
	}
	var cb [3]byte
	cbuf := bytes.NewBuffer(magicnumBZip2)
	err = binary.Read(cbuf, binary.BigEndian, &cb)
	if err != nil {
		return false, fmt.Errorf("error while converting bzip2 magic number for comparison: %s", err)
	}
	if hb == cb {
		return true, nil
	}
	return false, nil
}

// IsGZip checks to see if the received reader's contents are in gzip format
// by checking the magic numbers.
func IsGZip(r io.ReaderAt) (bool, error) {
	h := make([]byte, 2)
	// Read the first 2 bytes
	_, err := r.ReadAt(h, 0)
	if err != nil {
		return false, err
	}
	var h16 uint16
	// check for gzip
	hbuf := bytes.NewReader(h)
	err = binary.Read(hbuf, binary.BigEndian, &h16)
	if err != nil {
		return false, fmt.Errorf("error while checking if input matched bzip2's magic number: %s", err)
	}
	var c16 uint16
	cbuf := bytes.NewBuffer(magicnumGZip)
	err = binary.Read(cbuf, binary.BigEndian, &c16)
	if err != nil {
		return false, fmt.Errorf("error while converting bzip2 magic number for comparison: %s", err)
	}
	if h16 == c16 {
		return true, nil
	}
	return false, nil
}

// IsLZ4 checks to see if the received reader's contents are in LZ4 foramt by
// checking the magic numbers.
func IsLZ4(r io.ReaderAt) (bool, error) {
	h := make([]byte, 4)
	// Read the first 4 bytes
	_, err := r.ReadAt(h, 0)
	if err != nil {
		return false, err
	}
	var h32 uint32
	// check for lz4
	hbuf := bytes.NewReader(h)
	err = binary.Read(hbuf, binary.LittleEndian, &h32)
	if err != nil {
		return false, fmt.Errorf("error while checking if input matched LZ4's magic number: %s", err)
	}
	var c32 uint32
	cbuf := bytes.NewBuffer(magicnumLZ4)
	err = binary.Read(cbuf, binary.BigEndian, &c32)
	if err != nil {
		return false, fmt.Errorf("error while converting LZ4 magic number for comparison: %s", err)
	}
	if h32 == c32 {
		return true, nil
	}
	return false, nil
}

// IsLZW checks to see if the received reader's contents are in LZ4 format by
// checking the magic numbers.
//
// TODO: unsupported until I have a better understanding of how to handle LZW
/*
func IsLZW(r io.ReaderAt) (bool, error) {
	h := make([]byte, 2)
	// Reat the first 8 bytes since that's where most magic numbers are
	_, err := r.ReadAt(h, 0)
	if err != nil {
		return false, err
	}
	var h16 uint16
	// check for lzw
	hbuf := bytes.NewReader(h)
	err = binary.Read(hbuf, binary.LittleEndian, &h16)
	if err != nil {
		return false, fmt.Errorf("error while checking if input matched LZW's magic number: %s", err)
	}
	var c16 uint16
	cbuf := bytes.NewBuffer(magicnumLZW)
	err = binary.Read(cbuf, binary.BigEndian, &c16)
	if err != nil {
		return false, fmt.Errorf("error while converting LZW magic number for comparison: %s", err)
	}
	if h16 == c16 {
		return true, nil
	}
	return false, nil
}
*/

// IsTar checks to see if the received reader's contents are in the tar format
// by checking the magic numbers. This evaluates using both tar1 and tar2 magic
// numbers.
func IsTar(r io.ReaderAt) (bool, error) {
	h := make([]byte, 8)
	// Read the first 8 bytes at offset 257
	_, err := r.ReadAt(h, 257)
	if err != nil {
		return false, err
	}
	var h64 uint64
	// check for Zip
	hbuf := bytes.NewReader(h)
	err = binary.Read(hbuf, binary.BigEndian, &h64)
	if err != nil {
		return false, fmt.Errorf("error while checking if input matched tar's magic number: %s", err)
	}
	var c64 uint64
	cbuf := bytes.NewBuffer(magicnumTar1)
	err = binary.Read(cbuf, binary.BigEndian, &c64)
	if err != nil {
		return false, fmt.Errorf("error while converting the tar magic number for comparison: %s", err)
	}
	if h64 == c64 {
		return true, nil
	}
	cbuf = bytes.NewBuffer(magicnumTar2)
	err = binary.Read(cbuf, binary.BigEndian, &c64)
	if err != nil {
		return false, fmt.Errorf("error while converting the empty tar magic number for comparison: %s", err)
	}
	if h64 == c64 {
		return true, nil
	}
	return false, nil
}

// IsZip checks to see if the received reader's contents are in the zip format
// by checking the magic numbers. This will match on zip, empty zip and spanned
// zip magic numbers. If you need to distinguish between those, use something
// else.
func IsZip(r io.ReaderAt) (bool, error) {
	h := make([]byte, 4)
	// Read the first 4 bytes
	_, err := r.ReadAt(h, 0)
	if err != nil {
		return false, err
	}
	var h32 uint32
	// check for Zip
	hbuf := bytes.NewReader(h)
	err = binary.Read(hbuf, binary.BigEndian, &h32)
	if err != nil {
		return false, fmt.Errorf("error while checking if input matched zip's magic number: %s", err)
	}
	var c32 uint32
	cbuf := bytes.NewBuffer(magicnumZip)
	err = binary.Read(cbuf, binary.BigEndian, &c32)
	if err != nil {
		return false, fmt.Errorf("error while converting the zip magic number for comparison: %s", err)
	}
	if h32 == c32 {
		return true, nil
	}
	cbuf = bytes.NewBuffer(magicnumZipEmpty)
	err = binary.Read(cbuf, binary.BigEndian, &c32)
	if err != nil {
		return false, fmt.Errorf("error while converting the empty zip magic number for comparison: %s", err)
	}
	if h32 == c32 {
		return true, nil
	}
	cbuf = bytes.NewBuffer(magicnumZipSpanned)
	err = binary.Read(cbuf, binary.BigEndian, &c32)
	if err != nil {
		return false, fmt.Errorf("error while converting the spanned zip magic number for comparison: %s", err)
	}
	if h32 == c32 {
		return true, nil
	}
	return false, nil
}
<commit_msg>handle empty reader case<commit_after>package compress

import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"strings"
)

const (
	Unknown    Format = iota // unknown format
	GZip                     // Gzip compression format
	BZip2                    // Bzip2 compression
	LZ4                      // LZ4 compression
	Tar                      // Tar format; normally used
	Tar1                     // Tar1 magicnum format; normalizes to Tar
	Tar2                     // Tar1 magicnum format; normalizes to Tar
	Zip                      // Zip archive
	ZipEmpty                 // Empty Zip Archive
	ZipSpanned               // Spanned Zip Archive
)

// Magic numbers for compression and archive formats
var (
	magicnumGZip       = []byte{0x1f, 0x8b}
	magicnumBZip2      = []byte{0x42, 0x5a, 0x68}
	magicnumLZ4        = []byte{0x18, 0x4d, 0x22, 0x04}
	magicnumTar1       = []byte{0x75, 0x73, 0x74, 0x61, 0x72, 0x00, 0x30, 0x30} // offset: 257
	magicnumTar2       = []byte{0x75, 0x73, 0x74, 0x61, 0x72, 0x00, 0x20, 0x00} // offset: 257
	magicnumZip        = []byte{0x50, 0x4b, 0x03, 0x04}
	magicnumZipEmpty   = []byte{0x50, 0x4b, 0x05, 0x06}
	magicnumZipSpanned = []byte{0x50, 0x4b, 0x07, 0x08}
	//magicnumLZW        = []byte{0x1F, 0x9d}
)

var (
	ErrUnknown = errors.New("unknown compression format")
	ErrEmpty   = errors.New("no data to read")
)

type Format int

const formatName = "UnknownGZipBZip2LZ4TarTar1Tar2ZipEmpty ZipSpanned Zip"

var formatIndex = [...]uint8{0, 7, 11, 16, 19, 22, 26, 30, 33, 42, 53}

func (i Format) String() string {
	if i < 0 || i >= Format(len(formatIndex)-1) {
		return fmt.Sprintf("Format(%d)", i)
	}
	return formatName[formatIndex[i]:formatIndex[i+1]]
}

// Ext returns the extension for the format. Formats may have more than one
// accepted extension; alternate extensiona are not supported.
func (f Format) Ext() string {
	switch f {
	case GZip:
		return ".gz"
	case BZip2:
		return ".bz2"
	case LZ4:
		return ".lz4"
	case Tar, Tar1, Tar2:
		return ".tar"
	case Zip, ZipEmpty, ZipSpanned:
		return ".zip"
		//case LZW:
		//	return ".Z"
	}
	return "unknown"
}

// ParseFormat takes a string and returns the format or unknown. Any compressed
// tar extensions are returned as the compression format and not tar.
//
// If the passed string starts with a '.', it is removed.
// All strings are lowercased
func ParseFormat(s string) Format {
	if len(s) == 0 {
		return Unknown
	}
	if s[0] == '.' {
		s = s[1:]
	}
	s = strings.ToLower(s)
	switch s {
	case "gzip", "tar.gz", "tgz":
		return GZip
	case "tar":
		return Tar
	case "bz2", "tbz", "tb2", "tbz2", "tar.bz2":
		return BZip2
	case "lz4", "tar.lz4", "tz4":
		return LZ4
	case "zip":
		return Zip
	}
	return Unknown
}

// GetFormat tries to match up the data in the Reader to a supported
// magic number, if a match isn't found, UnsupportedFmt is returned
//
// For zips, this will also match on files with empty zip or spanned zip magic
// numbers.  If you need to distinguich between the various zip formats, use
// something else.
func GetFormat(r io.ReaderAt) (Format, error) {
	// see if the reader contains anything
	b := make([]byte, 1)
	if _, err := r.ReadAt(b, 0); err == io.EOF {
		return Unknown, ErrEmpty
	}

	ok, err := IsLZ4(r)
	if err != nil {
		return Unknown, err
	}
	if ok {
		return LZ4, nil
	}
	ok, err = IsGZip(r)
	if err != nil {
		return Unknown, err
	}
	if ok {
		return GZip, nil
	}
	ok, err = IsZip(r)
	if err != nil {
		return Unknown, err
	}
	if ok {
		return Zip, nil
	}
	ok, err = IsTar(r)
	if err != nil {
		return Unknown, err
	}
	if ok {
		return Tar, nil
	}
	ok, err = IsBZip2(r)
	if err != nil {
		return Unknown, err
	}
	if ok {
		return BZip2, nil
	}
	//ok, err = IsLZW(r)
	//if err != nil {
	//	return Unknown, err
	//}
	//if ok {
	//	return LZW, nil
	//}
	return Unknown, ErrUnknown
}

// IsBZip2 checks to see if the received reader's contents are in bzip2 format
// by checking the magic numbers.
func IsBZip2(r io.ReaderAt) (bool, error) {
	h := make([]byte, 3)
	// Read the first 3 bytes
	_, err := r.ReadAt(h, 0)
	if err != nil {
		return false, err
	}
	var hb [3]byte
	// check for bzip2
	hbuf := bytes.NewReader(h)
	err = binary.Read(hbuf, binary.LittleEndian, &hb)
	if err != nil {
		return false, fmt.Errorf("error while checking if input matched bzip2's magic number: %s", err)
	}
	var cb [3]byte
	cbuf := bytes.NewBuffer(magicnumBZip2)
	err = binary.Read(cbuf, binary.BigEndian, &cb)
	if err != nil {
		return false, fmt.Errorf("error while converting bzip2 magic number for comparison: %s", err)
	}
	if hb == cb {
		return true, nil
	}
	return false, nil
}

// IsGZip checks to see if the received reader's contents are in gzip format
// by checking the magic numbers.
func IsGZip(r io.ReaderAt) (bool, error) {
	h := make([]byte, 2)
	// Read the first 2 bytes
	_, err := r.ReadAt(h, 0)
	if err != nil {
		return false, err
	}
	var h16 uint16
	// check for gzip
	hbuf := bytes.NewReader(h)
	err = binary.Read(hbuf, binary.BigEndian, &h16)
	if err != nil {
		return false, fmt.Errorf("error while checking if input matched bzip2's magic number: %s", err)
	}
	var c16 uint16
	cbuf := bytes.NewBuffer(magicnumGZip)
	err = binary.Read(cbuf, binary.BigEndian, &c16)
	if err != nil {
		return false, fmt.Errorf("error while converting bzip2 magic number for comparison: %s", err)
	}
	if h16 == c16 {
		return true, nil
	}
	return false, nil
}

// IsLZ4 checks to see if the received reader's contents are in LZ4 foramt by
// checking the magic numbers.
func IsLZ4(r io.ReaderAt) (bool, error) {
	h := make([]byte, 4)
	// Read the first 4 bytes
	_, err := r.ReadAt(h, 0)
	if err != nil {
		return false, err
	}
	var h32 uint32
	// check for lz4
	hbuf := bytes.NewReader(h)
	err = binary.Read(hbuf, binary.LittleEndian, &h32)
	if err != nil {
		return false, fmt.Errorf("error while checking if input matched LZ4's magic number: %s", err)
	}
	var c32 uint32
	cbuf := bytes.NewBuffer(magicnumLZ4)
	err = binary.Read(cbuf, binary.BigEndian, &c32)
	if err != nil {
		return false, fmt.Errorf("error while converting LZ4 magic number for comparison: %s", err)
	}
	if h32 == c32 {
		return true, nil
	}
	return false, nil
}

// IsLZW checks to see if the received reader's contents are in LZ4 format by
// checking the magic numbers.
//
// TODO: unsupported until I have a better understanding of how to handle LZW
/*
func IsLZW(r io.ReaderAt) (bool, error) {
	h := make([]byte, 2)
	// Reat the first 8 bytes since that's where most magic numbers are
	_, err := r.ReadAt(h, 0)
	if err != nil {
		return false, err
	}
	var h16 uint16
	// check for lzw
	hbuf := bytes.NewReader(h)
	err = binary.Read(hbuf, binary.LittleEndian, &h16)
	if err != nil {
		return false, fmt.Errorf("error while checking if input matched LZW's magic number: %s", err)
	}
	var c16 uint16
	cbuf := bytes.NewBuffer(magicnumLZW)
	err = binary.Read(cbuf, binary.BigEndian, &c16)
	if err != nil {
		return false, fmt.Errorf("error while converting LZW magic number for comparison: %s", err)
	}
	if h16 == c16 {
		return true, nil
	}
	return false, nil
}
*/

// IsTar checks to see if the received reader's contents are in the tar format
// by checking the magic numbers. This evaluates using both tar1 and tar2 magic
// numbers.
func IsTar(r io.ReaderAt) (bool, error) {
	h := make([]byte, 8)
	// Read the first 8 bytes at offset 257
	_, err := r.ReadAt(h, 257)
	if err != nil {
		return false, err
	}
	var h64 uint64
	// check for Zip
	hbuf := bytes.NewReader(h)
	err = binary.Read(hbuf, binary.BigEndian, &h64)
	if err != nil {
		return false, fmt.Errorf("error while checking if input matched tar's magic number: %s", err)
	}
	var c64 uint64
	cbuf := bytes.NewBuffer(magicnumTar1)
	err = binary.Read(cbuf, binary.BigEndian, &c64)
	if err != nil {
		return false, fmt.Errorf("error while converting the tar magic number for comparison: %s", err)
	}
	if h64 == c64 {
		return true, nil
	}
	cbuf = bytes.NewBuffer(magicnumTar2)
	err = binary.Read(cbuf, binary.BigEndian, &c64)
	if err != nil {
		return false, fmt.Errorf("error while converting the empty tar magic number for comparison: %s", err)
	}
	if h64 == c64 {
		return true, nil
	}
	return false, nil
}

// IsZip checks to see if the received reader's contents are in the zip format
// by checking the magic numbers. This will match on zip, empty zip and spanned
// zip magic numbers. If you need to distinguish between those, use something
// else.
func IsZip(r io.ReaderAt) (bool, error) {
	h := make([]byte, 4)
	// Read the first 4 bytes
	_, err := r.ReadAt(h, 0)
	if err != nil {
		return false, err
	}
	var h32 uint32
	// check for Zip
	hbuf := bytes.NewReader(h)
	err = binary.Read(hbuf, binary.BigEndian, &h32)
	if err != nil {
		return false, fmt.Errorf("error while checking if input matched zip's magic number: %s", err)
	}
	var c32 uint32
	cbuf := bytes.NewBuffer(magicnumZip)
	err = binary.Read(cbuf, binary.BigEndian, &c32)
	if err != nil {
		return false, fmt.Errorf("error while converting the zip magic number for comparison: %s", err)
	}
	if h32 == c32 {
		return true, nil
	}
	cbuf = bytes.NewBuffer(magicnumZipEmpty)
	err = binary.Read(cbuf, binary.BigEndian, &c32)
	if err != nil {
		return false, fmt.Errorf("error while converting the empty zip magic number for comparison: %s", err)
	}
	if h32 == c32 {
		return true, nil
	}
	cbuf = bytes.NewBuffer(magicnumZipSpanned)
	err = binary.Read(cbuf, binary.BigEndian, &c32)
	if err != nil {
		return false, fmt.Errorf("error while converting the spanned zip magic number for comparison: %s", err)
	}
	if h32 == c32 {
		return true, nil
	}
	return false, nil
}
<|endoftext|>


<commit_before>// Package eventual provides values that eventually have a value.
package eventual

import (
	"sync"
	"sync/atomic"
	"time"
)

const (
	FALSE = 0
	TRUE  = 1
)

// Value is an eventual value, meaning that callers wishing to access the value
// block until the value is available.
type Value interface {
	// Set sets this Value to the given val.
	Set(val interface{})

	// Get gets the value, blocks until timeout for a value to become available if
	// one isn't immediately available.
	Get(timeout time.Duration) (interface{}, bool)
}

// Getter is a functional interface for the Value.Get function
type Getter func(time.Duration) (interface{}, bool)

type value struct {
	val      atomic.Value
	wg       sync.WaitGroup
	updates  chan interface{}
	gotFirst int32
}

// NewValue creates a new Value.
func NewValue() Value {
	v := &value{updates: make(chan interface{})}
	// Start off by incrementing the WaitGroup by 1 to indicate that we haven't
	// gotten the first value yet.
	v.wg.Add(1)
	go v.processUpdates()
	return v
}

// DefaultGetter builds a Getter that always returns the supplied value.
func DefaultGetter(val interface{}) Getter {
	return func(time.Duration) (interface{}, bool) {
		return val, true
	}
}

func (v *value) Set(val interface{}) {
	v.updates <- val
}

func (v *value) processUpdates() {
	for val := range v.updates {
		v.val.Store(val)
		if v.gotFirst == FALSE {
			// Signal to blocking callers that we have the first value
			v.wg.Done()
			v.gotFirst = TRUE
		}
	}
}

func (v *value) Get(timeout time.Duration) (interface{}, bool) {
	if atomic.LoadInt32(&v.gotFirst) == TRUE {
		// Short-cut used once value has been set, to avoid extra goroutine
		return v.val.Load(), true
	}

	valCh := make(chan interface{})
	go func() {
		v.wg.Wait()
		valCh <- v.val.Load()
	}()

	select {
	case val := <-valCh:
		return val, true
	case <-time.After(timeout):
		return nil, false
	}
}
<commit_msg>Fixed data race in eventual<commit_after>// Package eventual provides values that eventually have a value.
package eventual

import (
	"sync"
	"sync/atomic"
	"time"
)

const (
	FALSE = 0
	TRUE  = 1
)

// Value is an eventual value, meaning that callers wishing to access the value
// block until the value is available.
type Value interface {
	// Set sets this Value to the given val.
	Set(val interface{})

	// Get gets the value, blocks until timeout for a value to become available if
	// one isn't immediately available.
	Get(timeout time.Duration) (interface{}, bool)
}

// Getter is a functional interface for the Value.Get function
type Getter func(time.Duration) (interface{}, bool)

type value struct {
	val      atomic.Value
	wg       sync.WaitGroup
	updates  chan interface{}
	gotFirst int32
}

// NewValue creates a new Value.
func NewValue() Value {
	v := &value{updates: make(chan interface{})}
	// Start off by incrementing the WaitGroup by 1 to indicate that we haven't
	// gotten the first value yet.
	v.wg.Add(1)
	go v.processUpdates()
	return v
}

// DefaultGetter builds a Getter that always returns the supplied value.
func DefaultGetter(val interface{}) Getter {
	return func(time.Duration) (interface{}, bool) {
		return val, true
	}
}

func (v *value) Set(val interface{}) {
	v.updates <- val
}

func (v *value) processUpdates() {
	for val := range v.updates {
		v.val.Store(val)
		if v.gotFirst == FALSE {
			// Signal to blocking callers that we have the first value
			v.wg.Done()
			atomic.StoreInt32(&v.gotFirst, TRUE)
		}
	}
}

func (v *value) Get(timeout time.Duration) (interface{}, bool) {
	if atomic.LoadInt32(&v.gotFirst) == TRUE {
		// Short-cut used once value has been set, to avoid extra goroutine
		return v.val.Load(), true
	}

	valCh := make(chan interface{})
	go func() {
		v.wg.Wait()
		valCh <- v.val.Load()
	}()

	select {
	case val := <-valCh:
		return val, true
	case <-time.After(timeout):
		return nil, false
	}
}
<|endoftext|>


<commit_before>package vppcalls

import (
	"fmt"

	govppapi "git.fd.io/govpp.git/api"
	log "github.com/ligato/cn-infra/logging"
)

// VersionInfo contains values returned from ShowVersion
type VersionInfo struct {
	Program        string
	Version        string
	BuildDate      string
	BuildDirectory string
}

// VpeInfo contains information about VPP connection and process.
type VpeInfo struct {
	PID            uint32
	ClientIdx      uint32
	ModuleVersions []ModuleVersion
}

type ModuleVersion struct {
	Name  string
	Major uint32
	Minor uint32
	Patch uint32
}

func (m ModuleVersion) String() string {
	return fmt.Sprintf("%s-%d.%d.%d", m.Name, m.Major, m.Minor, m.Patch)
}

type VpeVppAPI interface {
	GetVersionInfo() (*VersionInfo, error)
	GetVpeInfo() (*VpeInfo, error)
	RunCli(cmd string) (string, error)
}

var Versions = map[string]HandlerVersion{}

type HandlerVersion struct {
	Msgs []govppapi.Message
	New  func(govppapi.Channel) VpeVppAPI
}

func CompatibleVpeHandler(ch govppapi.Channel) VpeVppAPI {
	for ver, h := range Versions {
		if err := ch.CheckCompatiblity(h.Msgs...); err != nil {
			log.Debugf("version %s not compatible", ver)
			continue
		}
		log.Debug("found compatible version:", ver)
		return h.New(ch)
	}
	panic("no compatible version available")
}
<commit_msg>Add some comments<commit_after>package vppcalls

import (
	"fmt"

	govppapi "git.fd.io/govpp.git/api"
	log "github.com/ligato/cn-infra/logging"
)

// VersionInfo contains values returned from ShowVersion
type VersionInfo struct {
	Program        string
	Version        string
	BuildDate      string
	BuildDirectory string
}

// VpeInfo contains information about VPP connection and process.
type VpeInfo struct {
	PID            uint32
	ClientIdx      uint32
	ModuleVersions []ModuleVersion
}

// ModuleVersion contains info about version of particular VPP module.
type ModuleVersion struct {
	Name  string
	Major uint32
	Minor uint32
	Patch uint32
}

func (m ModuleVersion) String() string {
	return fmt.Sprintf("%s-%d.%d.%d", m.Name, m.Major, m.Minor, m.Patch)
}

// VpeVppAPI provides methods for retrieving info and running CLI commands.
type VpeVppAPI interface {
	GetVersionInfo() (*VersionInfo, error)
	GetVpeInfo() (*VpeInfo, error)
	RunCli(cmd string) (string, error)
}

var Versions = map[string]HandlerVersion{}

type HandlerVersion struct {
	Msgs []govppapi.Message
	New  func(govppapi.Channel) VpeVppAPI
}

func CompatibleVpeHandler(ch govppapi.Channel) VpeVppAPI {
	for ver, h := range Versions {
		if err := ch.CheckCompatiblity(h.Msgs...); err != nil {
			log.Debugf("version %s not compatible", ver)
			continue
		}
		log.Debug("found compatible version:", ver)
		return h.New(ch)
	}
	panic("no compatible version available")
}
<|endoftext|>


<commit_before>// Copyright 2016 The Cockroach 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.
//
// Author: Matt Jibson (mjibson@cockroachlabs.com)

// +build acceptance

package acceptance

import "testing"

// TestRuby connects to a cluster with ruby.
func TestRuby(t *testing.T) {
	testDocker(t, "ruby", []string{"ruby", "-e", ruby})
}

const ruby = `
require 'pg'

conn = PG.connect()
res = conn.exec_params('SELECT 1, 2 > $1, $1', [3])
raise 'Unexpected: ' + res.values.to_s unless res.values == [["1", "f", "3"]]
`
<commit_msg>sql: add failure test for ruby<commit_after>// Copyright 2016 The Cockroach 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.
//
// Author: Matt Jibson (mjibson@cockroachlabs.com)

// +build acceptance

package acceptance

import (
	"strings"
	"testing"
)

// TestRuby connects to a cluster with ruby.
func TestRuby(t *testing.T) {
	testDockerSuccess(t, "ruby", []string{"ruby", "-e", strings.Replace(ruby, "%v", "3", 1)})
	testDockerFail(t, "ruby", []string{"ruby", "-e", strings.Replace(ruby, "%v", `"a"`, 1)})
}

const ruby = `
require 'pg'

conn = PG.connect()
res = conn.exec_params('SELECT 1, 2 > $1, $1', [%v])
raise 'Unexpected: ' + res.values.to_s unless res.values == [["1", "f", "3"]]
`
<|endoftext|>


<commit_before>// Copyright 2015 The Cockroach 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.
//
// Author: Peter Mattis (peter@cockroachlabs.com)

package acceptance

import (
	"bytes"
	"crypto/tls"
	"database/sql"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"regexp"
	"strconv"
	"testing"
	"time"

	"github.com/docker/engine-api/types"
	"github.com/docker/engine-api/types/container"

	"github.com/cockroachdb/cockroach/acceptance/cluster"
	"github.com/cockroachdb/cockroach/acceptance/terrafarm"
	"github.com/cockroachdb/cockroach/base"
	"github.com/cockroachdb/cockroach/util"
	"github.com/cockroachdb/cockroach/util/caller"
	"github.com/cockroachdb/cockroach/util/log"
	_ "github.com/cockroachdb/pq"
)

var flagDuration = flag.Duration("d", cluster.DefaultDuration, "duration to run the test")
var flagNodes = flag.Int("nodes", 3, "number of nodes")
var flagStores = flag.Int("stores", 1, "number of stores to use for each node")
var flagRemote = flag.Bool("remote", false, "run the test using terrafarm instead of docker")
var flagCwd = flag.String("cwd", "../cloud/aws", "directory to run terraform from")
var flagKeyName = flag.String("key-name", "", "name of key for remote cluster")
var flagLogDir = flag.String("l", "", "the directory to store log files, relative to the test source")
var flagTestConfigs = flag.Bool("test-configs", false, "instead of using the passed in configuration, use the default "+
	"cluster configurations for each test. This overrides the nodes, stores and duration flags and will run the test "+
	"against a collection of pre-specified cluster configurations.")
var flagConfig = flag.String("config", "", "a json TestConfig proto, see testconfig.proto")

var testFuncRE = regexp.MustCompile("^(Test|Benchmark)")

var stopper = make(chan struct{})

func farmer(t *testing.T) *terrafarm.Farmer {
	if !*flagRemote {
		t.Skip("running in docker mode")
	}
	if *flagKeyName == "" {
		t.Fatal("-key-name is required") // saves a lot of trouble
	}
	logDir := *flagLogDir
	if logDir == "" {
		var err error
		logDir, err = ioutil.TempDir("", "clustertest_")
		if err != nil {
			t.Fatal(err)
		}
	}
	if !filepath.IsAbs(logDir) {
		logDir = filepath.Join(filepath.Clean(os.ExpandEnv("${PWD}")), logDir)
	}
	stores := "ssd=data0"
	for j := 1; j < *flagStores; j++ {
		stores += ",ssd=data" + strconv.Itoa(j)
	}
	f := &terrafarm.Farmer{
		Output:  os.Stderr,
		Cwd:     *flagCwd,
		LogDir:  logDir,
		KeyName: *flagKeyName,
		Stores:  stores,
	}
	log.Infof("logging to %s", logDir)
	return f
}

// readConfigFromFlags will convert the flags to a TestConfig for the purposes
// of starting up a cluster.
func readConfigFromFlags() cluster.TestConfig {
	return cluster.TestConfig{
		Name:     fmt.Sprintf("AdHoc %dx%d", *flagNodes, *flagStores),
		Duration: *flagDuration,
		Nodes: []cluster.NodeConfig{
			{
				Count:  int32(*flagNodes),
				Stores: []cluster.StoreConfig{{Count: int32(*flagStores)}},
			},
		},
	}
}

// getConfigs returns a list of test configs based on the passed in flags.
func getConfigs(t *testing.T) []cluster.TestConfig {
	// If a config not supplied, just read the flags.
	if (flagConfig == nil || len(*flagConfig) == 0) &&
		(flagTestConfigs == nil || !*flagTestConfigs) {
		return []cluster.TestConfig{readConfigFromFlags()}
	}

	var configs []cluster.TestConfig
	if flagTestConfigs != nil && *flagTestConfigs {
		configs = append(configs, cluster.DefaultConfigs()...)
	}

	if flagConfig != nil && len(*flagConfig) > 0 {
		// Read the passed in config from the command line.
		var config cluster.TestConfig
		if err := json.Unmarshal([]byte(*flagConfig), &config); err != nil {
			t.Error(err)
		}
		configs = append(configs, config)
	}

	// Override duration in all configs if the flags are set.
	for i := 0; i < len(configs); i++ {
		// Override values.
		if flagDuration != nil && *flagDuration != cluster.DefaultDuration {
			configs[i].Duration = *flagDuration
		}
		// Set missing defaults.
		if configs[i].Duration == 0 {
			configs[i].Duration = cluster.DefaultDuration
		}
	}
	return configs
}

// runTestOnConfigs retrieves the full list of test configurations and runs the
// passed in test against each on serially.
func runTestOnConfigs(t *testing.T, testFunc func(*testing.T, cluster.Cluster, cluster.TestConfig)) {
	cfgs := getConfigs(t)
	if len(cfgs) == 0 {
		t.Fatal("no config defined so most tests won't run")
	}
	for _, cfg := range cfgs {
		func() {
			cluster := StartCluster(t, cfg)
			defer cluster.AssertAndStop(t)
			testFunc(t, cluster, cfg)
		}()
	}
}

// StartCluster starts a cluster from the relevant flags. All test clusters
// should be created through this command since it sets up the logging in a
// unified way.
func StartCluster(t *testing.T, cfg cluster.TestConfig) (c cluster.Cluster) {
	var completed bool
	defer func() {
		if !completed && c != nil {
			c.AssertAndStop(t)
		}
	}()
	if !*flagRemote {
		logDir := *flagLogDir
		if logDir != "" {
			_, _, fun := caller.Lookup(3)
			if !testFuncRE.MatchString(fun) {
				t.Fatalf("invalid caller %s; want TestX -> runTestOnConfigs -> func()", fun)
			}
			logDir = filepath.Join(logDir, fun)
		}
		l := cluster.CreateLocal(cfg, logDir, stopper)
		l.Start()
		c = l
		checkRangeReplication(t, l, 20*time.Second)
		completed = true
		return l
	}
	f := farmer(t)
	c = f
	if err := f.Resize(*flagNodes, 0); err != nil {
		t.Fatal(err)
	}
	if err := f.WaitReady(5 * time.Minute); err != nil {
		_ = f.Destroy()
		t.Fatalf("cluster not ready in time: %v", err)
	}
	checkRangeReplication(t, f, 20*time.Second)
	completed = true
	return f
}

// SkipUnlessLocal calls t.Skip if not running against a local cluster.
func SkipUnlessLocal(t *testing.T) {
	if *flagRemote {
		t.Skip("skipping since not run against local cluster")
	}
}

func makePGClient(t *testing.T, dest string) *sql.DB {
	db, err := sql.Open("postgres", dest)
	if err != nil {
		t.Fatal(err)
	}
	return db
}

// HTTPClient is an http.Client configured for querying a cluster. We need to
// run with "InsecureSkipVerify" (at least on Docker) due to the fact that we
// cannot use a fixed hostname to reach the cluster. This in turn means that we
// do not have a verified server name in the certs.
var HTTPClient = http.Client{
	Timeout: base.NetworkTimeout,
	Transport: &http.Transport{
		TLSClientConfig: &tls.Config{
			InsecureSkipVerify: true,
		},
	}}

// getJSON retrieves the URL specified by the parameters and
// and unmarshals the result into the supplied interface.
func getJSON(url, rel string, v interface{}) error {
	resp, err := HTTPClient.Get(url + rel)
	if err != nil {
		if log.V(1) {
			log.Info(err)
		}
		return err
	}
	defer func() { _ = resp.Body.Close() }()
	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		if log.V(1) {
			log.Info(err)
		}
		return err
	}
	return json.Unmarshal(b, v)
}

// postJSON POSTs to the URL specified by the parameters and unmarshals the
// result into the supplied interface.
func postJSON(url, rel string, reqBody interface{}, v interface{}) error {
	reqBodyBytes, err := json.Marshal(reqBody)
	if err != nil {
		return err
	}

	resp, err := HTTPClient.Post(url+rel, util.JSONContentType, bytes.NewReader(reqBodyBytes))
	if err != nil {
		return err
	}
	defer func() { _ = resp.Body.Close() }()
	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	return json.Unmarshal(b, v)
}

// testDockerFail ensures the specified docker cmd fails.
func testDockerFail(t *testing.T, name string, cmd []string) {
	if err := testDocker(t, name, cmd); err == nil {
		t.Error("expected failure")
	}
}

// testDockerSuccess ensures the specified docker cmd succeeds.
func testDockerSuccess(t *testing.T, name string, cmd []string) {
	if err := testDocker(t, name, cmd); err != nil {
		t.Errorf("expected success: %s", err)
	}
}

const (
	postgresTestTag = "20160406-1730"
)

func testDocker(t *testing.T, name string, cmd []string) error {
	const image = "cockroachdb/postgres-test"
	SkipUnlessLocal(t)
	l := StartCluster(t, readConfigFromFlags()).(*cluster.LocalCluster)

	defer l.AssertAndStop(t)
	containerConfig := container.Config{
		Image: fmt.Sprintf(image + ":" + postgresTestTag),
		Env: []string{
			"PGHOST=roach0",
			fmt.Sprintf("PGPORT=%s", base.DefaultPort),
			"PGSSLCERT=/certs/node.crt",
			"PGSSLKEY=/certs/node.key",
		},
		Cmd: cmd,
	}
	hostConfig := container.HostConfig{
		Binds:       []string{l.CertsDir + ":/certs"},
		NetworkMode: "host",
	}
	ipo := types.ImagePullOptions{
		ImageID: image,
		Tag:     postgresTestTag,
	}
	return l.OneShot(ipo, containerConfig, hostConfig, "docker-"+name)
}
<commit_msg>acceptance: bump image to debian based version<commit_after>// Copyright 2015 The Cockroach 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.
//
// Author: Peter Mattis (peter@cockroachlabs.com)

package acceptance

import (
	"bytes"
	"crypto/tls"
	"database/sql"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"regexp"
	"strconv"
	"testing"
	"time"

	"github.com/docker/engine-api/types"
	"github.com/docker/engine-api/types/container"

	"github.com/cockroachdb/cockroach/acceptance/cluster"
	"github.com/cockroachdb/cockroach/acceptance/terrafarm"
	"github.com/cockroachdb/cockroach/base"
	"github.com/cockroachdb/cockroach/util"
	"github.com/cockroachdb/cockroach/util/caller"
	"github.com/cockroachdb/cockroach/util/log"
	_ "github.com/cockroachdb/pq"
)

var flagDuration = flag.Duration("d", cluster.DefaultDuration, "duration to run the test")
var flagNodes = flag.Int("nodes", 3, "number of nodes")
var flagStores = flag.Int("stores", 1, "number of stores to use for each node")
var flagRemote = flag.Bool("remote", false, "run the test using terrafarm instead of docker")
var flagCwd = flag.String("cwd", "../cloud/aws", "directory to run terraform from")
var flagKeyName = flag.String("key-name", "", "name of key for remote cluster")
var flagLogDir = flag.String("l", "", "the directory to store log files, relative to the test source")
var flagTestConfigs = flag.Bool("test-configs", false, "instead of using the passed in configuration, use the default "+
	"cluster configurations for each test. This overrides the nodes, stores and duration flags and will run the test "+
	"against a collection of pre-specified cluster configurations.")
var flagConfig = flag.String("config", "", "a json TestConfig proto, see testconfig.proto")

var testFuncRE = regexp.MustCompile("^(Test|Benchmark)")

var stopper = make(chan struct{})

func farmer(t *testing.T) *terrafarm.Farmer {
	if !*flagRemote {
		t.Skip("running in docker mode")
	}
	if *flagKeyName == "" {
		t.Fatal("-key-name is required") // saves a lot of trouble
	}
	logDir := *flagLogDir
	if logDir == "" {
		var err error
		logDir, err = ioutil.TempDir("", "clustertest_")
		if err != nil {
			t.Fatal(err)
		}
	}
	if !filepath.IsAbs(logDir) {
		logDir = filepath.Join(filepath.Clean(os.ExpandEnv("${PWD}")), logDir)
	}
	stores := "ssd=data0"
	for j := 1; j < *flagStores; j++ {
		stores += ",ssd=data" + strconv.Itoa(j)
	}
	f := &terrafarm.Farmer{
		Output:  os.Stderr,
		Cwd:     *flagCwd,
		LogDir:  logDir,
		KeyName: *flagKeyName,
		Stores:  stores,
	}
	log.Infof("logging to %s", logDir)
	return f
}

// readConfigFromFlags will convert the flags to a TestConfig for the purposes
// of starting up a cluster.
func readConfigFromFlags() cluster.TestConfig {
	return cluster.TestConfig{
		Name:     fmt.Sprintf("AdHoc %dx%d", *flagNodes, *flagStores),
		Duration: *flagDuration,
		Nodes: []cluster.NodeConfig{
			{
				Count:  int32(*flagNodes),
				Stores: []cluster.StoreConfig{{Count: int32(*flagStores)}},
			},
		},
	}
}

// getConfigs returns a list of test configs based on the passed in flags.
func getConfigs(t *testing.T) []cluster.TestConfig {
	// If a config not supplied, just read the flags.
	if (flagConfig == nil || len(*flagConfig) == 0) &&
		(flagTestConfigs == nil || !*flagTestConfigs) {
		return []cluster.TestConfig{readConfigFromFlags()}
	}

	var configs []cluster.TestConfig
	if flagTestConfigs != nil && *flagTestConfigs {
		configs = append(configs, cluster.DefaultConfigs()...)
	}

	if flagConfig != nil && len(*flagConfig) > 0 {
		// Read the passed in config from the command line.
		var config cluster.TestConfig
		if err := json.Unmarshal([]byte(*flagConfig), &config); err != nil {
			t.Error(err)
		}
		configs = append(configs, config)
	}

	// Override duration in all configs if the flags are set.
	for i := 0; i < len(configs); i++ {
		// Override values.
		if flagDuration != nil && *flagDuration != cluster.DefaultDuration {
			configs[i].Duration = *flagDuration
		}
		// Set missing defaults.
		if configs[i].Duration == 0 {
			configs[i].Duration = cluster.DefaultDuration
		}
	}
	return configs
}

// runTestOnConfigs retrieves the full list of test configurations and runs the
// passed in test against each on serially.
func runTestOnConfigs(t *testing.T, testFunc func(*testing.T, cluster.Cluster, cluster.TestConfig)) {
	cfgs := getConfigs(t)
	if len(cfgs) == 0 {
		t.Fatal("no config defined so most tests won't run")
	}
	for _, cfg := range cfgs {
		func() {
			cluster := StartCluster(t, cfg)
			defer cluster.AssertAndStop(t)
			testFunc(t, cluster, cfg)
		}()
	}
}

// StartCluster starts a cluster from the relevant flags. All test clusters
// should be created through this command since it sets up the logging in a
// unified way.
func StartCluster(t *testing.T, cfg cluster.TestConfig) (c cluster.Cluster) {
	var completed bool
	defer func() {
		if !completed && c != nil {
			c.AssertAndStop(t)
		}
	}()
	if !*flagRemote {
		logDir := *flagLogDir
		if logDir != "" {
			_, _, fun := caller.Lookup(3)
			if !testFuncRE.MatchString(fun) {
				t.Fatalf("invalid caller %s; want TestX -> runTestOnConfigs -> func()", fun)
			}
			logDir = filepath.Join(logDir, fun)
		}
		l := cluster.CreateLocal(cfg, logDir, stopper)
		l.Start()
		c = l
		checkRangeReplication(t, l, 20*time.Second)
		completed = true
		return l
	}
	f := farmer(t)
	c = f
	if err := f.Resize(*flagNodes, 0); err != nil {
		t.Fatal(err)
	}
	if err := f.WaitReady(5 * time.Minute); err != nil {
		_ = f.Destroy()
		t.Fatalf("cluster not ready in time: %v", err)
	}
	checkRangeReplication(t, f, 20*time.Second)
	completed = true
	return f
}

// SkipUnlessLocal calls t.Skip if not running against a local cluster.
func SkipUnlessLocal(t *testing.T) {
	if *flagRemote {
		t.Skip("skipping since not run against local cluster")
	}
}

func makePGClient(t *testing.T, dest string) *sql.DB {
	db, err := sql.Open("postgres", dest)
	if err != nil {
		t.Fatal(err)
	}
	return db
}

// HTTPClient is an http.Client configured for querying a cluster. We need to
// run with "InsecureSkipVerify" (at least on Docker) due to the fact that we
// cannot use a fixed hostname to reach the cluster. This in turn means that we
// do not have a verified server name in the certs.
var HTTPClient = http.Client{
	Timeout: base.NetworkTimeout,
	Transport: &http.Transport{
		TLSClientConfig: &tls.Config{
			InsecureSkipVerify: true,
		},
	}}

// getJSON retrieves the URL specified by the parameters and
// and unmarshals the result into the supplied interface.
func getJSON(url, rel string, v interface{}) error {
	resp, err := HTTPClient.Get(url + rel)
	if err != nil {
		if log.V(1) {
			log.Info(err)
		}
		return err
	}
	defer func() { _ = resp.Body.Close() }()
	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		if log.V(1) {
			log.Info(err)
		}
		return err
	}
	return json.Unmarshal(b, v)
}

// postJSON POSTs to the URL specified by the parameters and unmarshals the
// result into the supplied interface.
func postJSON(url, rel string, reqBody interface{}, v interface{}) error {
	reqBodyBytes, err := json.Marshal(reqBody)
	if err != nil {
		return err
	}

	resp, err := HTTPClient.Post(url+rel, util.JSONContentType, bytes.NewReader(reqBodyBytes))
	if err != nil {
		return err
	}
	defer func() { _ = resp.Body.Close() }()
	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	return json.Unmarshal(b, v)
}

// testDockerFail ensures the specified docker cmd fails.
func testDockerFail(t *testing.T, name string, cmd []string) {
	if err := testDocker(t, name, cmd); err == nil {
		t.Error("expected failure")
	}
}

// testDockerSuccess ensures the specified docker cmd succeeds.
func testDockerSuccess(t *testing.T, name string, cmd []string) {
	if err := testDocker(t, name, cmd); err != nil {
		t.Errorf("expected success: %s", err)
	}
}

const (
	postgresTestTag = "20160413-1457"
)

func testDocker(t *testing.T, name string, cmd []string) error {
	const image = "cockroachdb/postgres-test"
	SkipUnlessLocal(t)
	l := StartCluster(t, readConfigFromFlags()).(*cluster.LocalCluster)

	defer l.AssertAndStop(t)
	containerConfig := container.Config{
		Image: fmt.Sprintf(image + ":" + postgresTestTag),
		Env: []string{
			"PGHOST=roach0",
			fmt.Sprintf("PGPORT=%s", base.DefaultPort),
			"PGSSLCERT=/certs/node.crt",
			"PGSSLKEY=/certs/node.key",
		},
		Cmd: cmd,
	}
	hostConfig := container.HostConfig{
		Binds:       []string{l.CertsDir + ":/certs"},
		NetworkMode: "host",
	}
	ipo := types.ImagePullOptions{
		ImageID: image,
		Tag:     postgresTestTag,
	}
	return l.OneShot(ipo, containerConfig, hostConfig, "docker-"+name)
}
<|endoftext|>