<commit_before>package main

import (
	"errors"
	r "gopkg.in/gorethink/gorethink.v3"
	"os"
)

func InitConnectionPool() {
	var err error

	dbUrl := os.Getenv("DB")
	if dbUrl == "" {
		log.Fatal("db env variable not specified")
	}

	session, err = r.Connect(r.ConnectOpts{
		Address:    dbUrl,
		InitialCap: 10,
		MaxOpen:    10,
		Database:   "OverStats",
	})
	if err != nil {
		log.Fatal(err)
	}

	res, err := r.Table("users").Filter(func(user r.Term) r.Term {
		return user.Field("id").Match("^tg")
	}).Changes().Run(session)
	if err != nil {
		log.Fatal(err)
	}

	var change Change
	for res.Next(&change) {
		SessionReport(change)
	}
}

func GetUser(id string) (User, error) {
	res, err := r.Table("users").Get(id).Run(session)
	if err != nil {
		return User{}, err
	}

	var user User
	err = res.One(&user)
	if err == r.ErrEmptyResult {
		return User{}, errors.New("db: row not found")
	}
	if err != nil {
		return User{}, err
	}

	defer res.Close()
	return user, nil
}

func GetRatingTop(platform string, limit int, chat int64) ([]User, error) {
	var (
		res *r.Cursor
		err error
	)

	if platform == "console" {
		if chat != 0 {
			res, err = r.Table("users").OrderBy(r.OrderByOpts{Index: r.Desc("rating")}).Filter(r.Row.Field("region").Eq("psn").Or(r.Row.Field("region").Eq("xbl")).And(r.Row.Field("chat").Eq(chat))).Limit(limit).Run(session)
		} else {
			res, err = r.Table("users").OrderBy(r.OrderByOpts{Index: r.Desc("rating")}).Filter(r.Row.Field("region").Eq("psn").Or(r.Row.Field("region").Eq("xbl"))).Limit(limit).Run(session)
		}
	} else {
		if chat != 0 {
			res, err = r.Table("users").OrderBy(r.OrderByOpts{Index: r.Desc("rating")}).Filter(r.Row.Field("region").Ne("psn").And(r.Row.Field("region").Ne("xbl")).And(r.Row.Field("chat").Eq(chat))).Limit(limit).Run(session)
		} else {
			res, err = r.Table("users").OrderBy(r.OrderByOpts{Index: r.Desc("rating")}).Filter(r.Row.Field("region").Ne("psn").And(r.Row.Field("region").Ne("xbl"))).Limit(limit).Run(session)
		}
	}

	if err != nil {
		return []User{}, err
	}

	var top []User
	err = res.All(&top)
	if err != nil {
		return []User{}, err
	}

	defer res.Close()
	return top, nil
}

func GetRatingPlace(id string) (Top, error) {
	res, err := r.Do(
		r.Table("users").OrderBy(r.OrderByOpts{Index: r.Desc("rating")}).OffsetsOf(r.Row.Field("id").Eq(id)).Nth(0),
		r.Table("users").Count(),
		func(place r.Term, count r.Term) r.Term {
			return r.Expr(
				map[string]interface{}{
					"place": place.Add(1),
					"rank":  place.Div(count).Mul(100),
				},
			)
		},
	).Run(session)

	var top Top
	err = res.One(&top)
	if err != nil {
		log.Warn(err)
		return Top{}, err
	}

	return top, nil
}

func GetRank(id string, index r.Term) (Top, error) {
	res, err := r.Do(
		r.Table("users").OrderBy(r.Desc(index)).OffsetsOf(r.Row.Field("id").Eq(id)).Nth(0),
		r.Table("users").Count(index.Ne(0)),
		func(place r.Term, count r.Term) r.Term {
			return r.Expr(
				map[string]interface{}{
					"place": place.Add(1),
					"rank":  place.Div(count).Mul(100),
				},
			)
		},
	).Run(session)

	var top Top
	err = res.One(&top)
	if err != nil {
		log.Warn(err)
		return Top{}, err
	}

	return top, nil
}

func InsertUser(user User) (r.WriteResponse, error) {
	newDoc := map[string]interface{}{
		"id":      user.Id,
		"profile": user.Profile,
		"nick":    user.Nick,
		"region":  user.Region,
		"date":    r.Now(),
	}

	res, err := r.Table("users").Insert(newDoc, r.InsertOpts{
		Conflict: "replace",
	}).RunWrite(session)
	if err != nil {
		return r.WriteResponse{}, err
	}

	return res, nil
}

func UpdateUser(user User) (r.WriteResponse, error) {
	newDoc := map[string]interface{}{
		"id":   user.Id,
		"chat": user.Chat,
	}

	res, err := r.Table("users").Get(user.Id).Update(newDoc).RunWrite(session)
	if err != nil {
		return r.WriteResponse{}, err
	}

	return res, nil
}
<commit_msg>Possible fix<commit_after>package main

import (
	"errors"
	r "gopkg.in/gorethink/gorethink.v3"
	"os"
)

func InitConnectionPool() {
	var err error

	dbUrl := os.Getenv("DB")
	if dbUrl == "" {
		log.Fatal("db env variable not specified")
	}

	session, err = r.Connect(r.ConnectOpts{
		Address:    dbUrl,
		InitialCap: 10,
		MaxOpen:    10,
		Database:   "OverStats",
	})
	if err != nil {
		log.Fatal(err)
	}

	res, err := r.Table("users").Filter(func(user r.Term) r.Term {
		return user.Field("id").Match("^tg")
	}).Changes().Run(session)
	if err != nil {
		log.Fatal(err)
	}

	var change Change
	for res.Next(&change) {
		SessionReport(change)
	}
}

func GetUser(id string) (User, error) {
	res, err := r.Table("users").Get(id).Run(session)
	if err != nil {
		return User{}, err
	}

	var user User
	err = res.One(&user)
	if err == r.ErrEmptyResult {
		return User{}, errors.New("db: row not found")
	}
	if err != nil {
		return User{}, err
	}

	defer res.Close()
	return user, nil
}

func GetRatingTop(platform string, limit int, chat int64) ([]User, error) {
	var (
		res *r.Cursor
		err error
	)

	query := r.Table("users").OrderBy(r.OrderByOpts{Index: r.Desc("rating")})
	if platform == "console" {
		query = query.Filter(r.Row.Field("region").Eq("psn").Or(r.Row.Field("region").Eq("xbl")))
	} else {
		query = query.Filter(r.Row.Field("region").Ne("psn").And(r.Row.Field("region").Ne("xbl")))
	}
	if chat != 0 {
		query = query.Filter(r.Row.Field("chat").Eq(chat))
	}

	res, err = query.Limit(limit).Run(session)

	if err != nil {
		return []User{}, err
	}

	var top []User
	err = res.All(&top)
	if err != nil {
		return []User{}, err
	}

	defer res.Close()
	return top, nil
}

func GetRatingPlace(id string) (Top, error) {
	res, err := r.Do(
		r.Table("users").OrderBy(r.OrderByOpts{Index: r.Desc("rating")}).OffsetsOf(r.Row.Field("id").Eq(id)).Nth(0),
		r.Table("users").Count(),
		func(place r.Term, count r.Term) r.Term {
			return r.Expr(
				map[string]interface{}{
					"place": place.Add(1),
					"rank":  place.Div(count).Mul(100),
				},
			)
		},
	).Run(session)

	var top Top
	err = res.One(&top)
	if err != nil {
		log.Warn(err)
		return Top{}, err
	}

	return top, nil
}

func GetRank(id string, index r.Term) (Top, error) {
	res, err := r.Do(
		r.Table("users").OrderBy(r.Desc(index)).OffsetsOf(r.Row.Field("id").Eq(id)).Nth(0),
		r.Table("users").Count(index.Ne(0)),
		func(place r.Term, count r.Term) r.Term {
			return r.Expr(
				map[string]interface{}{
					"place": place.Add(1),
					"rank":  place.Div(count).Mul(100),
				},
			)
		},
	).Run(session)

	var top Top
	err = res.One(&top)
	if err != nil {
		log.Warn(err)
		return Top{}, err
	}

	return top, nil
}

func InsertUser(user User) (r.WriteResponse, error) {
	newDoc := map[string]interface{}{
		"id":      user.Id,
		"profile": user.Profile,
		"nick":    user.Nick,
		"region":  user.Region,
		"date":    r.Now(),
	}

	res, err := r.Table("users").Insert(newDoc, r.InsertOpts{
		Conflict: "replace",
	}).RunWrite(session)
	if err != nil {
		return r.WriteResponse{}, err
	}

	return res, nil
}

func UpdateUser(user User) (r.WriteResponse, error) {
	newDoc := map[string]interface{}{
		"id":   user.Id,
		"chat": user.Chat,
	}

	res, err := r.Table("users").Get(user.Id).Update(newDoc).RunWrite(session)
	if err != nil {
		return r.WriteResponse{}, err
	}

	return res, nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2016-2018 Tigera, Inc. All rights reserved.

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

package k8s

import (
	"fmt"
	"strings"
	"time"

	log "github.com/sirupsen/logrus"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/runtime/serializer"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/kubernetes/scheme"
	_ "k8s.io/client-go/plugin/pkg/client/auth" // Import all auth providers.
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"

	capi "github.com/projectcalico/libcalico-go/lib/apis/v1"
	"github.com/projectcalico/libcalico-go/lib/backend/model"
	"github.com/projectcalico/libcalico-go/lib/errors"
	"github.com/projectcalico/libcalico-go/lib/upgrade/migrator/clients/v1/k8s/custom"
	"github.com/projectcalico/libcalico-go/lib/upgrade/migrator/clients/v1/k8s/resources"
)

type KubeClient struct {
	// Main Kubernetes clients.
	clientSet *kubernetes.Clientset

	// Client for interacting with CustomResourceDefinition.
	crdClientV1 *rest.RESTClient

	// Clients for interacting with Calico resources.
	nodeBgpPeerClient       resources.K8sResourceClient
	globalBgpConfigClient   resources.K8sResourceClient
	globalFelixConfigClient resources.K8sResourceClient
	nodeConfigClient        resources.K8sResourceClient
}

func NewKubeClient(kc *capi.KubeConfig) (*KubeClient, error) {
	// Use the kubernetes client code to load the kubeconfig file and combine it with the overrides.
	log.Debugf("Building client for config: %+v", kc)
	configOverrides := &clientcmd.ConfigOverrides{}
	var overridesMap = []struct {
		variable *string
		value    string
	}{
		{&configOverrides.ClusterInfo.Server, kc.K8sAPIEndpoint},
		{&configOverrides.AuthInfo.ClientCertificate, kc.K8sCertFile},
		{&configOverrides.AuthInfo.ClientKey, kc.K8sKeyFile},
		{&configOverrides.ClusterInfo.CertificateAuthority, kc.K8sCAFile},
		{&configOverrides.AuthInfo.Token, kc.K8sAPIToken},
	}

	// Set an explicit path to the kubeconfig if one
	// was provided.
	loadingRules := clientcmd.ClientConfigLoadingRules{}
	if kc.Kubeconfig != "" {
		loadingRules.ExplicitPath = kc.Kubeconfig
	}

	// Using the override map above, populate any non-empty values.
	for _, override := range overridesMap {
		if override.value != "" {
			*override.variable = override.value
		}
	}
	if kc.K8sInsecureSkipTLSVerify {
		configOverrides.ClusterInfo.InsecureSkipTLSVerify = true
	}
	log.Debugf("Config overrides: %+v", configOverrides)

	// A kubeconfig file was provided.  Use it to load a config, passing through
	// any overrides.
	config, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
		&loadingRules, configOverrides).ClientConfig()
	if err != nil {
		return nil, resources.K8sErrorToCalico(err, nil)
	}

	// Create the clientset
	cs, err := kubernetes.NewForConfig(config)
	if err != nil {
		return nil, resources.K8sErrorToCalico(err, nil)
	}
	log.Debugf("Created k8s clientSet: %+v", cs)

	crdClientV1, err := buildCRDClientV1(*config)
	if err != nil {
		return nil, fmt.Errorf("Failed to build V1 CRD client: %s", err)
	}

	kubeClient := &KubeClient{
		clientSet:   cs,
		crdClientV1: crdClientV1,
	}

	// Create the Calico sub-clients.
	kubeClient.nodeBgpPeerClient = resources.NewNodeBGPPeerClient(cs)
	kubeClient.globalBgpConfigClient = resources.NewGlobalBGPConfigClient(cs, crdClientV1)
	kubeClient.globalFelixConfigClient = resources.NewGlobalFelixConfigClient(cs, crdClientV1)

	return kubeClient, nil
}

