<commit_before>package main

import (
	/*	"fmt"*/
	"github.com/gorilla/mux"
	"github.com/rainycape/magick"
	"io"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
	"time"
)

func main() {
	r := mux.NewRouter()
	r.HandleFunc("/product/image/{id:[0-9]+}/{width:[0-9]+}x{height:[0-9]+}.{format}", rectangleHandler).Methods("GET")
	r.HandleFunc("/product/image/{id:[0-9]+}/x{width:[0-9]+}.{format}", squareHandler).Methods("GET")
	r.HandleFunc("/product/image/{id:[0-9]+}/w{width:[0-9]+}.{format}", widthHandler).Methods("GET")
	r.HandleFunc("/product/image/{id:[0-9]+}/full_size.{format}", fullSizeHandler).Methods("GET")
	http.Handle("/", r)
	log.Println("Listening on port 7000...")
	http.ListenAndServe(":7000", nil)
}

func downloadAndSaveOriginal(path string, productId string, source string) {
	if _, err := os.Stat(path); os.IsNotExist(err) {
		start := time.Now()
		var url string
		if source != "" {
			url = source
		} else {
			url = "http://cdn-s3-2.wanelo.com/product/image/" + productId + "/original.jpg"
		}
		resp, err := http.Get(url)
		if err != nil {
			log.Fatal(err)
		}
		defer resp.Body.Close()

		dir := filepath.Dir(path)
		os.Mkdir(dir, 0700)

		out, err := os.Create(path)
		defer out.Close()

		io.Copy(out, resp.Body)
		elapsed := time.Since(start)
		log.Printf("Took %s to download image: %s", elapsed, path)
	}
}

func createWithMagick(fullSizePath string, resizedPath string, width string, height string, format string) {
	start := time.Now()
	im, err := magick.DecodeFile(fullSizePath)
	if err != nil {
		log.Panicln(err)
		return
	}
	defer im.Dispose()

	w, _ := strconv.Atoi(width)
	h, _ := strconv.Atoi(height)

	im2, err := im.CropResize(w, h, magick.FHamming, magick.CSCenter)
	if err != nil {
		log.Panicln(err)
		return
	}

	out, err := os.Create(resizedPath)
	defer out.Close()

	info := magick.NewInfo()
	info.SetQuality(75)
	info.SetFormat(format)
	err = im2.Encode(out, info)

	if err != nil {
		log.Panicln(err)
		return
	}
	elapsed := time.Since(start)
	log.Printf("Took %s to generate image: %s", elapsed, resizedPath)
}

func createImages(ic *ImageConfiguration) (path string) {
	var resizedPath string
	if ic.height == "0" {
		resizedPath = "public/generated/" + ic.id + "_x" + ic.width + "." + ic.format
	} else {
		resizedPath = "public/generated/" + ic.id + "_" + ic.width + "x" + ic.height + "." + ic.format
	}

	log.Printf("Source specified: %s", ic.source)
	if _, err := os.Stat(resizedPath); os.IsNotExist(err) {
		dir := filepath.Dir(resizedPath)
		os.Mkdir(dir, 0700)

		originalPath := "public/" + ic.id
		downloadAndSaveOriginal(originalPath, ic.id, ic.source)
		createWithMagick(originalPath, resizedPath, ic.width, ic.height, ic.format)
	}

	return resizedPath
}

type ImageConfiguration struct {
	id     string
	width  string
	height string
	format string
	source string
}

func buildImageConfiguration(r *http.Request) *ImageConfiguration {
	ic := new(ImageConfiguration)
	params := mux.Vars(r)
	qs := r.URL.Query()

	ic.id = params["id"]
	ic.width = params["width"]
	ic.height = params["height"]
	ic.format = params["format"]
	ic.source = qs.Get("printer")

	return ic
}

func rectangleHandler(w http.ResponseWriter, r *http.Request) {
	ic := buildImageConfiguration(r)
	resizedPath := createImages(ic)
	http.ServeFile(w, r, resizedPath)
}

func squareHandler(w http.ResponseWriter, r *http.Request) {
	ic := buildImageConfiguration(r)
	ic.height = ic.width
	resizedPath := createImages(ic)
	http.ServeFile(w, r, resizedPath)
}

func widthHandler(w http.ResponseWriter, r *http.Request) {
	ic := buildImageConfiguration(r)
	ic.height = "0"
	resizedPath := createImages(ic)
	http.ServeFile(w, r, resizedPath)
}

func fullSizeHandler(w http.ResponseWriter, r *http.Request) {
	ic := buildImageConfiguration(r)
	fullSizePath := "public/" + ic.id
	resizedPath := "public/generated/" + ic.id + "_full_size." + ic.format

	if _, err := os.Stat(resizedPath); os.IsNotExist(err) {
		downloadAndSaveOriginal(fullSizePath, ic.id, ic.source)

		im, err := magick.DecodeFile(fullSizePath)
		if err != nil {
			log.Panicln(err)
			return
		}
		defer im.Dispose()

		out, err := os.Create(resizedPath)
		defer out.Close()

		info := magick.NewInfo()
		info.SetQuality(75)
		info.SetFormat(ic.format)
		err = im.Encode(out, info)

		if err != nil {
			log.Panicln(err)
			return
		}
	}

	http.ServeFile(w, r, resizedPath)
}
<commit_msg>Extract remoteImageUrl to be built from image configuration<commit_after>package main

import (
	/*	"fmt"*/
	"github.com/gorilla/mux"
	"github.com/rainycape/magick"
	"io"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
	"time"
)

func main() {
	r := mux.NewRouter()
	r.HandleFunc("/product/image/{id:[0-9]+}/{width:[0-9]+}x{height:[0-9]+}.{format}", rectangleHandler).Methods("GET")
	r.HandleFunc("/product/image/{id:[0-9]+}/x{width:[0-9]+}.{format}", squareHandler).Methods("GET")
	r.HandleFunc("/product/image/{id:[0-9]+}/w{width:[0-9]+}.{format}", widthHandler).Methods("GET")
	r.HandleFunc("/product/image/{id:[0-9]+}/full_size.{format}", fullSizeHandler).Methods("GET")
	http.Handle("/", r)
	log.Println("Listening on port 7000...")
	http.ListenAndServe(":7000", nil)
}

func downloadAndSaveOriginal(ic *ImageConfiguration, path string, productId string, source string) {
	if _, err := os.Stat(path); os.IsNotExist(err) {
		start := time.Now()

		remoteUrl := ic.RemoteImageUrl()
		resp, err := http.Get(remoteUrl)
		if err != nil {
			log.Fatal(err)
		}
		defer resp.Body.Close()

		dir := filepath.Dir(path)
		os.Mkdir(dir, 0700)

		out, err := os.Create(path)
		defer out.Close()

		io.Copy(out, resp.Body)
		elapsed := time.Since(start)
		log.Printf("Took %s to download image: %s", elapsed, path)
	}
}

func createWithMagick(fullSizePath string, resizedPath string, width string, height string, format string) {
	start := time.Now()
	im, err := magick.DecodeFile(fullSizePath)
	if err != nil {
		log.Panicln(err)
		return
	}
	defer im.Dispose()

	w, _ := strconv.Atoi(width)
	h, _ := strconv.Atoi(height)

	im2, err := im.CropResize(w, h, magick.FHamming, magick.CSCenter)
	if err != nil {
		log.Panicln(err)
		return
	}

	out, err := os.Create(resizedPath)
	defer out.Close()

	info := magick.NewInfo()
	info.SetQuality(75)
	info.SetFormat(format)
	err = im2.Encode(out, info)

	if err != nil {
		log.Panicln(err)
		return
	}
	elapsed := time.Since(start)
	log.Printf("Took %s to generate image: %s", elapsed, resizedPath)
}

func createImages(ic *ImageConfiguration) (path string) {
	var resizedPath string
	if ic.height == "0" {
		resizedPath = "public/generated/" + ic.id + "_x" + ic.width + "." + ic.format
	} else {
		resizedPath = "public/generated/" + ic.id + "_" + ic.width + "x" + ic.height + "." + ic.format
	}

	log.Printf("Source specified: %s", ic.source)
	if _, err := os.Stat(resizedPath); os.IsNotExist(err) {
		dir := filepath.Dir(resizedPath)
		os.Mkdir(dir, 0700)

		originalPath := "public/" + ic.id
		downloadAndSaveOriginal(ic, originalPath, ic.id, ic.source)
		createWithMagick(originalPath, resizedPath, ic.width, ic.height, ic.format)
	}

	return resizedPath
}

type ImageConfiguration struct {
	id     string
	width  string
	height string
	format string
	source string
}

func (ic *ImageConfiguration) RemoteImageUrl() string {
	if ic.source != "" {
		return ic.source
	} else {
		return "http://cdn-s3-2.wanelo.com/product/image/" + ic.id + "/original.jpg"
	}
}

func buildImageConfiguration(r *http.Request) *ImageConfiguration {
	ic := new(ImageConfiguration)
	params := mux.Vars(r)
	qs := r.URL.Query()

	ic.id = params["id"]
	ic.width = params["width"]
	ic.height = params["height"]
	ic.format = params["format"]
	ic.source = qs.Get("source")

	return ic
}

func rectangleHandler(w http.ResponseWriter, r *http.Request) {
	ic := buildImageConfiguration(r)
	resizedPath := createImages(ic)
	http.ServeFile(w, r, resizedPath)
}

func squareHandler(w http.ResponseWriter, r *http.Request) {
	ic := buildImageConfiguration(r)
	ic.height = ic.width
	resizedPath := createImages(ic)
	http.ServeFile(w, r, resizedPath)
}

func widthHandler(w http.ResponseWriter, r *http.Request) {
	ic := buildImageConfiguration(r)
	ic.height = "0"
	resizedPath := createImages(ic)
	http.ServeFile(w, r, resizedPath)
}

func fullSizeHandler(w http.ResponseWriter, r *http.Request) {
	ic := buildImageConfiguration(r)
	fullSizePath := "public/" + ic.id
	resizedPath := "public/generated/" + ic.id + "_full_size." + ic.format

	if _, err := os.Stat(resizedPath); os.IsNotExist(err) {
		downloadAndSaveOriginal(ic, fullSizePath, ic.id, ic.source)

		im, err := magick.DecodeFile(fullSizePath)
		if err != nil {
			log.Panicln(err)
			return
		}
		defer im.Dispose()

		out, err := os.Create(resizedPath)
		defer out.Close()

		info := magick.NewInfo()
		info.SetQuality(75)
		info.SetFormat(ic.format)
		err = im.Encode(out, info)

		if err != nil {
			log.Panicln(err)
			return
		}
	}

	http.ServeFile(w, r, resizedPath)
}
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes 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 federatedtypes

import (
	"reflect"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	pkgruntime "k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/types"
	"k8s.io/apimachinery/pkg/watch"
	federationclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset"
	"k8s.io/kubernetes/federation/pkg/federation-controller/util"
	"k8s.io/kubernetes/pkg/api/v1"
	extensionsv1 "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
	kubeclientset "k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
)

const (
	DaemonSetKind           = "daemonset"
	DaemonSetControllerName = "daemonsets"
)

func init() {
	RegisterFederatedType(DaemonSetKind, DaemonSetControllerName, []schema.GroupVersionResource{extensionsv1.SchemeGroupVersion.WithResource(DaemonSetControllerName)}, NewDaemonSetAdapter)
}

type DaemonSetAdapter struct {
	client federationclientset.Interface
}

func NewDaemonSetAdapter(client federationclientset.Interface) FederatedTypeAdapter {
	return &DaemonSetAdapter{client: client}
}

func (a *DaemonSetAdapter) Kind() string {
	return DaemonSetKind
}

func (a *DaemonSetAdapter) ObjectType() pkgruntime.Object {
	return &extensionsv1.DaemonSet{}
}

func (a *DaemonSetAdapter) IsExpectedType(obj interface{}) bool {
	_, ok := obj.(*extensionsv1.DaemonSet)
	return ok
}

func (a *DaemonSetAdapter) Copy(obj pkgruntime.Object) pkgruntime.Object {
	daemonset := obj.(*extensionsv1.DaemonSet)
	return &extensionsv1.DaemonSet{
		ObjectMeta: util.DeepCopyRelevantObjectMeta(daemonset.ObjectMeta),
		Spec:       *(util.DeepCopyApiTypeOrPanic(&daemonset.Spec).(*extensionsv1.DaemonSetSpec)),
	}
}