func (c *KubeClient) IsKDD() bool {
	return true
}

// waitForClusterType polls until GlobalFelixConfig is ready, or until 30 seconds have passed.
func (c *KubeClient) waitForClusterType() error {
	return wait.PollImmediate(1*time.Second, 30*time.Second, func() (bool, error) {
		return c.ensureClusterType()
	})
}

// ensureClusterType ensures that the ClusterType is configured.
func (c *KubeClient) ensureClusterType() (bool, error) {
	k := model.GlobalConfigKey{
		Name: "ClusterType",
	}
	value := "KDD"

	// See if a cluster type has been set.  If so, append
	// any existing values to it.
	ct, err := c.Get(k)
	if err != nil {
		if _, ok := err.(errors.ErrorResourceDoesNotExist); !ok {
			// Resource exists but we got another error.
			return false, err
		}
		// Resource does not exist.
	}
	rv := ""
	if ct != nil {
		existingValue := ct.Value.(string)
		if !strings.Contains(existingValue, "KDD") {
			existingValue = fmt.Sprintf("%s,KDD", existingValue)
		}
		value = existingValue
		rv = ct.Revision
	}
	log.WithField("value", value).Debug("Setting ClusterType")
	_, err = c.Apply(&model.KVPair{
		Key:      k,
		Value:    value,
		Revision: rv,
	})
	if err != nil {
		// Don't return an error, but indicate that we need
		// to retry.
		log.Warnf("Failed to apply ClusterType: %s", err)
		return false, nil
	}
	return true, nil
}

// buildCRDClientV1 builds a RESTClient configured to interact with Calico CustomResourceDefinitions
func buildCRDClientV1(cfg rest.Config) (*rest.RESTClient, error) {
	// Generate config using the base config.
	cfg.GroupVersion = &schema.GroupVersion{
		Group:   "crd.projectcalico.org",
		Version: "v1",
	}
	cfg.APIPath = "/apis"
	cfg.ContentType = runtime.ContentTypeJSON
	cfg.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}

	cli, err := rest.RESTClientFor(&cfg)
	if err != nil {
		return nil, err
	}

	// We also need to register resources.
	schemeBuilder := runtime.NewSchemeBuilder(
		func(scheme *runtime.Scheme) error {
			scheme.AddKnownTypes(
				*cfg.GroupVersion,
				&custom.GlobalFelixConfig{},
				&custom.GlobalFelixConfigList{},
				&custom.GlobalBGPConfig{},
				&custom.GlobalBGPConfigList{},
			)
			return nil
		})

	schemeBuilder.AddToScheme(scheme.Scheme)

	return cli, nil
}

// Update an existing entry in the datastore.  This errors if the entry does
// not exist. (Not implemented for KDD.)
func (c *KubeClient) Update(d *model.KVPair) (*model.KVPair, error) {
	log.Warn("Attempt to 'Update' using kubernetes backend is not supported.")
	return nil, errors.ErrorOperationNotSupported{
		Identifier: d.Key,
		Operation:  "Update",
	}
}

// Set an existing entry in the datastore.  This ignores whether an entry already
// exists.
func (c *KubeClient) Apply(d *model.KVPair) (*model.KVPair, error) {
	log.Warn("Attempt to 'Apply' using kubernetes backend is not supported.")
	return nil, errors.ErrorOperationNotSupported{
		Identifier: d.Key,
		Operation:  "Apply",
	}
}

// Get an entry from the datastore.  This errors if the entry does not exist.
func (c *KubeClient) Get(k model.Key) (*model.KVPair, error) {
	log.Debugf("Performing 'Get' for %+v", k)
	switch k.(type) {
	case model.GlobalConfigKey:
		return c.globalFelixConfigClient.Get(k)
	case model.NodeBGPPeerKey:
		return c.nodeBgpPeerClient.Get(k)
	case model.GlobalBGPConfigKey:
		return c.globalBgpConfigClient.Get(k)
	default:
		return nil, errors.ErrorOperationNotSupported{
			Identifier: k,
			Operation:  "Get",
		}
	}
}

// List entries in the datastore.  This may return an empty list if there are
// no entries matching the request in the ListInterface.
func (c *KubeClient) List(l model.ListInterface) ([]*model.KVPair, error) {
	log.Debugf("Performing 'List' for %+v", l)
	switch l.(type) {
	case model.NodeBGPPeerListOptions:
		k, _, err := c.nodeBgpPeerClient.List(l)
		return k, err
	case model.GlobalConfigListOptions:
		k, _, err := c.globalFelixConfigClient.List(l)
		return k, err
	case model.GlobalBGPConfigListOptions:
		k, _, err := c.globalBgpConfigClient.List(l)
		return k, err
	default:
		return nil, errors.ErrorOperationNotSupported{
			Identifier: l,
			Operation:  "List",
		}
	}
}
<commit_msg>Stop logging client config in the migrator<commit_after>// Copyright (c) 2016-2018 Tigera, Inc. All rights reserved.

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

package k8s

import (
	"fmt"
	"strings"
	"time"

	log "github.com/sirupsen/logrus"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/runtime/serializer"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/kubernetes/scheme"
	_ "k8s.io/client-go/plugin/pkg/client/auth" // Import all auth providers.
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"

	capi "github.com/projectcalico/libcalico-go/lib/apis/v1"
	"github.com/projectcalico/libcalico-go/lib/backend/model"
	"github.com/projectcalico/libcalico-go/lib/errors"
	"github.com/projectcalico/libcalico-go/lib/upgrade/migrator/clients/v1/k8s/custom"
	"github.com/projectcalico/libcalico-go/lib/upgrade/migrator/clients/v1/k8s/resources"
)

type KubeClient struct {
	// Main Kubernetes clients.
	clientSet *kubernetes.Clientset

	// Client for interacting with CustomResourceDefinition.
	crdClientV1 *rest.RESTClient

	// Clients for interacting with Calico resources.
	nodeBgpPeerClient       resources.K8sResourceClient
	globalBgpConfigClient   resources.K8sResourceClient
	globalFelixConfigClient resources.K8sResourceClient
	nodeConfigClient        resources.K8sResourceClient
}

func NewKubeClient(kc *capi.KubeConfig) (*KubeClient, error) {
	// Use the kubernetes client code to load the kubeconfig file and combine it with the overrides.
	configOverrides := &clientcmd.ConfigOverrides{}
	var overridesMap = []struct {
		variable *string
		value    string
	}{
		{&configOverrides.ClusterInfo.Server, kc.K8sAPIEndpoint},
		{&configOverrides.AuthInfo.ClientCertificate, kc.K8sCertFile},
		{&configOverrides.AuthInfo.ClientKey, kc.K8sKeyFile},
		{&configOverrides.ClusterInfo.CertificateAuthority, kc.K8sCAFile},
		{&configOverrides.AuthInfo.Token, kc.K8sAPIToken},
	}

	// Set an explicit path to the kubeconfig if one
	// was provided.
	loadingRules := clientcmd.ClientConfigLoadingRules{}
	if kc.Kubeconfig != "" {
		loadingRules.ExplicitPath = kc.Kubeconfig
	}

	// Using the override map above, populate any non-empty values.
	for _, override := range overridesMap {
		if override.value != "" {
			*override.variable = override.value
		}
	}
	if kc.K8sInsecureSkipTLSVerify {
		configOverrides.ClusterInfo.InsecureSkipTLSVerify = true
	}

	// A kubeconfig file was provided.  Use it to load a config, passing through
	// any overrides.
	config, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
		&loadingRules, configOverrides).ClientConfig()
	if err != nil {
		return nil, resources.K8sErrorToCalico(err, nil)
	}

	// Create the clientset
	cs, err := kubernetes.NewForConfig(config)
	if err != nil {
		return nil, resources.K8sErrorToCalico(err, nil)
	}
	log.Debugf("Created k8s clientSet: %+v", cs)

	crdClientV1, err := buildCRDClientV1(*config)
	if err != nil {
		return nil, fmt.Errorf("Failed to build V1 CRD client: %s", err)
	}

	kubeClient := &KubeClient{
		clientSet:   cs,
		crdClientV1: crdClientV1,
	}

	// Create the Calico sub-clients.
	kubeClient.nodeBgpPeerClient = resources.NewNodeBGPPeerClient(cs)
	kubeClient.globalBgpConfigClient = resources.NewGlobalBGPConfigClient(cs, crdClientV1)
	kubeClient.globalFelixConfigClient = resources.NewGlobalFelixConfigClient(cs, crdClientV1)

	return kubeClient, nil
}

func (c *KubeClient) IsKDD() bool {
	return true
}

// waitForClusterType polls until GlobalFelixConfig is ready, or until 30 seconds have passed.
func (c *KubeClient) waitForClusterType() error {
	return wait.PollImmediate(1*time.Second, 30*time.Second, func() (bool, error) {
		return c.ensureClusterType()
	})
}

// ensureClusterType ensures that the ClusterType is configured.
func (c *KubeClient) ensureClusterType() (bool, error) {
	k := model.GlobalConfigKey{
		Name: "ClusterType",
	}
	value := "KDD"

	// See if a cluster type has been set.  If so, append
	// any existing values to it.
	ct, err := c.Get(k)
	if err != nil {
		if _, ok := err.(errors.ErrorResourceDoesNotExist); !ok {
			// Resource exists but we got another error.
			return false, err
		}
		// Resource does not exist.
	}
	rv := ""
	if ct != nil {
		existingValue := ct.Value.(string)
		if !strings.Contains(existingValue, "KDD") {
			existingValue = fmt.Sprintf("%s,KDD", existingValue)
		}
		value = existingValue
		rv = ct.Revision
	}
	log.WithField("value", value).Debug("Setting ClusterType")
	_, err = c.Apply(&model.KVPair{
		Key:      k,
		Value:    value,
		Revision: rv,
	})
	if err != nil {
		// Don't return an error, but indicate that we need
		// to retry.
		log.Warnf("Failed to apply ClusterType: %s", err)
		return false, nil
	}
	return true, nil
}