func (a *DaemonSetAdapter) Equivalent(obj1, obj2 pkgruntime.Object) bool {
	daemonset1 := obj1.(*extensionsv1.DaemonSet)
	daemonset2 := obj2.(*extensionsv1.DaemonSet)
	return util.ObjectMetaEquivalent(daemonset1.ObjectMeta, daemonset2.ObjectMeta) && reflect.DeepEqual(daemonset1.Spec, daemonset2.Spec)
}

func (a *DaemonSetAdapter) NamespacedName(obj pkgruntime.Object) types.NamespacedName {
	daemonset := obj.(*extensionsv1.DaemonSet)
	return types.NamespacedName{Namespace: daemonset.Namespace, Name: daemonset.Name}
}

func (a *DaemonSetAdapter) ObjectMeta(obj pkgruntime.Object) *metav1.ObjectMeta {
	return &obj.(*extensionsv1.DaemonSet).ObjectMeta
}

func (a *DaemonSetAdapter) FedCreate(obj pkgruntime.Object) (pkgruntime.Object, error) {
	daemonset := obj.(*extensionsv1.DaemonSet)
	return a.client.Extensions().DaemonSets(daemonset.Namespace).Create(daemonset)
}

func (a *DaemonSetAdapter) FedDelete(namespacedName types.NamespacedName, options *metav1.DeleteOptions) error {
	return a.client.Extensions().DaemonSets(namespacedName.Namespace).Delete(namespacedName.Name, options)
}

func (a *DaemonSetAdapter) FedGet(namespacedName types.NamespacedName) (pkgruntime.Object, error) {
	return a.client.Extensions().DaemonSets(namespacedName.Namespace).Get(namespacedName.Name, metav1.GetOptions{})
}

func (a *DaemonSetAdapter) FedList(namespace string, options metav1.ListOptions) (pkgruntime.Object, error) {
	return a.client.Extensions().DaemonSets(namespace).List(options)
}

func (a *DaemonSetAdapter) FedUpdate(obj pkgruntime.Object) (pkgruntime.Object, error) {
	daemonset := obj.(*extensionsv1.DaemonSet)
	return a.client.Extensions().DaemonSets(daemonset.Namespace).Update(daemonset)
}

func (a *DaemonSetAdapter) FedWatch(namespace string, options metav1.ListOptions) (watch.Interface, error) {
	return a.client.Extensions().DaemonSets(namespace).Watch(options)
}

func (a *DaemonSetAdapter) ClusterCreate(client kubeclientset.Interface, obj pkgruntime.Object) (pkgruntime.Object, error) {
	daemonset := obj.(*extensionsv1.DaemonSet)
	return client.Extensions().DaemonSets(daemonset.Namespace).Create(daemonset)
}

func (a *DaemonSetAdapter) ClusterDelete(client kubeclientset.Interface, nsName types.NamespacedName, options *metav1.DeleteOptions) error {
	return client.Extensions().DaemonSets(nsName.Namespace).Delete(nsName.Name, options)
}

func (a *DaemonSetAdapter) ClusterGet(client kubeclientset.Interface, namespacedName types.NamespacedName) (pkgruntime.Object, error) {
	return client.Extensions().DaemonSets(namespacedName.Namespace).Get(namespacedName.Name, metav1.GetOptions{})
}

func (a *DaemonSetAdapter) ClusterList(client kubeclientset.Interface, namespace string, options metav1.ListOptions) (pkgruntime.Object, error) {
	return client.Extensions().DaemonSets(namespace).List(options)
}

func (a *DaemonSetAdapter) ClusterUpdate(client kubeclientset.Interface, obj pkgruntime.Object) (pkgruntime.Object, error) {
	daemonset := obj.(*extensionsv1.DaemonSet)
	return client.Extensions().DaemonSets(daemonset.Namespace).Update(daemonset)
}

func (a *DaemonSetAdapter) ClusterWatch(client kubeclientset.Interface, namespace string, options metav1.ListOptions) (watch.Interface, error) {
	return client.Extensions().DaemonSets(namespace).Watch(options)
}

func (a *DaemonSetAdapter) IsSchedulingAdapter() bool {
	return false
}