// buildCRDClientV1 builds a RESTClient configured to interact with Calico CustomResourceDefinitions
func buildCRDClientV1(cfg rest.Config) (*rest.RESTClient, error) {
	// Generate config using the base config.
	cfg.GroupVersion = &schema.GroupVersion{
		Group:   "crd.projectcalico.org",
		Version: "v1",
	}
	cfg.APIPath = "/apis"
	cfg.ContentType = runtime.ContentTypeJSON
	cfg.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}

	cli, err := rest.RESTClientFor(&cfg)
	if err != nil {
		return nil, err
	}

	// We also need to register resources.
	schemeBuilder := runtime.NewSchemeBuilder(
		func(scheme *runtime.Scheme) error {
			scheme.AddKnownTypes(
				*cfg.GroupVersion,
				&custom.GlobalFelixConfig{},
				&custom.GlobalFelixConfigList{},
				&custom.GlobalBGPConfig{},
				&custom.GlobalBGPConfigList{},
			)
			return nil
		})

	schemeBuilder.AddToScheme(scheme.Scheme)

	return cli, nil
}

// Update an existing entry in the datastore.  This errors if the entry does
// not exist. (Not implemented for KDD.)
func (c *KubeClient) Update(d *model.KVPair) (*model.KVPair, error) {
	log.Warn("Attempt to 'Update' using kubernetes backend is not supported.")
	return nil, errors.ErrorOperationNotSupported{
		Identifier: d.Key,
		Operation:  "Update",
	}
}

// Set an existing entry in the datastore.  This ignores whether an entry already
// exists.
func (c *KubeClient) Apply(d *model.KVPair) (*model.KVPair, error) {
	log.Warn("Attempt to 'Apply' using kubernetes backend is not supported.")
	return nil, errors.ErrorOperationNotSupported{
		Identifier: d.Key,
		Operation:  "Apply",
	}
}

// Get an entry from the datastore.  This errors if the entry does not exist.
func (c *KubeClient) Get(k model.Key) (*model.KVPair, error) {
	log.Debugf("Performing 'Get' for %+v", k)
	switch k.(type) {
	case model.GlobalConfigKey:
		return c.globalFelixConfigClient.Get(k)
	case model.NodeBGPPeerKey:
		return c.nodeBgpPeerClient.Get(k)
	case model.GlobalBGPConfigKey:
		return c.globalBgpConfigClient.Get(k)
	default:
		return nil, errors.ErrorOperationNotSupported{
			Identifier: k,
			Operation:  "Get",
		}
	}
}

// List entries in the datastore.  This may return an empty list if there are
// no entries matching the request in the ListInterface.
func (c *KubeClient) List(l model.ListInterface) ([]*model.KVPair, error) {
	log.Debugf("Performing 'List' for %+v", l)
	switch l.(type) {
	case model.NodeBGPPeerListOptions:
		k, _, err := c.nodeBgpPeerClient.List(l)
		return k, err
	case model.GlobalConfigListOptions:
		k, _, err := c.globalFelixConfigClient.List(l)
		return k, err
	case model.GlobalBGPConfigListOptions:
		k, _, err := c.globalBgpConfigClient.List(l)
		return k, err
	default:
		return nil, errors.ErrorOperationNotSupported{
			Identifier: l,
			Operation:  "List",
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"plaid/check"
	"plaid/codegen"
	"plaid/libs"
	"plaid/parser"
	"plaid/vm"
)

func main() {
	showAST := flag.Bool("ast", false, "output abstract syntax tree")
	showIR := flag.Bool("ir", false, "output intermediate representation")
	showBC := flag.Bool("bytecode", false, "output bytecode")
	showOut := flag.Bool("out", false, "run program and print output")
	flag.Parse()

	for _, filename := range flag.Args() {
		processFile(filename, *showAST, *showIR, *showBC, *showOut)
	}
}

func processFile(filename string, showAST bool, showIR bool, showBC bool, showOut bool) {
	buf, err := ioutil.ReadFile(filename)
	if err != nil {
		fmt.Println(err.Error())
		os.Exit(1)
	}

	src := string(buf)
	ast, err := parser.Parse(src)
	if err != nil {
		fmt.Println(err.Error())
		os.Exit(1)
	}

	if showAST {
		fmt.Println(ast.String())
	}

	scope := check.Check(ast, libs.IO, libs.Conv)
	if len(scope.Errors()) > 0 {
		for i, err := range scope.Errors() {
			fmt.Printf("%4d %s\n", i, err)
		}
		os.Exit(1)
	}

	ir := codegen.Transform(ast, libs.IO, libs.Conv)

	if showIR {
		fmt.Println(ir.String())
	}

	mod := codegen.Generate(ir)

	if showBC {
		fmt.Println(mod.Main.String())
	}

	if showOut {
		vm.Run(mod.Main)
	}
}
<commit_msg>add --check flag<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"plaid/check"
	"plaid/codegen"
	"plaid/libs"
	"plaid/parser"
	"plaid/vm"
)

func main() {
	showAST := flag.Bool("ast", false, "output abstract syntax tree")
	showCheck := flag.Bool("check", false, "output type checker results")
	showIR := flag.Bool("ir", false, "output intermediate representation")
	showBC := flag.Bool("bytecode", false, "output bytecode")
	showOut := flag.Bool("out", false, "run program and print output")
	flag.Parse()

	for _, filename := range flag.Args() {
		processFile(filename, *showAST, *showCheck, *showIR, *showBC, *showOut)
	}
}

func processFile(filename string, showAST bool, showCheck bool, showIR bool, showBC bool, showOut bool) {
	buf, err := ioutil.ReadFile(filename)
	if err != nil {
		fmt.Println(err.Error())
		os.Exit(1)
	}

	src := string(buf)
	ast, err := parser.Parse(src)
	if err != nil {
		fmt.Println(err.Error())
		os.Exit(1)
	}

	if showAST {
		fmt.Println(ast.String())
	}

	scope := check.Check(ast, libs.IO, libs.Conv)
	if len(scope.Errors()) > 0 {
		for i, err := range scope.Errors() {
			fmt.Printf("%4d %s\n", i, err)
		}
		os.Exit(1)
	} else if showCheck {
		fmt.Println(scope)
	}

	ir := codegen.Transform(ast, libs.IO, libs.Conv)

	if showIR {
		fmt.Println(ir.String())
	}

	mod := codegen.Generate(ir)

	if showBC {
		fmt.Println(mod.Main.String())
	}

	if showOut {
		vm.Run(mod.Main)
	}
}
<|endoftext|>


<commit_before>// Copyright 2017 Authors of Cilium
//
// 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 ciliumTest

import (
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"testing"
	"time"

	"github.com/cilium/cilium/pkg/logging"
	"github.com/cilium/cilium/test/config"
	. "github.com/cilium/cilium/test/ginkgo-ext"
	ginkgoext "github.com/cilium/cilium/test/ginkgo-ext"
	"github.com/cilium/cilium/test/helpers"

	gops "github.com/google/gops/agent"
	"github.com/onsi/ginkgo"
	ginkgoconfig "github.com/onsi/ginkgo/config"
	. "github.com/onsi/gomega"
	"github.com/sirupsen/logrus"
)

var (
	log             = logging.DefaultLogger
	DefaultSettings = map[string]string{
		"K8S_VERSION": "1.10",
	}
	k8sNodesEnv         = "K8S_NODES"
	commandsLogFileName = "cmds.log"
)

func init() {

	// Open socket for using gops to get stacktraces in case the tests deadlock.
	if err := gops.Listen(gops.Options{}); err != nil {
		errorString := fmt.Sprintf("unable to start gops: %s", err)
		fmt.Println(errorString)
		os.Exit(-1)
	}

	for k, v := range DefaultSettings {
		getOrSetEnvVar(k, v)
	}

	config.CiliumTestConfig.ParseFlags()

	os.RemoveAll(helpers.TestResultsPath)
}

func configLogsOutput() {
	log.SetLevel(logrus.DebugLevel)
	log.Out = &config.TestLogWriter
	logrus.SetFormatter(&config.Formatter)
	log.Formatter = &config.Formatter
	log.Hooks.Add(&config.LogHook{})

	ginkgoext.GinkgoWriter = NewWriter(log.Out)
}

func ShowCommands() {
	if !config.CiliumTestConfig.ShowCommands {
		return
	}

	helpers.SSHMetaLogs = ginkgoext.NewWriter(os.Stdout)
}

func TestTest(t *testing.T) {
	configLogsOutput()
	ShowCommands()

	if config.CiliumTestConfig.CiliumDSManifest != "" {
		helpers.CiliumDSPath = config.CiliumTestConfig.CiliumDSManifest
		log.Info("Using new Cilium daemonset manifest '%s'", helpers.CiliumDSPath)
	}

	if config.CiliumTestConfig.HoldEnvironment {
		RegisterFailHandler(helpers.Fail)
	} else {
		RegisterFailHandler(Fail)
	}
	junitReporter := ginkgoext.NewJUnitReporter(fmt.Sprintf(
		"%s.xml", helpers.GetScopeWithVersion()))
	RunSpecsWithDefaultAndCustomReporters(
		t, helpers.GetScopeWithVersion(), []ginkgo.Reporter{junitReporter})
}

func goReportVagrantStatus() chan bool {
	if ginkgoconfig.DefaultReporterConfig.Verbose ||
		ginkgoconfig.DefaultReporterConfig.Succinct {
		// Dev told us they want more/less information than default. Skip.
		return nil
	}

	exit := make(chan bool)
	go func() {
		done := false
		iter := 0
		for {
			var out string
			select {
			case ok := <-exit:
				if ok {
					out = "●\n"
				} else {
					out = "◌\n"
				}
				done = true
			default:
				out = string(rune(int('◜') + iter%4))
			}
			fmt.Printf("\rSpinning up vagrant VMs... %s", out)
			if done {
				return
			}
			time.Sleep(250 * time.Millisecond)
			iter++
		}
	}()
	return exit
}

func reportCreateVMFailure(vm string, err error) {
	failmsg := fmt.Sprintf(`
        ===================== ERROR - VM PROVISION FAILED =====================

        Unable to provision and start VM %q: %s", vm, err

        =======================================================================
        `, vm, err)
	ginkgoext.GinkgoPrint(failmsg)
	Fail(failmsg)
}

var _ = BeforeAll(func() {
	var err error

	if !config.CiliumTestConfig.Reprovision {
		// The developer has explicitly told us that they don't care
		// about updating Cilium inside the guest, so skip setup below.
		return
	}

	if config.CiliumTestConfig.SSHConfig != "" {
		// If we set a different VM that it's not in our test environment
		// ginkgo cannot provision it, so skip setup below.
		return
	}

	if progressChan := goReportVagrantStatus(); progressChan != nil {
		defer func() { progressChan <- err == nil }()
	}
	logger := log.WithFields(logrus.Fields{"testName": "BeforeSuite"})

	switch helpers.GetScope() {
	case helpers.Runtime:
		err = helpers.CreateVM(helpers.Runtime)
		if err != nil {
			log.WithError(err).Error("Error starting VM")
			reportCreateVMFailure(helpers.Runtime, err)
		}

		vm := helpers.InitRuntimeHelper(helpers.Runtime, logger)
		err = vm.SetUpCilium()

		if err != nil {
			// AfterFailed function is not defined in this scope, fired the
			// ReportFailed manually for this assert to gather cilium logs Fix
			// #3428
			vm.ReportFailed()
			log.WithError(err).Error("Cilium was unable to be set up correctly")
			reportCreateVMFailure(helpers.Runtime, err)
		}

	case helpers.K8s:
		//FIXME: This should be:
		// Start k8s1 and provision kubernetes.
		// When finish, start to build cilium in background
		// Start k8s2
		// Wait until compilation finished, and pull cilium image on k8s2

		// Name for K8s VMs depends on K8s version that is running.

		err = helpers.CreateVM(helpers.K8s1VMName())
		if err != nil {
			reportCreateVMFailure(helpers.K8s1VMName(), err)
		}

		err = helpers.CreateVM(helpers.K8s2VMName())
		if err != nil {
			reportCreateVMFailure(helpers.K8s2VMName(), err)
		}

		// For Nightly test we need to have more than two kubernetes nodes. If
		// the env variable K8S_NODES is present, more nodes will be created.
		if nodes := os.Getenv(k8sNodesEnv); nodes != "" {
			nodesInt, err := strconv.Atoi(nodes)
			if err != nil {
				Fail(fmt.Sprintf("%s value is not a number %q", k8sNodesEnv, nodes))
			}
			for i := 3; i <= nodesInt; i++ {
				vmName := fmt.Sprintf("%s%d-%s", helpers.K8s, i, helpers.GetCurrentK8SEnv())
				err = helpers.CreateVM(vmName)
				if err != nil {
					reportCreateVMFailure(vmName, err)
				}
			}
		}
		kubectl := helpers.CreateKubectl(helpers.K8s1VMName(), logger)
		kubectl.Apply(helpers.GetFilePath("../examples/kubernetes/prometheus.yaml"))
	}
	return
})

var _ = AfterAll(func() {
	if !helpers.IsRunningOnJenkins() {
		log.Infof("AfterSuite: not running on Jenkins; leaving VMs running for debugging")
		return
	}

	scope := helpers.GetScope()
	log.Infof("cleaning up VMs started for %s tests", scope)
	switch scope {
	case helpers.Runtime:
		helpers.DestroyVM(helpers.Runtime)
	case helpers.K8s:
		helpers.DestroyVM(helpers.K8s1VMName())
		helpers.DestroyVM(helpers.K8s2VMName())
	}
	return
})

func getOrSetEnvVar(key, value string) {
	if val := os.Getenv(key); val == "" {
		log.Infof("environment variable %q was not set; setting to default value %q", key, value)
		os.Setenv(key, value)
	}
}

var _ = AfterEach(func() {

	// Send the Checks output to Junit report to be render on Jenkins.
	defer helpers.CheckLogs.Reset()
	GinkgoPrint("<Checks>\n%s\n</Checks>\n", helpers.CheckLogs.Buffer.String())

	defer config.TestLogWriterReset()
	err := helpers.CreateLogFile(config.TestLogFileName, config.TestLogWriter.Bytes())
	if err != nil {
		log.WithError(err).Errorf("cannot create log file '%s'", config.TestLogFileName)
		return
	}

	defer helpers.SSHMetaLogs.Reset()
	err = helpers.CreateLogFile(commandsLogFileName, helpers.SSHMetaLogs.Bytes())
	if err != nil {
		log.WithError(err).Errorf("cannot create log file '%s'", commandsLogFileName)
		return
	}

	// This piece of code is to enable zip attachments on Junit Output.
	if ginkgo.CurrentGinkgoTestDescription().Failed && helpers.IsRunningOnJenkins() {
		// ReportDirectory is already created. No check the error
		path, _ := helpers.CreateReportDirectory()
		zipFileName := fmt.Sprintf("%s_%s.zip", helpers.MakeUID(), ginkgoext.GetTestName())
		zipFilePath := filepath.Join(helpers.TestResultsPath, zipFileName)

		_, err := exec.Command(
			"/bin/bash", "-c",
			fmt.Sprintf("zip -qr %s %s", zipFilePath, path)).CombinedOutput()
		if err != nil {
			log.WithError(err).Errorf("cannot create zip file '%s'", zipFilePath)
		}

		ginkgoext.GinkgoPrint("[[ATTACHMENT|%s]]", zipFileName)
	}

	if !ginkgo.CurrentGinkgoTestDescription().Failed && helpers.IsRunningOnJenkins() {
		// If the test success delete the monitor.log filename to not store all
		// the data in Jenkins
		testPath, err := helpers.CreateReportDirectory()
		if err != nil {
			log.WithError(err).Error("cannot retrieve test result path")
			return
		}
		_ = os.Remove(filepath.Join(testPath, helpers.MonitorLogFileName))
	}
})
<commit_msg>Test: Gomega enable the use of Stringer representation<commit_after>// Copyright 2017 Authors of Cilium
//
// 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 ciliumTest

import (
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"testing"
	"time"

	"github.com/cilium/cilium/pkg/logging"
	"github.com/cilium/cilium/test/config"
	. "github.com/cilium/cilium/test/ginkgo-ext"
	ginkgoext "github.com/cilium/cilium/test/ginkgo-ext"
	"github.com/cilium/cilium/test/helpers"

	gops "github.com/google/gops/agent"
	"github.com/onsi/ginkgo"
	ginkgoconfig "github.com/onsi/ginkgo/config"
	. "github.com/onsi/gomega"

	"github.com/onsi/gomega/format"
	"github.com/sirupsen/logrus"
)

var (
	log             = logging.DefaultLogger
	DefaultSettings = map[string]string{
		"K8S_VERSION": "1.10",
	}
	k8sNodesEnv         = "K8S_NODES"
	commandsLogFileName = "cmds.log"
)

func init() {

	// Open socket for using gops to get stacktraces in case the tests deadlock.
	if err := gops.Listen(gops.Options{}); err != nil {
		errorString := fmt.Sprintf("unable to start gops: %s", err)
		fmt.Println(errorString)
		os.Exit(-1)
	}

	for k, v := range DefaultSettings {
		getOrSetEnvVar(k, v)
	}

	config.CiliumTestConfig.ParseFlags()

	os.RemoveAll(helpers.TestResultsPath)

	format.UseStringerRepresentation = true
}

func configLogsOutput() {
	log.SetLevel(logrus.DebugLevel)
	log.Out = &config.TestLogWriter
	logrus.SetFormatter(&config.Formatter)
	log.Formatter = &config.Formatter
	log.Hooks.Add(&config.LogHook{})

	ginkgoext.GinkgoWriter = NewWriter(log.Out)
}

func ShowCommands() {
	if !config.CiliumTestConfig.ShowCommands {
		return
	}

	helpers.SSHMetaLogs = ginkgoext.NewWriter(os.Stdout)
}

func TestTest(t *testing.T) {
	configLogsOutput()
	ShowCommands()

	if config.CiliumTestConfig.CiliumDSManifest != "" {
		helpers.CiliumDSPath = config.CiliumTestConfig.CiliumDSManifest
		log.Info("Using new Cilium daemonset manifest '%s'", helpers.CiliumDSPath)
	}

	if config.CiliumTestConfig.HoldEnvironment {
		RegisterFailHandler(helpers.Fail)
	} else {
		RegisterFailHandler(Fail)
	}
	junitReporter := ginkgoext.NewJUnitReporter(fmt.Sprintf(
		"%s.xml", helpers.GetScopeWithVersion()))
	RunSpecsWithDefaultAndCustomReporters(
		t, helpers.GetScopeWithVersion(), []ginkgo.Reporter{junitReporter})
}

func goReportVagrantStatus() chan bool {
	if ginkgoconfig.DefaultReporterConfig.Verbose ||
		ginkgoconfig.DefaultReporterConfig.Succinct {
		// Dev told us they want more/less information than default. Skip.
		return nil
	}

	exit := make(chan bool)
	go func() {
		done := false
		iter := 0
		for {
			var out string
			select {
			case ok := <-exit:
				if ok {
					out = "●\n"
				} else {
					out = "◌\n"
				}
				done = true
			default:
				out = string(rune(int('◜') + iter%4))
			}
			fmt.Printf("\rSpinning up vagrant VMs... %s", out)
			if done {
				return
			}
			time.Sleep(250 * time.Millisecond)
			iter++
		}
	}()
	return exit
}

func reportCreateVMFailure(vm string, err error) {
	failmsg := fmt.Sprintf(`
        ===================== ERROR - VM PROVISION FAILED =====================

        Unable to provision and start VM %q: %s", vm, err

        =======================================================================
        `, vm, err)
	ginkgoext.GinkgoPrint(failmsg)
	Fail(failmsg)
}

var _ = BeforeAll(func() {
	var err error

	if !config.CiliumTestConfig.Reprovision {
		// The developer has explicitly told us that they don't care
		// about updating Cilium inside the guest, so skip setup below.
		return
	}

	if config.CiliumTestConfig.SSHConfig != "" {
		// If we set a different VM that it's not in our test environment
		// ginkgo cannot provision it, so skip setup below.
		return
	}

	if progressChan := goReportVagrantStatus(); progressChan != nil {
		defer func() { progressChan <- err == nil }()
	}
	logger := log.WithFields(logrus.Fields{"testName": "BeforeSuite"})

	switch helpers.GetScope() {
	case helpers.Runtime:
		err = helpers.CreateVM(helpers.Runtime)
		if err != nil {
			log.WithError(err).Error("Error starting VM")
			reportCreateVMFailure(helpers.Runtime, err)
		}

		vm := helpers.InitRuntimeHelper(helpers.Runtime, logger)
		err = vm.SetUpCilium()

		if err != nil {
			// AfterFailed function is not defined in this scope, fired the
			// ReportFailed manually for this assert to gather cilium logs Fix
			// #3428
			vm.ReportFailed()
			log.WithError(err).Error("Cilium was unable to be set up correctly")
			reportCreateVMFailure(helpers.Runtime, err)
		}

	case helpers.K8s:
		//FIXME: This should be:
		// Start k8s1 and provision kubernetes.
		// When finish, start to build cilium in background
		// Start k8s2
		// Wait until compilation finished, and pull cilium image on k8s2

		// Name for K8s VMs depends on K8s version that is running.

		err = helpers.CreateVM(helpers.K8s1VMName())
		if err != nil {
			reportCreateVMFailure(helpers.K8s1VMName(), err)
		}

		err = helpers.CreateVM(helpers.K8s2VMName())
		if err != nil {
			reportCreateVMFailure(helpers.K8s2VMName(), err)
		}

		// For Nightly test we need to have more than two kubernetes nodes. If
		// the env variable K8S_NODES is present, more nodes will be created.
		if nodes := os.Getenv(k8sNodesEnv); nodes != "" {
			nodesInt, err := strconv.Atoi(nodes)
			if err != nil {
				Fail(fmt.Sprintf("%s value is not a number %q", k8sNodesEnv, nodes))
			}
			for i := 3; i <= nodesInt; i++ {
				vmName := fmt.Sprintf("%s%d-%s", helpers.K8s, i, helpers.GetCurrentK8SEnv())
				err = helpers.CreateVM(vmName)
				if err != nil {
					reportCreateVMFailure(vmName, err)
				}
			}
		}
		kubectl := helpers.CreateKubectl(helpers.K8s1VMName(), logger)
		kubectl.Apply(helpers.GetFilePath("../examples/kubernetes/prometheus.yaml"))
	}
	return
})

var _ = AfterAll(func() {
	if !helpers.IsRunningOnJenkins() {
		log.Infof("AfterSuite: not running on Jenkins; leaving VMs running for debugging")
		return
	}

	scope := helpers.GetScope()
	log.Infof("cleaning up VMs started for %s tests", scope)
	switch scope {
	case helpers.Runtime:
		helpers.DestroyVM(helpers.Runtime)
	case helpers.K8s:
		helpers.DestroyVM(helpers.K8s1VMName())
		helpers.DestroyVM(helpers.K8s2VMName())
	}
	return
})

func getOrSetEnvVar(key, value string) {
	if val := os.Getenv(key); val == "" {
		log.Infof("environment variable %q was not set; setting to default value %q", key, value)
		os.Setenv(key, value)
	}
}

var _ = AfterEach(func() {

	// Send the Checks output to Junit report to be render on Jenkins.
	defer helpers.CheckLogs.Reset()
	GinkgoPrint("<Checks>\n%s\n</Checks>\n", helpers.CheckLogs.Buffer.String())

	defer config.TestLogWriterReset()
	err := helpers.CreateLogFile(config.TestLogFileName, config.TestLogWriter.Bytes())
	if err != nil {
		log.WithError(err).Errorf("cannot create log file '%s'", config.TestLogFileName)
		return
	}

	defer helpers.SSHMetaLogs.Reset()
	err = helpers.CreateLogFile(commandsLogFileName, helpers.SSHMetaLogs.Bytes())
	if err != nil {
		log.WithError(err).Errorf("cannot create log file '%s'", commandsLogFileName)
		return
	}

	// This piece of code is to enable zip attachments on Junit Output.
	if ginkgo.CurrentGinkgoTestDescription().Failed && helpers.IsRunningOnJenkins() {
		// ReportDirectory is already created. No check the error
		path, _ := helpers.CreateReportDirectory()
		zipFileName := fmt.Sprintf("%s_%s.zip", helpers.MakeUID(), ginkgoext.GetTestName())
		zipFilePath := filepath.Join(helpers.TestResultsPath, zipFileName)

		_, err := exec.Command(
			"/bin/bash", "-c",
			fmt.Sprintf("zip -qr %s %s", zipFilePath, path)).CombinedOutput()
		if err != nil {
			log.WithError(err).Errorf("cannot create zip file '%s'", zipFilePath)
		}

		ginkgoext.GinkgoPrint("[[ATTACHMENT|%s]]", zipFileName)
	}

	if !ginkgo.CurrentGinkgoTestDescription().Failed && helpers.IsRunningOnJenkins() {
		// If the test success delete the monitor.log filename to not store all
		// the data in Jenkins
		testPath, err := helpers.CreateReportDirectory()
		if err != nil {
			log.WithError(err).Error("cannot retrieve test result path")
			return
		}
		_ = os.Remove(filepath.Join(testPath, helpers.MonitorLogFileName))
	}
})
<|endoftext|>


<commit_before>// Copyright 2015 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 registry

import (
	"crypto/rand"
	"fmt"
	"io"
	"time"

	"github.com/jacobsa/comeback/crypto"
	"github.com/jacobsa/gcloud/gcs"
)

// Create a registry that stores data in the supplied GCS bucket, deriving a
// crypto key from the supplied password and ensuring that the bucket may not
// in the future be used with any other key and has not in the past, either.
// Return a crypter configured to use the key.
func NewGCSRegistry(
	bucket gcs.Bucket,
	cryptoPassword string,
	deriver crypto.KeyDeriver) (r Registry, crypter crypto.Crypter, err error) {
	return newGCSRegistry(
		bucket,
		cryptoPassword,
		deriver,
		crypto.NewCrypter,
		rand.Reader)
}

// Like NewGCSRegistry, but with more injected.
func newGCSRegistry(
	bucket gcs.Bucket,
	cryptoPassword string,
	deriver crypto.KeyDeriver,
	createCrypter func(key []byte) (crypto.Crypter, error),
	cryptoRandSrc io.Reader) (r Registry, crypter crypto.Crypter, err error) {
}

const (
	gcsJobKeyPrefix      = "jobs/"
	gcsMetadataKey_Name  = "job_name"
	gcsMetadataKey_Score = "hex_score"
)

// A registry that stores job records in a GCS bucket. Object names are of the
// form
//
//     <gcsJobKeyPrefix><time>
//
// where <time> is a time.Time with UTC location formatted according to
// time.RFC3339Nano. Additional information is stored as object metadata fields
// keyed by the constants above. Metadata fields are used in preference to
// object content so that they are accessible on a ListObjects request.
type gcsRegistry struct {
	bucket gcs.Bucket
}

func (r *gcsRegistry) RecordBackup(j CompletedJob) (err error) {
	err = fmt.Errorf("gcsRegistry.RecordBackup is not implemented.")
	return
}

func (r *gcsRegistry) ListRecentBackups() (jobs []CompletedJob, err error) {
	err = fmt.Errorf("gcsRegistry.ListRecentBackups is not implemented.")
	return
}

func (r *gcsRegistry) FindBackup(
	startTime time.Time) (job CompletedJob, err error) {
	err = fmt.Errorf("gcsRegistry.FindBackup is not implemented.")
	return
}
<commit_msg>Added comments about the marker item.<commit_after>// Copyright 2015 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 registry

import (
	"crypto/rand"
	"fmt"
	"io"
	"time"

	"github.com/jacobsa/comeback/crypto"
	"github.com/jacobsa/gcloud/gcs"
)

// Create a registry that stores data in the supplied GCS bucket, deriving a
// crypto key from the supplied password and ensuring that the bucket may not
// in the future be used with any other key and has not in the past, either.
// Return a crypter configured to use the key.
func NewGCSRegistry(
	bucket gcs.Bucket,
	cryptoPassword string,
	deriver crypto.KeyDeriver) (r Registry, crypter crypto.Crypter, err error) {
	return newGCSRegistry(
		bucket,
		cryptoPassword,
		deriver,
		crypto.NewCrypter,
		rand.Reader)
}

const (
	gcsJobKeyPrefix      = "jobs/"
	gcsMetadataKey_Name  = "job_name"
	gcsMetadataKey_Score = "hex_score"
)

// A registry that stores job records in a GCS bucket. Object names are of the
// form
//
//     <gcsJobKeyPrefix><time>
//
// where <time> is a time.Time with UTC location formatted according to
// time.RFC3339Nano. Additional information is stored as object metadata fields
// keyed by the constants above. Metadata fields are used in preference to
// object content so that they are accessible on a ListObjects request.
//
// The bucket additionally contains a "marker" object (named by the constant
// markerItemName) with metadata keys specifying a salt and a ciphertext for
// some random plaintext, generated ant written the first time the bucket is
// used. This marker allows us to verify that the user-provided crypto password
// is correct by deriving a key using the password and the salt and making sure
// that the ciphertext can be decrypted using that key.
type gcsRegistry struct {
	bucket gcs.Bucket
}

// Like NewGCSRegistry, but with more injected.
func newGCSRegistry(
	bucket gcs.Bucket,
	cryptoPassword string,
	deriver crypto.KeyDeriver,
	createCrypter func(key []byte) (crypto.Crypter, error),
	cryptoRandSrc io.Reader) (r Registry, crypter crypto.Crypter, err error) {
}

func (r *gcsRegistry) RecordBackup(j CompletedJob) (err error) {
	err = fmt.Errorf("gcsRegistry.RecordBackup is not implemented.")
	return
}

func (r *gcsRegistry) ListRecentBackups() (jobs []CompletedJob, err error) {
	err = fmt.Errorf("gcsRegistry.ListRecentBackups is not implemented.")
	return
}

func (r *gcsRegistry) FindBackup(
	startTime time.Time) (job CompletedJob, err error) {
	err = fmt.Errorf("gcsRegistry.FindBackup is not implemented.")
	return
}
<|endoftext|>


<commit_before>// This example demonstrates how to authenticate with Spotify.
// In order to run this example yourself, you'll need to:
//
//  1. Register an application at: https://developer.spotify.com/my-applications/
//       - Use "http://localhost:8080/callback" as the redirect URI
//  2. Set the SPOTIFY_ID environment variable to the client ID you got in step 1.
//  3. Set the SPOTIFY_SECRET environment variable to the client secret from step 1.
package main

import (
	"container/heap"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"time"

	"strconv"

	"github.com/coolbry95/partydj/backend/pool"
	"github.com/pressly/chi"
	"github.com/zmb3/spotify"
)

// redirectURI is the OAuth redirect URI for the application.
// You must register an application at Spotify's developer portal
// and enter this value.
const redirectURI = "https://linode.shellcode.in/callback"

var (
	auth = spotify.NewAuthenticator(redirectURI, spotify.ScopeUserLibraryModify, spotify.ScopePlaylistModifyPrivate,
		spotify.ScopePlaylistModifyPublic)
	ch    = make(chan spotify.Client)
	state = "stateless"
)

type DI struct {
	client spotify.Client
	pool   pool.Pool
}

var PoolShortIDToLongID map[int]string
var UserIDToPoolID map[string]string

func main() {
	// Initialize the pool (single for demonstration)
	var d *DI
	d = new(DI)

	// setup the router and paths
	r := chi.NewRouter()
	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
		log.Println(r.URL.String())
	})
	r.Get("/callback", completeAuth)
	r.Get("/getpool", d.getPool)
	r.Post("/createpool", d.createPool)
	r.Post("/add_song/:poolID/:songID", d.addSong)
	r.Post("/upvote/:poolID/:songID", d.upVote)
	r.Post("/downvote/:poolID/:songID", d.downVote)
	r.Post("/join_pool", d.joinPool)

	r.FileServer("/files", http.Dir("/home/coolbry95/gosrc/src/github.com/coolbry95/partydj/website"))

	// Authenticate the users spotify account
	url := auth.AuthURL(state)
	fmt.Println("Please log in to Spotify by visiting the following page in your browser:", url)

	go http.ListenAndServe(":6060", r)

	// wait for auth to complete
	d.client = <-ch
	d.pool.PlaylistID = spotify.ID("0nXlYUH7zBAzubO9Yub4rR") // change to spartahack playlist

	// Initialize the short id to long id map
	PoolShortIDToLongID = make(map[int]string)
	// hard code the one join digit for this sample pool to 121
	PoolShortIDToLongID[121] = "0nXlYUH7zBAzubO9Yub4rR"

	// initialize the user map
	UserIDToPoolID = make(map[string]string)

	userID, err := d.client.CurrentUser()
	if err != nil {
		log.Println(err)
	}

	d.pool.UserID = userID.ID

	block := make(chan struct{})
	<-block
}