func (a *DaemonSetAdapter) NewTestObject(namespace string) pkgruntime.Object {
	return &extensionsv1.DaemonSet{
		ObjectMeta: metav1.ObjectMeta{
			GenerateName: "test-daemonset-",
			Namespace:    namespace,
			Labels:       map[string]string{"app": "test-daemonset"},
		},
		Spec: extensionsv1.DaemonSetSpec{
			Template: v1.PodTemplateSpec{
				ObjectMeta: metav1.ObjectMeta{
					Labels: map[string]string{"name": "test-pod"},
				},
				Spec: v1.PodSpec{
					Containers: []v1.Container{
						{
							Name:  "test-daemonset",
							Image: "images/test-daemonset",
							Ports: []v1.ContainerPort{{ContainerPort: 9376}},
						},
					},
				},
			},
		},
	}
}
<commit_msg>Ignore `daemonset-controller-hash` label key in federation before comparing the federated object with its cluster equivalent.<commit_after>/*
Copyright 2017 The Kubernetes 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 federatedtypes

import (
	"reflect"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	pkgruntime "k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/types"
	"k8s.io/apimachinery/pkg/watch"
	federationclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset"
	"k8s.io/kubernetes/federation/pkg/federation-controller/util"
	"k8s.io/kubernetes/pkg/api/v1"
	extensionsv1 "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
	kubeclientset "k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
)

const (
	DaemonSetKind           = "daemonset"
	DaemonSetControllerName = "daemonsets"
)

func init() {
	RegisterFederatedType(DaemonSetKind, DaemonSetControllerName, []schema.GroupVersionResource{extensionsv1.SchemeGroupVersion.WithResource(DaemonSetControllerName)}, NewDaemonSetAdapter)
}

type DaemonSetAdapter struct {
	client federationclientset.Interface
}

func NewDaemonSetAdapter(client federationclientset.Interface) FederatedTypeAdapter {
	return &DaemonSetAdapter{client: client}
}

func (a *DaemonSetAdapter) Kind() string {
	return DaemonSetKind
}

func (a *DaemonSetAdapter) ObjectType() pkgruntime.Object {
	return &extensionsv1.DaemonSet{}
}

func (a *DaemonSetAdapter) IsExpectedType(obj interface{}) bool {
	_, ok := obj.(*extensionsv1.DaemonSet)
	return ok
}

func (a *DaemonSetAdapter) Copy(obj pkgruntime.Object) pkgruntime.Object {
	daemonset := obj.(*extensionsv1.DaemonSet)
	return &extensionsv1.DaemonSet{
		ObjectMeta: util.DeepCopyRelevantObjectMeta(daemonset.ObjectMeta),
		Spec:       *(util.DeepCopyApiTypeOrPanic(&daemonset.Spec).(*extensionsv1.DaemonSetSpec)),
	}
}

func (a *DaemonSetAdapter) Equivalent(obj1, obj2 pkgruntime.Object) bool {
	daemonset1 := obj1.(*extensionsv1.DaemonSet)
	daemonset2 := obj2.(*extensionsv1.DaemonSet)

	// Kubernetes daemonset controller writes a daemonset's hash to
	// the object label as an optimization to avoid recomputing it every
	// time. Adding a new label to the object that the federation is
	// unaware of causes problems because federated controllers compare
	// the objects in federation and their equivalents in clusters and
	// try to reconcile them. This leads to a constant fight between the
	// federated daemonset controller and the cluster controllers, and
	// they never reach a stable state.
	//
	// Ideally, cluster components should not update an object's spec or
	// metadata in a way federation cannot replicate. They can update an
	// object's status though. Therefore, this daemonset hash should
	// be a field in daemonset's status, not a label in object meta.
	// @janetkuo says that this label is only a short term solution. In
	// the near future, they are going to replace it with revision numbers
	// in daemonset status. We can then rip this bandaid out.
	//
	// We are deleting the keys here and that should be fine since we are
	// working on object copies. Also, propagating the deleted labels
	// should also be fine because we don't support daemonset rolling
	// update in federation yet.
	delete(daemonset1.ObjectMeta.Labels, extensionsv1.DefaultDaemonSetUniqueLabelKey)
	delete(daemonset2.ObjectMeta.Labels, extensionsv1.DefaultDaemonSetUniqueLabelKey)

	return util.ObjectMetaEquivalent(daemonset1.ObjectMeta, daemonset2.ObjectMeta) && reflect.DeepEqual(daemonset1.Spec, daemonset2.Spec)
}

func (a *DaemonSetAdapter) NamespacedName(obj pkgruntime.Object) types.NamespacedName {
	daemonset := obj.(*extensionsv1.DaemonSet)
	return types.NamespacedName{Namespace: daemonset.Namespace, Name: daemonset.Name}
}

func (a *DaemonSetAdapter) ObjectMeta(obj pkgruntime.Object) *metav1.ObjectMeta {
	return &obj.(*extensionsv1.DaemonSet).ObjectMeta
}

func (a *DaemonSetAdapter) FedCreate(obj pkgruntime.Object) (pkgruntime.Object, error) {
	daemonset := obj.(*extensionsv1.DaemonSet)
	return a.client.Extensions().DaemonSets(daemonset.Namespace).Create(daemonset)
}

func (a *DaemonSetAdapter) FedDelete(namespacedName types.NamespacedName, options *metav1.DeleteOptions) error {
	return a.client.Extensions().DaemonSets(namespacedName.Namespace).Delete(namespacedName.Name, options)
}

func (a *DaemonSetAdapter) FedGet(namespacedName types.NamespacedName) (pkgruntime.Object, error) {
	return a.client.Extensions().DaemonSets(namespacedName.Namespace).Get(namespacedName.Name, metav1.GetOptions{})
}

func (a *DaemonSetAdapter) FedList(namespace string, options metav1.ListOptions) (pkgruntime.Object, error) {
	return a.client.Extensions().DaemonSets(namespace).List(options)
}

func (a *DaemonSetAdapter) FedUpdate(obj pkgruntime.Object) (pkgruntime.Object, error) {
	daemonset := obj.(*extensionsv1.DaemonSet)
	return a.client.Extensions().DaemonSets(daemonset.Namespace).Update(daemonset)
}

func (a *DaemonSetAdapter) FedWatch(namespace string, options metav1.ListOptions) (watch.Interface, error) {
	return a.client.Extensions().DaemonSets(namespace).Watch(options)
}

func (a *DaemonSetAdapter) ClusterCreate(client kubeclientset.Interface, obj pkgruntime.Object) (pkgruntime.Object, error) {
	daemonset := obj.(*extensionsv1.DaemonSet)
	return client.Extensions().DaemonSets(daemonset.Namespace).Create(daemonset)
}

func (a *DaemonSetAdapter) ClusterDelete(client kubeclientset.Interface, nsName types.NamespacedName, options *metav1.DeleteOptions) error {
	return client.Extensions().DaemonSets(nsName.Namespace).Delete(nsName.Name, options)
}

func (a *DaemonSetAdapter) ClusterGet(client kubeclientset.Interface, namespacedName types.NamespacedName) (pkgruntime.Object, error) {
	return client.Extensions().DaemonSets(namespacedName.Namespace).Get(namespacedName.Name, metav1.GetOptions{})
}

func (a *DaemonSetAdapter) ClusterList(client kubeclientset.Interface, namespace string, options metav1.ListOptions) (pkgruntime.Object, error) {
	return client.Extensions().DaemonSets(namespace).List(options)
}

func (a *DaemonSetAdapter) ClusterUpdate(client kubeclientset.Interface, obj pkgruntime.Object) (pkgruntime.Object, error) {
	daemonset := obj.(*extensionsv1.DaemonSet)
	return client.Extensions().DaemonSets(daemonset.Namespace).Update(daemonset)
}

func (a *DaemonSetAdapter) ClusterWatch(client kubeclientset.Interface, namespace string, options metav1.ListOptions) (watch.Interface, error) {
	return client.Extensions().DaemonSets(namespace).Watch(options)
}

func (a *DaemonSetAdapter) IsSchedulingAdapter() bool {
	return false
}

func (a *DaemonSetAdapter) NewTestObject(namespace string) pkgruntime.Object {
	return &extensionsv1.DaemonSet{
		ObjectMeta: metav1.ObjectMeta{
			GenerateName: "test-daemonset-",
			Namespace:    namespace,
			Labels:       map[string]string{"app": "test-daemonset"},
		},
		Spec: extensionsv1.DaemonSetSpec{
			Template: v1.PodTemplateSpec{
				ObjectMeta: metav1.ObjectMeta{
					Labels: map[string]string{"name": "test-pod"},
				},
				Spec: v1.PodSpec{
					Containers: []v1.Container{
						{
							Name:  "test-daemonset",
							Image: "images/test-daemonset",
							Ports: []v1.ContainerPort{{ContainerPort: 9376}},
						},
					},
				},
			},
		},
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2011 Google Inc.

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

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

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

// Package signhandler implements the HTTP interface to signing and verifying
// Camlistore JSON blobs.
package signhandler

import (
	"crypto"
	"fmt"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"

	"camlistore.org/pkg/blob"
	"camlistore.org/pkg/blobserver"
	"camlistore.org/pkg/blobserver/gethandler"
	"camlistore.org/pkg/httputil"
	"camlistore.org/pkg/jsonconfig"
	"camlistore.org/pkg/jsonsign"
	"camlistore.org/pkg/schema"

	"camlistore.org/third_party/code.google.com/p/go.crypto/openpgp"
)

const kMaxJSONLength = 1024 * 1024

type Handler struct {
	// Optional path to non-standard secret gpg keyring file
	secretRing string

	pubKeyBlobRef blob.Ref
	pubKeyFetcher blob.StreamingFetcher

	pubKeyBlobRefServeSuffix string // "camli/sha1-xxxx"
	pubKeyHandler            http.Handler

	// Where & if our public key is published
	pubKeyDest    blobserver.Storage
	pubKeyWritten bool

	entity *openpgp.Entity
	signer *schema.Signer
}

func (h *Handler) Signer() *schema.Signer { return h.signer }

func (h *Handler) secretRingPath() string {
	if h.secretRing != "" {
		return h.secretRing
	}
	return filepath.Join(os.Getenv("HOME"), ".gnupg", "secring.gpg")
}

func init() {
	blobserver.RegisterHandlerConstructor("jsonsign", newJSONSignFromConfig)
}

func newJSONSignFromConfig(ld blobserver.Loader, conf jsonconfig.Obj) (http.Handler, error) {
	pubKeyDestPrefix := conf.OptionalString("publicKeyDest", "")

	// either a short form ("26F5ABDA") or one the longer forms.
	keyId := conf.RequiredString("keyId")

	h := &Handler{
		secretRing: conf.OptionalString("secretRing", ""),
	}
	var err error
	if err = conf.Validate(); err != nil {
		return nil, err
	}

	h.entity, err = jsonsign.EntityFromSecring(keyId, h.secretRingPath())
	if err != nil {
		return nil, err
	}

	armoredPublicKey, err := jsonsign.ArmoredPublicKey(h.entity)

	ms := new(blob.MemoryStore)
	h.pubKeyBlobRef, err = ms.AddBlob(crypto.SHA1, armoredPublicKey)
	if err != nil {
		return nil, err
	}
	h.pubKeyFetcher = ms

	if pubKeyDestPrefix != "" {
		sto, err := ld.GetStorage(pubKeyDestPrefix)
		if err != nil {
			return nil, err
		}
		h.pubKeyDest = sto
		if sto != nil {
			err := h.uploadPublicKey(sto, armoredPublicKey)
			if err != nil {
				return nil, fmt.Errorf("Error seeding self public key in storage: %v", err)
			}
		}
	}
	h.pubKeyBlobRefServeSuffix = "camli/" + h.pubKeyBlobRef.String()
	h.pubKeyHandler = &gethandler.Handler{
		Fetcher: ms,
	}

	h.signer, err = schema.NewSigner(h.pubKeyBlobRef, strings.NewReader(armoredPublicKey), h.entity)
	if err != nil {
		return nil, err
	}

	return h, nil
}

func (h *Handler) uploadPublicKey(sto blobserver.Storage, key string) error {
	_, err := blobserver.StatBlob(sto, h.pubKeyBlobRef)
	if err == nil {
		return nil
	}
	_, err = blobserver.Receive(sto, h.pubKeyBlobRef, strings.NewReader(key))
	return err
}

func (h *Handler) DiscoveryMap(base string) map[string]interface{} {
	m := map[string]interface{}{
		"publicKeyId":   h.entity.PrimaryKey.KeyIdString(),
		"signHandler":   base + "camli/sig/sign",
		"verifyHandler": base + "camli/sig/verify",
	}
	if h.pubKeyBlobRef.Valid() {
		m["publicKeyBlobRef"] = h.pubKeyBlobRef.String()
		m["publicKey"] = base + h.pubKeyBlobRefServeSuffix
	}
	return m
}

func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	base := httputil.PathBase(req)
	subPath := httputil.PathSuffix(req)
	switch req.Method {
	case "GET", "HEAD":
		switch subPath {
		case "":
			http.Redirect(rw, req, base+"camli/sig/discovery", http.StatusFound)
			return
		case h.pubKeyBlobRefServeSuffix:
			h.pubKeyHandler.ServeHTTP(rw, req)
			return
		case "camli/sig/sign":
			fallthrough
		case "camli/sig/verify":
			http.Error(rw, "POST required", 400)
			return
		case "camli/sig/discovery":
			httputil.ReturnJSON(rw, h.DiscoveryMap(base))
			return
		}
	case "POST":
		switch subPath {
		case "camli/sig/sign":
			h.handleSign(rw, req)
			return
		case "camli/sig/verify":
			h.handleVerify(rw, req)
			return
		}
	}
	http.Error(rw, "Unsupported path or method.", http.StatusBadRequest)
}

func (h *Handler) handleVerify(rw http.ResponseWriter, req *http.Request) {
	req.ParseForm()
	sjson := req.FormValue("sjson")
	if sjson == "" {
		http.Error(rw, "missing \"sjson\" parameter", http.StatusBadRequest)
		return
	}

	m := make(map[string]interface{})

	// TODO: use a different fetcher here that checks memory, disk,
	// the internet, etc.
	fetcher := h.pubKeyFetcher

	vreq := jsonsign.NewVerificationRequest(sjson, fetcher)
	if vreq.Verify() {
		m["signatureValid"] = 1
		m["signerKeyId"] = vreq.SignerKeyId
		m["verifiedData"] = vreq.PayloadMap
	} else {
		errStr := vreq.Err.Error()
		m["signatureValid"] = 0
		m["errorMessage"] = errStr
	}

	rw.WriteHeader(http.StatusOK) // no HTTP response code fun, error info in JSON
	httputil.ReturnJSON(rw, m)
}

func (h *Handler) handleSign(rw http.ResponseWriter, req *http.Request) {
	req.ParseForm()

	badReq := func(s string) {
		http.Error(rw, s, http.StatusBadRequest)
		log.Printf("bad request: %s", s)
		return
	}
	// TODO: SECURITY: auth

	jsonStr := req.FormValue("json")
	if jsonStr == "" {
		badReq("missing \"json\" parameter")
		return
	}
	if len(jsonStr) > kMaxJSONLength {
		badReq("parameter \"json\" too large")
		return
	}

	sreq := &jsonsign.SignRequest{
		UnsignedJSON:      jsonStr,
		Fetcher:           h.pubKeyFetcher,
		ServerMode:        true,
		SecretKeyringPath: h.secretRing,
	}
	signedJSON, err := sreq.Sign()
	if err != nil {
		// TODO: some aren't really a "bad request"
		badReq(fmt.Sprintf("%v", err))
		return
	}
	rw.Write([]byte(signedJSON))
}

func (h *Handler) Sign(bb *schema.Builder) (string, error) {
	bb.SetSigner(h.pubKeyBlobRef)
	unsigned, err := bb.JSON()
	if err != nil {
		return "", err
	}
	sreq := &jsonsign.SignRequest{
		UnsignedJSON:      unsigned,
		Fetcher:           h.pubKeyFetcher,
		ServerMode:        true,
		SecretKeyringPath: h.secretRing,
	}
	claimTime, err := bb.Blob().ClaimDate()
	if err != nil {
		if !schema.IsMissingField(err) {
			return "", err
		}
	} else {
		sreq.SignatureTime = claimTime
	}
	return sreq.Sign()
}
<commit_msg>jsonsign: don't upload public key until the first thing is signed<commit_after>/*
Copyright 2011 Google Inc.

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

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

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

// Package signhandler implements the HTTP interface to signing and verifying
// Camlistore JSON blobs.
package signhandler

import (
	"crypto"
	"fmt"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"sync"

	"camlistore.org/pkg/blob"
	"camlistore.org/pkg/blobserver"
	"camlistore.org/pkg/blobserver/gethandler"
	"camlistore.org/pkg/httputil"
	"camlistore.org/pkg/jsonconfig"
	"camlistore.org/pkg/jsonsign"
	"camlistore.org/pkg/schema"

	"camlistore.org/third_party/code.google.com/p/go.crypto/openpgp"
)

const kMaxJSONLength = 1024 * 1024

type Handler struct {
	// Optional path to non-standard secret gpg keyring file
	secretRing string

	pubKey        string // armored
	pubKeyBlobRef blob.Ref
	pubKeyFetcher blob.StreamingFetcher

	pubKeyBlobRefServeSuffix string // "camli/sha1-xxxx"
	pubKeyHandler            http.Handler

	pubKeyDest blobserver.Storage // Where our public key is published

	pubKeyUploadMu sync.RWMutex
	pubKeyUploaded bool

	entity *openpgp.Entity
	signer *schema.Signer
}

func (h *Handler) Signer() *schema.Signer { return h.signer }

func (h *Handler) secretRingPath() string {
	if h.secretRing != "" {
		return h.secretRing
	}
	return filepath.Join(os.Getenv("HOME"), ".gnupg", "secring.gpg")
}

func init() {
	blobserver.RegisterHandlerConstructor("jsonsign", newJSONSignFromConfig)
}

func newJSONSignFromConfig(ld blobserver.Loader, conf jsonconfig.Obj) (http.Handler, error) {
	pubKeyDestPrefix := conf.OptionalString("publicKeyDest", "")

	// either a short form ("26F5ABDA") or one the longer forms.
	keyId := conf.RequiredString("keyId")

	h := &Handler{
		secretRing: conf.OptionalString("secretRing", ""),
	}
	var err error
	if err = conf.Validate(); err != nil {
		return nil, err
	}

	h.entity, err = jsonsign.EntityFromSecring(keyId, h.secretRingPath())
	if err != nil {
		return nil, err
	}

	h.pubKey, err = jsonsign.ArmoredPublicKey(h.entity)

	ms := new(blob.MemoryStore)
	h.pubKeyBlobRef, err = ms.AddBlob(crypto.SHA1, h.pubKey)
	if err != nil {
		return nil, err
	}
	h.pubKeyFetcher = ms

	if pubKeyDestPrefix != "" {
		sto, err := ld.GetStorage(pubKeyDestPrefix)
		if err != nil {
			return nil, err
		}
		h.pubKeyDest = sto
	}
	h.pubKeyBlobRefServeSuffix = "camli/" + h.pubKeyBlobRef.String()
	h.pubKeyHandler = &gethandler.Handler{
		Fetcher: ms,
	}

	h.signer, err = schema.NewSigner(h.pubKeyBlobRef, strings.NewReader(h.pubKey), h.entity)
	if err != nil {
		return nil, err
	}

	return h, nil
}

func (h *Handler) uploadPublicKey() error {
	h.pubKeyUploadMu.RLock()
	if h.pubKeyUploaded {
		h.pubKeyUploadMu.RUnlock()
		return nil
	}
	h.pubKeyUploadMu.RUnlock()

	sto := h.pubKeyDest

	h.pubKeyUploadMu.Lock()
	defer h.pubKeyUploadMu.Unlock()
	if h.pubKeyUploaded {
		return nil
	}
	_, err := blobserver.StatBlob(sto, h.pubKeyBlobRef)
	if err == nil {
		h.pubKeyUploaded = true
		return nil
	}
	_, err = blobserver.Receive(sto, h.pubKeyBlobRef, strings.NewReader(h.pubKey))
	log.Printf("uploadPublicKey(%T, %v) = %v", sto, h.pubKeyBlobRef, err)
	if err == nil {
		h.pubKeyUploaded = true
	}
	return err
}

func (h *Handler) DiscoveryMap(base string) map[string]interface{} {
	m := map[string]interface{}{
		"publicKeyId":   h.entity.PrimaryKey.KeyIdString(),
		"signHandler":   base + "camli/sig/sign",
		"verifyHandler": base + "camli/sig/verify",
	}
	if h.pubKeyBlobRef.Valid() {
		m["publicKeyBlobRef"] = h.pubKeyBlobRef.String()
		m["publicKey"] = base + h.pubKeyBlobRefServeSuffix
	}
	return m
}

func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	base := httputil.PathBase(req)
	subPath := httputil.PathSuffix(req)
	switch req.Method {
	case "GET", "HEAD":
		switch subPath {
		case "":
			http.Redirect(rw, req, base+"camli/sig/discovery", http.StatusFound)
			return
		case h.pubKeyBlobRefServeSuffix:
			h.pubKeyHandler.ServeHTTP(rw, req)
			return
		case "camli/sig/sign":
			fallthrough
		case "camli/sig/verify":
			http.Error(rw, "POST required", 400)
			return
		case "camli/sig/discovery":
			httputil.ReturnJSON(rw, h.DiscoveryMap(base))
			return
		}
	case "POST":
		switch subPath {
		case "camli/sig/sign":
			h.handleSign(rw, req)
			return
		case "camli/sig/verify":
			h.handleVerify(rw, req)
			return
		}
	}
	http.Error(rw, "Unsupported path or method.", http.StatusBadRequest)
}

func (h *Handler) handleVerify(rw http.ResponseWriter, req *http.Request) {
	req.ParseForm()
	sjson := req.FormValue("sjson")
	if sjson == "" {
		http.Error(rw, "missing \"sjson\" parameter", http.StatusBadRequest)
		return
	}

	m := make(map[string]interface{})

	// TODO: use a different fetcher here that checks memory, disk,
	// the internet, etc.
	fetcher := h.pubKeyFetcher

	vreq := jsonsign.NewVerificationRequest(sjson, fetcher)
	if vreq.Verify() {
		m["signatureValid"] = 1
		m["signerKeyId"] = vreq.SignerKeyId
		m["verifiedData"] = vreq.PayloadMap
	} else {
		errStr := vreq.Err.Error()
		m["signatureValid"] = 0
		m["errorMessage"] = errStr
	}

	rw.WriteHeader(http.StatusOK) // no HTTP response code fun, error info in JSON
	httputil.ReturnJSON(rw, m)
}

func (h *Handler) handleSign(rw http.ResponseWriter, req *http.Request) {
	req.ParseForm()

	badReq := func(s string) {
		http.Error(rw, s, http.StatusBadRequest)
		log.Printf("bad request: %s", s)
		return
	}

	jsonStr := req.FormValue("json")
	if jsonStr == "" {
		badReq("missing \"json\" parameter")
		return
	}
	if len(jsonStr) > kMaxJSONLength {
		badReq("parameter \"json\" too large")
		return
	}

	sreq := &jsonsign.SignRequest{
		UnsignedJSON:      jsonStr,
		Fetcher:           h.pubKeyFetcher,
		ServerMode:        true,
		SecretKeyringPath: h.secretRing,
	}
	signedJSON, err := sreq.Sign()
	if err != nil {
		// TODO: some aren't really a "bad request"
		badReq(fmt.Sprintf("%v", err))
		return
	}
	h.uploadPublicKey()
	rw.Write([]byte(signedJSON))
}

func (h *Handler) Sign(bb *schema.Builder) (string, error) {
	bb.SetSigner(h.pubKeyBlobRef)
	unsigned, err := bb.JSON()
	if err != nil {
		return "", err
	}
	sreq := &jsonsign.SignRequest{
		UnsignedJSON:      unsigned,
		Fetcher:           h.pubKeyFetcher,
		ServerMode:        true,
		SecretKeyringPath: h.secretRing,
	}
	claimTime, err := bb.Blob().ClaimDate()
	if err != nil {
		if !schema.IsMissingField(err) {
			return "", err
		}
	} else {
		sreq.SignatureTime = claimTime
	}
	h.uploadPublicKey()
	return sreq.Sign()
}
<|endoftext|>


<commit_before>package router

import (
	"io"
	"sync"
	"sync/atomic"
	"testing"
	"time"

	"github.com/alicebob/miniredis"
	"github.com/garyburd/redigo/redis"
	"github.com/juju/errors"
	log "github.com/ngaut/logging"
	"github.com/ngaut/zkhelper"
	"github.com/wandoulabs/codis/pkg/models"
)

var (
	conf       *Conf
	s          *Server
	once       sync.Once
	waitonce   sync.Once
	conn       zkhelper.Conn
	redis1     *miniredis.Miniredis
	redis2     *miniredis.Miniredis
	proxyMutex sync.Mutex
)

func InitEnv() {
	go once.Do(func() {
		conn = zkhelper.NewConn()
		conf = &Conf{
			proxyId:     "proxy_test",
			productName: "test",
			zkAddr:      "localhost:2181",
			f:           func(string) (zkhelper.Conn, error) { return conn, nil },
		}

		//init action path
		prefix := models.GetWatchActionPath(conf.productName)
		err := models.CreateActionRootPath(conn, prefix)
		if err != nil {
			log.Fatal(err)
		}

		//init slot
		err = models.InitSlotSet(conn, conf.productName, 1024)
		if err != nil {
			log.Fatal(err)
		}

		err = models.SetSlotRange(conn, conf.productName, 0, 1023, 1, models.SLOT_STATUS_ONLINE)
		if err != nil {
			log.Fatal(err)
		}

		//init  server group
		g := models.NewServerGroup(conf.productName, 1)
		g.Create(conn)

		redis1, _ := miniredis.Run()
		redis2, _ := miniredis.Run()

		s1 := models.NewServer(models.SERVER_TYPE_MASTER, redis1.Addr())
		s2 := models.NewServer(models.SERVER_TYPE_MASTER, redis2.Addr())

		g.AddServer(conn, s1)
		g.AddServer(conn, s2)
		go func() { //set proxy online
			time.Sleep(5 * time.Second)
			err := models.SetProxyStatus(conn, conf.productName, conf.proxyId, models.PROXY_STATE_ONLINE)
			if err != nil {
				log.Fatal(errors.ErrorStack(err))
			}
			time.Sleep(2 * time.Second)
			proxyMutex.Lock()
			defer proxyMutex.Unlock()
			pi := s.getProxyInfo()
			if pi.State != models.PROXY_STATE_ONLINE {
				log.Fatalf("should be online, we got %s", pi.State)
			}
		}()

		proxyMutex.Lock()
		s = NewServer(":19000", ":11000",
			conf,
		)
		proxyMutex.Unlock()
		s.Run()
	})

	waitonce.Do(func() {
		time.Sleep(10 * time.Second)
	})
}

func TestSingleKeyRedisCmd(t *testing.T) {
	InitEnv()
	c, err := redis.Dial("tcp", "localhost:19000")
	if err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	_, err = c.Do("SET", "foo", "bar")
	if err != nil {
		t.Error(err)
	}

	if got, err := redis.String(c.Do("get", "foo")); err != nil || got != "bar" {
		t.Error("'foo' has the wrong value")
	}

	_, err = c.Do("SET", "bar", "foo")
	if err != nil {
		t.Error(err)
	}

	if got, err := redis.String(c.Do("get", "bar")); err != nil || got != "foo" {
		t.Error("'bar' has the wrong value")
	}
}

func TestMultiKeyRedisCmd(t *testing.T) {
	InitEnv()
	c, err := redis.Dial("tcp", "localhost:19000")
	if err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	_, err = c.Do("SET", "key1", "value1")
	if err != nil {
		t.Fatal(err)
	}
	_, err = c.Do("SET", "key2", "value2")
	if err != nil {
		t.Fatal(err)
	}

	var value1 string
	var value2 string
	var value3 string
	reply, err := redis.Values(c.Do("MGET", "key1", "key2", "key3"))
	if err != nil {
		t.Fatal(err)
	}

	if _, err := redis.Scan(reply, &value1, &value2, &value3); err != nil {
		t.Fatal(err)
	}

	if value1 != "value1" || value2 != "value2" || len(value3) != 0 {
		t.Error("value not match")
	}

	//test del
	if _, err := c.Do("del", "key1", "key2", "key3"); err != nil {
		t.Fatal(err)
	}

	//reset
	value1 = ""
	value2 = ""
	value3 = ""
	reply, err = redis.Values(c.Do("MGET", "key1", "key2", "key3"))
	if err != nil {
		t.Fatal(err)
	}

	if _, err := redis.Scan(reply, &value1, &value2, &value3); err != nil {
		t.Fatal(err)
	}

	if len(value1) != 0 || len(value2) != 0 || len(value3) != 0 {
		t.Error("value not match", value1, value2, value3)
	}
}

func TestInvalidRedisCmdUnknown(t *testing.T) {
	InitEnv()
	c, err := redis.Dial("tcp", "localhost:19000")
	if err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	if _, err := c.Do("unknown", "key1", "key2", "key3"); err == nil {
		t.Fatal(err)
	}
}

func TestInvalidRedisCmdPing(t *testing.T) {
	InitEnv()
	c, err := redis.Dial("tcp", "localhost:19000")
	if err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	_, err = c.Do("info")
	if err != io.EOF {
		t.Fatal(err)
	}
}

func TestInvalidRedisCmdQuit(t *testing.T) {
	InitEnv()
	c, err := redis.Dial("tcp", "localhost:19000")
	if err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	_, err = c.Do("quit")
	if err != nil {
		t.Fatal(err)
	}
}

func TestInvalidRedisCmdEcho(t *testing.T) {
	InitEnv()
	c, err := redis.Dial("tcp", "localhost:19000")
	if err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	_, err = c.Do("echo", "xx")
	if err != nil {
		t.Fatal(err)
	}

	_, err = c.Do("echo")
	if err == nil {
		t.Fatal("should be error")
	}

}

//this should be the last test
func TestMarkOffline(t *testing.T) {
	InitEnv()

	suicide := int64(0)
	proxyMutex.Lock()
	s.OnSuicide = func() error {
		atomic.StoreInt64(&suicide, 1)
		return nil
	}
	proxyMutex.Unlock()

	err := models.SetProxyStatus(conn, conf.productName, conf.proxyId, models.PROXY_STATE_MARK_OFFLINE)
	if err != nil {
		t.Fatal(errors.ErrorStack(err))
	}

	time.Sleep(3 * time.Second)

	if atomic.LoadInt64(&suicide) == 0 {
		t.Error("shoud be suicided")
	}
}
<commit_msg>sharding test<commit_after>package router

import (
	"io"
	"sync"
	"sync/atomic"
	"testing"
	"time"

	"github.com/alicebob/miniredis"
	"github.com/garyburd/redigo/redis"
	"github.com/juju/errors"
	log "github.com/ngaut/logging"
	"github.com/ngaut/zkhelper"
	"github.com/wandoulabs/codis/pkg/models"
)

var (
	conf       *Conf
	s          *Server
	once       sync.Once
	waitonce   sync.Once
	conn       zkhelper.Conn
	redis1     *miniredis.Miniredis
	redis2     *miniredis.Miniredis
	proxyMutex sync.Mutex
)

func InitEnv() {
	go once.Do(func() {
		conn = zkhelper.NewConn()
		conf = &Conf{
			proxyId:     "proxy_test",
			productName: "test",
			zkAddr:      "localhost:2181",
			f:           func(string) (zkhelper.Conn, error) { return conn, nil },
		}

		//init action path
		prefix := models.GetWatchActionPath(conf.productName)
		err := models.CreateActionRootPath(conn, prefix)
		if err != nil {
			log.Fatal(err)
		}

		//init slot
		err = models.InitSlotSet(conn, conf.productName, 1024)
		if err != nil {
			log.Fatal(err)
		}

		//init  server group
		g1 := models.NewServerGroup(conf.productName, 1)
		g1.Create(conn)
		g2 := models.NewServerGroup(conf.productName, 2)
		g2.Create(conn)

		redis1, _ := miniredis.Run()
		redis2, _ := miniredis.Run()

		s1 := models.NewServer(models.SERVER_TYPE_MASTER, redis1.Addr())
		s2 := models.NewServer(models.SERVER_TYPE_MASTER, redis2.Addr())

		g1.AddServer(conn, s1)
		g2.AddServer(conn, s2)

		//set slot range
		err = models.SetSlotRange(conn, conf.productName, 0, 511, 1, models.SLOT_STATUS_ONLINE)
		if err != nil {
			log.Fatal(err)
		}

		err = models.SetSlotRange(conn, conf.productName, 512, 1023, 2, models.SLOT_STATUS_ONLINE)
		if err != nil {
			log.Fatal(err)
		}

		go func() { //set proxy online
			time.Sleep(5 * time.Second)
			err := models.SetProxyStatus(conn, conf.productName, conf.proxyId, models.PROXY_STATE_ONLINE)
			if err != nil {
				log.Fatal(errors.ErrorStack(err))
			}
			time.Sleep(2 * time.Second)
			proxyMutex.Lock()
			defer proxyMutex.Unlock()
			pi := s.getProxyInfo()
			if pi.State != models.PROXY_STATE_ONLINE {
				log.Fatalf("should be online, we got %s", pi.State)
			}
		}()

		proxyMutex.Lock()
		s = NewServer(":19000", ":11000",
			conf,
		)
		proxyMutex.Unlock()
		s.Run()
	})

	waitonce.Do(func() {
		time.Sleep(10 * time.Second)
	})
}

func TestSingleKeyRedisCmd(t *testing.T) {
	InitEnv()
	c, err := redis.Dial("tcp", "localhost:19000")
	if err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	_, err = c.Do("SET", "foo", "bar")
	if err != nil {
		t.Error(err)
	}

	if got, err := redis.String(c.Do("get", "foo")); err != nil || got != "bar" {
		t.Error("'foo' has the wrong value")
	}

	_, err = c.Do("SET", "bar", "foo")
	if err != nil {
		t.Error(err)
	}

	if got, err := redis.String(c.Do("get", "bar")); err != nil || got != "foo" {
		t.Error("'bar' has the wrong value")
	}
}

func TestMultiKeyRedisCmd(t *testing.T) {
	InitEnv()
	c, err := redis.Dial("tcp", "localhost:19000")
	if err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	_, err = c.Do("SET", "key1", "value1")
	if err != nil {
		t.Fatal(err)
	}
	_, err = c.Do("SET", "key2", "value2")
	if err != nil {
		t.Fatal(err)
	}

	var value1 string
	var value2 string
	var value3 string
	reply, err := redis.Values(c.Do("MGET", "key1", "key2", "key3"))
	if err != nil {
		t.Fatal(err)
	}

	if _, err := redis.Scan(reply, &value1, &value2, &value3); err != nil {
		t.Fatal(err)
	}

	if value1 != "value1" || value2 != "value2" || len(value3) != 0 {
		t.Error("value not match")
	}

	//test del
	if _, err := c.Do("del", "key1", "key2", "key3"); err != nil {
		t.Fatal(err)
	}

	//reset
	value1 = ""
	value2 = ""
	value3 = ""
	reply, err = redis.Values(c.Do("MGET", "key1", "key2", "key3"))
	if err != nil {
		t.Fatal(err)
	}

	if _, err := redis.Scan(reply, &value1, &value2, &value3); err != nil {
		t.Fatal(err)
	}

	if len(value1) != 0 || len(value2) != 0 || len(value3) != 0 {
		t.Error("value not match", value1, value2, value3)
	}
}

func TestInvalidRedisCmdUnknown(t *testing.T) {
	InitEnv()
	c, err := redis.Dial("tcp", "localhost:19000")
	if err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	if _, err := c.Do("unknown", "key1", "key2", "key3"); err == nil {
		t.Fatal(err)
	}
}

func TestInvalidRedisCmdPing(t *testing.T) {
	InitEnv()
	c, err := redis.Dial("tcp", "localhost:19000")
	if err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	_, err = c.Do("info")
	if err != io.EOF {
		t.Fatal(err)
	}
}

func TestInvalidRedisCmdQuit(t *testing.T) {
	InitEnv()
	c, err := redis.Dial("tcp", "localhost:19000")
	if err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	_, err = c.Do("quit")
	if err != nil {
		t.Fatal(err)
	}
}

func TestInvalidRedisCmdEcho(t *testing.T) {
	InitEnv()
	c, err := redis.Dial("tcp", "localhost:19000")
	if err != nil {
		t.Fatal(err)
	}
	defer c.Close()

	_, err = c.Do("echo", "xx")
	if err != nil {
		t.Fatal(err)
	}

	_, err = c.Do("echo")
	if err == nil {
		t.Fatal("should be error")
	}

}

//this should be the last test
func TestMarkOffline(t *testing.T) {
	InitEnv()

	suicide := int64(0)
	proxyMutex.Lock()
	s.OnSuicide = func() error {
		atomic.StoreInt64(&suicide, 1)
		return nil
	}
	proxyMutex.Unlock()

	err := models.SetProxyStatus(conn, conf.productName, conf.proxyId, models.PROXY_STATE_MARK_OFFLINE)
	if err != nil {
		t.Fatal(errors.ErrorStack(err))
	}

	time.Sleep(3 * time.Second)

	if atomic.LoadInt64(&suicide) == 0 {
		t.Error("shoud be suicided")
	}
}
<|endoftext|>


<commit_before>package cleanup

import (
	"context"
	"io/ioutil"
	"os"
	"path"
	"time"

	"github.com/grafana/grafana/pkg/bus"
	"github.com/grafana/grafana/pkg/log"
	m "github.com/grafana/grafana/pkg/models"
	"github.com/grafana/grafana/pkg/registry"
	"github.com/grafana/grafana/pkg/setting"
)

type CleanUpService struct {
	log log.Logger
	Cfg *setting.Cfg `inject:""`
}

func init() {
	registry.RegisterService(&CleanUpService{})
}

func (srv *CleanUpService) Init() error {
	srv.log = log.New("cleanup")
	return nil
}

func (srv *CleanUpService) Run(ctx context.Context) error {
	srv.cleanUpTmpFiles()

	ticker := time.NewTicker(time.Minute * 10)
	for {
		select {
		case <-ticker.C:
			srv.cleanUpTmpFiles()
			srv.deleteExpiredSnapshots()
			srv.deleteExpiredDashboardVersions()
			srv.deleteOldLoginAttempts()
		case <-ctx.Done():
			return ctx.Err()
		}
	}
}

func (srv *CleanUpService) cleanUpTmpFiles() {
	if _, err := os.Stat(srv.Cfg.ImagesDir); os.IsNotExist(err) {
		return
	}

	files, err := ioutil.ReadDir(srv.Cfg.ImagesDir)
	if err != nil {
		srv.log.Error("Problem reading image dir", "error", err)
		return
	}

	var toDelete []os.FileInfo
	var now = time.Now()

	for _, file := range files {
		if srv.shouldCleanupTempFile(file.ModTime(), now) {
			toDelete = append(toDelete, file)
		}
	}

	for _, file := range toDelete {
		fullPath := path.Join(srv.Cfg.ImagesDir, file.Name())
		err := os.Remove(fullPath)
		if err != nil {
			srv.log.Error("Failed to delete temp file", "file", file.Name(), "error", err)
		}
	}

	srv.log.Debug("Found old rendered image to delete", "deleted", len(toDelete), "keept", len(files))
}

func (srv *CleanUpService) shouldCleanupTempFile(filemtime time.Time, now time.Time) bool {
	if srv.Cfg.TempDataLifetime == 0 {
		return false
	}

	return filemtime.Add(srv.Cfg.TempDataLifetime).Before(now)
}

func (srv *CleanUpService) deleteExpiredSnapshots() {
	cmd := m.DeleteExpiredSnapshotsCommand{}
	if err := bus.Dispatch(&cmd); err != nil {
		srv.log.Error("Failed to delete expired snapshots", "error", err.Error())
	} else {
		srv.log.Debug("Deleted expired snapshots", "rows affected", cmd.DeletedRows)
	}
}

func (srv *CleanUpService) deleteExpiredDashboardVersions() {
	cmd := m.DeleteExpiredVersionsCommand{}
	if err := bus.Dispatch(&cmd); err != nil {
		srv.log.Error("Failed to delete expired dashboard versions", "error", err.Error())
	} else {
		srv.log.Debug("Deleted old/expired dashboard versions", "rows affected", cmd.DeletedRows)
	}
}

func (srv *CleanUpService) deleteOldLoginAttempts() {
	if srv.Cfg.DisableBruteForceLoginProtection {
		return
	}

	cmd := m.DeleteOldLoginAttemptsCommand{
		OlderThan: time.Now().Add(time.Minute * -10),
	}
	if err := bus.Dispatch(&cmd); err != nil {
		srv.log.Error("Problem deleting expired login attempts", "error", err.Error())
	} else {
		srv.log.Debug("Deleted expired login attempts", "rows affected", cmd.DeletedRows)
	}
}
<commit_msg>Fix grammar in log message<commit_after>package cleanup

import (
	"context"
	"io/ioutil"
	"os"
	"path"
	"time"

	"github.com/grafana/grafana/pkg/bus"
	"github.com/grafana/grafana/pkg/log"
	m "github.com/grafana/grafana/pkg/models"
	"github.com/grafana/grafana/pkg/registry"
	"github.com/grafana/grafana/pkg/setting"
)

type CleanUpService struct {
	log log.Logger
	Cfg *setting.Cfg `inject:""`
}

func init() {
	registry.RegisterService(&CleanUpService{})
}

func (srv *CleanUpService) Init() error {
	srv.log = log.New("cleanup")
	return nil
}

func (srv *CleanUpService) Run(ctx context.Context) error {
	srv.cleanUpTmpFiles()

	ticker := time.NewTicker(time.Minute * 10)
	for {
		select {
		case <-ticker.C:
			srv.cleanUpTmpFiles()
			srv.deleteExpiredSnapshots()
			srv.deleteExpiredDashboardVersions()
			srv.deleteOldLoginAttempts()
		case <-ctx.Done():
			return ctx.Err()
		}
	}
}

func (srv *CleanUpService) cleanUpTmpFiles() {
	if _, err := os.Stat(srv.Cfg.ImagesDir); os.IsNotExist(err) {
		return
	}

	files, err := ioutil.ReadDir(srv.Cfg.ImagesDir)
	if err != nil {
		srv.log.Error("Problem reading image dir", "error", err)
		return
	}

	var toDelete []os.FileInfo
	var now = time.Now()

	for _, file := range files {
		if srv.shouldCleanupTempFile(file.ModTime(), now) {
			toDelete = append(toDelete, file)
		}
	}

	for _, file := range toDelete {
		fullPath := path.Join(srv.Cfg.ImagesDir, file.Name())
		err := os.Remove(fullPath)
		if err != nil {
			srv.log.Error("Failed to delete temp file", "file", file.Name(), "error", err)
		}
	}

	srv.log.Debug("Found old rendered image to delete", "deleted", len(toDelete), "kept", len(files))
}

func (srv *CleanUpService) shouldCleanupTempFile(filemtime time.Time, now time.Time) bool {
	if srv.Cfg.TempDataLifetime == 0 {
		return false
	}

	return filemtime.Add(srv.Cfg.TempDataLifetime).Before(now)
}

func (srv *CleanUpService) deleteExpiredSnapshots() {
	cmd := m.DeleteExpiredSnapshotsCommand{}
	if err := bus.Dispatch(&cmd); err != nil {
		srv.log.Error("Failed to delete expired snapshots", "error", err.Error())
	} else {
		srv.log.Debug("Deleted expired snapshots", "rows affected", cmd.DeletedRows)
	}
}

func (srv *CleanUpService) deleteExpiredDashboardVersions() {
	cmd := m.DeleteExpiredVersionsCommand{}
	if err := bus.Dispatch(&cmd); err != nil {
		srv.log.Error("Failed to delete expired dashboard versions", "error", err.Error())
	} else {
		srv.log.Debug("Deleted old/expired dashboard versions", "rows affected", cmd.DeletedRows)
	}
}

func (srv *CleanUpService) deleteOldLoginAttempts() {
	if srv.Cfg.DisableBruteForceLoginProtection {
		return
	}

	cmd := m.DeleteOldLoginAttemptsCommand{
		OlderThan: time.Now().Add(time.Minute * -10),
	}
	if err := bus.Dispatch(&cmd); err != nil {
		srv.log.Error("Problem deleting expired login attempts", "error", err.Error())
	} else {
		srv.log.Debug("Deleted expired login attempts", "rows affected", cmd.DeletedRows)
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 CNI 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 hwaddr_test

import (
	"net"

	"github.com/containernetworking/cni/pkg/utils/hwaddr"

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

var _ = Describe("Hwaddr", func() {
	Context("Generate Hardware Address", func() {
		It("generate hardware address based on ipv4 address", func() {
			testCases := []struct {
				ip          net.IP
				expectedMAC net.HardwareAddr
			}{
				{
					ip:          net.ParseIP("10.0.0.2"),
					expectedMAC: (net.HardwareAddr)(append(hwaddr.PrivateMACPrefix, 0x0a, 0x00, 0x00, 0x02)),
				},
				{
					ip:          net.ParseIP("10.250.0.244"),
					expectedMAC: (net.HardwareAddr)(append(hwaddr.PrivateMACPrefix, 0x0a, 0xfa, 0x00, 0xf4)),
				},
				{
					ip:          net.ParseIP("172.17.0.2"),
					expectedMAC: (net.HardwareAddr)(append(hwaddr.PrivateMACPrefix, 0xac, 0x11, 0x00, 0x02)),
				},
			}

			for _, tc := range testCases {
				mac, err := hwaddr.GenerateHardwareAddr4(tc.ip, hwaddr.PrivateMACPrefix)
				Expect(err).NotTo(HaveOccurred())
				Expect(mac).To(Equal(tc.expectedMAC))
			}
		})

		It("return error if input is not ipv4 address", func() {
			testCases := []net.IP{
				net.ParseIP(""),
				net.ParseIP("2001:db8:0:1:1:1:1:1"),
			}
			for _, tc := range testCases {
				_, err := hwaddr.GenerateHardwareAddr4(tc, hwaddr.PrivateMACPrefix)
				Expect(err).To(BeAssignableToTypeOf(hwaddr.SupportIp4OnlyErr{}))
			}
		})

		It("return error if prefix is invalid", func() {
			_, err := hwaddr.GenerateHardwareAddr4(net.ParseIP("10.0.0.2"), []byte{0x58})
			Expect(err).To(BeAssignableToTypeOf(hwaddr.InvalidPrefixLengthErr{}))
		})
	})
})
<commit_msg>pkg/utils/hwaddr tests: cover v4 in v6 addr<commit_after>// Copyright 2016 CNI 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 hwaddr_test

import (
	"net"

	"github.com/containernetworking/cni/pkg/utils/hwaddr"

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

var _ = Describe("Hwaddr", func() {
	Context("Generate Hardware Address", func() {
		It("generate hardware address based on ipv4 address", func() {
			testCases := []struct {
				ip          net.IP
				expectedMAC net.HardwareAddr
			}{
				{
					ip:          net.ParseIP("10.0.0.2"),
					expectedMAC: (net.HardwareAddr)(append(hwaddr.PrivateMACPrefix, 0x0a, 0x00, 0x00, 0x02)),
				},
				{
					ip:          net.ParseIP("10.250.0.244"),
					expectedMAC: (net.HardwareAddr)(append(hwaddr.PrivateMACPrefix, 0x0a, 0xfa, 0x00, 0xf4)),
				},
				{
					ip:          net.ParseIP("172.17.0.2"),
					expectedMAC: (net.HardwareAddr)(append(hwaddr.PrivateMACPrefix, 0xac, 0x11, 0x00, 0x02)),
				},
				{
					ip:          net.IPv4(byte(172), byte(17), byte(0), byte(2)),
					expectedMAC: (net.HardwareAddr)(append(hwaddr.PrivateMACPrefix, 0xac, 0x11, 0x00, 0x02)),
				},
			}

			for _, tc := range testCases {
				mac, err := hwaddr.GenerateHardwareAddr4(tc.ip, hwaddr.PrivateMACPrefix)
				Expect(err).NotTo(HaveOccurred())
				Expect(mac).To(Equal(tc.expectedMAC))
			}
		})

		It("return error if input is not ipv4 address", func() {
			testCases := []net.IP{
				net.ParseIP(""),
				net.ParseIP("2001:db8:0:1:1:1:1:1"),
			}
			for _, tc := range testCases {
				_, err := hwaddr.GenerateHardwareAddr4(tc, hwaddr.PrivateMACPrefix)
				Expect(err).To(BeAssignableToTypeOf(hwaddr.SupportIp4OnlyErr{}))
			}
		})

		It("return error if prefix is invalid", func() {
			_, err := hwaddr.GenerateHardwareAddr4(net.ParseIP("10.0.0.2"), []byte{0x58})
			Expect(err).To(BeAssignableToTypeOf(hwaddr.InvalidPrefixLengthErr{}))
		})
	})
})
<|endoftext|>


<commit_before>package clever

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/http/httputil"
	"net/url"
)

const debug = false

// API supports basic auth with an API key or bearer auth with a token
type Auth struct {
	APIKey, Token string
}

type Clever struct {
	Auth
	Url string
}

// Creates a new clever object to make requests with. URL must be a valid base url, e.g. "https://api.clever.com"
func New(auth Auth, url string) *Clever {
	return &Clever{auth, url}
}

type CleverError struct {
	Code    string
	Message string `json:"error"`
}

func (err *CleverError) Error() string {
	if err.Code == "" {
		return err.Message
	}
	return fmt.Sprintf("%s (%s)", err.Error, err.Code)
}

type Paging struct {
	Count   int
	Current int
	Total   int
}

type Link struct {
	Rel string
	Uri string
}

type DistrictsResp struct {
	Districts []DistrictResp `json:"data"`
	Links     []Link
	Paging
}

type DistrictResp struct {
	District District `json:"data"`
	Links    []Link
	Uri      string
}

type District struct {
	Id   string
	Name string
}

type SchoolsResp struct {
	Links []Link
	Paging
	Schools []SchoolResp `json:"data"`
}

type SchoolResp struct {
	Links  []Link
	School School `json:"data"`
	Uri    string
}

type School struct {
	Created      string
	District     string
	HighGrade    string `json:"high_grade"`
	Id           string
	LastModified string `json:"last_modified"`
	Location     Location
	LowGrade     string `json:"low_grade"`
	Name         string
	NcesId       string `json:"nces_id"`
	Phone        string
	SchoolNumber string `json:"school_number"`
	SisId        string `json:"sis_id"`
	StateId      string `json:"state_id"`
}

type TeachersResp struct {
	Links []Link
	Paging
	Teachers []TeacherResp `json:"data"`
}

type TeacherResp struct {
	Links   []Link
	Teacher Teacher `json:"data"`
	Uri     string
}

type Teacher struct {
	Created       string
	District      string
	Email         string
	Id            string
	LastModified  string `json:"last_modified"`
	Name          Name
	School        string
	SisId         string `json:"sis_id"`
	TeacherNumber string `json:"teacher_number"`
	Title         string
}

type StudentsResp struct {
	Links []Link
	Paging
	Students []StudentResp `json:"data"`
}

type StudentResp struct {
	Links   []Link
	Student Student `json:"data"`
	Uri     string
}

type Student struct {
	Created           string
	District          string
	Dob               string
	Email             string
	FrlStatus         string `json:"frl_status"`
	Gender            string
	Grade             string
	HispanicEthnicity string `json:"hispanic_ethnicity"`
	Id                string
	LastModified      string `json:"last_modified"`
	Location          Location
	Name              Name
	Race              string
	School            string
	SisId             string `json:"sis_id"`
	StateId           string `json:"state_id"`
	StudentNumber     string `json:"student_number"`
}

type SectionsResp struct {
	Links []Link
	Paging
	Sections []SectionResp `json:"data"`
}

type SectionResp struct {
	Links   []Link
	Section Section `json:"data"`
	Uri     string
}

type Section struct {
	CourseName   string `json:"course_name"`
	CourseNumber string `json:"course_number"`
	Created      string
	District     string
	Grade        string
	Id           string `json:"id"`
	LastModified string `json:"last_modified"`
	Name         string
	School       string
	SisId        string `json:"sis_id"`
	Students     []string
	Subject      string
	Teacher      string
	Term
}

type Location struct {
	Address string
	City    string
	State   string
	Zip     string
}

type Name struct {
	First  string
	Middle string
	Last   string
}

type Term struct {
	Name      string
	StartDate string `json:"start_date"`
	EndDate   string `json:"end_date"`
}

func (clever *Clever) Query(path string, params map[string]string, resp interface{}) error {
	v := url.Values{}
	for key, val := range params {
		v.Set(key, val)
	}
	url := fmt.Sprintf("%s%s?%s", clever.Url, path, v.Encode())
	client := &http.Client{}
	req, _ := http.NewRequest("GET", url, nil)
	if clever.Auth.Token != "" {
		req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", clever.Auth.Token))
	} else if clever.Auth.APIKey != "" {
		req.Header.Set("Authorization", fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString([]byte(clever.Auth.APIKey+":"))))
	} else {
		return fmt.Errorf("Must provide either API key or bearer token")
	}
	if debug {
		log.Printf("get { %v } -> {\n", url)
	}
	r, err := client.Do(req)
	if err != nil {
		return err
	}
	defer r.Body.Close()
	if debug {
		dump, _ := httputil.DumpResponse(r, true)
		log.Printf("response:\n")
		log.Printf("%v\n}\n", string(dump))
	}
	if r.StatusCode != 200 {
		var error CleverError
		json.NewDecoder(r.Body).Decode(&error)
		return &error
	}
	err = json.NewDecoder(r.Body).Decode(resp)
	return err
}
<commit_msg>Added support for scanning multi-page results.<commit_after>package clever

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/http/httputil"
	"net/url"
)

const debug = false

// API supports basic auth with an API key or bearer auth with a token
type Auth struct {
	APIKey, Token string
}

type Clever struct {
	Auth
	Url string
}

// Creates a new clever object to make requests with. URL must be a valid base url, e.g. "https://api.clever.com"
func New(auth Auth, url string) *Clever {
	return &Clever{auth, url}
}

type CleverError struct {
	Code    string
	Message string `json:"error"`
}

func (err *CleverError) Error() string {
	if err.Code == "" {
		return err.Message
	}
	return fmt.Sprintf("%s (%s)", err.Error, err.Code)
}

type Paging struct {
	Count   int
	Current int
	Total   int
}

type Link struct {
	Rel string
	Uri string
}

type DistrictsResp struct {
	Districts []DistrictResp `json:"data"`
	Links     []Link
	Paging    Paging
}

type DistrictResp struct {
	District District `json:"data"`
	Links    []Link
	Uri      string
}

type District struct {
	Id   string
	Name string
}

type SchoolsResp struct {
	Links   []Link
	Paging  Paging
	Schools []SchoolResp `json:"data"`
}

type SchoolResp struct {
	Links  []Link
	School School `json:"data"`
	Uri    string
}

type School struct {
	Created      string
	District     string
	HighGrade    string `json:"high_grade"`
	Id           string
	LastModified string `json:"last_modified"`
	Location     Location
	LowGrade     string `json:"low_grade"`
	Name         string
	NcesId       string `json:"nces_id"`
	Phone        string
	SchoolNumber string `json:"school_number"`
	SisId        string `json:"sis_id"`
	StateId      string `json:"state_id"`
}

type TeachersResp struct {
	Links    []Link
	Paging   Paging
	Teachers []TeacherResp `json:"data"`
}

type TeacherResp struct {
	Links   []Link
	Teacher Teacher `json:"data"`
	Uri     string
}

type Teacher struct {
	Created       string
	District      string
	Email         string
	Id            string
	LastModified  string `json:"last_modified"`
	Name          Name
	School        string
	SisId         string `json:"sis_id"`
	TeacherNumber string `json:"teacher_number"`
	Title         string
}

type StudentsResp struct {
	Links    []Link
	Paging   Paging
	Students []StudentResp `json:"data"`
}

type StudentResp struct {
	Links   []Link
	Student Student `json:"data"`
	Uri     string
}

type Student struct {
	Created           string
	District          string
	Dob               string
	Email             string
	FrlStatus         string `json:"frl_status"`
	Gender            string
	Grade             string
	HispanicEthnicity string `json:"hispanic_ethnicity"`
	Id                string
	LastModified      string `json:"last_modified"`
	Location          Location
	Name              Name
	Race              string
	School            string
	SisId             string `json:"sis_id"`
	StateId           string `json:"state_id"`
	StudentNumber     string `json:"student_number"`
}

type SectionsResp struct {
	Links    []Link
	Paging   Paging
	Sections []SectionResp `json:"data"`
}

type SectionResp struct {
	Links   []Link
	Section Section `json:"data"`
	Uri     string
}

type Section struct {
	CourseName   string `json:"course_name"`
	CourseNumber string `json:"course_number"`
	Created      string
	District     string
	Grade        string
	Id           string `json:"id"`
	LastModified string `json:"last_modified"`
	Name         string
	School       string
	SisId        string `json:"sis_id"`
	Students     []string
	Subject      string
	Teacher      string
	Term
}

type Location struct {
	Address string
	City    string
	State   string
	Zip     string
}

type Name struct {
	First  string
	Middle string
	Last   string
}

type Term struct {
	Name      string
	StartDate string `json:"start_date"`
	EndDate   string `json:"end_date"`
}

func (clever *Clever) Query(path string, params map[string]string, resp interface{}) error {
	uri := fmt.Sprintf("%s%s", clever.Url, path)
	if params != nil {
		v := url.Values{}
		for key, val := range params {
			v.Set(key, val)
		}
		uri = fmt.Sprintf("%s%s?%s", clever.Url, path, v.Encode())
	}
	client := &http.Client{}
	req, _ := http.NewRequest("GET", uri, nil)
	if clever.Auth.Token != "" {
		req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", clever.Auth.Token))
	} else if clever.Auth.APIKey != "" {
		req.Header.Set("Authorization", fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString([]byte(clever.Auth.APIKey+":"))))
	} else {
		return fmt.Errorf("Must provide either API key or bearer token")
	}
	if debug {
		log.Printf("get { %v } -> {\n", uri)
	}
	r, err := client.Do(req)
	if err != nil {
		return err
	}
	defer r.Body.Close()
	if debug {
		dump, _ := httputil.DumpResponse(r, true)
		log.Printf("response:\n")
		log.Printf("%v\n}\n", string(dump))
	}
	if r.StatusCode != 200 {
		var error CleverError
		json.NewDecoder(r.Body).Decode(&error)
		return &error
	}
	err = json.NewDecoder(r.Body).Decode(resp)
	return err
}

type PagedResult struct {
	clever         Clever
	nextPagePath   string
	lastData       []map[string]interface{}
	lastDataCursor int
	lastError      error
}

func (clever *Clever) QueryAll(path string, params map[string]string) PagedResult {
	paramString := ""
	if params != nil {
		v := url.Values{}
		for key, val := range params {
			v.Set(key, val)
		}
		paramString = "?" + v.Encode()
	}

	return PagedResult{clever: *clever, nextPagePath: path + paramString, lastDataCursor: -1}
}

func (r *PagedResult) Next() bool {
	if r.lastDataCursor != -1 && r.lastDataCursor < len(r.lastData)-1 {
		r.lastDataCursor++
		return true
	}

	if r.nextPagePath == "" {
		return false
	}

	resp := &struct {
		Data   []map[string]interface{}
		Links  []Link
		Paging Paging
	}{}
	r.lastError = r.clever.Query(r.nextPagePath, nil, resp)
	if r.lastError != nil {
		return false
	}
	r.lastData = resp.Data
	r.lastDataCursor = 0
	r.nextPagePath = ""
	for _, link := range resp.Links {
		if link.Rel == "next" {
			r.nextPagePath = link.Uri
			break
		}
	}
	return true
}

func (r *PagedResult) Scan(result interface{}) error {
	data, err := json.Marshal(r.lastData[r.lastDataCursor]["data"])
	if err != nil {
		return err
	}
	return json.Unmarshal(data, result)
}

func (r *PagedResult) Error() error {
	return r.lastError
}
<|endoftext|>


<commit_before>package client

import (
	"log"
	"syscall"

	"github.intel.com/hpdd/lustre/fs"
	"github.intel.com/hpdd/lustre/pkg/mntent"
)

type FsID struct {
	val [2]int32
}
type Client struct {
	root   fs.RootDir
	fsName string
	fsID   *FsID
}

func getFsName(mountPath string) (string, error) {
	entry, err := mntent.GetEntryByDir(mountPath)
	if err != nil {
		return "", err
	}
	return entry.Fsname, nil
}

func getFsID(mountPath string) (*FsID, error) {
	statfs := &syscall.Statfs_t{}

	if err := syscall.Statfs(mountPath, statfs); err != nil {
		return nil, err
	}
	var id FsID
	id.val[0] = statfs.Fsid.X__val[0]
	id.val[1] = statfs.Fsid.X__val[1]
	return &id, nil
}

func New(path string) (*Client, error) {
	root, err := fs.MountRoot(path)
	if err != nil {
		log.Fatal(err)
	}
	name, err := getFsName(root.Path())
	if err != nil {
		log.Fatal(err)
	}
	id, err := getFsID(path)
	if err != nil {
		log.Fatal(err)
	}
	return &Client{root: root,
		fsName: name,
		fsID:   id,
	}, nil
}

func (c *Client) FsName() string {
	return c.fsName
}

func (c *Client) Path() string {
	return c.root.Path()
}

func (c *Client) Root() fs.RootDir {
	return c.root
}
<commit_msg>More logging updates<commit_after>package client

import (
	"syscall"

	"github.intel.com/hpdd/lustre/fs"
	"github.intel.com/hpdd/lustre/pkg/mntent"
)

type FsID struct {
	val [2]int32
}
type Client struct {
	root   fs.RootDir
	fsName string
	fsID   *FsID
}

func getFsName(mountPath string) (string, error) {
	entry, err := mntent.GetEntryByDir(mountPath)
	if err != nil {
		return "", err
	}
	return entry.Fsname, nil
}

func getFsID(mountPath string) (*FsID, error) {
	statfs := &syscall.Statfs_t{}

	if err := syscall.Statfs(mountPath, statfs); err != nil {
		return nil, err
	}
	var id FsID
	id.val[0] = statfs.Fsid.X__val[0]
	id.val[1] = statfs.Fsid.X__val[1]
	return &id, nil
}

func New(path string) (*Client, error) {
	root, err := fs.MountRoot(path)
	if err != nil {
		return nil, err
	}
	name, err := getFsName(root.Path())
	if err != nil {
		return nil, err
	}
	id, err := getFsID(path)
	if err != nil {
		return nil, err
	}
	return &Client{root: root,
		fsName: name,
		fsID:   id,
	}, nil
}

func (c *Client) FsName() string {
	return c.fsName
}

func (c *Client) Path() string {
	return c.root.Path()
}

func (c *Client) Root() fs.RootDir {
	return c.root
}
<|endoftext|>


<commit_before>package twitch

import (
	"bufio"
	"crypto/tls"
	"errors"
	"fmt"
	"net"
	"net/textproto"
	"strings"
	"sync/atomic"
	"time"
)

const (
	// ircTwitch constant for twitch irc chat address
	ircTwitch = "irc.chat.twitch.tv:443"
)

// User data you receive from tmi
type User struct {
	UserID      int64
	Username    string
	DisplayName string
	UserType    string
	Color       string
	Badges      map[string]int
}

// Message data you receive from tmi
type Message struct {
	Type   msgType
	Time   time.Time
	Action bool
	Emotes []*Emote
	Tags   map[string]string
	Text   string
}

// Client client to control your connection and attach callbacks
type Client struct {
	IrcAddress             string
	ircUser                string
	ircToken               string
	connection             *tls.Conn
	connActive             tAtomBool
	wasPinged              tAtomBool
	onNewWhisper           func(user User, message Message)
	onNewMessage           func(channel string, user User, message Message)
	onNewRoomstateMessage  func(channel string, user User, message Message)
	onNewClearchatMessage  func(channel string, user User, message Message)
	onNewUsernoticeMessage func(channel string, user User, message Message)
}

// NewClient to create a new client
func NewClient(username, oauth string) *Client {
	return &Client{
		ircUser:    username,
		ircToken:   oauth,
		IrcAddress: ircTwitch,
	}
}

// OnNewWhisper attach callback to new whisper
func (c *Client) OnNewWhisper(callback func(user User, message Message)) {
	c.onNewWhisper = callback
}

// OnNewMessage attach callback to new standard chat messages
func (c *Client) OnNewMessage(callback func(channel string, user User, message Message)) {
	c.onNewMessage = callback
}

// OnNewRoomstateMessage attach callback to new messages such as submode enabled
func (c *Client) OnNewRoomstateMessage(callback func(channel string, user User, message Message)) {
	c.onNewRoomstateMessage = callback
}

// OnNewClearchatMessage attach callback to new messages such as timeouts
func (c *Client) OnNewClearchatMessage(callback func(channel string, user User, message Message)) {
	c.onNewClearchatMessage = callback
}

// OnNewUsernoticeMessage attach callback to new usernotice message such as sub, resub, and raids
func (c *Client) OnNewUsernoticeMessage(callback func(channel string, user User, message Message)) {
	c.onNewUsernoticeMessage = callback
}

// Say write something in a chat
func (c *Client) Say(channel, text string) {
	c.send(fmt.Sprintf("PRIVMSG #%s :%s", channel, text))
}

// Whisper write something in private to someone on twitch
// whispers are heavily spam protected
// so your message might get blocked because of this
// verify your bot to prevent this
func (c *Client) Whisper(username, text string) {
	c.send(fmt.Sprintf("PRIVMSG #jtv :/w %s %s", username, text))
}

// Join enter a twitch channel to read more messages
func (c *Client) Join(channel string) {
	go c.send(fmt.Sprintf("JOIN #%s", channel))
}

// Disconnect close current connection
func (c *Client) Disconnect() error {
	c.connActive.set(false)
	if c.connection != nil {
		return c.connection.Close()
	}
	return errors.New("connection not open")
}

// Connect connect the client to the irc server
func (c *Client) Connect() error {

	dialer := &net.Dialer{
		KeepAlive: time.Second * 10,
	}

	var conf *tls.Config
	// This means we are connecting to "localhost". Disable certificate chain check
	if strings.HasPrefix(c.IrcAddress, ":") {
		conf = &tls.Config{
			InsecureSkipVerify: true,
		}
	} else {
		conf = &tls.Config{}
	}
	for {
		conn, err := tls.DialWithDialer(dialer, "tcp", c.IrcAddress, conf)
		c.connection = conn
		if err != nil {
			return err
		}

		go c.setupConnection()

		err = c.readConnection(conn)
		if err != nil {
			time.Sleep(time.Millisecond * 200)
			continue
		}
	}
}

func (c *Client) readConnection(conn *tls.Conn) error {
	reader := bufio.NewReader(conn)
	tp := textproto.NewReader(reader)
	for {
		line, err := tp.ReadLine()
		if err != nil {
			return err
		}
		messages := strings.Split(line, "\r\n")
		for _, msg := range messages {
			if !c.connActive.get() && strings.Contains(msg, ":tmi.twitch.tv 001") {
				c.connActive.set(true)
			}
			c.handleLine(msg)
		}
	}
}

func (c *Client) setupConnection() {
	c.connection.Write([]byte("PASS " + c.ircToken + "\r\n"))
	c.connection.Write([]byte("NICK " + c.ircUser + "\r\n"))
	c.connection.Write([]byte("CAP REQ :twitch.tv/tags\r\n"))
	c.connection.Write([]byte("CAP REQ :twitch.tv/commands\r\n"))
	go c.keepConnectionAlive()
}

func (c *Client) keepConnectionAlive() {
	ticker := time.NewTicker(500 * time.Second)
	quit := make(chan struct{})
	go func() {
		for {
			select {
			case <-ticker.C:
				fmt.Println(c.wasPinged.get())
				if !c.wasPinged.get() {
					fmt.Println("restarting connection")
					c.Disconnect()
					c.Connect()
				}
				c.wasPinged.set(false)
			case <-quit:
				ticker.Stop()
				return
			}
		}
	}()
}

func (c *Client) send(line string) {
	for i := 0; i < 1000; i++ {
		if !c.connActive.get() {
			time.Sleep(time.Millisecond * 2)
			continue
		}
		c.connection.Write([]byte(line + "\r\n"))
		return
	}
}

func (c *Client) handleLine(line string) {
	if strings.HasPrefix(line, "PING") {
		fmt.Println("Twitch pinged!")
		c.send(strings.Replace(line, "PING", "PONG", 1))
		c.wasPinged.set(true)
	}
	if strings.HasPrefix(line, "@") {
		message := parseMessage(line)

		Channel := message.Channel

		User := &User{
			UserID:      message.UserID,
			Username:    message.Username,
			DisplayName: message.DisplayName,
			UserType:    message.UserType,
			Color:       message.Color,
			Badges:      message.Badges,
		}

		clientMessage := &Message{
			Type:   message.Type,
			Time:   message.Time,
			Action: message.Action,
			Emotes: message.Emotes,
			Tags:   message.Tags,
			Text:   message.Text,
		}

		switch message.Type {
		case PRIVMSG:
			if c.onNewMessage != nil {
				c.onNewMessage(Channel, *User, *clientMessage)
			}
		case WHISPER:
			if c.onNewWhisper != nil {
				c.onNewWhisper(*User, *clientMessage)
			}
		case ROOMSTATE:
			if c.onNewRoomstateMessage != nil {
				c.onNewRoomstateMessage(Channel, *User, *clientMessage)
			}
		case CLEARCHAT:
			if c.onNewClearchatMessage != nil {
				c.onNewClearchatMessage(Channel, *User, *clientMessage)
			}
		case USERNOTICE:
			if c.onNewUsernoticeMessage != nil {
				c.onNewUsernoticeMessage(Channel, *User, *clientMessage)
			}
		}
	}
}

// tAtomBool atomic bool for writing/reading across threads
type tAtomBool struct{ flag int32 }

func (b *tAtomBool) set(value bool) {
	var i int32
	if value {
		i = 1
	}
	atomic.StoreInt32(&(b.flag), int32(i))
}

func (b *tAtomBool) get() bool {
	if atomic.LoadInt32(&(b.flag)) != 0 {
		return true
	}
	return false
}
<commit_msg>remove debug messages<commit_after>package twitch

import (
	"bufio"
	"crypto/tls"
	"errors"
	"fmt"
	"net"
	"net/textproto"
	"strings"
	"sync/atomic"
	"time"
)

const (
	// ircTwitch constant for twitch irc chat address
	ircTwitch = "irc.chat.twitch.tv:443"
)

// User data you receive from tmi
type User struct {
	UserID      int64
	Username    string
	DisplayName string
	UserType    string
	Color       string
	Badges      map[string]int
}

// Message data you receive from tmi
type Message struct {
	Type   msgType
	Time   time.Time
	Action bool
	Emotes []*Emote
	Tags   map[string]string
	Text   string
}

// Client client to control your connection and attach callbacks
type Client struct {
	IrcAddress             string
	ircUser                string
	ircToken               string
	connection             *tls.Conn
	connActive             tAtomBool
	wasPinged              tAtomBool
	onNewWhisper           func(user User, message Message)
	onNewMessage           func(channel string, user User, message Message)
	onNewRoomstateMessage  func(channel string, user User, message Message)
	onNewClearchatMessage  func(channel string, user User, message Message)
	onNewUsernoticeMessage func(channel string, user User, message Message)
}

// NewClient to create a new client
func NewClient(username, oauth string) *Client {
	return &Client{
		ircUser:    username,
		ircToken:   oauth,
		IrcAddress: ircTwitch,
	}
}

// OnNewWhisper attach callback to new whisper
func (c *Client) OnNewWhisper(callback func(user User, message Message)) {
	c.onNewWhisper = callback
}

// OnNewMessage attach callback to new standard chat messages
func (c *Client) OnNewMessage(callback func(channel string, user User, message Message)) {
	c.onNewMessage = callback
}

// OnNewRoomstateMessage attach callback to new messages such as submode enabled
func (c *Client) OnNewRoomstateMessage(callback func(channel string, user User, message Message)) {
	c.onNewRoomstateMessage = callback
}

// OnNewClearchatMessage attach callback to new messages such as timeouts
func (c *Client) OnNewClearchatMessage(callback func(channel string, user User, message Message)) {
	c.onNewClearchatMessage = callback
}

// OnNewUsernoticeMessage attach callback to new usernotice message such as sub, resub, and raids
func (c *Client) OnNewUsernoticeMessage(callback func(channel string, user User, message Message)) {
	c.onNewUsernoticeMessage = callback
}

// Say write something in a chat
func (c *Client) Say(channel, text string) {
	c.send(fmt.Sprintf("PRIVMSG #%s :%s", channel, text))
}

// Whisper write something in private to someone on twitch
// whispers are heavily spam protected
// so your message might get blocked because of this
// verify your bot to prevent this
func (c *Client) Whisper(username, text string) {
	c.send(fmt.Sprintf("PRIVMSG #jtv :/w %s %s", username, text))
}

// Join enter a twitch channel to read more messages
func (c *Client) Join(channel string) {
	go c.send(fmt.Sprintf("JOIN #%s", channel))
}

// Disconnect close current connection
func (c *Client) Disconnect() error {
	c.connActive.set(false)
	if c.connection != nil {
		return c.connection.Close()
	}
	return errors.New("connection not open")
}

// Connect connect the client to the irc server
func (c *Client) Connect() error {

	dialer := &net.Dialer{
		KeepAlive: time.Second * 10,
	}

	var conf *tls.Config
	// This means we are connecting to "localhost". Disable certificate chain check
	if strings.HasPrefix(c.IrcAddress, ":") {
		conf = &tls.Config{
			InsecureSkipVerify: true,
		}
	} else {
		conf = &tls.Config{}
	}
	for {
		conn, err := tls.DialWithDialer(dialer, "tcp", c.IrcAddress, conf)
		c.connection = conn
		if err != nil {
			return err
		}

		go c.setupConnection()

		err = c.readConnection(conn)
		if err != nil {
			time.Sleep(time.Millisecond * 200)
			continue
		}
	}
}

func (c *Client) readConnection(conn *tls.Conn) error {
	reader := bufio.NewReader(conn)
	tp := textproto.NewReader(reader)
	for {
		line, err := tp.ReadLine()
		if err != nil {
			return err
		}
		messages := strings.Split(line, "\r\n")
		for _, msg := range messages {
			if !c.connActive.get() && strings.Contains(msg, ":tmi.twitch.tv 001") {
				c.connActive.set(true)
			}
			c.handleLine(msg)
		}
	}
}

func (c *Client) setupConnection() {
	c.connection.Write([]byte("PASS " + c.ircToken + "\r\n"))
	c.connection.Write([]byte("NICK " + c.ircUser + "\r\n"))
	c.connection.Write([]byte("CAP REQ :twitch.tv/tags\r\n"))
	c.connection.Write([]byte("CAP REQ :twitch.tv/commands\r\n"))
	go c.keepConnectionAlive()
}

func (c *Client) keepConnectionAlive() {
	ticker := time.NewTicker(500 * time.Second)
	quit := make(chan struct{})
	go func() {
		for {
			select {
			case <-ticker.C:
				if !c.wasPinged.get() {
					c.Disconnect()
					c.Connect()
				}
				c.wasPinged.set(false)
			case <-quit:
				ticker.Stop()
				return
			}
		}
	}()
}

func (c *Client) send(line string) {
	for i := 0; i < 1000; i++ {
		if !c.connActive.get() {
			time.Sleep(time.Millisecond * 2)
			continue
		}
		c.connection.Write([]byte(line + "\r\n"))
		return
	}
}

func (c *Client) handleLine(line string) {
	if strings.HasPrefix(line, "PING") {
		c.send(strings.Replace(line, "PING", "PONG", 1))
		c.wasPinged.set(true)
	}
	if strings.HasPrefix(line, "@") {
		message := parseMessage(line)

		Channel := message.Channel

		User := &User{
			UserID:      message.UserID,
			Username:    message.Username,
			DisplayName: message.DisplayName,
			UserType:    message.UserType,
			Color:       message.Color,
			Badges:      message.Badges,
		}

		clientMessage := &Message{
			Type:   message.Type,
			Time:   message.Time,
			Action: message.Action,
			Emotes: message.Emotes,
			Tags:   message.Tags,
			Text:   message.Text,
		}

		switch message.Type {
		case PRIVMSG:
			if c.onNewMessage != nil {
				c.onNewMessage(Channel, *User, *clientMessage)
			}
		case WHISPER:
			if c.onNewWhisper != nil {
				c.onNewWhisper(*User, *clientMessage)
			}
		case ROOMSTATE:
			if c.onNewRoomstateMessage != nil {
				c.onNewRoomstateMessage(Channel, *User, *clientMessage)
			}
		case CLEARCHAT:
			if c.onNewClearchatMessage != nil {
				c.onNewClearchatMessage(Channel, *User, *clientMessage)
			}
		case USERNOTICE:
			if c.onNewUsernoticeMessage != nil {
				c.onNewUsernoticeMessage(Channel, *User, *clientMessage)
			}
		}
	}
}

// tAtomBool atomic bool for writing/reading across threads
type tAtomBool struct{ flag int32 }

func (b *tAtomBool) set(value bool) {
	var i int32
	if value {
		i = 1
	}
	atomic.StoreInt32(&(b.flag), int32(i))
}

func (b *tAtomBool) get() bool {
	if atomic.LoadInt32(&(b.flag)) != 0 {
		return true
	}
	return false
}
<|endoftext|>


<commit_before>package kafka

import (
	"encoding/binary"
	"net"
)

type ApiKey int16
type ApiVersion int16

type API struct {
	key     ApiKey
	version ApiVersion
}

var (
	REQUEST_PRODUCE        = API{0, 0}
	REQUEST_FETCH          = API{1, 0}
	REQUEST_OFFSET         = API{2, 0}
	REQUEST_METADATA       = API{3, 0}
	REQUEST_LEADER_AND_ISR = API{4, 0}
	REQUEST_STOP_REPLICA   = API{5, 0}
	REQUEST_OFFSET_COMMIT  = API{6, 0}
	REQUEST_OFFSET_FETCH   = API{7, 0}
)

type Client struct {
	addr           string
	id             *string
	correlation_id int32
	conn           net.Conn
}

func NewClient(addr string) (client *Client, err error) {
	conn, err := net.Dial("tcp", addr)
	if err != nil {
		return nil, err
	}
	client = &Client{addr, nil, 0, conn}
	return client, err
}

func (client *Client) write(buf []byte) (err error) {
	size := make([]byte, 4)
	binary.BigEndian.PutUint32(size, uint32(len(buf)))
	_, err = client.conn.Write(size)
	if err != nil {
		return err
	}
	_, err = client.conn.Write(buf)
	if err != nil {
		return err
	}
	return nil
}

func (client *Client) read() (buf []byte, err error) {
	size := make([]byte, 4)
	n, err := client.conn.Read(size)
	if err != nil {
		return nil, err
	}
	if n != 4 {
		return nil, nil
	}
	s := binary.BigEndian.Uint32(size)
	buf = make([]byte, s)
	n, err = client.conn.Read(buf)
	if err != nil {
		return nil, err
	}
	if uint32(n) != s {
		return nil, nil
	}
	return buf, nil
}

func (client *Client) sendRequest(api *API, body []byte) (err error) {
	idLen, err := stringLen(client.id)
	if err != nil {
		return err
	}
	buf := make([]byte, 4+idLen+len(body))
	binary.BigEndian.PutUint16(buf[0:2], uint16(api.key))
	binary.BigEndian.PutUint16(buf[2:4], uint16(api.version))
	binary.BigEndian.PutUint32(buf[4:8], uint32(client.correlation_id))
	client.correlation_id++
	err = encodeString(client.id, buf[8:])
	if err != nil {
		return err
	}
	copy(buf[8+idLen:], body)
	return client.write(buf)
}
<commit_msg>Fix signedness when reading message len<commit_after>package kafka

import (
	"encoding/binary"
	"net"
)

type ApiKey int16
type ApiVersion int16

type API struct {
	key     ApiKey
	version ApiVersion
}

var (
	REQUEST_PRODUCE        = API{0, 0}
	REQUEST_FETCH          = API{1, 0}
	REQUEST_OFFSET         = API{2, 0}
	REQUEST_METADATA       = API{3, 0}
	REQUEST_LEADER_AND_ISR = API{4, 0}
	REQUEST_STOP_REPLICA   = API{5, 0}
	REQUEST_OFFSET_COMMIT  = API{6, 0}
	REQUEST_OFFSET_FETCH   = API{7, 0}
)

type Client struct {
	addr           string
	id             *string
	correlation_id int32
	conn           net.Conn
}

func NewClient(addr string) (client *Client, err error) {
	conn, err := net.Dial("tcp", addr)
	if err != nil {
		return nil, err
	}
	client = &Client{addr, nil, 0, conn}
	return client, err
}

func (client *Client) write(buf []byte) (err error) {
	size := make([]byte, 4)
	binary.BigEndian.PutUint32(size, uint32(len(buf)))
	_, err = client.conn.Write(size)
	if err != nil {
		return err
	}
	_, err = client.conn.Write(buf)
	if err != nil {
		return err
	}
	return nil
}

func (client *Client) read() (buf []byte, err error) {
	size := make([]byte, 4)
	n, err := client.conn.Read(size)
	if err != nil {
		return nil, err
	}
	if n != 4 {
		return nil, nil
	}
	s := int32(binary.BigEndian.Uint32(size))
	buf = make([]byte, s)
	n, err = client.conn.Read(buf)
	if err != nil {
		return nil, err
	}
	if n != int(s) {
		return nil, nil
	}
	return buf, nil
}

func (client *Client) sendRequest(api *API, body []byte) (err error) {
	idLen, err := stringLen(client.id)
	if err != nil {
		return err
	}
	buf := make([]byte, 4+idLen+len(body))
	binary.BigEndian.PutUint16(buf[0:2], uint16(api.key))
	binary.BigEndian.PutUint16(buf[2:4], uint16(api.version))
	binary.BigEndian.PutUint32(buf[4:8], uint32(client.correlation_id))
	client.correlation_id++
	err = encodeString(client.id, buf[8:])
	if err != nil {
		return err
	}
	copy(buf[8+idLen:], body)
	return client.write(buf)
}
<|endoftext|>