func (d *DI) joinPool(w http.ResponseWriter, r *http.Request) {
	w.Header().Add("Access-Control-Allow-Origin", "http://localhost")

	userIDNumber := r.PostFormValue("userId")
	poolIDNumberStr := r.PostFormValue("poolShortId")

	// Both must be present
	if len(userIDNumber) == 0 || len(poolIDNumberStr) == 0 {
		w.WriteHeader(http.StatusPartialContent)
		fmt.Println("One of the parameters were empty: ", "userId:",
			userIDNumber, "poolShortId:", poolIDNumberStr)
		return
	}

	poolIDNumber, convErr := strconv.Atoi(poolIDNumberStr)

	// Make sure the poolIDNumber is a valid integer, otherwise
	// respond with Status partial content
	if convErr != nil {
		w.WriteHeader(http.StatusPartialContent)
		fmt.Println("Conversion error: ", convErr)
		return
	}

	// Check if pool exists, if not respond with status not found
	if _, ok := PoolShortIDToLongID[poolIDNumber]; ok != true {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	UserIDToPoolID[userIDNumber] = poolIDNumberStr
	// Let the user know the request was accepted
	w.WriteHeader(http.StatusOK)
}

func (d *DI) addSong(w http.ResponseWriter, r *http.Request) {
	songID := chi.URLParam(r, "songID")
	//poolID := chi.URLParam(r, "poolID")

	s := &pool.Song{ID: spotify.ID(songID)}
	heap.Push(&d.pool, s)
}

func (d *DI) upVote(w http.ResponseWriter, r *http.Request) {
	// TODO check for user ID to see if they already voted
	songID := chi.URLParam(r, "songID")
	userID := r.PostFormValue("userId")

	if len(userID) == 0 || len(songID) == 0 {
		w.WriteHeader(http.StatusPartialContent)
		return
	}

	if !d.pool.HasUserVoted(userID, songID) {
		d.pool.UpVote(spotify.ID(songID), userID)
		d.pool.UpdateSpotifyPlaylist(&d.client, d.pool.PlaylistID)
	} else {
		w.WriteHeader(http.StatusMethodNotAllowed)
	}

	w.WriteHeader(http.StatusOK)
}

func (d *DI) downVote(w http.ResponseWriter, r *http.Request) {
	// TODO check for user ID to see if they already voted
	songID := chi.URLParam(r, "songID")
	userID := r.PostFormValue("userId")
	//poolID := chi.URLParam(r, "poolID")

	if len(userID) == 0 || len(songID) == 0 {
		w.WriteHeader(http.StatusPartialContent)
		return
	}

	if !d.pool.HasUserVoted(userID, songID) {
		d.pool.DownVote(spotify.ID(songID), userID)
		d.pool.UpdateSpotifyPlaylist(&d.client, d.pool.PlaylistID)
		w.WriteHeader(http.StatusOK)
	} else {
		w.WriteHeader(http.StatusMethodNotAllowed)
	}
}

func (d *DI) createPool(w http.ResponseWriter, r *http.Request) {
}

func (d *DI) getPool(w http.ResponseWriter, r *http.Request) {
	userid, err := d.client.CurrentUser()
	if err != nil {
		log.Println(err)
	}

	// TODO: instead of using existing playlist we require a new playlist to be created
	// playlist, err := d.client.CreatePlaylistForUser(userid.ID, playlistName, true)
	playlist, err := d.client.GetPlaylistTracks(userid.ID, "0nXlYUH7zBAzubO9Yub4rR")
	//spartahackPlaylistName := "Sparthack Sample Playlist!"
	//newPlaylist, err := d.client.CreatePlaylistForUser(userid.ID, spartahackPlaylistName, true)
	if err != nil {
		log.Println(err)
	}

	d.pool.SongHeap = make([]*pool.Song, 0, 100)
	for i, track := range playlist.Tracks {
		d.pool.SongHeap = append(d.pool.SongHeap, pool.TrackToSong(&track.Track, i))
	}
	d.pool.UserToVoteMap = make(map[string][]string)

	//TODO: only call this function only after the the current song finishes
	song := heap.Pop(&d.pool).(*pool.Song)
	heap.Push(&d.pool, song)

	go func() {
		songTime := song.Duration + 15
		time.Sleep(time.Duration(songTime) * time.Second)
		d.pool.AddNextSong(&d.client)
		fmt.Println("Now playing new song...")
	}()

	json.NewEncoder(w).Encode(d.pool)
	return
}

func completeAuth(w http.ResponseWriter, r *http.Request) {
	tok, err := auth.Token(state, r)
	if err != nil {
		http.Error(w, "Couldn't get token", http.StatusForbidden)
		log.Fatal(err)
	}

	if st := r.FormValue("state"); st != state {
		http.NotFound(w, r)
		log.Fatalf("State mismatch: %s != %s\n", st, state)
	}

	// use the token to get an authenticated client
	client := auth.NewClient(tok)
	ch <- client
	http.Redirect(w, r, "/getpool", 301)
}
<commit_msg>Fixed the play loop, added headers for website. Changed songID to songId in requests.<commit_after>// This example demonstrates how to authenticate with Spotify.
// In order to run this example yourself, you'll need to:
//
//  1. Register an application at: https://developer.spotify.com/my-applications/
//       - Use "http://localhost:8080/callback" as the redirect URI
//  2. Set the SPOTIFY_ID environment variable to the client ID you got in step 1.
//  3. Set the SPOTIFY_SECRET environment variable to the client secret from step 1.
package main

import (
	"container/heap"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"time"

	"strconv"

	"github.com/coolbry95/partydj/backend/pool"
	"github.com/pressly/chi"
	"github.com/zmb3/spotify"
)

// redirectURI is the OAuth redirect URI for the application.
// You must register an application at Spotify's developer portal
// and enter this value.
const redirectURI = "http://localhost:8080/callback"

var (
	auth = spotify.NewAuthenticator(redirectURI, spotify.ScopeUserLibraryModify, spotify.ScopePlaylistModifyPrivate,
		spotify.ScopePlaylistModifyPublic)
	ch    = make(chan spotify.Client)
	state = "stateless"
)

type DI struct {
	client spotify.Client
	pool   pool.Pool
}

var PoolShortIDToLongID map[int]string
var UserIDToPoolID map[string]string

func main() {
	// Initialize the pool (single for demonstration)
	var d *DI
	d = new(DI)

	// setup the router and paths
	r := chi.NewRouter()
	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
		log.Println(r.URL.String())
	})
	r.Get("/callback", completeAuth)
	r.Get("/getpool", d.getPool)
	r.Post("/createpool", d.createPool)
	r.Post("/add_song/:poolID/:songID", d.addSong)
	r.Post("/upvote/:poolID/:songID", d.upVote)
	r.Post("/downvote/:poolID/:songID", d.downVote)
	r.Post("/join_pool", d.joinPool)

	r.FileServer("/files", http.Dir("/home/coolbry95/gosrc/src/github.com/coolbry95/partydj/website"))

	// Authenticate the users spotify account
	url := auth.AuthURL(state)
	fmt.Println("Please log in to Spotify by visiting the following page in your browser:", url)

	go http.ListenAndServe(":8080", r)

	// wait for auth to complete
	d.client = <-ch
	d.pool.PlaylistID = spotify.ID("0nXlYUH7zBAzubO9Yub4rR") // change to spartahack playlist

	// Initialize the short id to long id map
	PoolShortIDToLongID = make(map[int]string)
	// hard code the one join digit for this sample pool to 121
	PoolShortIDToLongID[121] = "0nXlYUH7zBAzubO9Yub4rR"

	// initialize the user map
	UserIDToPoolID = make(map[string]string)

	userID, err := d.client.CurrentUser()
	if err != nil {
		log.Println(err)
	}

	d.pool.UserID = userID.ID

	// Begin the play loop when the server begins for spartahack
	d.BeginPlayLoop()

	block := make(chan struct{})
	<-block
}

func (d *DI) BeginPlayLoop() {
	//fmt.Println("Beginning play loop...")
	// Start the loop after 10 seconds of pool creation
	time.Sleep(10 * time.Second)

	go func() {
		song := heap.Pop(&d.pool).(*pool.Song)
		heap.Push(&d.pool, song)
		// song duration is in milliseconds
		songTime := time.Duration(((song.Duration)/1000) + 15) // 15 seconds + song length
		fmt.Print(songTime * time.Second)
		time.Sleep(songTime * time.Second)
		d.pool.AddNextSong(&d.client)
		//fmt.Println("Now playing new song...")
		d.BeginPlayLoop()
		//return // do this to kill the parent goroutine?
	}()
}

func (d *DI) joinPool(w http.ResponseWriter, r *http.Request) {
	w.Header().Add("Access-Control-Allow-Origin", "http://localhost")

	userIDNumber := r.PostFormValue("userId")
	poolIDNumberStr := r.PostFormValue("poolShortId")

	// Both must be present
	if len(userIDNumber) == 0 || len(poolIDNumberStr) == 0 {
		w.WriteHeader(http.StatusPartialContent)
		fmt.Println("One of the parameters were empty: ", "userId:",
			userIDNumber, "poolShortId:", poolIDNumberStr)
		return
	}

	poolIDNumber, convErr := strconv.Atoi(poolIDNumberStr)

	// Make sure the poolIDNumber is a valid integer, otherwise
	// respond with Status partial content
	if convErr != nil {
		w.WriteHeader(http.StatusPartialContent)
		fmt.Println("Conversion error: ", convErr)
		return
	}

	// Check if pool exists, if not respond with status not found
	if _, ok := PoolShortIDToLongID[poolIDNumber]; ok != true {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	UserIDToPoolID[userIDNumber] = poolIDNumberStr
	// this is the long pool id that links to the long id
	w.Header().Add("long_pool_id", PoolShortIDToLongID[poolIDNumber])
	// Let the user know the request was accepted
	w.WriteHeader(http.StatusOK)
}

func (d *DI) addSong(w http.ResponseWriter, r *http.Request) {
	songID := chi.URLParam(r, "songID")
	//poolID := chi.URLParam(r, "poolID")

	s := &pool.Song{ID: spotify.ID(songID)}
	heap.Push(&d.pool, s)
}

func (d *DI) upVote(w http.ResponseWriter, r *http.Request) {
	w.Header().Add("Access-Control-Allow-Origin", "http://localhost")

	// TODO check for user ID to see if they already voted
	songID := chi.URLParam(r, "songId")
	userID := r.PostFormValue("userId")

	if len(userID) == 0 || len(songID) == 0 {
		w.WriteHeader(http.StatusPartialContent)
		return
	}

	if !d.pool.HasUserVoted(userID, songID) {
		d.pool.UpVote(spotify.ID(songID), userID)
		d.pool.UpdateSpotifyPlaylist(&d.client, d.pool.PlaylistID)
	} else {
		w.WriteHeader(http.StatusMethodNotAllowed)
	}

	w.WriteHeader(http.StatusOK)
}

func (d *DI) downVote(w http.ResponseWriter, r *http.Request) {
	w.Header().Add("Access-Control-Allow-Origin", "http://localhost")

	// TODO check for user ID to see if they already voted
	songID := chi.URLParam(r, "songId")
	userID := r.PostFormValue("userId")
	//poolID := chi.URLParam(r, "poolID")

	if len(userID) == 0 || len(songID) == 0 {
		w.WriteHeader(http.StatusPartialContent)
		return
	}

	if !d.pool.HasUserVoted(userID, songID) {
		d.pool.DownVote(spotify.ID(songID), userID)
		d.pool.UpdateSpotifyPlaylist(&d.client, d.pool.PlaylistID)
		w.WriteHeader(http.StatusOK)
	} else {
		w.WriteHeader(http.StatusMethodNotAllowed)
	}
}

func (d *DI) createPool(w http.ResponseWriter, r *http.Request) {
}

func (d *DI) getPool(w http.ResponseWriter, r *http.Request) {
	w.Header().Add("Access-Control-Allow-Origin", "http://localhost")

	userid, err := d.client.CurrentUser()
	if err != nil {
		log.Println(err)
	}

	// TODO: instead of using existing playlist we require a new playlist to be created
	// playlist, err := d.client.CreatePlaylistForUser(userid.ID, playlistName, true)
	playlist, err := d.client.GetPlaylistTracks(userid.ID, "0nXlYUH7zBAzubO9Yub4rR")
	//spartahackPlaylistName := "Sparthack Sample Playlist!"
	//newPlaylist, err := d.client.CreatePlaylistForUser(userid.ID, spartahackPlaylistName, true)
	if err != nil {
		log.Println(err)
	}

	d.pool.SongHeap = make([]*pool.Song, 0, 100)
	for i, track := range playlist.Tracks {
		d.pool.SongHeap = append(d.pool.SongHeap, pool.TrackToSong(&track.Track, i))
	}
	d.pool.UserToVoteMap = make(map[string][]string)

	//TODO: only call this function only after the the current song finishes

	json.NewEncoder(w).Encode(d.pool)
	return
}

func completeAuth(w http.ResponseWriter, r *http.Request) {
	tok, err := auth.Token(state, r)
	if err != nil {
		http.Error(w, "Couldn't get token", http.StatusForbidden)
		log.Fatal(err)
	}

	if st := r.FormValue("state"); st != state {
		http.NotFound(w, r)
		log.Fatalf("State mismatch: %s != %s\n", st, state)
	}

	// use the token to get an authenticated client
	client := auth.NewClient(tok)
	ch <- client
	http.Redirect(w, r, "/getpool", 301)
}
<|endoftext|>


<commit_before>package mpredash

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

// UnsafeRedashStats represents a redash stats
type UnsafeRedashStats struct {
	WaitTasks       []UnsafeTaskStats `json:"waiting"`
	DoneTasks       []UnsafeTaskStats `json:"done"`
	InProgressTasks []UnsafeTaskStats `json:"in_progress"`
}

// UnsafeTaskStats represents a task stats
type UnsafeTaskStats struct {
	State     string `json:"state"`
	Scheduled bool   `json:"scheduled"`
}

// UnsafeAllTaskStats represents task states
var UnsafeAllTaskStates = []string{
	"waiting",
	"finished",
	"executing_query",
	"failed",
	"processing",
	"checking_alerts",
	"other", // other state is used for comprehensiveness
}

func getUnsafeStats(p RedashPlugin) (*UnsafeRedashStats, error) {
	// get json data
	timeout := time.Duration(p.Timeout) * time.Second
	client := http.Client{
		Timeout: timeout,
	}
	resp, err := client.Get(p.URI)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	// decode the json data to UnsafeRedashStats struct
	var s UnsafeRedashStats
	err = json.NewDecoder(resp.Body).Decode(&s)
	if err != nil {
		return nil, err
	}
	return &s, nil
}

func filterCount(ss []UnsafeTaskStats, test func(UnsafeTaskStats) bool) (count uint64) {
	for _, s := range ss {
		if test(s) {
			count++
		}
	}
	return
}

func isScheduled(s UnsafeTaskStats) bool { return s.Scheduled }
func isAdhoc(s UnsafeTaskStats) bool     { return !isScheduled(s) }
func isState(state string) func(UnsafeTaskStats) bool {
	return func(s UnsafeTaskStats) bool {
		if state == "other" {
			return isOtherState(s)
		}
		return s.State == state
	}
}
func isOtherState(s UnsafeTaskStats) bool {
	for _, state := range UnsafeAllTaskStates[0 : len(UnsafeAllTaskStates)-1] {
		if s.State == state {
			return false
		}
	}
	return true
}
<commit_msg>Fixed: comment<commit_after>package mpredash

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

// UnsafeRedashStats represents a redash stats
type UnsafeRedashStats struct {
	WaitTasks       []UnsafeTaskStats `json:"waiting"`
	DoneTasks       []UnsafeTaskStats `json:"done"`
	InProgressTasks []UnsafeTaskStats `json:"in_progress"`
}

// UnsafeTaskStats represents a task stats
type UnsafeTaskStats struct {
	State     string `json:"state"`
	Scheduled bool   `json:"scheduled"`
}

// UnsafeAllTaskStates represents task states
var UnsafeAllTaskStates = []string{
	"waiting",
	"finished",
	"executing_query",
	"failed",
	"processing",
	"checking_alerts",
	"other", // other state is used for comprehensiveness
}

func getUnsafeStats(p RedashPlugin) (*UnsafeRedashStats, error) {
	// get json data
	timeout := time.Duration(p.Timeout) * time.Second
	client := http.Client{
		Timeout: timeout,
	}
	resp, err := client.Get(p.URI)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	// decode the json data to UnsafeRedashStats struct
	var s UnsafeRedashStats
	err = json.NewDecoder(resp.Body).Decode(&s)
	if err != nil {
		return nil, err
	}
	return &s, nil
}

func filterCount(ss []UnsafeTaskStats, test func(UnsafeTaskStats) bool) (count uint64) {
	for _, s := range ss {
		if test(s) {
			count++
		}
	}
	return
}

func isScheduled(s UnsafeTaskStats) bool { return s.Scheduled }
func isAdhoc(s UnsafeTaskStats) bool     { return !isScheduled(s) }
func isState(state string) func(UnsafeTaskStats) bool {
	return func(s UnsafeTaskStats) bool {
		if state == "other" {
			return isOtherState(s)
		}
		return s.State == state
	}
}
func isOtherState(s UnsafeTaskStats) bool {
	for _, state := range UnsafeAllTaskStates[0 : len(UnsafeAllTaskStates)-1] {
		if s.State == state {
			return false
		}
	}
	return true
}
<|endoftext|>


<commit_before>package auth

import (
	"time"

	"github.com/EndFirstCorp/onedb/mgo"
	"github.com/pkg/errors"
	"gopkg.in/mgo.v2/bson"
)

type backendMongo struct {
	m mgo.Sessioner
	c Crypter
}

type mongoUser struct {
	ID                bson.ObjectId          `bson:"_id"               json:"id"`
	PrimaryEmail      string                 `bson:"primaryEmail"      json:"primaryEmail"`
	SecondaryEmails   []email                `bson:"secondaryEmails"   json:"secondaryEmails"`
	PasswordHash      string                 `bson:"passwordHash"      json:"passwordHash"`
	Info              map[string]interface{} `bson:"info"              json:"info"`
	LockoutEndTimeUTC *time.Time             `bson:"lockoutEndTimeUTC" json:"lockoutEndTimeUTC"`
	AccessFailedCount int                    `bson:"accessFailedCount" json:"accessFailedCount"`
}

type email struct {
	Address    string `bson:"address"    json:"address"`
	VerifyHash string `bson:"verifyHash" json:"verifyHash"`
	IsVerified bool   `bson:"isVerified" json:"isVerified"`
}

// NewBackendMongo creates a MongoDB-based Backender
func NewBackendMongo(m mgo.Sessioner, c Crypter) Backender {
	return &backendMongo{m, c}
}

func (b *backendMongo) Clone() Backender {
	return &backendMongo{b.m.Clone(), b.c}
}

func (b *backendMongo) AddUser(email string, info map[string]interface{}) (string, error) {
	u, err := b.getUser(email)
	if err == nil {
		return u.ID.Hex(), errors.New("user already exists")
	}

	id := bson.NewObjectId()
	return id.Hex(), b.users().Insert(mongoUser{ID: id, PrimaryEmail: email, Info: info})
}

func (b *backendMongo) AddUserFull(email, password string, info map[string]interface{}) (*User, error) {
	passwordHash, err := b.c.Hash(password)
	if err != nil {
		return nil, err
	}
	_, err = b.getUser(email)
	if err == nil {
		return nil, errors.New("user already exists")
	}

	id := bson.NewObjectId()
	return &User{id.Hex(), email, info}, b.users().Insert(mongoUser{ID: id, PrimaryEmail: email, PasswordHash: passwordHash, Info: info})
}

func (b *backendMongo) getUser(email string) (*mongoUser, error) {
	u := &mongoUser{}
	return u, b.users().Find(bson.M{"primaryEmail": email}).One(u)
}

func (b *backendMongo) GetUser(email string) (*User, error) {
	u, err := b.getUser(email)
	if err != nil {
		return nil, err
	}
	return &User{u.ID.Hex(), u.PrimaryEmail, u.Info}, nil
}

func (b *backendMongo) UpdateUser(userID, password string, info map[string]interface{}) error {
	passwordHash, err := b.c.Hash(password)
	if err != nil {
		return err
	}
	set := bson.M{"passwordHash": passwordHash, "info": info}
	return b.users().UpdateId(bson.ObjectIdHex(userID), bson.M{"$set": set})
}

func (b *backendMongo) UpdatePassword(userID, password string) error {
	passwordHash, err := b.c.Hash(password)
	if err != nil {
		return err
	}
	return b.users().UpdateId(bson.ObjectIdHex(userID), bson.M{"$set": bson.M{"passwordHash": passwordHash}})
}

func (b *backendMongo) UpdateInfo(userID string, info map[string]interface{}) error {
	var set bson.M
	for key := range info {
		set["info."+key] = info[key]
	}
	return b.users().UpdateId(bson.ObjectIdHex(userID), bson.M{"$set": set})
}

func (b *backendMongo) Close() error {
	b.m.Close()
	return nil
}

func (b *backendMongo) LoginAndGetUser(email, password string) (*User, error) {
	u, err := b.getUser(email)
	if err != nil {
		return nil, err
	}
	if err := b.c.HashEquals(password, u.PasswordHash); err != nil {
		return nil, err
	}
	return &User{u.ID.Hex(), u.PrimaryEmail, u.Info}, nil
}

func (b *backendMongo) Login(email, password string) error {
	_, err := b.LoginAndGetUser(email, password)
	return err
}

func (b *backendMongo) AddSecondaryEmail(userID, secondaryEmail string) error {
	return nil
}

func (b *backendMongo) UpdatePrimaryEmail(userID, secondaryEmail string) error {
	return nil
}

func (b *backendMongo) CreateEmailSession(userID, email string, info map[string]interface{}, emailVerifyHash, csrfToken string) error {
	s := b.emailSessions()
	c, _ := s.FindId(emailVerifyHash).Count()
	if c > 0 {
		return errors.New("invalid emailVerifyHash")
	}
	return s.Insert(&emailSession{userID, email, info, emailVerifyHash, csrfToken})
}

func (b *backendMongo) GetEmailSession(verifyHash string) (*emailSession, error) {
	session := &emailSession{}
	return session, b.emailSessions().FindId(verifyHash).One(session)
}

func (b *backendMongo) UpdateEmailSession(verifyHash, userID string) error {
	return b.emailSessions().UpdateId(verifyHash, bson.M{"$set": bson.M{"userID": userID}})
}
func (b *backendMongo) DeleteEmailSession(verifyHash string) error {
	return b.emailSessions().RemoveId(verifyHash)
}
func (b *backendMongo) CreateSession(userID, email string, info map[string]interface{}, sessionHash, csrfToken string, renewTimeUTC, expireTimeUTC time.Time) (*LoginSession, error) {
	s := LoginSession{userID, email, info, sessionHash, csrfToken, renewTimeUTC, expireTimeUTC}
	return &s, b.loginSessions().Insert(s)
}

func (b *backendMongo) CreateRememberMe(userID, email, selector, tokenHash string, renewTimeUTC, expireTimeUTC time.Time) (*rememberMeSession, error) {
	r := rememberMeSession{userID, email, selector, tokenHash, renewTimeUTC, expireTimeUTC}
	return &r, b.rememberMeSessions().Insert(&r)
}

func (b *backendMongo) GetSession(sessionHash string) (*LoginSession, error) {
	session := &LoginSession{}
	return session, b.loginSessions().FindId(sessionHash).One(session)
}

func (b *backendMongo) UpdateSession(sessionHash string, renewTimeUTC, expireTimeUTC time.Time) error {
	return b.loginSessions().UpdateId(sessionHash, bson.M{"$set": bson.M{"expireTimeUTC": expireTimeUTC, "renewTimeUTC": renewTimeUTC}})
}

func (b *backendMongo) DeleteSession(sessionHash string) error {
	return b.loginSessions().RemoveId(sessionHash)
}
func (b *backendMongo) DeleteSessions(e string) error {
	_, err := b.loginSessions().RemoveAll(bson.M{"email": e})
	return err
}
func (b *backendMongo) InvalidateSessions(email string) error {
	return nil
}
func (b *backendMongo) GetRememberMe(selector string) (*rememberMeSession, error) {
	rememberMe := &rememberMeSession{}
	return rememberMe, b.rememberMeSessions().FindId(selector).One(rememberMe)
}
func (b *backendMongo) UpdateRememberMe(selector string, renewTimeUTC time.Time) error {
	return b.rememberMeSessions().UpdateId(selector, bson.M{"$set": bson.M{"renewTimeUTC": renewTimeUTC}})
}
func (b *backendMongo) DeleteRememberMe(selector string) error {
	return b.rememberMeSessions().RemoveId(selector)
}
func (b *backendMongo) DeleteRememberMes(e string) error {
	_, err := b.rememberMeSessions().RemoveAll(bson.M{"email": e})
	return err
}

func (b *backendMongo) users() mgo.Collectioner {
	return b.m.DB("users").C("users")
}
func (b *backendMongo) emailSessions() mgo.Collectioner {
	return b.m.DB("users").C("emailSessions")
}
func (b *backendMongo) loginSessions() mgo.Collectioner {
	return b.m.DB("users").C("loginSessions")
}
func (b *backendMongo) rememberMeSessions() mgo.Collectioner {
	return b.m.DB("users").C("rememberMeSessions")
}
<commit_msg>update backendMongo to only deal with lower cased email addresses<commit_after>package auth

import (
	"strings"
	"time"

	"github.com/EndFirstCorp/onedb/mgo"
	"github.com/pkg/errors"
	"gopkg.in/mgo.v2/bson"
)

type backendMongo struct {
	m mgo.Sessioner
	c Crypter
}

type mongoUser struct {
	ID                bson.ObjectId          `bson:"_id"               json:"id"`
	PrimaryEmail      string                 `bson:"primaryEmail"      json:"primaryEmail"`
	SecondaryEmails   []email                `bson:"secondaryEmails"   json:"secondaryEmails"`
	PasswordHash      string                 `bson:"passwordHash"      json:"passwordHash"`
	Info              map[string]interface{} `bson:"info"              json:"info"`
	LockoutEndTimeUTC *time.Time             `bson:"lockoutEndTimeUTC" json:"lockoutEndTimeUTC"`
	AccessFailedCount int                    `bson:"accessFailedCount" json:"accessFailedCount"`
}

type email struct {
	Address    string `bson:"address"    json:"address"`
	VerifyHash string `bson:"verifyHash" json:"verifyHash"`
	IsVerified bool   `bson:"isVerified" json:"isVerified"`
}

// NewBackendMongo creates a MongoDB-based Backender
func NewBackendMongo(m mgo.Sessioner, c Crypter) Backender {
	return &backendMongo{m, c}
}

func (b *backendMongo) Clone() Backender {
	return &backendMongo{b.m.Clone(), b.c}
}

func (b *backendMongo) AddUser(email string, info map[string]interface{}) (string, error) {
	u, err := b.getUser(email)
	if err == nil {
		return u.ID.Hex(), errors.New("user already exists")
	}

	id := bson.NewObjectId()
	return id.Hex(), b.users().Insert(mongoUser{ID: id, PrimaryEmail: email, Info: info})
}

func (b *backendMongo) AddUserFull(email, password string, info map[string]interface{}) (*User, error) {
	passwordHash, err := b.c.Hash(password)
	if err != nil {
		return nil, err
	}
	_, err = b.getUser(email)
	if err == nil {
		return nil, errors.New("user already exists")
	}

	id := bson.NewObjectId()
	return &User{id.Hex(), strings.ToLower(email), info}, b.users().Insert(mongoUser{ID: id, PrimaryEmail: strings.ToLower(email), PasswordHash: passwordHash, Info: info})
}

func (b *backendMongo) getUser(email string) (*mongoUser, error) {
	u := &mongoUser{}
	return u, b.users().Find(bson.M{"primaryEmail": strings.ToLower(email)}).One(u)
}

func (b *backendMongo) GetUser(email string) (*User, error) {
	u, err := b.getUser(email)
	if err != nil {
		return nil, err
	}
	return &User{u.ID.Hex(), u.PrimaryEmail, u.Info}, nil
}

func (b *backendMongo) UpdateUser(userID, password string, info map[string]interface{}) error {
	passwordHash, err := b.c.Hash(password)
	if err != nil {
		return err
	}
	set := bson.M{"passwordHash": passwordHash, "info": info}
	return b.users().UpdateId(bson.ObjectIdHex(userID), bson.M{"$set": set})
}

func (b *backendMongo) UpdatePassword(userID, password string) error {
	passwordHash, err := b.c.Hash(password)
	if err != nil {
		return err
	}
	return b.users().UpdateId(bson.ObjectIdHex(userID), bson.M{"$set": bson.M{"passwordHash": passwordHash}})
}

func (b *backendMongo) UpdateInfo(userID string, info map[string]interface{}) error {
	var set bson.M
	for key := range info {
		set["info."+key] = info[key]
	}
	return b.users().UpdateId(bson.ObjectIdHex(userID), bson.M{"$set": set})
}

func (b *backendMongo) Close() error {
	b.m.Close()
	return nil
}

func (b *backendMongo) LoginAndGetUser(email, password string) (*User, error) {
	u, err := b.getUser(email)
	if err != nil {
		return nil, err
	}
	if err := b.c.HashEquals(password, u.PasswordHash); err != nil {
		return nil, err
	}
	return &User{u.ID.Hex(), u.PrimaryEmail, u.Info}, nil
}

func (b *backendMongo) Login(email, password string) error {
	_, err := b.LoginAndGetUser(email, password)
	return err
}

func (b *backendMongo) AddSecondaryEmail(userID, secondaryEmail string) error {
	return nil
}

func (b *backendMongo) UpdatePrimaryEmail(userID, secondaryEmail string) error {
	return nil
}

func (b *backendMongo) CreateEmailSession(userID, email string, info map[string]interface{}, emailVerifyHash, csrfToken string) error {
	s := b.emailSessions()
	c, _ := s.FindId(emailVerifyHash).Count()
	if c > 0 {
		return errors.New("invalid emailVerifyHash")
	}
	return s.Insert(&emailSession{userID, strings.ToLower(email), info, emailVerifyHash, csrfToken})
}

func (b *backendMongo) GetEmailSession(verifyHash string) (*emailSession, error) {
	session := &emailSession{}
	return session, b.emailSessions().FindId(verifyHash).One(session)
}

func (b *backendMongo) UpdateEmailSession(verifyHash, userID string) error {
	return b.emailSessions().UpdateId(verifyHash, bson.M{"$set": bson.M{"userID": userID}})
}
func (b *backendMongo) DeleteEmailSession(verifyHash string) error {
	return b.emailSessions().RemoveId(verifyHash)
}
func (b *backendMongo) CreateSession(userID, email string, info map[string]interface{}, sessionHash, csrfToken string, renewTimeUTC, expireTimeUTC time.Time) (*LoginSession, error) {
	s := LoginSession{userID, strings.ToLower(email), info, sessionHash, csrfToken, renewTimeUTC, expireTimeUTC}
	return &s, b.loginSessions().Insert(s)
}

func (b *backendMongo) CreateRememberMe(userID, email, selector, tokenHash string, renewTimeUTC, expireTimeUTC time.Time) (*rememberMeSession, error) {
	r := rememberMeSession{userID, strings.ToLower(email), selector, tokenHash, renewTimeUTC, expireTimeUTC}
	return &r, b.rememberMeSessions().Insert(&r)
}

func (b *backendMongo) GetSession(sessionHash string) (*LoginSession, error) {
	session := &LoginSession{}
	return session, b.loginSessions().FindId(sessionHash).One(session)
}

func (b *backendMongo) UpdateSession(sessionHash string, renewTimeUTC, expireTimeUTC time.Time) error {
	return b.loginSessions().UpdateId(sessionHash, bson.M{"$set": bson.M{"expireTimeUTC": expireTimeUTC, "renewTimeUTC": renewTimeUTC}})
}

func (b *backendMongo) DeleteSession(sessionHash string) error {
	return b.loginSessions().RemoveId(sessionHash)
}
func (b *backendMongo) DeleteSessions(e string) error {
	_, err := b.loginSessions().RemoveAll(bson.M{"email": strings.ToLower(e)})
	return err
}
func (b *backendMongo) InvalidateSessions(email string) error {
	return nil
}
func (b *backendMongo) GetRememberMe(selector string) (*rememberMeSession, error) {
	rememberMe := &rememberMeSession{}
	return rememberMe, b.rememberMeSessions().FindId(selector).One(rememberMe)
}
func (b *backendMongo) UpdateRememberMe(selector string, renewTimeUTC time.Time) error {
	return b.rememberMeSessions().UpdateId(selector, bson.M{"$set": bson.M{"renewTimeUTC": renewTimeUTC}})
}
func (b *backendMongo) DeleteRememberMe(selector string) error {
	return b.rememberMeSessions().RemoveId(selector)
}
func (b *backendMongo) DeleteRememberMes(e string) error {
	_, err := b.rememberMeSessions().RemoveAll(bson.M{"email": strings.ToLower(e)})
	return err
}

func (b *backendMongo) users() mgo.Collectioner {
	return b.m.DB("users").C("users")
}
func (b *backendMongo) emailSessions() mgo.Collectioner {
	return b.m.DB("users").C("emailSessions")
}
func (b *backendMongo) loginSessions() mgo.Collectioner {
	return b.m.DB("users").C("loginSessions")
}
func (b *backendMongo) rememberMeSessions() mgo.Collectioner {
	return b.m.DB("users").C("rememberMeSessions")
}
<|endoftext|>


<commit_before>// Copyright 2017 The go-hep 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 fastjet

type ClusterSequenceStructure struct {
	cs *ClusterSequence
}

func (css ClusterSequenceStructure) Constituents(jet *Jet) ([]Jet, error) {
	return css.cs.Constituents(jet)
}
<commit_msg>fastjet: document ClusterSequenceStructure<commit_after>// Copyright 2017 The go-hep 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 fastjet

// ClusterSequenceStructure is a ClusterSequence that implements
// the JetStructure interface.
type ClusterSequenceStructure struct {
	cs *ClusterSequence
}

func (css ClusterSequenceStructure) Constituents(jet *Jet) ([]Jet, error) {
	return css.cs.Constituents(jet)
}
<|endoftext|>